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
)
83 vg_error( "%u(current) + %u > %u\n", pscene
->vertex_count
,
85 pscene
->max_vertices
);
87 vg_warn( "%p ... %p\n", pscene
, sm
);
88 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
91 if( pscene
->indice_count
+ sm
->indice_count
> pscene
->max_indices
)
93 vg_error( "%u(current) + %u > %u\n", pscene
->indice_count
,
95 pscene
->max_indices
);
96 vg_warn( "%p ... %p\n", pscene
, sm
);
98 vg_fatal_exit_loop( "Scene index buffer overflow" );
101 mdl_vert
*src_verts
= mdl_submesh_vertices( mdl
, sm
);
102 scene_vert
*dst_verts
= &pscene
->arrvertices
[ pscene
->vertex_count
];
104 u32
*src_indices
= mdl_submesh_indices( mdl
, sm
),
105 *dst_indices
= &pscene
->arrindices
[ pscene
->indice_count
];
107 /* Transform and place vertices */
109 box_copy( sm
->bbx
, bbxnew
);
110 m4x3_transform_aabb( transform
, bbxnew
);
111 box_concat( pscene
->bbx
, bbxnew
);
114 m3x3_copy( transform
, normal_matrix
);
115 v3_normalize( normal_matrix
[0] );
116 v3_normalize( normal_matrix
[1] );
117 v3_normalize( normal_matrix
[2] );
119 for( u32 i
=0; i
<sm
->vertex_count
; i
++ )
121 mdl_vert
*src
= &src_verts
[ i
];
122 scene_vert
*pvert
= &dst_verts
[ i
];
124 m4x3_mulv( transform
, src
->co
, pvert
->co
);
127 m3x3_mulv( normal_matrix
, src
->norm
, normal
);
128 scene_vert_pack_norm( pvert
, normal
);
130 v2_copy( src
->uv
, pvert
->uv
);
133 for( u32 i
=0; i
<sm
->indice_count
; i
++ )
134 dst_indices
[i
] = src_indices
[i
] + pscene
->vertex_count
;
136 pscene
->vertex_count
+= sm
->vertex_count
;
137 pscene
->indice_count
+= sm
->indice_count
;
141 * One by one adders for simplified access (mostly procedural stuff)
143 VG_STATIC
void scene_push_tri( scene
*pscene
, u32 tri
[3] )
145 if( pscene
->indice_count
+ 3 > pscene
->max_indices
)
146 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
148 u32
*dst
= &pscene
->arrindices
[ pscene
->indice_count
];
154 pscene
->indice_count
+= 3;
157 VG_STATIC
void scene_push_vert( scene
*pscene
, scene_vert
*v
)
159 if( pscene
->vertex_count
+ 1 > pscene
->max_vertices
)
160 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
162 scene_vert
*dst
= &pscene
->arrvertices
[ pscene
->vertex_count
];
165 pscene
->vertex_count
++;
168 VG_STATIC
void scene_copy_slice( scene
*pscene
, mdl_submesh
*sm
)
170 sm
->indice_start
= pscene
->submesh
.indice_start
;
171 sm
->indice_count
= pscene
->indice_count
- sm
->indice_start
;
173 sm
->vertex_start
= pscene
->submesh
.vertex_start
;
174 sm
->vertex_count
= pscene
->vertex_count
- sm
->vertex_start
;
176 pscene
->submesh
.indice_start
= pscene
->indice_count
;
177 pscene
->submesh
.vertex_start
= pscene
->vertex_count
;
180 /* finalization: tightly pack data */
181 __attribute__((warn_unused_result
))
182 VG_STATIC scene
*scene_fix( void *lin_alloc
, scene
*pscene
)
184 /* FIXME: Why is this disabled? */
186 u32 vertex_count
= pscene
->vertex_count
,
187 indice_count
= pscene
->indice_count
,
188 vertex_length
= vertex_count
* sizeof(scene_vert
),
189 index_length
= indice_count
* sizeof(u32
),
190 tot_size
= sizeof(scene
) + vertex_length
+ index_length
;
192 /* copy down index data */
193 void *dst_indices
= pscene
->arrvertices
+ vertex_count
;
194 memmove( dst_indices
, pscene
->arrindices
, index_length
);
197 pscene
= vg_linear_resize( lin_alloc
, pscene
, tot_size
);
199 pscene
->arrvertices
= (scene_vert
*)(pscene
+1);
200 pscene
->arrindices
= (u32
*)(pscene
->arrvertices
+vertex_count
);
201 pscene
->max_vertices
= vertex_count
;
202 pscene
->max_indices
= indice_count
;
208 /* finalization: delete any offline buffers and reduce size */
209 __attribute__((warn_unused_result
))
210 VG_STATIC scene
*scene_free_offline_buffers( void *lin_alloc
, scene
*pscene
)
212 u32 tot_size
= sizeof(scene
);
214 scene
*src_scene
= pscene
;
215 mdl_vert
*src_verts
= pscene
->arrvertices
;
216 u32
*src_indices
= pscene
->arrindices
;
218 scene
*dst_scene
= vg_linear_resize( lin_alloc
, pscene
, tot_size
);
219 memcpy( dst_scene
, src_scene
, sizeof(scene
) );
221 dst_scene
->arrindices
= NULL
;
222 dst_scene
->arrvertices
= NULL
;
228 VG_STATIC
void scene_upload( scene
*pscene
, glmesh
*mesh
)
230 //assert( mesh->loaded == 0 );
232 glGenVertexArrays( 1, &mesh
->vao
);
233 glGenBuffers( 1, &mesh
->vbo
);
234 glGenBuffers( 1, &mesh
->ebo
);
235 glBindVertexArray( mesh
->vao
);
237 size_t stride
= sizeof(scene_vert
);
239 glBindBuffer( GL_ARRAY_BUFFER
, mesh
->vbo
);
240 glBufferData( GL_ARRAY_BUFFER
, pscene
->vertex_count
*stride
,
241 pscene
->arrvertices
, GL_STATIC_DRAW
);
243 glBindVertexArray( mesh
->vao
);
244 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER
, mesh
->ebo
);
245 glBufferData( GL_ELEMENT_ARRAY_BUFFER
, pscene
->indice_count
*sizeof(u32
),
246 pscene
->arrindices
, GL_STATIC_DRAW
);
249 glVertexAttribPointer( 0, 3, GL_FLOAT
, GL_FALSE
, stride
, (void*)0 );
250 glEnableVertexAttribArray( 0 );
253 glVertexAttribPointer( 1, 3, GL_BYTE
, GL_TRUE
,
254 stride
, (void *)offsetof(scene_vert
, norm
) );
255 glEnableVertexAttribArray( 1 );
258 glVertexAttribPointer( 2, 2, GL_FLOAT
, GL_FALSE
,
259 stride
, (void *)offsetof(scene_vert
, uv
) );
260 glEnableVertexAttribArray( 2 );
263 /* 3: light cluster */
264 glVertexAttribIPointer( 3, 4, GL_UNSIGNED_SHORT
,
265 stride
, (void *)offsetof(scene_vert
, lights
) );
266 glEnableVertexAttribArray( 3 );
271 mesh
->indice_count
= pscene
->indice_count
;
274 vg_info( "Scene upload ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
275 vg_info( " indices:%u\n", pscene
->indice_count
);
276 vg_info( " verts:%u\n", pscene
->vertex_count
);
283 VG_STATIC
void scene_bh_expand_bound( void *user
, boxf bound
, u32 item_index
)
286 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
287 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
288 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
290 box_addpt( bound
, pa
->co
);
291 box_addpt( bound
, pb
->co
);
292 box_addpt( bound
, pc
->co
);
295 VG_STATIC
float scene_bh_centroid( void *user
, u32 item_index
, int axis
)
298 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
299 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
300 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
306 min
= vg_minf( pa
->co
[axis
], pb
->co
[axis
] );
307 max
= vg_maxf( pa
->co
[axis
], pb
->co
[axis
] );
308 min
= vg_minf( min
, pc
->co
[axis
] );
309 max
= vg_maxf( max
, pc
->co
[axis
] );
311 return (min
+max
) * 0.5f
;
314 return (pa
->co
[axis
] + pb
->co
[axis
] + pc
->co
[axis
]) * (1.0f
/3.0f
);
318 VG_STATIC
void scene_bh_swap( void *user
, u32 ia
, u32 ib
)
322 u32
*ti
= &s
->arrindices
[ia
*3];
323 u32
*tj
= &s
->arrindices
[ib
*3];
339 VG_STATIC
void scene_bh_debug( void *user
, u32 item_index
)
342 u32 idx
= item_index
*3;
343 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[ idx
+0 ] ],
344 *pb
= &s
->arrvertices
[ s
->arrindices
[ idx
+1 ] ],
345 *pc
= &s
->arrvertices
[ s
->arrindices
[ idx
+2 ] ];
347 vg_line( pa
->co
, pb
->co
, 0xff0000ff );
348 vg_line( pb
->co
, pc
->co
, 0xff0000ff );
349 vg_line( pc
->co
, pa
->co
, 0xff0000ff );
352 VG_STATIC
int scene_bh_ray( void *user
, u32 index
, v3f co
,
353 v3f dir
, ray_hit
*hit
)
358 u32
*tri
= &s
->arrindices
[ index
*3 ];
360 for( int i
=0; i
<3; i
++ )
361 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
364 if(ray_tri( positions
, co
, dir
, &t
))
377 VG_STATIC
void scene_bh_closest( void *user
, u32 index
, v3f point
, v3f closest
)
382 u32
*tri
= &s
->arrindices
[ index
*3 ];
383 for( int i
=0; i
<3; i
++ )
384 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
386 closest_on_triangle_1( point
, positions
, closest
);
389 VG_STATIC bh_system bh_system_scene
=
391 .expand_bound
= scene_bh_expand_bound
,
392 .item_centroid
= scene_bh_centroid
,
393 .item_closest
= scene_bh_closest
,
394 .item_swap
= scene_bh_swap
,
395 .item_debug
= scene_bh_debug
,
396 .cast_ray
= scene_bh_ray
400 * An extra step is added onto the end to calculate the hit normal
402 VG_STATIC
int scene_raycast( scene
*s
, bh_tree
*bh
,
403 v3f co
, v3f dir
, ray_hit
*hit
)
405 int count
= bh_ray( bh
, co
, dir
, hit
);
411 float *pa
= s
->arrvertices
[hit
->tri
[0]].co
,
412 *pb
= s
->arrvertices
[hit
->tri
[1]].co
,
413 *pc
= s
->arrvertices
[hit
->tri
[2]].co
;
415 v3_sub( pa
, pb
, v0
);
416 v3_sub( pc
, pb
, v1
);
417 v3_cross( v1
, v0
, hit
->normal
);
418 v3_normalize( hit
->normal
);
419 v3_muladds( co
, dir
, hit
->dist
, hit
->pos
);
425 VG_STATIC bh_tree
*scene_bh_create( void *lin_alloc
, scene
*s
)
427 u32 triangle_count
= s
->indice_count
/ 3;
428 return bh_create( lin_alloc
, &bh_system_scene
, s
, triangle_count
, 2 );