////////////////////////////////////////////////////////////////////////// // initialise //virtual void ScnLightComponent::initialise( const Json::Value& Object ) { initialise(); const Json::Value& AmbientColourValue = Object[ "ambientcolour" ]; if( AmbientColourValue != Json::nullValue ) { AmbientColour_ = MaVec4d( AmbientColourValue.asCString() ); } const Json::Value& DiffuseColourValue = Object[ "diffusecolour" ]; if( DiffuseColourValue != Json::nullValue ) { DiffuseColour_ = MaVec4d( DiffuseColourValue.asCString() ); } const Json::Value& MinValue = Object[ "min" ]; const Json::Value& MidValue = Object[ "mid" ]; const Json::Value& MaxValue = Object[ "max" ]; if( MinValue != Json::nullValue && MidValue != Json::nullValue && MaxValue != Json::nullValue ) { createAttenuationValues( (BcF32)MinValue.asDouble(), (BcF32)MidValue.asDouble(), (BcF32)MaxValue.asDouble() ); } }
////////////////////////////////////////////////////////////////////////// // getDepth BcU32 ScnViewComponent::getDepth( const MaVec3d& WorldPos ) const { MaVec4d ScreenSpace = MaVec4d( WorldPos, 1.0f ) * ViewUniformBlock_.ClipTransform_; BcF32 Depth = 1.0f - BcClamp( ScreenSpace.z() / ScreenSpace.w(), 0.0f, 1.0f ); return BcU32( Depth * BcF32( 0xffffff ) ); }
////////////////////////////////////////////////////////////////////////// // update //virtual void GaSpeechBubbleComponent::update( BcF32 Tick ) { Super::update( Tick ); if ( !FontComponent_.isValid() ) { Canvas_ = ParentEntity_->getComponentAnyParentByType< ScnCanvasComponent >(); FontComponent_ = ParentEntity_->getComponentAnyParentByType< ScnFontComponent >(); } if ( !SpeechBubble_.isValid() ) { SpeechBubble_ = ParentEntity_->getComponentByType<ScnSpriteComponent>( BcName( "SpeechBubbleComponent", 0 ) ); } if ( SpeechBubble_.isValid() ) { SpeechBubble_->setColour( RsColour( 1, 1, 1, Visible_ ? 0.8 : 0 ) ); } if ( !TargetEntity_.isValid() ) { // We aren't even gonna bother return; } MaMat4d TextScaleMatrix; //TextScaleMatrix.scale( MaVec4d( 0.04f, 0.04f, 1.0f, 1.0f ) ); TextScaleMatrix.scale( MaVec4d( 1.00f, -1.00f, 1.0f, 1.0f ) ); FontComponent_->setAlphaTestStepping( MaVec2d( 0.4f, 0.45f ) ); if (Visible_) { TimeBeenVisible_ += Tick; if ( TimeBeenVisible_ > VisibleTime_ ) Visible_ = false; //MaMat4d Matrix = getParentEntity()->getWorldMatrix(); //Matrix = Canvas_->popMatrix(); Canvas_->pushMatrix( TextScaleMatrix ); MaVec2d Size; MaVec3d worldPos = TargetEntity_->getWorldPosition(); MaVec2d Position( 0 , 0 ); MaVec2d localPos = SpeechBubble_->getPosition(); localPos = MaVec2d(TargetEntity_->getWorldPosition().x(), -TargetEntity_->getWorldPosition().y() ) + FontOffset_; SpeechBubble_->setPosition( MaVec2d( TargetEntity_->getWorldPosition().x(), TargetEntity_->getWorldPosition().y() ) + SpriteOffset_ ); for( BcU32 Idx = 0; Idx < Text_.size(); ++Idx ) { const auto& Option( Text_[ Idx ] ); const auto Colour = RsColour::BLACK; Size = FontComponent_->drawCentered( Canvas_, localPos + Position, Text_[ Idx ] , Colour, 280 ); Position += MaVec2d( 0.0f, Size.y() ); } Canvas_->popMatrix(); } //Canvas_->pushMatrix( Matrix ); //Canvas_->setMatrix( Matrix ); }
////////////////////////////////////////////////////////////////////////// // initialise //virtual void ScnParticleSystemComponent::initialise( const Json::Value& Object ) { Super::initialise( Object ); // Grab number of particles. NoofParticles_ = Object["noofparticles"].asUInt(); ScnMaterialRef Material = getPackage()->getPackageCrossRef( Object["material"].asUInt() ); if( !CsCore::pImpl()->createResource( BcName::INVALID, getPackage(), MaterialComponent_, Material, scnSPF_PARTICLE_3D ) ) { BcAssertMsg( BcFalse, "Material invalid blah." ); } IsLocalSpace_ = Object["localspace"].asBool(); // Cache texture bounds. ScnTextureRef Texture = Material->getTexture( "aDiffuseTex" ); for( BcU32 Idx = 0; Idx < Texture->noofRects(); ++Idx ) { ScnRect Rect = Texture->getRect( Idx ); UVBounds_.push_back( MaVec4d( Rect.X_, Rect.Y_, Rect.X_ + Rect.W_, Rect.Y_ + Rect.H_ ) ); } WorldTransformParam_ = MaterialComponent_->findParameter( "uWorldTransform" ); BcMemZero( &VertexBuffers_, sizeof( VertexBuffers_ ) ); pParticleBuffer_ = NULL; CurrentVertexBuffer_ = 0; PotentialFreeParticle_ = 0; }
////////////////////////////////////////////////////////////////////////// // getScreenPosition MaVec2d ScnViewComponent::getScreenPosition( const MaVec3d& WorldPosition ) const { MaVec4d ScreenSpace = MaVec4d( WorldPosition, 1.0f ) * ViewUniformBlock_.ClipTransform_; MaVec2d ScreenPosition = MaVec2d( ScreenSpace.x() / ScreenSpace.w(), -ScreenSpace.y() / ScreenSpace.w() ); BcF32 HalfW = BcF32( Viewport_.width() ) * 0.5f; BcF32 HalfH = BcF32( Viewport_.height() ) * 0.5f; return MaVec2d( ( ScreenPosition.x() * HalfW ), ( ScreenPosition.y() * HalfH ) ); }
////////////////////////////////////////////////////////////////////////// // initialise //virtual void ScnParticleSystemComponent::initialise() { Super::initialise(); // Cache texture bounds. if( Material_ != nullptr ) { ScnTextureRef Texture = Material_->getTexture( "aDiffuseTex" ); if( Texture.isValid() ) { UVBounds_.reserve( Texture->noofRects() ); for( BcU32 Idx = 0; Idx < Texture->noofRects(); ++Idx ) { ScnRect Rect = Texture->getRect( Idx ); UVBounds_.push_back( MaVec4d( Rect.X_, Rect.Y_, Rect.X_ + Rect.W_, Rect.Y_ + Rect.H_ ) ); } } else { UVBounds_.push_back( MaVec4d( 0.0f, 0.0f, 1.0f, 1.0f ) ); } } }
//////////////////////////////////////////////////////////////////////////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(); }