📄 mgcbeziertriangle2.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 "MgcBezierTriangle2.h"
#include "MgcTriMesh.h"
MgcImplementRTTI(MgcBezierTriangle2,MgcBezierTriangle);
MgcImplementStream(MgcBezierTriangle2);
// macros for initialization in the subdivision
#define XA(i) akCtrlPoint[m_auiIndex[i]]
#define CA(i) akCtrlColor[m_auiIndex[i]]
#define TA(i) akCtrlTexture[m_auiIndex[i]]
//----------------------------------------------------------------------------
MgcBezierTriangle2::MgcBezierTriangle2 (unsigned int* auiIndex)
:
MgcBezierTriangle(2,6,auiIndex)
{
}
//----------------------------------------------------------------------------
MgcBezierTriangle2::MgcBezierTriangle2 ()
{
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2::InitializePoints (const MgcVector3* akCtrlPoint,
BlockParameters& rkBP)
{
// Xuu
rkBP.m_kXuu = 2.0*(XA(0) - 2.0*XA(1) + XA(2));
// Xvv
rkBP.m_kXvv = 2.0*(XA(0) - 2.0*XA(3) + XA(5));
// Xhh = Xuu - 2*Xuv + Xvv (d/dh = d/ds - d/dt)
rkBP.m_kXhh = 2.0*(XA(0) + XA(4) - XA(1) - XA(3));
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2::InitializeColors (const MgcColor* akCtrlColor,
BlockParameters& rkBP)
{
// Cuu
rkBP.m_kCuu = 2.0*(CA(0) - 2.0*CA(1) + CA(2));
// Cvv
rkBP.m_kCvv = 2.0*(CA(0) - 2.0*CA(3) + CA(5));
// Chh = Cuu - 2*Cuv + Cvv (d/dh = d/ds - d/dt)
rkBP.m_kChh = 2.0*(CA(0) + CA(4) - CA(1) - CA(3));
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2::InitializeTextures (const MgcVector2* akCtrlTexture,
BlockParameters& rkBP)
{
// Tuu
rkBP.m_kTuu = 2.0*(TA(0) - 2.0*TA(1) + TA(2));
// Tvv
rkBP.m_kTvv = 2.0*(TA(0) - 2.0*TA(3) + TA(5));
// Thh = Tuu - 2*Tuv + Tvv (d/dh = d/ds - d/dt)
rkBP.m_kThh = 2.0*(TA(0) + TA(4) - TA(1) - TA(3));
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2::Tessellate (unsigned int uiLevel,
const MgcVector3* akCtrlPoint, const MgcColor* akCtrlColor,
const MgcVector2* akCtrlTexture, MgcTriMesh* pkMesh,
unsigned int& ruiVertexStart, unsigned int& ruiTriangleStart)
{
GenerateConnectivity(uiLevel,pkMesh,ruiTriangleStart);
// number of vertices in the subdivision
unsigned int uiQuantity = GetVerticesPerTrianglePatch(uiLevel);
// indices of three corners of patch, I0 (w=1), I1 (u=1), I2 (v=1)
unsigned int uiTwoPowL = (1 << uiLevel);
unsigned int uiI0 = 0;
unsigned int uiI1 = uiTwoPowL;
unsigned int uiI2 = uiTwoPowL*(uiTwoPowL + 3) >> 1;
BlockParameters kBP;
// vertices for subdivision
MgcVector3* akX = pkMesh->Vertices() + ruiVertexStart;
akX[uiI0] = XA(0);
akX[uiI1] = XA(2);
akX[uiI2] = XA(5);
// derivatives for subdivision (for normal vectors)
MgcVector3* akXu;
MgcVector3* akXv;
if ( pkMesh->Normals() )
{
akXu = new MgcVector3[uiQuantity];
akXu[uiI0] = 2.0*(XA(1) - XA(0));
akXu[uiI1] = 2.0*(XA(2) - XA(1));
akXu[uiI2] = 2.0*(XA(4) - XA(3));
akXv = new MgcVector3[uiQuantity];
akXv[uiI0] = 2.0*(XA(3) - XA(0));
akXv[uiI1] = 2.0*(XA(5) - XA(3));
akXv[uiI2] = 2.0*(XA(4) - XA(1));
}
else
{
akXu = 0;
akXv = 0;
}
// colors for subdivision
MgcColor* akColor;
if ( pkMesh->Colors() )
{
akColor = pkMesh->Colors() + ruiVertexStart;
akColor[uiI0] = CA(0);
akColor[uiI1] = CA(2);
akColor[uiI2] = CA(5);
}
else
{
akColor = 0;
}
// textures for subdivision
MgcVector2* akTexture;
if ( pkMesh->Textures() )
{
akTexture = pkMesh->Textures() + ruiVertexStart;
akTexture[uiI0] = TA(0);
akTexture[uiI1] = TA(2);
akTexture[uiI2] = TA(5);
}
else
{
akTexture = 0;
}
// recursive subdivision
if ( uiLevel > 0 )
{
InitializePoints(akCtrlPoint,kBP);
if ( akCtrlColor )
InitializeColors(akCtrlColor,kBP);
if ( akCtrlTexture )
InitializeTextures(akCtrlTexture,kBP);
SubdivideLL(--uiLevel,0.25,akX,akXu,akXv,akColor,akTexture,uiI0,uiI1,
uiI2,kBP);
}
// calculate unit-length normals from derivative vectors
if ( pkMesh->Normals() )
{
MgcVector3* akNormal = pkMesh->Normals() + ruiVertexStart;
for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
akNormal[uiI] = akXu[uiI].UnitCross(akXv[uiI]);
delete[] akXu;
delete[] akXv;
}
ruiVertexStart += uiQuantity;
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2::SubdivideLL (unsigned int uiLevel, MgcReal fDSqr,
MgcVector3* akX, MgcVector3* akXu, MgcVector3* akXv, MgcColor* akColor,
MgcVector2* akTexture, unsigned int uiI0, unsigned int uiI1,
unsigned int uiI2, BlockParameters& rkBP)
{
/*
i2
+
| \
| \
+----+
i0 i1
*/
// subdivision indices
unsigned int uiI01 = (uiI0 + uiI1) >> 1;
unsigned int uiD10 = uiI1 - uiI0;
unsigned int uiI02 = (((uiI0 + uiI2) << 2) + uiD10*uiD10) >> 3;
unsigned int uiI12 = uiI02 + (uiD10 >> 1);
// vertices
// bottom u-edge subdivision
akX[uiI01] = 0.5*(akX[uiI0] + akX[uiI1] - fDSqr*rkBP.m_kXuu);
// left v-edge subdivision
akX[uiI02] = 0.5*(akX[uiI0] + akX[uiI2] - fDSqr*rkBP.m_kXvv);
// hypotenuse edge subdivision
akX[uiI12] = 0.5*(akX[uiI1] + akX[uiI2] - fDSqr*rkBP.m_kXhh);
// derivatives (for normal vectors)
if ( akXu )
{
// bottom u-edge subdivision
akXu[uiI01] = 0.5*(akXu[uiI0] + akXu[uiI1]);
akXv[uiI01] = 0.5*(akXv[uiI0] + akXv[uiI1]);
// left v-edge subdivision
akXu[uiI02] = 0.5*(akXu[uiI0] + akXu[uiI2]);
akXv[uiI02] = 0.5*(akXv[uiI0] + akXv[uiI2]);
// hypotenuse edge subdivision
akXu[uiI12] = 0.5*(akXu[uiI1] + akXu[uiI2]);
akXv[uiI12] = 0.5*(akXv[uiI1] + akXv[uiI2]);
}
// colors
if ( akColor )
{
// bottom u-edge subdivision
akColor[uiI01] = 0.5*(akColor[uiI0] + akColor[uiI1] -
fDSqr*rkBP.m_kCuu);
// left v-edge subdivision
akColor[uiI02] = 0.5*(akColor[uiI0] + akColor[uiI2] -
fDSqr*rkBP.m_kCvv);
// hypotenuse edge subdivision
akColor[uiI12] = 0.5*(akColor[uiI1] + akColor[uiI2] -
fDSqr*rkBP.m_kChh);
}
// textures
if ( akTexture )
{
// bottom u-edge subdivision
akTexture[uiI01] = 0.5*(akTexture[uiI0]+akTexture[uiI1]
- fDSqr*rkBP.m_kTuu);
// left v-edge subdivision
akTexture[uiI02] = 0.5*(akTexture[uiI0]+akTexture[uiI2]
- fDSqr*rkBP.m_kTvv);
// hypotenuse edge subdivision
akTexture[uiI12] = 0.5*(akTexture[uiI1]+akTexture[uiI2]
- fDSqr*rkBP.m_kThh);
}
// recurse on four children
if ( uiLevel > 0 )
{
uiLevel--;
fDSqr *= 0.25;
// subtriangle <(s0,t0),(sm,t0),(s0,tm)>
SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,uiI0,uiI01,
uiI02,rkBP);
// subtriangle <(sm,t0),(s1,t0),(sm,tm)>
SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,uiI01,uiI1,
uiI12,rkBP);
// subtriangle <(s0,tm),(sm,tm),(s0,t1)>
SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,uiI02,uiI12,
uiI2,rkBP);
// subtriangle <(sm,t0),(sm,tm),(s0,tm)>
SubdivideUR(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,uiI01,uiI12,
uiI02,rkBP);
}
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2::SubdivideUR (unsigned int uiLevel, MgcReal fDSqr,
MgcVector3* akX, MgcVector3* akXu, MgcVector3* akXv, MgcColor* akColor,
MgcVector2* akTexture, unsigned int uiI0, unsigned int uiI1,
unsigned int uiI2, BlockParameters& rkBP)
{
/*
i2 i1
+----+
\ |
\|
+
i0
*/
// subdivision indices
unsigned int uiI12 = (uiI1 + uiI2) >> 1;
unsigned int uiD12 = uiI1 - uiI2;
unsigned int uiI01 = (((uiI0 + uiI1) << 2) + uiD12*uiD12) >> 3;
unsigned int uiI02 = uiI01 - (uiD12 >> 1);
// vertices
// top u-edge subdivision
akX[uiI12] = 0.5*(akX[uiI1] + akX[uiI2] - fDSqr*rkBP.m_kXuu);
// right v-edge subdivision
akX[uiI01] = 0.5*(akX[uiI0] + akX[uiI1] - fDSqr*rkBP.m_kXvv);
// hypotenuse edge subdivision
akX[uiI02] = 0.5*(akX[uiI0] + akX[uiI2] - fDSqr*rkBP.m_kXhh);
// colors
MgcColor kCuu12, kCvv12, kChh12, kCuu01, kCvv01, kChh01, kCuu02, kCvv02,
kChh02;
if ( akColor )
{
// top u-edge subdivision
akColor[uiI12] = 0.5*(akColor[uiI1] + akColor[uiI2] -
fDSqr*rkBP.m_kCuu);
// right v-edge subdivision
akColor[uiI01] = 0.5*(akColor[uiI0] + akColor[uiI1] -
fDSqr*rkBP.m_kCvv);
// hypotenuse edge subdivision
akColor[uiI02] = 0.5*(akColor[uiI0] + akColor[uiI2] -
fDSqr*rkBP.m_kChh);
}
// textures
if ( akTexture )
{
// top u-edge subdivision
akTexture[uiI12] = 0.5*(akTexture[uiI1]+akTexture[uiI2]
- fDSqr*rkBP.m_kTuu);
// right v-edge subdivision
akTexture[uiI01] = 0.5*(akTexture[uiI0]+akTexture[uiI1]
- fDSqr*rkBP.m_kTvv);
// hypotenuse edge subdivision
akTexture[uiI02] = 0.5*(akTexture[uiI0]+akTexture[uiI2]
- fDSqr*rkBP.m_kThh);
}
// recurse on four children
if ( uiLevel > 0 )
{
uiLevel--;
fDSqr *= 0.25;
// subtriangle <(sm,tm),(sm,t1),(s0,t1)>
SubdivideUR(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,uiI02,uiI12,
uiI2,rkBP);
// subtriangle <(s1,tm),(s1,t1),(sm,t1)>
SubdivideUR(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,uiI01,uiI1,
uiI12,rkBP);
// subtriangle <(s1,t0),(s1,tm),(sm,tm)>
SubdivideUR(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,uiI0,uiI01,
uiI02,rkBP);
// subtriangle <(sm,tm),(s1,tm),(sm,t1)>
SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,uiI02,uiI01,
uiI12,rkBP);
}
}
//----------------------------------------------------------------------------
//---------------------------------------------------------------------------
// streaming
//---------------------------------------------------------------------------
MgcObject* MgcBezierTriangle2::Factory (MgcStream& rkStream)
{
MgcBezierTriangle2* pkObject = new MgcBezierTriangle2;
MgcStream::Link* pkLink = new MgcStream::Link(pkObject);
pkObject->Load(rkStream,pkLink);
return pkObject;
}
//---------------------------------------------------------------------------
void MgcBezierTriangle2::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
MgcBezierTriangle::Load(rkStream,pkLink);
}
//---------------------------------------------------------------------------
void MgcBezierTriangle2::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
MgcBezierTriangle::Link(rkStream,pkLink);
}
//---------------------------------------------------------------------------
bool MgcBezierTriangle2::Register (MgcStream& rkStream)
{
return MgcBezierTriangle::Register(rkStream);
}
//---------------------------------------------------------------------------
void MgcBezierTriangle2::Save (MgcStream& rkStream)
{
MgcBezierTriangle::Save(rkStream);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -