Сделайте сферу с равноотстоящими вершинами

Я пытаюсь сделать сферический всплеск лучей с целью проверки столкновения, но определенные взаимодействия происходят в зависимости от того, куда или куда попал каждый луч. Следовательно, почему я использую лучи, а не что-то более простое, такое как OverlapSphere,

Причина, по которой я ищу способ создания сферы, состоит в том, что я могу использовать ту же математику для своих лучей, заставляя их идти к вершинам того, где будет сфера. Но каждый способ, который я могу найти для создания сферы, состоит в том, что линии приближаются к полюсам, что имеет смысл, поскольку это довольно легко сделать. Но, как вы можете себе представить, это не так полезно для моего текущего проекта.

TL; DR: Как сделать сферу с равноотстоящими вершинами? Если он не идеально равноудален, то его нужно просто закрыть. Если это произойдет, было бы здорово, если бы вы могли указать, какая будет разница, и где, если применимо.

Дополнительные примечания: я смотрел на это и на это, но математика у меня над головой, так что то, что я искал, могло просто смотреть мне в лицо все это время.

6 ответов

Решение

Знаете ли вы, что сфера, данная вам Unity, на самом деле предназначена

с этой конкретной целью?

т. е. весь смысл сферы, встроенной в Unity, заключается в том, что точки довольно гладко расположены в пространстве, примерно равноудалены, как вы это сформулируете.

Чтобы создать такую ​​сферу в Unity, просто сделайте это:

Затем вы можете мгновенно получить доступ к вертам, как вы знаете,

Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vv = mesh.vertices;
int kVerts=vv.Length
for (int i=0; i<kVerts; ++i)
  Debug.Log ... vv[i] 

Обратите внимание, что вы можете легко проверить, "в какой части сферы" они находятся, например, проверив, как далеко они находятся от ваших "городов" (или чего-то еще), или просто проверить (например) значения z, чтобы увидеть, какое они полушарие. в.. и так далее.


Более того...

Пожалуйста, обратите внимание. Что касается вашей общей причины желания сделать это:

но конкретные взаимодействия происходят в зависимости от того, что или где каждый луч ударил

Обратите внимание, что это не может быть проще сделать с помощью PhysX. (Полностью встроенная игровая физика в Unity.) Действительно, я никогда, никогда не смотрел на столкновение, не делая что-то "конкретное" в зависимости от того, "где оно попало!"

Например, вы можете получить точку, где контакт был с http://docs.unity3d.com/ScriptReference/RaycastHit-point.html

Стоит отметить, что совершенно невероятно, что можно написать что-то, приближающееся к производительности PhysX в случайном программировании.

Я надеюсь, что это делает вещи проще!

Вы можете использовать икосферу. Поскольку вершины распределены по равносторонним треугольникам, ваши вершины гарантированно будут равноотстоящими.

введите описание изображения здесь

Чтобы построить икосферу, сначала создайте икосаэдр, а затем рекурсивно разделите грани на более мелкие треугольники, как описано в этой статье.

  1. разрезать сферу на N кругов
  2. вычислить периметр этого
  3. разделить его на тот же угол, который создает срез
    • это дает вам количество вершин
    • а также угол шага внутри круга
  4. литые лучи

Вот как я кодировал это в C++ + OpenGL:

// draw unit sphere points (r=1 center=(0,0,0)) ... your rays directions
int ia,na,ib,nb;
double x,y,z,r;
double a,b,da,db;
na=16;                                  // number of slices
da=M_PI/double(na-1);                   // latitude angle step
for (a=-0.5*M_PI,ia=0;ia<na;ia++,a+=da) // slice sphere to circles in xy planes
    {
    r=cos(a);                           // radius of actual circle in xy plane
    z=sin(a);                           // height of actual circle in xy plane
    nb=ceil(2.0*M_PI*r/da);
    db=2.0*M_PI/double(nb);             // longitude angle step
    if ((ia==0)||(ia==na-1)) { nb=1; db=0.0; }  // handle edge cases
    for (b=0.0,ib=0;ib<nb;ib++,b+=db)   // cut circle to vertexes
        {
        x=r*cos(b);                     // compute x,y of vertex
        y=r*sin(b);
        // this just draw the ray direction (x,y,z) as line in OpenGL
        // so you can ignore this
        // instead add the ray cast of yours
        double w=1.2;
        glBegin(GL_LINES);
        glColor3f(1.0,1.0,1.0); glVertex3d(x,y,z);
        glColor3f(0.0,0.0,0.0); glVertex3d(w*x,w*y,w*z);
        glEnd();
        }
    }

Вот как это выглядит:

вершины сферы

  • Линии R,G,B являются осями сферной системы координат X,Y,Z
  • Белые линии - это ваши вершины (белые) + направление (серые)

системы координат

[Заметки]

  • не забудьте включить math.h
  • и замените материал OpenGL своим

Если вы хотите 4, 6, 8, 12 или 20 вершин, то вы можете иметь ровно равноотстоящие вершины в качестве платоновского тела, которые все помещаются внутри сферы. Фактические координаты их должно быть легко получить. Для другого числа вершин вы можете использовать другие многогранники и масштабировать вершины так, чтобы они лежали на сфере. Если вам нужно много точек, то геодезический купол может стать хорошей базой. Баскетбольный мяч C60 может стать хорошей базой с 60 очками. Для большинства из них вы должны быть в состоянии найти 3D-модели, из которых вы можете извлечь координаты.

Я думаю, что самый простой способ контролировать точки на сфере - это использовать сферические координаты. Затем вы можете контролировать положение точек вокруг сферы, используя два угла (rho и phi) и радиус.

Пример кода для равномерного заполнения точек вокруг вращающейся сферы (для развлечения):

var time = 1; // Increment this variable every frame to see the rotation
var count = 1000;
for (int i = 0; i < count; i++)
{
    var rho = time + i; 
    var phi = 2 * Math.PI * i / count;
    var x = (float)(radius * Math.Sin(phi) * Math.Cos(rho));
    var z = (float)(radius * Math.Sin(phi) * Math.Sin(rho));
    var y = (float)(radius * Math.Cos(phi));
    Draw(x, y, z); // your drawing code for rendering the point
}

Как уже предлагалось в некоторых ответах, используйте решение на основе икосаэдра. Источник этого довольно прост (и я написал свой собственный несколько раз), но я считаю, что отличный плагин Primitives Pro чрезвычайно удобен при многих других обстоятельствах и всегда использует их сферу вместо встроенной Unity.

Ссылка на компонент Примитивы Pro

Примитивы Pro варианты

Другие вопросы по тегам