📄 wmlstandardmesh.cpp
字号:
}
//----------------------------------------------------------------------------
void Wml::CreateSphereMesh (TriMesh*& rpkMesh, int iZSamples,
int iRadialSamples, const Vector3f& rkCenter, float fRadius,
const Vector3f& rkU, const Vector3f& rkV, const Vector3f& rkAxis,
bool bWantNormals, bool bWantColors, bool bWantUVs, bool bOutsideView)
{
int iZSm1 = iZSamples-1, iZSm2 = iZSamples-2, iZSm3 = iZSamples-3;
int iRSp1 = iRadialSamples+1;
// allocate vertices
int iVQuantity = iZSm2*iRSp1 + 2;
Vector3f* akVertex = new Vector3f[iVQuantity];
// allocate normals if requested
Vector3f* akNormal = NULL;
if ( bWantNormals )
akNormal = new Vector3f[iVQuantity];
// allocate colors if requested
ColorRGB* akColor = NULL;
if ( bWantColors )
{
akColor = new ColorRGB[iVQuantity];
memset(akColor,0,iVQuantity*sizeof(ColorRGB));
}
// allocate texture coordinates if requested
Vector2f* akUV = NULL;
if ( bWantUVs )
akUV = new Vector2f[iVQuantity];
// allocate connectivity
int iTQuantity = 2*iZSm2*iRadialSamples;
int* aiConnect = new int[3*iTQuantity];
// generate geometry
float fInvRS = 1.0f/(float)iRadialSamples;
float fZFactor = 2.0f/(float)iZSm1;
int iR, iZ, iZStart, i;
// Generate points on the unit circle to be used in computing the mesh
// points on a cylinder slice.
float* afSin = new float[iRSp1];
float* afCos = new float[iRSp1];
for (iR = 0; iR < iRadialSamples; iR++)
{
float fAngle = Mathf::TWO_PI*fInvRS*iR;
afCos[iR] = Mathf::Cos(fAngle);
afSin[iR] = Mathf::Sin(fAngle);
}
afSin[iRadialSamples] = afSin[0];
afCos[iRadialSamples] = afCos[0];
// generate the cylinder itself
for (iZ = 1, i = 0; iZ < iZSm1; iZ++)
{
float fZFraction = -1.0f + fZFactor*iZ; // in (-1,1)
float fZ = fRadius*fZFraction;
// compute center of slice
Vector3f kSliceCenter = rkCenter + fZ*rkAxis;
// compute radius of slice
float fSliceRadius = Mathf::Sqrt(Mathf::FAbs(fRadius*fRadius-fZ*fZ));
// compute slice vertices with duplication at end point
Vector3f kNormal;
int iSave = i;
for (iR = 0; iR < iRadialSamples; iR++)
{
float fRadialFraction = iR*fInvRS; // in [0,1)
Vector3f kRadial = afCos[iR]*rkU + afSin[iR]*rkV;
akVertex[i] = kSliceCenter + fSliceRadius*kRadial;
if ( bWantNormals )
{
kNormal = akVertex[i] - rkCenter;
kNormal.Normalize();
if ( bOutsideView )
akNormal[i] = kNormal;
else
akNormal[i] = -kNormal;
}
if ( bWantUVs )
{
akUV[i].X() = fRadialFraction;
akUV[i].Y() = 0.5f*(fZFraction+1.0f);
}
i++;
}
akVertex[i] = akVertex[iSave];
if ( bWantNormals )
{
akNormal[i] = akNormal[iSave];
}
if ( bWantUVs )
{
akUV[i].X() = 1.0f;
akUV[i].Y() = 0.5f*(fZFraction+1.0f);
}
i++;
}
// south pole
akVertex[i] = rkCenter - fRadius*rkAxis;
if ( bWantNormals )
{
if ( bOutsideView )
akNormal[i] = -rkAxis;
else
akNormal[i] = rkAxis;
}
if ( bWantUVs )
{
akUV[i].X() = 0.5f;
akUV[i].Y() = 0.0f;
}
i++;
// north pole
akVertex[i] = rkCenter + fRadius*rkAxis;
if ( bWantNormals )
{
if ( bOutsideView )
akNormal[i] = rkAxis;
else
akNormal[i] = -rkAxis;
}
if ( bWantUVs )
{
akUV[i].X() = 0.5f;
akUV[i].Y() = 1.0f;
}
i++;
assert( i == iVQuantity );
// generate connectivity
int* aiLocalConnect = aiConnect;
for (iZ = 0, iZStart = 0; iZ < iZSm3; iZ++)
{
int i0 = iZStart;
int i1 = i0 + 1;
iZStart += iRSp1;
int i2 = iZStart;
int i3 = i2 + 1;
for (i = 0; i < iRadialSamples; i++, aiLocalConnect += 6)
{
if ( bOutsideView )
{
aiLocalConnect[0] = i0++;
aiLocalConnect[1] = i1;
aiLocalConnect[2] = i2;
aiLocalConnect[3] = i1++;
aiLocalConnect[4] = i3++;
aiLocalConnect[5] = i2++;
}
else // inside view
{
aiLocalConnect[0] = i0++;
aiLocalConnect[1] = i2;
aiLocalConnect[2] = i1;
aiLocalConnect[3] = i1++;
aiLocalConnect[4] = i2++;
aiLocalConnect[5] = i3++;
}
}
}
// south pole triangles
int iVQm2 = iVQuantity-2;
for (i = 0; i < iRadialSamples; i++, aiLocalConnect += 3)
{
if ( bOutsideView )
{
aiLocalConnect[0] = i;
aiLocalConnect[1] = iVQm2;
aiLocalConnect[2] = i+1;
}
else // inside view
{
aiLocalConnect[0] = i;
aiLocalConnect[1] = i+1;
aiLocalConnect[2] = iVQm2;
}
}
// north pole triangles
int iVQm1 = iVQuantity-1, iOffset = iZSm3*iRSp1;
for (i = 0; i < iRadialSamples; i++, aiLocalConnect += 3)
{
if ( bOutsideView )
{
aiLocalConnect[0] = i+iOffset;
aiLocalConnect[1] = i+1+iOffset;
aiLocalConnect[2] = iVQm1;
}
else // inside view
{
aiLocalConnect[0] = i+iOffset;
aiLocalConnect[1] = iVQm1;
aiLocalConnect[2] = i+1+iOffset;
}
}
int* aiFinalConnect = aiConnect + 3*iTQuantity;
assert( aiLocalConnect == aiFinalConnect );
delete[] afCos;
delete[] afSin;
if ( rpkMesh )
{
rpkMesh->Reconstruct(iVQuantity,akVertex,akNormal,akColor,akUV,
iTQuantity,aiConnect);
}
else
{
rpkMesh = new TriMesh(iVQuantity,akVertex,akNormal,akColor,akUV,
iTQuantity,aiConnect);
}
}
//----------------------------------------------------------------------------
void Wml::CreateTorusMesh (TriMesh*& rpkMesh, int iCircleSamples,
int iRadialSamples, const Vector3f& rkCenter, const Vector3f& rkU,
const Vector3f& rkV, const Vector3f& rkAxis, float fOuterRadius,
float fInnerRadius, bool bWantNormals, bool bWantColors, bool bWantUVs,
bool bOutsideView)
{
// allocate vertices
int iVQuantity = (iCircleSamples+1)*(iRadialSamples+1);
Vector3f* akVertex = new Vector3f[iVQuantity];
// allocate normals if requested
Vector3f* akNormal = NULL;
if ( bWantNormals )
akNormal = new Vector3f[iVQuantity];
// allocate colors if requested
ColorRGB* akColor = NULL;
if ( bWantColors )
{
akColor = new ColorRGB[iVQuantity];
memset(akColor,0,iVQuantity*sizeof(ColorRGB));
}
// allocate texture coordinates if requested
Vector2f* akUV = NULL;
if ( bWantUVs )
akUV = new Vector2f[iVQuantity];
// allocate connectivity
int iTQuantity = 2*iCircleSamples*iRadialSamples;
int* aiConnect = new int[3*iTQuantity];
// generate geometry
float fInvCS = 1.0f/(float)iCircleSamples;
float fInvRS = 1.0f/(float)iRadialSamples;
int iC, iR, i;
// generate the cylinder itself
for (iC = 0, i = 0; iC < iCircleSamples; iC++)
{
// compute center point on torus circle at specified angle
float fCircleFraction = iC*fInvCS; // in [0,1)
float fTheta = Mathf::TWO_PI*fCircleFraction;
float fCosTheta = Mathf::Cos(fTheta);
float fSinTheta = Mathf::Sin(fTheta);
Vector3f kRadial = fCosTheta*rkU + fSinTheta*rkV;
Vector3f kTorusMiddle = rkCenter + fOuterRadius*kRadial;
// compute slice vertices with duplication at end point
int iSave = i;
for (iR = 0; iR < iRadialSamples; iR++)
{
float fRadialFraction = iR*fInvRS; // in [0,1)
float fPhi = Mathf::TWO_PI*fRadialFraction;
float fCosPhi = Mathf::Cos(fPhi);
float fSinPhi = Mathf::Sin(fPhi);
Vector3f kNormal = fCosPhi*kRadial + fSinPhi*rkAxis;
akVertex[i] = kTorusMiddle + fInnerRadius*kNormal;
if ( bWantNormals )
{
if ( bOutsideView )
akNormal[i] = kNormal;
else
akNormal[i] = -kNormal;
}
if ( bWantUVs )
{
akUV[i].X() = fRadialFraction;
akUV[i].Y() = fCircleFraction;
}
i++;
}
akVertex[i] = akVertex[iSave];
if ( bWantNormals )
{
akNormal[i] = akNormal[iSave];
}
if ( bWantUVs )
{
akUV[i].X() = 1.0f;
akUV[i].Y() = fCircleFraction;
}
i++;
}
// duplicate the cylinder ends to form a torus
for (iR = 0; iR <= iRadialSamples; iR++, i++)
{
akVertex[i] = akVertex[iR];
if ( bWantNormals )
{
akNormal[i] = akNormal[iR];
}
if ( bWantUVs )
{
akUV[i].X() = akUV[iR].X();
akUV[i].Y() = 1.0f;
}
}
assert( i == iVQuantity );
// generate connectivity
int* aiLocalConnect = aiConnect;
int iCStart = 0;
for (iC = 0; iC < iCircleSamples; iC++)
{
int i0 = iCStart;
int i1 = i0 + 1;
iCStart += iRadialSamples + 1;
int i2 = iCStart;
int i3 = i2 + 1;
for (i = 0; i < iRadialSamples; i++, aiLocalConnect += 6)
{
if ( bOutsideView )
{
aiLocalConnect[0] = i0++;
aiLocalConnect[1] = i2;
aiLocalConnect[2] = i1;
aiLocalConnect[3] = i1++;
aiLocalConnect[4] = i2++;
aiLocalConnect[5] = i3++;
}
else // inside view
{
aiLocalConnect[0] = i0++;
aiLocalConnect[1] = i1;
aiLocalConnect[2] = i2;
aiLocalConnect[3] = i1++;
aiLocalConnect[4] = i3++;
aiLocalConnect[5] = i2++;
}
}
}
if ( rpkMesh )
{
rpkMesh->Reconstruct(iVQuantity,akVertex,akNormal,akColor,akUV,
iTQuantity,aiConnect);
}
else
{
rpkMesh = new TriMesh(iVQuantity,akVertex,akNormal,akColor,akUV,
iTQuantity,aiConnect);
}
}
//----------------------------------------------------------------------------
void Wml::CreateTetrahedronMesh (TriMesh*& rpkMesh, bool bWantNormals,
bool bWantColors, bool bWantUVs, bool bOutsideView)
{
float fSqrt2Div3 = Mathf::Sqrt(2.0f)/3.0f;
float fSqrt6Div3 = Mathf::Sqrt(6.0f)/3.0f;
float fOneThird = 1.0f/3.0f;
int i;
// allocate vertices
int iVQuantity = 4;
Vector3f* akVertex = new Vector3f[iVQuantity];
akVertex[0] = Vector3f(0.0f,0.0f,1.0f);
akVertex[1] = Vector3f(2.0f*fSqrt2Div3,0.0f,-fOneThird);
akVertex[2] = Vector3f(-fSqrt2Div3,fSqrt6Div3,-fOneThird);
akVertex[3] = Vector3f(-fSqrt2Div3,-fSqrt6Div3,-fOneThird);
// allocate normals if requested
Vector3f* akNormal = NULL;
if ( bWantNormals )
{
akNormal = new Vector3f[iVQuantity];
for (i = 0; i < iVQuantity; i++)
akNormal[i] = akVertex[i];
}
// allocate colors if requested
ColorRGB* akColor = NULL;
if ( bWantColors )
{
akColor = new ColorRGB[iVQuantity];
memset(akColor,0,iVQuantity*sizeof(ColorRGB));
}
// allocate texture coordinates if requested
Vector2f* akUV = NULL;
if ( bWantUVs )
{
akUV = new Vector2f[iVQuantity];
for (i = 0; i < iVQuantity; i++)
{
if ( Mathf::FAbs(akVertex[i].Z()) < 1.0f )
{
akUV[i].X() = 0.5f*(1.0f + Mathf::ATan2(akVertex[i].Y(),
akVertex[i].X())*Mathf::INV_PI);
}
else
{
akUV[i].X() = 0.5f;
}
akUV[i].Y() = Mathf::ACos(akVertex[i].Z())*Mathf::INV_PI;
}
}
// allocate connectivity
int iTQuantity = 4;
int* aiConnect = new int[3*iTQuantity];
aiConnect[ 0] = 0; aiConnect[ 1] = 1; aiConnect[ 2] = 2;
aiConnect[ 3] = 0; aiConnect[ 4] = 2; aiConnect[ 5] = 3;
aiConnect[ 6] = 0; aiConnect[ 7] = 3; aiConnect[ 8] = 1;
aiConnect[ 9] = 1; aiConnect[10] = 3; aiConnect[11] = 2;
if ( !bOutsideView )
{
for (i = 0; i < iTQuantity; i++)
{
int iSave = aiConnect[3*i+1];
aiConnect[3*i+1] = aiConnect[3*i+2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -