web-dev-qa-db-ja.com

球メッシュを手続き的に生成します

次のような球メッシュの3D座標を生成するアルゴリズム(擬似コード)を探しています。

alt text

水平スライスと横スライスの数は構成可能である必要があります

26
clamp

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 ))

{0、...、M}の各mと{0、...、N-1}のnについて、それに応じて点の間に線分を描画します。

編集:極で「緯度線」を数えるかどうかを決定する必要があるため、必要に応じてMを1または2だけ調整します。

36
Jonathan

これは、テストせずに頭のてっぺんから外れています。それは良い出発点かもしれません。これにより、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 curcumference point for each circle starting from the top.

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

}
2
bhavinp

推測ですが、おそらく(0,0,0)を中心とする球の式を使用できます。

x²+y²+z²=1

これをxについて解き、yとzの値のセットをループして、計算されたxでプロットします。

1
John Boker

これは、上記の回答に対して機能する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);
        }
    }
}
0
yshahak