////////////////////////////////////////////////////////////////////////// // transform MaAABB MaAABB::transform( const MaMat4d& Transform ) const { MaAABB NewAABB; // Add transformed corners. NewAABB.expandBy( corner( 0 ) * Transform ); NewAABB.expandBy( corner( 1 ) * Transform ); NewAABB.expandBy( corner( 2 ) * Transform ); NewAABB.expandBy( corner( 3 ) * Transform ); NewAABB.expandBy( corner( 4 ) * Transform ); NewAABB.expandBy( corner( 5 ) * Transform ); NewAABB.expandBy( corner( 6 ) * Transform ); NewAABB.expandBy( corner( 7 ) * Transform ); return NewAABB; }
////////////////////////////////////////////////////////////////////////// // findAABB MaAABB MdlMesh::findAABB() const { MaAABB MeshBounds; for( BcU32 VertIdx = 0; VertIdx < aVertices_.size(); ++VertIdx ) { MeshBounds.expandBy( aVertices_[ VertIdx ].Position_ ); } return MeshBounds; }
//////////////////////////////////////////////////////////////////////////pmatr // updateNodes void ScnModelComponent::updateNodes( MaMat4d RootMatrix ) { MaAABB FullAABB; // Wait for previous upload to finish. UploadFence_.wait(); // Update nodes. BcU32 NoofNodes = Model_->pHeader_->NoofNodes_; for( BcU32 NodeIdx = 0; NodeIdx < NoofNodes; ++NodeIdx ) { ScnModelNodeTransformData* pNodeTransformData = &pNodeTransformData_[ NodeIdx ]; ScnModelNodePropertyData* pNodePropertyData = &Model_->pNodePropertyData_[ NodeIdx ]; // Check parent index and process. if( pNodePropertyData->ParentIndex_ != BcErrorCode ) { ScnModelNodeTransformData* pParentScnModelNodeTransformData = &pNodeTransformData_[ pNodePropertyData->ParentIndex_ ]; pNodeTransformData->WorldTransform_ = pNodeTransformData->LocalTransform_ * pParentScnModelNodeTransformData->WorldTransform_; } else { pNodeTransformData->WorldTransform_ = pNodeTransformData->LocalTransform_ * RootMatrix; } } // Calculate bounds. BcU32 NoofPrimitives = Model_->pHeader_->NoofPrimitives_; for( BcU32 PrimitiveIdx = 0; PrimitiveIdx < NoofPrimitives; ++PrimitiveIdx ) { ScnModelMeshRuntime* pNodeMeshRuntime = &Model_->MeshRuntimes_[ PrimitiveIdx ]; ScnModelMeshData* pNodeMeshData = &Model_->pMeshData_[ pNodeMeshRuntime->MeshDataIndex_ ]; // Special case the skinned models for now. if( pNodeMeshData->IsSkinned_ == BcFalse ) { ScnModelNodeTransformData* pNodeTransformData = &pNodeTransformData_[ pNodeMeshData->NodeIndex_ ]; MaAABB PrimitiveAABB = pNodeMeshData->AABB_; FullAABB.expandBy( PrimitiveAABB.transform( pNodeTransformData->WorldTransform_ ) ); } else { MaAABB SkeletalAABB; for( BcU32 Idx = 0; Idx < SCN_MODEL_BONE_PALETTE_SIZE; ++Idx ) { BcU32 BoneIndex = pNodeMeshData->BonePalette_[ Idx ]; if( BoneIndex != BcErrorCode ) { // Get the distance from the parent bone, and make an AABB that size. ScnModelNodePropertyData* pNodePropertyData = &Model_->pNodePropertyData_[ BoneIndex ]; if( pNodePropertyData->ParentIndex_ != BcErrorCode && pNodePropertyData->IsBone_ ) { ScnModelNodeTransformData* pNodeTransformData = &pNodeTransformData_[ BoneIndex ]; ScnModelNodeTransformData* pParentNodeTransformData = &pNodeTransformData_[ pNodePropertyData->ParentIndex_ ]; MaAABB NewAABB( pNodeTransformData->WorldTransform_.translation(), pParentNodeTransformData->WorldTransform_.translation() ); // SkeletalAABB.expandBy( NewAABB ); } } } // HACK: Expand AABB slightly to cover skin. Should calculate bone sizes and pack them really. MaVec3d Centre = SkeletalAABB.centre(); MaVec3d Dimensions = SkeletalAABB.dimensions() * 0.75f; // 1.5 x size. SkeletalAABB.min( Centre - Dimensions ); SkeletalAABB.max( Centre + Dimensions ); // FullAABB.expandBy( SkeletalAABB ); } } AABB_ = FullAABB; // Setup skinning buffers. for( BcU32 PrimitiveIdx = 0; PrimitiveIdx < NoofPrimitives; ++PrimitiveIdx ) { ScnModelMeshRuntime* pNodeMeshRuntime = &Model_->MeshRuntimes_[ PrimitiveIdx ]; ScnModelMeshData* pNodeMeshData = &Model_->pMeshData_[ pNodeMeshRuntime->MeshDataIndex_ ]; TPerComponentMeshData& PerComponentMeshData = PerComponentMeshDataList_[ PrimitiveIdx ]; UploadFence_.increment(); if( pNodeMeshData->IsSkinned_ ) { RsCore::pImpl()->updateBuffer( PerComponentMeshData.UniformBuffer_, 0, sizeof( ScnShaderBoneUniformBlockData ), RsResourceUpdateFlags::ASYNC, [ this, pNodeMeshData ]( RsBuffer* Buffer, const RsBufferLock& Lock ) { ScnShaderBoneUniformBlockData* BoneUniformBlock = reinterpret_cast< ScnShaderBoneUniformBlockData* >( Lock.Buffer_ ); for( BcU32 Idx = 0; Idx < SCN_MODEL_BONE_PALETTE_SIZE; ++Idx ) { BcU32 NodeIndex = pNodeMeshData->BonePalette_[ Idx ]; if( NodeIndex != BcErrorCode ) { BoneUniformBlock->BoneTransform_[ Idx ] = pNodeMeshData->BoneInverseBindpose_[ Idx ] * pNodeTransformData_[ NodeIndex ].WorldTransform_; } } UploadFence_.decrement(); } ); } else { RsCore::pImpl()->updateBuffer( PerComponentMeshData.UniformBuffer_, 0, sizeof( ScnShaderObjectUniformBlockData ), RsResourceUpdateFlags::ASYNC, [ this, pNodeMeshData ]( RsBuffer* Buffer, const RsBufferLock& Lock ) { ScnShaderObjectUniformBlockData* ObjectUniformBlock = reinterpret_cast< ScnShaderObjectUniformBlockData* >( Lock.Buffer_ ); ScnModelNodeTransformData* pNodeTransformData = &pNodeTransformData_[ pNodeMeshData->NodeIndex_ ]; // World matrix. ObjectUniformBlock->WorldTransform_ = pNodeTransformData->WorldTransform_; // Normal matrix. ObjectUniformBlock->NormalTransform_ = pNodeTransformData->WorldTransform_; ObjectUniformBlock->NormalTransform_.row3( MaVec4d( 0.0f, 0.0f, 0.0f, 1.0f ) ); ObjectUniformBlock->NormalTransform_.inverse(); ObjectUniformBlock->NormalTransform_.transpose(); ObjectUniformBlock->NormalTransform_.row3( MaVec4d( 0.0f, 0.0f, 0.0f, 1.0f ) ); UploadFence_.decrement(); } ); } } UpdateFence_.decrement(); }