procedurally generate a sphere mesh
Asked Answered
S

5

33

i am looking for an algorithm ( in pseudo code) that generates the 3d coordinates of a sphere mesh like this:

alt text

the number of horizontal and lateral slices should be configurable

Shine answered 2/11, 2010 at 20:40 Comment(2)
no, it's not. it's for a personal project.Shine
that's called a disco ball configuration of points on a sphere as far as i know. its the easiest configuration.Pathic
C
48

If there are M lines of latitude (horizontal) and N lines of longitude (vertical), then put dots at

(x, y, z) = (sin(Pi * m/M) cos(2Pi * n/N), sin(Pi * m/M) sin(2Pi * n/N), cos(Pi * m/M))

for each m in { 0, ..., M } and n in { 0, ..., N-1 } and draw the line segments between the dots, accordingly.

edit: maybe adjust M by 1 or 2 as required, because you should decide whether or not to count "latitude lines" at the poles

Canst answered 2/11, 2010 at 20:55 Comment(2)
+1, because this works with any graphics library. Another Question: Is there a way to also control the radius of the sphere?Sixtynine
@Sixtynine : this gives values for (x, y, z) from 0 to 1. To scale it to any radius, just multiply each point by your desired radius.Custos
R
4

FWIW, you can use meshzoo (a project of mine) to generate meshes on spheres very easily.

You can optionally use optimesh (another one out of my stash) to optimize even further.

import meshzoo
import optimesh

points, cells = meshzoo.icosa_sphere(10)


class Sphere:
    def f(self, x):
        return (x[0] ** 2 + x[1] ** 2 + x[2] ** 2) - 1.0

    def grad(self, x):
        return 2 * x

points, cells = optimesh.cvt.quasi_newton_uniform_full(
    points, cells, 1.0e-2, 100, verbose=False,
    implicit_surface=Sphere(),
    # step_filename_format="out{:03d}.vtk"
)

enter image description here

Rubino answered 16/10, 2019 at 16:3 Comment(0)
L
2

This is just off the top of my head without testing. It could be a good starting point.

This will give you the most accurate and customizable results with the most degree of precision if you use double.

public void generateSphere(3DPoint center, 3DPoint northPoint
                          , int longNum, int latNum){

     // Find radius using simple length equation
        (distance between center and northPoint)

     // Find southPoint using radius.

     // Cut the line segment from northPoint to southPoint
        into the latitudinal number

     // These will be the number of horizontal slices (ie. equator)

     // Then divide 360 degrees by the longitudinal number
        to find the number of vertical slices.

     // Use trigonometry to determine the angle and then the
        circumference point for each circle starting from the top.

    // Stores these points in however format you want
       and return the data structure. 

}
Laterality answered 2/11, 2010 at 20:58 Comment(0)
B
2

This is a working C# code for the above answer:

using UnityEngine;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class ProcSphere : MonoBehaviour
{

    private Mesh mesh;
    private Vector3[] vertices;

    public int horizontalLines, verticalLines;
    public int radius;

    private void Awake()
    {
        GetComponent<MeshFilter>().mesh = mesh = new Mesh();
        mesh.name = "sphere";
        vertices = new Vector3[horizontalLines * verticalLines];
        int index = 0;
        for (int m = 0; m < horizontalLines; m++)
        {
            for (int n = 0; n < verticalLines - 1; n++)
            {
                float x = Mathf.Sin(Mathf.PI * m/horizontalLines) * Mathf.Cos(2 * Mathf.PI * n/verticalLines);
                float y = Mathf.Sin(Mathf.PI * m/horizontalLines) * Mathf.Sin(2 * Mathf.PI * n/verticalLines);
                float z = Mathf.Cos(Mathf.PI * m / horizontalLines);
                vertices[index++] = new Vector3(x, y, z) * radius;
            }
        }
        mesh.vertices = vertices;
    }

    private void OnDrawGizmos()
    {
        if (vertices == null) {
            return;
        }
        for (int i = 0; i < vertices.Length; i++) {
            Gizmos.color = Color.black;
            Gizmos.DrawSphere(transform.TransformPoint(vertices[i]), 0.1f);
        }
    }
}
Break answered 21/11, 2017 at 15:28 Comment(1)
I've tested this in Unity and it worked. But my edit stackoverflow.com/review/suggested-edits/24704133 got rejected. Why? @Break can you add my changes?Millipede
T
1

just a guess, you could probably use the formula for a sphere centered at (0,0,0)

x²+y²+z²=1

solve this for x, then loop throuh a set of values for y and z and plot them with your calculated x.

Tremulant answered 2/11, 2010 at 20:47 Comment(2)
Not sure this is a good idea, depending on the performance requirements of the project in question, as this method surely involves a sqrt(), which I believe is expensive.Jallier
If anyone decided they actually wanted to try this method, they would probably also need to be directed to an article on Marching Cubes...Rexer

© 2022 - 2024 — McMap. All rights reserved.