📄 mlrindexedpolymesh.cpp
字号:
//===========================================================================//
// Copyright (C) Microsoft Corporation. All rights reserved. //
//===========================================================================//
#include "MLRHeaders.hpp"
#include "OwnTrace.hpp"
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
BitTrace *MLRIndexedPolyMesh_Clip;
#define SET_MLRIndexedPolyMesh_CLIP() MLRIndexedPolyMesh_Clip->Set()
#define CLEAR_MLRIndexedPolyMesh_CLIP() MLRIndexedPolyMesh_Clip->Clear()
#else
#define SET_MLRIndexedPolyMesh_CLIP()
#define CLEAR_MLRIndexedPolyMesh_CLIP()
#endif
//#############################################################################
//############################### MLRIndexedPolyMesh ##################################
//#############################################################################
MLRIndexedPolyMesh::ClassData*
MLRIndexedPolyMesh::DefaultData = NULL;
MemoryBlock*
MLRIndexedPolyMesh::AllocatedMemory = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::InitializeClass()
{
Verify(!AllocatedMemory);
AllocatedMemory =
new MemoryBlock(
sizeof(MLRIndexedPolyMesh),
100,
100,
"MLRIndexedPolyMesh"
);
Register_Object(AllocatedMemory);
Verify(!DefaultData);
DefaultData =
new ClassData(
MLRIndexedPolyMeshClassID,
"MidLevelRenderer::MLRIndexedPolyMesh",
MLRIndexedPrimitive::DefaultData,
(MLRPrimitive::Factory)&Make
);
Register_Object(DefaultData);
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
MLRIndexedPolyMesh_Clip = new BitTrace("MLRIndexedPolyMesh_Clip");
Register_Object(MLRIndexedPolyMesh_Clip);
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
Unregister_Object(AllocatedMemory);
delete AllocatedMemory;
AllocatedMemory = NULL;
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
Unregister_Object(MLRIndexedPolyMesh_Clip);
delete MLRIndexedPolyMesh_Clip;
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRIndexedPolyMesh::MLRIndexedPolyMesh(
MemoryStream *stream,
int version
):
MLRIndexedPrimitive(DefaultData, stream, version)
{
Check_Pointer(this);
Check_Pointer(stream);
facePlanes.SetLength(GetNumPrimitives());
testList.SetLength(GetNumPrimitives());
FindFacePlanes();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRIndexedPolyMesh::MLRIndexedPolyMesh():
MLRIndexedPrimitive(DefaultData)
{
Check_Pointer(this);
drawMode = SortData::TriIndexedList;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRIndexedPolyMesh::~MLRIndexedPolyMesh()
{
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRIndexedPolyMesh*
MLRIndexedPolyMesh::Make(
MemoryStream *stream,
int version
)
{
return new MLRIndexedPolyMesh(stream, version);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::Save(MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
MLRIndexedPrimitive::Save(stream);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::InitializeDrawPrimitive(int vis, int parameter)
{
MLRIndexedPrimitive::InitializeDrawPrimitive(vis, parameter);
if(parameter & 1)
{
ResetTestList();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::SetPrimitiveLength (unsigned char *data, int numPrimitives)
{
Check_Object(this);
lengths.AssignData(data, numPrimitives);
facePlanes.SetLength(numPrimitives);
testList.SetLength(numPrimitives);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::GetPrimitiveLength (unsigned char **data, int *l)
{
Check_Object(this);
*l = lengths.GetLength();
*data = lengths.GetData();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::FindFacePlanes()
{
Check_Object(this);
int i, j, stride, numPrimitives = GetNumPrimitives();
Vector3D v;
Verify(index.GetLength() > 0);
for(i=0,j=0;i<numPrimitives;i++)
{
stride = lengths[i];
facePlanes[i].BuildPlane(
coords[index[j]],
coords[index[j+1]],
coords[index[j+2]]
);
j += stride;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MLRIndexedPolyMesh::FindBackFace(const Point3D& u)
{
Check_Object(this);
int i, numPrimitives = GetNumPrimitives();
int ret = 0, len = lengths.GetLength();
unsigned char *iPtr;
Plane *p;
if(len <= 0)
{
visible = 0;
return 0;
}
p = &facePlanes[0];
iPtr = &testList[0];
if(state.GetBackFaceMode() == MLRState::BackFaceOffMode)
{
ResetTestList();
ret = 1;
}
else
{
for(i=0;i<numPrimitives;i++,p++,iPtr++)
{
// Scalar s = p->DistanceTo(u);
// *iPtr = !Get_Sign_Bit(s);
*iPtr = (p->DistanceTo(u) >= 0.0f) ? (unsigned char)1: (unsigned char)0;
ret += *iPtr;
}
visible = ret ? (unsigned char)1 : (unsigned char)0;
}
visible = ret ? (unsigned char)1 : (unsigned char)0;
FindVisibleVertices();
return ret;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::ResetTestList()
{
int i, numPrimitives = GetNumPrimitives();
unsigned char *iPtr = &testList[0];
for(i=0;i<numPrimitives;i++,iPtr++)
{
*iPtr = 1;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MLRIndexedPolyMesh::FindVisibleVertices()
{
Check_Object(this);
Verify(index.GetLength() > 0);
int ret, i, j, k, stride, len = lengths.GetLength();
Verify(index.GetLength() > 0);
for(i=0,j=0,ret=0;i<len;i++)
{
stride = lengths[i];
Verify(stride >= 3);
if(testList[i] == 0)
{
j += stride;
continue;
}
for(k=j;k<j+stride;k++)
{
visibleIndexedVertices[index[k]] = 1;
ret++;
}
j += stride;
}
visibleIndexedVerticesKey = true;
return ret;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::Transform(Matrix4D *mat)
{
Check_Object(this);
Verify(index.GetLength() > 0);
int i, len = coords.GetLength();
if(visibleIndexedVerticesKey == false)
{
FindVisibleVertices();
}
for(i=0;i<len;i++)
{
if(visibleIndexedVertices[i] != 0)
{
transformedCoords[i].Multiply(coords[i], *mat);
#ifdef LAB_ONLY
Statistics::MLR_TransformedVertices++;
#endif
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedPolyMesh::TransformNoClip(Matrix4D *mat, GOSVertexPool *vt)
{
Check_Object(this);
Check_Object(vt);
Verify(index.GetLength() > 0);
SET_MLRIndexedPolyMesh_CLIP();
unsigned short stride;
int i, j, k, len = lengths.GetLength();
gos_vertices = vt->GetActualVertexPool();
numGOSVertices = 0;
Verify(index.GetLength() > 0);
k = visibleIndexedVertices.GetLength();
if(visibleIndexedVerticesKey == false)
{
FindVisibleVertices();
}
for(j=0,stride=0;j<k;j++)
{
if(visibleIndexedVertices[j] == 0)
{
stride++;
}
else
{
visibleIndexedVertices[j] = stride;
transformedCoords[j].Multiply(coords[j], *mat);
#ifdef LAB_ONLY
Statistics::MLR_TransformedVertices++;
#endif
//
//--------------------------------------------------------
// JM claims all vertices are in. lets check it. who knows
//--------------------------------------------------------
//
Verify(transformedCoords[j].x >= 0.0f && transformedCoords[j].x <= transformedCoords[j].w );
Verify(transformedCoords[j].y >= 0.0f && transformedCoords[j].y <= transformedCoords[j].w );
Verify(transformedCoords[j].z >= 0.0f && transformedCoords[j].z <= transformedCoords[j].w );
GOSCopyData(
&gos_vertices[numGOSVertices],
transformedCoords.GetData(),
actualColors->GetData(),
texCoords.GetData(),
j
);
numGOSVertices++;
}
}
#ifdef LAB_ONLY
Statistics::MLR_NonClippedVertices += numGOSVertices;
#endif
Check_Object(vt);
vt->Increase(numGOSVertices);
gos_indices = vt->GetActualIndexPool();
numGOSIndices = 0;
for(i=0,j=0;i<len;i++)
{
stride = lengths[i];
Verify(stride >= 3);
if(testList[i] == 0)
{
j += stride;
continue;
}
for(k=1;k<stride-1;k++)
{
Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());
gos_indices[numGOSIndices] = (unsigned short)(index[j] - visibleIndexedVertices[index[j]]);
gos_indices[numGOSIndices+1] = (unsigned short)(index[j+k+1] - visibleIndexedVertices[index[j+k+1]]);
gos_indices[numGOSIndices+2] = (unsigned short)(index[j+k] - visibleIndexedVertices[index[j+k]]);
numGOSIndices += 3;
}
j += stride;
}
Check_Object(vt);
vt->IncreaseIndex(numGOSIndices);
visible = numGOSVertices ? 1 : 0;
CLEAR_MLRIndexedPolyMesh_CLIP();
}
static MLRClippingState theAnd, theOr, theTest;
static int clipTrick[6][2] = {
{ 1, 1},
{ 1, 0},
{ 0, 1},
{ 0, 0},
{ 2, 0},
{ 2, 1}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Now it gets serious
int
MLRIndexedPolyMesh::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt)
{
StartCycleTiming( &Statistics::MLR_ClipTime );
SET_MLRIndexedPolyMesh_CLIP();
Check_Object(this);
unsigned short stride, l;
int i, j, k, ret = 0;
int len = lengths.GetLength();
Verify(len == testList.GetLength());
Verify(clippingFlags.GetClippingState() != 0);
//
//--------------------------------------
// See if we don't have to draw anything
//--------------------------------------
//
if(len <= 0)
{
visible = 0;
CLEAR_MLRIndexedPolyMesh_CLIP();
EndCycleTiming( &Statistics::MLR_ClipTime );
return visible;
}
int mask, end, k0, k1, ct=0;
Scalar a=0.0f;
// Scalar bc0=0.0f, bc1=0.0f;
int myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength;
myNumberUsedClipVertex = 0;
myNumberUsedClipIndex = 0;
myNumberUsedClipLength = 0;
Verify(index.GetLength() > 0);
if(visibleIndexedVerticesKey == false)
{
FindVisibleVertices();
}
//
//------------------------
// Handle the indexed case
//------------------------
//
//
//-----------------------------------------------------------------
// Step through each vertex and check visibility
// backfaced polygons
//-----------------------------------------------------------------
//
k = transformedCoords.GetLength();
Stuff::Vector4D *v4d = transformedCoords.GetData();
MLRClippingState *cs = clipPerVertex.GetData();
for(i=0;i<k;i++,v4d++,cs++)
{
if(visibleIndexedVertices[i] == 0)
{
continue;
}
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();
}
#ifdef LAB_ONLY
if( (*cs)==0)
{
Statistics::MLR_NonClippedVertices++;
}
else
{
Statistics::MLR_ClippedVertices++;
}
#endif
}
// initialize visibleIndexedVertices
memset(visibleIndexedVertices.GetData(), 0, visibleIndexedVertices.GetSize());
//
//-----------------------------------------------------------------
// 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;
for(k=j;k<end;k++)
{
theAnd &= clipPerVertex[index[k]];
theOr |= clipPerVertex[index[k]];
}
theAnd = theOr = 0; //ASSUME NO CLIPPING NEEDED FOR MC2. Its just not done here!
//
//-------------------------------------------------------------------
// 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;
#ifdef LAB_ONLY
Statistics::MLR_PolysClippedButOutside++;
#endif
}
else if (theOr == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -