7 typedef struct scene scene
;
8 typedef struct bvh_node bvh_node
;
44 GLuint tex_dual_noise
;
46 static void scene_init( scene
*pscene
)
49 pscene
->indices
= NULL
;
50 pscene
->vertex_count
= 0;
51 pscene
->indice_count
= 0;
52 pscene
->shadowers
= NULL
;
53 pscene
->shadower_count
= 0;
54 pscene
->shadower_cap
= 0;
55 pscene
->submesh
.indice_start
= 0;
56 pscene
->submesh
.indice_count
= 0;
58 v3_fill( pscene
->bbx
[0], 999999.9f
);
59 v3_fill( pscene
->bbx
[1], -999999.9f
);
61 static int noise_ready
= 0;
66 u8
*buf
= malloc( 256*256*2 );
68 for( int i
=0; i
<256*256; i
++ )
74 for( int y
=0; y
<256; y
++ )
76 for( int x
=0; x
<256; x
++ )
78 u8
*pr
= &buf
[(y
*256+x
)*2],
79 *pg
= &buf
[(((y
+17)&0xff)*256+((x
+37)&0xff))*2+1];
84 /* TODO: This texture should be delted somewhere */
85 glGenTextures( 1, &tex_dual_noise
);
86 glBindTexture( GL_TEXTURE_2D
, tex_dual_noise
);
87 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RG
, 256, 256, 0, GL_RG
,
88 GL_UNSIGNED_BYTE
, buf
);
97 static void *buffer_reserve( void *buffer
, u32 count
, u32
*cap
, u32 amount
,
100 if( count
+amount
> *cap
)
102 *cap
= VG_MAX( (*cap
)*2, (*cap
)+amount
);
104 return realloc( buffer
, (*cap
) * emsize
);
111 * Append a model into the scene with a given transform
113 static void scene_add_model( scene
*pscene
, model
*mdl
, submodel
*submodel
,
114 v3f pos
, float yaw
, float scale
)
116 pscene
->verts
= buffer_reserve( pscene
->verts
, pscene
->vertex_count
,
117 &pscene
->vertex_cap
, submodel
->vertex_count
, sizeof(model_vert
) );
118 pscene
->indices
= buffer_reserve( pscene
->indices
, pscene
->indice_count
,
119 &pscene
->indice_cap
, submodel
->indice_count
, sizeof(u32
) );
121 if( submodel
->sdf_type
)
123 pscene
->shadowers
= buffer_reserve( pscene
->shadowers
,
124 pscene
->shadower_count
, &pscene
->shadower_cap
, 1,
125 sizeof( struct shadower
));
127 struct shadower
*shadower
=
128 &pscene
->shadowers
[ pscene
->shadower_count
++ ];
130 shadower
->sdf
= submodel
->sdf
;
131 shadower
->sdf_type
= submodel
->sdf_type
;
133 v2_muls( shadower
->sdf
.info
, scale
, shadower
->sdf
.info
);
134 v3_muls( shadower
->sdf
.origin
, scale
, shadower
->sdf
.origin
);
135 v3_add( pos
, shadower
->sdf
.origin
, shadower
->sdf
.origin
);
138 /* Transform and place vertices */
139 model_vert
*src_verts
= submodel_vert_data( mdl
, submodel
);
140 u32
*src_indices
= submodel_indice_data( mdl
, submodel
);
143 m4x3_identity( mtx
);
144 m4x3_translate( mtx
, pos
);
145 m4x3_rotate_y( mtx
, yaw
);
146 m4x3_scale( mtx
, scale
);
149 box_copy( submodel
->bbx
, bbxnew
);
150 m4x3_transform_aabb( mtx
, bbxnew
);
151 box_concat( pscene
->bbx
, bbxnew
);
154 m4x3_to_3x3( mtx
, rotation
);
156 float rand_hue
= vg_randf();
158 for( u32 i
=0; i
<submodel
->vertex_count
; i
++ )
160 model_vert
*pvert
= &pscene
->verts
[ pscene
->vertex_count
+i
],
161 *src
= &src_verts
[ i
];
163 m4x3_mulv( mtx
, src
->co
, pvert
->co
);
164 m3x3_mulv( rotation
, src
->norm
, pvert
->norm
);
166 v4_copy( src
->colour
, pvert
->colour
);
167 v2_copy( src
->uv
, pvert
->uv
);
169 float rel_y
= src
->co
[1] / submodel
->bbx
[1][1];
170 pvert
->colour
[0] = rel_y
;
171 pvert
->colour
[2] = rand_hue
;
174 for( u32 i
=0; i
<submodel
->indice_count
; i
++ )
176 u32
*pidx
= &pscene
->indices
[ pscene
->indice_count
+i
];
177 *pidx
= src_indices
[i
] + pscene
->vertex_count
;
180 pscene
->vertex_count
+= submodel
->vertex_count
;
181 pscene
->indice_count
+= submodel
->indice_count
;
184 static void scene_add_foliage( scene
*pscene
, model
*mdl
, submodel
*submodel
,
187 pscene
->verts
= buffer_reserve( pscene
->verts
, pscene
->vertex_count
,
188 &pscene
->vertex_cap
, submodel
->vertex_count
, sizeof(model_vert
) );
189 pscene
->indices
= buffer_reserve( pscene
->indices
, pscene
->indice_count
,
190 &pscene
->indice_cap
, submodel
->indice_count
, sizeof(u32
) );
192 /* Transform and place vertices */
193 model_vert
*src_verts
= submodel_vert_data( mdl
, submodel
);
194 u32
*src_indices
= submodel_indice_data( mdl
, submodel
);
197 box_copy( submodel
->bbx
, bbxnew
);
198 m4x3_transform_aabb( transform
, bbxnew
);
199 box_concat( pscene
->bbx
, bbxnew
);
201 float rand_hue
= vg_randf();
202 for( u32 i
=0; i
<submodel
->vertex_count
; i
++ )
204 model_vert
*pvert
= &pscene
->verts
[ pscene
->vertex_count
+i
],
205 *src
= &src_verts
[ i
];
207 m4x3_mulv( transform
, src
->co
, pvert
->co
);
208 m3x3_mulv( transform
, src
->norm
, pvert
->norm
);
210 v4_copy( src
->colour
, pvert
->colour
);
211 v2_copy( src
->uv
, pvert
->uv
);
213 float rel_y
= src
->co
[1] / submodel
->bbx
[1][1];
214 pvert
->colour
[0] = rel_y
;
215 pvert
->colour
[2] = rand_hue
;
218 for( u32 i
=0; i
<submodel
->indice_count
; i
++ )
220 u32
*pidx
= &pscene
->indices
[ pscene
->indice_count
+i
];
221 *pidx
= src_indices
[i
] + pscene
->vertex_count
;
224 pscene
->vertex_count
+= submodel
->vertex_count
;
225 pscene
->indice_count
+= submodel
->indice_count
;
228 static void scene_copy_slice( scene
*pscene
, submodel
*sm
)
230 sm
->indice_start
= pscene
->submesh
.indice_start
;
231 sm
->indice_count
= pscene
->indice_count
- sm
->indice_start
;
233 sm
->vertex_start
= pscene
->submesh
.vertex_start
;
234 sm
->vertex_count
= pscene
->vertex_count
- sm
->vertex_start
;
236 pscene
->submesh
.indice_start
= pscene
->indice_count
;
237 pscene
->submesh
.vertex_start
= pscene
->vertex_count
;
240 static void scene_shadow_sphere( scene
*pscene
, v3f sphere
,
241 v4f params
, v3f lightdir
)
243 for( int i
=0; i
<pscene
->vertex_count
; i
++ )
245 model_vert
*vert
= &pscene
->verts
[i
];
248 v3_sub( sphere
, vert
->co
, delta
);
250 float d
= v3_dot( lightdir
, delta
);
253 v3_muls( lightdir
, d
, closest
);
254 float dist
= v3_dist( closest
, delta
),
255 shading
= vg_maxf( dist
- params
[0], 0.0f
);
257 shading
= vg_minf( shading
* params
[1], 1.0f
);
258 vert
->colour
[1] *= shading
;
262 static void scene_shadow_gradient( scene
*pscene
, int comp
,
263 float start
, float length
)
265 float scale
= 1.0f
/ length
;
267 for( int i
=0; i
<pscene
->vertex_count
; i
++ )
269 model_vert
*vert
= &pscene
->verts
[i
];
270 float shading
= start
+ vert
->co
[comp
] * scale
;
272 vert
->colour
[1] = shading
;
278 * Experimental SDF based shadows
280 * https://iquilezles.org/articles/distfunctions/
282 static float sd_cone( v3f co
, sdf_primative
*prim
)
284 float bound
= prim
->info
[1]*1.75f
;
285 if( v3_dist2( prim
->origin
, co
) > bound
*bound
)
289 v3_sub( co
, prim
->origin
, p
);
291 float h
= prim
->info
[1];
292 v2f c
= { prim
->info
[2], prim
->info
[3] };
295 v2_muls( (v2f
){ c
[0]/c
[1], -1.0f
}, h
, q
);
297 w
[0] = v2_length( (v2f
){ p
[0], p
[2] } );
300 v2_muladds( w
, q
, -vg_clampf( v2_dot(w
,q
)/v2_dot(q
,q
), 0.0f
, 1.0f
), a
);
301 v2_muladd( w
, q
, (v2f
){ vg_clampf( w
[0]/q
[0], 0.0f
, 1.0f
), 1.0f
}, b
);
303 float k
= vg_signf( q
[1] ),
304 d
= vg_minf( v2_dot( a
,a
), v2_dot( b
,b
) ),
305 s
= vg_maxf( k
*(w
[0]*q
[1]-w
[1]*q
[0]), k
*(w
[1]-q
[1]) );
307 return sqrtf(d
)*vg_signf(s
);
310 #define CACHE_AMBIENT_SHAPES
312 static float scene_ambient_sample( scene
*pscene
, v3f pos
, v3f dir
)
316 #ifdef CACHE_AMBIENT_SHAPES
317 static struct shadower
*local_shadowers
[32];
318 static int local_shadower_count
= 0;
319 static v3f local_shadower_last
= { -99999.9f
, -999999.9f
, -9999999.9f
};
321 if( v3_dist2( pos
, local_shadower_last
) > 10.0f
*10.0f
)
323 local_shadower_count
= 0;
324 v3_copy( pos
, local_shadower_last
);
326 for( int k
=0; k
<pscene
->shadower_count
; k
++ )
328 struct shadower
*shadower
= &pscene
->shadowers
[k
];
330 if( sd_cone( pos
, &shadower
->sdf
) <= 20.0f
)
332 local_shadowers
[ local_shadower_count
++ ] = shadower
;
333 if( local_shadower_count
== vg_list_size( local_shadowers
) )
340 for( int j
=0; j
<5; j
++ )
343 v3_muladds( pos
, dir
, 1.5f
*(float)j
, tracepos
);
345 float mindist
= 99999.9f
;
347 #ifndef CACHE_AMBIENT_SHAPES
349 for( int k
=0; k
<pscene
->shadower_count
; k
++ ){
350 struct shadower
*shadower
= &pscene
->shadowers
[k
];
353 for( int k
=0; k
<local_shadower_count
; k
++ ){
354 struct shadower
*shadower
= local_shadowers
[k
];
357 float dist
= vg_maxf( 0.0f
, sd_cone( tracepos
, &shadower
->sdf
));
358 mindist
= vg_minf( mindist
, dist
);
362 accum
+= vg_clampf( 1.0f
- mindist
, 0.0f
, 1.0f
)*0.2f
;
369 #define JUST_DO_EVERY_VERT
371 static void scene_compute_occlusion( scene
*pscene
)
373 v3f sundir
= { 0.2f
, 0.9f
, 0.2f
};
374 v3_normalize( sundir
);
376 /* TODO: Make this sample grid be dynamically required.
378 * 1. Only resample the light grid (1x1x1), when a vertex is outside the
381 * 2. Reorder all vertices so that each group of vertices that fit in a
382 * cube are next to eachother in the buffer. This will save cache
385 * for the sorting algorithm, i think we can already assume that *most
386 * vertices will be quite close to eachother. so instead of doing an
387 * exhaustive search we can reorder 1k chunks at a time.
391 v3_sub( pscene
->bbx
[1], pscene
->bbx
[0], sample_area
);
392 v3_ceil( sample_area
, sample_area
);
393 int ax
= sample_area
[0],
398 float *samplegrid
= malloc( ax
*ay
*az
* sizeof(float) );
400 for( int x
=0; x
<ax
; x
++ ){
401 for( int y
=0; y
<ay
; y
++ ){
402 for( int z
=0; z
<az
; z
++ )
404 v3f sample_pos
= { x
,y
,z
};
405 v3_add( pscene
->bbx
[0], sample_pos
, sample_pos
);
406 float accum
= scene_ambient_sample( pscene
, sample_pos
, sundir
);
408 samplegrid
[x
+ y
*ax
+ z
*ax
*ay
] = accum
;
411 v3i cube_pos
= { -999999, -999999, -999999 };
412 int cube_resamples
= 0, hits
= 0, misses
= 0;
414 float s0
=0.0f
,s1
=0.0f
,s2
=0.0f
,s3
=0.0f
,s4
=0.0f
,s5
=0.0f
,s6
=0.0f
,s7
=0.0f
;
417 for( int i
=0; i
<pscene
->vertex_count
; i
++ )
419 model_vert
*vert
= &pscene
->verts
[i
];
423 v3_sub( vert
->co
, pscene
->bbx
[0], q
);
425 v3_copy( vert
->co
, q
);
435 #ifndef JUST_DO_EVERY_VERT
445 s0
= samplegrid
[ x
+ y
*ax
+ z
*ax
*ay
],
446 s1
= samplegrid
[(x
+1) + y
*ax
+ z
*ax
*ay
],
447 s2
= samplegrid
[ x
+ (y
+1)*ax
+ z
*ax
*ay
],
448 s3
= samplegrid
[(x
+1) + (y
+1)*ax
+ z
*ax
*ay
],
449 s4
= samplegrid
[ x
+ y
*ax
+ (z
+1)*ax
*ay
],
450 s5
= samplegrid
[(x
+1) + y
*ax
+ (z
+1)*ax
*ay
],
451 s6
= samplegrid
[ x
+ (y
+1)*ax
+ (z
+1)*ax
*ay
],
452 s7
= samplegrid
[(x
+1) + (y
+1)*ax
+ (z
+1)*ax
*ay
],
454 if( x
!=cube_pos
[0] || y
!=cube_pos
[1] || z
!=cube_pos
[2] )
460 s0
= scene_ambient_sample( pscene
, (v3f
){ x
,y
,z
}, sundir
);
461 s1
= scene_ambient_sample( pscene
, (v3f
){ x
+1,y
,z
}, sundir
);
462 s2
= scene_ambient_sample( pscene
, (v3f
){ x
,y
+1,z
}, sundir
);
463 s3
= scene_ambient_sample( pscene
, (v3f
){ x
+1,y
+1,z
}, sundir
);
464 s4
= scene_ambient_sample( pscene
, (v3f
){ x
,y
,z
+1 }, sundir
);
465 s5
= scene_ambient_sample( pscene
, (v3f
){ x
+1,y
,z
+1 }, sundir
);
466 s6
= scene_ambient_sample( pscene
, (v3f
){ x
,y
+1,z
+1 }, sundir
);
467 s7
= scene_ambient_sample( pscene
, (v3f
){ x
+1,y
+1,z
+1 }, sundir
);
478 s0_s1
= vg_lerpf( s0
, s1
, q
[0] ),
479 s2_s3
= vg_lerpf( s2
, s3
, q
[0] ),
480 s4_s5
= vg_lerpf( s4
, s5
, q
[0] ),
481 s6_s7
= vg_lerpf( s6
, s7
, q
[0] ),
483 s0s1_s2s3
= vg_lerpf( s0_s1
, s2_s3
, q
[1] ),
484 s4s5_s6s7
= vg_lerpf( s4_s5
, s6_s7
, q
[1] ),
485 s0s1s2s3_s4s5s6s7
= vg_lerpf( s0s1_s2s3
, s4s5_s6s7
, q
[2] );
487 vert
->colour
[1] = s0s1s2s3_s4s5s6s7
;
489 vert
->colour
[1] = scene_ambient_sample( pscene
, vert
->co
, sundir
);
494 int cube_resamples
= -1, misses
= 0, hits
= 0;
497 int static_samples
= ax
*ay
*az
,
498 vertex_samples
= pscene
->vertex_count
;
500 if( cube_resamples
< static_samples
)
501 vg_success( "Walking cube beat static grid (%d<%d. %d)!\n",
502 cube_resamples
, static_samples
, vertex_samples
);
504 vg_warn( "Walking cube was worse than static grid (%d<%d. %d).\n",
505 cube_resamples
, static_samples
, vertex_samples
);
507 vg_info( "Hits; %d, misses: %d\n", hits
, misses
);
515 for( int i
=0; i
<pscene
->vertex_count
; i
++ )
517 model_vert
*vert
= &pscene
->verts
[i
];
520 for( int j
=0; j
<5; j
++ )
523 v3_copy( vert
->co
, tracepos
);
524 v3_muladds( tracepos
, sundir
, 1.5f
*(float)j
, tracepos
);
526 float mindist
= 99999.9f
;
528 for( int k
=0; k
<pscene
->shadower_count
; k
++ )
530 struct shadower
*shadower
= &pscene
->shadowers
[k
];
531 float dist
= vg_maxf( 0.0f
, sd_cone( tracepos
, &shadower
->sdf
));
532 mindist
= vg_minf( mindist
, dist
);
535 accum
+= vg_clampf( 1.0f
- mindist
, 0.0f
, 1.0f
)*0.2f
;
538 vert
->colour
[1] = vg_minf( accum
, 1.0f
);
542 static void scene_upload( scene
*pscene
)
544 mesh_upload( &pscene
->mesh
,
545 pscene
->verts
, pscene
->vertex_count
,
546 pscene
->indices
, pscene
->indice_count
);
548 vg_info( "Scene upload\n" );
549 vg_info( " indices:%u\n", pscene
->indice_count
);
550 vg_info( " verts:%u\n", pscene
->vertex_count
);
553 float scene_tree_sway
= 0.1f
;
556 static void scene_foliage_shader_use(void)
558 SHADER_USE( shader_debug_vcol
);
560 glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol
, "uPv" ),
561 1, GL_FALSE
, (float *)vg_pv
);
563 glUniform1i( SHADER_UNIFORM( shader_debug_vcol
, "uMode" ), debugview
);
564 glUniform1i( SHADER_UNIFORM( shader_debug_vcol
, "uTexMain" ), 0 );
566 glUniform1i( SHADER_UNIFORM( shader_debug_vcol
, "uTexGradients" ), 1 );
567 vg_tex2d_bind( &tex_gradients
, 1 );
569 glUniform1i( SHADER_UNIFORM( shader_debug_vcol
, "uTexNoise" ), 2 );
570 glActiveTexture( GL_TEXTURE2
);
571 glBindTexture( GL_TEXTURE_2D
, tex_dual_noise
);
573 glUniform1f( SHADER_UNIFORM( shader_debug_vcol
, "uTime" ), vg_time
);
574 glUniform1f( SHADER_UNIFORM( shader_debug_vcol
, "uSwayAmt" ),
579 static void scene_bind( scene
*pscene
)
581 mesh_bind( &pscene
->mesh
);
584 static void scene_draw( scene
*pscene
)
586 mesh_drawn( 0, pscene
->indice_count
);
589 static void scene_debugsdf( scene
*pscene
)
591 for( int i
=0; i
<pscene
->shadower_count
; i
++ )
593 struct shadower
*shadower
= &pscene
->shadowers
[i
];
596 v3_copy( shadower
->sdf
.origin
, base
);
597 base
[1] -= shadower
->sdf
.info
[1];
598 v3_copy( base
, side
);
599 side
[0] += shadower
->sdf
.info
[0];
601 vg_line2( shadower
->sdf
.origin
, base
, 0xff00ff00, 0xff0000ff );
602 vg_line2( side
, base
, 0xff00ff00, 0xff0000ff );
603 vg_line( side
, shadower
->sdf
.origin
, 0xff00ff00 );
606 v3f p0
= { pscene
->bbx
[0][0], pscene
->bbx
[0][1], pscene
->bbx
[0][2] },
607 p1
= { pscene
->bbx
[0][0], pscene
->bbx
[1][1], pscene
->bbx
[0][2] },
608 p2
= { pscene
->bbx
[1][0], pscene
->bbx
[1][1], pscene
->bbx
[0][2] },
609 p3
= { pscene
->bbx
[1][0], pscene
->bbx
[0][1], pscene
->bbx
[0][2] },
611 p4
= { pscene
->bbx
[0][0], pscene
->bbx
[0][1], pscene
->bbx
[1][2] },
612 p5
= { pscene
->bbx
[0][0], pscene
->bbx
[1][1], pscene
->bbx
[1][2] },
613 p6
= { pscene
->bbx
[1][0], pscene
->bbx
[1][1], pscene
->bbx
[1][2] },
614 p7
= { pscene
->bbx
[1][0], pscene
->bbx
[0][1], pscene
->bbx
[1][2] };
616 u32 col
= 0xffff00c8;
617 vg_line( p0
, p1
, col
);
618 vg_line( p1
, p2
, col
);
619 vg_line( p2
, p3
, col
);
620 vg_line( p3
, p0
, col
);
622 vg_line( p4
, p5
, col
);
623 vg_line( p5
, p6
, col
);
624 vg_line( p6
, p7
, col
);
625 vg_line( p7
, p4
, col
);
627 vg_line( p0
, p4
, col
);
628 vg_line( p1
, p5
, col
);
629 vg_line( p2
, p6
, col
);
630 vg_line( p3
, p7
, col
);
633 static void scene_register(void)
638 /* Physics segment */
640 static int triangle_raycast2d( v3f pA
, v3f pB
, v3f pC
, v3f ray
, float *height
)
642 v2f v0
, v1
, v2
, vp
, vp2
;
643 float d
, bca
= 0.f
, bcb
= 0.f
, bcc
= 0.f
;
645 v0
[0] = pB
[0] - pA
[0];
646 v0
[1] = pB
[2] - pA
[2];
647 v1
[0] = pC
[0] - pA
[0];
648 v1
[1] = pC
[2] - pA
[2];
649 v2
[0] = pB
[0] - pC
[0];
650 v2
[1] = pB
[2] - pC
[2];
652 d
= 1.f
/ (v0
[0]*v1
[1] - v1
[0]*v0
[1]);
655 /* Backface culling */
656 if( v2_cross( v0
, v1
) > 0.f
)
660 vp
[0] = ray
[0] - pA
[0];
661 vp
[1] = ray
[2] - pA
[2];
663 if( v2_cross( v0
, vp
) > 0.f
) return 0;
664 if( v2_cross( vp
, v1
) > 0.f
) return 0;
666 vp2
[0] = ray
[0] - pB
[0];
667 vp2
[1] = ray
[2] - pB
[2];
669 if( v2_cross( vp2
, v2
) > 0.f
) return 0;
671 bcb
= (vp
[0]*v1
[1] - v1
[0]*vp
[1]) * d
;
672 bcc
= (v0
[0]*vp
[1] - vp
[0]*v0
[1]) * d
;
673 bca
= 1.f
- bcb
- bcc
;
675 *height
= pA
[1]*bca
+ pB
[1]*bcb
+ pC
[1]*bcc
;
680 static int sample_scene_height( scene
*pscene
, v3f pos
, v3f norm
)
682 for( int i
=0; i
<pscene
->indice_count
/3; i
++ )
684 u32
*tri
= &pscene
->indices
[i
*3];
686 float *pA
= pscene
->verts
[tri
[0]].co
,
687 *pB
= pscene
->verts
[tri
[1]].co
,
688 *pC
= pscene
->verts
[tri
[2]].co
;
691 if( triangle_raycast2d( pA
, pB
, pC
, pos
, &height
))
698 v3_sub( pA
, pB
, v0
);
699 v3_sub( pC
, pB
, v1
);
700 v3_cross( v1
, v0
, norm
);
701 v3_normalize( norm
);
710 static void sample_scene_normal( scene
*pscene
, v3f pos
, v3f normal
)
712 for( int i
=0; i
<pscene
->indice_count
/3; i
++ )
714 u32
*tri
= &pscene
->indices
[i
*3];
717 if( triangle_raycast2d(
718 pscene
->verts
[ tri
[0] ].co
,
719 pscene
->verts
[ tri
[1] ].co
,
720 pscene
->verts
[ tri
[2] ].co
, pos
, &height
))
724 v3_sub( pscene
->verts
[ tri
[1] ].co
,
725 pscene
->verts
[ tri
[0] ].co
,
728 v3_sub( pscene
->verts
[ tri
[2] ].co
,
729 pscene
->verts
[ tri
[0] ].co
,
732 v3_cross( v0
, v1
, normal
);
733 v3_normalize( normal
);
747 /* if il is 0, this is a leaf */
749 union{ u32 ir
, start
; };
752 static void bvh_update_bounds( scene
*s
, u32 inode
)
754 bvh_node
*node
= &s
->bvh
.nodes
[ inode
];
756 box_init_inf( node
->bbx
);
757 for( u32 i
=0; i
<node
->count
; i
++ )
759 u32 idx
= node
->start
+i
;
760 model_vert
*pa
= &s
->verts
[ s
->indices
[idx
*3+0] ],
761 *pb
= &s
->verts
[ s
->indices
[idx
*3+1] ],
762 *pc
= &s
->verts
[ s
->indices
[idx
*3+2] ];
764 box_addpt( node
->bbx
, pa
->co
);
765 box_addpt( node
->bbx
, pb
->co
);
766 box_addpt( node
->bbx
, pc
->co
);
770 static void bvh_subdiv( scene
*s
, u32 inode
)
772 bvh_node
*node
= &s
->bvh
.nodes
[ inode
];
775 v3_sub( node
->bbx
[1], node
->bbx
[0], extent
);
778 if( extent
[1] > extent
[0] ) axis
= 1;
779 if( extent
[2] > extent
[axis
] ) axis
= 2;
781 float split
= node
->bbx
[0][axis
] + extent
[axis
]*0.5f
;
783 /* To beat: 121,687 / 136,579
788 for( u32 t
=0; t
<node
->count
; t
++ )
790 u32
*ti
= &s
->indices
[(node
->start
+t
)*3];
791 float a
= s
->verts
[ti
[0]].co
[axis
],
792 b
= s
->verts
[ti
[1]].co
[axis
],
793 c
= s
->verts
[ti
[2]].co
[axis
];
796 avg
/= (float)node
->count
;
801 j
= i
+ node
->count
-1;
805 u32
*ti
= &s
->indices
[i
*3];
807 float a
= s
->verts
[ti
[0]].co
[axis
],
808 b
= s
->verts
[ti
[1]].co
[axis
],
809 c
= s
->verts
[ti
[2]].co
[axis
];
811 if( ((a
+b
+c
) / 3.0f
) < split
)
815 /* Swap triangle indices */
816 u32
*tj
= &s
->indices
[j
*3];
834 u32 left_count
= i
- node
->start
;
835 if( left_count
== 0 || left_count
== node
->count
) return;
837 u32 il
= s
->bvh
.node_count
++,
838 ir
= s
->bvh
.node_count
++;
840 struct bvh_node
*lnode
= &s
->bvh
.nodes
[il
],
841 *rnode
= &s
->bvh
.nodes
[ir
];
843 lnode
->start
= node
->start
;
844 lnode
->count
= left_count
;
846 rnode
->count
= node
->count
- left_count
;
852 bvh_update_bounds( s
, il
);
853 bvh_update_bounds( s
, ir
);
858 static void bvh_create( scene
*s
)
860 u32 triangle_count
= s
->indice_count
/ 3;
861 s
->bvh
.nodes
= malloc( sizeof(struct bvh_node
) * (triangle_count
*2-1) );
863 bvh_node
*root
= &s
->bvh
.nodes
[0];
864 s
->bvh
.node_count
= 1;
868 root
->count
= triangle_count
;
871 bvh_update_bounds( s
, 0 );
875 realloc( s
->bvh
.nodes
, sizeof(struct bvh_node
) * s
->bvh
.node_count
);
877 vg_success( "BVH done, size: %u/%u\n", s
->bvh
.node_count
,
878 (triangle_count
*2-1) );
881 static void bvh_debug_node( scene
*s
, u32 inode
, v3f pos
, u32 colour
)
883 struct bvh_node
*node
= &s
->bvh
.nodes
[ inode
];
885 if( (pos
[0] >= node
->bbx
[0][0] && pos
[0] <= node
->bbx
[1][0]) &&
886 (pos
[2] >= node
->bbx
[0][2] && pos
[2] <= node
->bbx
[1][2]) )
890 vg_line_boxf( node
->bbx
, colour
);
892 bvh_debug_node( s
, node
->il
, pos
, colour
);
893 bvh_debug_node( s
, node
->ir
, pos
, colour
);
897 vg_line_boxf( node
->bbx
, 0xff00ff00 );
898 for( u32 i
=0; i
<node
->count
; i
++ )
900 u32 idx
= (node
->start
+i
)*3;
902 model_vert
*pa
= &s
->verts
[ s
->indices
[ idx
+0 ] ],
903 *pb
= &s
->verts
[ s
->indices
[ idx
+1 ] ],
904 *pc
= &s
->verts
[ s
->indices
[ idx
+2 ] ];
906 vg_line( pa
->co
, pb
->co
, 0xff0000ff );
907 vg_line( pb
->co
, pc
->co
, 0xff0000ff );
908 vg_line( pc
->co
, pa
->co
, 0xff0000ff );
914 static void bvh_debug( scene
*s
, v3f pos
)
916 bvh_debug_node( s
, 0, pos
, 0x4000ffa8 );
919 typedef struct ray_hit ray_hit
;
927 int ray_aabb( boxf box
, v3f co
, v3f dir
, float dist
)
932 v3_sub( box
[0], co
, v0
);
933 v3_sub( box
[1], co
, v1
);
934 v3_div( v0
, dir
, v0
);
935 v3_div( v1
, dir
, v1
);
937 tmin
= vg_minf( v0
[0], v1
[0] );
938 tmax
= vg_maxf( v0
[0], v1
[0] );
939 tmin
= vg_maxf( tmin
, vg_minf( v0
[1], v1
[1] ));
940 tmax
= vg_minf( tmax
, vg_maxf( v0
[1], v1
[1] ));
941 tmin
= vg_maxf( tmin
, vg_minf( v0
[2], v1
[2] ));
942 tmax
= vg_minf( tmax
, vg_maxf( v0
[2], v1
[2] ));
944 return tmax
>= tmin
&& tmin
< dist
&& tmax
> 0;
947 static int bvh_ray_tri( scene
*sc
, u32
*tri
, v3f co
, v3f dir
, ray_hit
*hit
)
950 for( int i
=0; i
<3; i
++ )
951 v3_copy( sc
->verts
[tri
[i
]].co
, positions
[i
] );
954 if(ray_tri( positions
, co
, dir
, &t
))
967 static int bvh_ray( scene
*s
, u32 inode
, v3f co
, v3f dir
, ray_hit
*hit
)
969 bvh_node
*node
= &s
->bvh
.nodes
[ inode
];
971 if( !ray_aabb( node
->bbx
, co
, dir
, hit
->dist
))
978 for( u32 i
=0; i
<node
->count
; i
++ )
980 u32
*indices
= &s
->indices
[ (node
->start
+i
)*3 ];
981 count
+= bvh_ray_tri( s
, indices
, co
, dir
, hit
);
986 count
+= bvh_ray( s
, node
->il
, co
, dir
, hit
);
987 count
+= bvh_ray( s
, node
->ir
, co
, dir
, hit
);
993 static int bvh_raycast( scene
*s
, v3f co
, v3f dir
, ray_hit
*hit
)
996 v3_muladds( co
, dir
, hit
->dist
, pb
);
998 int count
= bvh_ray( s
, 0, co
, dir
, hit
);
1002 //vg_line( co, pb, 0xff00ffff );
1006 float *pa
= s
->verts
[hit
->tri
[0]].co
,
1007 *pb
= s
->verts
[hit
->tri
[1]].co
,
1008 *pc
= s
->verts
[hit
->tri
[2]].co
;
1010 v3_sub( pa
, pb
, v0
);
1011 v3_sub( pc
, pb
, v1
);
1012 v3_cross( v1
, v0
, hit
->normal
);
1013 v3_normalize( hit
->normal
);
1014 v3_muladds( co
, dir
, hit
->dist
, hit
->pos
);
1018 //vg_line( co, pb, 0xff0000ff );
1024 static int bvh_select_triangles( scene
*s
, boxf box
, u32
*triangles
, int len
)
1026 /* TODO: use this stack system on the raycast function */
1032 stack
[1] = s
->bvh
.nodes
[0].il
;
1033 stack
[2] = s
->bvh
.nodes
[0].ir
;
1037 bvh_node
*inode
= &s
->bvh
.nodes
[ stack
[depth
] ];
1038 if( box_overlap( inode
->bbx
, box
) )
1042 if( count
+ inode
->count
>= len
)
1044 vg_error( "Maximum buffer reached!\n" );
1048 for( u32 i
=0; i
<inode
->count
; i
++ )
1049 triangles
[ count
++ ] = (inode
->start
+i
)*3;
1055 if( depth
+1 >= vg_list_size(stack
) )
1057 vg_error( "Maximum stack reached!\n" );
1061 stack
[depth
] = inode
->il
;
1062 stack
[depth
+1] = inode
->ir
;
1075 static int bvh_scene_sample_node_h( scene
*s
, u32 inode
, v3f pos
, v3f norm
)
1077 bvh_node
*node
= &s
->bvh
.nodes
[ inode
];
1079 if( (pos
[0] >= node
->bbx
[0][0] && pos
[0] <= node
->bbx
[1][0]) &&
1080 (pos
[2] >= node
->bbx
[0][2] && pos
[2] <= node
->bbx
[1][2]) )
1084 if( bvh_scene_sample_node_h( s
, node
->il
, pos
, norm
)) return 1;
1085 if( bvh_scene_sample_node_h( s
, node
->ir
, pos
, norm
)) return 1;
1089 for( u32 i
=0; i
<node
->count
; i
++ )
1091 u32 idx
= (node
->start
+i
)*3;
1092 model_vert
*pa
= &s
->verts
[ s
->indices
[ idx
+0 ] ],
1093 *pb
= &s
->verts
[ s
->indices
[ idx
+1 ] ],
1094 *pc
= &s
->verts
[ s
->indices
[ idx
+2 ] ];
1097 if( triangle_raycast2d( pa
->co
, pb
->co
, pc
->co
, pos
, &height
))
1104 v3_sub( pa
->co
, pb
->co
, v0
);
1105 v3_sub( pc
->co
, pb
->co
, v1
);
1106 v3_cross( v1
, v0
, norm
);
1107 v3_normalize( norm
);
1119 static int bvh_scene_sample_h( scene
*s
, v3f pos
, v3f norm
)
1121 return bvh_scene_sample_node_h( s
, 0, pos
, norm
);
1124 static int bvh_scene_sample( scene
*s
, v3f pos
, ray_hit
*hit
)
1126 hit
->dist
= INFINITY
;
1129 v3_add( pos
, (v3f
){0.0f
,4.0f
,0.0f
}, ray_pos
);
1131 if( bvh_raycast( s
, ray_pos
, (v3f
){0.0f
,-1.0f
,0.0f
}, hit
))
1133 pos
[1] = hit
->pos
[1];