This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/wwphys/widgetuser.cpp

433 lines
12 KiB
C++
Raw Permalink Normal View History

/*
** 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