dont remember
[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
174 /*
175 * BVH implementation
176 */
177
178 static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index )
179 {
180 scene *s = user;
181 mdl_vert *pa = &s->verts[ s->indices[item_index*3+0] ],
182 *pb = &s->verts[ s->indices[item_index*3+1] ],
183 *pc = &s->verts[ s->indices[item_index*3+2] ];
184
185 box_addpt( bound, pa->co );
186 box_addpt( bound, pb->co );
187 box_addpt( bound, pc->co );
188 }
189
190 static float scene_bh_centroid( void *user, u32 item_index, int axis )
191 {
192 scene *s = user;
193 mdl_vert *pa = &s->verts[ s->indices[item_index*3+0] ],
194 *pb = &s->verts[ s->indices[item_index*3+1] ],
195 *pc = &s->verts[ s->indices[item_index*3+2] ];
196
197 return (pa->co[axis] + pb->co[axis] + pc->co[axis]) * (1.0f/3.0f);
198 }
199
200 static void scene_bh_swap( void *user, u32 ia, u32 ib )
201 {
202 scene *s = user;
203
204 u32 *ti = &s->indices[ia*3];
205 u32 *tj = &s->indices[ib*3];
206
207 u32 temp[3];
208 temp[0] = ti[0];
209 temp[1] = ti[1];
210 temp[2] = ti[2];
211
212 ti[0] = tj[0];
213 ti[1] = tj[1];
214 ti[2] = tj[2];
215
216 tj[0] = temp[0];
217 tj[1] = temp[1];
218 tj[2] = temp[2];
219 }
220
221 static void scene_bh_debug( void *user, u32 item_index )
222 {
223 scene *s = user;
224 u32 idx = item_index*3;
225 mdl_vert *pa = &s->verts[ s->indices[ idx+0 ] ],
226 *pb = &s->verts[ s->indices[ idx+1 ] ],
227 *pc = &s->verts[ s->indices[ idx+2 ] ];
228
229 vg_line( pa->co, pb->co, 0xff0000ff );
230 vg_line( pb->co, pc->co, 0xff0000ff );
231 vg_line( pc->co, pa->co, 0xff0000ff );
232 }
233
234 static int scene_bh_ray( void *user, u32 index, v3f co, v3f dir, ray_hit *hit )
235 {
236 scene *s = user;
237 v3f positions[3];
238
239 u32 *tri = &s->indices[ index*3 ];
240
241 for( int i=0; i<3; i++ )
242 v3_copy( s->verts[tri[i]].co, positions[i] );
243
244 float t;
245 if(ray_tri( positions, co, dir, &t ))
246 {
247 if( t < hit->dist )
248 {
249 hit->dist = t;
250 hit->tri = tri;
251 return 1;
252 }
253 }
254
255 return 0;
256 }
257
258 static bh_system bh_system_scene =
259 {
260 .expand_bound = scene_bh_expand_bound,
261 .item_centroid = scene_bh_centroid,
262 .item_swap = scene_bh_swap,
263 .item_debug = scene_bh_debug,
264 .cast_ray = scene_bh_ray
265 };
266
267 /*
268 * An extra step is added onto the end to calculate the hit normal
269 */
270 static int scene_raycast( scene *s, v3f co, v3f dir, ray_hit *hit )
271 {
272 int count = bh_ray( &s->bhtris, 0, co, dir, hit );
273
274 if( count )
275 {
276 v3f v0, v1;
277
278 float *pa = s->verts[hit->tri[0]].co,
279 *pb = s->verts[hit->tri[1]].co,
280 *pc = s->verts[hit->tri[2]].co;
281
282 v3_sub( pa, pb, v0 );
283 v3_sub( pc, pb, v1 );
284 v3_cross( v1, v0, hit->normal );
285 v3_normalize( hit->normal );
286 v3_muladds( co, dir, hit->dist, hit->pos );
287 }
288
289 return count;
290 }
291
292 static void scene_bh_create( scene *s )
293 {
294 u32 triangle_count = s->indice_count / 3;
295 bh_create( &s->bhtris, &bh_system_scene, s, triangle_count );
296 }
297
298 #endif