Files
firestorm/Gameleap/code/mw4/Libraries/mlr/MLRPrimitiveBase.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

654 lines
17 KiB
C++

#include "MLRHeaders.hpp"
Stuff::ReadOnlyArrayOf<BYTE> MidLevelRenderer::temp_lengths;
int clipTrick[6][2] =
{
{ 1, 1},
{ 1, 0},
{ 0, 1},
{ 0, 0},
{ 2, 0},
{ 2, 1}
};
//#############################################################################
//######################### ClipPolygon2 ############################
//#############################################################################
void ClipPolygon2::Init(int passes)
{
Verify(gos_GetCurrentHeap() == StaticHeap);
coords.SetLength(Limits::Max_Number_Vertices_Per_Polygon);
colors.SetLength(Limits::Max_Number_Vertices_Per_Polygon);
texCoords.SetLength(passes*Limits::Max_Number_Vertices_Per_Polygon);
clipPerVertex.SetLength(Limits::Max_Number_Vertices_Per_Polygon);
for(int i=0;i<MLRPrimitiveBase::MaxNumberOfExtraChannel;i++)
{
extraChannel[i].SetLength(Limits::Max_Number_Vertices_Per_Polygon);
}
}
void ClipPolygon2::Destroy()
{
coords.SetLength(0);
colors.SetLength(0);
texCoords.SetLength(0);
clipPerVertex.SetLength(0);
for(int i=0;i<MLRPrimitiveBase::MaxNumberOfExtraChannel;i++)
{
extraChannel[i].SetLength(0);
}
}
//#############################################################################
//######################### MLRPrimitiveBase ############################
//#############################################################################
MLRPrimitiveBase::ClassData*
MLRPrimitiveBase::DefaultData = NULL;
DynamicArrayOf<Vector4D>
*MLRPrimitiveBase::transformedCoords;
DynamicArrayOf<MLRClippingState>
*MLRPrimitiveBase::clipPerVertex;
DynamicArrayOf<Vector4D>
*MLRPrimitiveBase::clipExtraCoords;
DynamicArrayOf<Vector2DScalar>
*MLRPrimitiveBase::clipExtraTexCoords;
DynamicArrayOf<ColorType>
MLR_I_C_PMesh::clipExtraColors;
DynamicArrayOf<WORD>
*MLRPrimitiveBase::clipExtraLength;
ClipPolygon2
*MLRPrimitiveBase::clipBuffer;
DynamicArrayOf<BYTE>
*MLRPrimitiveBase::extraChannels[2*MaxNumberOfExtraChannel];
Scalar
MLRPrimitiveBase::fogTable[Limits::Max_Number_Of_FogStates][4];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::InitializeClass()
{
Verify(!DefaultData);
Verify(gos_GetCurrentHeap() == StaticHeap);
DefaultData =
new ClassData(
MLRPrimitiveBaseClassID,
"MidLevelRenderer::MLRPrimitiveBase",
RegisteredClass::DefaultData,
NULL
);
Register_Object(DefaultData);
transformedCoords = new DynamicArrayOf<Vector4D> (Limits::Max_Number_Vertices_Per_Mesh);
Register_Object(transformedCoords);
clipPerVertex = new DynamicArrayOf<MLRClippingState> (2*Limits::Max_Number_Vertices_Per_Mesh);
Register_Object(clipPerVertex);
clipExtraCoords = new DynamicArrayOf<Vector4D> (2*Limits::Max_Number_Vertices_Per_Mesh);
Register_Object(clipExtraCoords);
clipExtraTexCoords = new DynamicArrayOf<Vector2DScalar> (2*Limits::Max_Number_Vertices_Per_Mesh);
Register_Object(clipExtraTexCoords);
// start - fix for bug #5367
// array overwrite - extra channels only was set to Max_Number_Vertices_Per_Mesh, I doubled this number
// my buddy: Paul Tozour
clipExtraColors = new DynamicArrayOf<ColorType>(2*Limits::Max_Number_Vertices_Per_Mesh);
Register_Object(clipExtraColors);
clipExtraLength = new DynamicArrayOf<WORD> (2*Limits::Max_Number_Vertices_Per_Mesh);
Register_Object(clipExtraLength);
clipBuffer = new ClipPolygon2 [2];
Register_Pointer(clipBuffer);
clipBuffer[0].Init(Limits::Max_Number_Of_Multitextures);
clipBuffer[1].Init(Limits::Max_Number_Of_Multitextures);
for(int i=0;i<2*MLRPrimitiveBase::MaxNumberOfExtraChannel;i++)
{
extraChannels[i] = new DynamicArrayOf<BYTE> (2*Limits::Max_Number_Vertices_Per_Mesh);
Register_Pointer(extraChannels[i]);
}
// end - fix for bug #5367
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::TerminateClass()
{
for(int i=0;i<2*MLRPrimitiveBase::MaxNumberOfExtraChannel;i++)
{
Unregister_Object(extraChannels[i]);
delete extraChannels[i];
}
clipBuffer[1].Destroy();
clipBuffer[0].Destroy();
Unregister_Pointer(clipBuffer);
delete [] clipBuffer;
Unregister_Object(transformedCoords);
delete transformedCoords;
Unregister_Object(clipPerVertex);
delete clipPerVertex;
Unregister_Object(clipExtraCoords);
delete clipExtraCoords;
Unregister_Object(clipExtraTexCoords);
delete clipExtraTexCoords;
Unregister_Object(clipExtraColors);
delete clipExtraColors;
Unregister_Object(clipExtraLength);
delete clipExtraLength;
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPrimitiveBase::MLRPrimitiveBase(
ClassData *class_data,
MemoryStream *stream,
int version
):
RegisteredClass(class_data)
{
Check_Pointer(this);
Check_Object(stream);
dataStore = NULL;
switch(version)
{
case 1:
case 2:
{
STOP(("This class got created only after version 2 !"));
}
break;
default:
{
bool too_big = false;
MemoryStreamIO_Read(stream, &coords);
MemoryStreamIO_Read(stream, &texCoords);
if (coords.GetLength()>Limits::Max_Number_Vertices_Per_Mesh)
{
too_big = true;
coords.AssignData(coords.GetData(), Limits::Max_Number_Vertices_Per_Mesh);
texCoords.AssignData(texCoords.GetData(), Limits::Max_Number_Vertices_Per_Mesh);
}
if(version<15)
{
MemoryStreamIO_Read(stream, &temp_lengths);
int dMode;
*stream >> dMode;
drawMode = static_cast<BYTE>(dMode);
}
else
{
*stream >> drawMode;
temp_lengths.AssignData(NULL, 0);
}
gos_PushCurrentHeap(StatesHeap);
referenceState.Load(stream, version);
gos_PopCurrentHeap();
#if defined (_DEBUG) && 0
if(too_big == true)
{
MLRTexture *tex = (*MLRTexturePool::Instance)[&referenceState];
const char *tex_name = NULL;
if(tex!=NULL)
{
tex_name = tex->GetTextureName();
}
if(tex_name!=NULL)
{
PAUSE(("Mesh with texture \"%s\" currently loaded has more than %d vertices", tex_name, Limits::Max_Number_Vertices_Per_Mesh));
}
else
{
PAUSE(("Mesh currently loaded has more than %d vertices", Limits::Max_Number_Vertices_Per_Mesh));
}
}
#endif
}
break;
}
passes = 1;
referenceCount = 1;
channelUse = 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::Save(MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
*stream << GetClassID();
MemoryStreamIO_Write(stream, &coords);
MemoryStreamIO_Write(stream, &texCoords);
*stream << drawMode;
referenceState.Save(stream);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPrimitiveBase::MLRPrimitiveBase(ClassData *class_data):
RegisteredClass(class_data)
{
referenceState = 0;
state = 0;
passes = 1;
referenceCount = 1;
dataStore = new DataStorage;
channelUse = 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPrimitiveBase::~MLRPrimitiveBase()
{
Verify(referenceCount==0);
if (dataStore)
delete dataStore;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::InitializeDraw()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::InitializeDrawPrimitive(BYTE vis, int)
{
gos_vertices = NULL;
numGOSVertices = -1;
visible = vis;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::SetCoordData(
const Point3D *data,
int dataSize
)
{
Check_Object(this);
Check_Pointer(data);
Verify(texCoords.GetLength() == 0 || dataSize == texCoords.GetLength());
#if defined (MAX_NUMBER_VERTICES)
Verify(dataSize <= MAX_NUMBER_VERTICES);
#endif
coords.AssignData(data, dataSize);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::GetCoordData(
const Point3D **data,
int *dataSize
)
{
Check_Object(this);
*data = coords.GetData();
*dataSize = coords.GetLength();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::SetTexCoordData(
const Vector2DScalar *data,
int dataSize
)
{
Check_Object(this);
Check_Pointer(data);
Verify(coords.GetLength() == 0 || dataSize == coords.GetLength());
texCoords.AssignData((Vector2DScalar *)data, dataSize);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::GetTexCoordData(
const Vector2DScalar **data,
int *dataSize
)
{
Check_Object(this);
*data = texCoords.GetData();
*dataSize = texCoords.GetLength();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::Transform(Matrix4D *mat)
{
Check_Object(this);
MLR_RENDER("Transform::MLRPrimitiveBase");
Start_Timer(Transform_Time);
int i, len = coords.GetLength();
for(i=0;i<len;i++)
{
(*transformedCoords)[i].Multiply(coords[i], *mat);
}
#ifdef LAB_ONLY
Set_Statistic(TransformedVertices, TransformedVertices+len);
#endif
Stop_Timer(Transform_Time);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::SetFogTableEntry(
int entry,
Scalar fogNearClip,
Scalar fogFarClip,
Scalar fogDensity
)
{
Verify(fogFarClip>fogNearClip);
Verify(entry>0 && entry<=Limits::Max_Number_Of_FogStates);
#if FOG_HACK
GOSVertex::SetFogTableEntry(entry, fogNearClip, fogFarClip, fogDensity);
#endif
entry--;
Verify(entry>=0);
fogTable[entry][0] = fogNearClip;
fogTable[entry][1] = fogFarClip;
fogTable[entry][2] = fogDensity;
if(Close_Enough(fogFarClip, fogNearClip))
{
#if defined(LAB_ONLY)
PAUSE((0, "FogNearClip: %f and FogFarClip: %f too close to each other!", fogNearClip, fogFarClip));
#endif
fogTable[entry][3] = 1.0f/500.0f;
}
else
{
fogTable[entry][3] = 1.0f/(fogFarClip-fogNearClip);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::GetFogTableEntry(int entry, Stuff::Scalar * pfogNearClip, Stuff::Scalar * pfogFarClip, Stuff::Scalar * pfogDensity)
{
Verify(entry>0 && entry<=Limits::Max_Number_Of_FogStates);
entry--;
*pfogNearClip = fogTable[entry][0];
*pfogFarClip = fogTable[entry][1];
*pfogDensity = fogTable[entry][2];
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPrimitiveBase::GetExtend(Stuff::ExtentBox *box)
{
Check_Object(this);
Check_Object(box);
if(coords.GetLength()==0)
{
return;
}
box->minX = box->maxX = coords[0].x;
box->minY = box->maxY = coords[0].y;
box->minZ = box->maxZ = coords[0].z;
for(int i=0;i<coords.GetLength();i++)
{
if(coords[i].x < box->minX)
{
box->minX = coords[i].x;
}
if(coords[i].y < box->minY)
{
box->minY = coords[i].y;
}
if(coords[i].z < box->minZ)
{
box->minZ = coords[i].z;
}
if(coords[i].x > box->maxX)
{
box->maxX = coords[i].x;
}
if(coords[i].y > box->maxY)
{
box->maxY = coords[i].y;
}
if(coords[i].z > box->maxZ)
{
box->maxZ = coords[i].z;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
MLRPrimitiveBase::CastRay(
Line3D *line,
Normal3D *normal
)
{
Check_Object(this);
Check_Object(line);
Check_Pointer(normal);
STOP(("Not implemented"));
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRShape*
MidLevelRenderer::CreateIndexedIcosahedron(IcoInfo& icoInfo, Stuff::DynamicArrayOf<MLRState> *states)
{
switch(icoInfo.type)
{
case MLR_I_PMeshClassID:
return CreateIndexedIcosahedron_NoColor_NoLit(icoInfo, &(*states)[0]);
break;
case MLR_I_C_PMeshClassID:
return CreateIndexedIcosahedron_Color_NoLit(icoInfo, &(*states)[0]);
break;
case MLR_I_L_PMeshClassID:
return CreateIndexedIcosahedron_Color_Lit(icoInfo, &(*states)[0]);
break;
case MLR_I_DT_PMeshClassID:
return CreateIndexedIcosahedron_NoColor_NoLit_2Tex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_C_DT_PMeshClassID:
return CreateIndexedIcosahedron_Color_NoLit_2Tex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_L_DT_PMeshClassID:
return CreateIndexedIcosahedron_Color_Lit_2Tex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_DeT_PMeshClassID:
return CreateIndexedIcosahedron_NoColor_NoLit_DetTex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_C_DeT_PMeshClassID:
return CreateIndexedIcosahedron_Color_NoLit_DetTex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_L_DeT_PMeshClassID:
return CreateIndexedIcosahedron_Color_Lit_DetTex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_TMeshClassID:
return CreateIndexedTriIcosahedron_NoColor_NoLit(icoInfo, &(*states)[0]);
break;
case MLR_I_C_TMeshClassID:
return CreateIndexedTriIcosahedron_Color_NoLit(icoInfo, &(*states)[0]);
break;
case MLR_I_L_TMeshClassID:
return CreateIndexedTriIcosahedron_Color_Lit(icoInfo, &(*states)[0]);
break;
case MLR_I_DeT_TMeshClassID:
return CreateIndexedTriIcosahedron_NoColor_NoLit_DetTex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_C_DeT_TMeshClassID:
return CreateIndexedTriIcosahedron_Color_NoLit_DetTex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_L_DeT_TMeshClassID:
return CreateIndexedTriIcosahedron_Color_Lit_DetTex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_DT_TMeshClassID:
return CreateIndexedTriIcosahedron_NoColor_NoLit_2Tex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_C_DT_TMeshClassID:
return CreateIndexedTriIcosahedron_Color_NoLit_2Tex(icoInfo, &(*states)[0], &(*states)[1]);
break;
case MLR_I_L_DT_TMeshClassID:
return CreateIndexedTriIcosahedron_Color_Lit_2Tex(icoInfo, &(*states)[0], &(*states)[1]);
break;
}
return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
const char *
MidLevelRenderer::IcoInfo::GetTypeName()
{
switch(type)
{
case MLR_I_PMeshClassID:
return "not colored, unlit mesh";
break;
case MLR_I_C_PMeshClassID:
return "colored, unlit mesh";
break;
case MLR_I_L_PMeshClassID:
return "colored, lit mesh";
break;
case MLR_I_DT_PMeshClassID:
return "not colored, unlit mesh w/ 2 Tex";
break;
case MLR_I_C_DT_PMeshClassID:
return "colored, unlit mesh w/ 2 Tex";
break;
case MLR_I_L_DT_PMeshClassID:
return "colored, lit mesh w/ 2 Tex";
break;
case MLR_I_MT_PMeshClassID:
return "not colored, unlit mesh w/ 4 Tex";
break;
case MLR_I_DeT_PMeshClassID:
return "not colored, unlit mesh w/ DetTex";
break;
case MLR_I_C_DeT_PMeshClassID:
return "colored, unlit mesh w/ DetTex";
break;
case MLR_I_L_DeT_PMeshClassID:
return "colored, lit mesh w/ DetTex";
break;
case MLR_I_TMeshClassID:
return "not colored, unlit tri. mesh";
break;
case MLR_I_C_TMeshClassID:
return "colored, unlit tri. mesh";
break;
case MLR_I_L_TMeshClassID:
return "colored, lit tri. mesh";
break;
case MLR_I_DeT_TMeshClassID:
return "not colored, unlit tri. mesh w/ DetTex";
break;
case MLR_I_C_DeT_TMeshClassID:
return "colored, unlit tri. mesh w/ DetTex";
break;
case MLR_I_L_DeT_TMeshClassID:
return "colored, lit tri. mesh w/ DetTex";
break;
case MLR_I_DT_TMeshClassID:
return "not colored, unlit tri. mesh w/ 2 Tex";
break;
case MLR_I_C_DT_TMeshClassID:
return "colored, unlit tri. mesh w/ 2 Tex";
break;
case MLR_I_L_DT_TMeshClassID:
return "colored, lit tri. mesh w/ 2 Tex";
break;
}
return "mesh";
}
//#############################################################################
//##################### MLRPrimitiveBase__ClassData #####################
//#############################################################################
void
MLRPrimitiveBase__ClassData::TestInstance()
{
Verify(IsDerivedFrom(MLRPrimitiveBase::DefaultData));
}