Files
firestorm/Gameleap/code/mw4/Libraries/gosFX/ShapeCloud.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

610 lines
18 KiB
C++

#include "gosFXHeaders.hpp"
#include <MLR\MLRShape.hpp>
//==========================================================================//
// File: gosFX_ShapeCloud.cpp //
// Project: gosFX //
// Contents: Base gosFX::ShapeCloud 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::ShapeCloud__Specification #############################
//############################################################################
//------------------------------------------------------------------------------
//
gosFX::ShapeCloud__Specification::ShapeCloud__Specification(
Stuff::MemoryStream *stream,
int gfx_version
):
SpinningCloud__Specification(gosFX::ShapeCloudClassID, stream, gfx_version)
{
Check_Pointer(this);
Verify(m_class == ShapeCloudClassID);
m_particleClassSize = sizeof(gosFX::ShapeCloud::Particle);
m_totalParticleSize = sizeof(gosFX::ShapeCloud::Particle);
//
//---------------------------------
// Ditch the shape if its old style
//---------------------------------
//
if (gfx_version < 25)
{
MidLevelRenderer::MLRShape *shape =
MidLevelRenderer::MLRShape::Make(
stream,
MidLevelRenderer::ReadMLRVersion(stream)
);
Check_Object(shape);
shape->DetachReference();
*stream >> m_radius;
m_shape = NULL;
}
//
//----------------------------------------
// Otherwise, read the filename and radius
//----------------------------------------
//
else
{
*stream >> m_shapeFile >> m_radius;
if(m_shapeFile)
m_shape = EffectLibrary::Instance->UseShape(m_shapeFile);
else
m_shape = NULL;
}
}
//------------------------------------------------------------------------------
//
gosFX::ShapeCloud__Specification::ShapeCloud__Specification():
SpinningCloud__Specification(gosFX::ShapeCloudClassID)
{
Check_Pointer(this);
m_totalParticleSize = m_particleClassSize = sizeof(gosFX::ShapeCloud::Particle);
m_shape = NULL;
m_radius=0.0f;
}
//------------------------------------------------------------------------------
//
gosFX::ShapeCloud__Specification::~ShapeCloud__Specification()
{
Check_Object(this);
if (m_shape)
{
Check_Object(m_shape);
m_shape->DetachReference();
}
}
//------------------------------------------------------------------------------
//
gosFX::ShapeCloud__Specification*
gosFX::ShapeCloud__Specification::Make(
Stuff::MemoryStream *stream,
int gfx_version
)
{
Check_Object(stream);
gos_PushCurrentHeap(Heap);
ShapeCloud__Specification *spec =
new gosFX::ShapeCloud__Specification(stream, gfx_version);
gos_PopCurrentHeap();
return spec;
}
//------------------------------------------------------------------------------
//
void
gosFX::ShapeCloud__Specification::Save(Stuff::MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
BaseClass::Save(stream);
*stream << m_shapeFile << m_radius;
}
//------------------------------------------------------------------------------
//
void
gosFX::ShapeCloud__Specification::Copy(ShapeCloud__Specification *spec)
{
Check_Object(this);
Check_Object(spec);
BaseClass::Copy(spec);
gos_PushCurrentHeap(Heap);
m_radius = spec->m_radius;
m_shape = spec->m_shape;
gos_PopCurrentHeap();
Check_Object(m_shape);
m_shape->AttachReference();
}
//------------------------------------------------------------------------------
//
void
gosFX::ShapeCloud__Specification::SetShape(Stuff::MString &shape)
{
Check_Object(this);
m_shapeFile=shape;
//
//------------------------------------
// Detach the old shape if it is there
//------------------------------------
//
if (m_shape)
{
Check_Object(m_shape);
m_shape->DetachReference();
}
//
//------------------------------------
// Attach the new shape if it is there
//------------------------------------
//
m_shape = EffectLibrary::Instance->UseShape(shape);
//
//-----------------------------------------------------------------
// Get the radius of the bounding sphere. This will be the largest
// distance any point is from the origin
//-----------------------------------------------------------------
//
m_radius = 0.0f;
int count = m_shape->GetNum();
for (int i=0; i<count; ++i)
{
MidLevelRenderer::MLRPrimitiveBase *primitive = m_shape->Find(i);
Check_Object(primitive);
const Stuff::Point3D *points;
int vertex_count;
primitive->GetCoordData(&points, &vertex_count);
for (int v=0; v<vertex_count; ++v)
{
Stuff::Scalar len = points[v].GetLengthSquared();
if (len > m_radius)
m_radius = len;
}
}
m_radius = Stuff::Sqrt(m_radius);
}
//############################################################################
//############################## gosFX::ShapeCloud ################################
//############################################################################
gosFX::ShapeCloud::ClassData*
gosFX::ShapeCloud::DefaultData = NULL;
//------------------------------------------------------------------------------
//
void
gosFX::ShapeCloud::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
ShapeCloudClassID,
"gosFX::ShapeCloud",
BaseClass::DefaultData,
(Effect::Factory)&Make,
(Specification::Factory)&Specification::Make
);
Check_Object(DefaultData);
}
//------------------------------------------------------------------------------
//
void
gosFX::ShapeCloud::TerminateClass()
{
Check_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//------------------------------------------------------------------------------
//
gosFX::ShapeCloud::ShapeCloud(
Specification *spec,
unsigned flags
):
SpinningCloud(DefaultData, spec, flags)
{
}
//------------------------------------------------------------------------------
//
gosFX::ShapeCloud*
gosFX::ShapeCloud::Make(
Specification *spec,
unsigned flags
)
{
Check_Object(spec);
gos_PushCurrentHeap(Heap);
ShapeCloud *cloud = new gosFX::ShapeCloud(spec, flags);
gos_PopCurrentHeap();
return cloud;
}
//------------------------------------------------------------------------------
//
void
gosFX::ShapeCloud::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);
Specification *spec = GetSpecification();
Check_Object(spec);
Particle *particle = GetParticle(index);
Check_Object(particle);
particle->m_radius = spec->m_radius;
}
//------------------------------------------------------------------------------
//
void
gosFX::ShapeCloud::Start(ExecuteInfo *info)
{
Check_Object(this);
Check_Pointer(info);
//
//--------------------------------------
// Load the shape if it isn't loaded yet
//--------------------------------------
//
Specification *spec = GetSpecification();
Check_Object(spec);
if (spec->m_shapeFile && !spec->m_shape)
{
spec->m_shape = EffectLibrary::Instance->UseShape(spec->m_shapeFile);
Check_Object(spec->m_shape);
}
BaseClass::Start(info);
}
//------------------------------------------------------------------------------
//
void gosFX::ShapeCloud::Draw(DrawInfo *info)
{
Check_Object(this);
Check_Object(info);
Check_Object(info->m_parentToWorld);
GFX_RENDER("ShapeCloud");
//
//----------------------------
// Set up the common draw info
//----------------------------
//
if (m_activeParticleCount)
{
MidLevelRenderer::DrawScalableShapeInformation dinfo;
MidLevelRenderer::MLRShape *shape = GetSpecification()->m_shape;
if (!shape)
return;
dinfo.clippingFlags.SetClippingState(0x3f);
dinfo.worldToShape = NULL;
Specification *spec = GetSpecification();
Check_Object(spec);
dinfo.state.Combine(info->m_state, spec->m_state);
dinfo.activeLights = NULL;
dinfo.nrOfActiveLights = 0;
dinfo.shape = shape;
Stuff::LinearMatrix4D local_to_world;
local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
//
//--------------------------------------------------------------
// Check the orientation mode. The first case is XY orientation
//--------------------------------------------------------------
//
unsigned i;
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
);
for (unsigned i = 0; i < m_activeParticleCount; i++)
{
Particle *particle = GetParticle(i);
Check_Object(particle);
//
//-----------------------------------------------------------------
// If the particle is still alive, concatenate into world space and
// issue the draw command
//-----------------------------------------------------------------
//
if (particle->m_age < 1.0f)
{
Stuff::Vector3D direction_in_cloud;
direction_in_cloud.Subtract(
camera_in_cloud,
particle->m_localTranslation
);
Stuff::LinearMatrix4D shape_to_cloud;
shape_to_cloud.BuildRotation(particle->m_localRotation);
shape_to_cloud.AlignLocalAxisToWorldVector(
direction_in_cloud,
Stuff::Z_Axis,
Stuff::Y_Axis,
Stuff::X_Axis
);
shape_to_cloud.BuildTranslation(particle->m_localTranslation);
Stuff::LinearMatrix4D shape_to_world;
shape_to_world.Multiply(
shape_to_cloud,
local_to_world
);
dinfo.shapeToWorld = &shape_to_world;
Stuff::Vector3D
scale(
particle->m_scale,
particle->m_scale,
particle->m_scale
);
dinfo.scaling = &scale;
particle->m_color.red = spec->m_pRed.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.green = spec->m_pGreen.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.blue = spec->m_pBlue.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.alpha = spec->m_pAlpha.ComputeValue(particle->m_age, particle->m_seed);
dinfo.paintMeColor = &particle->m_color;
info->m_clipper->DrawScalableShape(&dinfo);
}
}
}
//
//-----------------------
// 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
);
for (unsigned i = 0; i < m_activeParticleCount; i++)
{
Particle *particle = GetParticle(i);
Check_Object(particle);
//
//-----------------------------------------------------------------
// If the particle is still alive, concatenate into world space and
// issue the draw command
//-----------------------------------------------------------------
//
if (particle->m_age < 1.0f)
{
Stuff::Vector3D direction_in_cloud;
direction_in_cloud.Subtract(
camera_in_cloud,
particle->m_localTranslation
);
Stuff::LinearMatrix4D shape_to_cloud;
shape_to_cloud.BuildRotation(particle->m_localRotation);
shape_to_cloud.AlignLocalAxisToWorldVector(
direction_in_cloud,
Stuff::Z_Axis,
Stuff::X_Axis,
-1
);
shape_to_cloud.BuildTranslation(particle->m_localTranslation);
Stuff::LinearMatrix4D shape_to_world;
shape_to_world.Multiply(
shape_to_cloud,
local_to_world
);
dinfo.shapeToWorld = &shape_to_world;
Stuff::Vector3D
scale(
particle->m_scale,
particle->m_scale,
particle->m_scale
);
dinfo.scaling = &scale;
particle->m_color.red = spec->m_pRed.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.green = spec->m_pGreen.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.blue = spec->m_pBlue.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.alpha = spec->m_pAlpha.ComputeValue(particle->m_age, particle->m_seed);
dinfo.paintMeColor = &particle->m_color;
info->m_clipper->DrawScalableShape(&dinfo);
}
}
}
}
//
//-------------------------------------------------------
// 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
);
for (unsigned i = 0; i < m_activeParticleCount; i++)
{
Particle *particle = GetParticle(i);
Check_Object(particle);
//
//-----------------------------------------------------------------
// If the particle is still alive, concatenate into world space and
// issue the draw command
//-----------------------------------------------------------------
//
if (particle->m_age < 1.0f)
{
Stuff::Vector3D direction_in_cloud;
direction_in_cloud.Subtract(
camera_in_cloud,
particle->m_localTranslation
);
Stuff::LinearMatrix4D shape_to_cloud;
shape_to_cloud.BuildRotation(particle->m_localRotation);
shape_to_cloud.AlignLocalAxisToWorldVector(
direction_in_cloud,
Stuff::Z_Axis,
Stuff::Y_Axis,
-1
);
shape_to_cloud.BuildTranslation(particle->m_localTranslation);
Stuff::LinearMatrix4D shape_to_world;
shape_to_world.Multiply(
shape_to_cloud,
local_to_world
);
dinfo.shapeToWorld = &shape_to_world;
Stuff::Vector3D
scale(
particle->m_scale,
particle->m_scale,
particle->m_scale
);
dinfo.scaling = &scale;
particle->m_color.red = spec->m_pRed.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.green = spec->m_pGreen.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.blue = spec->m_pBlue.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.alpha = spec->m_pAlpha.ComputeValue(particle->m_age, particle->m_seed);
dinfo.paintMeColor = &particle->m_color;
info->m_clipper->DrawScalableShape(&dinfo);
}
}
}
//
//---------------------------------------------------------------
// 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);
//
//-----------------------------------------------------------------
// If the particle is still alive, concatenate into world space and
// issue the draw command
//-----------------------------------------------------------------
//
if (particle->m_age < 1.0f)
{
Stuff::LinearMatrix4D shape_to_cloud;
shape_to_cloud.BuildTranslation(particle->m_localTranslation);
shape_to_cloud.BuildRotation(particle->m_localRotation);
Stuff::LinearMatrix4D shape_to_world;
shape_to_world.Multiply(
shape_to_cloud,
local_to_world
);
dinfo.shapeToWorld = &shape_to_world;
Stuff::Vector3D
scale(
particle->m_scale,
particle->m_scale,
particle->m_scale
);
dinfo.scaling = &scale;
particle->m_color.red = spec->m_pRed.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.green = spec->m_pGreen.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.blue = spec->m_pBlue.ComputeValue(particle->m_age, particle->m_seed);
particle->m_color.alpha = spec->m_pAlpha.ComputeValue(particle->m_age, particle->m_seed);
dinfo.paintMeColor = &particle->m_color;
info->m_clipper->DrawScalableShape(&dinfo);
}
}
}
}
//
//----------------------------
// Let our parent do its thing
//----------------------------
//
BaseClass::Draw(info);
}
//------------------------------------------------------------------------------
//
void
gosFX::ShapeCloud::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}