+++ /dev/null
-float const k_road_width = 4.0f;
-
-#define ROAD_PATCH_NODES 1024
-#define ROAD_SEGMENT_VERTICES 8
-#define ROAD_SEGMENT_INDICES ((3*2)*5)
-#define ROAD_INDEX_BUFFER_SIZE (ROAD_SEGMENT_INDICES * (ROAD_PATCH_NODES-2))
-#define ROAD_RENDER_DIST 12
-#define ROAD_RENDER_DIST_INDICES (ROAD_SEGMENT_INDICES*ROAD_RENDER_DIST)
-
-typedef struct road_node
-{
- v3f pos,
- side,
- fwd;
-
-} road_node;
-
-typedef struct road_patch
-{
- road_node nodes[ ROAD_PATCH_NODES ];
-
- int active_id;
- road_node *active;
-}
-road_patch;
-
-static void road_get_range( road_patch *road, int range, int *start, int *end )
-{
- *start = VG_MIN( VG_MAX( 0, road->active_id-range ), ROAD_PATCH_NODES-2 );
- *end = VG_MIN( VG_MAX( 0, road->active_id+range ), ROAD_PATCH_NODES-2 );
-}
-
-static int test_edge_with_norm( v3f p0, v3f p1, v3f norm, v3f p )
-{
- v3f edge, edge_norm, v1;
-
- v3_sub( p1, p0, edge );
- v3_cross( edge, norm, edge_norm );
- v3_sub( p0, p, v1 );
-
- if( v3_dot( edge_norm, v1 ) > 0.0f )
- {
- vg_line( p0, p1, 0xff0000ff );
- return 0;
- }
- else
- {
- vg_line( p0, p1, 0xff00ff00 );
- return 1;
- }
-}
-
-static int patch_seg_test_inside( road_node *node, v3f p )
-{
- road_node *next = node + 1;
-
- v3f norm,
- sa, sb, sc, sd;
-
- v3_muls( node->side, -k_road_width, sa );
- v3_add( node->pos, sa, sa );
-
- v3_muls( next->side, -k_road_width, sb );
- v3_add( next->pos, sb, sb );
-
- v3_muls( next->side, k_road_width, sc );
- v3_add( next->pos, sc, sc );
-
- v3_muls( node->side, k_road_width, sd );
- v3_add( node->pos, sd, sd );
-
- v3_cross( node->side, node->fwd, norm );
-
- if( !test_edge_with_norm( sa, sb, norm, p ) ) return 0;
- if( !test_edge_with_norm( sb, sc, norm, p ) ) return 0;
- if( !test_edge_with_norm( sc, sd, norm, p ) ) return 0;
- if( !test_edge_with_norm( sd, sa, norm, p ) ) return 0;
-
- return 1;
-}
-
-static void road_patch_setplayer( road_patch *road, v3f pos )
-{
- int idx_start, idx_end;
- road_get_range( road, ROAD_RENDER_DIST, &idx_start, &idx_end );
-
- for( int i = idx_start; i < idx_end; i ++ )
- {
- if( patch_seg_test_inside( road->nodes + i, pos ) )
- {
- road->active_id = i;
- road->active = road->nodes + i;
- return;
- }
- }
-}
-
-static void road_patch_init( road_patch *road )
-{
- road->active = road->nodes + road->active_id;
-}
-
-static void road_generate( road_patch *road )
-{
- v3f dir_fwd = { 1.0f, 0.0f, 0.0f },
- dir_up = { 0.0f, 1.0f, 0.0f },
- dir_side = { 0.0f, 0.0f, 1.0f },
- current_point = { 0.0f, 0.0f, 0.0f };
-
- float current_rotation_amt = 0.0f,
- current_pitch_amt = -0.2f,
- current_roll_amt = 0.00f;
-
- for( int i = 0; i < ROAD_PATCH_NODES; i ++ )
- {
- road_node *node = road->nodes + i;
-
- if( (float)rand()/(float)(RAND_MAX) < 0.3f )
- {
- current_rotation_amt = (float)rand()/(float)(RAND_MAX)*0.6f-0.3f;
- current_pitch_amt = (float)rand()/(float)(RAND_MAX)*0.03f-0.015f;
- }
-
- v3_rotate( dir_up, current_roll_amt, dir_fwd, dir_up );
- v3_cross( dir_fwd, dir_up, dir_side );
- dir_side[1] = 0.0f;
-
- v3_rotate( dir_fwd, current_rotation_amt, (v3f){0.f, 1.f, 0.f}, dir_fwd );
- v3_rotate( dir_fwd, current_pitch_amt, dir_side, dir_fwd );
- v3_rotate( dir_up, current_pitch_amt, dir_side, dir_up );
-
- v3_muladds( current_point, dir_fwd, 7.0f, current_point );
-
- v3_copy( current_point, node->pos );
- v3_copy( dir_side, node->side );
- v3_copy( dir_fwd, node->fwd );
- current_pitch_amt = 0.f;
-
- node->pos[1] += (float)rand()/(float)(RAND_MAX)*0.2f;
- }
-
- road->active_id = 0;
-}
-
-void draw_road_patch_dev( road_patch *road )
-{
- v3f dir;
- v3f norm;
- v3f p0 = { 0.0f, 0.0f, 0.0f }, p1 = { 0.0f, 0.0f, 0.0f };
- v3f p2; v3f p3;
-
- for( int i = 0; i < ROAD_PATCH_NODES-1; i ++ )
- {
- road_node *node = &road->nodes[i];
- road_node *next = &road->nodes[i+1];
-
- vg_line( node->pos, next->pos, 0x55ffcc22 );
-
- // Get line dir
- v3_sub( next->pos, node->pos, dir );
- v3_normalize( dir );
-
-#if 0
- // Perpendicular vector
- norm[0] = -dir[2];
- norm[1] = 0.f;
- norm[2] = dir[0];
-#endif
-
- v3_muls( node->side, k_road_width, p2 );
- v3_add( p2, node->pos, p2 );
- v3_muls( node->side, -k_road_width, p3 );
- v3_add( p3, node->pos, p3 );
-
- vg_line( p3, p1, 0xccffcc22 );
- vg_line( p2, p0, 0xccffcc22 );
-
- v3_copy( p3, p1 );
- v3_copy( p2, p0 );
- }
-}
-
-static void sample_road( road_patch *patch, v3f pos )
-{
- v3f v1, norm;
- v3_sub( patch->active->pos, pos, v1 );
- v3_cross( patch->active->side, patch->active->fwd, norm );
-
- float d = v3_dot( norm, v1 );
- v3_muladds( pos, norm, d, pos );
-}
-
-static int triangle_raycast( v3f pA, v3f pB, v3f pC, v3f ray, float *height )
-{
- v2f v0, v1, v2, vp, vp2;
- float d, bca = 0.f, bcb = 0.f, bcc = 0.f;
-
- v0[0] = pB[0] - pA[0];
- v0[1] = pB[2] - pA[2];
- v1[0] = pC[0] - pA[0];
- v1[1] = pC[2] - pA[2];
- v2[0] = pB[0] - pC[0];
- v2[1] = pB[2] - pC[2];
-
- d = 1.f / (v0[0]*v1[1] - v1[0]*v0[1]);
-
-#if 0
- /* Backface culling */
- if( v2_cross( v0, v1 ) > 0.f )
- return;
-#endif
-
- vp[0] = ray[0] - pA[0];
- vp[1] = ray[2] - pA[2];
-
- if( v2_cross( v0, vp ) > 0.f ) return 0;
- if( v2_cross( vp, v1 ) > 0.f ) return 0;
-
- vp2[0] = ray[0] - pB[0];
- vp2[1] = ray[2] - pB[2];
-
- if( v2_cross( vp2, v2 ) > 0.f ) return 0;
-
- bcb = (vp[0]*v1[1] - v1[0]*vp[1]) * d;
- bcc = (v0[0]*vp[1] - vp[0]*v0[1]) * d;
- bca = 1.f - bcb - bcc;
-
- *height = pA[1]*bca + pB[1]*bcb + pC[1]*bcc;
- return 1;
-}
-
-
-static int sample_road_height( road_patch *road, v3f pos )
-{
- v3f norm,
- sa, sb, sc, sd;
-
- int idx_start, idx_end;
- road_get_range( road, ROAD_RENDER_DIST, &idx_start, &idx_end );
-
- for( int i = idx_start; i < idx_end; i ++ )
- {
- road_node *node = &road->nodes[i],
- *next = &road->nodes[i+1];
-
- v3_muls( node->side, -k_road_width, sa );
- v3_add( node->pos, sa, sa );
-
- v3_muls( next->side, -k_road_width, sb );
- v3_add( next->pos, sb, sb );
-
- v3_muls( next->side, k_road_width, sc );
- v3_add( next->pos, sc, sc );
-
- v3_muls( node->side, k_road_width, sd );
- v3_add( node->pos, sd, sd );
-
- /* Triangle 1 */
- float height;
-
- if( triangle_raycast( sa, sc, sb, pos, &height ) )
- {
- pos[1] = height;
- return 1;
- }
-
- if( triangle_raycast( sa, sd, sc, pos, &height ) )
- {
- pos[1] = height;
- return 1;
- }
- }
-
- return 0;
-}