8 typedef struct scene_context scene_context
;
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 */
20 u16 flags
; /* only for the cpu. its junk on the gpu */
27 * 1. this should probably be a CONTEXT based approach unlike this mess.
28 * take a bit of the mdl_context ideas and redo this header. its messed up
29 * pretty bad right now.
34 scene_vert
*arrvertices
;
37 u32 vertex_count
, indice_count
,
38 max_vertices
, max_indices
;
44 VG_STATIC u32
scene_mem_required( scene_context
*ctx
)
46 u32 vertex_length
= vg_align8(ctx
->max_vertices
* sizeof(scene_vert
)),
47 index_length
= vg_align8(ctx
->max_indices
* sizeof(u32
));
49 return vertex_length
+ index_length
;
53 void scene_init( scene_context
*ctx
, u32 max_vertices
, u32 max_indices
)
55 ctx
->vertex_count
= 0;
56 ctx
->indice_count
= 0;
57 ctx
->max_vertices
= max_vertices
;
58 ctx
->max_indices
= max_indices
;
59 ctx
->arrindices
= NULL
; /* must be filled out by user */
60 ctx
->arrvertices
= NULL
;
62 memset( &ctx
->submesh
, 0, sizeof(mdl_submesh
) );
64 v3_fill( ctx
->bbx
[0], 999999.9f
);
65 v3_fill( ctx
->bbx
[1], -999999.9f
);
68 void scene_supply_buffer( scene_context
*ctx
, void *buffer
)
70 u32 vertex_length
= vg_align8( ctx
->max_vertices
* sizeof(scene_vert
) );
72 ctx
->arrvertices
= buffer
;
73 ctx
->arrindices
= (u32
*)(((u8
*)buffer
) + vertex_length
);
76 VG_STATIC
void scene_vert_pack_norm( scene_vert
*vert
, v3f norm
)
79 v3_muls( norm
, 127.0f
, n
);
80 v3_minv( n
, (v3f
){ 127.0f
, 127.0f
, 127.0f
}, n
);
81 v3_maxv( n
, (v3f
){ -127.0f
, -127.0f
, -127.0f
}, n
);
85 vert
->norm
[3] = 0; /* free byte :D */
89 * Append a model into the scene with a given transform
91 VG_STATIC
void scene_add_mdl_submesh( scene_context
*ctx
, mdl_context
*mdl
,
92 mdl_submesh
*sm
, m4x3f transform
)
94 if( ctx
->vertex_count
+ sm
->vertex_count
> ctx
->max_vertices
){
95 vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
96 ctx
->vertex_count
+ sm
->vertex_count
,
100 if( ctx
->indice_count
+ sm
->indice_count
> ctx
->max_indices
){
101 vg_fatal_error( "Scene index buffer overflow (%u exceeds %u)\n",
102 ctx
->indice_count
+ sm
->indice_count
,
106 mdl_vert
*src_verts
= mdl_arritm( &mdl
->verts
, sm
->vertex_start
);
107 scene_vert
*dst_verts
= &ctx
->arrvertices
[ ctx
->vertex_count
];
109 u32
*src_indices
= mdl_arritm( &mdl
->indices
, sm
->indice_start
),
110 *dst_indices
= &ctx
->arrindices
[ ctx
->indice_count
];
112 /* Transform and place vertices */
114 box_init_inf( bbxnew
);
115 m4x3_expand_aabb_aabb( transform
, bbxnew
, sm
->bbx
);
116 box_concat( ctx
->bbx
, bbxnew
);
119 m3x3_copy( transform
, normal_matrix
);
120 v3_normalize( normal_matrix
[0] );
121 v3_normalize( normal_matrix
[1] );
122 v3_normalize( normal_matrix
[2] );
124 for( u32 i
=0; i
<sm
->vertex_count
; i
++ ){
125 mdl_vert
*src
= &src_verts
[i
];
126 scene_vert
*pvert
= &dst_verts
[i
];
128 m4x3_mulv( transform
, src
->co
, pvert
->co
);
131 m3x3_mulv( normal_matrix
, src
->norm
, normal
);
132 scene_vert_pack_norm( pvert
, normal
);
134 v2_copy( src
->uv
, pvert
->uv
);
137 u32 real_indices
= 0;
138 for( u32 i
=0; i
<sm
->indice_count
/3; i
++ ){
139 u32
*src
= &src_indices
[i
*3],
140 *dst
= &dst_indices
[real_indices
];
143 v3_sub( src_verts
[src
[2]].co
, src_verts
[src
[0]].co
, ab
);
144 v3_sub( src_verts
[src
[1]].co
, src_verts
[src
[0]].co
, ac
);
145 v3_cross( ac
, ab
, tn
);
148 if( v3_length2( tn
) <= 0.00001f
)
152 dst
[0] = src
[0] + ctx
->vertex_count
;
153 dst
[1] = src
[1] + ctx
->vertex_count
;
154 dst
[2] = src
[2] + ctx
->vertex_count
;
159 if( real_indices
!= sm
->indice_count
)
160 vg_warn( "Zero area triangles in model\n" );
162 ctx
->vertex_count
+= sm
->vertex_count
;
163 ctx
->indice_count
+= real_indices
;
167 * One by one adders for simplified access (mostly procedural stuff)
169 VG_STATIC
void scene_push_tri( scene_context
*ctx
, u32 tri
[3] )
171 if( ctx
->indice_count
+ 3 > ctx
->max_indices
)
172 vg_fatal_error( "Scene indice buffer overflow (%u exceeds %u)\n",
173 ctx
->indice_count
+3, ctx
->max_indices
);
175 u32
*dst
= &ctx
->arrindices
[ ctx
->indice_count
];
181 ctx
->indice_count
+= 3;
184 VG_STATIC
void scene_push_vert( scene_context
*ctx
, scene_vert
*v
)
186 if( ctx
->vertex_count
+ 1 > ctx
->max_vertices
)
187 vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
188 ctx
->vertex_count
+1, ctx
->max_vertices
);
190 scene_vert
*dst
= &ctx
->arrvertices
[ ctx
->vertex_count
];
193 ctx
->vertex_count
++;
196 VG_STATIC
void scene_copy_slice( scene_context
*ctx
, mdl_submesh
*sm
)
198 sm
->indice_start
= ctx
->submesh
.indice_start
;
199 sm
->indice_count
= ctx
->indice_count
- sm
->indice_start
;
201 sm
->vertex_start
= ctx
->submesh
.vertex_start
;
202 sm
->vertex_count
= ctx
->vertex_count
- sm
->vertex_start
;
204 ctx
->submesh
.indice_start
= ctx
->indice_count
;
205 ctx
->submesh
.vertex_start
= ctx
->vertex_count
;
208 VG_STATIC
void scene_set_vertex_flags( scene_context
*ctx
,
209 u32 start
, u32 count
, u16 flags
){
210 for( u32 i
=0; i
<count
; i
++ )
211 ctx
->arrvertices
[ start
+ i
].flags
= flags
;
214 struct scene_upload_info
{
219 VG_STATIC
void async_scene_upload( void *payload
, u32 size
)
221 struct scene_upload_info
*info
= payload
;
223 //assert( mesh->loaded == 0 );
225 glmesh
*mesh
= info
->mesh
;
226 scene_context
*ctx
= info
->ctx
;
228 glGenVertexArrays( 1, &mesh
->vao
);
229 glGenBuffers( 1, &mesh
->vbo
);
230 glGenBuffers( 1, &mesh
->ebo
);
231 glBindVertexArray( mesh
->vao
);
233 size_t stride
= sizeof(scene_vert
);
235 glBindBuffer( GL_ARRAY_BUFFER
, mesh
->vbo
);
236 glBufferData( GL_ARRAY_BUFFER
, ctx
->vertex_count
*stride
,
237 ctx
->arrvertices
, GL_STATIC_DRAW
);
239 glBindVertexArray( mesh
->vao
);
240 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER
, mesh
->ebo
);
241 glBufferData( GL_ELEMENT_ARRAY_BUFFER
, ctx
->indice_count
*sizeof(u32
),
242 ctx
->arrindices
, GL_STATIC_DRAW
);
245 glVertexAttribPointer( 0, 3, GL_FLOAT
, GL_FALSE
, stride
, (void*)0 );
246 glEnableVertexAttribArray( 0 );
249 glVertexAttribPointer( 1, 4, GL_BYTE
, GL_TRUE
,
250 stride
, (void *)offsetof(scene_vert
, norm
) );
251 glEnableVertexAttribArray( 1 );
254 glVertexAttribPointer( 2, 2, GL_FLOAT
, GL_FALSE
,
255 stride
, (void *)offsetof(scene_vert
, uv
) );
256 glEnableVertexAttribArray( 2 );
260 mesh
->indice_count
= ctx
->indice_count
;
263 vg_info( "Scene upload ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
264 vg_info( " indices:%u\n", ctx
->indice_count
);
265 vg_info( " verts:%u\n", ctx
->vertex_count
);
268 VG_STATIC
void scene_upload_async( scene_context
*ctx
, glmesh
*mesh
)
270 vg_async_item
*call
= vg_async_alloc( sizeof(struct scene_upload_info
) );
272 struct scene_upload_info
*info
= call
->payload
;
276 vg_async_dispatch( call
, async_scene_upload
);
280 vg_async_item
*scene_alloc_async( scene_context
*scene
, glmesh
*mesh
,
281 u32 max_vertices
, u32 max_indices
)
283 scene_init( scene
, max_vertices
, max_indices
);
284 u32 buf_size
= scene_mem_required( scene
);
286 u32 hdr_size
= vg_align8(sizeof(struct scene_upload_info
));
287 vg_async_item
*call
= vg_async_alloc( hdr_size
+ buf_size
);
289 struct scene_upload_info
*info
= call
->payload
;
294 void *buffer
= ((u8
*)call
->payload
)+hdr_size
;
295 scene_supply_buffer( scene
, buffer
);
305 VG_STATIC
void scene_bh_expand_bound( void *user
, boxf bound
, u32 item_index
)
307 scene_context
*s
= user
;
308 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
309 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
310 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
312 box_addpt( bound
, pa
->co
);
313 box_addpt( bound
, pb
->co
);
314 box_addpt( bound
, pc
->co
);
317 VG_STATIC
float scene_bh_centroid( void *user
, u32 item_index
, int axis
)
319 scene_context
*s
= user
;
320 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
321 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
322 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
328 min
= vg_minf( pa
->co
[axis
], pb
->co
[axis
] );
329 max
= vg_maxf( pa
->co
[axis
], pb
->co
[axis
] );
330 min
= vg_minf( min
, pc
->co
[axis
] );
331 max
= vg_maxf( max
, pc
->co
[axis
] );
333 return (min
+max
) * 0.5f
;
336 return (pa
->co
[axis
] + pb
->co
[axis
] + pc
->co
[axis
]) * (1.0f
/3.0f
);
340 VG_STATIC
void scene_bh_swap( void *user
, u32 ia
, u32 ib
)
342 scene_context
*s
= user
;
344 u32
*ti
= &s
->arrindices
[ia
*3];
345 u32
*tj
= &s
->arrindices
[ib
*3];
361 VG_STATIC
void scene_bh_debug( void *user
, u32 item_index
)
363 scene_context
*s
= user
;
364 u32 idx
= item_index
*3;
365 scene_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[ idx
+0 ] ],
366 *pb
= &s
->arrvertices
[ s
->arrindices
[ idx
+1 ] ],
367 *pc
= &s
->arrvertices
[ s
->arrindices
[ idx
+2 ] ];
369 vg_line( pa
->co
, pb
->co
, 0xff0000ff );
370 vg_line( pb
->co
, pc
->co
, 0xff0000ff );
371 vg_line( pc
->co
, pa
->co
, 0xff0000ff );
375 VG_STATIC
int scene_bh_ray( void *user
, u32 index
, v3f co
,
376 v3f dir
, ray_hit
*hit
)
378 scene_context
*s
= user
;
381 u32
*tri
= &s
->arrindices
[ index
*3 ];
383 for( int i
=0; i
<3; i
++ )
384 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
387 if(ray_tri( positions
, co
, dir
, &t
)){
399 VG_STATIC
void scene_bh_closest( void *user
, u32 index
, v3f point
, v3f closest
)
401 scene_context
*s
= user
;
404 u32
*tri
= &s
->arrindices
[ index
*3 ];
405 for( int i
=0; i
<3; i
++ )
406 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
408 closest_on_triangle_1( point
, positions
, closest
);
411 VG_STATIC bh_system bh_system_scene
=
413 .expand_bound
= scene_bh_expand_bound
,
414 .item_centroid
= scene_bh_centroid
,
415 .item_closest
= scene_bh_closest
,
416 .item_swap
= scene_bh_swap
,
417 .item_debug
= scene_bh_debug
,
421 * An extra step is added onto the end to calculate the hit normal
423 VG_STATIC
int scene_raycast( scene_context
*s
, bh_tree
*bh
,
424 v3f co
, v3f dir
, ray_hit
*hit
, u16 ignore
)
429 bh_iter_init_ray( 0, &it
, co
, dir
, hit
->dist
);
432 while( bh_next( bh
, &it
, &idx
) ){
433 u32
*tri
= &s
->arrindices
[ idx
*3 ];
435 if( s
->arrvertices
[tri
[0]].flags
& ignore
) continue;
438 for( u32 i
=0; i
<3; i
++ )
439 v3_copy( s
->arrvertices
[tri
[i
]].co
, vs
[i
] );
442 if( ray_tri( vs
, co
, dir
, &t
) ){
453 float *pa
= s
->arrvertices
[hit
->tri
[0]].co
,
454 *pb
= s
->arrvertices
[hit
->tri
[1]].co
,
455 *pc
= s
->arrvertices
[hit
->tri
[2]].co
;
457 v3_sub( pa
, pb
, v0
);
458 v3_sub( pc
, pb
, v1
);
459 v3_cross( v1
, v0
, hit
->normal
);
460 v3_normalize( hit
->normal
);
461 v3_muladds( co
, dir
, hit
->dist
, hit
->pos
);
467 VG_STATIC bh_tree
*scene_bh_create( void *lin_alloc
, scene_context
*s
)
469 u32 triangle_count
= s
->indice_count
/ 3;
470 return bh_create( lin_alloc
, &bh_system_scene
, s
, triangle_count
, 2 );