8 typedef struct scene scene
;
9 typedef struct scene_vert scene_vert
;
13 /* 28 byte vertexs, we don't care about the normals too much,
14 * maybe possible to bring down uv to i16s too */
20 u8 lights
[4]; /* 4*8 */
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 );
262 /* 3: light cluster */
263 glVertexAttribIPointer( 3, 4, GL_UNSIGNED_BYTE
,
264 stride
, (void *)offsetof(scene_vert
, lights
) );
265 glEnableVertexAttribArray( 3 );
269 mesh
->indice_count
= pscene
->indice_count
;
272 vg_info( "Scene upload ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
273 vg_info( " indices:%u\n", pscene
->indice_count
);
274 vg_info( " verts:%u\n", pscene
->vertex_count
);
281 VG_STATIC
void scene_bh_expand_bound( void *user
, boxf bound
, u32 item_index
)
284 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
285 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
286 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
288 box_addpt( bound
, pa
->co
);
289 box_addpt( bound
, pb
->co
);
290 box_addpt( bound
, pc
->co
);
293 VG_STATIC
float scene_bh_centroid( void *user
, u32 item_index
, int axis
)
296 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
297 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
298 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
304 min
= vg_minf( pa
->co
[axis
], pb
->co
[axis
] );
305 max
= vg_maxf( pa
->co
[axis
], pb
->co
[axis
] );
306 min
= vg_minf( min
, pc
->co
[axis
] );
307 max
= vg_maxf( max
, pc
->co
[axis
] );
309 return (min
+max
) * 0.5f
;
312 return (pa
->co
[axis
] + pb
->co
[axis
] + pc
->co
[axis
]) * (1.0f
/3.0f
);
316 VG_STATIC
void scene_bh_swap( void *user
, u32 ia
, u32 ib
)
320 u32
*ti
= &s
->arrindices
[ia
*3];
321 u32
*tj
= &s
->arrindices
[ib
*3];
337 VG_STATIC
void scene_bh_debug( void *user
, u32 item_index
)
340 u32 idx
= item_index
*3;
341 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[ idx
+0 ] ],
342 *pb
= &s
->arrvertices
[ s
->arrindices
[ idx
+1 ] ],
343 *pc
= &s
->arrvertices
[ s
->arrindices
[ idx
+2 ] ];
345 vg_line( pa
->co
, pb
->co
, 0xff0000ff );
346 vg_line( pb
->co
, pc
->co
, 0xff0000ff );
347 vg_line( pc
->co
, pa
->co
, 0xff0000ff );
350 VG_STATIC
int scene_bh_ray( void *user
, u32 index
, v3f co
,
351 v3f dir
, ray_hit
*hit
)
356 u32
*tri
= &s
->arrindices
[ index
*3 ];
358 for( int i
=0; i
<3; i
++ )
359 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
362 if(ray_tri( positions
, co
, dir
, &t
))
375 VG_STATIC
void scene_bh_closest( void *user
, u32 index
, v3f point
, v3f closest
)
380 u32
*tri
= &s
->arrindices
[ index
*3 ];
381 for( int i
=0; i
<3; i
++ )
382 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
384 closest_on_triangle_1( point
, positions
, closest
);
387 VG_STATIC bh_system bh_system_scene
=
389 .expand_bound
= scene_bh_expand_bound
,
390 .item_centroid
= scene_bh_centroid
,
391 .item_closest
= scene_bh_closest
,
392 .item_swap
= scene_bh_swap
,
393 .item_debug
= scene_bh_debug
,
394 .cast_ray
= scene_bh_ray
398 * An extra step is added onto the end to calculate the hit normal
400 VG_STATIC
int scene_raycast( scene
*s
, bh_tree
*bh
,
401 v3f co
, v3f dir
, ray_hit
*hit
)
403 int count
= bh_ray( bh
, co
, dir
, hit
);
409 float *pa
= s
->arrvertices
[hit
->tri
[0]].co
,
410 *pb
= s
->arrvertices
[hit
->tri
[1]].co
,
411 *pc
= s
->arrvertices
[hit
->tri
[2]].co
;
413 v3_sub( pa
, pb
, v0
);
414 v3_sub( pc
, pb
, v1
);
415 v3_cross( v1
, v0
, hit
->normal
);
416 v3_normalize( hit
->normal
);
417 v3_muladds( co
, dir
, hit
->dist
, hit
->pos
);
423 VG_STATIC bh_tree
*scene_bh_create( void *lin_alloc
, scene
*s
)
425 u32 triangle_count
= s
->indice_count
/ 3;
426 return bh_create( lin_alloc
, &bh_system_scene
, s
, triangle_count
, 2 );