Сделайте сферу с равноотстоящими вершинами
Я пытаюсь сделать сферический всплеск лучей с целью проверки столкновения, но определенные взаимодействия происходят в зависимости от того, куда или куда попал каждый луч. Следовательно, почему я использую лучи, а не что-то более простое, такое как 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 в случайном программировании.
Я надеюсь, что это делает вещи проще!
Вы можете использовать икосферу. Поскольку вершины распределены по равносторонним треугольникам, ваши вершины гарантированно будут равноотстоящими.
Чтобы построить икосферу, сначала создайте икосаэдр, а затем рекурсивно разделите грани на более мелкие треугольники, как описано в этой статье.
- разрезать сферу на N кругов
- вычислить периметр этого
- разделить его на тот же угол, который создает срез
- это дает вам количество вершин
- а также угол шага внутри круга
- литые лучи
Вот как я кодировал это в 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.