8 typedef struct scene scene
;
9 typedef struct scene_vert scene_vert
;
13 /* 32 byte vertexs, we don't care about the normals too much,
14 * maybe possible to bring down uv to i16s too */
27 scene_vert
*arrvertices
;
31 u32 vertex_count
, indice_count
,
32 max_vertices
, max_indices
;
38 /* Initialize a scene description with bounded buffers */
39 VG_STATIC scene
*scene_init( void *lin_alloc
, u32 max_verts
, u32 max_indices
)
41 u32 vertex_length
= max_verts
* sizeof(scene_vert
),
42 index_length
= max_indices
* sizeof(u32
),
43 tot_size
= sizeof(scene
) + vertex_length
+ index_length
;
45 scene
*pscene
= vg_linear_alloc( lin_alloc
, tot_size
);
47 pscene
->arrvertices
= (scene_vert
*)(pscene
+1);
48 pscene
->arrindices
= (u32
*)( pscene
->arrvertices
+ max_verts
);
50 pscene
->vertex_count
= 0;
51 pscene
->indice_count
= 0;
52 pscene
->max_vertices
= max_verts
;
53 pscene
->max_indices
= max_indices
;
55 memset( &pscene
->submesh
, 0, sizeof(mdl_submesh
) );
57 v3_fill( pscene
->bbx
[0], 999999.9f
);
58 v3_fill( pscene
->bbx
[1], -999999.9f
);
63 VG_STATIC
void scene_vert_pack_norm( scene_vert
*vert
, v3f norm
)
66 v3_muls( norm
, 127.0f
, n
);
67 v3_minv( n
, (v3f
){ 127.0f
, 127.0f
, 127.0f
}, n
);
68 v3_maxv( n
, (v3f
){ -127.0f
, -127.0f
, -127.0f
}, n
);
72 vert
->norm
[3] = 0; /* free byte :D */
76 * Append a model into the scene with a given transform
78 VG_STATIC
void scene_add_mdl_submesh( scene
*pscene
, mdl_context
*mdl
,
79 mdl_submesh
*sm
, m4x3f transform
)
81 if( pscene
->vertex_count
+ sm
->vertex_count
> pscene
->max_vertices
){
82 vg_error( "%u(current) + %u > %u\n", pscene
->vertex_count
,
84 pscene
->max_vertices
);
86 vg_warn( "%p ... %p\n", pscene
, sm
);
87 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
90 if( pscene
->indice_count
+ sm
->indice_count
> pscene
->max_indices
){
91 vg_error( "%u(current) + %u > %u\n", pscene
->indice_count
,
93 pscene
->max_indices
);
94 vg_warn( "%p ... %p\n", pscene
, sm
);
96 vg_fatal_exit_loop( "Scene index buffer overflow" );
99 mdl_vert
*src_verts
= mdl_arritm( &mdl
->verts
, sm
->vertex_start
);
100 scene_vert
*dst_verts
= &pscene
->arrvertices
[ pscene
->vertex_count
];
102 u32
*src_indices
= mdl_arritm( &mdl
->indices
, sm
->indice_start
),
103 *dst_indices
= &pscene
->arrindices
[ pscene
->indice_count
];
105 /* Transform and place vertices */
107 box_copy( sm
->bbx
, bbxnew
);
108 m4x3_transform_aabb( transform
, bbxnew
);
109 box_concat( pscene
->bbx
, bbxnew
);
112 m3x3_copy( transform
, normal_matrix
);
113 v3_normalize( normal_matrix
[0] );
114 v3_normalize( normal_matrix
[1] );
115 v3_normalize( normal_matrix
[2] );
117 for( u32 i
=0; i
<sm
->vertex_count
; i
++ ){
118 mdl_vert
*src
= &src_verts
[ i
];
119 scene_vert
*pvert
= &dst_verts
[ i
];
121 m4x3_mulv( transform
, src
->co
, pvert
->co
);
124 m3x3_mulv( normal_matrix
, src
->norm
, normal
);
125 scene_vert_pack_norm( pvert
, normal
);
127 v2_copy( src
->uv
, pvert
->uv
);
130 for( u32 i
=0; i
<sm
->indice_count
; i
++ )
131 dst_indices
[i
] = src_indices
[i
] + pscene
->vertex_count
;
133 pscene
->vertex_count
+= sm
->vertex_count
;
134 pscene
->indice_count
+= sm
->indice_count
;
138 * One by one adders for simplified access (mostly procedural stuff)
140 VG_STATIC
void scene_push_tri( scene
*pscene
, u32 tri
[3] )
142 if( pscene
->indice_count
+ 3 > pscene
->max_indices
)
143 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
145 u32
*dst
= &pscene
->arrindices
[ pscene
->indice_count
];
151 pscene
->indice_count
+= 3;
154 VG_STATIC
void scene_push_vert( scene
*pscene
, scene_vert
*v
)
156 if( pscene
->vertex_count
+ 1 > pscene
->max_vertices
)
157 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
159 scene_vert
*dst
= &pscene
->arrvertices
[ pscene
->vertex_count
];
162 pscene
->vertex_count
++;
165 VG_STATIC
void scene_copy_slice( scene
*pscene
, mdl_submesh
*sm
)
167 sm
->indice_start
= pscene
->submesh
.indice_start
;
168 sm
->indice_count
= pscene
->indice_count
- sm
->indice_start
;
170 sm
->vertex_start
= pscene
->submesh
.vertex_start
;
171 sm
->vertex_count
= pscene
->vertex_count
- sm
->vertex_start
;
173 pscene
->submesh
.indice_start
= pscene
->indice_count
;
174 pscene
->submesh
.vertex_start
= pscene
->vertex_count
;
177 /* finalization: tightly pack data */
178 __attribute__((warn_unused_result
))
179 VG_STATIC scene
*scene_fix( void *lin_alloc
, scene
*pscene
)
181 /* FIXME: Why is this disabled? */
183 u32 vertex_count
= pscene
->vertex_count
,
184 indice_count
= pscene
->indice_count
,
185 vertex_length
= vertex_count
* sizeof(scene_vert
),
186 index_length
= indice_count
* sizeof(u32
),
187 tot_size
= vg_align8(sizeof(scene
) + vertex_length
+ index_length
);
189 /* copy down index data */
190 void *dst_indices
= pscene
->arrvertices
+ vertex_count
;
191 memmove( dst_indices
, pscene
->arrindices
, index_length
);
194 pscene
= vg_linear_resize( lin_alloc
, pscene
, tot_size
);
196 pscene
->arrvertices
= (scene_vert
*)(pscene
+1);
197 pscene
->arrindices
= (u32
*)(pscene
->arrvertices
+vertex_count
);
198 pscene
->max_vertices
= vertex_count
;
199 pscene
->max_indices
= indice_count
;
205 /* finalization: delete any offline buffers and reduce size */
206 __attribute__((warn_unused_result
))
207 VG_STATIC scene
*scene_free_offline_buffers( void *lin_alloc
, scene
*pscene
)
209 u32 tot_size
= sizeof(scene
);
211 scene
*src_scene
= pscene
;
212 mdl_vert
*src_verts
= pscene
->arrvertices
;
213 u32
*src_indices
= pscene
->arrindices
;
215 scene
*dst_scene
= vg_linear_resize( lin_alloc
, pscene
, tot_size
);
216 memcpy( dst_scene
, src_scene
, sizeof(scene
) );
218 dst_scene
->arrindices
= NULL
;
219 dst_scene
->arrvertices
= NULL
;
225 VG_STATIC
void scene_upload( scene
*pscene
, glmesh
*mesh
)
227 //assert( mesh->loaded == 0 );
229 glGenVertexArrays( 1, &mesh
->vao
);
230 glGenBuffers( 1, &mesh
->vbo
);
231 glGenBuffers( 1, &mesh
->ebo
);
232 glBindVertexArray( mesh
->vao
);
234 size_t stride
= sizeof(scene_vert
);
236 glBindBuffer( GL_ARRAY_BUFFER
, mesh
->vbo
);
237 glBufferData( GL_ARRAY_BUFFER
, pscene
->vertex_count
*stride
,
238 pscene
->arrvertices
, GL_STATIC_DRAW
);
240 glBindVertexArray( mesh
->vao
);
241 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER
, mesh
->ebo
);
242 glBufferData( GL_ELEMENT_ARRAY_BUFFER
, pscene
->indice_count
*sizeof(u32
),
243 pscene
->arrindices
, GL_STATIC_DRAW
);
246 glVertexAttribPointer( 0, 3, GL_FLOAT
, GL_FALSE
, stride
, (void*)0 );
247 glEnableVertexAttribArray( 0 );
250 glVertexAttribPointer( 1, 4, GL_BYTE
, GL_TRUE
,
251 stride
, (void *)offsetof(scene_vert
, norm
) );
252 glEnableVertexAttribArray( 1 );
255 glVertexAttribPointer( 2, 2, GL_FLOAT
, GL_FALSE
,
256 stride
, (void *)offsetof(scene_vert
, uv
) );
257 glEnableVertexAttribArray( 2 );
260 /* 3: light cluster */
261 glVertexAttribIPointer( 3, 4, GL_UNSIGNED_SHORT
,
262 stride
, (void *)offsetof(scene_vert
, lights
) );
263 glEnableVertexAttribArray( 3 );
268 mesh
->indice_count
= pscene
->indice_count
;
271 vg_info( "Scene upload ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
272 vg_info( " indices:%u\n", pscene
->indice_count
);
273 vg_info( " verts:%u\n", pscene
->vertex_count
);
280 VG_STATIC
void scene_bh_expand_bound( void *user
, boxf bound
, u32 item_index
)
283 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
284 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
285 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
287 box_addpt( bound
, pa
->co
);
288 box_addpt( bound
, pb
->co
);
289 box_addpt( bound
, pc
->co
);
292 VG_STATIC
float scene_bh_centroid( void *user
, u32 item_index
, int axis
)
295 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
296 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
297 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
303 min
= vg_minf( pa
->co
[axis
], pb
->co
[axis
] );
304 max
= vg_maxf( pa
->co
[axis
], pb
->co
[axis
] );
305 min
= vg_minf( min
, pc
->co
[axis
] );
306 max
= vg_maxf( max
, pc
->co
[axis
] );
308 return (min
+max
) * 0.5f
;
311 return (pa
->co
[axis
] + pb
->co
[axis
] + pc
->co
[axis
]) * (1.0f
/3.0f
);
315 VG_STATIC
void scene_bh_swap( void *user
, u32 ia
, u32 ib
)
319 u32
*ti
= &s
->arrindices
[ia
*3];
320 u32
*tj
= &s
->arrindices
[ib
*3];
336 VG_STATIC
void scene_bh_debug( void *user
, u32 item_index
)
339 u32 idx
= item_index
*3;
340 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[ idx
+0 ] ],
341 *pb
= &s
->arrvertices
[ s
->arrindices
[ idx
+1 ] ],
342 *pc
= &s
->arrvertices
[ s
->arrindices
[ idx
+2 ] ];
344 vg_line( pa
->co
, pb
->co
, 0xff0000ff );
345 vg_line( pb
->co
, pc
->co
, 0xff0000ff );
346 vg_line( pc
->co
, pa
->co
, 0xff0000ff );
349 VG_STATIC
int scene_bh_ray( void *user
, u32 index
, v3f co
,
350 v3f dir
, ray_hit
*hit
)
355 u32
*tri
= &s
->arrindices
[ index
*3 ];
357 for( int i
=0; i
<3; i
++ )
358 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
361 if(ray_tri( positions
, co
, dir
, &t
))
374 VG_STATIC
void scene_bh_closest( void *user
, u32 index
, v3f point
, v3f closest
)
379 u32
*tri
= &s
->arrindices
[ index
*3 ];
380 for( int i
=0; i
<3; i
++ )
381 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
383 closest_on_triangle_1( point
, positions
, closest
);
386 VG_STATIC bh_system bh_system_scene
=
388 .expand_bound
= scene_bh_expand_bound
,
389 .item_centroid
= scene_bh_centroid
,
390 .item_closest
= scene_bh_closest
,
391 .item_swap
= scene_bh_swap
,
392 .item_debug
= scene_bh_debug
,
393 .cast_ray
= scene_bh_ray
397 * An extra step is added onto the end to calculate the hit normal
399 VG_STATIC
int scene_raycast( scene
*s
, bh_tree
*bh
,
400 v3f co
, v3f dir
, ray_hit
*hit
)
402 int count
= bh_ray( bh
, co
, dir
, hit
);
408 float *pa
= s
->arrvertices
[hit
->tri
[0]].co
,
409 *pb
= s
->arrvertices
[hit
->tri
[1]].co
,
410 *pc
= s
->arrvertices
[hit
->tri
[2]].co
;
412 v3_sub( pa
, pb
, v0
);
413 v3_sub( pc
, pb
, v1
);
414 v3_cross( v1
, v0
, hit
->normal
);
415 v3_normalize( hit
->normal
);
416 v3_muladds( co
, dir
, hit
->dist
, hit
->pos
);
422 VG_STATIC bh_tree
*scene_bh_create( void *lin_alloc
, scene
*s
)
424 u32 triangle_count
= s
->indice_count
/ 3;
425 return bh_create( lin_alloc
, &bh_system_scene
, s
, triangle_count
, 2 );