Skip to content

Commit

Permalink
Apply transforms to child meshes' vertices
Browse files Browse the repository at this point in the history
  • Loading branch information
sultim-t committed Oct 1, 2023
1 parent a2c1e14 commit 1414e4d
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 81 deletions.
156 changes: 108 additions & 48 deletions Source/GltfImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,62 @@ namespace
#undef MAT
}

RgTransform MakeRgTransformFromGltfNode( const cgltf_node& node )
RgTransform MakeRgTransform( const cgltf_node& node )
{
float mat[ 16 ];
cgltf_node_transform_local( &node, mat );

return ColumnsToRows( mat );
}

// based on cgltf_node_transform_world
RgTransform MakeRgTransformRelativeTo( const cgltf_node* target, const cgltf_node* relativeTo )
{
// clang-format off
cgltf_float lm[ 16 ] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1,
};
// clang-format on

const cgltf_node* cur = target;
while( cur )
{
if( cur == relativeTo )
{
break;
}

float pm[ 16 ];
cgltf_node_transform_local( cur, pm );

for( int i = 0; i < 4; ++i )
{
float l0 = lm[ i * 4 + 0 ];
float l1 = lm[ i * 4 + 1 ];
float l2 = lm[ i * 4 + 2 ];

float r0 = l0 * pm[ 0 ] + l1 * pm[ 4 ] + l2 * pm[ 8 ];
float r1 = l0 * pm[ 1 ] + l1 * pm[ 5 ] + l2 * pm[ 9 ];
float r2 = l0 * pm[ 2 ] + l1 * pm[ 6 ] + l2 * pm[ 10 ];

lm[ i * 4 + 0 ] = r0;
lm[ i * 4 + 1 ] = r1;
lm[ i * 4 + 2 ] = r2;
}

lm[ 12 ] += pm[ 12 ];
lm[ 13 ] += pm[ 13 ];
lm[ 14 ] += pm[ 14 ];

cur = cur->parent;
}

return ColumnsToRows( lm );
}

void ApplyInverseWorldTransform( cgltf_node& mainNode, const RgTransform& worldTransform )
{
mainNode.has_translation = false;
Expand Down Expand Up @@ -128,13 +176,12 @@ namespace
return n ? nodeName( *n ) : std::string_view{};
}

bool IsAlmostIdentity( const cgltf_node& n )
bool IsAlmostIdentity( const RgTransform& tr )
{
auto areclose = []( float a, float b ) {
return std::abs( a - b ) < 0.0001f;
return std::abs( a - b ) < 0.000001f;
};

const RgTransform tr = MakeRgTransformFromGltfNode( n );
for( int i = 0; i < 3; i++ )
{
for( int j = 0; j < 4; j++ )
Expand All @@ -148,15 +195,20 @@ namespace
return true;
}

template<typename Func>
void ForEachNodeRecursively( Func&& func, const cgltf_node* src )
template< bool IsTopLevel = true, typename Func >
void ForEachChildNodeRecursively( Func&& func, const cgltf_node* src )
{
if( src )
{
func( *src );
// do not process global parent
if( !IsTopLevel )
{
func( *src );
}

for( const cgltf_node* child : std::span{ src->children, src->children_count } )
{
ForEachNodeRecursively( func, child );
ForEachChildNodeRecursively< false >( func, child );
}
}
}
Expand Down Expand Up @@ -677,8 +729,10 @@ namespace
};
}

auto ParseNodeAsLight( const cgltf_node* srcNode, uint64_t uniqueId, float oneGameUnitInMeters )
-> std::optional< LightCopy >
auto ParseNodeAsLight( const cgltf_node* srcNode,
uint64_t uniqueId,
float oneGameUnitInMeters,
const RgTransform& relativeTransform ) -> std::optional< LightCopy >
{
if( !srcNode || !srcNode->light )
{
Expand All @@ -702,18 +756,16 @@ namespace
Utils::SafeCstr( extradata ) );
};

RgTransform tr = MakeRgTransformFromGltfNode( node );

