Unity3d 如何构造十二面体及其边的纹理
我想创建一个基于十二面体的行星三维模型,给每一面不同的纹理,代表该区域的主要景观和其他内容。(或者,将地球分成12个五边形会更好,但可能更复杂。) 由于这是一个游戏项目,我想在Unity3d中完成,但任何方法(脚本或免费的3d图形工具)都会有所帮助Unity3d 如何构造十二面体及其边的纹理,unity3d,3d,polygons,Unity3d,3d,Polygons,我想创建一个基于十二面体的行星三维模型,给每一面不同的纹理,代表该区域的主要景观和其他内容。(或者,将地球分成12个五边形会更好,但可能更复杂。) 由于这是一个游戏项目,我想在Unity3d中完成,但任何方法(脚本或免费的3d图形工具)都会有所帮助 我已经研究了柏拉图式物体的几何学,并试图找出如何画五边形,然后将它们适当地倾斜,或者只是找到一个现成的解决方案,但到目前为止,我还没有找到任何方法。经过进一步的摸索,我确实找到了一个答案: 步骤1:在搅拌机中创建五角大楼 这其实非常简单。创建一个圆并
我已经研究了柏拉图式物体的几何学,并试图找出如何画五边形,然后将它们适当地倾斜,或者只是找到一个现成的解决方案,但到目前为止,我还没有找到任何方法。经过进一步的摸索,我确实找到了一个答案: 步骤1:在搅拌机中创建五角大楼 这其实非常简单。创建一个圆并将顶点数减少到5。实际上,我使用了一个尺寸为X=1,Y=1,Z=0.1的圆柱体,但是对于一个扁平的五边形,整体解决方案是相同的 第二步:进入Unity3d Unity3d自然导入.blend文件,所以我只是将五角大楼保存为.blend文件,并将其作为资源导入Unity3d 步骤3:将五角大楼放在一根棍子上。 为了方便地围绕后面的十二面体的中心旋转五边形,我在Unity3d中创建了一个尺寸为X=0.1、Y=2、Z=0.1的圆柱体。然后我将五角大楼作为子对象放在圆柱体的精确末端(对于我的3d五角大楼,变换Y=9,75,如果使用平面五角大楼,则为10,旋转X=90)。我在另一端也做了同样的事情,五角大楼掉头了。(变换=-9,75并旋转X=90,Z=180)以同时进行两个半部分 第3步:旋转和缩放 现在我可以复制并旋转圆柱体(带有附加的五边形)X=63.435(十二面体侧面之间的角度)和Y=180(使边彼此面对),以使其处于正确的位置。现在,我必须找到五边形的正确比例来缩小这个差距,这个差距恰好接近15.275。用相应的角度重复五次(y=180+/-72的倍数,五边形两侧之间的角度)
完成。首先创建一些数学助手:
using System;
using UnityEngine;
public static class MathUtils
{
public static Vector3 MultiplyMatrixAndVector(float[,] m, Vector3 v)
{
return new Vector3(
v.x * m[0, 0] + v.y * m[0, 1] + v.z * m[0, 2],
v.x * m[1, 0] + v.y * m[1, 1] + v.z * m[1, 2],
v.x * m[2, 0] + v.y * m[2, 1] + v.z * m[2, 2]
);
}
public static Vector3 RotateVectorAroundAxis(Vector3 vector, Vector3 a, Vector3 b, double angle)
{
var normalizedAxis = (b - a).normalized;
var x = normalizedAxis.x;
var y = normalizedAxis.y;
var z = normalizedAxis.z;
var translationVector = ProjectPointOnAxis(vector, a, b);
var c = (float) Math.Cos(angle);
var s = (float) Math.Sin(angle);
var rotationMatrix = new float[3, 3];
rotationMatrix[0, 0] = c + x * x * (1 - c);
rotationMatrix[0, 1] = x * y * (1 - c) - z * s;
rotationMatrix[0, 2] = x * z * (1 - c) + y * s;
rotationMatrix[1, 0] = y * x * (1 - c) + z * s;
rotationMatrix[1, 1] = c + y * y * (1 - c);
rotationMatrix[1, 2] = y * z * (1 - c) - x * s;
rotationMatrix[2, 0] = z * x * (1 - c) - y * s;
rotationMatrix[2, 1] = z * y * (1 - c) + x * s;
rotationMatrix[2, 2] = c + z * z * (1 - c);
return MultiplyMatrixAndVector(rotationMatrix, vector - translationVector) + translationVector;
}
public static Vector3 ProjectPointOnAxis(Vector3 vector, Vector3 a, Vector3 b)
{
var ba = b - a;
var lambda = Vector3.Dot(ba, vector - a) / Vector3.Dot(ba, ba);
return a + lambda * ba;
}
}
然后创建一个多面体管理器:
using System;
using System.Collections.Generic;
using UnityEngine;
public static class PolyhedronManager
{
public static GameObject CreatePolyhedron(string name)
{
var material = Resources.Load("Materials/Cube") as Material;
var gameObject = new GameObject();
Mesh mesh;
switch (name)
{
case "hexahedron":
{
mesh = CreatePolyhedronMesh(4, Math.PI / 2);
break;
}
case "tetrahedron":
{
mesh = CreatePolyhedronMesh(3, Math.Acos(1d / 3));
break;
}
case "octahedron":
{
mesh = CreatePolyhedronMesh(3, Math.Acos(-1d / 3));
break;
}
case "icosahedron":
{
mesh = CreatePolyhedronMesh(3, Math.Acos(-Math.Sqrt(5) / 3));
break;
}
case "dodecahedron":
{
mesh = CreatePolyhedronMesh(5, 2 * Math.Atan2(1 + Math.Sqrt(5), 2));
break;
}
default:
{
throw new Exception("Invalid polyhedron name");
}
}
mesh.RecalculateNormals();
gameObject.AddComponent<MeshRenderer>().material = material;
gameObject.AddComponent<MeshFilter>().mesh = mesh;
gameObject.name = char.ToUpper(name[0]) + name.Substring(1);
gameObject.transform.rotation = Quaternion.Euler(180, 0, 0);
return gameObject;
}
private static List<Vector3> CreatePolygonVertices(int nSides, Vector3 origin, Vector3 normal, Vector3 firstNode, bool shouldUseFirstNode)
{
var angle = 2 * Math.PI / nSides;
var distanceFromCenter = (float) Math.Sqrt(0.5 / (1 - Math.Cos(angle)));
var actualFirstNode = shouldUseFirstNode ? firstNode : origin + distanceFromCenter * Vector3.right;
var vertices = new List<Vector3> {actualFirstNode};
for (var i = 1; i < nSides; i++)
{
vertices.Add(MathUtils.RotateVectorAroundAxis(vertices[i - 1], origin, origin + normal, angle));
}
return vertices;
}
private static Mesh CreatePolyhedronMesh(int nSides, double dihedralAngle)
{
var supplementaryAngle = Math.PI - dihedralAngle;
var origin = Vector3.zero;
var faces = new List<List<Vector3>> {CreatePolygonVertices(nSides, origin, Vector3.up, origin, false)};
var centers = new List<Vector3> {origin};
var facesQueue = new List<List<Vector3>> {faces[0]};
var centersQueue = new List<Vector3> {centers[0]};
while (true)
{
if (facesQueue.Count == 0)
{
break;
}
var face = facesQueue[0];
var center = centersQueue[0];
facesQueue.RemoveAt(0);
centersQueue.RemoveAt(0);
for (var i = 0; i < nSides; i++)
{
var a = face[i];
var b = face[i == nSides - 1 ? 0 : i + 1];
var dihedralAxis = b - a;
var pivot = (b + a) / 2;
var p = pivot - center;
var nextCenter = pivot + p;
var rotatedCenter = MathUtils.RotateVectorAroundAxis(nextCenter, a, b, supplementaryAngle);
var centerAlreadyExists = false;
centers.ForEach(existingCenter =>
{
if ((rotatedCenter - existingCenter).sqrMagnitude < 0.01)
{
centerAlreadyExists = true;
}
});
if (centerAlreadyExists)
{
continue;
}
var normal = Vector3.Cross(p, dihedralAxis);
var nextFace = CreatePolygonVertices(nSides, nextCenter, normal, a, true)
.ConvertAll(new Converter<Vector3, Vector3>(vertex => MathUtils.RotateVectorAroundAxis(vertex, a, b, supplementaryAngle)));
faces.Add(nextFace);
centers.Add(rotatedCenter);
facesQueue.Add(nextFace);
centersQueue.Add(rotatedCenter);
}
}
var vertices = new List<Vector3>();
var triangles = new List<int>();
var c = -1;
for (var i = 0; i < faces.Count; i++)
{
var face = faces[i];
var center = centers[i];
c++;
vertices.Add(center);
var centerVertexIndex = c;
for (var j = 0; j < face.Count; j++)
{
var vertex = face[j];
c++;
vertices.Add(vertex);
triangles.Add(centerVertexIndex);
triangles.Add(c);
triangles.Add(j == face.Count - 1 ? centerVertexIndex + 1 : c + 1);
}
}
return new Mesh
{
vertices = vertices.ToArray(),
triangles = triangles.ToArray()
};
}
}
该脚本基于多边形边上的数量和多面体的二面角生成顶点和三角形。为此,它使用呼吸优先搜索策略在面上构建多面体
希望这能有所帮助。听起来你想要的是3D建模程序,而不是3D游戏引擎。看看Blender(免费)和这个关于的问题。柏拉图式的身体插件似乎已经不存在了,斜面解决方案已经超出了我微薄的Blender技能。。但你的回答为我指明了正确的方向。。。
var polyhedronGameObject = PolyhedronManager.CreatePolyhedron("dodecahedron");