fix regression with gate flipping
[carveJwlIkooP6JGAAIwe30JlM.git] / world_physics.c
1 #ifndef WORLD_PHYSICS_C
2 #define WORLD_PHYSICS_C
3
4 #include "world.h"
5 #include "world_physics.h"
6
7 void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] )
8 {
9 for( int i=0; i<3; i++ )
10 v3_copy( world->scene_geo.arrvertices[ hit->tri[i] ].co, tri[i] );
11 }
12
13 int ray_world( world_instance *world,
14 v3f pos, v3f dir, ray_hit *hit, u16 ignore )
15 {
16 return scene_raycast( &world->scene_geo, world->geo_bh, pos, dir, hit,
17 ignore );
18 }
19
20 /*
21 * Cast a sphere from a to b and see what time it hits
22 */
23 int spherecast_world( world_instance *world,
24 v3f pa, v3f pb, float r, float *t, v3f n, u16 ignore )
25 {
26 boxf region;
27 box_init_inf( region );
28 box_addpt( region, pa );
29 box_addpt( region, pb );
30
31 v3_add( (v3f){ r, r, r}, region[1], region[1] );
32 v3_add( (v3f){-r,-r,-r}, region[0], region[0] );
33
34 v3f dir;
35 v3_sub( pb, pa, dir );
36
37 v3f dir_inv;
38 dir_inv[0] = 1.0f/dir[0];
39 dir_inv[1] = 1.0f/dir[1];
40 dir_inv[2] = 1.0f/dir[2];
41
42 int hit = -1;
43 float min_t = 1.0f;
44
45 bh_iter it;
46 bh_iter_init_box( 0, &it, region );
47 i32 idx;
48 while( bh_next( world->geo_bh, &it, &idx ) ){
49 u32 *ptri = &world->scene_geo.arrindices[ idx*3 ];
50 if( world->scene_geo.arrvertices[ptri[0]].flags & ignore ) continue;
51
52 v3f tri[3];
53 boxf box;
54 box_init_inf( box );
55 for( int j=0; j<3; j++ ){
56 v3_copy( world->scene_geo.arrvertices[ptri[j]].co, tri[j] );
57 box_addpt( box, tri[j] );
58 }
59
60 v3_add( (v3f){ r, r, r}, box[1], box[1] );
61 v3_add( (v3f){-r,-r,-r}, box[0], box[0] );
62
63 if( !ray_aabb1( box, pa, dir_inv, 1.0f ) )
64 continue;
65
66 float t;
67 v3f n1;
68 if( spherecast_triangle( tri, pa, dir, r, &t, n1 ) ){
69 if( t < min_t ){
70 min_t = t;
71 hit = idx;
72 v3_copy( n1, n );
73 }
74 }
75 }
76
77 *t = min_t;
78 return hit;
79 }
80
81 struct world_surface *world_tri_index_surface( world_instance *world,
82 u32 index )
83 {
84 for( int i=1; i<world->surface_count; i++ ){
85 struct world_surface *surf = &world->surfaces[i];
86
87 if( (index >= surf->sm_geo.vertex_start) &&
88 (index < surf->sm_geo.vertex_start+surf->sm_geo.vertex_count ) )
89 {
90 return surf;
91 }
92 }
93
94 return &world->surfaces[0];
95 }
96
97 struct world_surface *world_contact_surface( world_instance *world, rb_ct *ct )
98 {
99 return world_tri_index_surface( world, ct->element_id );
100 }
101
102 struct world_surface *ray_hit_surface( world_instance *world, ray_hit *hit )
103 {
104 return world_tri_index_surface( world, hit->tri[0] );
105 }
106
107 #endif /* WORLD_PHYSICS_C */