1517 lines
66 KiB
C++
1517 lines
66 KiB
C++
/*
|
|
** Command & Conquer Renegade(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/***********************************************************************************************
|
|
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : WW3D *
|
|
* *
|
|
* $Archive:: /Commando/Code/ww3d2/ringobj.cpp $*
|
|
* *
|
|
* Author:: Greg Hjelstrom *
|
|
* *
|
|
* $Modtime:: 11/24/01 6:17p $*
|
|
* *
|
|
* $Revision:: 27 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* RingRenderObjClass::RingRenderObjClass -- Constructor *
|
|
* RingRenderObjClass::RingRenderObjClass -- Constructor - init from a definition *
|
|
* RingRenderObjClass::RingRenderObjClass -- Copy constructor *
|
|
* RingRenderObjClass::~RingRenderObjClass -- destructor *
|
|
* RingRenderObjClass::operator -- assignment operator *
|
|
* RingRenderObjClass::Get_Num_Polys -- returns number of polygons *
|
|
* RingRenderObjClass::Get_Name -- returns name *
|
|
* RingRenderObjClass::Set_Name -- sets the name *
|
|
* RingRenderObjClass::Set_Color -- Sets the color of the Ring *
|
|
* RingRenderObjClass::Init_Ring_Render_System -- global initialization needed for Ring *
|
|
* RingRenderObjClass::Shutdown_Ring_Render_System -- cleanup Ring render system *
|
|
* RingRenderObjClass::Set_Ring_Display_Mask -- Sets global display mask for all Ringes *
|
|
* RingRenderObjClass::Get_Ring_Display_Mask -- returns the display mask *
|
|
* RingRenderObjClass::update_mesh_data -- Updates vertex positions, etc *
|
|
* RingRenderObjClass::render_Ring -- submits the Ring to the GERD *
|
|
* RingRenderObjClass::vis_render_Ring -- submits Ring to the GERD for VIS *
|
|
* RingRenderObjClass::RingRenderObjClass -- constructor *
|
|
* RingRenderObjClass::RingRenderObjClass -- Constructor - init from a definition *
|
|
* RingRenderObjClass::RingRenderObjClass -- copy constructor *
|
|
* RingRenderObjClass::RingRenderObjClass -- Constructor from a wwmath aaRing *
|
|
* RingRenderObjClass::operator -- assignment operator *
|
|
* RingRenderObjClass::Clone -- clones the Ring *
|
|
* RingRenderObjClass::Class_ID -- returns the class-id for AARing's *
|
|
* RingRenderObjClass::Render -- render this Ring *
|
|
* RingRenderObjClass::Special_Render -- special render this Ring (vis) *
|
|
* RingRenderObjClass::Set_Transform -- set the transform for this Ring *
|
|
* RingRenderObjClass::Set_Position -- Set the position of this Ring *
|
|
* RingRenderObjClass::update_cached_Ring -- update the world-space version of this Ring *
|
|
* RingRenderObjClass::Cast_Ray -- cast a ray against this Ring *
|
|
* RingRenderObjClass::Cast_AARing -- cast an AARing against this Ring *
|
|
* RingRenderObjClass::Cast_OBRing -- cast an OBRing against this Ring *
|
|
* RingRenderObjClass::Get_Obj_Space_Bounding_Ring -- return the object-space bounding sp *
|
|
* RingRenderObjClass::Get_Obj_Space_Bounding_Ring -- returns the obj-space bounding Sphe *
|
|
* RingRenderObjClass::Update_Cached_Bounding_Volumes -- Updates world-space bounding volum *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#include "ringobj.h"
|
|
#include "w3d_util.h"
|
|
#include "wwdebug.h"
|
|
#include "vertmaterial.h"
|
|
#include "ww3d.h"
|
|
#include "chunkio.h"
|
|
#include "rinfo.h"
|
|
#include "coltest.h"
|
|
#include "inttest.h"
|
|
#include "matrix3.h"
|
|
#include "wwmath.h"
|
|
#include "assetmgr.h"
|
|
#include "wwstring.h"
|
|
#include "camera.h"
|
|
#include "statistics.h"
|
|
#include "dx8wrapper.h"
|
|
#include "dx8indexbuffer.h"
|
|
#include "dx8vertexbuffer.h"
|
|
#include "sortingrenderer.h"
|
|
#include "vector3i.h"
|
|
#include "visrasterizer.h"
|
|
|
|
|
|
#define RING_NUM_LOD (20)
|
|
#define RING_LOWEST_LOD (3)
|
|
#define RING_HIGHEST_LOD (30)
|
|
|
|
#define STATIC_SORT_RINGS 1 // makes all ring use a static sort level rather than per-poly sorting
|
|
#define RING_SORT_LEVEL 1 // the static sort level for all rings (when enabled)
|
|
|
|
static bool Ring_Array_Valid = false;
|
|
|
|
|
|
/**
|
|
** RingMeshClass
|
|
** A set of LODs of RingMeshes are re-used by all RingRenderObjClasses.
|
|
*/
|
|
class RingMeshClass
|
|
{
|
|
friend class RingRenderObjClass;
|
|
|
|
public:
|
|
// Constructor
|
|
RingMeshClass(void);
|
|
RingMeshClass(float radius, int slices);
|
|
// Destructor
|
|
~RingMeshClass(void);
|
|
|
|
void Generate(float radius, int slices);
|
|
|
|
int Get_Num_Polys(void) { return face_ct; };
|
|
|
|
void Scale (const Vector2 &inner_scale, const Vector2 &outer_scale);
|
|
void Set_Tiling (int count);
|
|
|
|
private:
|
|
|
|
void Free(void);
|
|
|
|
float Radius;
|
|
int Slices;
|
|
int face_ct; //# of faces
|
|
|
|
int TileCount;
|
|
Vector2 InnerScale;
|
|
Vector2 OuterScale;
|
|
|
|
int Vertex_ct; // vertex count
|
|
Vector3 *vtx; // array of vertices
|
|
Vector2 *orig_vtx; // array of vertices representing a 'unit' ring
|
|
Vector3 *vtx_normal; // array of vertex normals
|
|
Vector2 *vtx_uv; // array of vertex uv coordinates
|
|
|
|
TriIndex *tri_poly; // array of triangle polys, vertex indices (can be discard if switch to fan renderer)
|
|
};
|
|
|
|
|
|
RingMeshClass RingMeshArray[RING_NUM_LOD];
|
|
|
|
|
|
|
|
/*
|
|
** RingRenderObjClass Implementation
|
|
*/
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::RingRenderObjClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
RingRenderObjClass::RingRenderObjClass(void)
|
|
: anim_time (0.0F),
|
|
IsAnimating(false),
|
|
AnimDuration (0.0F),
|
|
RingMaterial (NULL),
|
|
RingTexture (NULL),
|
|
Color (0.75F,0.75F,0.75F),
|
|
InnerScale (1, 1),
|
|
OuterScale (1, 1),
|
|
Alpha (1.0F),
|
|
Flags(0),
|
|
TextureTileCount(5),
|
|
ObjSpaceCenter (0, 0, 0),
|
|
ObjSpaceExtent (1, 1, 1),
|
|
InnerExtent (0.5F, 0.5F),
|
|
OuterExtent (1.0F, 1.0F),
|
|
CurrentLOD (RING_NUM_LOD - 1)
|
|
{
|
|
Generate_Shared_Mesh_Arrays ();
|
|
|
|
memset(Name,0,sizeof(Name));
|
|
|
|
Init_Material () ;
|
|
|
|
#if (STATIC_SORT_RINGS)
|
|
// (gth) testing whether we can get away without poly-sorting rings and spheres
|
|
Set_Sort_Level(RING_SORT_LEVEL);
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::RingRenderObjClass -- Constructor - init from a definition *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
RingRenderObjClass::RingRenderObjClass(const W3dRingStruct & def)
|
|
: anim_time (0.0F),
|
|
IsAnimating(false),
|
|
AnimDuration (0.0F),
|
|
RingMaterial (NULL),
|
|
RingTexture (NULL),
|
|
Color (0.75F,0.75F,0.75F),
|
|
InnerScale (1, 1),
|
|
OuterScale (1, 1),
|
|
Alpha (1.0F),
|
|
Flags(0),
|
|
TextureTileCount(5),
|
|
ObjSpaceCenter (0, 0, 0),
|
|
ObjSpaceExtent (1, 1, 1),
|
|
InnerExtent (0.5F, 0.5F),
|
|
OuterExtent (1.0F, 1.0F),
|
|
CurrentLOD (RING_NUM_LOD - 1)
|
|
{
|
|
Generate_Shared_Mesh_Arrays ();
|
|
Init_Material ();
|
|
|
|
//
|
|
// Initialize from the defintion
|
|
//
|
|
Set_Name(def.Name);
|
|
Set_Local_Center_Extent ( Vector3 (def.Center.X, def.Center.Y, def.Center.Z),
|
|
Vector3 (def.Extent.X, def.Extent.Y, def.Extent.Z));
|
|
|
|
if (def.TextureName[0] != 0) {
|
|
RingTexture = WW3DAssetManager::Get_Instance ()->Get_Texture (def.TextureName);
|
|
}
|
|
|
|
#if (STATIC_SORT_RINGS)
|
|
// (gth) testing whether we can get away without poly-sorting rings and spheres
|
|
Set_Sort_Level(RING_SORT_LEVEL);
|
|
#endif
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::RingRenderObjClass -- Copy constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
RingRenderObjClass::RingRenderObjClass(const RingRenderObjClass & src)
|
|
: anim_time (0.0F),
|
|
IsAnimating(false),
|
|
AnimDuration (0.0F),
|
|
RingMaterial (NULL),
|
|
RingTexture (NULL),
|
|
Color (0.75F,0.75F,0.75F),
|
|
InnerScale (1, 1),
|
|
OuterScale (1, 1),
|
|
Alpha (1.0F),
|
|
Flags(0),
|
|
TextureTileCount(5),
|
|
ObjSpaceCenter (0, 0, 0),
|
|
ObjSpaceExtent (1, 1, 1),
|
|
InnerExtent (0.5F, 0.5F),
|
|
OuterExtent (1.0F, 1.0F),
|
|
CurrentLOD (RING_NUM_LOD - 1)
|
|
{
|
|
Generate_Shared_Mesh_Arrays ();
|
|
Init_Material ();
|
|
|
|
*this = src;
|
|
|
|
#if (STATIC_SORT_RINGS)
|
|
// (gth) testing whether we can get away without poly-sorting rings and spheres
|
|
Set_Sort_Level(RING_SORT_LEVEL);
|
|
#endif
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::~RingRenderObjClass -- destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/7/2001 gth : Created. *
|
|
*=============================================================================================*/
|
|
RingRenderObjClass::~RingRenderObjClass()
|
|
{
|
|
REF_PTR_RELEASE(RingMaterial);
|
|
REF_PTR_RELEASE(RingTexture);
|
|
} // destructor
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::operator -- assignment operator *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
RingRenderObjClass & RingRenderObjClass::operator = (const RingRenderObjClass & that)
|
|
{
|
|
if (this != &that) {
|
|
RenderObjClass::operator = (that);
|
|
Set_Name(that.Get_Name());
|
|
Color = that.Color;
|
|
Alpha = that.Alpha;
|
|
InnerScale = that.InnerScale;
|
|
OuterScale = that.OuterScale;
|
|
Flags = that.Flags;
|
|
RingShader = that.RingShader;
|
|
CachedBox = that.CachedBox;
|
|
anim_time = that.anim_time;
|
|
AnimDuration = that.AnimDuration;
|
|
ObjSpaceCenter = that.ObjSpaceCenter;
|
|
ObjSpaceExtent = that.ObjSpaceExtent;
|
|
ColorChannel = that.ColorChannel;
|
|
AlphaChannel = that.AlphaChannel;
|
|
InnerScaleChannel = that.InnerScaleChannel;
|
|
OuterScaleChannel = that.OuterScaleChannel;
|
|
InnerExtent = that.InnerExtent;
|
|
OuterExtent = that.OuterExtent;
|
|
TextureTileCount = that.TextureTileCount;
|
|
|
|
Set_Texture (that.RingTexture);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Generate_Shared_Mesh_Arrays -- Generates mesh LOD arrays. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 03/08/00 pds : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Generate_Shared_Mesh_Arrays (void)
|
|
{
|
|
// Generate shared Mesh Arrays
|
|
if (!Ring_Array_Valid) {
|
|
|
|
float size = RING_LOWEST_LOD;
|
|
float step = (RING_HIGHEST_LOD - RING_LOWEST_LOD);
|
|
step /= RING_NUM_LOD;
|
|
|
|
for(int i=0; i < RING_NUM_LOD; i++) {
|
|
|
|
RingMeshArray[i].Generate(1.0f, size);
|
|
|
|
size+=step;
|
|
}
|
|
|
|
Ring_Array_Valid = true;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Init_Material -- Sets up the material and default shader for the Ring.*
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 03/08/00 pds : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Init_Material (void)
|
|
{
|
|
REF_PTR_RELEASE (RingMaterial);
|
|
|
|
RingMaterial = NEW_REF(VertexMaterialClass,());
|
|
RingMaterial->Set_Ambient(0,0,0);
|
|
RingMaterial->Set_Diffuse(0,0,0);
|
|
RingMaterial->Set_Specular(0,0,0);
|
|
RingMaterial->Set_Emissive(1,1,1);
|
|
RingMaterial->Set_Opacity(0.25f);
|
|
RingMaterial->Set_Shininess(0.0f);
|
|
|
|
// Texturing, zbuffer, primary gradient, alpha blending
|
|
RingShader = ShaderClass::_PresetAlphaShader;
|
|
|
|
} // Init_Material
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Get_Num_Polys -- returns number of polygons *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
int RingRenderObjClass::Get_Num_Polys(void) const
|
|
{
|
|
return RingMeshArray[ CurrentLOD ].Get_Num_Polys();
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Set_Texture *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Set_Texture(TextureClass *tf)
|
|
{
|
|
REF_PTR_SET(RingTexture,tf);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Get_Name -- returns name *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
const char * RingRenderObjClass::Get_Name(void) const
|
|
{
|
|
return Name;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Set_Name -- sets the name *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Set_Name(const char * name)
|
|
{
|
|
WWASSERT(name != NULL);
|
|
WWASSERT(strlen(name) < 2*W3D_NAME_LEN);
|
|
strcpy(Name,name);
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::render_ring -- submits the box to the GERD *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::render_ring(RenderInfoClass & rinfo,const Vector3 & center,const Vector3 & extent)
|
|
{
|
|
RingMeshClass & ring = RingMeshArray[ CurrentLOD ];
|
|
|
|
if (RingTexture) {
|
|
RingShader.Set_Texturing (ShaderClass::TEXTURING_ENABLE);
|
|
} else {
|
|
RingShader.Set_Texturing (ShaderClass::TEXTURING_DISABLE);
|
|
}
|
|
DX8Wrapper::Set_Shader(RingShader);
|
|
DX8Wrapper::Set_Texture(0,RingTexture);
|
|
DX8Wrapper::Set_Material(RingMaterial);
|
|
|
|
DynamicVBAccessClass vb(BUFFER_TYPE_DYNAMIC_SORTING,dynamic_fvf_type,ring.Vertex_ct);
|
|
{
|
|
DynamicVBAccessClass::WriteLockClass Lock(&vb);
|
|
VertexFormatXYZNDUV2 *vb = Lock.Get_Formatted_Vertex_Array();
|
|
|
|
//
|
|
// set up the vertex color+alpha
|
|
//
|
|
unsigned color;
|
|
if (RingShader.Get_Dst_Blend_Func () == ShaderClass::DSTBLEND_ONE) {
|
|
color = DX8Wrapper::Convert_Color(Alpha * Color,1.0f);
|
|
} else {
|
|
color = DX8Wrapper::Convert_Color(Color,Alpha);
|
|
}
|
|
|
|
for (int i=0; i<ring.Vertex_ct; i++)
|
|
{
|
|
vb->x = ring.vtx[i].X;
|
|
vb->y = ring.vtx[i].Y;
|
|
vb->z = ring.vtx[i].Z;
|
|
|
|
vb->nx = ring.vtx_normal[i].X; // may not need this!
|
|
vb->ny = ring.vtx_normal[i].Y;
|
|
vb->nz = ring.vtx_normal[i].Z;
|
|
|
|
vb->diffuse = color;
|
|
|
|
if (RingTexture) {
|
|
vb->u1 = ring.vtx_uv[i].X;
|
|
vb->v1 = ring.vtx_uv[i].Y;
|
|
}
|
|
vb++;
|
|
}
|
|
}
|
|
|
|
DynamicIBAccessClass ib(BUFFER_TYPE_DYNAMIC_SORTING,ring.face_ct*3);
|
|
{
|
|
DynamicIBAccessClass::WriteLockClass Lock(&ib);
|
|
unsigned short *mem=Lock.Get_Index_Array();
|
|
for (int i=0; i<ring.face_ct; i++)
|
|
{
|
|
mem[3*i]=ring.tri_poly[i].I;
|
|
mem[3*i+1]=ring.tri_poly[i].J;
|
|
mem[3*i+2]=ring.tri_poly[i].K;
|
|
}
|
|
}
|
|
|
|
DX8Wrapper::Set_Vertex_Buffer(vb);
|
|
DX8Wrapper::Set_Index_Buffer(ib,0);
|
|
|
|
#if (STATIC_SORT_RINGS)
|
|
DX8Wrapper::Draw_Triangles(0,ring.face_ct,0,ring.Vertex_ct);
|
|
#else
|
|
SortingRendererClass::Insert_Triangles(
|
|
Get_Bounding_Sphere(),
|
|
0,
|
|
ring.face_ct,
|
|
0,
|
|
ring.Vertex_ct);
|
|
#endif
|
|
|
|
} // render_ring
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::vis_render_ring -- submits box to the GERD for VIS *
|
|
* *
|
|
* this renders the ring with the specified VIS-ID. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::vis_render_ring(SpecialRenderInfoClass & rinfo,const Vector3 & center,const Vector3 & extent)
|
|
{
|
|
WWASSERT(0);
|
|
} // vis_render_ring
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Clone -- clones the ring *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
RenderObjClass * RingRenderObjClass::Clone(void) const
|
|
{
|
|
return new RingRenderObjClass(*this);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Class_ID -- returns the class-id for Rings's *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
int RingRenderObjClass::Class_ID(void) const
|
|
{
|
|
return RenderObjClass::CLASSID_RING;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Render -- render this box *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Render(RenderInfoClass & rinfo)
|
|
{
|
|
if (Is_Not_Hidden_At_All() == false) {
|
|
return;
|
|
}
|
|
|
|
// If static sort lists are enabled and this mesh has a sort level, put it on the list instead
|
|
// of rendering it.
|
|
unsigned int sort_level = (unsigned int)Get_Sort_Level();
|
|
|
|
if (WW3D::Are_Static_Sort_Lists_Enabled() && sort_level != SORT_LEVEL_NONE) {
|
|
|
|
WW3D::Add_To_Static_Sort_List(this, sort_level);
|
|
|
|
} else {
|
|
|
|
// Process texture reductions:
|
|
// if (RingTexture) RingTexture->Process_Reduction();
|
|
|
|
// Determine LOD
|
|
|
|
float screen_size = Get_Screen_Size (rinfo.Camera);
|
|
|
|
// This code assumes that screen_size returns back the percentage of the screen, 0.0 = 0%, 1.0f = 100%
|
|
|
|
// Currently it will use Linear interpolation over 0.0 to 1.0, with the RING_NUM_LOD
|
|
// to set the CurrentLOD
|
|
|
|
screen_size = sqrtf(screen_size);
|
|
|
|
float lod = screen_size * ((float) RING_NUM_LOD);
|
|
int lod_int = lod;
|
|
lod-=lod_int;
|
|
|
|
if (lod >= 0.5f) lod_int++;
|
|
|
|
if (lod_int < 0) lod_int = 0;
|
|
if (lod_int >= RING_NUM_LOD) lod_int = RING_NUM_LOD-1;
|
|
|
|
CurrentLOD = lod_int;
|
|
|
|
|
|
// End LOD Determination
|
|
|
|
|
|
Matrix3D temp = Transform;
|
|
|
|
// Do Time Based Animation
|
|
animate ();
|
|
|
|
//
|
|
// Scale the inner and outer parts of the ring.
|
|
//
|
|
Vector2 inner_scale (InnerExtent.X * InnerScale.X, InnerExtent.Y * InnerScale.Y);
|
|
Vector2 outer_scale (OuterExtent.X * OuterScale.X, OuterExtent.Y * OuterScale.Y);
|
|
RingMeshArray[CurrentLOD].Scale (inner_scale, outer_scale);
|
|
|
|
//
|
|
// Make sure this mesh uses the correct UV tiling
|
|
//
|
|
if (RingTexture != NULL) {
|
|
RingMeshArray[CurrentLOD].Set_Tiling (TextureTileCount);
|
|
}
|
|
|
|
//
|
|
// Should we force the ring to be camera aligned?
|
|
//
|
|
|
|
if (Flags & USE_CAMERA_ALIGN) {
|
|
#ifdef WW3D_DX8
|
|
srMatrix4 srtm;
|
|
rinfo.Gerd.matrixMode (srGERD::MODELVIEW);
|
|
rinfo.Gerd.pushMatrix ();
|
|
rinfo.Gerd.getMatrix (srGERD::MODELVIEW, srtm);
|
|
|
|
srVector3 wpos(Transform[0][3],Transform[1][3],Transform[2][3]);
|
|
srVector4 cpos = srtm.transform (wpos);
|
|
|
|
Matrix3D tm(1.0f, 0.0f, 0.0f, cpos.x,
|
|
0.0f, 1.0f, 0.0f, cpos.y,
|
|
0.0f, 0.0f, 1.0f, cpos.z);
|
|
|
|
Convert_Westwood_Matrix (tm, &srtm);
|
|
rinfo.Gerd.loadMatrix (srtm);
|
|
#endif //WW3D_DX8
|
|
} else {
|
|
DX8Wrapper::Set_Transform(D3DTS_WORLD,temp);
|
|
}
|
|
|
|
//
|
|
// Pass the geometry onto Surrender
|
|
//
|
|
render_ring (rinfo, ObjSpaceCenter, ObjSpaceExtent);
|
|
}
|
|
} // Render
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Get_Default_Color - get the default (or first frame) value *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/13/2000 pds : Created. *
|
|
*=============================================================================================*/
|
|
Vector3 RingRenderObjClass::Get_Default_Color(void) const
|
|
{
|
|
Vector3 value;
|
|
|
|
if (ColorChannel.Get_Key_Count () > 0) {
|
|
value = ColorChannel.Get_Key (0).Get_Value ();
|
|
} else {
|
|
value = Color;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Get_Default_Alpha - get the default (or first frame) value *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/13/2000 pds : Created. *
|
|
*=============================================================================================*/
|
|
float RingRenderObjClass::Get_Default_Alpha(void) const
|
|
{
|
|
float value;
|
|
|
|
if (AlphaChannel.Get_Key_Count () > 0) {
|
|
value = AlphaChannel.Get_Key (0).Get_Value ();
|
|
} else {
|
|
value = Alpha;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Get_Default_Inner_Scale - get the default (or first frame) value *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/13/2000 pds : Created. *
|
|
*=============================================================================================*/
|
|
Vector2 RingRenderObjClass::Get_Default_Inner_Scale(void) const
|
|
{
|
|
Vector2 value;
|
|
|
|
if (InnerScaleChannel.Get_Key_Count () > 0) {
|
|
value = InnerScaleChannel.Get_Key (0).Get_Value ();
|
|
} else {
|
|
value = InnerScale;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Get_Default_Outer_Scale - get the default (or first frame) value *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/13/2000 pds : Created. *
|
|
*=============================================================================================*/
|
|
Vector2 RingRenderObjClass::Get_Default_Outer_Scale(void) const
|
|
{
|
|
Vector2 value;
|
|
|
|
if (OuterScaleChannel.Get_Key_Count () > 0) {
|
|
value = OuterScaleChannel.Get_Key (0).Get_Value ();
|
|
} else {
|
|
value = OuterScale;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Special_Render -- special render this box (vis) *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
, * *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Special_Render(SpecialRenderInfoClass & rinfo)
|
|
{
|
|
Matrix3D temp(1);
|
|
temp.Translate(Transform.Get_Translation());
|
|
|
|
if (rinfo.RenderType == SpecialRenderInfoClass::RENDER_VIS) {
|
|
WWASSERT(rinfo.VisRasterizer != NULL);
|
|
rinfo.VisRasterizer->Set_Model_Transform(temp);
|
|
vis_render_ring(rinfo,ObjSpaceCenter,ObjSpaceExtent);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Set_Transform -- set the transform for this box *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Set_Transform(const Matrix3D &m)
|
|
{
|
|
RenderObjClass::Set_Transform(m);
|
|
update_cached_box();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Set_Position -- Set the position of this box *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Set_Position(const Vector3 &v)
|
|
{
|
|
RenderObjClass::Set_Position(v);
|
|
update_cached_box();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::update_cached_box -- update the world-space version of this box *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::update_cached_box(void)
|
|
{
|
|
CachedBox.Center = Transform.Get_Translation() + ObjSpaceCenter;
|
|
CachedBox.Extent = ObjSpaceExtent;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Get_Obj_Space_Bounding_Ring -- return the object-space bounding sphe *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
|
|
{
|
|
sphere.Center = ObjSpaceCenter;
|
|
sphere.Radius = ObjSpaceExtent.Length();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::Get_Obj_Space_Bounding_Box -- returns the obj-space bounding box *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/19/00 gth : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
|
|
{
|
|
box.Center = ObjSpaceCenter;
|
|
box.Extent = ObjSpaceExtent;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SphereRenderObjClass::Update_On_Visibilty -- Either starts or stops the animation based on visibility*
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 4/04/00 pds : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::Update_On_Visibilty(void)
|
|
{
|
|
// Simply start or stop the animation based on
|
|
// the visibility state of the primitive.
|
|
if (Is_Not_Hidden_At_All () && Is_Animating () == false) {
|
|
Start_Animating ();
|
|
} else if ((Is_Not_Hidden_At_All () == false) && Is_Animating ()) {
|
|
Stop_Animating ();
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* RingRenderObjClass::animate -- Update Current Display state *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/07/00 jga : Created. *
|
|
*=============================================================================================*/
|
|
void RingRenderObjClass::animate()
|
|
{
|
|
if (Is_Animating ()) {
|
|
|
|
if ( ColorChannel.Get_Key_Count () > 0 ||
|
|
AlphaChannel.Get_Key_Count () > 0 ||
|
|
InnerScaleChannel.Get_Key_Count () > 0 ||
|
|
OuterScaleChannel.Get_Key_Count () > 0)
|
|
{
|
|
//
|
|
// Convert from milliseconds to seconds and normalize the time
|
|
//
|
|
if (AnimDuration > 0) {
|
|
float frametime = WW3D::Get_Frame_Time();
|
|
frametime = (frametime * 0.001F) / AnimDuration;
|
|
anim_time += frametime;
|
|
} else {
|
|
anim_time = 1.0F;
|
|
}
|
|
WWASSERT (anim_time >= 0.0F);
|
|
|
|
if ((Flags & USE_ANIMATION_LOOP) && anim_time > 1.0F) {
|
|
anim_time -= 1.0F;
|
|
}
|
|
|
|
if (ColorChannel.Get_Key_Count () > 0) {
|
|
Color = ColorChannel.Evaluate (anim_time);
|
|
}
|
|
|
|
if (AlphaChannel.Get_Key_Count () > 0) {
|
|
Alpha = AlphaChannel.Evaluate (anim_time);
|
|
}
|
|
|
|
if (InnerScaleChannel.Get_Key_Count () > 0) {
|
|
InnerScale = InnerScaleChannel.Evaluate (anim_time);
|
|
}
|
|
|
|
if (OuterScaleChannel.Get_Key_Count () > 0) {
|
|
OuterScale = OuterScaleChannel.Evaluate (anim_time);
|
|
ObjSpaceExtent.X = OuterScale.X * OuterExtent.X;
|
|
ObjSpaceExtent.Y = OuterScale.Y * OuterExtent.Y;
|
|
ObjSpaceExtent.Z = 0;
|
|
Update_Cached_Bounding_Volumes ();
|
|
}
|
|
}
|
|
}
|
|
|
|
return ;
|
|
} // animate
|
|
|
|
|
|
/*
|
|
** RingLoaderClass Implementation
|
|
*/
|
|
PrototypeClass * RingLoaderClass::Load_W3D(ChunkLoadClass & cload)
|
|
{
|
|
RingPrototypeClass *prototype = new RingPrototypeClass ();
|
|
prototype->Load (cload);
|
|
return prototype;
|
|
}
|
|
|
|
/*
|
|
** RingPrototypeClass Implementation
|
|
*/
|
|
RingPrototypeClass::RingPrototypeClass (void)
|
|
{
|
|
::memset (&Definition, 0, sizeof (Definition));
|
|
return ;
|
|
}
|
|
|
|
RingPrototypeClass::RingPrototypeClass(RingRenderObjClass *ring)
|
|
{
|
|
::memset (&Definition, 0, sizeof (Definition));
|
|
::strcpy (Definition.Name, ring->Get_Name ());
|
|
|
|
Definition.AnimDuration = ring->AnimDuration;
|
|
Definition.Attributes = ring->Get_Flags ();
|
|
Definition.DefaultAlpha = ring->Get_Default_Alpha ();
|
|
Definition.DefaultInnerScale = ring->Get_Default_Inner_Scale ();
|
|
Definition.DefaultOuterScale = ring->Get_Default_Outer_Scale ();
|
|
Definition.TextureTileCount = ring->Get_Texture_Tiling ();
|
|
|
|
Definition.InnerExtent = ring->Get_Inner_Extent ();
|
|
Definition.OuterExtent = ring->Get_Outer_Extent ();
|
|
|
|
Vector3 def_color = ring->Get_Default_Color ();
|
|
W3dUtilityClass::Convert_Vector (def_color, &Definition.DefaultColor);
|
|
|
|
W3dUtilityClass::Convert_Vector (ring->Get_Box ().Center, &Definition.Center);
|
|
W3dUtilityClass::Convert_Vector (ring->Get_Box ().Extent, &Definition.Extent);
|
|
W3dUtilityClass::Convert_Shader (ring->RingShader, &Definition.Shader);
|
|
|
|
//
|
|
// Determine the texture name for this sphere
|
|
//
|
|
if (ring->RingTexture != NULL) {
|
|
StringClass name = ring->RingTexture->Get_Full_Path();
|
|
const char *filename = ::strrchr (name, '\\');
|
|
if (filename != NULL) {
|
|
filename ++;
|
|
} else {
|
|
filename = name;
|
|
}
|
|
|
|
::strcpy (Definition.TextureName, filename);
|
|
}
|
|
|
|
//
|
|
// Save the animateable channels
|
|
//
|
|
ColorChannel = ring->Peek_Color_Channel ();
|
|
AlphaChannel = ring->Peek_Alpha_Channel ();
|
|
InnerScaleChannel = ring->Peek_Inner_Scale_Channel ();
|
|
OuterScaleChannel = ring->Peek_Outer_Scale_Channel ();
|
|
return ;
|
|
}
|
|
|
|
RingPrototypeClass::~RingPrototypeClass (void)
|
|
{
|
|
return ;
|
|
}
|
|
|
|
const char * RingPrototypeClass::Get_Name(void) const
|
|
{
|
|
return Definition.Name;
|
|
}
|
|
|
|
int RingPrototypeClass::Get_Class_ID(void) const
|
|
{
|
|
return RenderObjClass::CLASSID_RING;
|
|
}
|
|
|
|
enum
|
|
{
|
|
CHUNKID_RING_DEF = 1,
|
|
CHUNKID_COLOR_CHANNEL,
|
|
CHUNKID_ALPHA_CHANNEL,
|
|
CHUNKID_INNER_SCALE_CHANNEL,
|
|
CHUNKID_OUTER_SCALE_CHANNEL
|
|
};
|
|
|
|
bool RingPrototypeClass::Load (ChunkLoadClass &cload)
|
|
{
|
|
ColorChannel.Reset ();
|
|
AlphaChannel.Reset ();
|
|
InnerScaleChannel.Reset ();
|
|
OuterScaleChannel.Reset ();
|
|
|
|
while (cload.Open_Chunk ()) {
|
|
switch (cload.Cur_Chunk_ID ()) {
|
|
|
|
case CHUNKID_RING_DEF:
|
|
cload.Read (&Definition, sizeof (Definition));
|
|
break;
|
|
|
|
case CHUNKID_COLOR_CHANNEL:
|
|
ColorChannel.Load (cload);
|
|
break;
|
|
|
|
case CHUNKID_ALPHA_CHANNEL:
|
|
AlphaChannel.Load (cload);
|
|
break;
|
|
|
|
case CHUNKID_INNER_SCALE_CHANNEL:
|
|
InnerScaleChannel.Load (cload);
|
|
break;
|
|
|
|
case CHUNKID_OUTER_SCALE_CHANNEL:
|
|
OuterScaleChannel.Load (cload);
|
|
break;
|
|
}
|
|
|
|
cload.Close_Chunk ();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RingPrototypeClass::Save (ChunkSaveClass &csave)
|
|
{
|
|
csave.Begin_Chunk (W3D_CHUNK_RING);
|
|
|
|
csave.Begin_Chunk (CHUNKID_RING_DEF);
|
|
csave.Write (&Definition, sizeof (Definition));
|
|
csave.End_Chunk ();
|
|
|
|
if (ColorChannel.Get_Key_Count () > 0) {
|
|
csave.Begin_Chunk (CHUNKID_COLOR_CHANNEL);
|
|
ColorChannel.Save (csave);
|
|
csave.End_Chunk ();
|
|
}
|
|
|
|
if (AlphaChannel.Get_Key_Count () > 0) {
|
|
csave.Begin_Chunk (CHUNKID_ALPHA_CHANNEL);
|
|
AlphaChannel.Save (csave);
|
|
csave.End_Chunk ();
|
|
}
|
|
|
|
if (InnerScaleChannel.Get_Key_Count () > 0) {
|
|
csave.Begin_Chunk (CHUNKID_INNER_SCALE_CHANNEL);
|
|
InnerScaleChannel.Save (csave);
|
|
csave.End_Chunk ();
|
|
}
|
|
|
|
if (OuterScaleChannel.Get_Key_Count () > 0) {
|
|
csave.Begin_Chunk (CHUNKID_OUTER_SCALE_CHANNEL);
|
|
OuterScaleChannel.Save (csave);
|
|
csave.End_Chunk ();
|
|
}
|
|
|
|
csave.End_Chunk ();
|
|
return true;
|
|
}
|
|
|
|
RenderObjClass * RingPrototypeClass::Create(void)
|
|
{
|
|
//
|
|
// Create the new render object
|
|
//
|
|
RingRenderObjClass *ring = new RingRenderObjClass (Definition);
|
|
|
|
//
|
|
// Configure the ring
|
|
//
|
|
W3dUtilityClass::Convert_Shader (Definition.Shader, &ring->RingShader);
|
|
if (WW3DAssetManager::Get_Instance()->Get_Activate_Fog_On_Load()) {
|
|
ring->RingShader.Enable_Fog ("RingPrototypeClass");
|
|
ring->RingShader.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
|
|
}
|
|
W3dUtilityClass::Convert_Vector (Definition.DefaultColor, &ring->Color);
|
|
ring->InnerScale = Definition.DefaultInnerScale;
|
|
ring->OuterScale = Definition.DefaultOuterScale;
|
|
ring->Set_Animation_Duration (Definition.AnimDuration);
|
|
ring->Alpha = Definition.DefaultAlpha;
|
|
ring->Set_Flags (Definition.Attributes);
|
|
ring->Set_Inner_Extent (Definition.InnerExtent);
|
|
ring->Set_Outer_Extent (Definition.OuterExtent);
|
|
ring->Set_Texture_Tiling (Definition.TextureTileCount);
|
|
|
|
//
|
|
// Initialize the render object with the keyframe arrays
|
|
//
|
|
ring->Set_Color_Channel (ColorChannel);
|
|
ring->Set_Alpha_Channel (AlphaChannel);
|
|
ring->Set_Inner_Scale_Channel (InnerScaleChannel);
|
|
ring->Set_Outer_Scale_Channel (OuterScaleChannel);
|
|
return ring;
|
|
}
|
|
|
|
/*
|
|
** Global instance of the box loader
|
|
*/
|
|
RingLoaderClass _RingLoader;
|
|
|
|
|
|
//
|
|
// Vertices are ordered as such
|
|
// center, followed by outer ring
|
|
//
|
|
/***********************************************************************************************
|
|
* RingMeshClass::RingMeshClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/07/00 jga : Created. *
|
|
*=============================================================================================*/
|
|
RingMeshClass::RingMeshClass(float radius, int slices):
|
|
Radius(radius),
|
|
Slices(slices),
|
|
Vertex_ct(0), // 1 vertex minimum, for center
|
|
vtx(NULL),
|
|
orig_vtx(NULL),
|
|
vtx_normal(NULL),
|
|
vtx_uv(NULL),
|
|
face_ct(0),
|
|
tri_poly(NULL),
|
|
TileCount (5),
|
|
InnerScale (1.0F, 1.0F),
|
|
OuterScale (1.0F, 1.0F)
|
|
{
|
|
Generate(radius, slices);
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* RingMeshClass::RingMeshClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/07/00 jga : Created. *
|
|
*=============================================================================================*/
|
|
RingMeshClass::RingMeshClass(void):
|
|
Radius(0.0f),
|
|
Slices(0),
|
|
Vertex_ct(0), // 1 vertex minimum, for center
|
|
vtx(NULL),
|
|
orig_vtx(NULL),
|
|
vtx_normal(NULL),
|
|
vtx_uv(NULL),
|
|
face_ct(0),
|
|
tri_poly(NULL),
|
|
TileCount (5),
|
|
InnerScale (1.0F, 1.0F),
|
|
OuterScale (1.0F, 1.0F)
|
|
{
|
|
} // empty ringmesh Constructor
|
|
|
|
|
|
void RingMeshClass::Set_Tiling (int count)
|
|
{
|
|
if (TileCount != count) {
|
|
TileCount = count;
|
|
|
|
//
|
|
// Calculate the increment 'u' increment value (as in UV).
|
|
//
|
|
float u_inc = ((float)TileCount) / ((float)(Slices));
|
|
float u_value = 0.0F;
|
|
|
|
//
|
|
// Reassign the UVs
|
|
//
|
|
for (int index = 0; index < Vertex_ct; index += 2) {
|
|
vtx_uv[index].Set (u_value, 0.0F);
|
|
vtx_uv[index + 1].Set (u_value, 1.0F);
|
|
u_value += u_inc;
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
void RingMeshClass::Scale (const Vector2 &inner_scale, const Vector2 &outer_scale)
|
|
{
|
|
bool do_inner = (inner_scale != InnerScale);
|
|
bool do_outer = (outer_scale != OuterScale);
|
|
|
|
//
|
|
// Only scale the inner ring if necessary
|
|
//
|
|
if (do_inner) {
|
|
|
|
for (int index = 0; index < Vertex_ct; index += 2) {
|
|
vtx[index].X = orig_vtx[index].X * inner_scale.X;
|
|
vtx[index].Y = orig_vtx[index].Y * inner_scale.Y;
|
|
vtx[index].Z = 0;
|
|
}
|
|
|
|
InnerScale = inner_scale;
|
|
}
|
|
|
|
//
|
|
// Only scale the outer ring if necessary
|
|
//
|
|
if (do_outer) {
|
|
|
|
for (int index = 1; index < Vertex_ct; index += 2) {
|
|
vtx[index].X = orig_vtx[index].X * outer_scale.X;
|
|
vtx[index].Y = orig_vtx[index].Y * outer_scale.Y;
|
|
vtx[index].Z = 0;
|
|
}
|
|
|
|
OuterScale = outer_scale;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingMeshClass::Generate - Create Ring Geometry *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/07/00 jga : Created. *
|
|
*=============================================================================================*/
|
|
void RingMeshClass::Generate(float radius, int slices)
|
|
{
|
|
Free ();
|
|
|
|
Slices = slices;
|
|
Radius = radius;
|
|
|
|
face_ct = (Slices * 2);
|
|
Vertex_ct = (Slices * 2) + 2;
|
|
|
|
vtx = new Vector3[Vertex_ct];
|
|
orig_vtx = new Vector2[Vertex_ct];
|
|
vtx_normal = new Vector3[Vertex_ct];
|
|
vtx_uv = new Vector2[Vertex_ct];
|
|
tri_poly = new TriIndex[face_ct];
|
|
|
|
//
|
|
// Generate vertices, normals, and uv's
|
|
//
|
|
float angle_inc = DEG_TO_RADF (360) / ((float)Slices);
|
|
float u_inc = ((float)TileCount) / ((float)(Slices));
|
|
float u_value = 0.0F;
|
|
float angle = 0;
|
|
int index = 0;
|
|
|
|
for (index = 0; index < Vertex_ct; index += 2) {
|
|
|
|
float x_pos = -WWMath::Sin (angle);
|
|
float y_pos = WWMath::Cos (angle);
|
|
|
|
//
|
|
// Place the inner index
|
|
//
|
|
vtx[index].X = orig_vtx[index].X = x_pos;
|
|
vtx[index].Y = orig_vtx[index].Y = y_pos;
|
|
vtx[index].Z = 0;
|
|
|
|
//
|
|
// Place the outer index
|
|
//
|
|
vtx[index+1].X = orig_vtx[index+1].X = x_pos;
|
|
vtx[index+1].Y = orig_vtx[index+1].Y = y_pos;
|
|
vtx[index+1].Z = 0;
|
|
|
|
//
|
|
// Normals will just point straight up from the ring...
|
|
//
|
|
vtx_normal[index].Set (0, 0, 1);
|
|
vtx_normal[index + 1].Set (0, 0, 1);
|
|
|
|
//
|
|
// Assign the UVs
|
|
//
|
|
vtx_uv[index].Set (u_value, 0.0F);
|
|
vtx_uv[index + 1].Set (u_value, 1.0F);
|
|
u_value += u_inc;
|
|
|
|
angle += angle_inc;
|
|
}
|
|
|
|
//
|
|
// Make the triangle strip...
|
|
//
|
|
for (index = 0; index < face_ct; index ++) {
|
|
tri_poly[index].I = index;
|
|
tri_poly[index].J = index+1;
|
|
tri_poly[index].K = index+2;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* RingMeshClass::~RingMeshClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/07/00 jga : Created. *
|
|
*=============================================================================================*/
|
|
RingMeshClass::~RingMeshClass(void)
|
|
{
|
|
Free();
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* RingMeshClass::Free - Release Memory, that the ring mesh is using *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/07/00 jga : Created. *
|
|
*=============================================================================================*/
|
|
void RingMeshClass::Free(void)
|
|
{
|
|
|
|
if (vtx) delete vtx;
|
|
if (orig_vtx) delete orig_vtx;
|
|
if (vtx_normal) delete vtx_normal;
|
|
if (vtx_uv) delete vtx_uv;
|
|
if (tri_poly) delete tri_poly;
|
|
|
|
vtx = NULL;
|
|
orig_vtx = NULL;
|
|
vtx_normal = NULL;
|
|
vtx_uv = NULL;
|
|
tri_poly = NULL;
|
|
|
|
} // Free
|
|
|
|
// EOF - ringobj.cpp
|