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