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 }