- Home /
Procedural Mesh Generation: Creating a spherical sector
So, I am creating a spherical sector with the given theta and phi angles (Latitude and Longitude) and I know my vertices positioning is correct but no mesh is visible. Does any one have any idea about what is wrong with this code. Why isn't it showing any mesh.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor.UIElements;
public class Please : MonoBehaviour
{
public int ThetaUpper = 30;
public int ThetaLower = 40;
public int PhiUpper = 30;
public int PhiLower = 10;
public bool edit = true;
private int ThetaU;
private int ThetaL;
private int PhiU;
private int PhiL;
public float size = 0.001f;
private readonly int res = 2;
private Mesh mesh;
private MeshFilter meshFilter;
public float radius = 5.0f;
private GameObject[] points;
private Vector3[] vertices;
private string[] names;
// Start is called before the first frame update
void Start()
{
this.gameObject.AddComponent<MeshFilter>();
this.gameObject.AddComponent<MeshRenderer>();
meshFilter = this.gameObject.GetComponent<MeshFilter>();
meshFilter.sharedMesh = new Mesh();
mesh = meshFilter.sharedMesh;
Create();
Assign();
}
// Update is called once per frame
void Update()
{
}
bool check()
{
if (ThetaLower == ThetaL && ThetaUpper == ThetaU && PhiLower == PhiL && PhiUpper == PhiU)
return true;
else return false;
}
void Assign()
{
ThetaU = ThetaUpper;
ThetaL = ThetaLower;
PhiL = PhiLower;
PhiU = PhiUpper;
}
void Create()
{
int index1 = (ThetaLower - ThetaUpper) * 2;
int index2 = (PhiUpper - PhiLower) * 2;
vertices = new Vector3[index1 * index2];
names = new string[vertices.Length];
int[,] temp = new int[index1, index2];
int no = 0;
for (int i = 0; i < index1; i++)
{
float theta = ((0.5f * i) + ThetaUpper) * Mathf.Deg2Rad;
for (int j = 0; j < index2; j++, no++)
{
float phi = ((0.5f * j) + PhiLower) * Mathf.Deg2Rad;
float x = radius * Mathf.Sin(theta) * Mathf.Cos(phi);
float z = radius * Mathf.Sin(theta) * Mathf.Sin(phi);
float y = radius * Mathf.Cos(theta);
vertices[no] = new Vector3(x, y, z);
names[no] = "Vertex No. " + no.ToString() + " Theta " + i.ToString() + " phi " + j.ToString();
temp[i, j] = no;
}
}
int[] triangles = new int[(index1 - 1) * (index2 - 1) * 6];
int triIndex = 0;
for (int i = 0; i < index1-1; i++)
{
for (int j = 0; j < index2-1; j++, triIndex += 6)
{
triangles[triIndex] = temp[i, j];
triangles[triIndex] = temp[i , j + 1];
triangles[triIndex] = temp[i + 1, j + 1];
triangles[triIndex] = temp[i, j];
triangles[triIndex] = temp[i + 1, j + 1];
triangles[triIndex] = temp[i + 1, j];
}
}
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
DrawSphere();
}
void DrawSphere()
{
points = new GameObject[mesh.vertexCount];
for (int i = 0; i < mesh.vertexCount; i++)
{
points[i] = GameObject.CreatePrimitive(PrimitiveType.Sphere);
points[i].name = names[i];
points[i].transform.parent = transform;
points[i].transform.localScale = new Vector3(size, size, size);
points[i].transform.position = vertices[i];
}
}
}
Well, as a point of reference, if you simplify the mesh to a sure thing, does it still work?
For example, you could try something like:
vertices = new Vector3[]
{
new Vector3(-1f, -1f, 0f), // 0: bottom left
new Vector3(1f, -1f, 0f), // 1: bottom right
new Vector3(1f, 1f, 0f), // 2: top right
new Vector3(-1f, 1f, 0f) // 3: top left
};
triangles = new int[]
{
0, 1, 2,
0, 2, 3
};
If that's visible, then it's a flaw in your vertex/triangle generation.
However, if it's not visible, then it's a flaw in creating/applying the mesh.
Edit: Fixed a dumb error
I added the DrawSphere function to visualize the vertices that are created. The Attached figure are the vertices that are resulting from given angles of 10 to 60 in theta and 0 to 60 in phi. The Vertices are verified to be correct because of it. The issue must be in the triangles then. As for the simpler meshes, they are working.
Answer by LionWare · Nov 26, 2020 at 08:03 AM
Got it. It was a silly silly mistake. I was setting all the triangles on the same index. (Yeah I know. I should probably shoot myself) Anyways thanks. Here is the working code for those who need it. using System; using System.Collections; using System.Collections.Generic; using System.Data; using UnityEngine; using UnityEngine.UI; using UnityEditor.UIElements;
public class Please : MonoBehaviour
{
public int ThetaUpper = 30;
public int ThetaLower = 40;
public int PhiUpper = 30;
public int PhiLower = 10;
public bool edit = true;
private int ThetaU;
private int ThetaL;
private int PhiU;
private int PhiL;
public float size = 0.001f;
private readonly int res = 2;
private Mesh mesh;
private MeshFilter meshFilter;
public float radius = 5.0f;
private GameObject[] points;
private Vector3[] vertices;
private string[] names;
// Start is called before the first frame update
void Start()
{
this.gameObject.AddComponent<MeshFilter>();
this.gameObject.AddComponent<MeshRenderer>();
meshFilter = this.gameObject.GetComponent<MeshFilter>();
meshFilter.sharedMesh = new Mesh();
mesh = meshFilter.sharedMesh;
Create();
Assign();
}
// Update is called once per frame
void Update()
{
}
bool check()
{
if (ThetaLower == ThetaL && ThetaUpper == ThetaU && PhiLower == PhiL && PhiUpper == PhiU)
return true;
else return false;
}
void Assign()
{
ThetaU = ThetaUpper;
ThetaL = ThetaLower;
PhiL = PhiLower;
PhiU = PhiUpper;
}
void Create()
{
int index1 = (ThetaLower - ThetaUpper) * 2;
int index2 = (PhiUpper - PhiLower) * 2;
vertices = new Vector3[index1 * index2];
names = new string[vertices.Length];
int[,] temp = new int[index1, index2];
int no = 0;
for (int i = 0; i < index1; i++)
{
float theta = ((0.5f * i) + ThetaUpper) * Mathf.Deg2Rad;
for (int j = 0; j < index2; j++, no++)
{
float phi = ((0.5f * j) + PhiLower) * Mathf.Deg2Rad;
float x = radius * Mathf.Sin(theta) * Mathf.Cos(phi);
float z = radius * Mathf.Sin(theta) * Mathf.Sin(phi);
float y = radius * Mathf.Cos(theta);
vertices[no] = new Vector3(x, y, z);
names[no] = "Vertex No. " + no.ToString() + " Theta " + i.ToString() + " phi " + j.ToString();
temp[i, j] = no;
}
}
int[] triangles = new int[(index1 - 1) * (index2 - 1) * 6];
int triIndex = 0;
for (int i = 0; i < index1-1; i++)
{
for (int j = 0; j < index2-1; j++)
{
triangles[triIndex] = temp[i, j];
triangles[triIndex + 1] = temp[i + 1, j + 1];
triangles[triIndex + 2] = temp[i, j + 1];
triangles[triIndex + 3] = temp[i, j];
triangles[triIndex + 4] = temp[i + 1, j];
triangles[triIndex + 5] = temp[i + 1, j + 1];
triIndex += 6;
}
}
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
void DrawSphere()
{
points = new GameObject[mesh.vertexCount];
for (int i = 0; i < mesh.vertexCount; i++)
{
points[i] = GameObject.CreatePrimitive(PrimitiveType.Sphere);
points[i].name = names[i];
points[i].transform.parent = transform;
points[i].transform.localScale = new Vector3(size, size, size);
points[i].transform.position = vertices[i];
}
}
}
I removed the DrawSphere because I dont need it now.
Answer by Llama_w_2Ls · Nov 26, 2020 at 07:15 AM
Maybe the triangles are being drawn on the inside? If not, here's one example from the web:
public static MeshGeometry3D Sphere(double radius, int TopBottomDetail, int SidesDetail)
{
MeshGeometry3D sphere_mesh = new MeshGeometry3D();
double dphi = Math.PI / TopBottomDetail;
double dtheta = 2 * Math.PI / SidesDetail;
// Remember the first point.
int pt0 = sphere_mesh.Positions.Count;
// Make the points.
double phi1 = Math.PI / 2;
for (int p = 0; p <= TopBottomDetail; p++)
{
double r1 = radius * Math.Cos(phi1);
double y1 = radius * Math.Sin(phi1);
double theta = 0;
for (int t = 0; t <= SidesDetail; t++)
{
sphere_mesh.Positions.Add(new Point3D(r1 * Math.Cos(theta), y1, -r1 * Math.Sin(theta)));
sphere_mesh.TextureCoordinates.Add(new Point((double)t / SidesDetail, (double)p / TopBottomDetail));
theta += dtheta;
}
phi1 -= dphi;
}
// Make the triangles.
int i1, i2, i3, i4;
for (int p = 0; p <= TopBottomDetail - 1; p++)
{
i1 = p * (SidesDetail + 1);
i2 = i1 + (SidesDetail + 1);
for (int t = 0; t <= SidesDetail - 1; t++)
{
i3 = i1 + 1;
i4 = i2 + 1;
sphere_mesh.TriangleIndices.Add(pt0 + i1);
sphere_mesh.TriangleIndices.Add(pt0 + i2);
sphere_mesh.TriangleIndices.Add(pt0 + i4);
sphere_mesh.TriangleIndices.Add(pt0 + i1);
sphere_mesh.TriangleIndices.Add(pt0 + i4);
sphere_mesh.TriangleIndices.Add(pt0 + i3);
i1 += 1;
i2 += 1;
}
}
return sphere_mesh;
}
Some classes such as MeshGeometry3D, are only found in WPF, however, you can just replace it with Unity's mesh class instead. @LionWare
I am almost sure that the problem I am getting is with triangles as my vertices are in correct position, (validated by the DrawSphere function) but I cant get the problem with the triangles. The Code that you have given is for a complete sphere I dont need to generate a complete sphere.
Your answer
Follow this Question
Related Questions
Why does Frame Selected toggle between position and bounds for procedural and imported meshes? 1 Answer
Setting triangles failing 0 Answers
Mesh generated from bezier curve loop going outside loop 0 Answers
How to get a smoothed Icosphere procedurally 1 Answer
Prevent seams on a generated mesh with split edges. 0 Answers