////////////////////////////////////////////////////////////////////////// // intersect BcBool ScnViewComponent::intersect( const MaAABB& AABB ) const { MaVec3d Centre = AABB.centre(); BcF32 Radius = ( AABB.max() - AABB.min() ).magnitude() * 0.5f; BcF32 Distance; for( BcU32 i = 0; i < 6; ++i ) { Distance = FrustumPlanes_[ i ].distance( Centre ); if( Distance > Radius ) { return BcFalse; } } return BcTrue; }
//////////////////////////////////////////////////////////////////////////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(); }