123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- #include "gosFXHeaders.hpp"
- #include <MLR\MLRPointCloud.hpp>
- //==========================================================================//
- // File: gosFX_PointCloud.cpp //
- // Contents: Base gosFX::PointCloud Component //
- //---------------------------------------------------------------------------//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- //
- //############################################################################
- //######################## gosFX::PointCloud__Specification #############################
- //############################################################################
- //------------------------------------------------------------------------------
- //
- gosFX::PointCloud__Specification::PointCloud__Specification(
- Stuff::MemoryStream *stream,
- int gfx_version
- ):
- ParticleCloud__Specification(gosFX::PointCloudClassID, stream, gfx_version)
- {
- Check_Pointer(this);
- Verify(m_class == PointCloudClassID);
- Verify(gos_GetCurrentHeap() == Heap);
- m_totalParticleSize = gosFX::PointCloud::ParticleSize;
- m_particleClassSize = sizeof(gosFX::PointCloud::Particle);
- }
- //------------------------------------------------------------------------------
- //
- gosFX::PointCloud__Specification::PointCloud__Specification():
- ParticleCloud__Specification(gosFX::PointCloudClassID)
- {
- Check_Pointer(this);
- Verify(gos_GetCurrentHeap() == Heap);
- m_totalParticleSize = gosFX::PointCloud::ParticleSize;
- m_particleClassSize = sizeof(gosFX::PointCloud::Particle);
- }
- //------------------------------------------------------------------------------
- //
- gosFX::PointCloud__Specification*
- gosFX::PointCloud__Specification::Make(
- Stuff::MemoryStream *stream,
- int gfx_version
- )
- {
- Check_Object(stream);
- gos_PushCurrentHeap(Heap);
- PointCloud__Specification *spec =
- new gosFX::PointCloud__Specification(stream, gfx_version);
- gos_PopCurrentHeap();
- return spec;
- }
- //############################################################################
- //############################## gosFX::PointCloud ################################
- //############################################################################
- gosFX::PointCloud::ClassData*
- gosFX::PointCloud::DefaultData = NULL;
- //------------------------------------------------------------------------------
- //
- void
- gosFX::PointCloud::InitializeClass()
- {
- Verify(!DefaultData);
- Verify(gos_GetCurrentHeap() == Heap);
- DefaultData =
- new ClassData(
- PointCloudClassID,
- "gosFX::PointCloud",
- ParticleCloud::DefaultData,
- (Effect::Factory)&Make,
- (Specification::Factory)&Specification::Make
- );
- Register_Object(DefaultData);
- }
- //------------------------------------------------------------------------------
- //
- void
- gosFX::PointCloud::TerminateClass()
- {
- Unregister_Object(DefaultData);
- delete DefaultData;
- DefaultData = NULL;
- }
- //------------------------------------------------------------------------------
- //
- gosFX::PointCloud::PointCloud(
- Specification *spec,
- unsigned flags
- ):
- ParticleCloud(DefaultData, spec, flags)
- {
- Check_Object(spec);
- Verify(gos_GetCurrentHeap() == Heap);
- gos_PushCurrentHeap(MidLevelRenderer::Heap);
- m_cloudImplementation =
- new MidLevelRenderer::MLRPointCloud(spec->m_maxParticleCount);
- Register_Object(m_cloudImplementation);
- gos_PopCurrentHeap();
- unsigned index = spec->m_maxParticleCount*sizeof(Particle);
- m_P_localTranslation = Cast_Pointer(Stuff::Point3D*, &m_data[index]);
- index += spec->m_maxParticleCount*sizeof(Stuff::Point3D);
- m_P_color = Cast_Pointer(Stuff::RGBAColor*, &m_data[index]);
- m_cloudImplementation->SetData(
- Cast_Pointer(const int *, &m_activeParticleCount),
- m_P_localTranslation,
- m_P_color
- );
- }
- //------------------------------------------------------------------------------
- //
- gosFX::PointCloud::~PointCloud()
- {
- Unregister_Object(m_cloudImplementation);
- delete m_cloudImplementation;
- }
- //------------------------------------------------------------------------------
- //
- gosFX::PointCloud*
- gosFX::PointCloud::Make(
- Specification *spec,
- unsigned flags
- )
- {
- Check_Object(spec);
- gos_PushCurrentHeap(Heap);
- PointCloud *cloud = new gosFX::PointCloud(spec, flags);
- gos_PopCurrentHeap();
- return cloud;
- }
- //------------------------------------------------------------------------------
- //
- bool
- gosFX::PointCloud::Execute(ExecuteInfo *info)
- {
- Check_Object(this);
- Check_Object(info);
- //
- //----------------------------------------
- // If we aren't supposed to execute, don't
- //----------------------------------------
- //
- if (!IsExecuted())
- return false;
- //
- //------------------------------------------------------------------
- // Animate the particles. If it is time for us to die, return false
- //------------------------------------------------------------------
- //
- if (!ParticleCloud::Execute(info))
- return false;
- //
- //-----------------------------------------------------------------------
- // If there are active particles to animate, get the current center point
- // of the bounds
- //-----------------------------------------------------------------------
- //
- if (m_activeParticleCount > 0)
- {
- Stuff::ExtentBox box(Stuff::Point3D::Identity, Stuff::Point3D::Identity);
- Stuff::Point3D *vertex = &m_P_localTranslation[0];
- unsigned i=0;
- //
- //-------------------------------------------------------------------
- // If there is no bounds yet, we need to create our extent box around
- // the first legal point we find
- //-------------------------------------------------------------------
- //
- while (i<m_activeParticleCount)
- {
- Particle *particle = GetParticle(i);
- Check_Object(particle);
- if (particle->m_age < 1.0f)
- {
- Check_Object(vertex);
- box.maxX = vertex->x;
- box.minX = vertex->x;
- box.maxY = vertex->y;
- box.minY = vertex->y;
- box.maxZ = vertex->z;
- box.minZ = vertex->z;
- ++vertex;
- ++i;
- break;
- }
- ++vertex;
- ++i;
- }
- //
- //-----------------------------
- // Look for the other particles
- //-----------------------------
- //
- while (i<m_activeParticleCount)
- {
- Particle *particle = GetParticle(i);
- Check_Object(particle);
- if (particle->m_age < 1.0f)
- {
- Check_Object(vertex);
- if (vertex->x > box.maxX)
- box.maxX = vertex->x;
- else if (vertex->x < box.minX)
- box.minX = vertex->x;
- if (vertex->y > box.maxY)
- box.maxY = vertex->y;
- else if (vertex->y < box.minY)
- box.minY = vertex->y;
- if (vertex->z > box.maxZ)
- box.maxZ = vertex->z;
- else if (vertex->z < box.minZ)
- box.minZ = vertex->z;
- }
- ++vertex;
- ++i;
- }
- //
- //------------------------------------
- // Now, build a info->m_bounds around this box
- //------------------------------------
- //
- Verify(box.maxX >= box.minX);
- Verify(box.maxY >= box.minY);
- Verify(box.maxZ >= box.minZ);
- Stuff::OBB local_bounds = Stuff::OBB::Identity;
- local_bounds.axisExtents.x = 0.5f * (box.maxX - box.minX);
- local_bounds.axisExtents.y = 0.5f * (box.maxY - box.minY);
- local_bounds.axisExtents.z = 0.5f * (box.maxZ - box.minZ);
- local_bounds.localToParent(3,0) = box.minX + local_bounds.axisExtents.x;
- local_bounds.localToParent(3,1) = box.minY + local_bounds.axisExtents.y;
- local_bounds.localToParent(3,2) = box.minZ + local_bounds.axisExtents.z;
- local_bounds.sphereRadius = local_bounds.axisExtents.GetLength();
- if (local_bounds.sphereRadius < Stuff::SMALL)
- local_bounds.sphereRadius = 0.01f;
- Stuff::OBB parent_bounds;
- parent_bounds.Multiply(local_bounds, m_localToParent);
- info->m_bounds->Union(*info->m_bounds, parent_bounds);
- }
- //
- //----------------------------------------------
- // Tell our caller that we get to keep executing
- //----------------------------------------------
- //
- return true;
- }
- //------------------------------------------------------------------------------
- //
- void
- gosFX::PointCloud::CreateNewParticle(
- unsigned index,
- Stuff::Point3D *translation
- )
- {
- Check_Object(this);
- Check_Pointer(translation);
- //
- //-----------------------------------------------------------------------
- // Let our parent do creation, then turn on the particle in the cloud and
- // set its position
- //-----------------------------------------------------------------------
- //
- ParticleCloud::CreateNewParticle(index, translation);
- m_cloudImplementation->TurnOn(index);
- Verify(m_cloudImplementation->IsOn(index));
- m_P_localTranslation[index] = *translation;
- }
- //------------------------------------------------------------------------------
- //
- bool
- gosFX::PointCloud::AnimateParticle(
- unsigned index,
- const Stuff::LinearMatrix4D *world_to_new_local,
- Stuff::Time till
- )
- {
- Check_Object(this);
- //
- //-----------------------------------------------------------------------
- // If this cloud is unparented, we need to transform the point from local
- // space into world space and set the internal position/velocity pointers
- // to these temporary values
- //-----------------------------------------------------------------------
- //
- Particle *particle = GetParticle(index);
- Check_Object(particle);
- Stuff::Scalar age = particle->m_age;
- if (age >= 1.0f)
- return false;
- Set_Statistic(Point_Count, Point_Count+1);
- Stuff::Vector3D *velocity = &particle->m_localLinearVelocity;
- Stuff::Point3D *translation = &m_P_localTranslation[index];
- int sim_mode = GetSimulationMode();
- if (sim_mode == DynamicWorldSpaceSimulationMode)
- {
- Check_Object(translation);
- Check_Object(velocity);
- particle->m_worldLinearVelocity.Multiply(*velocity, m_localToWorld);
- particle->m_worldTranslation.Multiply(*translation, m_localToWorld);
- translation = &particle->m_worldTranslation;
- velocity = &particle->m_worldLinearVelocity;
- }
- Check_Object(translation);
- Check_Object(velocity);
- //
- //------------------------------------------------------------------
- // First, calculate the drag on the particle. Drag can never assist
- // velocity
- //------------------------------------------------------------------
- //
- Stuff::Scalar seed = particle->m_seed;
- Specification *spec = GetSpecification();
- Check_Object(spec);
- Stuff::Vector3D ether;
- ether.x = spec->m_pEtherVelocityX.ComputeValue(age, seed);
- ether.y = spec->m_pEtherVelocityY.ComputeValue(age, seed);
- ether.z = spec->m_pEtherVelocityZ.ComputeValue(age, seed);
- Stuff::Vector3D accel(Stuff::Vector3D::Identity);
- //
- //-------------------------------------------------------------------
- // Deal with pseudo-world simulation. In this mode, we interpret the
- // forces as if they are already in worldspace, and we transform them
- // back to local space
- //-------------------------------------------------------------------
- //
- Stuff::Scalar drag = -spec->m_pDrag.ComputeValue(age, seed);
- Max_Clamp(drag, 0.0f);
- if (sim_mode == StaticWorldSpaceSimulationMode)
- {
- Stuff::LinearMatrix4D world_to_effect;
- world_to_effect.Invert(m_localToWorld);
- Stuff::Vector3D local_ether;
- local_ether.MultiplyByInverse(ether, world_to_effect);
- Stuff::Vector3D rel_vel;
- rel_vel.Subtract(*velocity, local_ether);
- accel.Multiply(rel_vel, drag);
- //
- //-----------------------------------------
- // Now, add in acceleration of the particle
- //-----------------------------------------
- //
- Stuff::Vector3D world_accel;
- world_accel.x = spec->m_pAccelerationX.ComputeValue(age, seed);
- world_accel.y = spec->m_pAccelerationY.ComputeValue(age, seed);
- world_accel.z = spec->m_pAccelerationZ.ComputeValue(age, seed);
- Stuff::Vector3D local_accel;
- local_accel.Multiply(world_accel, world_to_effect);
- accel += local_accel;
- }
- //
- //----------------------------------------------------------------------
- // Otherwise, just add the forces in the same space the particles are in
- //----------------------------------------------------------------------
- //
- else
- {
- Stuff::Vector3D rel_vel;
- rel_vel.Subtract(*velocity, ether);
- accel.Multiply(rel_vel, drag);
- //
- //-----------------------------------------
- // Now, add in acceleration of the particle
- //-----------------------------------------
- //
- accel.x += spec->m_pAccelerationX.ComputeValue(age, seed);
- accel.y += spec->m_pAccelerationY.ComputeValue(age, seed);
- accel.z += spec->m_pAccelerationZ.ComputeValue(age, seed);
- }
- //
- //-------------------------------------------------
- // Compute the particle's new velocity and position
- //-------------------------------------------------
- //
- Stuff::Scalar time_slice =
- static_cast<Stuff::Scalar>(till - m_lastRan);
- velocity->AddScaled(*velocity, accel, time_slice);
- translation->AddScaled(*translation, *velocity, time_slice);
- //
- //---------------------------------------------------------------------
- // If we are unparented, we need to transform the velocity and position
- // data back into the NEW local space
- //---------------------------------------------------------------------
- //
- if (sim_mode == DynamicWorldSpaceSimulationMode)
- {
- Check_Object(world_to_new_local);
- particle->m_localLinearVelocity.Multiply(
- particle->m_worldLinearVelocity,
- *world_to_new_local
- );
- m_P_localTranslation[index].Multiply(
- particle->m_worldTranslation,
- *world_to_new_local
- );
- }
- //
- //------------------
- // Animate the color
- //------------------
- //
- Check_Pointer(m_P_color);
- m_P_color[index].red = spec->m_pRed.ComputeValue(age, seed);
- m_P_color[index].green = spec->m_pGreen.ComputeValue(age, seed);
- m_P_color[index].blue = spec->m_pBlue.ComputeValue(age, seed);
- m_P_color[index].alpha = spec->m_pAlpha.ComputeValue(age, seed);
- return true;
- }
- //------------------------------------------------------------------------------
- //
- void gosFX::PointCloud::DestroyParticle(unsigned index)
- {
- Check_Object(this);
- m_cloudImplementation->TurnOff(index);
- Verify(!m_cloudImplementation->IsOn(index));
- ParticleCloud::DestroyParticle(index);
- }
- //------------------------------------------------------------------------------
- //
- void gosFX::PointCloud::Draw(DrawInfo *info)
- {
- Check_Object(this);
- Check_Object(info);
- if (m_activeParticleCount)
- {
- MidLevelRenderer::DrawEffectInformation dInfo;
- dInfo.effect = m_cloudImplementation;
- Specification *spec = GetSpecification();
- Check_Object(spec);
- dInfo.state.Combine(info->m_state, spec->m_state);
- dInfo.clippingFlags = info->m_clippingFlags;
- Stuff::LinearMatrix4D local_to_world;
- local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
- dInfo.effectToWorld = &local_to_world;
-
- info->m_clipper->DrawEffect(&dInfo);
- }
- ParticleCloud::Draw(info);
- }
- //------------------------------------------------------------------------------
- //
- void
- gosFX::PointCloud::TestInstance() const
- {
- Verify(IsDerivedFrom(DefaultData));
- }
|