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.
610 lines
18 KiB
C++
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));
|
|
}
|