📄 mlrpolymesh.cpp
字号:
//===========================================================================//
// Copyright (C) Microsoft Corporation. All rights reserved. //
//===========================================================================//
#include "MLRHeaders.hpp"
#include "OwnTrace.hpp"
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
BitTrace *MLRPolyMesh_Clip;
#define SET_MLRPOLYMESH_CLIP() MLRPolyMesh_Clip->Set()
#define CLEAR_MLRPOLYMESH_CLIP() MLRPolyMesh_Clip->Clear()
#else
#define SET_MLRPOLYMESH_CLIP()
#define CLEAR_MLRPOLYMESH_CLIP()
#endif
OwnTrace *clipTrace;
//#############################################################################
//############################### MLRPolyMesh ##################################
//#############################################################################
MLRPolyMesh::ClassData*
MLRPolyMesh::DefaultData = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
MLRPolyMeshClassID,
"MidLevelRenderer::MLRPolyMesh",
MLRPrimitive::DefaultData,
(MLRPrimitive::Factory)&Make
);
Register_Object(DefaultData);
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
MLRPolyMesh_Clip = new BitTrace("MLRPolyMesh_Clip");
Register_Object(MLRPolyMesh_Clip);
#endif
clipTrace = new OwnTrace("Clip Timing");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
Unregister_Object(MLRPolyMesh_Clip);
delete MLRPolyMesh_Clip;
#endif
clipTrace->Print();
delete clipTrace;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPolyMesh::MLRPolyMesh(
MemoryStream *stream,
int version
) :
MLRPrimitive(DefaultData, stream, version)
{
Check_Pointer(this);
Check_Pointer(stream);
facePlanes.SetLength(GetNumPrimitives());
testList.SetLength(GetNumPrimitives());
FindFacePlanes();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPolyMesh::MLRPolyMesh():
MLRPrimitive(DefaultData)
{
Check_Pointer(this);
drawMode = SortData::TriList;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPolyMesh::~MLRPolyMesh()
{
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPolyMesh*
MLRPolyMesh::Make(
MemoryStream *stream,
int version
)
{
return new MLRPolyMesh(stream, version);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::Save(MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
MLRPrimitive::Save(stream);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::SetPrimitiveLength (unsigned char *data, int numPrimitives)
{
Check_Object(this);
lengths.AssignData(data, numPrimitives);
facePlanes.SetLength(numPrimitives);
testList.SetLength(numPrimitives);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::GetPrimitiveLength (unsigned char **data, int *l)
{
Check_Object(this);
*l = lengths.GetLength();
*data = lengths.GetData();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::FindFacePlanes()
{
Check_Object(this);
int i, j, stride, numPrimitives = GetNumPrimitives();
Vector3D v;
for(i=0,j=0;i<numPrimitives;i++)
{
stride = lengths[i];
facePlanes[i].BuildPlane(
coords[j],
coords[j+1],
coords[j+2]
);
j += stride;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MLRPolyMesh::FindBackFace(const Point3D& u)
{
Check_Object(this);
unsigned char *iPtr;
int i, numPrimitives = GetNumPrimitives();
int ret = 0, len = lengths.GetLength();
Plane *p;
if(len <= 0)
{
visible = 0;
return 0;
}
p = &facePlanes[0];
iPtr = &testList[0];
if(state.GetBackFaceMode() == MLRState::BackFaceOffMode)
{
for(i=0;i<numPrimitives;i++,p++,iPtr++)
{
#if defined(_ARMOR)
*iPtr = (p->DistanceTo(u) >= 0.0f) ? (unsigned char)1: (unsigned char)0;
Verify (*iPtr != (unsigned char)0);
#else
*iPtr = (unsigned char)1;
#endif
}
ret = (unsigned char)1;
}
else
{
for(i=0;i<numPrimitives;i++,p++,iPtr++)
{
*iPtr = (p->DistanceTo(u) >= 0.0f) ? (unsigned char)1: (unsigned char)0;
ret += *iPtr;
}
visible = ret ? (unsigned char)1 : (unsigned char)0;
}
return ret;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::ResetTestList()
{
int i, numPrimitives = GetNumPrimitives();
unsigned char *iPtr = &testList[0];
for(i=0;i<numPrimitives;i++,iPtr++)
{
*iPtr = 1;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::Transform(Matrix4D *mat)
{
Check_Object(this);
int i, j, k;
int pLen, len = lengths.GetLength();
for(i=0,j=0;i<len;i++)
{
pLen = lengths[i];
if(testList[i] != 0)
{
for(k=j;k<pLen+j;k++)
{
transformedCoords[k].Multiply(coords[k], *mat);
}
#ifdef LAB_ONLY
Statistics::MLR_TransformedVertices += pLen;
#endif
}
j += pLen;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRPolyMesh::TransformNoClip(Matrix4D *mat, GOSVertexPool *vt)
{
Check_Object(this);
SET_MLRPOLYMESH_CLIP();
int i, j, k, stride;
int len = lengths.GetLength();
if(len <= 0)
{
visible = 0;
return;
}
Check_Object(vt);
gos_vertices = vt->GetActualVertexPool();
numGOSVertices = 0;
//
//-------------------------------
// Handle the non-indexed version
//-------------------------------
//
for(i=0,j=0;i<len;i++)
{
stride = lengths[i];
Verify(stride >= 3);
if(testList[i] == 0)
{
j += stride;
continue;
}
for(k=j;k<stride+j;k++)
{
transformedCoords[k].Multiply(coords[k], *mat);
}
#ifdef LAB_ONLY
Statistics::MLR_TransformedVertices += stride;
#endif
//
//--------------------------------------------------------
// JM claims all vertices are in. lets check it. who knows
//--------------------------------------------------------
//
#if defined(_ARMOR)
for(k=j;k<j+stride;k++)
{
Verify(transformedCoords[k].x >= 0.0f && transformedCoords[k].x <= transformedCoords[k].w );
Verify(transformedCoords[k].y >= 0.0f && transformedCoords[k].y <= transformedCoords[k].w );
Verify(transformedCoords[k].z >= 0.0f && transformedCoords[k].z <= transformedCoords[k].w );
}
#endif
for(k=1;k<stride-1;k++)
{
Verify((vt->GetLast() + 3 + numGOSVertices) < vt->GetLength());
Verify((*actualColors).GetLength() == coords.GetLength());
Verify(texCoords.GetLength() == coords.GetLength());
GOSCopyTriangleData(
&gos_vertices[numGOSVertices],
transformedCoords.GetData(),
actualColors->GetData(),
texCoords.GetData(),
j, j+k+1, j+k
);
numGOSVertices += 3;
}
#ifdef LAB_ONLY
Statistics::MLR_NonClippedVertices += stride;
#endif
j += stride;
}
Check_Object(vt);
vt->Increase(numGOSVertices);
visible = numGOSVertices ? 1 : 0;
CLEAR_MLRPOLYMESH_CLIP();
}
static MLRClippingState theAnd, theOr, theTest;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Now it gets serious
int
MLRPolyMesh::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt)
{
clipTrace->Start();
SET_MLRPOLYMESH_CLIP();
Check_Object(this);
static int clipTrick[6][2] = {
{ 1, 1},
{ 1, 0},
{ 0, 1},
{ 0, 0},
{ 2, 0},
{ 2, 1}
};
int i, j, k, l;
int stride, end, len = lengths.GetLength();
int mask, k1, ct=0, ret = 0;
Scalar a=0.0f, bc0, bc1;
Verify(len == testList.GetLength());
Verify(clippingFlags.GetClippingState() != 0);
//
//--------------------------------------
// See if we don't have to draw anything
//--------------------------------------
//
if(len <= 0)
{
visible = 0;
CLEAR_MLRPOLYMESH_CLIP();
clipTrace->Stop();
return visible;
}
int myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength;
myNumberUsedClipVertex = 0;
myNumberUsedClipIndex = 0;
myNumberUsedClipLength = 0;
//
//-----------------------------------------------------------------
// Step through each polygon, making sure that we don't try to clip
// backfaced polygons
//-----------------------------------------------------------------
//
for(i=0,j=0;i<len;i++)
{
stride = lengths[i];
if(testList[i] == 0)
{
j += stride;
continue;
}
//
//---------------------------------------------------------------
// Test each vertex of the polygon against the allowed clipping
// planes, and accumulate status for which planes always clip and
// which planes clipped at least once
//---------------------------------------------------------------
//
theAnd.SetClippingState(0x3f);
theOr.SetClippingState(0);
end = j+stride;
Stuff::Vector4D *v4d = transformedCoords.GetData() + j;
MLRClippingState *cs = clipPerVertex.GetData() + j;
for(k=j;k<end;k++,v4d++,cs++)
{
cs->SetClippingState(0);
if( clippingFlags.IsFarClipped() && v4d->w < v4d->z)
{
cs->SetFarClip();
}
if( clippingFlags.IsNearClipped() && v4d->z < 0.0f)
{
cs->SetNearClip();
}
if( clippingFlags.IsRightClipped() && v4d->x < 0.0f)
{
cs->SetRightClip();
}
if( clippingFlags.IsLeftClipped() && v4d->w < v4d->x)
{
cs->SetLeftClip();
}
if( clippingFlags.IsBottomClipped() && v4d->y < 0.0f)
{
cs->SetBottomClip();
}
if(clippingFlags.IsTopClipped() && v4d->w < v4d->y)
{
cs->SetTopClip();
}
theAnd &= *cs;
theOr |= *cs;
theAnd = theOr = 0;
#ifdef LAB_ONLY
if(clipPerVertex[k]==0)
{
Statistics::MLR_NonClippedVertices++;
}
else
{
Statistics::MLR_ClippedVertices++;
}
#endif
}
//
//-------------------------------------------------------------------
// If any bit is set for all vertices, then the polygon is completely
// outside the viewing space and we don't have to draw it. On the
// other hand, if no bits at all were ever set, we can do a trivial
// accept of the polygon
//-------------------------------------------------------------------
//
if (theAnd != 0)
{
testList[i] = 0;
}
else if (theOr == 0)
{
ret++;
}
//
//-----------------------------------------------------------------
// It is not a trivial case, so we must now do real clipping on the
// polygon
//-----------------------------------------------------------------
//
else
{
unsigned short numberVerticesPerPolygon = 0;
//
//---------------------------------------------------------------
// Handle the case of a single clipping plane by stepping through
// the vertices and finding the edge it originates
//---------------------------------------------------------------
//
if (theOr.GetNumberOfSetBits() == 1)
{
for(k=j;k<end;k++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -