medfall

A super great game engine
Log | Files | Refs

immediate.cc (7069B)


      1 #include <stddef.h>
      2 #include <math.h>
      3 
      4 #include "intrinsics.h"
      5 #include "array.h"
      6 #include "linear_algebra.h"
      7 #include "immediate.h"
      8 #include "renderer.h"
      9 
     10 struct ImmediateTriangle {
     11 	ImmediateVertex vertices[ 3 ];
     12 };
     13 
     14 static DynamicArray< ImmediateTriangle > triangles;
     15 
     16 void immediate_triangle( v3 p1, v3 p2, v3 p3, v4 colour ) {
     17 	v3 normal = normalize( cross( p2 - p1, p3 - p1 ) );
     18 	v2 uv( 0, 0 );
     19 
     20 	ImmediateTriangle triangle;
     21 	triangle.vertices[ 0 ] = { p1, normal, colour, uv };
     22 	triangle.vertices[ 1 ] = { p2, normal, colour, uv };
     23 	triangle.vertices[ 2 ] = { p3, normal, colour, uv };
     24 
     25 	triangles.add( triangle );
     26 }
     27 
     28 void immediate_triangle( ImmediateVertex v1, ImmediateVertex v2, ImmediateVertex v3 ) {
     29 	ImmediateTriangle triangle;
     30 	triangle.vertices[ 0 ] = v1;
     31 	triangle.vertices[ 1 ] = v2;
     32 	triangle.vertices[ 2 ] = v3;
     33 
     34 	triangles.add( triangle );
     35 }
     36 
     37 void immediate_sphere( v3 centre, float radius, v4 colour, u32 subdivisions ) {
     38 	const float azimuth_max = TAU;
     39 	const float pitch_max = PI;
     40 
     41 	const float dsa = sinf( 0.5f * azimuth_max / ( subdivisions - 1 ) );
     42 	const float dca = cosf( 0.5f * azimuth_max / ( subdivisions - 1 ) );
     43 	const float dsp = sinf( pitch_max / subdivisions );
     44 	const float dcp = cosf( pitch_max / subdivisions );
     45 
     46 	float sa0 = 0;
     47 	float sa1 = dsa;
     48 	float ca0 = 1;
     49 	float ca1 = dca;
     50 
     51 	for( u32 a = 0; a < subdivisions * 2 - 2; a++ ) {
     52 		float sp0 = 0;
     53 		float sp1 = dsp;
     54 		float cp0 = 1;
     55 		float cp1 = dcp;
     56 
     57 		for( u32 p = 0; p < subdivisions; p++ ) {
     58 #define VERT( n ) { centre + radius * n, n, colour, v2( 0, 0 ) }
     59 			ImmediateVertex top_left = VERT( v3( ca0 * sp0, sa0 * sp0, cp0 ) );
     60 			ImmediateVertex top_right = VERT( v3( ca1 * sp0, sa1 * sp0, cp0 ) );
     61 			ImmediateVertex bottom_left = VERT( v3( ca0 * sp1, sa0 * sp1, cp1 ) );
     62 			ImmediateVertex bottom_right = VERT( v3( ca1 * sp1, sa1 * sp1, cp1 ) );
     63 #undef VERT
     64 
     65 			immediate_triangle( top_right, top_left, bottom_left );
     66 			immediate_triangle( bottom_left, bottom_right, top_right );
     67 
     68 			sp0 = sp1;
     69 			cp0 = cp1;
     70 			sp1 = sp0 * dcp + cp0 * dsp;
     71 			cp1 = cp0 * dcp - sp0 * dsp;
     72 		}
     73 
     74 		sa0 = sa1;
     75 		ca0 = ca1;
     76 		sa1 = sa0 * dca + ca0 * dsa;
     77 		ca1 = ca0 * dca - sa0 * dsa;
     78 	}
     79 }
     80 
     81 void immediate_aabb( v3 mins, v3 maxs, v4 colour ) {
     82 	const v3 p0( mins.x, mins.y, mins.z );
     83 	const v3 p1( maxs.x, mins.y, mins.z );
     84 	const v3 p2( mins.x, maxs.y, mins.z );
     85 	const v3 p3( maxs.x, maxs.y, mins.z );
     86 	const v3 p4( mins.x, mins.y, maxs.z );
     87 	const v3 p5( maxs.x, mins.y, maxs.z );
     88 	const v3 p6( mins.x, maxs.y, maxs.z );
     89 	const v3 p7( maxs.x, maxs.y, maxs.z );
     90 
     91 	immediate_triangle( p0, p2, p1, colour ); // bottom
     92 	immediate_triangle( p1, p2, p3, colour );
     93 	immediate_triangle( p4, p5, p6, colour ); // top
     94 	immediate_triangle( p6, p5, p7, colour );
     95 	immediate_triangle( p2, p0, p6, colour ); // left
     96 	immediate_triangle( p6, p0, p4, colour );
     97 	immediate_triangle( p1, p3, p5, colour ); // right
     98 	immediate_triangle( p5, p3, p7, colour );
     99 	immediate_triangle( p0, p1, p4, colour ); // front
    100 	immediate_triangle( p4, p1, p5, colour );
    101 	immediate_triangle( p3, p2, p7, colour ); // back
    102 	immediate_triangle( p7, p2, p6, colour );
    103 }
    104 
    105 static m3 about_with_sin_cos( v3 axis, float s, float c ) {
    106 	return m3(
    107 		axis.x * axis.x + ( 1.0f - axis.x * axis.x ) * c,
    108 		axis.x * axis.y * ( 1.0f - c ) - axis.z * s,
    109 		axis.x * axis.z * ( 1.0f - c ) + axis.y * s,
    110 		axis.y * axis.x * ( 1.0f - c ) + axis.z * s,
    111 		axis.y * axis.y + ( 1.0f - axis.y * axis.y ) * c,
    112 		axis.y * axis.z * ( 1.0f - c ) - axis.x * s,
    113 		axis.z * axis.x * ( 1.0f - c ) - axis.y * s,
    114 		axis.z * axis.y * ( 1.0f - c ) + axis.x * s,
    115 		axis.z * axis.z + ( 1.0f - axis.z * axis.z ) * c
    116 	);
    117 }
    118 
    119 static m3 rotation_between( v3 from, v3 to ) {
    120 	// TODO: http://www.iquilezles.org/www/articles/noacos/noacos.htm
    121 	if( from == to ) return m3_identity();
    122 	if( from == -to ) return -m3_identity();
    123 
    124 	v3 axis = normalize( cross( from, to ) );
    125 	float cos_theta = dot( from, to );
    126 	float sin_theta = sqrtf( 1.0f - cos_theta * cos_theta );
    127 
    128 	return about_with_sin_cos( axis, sin_theta, cos_theta );
    129 }
    130 
    131 void immediate_arrow( v3 origin, v3 direction, float length, v4 colour ) {
    132 	v3 v[] = {
    133 		// base of stick
    134 		v3( -0.05f, -0.05f, 0.0f ),
    135 		v3( 0.05f, -0.05f, 0.0f ),
    136 		v3( -0.05f, 0.05f, 0.0f ),
    137 		v3( 0.05f, 0.05f, 0.0f ),
    138 
    139 		// top of stick
    140 		v3( -0.05f, -0.05f, 0.6f ),
    141 		v3( 0.05f, -0.05f, 0.6f ),
    142 		v3( -0.05f, 0.05f, 0.6f ),
    143 		v3( 0.05f, 0.05f, 0.6f ),
    144 
    145 		// point
    146 		v3( 0.0f, 0.0f, 1.0f ),
    147 		v3( 0.0f, 0.0f, 0.6f ),
    148 	};
    149 
    150 	const size_t CONE_SUBDIVISIONS = 8;
    151 	v3 cone[ CONE_SUBDIVISIONS ];
    152 
    153 	// TODO: do the fast sin/cos thing
    154 	// TODO: make a helper function to do it that fills in an array of floats
    155 	for( size_t i = 0; i < ARRAY_COUNT( cone ); i++ ) {
    156 		float s = sinf( float( i ) / float( ARRAY_COUNT( cone ) ) * TAU );
    157 		float c = cosf( float( i ) / float( ARRAY_COUNT( cone ) ) * TAU );
    158 
    159 		cone[ i ] = v3( 0.2f * c, 0.2f * s, 0.6f );
    160 	}
    161 
    162 	m3 rot = rotation_between( v3( 0, 0, 1 ), normalize( direction ) );
    163 
    164 	for( size_t i = 0; i < ARRAY_COUNT( v ); i++ ) {
    165 		v[ i ] = ( rot * v[ i ] ) * length + origin;
    166 	}
    167 	for( size_t i = 0; i < ARRAY_COUNT( cone ); i++ ) {
    168 		cone[ i ] = ( rot * cone[ i ] ) * length + origin;
    169 	}
    170 
    171 	immediate_triangle( v[ 0 ], v[ 2 ], v[ 1 ], colour ); // bottom
    172 	immediate_triangle( v[ 1 ], v[ 2 ], v[ 3 ], colour );
    173 	immediate_triangle( v[ 4 ], v[ 5 ], v[ 6 ], colour ); // top
    174 	immediate_triangle( v[ 6 ], v[ 5 ], v[ 7 ], colour );
    175 	immediate_triangle( v[ 2 ], v[ 0 ], v[ 6 ], colour ); // left
    176 	immediate_triangle( v[ 6 ], v[ 0 ], v[ 4 ], colour );
    177 	immediate_triangle( v[ 1 ], v[ 3 ], v[ 5 ], colour ); // right
    178 	immediate_triangle( v[ 5 ], v[ 3 ], v[ 7 ], colour );
    179 	immediate_triangle( v[ 0 ], v[ 1 ], v[ 4 ], colour ); // front
    180 	immediate_triangle( v[ 4 ], v[ 1 ], v[ 5 ], colour );
    181 	immediate_triangle( v[ 3 ], v[ 2 ], v[ 7 ], colour ); // back
    182 	immediate_triangle( v[ 7 ], v[ 2 ], v[ 6 ], colour );
    183 
    184 	for( size_t i = 0; i < ARRAY_COUNT( cone ); i++ ) {
    185 		immediate_triangle( v[ 8 ], cone[ ( i + 1 ) % ARRAY_COUNT( cone ) ], cone[ i ], colour );
    186 	}
    187 
    188 	for( size_t i = 0; i < ARRAY_COUNT( cone ); i++ ) {
    189 		immediate_triangle( v[ 9 ], cone[ i ], cone[ ( i + 1 ) % ARRAY_COUNT( cone ) ], colour );
    190 	}
    191 }
    192 
    193 void immediate_render( const RenderState & render_state ) {
    194 	if( triangles.size() == 0 ) {
    195 		return;
    196 	}
    197 
    198 	VB vb = renderer_new_vb( triangles.ptr(), triangles.num_bytes(), BUFFERUSAGE_STREAM );
    199 
    200 	MeshConfig mesh_config;
    201 	mesh_config.unified_buffer = vb;
    202 	mesh_config.stride = sizeof( ImmediateVertex );
    203 	mesh_config.positions_offset = checked_cast< u32 >( offsetof( ImmediateVertex, pos ) );
    204 	mesh_config.normals_offset = checked_cast< u32 >( offsetof( ImmediateVertex, normal ) );
    205 	mesh_config.colours_offset = checked_cast< u32 >( offsetof( ImmediateVertex, colour ) );
    206 	mesh_config.num_vertices = triangles.size() * 3;
    207 	if( render_state.num_textures > 0 ) {
    208 		mesh_config.tex_coords0_offset = checked_cast< u32 >( offsetof( ImmediateVertex, uv ) );
    209 	}
    210 
    211 	Mesh mesh = renderer_new_mesh( mesh_config );
    212 	renderer_draw_mesh( mesh, render_state );
    213 	renderer_delete_mesh( mesh );
    214 
    215 	triangles.clear();
    216 }