cleanup: Attribute Loading

This commit is contained in:
Anish Bhobe 2025-06-30 19:57:44 +02:00
parent afec17cb0f
commit 9314b3504e
5 changed files with 81 additions and 112 deletions

View File

@ -46,8 +46,7 @@ SDL_AppResult SDL_AppInit( void** appstate, int, char** )
AppState& appState = *static_cast<AppState*>( *appstate ); AppState& appState = *static_cast<AppState*>( *appstate );
Entity const* entity = Entity const* entity = LoadModel( appState.renderDevice, appState.entityManager, "Assets/Models/DamagedHelmet.glb" );
LoadModel( appState.renderDevice, appState.entityManager, "Assets/Models/OrientationTest.glb" );
ASSERT( entity ); ASSERT( entity );
std::array pointLight = { std::array pointLight = {

View File

@ -36,3 +36,5 @@
while ( false ) while ( false )
#define Take( OBJ ) std::exchange( OBJ, {} ) #define Take( OBJ ) std::exchange( OBJ, {} )
#define UNREACHABLE G_ASSERT( false )

View File

@ -289,7 +289,7 @@ bool MiscData::init( RenderDevice const& renderDevice )
// Camera // Camera
{ {
cameraData.cameraPosition = DirectX::XMVectorSet( 0.0f, 20.0f, -20.0f, 1.0f ); cameraData.cameraPosition = DirectX::XMVectorSet( 0.0f, 2.0f, -2.0f, 1.0f );
cameraTarget = DirectX::XMVectorSet( 0.0f, 0.0f, 0.0f, 1.0f ); cameraTarget = DirectX::XMVectorSet( 0.0f, 0.0f, 0.0f, 1.0f );
cameraUp = DirectX::XMVectorSet( 0.0f, 1.0f, 0.0f, 1.0f ); cameraUp = DirectX::XMVectorSet( 0.0f, 1.0f, 0.0f, 1.0f );
cameraData.viewMatrix = DirectX::XMMatrixLookAtLH( cameraData.cameraPosition, cameraTarget, cameraUp ); cameraData.viewMatrix = DirectX::XMMatrixLookAtLH( cameraData.cameraPosition, cameraTarget, cameraUp );

View File

@ -443,12 +443,42 @@ uint32_t ProcessMaterial( RenderDevice* renderDevice, Model* model, cgltf_materi
return materialIdx; return materialIdx;
} }
void LoadAttribute(
std::vector<Vertex>* pVertices,
int32_t const vertexStart,
std::vector<float>* scratch,
cgltf_attribute const& positionAttr,
size_t const stride,
size_t const offset,
size_t const components )
{
size_t const floatCount = cgltf_accessor_unpack_floats( positionAttr.data, nullptr, 0 );
ASSERT( floatCount % 3 == 0 );
scratch->resize( floatCount );
cgltf_accessor_unpack_floats( positionAttr.data, scratch->data(), scratch->size() );
// Guaranteed to have space for these vertices.
pVertices->resize( vertexStart + floatCount / components );
byte* writePtr = reinterpret_cast<byte*>( pVertices->data() + vertexStart ) + offset;
float* readPtr = scratch->data();
for ( size_t i = vertexStart; i < pVertices->size(); ++i )
{
memcpy( writePtr, readPtr, components * sizeof( float ) );
readPtr += components;
writePtr += stride;
}
scratch->clear();
}
ModelMesh ProcessMesh( ModelMesh ProcessMesh(
RenderDevice* renderDevice, RenderDevice* renderDevice,
Model* model, Model* model,
std::pmr::vector<Vertex>* pVertices, std::vector<Vertex>* pVertices,
std::pmr::vector<uint32_t>* pIndices, std::vector<uint32_t>* pIndices,
cgltf_mesh const& mesh ) cgltf_mesh const& mesh )
{ {
using namespace std::string_view_literals; using namespace std::string_view_literals;
@ -488,6 +518,8 @@ ModelMesh ProcessMesh(
.vertexOffset = vertexStart, .vertexOffset = vertexStart,
} ); } );
std::vector<float> scratch;
cgltf_attribute const* attributes = primitive.attributes; cgltf_attribute const* attributes = primitive.attributes;
for ( uint32_t attribIndex = 0; attribIndex < primitive.attributes_count; ++attribIndex ) for ( uint32_t attribIndex = 0; attribIndex < primitive.attributes_count; ++attribIndex )
{ {
@ -497,22 +529,11 @@ ModelMesh ProcessMesh(
ASSERT( positionAttr.data->component_type == cgltf_component_type_r_32f ); ASSERT( positionAttr.data->component_type == cgltf_component_type_r_32f );
ASSERT( positionAttr.data->type == cgltf_type_vec3 ); ASSERT( positionAttr.data->type == cgltf_type_vec3 );
std::pmr::vector<DirectX::XMFLOAT3> positions{ pVertices->get_allocator() }; size_t constexpr stride = sizeof( Vertex );
size_t constexpr offset = offsetof( Vertex, position );
size_t constexpr components = 3;
size_t const floatCount = cgltf_accessor_unpack_floats( positionAttr.data, nullptr, 0 ); LoadAttribute( pVertices, vertexStart, &scratch, positionAttr, stride, offset, components );
positions.resize( floatCount / 3 );
cgltf_accessor_unpack_floats(
positionAttr.data, reinterpret_cast<cgltf_float*>( positions.data() ), floatCount );
// Guaranteed to have space for these vertices.
pVertices->resize( vertexStart + positions.size() );
auto vertexIter = pVertices->begin() + vertexStart;
for ( DirectX::XMFLOAT3 const& position : positions )
{
vertexIter->position = position;
++vertexIter;
}
} }
if ( "NORMAL"sv == attributes[attribIndex].name ) if ( "NORMAL"sv == attributes[attribIndex].name )
{ {
@ -520,21 +541,11 @@ ModelMesh ProcessMesh(
ASSERT( normalAttr.data->component_type == cgltf_component_type_r_32f ); ASSERT( normalAttr.data->component_type == cgltf_component_type_r_32f );
ASSERT( normalAttr.data->type == cgltf_type_vec3 ); ASSERT( normalAttr.data->type == cgltf_type_vec3 );
std::pmr::vector<DirectX::XMFLOAT3> normals{ pVertices->get_allocator() }; size_t constexpr stride = sizeof( Vertex );
size_t constexpr offset = offsetof( Vertex, normal );
size_t constexpr components = 3;
size_t const floatCount = cgltf_accessor_unpack_floats( normalAttr.data, nullptr, 0 ); LoadAttribute( pVertices, vertexStart, &scratch, normalAttr, stride, offset, components );
normals.resize( floatCount / 3 );
cgltf_accessor_unpack_floats( normalAttr.data, reinterpret_cast<cgltf_float*>( normals.data() ), floatCount );
// Guaranteed to have space for these vertices.
pVertices->resize( vertexStart + normals.size() );
auto vertexIter = pVertices->begin() + vertexStart;
for ( DirectX::XMFLOAT3 const& normal : normals )
{
vertexIter->normal = normal;
++vertexIter;
}
} }
if ( "TEXCOORD_0"sv == attributes[attribIndex].name ) if ( "TEXCOORD_0"sv == attributes[attribIndex].name )
{ {
@ -542,22 +553,11 @@ ModelMesh ProcessMesh(
ASSERT( texCoordAttr.data->component_type == cgltf_component_type_r_32f ); ASSERT( texCoordAttr.data->component_type == cgltf_component_type_r_32f );
ASSERT( texCoordAttr.data->type == cgltf_type_vec2 ); ASSERT( texCoordAttr.data->type == cgltf_type_vec2 );
std::pmr::vector<DirectX::XMFLOAT2> texCoords{ pVertices->get_allocator() }; size_t constexpr stride = sizeof( Vertex );
size_t constexpr offset = offsetof( Vertex, texCoord0 );
size_t constexpr components = 2;
size_t const floatCount = cgltf_accessor_unpack_floats( texCoordAttr.data, nullptr, 0 ); LoadAttribute( pVertices, vertexStart, &scratch, texCoordAttr, stride, offset, components );
texCoords.resize( floatCount / 2 );
cgltf_accessor_unpack_floats(
texCoordAttr.data, reinterpret_cast<cgltf_float*>( texCoords.data() ), floatCount );
// Guaranteed to have space for these vertices.
pVertices->resize( vertexStart + texCoords.size() );
auto vertexIter = pVertices->begin() + vertexStart;
for ( DirectX::XMFLOAT2 const& texCoord : texCoords )
{
vertexIter->texCoord0 = texCoord;
++vertexIter;
}
} }
if ( "TEXCOORD_1"sv == attributes[attribIndex].name ) if ( "TEXCOORD_1"sv == attributes[attribIndex].name )
{ {
@ -565,65 +565,33 @@ ModelMesh ProcessMesh(
ASSERT( texCoordAttr.data->component_type == cgltf_component_type_r_32f ); ASSERT( texCoordAttr.data->component_type == cgltf_component_type_r_32f );
ASSERT( texCoordAttr.data->type == cgltf_type_vec2 ); ASSERT( texCoordAttr.data->type == cgltf_type_vec2 );
std::pmr::vector<DirectX::XMFLOAT2> texCoords{ pVertices->get_allocator() }; size_t constexpr stride = sizeof( Vertex );
size_t constexpr offset = offsetof( Vertex, texCoord1 );
size_t constexpr components = 2;
size_t const floatCount = cgltf_accessor_unpack_floats( texCoordAttr.data, nullptr, 0 ); LoadAttribute( pVertices, vertexStart, &scratch, texCoordAttr, stride, offset, components );
texCoords.resize( floatCount / 2 );
cgltf_accessor_unpack_floats(
texCoordAttr.data, reinterpret_cast<cgltf_float*>( texCoords.data() ), floatCount );
// Guaranteed to have space for these vertices.
pVertices->resize( vertexStart + texCoords.size() );
auto vertexIter = pVertices->begin() + vertexStart;
for ( DirectX::XMFLOAT2 const& texCoord : texCoords )
{
vertexIter->texCoord1 = texCoord;
++vertexIter;
}
} }
if ( "COLOR_0"sv == attributes[attribIndex].name ) if ( "COLOR_0"sv == attributes[attribIndex].name )
{ {
cgltf_attribute const& colorAttr = attributes[attribIndex]; cgltf_attribute const& colorAttr = attributes[attribIndex];
ASSERT( colorAttr.data->component_type == cgltf_component_type_r_32f ); ASSERT( colorAttr.data->component_type == cgltf_component_type_r_32f );
ASSERT( colorAttr.data->type == cgltf_type_vec3 or colorAttr.data->type == cgltf_type_vec4 );
if ( colorAttr.data->type == cgltf_type_vec3 ) size_t constexpr stride = sizeof( Vertex );
size_t constexpr offset = offsetof( Vertex, texCoord1 );
size_t components = 3;
switch ( colorAttr.data->type )
{ {
std::pmr::vector<DirectX::XMFLOAT3> colors{ pVertices->get_allocator() }; case cgltf_type_vec3:
components = 3;
size_t const floatCount = cgltf_accessor_unpack_floats( colorAttr.data, nullptr, 0 ); break;
colors.resize( floatCount / 3 ); case cgltf_type_vec4:
cgltf_accessor_unpack_floats( colorAttr.data, reinterpret_cast<cgltf_float*>( colors.data() ), floatCount ); components = 4;
break;
// Guaranteed to have space for these vertices. default:
pVertices->resize( vertexStart + colors.size() ); UNREACHABLE;
auto vertexIter = pVertices->begin() + vertexStart;
for ( DirectX::XMFLOAT3 const& color : colors )
{
vertexIter->color0 = { color.x, color.y, color.z, 1.0f };
++vertexIter;
}
} }
else // Since only two options
{
std::pmr::vector<DirectX::XMFLOAT4> colors{ pVertices->get_allocator() };
size_t const floatCount = cgltf_accessor_unpack_floats( colorAttr.data, nullptr, 0 ); LoadAttribute( pVertices, vertexStart, &scratch, colorAttr, stride, offset, components );
colors.resize( floatCount / 4 );
cgltf_accessor_unpack_floats( colorAttr.data, reinterpret_cast<cgltf_float*>( colors.data() ), floatCount );
// Guaranteed to have space for these vertices.
pVertices->resize( vertexStart + colors.size() );
auto vertexIter = pVertices->begin() + vertexStart;
for ( DirectX::XMFLOAT4 const& color : colors )
{
vertexIter->color0 = color;
++vertexIter;
}
}
} }
// TODO: Grab other attributes. // TODO: Grab other attributes.
} }
@ -633,12 +601,12 @@ ModelMesh ProcessMesh(
} }
Entity* ProcessNode( Entity* ProcessNode(
RenderDevice* renderDevice, RenderDevice* renderDevice,
EntityManager* entityManager, EntityManager* entityManager,
Model* model, Model* model,
std::pmr::vector<Vertex>* vertices, std::vector<Vertex>* vertices,
std::pmr::vector<uint32_t>* indices, std::vector<uint32_t>* indices,
cgltf_node const& node ) cgltf_node const& node )
{ {
DirectX::XMVECTOR vTranslation; DirectX::XMVECTOR vTranslation;
DirectX::XMVECTOR qRotation; DirectX::XMVECTOR qRotation;
@ -722,10 +690,10 @@ Entity* LoadModel( RenderDevice* renderDevice, EntityManager* entityManager, con
} ); } );
// Output data // Output data
std::pmr::vector<Vertex> vertices; std::vector<Vertex> vertices;
std::pmr::vector<uint32_t> indices; std::vector<uint32_t> indices;
cgltf_scene const* currentScene = gltfModel->scene; cgltf_scene const* currentScene = gltfModel->scene;
for ( uint32_t nodeIdx = 0; nodeIdx < currentScene->nodes_count; ++nodeIdx ) for ( uint32_t nodeIdx = 0; nodeIdx < currentScene->nodes_count; ++nodeIdx )
{ {
entity->addChild( ProcessNode( entity->addChild( ProcessNode(

View File

@ -14,8 +14,8 @@ struct GlobalMemory;
struct Vertex struct Vertex
{ {
DirectX::XMFLOAT3 position = { 0.0f, 0.0f, 0.0f }; DirectX::XMFLOAT4 position = { 0.0f, 0.0f, 0.0f, 1.0f };
DirectX::XMFLOAT3 normal = { 1.0f, 1.0f, 1.0f }; DirectX::XMFLOAT4 normal = { 1.0f, 1.0f, 1.0f, 0.0f };
DirectX::XMFLOAT2 texCoord0 = { 0.0f, 0.0f }; DirectX::XMFLOAT2 texCoord0 = { 0.0f, 0.0f };
DirectX::XMFLOAT2 texCoord1 = { 0.0f, 0.0f }; DirectX::XMFLOAT2 texCoord1 = { 0.0f, 0.0f };
DirectX::XMFLOAT4 color0 = { 1.0f, 1.0f, 1.0f, 1.0f }; DirectX::XMFLOAT4 color0 = { 1.0f, 1.0f, 1.0f, 1.0f };