/*
** Command & Conquer Generals(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 .
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: W3DDebugIcons.cpp ////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Heightmap.cpp
//
// Created: John Ahlquist, March 2002
//
// Desc: Draws huge numbers of debug icons for pathfinding quickly.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "W3DDevice/GameClient/W3DDebugIcons.h"
#include "Common/GlobalData.h"
#include "GameLogic/GameLogic.h"
#include "Common/MapObject.h"
#include "WW3D2/DX8Wrapper.h"
#if defined _DEBUG || defined _INTERNAL
// Texturing, no zbuffer, disabled zbuffer write, primary gradient, alpha blending
#define SC_OPAQUE ( SHADE_CNST(ShaderClass::PASS_ALWAYS, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_ONE, \
ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_DISABLE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
// Texturing, no zbuffer, disabled zbuffer write, primary gradient, alpha blending
#define SC_ALPHA ( SHADE_CNST(ShaderClass::PASS_ALWAYS, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, \
ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
// Texturing, no zbuffer, disabled zbuffer write, primary gradient, alpha blending
#define SC_ALPHA_Z ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
// Texturing, no zbuffer, disabled zbuffer write, primary gradient, alpha blending
#define SC_OPAQUE_Z ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_ONE, \
ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_DISABLE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
void addIcon(const Coord3D *pos, Real width, Int numFramesDuration, RGBColor color)
{
W3DDebugIcons::addIcon(pos, width, numFramesDuration, color);
}
struct DebugIcon {
Coord3D position;
Real width; // all are squares centered about pos.
RGBColor color;
Int endFrame; // Frame when this disappears.
};
DebugIcon *W3DDebugIcons::m_debugIcons = NULL;
Int W3DDebugIcons::m_numDebugIcons = 0;
W3DDebugIcons::~W3DDebugIcons(void)
{
REF_PTR_RELEASE(m_vertexMaterialClass);
if (m_debugIcons) delete m_debugIcons;
m_debugIcons = NULL;
m_numDebugIcons = 0;
}
W3DDebugIcons::W3DDebugIcons(void)
{
//go with a preset material for now.
m_vertexMaterialClass=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
allocateIconsArray();
}
bool W3DDebugIcons::Cast_Ray(RayCollisionTestClass & raytest)
{
return false;
}
//@todo: MW Handle both of these properly!!
W3DDebugIcons::W3DDebugIcons(const W3DDebugIcons & src)
{
*this = src;
}
W3DDebugIcons & W3DDebugIcons::operator = (const W3DDebugIcons & that)
{
DEBUG_CRASH(("oops"));
return *this;
}
void W3DDebugIcons::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
{
Vector3 ObjSpaceCenter(TheGlobalData->m_waterExtentX,TheGlobalData->m_waterExtentY,50*MAP_XY_FACTOR);
float length = ObjSpaceCenter.Length();
sphere.Init(ObjSpaceCenter, length);
}
void W3DDebugIcons::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
{
Vector3 minPt(-2*TheGlobalData->m_waterExtentX,-2*TheGlobalData->m_waterExtentY,0);
Vector3 maxPt(2*TheGlobalData->m_waterExtentX,2*TheGlobalData->m_waterExtentY,100*MAP_XY_FACTOR);
box.Init(minPt,maxPt);
}
Int W3DDebugIcons::Class_ID(void) const
{
return RenderObjClass::CLASSID_UNKNOWN;
}
RenderObjClass * W3DDebugIcons::Clone(void) const
{
return NEW W3DDebugIcons(*this); // poolify
}
void W3DDebugIcons::allocateIconsArray(void)
{
m_debugIcons = NEW DebugIcon[MAX_ICONS];
m_numDebugIcons = 0;
}
void W3DDebugIcons::compressIconsArray(void)
{
if (m_debugIcons && m_numDebugIcons > 0) {
Int newNum = 0;
Int i;
for (i=0; i= TheGameLogic->getFrame() && i>newNum) {
m_debugIcons[newNum] = m_debugIcons[i];
newNum++;
}
}
m_numDebugIcons = newNum;
}
}
static Int maxIcons = 0;
void W3DDebugIcons::addIcon(const Coord3D *pos, Real width, Int numFramesDuration, RGBColor color)
{
if (pos==NULL) {
if (m_numDebugIcons > maxIcons) {
DEBUG_LOG(("Max icons %d\n", m_numDebugIcons));
maxIcons = m_numDebugIcons;
}
m_numDebugIcons = 0;
return;
}
if (m_numDebugIcons>= MAX_ICONS) return;
if (m_debugIcons==NULL) return;
m_debugIcons[m_numDebugIcons].position = *pos;
m_debugIcons[m_numDebugIcons].width = width;
m_debugIcons[m_numDebugIcons].color = color;
m_debugIcons[m_numDebugIcons].endFrame = TheGameLogic->getFrame()+numFramesDuration;
m_numDebugIcons++;
}
/** Render draws into the current 3d context. */
void W3DDebugIcons::Render(RenderInfoClass & rinfo)
{
//
if (WW3D::Are_Static_Sort_Lists_Enabled()) {
WW3D::Add_To_Static_Sort_List(this, 1);
return;
}
//
Bool anyVanished = false;
if (m_numDebugIcons==0) return;
DX8Wrapper::Apply_Render_State_Changes();
DX8Wrapper::Set_Material(m_vertexMaterialClass);
DX8Wrapper::Set_Texture(0, NULL);
DX8Wrapper::Apply_Render_State_Changes();
Matrix3D tm(Transform);
DX8Wrapper::Set_Transform(D3DTS_WORLD,tm);
Int numRect = m_numDebugIcons;
static Real offset = 30;
const Int MAX_RECT = 5000; // cap drawing n rects.
if (numRect > MAX_RECT) numRect = MAX_RECT;
offset+= 0.5f;
Int k;
for (k=0; kgetFrame();
if (framesLeft < 1) {
anyVanished = true;
continue;
}
if (framesLeftx= pt1.x-halfWidth;
vb->y= pt1.y-halfWidth;
vb->z= pt1.z;
vb->diffuse=diffuse; // b g<<8 r<<16 a<<24.
vb->u1=0 ;
vb->v1=0 ;
vb++;
vb->x= pt1.x+halfWidth;
vb->y= pt1.y-halfWidth;
vb->z= pt1.z;
vb->diffuse=diffuse; // b g<<8 r<<16 a<<24.
vb->u1=0 ;
vb->v1=0 ;
vb++;
vb->x= pt1.x+halfWidth;
vb->y= pt1.y+halfWidth;
vb->z= pt1.z;
vb->diffuse=diffuse; // b g<<8 r<<16 a<<24.
vb->u1=0 ;
vb->v1=0 ;
vb++;
vb->x= pt1.x-halfWidth;
vb->y= pt1.y+halfWidth;
vb->z= pt1.z;
vb->diffuse=diffuse; // b g<<8 r<<16 a<<24.
vb->u1=0 ;
vb->v1=0 ;
vb++;
*curIb++ = numVertex;
*curIb++ = numVertex+1;
*curIb++ = numVertex+2;
*curIb++ = numVertex;
*curIb++ = numVertex+2;
*curIb++ = numVertex+3;
curIndex += 6;
numVertex += 4;
}
}
if (numVertex == 0) break;
DX8Wrapper::Set_Shader(ShaderClass(SC_ALPHA));
DX8Wrapper::Set_Index_Buffer(ib_access,0);
DX8Wrapper::Set_Vertex_Buffer(vb_access);
DX8Wrapper::Draw_Triangles( 0,curIndex/3, 0, numVertex); //draw a quad, 2 triangles, 4 verts
}
if (anyVanished) {
compressIconsArray();
}
}
#endif // _DEBUG or _INTERNAL