diff options
Diffstat (limited to 'APEX_1.4/module/particles/src/EffectPackageActorImpl.cpp')
| -rw-r--r-- | APEX_1.4/module/particles/src/EffectPackageActorImpl.cpp | 3186 |
1 files changed, 3186 insertions, 0 deletions
diff --git a/APEX_1.4/module/particles/src/EffectPackageActorImpl.cpp b/APEX_1.4/module/particles/src/EffectPackageActorImpl.cpp new file mode 100644 index 00000000..77bfb300 --- /dev/null +++ b/APEX_1.4/module/particles/src/EffectPackageActorImpl.cpp @@ -0,0 +1,3186 @@ +/* + * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + + +#include "EffectPackageActorImpl.h" +#include "FloatMath.h" +#include "ParticlesScene.h" +#include "SceneIntl.h" +#include "EmitterActor.h" +#include "EmitterAsset.h" +#include "TurbulenceFSActor.h" +#include "AttractorFSActor.h" +#include "JetFSActor.h" +#include "WindFSActor.h" +#include "NoiseFSActor.h" +#include "VortexFSActor.h" +#include "nvparameterized/NvParamUtils.h" +#include "ImpactEmitterActor.h" +#include "GroundEmitterActor.h" +#include "TurbulenceFSAsset.h" +#include "BasicIosAsset.h" +#include "RenderDebugInterface.h" +#include "BasicFSAsset.h" +#include "RenderDebugInterface.h" +#include "SceneIntl.h" +#include "ForceFieldAsset.h" +#include "ForceFieldActor.h" +#include "HeatSourceAsset.h" +#include "HeatSourceActor.h" +#include "HeatSourceAssetParams.h" + +#include "ApexEmitterActorParameters.h" +#include "ApexEmitterAssetParameters.h" + +#include "SubstanceSourceAsset.h" +#include "SubstanceSourceActor.h" +#include "SubstanceSourceAsset.h" +#include "SubstanceSourceAssetParams.h" + +#include "VelocitySourceAsset.h" +#include "VelocitySourceActor.h" +#include "VelocitySourceAssetParams.h" + +#include "FlameEmitterAsset.h" +#include "FlameEmitterActor.h" +#include "FlameEmitterAssetParams.h" + +#include "TurbulenceFSAssetParams.h" + +#include "ScopedPhysXLock.h" + +#include "PxPhysics.h" +#include "PxScene.h" +#include "ApexResourceHelper.h" +#include "PsMathUtils.h" + + +#pragma warning(disable:4100) + +namespace nvidia +{ +namespace particles +{ + using namespace physx; + +static PxTransform _getPose(float x, float y, float z, float rotX, float rotY, float rotZ) +{ + PxTransform ret; + ret.p = PxVec3(x, y, z); + fm_eulerToQuat(rotX * FM_DEG_TO_RAD, rotY * FM_DEG_TO_RAD, rotZ * FM_DEG_TO_RAD, &ret.q.x); + return ret; +} + +void _getRot(const PxQuat& q, float& rotX, float& rotY, float& rotZ) +{ + fm_quatToEuler((float*)&q, rotX, rotY, rotZ); + rotX *= FM_RAD_TO_DEG; + rotY *= FM_RAD_TO_DEG; + rotZ *= FM_RAD_TO_DEG; +} + +static float ranf(void) +{ + uint32_t r = (uint32_t)::rand(); + r &= 0x7FFF; + return (float)r * (1.0f / 32768.0f); +} + +static float ranf(float min, float max) +{ + return ranf() * (max - min) + min; +} + +EffectPackageActorImpl::EffectPackageActorImpl(EffectPackageAsset* apexAsset, + const EffectPackageAssetParams* assetParams, + const EffectPackageActorParams* actorParams, + nvidia::apex::ApexSDK& sdk, + nvidia::apex::Scene& scene, + ParticlesScene& dynamicSystemScene, + ModuleTurbulenceFS* moduleTurbulenceFS) +{ + mRigidBodyChange = false; + mRenderVolume = NULL; + mEmitterValidateCallback = NULL; + mAlive = true; + mSimTime = 0; + mCurrentLifeTime = 0; + mFadeIn = false; + mFadeInTime = 0; + mFadeInDuration = 0; + mFadeOut = false; + mFadeOutTime = 0; + mFadeOutDuration = 0; + mFirstFrame = true; + mData = assetParams; + mAsset = apexAsset; + mScene = &scene; + mModuleTurbulenceFS = moduleTurbulenceFS; + mEnabled = actorParams->Enabled; + mVisible = false; + mEverVisible = false; + mOffScreenTime = 0; + mVisState = VS_ON_SCREEN; + mFadeTime = 0; + mNotVisibleTime = 0; + mPose = actorParams->InitialPose; + mObjectScale = actorParams->objectScale; + mEffectPath = PX_NEW(EffectPath); + { + RigidBodyEffectNS::EffectPath_Type *path = (RigidBodyEffectNS::EffectPath_Type *)&mData->Path; + if ( !mEffectPath->init(*path)) + { + delete mEffectPath; + mEffectPath = NULL; + } + } + + for (int32_t i = 0; i < mData->Effects.arraySizes[0]; i++) + { + NvParameterized::Interface* iface = mData->Effects.buf[i]; + PX_ASSERT(iface); + if (iface) + { + EffectType type = getEffectType(iface); + switch (type) + { + case ET_EMITTER: + { + EmitterEffect* ed = static_cast< EmitterEffect*>(iface); + if (ed->Emitter) + { + EffectEmitter* ee = PX_NEW(EffectEmitter)(ed->Emitter->name(), ed, sdk, scene, dynamicSystemScene, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + } + break; + case ET_HEAT_SOURCE: + { + HeatSourceEffect* ed = static_cast< HeatSourceEffect*>(iface); + EffectHeatSource* ee = PX_NEW(EffectHeatSource)(ed->HeatSource->name(), ed, sdk, scene, dynamicSystemScene, moduleTurbulenceFS, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_SUBSTANCE_SOURCE: + { + SubstanceSourceEffect* ed = static_cast< SubstanceSourceEffect*>(iface); + EffectSubstanceSource* ee = PX_NEW(EffectSubstanceSource)(ed->SubstanceSource->name(), ed, sdk, scene, dynamicSystemScene, moduleTurbulenceFS, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_VELOCITY_SOURCE: + { + VelocitySourceEffect* ed = static_cast< VelocitySourceEffect*>(iface); + EffectVelocitySource* ee = PX_NEW(EffectVelocitySource)(ed->VelocitySource->name(), ed, sdk, scene, dynamicSystemScene, moduleTurbulenceFS, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_FLAME_EMITTER: + { + FlameEmitterEffect* ed = static_cast< FlameEmitterEffect*>(iface); + EffectFlameEmitter* ee = PX_NEW(EffectFlameEmitter)(ed->FlameEmitter->name(), ed, sdk, scene, dynamicSystemScene, moduleTurbulenceFS, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_TURBULENCE_FS: + { + TurbulenceFieldSamplerEffect* ed = static_cast< TurbulenceFieldSamplerEffect*>(iface); + EffectTurbulenceFS* ee = PX_NEW(EffectTurbulenceFS)(ed->TurbulenceFieldSampler->name(), ed, sdk, scene, dynamicSystemScene, moduleTurbulenceFS, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_JET_FS: + { + JetFieldSamplerEffect* ed = static_cast< JetFieldSamplerEffect*>(iface); + EffectJetFS* ee = PX_NEW(EffectJetFS)(ed->JetFieldSampler->name(), ed, sdk, scene, dynamicSystemScene, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_WIND_FS: + { + WindFieldSamplerEffect* ed = static_cast< WindFieldSamplerEffect*>(iface); + EffectWindFS* ee = PX_NEW(EffectWindFS)(ed->WindFieldSampler->name(), ed, sdk, scene, dynamicSystemScene, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_RIGID_BODY: + { + RigidBodyEffect* ed = static_cast< RigidBodyEffect*>(iface); + EffectRigidBody* ee = PX_NEW(EffectRigidBody)("RigidBody", ed, sdk, scene, dynamicSystemScene, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_NOISE_FS: + { + NoiseFieldSamplerEffect* ed = static_cast< NoiseFieldSamplerEffect*>(iface); + EffectNoiseFS* ee = PX_NEW(EffectNoiseFS)(ed->NoiseFieldSampler->name(), ed, sdk, scene, dynamicSystemScene, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_VORTEX_FS: + { + VortexFieldSamplerEffect* ed = static_cast< VortexFieldSamplerEffect*>(iface); + EffectVortexFS* ee = PX_NEW(EffectVortexFS)(ed->VortexFieldSampler->name(), ed, sdk, scene, dynamicSystemScene, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_ATTRACTOR_FS: + { + AttractorFieldSamplerEffect* ed = static_cast< AttractorFieldSamplerEffect*>(iface); + EffectAttractorFS* ee = PX_NEW(EffectAttractorFS)(ed->AttractorFieldSampler->name(), ed, sdk, scene, dynamicSystemScene, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + case ET_FORCE_FIELD: + { + ForceFieldEffect* ed = static_cast< ForceFieldEffect*>(iface); + EffectForceField* ee = PX_NEW(EffectForceField)(ed->ForceField->name(), ed, sdk, scene, dynamicSystemScene, mPose, mEnabled); + ee->setCurrentScale(mObjectScale,mEffectPath); + mEffects.pushBack(static_cast< EffectData*>(ee)); + } + break; + default: + PX_ALWAYS_ASSERT(); + break; + } + } + } + addSelfToContext(*dynamicSystemScene.mApexScene->getApexContext()); // Add self to ApexScene + addSelfToContext(dynamicSystemScene); // Add self to ParticlesScene's list of actors +} + +EffectPackageActorImpl::~EffectPackageActorImpl(void) +{ + for (uint32_t i = 0; i < mEffects.size(); i++) + { + EffectData* ed = mEffects[i]; + delete ed; + } + delete mEffectPath; +} + +EffectType EffectPackageActorImpl::getEffectType(const NvParameterized::Interface* iface) +{ + EffectType ret = ET_LAST; + + if (nvidia::strcmp(iface->className(), EmitterEffect::staticClassName()) == 0) + { + ret = ET_EMITTER; + } + else if (nvidia::strcmp(iface->className(), HeatSourceEffect::staticClassName()) == 0) + { + ret = ET_HEAT_SOURCE; + } + else if (nvidia::strcmp(iface->className(), SubstanceSourceEffect::staticClassName()) == 0) + { + ret = ET_SUBSTANCE_SOURCE; + } + else if (nvidia::strcmp(iface->className(), VelocitySourceEffect::staticClassName()) == 0) + { + ret = ET_VELOCITY_SOURCE; + } + else if (nvidia::strcmp(iface->className(), FlameEmitterEffect::staticClassName()) == 0) + { + ret = ET_FLAME_EMITTER; + } + else if (nvidia::strcmp(iface->className(), ForceFieldEffect::staticClassName()) == 0) + { + ret = ET_FORCE_FIELD; + } + else if (nvidia::strcmp(iface->className(), JetFieldSamplerEffect::staticClassName()) == 0) + { + ret = ET_JET_FS; + } + else if (nvidia::strcmp(iface->className(), WindFieldSamplerEffect::staticClassName()) == 0) + { + ret = ET_WIND_FS; + } + else if (nvidia::strcmp(iface->className(), RigidBodyEffect::staticClassName()) == 0) + { + ret = ET_RIGID_BODY; + } + else if (nvidia::strcmp(iface->className(), NoiseFieldSamplerEffect::staticClassName()) == 0) + { + ret = ET_NOISE_FS; + } + else if (nvidia::strcmp(iface->className(), VortexFieldSamplerEffect::staticClassName()) == 0) + { + ret = ET_VORTEX_FS; + } + else if (nvidia::strcmp(iface->className(), AttractorFieldSamplerEffect::staticClassName()) == 0) + { + ret = ET_ATTRACTOR_FS; + } + else if (nvidia::strcmp(iface->className(), TurbulenceFieldSamplerEffect::staticClassName()) == 0) + { + ret = ET_TURBULENCE_FS; + } + else + { + PX_ALWAYS_ASSERT(); + } + + return ret; +} + +const PxTransform& EffectPackageActorImpl::getPose(void) const +{ + READ_ZONE(); + return mPose; +} + +void EffectPackageActorImpl::visualize(RenderDebugInterface* callback, bool solid) const +{ + using RENDER_DEBUG::DebugRenderState; + if ( !mEnableDebugVisualization ) return; + RENDER_DEBUG_IFACE(callback)->pushRenderState(); + + RENDER_DEBUG_IFACE(callback)->addToCurrentState(DebugRenderState::CameraFacing); + RENDER_DEBUG_IFACE(callback)->addToCurrentState(DebugRenderState::CenterText); + + RENDER_DEBUG_IFACE(callback)->debugText(mPose.p - PxVec3(0, 0.35f, 0), mAsset->getName()); + + RENDER_DEBUG_IFACE(callback)->debugAxes(PxMat44(mPose)); + + for (uint32_t i = 0; i < mEffects.size(); i++) + { + mEffects[i]->visualize(callback, solid); + } + + RENDER_DEBUG_IFACE(callback)->popRenderState(); +} + +void EffectPackageActorImpl::setPose(const PxTransform& pose) +{ + WRITE_ZONE(); + mPose = pose; + + for (uint32_t i = 0; i < mEffects.size(); i++) + { + mEffects[i]->refresh(mPose, mEnabled, true, mRenderVolume,mEmitterValidateCallback); + } +} + +void EffectPackageActorImpl::refresh(void) +{ + WRITE_ZONE(); + for (uint32_t i = 0; i < mEffects.size(); i++) + { + EffectData* ed = mEffects[i]; + + if (ed->getEffectActor() ) + { + ed->refresh(mPose, mEnabled, true, mRenderVolume,mEmitterValidateCallback); + } + else if ( ed->getType() == ET_RIGID_BODY ) + { + EffectRigidBody *erb = static_cast< EffectRigidBody *>(ed); + if ( erb->mRigidDynamic ) + { + ed->refresh(mPose, mEnabled, true, mRenderVolume,mEmitterValidateCallback); + } + } + } +} + +void EffectPackageActorImpl::release(void) +{ + delete this; +} + +const char* EffectPackageActorImpl::getName(void) const +{ + READ_ZONE(); + return mAsset ? mAsset->getName() : NULL; +} + + +uint32_t EffectPackageActorImpl::getEffectCount(void) const // returns the number of effects in the effect package +{ + READ_ZONE(); + return mEffects.size(); +} + +EffectType EffectPackageActorImpl::getEffectType(uint32_t effectIndex) const // return the type of effect. +{ + READ_ZONE(); + EffectType ret = ET_LAST; + + if (effectIndex < mEffects.size()) + { + EffectData* ed = mEffects[effectIndex]; + ret = ed->getType(); + } + + return ret; +} + +Actor* EffectPackageActorImpl::getEffectActor(uint32_t effectIndex) const // return the base Actor pointer +{ + READ_ZONE(); + Actor* ret = NULL; + + if (effectIndex < mEffects.size()) + { + EffectData* ed = mEffects[effectIndex]; + ret = ed->getEffectActor(); + } + + + return ret; +} +void EffectPackageActorImpl::setEmitterState(bool state) // set the state for all emitters in this effect package. +{ + WRITE_ZONE(); + for (uint32_t i = 0; i < mEffects.size(); i++) + { + if (mEffects[i]->getType() == ET_EMITTER) + { + Actor* a = mEffects[i]->getEffectActor(); + if (a) + { + EmitterActor* ae = static_cast< EmitterActor*>(a); + if (state) + { + ae->startEmit(false); + } + else + { + ae->stopEmit(); + } + } + } + } +} + +uint32_t EffectPackageActorImpl::getActiveParticleCount(void) const // return the total number of particles still active in this effect package. +{ + READ_ZONE(); + uint32_t ret = 0; + + for (uint32_t i = 0; i < mEffects.size(); i++) + { + if (mEffects[i]->getType() == ET_EMITTER) + { + Actor* a = mEffects[i]->getEffectActor(); + if (a) + { + EmitterActor* ae = static_cast< EmitterActor*>(a); + ret += ae->getActiveParticleCount(); + } + } + } + return ret; +} + +bool EffectPackageActorImpl::isStillEmitting(void) const // return true if any emitters are still actively emitting particles. +{ + READ_ZONE(); + bool ret = false; + + for (uint32_t i = 0; i < mEffects.size(); i++) + { + if (mEffects[i]->getType() == ET_EMITTER) + { + Actor* a = mEffects[i]->getEffectActor(); + if (a) + { + EmitterActor* ae = static_cast< EmitterActor*>(a); + if (ae->isEmitting()) + { + ret = true; + break; + } + } + } + } + return ret; +} + +// Effect class implementations + +EffectEmitter::EffectEmitter(const char* parentName, + const EmitterEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), EffectData(ET_EMITTER, &sdk, + &scene, + &dscene, + parentName, + EMITTER_AUTHORING_TYPE_NAME, + *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ + mEmitterVelocity = PxVec3(0, 0, 0); + mFirstVelocityFrame = true; + mHaveSetPosition = false; + mVelocityTime = 0; + mLastEmitterPosition = PxVec3(0, 0, 0); +} + +EffectEmitter::~EffectEmitter(void) +{ +} + +EffectTurbulenceFS::EffectTurbulenceFS(const char* parentName, + TurbulenceFieldSamplerEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + ModuleTurbulenceFS* moduleTurbulenceFS, + const PxTransform& rootPose, + bool parentEnabled) : + mData(data), + mModuleTurbulenceFS(moduleTurbulenceFS), + EffectData(ET_TURBULENCE_FS, &sdk, &scene, &dscene, parentName, TURBULENCE_FS_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectTurbulenceFS::~EffectTurbulenceFS(void) +{ +} + +EffectJetFS::EffectJetFS(const char* parentName, + JetFieldSamplerEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), EffectData(ET_JET_FS, &sdk, &scene, &dscene, parentName, JET_FS_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectJetFS::~EffectJetFS(void) +{ +} + +EffectWindFS::EffectWindFS(const char* parentName, + WindFieldSamplerEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), EffectData(ET_WIND_FS, &sdk, &scene, &dscene, parentName, WIND_FS_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectWindFS::~EffectWindFS(void) +{ +} + + + +EffectAttractorFS::EffectAttractorFS(const char* parentName, + AttractorFieldSamplerEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), EffectData(ET_ATTRACTOR_FS, &sdk, &scene, &dscene, parentName, ATTRACTOR_FS_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectAttractorFS::~EffectAttractorFS(void) +{ +} + +void EffectEmitter::visualize(RenderDebugInterface* callback, bool solid) const +{ + RENDER_DEBUG_IFACE(callback)->debugText(mPose.p, mData->Emitter->name()); + RENDER_DEBUG_IFACE(callback)->debugAxes(PxMat44(mPose)); + +} + + + +EffectHeatSource::EffectHeatSource(const char* parentName, + HeatSourceEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + ModuleTurbulenceFS* moduleTurbulenceFS, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), + mModuleTurbulenceFS(moduleTurbulenceFS), + EffectData(ET_HEAT_SOURCE, &sdk, &scene, &dscene, parentName, HEAT_SOURCE_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectHeatSource::~EffectHeatSource(void) +{ +} + +void EffectHeatSource::visualize(RenderDebugInterface* callback, bool solid) const +{ +} + +bool EffectHeatSource::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + PxTransform pose(myPose); + bool ok = NvParameterized::setParamTransform(*descParams, "initialPose", pose); + PX_ASSERT(ok); + ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + ret = true; + } + const NvParameterized::Interface* iface = mAsset->getAssetNvParameterized(); + const turbulencefs::HeatSourceAssetParams* hap = static_cast< const turbulencefs::HeatSourceAssetParams*>(iface); + mAverageTemperature = hap->averageTemperature; + mStandardDeviationTemperature = hap->stdTemperature; + } + else if (mActor) + { + HeatSourceActor* a = static_cast< HeatSourceActor*>(mActor); + nvidia::apex::Shape *s = a->getShape(); + s->setPose(myPose); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + +EffectSubstanceSource::EffectSubstanceSource(const char* parentName, + SubstanceSourceEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + ModuleTurbulenceFS* moduleTurbulenceFS, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), + mModuleTurbulenceFS(moduleTurbulenceFS), + EffectData(ET_SUBSTANCE_SOURCE, &sdk, &scene, &dscene, parentName, SUBSTANCE_SOURCE_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectSubstanceSource::~EffectSubstanceSource(void) +{ +} + +void EffectSubstanceSource::visualize(RenderDebugInterface* callback, bool solid) const +{ +} + +bool EffectSubstanceSource::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + PxTransform pose(myPose); + bool ok = NvParameterized::setParamTransform(*descParams, "initialPose", pose); + PX_ASSERT(ok); + ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + ret = true; + } + const NvParameterized::Interface* iface = mAsset->getAssetNvParameterized(); + const turbulencefs::SubstanceSourceAssetParams* hap = static_cast< const turbulencefs::SubstanceSourceAssetParams*>(iface); + mAverageDensity = hap->averageDensity; + mStandardDeviationDensity = hap->stdDensity; + } + else if (mActor) + { + SubstanceSourceActor* a = static_cast< SubstanceSourceActor*>(mActor); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + nvidia::apex::Shape *s = a->getShape(); + s->setPose(myPose); + } + } + else + { + if ( mActor ) + { + ret = true; + releaseActor(); + } + } + return ret; +} + +EffectVelocitySource::EffectVelocitySource(const char* parentName, + VelocitySourceEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + ModuleTurbulenceFS* moduleTurbulenceFS, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), + mModuleTurbulenceFS(moduleTurbulenceFS), + EffectData(ET_VELOCITY_SOURCE, &sdk, &scene, &dscene, parentName, VELOCITY_SOURCE_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectVelocitySource::~EffectVelocitySource(void) +{ +} + +void EffectVelocitySource::visualize(RenderDebugInterface* callback, bool solid) const +{ +} + +bool EffectVelocitySource::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + PxTransform pose(myPose); + bool ok = NvParameterized::setParamTransform(*descParams, "initialPose", pose); + PX_ASSERT(ok); + ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + ret = true; + } + const NvParameterized::Interface* iface = mAsset->getAssetNvParameterized(); + const turbulencefs::VelocitySourceAssetParams* hap = static_cast< const turbulencefs::VelocitySourceAssetParams*>(iface); + mAverageVelocity = hap->averageVelocity; + mStandardDeviationVelocity = hap->stdVelocity; + } + else if (mActor) + { + VelocitySourceActor* a = static_cast< VelocitySourceActor*>(mActor); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + nvidia::apex::Shape *s = a->getShape(); + s->setPose(myPose); + } + } + else + { + if ( mActor ) + { + ret = true; + releaseActor(); + } + } + return ret; +} + + +EffectFlameEmitter::EffectFlameEmitter(const char* parentName, + FlameEmitterEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + ModuleTurbulenceFS* moduleTurbulenceFS, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), + mModuleTurbulenceFS(moduleTurbulenceFS), + EffectData(ET_FLAME_EMITTER, &sdk, &scene, &dscene, parentName, FLAME_EMITTER_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectFlameEmitter::~EffectFlameEmitter(void) +{ +} + +void EffectFlameEmitter::visualize(RenderDebugInterface* callback, bool solid) const +{ +} + +bool EffectFlameEmitter::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + PxTransform pose(myPose); + bool ok = NvParameterized::setParamTransform(*descParams, "initialPose", pose); + PX_ASSERT(ok); + ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + ret = true; + } + } + else if (mActor) + { + FlameEmitterActor* a = static_cast< FlameEmitterActor*>(mActor); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + a->setPose(myPose); + } + } + else + { + if ( mActor ) + { + ret = true; + releaseActor(); + } + } + return ret; +} + + +void EffectTurbulenceFS::visualize(RenderDebugInterface* callback, bool solid) const +{ + +} + +void EffectJetFS::visualize(RenderDebugInterface* callback, bool solid) const +{ + +} + +void EffectWindFS::visualize(RenderDebugInterface* callback, bool solid) const +{ + +} + +void EffectAttractorFS::visualize(RenderDebugInterface* callback, bool solid) const +{ + +} + +void EffectEmitter::computeVelocity(float dtime) +{ + mVelocityTime += dtime; + if (mFirstVelocityFrame) + { + if (mActor) + { + mFirstVelocityFrame = false; + mVelocityTime = 0; + EmitterActor* ea = static_cast< EmitterActor*>(mActor); + mLastEmitterPosition = ea->getGlobalPose().getPosition(); + } + } + else if (mHaveSetPosition && mActor) + { + mHaveSetPosition = false; + EmitterActor* ea = static_cast< EmitterActor*>(mActor); + PxVec3 newPos = ea->getGlobalPose().getPosition(); + mEmitterVelocity = (newPos - mLastEmitterPosition) * (1.0f / mVelocityTime); + mLastEmitterPosition = newPos; + mVelocityTime = 0; + } +} + +bool EffectEmitter::refresh(const PxTransform& parent, + bool parentEnabled, + bool fromSetPose, + RenderVolume* renderVolume, + EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + + mPose = parent * localPose; + getSamplePoseSpline(mPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + mFirstVelocityFrame = true; + mHaveSetPosition = false; + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + bool ok = NvParameterized::setParamTransform(*descParams, "initialPose", mPose); + PX_UNUSED(ok); + PX_ASSERT(ok); + ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + ok = NvParameterized::setParamBool(*descParams, "emitAssetParticles", true); + PX_ASSERT(ok); + EmitterAsset* easset = static_cast< EmitterAsset*>(mAsset); + EmitterActor* ea = mParticlesScene->getEmitterFromPool(easset); + if (ea) + { + ea->setCurrentPose(mPose); + ea->setCurrentScale(mObjectScale*getSampleScaleSpline()); + mActor = static_cast< Actor*>(ea); + } + else + { + mActor = mAsset->createApexActor(*descParams, *mApexScene); + } + if (mActor) + { + const NvParameterized::Interface* iface = mAsset->getAssetNvParameterized(); + const char* className = iface->className(); + if (nvidia::strcmp(className, "ApexEmitterAssetParameters") == 0) + { + const emitter::ApexEmitterAssetParameters* ap = static_cast<const emitter::ApexEmitterAssetParameters*>(iface); + mRate = ap->rate; + mLifetimeLow = ap->lifetimeLow; + mLifetimeHigh = ap->lifetimeHigh; + EmitterActor* ea = static_cast< EmitterActor*>(mActor); + ea->setRate(mRate); + ea->setLifetimeLow(mLifetimeLow); + ea->setLifetimeHigh(mLifetimeHigh); + ea->startEmit(false); + ea->setPreferredRenderVolume(renderVolume); + ea->setApexEmitterValidateCallback(callback); + } + ret = true; + } + } + } + else if (mActor) + { + EmitterActor* ea = static_cast< EmitterActor*>(mActor); + mHaveSetPosition = true; // set semaphore for computing the velocity. + ea->setCurrentPose(mPose); + ea->setObjectScale(mObjectScale*getSampleScaleSpline()); + ea->setPreferredRenderVolume(renderVolume); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + + +bool EffectTurbulenceFS::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + bool ok = NvParameterized::setParamTransform(*descParams, "initialPose", myPose); + PX_UNUSED(ok); + PX_ASSERT(ok); + ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + ret = true; + } + } + else if (mActor) + { + TurbulenceFSActor* a = static_cast< TurbulenceFSActor*>(mActor); + a->setPose(myPose); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + +bool EffectJetFS::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + bool ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + if (mActor) + { + JetFSActor* fs = static_cast< JetFSActor*>(mActor); + if (fs) + { + fs->setCurrentPose(myPose); + fs->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + ret = true; + } + } + } + else if (mActor) + { + JetFSActor* a = static_cast< JetFSActor*>(mActor); + a->setCurrentPose(myPose); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + +bool EffectWindFS::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + bool ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + if (mActor) + { + WindFSActor* fs = static_cast< WindFSActor*>(mActor); + if (fs) + { + fs->setCurrentPose(myPose); + fs->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + ret = true; + } + } + } + else if (mActor) + { + WindFSActor* a = static_cast< WindFSActor*>(mActor); + a->setCurrentPose(myPose); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + +bool EffectAttractorFS::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform initialPose = _getPose(mData->EffectProperties.Position.TranslateX*mObjectScale*getSampleScaleSpline(), + mData->EffectProperties.Position.TranslateY*mObjectScale*getSampleScaleSpline(), + mData->EffectProperties.Position.TranslateZ*mObjectScale*getSampleScaleSpline(), + mData->EffectProperties.Orientation.RotateX, + mData->EffectProperties.Orientation.RotateY, + mData->EffectProperties.Orientation.RotateZ); + + PxTransform myPose(parent * initialPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + + bool ok = NvParameterized::setParamTransform(*descParams, "initialPose", myPose); + PX_UNUSED(ok); + PX_ASSERT(ok); + ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + ret = true; + } + } + else if (mActor) + { + AttractorFSActor* a = static_cast< AttractorFSActor*>(mActor); + a->setCurrentPosition(myPose.p); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + + +EffectForceField::EffectForceField(const char* parentName, ForceFieldEffect* data, ApexSDK& sdk, Scene& scene, ParticlesScene& dscene, const PxTransform& rootPose, bool parentEnabled) : mData(data), EffectData(ET_FORCE_FIELD, &sdk, &scene, &dscene, parentName, FORCEFIELD_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectForceField::~EffectForceField(void) +{ +} + +void EffectForceField::visualize(RenderDebugInterface* callback, bool solid) const +{ + +} + +bool EffectForceField::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform initialPose = _getPose(mData->EffectProperties.Position.TranslateX*mObjectScale*getSampleScaleSpline(), + mData->EffectProperties.Position.TranslateY*mObjectScale*getSampleScaleSpline(), + mData->EffectProperties.Position.TranslateZ*mObjectScale*getSampleScaleSpline(), + mData->EffectProperties.Orientation.RotateX, + mData->EffectProperties.Orientation.RotateY, + mData->EffectProperties.Orientation.RotateZ); + PxTransform myPose(parent * initialPose); + getSamplePoseSpline(myPose); + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + bool ok = NvParameterized::setParamF32(*descParams, "scale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + if (mActor) + { + ForceFieldActor* fs = static_cast< ForceFieldActor*>(mActor); + if (fs) + { + fs->setPose(myPose); + fs->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + ret = true; + } + } + } + else if (mActor) + { + ForceFieldActor* a = static_cast< ForceFieldActor*>(mActor); + a->setPose(myPose); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + +// Returns true if this is a type which has a named resource asset which needs to be resolved. RigidBody effects do not; all of their properties are embedded +static bool isNamedResourceType(EffectType type) +{ + bool ret = true; + + if ( type == ET_RIGID_BODY ) + { + ret = false; + } + + return ret; +} + +EffectData::EffectData(EffectType type, + ApexSDK* sdk, + Scene* scene, + ParticlesScene* dscene, + const char* assetName, + const char* nameSpace, + RigidBodyEffectNS::EffectProperties_Type &effectProperties) +{ + mEffectPath = NULL; + mParentPath = NULL; + mObjectScale = 1; + + mLocalPose = _getPose(effectProperties.Position.TranslateX, + effectProperties.Position.TranslateY, + effectProperties.Position.TranslateZ, + effectProperties.Orientation.RotateX, + effectProperties.Orientation.RotateY, + effectProperties.Orientation.RotateZ); + + mEffectPath = PX_NEW(EffectPath); + if ( !mEffectPath->init(effectProperties.Path) ) + { + delete mEffectPath; + mEffectPath = NULL; + } + + mEnabled = effectProperties.Enable; + mRandomDeviation = effectProperties.RandomizeRepeatTime; + mForceRenableEmitter = false; + mUseEmitterPool = dscene->getModuleParticles()->getUseEmitterPool(); + mFirstRate = true; + mType = type; + mState = ES_INITIAL_DELAY; + mStateTime = getRandomTime(effectProperties.InitialDelayTime); + mSimulationTime = 0; + mStateCount = 0; + mParticlesScene = dscene; + mInitialDelayTime = effectProperties.InitialDelayTime; + mDuration = effectProperties.Duration; + mRepeatCount = effectProperties.RepeatCount; + mRepeatDelay = effectProperties.RepeatDelay; + mApexSDK = sdk; + mApexScene = scene; + mActor = NULL; + mNameSpace = nameSpace; + mAsset = NULL; + if ( isNamedResourceType(mType) ) + { + mAsset = (nvidia::apex::Asset*)mApexSDK->getNamedResourceProvider()->getResource(mNameSpace, assetName); + if (mAsset) + { + if (mType == ET_EMITTER) + { + if (!mUseEmitterPool) + { + mApexSDK->getNamedResourceProvider()->setResource(mNameSpace, assetName, mAsset, true); + } + } + else + { + mApexSDK->getNamedResourceProvider()->setResource(mNameSpace, assetName, mAsset, true); + } + } + } +} + +EffectData::~EffectData(void) +{ + releaseActor(); + + delete mEffectPath; + + if (mAsset) + { + if (mType == ET_EMITTER) + { + if (!mUseEmitterPool) + { + mApexSDK->getNamedResourceProvider()->releaseResource(mNameSpace, mAsset->getName()); + } + } + else + { + mApexSDK->getNamedResourceProvider()->releaseResource(mNameSpace, mAsset->getName()); + } + } +} + +void EffectData::releaseActor(void) +{ + if (mActor) + { + if (mType == ET_EMITTER && mUseEmitterPool) + { + EmitterActor* ae = static_cast< EmitterActor*>(mActor); + mParticlesScene->addToEmitterPool(ae); + } + else + { + mActor->release(); + } + mActor = NULL; + } +} + +float EffectData::getRandomTime(float baseTime) +{ + float deviation = baseTime * mRandomDeviation; + return ranf(baseTime - deviation, baseTime + deviation); +} + +bool EffectData::simulate(float dtime, bool& reset) +{ + bool ret = false; + + if (!mEnabled) + { + return false; + } + + switch (mState) + { + case ES_INITIAL_DELAY: + mStateTime -= dtime; + if (mStateTime <= 0) + { + mState = ES_ACTIVE; // once past the initial delay, it is now active + mStateTime = getRandomTime(mDuration); // Time to the next state change... + ret = true; // set ret to true because the effect is alive + } + break; + case ES_ACTIVE: + ret = true; // it's still active.. + mStateTime -= dtime; // decrement delta time to next state change. + mSimulationTime+=dtime; + if (mStateTime <= 0) // if it's time for a state change. + { + if (mDuration == 0) // if the + { + if (mRepeatDelay > 0) // if there is a delay until the time we repeate + { + mStateTime = getRandomTime(mRepeatDelay); // set time until repeat delay + mState = ES_REPEAT_DELAY; // change state to repeat delay + } + else + { + mStateTime = getRandomTime(mDuration); // if there is no repeat delay; just continue + if (mRepeatCount > 1) + { + reset = true; // looped.. + } + } + } + else + { + mStateCount++; // increment the state change counter. + if (mStateCount >= mRepeatCount && mRepeatCount != 9999) // have we hit the total number repeat counts. + { + mState = ES_DONE; // then we are completely done; the actor is no longer alive + ret = false; + } + else + { + if (mRepeatDelay > 0) // is there a repeat delay? + { + mStateTime = getRandomTime(mRepeatDelay); + mState = ES_REPEAT_DELAY; + } + else + { + mStateTime = getRandomTime(mDuration); + reset = true; + } + } + } + } + else + { + if ( mEffectPath && mDuration != 0 ) + { + mEffectPath->computeSampleTime(mStateTime,mDuration); + } + } + if ( mDuration == 0 && mEffectPath ) + { + mEffectPath->computeSampleTime(mSimulationTime,mEffectPath->getPathDuration()); + } + break; + case ES_REPEAT_DELAY: + mStateTime -= dtime; + if (mStateTime < 0) + { + mState = ES_ACTIVE; + mStateTime = getRandomTime(mDuration); + reset = true; + ret = true; + } + break; + case ES_DONE: + break; + default: + //PX_ASSERT(0); + break; + } + + return ret; +} + +void EffectPackageActorImpl::updateParticles(float dtime) +{ + mSimTime = dtime; + mCurrentLifeTime += mSimTime; + + // If there has been some state change on one of the emitters, then we rebuild the emitter list! + if ( mRigidBodyChange ) + { + mRigidBodyChange = false; + } +} + +float EffectPackageActorImpl::internalGetDuration(void) +{ + float duration = 1000; + for (uint32_t i = 0; i < mEffects.size(); i++) + { + EffectData* ed = mEffects[i]; + if (ed->getDuration() < duration) + { + duration = ed->getDuration(); + } + } + return duration; +} + +// applies velocity adjustment to this range +static float processVelocityAdjust(const particles::EmitterEffectNS::EmitterVelocityAdjust_Type& vprops, + const PxVec3& velocity) +{ + + float r = 1; + float v = velocity.magnitude(); // compute the absolute magnitude of the current emitter velocity + if (v <= vprops.VelocityLow) // if the velocity is less than the minimum velocity adjustment range + { + r = vprops.LowValue; // Use the 'low-value' ratio adjustment + } + else if (v >= vprops.VelocityHigh) // If the velocity is greater than the high range + { + r = vprops.HighValue; // then clamp tot he high value adjustment + } + else + { + float ratio = 1; + float diff = vprops.VelocityHigh - vprops.VelocityLow; // Compute the velocity differntial + if (diff > 0) + { + ratio = 1.0f / diff; // compute the inverse velocity differential + } + float l = (v - vprops.VelocityLow) * ratio; // find out the velocity lerp rate + r = (vprops.HighValue - vprops.LowValue) * l + vprops.LowValue; + } + return r; +} + + +void EffectPackageActorImpl::updatePoseAndBounds(bool screenCulling, bool znegative) +{ + if (!mEnabled) + { + for (uint32_t i = 0; i < mEffects.size(); i++) + { + EffectData* ed = mEffects[i]; + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + else if ( ed->getType() == ET_RIGID_BODY ) + { + EffectRigidBody *erb = static_cast< EffectRigidBody *>(ed); + erb->releaseRigidBody(); + } + } + mAlive = false; + return; + } + + float ZCOMPARE = -1; + if (znegative) + { + ZCOMPARE *= -1; + } + + // + bool prevVisible = mVisible; + mVisible = true; // default visibile state is based on whether or not this effect is enabled. + float emitterRate = 1; + mVisState = VS_ON_SCREEN; // default value + if (mVisible) // if it's considered visible/enabled then let's do the LOD cacluation + { + const PxMat44& viewMatrix = mScene->getViewMatrix(); + PxVec3 pos = viewMatrix.transform(mPose.p); + float magnitudeSquared = pos.magnitudeSquared(); + if (mData->LODSettings.CullByDistance) // if distance culling is enabled + { + + // If the effect is past the maximum distance then mark it is no longer visible. + if (magnitudeSquared > mData->LODSettings.FadeDistanceEnd * mData->LODSettings.FadeDistanceEnd) + { + mVisible = false; + mVisState = VS_OFF_SCREEN; + } // if the effect is within the fade range; then compute the lerp value for it along that range as 'emitterRate' + else if (magnitudeSquared > mData->LODSettings.FadeDistanceEnd * mData->LODSettings.FadeDistanceBegin) + { + float distance = PxSqrt(magnitudeSquared); + float delta = mData->LODSettings.FadeDistanceEnd - mData->LODSettings.FadeDistanceBegin; + if (delta > 0) + { + emitterRate = 1.0f - ((distance - mData->LODSettings.FadeDistanceBegin) / delta); + } + } + } + // If it's still considered visible (i.e. in range) and off screen culling is enabled; let's test it's status on/off screen + if (mVisible && mData->LODSettings.CullOffScreen && screenCulling) + { + if (magnitudeSquared < (mData->LODSettings.ScreenCullDistance * mData->LODSettings.ScreenCullDistance)) + { + mVisState = VS_TOO_CLOSE; + } + else if (pos.z * ZCOMPARE > 0) + { + mVisState = VS_BEHIND_SCREEN; + } + else + { + const PxMat44& projMatrix = mScene->getProjMatrix(); + PxVec4 p(pos.x, pos.y, pos.z, 1); + p = projMatrix.transform(p); + float recipW = 1.0f / p.w; + + p.x = p.x * recipW; + p.y = p.y * recipW; + p.z = p.z * recipW; + + float smin = -1 - mData->LODSettings.ScreenCullSize; + float smax = 1 + mData->LODSettings.ScreenCullSize; + + if (p.x >= smin && p.x <= smax && p.y >= smin && p.y <= smax) + { + mVisState = VS_ON_SCREEN; + } + else + { + mVisState = VS_OFF_SCREEN; + } + } + } + } + if (mVisState == VS_ON_SCREEN || mVisState == VS_TOO_CLOSE) + { + mOffScreenTime = 0; + } + else + { + mOffScreenTime += mSimTime; + if (mOffScreenTime > mData->LODSettings.OffScreenCullTime) + { + mVisible = false; // mark it as non-visible due to it being off sceen too long. + mAlive = false; + } + else + { + mVisible = mEverVisible; // was it ever visible? + } + } + + if ( mEffectPath ) + { + mEffectPath->computeSampleTime(mCurrentLifeTime,mData->Path.PathDuration); + } + + if (mFirstFrame && !mVisible && screenCulling) + { + if (getDuration() != 0) + { + mEnabled = false; + return; + } + } + + + if (mVisible) + { + mEverVisible = true; + } + + + bool aliveState = mVisible; + + // do the fade in/fade out over time logic... + if (mData->LODSettings.FadeOutRate > 0) // If there is a fade in/out time. + { + if (aliveState) // if the effect is considered alive/visible then attenuate the emitterRate based on that fade in time value + { + mFadeTime += mSimTime; + if (mFadeTime < mData->LODSettings.FadeOutRate) + { + emitterRate = emitterRate * mFadeTime / mData->LODSettings.FadeOutRate; + } + else + { + mFadeTime = mData->LODSettings.FadeOutRate; + } + } + else // if the effect is not visible then attenuate it based on the fade out time + { + mFadeTime -= mSimTime; + if (mFadeTime > 0) + { + emitterRate = emitterRate * mFadeTime / mData->LODSettings.FadeOutRate; + aliveState = true; // still alive because it hasn't finsihed fading out... + } + else + { + mFadeTime = 0; + } + } + } + + if (mFadeIn) + { + mFadeInDuration += mSimTime; + if (mFadeInDuration > mFadeInTime) + { + mFadeIn = false; + } + else + { + float fadeScale = (mFadeInDuration / mFadeInTime); + emitterRate *= fadeScale; + } + } + + if (mFadeOut) + { + mFadeOutDuration += mSimTime; + if (mFadeOutDuration > mFadeOutTime) + { + aliveState = mVisible = false; + } + else + { + float fadeScale = 1.0f - (mFadeOutDuration / mFadeOutTime); + emitterRate *= fadeScale; + } + } + + if (mVisible) + { + mNotVisibleTime = 0; + } + else + { + mNotVisibleTime += mSimTime; + } + + bool anyAlive = false; + bool rigidBodyChange = false; + + for (uint32_t i = 0; i < mEffects.size(); i++) + { + bool alive = aliveState; + EffectData* ed = mEffects[i]; + // only emitters can handle a 'repeat' count. + // others have an initial delay + bool reset = false; + + if (ed->getDuration() == 0) + { + reset = !prevVisible; // if it was not previously visible then force a reset to bring it back to life. + } + if (alive) + { + alive = ed->simulate(mSimTime, reset); + if ( alive ) + { + anyAlive = true; + } + } + if (ed->isDead()) // if it's lifetime has completely expired kill it! + { + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + else if ( ed->getType() == ET_RIGID_BODY ) + { + EffectRigidBody *erb = static_cast< EffectRigidBody *>(ed); + erb->releaseRigidBody(); + rigidBodyChange = true; + } + } + else + { + switch (ed->getType()) + { + case ET_EMITTER: + { + EffectEmitter* ee = static_cast< EffectEmitter*>(ed); + ee->computeVelocity(mSimTime); + EmitterActor* ea = static_cast< EmitterActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if ( ed->getForceRenableEmitterSemaphore() && !ea->isEmitting() ) + { + reset = true; + } + if (reset) // is it time to reset it's condition? + { + ea->startEmit(false); + } + if (mData->LODSettings.FadeEmitterRate || mData->LODSettings.RandomizeEmitterRate || mFadeOut || mFadeIn) + { + // attenuate the emitter rate range based on the previously computed LOD lerp value + if (mData->LODSettings.RandomizeEmitterRate && ee->mFirstRate) + { + ee->mFirstRate = false; + } + if (mData->LODSettings.FadeEmitterRate || + mFadeOut || + mFadeIn || + ee->mData->EmitterVelocityChanges.AdjustEmitterRate.AdjustEnabled || + ee->mData->EmitterVelocityChanges.AdjustLifetime.AdjustEnabled) + { + float rate = ee->mRate * emitterRate; + if (ee->mData->EmitterVelocityChanges.AdjustEmitterRate.AdjustEnabled) + { + rate *= processVelocityAdjust(ee->mData->EmitterVelocityChanges.AdjustEmitterRate, ee->mEmitterVelocity); + } + ea->setRate(rate); + if (ee->mData->EmitterVelocityChanges.AdjustLifetime.AdjustEnabled) + { + float va = processVelocityAdjust(ee->mData->EmitterVelocityChanges.AdjustLifetime, ee->mEmitterVelocity); + ea->setLifetimeLow(ee->mLifetimeLow * va); + ea->setLifetimeLow(ee->mLifetimeHigh * va); + } + } + } + + if ( ee->activePath() ) + { + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setCurrentPose(pose); + } + + } + else + { + if (mNotVisibleTime > mData->LODSettings.NonVisibleDeleteTime) // if it's been non-visible for a long time; delete it, don't just disable it! + { + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + } + else + { + if (ea->isEmitting()) + { + ea->stopEmit(); // just stop emitting but don't destroy the actor. + } + } + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_ATTRACTOR_FS: + { + EffectAttractorFS *ee = static_cast< EffectAttractorFS *>(ed); + AttractorFSActor* ea = static_cast< AttractorFSActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setEnabled(true); + } + if (mData->LODSettings.FadeAttractorFieldStrength) + { + // TODO + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setCurrentPosition(pose.p); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + if (mNotVisibleTime > mData->LODSettings.NonVisibleDeleteTime) // if it's been non-visible for a long time; delete it, don't just disable it! + { + + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + } + else + { + ea->setEnabled(false); + } + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_JET_FS: + { + EffectJetFS *ee = static_cast< EffectJetFS *>(ed); + JetFSActor* ea = static_cast< JetFSActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setEnabled(true); + } + if (mData->LODSettings.FadeJetFieldStrength) + { + // TODO + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setCurrentPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + if (mNotVisibleTime > mData->LODSettings.NonVisibleDeleteTime) // if it's been non-visible for a long time; delete it, don't just disable it! + { + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + } + else + { + ea->setEnabled(false); + } + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_RIGID_BODY: + { + EffectRigidBody *erb = static_cast< EffectRigidBody *>(ed); + if ( alive ) + { + if ( ed->refresh(mPose, true, reset, mRenderVolume,mEmitterValidateCallback) ) + { + rigidBodyChange = true; + } + } + else + { + if ( erb->mRigidDynamic ) + { + erb->releaseRigidBody(); + rigidBodyChange = true; + } + } + } + break; + case ET_WIND_FS: + { + EffectWindFS *ee = static_cast< EffectWindFS *>(ed); + WindFSActor* ea = static_cast< WindFSActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setEnabled(true); + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setCurrentPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + if (mNotVisibleTime > mData->LODSettings.NonVisibleDeleteTime) // if it's been non-visible for a long time; delete it, don't just disable it! + { + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + } + else + { + ea->setEnabled(false); + } + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_NOISE_FS: + { + EffectNoiseFS *ee = static_cast< EffectNoiseFS *>(ed); + NoiseFSActor* ea = static_cast< NoiseFSActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setEnabled(true); + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setCurrentPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + if (mNotVisibleTime > mData->LODSettings.NonVisibleDeleteTime) // if it's been non-visible for a long time; delete it, don't just disable it! + { + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + } + else + { + ea->setEnabled(false); + } + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_VORTEX_FS: + { + EffectVortexFS *ee = static_cast< EffectVortexFS *>(ed); + VortexFSActor* ea = static_cast< VortexFSActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setEnabled(true); + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setCurrentPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + if (mNotVisibleTime > mData->LODSettings.NonVisibleDeleteTime) // if it's been non-visible for a long time; delete it, don't just disable it! + { + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + } + else + { + ea->setEnabled(false); + } + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_TURBULENCE_FS: + { + EffectTurbulenceFS *ee = static_cast< EffectTurbulenceFS *>(ed); + TurbulenceFSActor* ea = static_cast< TurbulenceFSActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setEnabled(true); + } + if (mData->LODSettings.FadeTurbulenceNoise) + { + // TODO + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + if (mNotVisibleTime > mData->LODSettings.NonVisibleDeleteTime) // if it's been non-visible for a long time; delete it, don't just disable it! + { + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + } + else + { + ea->setEnabled(false); + } + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_FORCE_FIELD: + { + EffectForceField *ee = static_cast< EffectForceField *>(ed); + ForceFieldActor* ea = static_cast< ForceFieldActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->enable(); + } + if (mData->LODSettings.FadeForceFieldStrength) + { + // TODO + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + if (mNotVisibleTime > mData->LODSettings.NonVisibleDeleteTime) // if it's been non-visible for a long time; delete it, don't just disable it! + { + if (ed->getEffectActor()) + { + ed->releaseActor(); + } + } + else + { + if (ea->isEnable()) + { + ea->disable(); + } + } + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_HEAT_SOURCE: + { + EffectHeatSource* ee = static_cast< EffectHeatSource*>(ed); + HeatSourceActor* ea = static_cast< HeatSourceActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setTemperature(ee->mAverageTemperature, ee->mStandardDeviationTemperature); + //ea->enable(); + //TODO! + } + if (mData->LODSettings.FadeHeatSourceTemperature) + { + // TODO + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + ed->releaseActor(); + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_SUBSTANCE_SOURCE: + { + EffectSubstanceSource* ee = static_cast< EffectSubstanceSource*>(ed); + SubstanceSourceActor* ea = static_cast< SubstanceSourceActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setDensity(ee->mAverageDensity, ee->mStandardDeviationDensity); + //ea->enable(); + //TODO! + } + if (mData->LODSettings.FadeHeatSourceTemperature) + { + // TODO + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + nvidia::apex::Shape *shape = ea->getShape(); + shape->setPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + ed->releaseActor(); + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_VELOCITY_SOURCE: + { + EffectVelocitySource* ee = static_cast< EffectVelocitySource*>(ed); + VelocitySourceActor* ea = static_cast< VelocitySourceActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setVelocity(ee->mAverageVelocity, ee->mStandardDeviationVelocity); + //ea->enable(); + //TODO! + } + if (mData->LODSettings.FadeHeatSourceTemperature) + { + // TODO + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + ed->releaseActor(); + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + case ET_FLAME_EMITTER: + { + EffectFlameEmitter* ee = static_cast< EffectFlameEmitter*>(ed); + FlameEmitterActor* ea = static_cast< FlameEmitterActor*>(ed->getEffectActor()); + // if there is already an emitter actor... + if (ea) + { + if (alive) // is it alive? + { + if (reset) // is it time to reset it's condition? + { + ea->setEnabled(true); + } + if ( ee->activePath() ) + { + PxTransform pose = mPose; + ee->getSamplePoseSpline(pose); + ea->setPose(pose); + ea->setCurrentScale(ee->mObjectScale*ee->getSampleScaleSpline()); + } + } + else + { + ed->releaseActor(); + } + } + else + { + if (alive) // if it is now alive but was not previously; start the initial instance. + { + ed->refresh(mPose, true, false, mRenderVolume,mEmitterValidateCallback); + } + } + } + break; + default: + PX_ALWAYS_ASSERT(); // effect type not handled! + break; + } + } + } + if ( rigidBodyChange ) + { + mRigidBodyChange = true; + } + mAlive = anyAlive; + mFirstFrame = false; +} + + +/** +\brief Returns the name of the effect at this index. + +\param [in] effectIndex : The effect number to refer to; must be less than the result of getEffectCount +*/ +const char* EffectPackageActorImpl::getEffectName(uint32_t effectIndex) const +{ + READ_ZONE(); + const char* ret = NULL; + if (effectIndex < mEffects.size()) + { + EffectData* ed = mEffects[effectIndex]; + ret = ed->getEffectAsset()->getName(); + } + return ret; +} + +/** +\brief Returns true if this sub-effect is currently enabled. + +\param [in] effectIndex : The effect number to refer to; must be less than the result of getEffectCount +*/ +bool EffectPackageActorImpl::isEffectEnabled(uint32_t effectIndex) const +{ + READ_ZONE(); + bool ret = false; + if (effectIndex < mEffects.size()) + { + EffectData* ed = mEffects[effectIndex]; + ret = ed->isEnabled(); + } + return ret; +} + +/** +\brief Set's the enabled state of this sub-effect + +\param [in] effectIndex : The effect number to refer to; must be less than the result of getEffectCount +\param [in] state : Whether the effect should be enabled or not. +*/ +bool EffectPackageActorImpl::setEffectEnabled(uint32_t effectIndex, bool state) +{ + WRITE_ZONE(); + bool ret = false; + + if (effectIndex < mEffects.size()) + { + EffectData* ed = mEffects[effectIndex]; + ed->setEnabled(state); + if ( ed->getType() == ET_EMITTER ) + { + ed->setForceRenableEmitter(state); // set the re-enable semaphore + } + ret = true; + } + + return ret; +} + +/** +\brief Returns the pose of this sub-effect; returns as a a bool the active state of this effect. + +\param [in] effectIndex : The effect number to refer to; must be less than the result of getEffectCount +\param [pose] : Contains the pose requested +\param [worldSpace] : Whether to return the pose in world-space or in parent-relative space. +*/ +bool EffectPackageActorImpl::getEffectPose(uint32_t effectIndex, PxTransform& pose, bool worldSpace) +{ + READ_ZONE(); + bool ret = false; + + if (effectIndex < mEffects.size()) + { + EffectData* ed = mEffects[effectIndex]; + + if (worldSpace) + { + pose = ed->getWorldPose(); + } + else + { + pose = ed->getLocalPose(); + } + ret = true; + } + + return ret; +} + +void EffectPackageActorImpl::setCurrentScale(float scale) +{ + WRITE_ZONE(); + mObjectScale = scale; + for (uint32_t i = 0; i < mEffects.size(); i++) + { + EffectData* ed = mEffects[i]; + ed->setCurrentScale(mObjectScale,mEffectPath); + ed->refresh(mPose, mEnabled, true, mRenderVolume,mEmitterValidateCallback); + } +} + +/** +\brief Sets the pose of this sub-effect; returns as a a bool the active state of this effect. + +\param [in] effectIndex : The effect number to refer to; must be less than the result of getEffectCount +\param [pose] : Contains the pose to be set +\param [worldSpace] : Whether to return the pose in world-space or in parent-relative space. +*/ +bool EffectPackageActorImpl::setEffectPose(uint32_t effectIndex, const PxTransform& pose, bool worldSpace) +{ + WRITE_ZONE(); + bool ret = false; + + if (effectIndex < mEffects.size()) + { + EffectData* ed = mEffects[effectIndex]; + if (worldSpace) + { + PxTransform p = getPose(); // get root pose + PxTransform i = p.getInverse(); + PxTransform l = i * pose; + ed->setLocalPose(pose); // change the local pose + setPose(p); + } + else + { + ed->setLocalPose(pose); // change the local pose + PxTransform p = getPose(); + setPose(p); + } + ret = true; + } + return ret; +} + +/** +\brief Returns the current lifetime of the particle. +*/ +float EffectPackageActorImpl::getCurrentLife(void) const +{ + READ_ZONE(); + return mCurrentLifeTime; +} + +float EffectData::getRealDuration(void) const +{ + float ret = 0; + + if (mDuration != 0 && mRepeatCount != 9999) // if it's not an infinite lifespan... + { + ret = mInitialDelayTime + mRepeatCount * mDuration + mRepeatCount * mRepeatDelay; + } + + return ret; +} + +float EffectPackageActorImpl::getDuration(void) const +{ + READ_ZONE(); + float ret = 0; + + for (uint32_t i = 0; i < mEffects.size(); i++) + { + EffectData* ed = mEffects[i]; + if (ed->getType() == ET_EMITTER) // if it's an emitter + { + float v = ed->getRealDuration(); + if (v > ret) + { + ret = v; + } + } + } + return ret; +} + +void EffectPackageActorImpl::setPreferredRenderVolume(RenderVolume* volume) +{ + WRITE_ZONE(); + mRenderVolume = volume; + for (uint32_t i = 0; i < mEffects.size(); i++) + { + EffectData* ed = mEffects[i]; + if (ed->getType() == ET_EMITTER) // if it's an emitter + { + EffectEmitter* ee = static_cast< EffectEmitter*>(ed); + if (ee->getEffectActor()) + { + EmitterActor* ea = static_cast< EmitterActor*>(ee->getEffectActor()); + ea->setPreferredRenderVolume(volume); + } + } + } + +} + + +EffectNoiseFS::EffectNoiseFS(const char* parentName, + NoiseFieldSamplerEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), EffectData(ET_NOISE_FS, &sdk, &scene, &dscene, parentName, NOISE_FS_AUTHORING_TYPE_NAME,*(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties) ) +{ +} + +EffectNoiseFS::~EffectNoiseFS(void) +{ +} + +void EffectNoiseFS::visualize(RenderDebugInterface* callback, bool solid) const +{ + +} + +bool EffectNoiseFS::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + bool ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + if (mActor) + { + NoiseFSActor* fs = static_cast< NoiseFSActor*>(mActor); + if (fs) + { + fs->setCurrentPose(myPose); + fs->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + ret = true; + } + } + } + else if (mActor) + { + NoiseFSActor* a = static_cast< NoiseFSActor*>(mActor); + a->setCurrentPose(myPose); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + +EffectVortexFS::EffectVortexFS(const char* parentName, + VortexFieldSamplerEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), EffectData(ET_VORTEX_FS, &sdk, &scene, &dscene, parentName, VORTEX_FS_AUTHORING_TYPE_NAME, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ +} + +EffectVortexFS::~EffectVortexFS(void) +{ +} + +void EffectVortexFS::visualize(RenderDebugInterface* callback, bool solid) const +{ + +} + +bool EffectVortexFS::refresh(const PxTransform& parent, bool parentEnabled, bool fromSetPose, RenderVolume* renderVolume,EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + + if (parentEnabled && mEnabled && mAsset) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose(parent * localPose); + getSamplePoseSpline(myPose); + + if (mActor == NULL && mAsset && !fromSetPose) + { + NvParameterized::Interface* descParams = mAsset->getDefaultActorDesc(); + if (descParams) + { + bool ok = NvParameterized::setParamF32(*descParams, "initialScale", mObjectScale*getSampleScaleSpline() ); + PX_ASSERT(ok); + PX_UNUSED(ok); + mActor = mAsset->createApexActor(*descParams, *mApexScene); + if (mActor) + { + VortexFSActor* fs = static_cast< VortexFSActor*>(mActor); + if (fs) + { + fs->setCurrentPose(myPose); + fs->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + ret = true; + } + } + } + else if (mActor) + { + VortexFSActor* a = static_cast< VortexFSActor*>(mActor); + a->setCurrentPose(myPose); + a->setCurrentScale(mObjectScale*getSampleScaleSpline()); + } + } + else + { + if ( mActor ) + { + releaseActor(); + ret = true; + } + } + return ret; +} + +const char * EffectPackageActorImpl::hasVolumeRenderMaterial(uint32_t &index) const +{ + READ_ZONE(); + const char *ret = NULL; + + for (uint32_t i=0; i<mEffects.size(); i++) + { + EffectData *d = mEffects[i]; + if ( d->getType() == ET_TURBULENCE_FS ) + { + const NvParameterized::Interface *iface = d->getAsset()->getAssetNvParameterized(); + const turbulencefs::TurbulenceFSAssetParams *ap = static_cast< const turbulencefs::TurbulenceFSAssetParams *>(iface); + if ( ap->volumeRenderMaterialName ) + { + if ( strlen(ap->volumeRenderMaterialName->name()) > 0 ) + { + index = i; + ret = ap->volumeRenderMaterialName->name(); + break; + } + } + } + } + + return ret; +} + +EffectRigidBody::EffectRigidBody(const char* parentName, + RigidBodyEffect* data, + ApexSDK& sdk, + Scene& scene, + ParticlesScene& dscene, + const PxTransform& rootPose, + bool parentEnabled) : mData(data), EffectData(ET_RIGID_BODY, &sdk, &scene, &dscene, parentName, NULL, *(RigidBodyEffectNS::EffectProperties_Type *)(&data->EffectProperties)) +{ + mRigidDynamic = NULL; +} + +EffectRigidBody::~EffectRigidBody(void) +{ + releaseRigidBody(); +} + + +void EffectRigidBody::visualize(RenderDebugInterface* callback, bool solid) const +{ + +} + +bool EffectRigidBody::refresh(const PxTransform& parent, + bool parentEnabled, + bool fromSetPose, + RenderVolume* renderVolume, + EmitterActor::EmitterValidateCallback *callback) +{ + bool ret = false; + SCOPED_PHYSX_LOCK_WRITE(mApexScene); + if (parentEnabled && mEnabled ) + { + PxTransform localPose = mLocalPose; + localPose.p*=mObjectScale*getSampleScaleSpline(); + PxTransform myPose = parent * localPose; + getSamplePoseSpline(myPose); + + if (mRigidDynamic == NULL && !fromSetPose) + { + PxScene * scene = mApexScene->getPhysXScene(); + PxPhysics &sdk = scene->getPhysics(); + PxMaterial * material = mParticlesScene->getModuleParticles()->getDefaultMaterial(); + RigidBodyEffect *rbe = static_cast< RigidBodyEffect *>(mData); + physx::PxFilterData data = ApexResourceHelper::resolveCollisionGroup128(rbe->CollisionFilterDataName.buf); + mRigidDynamic = sdk.createRigidDynamic(myPose); + ret = true; + if ( mRigidDynamic ) + { + mRigidDynamic->setLinearVelocity(rbe->InitialLinearVelocity); + mRigidDynamic->setAngularVelocity(rbe->InitialAngularVelocity); + mRigidDynamic->setMass(rbe->Mass); + mRigidDynamic->setLinearDamping(rbe->LinearDamping); + mRigidDynamic->setAngularDamping(rbe->AngularDamping); + mRigidDynamic->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC,!rbe->Dynamic); + + physx::PxShape *shape = NULL; + if ( nvidia::strcmp(rbe->Type,"SPHERE") == 0 ) + { + PxSphereGeometry sphere; + sphere.radius = rbe->Extents.x*getSampleScaleSpline(); + shape = mRigidDynamic->createShape(sphere,*material); + shape->setLocalPose(localPose); + } + else if ( nvidia::strcmp(rbe->Type,"CAPSULE") == 0 ) + { + PxCapsuleGeometry capsule; + capsule.radius = rbe->Extents.x*getSampleScaleSpline(); + capsule.halfHeight = rbe->Extents.y*getSampleScaleSpline(); + shape = mRigidDynamic->createShape(capsule,*material); + shape->setLocalPose(localPose); + } + else if ( nvidia::strcmp(rbe->Type,"BOX") == 0 ) + { + PxBoxGeometry box; + box.halfExtents.x = rbe->Extents.x*0.5f*getSampleScaleSpline(); + box.halfExtents.y = rbe->Extents.y*0.5f*getSampleScaleSpline(); + box.halfExtents.z = rbe->Extents.z*0.5f*getSampleScaleSpline(); + shape = mRigidDynamic->createShape(box,*material); + shape->setLocalPose(localPose); + } + else + { + PX_ALWAYS_ASSERT(); + } + if ( shape ) + { + // do stuff here... + shape->setSimulationFilterData(data); + shape->setQueryFilterData(data); + shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE,true); + shape->setMaterials(&material,1); + } + mRigidDynamic->setActorFlag(PxActorFlag::eDISABLE_GRAVITY,!rbe->Gravity); + mRigidDynamic->setActorFlag(PxActorFlag::eDISABLE_SIMULATION,false); + mRigidDynamic->setActorFlag(PxActorFlag::eVISUALIZATION,true); + scene->addActor(*mRigidDynamic); + } + } + else if (mRigidDynamic && fromSetPose ) + { + if ( mRigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC ) + { + mRigidDynamic->setKinematicTarget(myPose); + } + else + { + mRigidDynamic->setGlobalPose(myPose); + } + } + if ( activePath() && mRigidDynamic ) + { + // if we are sampling a spline curve to control the scale of the object.. + RigidBodyEffect *rbe = static_cast< RigidBodyEffect *>(mData); + physx::PxShape *shape = NULL; + mRigidDynamic->getShapes(&shape,1,0); + if ( shape ) + { + if ( nvidia::strcmp(rbe->Type,"SPHERE") == 0 ) + { + PxSphereGeometry sphere; + sphere.radius = rbe->Extents.x*getSampleScaleSpline(); + shape->setGeometry(sphere); + } + else if ( nvidia::strcmp(rbe->Type,"CAPSULE") == 0 ) + { + PxCapsuleGeometry capsule; + capsule.radius = rbe->Extents.x*getSampleScaleSpline(); + capsule.halfHeight = rbe->Extents.y*getSampleScaleSpline(); + shape->setGeometry(capsule); + } + else if ( nvidia::strcmp(rbe->Type,"BOX") == 0 ) + { + PxBoxGeometry box; + box.halfExtents.x = rbe->Extents.x*0.5f*getSampleScaleSpline(); + box.halfExtents.y = rbe->Extents.y*0.5f*getSampleScaleSpline(); + box.halfExtents.z = rbe->Extents.z*0.5f*getSampleScaleSpline(); + shape->setGeometry(box); + } + } + if ( mRigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC ) + { + mRigidDynamic->setKinematicTarget(myPose); + } + else + { + mRigidDynamic->setGlobalPose(myPose); + } + } + } + else + { + //releaseActor(); + } + return ret; +} + +PxRigidDynamic* EffectPackageActorImpl::getEffectRigidDynamic(uint32_t effectIndex) const +{ + READ_ZONE(); + PxRigidDynamic *ret = NULL; + + if (effectIndex < mEffects.size()) + { + EffectData* ed = mEffects[effectIndex]; + if ( ed->getType() == ET_RIGID_BODY ) + { + EffectRigidBody *erd = static_cast< EffectRigidBody *>(ed); + ret = erd->mRigidDynamic; + } + } + + + return ret; +} + +void EffectRigidBody::releaseRigidBody(void) +{ + if ( mRigidDynamic ) + { + SCOPED_PHYSX_LOCK_WRITE(mApexScene); + mRigidDynamic->release(); + mRigidDynamic = NULL; + } +} + +EffectPath::EffectPath(void) +{ + mRotations = NULL; + mPathSpline = NULL; + mScaleSpline = NULL; + mSampleScaleSpline = 1.0f; + mSpeedSpline = NULL; + mPathDuration = 1; +} + +EffectPath::~EffectPath(void) +{ + delete mScaleSpline; + delete mSpeedSpline; + delete mPathSpline; + PX_FREE(mRotations); +} + +bool EffectPath::init(RigidBodyEffectNS::EffectPath_Type &path) +{ + bool ret = path.Scale.arraySizes[0] > 2; + + mPathDuration = path.PathDuration; + mMode = EM_LOOP; + if ( nvidia::strcmp(path.PlaybackMode,"LOOP") == 0 ) + { + mMode = EM_LOOP; + } + else if ( nvidia::strcmp(path.PlaybackMode,"PLAY_ONCE") == 0 ) + { + mMode = EM_PLAY_ONCE; + } + else if ( nvidia::strcmp(path.PlaybackMode,"PING_PONG") == 0 ) + { + mMode = EM_PING_PONG; + } + + delete mScaleSpline; + mScaleSpline = NULL; + + if ( path.Scale.arraySizes[0] == 2 ) + { + if ( path.Scale.buf[0].y != 1 || + path.Scale.buf[1].y != 1 ) + { + ret = true; + } + } + else if ( path.Scale.arraySizes[0] > 2 ) + { + ret = true; + } + + if ( ret ) + { + mScaleSpline = PX_NEW(Spline); + int32_t scount = path.Scale.arraySizes[0]; + mScaleSpline->Reserve(scount); + for (int32_t i=0; i<scount; i++) + { + float x = path.Scale.buf[i].x; + float y = path.Scale.buf[i].y; + mScaleSpline->AddNode(x,y); + } + mScaleSpline->ComputeSpline(); + uint32_t index; + float t; + mSampleScaleSpline = mScaleSpline->Evaluate(0,index,t); + } + + + bool hasSpeed = false; + + if ( path.Speed.arraySizes[0] == 2 ) + { + if ( path.Speed.buf[0].y != 1 || + path.Speed.buf[1].y != 1 ) + { + hasSpeed = true; + } + } + else if ( path.Speed.arraySizes[0] > 2 ) + { + hasSpeed = true; + } + + delete mSpeedSpline; + mSpeedSpline = NULL; + + if ( hasSpeed ) + { + ret = true; + + Spline speed; + int32_t scount = path.Speed.arraySizes[0]; + speed.Reserve(scount); + for (int32_t i=0; i<scount; i++) + { + float x = path.Speed.buf[i].x; + float y = path.Speed.buf[i].y; + speed.AddNode(x,y); + } + speed.ComputeSpline(); + + float distance = 0; + uint32_t index; + for (int32_t i=0; i<32; i++) + { + float t = (float)i/32.0f; + float fraction; + float dt = speed.Evaluate(t,index,fraction); + distance+=dt; + } + float recipDistance = 1.0f / distance; + mSpeedSpline = PX_NEW(Spline); + mSpeedSpline->Reserve(32); + distance = 0; + for (int32_t i=0; i<32; i++) + { + float t = (float)i/32.0f; + float fraction; + float dt = speed.Evaluate(t,index,fraction); + distance+=dt; + float d = distance*recipDistance; + mSpeedSpline->AddNode(t,d); + } + mSpeedSpline->ComputeSpline(); + float fraction; + mSampleSpeedSpline = mSpeedSpline->Evaluate(0,index,fraction); + } + + + PX_FREE(mRotations); + mRotations = NULL; + delete mPathSpline; + mPathSpline = NULL; + + if ( path.ControlPoints.arraySizes[0] >= 3 ) + { + mPathSpline = PX_NEW(SplineCurve); + int32_t count = path.ControlPoints.arraySizes[0]; + PxVec3Vector points; + mRotationCount = (uint32_t)count-1; + mRotations = (PxQuat *)PX_ALLOC(sizeof(PxQuat)*(count-1),"PathRotations"); + mPathRoot = path.ControlPoints.buf[0]; + for (int32_t i=1; i<count; i++) + { + const PxTransform &t = path.ControlPoints.buf[i]; + mRotations[i-1] = t.q; + points.pushBack(t.p); + } + mPathSpline->setControlPoints(points); + + float fraction; + uint32_t index; + mSamplePoseSpline.p = mPathSpline->Evaluate(0,index,fraction); + mSamplePoseSpline.q = PxQuat(PxIdentity); + mSamplePoseSpline = mPathRoot * mSamplePoseSpline; + ret = true; + } + + + + return ret; +} + +float EffectPath::sampleSpline(float x) +{ + if ( mScaleSpline ) + { + uint32_t index; + float fraction; + mSampleScaleSpline = mScaleSpline->Evaluate(x,index,fraction); + if ( mSampleScaleSpline < 0.001f ) + { + mSampleScaleSpline = 0.001f; + } + } + if ( mPathSpline ) + { + uint32_t index; + float fraction; + if ( mSpeedSpline ) + { + x = mSpeedSpline->Evaluate(x,index,fraction); + } + float duration = mPathSpline->GetLength(); + duration*=x; + mSamplePoseSpline.p = mPathSpline->Evaluate(duration,index,fraction); + PX_ASSERT( index < mRotationCount ); + PxQuat q0 = mRotations[index]; + uint32_t index2 = index+1; + if ( index2 >= mRotationCount ) + { + index2 = 0; + } + PxQuat q1 = mRotations[index2]; + + PxQuat q = physx::shdfnd::slerp(fraction,q0,q1); + + mSamplePoseSpline.q = q; + mSamplePoseSpline = mPathRoot * mSamplePoseSpline; + } + + return mSampleScaleSpline; +} + +void EffectPath::computeSampleTime(float ctime,float duration) +{ + float sampleTime=0; + switch ( mMode ) + { + case EM_PLAY_ONCE: + if ( ctime >= duration ) + { + sampleTime = 1; + } + else + { + sampleTime = ctime / duration; + } + break; + case EM_LOOP: + sampleTime = fmodf(ctime,duration) / duration; + break; + case EM_PING_PONG: + sampleTime = fmodf(ctime,duration*2) / duration; + if ( sampleTime > 1 ) + { + sampleTime = 2.0f - sampleTime; + } + break; + default: + PX_ALWAYS_ASSERT(); + break; + } + sampleSpline(sampleTime); +} +} // end of particles namespace +} // end of nvidia namespace |