gpt4 book ai didi

c# - 生成的 Icosphere 上的尖峰顶点

转载 作者:行者123 更新时间:2023-11-30 18:03:47 28 4
gpt4 key购买 nike

我一直在研究一个生成 icosphere 的程序。 (一个顶点分布均匀的球体,用于地形变形)

我几乎完成了所有工作,生成、分割并绘制了球体。我遇到的问题是,在代码的某处,一些顶点(我相信是十二个起始顶点)被设置为半径的两倍,而不仅仅是半径。

这是三张图片,分别显示了零、一和两次细化过程中的棱角层:

http://i41.photobucket.com/albums/e262/cstgirllover/Cho/Ico0Refinement.png

http://i41.photobucket.com/albums/e262/cstgirllover/Cho/Ico1Refinement.png

http://i41.photobucket.com/albums/e262/cstgirllover/Cho/Ico2Refinement.png

下面是生成二十面体的代码,然后将其分解为二十面体:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Icosahedron_Test
{
class Icosahedron
{
int radius; // radius of the planet
int refinement; // number of times to refine the traingles
int faces = 20;
Vector3[] basePositions; // Vertex points for three defining rectangles
TriXYZ[] vertices; // Vertex points for triangles which define the spherical surface

public Icosahedron(int tRadius, int tRefinement, TriXYZ[] tVertices)
{
radius = tRadius;
refinement = tRefinement;
vertices = tVertices;
}

public TriXYZ[] InitializeArray()
{
double t = radius*((1+Math.Sqrt(5))/2);

Vector3[] basePositions =
{
//First Rectangle
new Vector3(-radius, (float)t, 0),
new Vector3(radius, (float)t, 0),
new Vector3(-radius, (float)-t, 0),
new Vector3(radius, (float)-t, 0),

//Seconds Rectangle
new Vector3(0, -radius, (float)t),
new Vector3(0, radius, (float)t),
new Vector3(0, -radius, (float)-t),
new Vector3(0, radius, (float)-t),

//Third Rectangle
new Vector3((float)t, 0, -radius),
new Vector3((float)t, 0, radius),
new Vector3((float)-t, 0, -radius),
new Vector3((float)-t, 0, radius)
};

TriXYZ[] vertices =
{
new TriXYZ(basePositions[5], basePositions[11], basePositions[0], 1),
new TriXYZ(basePositions[1], basePositions[5], basePositions[0], 1),
new TriXYZ(basePositions[7], basePositions[1], basePositions[0], 1),
new TriXYZ(basePositions[10], basePositions[7], basePositions[0], 1),
new TriXYZ(basePositions[11], basePositions[10], basePositions[0], 1),

new TriXYZ(basePositions[9], basePositions[5], basePositions[1], 1),
new TriXYZ(basePositions[4], basePositions[11], basePositions[5], 1),
new TriXYZ(basePositions[2], basePositions[10], basePositions[11], 1),
new TriXYZ(basePositions[6], basePositions[7], basePositions[10], 1),
new TriXYZ(basePositions[8], basePositions[1], basePositions[7], 1),

new TriXYZ(basePositions[4], basePositions[9], basePositions[3], 1),
new TriXYZ(basePositions[2], basePositions[4], basePositions[3], 1),
new TriXYZ(basePositions[6], basePositions[2], basePositions[3], 1),
new TriXYZ(basePositions[8], basePositions[6], basePositions[3], 1),
new TriXYZ(basePositions[9], basePositions[8], basePositions[3], 1),

new TriXYZ(basePositions[5], basePositions[9], basePositions[4], 1),
new TriXYZ(basePositions[11], basePositions[4], basePositions[2], 1),
new TriXYZ(basePositions[10], basePositions[2], basePositions[6], 1),
new TriXYZ(basePositions[7], basePositions[6], basePositions[8], 1),
new TriXYZ(basePositions[1], basePositions[8], basePositions[9], 1),

};

return vertices;
}

public TriXYZ[] Refine(TriXYZ[] rVertices, int rRefinement, float radius)
{
TriXYZ[] tVertices; // Temp list of triangles

Vector3 vertex1; // position of first vertex of base triangle
Vector3 vertex2; // position of second vertex of base triangle
Vector3 vertex3; // position of third vertex of base triangle
int tDepth; // depth of the current triangle

//int listPos = 0; // base list position integer
int nListPos = 0; // new list position integer

int cRefine = 0; // current refinement iteration

while(cRefine < rRefinement) // loop until the icosphere has been refined the inputted number of times
{

tVertices = new TriXYZ[20 + (4*rVertices.Length)]; // make the temporary list empty, and long enough for the original 20 triangles, plus four per triangle for each level of refinement.

for (int listPos = 0; listPos < rVertices.Length; listPos++ ) // Loop through every triangle in the list
{
TriXYZ cTriangle = rVertices[listPos];

tDepth = cTriangle.GetDepth;
vertex1 = cTriangle.GetVertex1; // point 0
vertex2 = cTriangle.GetVertex2; // point 1
vertex3 = cTriangle.GetVertex3; // point 2

if (tDepth == cRefine + 1) // if the depth of this triangle in the list equals the current refinement iteration;
// depth one for first refinement pass, depth two for second, etc; subdivide the triangle
// This prevents unnecessarily re-refining old triangles
{
TriXYZ[] parts = new TriXYZ[5];

parts = cTriangle.subDivide(radius);

tVertices[nListPos] = parts[0]; // Put the original larger triangle at the front if the list
tVertices[nListPos + 1] = parts[1]; // First subdivided triangle
tVertices[nListPos + 2] = parts[2]; // Second subdivided triangle
tVertices[nListPos + 3] = parts[3]; // Third subdivided triangle
tVertices[nListPos + 4] = parts[4]; // Fourth subdivided triangle

nListPos = nListPos + 5; // Move forward in the new triangle list so the next set of triangles doesn't overwrite this set.

}
else if (tDepth < cRefine + 1) // Ifthe triangle's depth is less than the current refinement iteration (depth 1 on refinement 2) then add the current triangle to the new list at nListPos
{
tVertices[nListPos] = new TriXYZ(vertex1, vertex2, vertex3, tDepth);
nListPos++;
}
// it shouldn't be possible for the tDepth to be greater than cRefine
} // end for loop: either move to the next triangel in the original list, or move on to the next level of refinement


rVertices = tVertices; // Replace the old list with the new one, so that the next time it
// runs through the refinement process, it will refine the new
// traingles
cRefine++; // increase refinement interation variable so that it will either refine the next set of triangles, or exit the refinement loop.
nListPos = 0; // reset the new list position integer so it overwrites the exiting data

} // end while loop: either move on to the next refinement set, or exit the loop

vertices = rVertices; // make sure the class=level vertices

return rVertices;
} // End Refinement Class

public int Length
{
get { return vertices.Length; }
private set { }
}

public VertexPositionColor[] BuildList(TriXYZ[] tList, int tDepth)
{
VertexPositionColor[] finalList = new VertexPositionColor[tList.Length*3]; // final list to be returned for drawing
int listPos = 0; // current position in the final list (where the vector 3 is being applied)

Vector3 pos1; // Vertex 1 position of TriXYZ triangle
Vector3 pos2; // Vertex 2 position of TriXYZ triangle
Vector3 pos3; // Vertex 3 position of TriXYZ triangle
int depth;

for(int cTri = 0; cTri<tList.Length; cTri+=1) // Loop through the TriXYZ list and get all the vertexes from it, then apply them to the final draw list
{
pos1 = tList[cTri].GetVertex1;
pos2 = tList[cTri].GetVertex2;
pos3 = tList[cTri].GetVertex3;
depth = tList[cTri].GetDepth;

if (depth == tDepth)
{
finalList[listPos] = new VertexPositionColor(pos1, Color.Blue);
finalList[listPos + 1] = new VertexPositionColor(pos2, Color.Red);
finalList[listPos + 2] = new VertexPositionColor(pos3, Color.Green);

listPos = listPos + 3;

}
}

return finalList;
}


}
}

