433 lines
12 KiB
C++
433 lines
12 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 : WWPhys *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/wwphys/widgetuser.cpp $*
|
||
|
* *
|
||
|
* Author:: Greg Hjelstrom *
|
||
|
* *
|
||
|
* $Modtime:: 10/11/01 2:29p $*
|
||
|
* *
|
||
|
* $Revision:: 5 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
|
||
|
#include "widgetuser.h"
|
||
|
#include "widgets.h"
|
||
|
#include "mempool.h"
|
||
|
#include "vertmaterial.h"
|
||
|
#include "matinfo.h"
|
||
|
#include "boxrobj.h"
|
||
|
#include "ww3d.h"
|
||
|
|
||
|
|
||
|
/*
|
||
|
** WidgetRenderOpClass
|
||
|
** This class encapsulates the instructions from a physics object to render
|
||
|
** a debug widget. Each physics object has a list of these hanging off it
|
||
|
** for rendering vectors, points, etc.
|
||
|
** Since instances of this class are constantly allocated and deallocated
|
||
|
** each frame they are derived from AutoPoolClass.
|
||
|
*/
|
||
|
class WidgetRenderOpClass : public AutoPoolClass<WidgetRenderOpClass,256>
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
WidgetRenderOpClass(void);
|
||
|
|
||
|
void Set_Color(const Vector3 & color);
|
||
|
void Set_Opacity(float opacity);
|
||
|
void Init_Point(const Vector3 & point);
|
||
|
void Init_Vector(const Vector3 & point,const Vector3 & vector);
|
||
|
void Init_AABox(const AABoxClass & box);
|
||
|
void Init_OBBox(const OBBoxClass & box);
|
||
|
void Init_Coord_Axes(const Matrix3D & tm);
|
||
|
|
||
|
void Render(RenderInfoClass & rinfo);
|
||
|
|
||
|
void Set_Next(WidgetRenderOpClass * next) { Next = next; }
|
||
|
WidgetRenderOpClass * Get_Next(void) { return Next; }
|
||
|
|
||
|
protected:
|
||
|
|
||
|
void render_point(RenderInfoClass & rinfo);
|
||
|
void render_vector(RenderInfoClass & rinfo);
|
||
|
void render_aabox(RenderInfoClass & rinfo);
|
||
|
void render_obbox(RenderInfoClass & rinfo);
|
||
|
void render_axes(RenderInfoClass & rinfo);
|
||
|
|
||
|
enum { RENDER_NONE = 0, RENDER_POINT, RENDER_VECTOR, RENDER_AABOX, RENDER_OBBOX, RENDER_AXES };
|
||
|
|
||
|
int RenderOp;
|
||
|
Vector3 Color;
|
||
|
float Opacity;
|
||
|
|
||
|
Vector3 V0; // these are all re-used depending on the render op
|
||
|
Vector3 V1;
|
||
|
Vector3 V2;
|
||
|
Matrix3D Transform;
|
||
|
|
||
|
WidgetRenderOpClass * Next;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
** declare the instance of the pool object for all WidgetRenderOpClass's
|
||
|
*/
|
||
|
DEFINE_AUTO_POOL(WidgetRenderOpClass,256);
|
||
|
|
||
|
|
||
|
/*******************************************
|
||
|
**
|
||
|
** WidgetRenderOpClass Implementation
|
||
|
**
|
||
|
*******************************************/
|
||
|
WidgetRenderOpClass::WidgetRenderOpClass(void) :
|
||
|
RenderOp(RENDER_NONE),
|
||
|
Next(NULL)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::Set_Color(const Vector3 & color)
|
||
|
{
|
||
|
Color = color;
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::Set_Opacity(float opacity)
|
||
|
{
|
||
|
Opacity = opacity;
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::Init_Point(const Vector3 & p0)
|
||
|
{
|
||
|
RenderOp = RENDER_POINT;
|
||
|
V0 = p0;
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::Init_Vector(const Vector3 & point,const Vector3 & vector)
|
||
|
{
|
||
|
RenderOp = RENDER_VECTOR;
|
||
|
V0 = point;
|
||
|
V1 = vector;
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::Init_AABox(const AABoxClass & box)
|
||
|
{
|
||
|
RenderOp = RENDER_AABOX;
|
||
|
V0 = box.Center;
|
||
|
V1 = box.Extent;
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::Init_OBBox(const OBBoxClass & box)
|
||
|
{
|
||
|
RenderOp = RENDER_OBBOX;
|
||
|
V0 = Vector3(0,0,0);
|
||
|
V1 = box.Extent;
|
||
|
Transform.Set(box.Basis,box.Center);
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::Init_Coord_Axes(const Matrix3D & tm)
|
||
|
{
|
||
|
RenderOp = RENDER_AXES;
|
||
|
Transform = tm;
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::Render(RenderInfoClass & rinfo)
|
||
|
{
|
||
|
switch(RenderOp)
|
||
|
{
|
||
|
case RENDER_NONE:
|
||
|
break;
|
||
|
case RENDER_POINT:
|
||
|
render_point(rinfo);
|
||
|
break;
|
||
|
case RENDER_VECTOR:
|
||
|
render_vector(rinfo);
|
||
|
break;
|
||
|
case RENDER_AABOX:
|
||
|
render_aabox(rinfo);
|
||
|
break;
|
||
|
case RENDER_OBBOX:
|
||
|
render_obbox(rinfo);
|
||
|
break;
|
||
|
case RENDER_AXES:
|
||
|
render_axes(rinfo);
|
||
|
break;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::render_point(RenderInfoClass & rinfo)
|
||
|
{
|
||
|
#ifdef WWDEBUG
|
||
|
// Get the point model
|
||
|
RenderObjClass * model = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_POINT);
|
||
|
if (model == NULL) return;
|
||
|
if (model->Class_ID() != RenderObjClass::CLASSID_MESH) {
|
||
|
model->Release_Ref();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Set its color
|
||
|
MaterialInfoClass * matinfo = model->Get_Material_Info();
|
||
|
if (matinfo) {
|
||
|
VertexMaterialClass * vmat = matinfo->Peek_Vertex_Material(0);
|
||
|
if (vmat) {
|
||
|
vmat->Set_Emissive(Color);
|
||
|
}
|
||
|
matinfo->Release_Ref();
|
||
|
}
|
||
|
|
||
|
// Render it
|
||
|
model->Set_Transform(Matrix3D(V0));
|
||
|
model->Render(rinfo);
|
||
|
model->Release_Ref();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::render_vector(RenderInfoClass & rinfo)
|
||
|
{
|
||
|
#ifdef WWDEBUG
|
||
|
if (V1.Length2() < WWMATH_EPSILON) return;
|
||
|
|
||
|
RenderObjClass * vecmodel = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_VECTOR);
|
||
|
if (vecmodel) {
|
||
|
|
||
|
// set the color, the vector model is a skin so we have to get the
|
||
|
// first sub-object, get its material info, then get the first vertex material
|
||
|
RenderObjClass * subobj = vecmodel->Get_Sub_Object(0);
|
||
|
if (subobj) {
|
||
|
MaterialInfoClass * matinfo = subobj->Get_Material_Info();
|
||
|
if (matinfo) {
|
||
|
VertexMaterialClass * vmat = matinfo->Peek_Vertex_Material(0);
|
||
|
if (vmat) {
|
||
|
vmat->Set_Emissive(Color);
|
||
|
}
|
||
|
matinfo->Release_Ref();
|
||
|
}
|
||
|
subobj->Release_Ref();
|
||
|
}
|
||
|
|
||
|
// set the transform to be at p0, pointing -z at p1
|
||
|
Matrix3D tm0;
|
||
|
Matrix3D tm1(1);
|
||
|
tm0.Look_At(V0,V0+V1,0.0f); // point -z from pt along vec
|
||
|
tm1.Translate(Vector3(0,0,1.0f - V1.Length())); // p1 is along -z (Point1 starts at -1)
|
||
|
vecmodel->Set_Transform(tm0);
|
||
|
|
||
|
// set bone "Point1" to be at p1
|
||
|
int p1index = vecmodel->Get_Bone_Index("Point1");
|
||
|
vecmodel->Capture_Bone(p1index);
|
||
|
vecmodel->Control_Bone(p1index,tm1);
|
||
|
|
||
|
vecmodel->Render(rinfo);
|
||
|
vecmodel->Release_Ref();
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::render_aabox(RenderInfoClass & rinfo)
|
||
|
{
|
||
|
#ifdef WWDEBUG
|
||
|
RenderObjClass * model = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_AABOX);
|
||
|
if (model == NULL) return;
|
||
|
if (model->Class_ID() != RenderObjClass::CLASSID_AABOX) {
|
||
|
model->Release_Ref();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// force this box to get rendered (bypass the built in collision bit masking)
|
||
|
int oldmask = WW3D::Get_Collision_Box_Display_Mask();
|
||
|
int newmask = oldmask | 0x01;
|
||
|
WW3D::Set_Collision_Box_Display_Mask(newmask);
|
||
|
|
||
|
AABoxRenderObjClass * boxmodel = (AABoxRenderObjClass *)model;
|
||
|
boxmodel->Set_Local_Center_Extent(V0,V1);
|
||
|
boxmodel->Set_Transform(Matrix3D(1));
|
||
|
boxmodel->Set_Color(Color);
|
||
|
boxmodel->Set_Opacity(Opacity);
|
||
|
boxmodel->Render(rinfo);
|
||
|
boxmodel->Release_Ref();
|
||
|
|
||
|
// restore the old mask
|
||
|
WW3D::Set_Collision_Box_Display_Mask(oldmask);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::render_obbox(RenderInfoClass & rinfo)
|
||
|
{
|
||
|
#ifdef WWDEBUG
|
||
|
RenderObjClass * model = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_OBBOX);
|
||
|
if (model == NULL) return;
|
||
|
if (model->Class_ID() != RenderObjClass::CLASSID_OBBOX) {
|
||
|
model->Release_Ref();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// force this box to get rendered (bypass the built in collision bit masking)
|
||
|
int oldmask = WW3D::Get_Collision_Box_Display_Mask();
|
||
|
int newmask = oldmask | 0x01;
|
||
|
WW3D::Set_Collision_Box_Display_Mask(newmask);
|
||
|
|
||
|
OBBoxRenderObjClass * boxmodel = (OBBoxRenderObjClass *)model;
|
||
|
boxmodel->Set_Collision_Type(0xFF);
|
||
|
boxmodel->Set_Transform(Transform);
|
||
|
boxmodel->Set_Local_Center_Extent(V0,V1);
|
||
|
boxmodel->Set_Color(Color);
|
||
|
boxmodel->Set_Opacity(Opacity);
|
||
|
boxmodel->Render(rinfo);
|
||
|
boxmodel->Release_Ref();
|
||
|
|
||
|
// restore the old mask
|
||
|
WW3D::Set_Collision_Box_Display_Mask(oldmask);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void WidgetRenderOpClass::render_axes(RenderInfoClass & rinfo)
|
||
|
{
|
||
|
#ifdef WWDEBUG
|
||
|
RenderObjClass * model = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_AXES);
|
||
|
if (model == NULL) return;
|
||
|
if (model->Class_ID() != RenderObjClass::CLASSID_MESH) {
|
||
|
model->Release_Ref();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
model->Set_Transform(Transform);
|
||
|
model->Render(rinfo);
|
||
|
model->Release_Ref();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************
|
||
|
**
|
||
|
** WidgetUserClass Implementation
|
||
|
**
|
||
|
*******************************************/
|
||
|
WidgetUserClass::WidgetUserClass(void)
|
||
|
{
|
||
|
#ifdef WWDEBUG
|
||
|
WidgetRenderOpList = NULL;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
WidgetUserClass::~WidgetUserClass(void)
|
||
|
{
|
||
|
Reset_Debug_Widget_List();
|
||
|
}
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
void WidgetUserClass::Reset_Debug_Widget_List(void)
|
||
|
{
|
||
|
WidgetRenderOpClass * op = WidgetRenderOpList;
|
||
|
while (op) {
|
||
|
WidgetRenderOpClass * nextop = op->Get_Next();
|
||
|
delete op;
|
||
|
op = nextop;
|
||
|
}
|
||
|
WidgetRenderOpList = NULL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
void WidgetUserClass::Add_Debug_Widget(WidgetRenderOpClass * op)
|
||
|
{
|
||
|
WWASSERT(op->Get_Next() == NULL);
|
||
|
op->Set_Next(WidgetRenderOpList);
|
||
|
WidgetRenderOpList = op;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
void WidgetUserClass::Add_Debug_Point(const Vector3 & p,const Vector3 & color)
|
||
|
{
|
||
|
WidgetRenderOpClass * op = new WidgetRenderOpClass;
|
||
|
op->Set_Color(color);
|
||
|
op->Init_Point(p);
|
||
|
Add_Debug_Widget(op);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
void WidgetUserClass::Add_Debug_Vector(const Vector3 & p,const Vector3 & v,const Vector3 & color)
|
||
|
{
|
||
|
if (v.Length2() > 0.0f) {
|
||
|
WidgetRenderOpClass * op = new WidgetRenderOpClass;
|
||
|
op->Set_Color(color);
|
||
|
op->Init_Vector(p,v);
|
||
|
Add_Debug_Widget(op);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
void WidgetUserClass::Add_Debug_AABox(const AABoxClass & box,const Vector3 & color,float opacity)
|
||
|
{
|
||
|
WidgetRenderOpClass * op = new WidgetRenderOpClass;
|
||
|
op->Set_Color(color);
|
||
|
op->Set_Opacity(opacity);
|
||
|
op->Init_AABox(box);
|
||
|
Add_Debug_Widget(op);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
void WidgetUserClass::Add_Debug_OBBox(const OBBoxClass & box,const Vector3 & color,float opacity)
|
||
|
{
|
||
|
WidgetRenderOpClass * op = new WidgetRenderOpClass;
|
||
|
op->Set_Color(color);
|
||
|
op->Set_Opacity(opacity);
|
||
|
op->Init_OBBox(box);
|
||
|
Add_Debug_Widget(op);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
void WidgetUserClass::Add_Debug_Axes(const Matrix3D & transform,const Vector3 & color)
|
||
|
{
|
||
|
WidgetRenderOpClass * op = new WidgetRenderOpClass;
|
||
|
op->Set_Color(color);
|
||
|
op->Init_Coord_Axes(transform);
|
||
|
Add_Debug_Widget(op);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
void WidgetUserClass::Render_Debug_Widgets(RenderInfoClass & rinfo)
|
||
|
{
|
||
|
WW3D::Flush(rinfo);
|
||
|
|
||
|
WidgetRenderOpClass * op = WidgetRenderOpList;
|
||
|
while (op) {
|
||
|
op->Render(rinfo);
|
||
|
op = op->Get_Next();
|
||
|
WW3D::Flush(rinfo);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|