📄 mlrindexedtrianglecloud.cpp
字号:
//===========================================================================//
// Copyright (C) Microsoft Corporation. All rights reserved. //
//===========================================================================//
#include "MLRHeaders.hpp"
#if !defined(MLR_MLRCLIPTRICK_HPP)
#include <MLR\MLRClipTrick.hpp>
#endif
#if !defined(MLR_MLRINDEXEDTRIANGLECLOUD_HPP)
#include <MLR\MLRIndexedTriangleCloud.hpp>
#endif
extern DWORD gShowClippedPolys;
extern unsigned short *indexOffset; // [MidLevelRenderer::Max_Number_Vertices_Per_Mesh]
//#############################################################################
//#################### MLRIndexedTriangleCloud ##########################
//#############################################################################
DynamicArrayOf<unsigned short>
*MLRIndexedTriangleCloud::clipExtraIndex;
DynamicArrayOf<Vector2DScalar>
*MLRIndexedTriangleCloud::clipExtraTexCoords;
DynamicArrayOf<unsigned char>
*MLRIndexedTriangleCloud::visibleIndexedVertices;
MLRIndexedTriangleCloud::ClassData*
MLRIndexedTriangleCloud::DefaultData = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedTriangleCloud::InitializeClass()
{
Verify(!DefaultData);
Verify(gos_GetCurrentHeap() == StaticHeap);
DefaultData =
new ClassData(
MLRIndexedTriangleCloudClassID,
"MidLevelRenderer::MLRIndexedTriangleCloud",
MLRTriangleCloud::DefaultData
);
Register_Object(DefaultData);
clipExtraIndex = new DynamicArrayOf<unsigned short> (Limits::Max_Number_Vertices_Per_Mesh);
Register_Pointer(clipExtraIndex);
clipExtraTexCoords = new DynamicArrayOf<Vector2DScalar> (Limits::Max_Number_Vertices_Per_Mesh);
Register_Pointer(clipExtraTexCoords);
visibleIndexedVertices = new DynamicArrayOf<unsigned char> (Limits::Max_Number_Vertices_Per_Mesh);
Register_Pointer(visibleIndexedVertices);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedTriangleCloud::TerminateClass()
{
Unregister_Pointer(clipExtraIndex);
delete clipExtraIndex;
Unregister_Pointer(clipExtraTexCoords);
delete clipExtraTexCoords;
Unregister_Pointer(visibleIndexedVertices);
delete visibleIndexedVertices;
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRIndexedTriangleCloud::MLRIndexedTriangleCloud(int nr) :
MLRTriangleCloud(nr)
{
Verify(gos_GetCurrentHeap() == Heap);
usedNrOfPoints = NULL;
Check_Pointer(this);
drawMode = SortData::TriIndexedList;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRIndexedTriangleCloud::~MLRIndexedTriangleCloud()
{
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedTriangleCloud::SetData
(
const int *tri_count,
const int *point_count,
const unsigned short *index_data,
const Stuff::Point3D *point_data,
const Stuff::RGBAColor *color_data,
const Vector2DScalar *uv_data
)
{
Check_Pointer(this);
usedNrOfTriangles = tri_count;
usedNrOfPoints = point_count;
Verify(*usedNrOfTriangles <= maxNrOf);
index = index_data;
points = point_data;
colors = color_data;
texCoords = uv_data;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRIndexedTriangleCloud::Draw (DrawEffectInformation *dInfo, GOSVertexPool *allVerticesToDraw, MLRSorter *sorter)
{
Check_Object(this);
worldToEffect.Invert(*dInfo->effectToWorld);
Vector4D *v4 = transformedCoords->GetData();
for(int k=0;k<*usedNrOfPoints;k++, v4++)
{
v4->Multiply(points[k], effectToClipMatrix);
(*clipPerVertex)[k].Clip4dVertex(v4);
}
#if 0
Lighting(*shape->worldToShape, dInfo->activeLights, dInfo->nrOfActiveLights);
#endif
if( Clip(dInfo->clippingFlags, allVerticesToDraw) )
{
sorter->AddEffect(this, dInfo->state);
}
}
static MLRClippingState theAnd, theOr, theTest;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MLRIndexedTriangleCloud::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt)
{
int myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength;
myNumberUsedClipVertex = 0;
myNumberUsedClipIndex = 0;
myNumberUsedClipLength = 0;
Verify(*usedNrOfTriangles > 0);
//
//------------------------
// Handle the indexed case
//------------------------
//
memset(visibleIndexedVertices->GetData(), 0, *usedNrOfPoints);
//
//-----------------------------------------------------------------
// Step through each polygon, making sure that we don't try to clip
// backfaced polygons
//-----------------------------------------------------------------
//
int i, j, k, k0, k1, *cs = (int *)clipPerVertex->GetData();
unsigned short l;
int index0, index1, index2, ret = 0;
int mask;
Scalar a = 0.0f;
for(i=0,j=0;i<*usedNrOfTriangles;j+=3,++i)
{
index0 = index[j];
index1 = index[j+1];
index2 = index[j+2];
//
//---------------------------------------------------------------
// 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 = cs[index0];
theAnd &= (cs[index1] & cs[index2]);
theOr |= (cs[index1] | cs[index2]);
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
Set_Statistic(PolysClippedButOutside, PolysClippedButOutside+1);
#endif
}
else if (theOr == 0)
{
testList[i] = 1;
ret++;
(*visibleIndexedVertices)[index0] = 1;
(*visibleIndexedVertices)[index1] = 1;
(*visibleIndexedVertices)[index2] = 1;
#ifdef LAB_ONLY
Set_Statistic(PolysClippedButInside, PolysClippedButInside+1);
#endif
}
//
//-----------------------------------------------------------------
// 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
//---------------------------------------------------------------
//
bool firstIsIn;
if (theOr.GetNumberOfSetBits() == 1)
{
#ifdef LAB_ONLY
Set_Statistic(PolysClippedButOnePlane, PolysClippedButOnePlane+1);
#endif
for(k=j;k<j+3;k++)
{
k0 = index[k];
k1 = index[(k+1) < j+3 ? k+1 : j];
//
//----------------------------------------------------
// If this vertex is inside the viewing space, copy it
// directly to the clipping buffer
//----------------------------------------------------
//
int clipped_index =
myNumberUsedClipVertex + numberVerticesPerPolygon;
theTest = cs[k0];
if(theTest == 0)
{
firstIsIn = true;
(*clipExtraCoords)[clipped_index] = (*transformedCoords)[k0];
(*clipExtraColors)[clipped_index] = colors[k0];
(*clipExtraTexCoords)[clipped_index] = texCoords[k0];
numberVerticesPerPolygon++;
clipped_index++;
//
//-------------------------------------------------------
// We don't need to clip this edge if the next vertex is
// also in the viewing space, so just move on to the next
// vertex
//-------------------------------------------------------
//
if(cs[k1] == 0)
{
continue;
}
}
//
//---------------------------------------------------------
// This vertex is outside the viewing space, so if the next
// vertex is also outside the viewing space, no clipping is
// needed and we throw this vertex away. Since only one
// clipping plane is involved, it must be in the same space
// as the first vertex
//---------------------------------------------------------
//
else
{
firstIsIn = false;
if(cs[k1] != 0)
{
Verify(cs[k1] == cs[k0]);
continue;
}
}
//
//--------------------------------------------------
// We now find the distance along the edge where the
// clipping plane will intersect
//--------------------------------------------------
//
int ct = 0;
mask = 1;
theTest |= cs[k1];
//
//-----------------------------------------------------
// Find the boundary conditions that match our clipping
// plane
//-----------------------------------------------------
//
for (l=0; l<MLRClippingState::NextBit; l++)
{
if(theTest.IsClipped(mask))
{
// GetDoubleBC(l, bc0, bc1, transformedCoords[k0], transformedCoords[k1]);
//
//-------------------------------------------
// Find the clipping interval from bc0 to bc1
//-------------------------------------------
//
if(firstIsIn==true)
{
a = GetLerpFactor(l, (*transformedCoords)[k0], (*transformedCoords)[k1]);
}
else
{
a = GetLerpFactor(l, (*transformedCoords)[k1], (*transformedCoords)[k0]);
}
Verify(a >= 0.0f && a <= 1.0f);
ct = l;
break;
}
mask <<= 1;
}
//
//------------------------------
// Lerp the homogeneous position
//------------------------------
//
if(firstIsIn==true)
{
(*clipExtraCoords)[clipped_index].Lerp(
(*transformedCoords)[k0],
(*transformedCoords)[k1],
a
);
DoClipTrick((*clipExtraCoords)[clipped_index], ct);
//
//----------------------------------------------------------
// If there are colors, lerp them in screen space for now as
// most cards do that anyway
//----------------------------------------------------------
//
#if COLOR_AS_DWORD
(*clipExtraColors)[clipped_index] = Color_DWORD_Lerp (
colors[k0],
colors[k1],
a
);
#else
(*clipExtraColors)[clipped_index].Lerp(
colors[k0],
colors[k1],
a
);
#endif
//
//-----------------------------------------------------
// If there are texture uv's, we need to lerp them in a
// perspective correct manner
//-----------------------------------------------------
//
(*clipExtraTexCoords)[clipped_index].Lerp
(
texCoords[k0],
texCoords[k1],
a
);
}
else
{
(*clipExtraCoords)[clipped_index].Lerp(
(*transformedCoords)[k1],
(*transformedCoords)[k0],
a
);
DoClipTrick((*clipExtraCoords)[clipped_index], ct);
//
//----------------------------------------------------------
// If there are colors, lerp them in screen space for now as
// most cards do that anyway
//----------------------------------------------------------
//
#if COLOR_AS_DWORD
(*clipExtraColors)[clipped_index] = Color_DWORD_Lerp (
colors[k1],
colors[k0],
a
);
#else
(*clipExtraColors)[clipped_index].Lerp(
colors[k1],
colors[k0],
a
);
#endif
//
//-----------------------------------------------------
// If there are texture uv's, we need to lerp them in a
// perspective correct manner
//-----------------------------------------------------
//
(*clipExtraTexCoords)[clipped_index].Lerp
(
texCoords[k1],
texCoords[k0],
a
);
}
//
//--------------------------------
// Bump the polygon's vertex count
//--------------------------------
//
numberVerticesPerPolygon++;
}
(*clipExtraLength)[myNumberUsedClipLength] = numberVerticesPerPolygon;
#ifdef _ARMOR
(*clipExtraLength)[myNumberUsedClipLength] &= ~0x8000;
#endif
}
//
//---------------------------------------------------------------
// We have to handle multiple planes. We do this by creating two
// buffers and we switch between them as we clip plane by plane
//---------------------------------------------------------------
//
else
{
#ifdef LAB_ONLY
Set_Statistic(PolysClippedButGOnePlane, PolysClippedButGOnePlane+1);
#endif
ClipData2 srcPolygon, dstPolygon;
int dstBuffer = 1;
srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();
//
//----------------------------------------------------------
// unravel and copy the original data into the source buffer
//----------------------------------------------------------
//
for(k=j,l=0;k<j+3;k++,l++)
{
int indexK = index[k];
srcPolygon.coords[l] = (*transformedCoords)[indexK];
srcPolygon.colors[l] = colors[indexK];
srcPolygon.texCoords[l] = texCoords[indexK];
srcPolygon.clipPerVertex[l] = (*clipPerVertex)[indexK];
}
srcPolygon.length = l;
//
//--------------------------------
// Point to the destination buffer
//--------------------------------
//
dstBuffer = 0;
dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -