#include "gosFXHeaders.hpp" #include //==========================================================================// // File: gosFX_ShardCloud.cpp // // Project: gosFX // // Contents: Base gosFX::ShardCloud Component // //--------------------------------------------------------------------------// // Date Who Modification // // 09/28/98 JTR Created // // // //--------------------------------------------------------------------------// // Copyright (C) 1997-1998, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //==========================================================================// //------------------------------------------------------------------------------ // gosFX::ShardCloud__Specification::ShardCloud__Specification( Stuff::MemoryStream *stream, int gfx_version ): SpinningCloud__Specification(gosFX::ShardCloudClassID, stream, gfx_version) { Check_Pointer(this); Check_Object(stream); Verify(m_class == ShardCloudClassID); m_size.Load(stream, gfx_version); m_angularity.Load(stream, gfx_version); m_totalParticleSize = gosFX::ShardCloud::ParticleSize; m_particleClassSize = sizeof(gosFX::ShardCloud::Particle); } //------------------------------------------------------------------------------ // gosFX::ShardCloud__Specification::ShardCloud__Specification(): SpinningCloud__Specification(gosFX::ShardCloudClassID) { Check_Pointer(this); m_totalParticleSize = gosFX::ShardCloud::ParticleSize; m_particleClassSize = sizeof(gosFX::ShardCloud::Particle); } //------------------------------------------------------------------------------ // gosFX::ShardCloud__Specification::~ShardCloud__Specification() { Check_Object(this); } //------------------------------------------------------------------------------ // gosFX::ShardCloud__Specification* gosFX::ShardCloud__Specification::Make( Stuff::MemoryStream *stream, int gfx_version ) { Check_Object(stream); gos_PushCurrentHeap(Heap); ShardCloud__Specification *spec = new gosFX::ShardCloud__Specification(stream, gfx_version); gos_PopCurrentHeap(); return spec; } //------------------------------------------------------------------------------ // void gosFX::ShardCloud__Specification::Save(Stuff::MemoryStream *stream) { Check_Object(this); Check_Object(stream); BaseClass::Save(stream); m_size.Save(stream); m_angularity.Save(stream); } //------------------------------------------------------------------------------ // void gosFX::ShardCloud__Specification::BuildDefaults() { Check_Object(this); BaseClass::BuildDefaults(); m_size.m_ageCurve.SetCurve(1.0f); m_size.m_seeded = false; m_size.m_seedCurve.SetCurve(1.0f); m_angularity.m_ageCurve.SetCurve(1.0f); m_angularity.m_seeded = false; m_angularity.m_seedCurve.SetCurve(1.0f); } //------------------------------------------------------------------------------ // bool gosFX::ShardCloud__Specification::IsDataValid(bool fix_data) { // //----------------------------------------- // Make sure we don't overwrite MLR buffers //----------------------------------------- // int particle_limit = MidLevelRenderer::Limits::Max_Number_Vertices_Per_Effect/3; if (m_maxParticleCount > particle_limit) { if (fix_data) { m_maxParticleCount = particle_limit; PAUSE(("Warning: Max Particle Count in Effect \"%s\" is too big and has been reset",(char *)m_name)); } else return false; } return BaseClass::IsDataValid(fix_data); } //------------------------------------------------------------------------------ // void gosFX::ShardCloud__Specification::Copy(ShardCloud__Specification *spec) { Check_Object(this); Check_Object(spec); BaseClass::Copy(spec); gos_PushCurrentHeap(Heap); m_size = spec->m_size; m_angularity = spec->m_angularity; gos_PopCurrentHeap(); } //############################################################################ //############################## gosFX::ShardCloud ################################ //############################################################################ gosFX::ShardCloud::ClassData* gosFX::ShardCloud::DefaultData = NULL; //------------------------------------------------------------------------------ // void gosFX::ShardCloud::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( ShardCloudClassID, "gosFX::ShardCloud", BaseClass::DefaultData, (Effect::Factory)&Make, (Specification::Factory)&Specification::Make ); Check_Object(DefaultData); } //------------------------------------------------------------------------------ // void gosFX::ShardCloud::TerminateClass() { Check_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //------------------------------------------------------------------------------ // gosFX::ShardCloud::ShardCloud( Specification *spec, unsigned flags ): SpinningCloud(DefaultData, spec, flags) { Check_Object(spec); gos_PushCurrentHeap(MidLevelRenderer::EffectHeap); m_cloudImplementation = new MidLevelRenderer::MLRTriangleCloud(spec->m_maxParticleCount); Check_Object(m_cloudImplementation); gos_PopCurrentHeap(); unsigned index = spec->m_maxParticleCount*sizeof(Particle); m_P_vertices = Cast_Pointer(Stuff::Point3D*, &m_data[index]); index += 3*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_vertices, m_P_color ); } //------------------------------------------------------------------------------ // gosFX::ShardCloud::~ShardCloud() { Check_Object(this); Check_Object(m_cloudImplementation); delete m_cloudImplementation; } //------------------------------------------------------------------------------ // gosFX::ShardCloud* gosFX::ShardCloud::Make( Specification *spec, unsigned flags ) { Check_Object(spec); gos_PushCurrentHeap(Heap); ShardCloud *cloud = new gosFX::ShardCloud(spec, flags); gos_PopCurrentHeap(); return cloud; } //------------------------------------------------------------------------------ // void gosFX::ShardCloud::CreateNewParticle( unsigned index, Stuff::Point3D *translation ) { Check_Object(this); // //------------------------------------------------------------------- // Let our parent do creation, then turn on the particle in the cloud //------------------------------------------------------------------- // BaseClass::CreateNewParticle(index, translation); m_cloudImplementation->TurnOn(index); Verify(m_cloudImplementation->IsOn(index)); // //----------------------------- // Figure out the particle size //----------------------------- // Specification *spec = GetSpecification(); Check_Object(spec); Particle *particle = GetParticle(index); Check_Object(particle); particle->m_radius = spec->m_size.ComputeValue(m_age, particle->m_seed); particle->m_angle = Stuff::Sin(spec->m_angularity.ComputeValue(m_age, particle->m_seed)); } //------------------------------------------------------------------------------ // void gosFX::ShardCloud::DestroyParticle(unsigned index) { Check_Object(this); m_cloudImplementation->TurnOff(index); Verify(!m_cloudImplementation->IsOn(index)); BaseClass::DestroyParticle(index); } //------------------------------------------------------------------------------ // void gosFX::ShardCloud::SetVertexData( unsigned i, const Stuff::LinearMatrix4D &shard_to_cloud ) { Check_Object(this); // //-------------------------------------------------- // Figure out the scale, then build the three points //-------------------------------------------------- // Specification *spec = GetSpecification(); Check_Object(spec); Particle *particle = GetParticle(i); Check_Object(particle); unsigned vert = i*3; m_P_vertices[vert].Multiply( Stuff::Point3D( 0.0f, -0.5f*particle->m_scale*particle->m_radius, 0.0f ), shard_to_cloud ); m_P_vertices[vert+1].Multiply( Stuff::Point3D( particle->m_scale*particle->m_angle*particle->m_radius, particle->m_scale*particle->m_radius*0.5f, 0.0f ), shard_to_cloud ); m_P_vertices[vert+2].Multiply( Stuff::Point3D( -particle->m_scale*particle->m_angle*particle->m_radius, particle->m_scale*particle->m_radius*0.5f, 0.0f ), shard_to_cloud ); // //------------------ // Animate the color //------------------ // m_P_color[vert].red = spec->m_pRed.ComputeValue(particle->m_age, particle->m_seed); m_P_color[vert].green = spec->m_pGreen.ComputeValue(particle->m_age, particle->m_seed); m_P_color[vert].blue = spec->m_pBlue.ComputeValue(particle->m_age, particle->m_seed); m_P_color[vert].alpha = spec->m_pAlpha.ComputeValue(particle->m_age, particle->m_seed); m_P_color[vert+2] = m_P_color[vert+1] = m_P_color[vert]; } //------------------------------------------------------------------------------ // void gosFX::ShardCloud::Draw(DrawInfo *info) { Check_Object(this); Check_Object(info); GFX_RENDER("ShardCloud"); // //--------------------------------------------------------- // If we have active particles, set up the draw information //--------------------------------------------------------- // 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; // //-------------------------------------------------------------- // Check the orientation mode. The first case is XY orientation //-------------------------------------------------------------- // unsigned i; Check_Pointer(m_P_color); if (spec->m_alignZUsingX) { if (spec->m_alignZUsingY) { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse( camera_in_world, local_to_world ); // //-------------------------------------- // Spin through all the active particles //-------------------------------------- // for (i = 0; i < m_activeParticleCount; i++) { Particle *particle = GetParticle(i); Check_Object(particle); Stuff::Scalar age = particle->m_age; if (age < 1.0f) { // //-------------------------------- // Build the local to cloud matrix //-------------------------------- // Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract( camera_in_cloud, particle->m_localTranslation ); Stuff::LinearMatrix4D shard_to_cloud; shard_to_cloud.BuildRotation(particle->m_localRotation); shard_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::Y_Axis, Stuff::X_Axis ); shard_to_cloud.BuildTranslation(particle->m_localTranslation); // //--------------------- // Now fill in the data //--------------------- // SetVertexData(i, shard_to_cloud); } } } // //----------------------- // Handle X-only rotation //----------------------- // else { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse( camera_in_world, local_to_world ); // //-------------------------------------- // Spin through all the active particles //-------------------------------------- // for (i = 0; i < m_activeParticleCount; i++) { Particle *particle = GetParticle(i); Check_Object(particle); Stuff::Scalar age = particle->m_age; if (age < 1.0f) { // //-------------------------------- // Build the local to cloud matrix //-------------------------------- // Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract( camera_in_cloud, particle->m_localTranslation ); Stuff::LinearMatrix4D shard_to_cloud; shard_to_cloud.BuildRotation(particle->m_localRotation); shard_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::X_Axis, -1 ); shard_to_cloud.BuildTranslation(particle->m_localTranslation); // //--------------------- // Now fill in the data //--------------------- // SetVertexData(i, shard_to_cloud); } } } } // //------------------------------------------------------- // Each matrix needs to be aligned to the camera around Y //------------------------------------------------------- // else if (spec->m_alignZUsingY) { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse( camera_in_world, local_to_world ); // //-------------------------------------- // Spin through all the active particles //-------------------------------------- // for (i = 0; i < m_activeParticleCount; i++) { Particle *particle = GetParticle(i); Check_Object(particle); Stuff::Scalar age = particle->m_age; if (age < 1.0f) { // //-------------------------------- // Build the local to cloud matrix //-------------------------------- // Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract( camera_in_cloud, particle->m_localTranslation ); Stuff::LinearMatrix4D shard_to_cloud; shard_to_cloud.BuildRotation(particle->m_localRotation); shard_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::Y_Axis, -1 ); shard_to_cloud.BuildTranslation(particle->m_localTranslation); // //--------------------- // Now fill in the data //--------------------- // SetVertexData(i, shard_to_cloud); } } } // //--------------------------------------------------------------- // No alignment is necessary, so just multiply out all the active // particles //--------------------------------------------------------------- // else { for (i = 0; i < m_activeParticleCount; i++) { Particle *particle = GetParticle(i); Check_Object(particle); Stuff::Scalar age = particle->m_age; if (age < 1.0f) { // //-------------------------------- // Build the local to cloud matrix //-------------------------------- // Stuff::LinearMatrix4D shard_to_cloud; shard_to_cloud.BuildRotation(particle->m_localRotation); shard_to_cloud.BuildTranslation(particle->m_localTranslation); // //--------------------- // Now fill in the data //--------------------- // SetVertexData(i, shard_to_cloud); } } } // //--------------------- // Now just do the draw //--------------------- // info->m_clipper->DrawEffect(&dInfo); } BaseClass::Draw(info); } //------------------------------------------------------------------------------ // void gosFX::ShardCloud::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); }