- Home /
Procedural circle mesh with uniform faces
I'm trying to create a 2d circle procedurally with uniform faces like so.
Normally, I would create it with a triangle fan structure, but I need faces to be roughly identical. I looked for examples, but I could only find "cube to sphere" examples.
Could you help me finding a way to draw this structure? I'd like to do it in C# but js or even pseudo code could do!
Thanks a lot
I fear this problem is not as simple as it look. If what you want is being able to generate a circle with an arbitrary triangle size, I think you will have to use some non trivial mesh optimisation steps.
On simpler solution I can imagin is to generate your triangle with the folowing pattern : The result may be not as nice and regular but seem simpler to generate for me. The blue line repesent a part of the circle mesh and the light gray circle are just guide. I would generate the whole thing starting from the circle and expanding out, layer by layer. To create a new circle dothe following: ![alt text][1] [1]: /storage/temp/128123-bitmap.png Generate the first layer with a fan structure, then : To generate a new layer you can do something like: take all the outer point of the previous layer one by one, for each add two new point on the layer you are generating: one that is alligned with the next point on the previous layer and the centre of the circle, and a second one that stand with a polar coordinate angle in the middle between the point you just added and the previous one (like this point is sort of in the midle but still on the layer circle). Then add relvant edges between the two point you created and : the previous point on the layer youare generating, the current point on the prevoius layer, the next point on the previous layer.
You will need a bit of additional fidling to start and close each layer.
Otherwise you may consider why you need to generate such circle and see if you can find a way to have the property you need without actual mesh generation.
$$anonymous$$aybe I could apply tessalation on a vector field like this one https://stackoverflow.com/questions/33510979/generator-of-evenly-spaced-points-in-a-circle-in-python
Answer by michi_b · Nov 21, 2018 at 08:07 PM
This won't give you exactly as good results but this is the approach I would try (I won't code it all out here though): First, find your vertices. For that I would start at the center. Then define a mean edge length for your triangulation, let's call it "l". It defines the density of the resulting mesh. Now iteratively increase a your radius r by l until you reach your desired full circle radius. At each iteration i, determine the vertices that lie on the circle with the radius l*i. the amount of vertices at each circle should be chosen so the distance between these vertices is as close as possible to l. Once this is done, you should have a bunch of vertices with more or less equal space between them in a circular shape.
Next you will have to triangulate those vertices. I would suggest you look up Delaunay Triangulation for that. It gives the least "slithery" triangles, meaning it avoids narrow angles in your triangles, which makes it a very good triangulation for many purposes. It is so well known that you should find enough clues on how to implement it online.
Answer by Bunny83 · Nov 22, 2018 at 03:15 AM
First of all if we analyse your example you get this:
As you can see it's actually not that well distributed. However you can see some generally valid geometry which can be justified just fine by looking at the numbers. The general layout is a hexagon. The center hexagon is a "classical" hexagon made up of 6 equilateral triangles with side length 1. This gives a diameter of 2 and a circumference of 6. The enclosing circle of the inner most hexagon also has radius 1 but a circumference of 2PI (6.283).
If you look at the next ring (green) it has a radius of 2 (diameter of 4) and 2 times the number of triangles. The next ring (yellow) has a radius of 3 (diameter of 6) and 3 times the number of triangles. This pattern continues. The 4 spikes in the blue ring wouldn't be necessary if we had continued the pattern in the outer ring just like at the bottom part.
. To generate this you can look at the problem in a different way. This is the same circle colored in a different pattern:
As you can see the circle actually is nothing but a big tessellated hexagon but the further you go out the more the intermediate points are pushed outwards to it's circular equivalent. If you just create a tessellated hexagon and lerp the intermediate points between the tessellated hexagon points and the points on the corresponding point on the circle radius of each ring you get a result similar to your example. Just keep in mind that you increase the lerping from 0 to 1 as you go from the inner most ring to the outer ring. So the outer ring will bit an actual circle while the rings in between are not exactly on their circle . The orange big triangle roughly shows how it would look like. Though it has one additional triangle here.
So you have to decide how many rings you want to use. Divide your desired circle radius by the ring count and you get your "unit length" for the innermost ring / hexagon. How you create the circle points is up to you. However the easiest way would be to just divide each ring into X equal parts where X is 6*ringIndex
Answer by Ignivome · Nov 22, 2018 at 06:20 AM
It's been answered on Stackoverflow. Credit to Yuri Nudelman.
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class UniformCirclePlane : MonoBehaviour {
public int resolution = 4;
// Use this for initialization
void Start() {
GetComponent<MeshFilter>().mesh = GenerateCircle(resolution);
}
// Update is called once per frame
void Update() {
}
// Get the index of point number 'x' in circle number 'c'
static int GetPointIndex(int c, int x) {
if (c < 0) return 0; // In case of center point
x = x % ((c + 1) * 6); // Make the point index circular
// Explanation: index = number of points in previous circles + central point + x
// hence: (0+1+2+...+c)*6+x+1 = ((c/2)*(c+1))*6+x+1 = 3*c*(c+1)+x+1
return (3 * c * (c + 1) + x + 1);
}
public static Mesh GenerateCircle(int res) {
float d = 1f / res;
var vtc = new List<Vector3>();
vtc.Add(Vector3.zero); // Start with only center point
var tris = new List<int>();
// First pass => build vertices
for (int circ = 0; circ < res; ++circ) {
float angleStep = (Mathf.PI * 2f) / ((circ + 1) * 6);
for (int point = 0; point < (circ + 1) * 6; ++point) {
vtc.Add(new Vector2(
Mathf.Cos(angleStep * point),
Mathf.Sin(angleStep * point)) * d * (circ + 1));
}
}
// Second pass => connect vertices into triangles
for (int circ = 0; circ < res; ++circ) {
for (int point = 0, other = 0; point < (circ + 1) * 6; ++point) {
if (point % (circ + 1) != 0) {
// Create 2 triangles
tris.Add(GetPointIndex(circ - 1, other + 1));
tris.Add(GetPointIndex(circ - 1, other));
tris.Add(GetPointIndex(circ, point));
tris.Add(GetPointIndex(circ, point));
tris.Add(GetPointIndex(circ, point + 1));
tris.Add(GetPointIndex(circ - 1, other + 1));
++other;
} else {
// Create 1 inverse triange
tris.Add(GetPointIndex(circ, point));
tris.Add(GetPointIndex(circ, point + 1));
tris.Add(GetPointIndex(circ - 1, other));
// Do not move to the next point in the smaller circle
}
}
}
// Create the mesh
var m = new Mesh();
m.SetVertices(vtc);
m.SetTriangles(tris, 0);
m.RecalculateNormals();
m.UploadMeshData(true);
return m;
}
}
Your answer
Follow this Question
Related Questions
Creating 3D representation of procedurally generated 2D tile map 1 Answer
Shadow artifects on mesh with Standard shader 1 Answer
How to darken a procedurally added texture (explained below) 0 Answers
How to calculate uvs for roof procedurally generated? 3 Answers
Correctly threading calculations 0 Answers