您的位置:首页 > 其它

[6] 胶囊体(Capsule)图形的生成算法

2013-11-09 08:29 211 查看




顶点数据的生成

bool                        YfBuildCapsuleVertices
(
Yreal                   radius,
Yreal                   height,
Yuint                   slices,
Yuint                   stacks,
YeOriginPose            originPose,
Yuint                   vertexStriding,
Yuint                   vertexPos,
void*                   pVerticesBuffer
)
{
Yuint halfStacks = stacks / 2;
if (slices < 2 || halfStacks < 2 || !pVerticesBuffer)
{
return false;
}

Yuint numVertices     = slices * (halfStacks - 1) * 2 + 2;
Yuint numHalfVertices = numVertices / 2;

// 顶点赋值
char* vertexPtr   = (char*)pVerticesBuffer + vertexPos;
YsVector3* curVertexPtr   = NULL;

Yuint nOffset = 0;

Yreal originOffsetY = 0.0f;
if (originPose == YE_ORIGIN_POSE_TOP)
{
originOffsetY = -radius - height*0.5f;
}
else if (originPose == YE_ORIGIN_POSE_BOTTOM)
{
originOffsetY = radius + height*0.5f;
}

Yreal halfHeight = height * 0.5f;
Yreal tallness = radius*2 + height;        // 胶囊体真正高度

// 最高顶点
{
nOffset = 0 * vertexStriding;
curVertexPtr = (YsVector3*)(vertexPtr + nOffset);
curVertexPtr->x = 0.0f;
curVertexPtr->y = halfHeight + radius + originOffsetY;
curVertexPtr->z = 0.0f;
}
// 最底顶点
{
nOffset = numHalfVertices * vertexStriding;
curVertexPtr = (YsVector3*)(vertexPtr + nOffset);
curVertexPtr->x = 0.0f;
curVertexPtr->y = -halfHeight - radius + originOffsetY;
curVertexPtr->z = 0.0f;
}

Yreal* pSinList = YD_NEW_ARRAY(Yreal, slices);
Yreal* pCosList = YD_NEW_ARRAY(Yreal, slices);
Yreal angleXZ;
for (Yuint j = 0; j < slices; j++)
{
angleXZ = YD_REAL_TWAIN_PI * j / slices;
pSinList[j] = yf_sin(angleXZ);
pCosList[j] = yf_cos(angleXZ);
}

for (Yuint i = 1; i < halfStacks; i++)
{
Yreal angleY = YD_REAL_HALF_PI * i / (halfStacks - 1);
Yreal posY = radius * yf_cos(angleY);
Yreal radiusXZ = radius * yf_sin(angleY);
Yreal posX, posZ;

for (Yuint j = 0; j < slices; j++)
{
posX = radiusXZ * pSinList[j % slices];
posZ = radiusXZ * pCosList[j % slices];

nOffset = (1 + (i - 1) * slices + j) * vertexStriding;
curVertexPtr = (YsVector3*)(vertexPtr + nOffset);
curVertexPtr->x = posX;
curVertexPtr->y = posY + halfHeight + originOffsetY;
curVertexPtr->z = posZ;

nOffset = (numHalfVertices + 1 + (i - 1) * slices + j) * vertexStriding;
curVertexPtr = (YsVector3*)(vertexPtr + nOffset);
curVertexPtr->x = posX;
curVertexPtr->y = -posY - halfHeight + originOffsetY;
curVertexPtr->z = posZ;
}
}

YD_SAFE_DELETE_ARRAY(pSinList);
YD_SAFE_DELETE_ARRAY(pCosList);

return true;
}


三角形索引数据的生成

bool                        YfBuildCapsuleTriIndices
(
Yuint                   slices,
Yuint                   stacks,
YeIndexType             indexType,
Yuint                   indexStriding,
Yuint                   indexPos,
void*                   pTriIndicesBuffer
)
{
Yuint halfStacks = stacks / 2;
if (slices < 2 || halfStacks < 2 || !pTriIndicesBuffer)
{
return false;
}

Yuint numVertices  = slices * (halfStacks - 1) * 2 + 2;
if (indexType == YE_INDEX_16_BIT &&
numVertices > YD_MAX_UNSIGNED_INT16)
{
return false;
}
Yuint numHalfVertices = numVertices / 2;
Yuint numTriangles    = slices * (halfStacks - 1) * 4;

// 索引赋值
char* indexPtr = (char*)pTriIndicesBuffer + indexPos;
Yuint nOffset = 0;
if (indexType == YE_INDEX_16_BIT)
{
YsTriIndex16* triIndexPtr = NULL;

for (Yuint i = 0; i < halfStacks - 1; i++)
{
if (i == 0)                                 // 第一层
{
for (Yuint j = 0; j < slices; j++)
{
nOffset = j * 2 * indexStriding;
triIndexPtr = (YsTriIndex16*)(indexPtr + nOffset);
triIndexPtr->index0 = 0;
triIndexPtr->index1 = 1 + j;
triIndexPtr->index2 = 1 + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex16*)(indexPtr + nOffset);
triIndexPtr->index0 = numHalfVertices;
triIndexPtr->index1 = numHalfVertices + 1 + (j + 1)%slices;
triIndexPtr->index2 = numHalfVertices + 1 + j;
}
}
else
{
for (Yuint j = 0; j < slices; j++)
{
nOffset = ((i - 1)*slices*4 + slices*2 + j*4) * indexStriding;
triIndexPtr = (YsTriIndex16*)(indexPtr + nOffset);
triIndexPtr->index0 = 1 + slices * (i - 1) + j;
triIndexPtr->index1 = 1 + slices * i + j;
triIndexPtr->index2 = 1 + slices * (i - 1) + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex16*)(indexPtr + nOffset);
triIndexPtr->index0 = 1 + slices * (i - 1) + (j + 1)%slices;
triIndexPtr->index1 = 1 + slices * i + j;
triIndexPtr->index2 = 1 + slices * i + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex16*)(indexPtr + nOffset);
triIndexPtr->index0 = numHalfVertices + 1 + slices * (i - 1) + j;
triIndexPtr->index1 = numHalfVertices + 1 + slices * (i - 1) + (j + 1)%slices;
triIndexPtr->index2 = numHalfVertices + 1 + slices * i + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex16*)(indexPtr + nOffset);
triIndexPtr->index0 = numHalfVertices + 1 + slices * (i - 1) + j;
triIndexPtr->index1 = numHalfVertices + 1 + slices * i + (j + 1)%slices;
triIndexPtr->index2 = numHalfVertices + 1 + slices * i + j;
}
}
}

// 连接两个半球
for (Yuint j = 0; j < slices; j++)
{
nOffset = ((halfStacks - 2)*slices*4 + slices*2 + j*2) * indexStriding;
triIndexPtr = (YsTriIndex16*)(indexPtr + nOffset);
triIndexPtr->index0 = 1 + slices  * (halfStacks - 2) + j;
triIndexPtr->index1 = numHalfVertices + 1 + slices * (halfStacks - 2) + j;
triIndexPtr->index2 = 1 + slices * (halfStacks - 2) + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex16*)(indexPtr + nOffset);
triIndexPtr->index0 = 1 + slices * (halfStacks - 2) + (j + 1)%slices;
triIndexPtr->index1 = numHalfVertices + 1 + slices * (halfStacks - 2) + j;
triIndexPtr->index2 = numHalfVertices + 1 + slices * (halfStacks - 2) + (j + 1)%slices;
}
}
else
{
YsTriIndex32* triIndexPtr = NULL;

for (Yuint i = 0; i < halfStacks - 1; i++)
{
if (i == 0)                                 // 第一层
{
for (Yuint j = 0; j < slices; j++)
{
nOffset = j * 2 * indexStriding;
triIndexPtr = (YsTriIndex32*)(indexPtr + nOffset);
triIndexPtr->index0 = 0;
triIndexPtr->index1 = 1 + j;
triIndexPtr->index2 = 1 + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex32*)(indexPtr + nOffset);
triIndexPtr->index0 = numHalfVertices;
triIndexPtr->index1 = numHalfVertices + 1 + (j + 1)%slices;
triIndexPtr->index2 = numHalfVertices + (j + 1)%slices;
}
}
else
{
for (Yuint j = 0; j < slices; j++)
{
nOffset = ((i - 1)*slices*4 + slices*2 + j*4) * indexStriding;
triIndexPtr = (YsTriIndex32*)(indexPtr + nOffset);
triIndexPtr->index0 = 1 + slices * (i - 1) + j;
triIndexPtr->index1 = 1 + slices * i + j;
triIndexPtr->index2 = 1 + slices * (i - 1) + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex32*)(indexPtr + nOffset);
triIndexPtr->index0 = 1 + slices * (i - 1) + (j + 1)%slices;
triIndexPtr->index1 = 1 + slices * i + j;
triIndexPtr->index2 = 1 + slices * i + j + 1;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex32*)(indexPtr + nOffset);
triIndexPtr->index0 = numHalfVertices + 1 + slices * (i - 1) + j;
triIndexPtr->index1 = numHalfVertices + 1 + slices * (i - 1) + (j + 1)%slices;
triIndexPtr->index2 = numHalfVertices + 1 + slices * i + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex32*)(indexPtr + nOffset);
triIndexPtr->index0 = numHalfVertices + 1 + slices * (i - 1) + j;
triIndexPtr->index1 = numHalfVertices + 1 + slices * i + (j + 1)%slices;
triIndexPtr->index2 = numHalfVertices + 1 + slices * i + j;
}
}
}

