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