Fix major overstep with last commit
[carveJwlIkooP6JGAAIwe30JlM.git] / scene.h
1 #ifndef SCENE_H
2 #define SCENE_H
3
4 #include "common.h"
5 #include "model.h"
6 #include "bvh.h"
7
8 typedef struct scene scene;
9
10 struct scene
11 {
12 glmesh mesh;
13
14 mdl_vert *verts;
15 u32 *indices;
16
17 bh_tree bhtris;
18 u32 vertex_count,
19 indice_count,
20 vertex_cap,
21 indice_cap;
22
23 boxf bbx;
24
25 u32 shadower_count,
26 shadower_cap;
27
28 mdl_submesh submesh;
29 };
30
31 static void scene_init( scene *pscene )
32 {
33 pscene->verts = NULL;
34 pscene->indices = NULL;
35 pscene->vertex_count = 0;
36 pscene->indice_count = 0;
37 pscene->shadower_count = 0;
38 pscene->shadower_cap = 0;
39 pscene->submesh.indice_start = 0;
40 pscene->submesh.indice_count = 0;
41
42 v3_fill( pscene->bbx[0], 999999.9f );
43 v3_fill( pscene->bbx[1], -999999.9f );
44 }
45
46 /*
47 * Append a model into the scene with a given transform
48 */
49 static void scene_add_submesh( scene *pscene, mdl_header *mdl,
50 mdl_submesh *sm, m4x3f transform )
51 {
52 pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count,
53 &pscene->vertex_cap, sm->vertex_count, sizeof(mdl_vert) );
54
55 pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count,
56 &pscene->indice_cap, sm->indice_count, sizeof(u32) );
57
58 m3x3f normal_matrix;
59 m3x3_copy( transform, normal_matrix );
60 v3_normalize( normal_matrix[0] );
61 v3_normalize( normal_matrix[1] );
62 v3_normalize( normal_matrix[2] );
63
64 /* Transform and place vertices */
65 mdl_vert *src_verts = mdl_submesh_vertices( mdl, sm );
66 u32 *src_indices = mdl_submesh_indices( mdl, sm );
67
68 boxf bbxnew;
69 box_copy( sm->bbx, bbxnew );
70 m4x3_transform_aabb( transform, bbxnew );
71 box_concat( pscene->bbx, bbxnew );
72
73 for( u32 i=0; i<sm->vertex_count; i++ )
74 {
75 mdl_vert *pvert = &pscene->verts[ pscene->vertex_count+i ],
76 *src = &src_verts[ i ];
77
78 m4x3_mulv( transform, src->co, pvert->co );
79 m3x3_mulv( normal_matrix, src->norm, pvert->norm );
80
81 pvert->colour[0] = src->colour[0];
82 pvert->colour[1] = src->colour[1];
83 pvert->colour[2] = src->colour[2];
84 pvert->colour[3] = src->colour[3];
85 v2_copy( src->uv, pvert->uv );
86 }
87
88 for( u32 i=0; i<sm->indice_count; i++ )
89 {
90 u32 *pidx = &pscene->indices[ pscene->indice_count+i ];
91 *pidx = src_indices[i] + pscene->vertex_count;
92 }
93
94 pscene->vertex_count += sm->vertex_count;
95 pscene->indice_count += sm->indice_count;
96 }
97
98 /*
99 * One by one adders for simplified access (mostly procedural stuff)
100 */
101 static void scene_push_tri( scene *pscene, u32 tri[3] )
102 {
103 pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count,
104 &pscene->indice_cap, 3, sizeof(u32) );
105
106 u32 *dst = &pscene->indices[pscene->indice_count];
107 dst[0] = tri[0];
108 dst[1] = tri[1];
109 dst[2] = tri[2];
110
111 pscene->indice_count += 3;
112 }
113
114 static void scene_push_vert( scene *pscene, mdl_vert *v )
115 {
116 pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count,
117 &pscene->vertex_cap, 1, sizeof(mdl_vert) );
118 pscene->verts[pscene->vertex_count ++] = *v;
119 }
120
121 static void scene_copy_slice( scene *pscene, mdl_submesh *sm )
122 {
123 sm->indice_start = pscene->submesh.indice_start;
124 sm->indice_count = pscene->indice_count - sm->indice_start;
125
126 sm->vertex_start = pscene->submesh.vertex_start;
127 sm->vertex_count = pscene->vertex_count - sm->vertex_start;
128
129 pscene->submesh.indice_start = pscene->indice_count;
130 pscene->submesh.vertex_start = pscene->vertex_count;
131 }
132
133 static void scene_fix( scene *pscene )
134 {
135 buffer_fix( pscene->verts, pscene->vertex_count,
136 &pscene->vertex_cap, sizeof( mdl_vert ));
137
138 buffer_fix( pscene->indices, pscene->indice_count,
139 &pscene->indice_cap, sizeof( mdl_vert ));
140 }
141
142 static void scene_upload( scene *pscene )
143 {
144 mesh_upload( &pscene->mesh,
145 pscene->verts, pscene->vertex_count,
146 pscene->indices, pscene->indice_count );
147
148 vg_info( "Scene upload\n" );
149 vg_info( " indices:%u\n", pscene->indice_count );
150 vg_info( " verts:%u\n", pscene->vertex_count );
151 }
152
153 static void scene_bind( scene *pscene )
154 {
155 mesh_bind( &pscene->mesh );
156 }
157
158 static void scene_draw( scene *pscene )
159 {
160 mesh_drawn( 0, pscene->indice_count );
161 }
162
163 static void scene_free_offline_buffers( scene *pscene )
164 {
165 vg_free( pscene->verts );
166 vg_free( pscene->indices );
167 }
168
169 static void scene_free( scene *pscene )
170 {
171 scene_free_offline_buffers( pscene );
172
173 /* TODO: bvh */
174 }
175
176 /*
177 * BVH implementation
178 */
179
180 static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index )
181 {
182 scene *s = user;
183 mdl_vert *pa = &s->verts[ s->indices[item_index*3+0] ],
184 *pb = &s->verts[ s->indices[item_index*3+1] ],
185 *pc = &s->verts[ s->indices[item_index*3+2] ];
186
187 box_addpt( bound, pa->co );
188 box_addpt( bound, pb->co );
189 box_addpt( bound, pc->co );
190 }
191
192 static float scene_bh_centroid( void *user, u32 item_index, int axis )
193 {
194 scene *s = user;
195 mdl_vert *pa = &s->verts[ s->indices[item_index*3+0] ],
196 *pb = &s->verts[ s->indices[item_index*3+1] ],
197 *pc = &s->verts[ s->indices[item_index*3+2] ];
198
199 return (pa->co[axis] + pb->co[axis] + pc->co[axis]) * (1.0f/3.0f);
200 }
201
202 static void scene_bh_swap( void *user, u32 ia, u32 ib )
203 {
204 scene *s = user;
205
206 u32 *ti = &s->indices[ia*3];
207 u32 *tj = &s->indices[ib*3];
208
209 u32 temp[3];
210 temp[0] = ti[0];
211 temp[1] = ti[1];
212 temp[2] = ti[2];
213
214 ti[0] = tj[0];
215 ti[1] = tj[1];
216 ti[2] = tj[2];
217
218 tj[0] = temp[0];
219 tj[1] = temp[1];
220 tj[2] = temp[2];
221 }
222
223 static void scene_bh_debug( void *user, u32 item_index )
224 {
225 scene *s = user;
226 u32 idx = item_index*3;
227 mdl_vert *pa = &s->verts[ s->indices[ idx+0 ] ],
228 *pb = &s->verts[ s->indices[ idx+1 ] ],
229 *pc = &s->verts[ s->indices[ idx+2 ] ];
230
231 vg_line( pa->co, pb->co, 0xff0000ff );
232 vg_line( pb->co, pc->co, 0xff0000ff );
233 vg_line( pc->co, pa->co, 0xff0000ff );
234 }
235
236 static int scene_bh_ray( void *user, u32 index, v3f co, v3f dir, ray_hit *hit )
237 {
238 scene *s = user;
239 v3f positions[3];
240
241 u32 *tri = &s->indices[ index*3 ];
242
243 for( int i=0; i<3; i++ )
244 v3_copy( s->verts[tri[i]].co, positions[i] );
245
246 float t;
247 if(ray_tri( positions, co, dir, &t ))
248 {
249 if( t < hit->dist )
250 {
251 hit->dist = t;
252 hit->tri = tri;
253 return 1;
254 }
255 }
256
257 return 0;
258 }
259
260 static bh_system bh_system_scene =
261 {
262 .expand_bound = scene_bh_expand_bound,
263 .item_centroid = scene_bh_centroid,
264 .item_swap = scene_bh_swap,
265 .item_debug = scene_bh_debug,
266 .cast_ray = scene_bh_ray
267 };
268
269 /*
270 * An extra step is added onto the end to calculate the hit normal
271 */
272 static int scene_raycast( scene *s, v3f co, v3f dir, ray_hit *hit )
273 {
274 int count = bh_ray( &s->bhtris, 0, co, dir, hit );
275
276 if( count )
277 {
278 v3f v0, v1;
279
280 float *pa = s->verts[hit->tri[0]].co,
281 *pb = s->verts[hit->tri[1]].co,
282 *pc = s->verts[hit->tri[2]].co;
283
284 v3_sub( pa, pb, v0 );
285 v3_sub( pc, pb, v1 );
286 v3_cross( v1, v0, hit->normal );
287 v3_normalize( hit->normal );
288 v3_muladds( co, dir, hit->dist, hit->pos );
289 }
290
291 return count;
292 }
293
294 static void scene_bh_create( scene *s )
295 {
296 u32 triangle_count = s->indice_count / 3;
297 bh_create( &s->bhtris, &bh_system_scene, s, triangle_count );
298 }
299
300 #endif