RgFloat3D position = {
tr.matrix[ 0 ][ 3 ],
tr.matrix[ 1 ][ 3 ],
tr.matrix[ 2 ][ 3 ],
const auto position = RgFloat3D{
relativeTransform.matrix[ 0 ][ 3 ],
relativeTransform.matrix[ 1 ][ 3 ],
relativeTransform.matrix[ 2 ][ 3 ],
};

RgFloat3D direction = {
-tr.matrix[ 0 ][ 2 ],
-tr.matrix[ 1 ][ 2 ],
-tr.matrix[ 2 ][ 2 ],
const auto direction = RgFloat3D{
-relativeTransform.matrix[ 0 ][ 2 ],
-relativeTransform.matrix[ 1 ][ 2 ],
-relativeTransform.matrix[ 2 ][ 2 ],
};

RgColor4DPacked32 packedColor =
Expand Down Expand Up @@ -931,9 +983,11 @@ auto RTGL1::GltfImporter::ParseFile( VkCommandBuffer cmdForTextures,


// global lights
if( auto l = ParseNodeAsLight( srcNode, srcNodeHash, oneGameUnitInMeters ) )
if( auto l = ParseNodeAsLight(
srcNode, srcNodeHash, oneGameUnitInMeters, MakeRgTransform( *srcNode ) ) )
{
result.lights.push_back( *l );
continue;
}


Expand All @@ -951,7 +1005,7 @@ auto RTGL1::GltfImporter::ParseFile( VkCommandBuffer cmdForTextures,
result.models.emplace( nodeName( srcNode ),
WholeModelFile::RawModelData{
.uniqueObjectID = srcNodeHash,
.meshTransform = MakeRgTransformFromGltfNode( *srcNode ),
.meshTransform = MakeRgTransform( *srcNode ),
.primitives = {},
.localLights = {},
} );
Expand All @@ -960,10 +1014,11 @@ auto RTGL1::GltfImporter::ParseFile( VkCommandBuffer cmdForTextures,


// mesh
auto appendMeshPrimitives =
auto AppendMeshPrimitives =
[ this, &cmdForTextures, &frameIndex, &textureManager, &textureMeta ](
std::vector< WholeModelFile::RawModelData::RawPrimitiveData >& target,
const cgltf_node* atnode ) {
const cgltf_node* atnode,
const RgTransform* transform ) {
if( !atnode || !atnode->mesh )
{
return;
Expand All @@ -977,12 +1032,23 @@ auto RTGL1::GltfImporter::ParseFile( VkCommandBuffer cmdForTextures,
{
const cgltf_primitive& srcPrim = atnode->mesh->primitives[ i ];


auto vertices = GatherVertices(
srcPrim, gltfPath, nodeName( atnode ), nodeName( atnode->parent ) );
if( vertices.empty() )
{
continue;
}
if( transform )
{
for( auto& v : vertices )
{
ApplyTransformToPosition( transform, v.position );
ApplyTransformToDirection( transform, v.normal );
ApplyTransformToDirection( transform, v.tangent );
}
}


auto indices = GatherIndices(
srcPrim, gltfPath, nodeName( atnode ), nodeName( atnode->parent ) );
Expand Down Expand Up @@ -1100,34 +1166,28 @@ auto RTGL1::GltfImporter::ParseFile( VkCommandBuffer cmdForTextures,
} );
}
};
appendMeshPrimitives( result_dstModel.primitives, srcNode );
ForEachNodeRecursively(
[ this, &appendMeshPrimitives, &result_dstModel ]( const cgltf_node& child ) {
if( child.mesh && !IsAlmostIdentity( child ) )
{
debug::Warning( "Expect incorrect transform on ...->{}->{}: "
"Nodes attached to {} must have identity transformation. {}",
nodeName( child.parent ),
nodeName( child ),
nodeName( child.parent ),
gltfPath );
}

appendMeshPrimitives( result_dstModel.primitives, &child );
},
srcNode );
AppendMeshPrimitives( result_dstModel.primitives, srcNode, nullptr );

ForEachChildNodeRecursively(
[ & ]( const cgltf_node& child ) {
const auto childHash = hashCombine( srcNodeHash, nodeName( child ) );
const auto relativeTransform = MakeRgTransformRelativeTo( &child, srcNode );

// local lights
for( const cgltf_node* child : std::span{ srcNode->children, srcNode->children_count } )
{
const auto childHash = hashCombine( srcNodeHash, nodeName( child ) );
// child meshes
AppendMeshPrimitives( result_dstModel.primitives,
&child,
IsAlmostIdentity( relativeTransform ) ? nullptr
: &relativeTransform );

if( auto l = ParseNodeAsLight( child, childHash, oneGameUnitInMeters ) )
{
result_dstModel.localLights.push_back( *l );
}
}
// local lights
if( auto l = ParseNodeAsLight(
&child, childHash, oneGameUnitInMeters, relativeTransform ) )
{
result_dstModel.localLights.push_back( *l );
}
},
srcNode );
}

return result;
Expand Down
36 changes: 3 additions & 33 deletions Source/LightManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,36 +96,6 @@ RTGL1::LightManager::~LightManager()
namespace
{

RgFloat3D ApplyTransformToPosition( const RgTransform* transform, const RgFloat3D& pos )
{
if( transform )
{
const auto& m = transform->matrix;
const auto& p = pos.data;
return RgFloat3D{
m[ 0 ][ 0 ] * p[ 0 ] + m[ 0 ][ 1 ] * p[ 1 ] + m[ 0 ][ 2 ] * p[ 2 ] + m[ 0 ][ 3 ],
m[ 1 ][ 0 ] * p[ 0 ] + m[ 1 ][ 1 ] * p[ 1 ] + m[ 1 ][ 2 ] * p[ 2 ] + m[ 1 ][ 3 ],
m[ 2 ][ 0 ] * p[ 0 ] + m[ 2 ][ 1 ] * p[ 1 ] + m[ 2 ][ 2 ] * p[ 2 ] + m[ 2 ][ 3 ],
};
}
return pos;
}

RgFloat3D ApplyTransformToDirection( const RgTransform *transform, const RgFloat3D &dir )
{
if( transform )
{
const auto& m = transform->matrix;
const auto& d = dir.data;
return RgFloat3D{
m[ 0 ][ 0 ] * d[ 0 ] + m[ 0 ][ 1 ] * d[ 1 ] + m[ 0 ][ 2 ] * d[ 2 ],
m[ 1 ][ 0 ] * d[ 0 ] + m[ 1 ][ 1 ] * d[ 1 ] + m[ 1 ][ 2 ] * d[ 2 ],
m[ 2 ][ 0 ] * d[ 0 ] + m[ 2 ][ 1 ] * d[ 1 ] + m[ 2 ][ 2 ] * d[ 2 ],
};
}
return dir;
}

RTGL1::ShLightEncoded EncodeAsDirectionalLight( const RgLightDirectionalEXT& info,
float mult,
const RgTransform* transform )
Expand Down Expand Up @@ -158,7 +128,7 @@ RTGL1::ShLightEncoded EncodeAsSphereLight( const RgLightSphericalEXT& info,
float mult,
const RgTransform* transform )
{
RgFloat3D pos = ApplyTransformToPosition( transform, info.position );
RgFloat3D pos = RTGL1::ApplyTransformToPosition( transform, info.position );

float radius = std::max( RTGL1::MIN_SPHERE_RADIUS, info.radius );
// disk is visible from the point
Expand Down Expand Up @@ -232,10 +202,10 @@ RTGL1::ShLightEncoded EncodeAsSpotLight( const RgLightSpotEXT& info,
float mult,
const RgTransform* transform )
{
RgFloat3D pos = ApplyTransformToPosition( transform, info.position );
RgFloat3D pos = RTGL1::ApplyTransformToPosition( transform, info.position );

RgFloat3D direction =
ApplyTransformToDirection( transform, RTGL1::Utils::Normalize( info.direction ) );
RTGL1::ApplyTransformToDirection( transform, RTGL1::Utils::Normalize( info.direction ) );
assert( std::abs( RTGL1::Utils::Length( direction.data ) - 1.0f ) < 0.001f );

float radius = std::max( RTGL1::MIN_SPHERE_RADIUS, info.radius );
Expand Down
52 changes: 52 additions & 0 deletions Source/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,58 @@ namespace Utils
// clang-format on
};


template< size_t N >
requires( N >= 3 )
void ApplyTransformToPosition( const RgTransform* transform, float ( &pos )[ N ] )
{
if( transform )
{
const auto& m = transform->matrix;
const float out[] = {
m[ 0 ][ 0 ] * pos[ 0 ] + m[ 0 ][ 1 ] * pos[ 1 ] + m[ 0 ][ 2 ] * pos[ 2 ] + m[ 0 ][ 3 ],
m[ 1 ][ 0 ] * pos[ 0 ] + m[ 1 ][ 1 ] * pos[ 1 ] + m[ 1 ][ 2 ] * pos[ 2 ] + m[ 1 ][ 3 ],
m[ 2 ][ 0 ] * pos[ 0 ] + m[ 2 ][ 1 ] * pos[ 1 ] + m[ 2 ][ 2 ] * pos[ 2 ] + m[ 2 ][ 3 ],
};
pos[ 0 ] = out[ 0 ];
pos[ 1 ] = out[ 1 ];
pos[ 2 ] = out[ 2 ];
}
}

template< size_t N >
requires( N >= 3 )
void ApplyTransformToDirection( const RgTransform* transform, float ( &dir )[ N ] )
{
if( transform )
{
const auto& m = transform->matrix;
const float out[] = {
m[ 0 ][ 0 ] * dir[ 0 ] + m[ 0 ][ 1 ] * dir[ 1 ] + m[ 0 ][ 2 ] * dir[ 2 ],
m[ 1 ][ 0 ] * dir[ 0 ] + m[ 1 ][ 1 ] * dir[ 1 ] + m[ 1 ][ 2 ] * dir[ 2 ],
m[ 2 ][ 0 ] * dir[ 0 ] + m[ 2 ][ 1 ] * dir[ 1 ] + m[ 2 ][ 2 ] * dir[ 2 ],
};
dir[ 0 ] = out[ 0 ];
dir[ 1 ] = out[ 1 ];
dir[ 2 ] = out[ 2 ];
}
}

inline RgFloat3D ApplyTransformToPosition( const RgTransform* transform, const RgFloat3D& pos )
{
RgFloat3D r = pos;
ApplyTransformToPosition( transform, r.data );
return r;
}

inline RgFloat3D ApplyTransformToDirection( const RgTransform* transform, const RgFloat3D& dir )
{
RgFloat3D r = dir;
ApplyTransformToDirection( transform, r.data );
return r;
}


template< typename T >
constexpr T clamp( const T& v, const T& v_min, const T& v_max )
{
Expand Down

0 comments on commit 1414e4d

Please sign in to comment.