这是保存三角形数据的 TriXYZ 类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Icosahedron_Test
{
class TriXYZ
{
Vector3 vertex1;
Vector3 vertex2;
Vector3 vertex3;
int depth;
float material1; // float for first material value amount (in %) deals with blending
float material2; // float for second material value amount (in %) deals with blending

public TriXYZ(Vector3 pos1, Vector3 pos2, Vector3 pos3, int tDepth)
{
vertex1 = pos1;
vertex2 = pos2;
vertex3 = pos3;
depth = tDepth;
}

public TriXYZ(Vector3 pos1, Vector3 pos2, Vector3 pos3, int tDepth, float tMaterial1, float tMaterial2)
{
vertex1 = pos1;
vertex2 = pos2;
vertex3 = pos3;
depth = tDepth;
material1 = tMaterial1;
material2 = tMaterial2;
}

// public access to triangle data, read-write

public Vector3 GetVertex1
{
get { return vertex1; }
set { vertex1 = value; }
}
public Vector3 GetVertex2
{
get { return vertex2; }
set { vertex2 = value; }
}
public Vector3 GetVertex3
{
get { return vertex3; }
set { vertex3 = value; }
}
public int GetDepth
{
get { return depth; }
set { depth = value; }
}



public static Vector3 Midpoint(Vector3 pos1, Vector3 pos2, float radius)
{
Vector3 midpoint; // returned midpoint between the two inputted vectors
float x;
float y;
float z;

x = (pos1.X + pos2.X)/2;
y = (pos1.Y + pos2.Y)/2;
z = (pos1.Z + pos2.Z)/2;

midpoint = new Vector3(x, y, z);
midpoint.Normalize();
midpoint = midpoint * radius;

return midpoint;
}

public TriXYZ[] subDivide(float radius)
{
Vector3 r; // placeholder for new vertex position, aligned to planet sphere radius
Vector3 UV; // new vector position

TriXYZ[] nTriangle = new TriXYZ[5]; // array of triangle values to return

Vector3 mid1 = Midpoint(vertex1, vertex2, radius);
Vector3 mid2 = Midpoint(vertex2, vertex3, radius);
Vector3 mid3 = Midpoint(vertex3, vertex1, radius);

nTriangle[0] = new TriXYZ(vertex1, vertex2, vertex3, depth); // Put the original larger triangle at the front if the list
nTriangle[1] = new TriXYZ(vertex1, mid1, mid3, depth + 1); // First subdivided triangle
nTriangle[2] = new TriXYZ(mid1, vertex2, mid2, depth + 1); // Second subdivided triangle
nTriangle[3] = new TriXYZ(mid3, mid2, vertex3, depth + 1); // Third subdivided triangle
nTriangle[4] = new TriXYZ(mid3, mid1, mid2, depth + 1); // Fourth subdivided triangle

return nTriangle;
}

}
}

任何帮助将不胜感激。我想这很简单,我似乎找不到问题。

最佳答案

这绝对是初始向量。如果没记错(自从我处理二十面体等问题以来已经有一段时间了),您只需使用黄金比例来创建边长为 2 的一个(您正在这样做)。也许在乘以半径之前对向量进行归一化?我这么说的原因是因为这些顶点永远不会在您的代码中更新,所以它必须是初始值(当然除非我遗漏了什么,这是可能的)。

关于c# - 生成的 Icosphere 上的尖峰顶点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6778031/

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