bb4f5f6371a527418c17a03f2c6e146db56dc2ed
1 float const k_road_width
= 4.0f
;
3 #define ROAD_PATCH_NODES 1024
4 #define ROAD_SEGMENT_VERTICES 8
5 #define ROAD_SEGMENT_INDICES ((3*2)*5)
6 #define ROAD_INDEX_BUFFER_SIZE (ROAD_SEGMENT_INDICES * (ROAD_PATCH_NODES-2))
7 #define ROAD_RENDER_DIST 12
8 #define ROAD_RENDER_DIST_INDICES (ROAD_SEGMENT_INDICES*ROAD_RENDER_DIST)
10 typedef struct road_node
18 typedef struct road_patch
20 road_node nodes
[ ROAD_PATCH_NODES
];
27 static void road_get_range( road_patch
*road
, int range
, int *start
, int *end
)
29 *start
= VG_MIN( VG_MAX( 0, road
->active_id
-range
), ROAD_PATCH_NODES
-2 );
30 *end
= VG_MIN( VG_MAX( 0, road
->active_id
+range
), ROAD_PATCH_NODES
-2 );
33 static int test_edge_with_norm( v3f p0
, v3f p1
, v3f norm
, v3f p
)
35 v3f edge
, edge_norm
, v1
;
37 v3_sub( p1
, p0
, edge
);
38 v3_cross( edge
, norm
, edge_norm
);
41 if( v3_dot( edge_norm
, v1
) > 0.0f
)
43 vg_line( p0
, p1
, 0xff0000ff );
48 vg_line( p0
, p1
, 0xff00ff00 );
53 static int patch_seg_test_inside( road_node
*node
, v3f p
)
55 road_node
*next
= node
+ 1;
60 v3_muls( node
->side
, -k_road_width
, sa
);
61 v3_add( node
->pos
, sa
, sa
);
63 v3_muls( next
->side
, -k_road_width
, sb
);
64 v3_add( next
->pos
, sb
, sb
);
66 v3_muls( next
->side
, k_road_width
, sc
);
67 v3_add( next
->pos
, sc
, sc
);
69 v3_muls( node
->side
, k_road_width
, sd
);
70 v3_add( node
->pos
, sd
, sd
);
72 v3_cross( node
->side
, node
->fwd
, norm
);
74 if( !test_edge_with_norm( sa
, sb
, norm
, p
) ) return 0;
75 if( !test_edge_with_norm( sb
, sc
, norm
, p
) ) return 0;
76 if( !test_edge_with_norm( sc
, sd
, norm
, p
) ) return 0;
77 if( !test_edge_with_norm( sd
, sa
, norm
, p
) ) return 0;
82 static void road_patch_setplayer( road_patch
*road
, v3f pos
)
84 int idx_start
, idx_end
;
85 road_get_range( road
, ROAD_RENDER_DIST
, &idx_start
, &idx_end
);
87 for( int i
= idx_start
; i
< idx_end
; i
++ )
89 if( patch_seg_test_inside( road
->nodes
+ i
, pos
) )
92 road
->active
= road
->nodes
+ i
;
98 static void road_patch_init( road_patch
*road
)
100 road
->active
= road
->nodes
+ road
->active_id
;
103 static void road_generate( road_patch
*road
)
105 v3f dir_fwd
= { 1.0f
, 0.0f
, 0.0f
},
106 dir_up
= { 0.0f
, 1.0f
, 0.0f
},
107 dir_side
= { 0.0f
, 0.0f
, 1.0f
},
108 current_point
= { 0.0f
, 0.0f
, 0.0f
};
110 float current_rotation_amt
= 0.0f
,
111 current_pitch_amt
= -0.2f
,
112 current_roll_amt
= 0.00f
;
114 for( int i
= 0; i
< ROAD_PATCH_NODES
; i
++ )
116 road_node
*node
= road
->nodes
+ i
;
118 if( (float)rand()/(float)(RAND_MAX
) < 0.3f
)
120 current_rotation_amt
= (float)rand()/(float)(RAND_MAX
)*0.6f
-0.3f
;
121 current_pitch_amt
= (float)rand()/(float)(RAND_MAX
)*0.03f
-0.015f
;
124 v3_rotate( dir_up
, current_roll_amt
, dir_fwd
, dir_up
);
125 v3_cross( dir_fwd
, dir_up
, dir_side
);
128 v3_rotate( dir_fwd
, current_rotation_amt
, (v3f
){0.f
, 1.f
, 0.f
}, dir_fwd
);
129 v3_rotate( dir_fwd
, current_pitch_amt
, dir_side
, dir_fwd
);
130 v3_rotate( dir_up
, current_pitch_amt
, dir_side
, dir_up
);
132 v3_muladds( current_point
, dir_fwd
, 7.0f
, current_point
);
134 v3_copy( current_point
, node
->pos
);
135 v3_copy( dir_side
, node
->side
);
136 v3_copy( dir_fwd
, node
->fwd
);
137 current_pitch_amt
= 0.f
;
139 node
->pos
[1] += (float)rand()/(float)(RAND_MAX
)*0.2f
;
145 void draw_road_patch_dev( road_patch
*road
)
149 v3f p0
= { 0.0f
, 0.0f
, 0.0f
}, p1
= { 0.0f
, 0.0f
, 0.0f
};
152 for( int i
= 0; i
< ROAD_PATCH_NODES
-1; i
++ )
154 road_node
*node
= &road
->nodes
[i
];
155 road_node
*next
= &road
->nodes
[i
+1];
157 vg_line( node
->pos
, next
->pos
, 0x55ffcc22 );
160 v3_sub( next
->pos
, node
->pos
, dir
);
164 // Perpendicular vector
170 v3_muls( node
->side
, k_road_width
, p2
);
171 v3_add( p2
, node
->pos
, p2
);
172 v3_muls( node
->side
, -k_road_width
, p3
);
173 v3_add( p3
, node
->pos
, p3
);
175 vg_line( p3
, p1
, 0xccffcc22 );
176 vg_line( p2
, p0
, 0xccffcc22 );
183 static void sample_road( road_patch
*patch
, v3f pos
)
186 v3_sub( patch
->active
->pos
, pos
, v1
);
187 v3_cross( patch
->active
->side
, patch
->active
->fwd
, norm
);
189 float d
= v3_dot( norm
, v1
);
190 v3_muladds( pos
, norm
, d
, pos
);
193 static int triangle_raycast( v3f pA
, v3f pB
, v3f pC
, v3f ray
, float *height
)
195 v2f v0
, v1
, v2
, vp
, vp2
;
196 float d
, bca
= 0.f
, bcb
= 0.f
, bcc
= 0.f
;
198 v0
[0] = pB
[0] - pA
[0];
199 v0
[1] = pB
[2] - pA
[2];
200 v1
[0] = pC
[0] - pA
[0];
201 v1
[1] = pC
[2] - pA
[2];
202 v2
[0] = pB
[0] - pC
[0];
203 v2
[1] = pB
[2] - pC
[2];
205 d
= 1.f
/ (v0
[0]*v1
[1] - v1
[0]*v0
[1]);
208 /* Backface culling */
209 if( v2_cross( v0
, v1
) > 0.f
)
213 vp
[0] = ray
[0] - pA
[0];
214 vp
[1] = ray
[2] - pA
[2];
216 if( v2_cross( v0
, vp
) > 0.f
) return 0;
217 if( v2_cross( vp
, v1
) > 0.f
) return 0;
219 vp2
[0] = ray
[0] - pB
[0];
220 vp2
[1] = ray
[2] - pB
[2];
222 if( v2_cross( vp2
, v2
) > 0.f
) return 0;
224 bcb
= (vp
[0]*v1
[1] - v1
[0]*vp
[1]) * d
;
225 bcc
= (v0
[0]*vp
[1] - vp
[0]*v0
[1]) * d
;
226 bca
= 1.f
- bcb
- bcc
;
228 *height
= pA
[1]*bca
+ pB
[1]*bcb
+ pC
[1]*bcc
;
233 static int sample_road_height( road_patch
*road
, v3f pos
)
238 int idx_start
, idx_end
;
239 road_get_range( road
, ROAD_RENDER_DIST
, &idx_start
, &idx_end
);
241 for( int i
= idx_start
; i
< idx_end
; i
++ )
243 road_node
*node
= &road
->nodes
[i
],
244 *next
= &road
->nodes
[i
+1];
246 v3_muls( node
->side
, -k_road_width
, sa
);
247 v3_add( node
->pos
, sa
, sa
);
249 v3_muls( next
->side
, -k_road_width
, sb
);
250 v3_add( next
->pos
, sb
, sb
);
252 v3_muls( next
->side
, k_road_width
, sc
);
253 v3_add( next
->pos
, sc
, sc
);
255 v3_muls( node
->side
, k_road_width
, sd
);
256 v3_add( node
->pos
, sd
, sd
);
261 if( triangle_raycast( sa
, sc
, sb
, pos
, &height
) )
267 if( triangle_raycast( sa
, sd
, sc
, pos
, &height
) )