8 typedef struct scene scene
;
12 mdl_vert
*arrvertices
;
15 u32 vertex_count
, indice_count
,
16 max_vertices
, max_indices
;
22 /* Initialize a scene description with bounded buffers */
23 VG_STATIC scene
*scene_init( void *lin_alloc
, u32 max_verts
, u32 max_indices
)
25 u32 vertex_length
= max_verts
* sizeof(mdl_vert
),
26 index_length
= max_indices
* sizeof(u32
),
27 tot_size
= sizeof(scene
) + vertex_length
+ index_length
;
29 scene
*pscene
= vg_linear_alloc( lin_alloc
, tot_size
);
31 pscene
->arrvertices
= (mdl_vert
*)(pscene
+1);
32 pscene
->arrindices
= (u32
*)( pscene
->arrvertices
+ max_verts
);
34 pscene
->vertex_count
= 0;
35 pscene
->indice_count
= 0;
36 pscene
->max_vertices
= max_verts
;
37 pscene
->max_indices
= max_indices
;
39 memset( &pscene
->submesh
, 0, sizeof(mdl_submesh
) );
41 v3_fill( pscene
->bbx
[0], 999999.9f
);
42 v3_fill( pscene
->bbx
[1], -999999.9f
);
48 * Append a model into the scene with a given transform
50 VG_STATIC
void scene_add_submesh( scene
*pscene
, mdl_context
*mdl
,
51 mdl_submesh
*sm
, m4x3f transform
)
53 if( pscene
->vertex_count
+ sm
->vertex_count
> pscene
->max_vertices
)
55 vg_error( "%u(current) + %u > %u\n", pscene
->vertex_count
,
57 pscene
->max_vertices
);
59 vg_warn( "%p ... %p\n", pscene
, sm
);
60 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
63 if( pscene
->indice_count
+ sm
->indice_count
> pscene
->max_indices
)
65 vg_error( "%u(current) + %u > %u\n", pscene
->indice_count
,
67 pscene
->max_indices
);
68 vg_warn( "%p ... %p\n", pscene
, sm
);
70 vg_fatal_exit_loop( "Scene index buffer overflow" );
73 mdl_vert
*src_verts
= mdl_submesh_vertices( mdl
, sm
),
74 *dst_verts
= &pscene
->arrvertices
[ pscene
->vertex_count
];
76 u32
*src_indices
= mdl_submesh_indices( mdl
, sm
),
77 *dst_indices
= &pscene
->arrindices
[ pscene
->indice_count
];
79 /* Transform and place vertices */
81 box_copy( sm
->bbx
, bbxnew
);
82 m4x3_transform_aabb( transform
, bbxnew
);
83 box_concat( pscene
->bbx
, bbxnew
);
86 m3x3_copy( transform
, normal_matrix
);
87 v3_normalize( normal_matrix
[0] );
88 v3_normalize( normal_matrix
[1] );
89 v3_normalize( normal_matrix
[2] );
91 for( u32 i
=0; i
<sm
->vertex_count
; i
++ )
93 mdl_vert
*pvert
= &dst_verts
[ i
],
94 *src
= &src_verts
[ i
];
96 m4x3_mulv( transform
, src
->co
, pvert
->co
);
97 m3x3_mulv( normal_matrix
, src
->norm
, pvert
->norm
);
99 pvert
->colour
[0] = src
->colour
[0];
100 pvert
->colour
[1] = src
->colour
[1];
101 pvert
->colour
[2] = src
->colour
[2];
102 pvert
->colour
[3] = src
->colour
[3];
103 pvert
->weights
[0] = src
->weights
[0];
104 pvert
->weights
[1] = src
->weights
[1];
105 pvert
->weights
[2] = src
->weights
[2];
106 pvert
->weights
[3] = src
->weights
[3];
107 v2_copy( src
->uv
, pvert
->uv
);
110 for( u32 i
=0; i
<sm
->indice_count
; i
++ )
112 dst_indices
[i
] = src_indices
[i
] + pscene
->vertex_count
;
115 pscene
->vertex_count
+= sm
->vertex_count
;
116 pscene
->indice_count
+= sm
->indice_count
;
120 * One by one adders for simplified access (mostly procedural stuff)
122 VG_STATIC
void scene_push_tri( scene
*pscene
, u32 tri
[3] )
124 if( pscene
->indice_count
+ 3 > pscene
->max_indices
)
125 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
127 u32
*dst
= &pscene
->arrindices
[ pscene
->indice_count
];
133 pscene
->indice_count
+= 3;
136 VG_STATIC
void scene_push_vert( scene
*pscene
, mdl_vert
*v
)
138 if( pscene
->vertex_count
+ 1 > pscene
->max_vertices
)
139 vg_fatal_exit_loop( "Scene vertex buffer overflow" );
141 mdl_vert
*dst
= &pscene
->arrvertices
[ pscene
->vertex_count
];
144 pscene
->vertex_count
++;
147 VG_STATIC
void scene_copy_slice( scene
*pscene
, mdl_submesh
*sm
)
149 sm
->indice_start
= pscene
->submesh
.indice_start
;
150 sm
->indice_count
= pscene
->indice_count
- sm
->indice_start
;
152 sm
->vertex_start
= pscene
->submesh
.vertex_start
;
153 sm
->vertex_count
= pscene
->vertex_count
- sm
->vertex_start
;
155 pscene
->submesh
.indice_start
= pscene
->indice_count
;
156 pscene
->submesh
.vertex_start
= pscene
->vertex_count
;
159 /* finalization: tightly pack data */
160 __attribute__((warn_unused_result
))
161 VG_STATIC scene
*scene_fix( void *lin_alloc
, scene
*pscene
)
164 u32 vertex_count
= pscene
->vertex_count
,
165 indice_count
= pscene
->indice_count
,
166 vertex_length
= vertex_count
* sizeof(mdl_vert
),
167 index_length
= indice_count
* sizeof(u32
),
168 tot_size
= sizeof(scene
) + vertex_length
+ index_length
;
170 /* copy down index data */
171 void *dst_indices
= pscene
->arrvertices
+ vertex_length
;
172 memmove( dst_indices
, pscene
->arrindices
, index_length
);
175 pscene
= vg_linear_resize( lin_alloc
, pscene
, tot_size
);
177 pscene
->arrvertices
= (mdl_vert
*)(pscene
+1);
178 pscene
->arrindices
= (u32
*)(pscene
->arrvertices
+vertex_count
);
179 pscene
->max_vertices
= vertex_count
;
180 pscene
->max_indices
= indice_count
;
186 /* finalization: delete any offline buffers and reduce size */
187 __attribute__((warn_unused_result
))
188 VG_STATIC scene
*scene_free_offline_buffers( void *lin_alloc
, scene
*pscene
)
190 u32 tot_size
= sizeof(scene
);
192 scene
*src_scene
= pscene
;
193 mdl_vert
*src_verts
= pscene
->arrvertices
;
194 u32
*src_indices
= pscene
->arrindices
;
196 scene
*dst_scene
= vg_linear_resize( lin_alloc
, pscene
, tot_size
);
197 memcpy( dst_scene
, src_scene
, sizeof(scene
) );
199 dst_scene
->arrindices
= NULL
;
200 dst_scene
->arrvertices
= NULL
;
206 VG_STATIC
void scene_upload( scene
*pscene
, glmesh
*mesh
)
209 pscene
->arrvertices
, pscene
->vertex_count
,
210 pscene
->arrindices
, pscene
->indice_count
);
212 vg_info( "Scene upload\n" );
213 vg_info( " indices:%u\n", pscene
->indice_count
);
214 vg_info( " verts:%u\n", pscene
->vertex_count
);
221 VG_STATIC
void scene_bh_expand_bound( void *user
, boxf bound
, u32 item_index
)
224 mdl_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
225 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
226 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
228 box_addpt( bound
, pa
->co
);
229 box_addpt( bound
, pb
->co
);
230 box_addpt( bound
, pc
->co
);
233 VG_STATIC
float scene_bh_centroid( void *user
, u32 item_index
, int axis
)
236 mdl_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+0] ],
237 *pb
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+1] ],
238 *pc
= &s
->arrvertices
[ s
->arrindices
[item_index
*3+2] ];
240 return (pa
->co
[axis
] + pb
->co
[axis
] + pc
->co
[axis
]) * (1.0f
/3.0f
);
243 VG_STATIC
void scene_bh_swap( void *user
, u32 ia
, u32 ib
)
247 u32
*ti
= &s
->arrindices
[ia
*3];
248 u32
*tj
= &s
->arrindices
[ib
*3];
264 VG_STATIC
void scene_bh_debug( void *user
, u32 item_index
)
267 u32 idx
= item_index
*3;
268 mdl_vert
*pa
= &s
->arrvertices
[ s
->arrindices
[ idx
+0 ] ],
269 *pb
= &s
->arrvertices
[ s
->arrindices
[ idx
+1 ] ],
270 *pc
= &s
->arrvertices
[ s
->arrindices
[ idx
+2 ] ];
272 vg_line( pa
->co
, pb
->co
, 0xff0000ff );
273 vg_line( pb
->co
, pc
->co
, 0xff0000ff );
274 vg_line( pc
->co
, pa
->co
, 0xff0000ff );
277 VG_STATIC
int scene_bh_ray( void *user
, u32 index
, v3f co
,
278 v3f dir
, ray_hit
*hit
)
283 u32
*tri
= &s
->arrindices
[ index
*3 ];
285 for( int i
=0; i
<3; i
++ )
286 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
289 if(ray_tri( positions
, co
, dir
, &t
))
302 VG_STATIC
void scene_bh_closest( void *user
, u32 index
, v3f point
, v3f closest
)
307 u32
*tri
= &s
->arrindices
[ index
*3 ];
308 for( int i
=0; i
<3; i
++ )
309 v3_copy( s
->arrvertices
[tri
[i
]].co
, positions
[i
] );
311 closest_on_triangle_1( point
, positions
, closest
);
314 VG_STATIC bh_system bh_system_scene
=
316 .expand_bound
= scene_bh_expand_bound
,
317 .item_centroid
= scene_bh_centroid
,
318 .item_closest
= scene_bh_closest
,
319 .item_swap
= scene_bh_swap
,
320 .item_debug
= scene_bh_debug
,
321 .cast_ray
= scene_bh_ray
325 * An extra step is added onto the end to calculate the hit normal
327 VG_STATIC
int scene_raycast( scene
*s
, bh_tree
*bh
,
328 v3f co
, v3f dir
, ray_hit
*hit
)
330 int count
= bh_ray( bh
, co
, dir
, hit
);
336 float *pa
= s
->arrvertices
[hit
->tri
[0]].co
,
337 *pb
= s
->arrvertices
[hit
->tri
[1]].co
,
338 *pc
= s
->arrvertices
[hit
->tri
[2]].co
;
340 v3_sub( pa
, pb
, v0
);
341 v3_sub( pc
, pb
, v1
);
342 v3_cross( v1
, v0
, hit
->normal
);
343 v3_normalize( hit
->normal
);
344 v3_muladds( co
, dir
, hit
->dist
, hit
->pos
);
350 VG_STATIC bh_tree
*scene_bh_create( void *lin_alloc
, scene
*s
)
352 u32 triangle_count
= s
->indice_count
/ 3;
353 return bh_create( lin_alloc
, &bh_system_scene
, s
, triangle_count
, 2 );