📄 mgcgprendererclip.cpp
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement. The various license agreements may be found at
// the Magic Software web site. This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf
#include "MgcGPRenderer.h"
//---------------------------------------------------------------------------
bool MgcGPRenderer::Clip ()
{
// Clip against each clipping plane. Camera will eventually maintain
// an array of clipping planes (standard frustum and portal planes) and
// will have the ability to "disable" the plane based on object-level
// culling. Portal planes should be clipped first as they provide a
// higher probability of actually culling triangles compared to that for
// near and far planes.
//
// Return value of 'true' indicates trimesh is completely culled.
if ( ClipNear() )
return true;
if ( ClipFar() )
return true;
if ( ClipLeft() )
return true;
if ( ClipRight() )
return true;
if ( ClipTop() )
return true;
if ( ClipBottom() )
return true;
return false;
}
//---------------------------------------------------------------------------
bool MgcGPRenderer::ClipTriMesh ()
{
unsigned int uiE, uiT;
unsigned int uiOldNumEdges = m_kMesh.m_uiEdgesUsed;
// clip the visible edges
for (uiE = 0; uiE < uiOldNumEdges; uiE++)
{
if ( m_kMesh.m_abEdgeVisible[uiE] )
{
unsigned int uiV0 = m_kMesh.Edge(uiE).Vertex(0);
unsigned int uiV1 = m_kMesh.Edge(uiE).Vertex(1);
MgcReal fD0 = m_kMesh.m_afDistance[uiV0];
MgcReal fD1 = m_kMesh.m_afDistance[uiV1];
if ( fD0*fD1 < 0.0 )
{
MgcReal fParam = fD0/(fD0-fD1);
// add new vertex
unsigned int uiNV = m_kMesh.AddVertex();
m_kMesh.m_auiClipVertex[uiE] = uiNV;
m_kMesh.m_afClipParam[uiE] = fParam;
// clip only the geometry
MgcVector3& rkP0 = m_kMesh.Vertex(uiV0);
MgcVector3& rkP1 = m_kMesh.Vertex(uiV1);
m_kMesh.Vertex(uiNV) = rkP0 + fParam*(rkP1 - rkP0);
// add new edge and cull old vertex
unsigned int uiNE = m_kMesh.AddEdge();
MgcGPTriMesh::EdgeRecord& rkNE = m_kMesh.Edge(uiNE);
rkNE.Vertex(0) = uiNV;
m_kMesh.m_abEdgeVisible[uiNE] = true;
rkNE.Vertex(1) = ( fD1 > 0.0 ? uiV1 : uiV0 );
// Use old triangle indices. These fields will
// be updated later when the triangles are split.
rkNE.Triangle(0) = m_kMesh.Edge(uiE).Triangle(0);
rkNE.Triangle(1) = m_kMesh.Edge(uiE).Triangle(1);
// save old and new edge info for clipped vertex
m_kMesh.m_auiOldEdge[uiNV] = uiE;
m_kMesh.m_auiNewEdge[uiNV] = uiNE;
// cull old edge
m_kMesh.m_abEdgeVisible[uiE] = false;
}
}
}
// process all the newly added edges from clipping (update mesh)
unsigned int uiOldNumTriangles = m_kMesh.m_uiTrianglesUsed;
unsigned int uiNewNumEdges = m_kMesh.m_uiEdgesUsed;
for (uiE = uiOldNumEdges; uiE < uiNewNumEdges; uiE++)
{
// clipped edge is m_kMesh.Edge(uiE)
for (int i = 0; i < 2; i++)
{
// get adjacent triangle
uiT = m_kMesh.Edge(uiE).Triangle(i);
assert( uiT == MgcGPTriMesh::INVALID_INDEX ||
uiT < m_kMesh.m_uiTrianglesUsed );
if ( uiT == MgcGPTriMesh::INVALID_INDEX
|| uiT >= uiOldNumTriangles
|| !m_kMesh.m_abTriangleVisible[uiT] )
{
continue;
}
MgcGPTriMesh::TriangleRecord& rkOldTri = m_kMesh.Triangle(uiT);
// Inverse table look up where m_kMesh.Edge(uiE).Vertex(0) is
// the index of the clipped vertex for the old edge shared between
// T0 and T1.
unsigned int uiClipV0 = m_kMesh.Edge(uiE).Vertex(0);
assert( uiClipV0 < m_kMesh.m_uiVerticesUsed );
unsigned int uiSE = m_kMesh.m_auiOldEdge[uiClipV0];
assert( uiSE < m_kMesh.m_uiEdgesUsed );
MgcGPTriMesh::EdgeRecord& rkSE = m_kMesh.Edge(uiSE);
int iV0, iV1, iV2, iE0, iE1, iE2;
iE0 = rkOldTri.GetEdgeIndex(uiSE);
assert( iE0 != -1 );
iV0 = rkOldTri.GetVertexIndex(m_kMesh.Edge(uiE).Vertex(1));
assert( iV0 != -1 );
if ( rkSE.Vertex(0) == m_kMesh.Edge(uiE).Vertex(1) )
iV1 = rkOldTri.GetVertexIndex(rkSE.Vertex(1));
else
iV1 = rkOldTri.GetVertexIndex(rkSE.Vertex(0));
assert( iV1 != -1 && iV1 != iV0 );
if ( iV1 == ((iV0+1)%3) )
{
iV2 = (iV1+1)%3;
iE1 = (iE0+1)%3;
iE2 = (iE1+1)%3;
}
else
{
iV2 = (iV1+2)%3;
iE1 = (iE0+2)%3;
iE2 = (iE1+2)%3;
}
// finally, split the triangle
unsigned int uiV0 = rkOldTri.Vertex(iV0);
unsigned int uiV1 = rkOldTri.Vertex(iV1);
unsigned int uiV2 = rkOldTri.Vertex(iV2);
unsigned int uiE0 = rkOldTri.Edge(iE0);
unsigned int uiE1 = rkOldTri.Edge(iE1);
unsigned int uiE2 = rkOldTri.Edge(iE2);
assert( uiV0 < m_kMesh.m_uiVerticesUsed );
assert( uiV1 < m_kMesh.m_uiVerticesUsed );
assert( uiV2 < m_kMesh.m_uiVerticesUsed );
assert( uiE0 < m_kMesh.m_uiEdgesUsed );
assert( uiE1 < m_kMesh.m_uiEdgesUsed );
assert( uiE2 < m_kMesh.m_uiEdgesUsed );
unsigned int uiNE, uiNT, uiNE0, uiNE1, uiNT0, uiNT1;
unsigned int uiClipV1, uiClipV2, uiAE;
if ( m_kMesh.m_auiClipVertex[uiE2] != MgcGPTriMesh::INVALID_INDEX )
{
// edge uiE2 was clipped
// add edge
uiNE = m_kMesh.AddEdge();
MgcGPTriMesh::EdgeRecord& rkNE = m_kMesh.Edge(uiNE);
// add triangle
uiNT = m_kMesh.AddTriangle();
MgcGPTriMesh::TriangleRecord& rkNT = m_kMesh.Triangle(uiNT);
// update fields
uiClipV2 = m_kMesh.m_auiClipVertex[uiE2];
assert( uiClipV2 < m_kMesh.m_uiVerticesUsed );
uiAE = m_kMesh.m_auiNewEdge[uiClipV2];
assert( uiAE < m_kMesh.m_uiEdgesUsed );
rkNE.Vertex(0) = uiClipV0;
rkNE.Vertex(1) = uiClipV2;
rkNE.Triangle(0) = uiNT;
rkNE.Triangle(1) = MgcGPTriMesh::INVALID_INDEX;
rkNT.Vertex(0) = uiV0;
rkNT.Vertex(1) = uiClipV0;
rkNT.Vertex(2) = uiClipV2;
rkNT.Edge(0) = uiE;
rkNT.Edge(1) = uiNE;
rkNT.Edge(2) = uiAE;
m_kMesh.Edge(uiE).Triangle(i) = uiNT;
MgcGPTriMesh::EdgeRecord& rkAE = m_kMesh.Edge(uiAE);
if ( rkAE.Triangle(0) == uiT )
rkAE.Triangle(0) = uiNT;
else
rkAE.Triangle(1) = uiNT;
// cull old edge
m_kMesh.m_abEdgeVisible[uiE2] = false;
}
else if ( m_kMesh.m_auiClipVertex[uiE1] !=
MgcGPTriMesh::INVALID_INDEX )
{
// edge uiE1 was clipped
// add edges
uiNE0 = m_kMesh.AddEdge();
uiNE1 = m_kMesh.AddEdge();
MgcGPTriMesh::EdgeRecord& rkNE0 = m_kMesh.Edge(uiNE0);
MgcGPTriMesh::EdgeRecord& rkNE1 = m_kMesh.Edge(uiNE1);
// add triangles
uiNT0 = m_kMesh.AddTriangle();
uiNT1 = m_kMesh.AddTriangle();
MgcGPTriMesh::TriangleRecord& rkNT0 = m_kMesh.Triangle(uiNT0);
MgcGPTriMesh::TriangleRecord& rkNT1 = m_kMesh.Triangle(uiNT1);
// update fields
uiClipV1 = m_kMesh.m_auiClipVertex[uiE1];
assert( uiClipV1 < m_kMesh.m_uiVerticesUsed );
uiAE = m_kMesh.m_auiNewEdge[uiClipV1];
assert( uiAE < m_kMesh.m_uiEdgesUsed );
rkNE0.Vertex(0) = uiClipV0;
rkNE0.Vertex(1) = uiV2;
rkNE0.Triangle(0) = uiNT0;
rkNE0.Triangle(1) = uiNT1;
rkNE1.Vertex(0) = uiClipV0;
rkNE1.Vertex(1) = uiClipV1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -