gpt4 book ai didi

C++ 创建一个带有部分的立方体

转载 作者:太空狗 更新时间:2023-10-29 23:00:22 25 4
gpt4 key购买 nike

我正在尝试找出一种算法来创建一个立方体/盒子,其中每个维度都可以分为多个部分。创建球体或圆柱体时类似于环和边的东西。

例如,一次获取一个球体的所有顶点可以这样做:

for (int r = 0; r < rings-1; ++r)
{
float u = -M_PI_2 + ((r+1) * M_PI / rings);
float v = -M_PI;

for (int s= 0; s < sides; ++s)
{
float x = radius * cos(u) * cos(v);
float y = radius * sin(u);
float z = radius * cos(u) * sin(v);
add_vertex(x, y, z);
v += 2 * M_PI / sides;
}
}

任何关于如何在理论上做类似事情的帮助将不胜感激。

最佳答案

这是使用堆栈、wslices 和 dslices 创建 cude 的代码。它用于将数组缓冲区绘制到 OpenGL。您可以简单地删除未使用的法线和颜色数组并仅使用顶点数组。不要因为 GLintGLfloat 类型而感到害怕,它们只是 int 和 float 的同义词。

void DrawBox(GLfloat fWidth,GLfloat fHeight,GLfloat fDepth,GLint wslices,GLint dslices,GLint stacks)
{
// Calculate number of primitives on each side of box
// because we can use different tessalation configurations
// we must calculate separate group of box sides

int iTopButtonQuads = wslices * dslices * 2; // Calculate number of quads in top and button sides
int iLeftRightQuads = dslices * stacks * 2; // Calculate number of quads in left and right sides
int iFrontBackQuads = wslices * stacks * 2; // Calculate number of quads in front and back sides

// If we consider to use quads as primitive then each primitive will
// have 4 points, and each point has color, coord and normal attribute.
// So we create separate array to contain each attibute values.

float* pfVertices = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];
float* pfColors = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];
float* pfNormals = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];

int iVertexIndex = 0;

GLfloat Xstep = fWidth / wslices;
GLfloat Ystep = fHeight / stacks;
GLfloat Zstep = fDepth / dslices;

GLfloat firstX = fWidth / 2.0f;
GLfloat firstY = fHeight / 2.0f;
GLfloat firstZ = fDepth / 2.0f;

GLfloat currX = 0.0f;
GLfloat currY = 0.0f;
GLfloat currZ = 0.0f;

GLfloat x_status = 0.0f;
GLfloat y_status = 0.0f;
GLfloat z_status = 0.0f;

// the bottom and the top of the box
for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
{
for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
{
int iCurrentIndex = iVertexIndex * 3 * 4;

float pfNormal[3] = { 0.0f, -1.0f, 0.0f };

memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

float pfColor[3] = { 1.0f, 0.0f, 0.0f };

memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

float pfVertex0[3] = {currX,-firstY,currZ};
float pfVertex1[3] = {currX + Xstep,-firstY,currZ};
float pfVertex2[3] = {currX + Xstep,-firstY,currZ + Zstep};
float pfVertex3[3] = {currX,-firstY,currZ + Zstep};

memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

iVertexIndex++;
}

for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
{
int iCurrentIndex = iVertexIndex * 3 * 4;

float pfNormal[3] = { 0.0f, 1.0f, 0.0f };

memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

float pfColor[3] = { 0.0f, 1.0f, 0.0f };

memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

float pfVertex0[3] = {currX + Xstep,firstY,currZ + Zstep};
float pfVertex1[3] = {currX + Xstep,firstY,currZ};
float pfVertex2[3] = {currX,firstY,currZ};
float pfVertex3[3] = {currX,firstY,currZ + Zstep};

memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

iVertexIndex++;
}
}

// the front and the back of the box
for (currY = -firstY, y_status = 0.0f; currY < firstY - Ystep / 2.0f ; currY += Ystep, y_status += Ystep)
{
for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
{
int iCurrentIndex = iVertexIndex * 3 * 4;

float pfNormal[3] = { 0.0f, 0.0f, 1.0f };

memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

float pfColor[3] = { 0.0f, 0.0f, 1.0f };

memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

float pfVertex0[3] = {currX,currY,firstZ};
float pfVertex1[3] = {currX + Xstep,currY,firstZ};
float pfVertex2[3] = {currX + Xstep,currY + Ystep,firstZ};
float pfVertex3[3] = {currX,currY + Ystep,firstZ};

memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

iVertexIndex++;
}

for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
{
int iCurrentIndex = iVertexIndex * 3 * 4;

float pfNormal[3] = { 0.0f, 0.0f, -1.0f };

memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

float pfColor[3] = { 0.0f, 1.0f, 1.0f };

memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

float pfVertex0[3] = {currX + Xstep,currY + Ystep,-firstZ};
float pfVertex1[3] = {currX + Xstep,currY,-firstZ};
float pfVertex2[3] = {currX,currY,-firstZ};
float pfVertex3[3] = {currX,currY + Ystep,-firstZ};

memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

iVertexIndex++;
}
}

// Right side and the left side of the box
for (currY = -firstY, y_status = 0.0f; currY < firstY - Ystep / 2.0f; currY += Ystep, y_status += Ystep)
{
for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
{
int iCurrentIndex = iVertexIndex * 3 * 4;

float pfNormal[3] = { 1.0f, 0.0f, 0.0f };

memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

float pfColor[3] = { 1.0f, 0.0f, 1.0f };

memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

float pfVertex0[3] = {firstX,currY,currZ};
float pfVertex1[3] = {firstX,currY + Ystep,currZ};
float pfVertex2[3] = {firstX,currY + Ystep,currZ + Zstep};
float pfVertex3[3] = {firstX,currY,currZ + Zstep};

memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

iVertexIndex++;
}

for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
{
int iCurrentIndex = iVertexIndex * 3 * 4;

float pfNormal[3] = { -1.0f, 0.0f, 0.0f };

memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

float pfColor[3] = { 1.0f, 1.0f, 0.0f };

memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

float pfVertex0[3] = {-firstX,currY,currZ};
float pfVertex1[3] = {-firstX,currY,currZ + Zstep};
float pfVertex2[3] = {-firstX,currY + Ystep,currZ + Zstep};
float pfVertex3[3] = {-firstX,currY + Ystep,currZ};

memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

iVertexIndex++;
}
}

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glColorPointer(3, GL_FLOAT, 0, (void*)pfColors);
glNormalPointer(GL_FLOAT, 0, (void*)pfNormals);
glVertexPointer(3, GL_FLOAT, 0, (void*)pfVertices);

glDrawArrays(GL_QUADS, 0, (iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 4);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

delete [] pfVertices;
delete [] pfNormals;
delete [] pfColors;
}

这里是优化顶点数组的代码。

// 1254 Verticies
// 2141 Texture Coordinates
// 1227 Normals
// 2248 Triangles

static short face_indicies[2248][9] = {
// Object #-1
{0,15,14 ,0,1,2 ,0,1,2 }, {0,1,15 ,0,3,1 ,0,3,1 }, {1,16,15 ,3,4,1 ,3,4,1 },
{1,2,16 ,3,5,4 ,3,5,4 }, {2,17,16 ,5,6,4 ,5,6,4 }, {2,3,17 ,5,7,6 ,5,7,6 },
{3,18,17 ,7,8,6 ,7,8,6 }, {3,4,18 ,7,9,8 ,7,9,8 }, {4,19,18 ,9,10,8 ,9,10,8 },
//.................................................................
};

static GLfloat vertices [1254][3] = {
{1.32715f,-1.99755f,-0.614826f},{1.32715f,-2.20819f,-0.343913f},{1.32715f,-2.5155f,-0.191263f},
{1.32715f,-2.85867f,-0.187049f},{1.32715f,-3.16964f,-0.332104f},{1.32715f,-3.38686f,-0.597763f},
{1.32715f,-3.46734f,-0.931359f},{1.32715f,-3.39508f,-1.26683f},{1.32715f,-3.18445f,-1.53774f},
//..................................................................
};

static GLfloat normals [1227][3] = {
{-0.45634f,0.376195f,-0.80637f},{0.456348f,0.688811f,-0.563281f},{0.45634f,0.376194f,-0.80637f},
{-0.456348f,0.688811f,-0.563281f},{0.456341f,0.865005f,-0.208615f},{-0.456341f,0.865005f,-0.208615f},
{0.456341f,0.869868f,0.187303f},{-0.456341f,0.869868f,0.187303f},{0.456349f,0.702436f,0.546196f},
//..................................................................
};

static GLfloat textures [2141][2] = {
{0.94929f,0.497934f},{0.99452f,0.477509f},{0.994669f,0.497506f},
{0.949142f,0.47796f},{0.994339f,0.457508f},{0.948961f,0.457992f},
};

////////////////////////////////////////////////////////////////
// These are hard coded for this particular example
GLushort uiIndexes[2248*3]; // Maximum number of indexes
GLfloat vVerts[2248*3][3]; // (Worst case scenario)
GLfloat vText[2248*3][2];
GLfloat vNorms[2248*3][3];
int iLastIndex = 0; // Number of indexes actually used



/////////////////////////////////////////////////////////////////
// Compare two floating point values and return true if they are
// close enough together to be considered the same.
int IsSame(float x, float y, float epsilon)
{
if(fabs(x-y) < epsilon)
return 1;

return 0;
}


///////////////////////////////////////////////////////////////
// Goes through the arrays and looks for duplicate verticies
// that can be shared. This expands the original array somewhat
// and returns the number of true unique verticies that now
// populates the vVerts array.
int IndexTriangles(void)
{
int iFace, iPoint, iMatch;
float e = 0.000001; // How small a difference to equate

// LOOP THROUGH all the faces
int iIndexCount = 0;
for(iFace = 0; iFace < 2248; iFace++)
{
for(iPoint = 0; iPoint < 3; iPoint++)
{
// Search for match
for(iMatch = 0; iMatch < iLastIndex; iMatch++)
{
// If Vertex is the same...
if(IsSame(vertices[face_indicies[iFace][iPoint]][0], vVerts[iMatch][0], e) &&
IsSame(vertices[face_indicies[iFace][iPoint]][1], vVerts[iMatch][1], e) &&
IsSame(vertices[face_indicies[iFace][iPoint]][2], vVerts[iMatch][2], e) &&

// AND the Normal is the same...
IsSame(normals[face_indicies[iFace][iPoint+3]][0], vNorms[iMatch][0], e) &&
IsSame(normals[face_indicies[iFace][iPoint+3]][1], vNorms[iMatch][1], e) &&
IsSame(normals[face_indicies[iFace][iPoint+3]][2], vNorms[iMatch][2], e) &&

// And Texture is the same...
IsSame(textures[face_indicies[iFace][iPoint+6]][0], vText[iMatch][0], e) &&
IsSame(textures[face_indicies[iFace][iPoint+6]][1], vText[iMatch][1], e))
{
// Then add the index only
uiIndexes[iIndexCount] = iMatch;
iIndexCount++;
break;
}
}

// No match found, add this vertex to the end of our list, and update the index array
if(iMatch == iLastIndex)
{
// Add data and new index
memcpy(vVerts[iMatch], vertices[face_indicies[iFace][iPoint]], sizeof(float) * 3);
memcpy(vNorms[iMatch], normals[face_indicies[iFace][iPoint+3]], sizeof(float) * 3);
memcpy(vText[iMatch], textures[face_indicies[iFace][iPoint+6]], sizeof(float) * 2);
uiIndexes[iIndexCount] = iLastIndex;
iIndexCount++;
iLastIndex++;
}
}
}
return iIndexCount;
}

/////////////////////////////////////////////
// Function to stitch the triangles together
// and draw the ship
void DrawModel(void)
{
static int iIndexes = 0;
char cBuffer[32];


// The first time this is called, reindex the triangles. Report the results
// in the window title
if(iIndexes == 0)
{
iIndexes = IndexTriangles();
sprintf(cBuffer,"Verts = %d Indexes = %d", iLastIndex, iIndexes);
glutSetWindowTitle(cBuffer);
}

// Use vertices, normals, and texture coordinates
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

// Here's where the data is now
glVertexPointer(3, GL_FLOAT,0, vVerts);
glNormalPointer(GL_FLOAT, 0, vNorms);
glTexCoordPointer(2, GL_FLOAT, 0, vText);

// Draw them
glDrawElements(GL_TRIANGLES, iIndexes, GL_UNSIGNED_SHORT, uiIndexes);
}

此算法适用于任意网格阵列。 或者只是放置唯一值,这意味着删除出现 curr + step 的值,因此每个循环体必须保留 1 个顶点,而不是全部 4 个。 示例

我们有 4 个顶点

  float pfVertex0[3] = {-firstX,currY,currZ};
float pfVertex1[3] = {-firstX,currY,currZ + Zstep};
float pfVertex2[3] = {-firstX,currY + Ystep,currZ + Zstep};
float pfVertex3[3] = {-firstX,currY + Ystep,currZ};

剩下的唯一顶点将是

  float pfVertex0[3] = {-firstX,currY,currZ};

简单的算术显示 24/4 = 6 != 8所以为了形成合适的盒子,我们只需要在盒子的一侧(2 个顶点)添加额外的迭代。

关于C++ 创建一个带有部分的立方体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33838438/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com