update model format
[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 #if 0
32 GLuint tex_dual_noise;
33 #endif
34
35 static void scene_init( scene *pscene )
36 {
37 pscene->verts = NULL;
38 pscene->indices = NULL;
39 pscene->vertex_count = 0;
40 pscene->indice_count = 0;
41 pscene->shadower_count = 0;
42 pscene->shadower_cap = 0;
43 pscene->submesh.indice_start = 0;
44 pscene->submesh.indice_count = 0;
45
46 v3_fill( pscene->bbx[0], 999999.9f );
47 v3_fill( pscene->bbx[1], -999999.9f );
48
49 #if 0
50 static int noise_ready = 0;
51 if( !noise_ready )
52 {
53 noise_ready = 1;
54
55 u8 *buf = malloc( 256*256*2 );
56
57 for( int i=0; i<256*256; i++ )
58 {
59 u8 val = rand()&0xff;
60 buf[i*2] = val;
61 }
62
63 for( int y=0; y<256; y++ )
64 {
65 for( int x=0; x<256; x++ )
66 {
67 u8 *pr = &buf[(y*256+x)*2],
68 *pg = &buf[(((y+17)&0xff)*256+((x+37)&0xff))*2+1];
69 *pg = *pr;
70 }
71 }
72
73 /* TODO: This texture should be delted somewhere */
74 glGenTextures( 1, &tex_dual_noise );
75 glBindTexture( GL_TEXTURE_2D, tex_dual_noise );
76 glTexImage2D( GL_TEXTURE_2D, 0, GL_RG, 256, 256, 0, GL_RG,
77 GL_UNSIGNED_BYTE, buf );
78
79 vg_tex2d_linear();
80 vg_tex2d_repeat();
81
82 free( buf );
83 }
84 #endif
85 }
86
87 static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount,
88 size_t emsize )
89 {
90 if( count+amount > *cap )
91 {
92 *cap = VG_MAX( (*cap)*2, (*cap)+amount );
93
94 return realloc( buffer, (*cap) * emsize );
95 }
96
97 return buffer;
98 }
99
100 static void *buffer_fix( void *buffer, u32 count, u32 *cap, size_t emsize )
101 {
102 *cap = count;
103 return realloc( buffer, (*cap) * emsize );
104 }
105
106 /*
107 * Append a model into the scene with a given transform
108 */
109 static void scene_add_submesh( scene *pscene, mdl_header *mdl,
110 mdl_submesh *sm, m4x3f transform )
111 {
112 pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count,
113 &pscene->vertex_cap, sm->vertex_count, sizeof(mdl_vert) );
114 pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count,
115 &pscene->indice_cap, sm->indice_count, sizeof(u32) );
116
117 m3x3f normal_matrix;
118 m3x3_copy( transform, normal_matrix );
119 v3_normalize( normal_matrix[0] );
120 v3_normalize( normal_matrix[1] );
121 v3_normalize( normal_matrix[2] );
122
123 /* Transform and place vertices */
124 mdl_vert *src_verts = mdl_submesh_vertices( mdl, sm );
125 u32 *src_indices = mdl_submesh_indices( mdl, sm );
126
127 boxf bbxnew;
128 box_copy( sm->bbx, bbxnew );
129 m4x3_transform_aabb( transform, bbxnew );
130 box_concat( pscene->bbx, bbxnew );
131
132 for( u32 i=0; i<sm->vertex_count; i++ )
133 {
134 mdl_vert *pvert = &pscene->verts[ pscene->vertex_count+i ],
135 *src = &src_verts[ i ];
136
137 m4x3_mulv( transform, src->co, pvert->co );
138 m3x3_mulv( normal_matrix, src->norm, pvert->norm );
139
140 pvert->colour[0] = src->colour[0];
141 pvert->colour[1] = src->colour[1];
142 pvert->colour[2] = src->colour[2];
143 pvert->colour[3] = src->colour[3];
144 v2_copy( src->uv, pvert->uv );
145 }
146
147 for( u32 i=0; i<sm->indice_count; i++ )
148 {
149 u32 *pidx = &pscene->indices[ pscene->indice_count+i ];
150 *pidx = src_indices[i] + pscene->vertex_count;
151 }
152
153 pscene->vertex_count += sm->vertex_count;
154 pscene->indice_count += sm->indice_count;
155 }
156
157 /*
158 * One by one adders for simplified access (mostly procedural stuff)
159 */
160 static void scene_push_tri( scene *pscene, u32 tri[3] )
161 {
162 pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count,
163 &pscene->indice_cap, 3, sizeof(u32) );
164
165 u32 *dst = &pscene->indices[pscene->indice_count];
166 dst[0] = tri[0];
167 dst[1] = tri[1];
168 dst[2] = tri[2];
169
170 pscene->indice_count += 3;
171 }
172
173 static void scene_push_vert( scene *pscene, mdl_vert *v )
174 {
175 pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count,
176 &pscene->vertex_cap, 1, sizeof(mdl_vert) );
177
178 pscene->verts[pscene->vertex_count ++] = *v;
179 }
180
181 static void scene_copy_slice( scene *pscene, mdl_submesh *sm )
182 {
183 sm->indice_start = pscene->submesh.indice_start;
184 sm->indice_count = pscene->indice_count - sm->indice_start;
185
186 sm->vertex_start = pscene->submesh.vertex_start;
187 sm->vertex_count = pscene->vertex_count - sm->vertex_start;
188
189 pscene->submesh.indice_start = pscene->indice_count;
190 pscene->submesh.vertex_start = pscene->vertex_count;
191 }
192
193 static void scene_fix( scene *pscene )
194 {
195 buffer_fix( pscene->verts, pscene->vertex_count,
196 &pscene->vertex_cap, sizeof( mdl_vert ));
197
198 buffer_fix( pscene->indices, pscene->indice_count,
199 &pscene->indice_cap, sizeof( mdl_vert ));
200 }
201
202 static void scene_upload( scene *pscene )
203 {
204 mesh_upload( &pscene->mesh,
205 pscene->verts, pscene->vertex_count,
206 pscene->indices, pscene->indice_count );
207
208 vg_info( "Scene upload\n" );
209 vg_info( " indices:%u\n", pscene->indice_count );
210 vg_info( " verts:%u\n", pscene->vertex_count );
211 }
212
213 static void scene_bind( scene *pscene )
214 {
215 mesh_bind( &pscene->mesh );
216 }
217
218 static void scene_draw( scene *pscene )
219 {
220 mesh_drawn( 0, pscene->indice_count );
221 }
222
223 static void scene_free_offline_buffers( scene *pscene )
224 {
225 free( pscene->verts );
226 free( pscene->indices );
227 }
228
229 static void scene_free( scene *pscene )
230 {
231 scene_free_offline_buffers( pscene );
232 /* TODO: bvh */
233 }
234
235 static void scene_register(void)
236 {
237 }
238
239 /*
240 * BVH implementation
241 */
242
243 static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index )
244 {
245 scene *s = user;
246 mdl_vert *pa = &s->verts[ s->indices[item_index*3+0] ],
247 *pb = &s->verts[ s->indices[item_index*3+1] ],
248 *pc = &s->verts[ s->indices[item_index*3+2] ];
249
250 box_addpt( bound, pa->co );
251 box_addpt( bound, pb->co );
252 box_addpt( bound, pc->co );
253 }
254
255 static float scene_bh_centroid( void *user, u32 item_index, int axis )
256 {
257 scene *s = user;
258 mdl_vert *pa = &s->verts[ s->indices[item_index*3+0] ],
259 *pb = &s->verts[ s->indices[item_index*3+1] ],
260 *pc = &s->verts[ s->indices[item_index*3+2] ];
261
262 return (pa->co[axis] + pb->co[axis] + pc->co[axis]) * (1.0f/3.0f);
263 }
264
265 static void scene_bh_swap( void *user, u32 ia, u32 ib )
266 {
267 scene *s = user;
268
269 u32 *ti = &s->indices[ia*3];
270 u32 *tj = &s->indices[ib*3];
271
272 u32 temp[3];
273 temp[0] = ti[0];
274 temp[1] = ti[1];
275 temp[2] = ti[2];
276
277 ti[0] = tj[0];
278 ti[1] = tj[1];
279 ti[2] = tj[2];
280
281 tj[0] = temp[0];
282 tj[1] = temp[1];
283 tj[2] = temp[2];
284 }
285
286 static void scene_bh_debug( void *user, u32 item_index )
287 {
288 scene *s = user;
289 u32 idx = item_index*3;
290 mdl_vert *pa = &s->verts[ s->indices[ idx+0 ] ],
291 *pb = &s->verts[ s->indices[ idx+1 ] ],
292 *pc = &s->verts[ s->indices[ idx+2 ] ];
293
294 vg_line( pa->co, pb->co, 0xff0000ff );
295 vg_line( pb->co, pc->co, 0xff0000ff );
296 vg_line( pc->co, pa->co, 0xff0000ff );
297 }
298
299 static int scene_bh_ray( void *user, u32 index, v3f co, v3f dir, ray_hit *hit )
300 {
301 scene *s = user;
302 v3f positions[3];
303
304 u32 *tri = &s->indices[ index*3 ];
305
306 for( int i=0; i<3; i++ )
307 v3_copy( s->verts[tri[i]].co, positions[i] );
308
309 float t;
310 if(ray_tri( positions, co, dir, &t ))
311 {
312 if( t < hit->dist )
313 {
314 hit->dist = t;
315 hit->tri = tri;
316 return 1;
317 }
318 }
319
320 return 0;
321 }
322
323 static bh_system bh_system_scene =
324 {
325 .expand_bound = scene_bh_expand_bound,
326 .item_centroid = scene_bh_centroid,
327 .item_swap = scene_bh_swap,
328 .item_debug = scene_bh_debug,
329 .cast_ray = scene_bh_ray
330 };
331
332 /*
333 * An extra step is added onto the end to calculate the hit normal
334 */
335 static int scene_raycast( scene *s, v3f co, v3f dir, ray_hit *hit )
336 {
337 int count = bh_ray( &s->bhtris, 0, co, dir, hit );
338
339 if( count )
340 {
341 v3f v0, v1;
342
343 float *pa = s->verts[hit->tri[0]].co,
344 *pb = s->verts[hit->tri[1]].co,
345 *pc = s->verts[hit->tri[2]].co;
346
347 v3_sub( pa, pb, v0 );
348 v3_sub( pc, pb, v1 );
349 v3_cross( v1, v0, hit->normal );
350 v3_normalize( hit->normal );
351 v3_muladds( co, dir, hit->dist, hit->pos );
352 }
353
354 return count;
355 }
356
357 static void scene_bh_create( scene *s )
358 {
359 u32 triangle_count = s->indice_count / 3;
360 bh_create( &s->bhtris, &bh_system_scene, s, triangle_count );
361 }
362
363 #endif