代码之家  ›  专栏  ›  技术社区  ›  clamp

程序生成球体网格

  •  26
  • clamp  · 技术社区  · 14 年前

    我正在寻找一个算法(伪代码),生成一个球体网格的三维坐标,如下所示:

    alt text

    水平和横向切片的数量应该是可配置的

    4 回复  |  直到 9 年前
        1
  •  36
  •   Jonathan    14 年前

    如果有M条纬度线(水平)和N条经度线(垂直),则在

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

    编辑:可能根据需要将M调整为1或2,因为您应该决定是否在极点处计算“纬度线”

        2
  •  2
  •   Clemens Tolboom    5 年前

    这只是我的头上没有测试。这可能是一个很好的起点。

    如果您使用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. 
    
    }
    
        3
  •  1
  •   John Boker    14 年前

    只是猜测一下,你也许可以用公式计算一个以(0,0,0)为中心的球体

    x²+y²+z²=1
    

        4
  •  1
  •   yshahak    7 年前

    这是上述答案的有效C代码:

    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);
            }
        }
    }
    
        5
  •  -1
  •   Nico Schlömer David Maze    5 年前

    FWIW,你可以用 meshzoo

    您可以选择使用 optimesh (我藏起来的另一个)进一步优化。

    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

    推荐文章