为什么立方体网格在高分辨率下会变成平面?
Why cube mesh becomes a plane when in high resolution?
我使用以下代码将立方体生成为单个网格。我的目的是通过规范化从中生成一个球体,如我在注释行中所示(我只需要对以下行中的所有这些语句执行此操作)。这里的问题是,随着我不断增加分辨率(给定的参数 public int resolution
),网格从立方体变为平面。
(此代码的灵感来自于此视频 https://youtu.be/QN39W020LqU。但我正在以我自己的方式使用该技术,如下面的代码所示,这样我就可以生成单个网格而不是 6 个网格的组合网格,这是我工作所必需的)
[code=CSharp]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sc_Planet : MonoBehaviour
{
[Range(2, 512)]
public int resolution = 2;
[Range(2, 256)]
public int radius = 10;
MeshFilter meshFilter;
void OnValidate()
{
Initialize();
}
void Initialize()
{
if (meshFilter == null)
{
GameObject meshObj = new GameObject("mesh_Planet");
meshObj.transform.parent = transform;
meshObj.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Standard"));
meshFilter = meshObj.AddComponent<MeshFilter>();
meshFilter.sharedMesh = new Mesh();
}
int xmax = resolution + 1;
int ymax = resolution + 1;
float dx = 1.0f / resolution;
float dy = 1.0f / resolution;
Vector3[] vertsTop = new Vector3[xmax * ymax];
Vector3[] vertsRight = new Vector3[xmax * ymax];
Vector3[] vertsFront = new Vector3[xmax * ymax];
Vector3[] vertsBottom = new Vector3[xmax * ymax];
Vector3[] vertsLeft = new Vector3[xmax * ymax];
Vector3[] vertsBack = new Vector3[xmax * ymax];
for (int y = 0; y < ymax; y++)
{
for (int x = 0; x < xmax; x++)
{
float px = dx * x - 0.5f;
float py = dy * y - 0.5f;
int t = x + y * xmax;
//vertsTop[t] = new Vector3(py, 0.5f, px).normalized * radius;
vertsTop[t] = new Vector3(py, 0.5f, px);
vertsRight[t] = new Vector3(px, py, 0.5f);
vertsFront[t] = new Vector3(0.5f, px, py);
vertsBottom[t] = new Vector3(px, -0.5f, py);
vertsLeft[t] = new Vector3(py, px, -0.5f);
vertsBack[t] = new Vector3(-0.5f, py, px);
}
}
List<int> trianglesList = new List<int>();
for (int y = 0; y < ymax - 1; ++y)
{
for (int x = 0; x < xmax; ++x)
{
if (x % xmax != xmax - 1)
{
int f = x + y * xmax;
trianglesList.Add(f);
trianglesList.Add(f + 1);
trianglesList.Add(f + 1 + xmax);
trianglesList.Add(f);
trianglesList.Add(f + 1 + xmax);
trianglesList.Add(f + xmax);
}
}
}
List<Vector3> verts = new List<Vector3>();
Dictionary<Vector3, int> vdict = new Dictionary<Vector3, int>();
List<int> triangles = new List<int>();
int nextIndex = 0;
void addFace(Vector3 [] in_verts, List<int> in_triangles)
{
for(int i = 0; i < in_verts.Length; ++i)
{
if (!vdict.ContainsKey(in_verts[i]))
{
vdict.Add(in_verts[i], nextIndex);
verts.Add(in_verts[i]);
++nextIndex;
}
}
for(int i = 0; i < in_triangles.Count; ++i)
{
triangles.Add(vdict[in_verts[in_triangles[i]]]);
}
}
addFace(vertsTop, trianglesList);
addFace(vertsRight, trianglesList);
addFace(vertsFront, trianglesList);
addFace(vertsBottom, trianglesList);
addFace(vertsLeft, trianglesList);
addFace(vertsBack, trianglesList);
var mesh = meshFilter.sharedMesh;
mesh.Clear();
mesh.vertices = verts.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
}
}
[/code]
此代码在 Blender 中有效(我使用 python 在 Blender 上编写脚本并且它适用于任何分辨率)。
唯一的问题是,当我在 Unity 中使用它时,网格变得很奇怪,正如我在下面附上的图片中所示。
在分辨率 = 96 时:
在分辨率 = 122 时:
在分辨率 = 182 时:
在分辨率 = 344 时:
为什么会这样?
我该如何纠正?
(我也在 unity 论坛上发过:Why cube mesh becomes a plane when in high resolution?)
好的,我找到了答案。这超出了基于 16 位的网格的统一顶点数限制 api。我不得不将其更改为 32 位索引网格以更正它。
我只需添加代码即可:
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
就是这样。
我使用以下代码将立方体生成为单个网格。我的目的是通过规范化从中生成一个球体,如我在注释行中所示(我只需要对以下行中的所有这些语句执行此操作)。这里的问题是,随着我不断增加分辨率(给定的参数 public int resolution
),网格从立方体变为平面。
(此代码的灵感来自于此视频 https://youtu.be/QN39W020LqU。但我正在以我自己的方式使用该技术,如下面的代码所示,这样我就可以生成单个网格而不是 6 个网格的组合网格,这是我工作所必需的)
[code=CSharp]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sc_Planet : MonoBehaviour
{
[Range(2, 512)]
public int resolution = 2;
[Range(2, 256)]
public int radius = 10;
MeshFilter meshFilter;
void OnValidate()
{
Initialize();
}
void Initialize()
{
if (meshFilter == null)
{
GameObject meshObj = new GameObject("mesh_Planet");
meshObj.transform.parent = transform;
meshObj.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Standard"));
meshFilter = meshObj.AddComponent<MeshFilter>();
meshFilter.sharedMesh = new Mesh();
}
int xmax = resolution + 1;
int ymax = resolution + 1;
float dx = 1.0f / resolution;
float dy = 1.0f / resolution;
Vector3[] vertsTop = new Vector3[xmax * ymax];
Vector3[] vertsRight = new Vector3[xmax * ymax];
Vector3[] vertsFront = new Vector3[xmax * ymax];
Vector3[] vertsBottom = new Vector3[xmax * ymax];
Vector3[] vertsLeft = new Vector3[xmax * ymax];
Vector3[] vertsBack = new Vector3[xmax * ymax];
for (int y = 0; y < ymax; y++)
{
for (int x = 0; x < xmax; x++)
{
float px = dx * x - 0.5f;
float py = dy * y - 0.5f;
int t = x + y * xmax;
//vertsTop[t] = new Vector3(py, 0.5f, px).normalized * radius;
vertsTop[t] = new Vector3(py, 0.5f, px);
vertsRight[t] = new Vector3(px, py, 0.5f);
vertsFront[t] = new Vector3(0.5f, px, py);
vertsBottom[t] = new Vector3(px, -0.5f, py);
vertsLeft[t] = new Vector3(py, px, -0.5f);
vertsBack[t] = new Vector3(-0.5f, py, px);
}
}
List<int> trianglesList = new List<int>();
for (int y = 0; y < ymax - 1; ++y)
{
for (int x = 0; x < xmax; ++x)
{
if (x % xmax != xmax - 1)
{
int f = x + y * xmax;
trianglesList.Add(f);
trianglesList.Add(f + 1);
trianglesList.Add(f + 1 + xmax);
trianglesList.Add(f);
trianglesList.Add(f + 1 + xmax);
trianglesList.Add(f + xmax);
}
}
}
List<Vector3> verts = new List<Vector3>();
Dictionary<Vector3, int> vdict = new Dictionary<Vector3, int>();
List<int> triangles = new List<int>();
int nextIndex = 0;
void addFace(Vector3 [] in_verts, List<int> in_triangles)
{
for(int i = 0; i < in_verts.Length; ++i)
{
if (!vdict.ContainsKey(in_verts[i]))
{
vdict.Add(in_verts[i], nextIndex);
verts.Add(in_verts[i]);
++nextIndex;
}
}
for(int i = 0; i < in_triangles.Count; ++i)
{
triangles.Add(vdict[in_verts[in_triangles[i]]]);
}
}
addFace(vertsTop, trianglesList);
addFace(vertsRight, trianglesList);
addFace(vertsFront, trianglesList);
addFace(vertsBottom, trianglesList);
addFace(vertsLeft, trianglesList);
addFace(vertsBack, trianglesList);
var mesh = meshFilter.sharedMesh;
mesh.Clear();
mesh.vertices = verts.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
}
}
[/code]
此代码在 Blender 中有效(我使用 python 在 Blender 上编写脚本并且它适用于任何分辨率)。 唯一的问题是,当我在 Unity 中使用它时,网格变得很奇怪,正如我在下面附上的图片中所示。
在分辨率 = 96 时:
在分辨率 = 122 时:
在分辨率 = 182 时:
在分辨率 = 344 时:
为什么会这样? 我该如何纠正?
(我也在 unity 论坛上发过:Why cube mesh becomes a plane when in high resolution?)
好的,我找到了答案。这超出了基于 16 位的网格的统一顶点数限制 api。我不得不将其更改为 32 位索引网格以更正它。
我只需添加代码即可:
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
就是这样。