Создание сферического сектора во время выполнения

#c# #unity3d #mesh #polar-coordinates

#c# #unity3d #сетка #полярные координаты

Вопрос:

Я пытался создать сферические сектора в Unity3d из заданных углов phi и theta во время выполнения. Я написал скрипт для его создания, но при его запуске ничего не отображается. Я знаю математику, лежащую в основе вычисления координат, но только начал генерировать эту сетку. Я думаю, что проблема может заключаться в создании треугольников. Есть идеи? Код прилагается. Буду признателен за любую помощь.

 using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using UnityEngine;

public class Sector
{
Mesh mesh;
int resolution;
float radius;
int ThetaLim1;
int ThetaLim2;
int PhiLim1;
int PhiLim2;

private float DegreetoRadians(float Degrees)
{
    float rads = Degrees * (Mathf.PI / 180);
    return rads;
}

public Sector(Mesh mesh ,int ThetaLim1, int ThetaLim2, int PhiLim1, int PhiLim2, int resolution, float radius)
{
    this.mesh = mesh;
    this.resolution = resolution;
    this.radius = radius;
    this.ThetaLim1 = ThetaLim1 > ThetaLim2 ? ThetaLim1 : ThetaLim2;
    this.ThetaLim2 = ThetaLim2 < ThetaLim1 ? ThetaLim2 : ThetaLim1;
    this.PhiLim1 = PhiLim1 > PhiLim2 ? PhiLim1 : PhiLim2;
    this.PhiLim2 = PhiLim2 < PhiLim1 ? PhiLim2 : PhiLim1;
}

public void ConstructMesh()
{
    UnityEngine.Vector3[] vertices = new UnityEngine.Vector3[((ThetaLim1 - ThetaLim2) * resolution) * ((PhiLim1 - PhiLim2) * resolution)];
    int a = vertices.Length;
    int[] triangles = new int[(int)((Mathf.Sqrt(a) - 1) * (Mathf.Sqrt(a) - 1) * 6)];
    int TriIndex = 0;

    for (float theta = ThetaLim2; theta <= ThetaLim1; theta  = 1/resolution)
    {
        for (float phi = PhiLim2; phi <= PhiLim1; phi  = 1 / resolution)
        {
            int i = (int)(phi * theta * resolution);
            float x = radius * Mathf.Sin(DegreetoRadians(theta)) * Mathf.Cos(DegreetoRadians(phi));
            float y = radius * Mathf.Sin(DegreetoRadians(theta)) * Mathf.Sin(DegreetoRadians(phi));
            float z = radius * Mathf.Cos(DegreetoRadians(theta));
            vertices[i] = new UnityEngine.Vector3(x, y, z);

            if (theta != resolution - 1 amp;amp; phi != resolution - 1)
            {
                triangles[TriIndex] = i;
                triangles[TriIndex   1] = i   ((PhiLim1 - PhiLim2) * resolution)   1;
                triangles[TriIndex   2] = i   ((PhiLim1 - PhiLim2) * resolution);

                triangles[TriIndex   3] = i;
                triangles[TriIndex   4] = i   1;
                triangles[TriIndex   5] = i   ((PhiLim1 - PhiLim2) * resolution)   1;
                TriIndex  = 6;

            }
        }
    }

    mesh.Clear();
    mesh.vertices = vertices;
    mesh.triangles = triangles;
    mesh.RecalculateNormals();
}
}
  

[ПРАВИТЬ]
Итак, я снова немного покопался и отредактировал свой код. Теперь я уверен, что даже сгенерированные треугольники верны, но теперь я получаю сообщение об ошибке при запуске скрипта, индекс вышел за пределы массива в 2d-массиве в цикле. Я проверил, добавив индексы массива в мой цикл отладки, и он даже не переходит во внешний цикл. Я понятия не имею, что происходит не так. Кажется, я все сделал правильно. В любом случае обновленный код выглядит следующим образом

 using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using UnityEngine;

