genesis-3d_engine/Engine/app/particlefeature/components/particlerendercomponent.cc
zhongdaohuan ad5cd7b16a * upate genesis-3d engine to version 1.3.1.
match the genesis editor version 1.3.1.921.
2014-06-19 16:26:14 +08:00

892 lines
27 KiB
C++
Raw Blame History

/****************************************************************************
Copyright (c) 2011-2013,WebJet Business Division,CYOU
http://www.genesis-3d.com.cn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "stdneb.h"
#include "appframework/actor.h"
#include "particlefeature/components/particlerenderobject.h"
#include "particlefeature/components/particlerendercomponent.h"
#include "particlefeature/particlefeatureprotocol.h"
#include "graphicfeature/graphicsfeatureprotocol.h"
#include "particles/particletarget.h"
#include "particles/targets/particleEntityTarget.h"
#include "particles/particleserver.h"
#include "serialization/serializeserver.h"
#include "graphicfeature/graphicsfeature.h"
#include "basegamefeature/managers/timemanager.h"
#include "basegamefeature/managers/timesource.h"
#include "graphicfeature/components/skinnedmeshrendercomponent.h"
#include "particles/affectors/particleLinearForceAffector.h"
#include "particles/affectors/particleTextureRotatorAffector.h"
#include "particles/affectors/particleGravityAffector.h"
#include "particles/affectors/particleVortexAffector.h"
#include "particles/affectors/particleLimitAffector.h"
#include "particles/affectors/particleColorAffector.h"
#include "particles/affectors/particleMovementAffector.h"
#include "particles/affectors/particleScaleAffector.h"
#include "particles/affectors/particleTextureAnimatorAffector.h"
#include "particles/emitters/particleSphereSurfaceEmitter.h"
#include "particles/emitters/particleModelEmitter.h"
#include "particles/emitters/particleBoxEmitter.h"
#include "particles/emitters/particleConeEmitter.h"
#include "particles/targets/particlebillboardtarget.h"
#include "particles/targets/particleDecalTarget.h"
#include "particles/targets/particleGPUTarget.h"
#include "particles/targets/particleEntityTarget.h"
#include "graphicfeature/components/skinnedmeshrendercomponent.h"
namespace App
{
using namespace Resources;
using namespace Particles;
using namespace RenderBase;
using namespace Graphic;
__ImplementClass(App::ParticleRenderComponent, 'APRC', App::RenderComponent);
//------------------------------------------------------------------------
ParticleRenderComponent::ParticleRenderComponent()
: mIsBuild(false)
, mIsAttached(false)
, mIsTrans(false)
, mPrimitiveResInfo(NULL)
, mEmitMeshRes(NULL)
, mShowSimpleShape(false)
, mSelectTech(0)
, mTemplateName("sys:Mesh.template")
, mCurCamera(NULL)
{
mMeshInfo.dirty = false;
mMeshInfo.meshID = "sys:box.mesh";
mMeshInfo.priority = Resources::ResourcePriority::Synchronization;
}
//------------------------------------------------------------------------
void ParticleRenderComponent::InitParticleSystem()
{
GPtr<ParticleSystem> ParSystem = ParticleSystem::Create();
{
GPtr<SphereSurfaceEmitter> emitter = SphereSurfaceEmitter::Create();
emitter->getMinMaxCurve(Emitter_SphereRadius)->SetScalar(0.1f);
ParSystem->SetEmitter( emitter.get() );
GPtr<ParticleAffector> pAffector = ParticleAffector::Create();
ParSystem->AddAffector( pAffector.get() );
GPtr<ParticleBillBoardTarget> target = ParticleBillBoardTarget::Create();
ParSystem->SetTarget( target.get() );
}
ParSystem->SetName(Util::String("system_14"));
this->SetParticleSystem(ParSystem);
//create Matrails
this->SetMaterialID(0, "sys:Default_Particle.material");
}
//------------------------------------------------------------------------
void ParticleRenderComponent::InitMobielParticle()
{
GPtr<ParticleSystem> ParSystem = ParticleSystem::Create();
{
GPtr<SphereSurfaceEmitter> emitter = SphereSurfaceEmitter::Create();
emitter->getMinMaxCurve(Emitter_SphereRadius)->SetScalar(0.1f);
ParSystem->SetEmitter( emitter.get() );
GPtr<ParticleGPUTarget> target = ParticleGPUTarget::Create();
ParSystem->SetTarget( target.get() );
}
ParSystem->SetName(Util::String("system_14"));
this->SetParticleSystem(ParSystem);
//create Matrails
this->SetMaterialID(0, "sys:Default_MobielParticle.material");
}
//------------------------------------------------------------------------
ParticleRenderComponent::~ParticleRenderComponent()
{
mPrimitiveResInfo = NULL;
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::SetupCallbacks(void)
{
mActor->RegisterComponentCallback(this, BeginFrame );
mActor->RegisterComponentCallback(this, OnFrame );
mActor->RegisterComponentCallback(this, MoveAfter);
Super::SetupCallbacks();
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::SetupAcceptedMessages()
{
Super::SetupAcceptedMessages();
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::HandleMessage(const GPtr<Messaging::Message>& msg)
{
}
//------------------------------------------------------------------------
void ParticleRenderComponent::SetRenderShapeEnable(bool enable)
{
//[zhongdaohuan][render_obj
}
//------------------------------------------------------------------------
void ParticleRenderComponent::OnActivate()
{
if ( mParticleSystem.isvalid() )
{
mParticleSystem->Active();
if ( NULL!=mActor )
{
mParticleSystem->SetWorldMatrix( mActor->GetWorldTransform() );
}
}
n_assert( mRenderDates.Size() == 0 );
LoadEmitterMesh();
BuildRenderData();
Graphic::GraphicSystem::Instance()->m_BeforeDrawEvent += Delegates::newDelegate(this, &ParticleRenderComponent::_updateTarget);
Super::OnActivate();
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::OnDeactivate()
{
if ( mParticleSystem.isvalid() )
{
mParticleSystem->DeActive();
}
_DeattachRenderObject();
DiscardRenderData();
Graphic::GraphicSystem::Instance()->m_BeforeDrawEvent -= Delegates::newDelegate(this, &ParticleRenderComponent::_updateTarget);
Super::OnDeactivate();
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::OnDestroy()
{
if ( mParticleSystem.isvalid() && mParticleSystem->IsActive() )
{
mParticleSystem->DeActive();
}
mParticleSystem = NULL;
_DeattachRenderObject();
DiscardRenderData();
}
//------------------------------------------------------------------------
void ParticleRenderComponent::_OnMoveAfter()
{
if ( !mActor || !mParticleSystem.isvalid() )
return;
if ( !mActor || !mParticleSystem.isvalid() )
return;
//const Math::vector& wolrdPos = mActor->GetWorldPosition();
const Math::matrix44& worldMat = mActor->GetWorldTransform();
mParticleSystem->SetWorldMatrix(worldMat);
if (mRenderObject.isvalid())
{
mRenderObject->SetTransform(worldMat);
}
//if (mSimpleShape.isvalid())
//{
// mSimpleShape->SetTransform(worldMat);
//}
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::_OnBeginFrame()
{
if ( !mParticleSystem.isvalid() )
return;
if ( mMeshInfo.dirty)
{
if (CheckMeshChanged() )
{
mIsBuild = false;
mIsAttached = false;
mMeshInfo.dirty = false;
_DeattachRenderObject();
}
}
//const GPtr<Actor>& pCamera = GraphicsFeature::Instance()->GetDefaultCameraActor();
// if ( pCamera.isvalid() )
// mParticleSystem->SetCameraMatrix( pCamera->GetWorldTransform() );
LoadEmitterMesh();
BuildRenderData();
mParticleSystem->SetParticleFPS(_fpsControl());
Super::_OnBeginFrame();
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::OnParticleDataChange()
{
_DeattachRenderObject();
DiscardRenderData();
BuildRenderData();
}
//------------------------------------------------------------------------
bool ParticleRenderComponent::CheckMeshChanged(void)
{
if(mPrimitiveResInfo&& mPrimitiveResInfo->GetHandle().IsValid())
return true;
return false;
}
//--------------------------------------------------------------------------------
const GPtr<Resources::MeshRes> ParticleRenderComponent::GetMesh() const
{
if (!mPrimitiveResInfo || !mPrimitiveResInfo->GetRes().isvalid())
{
return NULL;
}
else
{
return mPrimitiveResInfo->GetRes().downcast<Resources::MeshRes>();
}
}
//--------------------------------------------------------------------------------
void ParticleRenderComponent::LoadEmitterMesh(void)
{
const GPtr<ParticleSystem>& parSystem = GetParticleSystem();
if ( !parSystem.isvalid() )
return;
// load modelEmitter 's meshres
if ( !parSystem->IsLoadEmitterMesh())
{
const GPtr<Particles::ParticleEmitter>& pEmit = parSystem->GetEmitter();
if( pEmit.isvalid() && pEmit->IsA( Particles::ModelEmitter::RTTI ) )
{
const GPtr<Particles::ModelEmitter>& pModelEmit = pEmit.downcast<Particles::ModelEmitter>();
const Resources::ResourceId& meshId= pModelEmit->GetMeshName();
if("" == meshId.AsString())
return;
if ( !mEmitMeshRes || mEmitMeshRes->GetResID() != meshId)
{
mEmitMeshRes = Resources::ResourceManager::Instance()->CreatePrimitiveInfo(meshId, Resources::ResourcePriority::MeshDefault);
}
if ( mEmitMeshRes->GetHandle().IsValid() )
{
pModelEmit->SetMeshRes(mEmitMeshRes->GetRes());
}
}
parSystem->SetLoadEmitterMesh(true);
}
}
//------------------------------------------------------------------------
void ParticleRenderComponent::BuildRenderData(void)
{
if ( mIsBuild )
return;
mRenderDates.Clear();
n_assert( mRenderDates.Size() == 0 );
const GPtr<ParticleSystem>& parSystem = GetParticleSystem();
if ( !parSystem.isvalid() )
return;
const GPtr<Particles::ParticleTarget>& pTarget = parSystem->GetTarget();
if( !pTarget.isvalid() )
return;
if ( pTarget->GetTargetType() == ParticleTarget::Mesh )
{
ResourceId& resId = mMeshInfo.meshID;
Resources::Priority priority = mMeshInfo.priority;
if ( !mPrimitiveResInfo.isvalid() || mPrimitiveResInfo->GetResID() != resId )
{
mPrimitiveResInfo = Resources::ResourceManager::Instance()->CreatePrimitiveInfo( resId, priority);
return;
}
if ( !mPrimitiveResInfo->GetHandle().IsValid() )
return;
const GPtr<Resources::Resource>& resource = mPrimitiveResInfo->GetRes();
if ( resource.isvalid() && resource->GetState() == Resource::Loaded )
{
const GPtr<Resources::MeshRes>& meshResource = resource.downcast<Resources::MeshRes>();
n_assert( meshResource.isvalid() );
SizeT subMeshCount = meshResource->GetSubMeshCount();
while ( mRenderableResUnitList.Size() < subMeshCount )
{
mRenderableResUnitList.Append(RenderbleResUnit());
mRenderableResUnitList.Back().CopyFrom( mRenderableResUnitList[0]);
}
Math::bbox box;
box.begin_extend();
SizeT curMat = 0;
for ( IndexT subIndex = 0 ; subIndex < subMeshCount; ++subIndex)
{
mRenderDates.Append( RenderData());
RenderData& renderData = mRenderDates.Back();
renderData.mPartType = (ushort)ParticleTarget::Mesh;
renderData.mPrimitiveHandle = mPrimitiveResInfo->GetHandle();
renderData.mSubmeshIndex = subIndex;
renderData.mTargetIndex = 0;
const SubMesh* subMesh = meshResource->GetSubMesh(subIndex);
RenderObjectType::RenderableType* renderable = mRenderableResUnitList[curMat].ResetRenderable<RenderObjectType::RenderableType>();
_SetRenderable( meshResource, curMat, renderable);
box.extend( subMesh->box );
++curMat;
}
box.end_extend();
const ParticleTargetPtr& target = mParticleSystem->GetTarget();
target.downcast<ParticleEntityTarget>()->_setMeshBox(box);
}
else
{
_DeattachRenderObject();
return;
}
}
else
{
// just rebuild pool
int quota = parSystem->GetParticleQuota();
parSystem->_resetPool( quota );
mRenderDates.Append( RenderData() );
RenderData& renderData = mRenderDates[0];
//renderData.mPrimitiveGroup = PrimitiveGroup::Create();
renderData.mTargetIndex = 0;
renderData.mPartType = pTarget->GetTargetType();
//pTarget->SetPrimitiveGroup( renderData.mPrimitiveGroup );
pTarget->SetNeedPrimitive(true);
RenderObjectType::RenderableType* renderable = mRenderableResUnitList[0].ResetRenderable<RenderObjectType::RenderableType>();
_SetRenderable(NULL, 0, renderable);
}
//New RenderObject
if( !mRenderObject.isvalid() )
{
mRenderObject = RenderObjectType::Create();
}
mRenderObject->SetOwner(this);
mRenderObject->SetTransform(mActor->GetWorldTransform());
_AttachRenderObject();
mIsBuild = true;
}
//------------------------------------------------------------------------
void ParticleRenderComponent::DiscardRenderData(void)
{
//if ( !mIsBuild )
//{
// n_assert( mRenderDates.IsEmpty() );
// return;
//}
mIsBuild = false;
SizeT count = mRenderDates.Size();
for ( IndexT index = 0; index < mRenderDates.Size(); ++index )
{
RenderData& renderData = mRenderDates[index];
if ( renderData.mPrimitiveHandle.IsValid() )
{
//GraphicSystem::Instance()->RemovePrimitive( renderData.mPrimitiveHandle );
//GraphicObjectManager::Instance()->DiscardPrimitiveHandle( renderData.mPrimitiveHandle );
const ParticleTargetPtr& target = mParticleSystem->GetTarget();
if(target.isvalid())
target->SetDirtyPrim(true);
renderData.mPrimitiveHandle = RenderBase::PrimitiveHandle();
}
}
mRenderDates.Clear();
}
void ParticleRenderComponent::UpdateRenderLayer()
{
if (mRenderObject.isvalid())
{
mRenderObject->SetLayerID(mActor->GetLayerID());
}
}
void ParticleRenderComponent::SetVisible(bool bVis)
{
if ( bVis == mVisible )
{
return;
}
mVisible = bVis;
if (IsActive())
{
if (mVisible)
{
_AttachRenderObject();
}
else
{
_DeattachRenderObject();
}
}
}
#ifdef __GENESIS_EDITOR__
void ParticleRenderComponent::SetEditorVisible(bool bVis)
{
Super::SetEditorVisible(bVis);
if (IsActive())
{
mRenderObject->SetEditorVisible(bVis);
}
}
#endif
void ParticleRenderComponent::OnRenderSceneChanged()
{
if (mRenderObject.isvalid() && mRenderObject->Attached())
{
mRenderObject->Attach(mActor->GetRenderScene());
}
}
void ParticleRenderComponent::_AttachRenderObject()
{
if(!mVisible)
return;
if (mRenderObject.isvalid())
{
n_assert(mActor);
mRenderObject->Attach(mActor->GetRenderScene());
}
}
void ParticleRenderComponent::_DeattachRenderObject()
{
if (mRenderObject.isvalid())
{
n_assert(mActor);
mRenderObject->Detach();
}
}
void ParticleRenderComponent::_updateTarget( Graphic::Camera* camera )
{
if(mIsBuild)
{
mParticleSystem->SetCameraMatrix( camera->GetTransform());
mParticleSystem->_postProcessParticles();
UpdateRenderData();
}
mCurCamera = camera;
}
void ParticleRenderComponent::_SetRenderable(const GPtr<Resources::MeshRes>& meshRes, IndexT index, RenderObjectType::RenderableType* renderable)
{
if (meshRes.isvalid())
{
SubMesh* subMesh = meshRes->GetSubMesh(index);
n_assert(subMesh);
renderable->SetParticleRenderInfo(index,
subMesh->firstVertex,
subMesh->numVertex,
subMesh->FirstIndex,
subMesh->numIndex);
}
else
{
RenderData& renderdata = mRenderDates[index];
if ( renderdata.mPrimitiveHandle.IsValid())
{
const ParticleTargetPtr& target = mParticleSystem->GetTarget();
renderable->SetParticleRenderInfo(index,
0, target->GetActiveVertexCount(),
0, target->GetActiveIndexCount());
}
else
{
renderable->SetParticleRenderInfo(index, 0, 0, 0, 0);
}
}
}
void
ParticleRenderComponent::_UpdateRenderable(IndexT index, SizeT activeVertexCount, SizeT activeIndexCount, signed char sort, RenderObjectType::RenderableType* renderable)
{
renderable->SetParticleRenderInfo(index,
0, activeVertexCount,
0, activeIndexCount);
renderable->SetSort(sort);
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::UpdateRenderData(void)
{
for ( IndexT index = 0; index < mRenderDates.Size(); ++index )
{
RenderData& renderData = mRenderDates[index];
RenderObjectType::RenderableType* renderable = mRenderableResUnitList[index].GetRenderableFast<RenderObjectType::RenderableType>();
if ( renderData.mPartType == ParticleTarget::Mesh )
{
const GPtr<ParticleSystem>& parSystem = GetParticleSystem();
if ( !parSystem.isvalid() )
return;
const ParticleTargetPtr& target = parSystem->GetTarget();
const GPtr<ParticleEntityTarget>& entityTarget = target.downcast<ParticleEntityTarget>();
if ( !entityTarget->IsNeedToRender() )
return;
GPtr<MeshRes> meshres = mPrimitiveResInfo->GetRes().downcast<MeshRes>();
if ( meshres.isvalid() && meshres->GetState() == Resource::Loaded )
{
SizeT vertexCount = meshres->GetVertexCount();
ColorData colorData;
Math::Color32 color(255,255,255,255);
ColorData::Elem* elem = meshres->GetVertexData<ColorData>();
if ( elem == NULL )
{
colorData.Fill(0, vertexCount, color );
if( !meshres->SetVertexData<ColorData>(&colorData[0], vertexCount ) )
return;
}
if ( !renderData.mPrimitiveHandle.IsValid() )
renderData.mPrimitiveHandle = mPrimitiveResInfo->GetHandle();
else
GraphicObjectManager::Instance()->UpdataPrimitiveHandle(meshres);
if( renderData.mSubmeshIndex >= meshres->GetSubMeshCount())
continue;
_SetRenderable(meshres, index, renderable);
}
}// end: if ( renderData.mPartType == ParticleTarget::Mesh )
else
{
const ParticleTargetPtr& target = mParticleSystem->GetTarget();
signed char sort = mParticleSystem->GetSort();
if (target.isvalid())
{
if (target->IsDirtyPrim())
{
renderData.mPrimitiveHandle = mParticleSystem->GetTarget()->GetPrimitiveHandle();
target->SetDirtyPrim(false);
}
_UpdateRenderable(index, target->GetActiveVertexCount(), target->GetActiveIndexCount(), sort, renderable);
}
else
{
_UpdateRenderable(index, 0, 0, sort, renderable);
}
}//end: if ( renderData.mPartType != ParticleTarget::Mesh )
}//end: for ( IndexT index = 0; index < mRenderDates.Size(); ++index )
if(mParticleSystem->_NeedUpdateBox())
{
mRenderObject->SetBoundingBox(mParticleSystem->GetBoundingBox());
}
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::_OnFrame()
{
}
//------------------------------------------------------------------------
void ParticleRenderComponent::SetShaderMask()
{
SizeT sub_count = mRenderableResUnitList.Size();
for ( IndexT index = 0; index < sub_count; ++index )
{
Renderable* renderable = mRenderableResUnitList[index].GetRenderable();
if (renderable == NULL)
{
return;
}
const MaterialInstance* material_instance = renderable->GetMaterial();
{
const Util::Array< GPtr<MaterialPass> >& passList = material_instance->GetTech()->GetPassList();
//<2F><><EFBFBD><EFBFBD>forward pass <20><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD> <20><>
const GPtr<MaterialPass>& pass = passList[eForward - 1];
const GPtr<ShaderProgramCompiler::ShaderMarcro>& pMarcro = pass->GetShaderMarcro();
pMarcro->Reset();
mParticleSystem->SetShaderMask(pMarcro);
renderable->SetShaderMask(eForward,pMarcro->GetShaderMask());
}
}
}
//------------------------------------------------------------------------
void ParticleRenderComponent::GetTargetInfo(ushort& partType,Util::Array<Math::matrix44>& mMats, Util::Array<Math::float4>& mColors)
{
const GPtr<ParticleSystem>& parSystem = GetParticleSystem();
if ( !parSystem.isvalid() )
return ;
const GPtr<Particles::ParticleTarget>& pTarget = parSystem->GetTarget();
if( !pTarget.isvalid() )
return ;
partType = pTarget->GetTargetType();
if ( partType == ParticleTarget::Mesh )
{
if(mMeshInfo.dirty || !mIsBuild)
return;
GPtr<Particles::ParticleEntityTarget> entityTar = pTarget.downcast<ParticleEntityTarget>();
mMats.AppendArray( entityTar->GetMatrixList());
mColors.AppendArray( entityTar->GetColorList());
}
else if ( partType == ParticleTarget::Decal )
{
GPtr<Particles::ParticleDecalTarget> decalTar = pTarget.downcast<ParticleDecalTarget>();
mMats.Append( decalTar->GetDecalRotation());
mColors.Append( Math::float4(1.0f,1.0f,1.0f,1.0f));
}
else
{
mMats.Append( Math::matrix44::identity());
mColors.Append( Math::float4(1.0f,1.0f,1.0f,1.0f));
}
}
//------------------------------------------------------------------------
void ParticleRenderComponent::CalculateBBox(Math::bbox& box,const Util::Array<Math::matrix44>& matlist)
{
SizeT PosIndex = 0;
while (PosIndex < matlist.Size())
{
Math::float4 curPos = matlist[PosIndex].get_position();
box.extend(curPos);
PosIndex++;
}
}
//--------------------------------------------------------------------------------
void ParticleRenderComponent::RemoveShader( IndexT iSubMesh )
{
if ( iSubMesh < 0 )
{
return;
}
//whether need to determine the render type is entity target
if ( iSubMesh >= mRenderableResUnitList.Size() )
{
// delete the renderable from graphic system
mRenderableResUnitList.EraseIndex(iSubMesh);
}
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::SetParticleSystem( const GPtr<Particles::ParticleSystem>& parSystem )
{
if ( mParticleSystem == parSystem )
{
return;
}
if ( mParticleSystem.isvalid() )
{
if ( mParticleSystem->IsActive() )
{
mParticleSystem->DeActive();
}
}
mParticleSystem = parSystem;
if ( mParticleSystem.isvalid() )
{
if ( IsActive() )
{
mParticleSystem->Active();
}
}
OnParticleSystemChange();
}
//--------------------------------------------------------------------------------
void ParticleRenderComponent::SetEmitMeshRes(const Resources::ResourceId& meshID, int techIdx , int emitIdx )
{
const GPtr<ParticleSystem>& parSystem = GetParticleSystem();
if ( !parSystem.isvalid() )
return;
const GPtr<Particles::ParticleEmitter>& pEmit = parSystem->GetEmitter();
if( pEmit.isvalid() && pEmit->IsA( Particles::ModelEmitter::RTTI ) )
{
const GPtr<Particles::ModelEmitter>& pModelEmit = pEmit.downcast<Particles::ModelEmitter>();
pModelEmit->SetMeshName(meshID.AsString());
}
}
//------------------------------------------------------------------------
void
ParticleRenderComponent::OnParticleSystemChange()
{
if ( mActor )
{
GPtr<ParticleComponentChangeMsg> msg = ParticleComponentChangeMsg::Create();
mActor->SendSync( msg.upcast<Messaging::Message>() );
}
}
//------------------------------------------------------------------------
void ParticleRenderComponent::CopyFrom( const GPtr<Component>& pComponent )
{
if( !pComponent.isvalid() )
return;
if( !pComponent->GetRtti()->IsDerivedFrom( *(this->GetRtti()) ) )
return;
GPtr<ParticleRenderComponent> pSource = pComponent.downcast<ParticleRenderComponent>();
SetMeshID(pSource->GetMeshID(), pSource->GetMeshLoadPriority());
mTemplateName = pSource->GetTemplateID();
ParticleSystemPtr newPartSystem = ParticleSystem::Create();
newPartSystem->CopyFrom(pSource->GetParticleSystem());
SetParticleSystem(newPartSystem);
Super::CopyFrom( pComponent );
}
//------------------------------------------------------------------------------
void ParticleRenderComponent::GetReferenceResourceId(Util::Array<Resources::ReferenceResource>& list) const
{
if (mEmitMeshRes.isvalid())
{
list.Append(ReferenceResource(mEmitMeshRes->GetResID(), Resources::RR_Unknown));
}
list.Append(ReferenceResource(mTemplateName, Resources::RR_Unknown));
Super::GetReferenceResourceId(list);
}
//------------------------------------------------------------------------
void ParticleRenderComponent::SetMeshID(const Resources::ResourceId& meshID, Resources::Priority priority )
{
//if( mMeshInfo.meshID != meshID ) //<2F>ȼ<EFBFBD><C8BC><EFBFBD>
{
if (mActor && mActor->PriorityDefinition())
{
priority = mActor->GetPriority();
}
mMeshInfo.meshID = meshID;
mMeshInfo.priority = priority;
mMeshInfo.dirty = true;
}
}
//------------------------------------------------------------------------
void ParticleRenderComponent::SetTemplateID( const Resources::ResourceId& templateID )
{
mTemplateName = templateID;
}
//------------------------------------------------------------------------
const Resources::ResourceId& ParticleRenderComponent::GetTemplateID( void ) const
{
return mTemplateName;
}
//-------------------------------------------------------------------------
SizeT ParticleRenderComponent::_fpsControl()
{
Math::bbox box = mParticleSystem->GetBoundingBox();
Math::float4 boxSizeVec = box.pmax - box.pmin;
float boxSize = boxSizeVec.x()*boxSizeVec.x()+boxSizeVec.y()*boxSizeVec.y()+boxSizeVec.z()*boxSizeVec.z();
float minViewSize = 400000000;
if(!mActor)
{
return (SizeT)(minViewSize);
}
const Graphic::RenderScene* renderScene = mActor->GetRenderScene();
if(!renderScene)
{
return (SizeT)(minViewSize);
}
const Graphic::RenderScene::CameraList& cameraList = renderScene->GetCameraList();
for(IndexT cameraIndex = 0; cameraIndex < cameraList.Size(); cameraIndex++)
{
if(cameraList[cameraIndex])
{
Math::vector cameraLocalPos = cameraList[cameraIndex]->GetTransform().get_position() - mActor->GetWorldPosition();
float dis = cameraLocalPos.x()*cameraLocalPos.x()+cameraLocalPos.y()*cameraLocalPos.y()+cameraLocalPos.z()*cameraLocalPos.z();
float zNear = cameraList[cameraIndex]->GetCameraSetting().GetZNear();
float zFar = cameraList[cameraIndex]->GetCameraSetting().GetZFar();
float farWidth = cameraList[cameraIndex]->GetCameraSetting().GetFarWidth();
float farHeight = cameraList[cameraIndex]->GetCameraSetting().GetFarHeight();
float viewSize = dis/((zFar-zNear)*(zFar-zNear))*(farWidth*farWidth + farHeight*farHeight);
minViewSize = Math::n_min(viewSize,minViewSize);
}
}
float ratioInView = minViewSize/boxSize;
float MINTIME = 0.033f;
float MAXTIME = 0.33f;
float updateTime = MINTIME + (MAXTIME-MINTIME) * ratioInView * ParticleSystem::UpdateFactor;
updateTime = updateTime>MAXTIME?MAXTIME:updateTime;
return (SizeT)(1.0/updateTime);
}
}