- Home /
Setting triangles failing
So, I'm modifying the sphere generation script found on the Unity wikia so that I can generate spheres with more than 65000 vertices (by splitting apart the mesh). However, I have run into an issue. The code below works fine (including creating a child object and applying the mesh) up until I input latitude and longitude values that would generate a sphere over 65000 vertices. Once it reaches a number higher than that, the debugger is telling me I am trying to assign triangles to non-existant vertices (some indices are referencing out of bounds vertices). I know what this error means, but I don't know what is wrong in the code - if I had to guess, though, it's just some bad math.
Here's the code:
IEnumerator BuildPlanet()
{
noise = new Perlin();
//Mesh mesh = new Mesh();
MeshFilter filter = gameObject.AddComponent< MeshFilter >();
//Mesh mesh = filter.mesh;
//mesh.Clear();
//Mesh[] mesh = new Mesh[];
float radius = 1f;
// Longitude |||
int nbLong = 360;
// Latitude ---
int nbLat = 184;
#region Vertices
Vector3[] vertices = new Vector3[(nbLong+1) * nbLat + 2];
//print (vertices.Length);
float _pi = Mathf.PI;
float _2pi = _pi * 2f;
int obj = Mathf.CeilToInt((float)vertices.Length/65000);
vertices[0] = Vector3.up * radius;
//for(int m = 0; m < obj; m++)
//{
for( int lat = 0; lat < nbLat; lat++ )
{
float a1 = _pi * (float)(lat+1) / (nbLat+1);
float sin1 = Mathf.Sin(a1);
float cos1 = Mathf.Cos(a1);
for( int lon = 0; lon <= nbLong; lon++ )
{
float a2 = _2pi * (float)(lon == nbLong ? 0 : lon) / nbLong;
float sin2 = Mathf.Sin(a2);
float cos2 = Mathf.Cos(a2);
vertices[ lon + lat * (nbLong + 1) + 1] = new Vector3( sin1 * cos2, cos1, sin1 * sin2 ) * radius;
//vertices[ lon + lat * (nbLong + 1) + 1] = vertices[ lon + lat * (nbLong + 1) + 1].normalized*(float)(100+noise.GetValue(sin1*cos2, cos1, sin1*cos2)*2);
//vertices.normalized*(float)(100+noise.GetValue(pos.x, pos.y, pos.z)*2);
}
}
//}
vertices[vertices.Length-1] = Vector3.up * -radius;
#endregion
#region Normales
Vector3[] normales = new Vector3[vertices.Length];
for( int n = 0; n < vertices.Length; n++ )
normales[n] = vertices[n].normalized;
#endregion
#region UVs
Vector2[] uvs = new Vector2[vertices.Length];
uvs[0] = Vector2.up;
uvs[uvs.Length-1] = Vector2.zero;
for( int lat = 0; lat < nbLat; lat++ )
for( int lon = 0; lon <= nbLong; lon++ )
uvs[lon + lat * (nbLong + 1) + 1] = new Vector2( (float)lon / nbLong, 1f - (float)(lat+1) / (nbLat+1) );
#endregion
#region Triangles
int nbFaces = vertices.Length;
int nbTriangles = nbFaces * 2;
int nbIndexes = nbTriangles * 3;
int[] triangles = new int[ nbIndexes ];
//Top Cap
int i = 0;
for( int lon = 0; lon < nbLong; lon++ )
{
triangles[i++] = lon+2;
triangles[i++] = lon+1;
triangles[i++] = 0;
}
//Middle
for( int lat = 0; lat < nbLat - 1; lat++ )
{
for( int lon = 0; lon < nbLong; lon++ )
{
int current = lon + lat * (nbLong + 1) + 1;
int next = current + nbLong + 1;
triangles[i++] = current;
triangles[i++] = current + 1;
triangles[i++] = next + 1;
triangles[i++] = current;
triangles[i++] = next + 1;
triangles[i++] = next;
}
}
//Bottom Cap
for( int lon = 0; lon < nbLong; lon++ )
{
triangles[i++] = vertices.Length - 1;
triangles[i++] = vertices.Length - (lon+2) - 1;
triangles[i++] = vertices.Length - (lon+1) - 1;
}
#endregion
for(int m = 0; m < obj; m++)
{
int v = m*65000;
Mesh mesh = new Mesh();
mesh.Clear();
GameObject gos = new GameObject("GO");
Vector3[] verts = new Vector3[Mathf.Clamp (vertices.Length-v, 3, 65000)];
Vector3[] norms = new Vector3[verts.Length];
Vector2[] uv = new Vector2[verts.Length];
int[] tris = new int[verts.Length*6];
for(int a = 0; a < verts.Length; a++)
{
verts[a] = vertices[a+v];
}
for(int b = 0; b < norms.Length; b++)
{
norms[b] = normales[b+v];
}
for(int c = 0; c < uv.Length; c++)
{
uv[c] = uvs[c+v];
}
for(int d = 0; d < tris.Length; d++)
{
tris[d] = triangles[d+v];
}
mesh.vertices = verts;
mesh.normals = norms;
mesh.uv = uv;
mesh.triangles = tris;
mesh.RecalculateBounds();
mesh.Optimize();
gos.AddComponent<MeshFilter>();
gos.AddComponent<MeshRenderer>();
gos.AddComponent<MeshCollider>();
gos.GetComponent<MeshFilter>().mesh = mesh;
gos.GetComponent<MeshCollider>().sharedMesh = mesh;
gos.transform.parent = transform;
gos.GetComponent<MeshRenderer>().material = transform.GetComponent<MeshRenderer>().material;
}
yield return null;
}
Permitting the question because it doesn't violate any rules, but I would not expect pro bono help with complex math-heavy algorithms.