BcBool MaAABB::boxIntersect( const MaAABB& AABB, MaAABB* pIntersectionBox ) const { // Check for no overlap. if( ( Min_.x() > AABB.Max_.x() ) || ( Max_.x() < AABB.Min_.x() ) || ( Min_.y() > AABB.Max_.y() ) || ( Max_.y() < AABB.Min_.y() ) || ( Min_.z() > AABB.Max_.z() ) || ( Max_.z() < AABB.Min_.z() ) ) { return BcFalse; } // Overlap, compute AABB of intersection. if( pIntersectionBox != NULL ) { pIntersectionBox->Min_.x( BcMax( Min_.x(), AABB.Min_.x() ) ); pIntersectionBox->Max_.x( BcMin( Max_.x(), AABB.Max_.x() ) ); pIntersectionBox->Min_.y( BcMax( Min_.y(), AABB.Min_.y() ) ); pIntersectionBox->Max_.y( BcMin( Max_.y(), AABB.Max_.y() ) ); pIntersectionBox->Min_.z( BcMax( Min_.z(), AABB.Min_.z() ) ); pIntersectionBox->Max_.z( BcMin( Max_.z(), AABB.Max_.z() ) ); } return BcTrue; }
void MaAABB::expandBy( const MaAABB& AABB ) { Min_.x( BcMin( Min_.x(), AABB.Min_.x() ) ); Min_.y( BcMin( Min_.y(), AABB.Min_.y() ) ); Min_.z( BcMin( Min_.z(), AABB.Min_.z() ) ); Max_.x( BcMax( Max_.x(), AABB.Max_.x() ) ); Max_.y( BcMax( Max_.y(), AABB.Max_.y() ) ); Max_.z( BcMax( Max_.z(), AABB.Max_.z() ) ); }
void MaAABB::expandBy( const MaVec3d& Point ) { Min_.x( BcMin( Min_.x(), Point.x() ) ); Min_.y( BcMin( Min_.y(), Point.y() ) ); Min_.z( BcMin( Min_.z(), Point.z() ) ); Max_.x( BcMax( Max_.x(), Point.x() ) ); Max_.y( BcMax( Max_.y(), Point.y() ) ); Max_.z( BcMax( Max_.z(), Point.z() ) ); }
////////////////////////////////////////////////////////////////////////// // Ctor SysKernel::SysKernel( BcReal TickRate ): JobQueue_( BcMax( BcGetHardwareThreadCount(), BcU32( 1 ) ) ), TickRate_( TickRate ) { ShuttingDown_ = BcFalse; SleepAccumulator_ = 0.0f; FrameTime_ = 0.0f; // Set user mask to the workers we have. SysKernel::USER_WORKER_MASK = ( ( 1 << JobQueue_.workerCount() ) - 1 ); }
//////////////////////////////////////////////////////////////////////////////// // render //virtual void GaMainGameState::render() { // NEILO HACK: REMOVE. OsClient* pClient = OsCore::pImpl()->getClient( 0 ); RsViewport Viewport( 0, 0, pClient->getWidth(), pClient->getHeight() ); // Render background. Projection_.perspProjectionHorizontal( BcPIDIV4, (BcReal)pClient->getWidth() / (BcReal)pClient->getHeight(), 1.0f, 1024.0f ); WorldView_.lookAt( BcVec3d( 0.0f, 350.0f, 270.0f ), BcVec3d( 0.0f, 0.0f, 0.0f ), BcVec3d( 0.0f, 0.0f, 1.0f ) ); if( SsCore::pImpl() != NULL ) { SsCore::pImpl()->setListener( BcVec3d( 0.0f, 350.0f, 270.0f ), BcVec3d( 0.0f, -4.0f, -2.0f ).normal(), BcVec3d( 0.0f, 0.0f, 1.0f ) ); } setMaterialComponentParams( BackgroundMaterialComponent_, BcMat4d() ); Canvas_->setMaterialComponent( BackgroundMaterialComponent_ ); Canvas_->drawSpriteCentered3D( BcVec3d( 0.0f, 0.0f, 0.0f ), WorldHalfSize_ * 4.0f, 0, RsColour::WHITE, 0 ); // Render entities. for( BcU32 Idx = 0; Idx < Entities_.size(); ++Idx ) { GaGameComponent* pEntity = Entities_[ Idx ]; pEntity->render( Canvas_ ); } // Draw foreground. BcMat4d Ortho; Ortho.orthoProjection( -WorldHalfSize_.x(), WorldHalfSize_.x(), -WorldHalfSize_.y(), WorldHalfSize_.y(), -1.0f, 0.0f ); Canvas_->pushMatrix( Ortho ); Canvas_->setMaterialComponent( ForegroundMaterialComponent_ ); Canvas_->drawSpriteCentered( BcVec2d( 0.0f, 0.0f ), BcVec2d( WorldHalfSize_.x() * 2.2f, WorldHalfSize_.y() * -2.0f ), 0, RsColour::WHITE, 20 ); BcReal Width = BcMax( 0.0f, FoodHealth_ - 0.5f ) * 2.0f; RsColour Colour; Colour.lerp( RsColour::RED, RsColour::GREEN, Width ); Canvas_->setMaterialComponent( BarMaterialComponent_ ); Canvas_->drawSpriteCentered( BcVec2d( 0.0f, WorldHalfSize_.y() - ( WorldHalfSize_.y() * 0.05f ) ), BcVec2d( WorldHalfSize_.x() * 1.5f * Width, WorldHalfSize_.y() * 0.05f ), 0, Colour, 20 ); Canvas_->popMatrix(); // Base render. GaBaseGameState::render(); }
////////////////////////////////////////////////////////////////////////// // execute //virtual void SysKernel::execute() { // Set main thread. extern void BcSetGameThread(); BcSetGameThread(); // Run until there are no more systems to run. do { // Mark main timer. MainTimer_.mark(); // Tick systems. tick(); // Sleep if we have a fixed rate specified, otherwise just yield. if( TickRate_ > 0.0f ) { BcReal TimeSpent = MainTimer_.time(); SleepAccumulator_ += BcMax( ( TickRate_ ) - TimeSpent, 0.0f ); if( SleepAccumulator_ > 0.0f ) { BcReal SleepTime = SleepAccumulator_; SleepAccumulator_ -= SleepTime; BcSleep( BcMin( SleepTime, TickRate_ ) ); } } else { BcYield(); } // Store frame time. FrameTime_ = BcMin( MainTimer_.time(), TickRate_ * 4.0f ); BcAssert( FrameTime_ >= 0.0f ); } while( SystemList_.size() > 0 ); }
////////////////////////////////////////////////////////////////////////// // updateParticles void ScnParticleSystemComponent::updateParticles( BcF32 Tick ) { // Wait for upload to have completed. UploadFence_.wait(); // TODO: Iterate over every "affector" at a time, rather than by particle. // - See "updateParticle". MaAABB FullAABB( MaVec3d( 0.0f, 0.0f, 0.0f ), MaVec3d( 0.0f, 0.0f, 0.0f ) ); // Not optimal, but clear code is clear. (For now...) for( BcU32 Idx = 0; Idx < NoofParticles_; ++Idx ) { ScnParticle& Particle = pParticleBuffer_[ Idx ]; if( Particle.Alive_ ) { // Update particle. updateParticle( Particle, Tick ); // Expand AABB by particle's max bounds. const BcF32 MaxHalfSize = BcMax( Particle.Scale_.x(), Particle.Scale_.y() ) * 0.5f; FullAABB.expandBy( Particle.Position_ - MaVec3d( MaxHalfSize, MaxHalfSize, MaxHalfSize ) ); FullAABB.expandBy( Particle.Position_ + MaVec3d( MaxHalfSize, MaxHalfSize, MaxHalfSize ) ); } } // Transform AABB. if( IsLocalSpace_ ) { const MaMat4d& WorldTransform = getParentEntity()->getWorldMatrix(); AABB_ = FullAABB.transform( WorldTransform ); } else { AABB_ = FullAABB; } UpdateFence_.decrement(); }
////////////////////////////////////////////////////////////////////////// // update //virtual void GaRobotComponent::update( BcF32 Tick ) { if( Health_ <= 0.0f ) { return; } CurrentOpTimer_ -= Tick; if( CurrentOpTimer_ < 0.0f ) { CurrentOpTimer_ += CurrentOpTime_; // Handle robot program. BcBool ExecutedCode = BcFalse; if( Program_.size() > 0 ) { CurrentOp_ = NextOp_; const auto& Op = Program_[ CurrentOp_ ]; if( Op.State_ == CurrentState_ ) { auto Condition = ProgramFunctionMap_[ Op.Condition_ ]; if( Condition != nullptr ) { if( Condition( this, Op.ConditionVar_ ) ) { auto Operation = ProgramFunctionMap_[ Op.Operation_ ]; if( Operation == nullptr ) { BcPrintf( "No operation \"%s\"\n", Op.Operation_.c_str() ); } else { auto RetVal = Operation( this, Op.OperationVar_ ); if( RetVal != BcErrorCode ) { CurrentState_ = RetVal; } } } } ExecutedCode = BcTrue; } // Advance to next valid op. if( ExecutedCode ) { for( BcU32 Idx = 0; Idx < Program_.size(); ++Idx ) { NextOp_ = ( NextOp_ + 1 ) % Program_.size(); if( Program_[ NextOp_ ].State_ == CurrentState_ ) { break; } } } // Did we fail to run code? If so, reset to op 0 and the state of op 0. if( ExecutedCode == BcFalse ) { NextOp_ = 0; CurrentState_ = Program_[ NextOp_ ].State_; } } } // Grab entity + position. auto Entity = getParentEntity(); auto LocalPosition = Entity->getLocalPosition(); // Move if we need to move towards our target position. if( ( TargetPosition_ - LocalPosition ).magnitudeSquared() > ( TargetDistance_ * TargetDistance_ ) ) { if( MoveTimer_ <= 0.0f ) { Velocity_ += ( TargetPosition_ - LocalPosition ).normal() * MaxVelocity_; } } else { BcF32 SlowDownTick = BcClamp( Tick * 50.0f, 0.0f, 1.0f ); Velocity_ -= ( Velocity_ * SlowDownTick ); } // TODO LATER: Do rotation. if( Velocity_.magnitudeSquared() > 0.1f ) { auto Angle = std::atan2( Velocity_.z(), Velocity_.x() ) + BcPIDIV2; MaMat4d RotMat; RotMat.rotation( MaVec3d( 0.0f, Angle, 0.0f ) ); Base_->setLocalMatrix( RotMat ); } // TODO LATER: Do rotation. auto Robots = getRobots( 1 - Team_ ); if( Robots.size() > 0 ) { auto Robot = Robots[ 0 ]; auto RobotPosition = Robot->getParentEntity()->getLocalPosition(); auto VectorTo = RobotPosition - LocalPosition; // Push out of away. if( VectorTo.magnitude() < 3.0f ) { BcF32 Factor = ( 3.0f - VectorTo.magnitude() ) / 3.0f; BcF32 InvFactor = 1.0f - Factor; Velocity_ = ( -( VectorTo.normal() * MaxVelocity_ ) * Factor * 3.0f ) + ( Velocity_ * InvFactor ); } // Face turret. auto Angle = std::atan2( VectorTo.z(), VectorTo.x() ) + BcPIDIV2; MaMat4d RotMat; RotMat.rotation( MaVec3d( 0.0f, Angle, 0.0f ) ); Turret_->setLocalMatrix( RotMat ); } LocalPosition += Velocity_ * Tick; // Slow down velocity. BcF32 SlowDownTick = BcClamp( Tick * 10.0f, 0.0f, 1.0f ); Velocity_ -= ( Velocity_ * SlowDownTick ); if( Velocity_.magnitude() > MaxVelocity_ ) { Velocity_ = Velocity_.normal() * MaxVelocity_; } // Set local position. Entity->setLocalPosition( LocalPosition ); // Handle health + energy. Health_ = BcClamp( Health_, 0.0f, 100.0f ); Energy_ = BcClamp( Energy_ + ( EnergyChargeRate_ * Tick ), 0.0f, 100.0f ); // Weapon timers. WeaponATimer_ = BcMax( WeaponATimer_ - Tick, -1.0f ); WeaponBTimer_ = BcMax( WeaponBTimer_ - Tick, -1.0f ); MoveTimer_ = BcMax( MoveTimer_ - Tick, -1.0f ); // Health/energy bars. OsClient* Client = OsCore::pImpl()->getClient( 0 ); BcF32 Width = BcF32( Client->getWidth() ) * 0.5f; BcF32 Height = BcF32( Client->getHeight() ) * 0.5f; MaMat4d Projection; Projection.orthoProjection( -Width, Width, Height, -Height, -1.0f, 1.0f ); Canvas_->pushMatrix( Projection ); Canvas_->setMaterialComponent( Material_ ); auto ScreenPos = View_->getScreenPosition( getParentEntity()->getWorldPosition() ); ScreenPos -= MaVec2d( 0.0f, Height / 8.0f ); auto TLPos = ScreenPos - MaVec2d( Width / 16.0f, Height / 64.0f ); auto BRPos = ScreenPos + MaVec2d( Width / 16.0f, Height / 64.0f ); // Draw background. Canvas_->drawBox( TLPos, BRPos, RsColour::BLACK, 0 ); // Draw inner bars. TLPos += MaVec2d( 1.0f, 1.0f ); BRPos -= MaVec2d( 1.0f, 1.0f ); auto HealthTL = MaVec2d( TLPos.x(), TLPos.y() ); auto HealthBR = MaVec2d( TLPos.x() + ( BRPos.x() - TLPos.x() ) * ( Health_ / 100.0f ), ( TLPos.y() + BRPos.y() ) * 0.5f ); auto EnergyTL = MaVec2d( TLPos.x(), ( TLPos.y() + BRPos.y() ) * 0.5f ); auto EnergyBR = MaVec2d( TLPos.x() + ( BRPos.x() - TLPos.x() ) * ( Energy_ / 100.0f ), BRPos.y() ); Canvas_->drawBox( HealthTL, HealthBR, RsColour::GREEN, 0 ); Canvas_->drawBox( EnergyTL, EnergyBR, RsColour::BLUE, 0 ); Canvas_->popMatrix( ); ScnDebugRenderComponent::pImpl()->drawLine( LocalPosition, TargetPosition_, RsColour::WHITE, 0 ); Super::update( Tick ); }
////////////////////////////////////////////////////////////////////////// // tickBehaviour void GaGameUnit::tickBehaviour( BcFixed Delta ) { #if PSY_DEBUG static BcU32 BreakID = BcErrorCode; if( ID_ == BreakID ) { BcBreakpoint; } #endif switch( Behaviour_ ) { case BEHAVIOUR_IDLE: { CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f ); BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) ); if( NearestUnit != BcErrorCode ) { doAttack( NearestUnit ); } } break; case BEHAVIOUR_GUARD: { CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f ); BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) ); if( NearestUnit != BcErrorCode ) { doAttack( NearestUnit ); } } break; case BEHAVIOUR_MOVE: { BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) ); if( IsAttackMove_ && inRangeForAttack( NearestUnit ) == RANGE_IN ) { CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f ); doAttack( NearestUnit ); } else { // Reset attack timer. AttackTimer_ = BcMax( AttackTimer_, BcFixed( Desc_.CoolDownMultiplier_ ) / Desc_.RateOfAttack_ ); // Make longer whe moving. AttackTimer_ = BcMin( BcFixed( 1.0f ) / Desc_.RateOfAttack_, AttackTimer_ + ( BcFixed( 1.0f ) / Desc_.RateOfAttack_ ) * ( Delta * 0.05f ) ); // Calculate velocity vector. CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_; BcFixed MoveDistance = Desc_.MoveSpeed_ * Delta; if( ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared() < ( MoveDistance * MoveDistance ) ) { CurrState_.Position_ = MoveTargetPosition_; setBehaviourIdle(); } } } break; case BEHAVIOUR_ATTACK: { TRange Range = inRangeForAttack( TargetUnitID_ ); if( Range == RANGE_IN ) { doAttack( TargetUnitID_ ); } else { // Reset attack timer. AttackTimer_ = BcMax( AttackTimer_, BcFixed( Desc_.CoolDownMultiplier_ ) / ( Desc_.RateOfAttack_ ) ); // Make longer whe moving. AttackTimer_ = BcMin( BcFixed( 1.0f ) / Desc_.RateOfAttack_, AttackTimer_ + ( BcFixed( 1.0f ) / Desc_.RateOfAttack_ ) * ( Delta * 0.05f ) ); // Get unit position. GaGameUnit* pUnit = pSimulator_->getUnit( TargetUnitID_ ); if( pUnit != NULL ) { BcFixedVec2d Direction = ( getPosition() - pUnit->getPosition() ).normal() * ( ( Desc_.MinRange_ + Desc_.Range_ ) * 0.5f ); MoveTargetPosition_ = pUnit->getPosition() + Direction; } else { // Attack move to previous target. IsAttackMove_ = BcTrue; Behaviour_ = BEHAVIOUR_MOVE; } // Calculate velocity vector. CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_; // If we moved further away, then stop and set target. BcFixed CurrMagnitudeSquared = ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared(); BcFixed PrevMagnitudeSquared = ( PrevState_.Position_ - MoveTargetPosition_ ).magnitudeSquared(); if( CurrMagnitudeSquared > PrevMagnitudeSquared ) { setBehaviourIdle(); } } } break; case BEHAVIOUR_DAMAGE: { // Calculate velocity vector. CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_; BcFixed MoveDistance = Desc_.MoveSpeed_ * Delta; if( ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared() < ( MoveDistance * MoveDistance ) ) { CurrState_.Position_ = MoveTargetPosition_; // Cause damage. pSimulator_->applyDamage( MoveTargetPosition_, Desc_.Range_, Desc_.Health_ ); // Debug point! pSimulator_->addDebugPoint( getPosition(), Desc_.Range_, RsColour::YELLOW ); if( Desc_.pHitSound_ != NULL ) { GaTopState::pImpl()->playSound( Desc_.pHitSound_, MoveTargetPosition_ ); } // Set as dead. setBehaviourDead(); } } break; } // Attack timer. if( AttackTimer_ > 0.0f ) { AttackTimer_ -= Delta; } else if( AttackTimer_ < 0.0f ) { AttackTimer_ = 0.0f; } // Death. if( Health_ <= 0.0f ) { Health_ = 0.0f; Behaviour_ = BEHAVIOUR_DEAD; } }
//virtual void ScnParticleSystemComponent::render( class ScnViewComponent* pViewComponent, RsFrame* pFrame, RsRenderSort Sort ) { // Wait for update fence. UpdateFence_.wait(); // Grab vertex buffer and flip for next frame to use. TVertexBuffer& VertexBuffer = VertexBuffers_[ CurrentVertexBuffer_ ]; CurrentVertexBuffer_ = 1 - CurrentVertexBuffer_; // Lock vertex buffer. VertexBuffer.pVertexBuffer_->lock(); // Iterate over alive particles, and setup vertex buffer. BcU32 NoofParticlesToRender = 0; ScnParticleVertex* pVertex = VertexBuffer.pVertexArray_; for( BcU32 Idx = 0; Idx < NoofParticles_; ++Idx ) { ScnParticle& Particle = pParticleBuffer_[ Idx ]; if( Particle.Alive_ ) { // Half size. const MaVec2d HalfSize = Particle.Scale_ * 0.5f; const BcF32 MaxHalfSize = BcMax( HalfSize.x(), HalfSize.y() ); BcAssert( Particle.TextureIndex_ < UVBounds_.size() ); const MaVec4d& UVBounds( UVBounds_[ Particle.TextureIndex_ ] ); // Crappy rotation implementation :P const BcF32 Radians = Particle.Rotation_; MaVec2d CornerA = MaVec2d( -1.0f, -1.0f ) * HalfSize; MaVec2d CornerB = MaVec2d( 1.0f, -1.0f ) * HalfSize; MaVec2d CornerC = MaVec2d( 1.0f, 1.0f ) * HalfSize; MaVec2d CornerD = MaVec2d( -1.0f, 1.0f ) * HalfSize; if( Radians != NULL ) { MaMat4d Rotation; Rotation.rotation( MaVec3d( 0.0f, 0.0f, Radians ) ); CornerA = CornerA * Rotation; CornerB = CornerB * Rotation; CornerC = CornerC * Rotation; CornerD = CornerD * Rotation; } const BcU32 Colour = Particle.Colour_.asABGR(); // Grab vertices. ScnParticleVertex& VertexA = *pVertex++; ScnParticleVertex& VertexB = *pVertex++; ScnParticleVertex& VertexC = *pVertex++; ScnParticleVertex& VertexD = *pVertex++; ScnParticleVertex& VertexE = *pVertex++; ScnParticleVertex& VertexF = *pVertex++; // VertexA.X_ = Particle.Position_.x(); VertexA.Y_ = Particle.Position_.y(); VertexA.Z_ = Particle.Position_.z(); VertexA.NX_ = CornerA.x(); VertexA.NY_ = CornerA.y(); VertexA.NZ_ = 0.0f; VertexA.U_ = UVBounds.x(); VertexA.V_ = UVBounds.y(); VertexA.RGBA_ = Colour; // VertexB.X_ = Particle.Position_.x(); VertexB.Y_ = Particle.Position_.y(); VertexB.Z_ = Particle.Position_.z(); VertexB.NX_ = CornerB.x(); VertexB.NY_ = CornerB.y(); VertexB.NZ_ = 0.0f; VertexB.U_ = UVBounds.z(); VertexB.V_ = UVBounds.y(); VertexB.RGBA_ = Colour; // VertexC.X_ = Particle.Position_.x(); VertexC.Y_ = Particle.Position_.y(); VertexC.Z_ = Particle.Position_.z(); VertexC.NX_ = CornerC.x(); VertexC.NY_ = CornerC.y(); VertexC.NZ_ = 0.0f; VertexC.U_ = UVBounds.z(); VertexC.V_ = UVBounds.w(); VertexC.RGBA_ = Colour; // VertexD.X_ = Particle.Position_.x(); VertexD.Y_ = Particle.Position_.y(); VertexD.Z_ = Particle.Position_.z(); VertexD.NX_ = CornerC.x(); VertexD.NY_ = CornerC.y(); VertexD.NZ_ = 0.0f; VertexD.U_ = UVBounds.z(); VertexD.V_ = UVBounds.w(); VertexD.RGBA_ = Colour; // VertexE.X_ = Particle.Position_.x(); VertexE.Y_ = Particle.Position_.y(); VertexE.Z_ = Particle.Position_.z(); VertexE.NX_ = CornerD.x(); VertexE.NY_ = CornerD.y(); VertexE.NZ_ = 0.0f; VertexE.U_ = UVBounds.x(); VertexE.V_ = UVBounds.w(); VertexE.RGBA_ = Colour; // VertexF.X_ = Particle.Position_.x(); VertexF.Y_ = Particle.Position_.y(); VertexF.Z_ = Particle.Position_.z(); VertexF.NX_ = CornerA.x(); VertexF.NY_ = CornerA.y(); VertexF.NZ_ = 0.0f; VertexF.U_ = UVBounds.x(); VertexF.V_ = UVBounds.y(); VertexF.RGBA_ = Colour; // ++NoofParticlesToRender; } } // Update and unlock vertex buffer. VertexBuffer.pVertexBuffer_->setNoofUpdateVertices( NoofParticlesToRender * 6 ); VertexBuffer.pVertexBuffer_->unlock(); // Draw particles last. if( NoofParticlesToRender > 0 ) { Sort.Layer_ = 15; // Bind material. if( IsLocalSpace_ ) { const MaMat4d& WorldTransform = getParentEntity()->getWorldMatrix(); MaterialComponent_->setParameter( WorldTransformParam_, WorldTransform ); } else { MaterialComponent_->setParameter( WorldTransformParam_, MaMat4d() ); } // Set material parameters for view. pViewComponent->setMaterialParameters( MaterialComponent_ ); // Bind material component. MaterialComponent_->bind( pFrame, Sort ); // Setup render node. ScnParticleSystemComponentRenderNode* pRenderNode = pFrame->newObject< ScnParticleSystemComponentRenderNode >(); pRenderNode->pPrimitive_ = VertexBuffer.pPrimitive_; pRenderNode->NoofIndices_ = NoofParticlesToRender * 6; // Add to frame. pRenderNode->Sort_ = Sort; pFrame->addRenderNode( pRenderNode ); } }