// 连接两个半球
for (Yuint j = 0; j < slices; j++)
{
nOffset = ((halfStacks - 2)*slices*4 + slices*2 + j*2) * indexStriding;
triIndexPtr = (YsTriIndex32*)(indexPtr + nOffset);
triIndexPtr->index0 = 1 + slices  * (halfStacks - 2) + j;
triIndexPtr->index1 = numHalfVertices + 1 + slices * (halfStacks - 2) + j;
triIndexPtr->index2 = 1 + slices * (halfStacks - 2) + (j + 1)%slices;

nOffset += indexStriding;
triIndexPtr = (YsTriIndex32*)(indexPtr + nOffset);
triIndexPtr->index0 = 1 + slices * (halfStacks - 2) + (j + 1)%slices;
triIndexPtr->index1 = numHalfVertices + 1 + slices * (halfStacks - 2) + j;
triIndexPtr->index2 = numHalfVertices + 1 + slices * (halfStacks - 2) + (j + 1)%slices;
}
}

return true;
}


线框索引数据的生成

bool                        YfBuildCapsuleWireIndices
(
Yuint                   slices,
Yuint                   stacks,
YeIndexType             indexType,
Yuint                   indexStriding,
Yuint                   indexPos,
void*                   pWireIndicesBuffer
)
{
Yuint halfStacks = stacks / 2;
if (slices < 2 || halfStacks < 2 || !pWireIndicesBuffer)
{
return false;
}

Yuint numVertices  = slices * (halfStacks - 1) * 2 + 2;
Yuint numLines     = slices * (halfStacks - 1) * 2 + slices * (2 * halfStacks - 1);
Yuint numHalfVertices = numVertices / 2;
if (indexType == YE_INDEX_16_BIT &&
numVertices > YD_MAX_UNSIGNED_INT16)
{
return false;
}

// 索引赋值
char* indexPtr = (char*)pWireIndicesBuffer + indexPos;
Yuint nOffset = 0;
if (indexType == YE_INDEX_16_BIT)
{
YsLineIndex16* lineIndexPtr = NULL;
for (Yuint i = 1; i < halfStacks; i++)
{
for (Yuint j = 0; j < slices; j++)
{
nOffset = ((i - 1)*slices + j) * 2 * indexStriding;
lineIndexPtr = (YsLineIndex16*)(indexPtr + nOffset);
lineIndexPtr->index0 = 1 + (i - 1)*slices + j;
lineIndexPtr->index1 = 1 + (i - 1)*slices + (j + 1)%slices;

nOffset += indexStriding;
lineIndexPtr = (YsLineIndex16*)(indexPtr + nOffset);
lineIndexPtr->index0 = numHalfVertices + 1 + (i - 1)*slices + j;
lineIndexPtr->index1 = numHalfVertices + 1 + (i - 1)*slices + (j + 1)%slices;
}
}

Yuint half = (halfStacks - 1) * slices *2;
for (Yuint j = 0; j < slices; j++)
{
for (Yuint i = 0; i < halfStacks - 1; i++)
{
if (i == 0)
{
nOffset = (half + (halfStacks*2 - 1) * j) * indexStriding;
lineIndexPtr = (YsLineIndex16*)(indexPtr + nOffset);
lineIndexPtr->index0 = 0;
lineIndexPtr->index1 = 1 + j;

nOffset += indexStriding;
lineIndexPtr = (YsLineIndex16*)(indexPtr + nOffset);
lineIndexPtr->index0 = numHalfVertices;
lineIndexPtr->index1 = numHalfVertices + 1 + j;
}
else
{
nOffset = (half + (halfStacks*2 - 1) * j + i * 2) * indexStriding;
lineIndexPtr = (YsLineIndex16*)(indexPtr + nOffset);
lineIndexPtr->index0 = 1 + slices*(i - 1) + j;
lineIndexPtr->index1 = 1 + slices*i + j;

nOffset += indexStriding;
lineIndexPtr = (YsLineIndex16*)(indexPtr + nOffset);
lineIndexPtr->index0 = numHalfVertices + 1 + slices*(i - 1) + j;
lineIndexPtr->index1 = numHalfVertices + 1 + slices*i + j;
}
}

nOffset = (half + (halfStacks*2 - 1) * (j + 1) - 1) * indexStriding;
lineIndexPtr = (YsLineIndex16*)(indexPtr + nOffset);
lineIndexPtr->index0 = 1 + slices  * (halfStacks - 2) + j;
lineIndexPtr->index1 = numHalfVertices + 1 + slices * (halfStacks - 2) + j;
}
}
else
{
YsLineIndex32* lineIndexPtr = NULL;
for (Yuint i= 0; i < slices; i++)
{
YsLineIndex32* lineIndexPtr = NULL;
for (Yuint i = 1; i < halfStacks; i++)
{
for (Yuint j = 0; j < slices; j++)
{
nOffset = ((i - 1)*slices + j) * 2 * indexStriding;
lineIndexPtr = (YsLineIndex32*)(indexPtr + nOffset);
lineIndexPtr->index0 = 1 + (i - 1)*slices + j;
lineIndexPtr->index1 = 1 + (i - 1)*slices + (j + 1)%slices;

nOffset += indexStriding;
lineIndexPtr = (YsLineIndex32*)(indexPtr + nOffset);
lineIndexPtr->index0 = numHalfVertices + 1 + (i - 1)*slices + j;
lineIndexPtr->index1 = numHalfVertices + 1 + (i - 1)*slices + (j + 1)%slices;
}
}

Yuint half = (halfStacks - 1) * slices *2;
for (Yuint j = 0; j < slices; j++)
{
for (Yuint i = 0; i < halfStacks - 1; i++)
{
if (i == 0)
{
nOffset = (half + (halfStacks*2 - 1) * j) * indexStriding;
lineIndexPtr = (YsLineIndex32*)(indexPtr + nOffset);
lineIndexPtr->index0 = 0;
lineIndexPtr->index1 = 1 + j;

nOffset += indexStriding;
lineIndexPtr = (YsLineIndex32*)(indexPtr + nOffset);
lineIndexPtr->index0 = numHalfVertices;
lineIndexPtr->index1 = numHalfVertices + 1 + j;
}
else
{
nOffset = (half + (halfStacks*2 - 1) * j + i * 2) * indexStriding;
lineIndexPtr = (YsLineIndex32*)(indexPtr + nOffset);
lineIndexPtr->index0 = 1 + slices*(i - 1) + j;
lineIndexPtr->index1 = 1 + slices*i + j;

nOffset += indexStriding;
lineIndexPtr = (YsLineIndex32*)(indexPtr + nOffset);
lineIndexPtr->index0 = numHalfVertices + 1 + slices*(i - 1) + j;
lineIndexPtr->index1 = numHalfVertices + 1 + slices*i + j;
}
}

nOffset = (half + (halfStacks*2 - 1) * (j + 1) - 1) * indexStriding;
lineIndexPtr = (YsLineIndex32*)(indexPtr + nOffset);
lineIndexPtr->index0 = 1 + slices  * (halfStacks - 2) + j;
lineIndexPtr->index1 = numHalfVertices + 1 + slices * (halfStacks - 2) + j;
}
}
}

return true;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: