1478 lines
64 KiB
C++
1478 lines
64 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 : G *
|
|
* *
|
|
* $Archive:: /VSS_Sync/ww3d2/pointgr.cpp $*
|
|
* *
|
|
* $Author:: Vss_sync $*
|
|
* *
|
|
* $Modtime:: 9/12/01 10:01p $*
|
|
* *
|
|
* $Revision:: 38 $*
|
|
* *
|
|
*-------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* PointGroupClass::PointGroupClass -- PointGroupClass CTor. *
|
|
* PointGroupClass::~PointGroupClass -- PointGroupClass DTor. *
|
|
* PointGroupClass::operator = -- PointGroupClass assignment operator. *
|
|
* PointGroupClass::Set_Arrays -- Set point location/color/enable arrays.*
|
|
* PointGroupClass::Set_Point_Size -- Set default point size. *
|
|
* PointGroupClass::Get_Point_Size -- Get default point size. *
|
|
* PointGroupClass::Set_Point_Color -- Set default point color. *
|
|
* PointGroupClass::Get_Point_Color -- Get default point color. *
|
|
* PointGroupClass::Set_Point_Alpha -- Set default point alpha. *
|
|
* PointGroupClass::Get_Point_Alpha -- Get default point alpha. *
|
|
* PointGroupClass::Set_Point_Orientation -- Set default point orientatio*
|
|
* PointGroupClass::Get_Point_Orientation -- Get default point orientatio*
|
|
* PointGroupClass::Set_Point_Frame -- Set default point frame. *
|
|
* PointGroupClass::Get_Point_Frame -- Get default point frame. *
|
|
* PointGroupClass::Set_Point_Mode -- Set point rendering method. *
|
|
* PointGroupClass::Get_Point_Mode -- Get point rendering method. *
|
|
* PointGroupClass::Set_Flag -- Set given flag to on or off. *
|
|
* PointGroupClass::Get_Flag -- Get current value (on/off) of given flag.*
|
|
* PointGroupClass::Set_Texture -- Set texture used. *
|
|
* PointGroupClass::Get_Texture -- Get texture used. *
|
|
* PointGroupClass::Set_Shader -- Set shader used. *
|
|
* PointGroupClass::Get_Shader -- Get shader used. *
|
|
* PointGroupClass::Get_Discrete_Orientation_Count_Log2 -- what it says *
|
|
* PointGroupClass::Set_Discrete_Orientation_Count_Log2 -- what it says. *
|
|
* PointGroupClass::Get_Frame_Row_Column_Count_Log2 -- what it says *
|
|
* PointGroupClass::Set_Frame_Row_Column_Count_Log2 -- what it says. *
|
|
* PointGroupClass::Get_Polygon_Count -- Get estimated polygon count. *
|
|
* PointGroupClass::Render -- draw point group. *
|
|
* PointGroupClass::vInstance -- Create instance of class. *
|
|
* PointGroupClass::sGetClassName -- Get name of class. *
|
|
* PointGroupClass::Update_Arrays -- Update all arrays used in rendering *
|
|
* PointGroupClass::Peek_Texture -- Peeks texture *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
#include "pointgr.h"
|
|
#include "vertmaterial.h"
|
|
#include "ww3d.h"
|
|
#include "aabox.h"
|
|
#include "statistics.h"
|
|
#include "simplevec.h"
|
|
#include "texture.h"
|
|
#include "vector.h"
|
|
#include "vp.h"
|
|
#include "matrix4.h"
|
|
#include "dx8wrapper.h"
|
|
#include "dx8vertexbuffer.h"
|
|
#include "dx8indexbuffer.h"
|
|
#include "rinfo.h"
|
|
#include "camera.h"
|
|
#include "dx8fvf.h"
|
|
#include "sortingrenderer.h"
|
|
|
|
// Upgraded to DX8 2/2/01 HY
|
|
|
|
// static data members
|
|
Vector3 PointGroupClass::_TriVertexLocationOrientationTable[256][3];
|
|
Vector3 PointGroupClass::_QuadVertexLocationOrientationTable[256][4];
|
|
Vector2 *PointGroupClass::_TriVertexUVFrameTable[5] = { NULL, NULL, NULL, NULL, NULL};
|
|
Vector2 *PointGroupClass::_QuadVertexUVFrameTable[5] = { NULL, NULL, NULL, NULL, NULL};
|
|
VertexMaterialClass *PointGroupClass::PointMaterial=NULL;
|
|
|
|
// This array has vertex locations for screenspace mode - calculated to cover exactly 1x1 and 2x2 pixels.
|
|
Vector3 PointGroupClass::_ScreenspaceVertexLocationSizeTable[2][3] =
|
|
{
|
|
Vector3(0.5f, 0.0f, -1.0f),
|
|
Vector3(1.0f, 1.0f, -1.0f),
|
|
Vector3(0.0f, 1.0f, -1.0f),
|
|
Vector3(1.0f, -0.5f, -1.0f),
|
|
Vector3(2.7f, 2.0f, -1.0f),
|
|
Vector3(-0.7f, 2.0f, -1.0f)
|
|
};
|
|
|
|
// Some internal variables
|
|
VectorClass<Vector3> VertexLoc; // camera-space vertex locations
|
|
VectorClass<Vector4> VertexDiffuse; // vertex diffuse/alpha colors
|
|
VectorClass<Vector2> VertexUV; // vertex texture coords
|
|
|
|
// Some DX 8 variables
|
|
#define MAX_VB_SIZE 1200
|
|
#define MAX_TRI_POINTS MAX_VB_SIZE/3
|
|
#define MAX_TRI_IB_SIZE 3*MAX_TRI_POINTS
|
|
#define MAX_QUAD_POINTS MAX_VB_SIZE/4
|
|
#define MAX_QUAD_IB_SIZE 6*MAX_QUAD_POINTS
|
|
|
|
DX8IndexBufferClass *Tris, *Quads; // Index buffers.
|
|
SortingIndexBufferClass *SortingTris, *SortingQuads; // Sorting index buffers.
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::PointGroupClass -- PointGroupClass CTor. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
PointGroupClass::PointGroupClass(void) :
|
|
PointLoc(NULL),
|
|
PointDiffuse(NULL),
|
|
APT(NULL),
|
|
PointSize(NULL),
|
|
PointOrientation(NULL),
|
|
PointFrame(NULL),
|
|
PointCount(0),
|
|
FrameRowColumnCountLog2(0),
|
|
Texture(NULL),
|
|
Flags(0),
|
|
Shader(ShaderClass::_PresetAdditiveSpriteShader),
|
|
PointMode(TRIS),
|
|
DefaultPointSize(0.0f),
|
|
DefaultPointColor(1.0f, 1.0f, 1.0f),
|
|
DefaultPointAlpha(1.0f),
|
|
DefaultPointOrientation(0),
|
|
DefaultPointFrame(0),
|
|
VPXMin(0.0f),
|
|
VPYMin(0.0f),
|
|
VPXMax(0.0f),
|
|
VPYMax(0.0f)
|
|
{
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::~PointGroupClass -- PointGroupClass DTor. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
PointGroupClass::~PointGroupClass(void)
|
|
{
|
|
if (PointLoc) {
|
|
PointLoc->Release_Ref();
|
|
PointLoc = NULL;
|
|
}
|
|
if (PointDiffuse) {
|
|
PointDiffuse->Release_Ref();
|
|
PointDiffuse=NULL;
|
|
}
|
|
if (APT) {
|
|
APT->Release_Ref();
|
|
APT = NULL;
|
|
}
|
|
if (PointSize) {
|
|
PointSize->Release_Ref();
|
|
PointSize = NULL;
|
|
}
|
|
if (PointOrientation) {
|
|
PointOrientation->Release_Ref();
|
|
PointOrientation = NULL;
|
|
}
|
|
if (PointFrame) {
|
|
PointFrame->Release_Ref();
|
|
PointFrame = NULL;
|
|
}
|
|
if (Texture) {
|
|
REF_PTR_RELEASE(Texture);
|
|
Texture = NULL;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::operator = -- PointGroupClass assignment operator. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
PointGroupClass & PointGroupClass::operator = (const PointGroupClass & that)
|
|
{
|
|
if (this != &that) {
|
|
WWASSERT(0); // If you hit this assert implement the function!
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Arrays -- Set point location/color/enable arrays. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* NOTES: colors, alphas, APT, sizes, orientations and frames are *
|
|
* optional. active_point_count can also be used with a NULL apt.*
|
|
* In this case active_point_count is ignored if it is -1 *
|
|
* (default value) and otherwise it indicates the first N active *
|
|
* points in the arrays. *
|
|
* The view plane rectangle may optionally be passed as well - *
|
|
* this is only used in SCREENSPACE mode. *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
* 08/25/1999 NH : Alphas added. *
|
|
* 06/28/2000 NH : Orientations and frames added. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Arrays(
|
|
ShareBufferClass<Vector3> *locs,
|
|
ShareBufferClass<Vector4> *diffuse,
|
|
ShareBufferClass<unsigned int> *apt,
|
|
ShareBufferClass<float> *sizes,
|
|
ShareBufferClass<unsigned char> *orientations,
|
|
ShareBufferClass<unsigned char> *frames,
|
|
int active_point_count,
|
|
float vpxmin,
|
|
float vpymin,
|
|
float vpxmax,
|
|
float vpymax)
|
|
{
|
|
// The point locations array is NOT optional!
|
|
WWASSERT(locs);
|
|
|
|
// Ensure lengths of all arrays are the same:
|
|
WWASSERT(!diffuse || locs->Get_Count() == diffuse->Get_Count());
|
|
WWASSERT(!apt || locs->Get_Count() == apt->Get_Count());
|
|
WWASSERT(!sizes || locs->Get_Count() == sizes->Get_Count());
|
|
WWASSERT(!orientations || locs->Get_Count() == orientations->Get_Count());
|
|
WWASSERT(!frames || locs->Get_Count() == frames->Get_Count());
|
|
|
|
REF_PTR_SET(PointLoc,locs);
|
|
REF_PTR_SET(PointDiffuse,diffuse);
|
|
REF_PTR_SET(APT,apt);
|
|
REF_PTR_SET(PointSize,sizes);
|
|
REF_PTR_SET(PointOrientation,orientations);
|
|
REF_PTR_SET(PointFrame,frames);
|
|
|
|
if (APT) {
|
|
PointCount = active_point_count;
|
|
} else {
|
|
PointCount = (active_point_count >= 0) ? active_point_count : PointLoc->Get_Count();
|
|
}
|
|
|
|
// Store view plane rectangle (only used in SCREENSPACE mode)
|
|
VPXMin = vpxmin;
|
|
VPYMin = vpymin;
|
|
VPXMax = vpxmax;
|
|
VPYMax = vpymax;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Point_Size -- Set default point size. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This size is ignored if a size array is present. *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Point_Size(float size)
|
|
{
|
|
DefaultPointSize = size;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Point_Size -- Get default point size. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This size is ignored if a size array is present. *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
float PointGroupClass::Get_Point_Size(void)
|
|
{
|
|
return DefaultPointSize;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Point_Color -- Set default point color. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This color is ignored if a color array is present. *
|
|
* *
|
|
* HISTORY: *
|
|
* 04/20/1999 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Point_Color(Vector3 color)
|
|
{
|
|
DefaultPointColor = color;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Point_Color -- Get default point color. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This color is ignored if a color array is present. *
|
|
* *
|
|
* HISTORY: *
|
|
* 04/20/1999 NH : Created. *
|
|
*========================================================================*/
|
|
Vector3 PointGroupClass::Get_Point_Color(void)
|
|
{
|
|
return DefaultPointColor;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Point_Alpha -- Set default point alpha. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This alpha is ignored if an alpha array is present. *
|
|
* *
|
|
* HISTORY: *
|
|
* 08/25/1999 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Point_Alpha(float alpha)
|
|
{
|
|
DefaultPointAlpha = alpha;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Point_Alpha -- Get default point alpha. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This alpha is ignored if an alpha array is present. *
|
|
* *
|
|
* HISTORY: *
|
|
* 08/25/1999 NH : Created. *
|
|
*========================================================================*/
|
|
float PointGroupClass::Get_Point_Alpha(void)
|
|
{
|
|
return DefaultPointAlpha;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Point_Orientation -- Set default point orientation*
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This is ignored if an orientation array is present. *
|
|
* *
|
|
* NOTE: No need to ensure value in valid range - it will be masked later.*
|
|
* *
|
|
* HISTORY: *
|
|
* 06/28/2000 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Point_Orientation(unsigned char orientation)
|
|
{
|
|
DefaultPointOrientation = orientation;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Point_Orientation -- Get default point orientation*
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This is ignored if an orientation array is present. *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/28/2000 NH : Created. *
|
|
*========================================================================*/
|
|
unsigned char PointGroupClass::Get_Point_Orientation(void)
|
|
{
|
|
return DefaultPointOrientation;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Point_Frame -- Set default point frame. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This frame is ignored if an frame array is present. *
|
|
* *
|
|
* NOTE: No need to ensure value in valid range - it will be masked later.*
|
|
* *
|
|
* HISTORY: *
|
|
* 06/28/2000 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Point_Frame(unsigned char frame)
|
|
{
|
|
DefaultPointFrame = frame;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Point_Frame -- Get default point frame. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: This frame is ignored if an frame array is present. *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/28/2000 NH : Created. *
|
|
*========================================================================*/
|
|
unsigned char PointGroupClass::Get_Point_Frame(void)
|
|
{
|
|
return DefaultPointFrame;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Point_Mode -- Set point rendering method. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Point_Mode(PointModeEnum mode)
|
|
{
|
|
PointMode = mode;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Point_Mode -- Get point rendering method. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
PointGroupClass::PointModeEnum PointGroupClass::Get_Point_Mode(void)
|
|
{
|
|
return PointMode;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* Set_Flag -- PointGroupClass::Set given flag to on or off. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Flag(FlagsType flag, bool onoff)
|
|
{
|
|
if (onoff) Flags|=1<<flag;
|
|
else
|
|
Flags&=~(1<<flag);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Flag -- Get current value (on/off) of given flag. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
int PointGroupClass::Get_Flag(FlagsType flag)
|
|
{
|
|
return (Flags>>flag) & 0x1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Texture -- Set texture used. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Texture(TextureClass* texture)
|
|
{
|
|
REF_PTR_SET(Texture,texture);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Texture -- Get texture used. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
TextureClass * PointGroupClass::Get_Texture(void)
|
|
{
|
|
if (Texture) Texture->Add_Ref();
|
|
return Texture;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PointGroupClass::Peek_Texture -- Peeks texture *
|
|
* *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 4/12/2001 hy : Created. *
|
|
*=============================================================================================*/
|
|
TextureClass * PointGroupClass::Peek_Texture(void)
|
|
{
|
|
return Texture;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Shader -- Set shader used. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: the primary gradient will be set to MODULATE/DISABLE in *
|
|
* the shader depending on whether a color or alpha array was *
|
|
* passed in Set_Point_Arrays. also, texturing will be *
|
|
* enabled or disabled dependent on whether a non-NULL *
|
|
* texture was set. *
|
|
* these will override the primary gradient/texturing *
|
|
* settings in the given shader. *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Shader(ShaderClass shader)
|
|
{
|
|
Shader = shader;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Shader -- Get shader used. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
ShaderClass PointGroupClass::Get_Shader(void)
|
|
{
|
|
return Shader;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Frame_Row_Column_Count_Log2 -- what it says *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/28/2000 NH : Created. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
unsigned char PointGroupClass::Get_Frame_Row_Column_Count_Log2(void)
|
|
{
|
|
return FrameRowColumnCountLog2;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Set_Frame_Row_Column_Count_Log2 -- what it says. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/28/2000 NH : Created. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
void PointGroupClass::Set_Frame_Row_Column_Count_Log2(unsigned char frccl2)
|
|
{
|
|
FrameRowColumnCountLog2 = MIN(frccl2, 4);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Get_Polygon_Count -- Get estimated polygon count. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/18/1998 NH : Created. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
int PointGroupClass::Get_Polygon_Count(void)
|
|
{
|
|
switch (PointMode) {
|
|
case TRIS:
|
|
case SCREENSPACE:
|
|
return PointCount;
|
|
break;
|
|
case QUADS:
|
|
return PointCount * 2;
|
|
break;
|
|
}
|
|
WWASSERT(0);
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Render -- draw point group. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/10/1998 NH : Created. *
|
|
* 02/08/2001 HY : Upgraded to DX8 *
|
|
*========================================================================*/
|
|
static SimpleVecClass<unsigned long> remap;
|
|
void PointGroupClass::Render(RenderInfoClass &rinfo)
|
|
{
|
|
// NB: the winding for pointgroups is wrong, but we
|
|
// are disabling culling for particles anyway
|
|
Shader.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
|
|
|
|
// If no points, do nothing:
|
|
if (PointCount == 0) return;
|
|
|
|
WWASSERT(PointLoc && PointLoc->Get_Array());
|
|
|
|
// Process texture reductions:
|
|
// if (Texture) Texture->Process_Reduction();
|
|
|
|
// Static arrays for intermediate calcs (never resized down, just up):
|
|
static VectorClass<Vector3> compressed_loc; // point locations 'compressed' by APT
|
|
static VectorClass<Vector4> compressed_diffuse; // point colors 'compressed' by APT
|
|
static VectorClass<float> compressed_size; // point sizes 'compressed' by APT
|
|
static VectorClass<unsigned char> compressed_orient; // point orientations 'compressed' by APT
|
|
static VectorClass<unsigned char> compressed_frame; // point frames 'compressed' by APT
|
|
static VectorClass<Vector3> transformed_loc; // transformed point locations
|
|
|
|
// Pointers which point into existing buffers (member or static):
|
|
Vector3 *current_loc = NULL;
|
|
Vector4 *current_diffuse = NULL;
|
|
float *current_size = NULL;
|
|
unsigned char *current_orient = NULL;
|
|
unsigned char *current_frame = NULL;
|
|
|
|
// If there is a color or alpha array enable gradient in shader - otherwise disable.
|
|
float value_255 = 0.9961f; //254 / 255
|
|
bool default_white_opaque = ( DefaultPointColor.X > value_255 &&
|
|
DefaultPointColor.Y > value_255 &&
|
|
DefaultPointColor.Z > value_255 &&
|
|
DefaultPointAlpha > value_255);
|
|
|
|
// The reason we check for lack of texture here is that SR seems to render black triangles
|
|
// rather than white triangles as would be expected) when there is no texture AND no gradient.
|
|
if (PointDiffuse || !default_white_opaque || !Texture) {
|
|
Shader.Set_Primary_Gradient(ShaderClass::GRADIENT_MODULATE);
|
|
} else {
|
|
Shader.Set_Primary_Gradient(ShaderClass::GRADIENT_DISABLE);
|
|
}
|
|
|
|
// If Texture is non-NULL enable texturing in shader - otherwise disable.
|
|
if (Texture) {
|
|
Shader.Set_Texturing(ShaderClass::TEXTURING_ENABLE);
|
|
} else {
|
|
Shader.Set_Texturing(ShaderClass::TEXTURING_DISABLE);
|
|
}
|
|
|
|
// If there is an active point table, use it to compress the point
|
|
// locations/colors/alphas/sizes/orientations/frames.
|
|
if (APT) {
|
|
// Resize compressed result arrays if needed (2x guardband to prevent
|
|
// frequent reallocations):
|
|
if (compressed_loc.Length() < PointCount) {
|
|
compressed_loc.Resize(PointCount * 2);
|
|
}
|
|
VectorProcessorClass::CopyIndexed(&compressed_loc[0],
|
|
PointLoc->Get_Array(), APT->Get_Array(), PointCount);
|
|
current_loc = &compressed_loc[0];
|
|
if (PointDiffuse) {
|
|
if (compressed_diffuse.Length() < PointCount) {
|
|
compressed_diffuse.Resize(PointCount * 2);
|
|
}
|
|
VectorProcessorClass::CopyIndexed(&compressed_diffuse[0],
|
|
PointDiffuse->Get_Array(), APT->Get_Array(), PointCount);
|
|
current_diffuse = &compressed_diffuse[0];
|
|
}
|
|
if (PointSize) {
|
|
if (compressed_size.Length() < PointCount) {
|
|
compressed_size.Resize(PointCount * 2);
|
|
}
|
|
VectorProcessorClass::CopyIndexed(&compressed_size[0],
|
|
PointSize->Get_Array(), APT->Get_Array(), PointCount);
|
|
current_size = &compressed_size[0];
|
|
}
|
|
if (PointOrientation) {
|
|
if (compressed_orient.Length() < PointCount) {
|
|
compressed_orient.Resize(PointCount * 2);
|
|
}
|
|
VectorProcessorClass::CopyIndexed(&compressed_orient[0],
|
|
PointOrientation->Get_Array(), APT->Get_Array(), PointCount);
|
|
current_orient = &compressed_orient[0];
|
|
}
|
|
if (PointFrame) {
|
|
if (compressed_frame.Length() < PointCount) {
|
|
compressed_frame.Resize(PointCount * 2);
|
|
}
|
|
VectorProcessorClass::CopyIndexed(&compressed_frame[0],
|
|
PointFrame->Get_Array(), APT->Get_Array(), PointCount);
|
|
current_frame = &compressed_frame[0];
|
|
}
|
|
} else {
|
|
current_loc = PointLoc->Get_Array();
|
|
if (PointDiffuse) {
|
|
current_diffuse = PointDiffuse->Get_Array();
|
|
}
|
|
if (PointSize) {
|
|
current_size = PointSize->Get_Array();
|
|
}
|
|
if (PointOrientation) {
|
|
current_orient = PointOrientation->Get_Array();
|
|
}
|
|
if (PointFrame) {
|
|
current_frame = PointFrame->Get_Array();
|
|
}
|
|
}
|
|
|
|
// Get the world and view matrices
|
|
Matrix4 view;
|
|
DX8Wrapper::Get_Transform(D3DTS_VIEW,view);
|
|
|
|
// Transform the point locations from worldspace to camera space if needed
|
|
// (i.e. if they are not already in camera space):
|
|
if (Get_Flag(TRANSFORM)) {
|
|
// Resize transformed location array if needed (2x guardband to prevent
|
|
// frequent reallocations):
|
|
if (transformed_loc.Length() < PointCount) {
|
|
transformed_loc.Resize(PointCount * 2);
|
|
}
|
|
|
|
// Not using vector processor class because we are discarding w
|
|
// Not using T&L in DX8 because we don't want DX8 to transform
|
|
// 3 times per particle when we can do it once
|
|
for (int i=0; i<PointCount; i++)
|
|
{
|
|
Vector4 result=view*current_loc[i];
|
|
transformed_loc[i].X=result.X;
|
|
transformed_loc[i].Y=result.Y;
|
|
transformed_loc[i].Z=result.Z;
|
|
}
|
|
current_loc = &transformed_loc[0];
|
|
} // if transform
|
|
|
|
// Update the arrays with the offsets.
|
|
int vnum, pnum;
|
|
|
|
Update_Arrays(current_loc, current_diffuse, current_size, current_orient, current_frame,
|
|
PointCount, PointLoc->Get_Count(), vnum, pnum);
|
|
|
|
// the locations are now in view space
|
|
// so set world and view matrices to identity and render
|
|
|
|
Matrix4 identity(true);
|
|
DX8Wrapper::Set_Transform(D3DTS_WORLD,identity);
|
|
DX8Wrapper::Set_Transform(D3DTS_VIEW,identity);
|
|
|
|
DX8Wrapper::Set_Material(PointMaterial);
|
|
DX8Wrapper::Set_Shader(Shader);
|
|
DX8Wrapper::Set_Texture(0,Texture);
|
|
|
|
// Enable sorting if the primitives are translucent and alpha testing is not enabled.
|
|
const bool sort = (Shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO) && (Shader.Get_Alpha_Test() == ShaderClass::ALPHATEST_DISABLE) && (WW3D::Is_Sorting_Enabled());
|
|
|
|
IndexBufferClass *indexbuffer;
|
|
int verticesperprimitive, current, delta;
|
|
|
|
if (PointMode == QUADS) {
|
|
verticesperprimitive = 2;
|
|
indexbuffer = sort ? static_cast <IndexBufferClass*> (SortingQuads) : static_cast <IndexBufferClass*> (Quads);
|
|
} else {
|
|
verticesperprimitive = 3;
|
|
indexbuffer = sort ? static_cast <IndexBufferClass*> (SortingTris) : static_cast <IndexBufferClass*> (Tris);
|
|
}
|
|
|
|
current = 0;
|
|
while (current<vnum)
|
|
{
|
|
delta=MIN(vnum-current,MAX_VB_SIZE);
|
|
DynamicVBAccessClass PointVerts (sort ? BUFFER_TYPE_DYNAMIC_SORTING : BUFFER_TYPE_DYNAMIC_DX8, dynamic_fvf_type, delta);
|
|
|
|
// Copy in the data to the VB
|
|
{
|
|
DynamicVBAccessClass::WriteLockClass Lock(&PointVerts);
|
|
int i;
|
|
unsigned char *vb=(unsigned char*)Lock.Get_Formatted_Vertex_Array();
|
|
const FVFInfoClass& fvfinfo=PointVerts.FVF_Info();
|
|
|
|
for (i = current; i < current + delta; i++)
|
|
{
|
|
// Copy Locations
|
|
*(Vector3*)(vb+fvfinfo.Get_Location_Offset())=VertexLoc[i];
|
|
if (current_diffuse) {
|
|
unsigned color=DX8Wrapper::Convert_Color_Clamp(VertexDiffuse[i]);
|
|
*(unsigned int*)(vb+fvfinfo.Get_Diffuse_Offset())=color;
|
|
}
|
|
else
|
|
*(unsigned int*)(vb+fvfinfo.Get_Diffuse_Offset())=
|
|
DX8Wrapper::Convert_Color_Clamp(Vector4(DefaultPointColor[0],DefaultPointColor[1],DefaultPointColor[2],DefaultPointAlpha));
|
|
*(Vector2*)(vb+fvfinfo.Get_Tex_Offset(0))=VertexUV[i];
|
|
vb+=fvfinfo.Get_FVF_Size();
|
|
}
|
|
} // copy
|
|
|
|
DX8Wrapper::Set_Index_Buffer (indexbuffer, 0);
|
|
DX8Wrapper::Set_Vertex_Buffer (PointVerts);
|
|
if (sort) {
|
|
SortingRendererClass::Insert_Triangles (0, delta / verticesperprimitive, 0, delta);
|
|
} else {
|
|
DX8Wrapper::Draw_Triangles (0, delta / verticesperprimitive, 0, delta);
|
|
}
|
|
|
|
current+=delta;
|
|
}
|
|
|
|
// restore the matrices
|
|
DX8Wrapper::Set_Transform(D3DTS_VIEW,view);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::Update_Arrays -- Update all arrays used in rendering *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 11/17/1998 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::Update_Arrays(
|
|
Vector3 *point_loc,
|
|
Vector4 *point_diffuse,
|
|
float *point_size,
|
|
unsigned char *point_orientation,
|
|
unsigned char *point_frame,
|
|
int active_points,
|
|
int total_points,
|
|
int &vnum,
|
|
int &pnum)
|
|
{
|
|
int verts_per_point = (PointMode == QUADS) ? 4 : 3;
|
|
int polys_per_point = (PointMode == QUADS) ? 2 : 1;
|
|
|
|
// total_vnum/pnum reflect the size of the point arrays passed to the
|
|
// point group. These (instead of vnum/pnum, which reflect the number of
|
|
// active points) are used for the resize logic - the idea is that these
|
|
// numbers will vary less often than the active numbers.
|
|
int total_vnum = verts_per_point * total_points;
|
|
vnum = verts_per_point * active_points;
|
|
pnum = polys_per_point * active_points;
|
|
|
|
// Resize the arrays if they are too small. We only need to check the length of one array
|
|
// since they always all have the same length.
|
|
if (VertexLoc.Length() < total_vnum) {
|
|
// Resize arrays (2x guardband to prevent frequent reallocations).
|
|
VertexLoc.Resize(total_vnum * 2, false);
|
|
VertexUV.Resize(total_vnum * 2, false);
|
|
VertexDiffuse.Resize(total_vnum * 2, false);
|
|
}
|
|
|
|
int vert, i, j;
|
|
|
|
/*
|
|
** Generate the vertex locations from the point locations (note that both are in camera space).
|
|
** Vertex locations depend on the point mode and the points' orientation and size
|
|
*/
|
|
|
|
// This defines the loop we run: the LSB indicates whether there is a size override array, the
|
|
// next bit indicates whether there is an orientation override array, and the higher bits
|
|
// indicate the point mode.
|
|
enum LoopSelectionEnum {
|
|
TRIS_NOSIZE_NOORIENT = ((int)TRIS << 2) + 0,
|
|
TRIS_SIZE_NOORIENT = ((int)TRIS << 2) + 1,
|
|
TRIS_NOSIZE_ORIENT = ((int)TRIS << 2) + 2,
|
|
TRIS_SIZE_ORIENT = ((int)TRIS << 2) + 3,
|
|
QUADS_NOSIZE_NOORIENT = ((int)QUADS << 2) + 0,
|
|
QUADS_SIZE_NOORIENT = ((int)QUADS << 2) + 1,
|
|
QUADS_NOSIZE_ORIENT = ((int)QUADS << 2) + 2,
|
|
QUADS_SIZE_ORIENT = ((int)QUADS << 2) + 3,
|
|
SCREEN_NOSIZE_NOORIENT = ((int)SCREENSPACE << 2) + 0,
|
|
SCREEN_SIZE_NOORIENT = ((int)SCREENSPACE << 2) + 1,
|
|
SCREEN_NOSIZE_ORIENT = ((int)SCREENSPACE << 2) + 2,
|
|
SCREEN_SIZE_ORIENT = ((int)SCREENSPACE << 2) + 3,
|
|
};
|
|
LoopSelectionEnum loop_sel = (LoopSelectionEnum)(((int)PointMode << 2) +
|
|
(point_orientation ? 2 : 0) + (point_size ? 1 : 0));
|
|
|
|
vert = 0;
|
|
Vector3 *vertex_loc = &VertexLoc[0];
|
|
|
|
switch (loop_sel) {
|
|
|
|
case TRIS_NOSIZE_NOORIENT:
|
|
{
|
|
// Setup constant vertex offsets (since size and orientation are invariants)
|
|
Vector3 scaled_offset[3];
|
|
scaled_offset[0] = _TriVertexLocationOrientationTable[DefaultPointOrientation][0] * DefaultPointSize;
|
|
scaled_offset[1] = _TriVertexLocationOrientationTable[DefaultPointOrientation][1] * DefaultPointSize;
|
|
scaled_offset[2] = _TriVertexLocationOrientationTable[DefaultPointOrientation][2] * DefaultPointSize;
|
|
|
|
// Add vertex offsets to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] + scaled_offset[0];
|
|
vertex_loc[vert + 1] = point_loc[i] + scaled_offset[1];
|
|
vertex_loc[vert + 2] = point_loc[i] + scaled_offset[2];
|
|
vert += 3;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TRIS_SIZE_NOORIENT:
|
|
{
|
|
// Scale vertex offsets and add them to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[DefaultPointOrientation][0] * point_size[i];
|
|
vertex_loc[vert + 1] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[DefaultPointOrientation][1] * point_size[i];
|
|
vertex_loc[vert + 2] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[DefaultPointOrientation][2] * point_size[i];
|
|
vert += 3;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TRIS_NOSIZE_ORIENT:
|
|
{
|
|
// Scale vertex offsets and add them to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[point_orientation[i]][0] * DefaultPointSize;
|
|
vertex_loc[vert + 1] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[point_orientation[i]][1] * DefaultPointSize;
|
|
vertex_loc[vert + 2] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[point_orientation[i]][2] * DefaultPointSize;
|
|
vert += 3;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TRIS_SIZE_ORIENT:
|
|
{
|
|
// Scale vertex offsets and add them to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[point_orientation[i]][0] * point_size[i];
|
|
vertex_loc[vert + 1] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[point_orientation[i]][1] * point_size[i];
|
|
vertex_loc[vert + 2] = point_loc[i] +
|
|
_TriVertexLocationOrientationTable[point_orientation[i]][2] * point_size[i];
|
|
vert += 3;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QUADS_NOSIZE_NOORIENT:
|
|
{
|
|
// Setup constant vertex offsets (since size and orientation are invariants)
|
|
Vector3 scaled_offset[4];
|
|
scaled_offset[0] = _QuadVertexLocationOrientationTable[DefaultPointOrientation][0] * DefaultPointSize;
|
|
scaled_offset[1] = _QuadVertexLocationOrientationTable[DefaultPointOrientation][1] * DefaultPointSize;
|
|
scaled_offset[2] = _QuadVertexLocationOrientationTable[DefaultPointOrientation][2] * DefaultPointSize;
|
|
scaled_offset[3] = _QuadVertexLocationOrientationTable[DefaultPointOrientation][3] * DefaultPointSize;
|
|
|
|
// Add vertex offsets to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] + scaled_offset[0];
|
|
vertex_loc[vert + 1] = point_loc[i] + scaled_offset[1];
|
|
vertex_loc[vert + 2] = point_loc[i] + scaled_offset[2];
|
|
vertex_loc[vert + 3] = point_loc[i] + scaled_offset[3];
|
|
vert += 4;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QUADS_SIZE_NOORIENT:
|
|
{
|
|
// Scale vertex offsets and add them to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[DefaultPointOrientation][0] * point_size[i];
|
|
vertex_loc[vert + 1] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[DefaultPointOrientation][1] * point_size[i];
|
|
vertex_loc[vert + 2] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[DefaultPointOrientation][2] * point_size[i];
|
|
vertex_loc[vert + 3] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[DefaultPointOrientation][3] * point_size[i];
|
|
vert += 4;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QUADS_NOSIZE_ORIENT:
|
|
{
|
|
// Scale vertex offsets and add them to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[point_orientation[i]][0] * DefaultPointSize;
|
|
vertex_loc[vert + 1] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[point_orientation[i]][1] * DefaultPointSize;
|
|
vertex_loc[vert + 2] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[point_orientation[i]][2] * DefaultPointSize;
|
|
vertex_loc[vert + 3] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[point_orientation[i]][3] * DefaultPointSize;
|
|
vert += 4;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QUADS_SIZE_ORIENT:
|
|
{
|
|
// Scale vertex offsets and add them to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[point_orientation[i]][0] * point_size[i];
|
|
vertex_loc[vert + 1] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[point_orientation[i]][1] * point_size[i];
|
|
vertex_loc[vert + 2] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[point_orientation[i]][2] * point_size[i];
|
|
vertex_loc[vert + 3] = point_loc[i] +
|
|
_QuadVertexLocationOrientationTable[point_orientation[i]][3] * point_size[i];
|
|
vert += 4;
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Orientations are ignored for screensize pointgroups
|
|
case SCREEN_NOSIZE_NOORIENT:
|
|
case SCREEN_NOSIZE_ORIENT:
|
|
{
|
|
// Offsets need to be scaled to the current screen resolution
|
|
|
|
// First find x and y scale factors (sizes in pixels need to be
|
|
// normalized to 2D cam viewplane of -1,-1 to 1,1)
|
|
int xres, yres, bitdepth;
|
|
bool windowed;
|
|
WW3D::Get_Render_Target_Resolution(xres, yres, bitdepth, windowed);
|
|
|
|
float x_scale = (VPXMax - VPXMin) / xres;
|
|
float y_scale = (VPYMax - VPYMin) / yres;
|
|
|
|
Vector3 scaled_locs[2][3];
|
|
for (int i = 0; i < 2; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
scaled_locs[i][j].X = _ScreenspaceVertexLocationSizeTable[i][j].X * x_scale;
|
|
scaled_locs[i][j].Y = _ScreenspaceVertexLocationSizeTable[i][j].Y * y_scale;
|
|
scaled_locs[i][j].Z = _ScreenspaceVertexLocationSizeTable[i][j].Z;
|
|
}
|
|
}
|
|
|
|
// Add vertex offsets to point locations to get vertex locations
|
|
int size_idx = (DefaultPointSize <= 1.0f) ? 0 : 1;
|
|
for (i = 0; i < active_points; i++) {
|
|
vertex_loc[vert + 0] = point_loc[i] + scaled_locs[size_idx][0];
|
|
vertex_loc[vert + 1] = point_loc[i] + scaled_locs[size_idx][1];
|
|
vertex_loc[vert + 2] = point_loc[i] + scaled_locs[size_idx][2];
|
|
vert += 3;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SCREEN_SIZE_NOORIENT:
|
|
case SCREEN_SIZE_ORIENT:
|
|
{
|
|
// Offsets need to be scaled to the current screen resolution
|
|
|
|
// First find x and y scale factors (sizes in pixels need to be
|
|
// normalized to 2D cam viewplane of -1,-1 to 1,1)
|
|
int xres, yres, bitdepth;
|
|
bool windowed;
|
|
WW3D::Get_Render_Target_Resolution(xres, yres, bitdepth, windowed);
|
|
|
|
float x_scale = (VPXMax - VPXMin) / xres;
|
|
float y_scale = (VPYMax - VPYMin) / yres;
|
|
|
|
Vector3 scaled_locs[2][3];
|
|
for (int i = 0; i < 2; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
scaled_locs[i][j].X = _ScreenspaceVertexLocationSizeTable[i][j].X * x_scale;
|
|
scaled_locs[i][j].Y = _ScreenspaceVertexLocationSizeTable[i][j].Y * y_scale;
|
|
scaled_locs[i][j].Z = _ScreenspaceVertexLocationSizeTable[i][j].Z;
|
|
}
|
|
}
|
|
|
|
// Add vertex offsets to point locations to get vertex locations
|
|
for (i = 0; i < active_points; i++) {
|
|
int size_idx = (point_size[i] <= 1.0f) ? 0 : 1;
|
|
vertex_loc[vert + 0] = point_loc[i] + scaled_locs[size_idx][0];
|
|
vertex_loc[vert + 1] = point_loc[i] + scaled_locs[size_idx][1];
|
|
vertex_loc[vert + 2] = point_loc[i] + scaled_locs[size_idx][2];
|
|
vert += 3;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
WWASSERT(0);
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
|
** Fill the UV vertex array
|
|
*/
|
|
|
|
unsigned int frame_mask = ~(0xFFFFFFFF << (FrameRowColumnCountLog2 + FrameRowColumnCountLog2));// To ensure frames in range
|
|
if (point_frame) {
|
|
|
|
// Fill UV array according to frame override array:
|
|
Vector2 *vertex_uv = &VertexUV[0];
|
|
if (PointMode != QUADS) {
|
|
// Modes with three vertices per point:
|
|
Vector2 *uv_ptr = _TriVertexUVFrameTable[FrameRowColumnCountLog2];
|
|
int vert = 0;
|
|
for (int i = 0; i < active_points; i++) {
|
|
int uv_idx = (point_frame[i] & frame_mask) * 3;
|
|
vertex_uv[vert++] = uv_ptr[uv_idx + 0];
|
|
vertex_uv[vert++] = uv_ptr[uv_idx + 1];
|
|
vertex_uv[vert++] = uv_ptr[uv_idx + 2];
|
|
}
|
|
} else {
|
|
// Modes with four vertices per point:
|
|
Vector2 *uv_ptr = _QuadVertexUVFrameTable[FrameRowColumnCountLog2];
|
|
int vert = 0;
|
|
for (int i = 0; i < active_points; i++) {
|
|
int uv_idx = (point_frame[i] & frame_mask) * 4;
|
|
vertex_uv[vert++] = uv_ptr[uv_idx + 0];
|
|
vertex_uv[vert++] = uv_ptr[uv_idx + 1];
|
|
vertex_uv[vert++] = uv_ptr[uv_idx + 2];
|
|
vertex_uv[vert++] = uv_ptr[uv_idx + 3];
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
// Fill UV array according to frame state:
|
|
Vector2 *vertex_uv = &VertexUV[0];
|
|
if (PointMode != QUADS) {
|
|
// Modes with three vertices per point:
|
|
Vector2 *uv_ptr = _TriVertexUVFrameTable[FrameRowColumnCountLog2] + ((DefaultPointFrame & frame_mask) * 3);
|
|
int vert = 0;
|
|
for (int i = 0; i < active_points; i++) {
|
|
vertex_uv[vert++] = uv_ptr[0];
|
|
vertex_uv[vert++] = uv_ptr[1];
|
|
vertex_uv[vert++] = uv_ptr[2];
|
|
}
|
|
} else {
|
|
// Modes with four vertices per point:
|
|
Vector2 *uv_ptr = _QuadVertexUVFrameTable[FrameRowColumnCountLog2] + ((DefaultPointFrame & frame_mask) * 4);
|
|
int vert = 0;
|
|
for (int i = 0; i < active_points; i++) {
|
|
vertex_uv[vert++] = uv_ptr[0];
|
|
vertex_uv[vert++] = uv_ptr[1];
|
|
vertex_uv[vert++] = uv_ptr[2];
|
|
vertex_uv[vert++] = uv_ptr[3];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
** If we have a point color array, fill the vertex diffuse array from it.
|
|
*/
|
|
vert = 0;
|
|
if (point_diffuse) {
|
|
Vector4* vertex_color = &VertexDiffuse[0];
|
|
for (i = 0; i < active_points; i++) {
|
|
for (j = 0; j < verts_per_point; j++) {
|
|
vertex_color[vert + j] = point_diffuse[i];
|
|
}
|
|
vert += verts_per_point;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::_Init -- Create static data. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/28/2000 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::_Init(void)
|
|
{
|
|
int i, j;
|
|
|
|
/*
|
|
** Fill vertex location orientation tables
|
|
*/
|
|
|
|
// Unrotated locations
|
|
Vector3 tri_locs[3] = {
|
|
Vector3(0.0f, -2.0f, 0.0f),
|
|
Vector3(-1.732f, 1.0f, 0.0f),
|
|
Vector3(1.732f, 1.0f, 0.0f)
|
|
};
|
|
Vector3 quad_locs[4] = {
|
|
Vector3(-0.5f, 0.5f, 0.0f),
|
|
Vector3(-0.5f, -0.5f, 0.0f),
|
|
Vector3(0.5f, -0.5f, 0.0f),
|
|
Vector3(0.5f, 0.5f, 0.0f)
|
|
};
|
|
|
|
float angle = 0.0f; // In radians
|
|
float angle_step = (WWMATH_PI * 2.0f) / 256.0f; // In radians
|
|
for (i = 0; i < 256; i++) {
|
|
float c = WWMath::Fast_Cos(angle);
|
|
float s = WWMath::Fast_Sin(angle);
|
|
for (j = 0; j < 3; j++) {
|
|
_TriVertexLocationOrientationTable[i][j].X = tri_locs[j].X * c - tri_locs[j].Y * s;
|
|
_TriVertexLocationOrientationTable[i][j].Y = tri_locs[j].X * s + tri_locs[j].Y * c;
|
|
_TriVertexLocationOrientationTable[i][j].Z = tri_locs[j].Z;
|
|
}
|
|
for (j = 0; j < 4; j++) {
|
|
_QuadVertexLocationOrientationTable[i][j].X = quad_locs[j].X * c - quad_locs[j].Y * s;
|
|
_QuadVertexLocationOrientationTable[i][j].Y = quad_locs[j].X * s + quad_locs[j].Y * c;
|
|
_QuadVertexLocationOrientationTable[i][j].Z = quad_locs[j].Z;
|
|
}
|
|
angle += angle_step;
|
|
}
|
|
|
|
/*
|
|
** Fill frame UV tables
|
|
*/
|
|
// Unscaled / untranslated UVs
|
|
Vector2 tri_uvs[3] = {
|
|
Vector2(0.5f, 0.0f),
|
|
Vector2(0.0f, 0.866f),
|
|
Vector2(1.0f, 0.866f)
|
|
};
|
|
Vector2 quad_uvs[4] = {
|
|
Vector2(0.0f, 0.0f),
|
|
Vector2(0.0f, 1.0f),
|
|
Vector2(1.0f, 1.0f),
|
|
Vector2(1.0f, 0.0f)
|
|
};
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
|
|
unsigned int rows = 1 << i;
|
|
unsigned int count = rows * rows;
|
|
|
|
Vector2 *tri_table = _TriVertexUVFrameTable[i] = new Vector2[count * 3];
|
|
Vector2 *quad_table = _QuadVertexUVFrameTable[i] = new Vector2[count * 4];
|
|
|
|
Vector2 corner(0.0f, 0.0f);
|
|
float scale = 1.0f / (float)rows;
|
|
|
|
int tri_idx = 0;
|
|
int quad_idx = 0;
|
|
for (unsigned int v = 0; v < rows; v++) {
|
|
for (unsigned int u = 0; u < rows; u++) {
|
|
|
|
tri_table[tri_idx++] = corner + (tri_uvs[0] * scale);
|
|
tri_table[tri_idx++] = corner + (tri_uvs[1] * scale);
|
|
tri_table[tri_idx++] = corner + (tri_uvs[2] * scale);
|
|
|
|
quad_table[quad_idx++] = corner + (quad_uvs[0] * scale);
|
|
quad_table[quad_idx++] = corner + (quad_uvs[1] * scale);
|
|
quad_table[quad_idx++] = corner + (quad_uvs[2] * scale);
|
|
quad_table[quad_idx++] = corner + (quad_uvs[3] * scale);
|
|
|
|
corner.X += scale;
|
|
}
|
|
corner.Y += scale;
|
|
corner.X = 0.0f;
|
|
}
|
|
}
|
|
|
|
// Create the IBs
|
|
Tris=NEW_REF(DX8IndexBufferClass,(MAX_TRI_IB_SIZE));
|
|
Quads=NEW_REF(DX8IndexBufferClass,(MAX_QUAD_IB_SIZE));
|
|
SortingTris=NEW_REF(SortingIndexBufferClass,(MAX_TRI_IB_SIZE));
|
|
SortingQuads=NEW_REF(SortingIndexBufferClass,(MAX_QUAD_IB_SIZE));
|
|
|
|
// Fill up the IBs
|
|
{
|
|
DX8IndexBufferClass::WriteLockClass locktris(Tris);
|
|
unsigned short *ib=locktris.Get_Index_Array();
|
|
for (i=0; i<MAX_TRI_IB_SIZE; i++) ib[i]=(unsigned short) i;
|
|
}
|
|
|
|
{
|
|
unsigned short vert=0;
|
|
DX8IndexBufferClass::WriteLockClass lockquads(Quads);
|
|
unsigned short *ib=lockquads.Get_Index_Array();
|
|
vert=0;
|
|
for (i=0; i<MAX_QUAD_IB_SIZE; i+=6)
|
|
{
|
|
ib[i]=vert;
|
|
ib[i+1]=vert+1;
|
|
ib[i+2]=vert+2;
|
|
|
|
ib[i+3]=vert+2;
|
|
ib[i+4]=vert+3;
|
|
ib[i+5]=vert;
|
|
vert+=4;
|
|
}
|
|
}
|
|
|
|
{
|
|
SortingIndexBufferClass::WriteLockClass locktris(SortingTris);
|
|
unsigned short *ib=locktris.Get_Index_Array();
|
|
for (i=0; i<MAX_TRI_IB_SIZE; i++) ib[i]=(unsigned short) i;
|
|
}
|
|
|
|
{
|
|
unsigned short vert=0;
|
|
SortingIndexBufferClass::WriteLockClass lockquads(SortingQuads);
|
|
unsigned short *ib=lockquads.Get_Index_Array();
|
|
vert=0;
|
|
for (i=0; i<MAX_QUAD_IB_SIZE; i+=6)
|
|
{
|
|
ib[i]=vert;
|
|
ib[i+1]=vert+1;
|
|
ib[i+2]=vert+2;
|
|
|
|
ib[i+3]=vert+2;
|
|
ib[i+4]=vert+3;
|
|
ib[i+5]=vert;
|
|
vert+=4;
|
|
}
|
|
}
|
|
|
|
PointMaterial=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PointGroupClass::_Shutdown -- Destroy static data. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/28/2000 NH : Created. *
|
|
*========================================================================*/
|
|
void PointGroupClass::_Shutdown(void)
|
|
{
|
|
for (int i = 0; i < 5; i++) {
|
|
delete [] _TriVertexUVFrameTable[i];
|
|
delete [] _QuadVertexUVFrameTable[i];
|
|
}
|
|
REF_PTR_RELEASE(PointMaterial);
|
|
REF_PTR_RELEASE(SortingQuads);
|
|
REF_PTR_RELEASE(SortingTris);
|
|
REF_PTR_RELEASE(Quads);
|
|
REF_PTR_RELEASE(Tris);
|
|
}
|
|
|
|
|