public class Sector
{
Mesh mesh;
int resolution;
float radius;
int ThetaLim1;
int ThetaLim2;
int PhiLim1;
int PhiLim2;

private float DegreetoRadians(float Degrees)
{
    float rads = Degrees * (Mathf.PI / 180);
    return rads;
}

public Sector(Mesh mesh ,int ThetaLim1, int ThetaLim2, int PhiLim1, int PhiLim2, int resolution, float radius)
{
    this.mesh = mesh;
    this.resolution = resolution;
    this.radius = radius;
    this.ThetaLim1 = ThetaLim1 > ThetaLim2 ? ThetaLim1 : ThetaLim2;
    this.ThetaLim2 = ThetaLim2 < ThetaLim1 ? ThetaLim2 : ThetaLim1;
    this.PhiLim1 = PhiLim1 > PhiLim2 ? PhiLim1 : PhiLim2;
    this.PhiLim2 = PhiLim2 < PhiLim1 ? PhiLim2 : PhiLim1;
}

public void ConstructMesh()
{
    int[,] VertexTell = new int[(ThetaLim1 - ThetaLim1) * resolution, (PhiLim1 - PhiLim2) * resolution];
    UnityEngine.Vector3[] vertices = new UnityEngine.Vector3[((ThetaLim1 - ThetaLim2) * resolution) * ((PhiLim1 - PhiLim2) * resolution)];
    int a = vertices.Length;
    int[] triangles = new int[(int)((Mathf.Sqrt(a) - 1) * (Mathf.Sqrt(a) - 1) * 6)];
    int TriIndex = 0;
    int i = 0;
    int ThetaIndex = 0;
    int PhiIndex = 0;
    int MaxPhi = 0;

    for (float theta = ThetaLim2; theta < ThetaLim1; theta  = 1/resolution)
    {
        for (float phi = PhiLim2; phi < PhiLim1; phi  = 1 / resolution)
        {
            float x = radius * Mathf.Sin(DegreetoRadians(theta)) * Mathf.Cos(DegreetoRadians(phi));
            float y = radius * Mathf.Sin(DegreetoRadians(theta)) * Mathf.Sin(DegreetoRadians(phi));
            float z = radius * Mathf.Cos(DegreetoRadians(theta));
            vertices[i] = new UnityEngine.Vector3(x, y, z);
            VertexTell[ThetaIndex, PhiIndex] = i;
            PhiIndex  ;
            i  ;
        }
        ThetaIndex  ;
        MaxPhi = PhiIndex;
        PhiIndex = 0;
    }

    for (int j = 0; j < ThetaIndex; j  )
    {
        for (int k = 0; k < MaxPhi; k  )
        {
            triangles[TriIndex] = VertexTell[j, k];
            triangles[TriIndex] = VertexTell[j   1, k   1];
            triangles[TriIndex] = VertexTell[j   1, k];
            triangles[TriIndex] = VertexTell[j, k];
            triangles[TriIndex] = VertexTell[j, k   1];
            triangles[TriIndex] = VertexTell[j   1, k   1];
            TriIndex  = 6;
        }
    }

    mesh.Clear();
    mesh.vertices = vertices;
    mesh.triangles = triangles;
    mesh.RecalculateNormals();
}
}
  

[ПРАВКА]
Итак, я поработал над этим дальше и избавился от всех ошибок. Теперь я перехожу к лучшей части: «Ошибок нет, но ничего не работает». Новый код ниже

 using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Net.Http.Headers;
using System.Reflection;
using UnityEngine;
using UnityEngine.Rendering.VirtualTexturing;

