//! Prepares a bullet for rendering void PelletManager::SetupRendering(Bullet* pBullet, u32 index, VertexBuffer* pVB) { Vertex3D* pVertices = pVB->GetVertices(); if(GraphicExtensionHandler::Instance()->HasExtension(GraphicExtensionHandler::E_PointSprite)) { pVertices[index].Pos = pBullet->vPosition; pVB->SetNumVertices(index+1); } else { const Matrix44& viewInverse = EntityRenderer::Instance()->Get3DCamera()->GetViewMatrixInverse(); const f32 fHalfSize = pBullet->fRadius; const u32 vtx = index*6; pVertices[vtx+0].UV = Vector2(0.0f, 1.0f); pVertices[vtx+0].Pos = Vector3::Create(-fHalfSize, -fHalfSize, 0.0f); pVertices[vtx+1].UV = Vector2(0.0f, 0.0f); pVertices[vtx+1].Pos = Vector3::Create(-fHalfSize, fHalfSize, 0.0f); pVertices[vtx+2].UV = Vector2(1.0f, 0.0f); pVertices[vtx+2].Pos = Vector3::Create(fHalfSize, fHalfSize, 0.0f); pVertices[vtx+3].UV = Vector2(0.0f, 1.0f); pVertices[vtx+3].Pos = Vector3::Create(-fHalfSize, -fHalfSize, 0.0f); pVertices[vtx+4].UV = Vector2(1.0f, 0.0f); pVertices[vtx+4].Pos = Vector3::Create(fHalfSize, fHalfSize, 0.0f); pVertices[vtx+5].UV = Vector2(1.0f, 1.0f); pVertices[vtx+5].Pos = Vector3::Create(fHalfSize, -fHalfSize, 0.0f); Matrix44 transform = viewInverse; transform.SetTranslation(pBullet->vPosition); for(u32 i=0; i<6; ++i) { pVertices[vtx+i].Pos = transform.TransformVect(pVertices[vtx+i].Pos); } pVB->SetNumVertices(vtx+6); } }
//! Sets the absolute position void Entity2D::SetAbsolutePosition(const Vector2& vAbsPos) { Vector3 vPos = Vector3::Create(vAbsPos.X, vAbsPos.Y, 0.0f); if(Entity2D* pParent = GetAncestor<Entity2D>()) { Matrix44 inverse; if(pParent->GetTransformationMatrix().GetInverse(inverse)) { vPos = inverse.TransformVect(vPos); } } SetPosition(Vector2(vPos.X, vPos.Y) + (m_vCenter*m_vScale)); }
int ParticleGenerator::TesselateLine(Particle* pParticle, Vertex3D* pVertices, int current, const Vector3& vScale) { Vector3 vDir = (pParticle->Pos - pParticle->PreviousPos).Normalized(); pVertices[current+0].UV = Vector2::Zero; pVertices[current+0].Pos = Vector3::Zero; pVertices[current+1].UV = Vector2::One; pVertices[current+1].Pos = vDir*vScale*m_fSparkFactor; pParticle->PreviousPos = pParticle->Pos; Matrix44 transform = Matrix44::Identity; transform.SetTranslation(m_bApplyWorldTransform ? super::GetWorldTransform().TransformVect(pParticle->Pos) : pParticle->Pos); for(int i=0; i<2; ++i) { pVertices[current+i].Pos = transform.TransformVect(pVertices[current+i].Pos); pVertices[current+i].color = Color::Create(m_ParticleColor.R, m_ParticleColor.G, m_ParticleColor.B, pParticle->Alpha); } return 2; }
int ParticleGenerator::TesselateQuad(Particle* pParticle, Vertex3D* pVertices, int current, const Vector3& vScale) { auto halfSize = pParticle->Size; pVertices[current+0].UV = Vector2::Create(0.0f, 1.0f); pVertices[current+0].Pos = Vector3::Create(-halfSize, -halfSize, 0.0f)*vScale; pVertices[current+1].UV = Vector2::Create(0.0f, 0.0f); pVertices[current+1].Pos = Vector3::Create(-halfSize, halfSize, 0.0f)*vScale; pVertices[current+2].UV = Vector2::Create(1.0f, 0.0f); pVertices[current+2].Pos = Vector3::Create(halfSize, halfSize, 0.0f)*vScale; pVertices[current+3].UV = Vector2::Create(0.0f, 1.0f); pVertices[current+3].Pos = Vector3::Create(-halfSize, -halfSize, 0.0f)*vScale; pVertices[current+4].UV = Vector2::Create(1.0f, 0.0f); pVertices[current+4].Pos = Vector3::Create(halfSize, halfSize, 0.0f)*vScale; pVertices[current+5].UV = Vector2::Create(1.0f, 1.0f); pVertices[current+5].Pos = Vector3::Create(halfSize, -halfSize, 0.0f)*vScale; Matrix44 transform = m_ViewInverse; transform.SetTranslation(m_bApplyWorldTransform ? super::GetWorldTransform().TransformVect(pParticle->Pos) : pParticle->Pos); for(int i=0; i<6; ++i) { pVertices[current+i].Pos = transform.TransformVect(pVertices[current+i].Pos); pVertices[current+i].color = Color::Create(m_ParticleColor.R, m_ParticleColor.G, m_ParticleColor.B, pParticle->Alpha); } return 6; }
//! returns true if the button is touched bool Button::IsTouched() const { Matrix44 transformation = Matrix44::Identity; transformation.Translate(-Vector3::Create(m_vCenter.X, m_vCenter.Y, 0.0f)); transformation.Scale(Vector3::Create(m_vScale.X, m_vScale.Y, 1.0f)); transformation.Rotate(Vector3::Create(0.0f, 0.0f, m_fRotation*Math::DegToRadFactor)); transformation.Translate(Vector3::Create(m_vOriginalPosition.X, m_vOriginalPosition.Y, 0.0f)); if(Entity2D* p2DEntity = GetAncestor<Entity2D>()) { transformation *= p2DEntity->GetTransformationMatrix(); } Matrix44 inverse; if(transformation.GetInverse(inverse)) { Vector2 vTouchPos = InputManager::Instance()->GetTouchState().vPosition; Vector3 invTouchPos3D = inverse.TransformVect(Vector3::Create(vTouchPos.X, vTouchPos.Y, 0.0f)); Vector2 vInvTouchPos(invTouchPos3D.X, invTouchPos3D.Y); return GetBoundingBox().Contains(vInvTouchPos); } return false; }
//! called during the update of the entity void ParticleGenerator::Update() { auto camera = EntityRenderer::Instance()->Get3DCamera(); if (!camera) return; // generate new particles if(m_bActive) { m_fNewParticlesCounter += g_fDeltaTime * m_ParticlesPerSecond; int numNewParticles = int(m_fNewParticlesCounter); if(m_Pool.GetElementCount() + numNewParticles > m_MaxParticles) numNewParticles = m_MaxParticles - (int)m_Pool.GetElementCount(); // determine emission center Vector3 vCenter = m_EmitBox.Min()+m_EmitBox.Size()/2.0f; if(!m_bApplyWorldTransform) vCenter = super::GetWorldTransform().TransformVect(vCenter); Matrix44 speedTransform = super::GetWorldTransform(); speedTransform.SetTranslation(Vector3::Zero); // Pre-emit void* pEmitData = (this->*m_PreEmitFunctor)(); for(int i=0; i<numNewParticles; ++i) { auto pParticle = m_Pool.Alloc(); if(!pParticle) continue; pParticle->InitialLife = Random::GetFloat(m_rParticleLife.Min, m_rParticleLife.Max); pParticle->Life = pParticle->InitialLife; pParticle->Pos = Vector3::Create(Random::GetFloat(m_EmitBox.Min().X, m_EmitBox.Max().X), Random::GetFloat(m_EmitBox.Min().Y, m_EmitBox.Max().Y), Random::GetFloat(m_EmitBox.Min().Z, m_EmitBox.Max().Z)); if(!m_bApplyWorldTransform) pParticle->Pos = super::GetWorldTransform().TransformVect(pParticle->Pos); pParticle->PreviousPos = pParticle->Pos; // Emit (this->*m_EmitFunctor)(pParticle, vCenter, pEmitData); if(!m_bApplyWorldTransform) pParticle->Speed = speedTransform.TransformVect(pParticle->Speed); pParticle->Alpha = 1.0f; } m_fNewParticlesCounter -= numNewParticles; if(m_fActiveTime >= 0.0f) { m_fActiveTime -= g_fDeltaTime; if(m_fActiveTime < 0.0f) m_bActive = false; } } // update particles GraphicComponent* pGraphic = GetComponent<GraphicComponent>(); VertexBuffer* pVB = pGraphic->GetVertexBuffer(); Vertex3D* pVertices = reinterpret_cast<Vertex3D*>(pVB->GetVertices()); const Vector3 vScale = GetAbsoluteScale(); m_ViewInverse = camera->GetViewMatrixInverse(); m_ParticleColor = pGraphic->GetMaterial() ? pGraphic->GetMaterial()->GetColor() : Color::White; int vtx = 0; for (size_t i = 0; i < m_Pool.GetCapacity(); ++i) { auto particle = m_Pool.GetElement(i); if (!particle) continue; particle->Pos += particle->Speed * g_fDeltaTime; particle->Speed += m_vGravity * g_fDeltaTime; auto lifeFactor = particle->Life / particle->InitialLife; particle->Alpha = lifeFactor*lifeFactor; particle->Size = (this->*m_SizeFuncFunctor)(particle); // Tesselate auto numParticleVertices = (this->*m_TesselateFunctor)(particle, pVertices, vtx, vScale); vtx += numParticleVertices; particle->Life -= g_fDeltaTime; if(particle->Life < 0.0f) m_Pool.Free(particle); } pVB->SetNumVertices(vtx); pVB->SetDirty(true); }
//! called during the update of the entity void ParticleGenerator::Update() { // generate new particles if(m_bActive) { m_fNewParticlesCounter += g_fDeltaTime * m_ParticlesPerSecond; u32 numNewParticles = u32(m_fNewParticlesCounter); if(m_aParticles.size() + numNewParticles > m_MaxParticles) { numNewParticles = m_MaxParticles-m_aParticles.size(); } for(u32 i=0; i<numNewParticles; ++i) { if(Particle* pParticle = m_Pool->Alloc<Particle>()) { pParticle->InitialLife = Random::GetFloat(m_rParticleLife.Min, m_rParticleLife.Max); pParticle->Life = pParticle->InitialLife; pParticle->Position = Vector3::Create(Random::GetFloat(m_EmitBox.Min().X, m_EmitBox.Max().X), Random::GetFloat(m_EmitBox.Min().Y, m_EmitBox.Max().Y), Random::GetFloat(m_EmitBox.Min().Z, m_EmitBox.Max().Z)); Vector3 vCenter = m_EmitBox.Min()+m_EmitBox.Size()/2.0f; if(!m_bApplyWorldTransform) { Vector3 vTranslation = GetTransformationMatrix().GetTranslation(); pParticle->Position += vTranslation; vCenter += vTranslation; } if(m_bExplosive) { pParticle->Speed = (pParticle->Position-vCenter).Normalize(); pParticle->Speed *= Random::GetFloat(m_rParticleInitialSpeed.Min, m_rParticleInitialSpeed.Max); } else { pParticle->Speed = Vector3::Create(m_vDirection.X * Random::GetFloat(m_rParticleInitialSpeed.Min, m_rParticleInitialSpeed.Max), m_vDirection.Y * Random::GetFloat(m_rParticleInitialSpeed.Min, m_rParticleInitialSpeed.Max), m_vDirection.Z * Random::GetFloat(m_rParticleInitialSpeed.Min, m_rParticleInitialSpeed.Max)); } pParticle->Alpha = 1.0f; m_aParticles.push_back(pParticle); } } m_fNewParticlesCounter -= numNewParticles; if(m_fActiveTime >= 0.0f) { m_fActiveTime -= g_fDeltaTime; if(m_fActiveTime < 0.0f) { m_bActive = false; } } } // update particles GraphicComponent* pGraphic = GetComponent<GraphicComponent>(); VertexBuffer* pVertexBuffer = pGraphic->GetVertexBuffer(); Material* pMaterial = pGraphic->GetMaterial(); const Matrix44& viewInverse = EntityRenderer::Instance()->Get3DCamera()->GetViewMatrixInverse(); const f32 fHalfSize = m_fParticleSize/2.0f; const bool bPointSprite = GraphicExtensionHandler::Instance()->HasExtension(GraphicExtensionHandler::E_PointSprite); u32 vtx = 0; for(std::list<Particle*>::iterator it = m_aParticles.begin(); it != m_aParticles.end(); ) { if((*it)->Life > 0.0f) { (*it)->Position += (*it)->Speed * g_fDeltaTime; (*it)->Speed += m_vGravity * g_fDeltaTime; (*it)->Alpha = (*it)->Life / (*it)->InitialLife; (*it)->Life -= g_fDeltaTime; const Color& color = pMaterial->GetColor(); Vertex3D* pVertices = pVertexBuffer->GetVertices(); const Vector3& pos = (*it)->Position; if(bPointSprite) { pVertices[vtx].Pos = pos; pVertices[vtx].color = Color(color.R, color.G, color.B, (*it)->Alpha); ++vtx; } else { Vector3 vScale = GetAbsoluteScale(); pVertices[vtx+0].UV = Vector2(0.0f, 1.0f); pVertices[vtx+0].Pos = Vector3::Create(-fHalfSize, -fHalfSize, 0.0f)*vScale; pVertices[vtx+1].UV = Vector2(0.0f, 0.0f); pVertices[vtx+1].Pos = Vector3::Create(-fHalfSize, fHalfSize, 0.0f)*vScale; pVertices[vtx+2].UV = Vector2(1.0f, 0.0f); pVertices[vtx+2].Pos = Vector3::Create(fHalfSize, fHalfSize, 0.0f)*vScale; pVertices[vtx+3].UV = Vector2(0.0f, 1.0f); pVertices[vtx+3].Pos = Vector3::Create(-fHalfSize, -fHalfSize, 0.0f)*vScale; pVertices[vtx+4].UV = Vector2(1.0f, 0.0f); pVertices[vtx+4].Pos = Vector3::Create(fHalfSize, fHalfSize, 0.0f)*vScale; pVertices[vtx+5].UV = Vector2(1.0f, 1.0f); pVertices[vtx+5].Pos = Vector3::Create(fHalfSize, -fHalfSize, 0.0f)*vScale; Matrix44 transform = viewInverse; transform.SetTranslation(super::GetTransformationMatrix().TransformVect(pos)); for(u32 i=0; i<6; ++i) { pVertices[vtx+i].Pos = transform.TransformVect(pVertices[vtx+i].Pos); pVertices[vtx+i].color = Color(color.R, color.G, color.B, (*it)->Alpha); } vtx += 6; } ++it; } else { // remove particle m_Pool->Free((*it)); it = m_aParticles.erase(it); } } pVertexBuffer->SetNumVertices(vtx); pVertexBuffer->SetDirty(true); }