bvh interface and high perf gate
[carveJwlIkooP6JGAAIwe30JlM.git] / scene.h
1 #ifndef SCENE_H
2 #define SCENE_H
3
4 #include "common.h"
5 #include "model.h"
6
7 typedef struct scene scene;
8 typedef struct bvh_node bvh_node;
9
10 struct scene
11 {
12 glmesh mesh;
13
14 model_vert *verts;
15 u32 *indices;
16
17 struct
18 {
19 bvh_node *nodes;
20 u32 node_count;
21 }
22 bvh;
23
24 u32 vertex_count,
25 indice_count,
26 vertex_cap,
27 indice_cap;
28
29 boxf bbx;
30
31 u32 shadower_count,
32 shadower_cap;
33
34 submodel submesh;
35 };
36
37 GLuint tex_dual_noise;
38
39 static void scene_init( scene *pscene )
40 {
41 pscene->verts = NULL;
42 pscene->indices = NULL;
43 pscene->vertex_count = 0;
44 pscene->indice_count = 0;
45 pscene->shadower_count = 0;
46 pscene->shadower_cap = 0;
47 pscene->submesh.indice_start = 0;
48 pscene->submesh.indice_count = 0;
49
50 v3_fill( pscene->bbx[0], 999999.9f );
51 v3_fill( pscene->bbx[1], -999999.9f );
52
53 static int noise_ready = 0;
54 if( !noise_ready )
55 {
56 noise_ready = 1;
57
58 u8 *buf = malloc( 256*256*2 );
59
60 for( int i=0; i<256*256; i++ )
61 {
62 u8 val = rand()&0xff;
63 buf[i*2] = val;
64 }
65
66 for( int y=0; y<256; y++ )
67 {
68 for( int x=0; x<256; x++ )
69 {
70 u8 *pr = &buf[(y*256+x)*2],
71 *pg = &buf[(((y+17)&0xff)*256+((x+37)&0xff))*2+1];
72 *pg = *pr;
73 }
74 }
75
76 /* TODO: This texture should be delted somewhere */
77 glGenTextures( 1, &tex_dual_noise );
78 glBindTexture( GL_TEXTURE_2D, tex_dual_noise );
79 glTexImage2D( GL_TEXTURE_2D, 0, GL_RG, 256, 256, 0, GL_RG,
80 GL_UNSIGNED_BYTE, buf );
81
82 vg_tex2d_linear();
83 vg_tex2d_repeat();
84
85 free( buf );
86 }
87 }
88
89 static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount,
90 size_t emsize )
91 {
92 if( count+amount > *cap )
93 {
94 *cap = VG_MAX( (*cap)*2, (*cap)+amount );
95
96 return realloc( buffer, (*cap) * emsize );
97 }
98
99 return buffer;
100 }
101
102 /*
103 * Append a model into the scene with a given transform
104 */
105 static void scene_add_model( scene *pscene, model *mdl, submodel *submodel,
106 v3f pos, float yaw, float scale )
107 {
108 pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count,
109 &pscene->vertex_cap, submodel->vertex_count, sizeof(model_vert) );
110 pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count,
111 &pscene->indice_cap, submodel->indice_count, sizeof(u32) );
112
113 /* Transform and place vertices */
114 model_vert *src_verts = submodel_vert_data( mdl, submodel );
115 u32 *src_indices = submodel_indice_data( mdl, submodel );
116
117 m4x3f mtx;
118 m4x3_identity( mtx );
119 m4x3_translate( mtx, pos );
120 m4x3_rotate_y( mtx, yaw );
121 m4x3_scale( mtx, scale );
122
123 boxf bbxnew;
124 box_copy( submodel->bbx, bbxnew );
125 m4x3_transform_aabb( mtx, bbxnew );
126 box_concat( pscene->bbx, bbxnew );
127
128 m3x3f rotation;
129 m4x3_to_3x3( mtx, rotation );
130
131 float rand_hue = vg_randf();
132
133 for( u32 i=0; i<submodel->vertex_count; i++ )
134 {
135 model_vert *pvert = &pscene->verts[ pscene->vertex_count+i ],
136 *src = &src_verts[ i ];
137
138 m4x3_mulv( mtx, src->co, pvert->co );
139 m3x3_mulv( rotation, src->norm, pvert->norm );
140
141 v4_copy( src->colour, pvert->colour );
142 v2_copy( src->uv, pvert->uv );
143
144 float rel_y = src->co[1] / submodel->bbx[1][1];
145 pvert->colour[0] = rel_y;
146 pvert->colour[2] = rand_hue;
147 }
148
149 for( u32 i=0; i<submodel->indice_count; i++ )
150 {
151 u32 *pidx = &pscene->indices[ pscene->indice_count+i ];
152 *pidx = src_indices[i] + pscene->vertex_count;
153 }
154
155 pscene->vertex_count += submodel->vertex_count;
156 pscene->indice_count += submodel->indice_count;
157 }
158
159 static void scene_add_foliage( scene *pscene, model *mdl, submodel *submodel,
160 m4x3f transform )
161 {
162 pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count,
163 &pscene->vertex_cap, submodel->vertex_count, sizeof(model_vert) );
164 pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count,
165 &pscene->indice_cap, submodel->indice_count, sizeof(u32) );
166
167 /* Transform and place vertices */
168 model_vert *src_verts = submodel_vert_data( mdl, submodel );
169 u32 *src_indices = submodel_indice_data( mdl, submodel );
170
171 boxf bbxnew;
172 box_copy( submodel->bbx, bbxnew );
173 m4x3_transform_aabb( transform, bbxnew );
174 box_concat( pscene->bbx, bbxnew );
175
176 float rand_hue = vg_randf();
177 for( u32 i=0; i<submodel->vertex_count; i++ )
178 {
179 model_vert *pvert = &pscene->verts[ pscene->vertex_count+i ],
180 *src = &src_verts[ i ];
181
182 m4x3_mulv( transform, src->co, pvert->co );
183 m3x3_mulv( transform, src->norm, pvert->norm );
184
185 v4_copy( src->colour, pvert->colour );
186 v2_copy( src->uv, pvert->uv );
187
188 float rel_y = src->co[1] / submodel->bbx[1][1];
189 pvert->colour[0] = rel_y;
190 pvert->colour[2] = rand_hue;
191 }
192
193 for( u32 i=0; i<submodel->indice_count; i++ )
194 {
195 u32 *pidx = &pscene->indices[ pscene->indice_count+i ];
196 *pidx = src_indices[i] + pscene->vertex_count;
197 }
198
199 pscene->vertex_count += submodel->vertex_count;
200 pscene->indice_count += submodel->indice_count;
201 }
202
203 static void scene_copy_slice( scene *pscene, submodel *sm )
204 {
205 sm->indice_start = pscene->submesh.indice_start;
206 sm->indice_count = pscene->indice_count - sm->indice_start;
207
208 sm->vertex_start = pscene->submesh.vertex_start;
209 sm->vertex_count = pscene->vertex_count - sm->vertex_start;
210
211 pscene->submesh.indice_start = pscene->indice_count;
212 pscene->submesh.vertex_start = pscene->vertex_count;
213 }
214
215 static void scene_upload( scene *pscene )
216 {
217 mesh_upload( &pscene->mesh,
218 pscene->verts, pscene->vertex_count,
219 pscene->indices, pscene->indice_count );
220
221 vg_info( "Scene upload\n" );
222 vg_info( " indices:%u\n", pscene->indice_count );
223 vg_info( " verts:%u\n", pscene->vertex_count );
224 }
225
226 float scene_tree_sway = 0.1f;
227
228 #if 0
229 static void scene_foliage_shader_use(void)
230 {
231 SHADER_USE( shader_debug_vcol );
232
233 glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol, "uPv" ),
234 1, GL_FALSE, (float *)vg_pv );
235
236 glUniform1i( SHADER_UNIFORM( shader_debug_vcol, "uMode" ), debugview );
237 glUniform1i( SHADER_UNIFORM( shader_debug_vcol, "uTexMain" ), 0 );
238
239 glUniform1i( SHADER_UNIFORM( shader_debug_vcol, "uTexGradients" ), 1 );
240 vg_tex2d_bind( &tex_gradients, 1 );
241
242 glUniform1i( SHADER_UNIFORM( shader_debug_vcol, "uTexNoise" ), 2 );
243 glActiveTexture( GL_TEXTURE2 );
244 glBindTexture( GL_TEXTURE_2D, tex_dual_noise );
245
246 glUniform1f( SHADER_UNIFORM( shader_debug_vcol, "uTime" ), vg_time );
247 glUniform1f( SHADER_UNIFORM( shader_debug_vcol, "uSwayAmt" ),
248 scene_tree_sway );
249 }
250 #endif
251
252 static void scene_bind( scene *pscene )
253 {
254 mesh_bind( &pscene->mesh );
255 }
256
257 static void scene_draw( scene *pscene )
258 {
259 mesh_drawn( 0, pscene->indice_count );
260 }
261
262 static void scene_register(void)
263 {
264 }
265
266
267 /* Physics segment */
268
269 static int triangle_raycast2d( v3f pA, v3f pB, v3f pC, v3f ray, float *height )
270 {
271 v2f v0, v1, v2, vp, vp2;
272 float d, bca = 0.f, bcb = 0.f, bcc = 0.f;
273
274 v0[0] = pB[0] - pA[0];
275 v0[1] = pB[2] - pA[2];
276 v1[0] = pC[0] - pA[0];
277 v1[1] = pC[2] - pA[2];
278 v2[0] = pB[0] - pC[0];
279 v2[1] = pB[2] - pC[2];
280
281 d = 1.f / (v0[0]*v1[1] - v1[0]*v0[1]);
282
283 #if 0
284 /* Backface culling */
285 if( v2_cross( v0, v1 ) > 0.f )
286 return;
287 #endif
288
289 vp[0] = ray[0] - pA[0];
290 vp[1] = ray[2] - pA[2];
291
292 if( v2_cross( v0, vp ) > 0.f ) return 0;
293 if( v2_cross( vp, v1 ) > 0.f ) return 0;
294
295 vp2[0] = ray[0] - pB[0];
296 vp2[1] = ray[2] - pB[2];
297
298 if( v2_cross( vp2, v2 ) > 0.f ) return 0;
299
300 bcb = (vp[0]*v1[1] - v1[0]*vp[1]) * d;
301 bcc = (v0[0]*vp[1] - vp[0]*v0[1]) * d;
302 bca = 1.f - bcb - bcc;
303
304 *height = pA[1]*bca + pB[1]*bcb + pC[1]*bcc;
305 return 1;
306 }
307
308 /* Temporary */
309 static int sample_scene_height( scene *pscene, v3f pos, v3f norm )
310 {
311 for( int i=0; i<pscene->indice_count/3; i++ )
312 {
313 u32 *tri = &pscene->indices[i*3];
314
315 float *pA = pscene->verts[tri[0]].co,
316 *pB = pscene->verts[tri[1]].co,
317 *pC = pscene->verts[tri[2]].co;
318
319 float height;
320 if( triangle_raycast2d( pA, pB, pC, pos, &height ))
321 {
322 pos[1] = height;
323
324 if( norm )
325 {
326 v3f v0, v1;
327 v3_sub( pA, pB, v0 );
328 v3_sub( pC, pB, v1 );
329 v3_cross( v1, v0, norm );
330 v3_normalize( norm );
331 }
332
333 return 1;
334 }
335 }
336 return 0;
337 }
338
339 static void sample_scene_normal( scene *pscene, v3f pos, v3f normal )
340 {
341 for( int i=0; i<pscene->indice_count/3; i++ )
342 {
343 u32 *tri = &pscene->indices[i*3];
344
345 float height;
346 if( triangle_raycast2d(
347 pscene->verts[ tri[0] ].co,
348 pscene->verts[ tri[1] ].co,
349 pscene->verts[ tri[2] ].co, pos, &height ))
350 {
351 v3f v0, v1;
352
353 v3_sub( pscene->verts[ tri[1] ].co,
354 pscene->verts[ tri[0] ].co,
355 v0 );
356
357 v3_sub( pscene->verts[ tri[2] ].co,
358 pscene->verts[ tri[0] ].co,
359 v1 );
360
361 v3_cross( v0, v1, normal );
362 v3_normalize( normal );
363 return;
364 }
365 }
366
367 normal[0] = 0.0f;
368 normal[1] = 1.0f;
369 normal[2] = 0.0f;
370 }
371
372
373 /*
374 *
375 *
376 * TODO: THIS SHIT IS DEPRECATED FOR THE NEW SHIT IN BVH.H
377 *
378 *
379 */
380
381 struct bvh_node
382 {
383 boxf bbx;
384
385 /* if il is 0, this is a leaf */
386 u32 il, count;
387 union{ u32 ir, start; };
388 };
389
390 static void bvh_update_bounds( scene *s, u32 inode )
391 {
392 bvh_node *node = &s->bvh.nodes[ inode ];
393
394 box_init_inf( node->bbx );
395 for( u32 i=0; i<node->count; i++ )
396 {
397 u32 idx = node->start+i;
398 model_vert *pa = &s->verts[ s->indices[idx*3+0] ],
399 *pb = &s->verts[ s->indices[idx*3+1] ],
400 *pc = &s->verts[ s->indices[idx*3+2] ];
401
402 box_addpt( node->bbx, pa->co );
403 box_addpt( node->bbx, pb->co );
404 box_addpt( node->bbx, pc->co );
405 }
406 }
407
408 static void bvh_subdiv( scene *s, u32 inode )
409 {
410 bvh_node *node = &s->bvh.nodes[ inode ];
411
412 v3f extent;
413 v3_sub( node->bbx[1], node->bbx[0], extent );
414
415 int axis = 0;
416 if( extent[1] > extent[0] ) axis = 1;
417 if( extent[2] > extent[axis] ) axis = 2;
418
419 float split = node->bbx[0][axis] + extent[axis]*0.5f;
420
421 float avg = 0.0;
422 for( u32 t=0; t<node->count; t++ )
423 {
424 u32 *ti = &s->indices[(node->start+t)*3];
425 float a = s->verts[ti[0]].co[axis],
426 b = s->verts[ti[1]].co[axis],
427 c = s->verts[ti[2]].co[axis];
428 avg += (a+b+c) * (1.0f/3.0f);
429 }
430 avg /= (float)node->count;
431
432 split = avg;
433
434 i32 i = node->start,
435 j = i + node->count-1;
436
437 while( i <= j )
438 {
439 u32 *ti = &s->indices[i*3];
440
441 float a = s->verts[ti[0]].co[axis],
442 b = s->verts[ti[1]].co[axis],
443 c = s->verts[ti[2]].co[axis];
444
445 if( (a+b+c) * (1.0f/3.0f) < split )
446 i ++;
447 else
448 {
449 /* Swap triangle indices */
450 u32 *tj = &s->indices[j*3];
451 u32 temp[3];
452 temp[0] = ti[0];
453 temp[1] = ti[1];
454 temp[2] = ti[2];
455
456 ti[0] = tj[0];
457 ti[1] = tj[1];
458 ti[2] = tj[2];
459
460 tj[0] = temp[0];
461 tj[1] = temp[1];
462 tj[2] = temp[2];
463
464 j --;
465 }
466 }
467
468 u32 left_count = i - node->start;
469 if( left_count == 0 || left_count == node->count ) return;
470
471 u32 il = s->bvh.node_count ++,
472 ir = s->bvh.node_count ++;
473
474 struct bvh_node *lnode = &s->bvh.nodes[il],
475 *rnode = &s->bvh.nodes[ir];
476
477 lnode->start = node->start;
478 lnode->count = left_count;
479 rnode->start = i;
480 rnode->count = node->count - left_count;
481
482 node->il = il;
483 node->ir = ir;
484 node->count = 0;
485
486 bvh_update_bounds( s, il );
487 bvh_update_bounds( s, ir );
488 bvh_subdiv( s, il );
489 bvh_subdiv( s, ir );
490 }
491
492 static void bvh_create( scene *s )
493 {
494 u32 triangle_count = s->indice_count / 3;
495 s->bvh.nodes = malloc( sizeof(struct bvh_node) * (triangle_count*2-1) );
496
497 bvh_node *root = &s->bvh.nodes[0];
498 s->bvh.node_count = 1;
499
500 root->il = 0;
501 root->ir = 0;
502 root->count = triangle_count;
503 root->start = 0;
504
505 bvh_update_bounds( s, 0 );
506 bvh_subdiv( s, 0 );
507
508 s->bvh.nodes =
509 realloc( s->bvh.nodes, sizeof(struct bvh_node) * s->bvh.node_count );
510
511 vg_success( "BVH done, size: %u/%u\n", s->bvh.node_count,
512 (triangle_count*2-1) );
513 }
514
515 static void bvh_debug_node( scene *s, u32 inode, v3f pos, u32 colour )
516 {
517 struct bvh_node *node = &s->bvh.nodes[ inode ];
518
519 if( (pos[0] >= node->bbx[0][0] && pos[0] <= node->bbx[1][0]) &&
520 (pos[2] >= node->bbx[0][2] && pos[2] <= node->bbx[1][2]) )
521 {
522 if( !node->count )
523 {
524 vg_line_boxf( node->bbx, colour );
525
526 bvh_debug_node( s, node->il, pos, colour );
527 bvh_debug_node( s, node->ir, pos, colour );
528 }
529 else
530 {
531 vg_line_boxf( node->bbx, 0xff00ff00 );
532 for( u32 i=0; i<node->count; i++ )
533 {
534 u32 idx = (node->start+i)*3;
535
536 model_vert *pa = &s->verts[ s->indices[ idx+0 ] ],
537 *pb = &s->verts[ s->indices[ idx+1 ] ],
538 *pc = &s->verts[ s->indices[ idx+2 ] ];
539
540 vg_line( pa->co, pb->co, 0xff0000ff );
541 vg_line( pb->co, pc->co, 0xff0000ff );
542 vg_line( pc->co, pa->co, 0xff0000ff );
543 }
544 }
545 }
546 }
547
548 static void bvh_debug( scene *s, v3f pos )
549 {
550 bvh_debug_node( s, 0, pos, 0x4000ffa8 );
551 }
552
553 static int bvh_ray_tri( scene *sc, u32 *tri, v3f co, v3f dir, ray_hit *hit )
554 {
555 v3f positions[3];
556 for( int i=0; i<3; i++ )
557 v3_copy( sc->verts[tri[i]].co, positions[i] );
558
559 float t;
560 if(ray_tri( positions, co, dir, &t ))
561 {
562 if( t < hit->dist )
563 {
564 hit->dist = t;
565 hit->tri = tri;
566 return 1;
567 }
568 }
569
570 return 0;
571 }
572
573 static int bvh_ray( scene *s, u32 inode, v3f co, v3f dir, ray_hit *hit )
574 {
575 #if 0
576 bvh_node *node = &s->bvh.nodes[ inode ];
577
578 if( !ray_aabb( node->bbx, co, dir, hit->dist ))
579 return 0;
580
581 int count = 0;
582
583 if( node->count )
584 {
585 for( u32 i=0; i<node->count; i++ )
586 {
587 u32 *indices = &s->indices[ (node->start+i)*3 ];
588 count += bvh_ray_tri( s, indices, co, dir, hit );
589 }
590 }
591 else
592 {
593 count += bvh_ray( s, node->il, co, dir, hit );
594 count += bvh_ray( s, node->ir, co, dir, hit );
595 }
596
597 return count;
598 #endif
599
600 int count = 0;
601 u32 stack[100];
602 u32 depth = 2;
603
604 stack[0] = 0;
605 stack[1] = s->bvh.nodes[0].il;
606 stack[2] = s->bvh.nodes[0].ir;
607
608 while(depth)
609 {
610 bvh_node *inode = &s->bvh.nodes[ stack[depth] ];
611 if( ray_aabb( inode->bbx, co, dir, hit->dist ) )
612 {
613 if( inode->count )
614 {
615 for( u32 i=0; i<inode->count; i++ )
616 {
617 u32 *indices = &s->indices[ (inode->start+i)*3 ];
618 count += bvh_ray_tri( s, indices, co, dir, hit );
619 }
620
621 depth --;
622 }
623 else
624 {
625 if( depth+1 >= vg_list_size(stack) )
626 {
627 vg_error( "Maximum stack reached!\n" );
628 return count;
629 }
630
631 stack[depth] = inode->il;
632 stack[depth+1] = inode->ir;
633 depth ++;
634 }
635 }
636 else
637 {
638 depth --;
639 }
640 }
641
642 return count;
643 }
644
645 static int bvh_raycast( scene *s, v3f co, v3f dir, ray_hit *hit )
646 {
647 v3f pb;
648 v3_muladds( co, dir, hit->dist, pb );
649
650 int count = bvh_ray( s, 0, co, dir, hit );
651
652 if( count )
653 {
654 //vg_line( co, pb, 0xff00ffff );
655
656 v3f v0, v1;
657
658 float *pa = s->verts[hit->tri[0]].co,
659 *pb = s->verts[hit->tri[1]].co,
660 *pc = s->verts[hit->tri[2]].co;
661
662 v3_sub( pa, pb, v0 );
663 v3_sub( pc, pb, v1 );
664 v3_cross( v1, v0, hit->normal );
665 v3_normalize( hit->normal );
666 v3_muladds( co, dir, hit->dist, hit->pos );
667 }
668 else
669 {
670 //vg_line( co, pb, 0xff0000ff );
671 }
672
673 return count;
674 }
675
676 static int bvh_select_triangles( scene *s, boxf box, u32 *triangles, int len )
677 {
678 /* TODO: use this stack system on the raycast function */
679 int count = 0;
680 u32 stack[100];
681 u32 depth = 2;
682
683 stack[0] = 0;
684 stack[1] = s->bvh.nodes[0].il;
685 stack[2] = s->bvh.nodes[0].ir;
686
687 while(depth)
688 {
689 bvh_node *inode = &s->bvh.nodes[ stack[depth] ];
690 if( box_overlap( inode->bbx, box ) )
691 {
692 if( inode->count )
693 {
694 if( count + inode->count >= len )
695 {
696 vg_error( "Maximum buffer reached!\n" );
697 return count;
698 }
699
700 for( u32 i=0; i<inode->count; i++ )
701 triangles[ count ++ ] = (inode->start+i)*3;
702
703 depth --;
704 }
705 else
706 {
707 if( depth+1 >= vg_list_size(stack) )
708 {
709 vg_error( "Maximum stack reached!\n" );
710 return count;
711 }
712
713 stack[depth] = inode->il;
714 stack[depth+1] = inode->ir;
715 depth ++;
716 }
717 }
718 else
719 {
720 depth --;
721 }
722 }
723
724 return count;
725 }
726
727 static int bvh_scene_sample_node_h( scene *s, u32 inode, v3f pos, v3f norm )
728 {
729 bvh_node *node = &s->bvh.nodes[ inode ];
730
731 if( (pos[0] >= node->bbx[0][0] && pos[0] <= node->bbx[1][0]) &&
732 (pos[2] >= node->bbx[0][2] && pos[2] <= node->bbx[1][2]) )
733 {
734 if( !node->count )
735 {
736 if( bvh_scene_sample_node_h( s, node->il, pos, norm )) return 1;
737 if( bvh_scene_sample_node_h( s, node->ir, pos, norm )) return 1;
738 }
739 else
740 {
741 for( u32 i=0; i<node->count; i++ )
742 {
743 u32 idx = (node->start+i)*3;
744 model_vert *pa = &s->verts[ s->indices[ idx+0 ] ],
745 *pb = &s->verts[ s->indices[ idx+1 ] ],
746 *pc = &s->verts[ s->indices[ idx+2 ] ];
747
748 float height;
749 if( triangle_raycast2d( pa->co, pb->co, pc->co, pos, &height ))
750 {
751 pos[1] = height;
752
753 if( norm )
754 {
755 v3f v0, v1;
756 v3_sub( pa->co, pb->co, v0 );
757 v3_sub( pc->co, pb->co, v1 );
758 v3_cross( v1, v0, norm );
759 v3_normalize( norm );
760 }
761
762 return 1;
763 }
764 }
765 }
766 }
767
768 return 0;
769 }
770
771 static int bvh_scene_sample_h( scene *s, v3f pos, v3f norm)
772 {
773 return bvh_scene_sample_node_h( s, 0, pos, norm );
774 }
775
776 static int bvh_scene_sample( scene *s, v3f pos, ray_hit *hit )
777 {
778 hit->dist = INFINITY;
779
780 v3f ray_pos;
781 v3_add( pos, (v3f){0.0f,4.0f,0.0f}, ray_pos );
782
783 if( bvh_raycast( s, ray_pos, (v3f){0.0f,-1.0f,0.0f}, hit ))
784 {
785 pos[1] = hit->pos[1];
786 return 1;
787 }
788
789 return 0;
790 }
791
792 #endif