public class Sector
{
Mesh mesh;
int resolution;
float radius;
int ThetaLim1;
int ThetaLim2;
int PhiLim1;
int PhiLim2;

private float DegreetoRadians(float Degrees)
{
    float rads = Degrees * Mathf.Deg2Rad;
    return rads;
}

public Sector(Mesh mesh ,int ThetaLim1, int ThetaLim2, int PhiLim1, int PhiLim2, int resolution, float radius)
{
    this.mesh = mesh;
    this.resolution = resolution;
    this.radius = radius;
    this.ThetaLim1 = ThetaLim1 > ThetaLim2 ? ThetaLim1 : ThetaLim2;
    this.ThetaLim2 = ThetaLim2 < ThetaLim1 ? ThetaLim2 : ThetaLim1;
    this.PhiLim1 = PhiLim1 > PhiLim2 ? PhiLim1 : PhiLim2;
    this.PhiLim2 = PhiLim2 < PhiLim1 ? PhiLim2 : PhiLim1;
}

public void ConstructMesh()
{
    int index1 = (ThetaLim1 - ThetaLim2) * resolution;
    int index2 = (PhiLim1 - PhiLim2) * resolution;
    Debug.Log("INDEX OF THETA "   index1   " INDEX OF PHI "   index2);
    int[,] VertexTell = new int[(ThetaLim1 - ThetaLim2) * resolution, (PhiLim1 - PhiLim2) * resolution];
    Debug.Log(VertexTell.Length);
    UnityEngine.Vector3[] vertices = new UnityEngine.Vector3[((ThetaLim1 - ThetaLim2) * resolution) * ((PhiLim1 - PhiLim2) * resolution)];
    UnityEngine.Vector3[] normals = new UnityEngine.Vector3[vertices.Length];
    int[] triangles = new int[((ThetaLim1 - ThetaLim2) * resolution - 1) * ((PhiLim1 - PhiLim2) * resolution - 1) * 6];
    int TriIndex = 0;
    int i = 0;

    float res = resolution * 1.0f;

    for (int j = 0; j < index1; j  )
    {
        for (int k = 0; k < index2; k  )
        {
            float theta = ThetaLim2   (j /res);
            float phi = PhiLim2   (k /res);
            float x = radius * Mathf.Sin(DegreetoRadians(theta)) * Mathf.Cos(DegreetoRadians(phi));
            float y = radius * Mathf.Cos(DegreetoRadians(theta));
            float z = radius * Mathf.Sin(DegreetoRadians(theta)) * Mathf.Sin(DegreetoRadians(phi));
            vertices[i] = new UnityEngine.Vector3(x, y, z);
            normals[i] = new UnityEngine.Vector3(Mathf.Pow(0 - x, 2) / Mathf.Sqrt(Mathf.Pow(x, 2)   Mathf.Pow(y, 2)   Mathf.Pow(z, 2)), Mathf.Pow(0 - y, 2) / Mathf.Sqrt(Mathf.Pow(x, 2)   Mathf.Pow(y, 2)   Mathf.Pow(z, 2)), Mathf.Pow(0 - z, 2) / Mathf.Sqrt(Mathf.Pow(x, 2)   Mathf.Pow(y, 2)   Mathf.Pow(z, 2)));
            VertexTell[j, k] = i;
            i  ;
            // Now how the hell should I calculate normals?
        }
    }

    for (int j = 0; j < index1 - 1 ; j  )
    {
        for (int k = 0; k < index2 - 1; k  )
        {
            triangles[TriIndex] = VertexTell[j, k];
            triangles[TriIndex] = VertexTell[j   1, k   1];
            triangles[TriIndex] = VertexTell[j   1, k];
            triangles[TriIndex] = VertexTell[j, k];
            triangles[TriIndex] = VertexTell[j, k   1];
            triangles[TriIndex] = VertexTell[j   1, k   1];
            TriIndex  = 6;
        }
    }

    mesh.Clear();
    mesh.vertices = vertices;
    mesh.triangles = triangles;
    mesh.RecalculateNormals();

}
}
  

Комментарии:

1. некоторые общие рекомендации: Убедитесь, что направления нормалей / треугольников не инвертированы. Попробуйте экспортировать сетку и открыть ее в каком-нибудь стороннем инструменте, чтобы вы могли проверить построение сетки.

2. Я на самом деле немного следил за уроком YouTube, где он процедурно генерировал сферы для создания планет, он использовал ту же функцию для вычисления нормалей, это собственная функция вычисления нормалей unity. Кроме того, я раньше работал только над Unity.