Использование сферическая координата system. Углы long,lat
: 2D Линейные u,v
Координаты в вашей плоскости и продукции 3Dx,y,z
.
Преобразовать Вершины (точки) вашей плоской сетки к поверхности сферы
Я подозреваю, что вы получили очки в форме (x,y,z)
так что вам нужно первым вычислить u,v
. Пусть U,V
являются перпендикулярными единичными базисными векторами, лежащими на плоскости. Их можно получить, вычитая 2 точки на плоской сетке, нормализуя размер и используя перекрестное изделие, чтобы обеспечить перпендикулярность. Итак:
u = `dot_product((x,y,z),U)` = x*U.x + y*U.y + z*U.z
v = `dot_product((x,y,z),V)` = x*V.x + y*V.y + z*V.z
Теперь конвертировать в сферу углов:
long=6.2831853*u/u_size_of_mesh
lat =3.1415926*v/v_size_of_mesh
И, наконец, вычислить новый (x,y,z)
на поверхности сферы:
x = R*cos(lat)*cos(long)
y = R*cos(lat)*sin(long)
z = R*sin(lat)
сетки
планарной сетки должно быть достаточно плотным (достаточно треугольников/граней), иначе сфера не будет выглядеть так, как должна. Другая проблема заключается в том, что в плоской сетке нет ребер и поверхности сферы. Ti s, возможно, создаст вид/зазоры на поверхности сферы, где соединяются края плоскости. Если вы хотите избежать этого, вы можете либо добавить грани между краями на противоположных сторонах плоской сетки, чтобы заполнить пробелы, либо полностью выбросить вашу сетку, и повторно пробовать плоскость с единой сеткой точек.
Если вы хотите, чтобы полностью повторно попробовать вашу сетку, то лучшее, что вы можете сделать, это сначала создать регулярную сферу сетки, например, с:
Sphere triangulation by mesh subdivision
А затем вычислить соответствующую точку на плоскости с помощью обратного процесса в # 1 так что вы можете интерполировать другие параметры точек (например, цвет, координаты текстуры и т.д.)
[Примечания]
Если вы хотите, чтобы оживить это, то просто использовать линейную интерполяцию между исходной точкой плоскости P0(x,y,z)
и соответствующей точкой поверхности сферы P1(x,y,z)
с параметром анимации t=<0.0,1.0>
как это:
P = P0 + (P1-P0)*t
если t=0
то выход плоской сеткой еще если t=1
, то это сфера. где-нибудь между собой процесс оборачивания так увеличивает t
до 1
с достаточно малым шагом (например, 0.01
) и сделать в каком-то таймере ...
[Edit1] U, V базисных векторы
Идея является просто получить 2 непараллельных вектора и изменить один из них, чтобы перпендикулярно первому, но все же на одной плоскости.
принимать какие-либо сетки лицо
, например, треугольник ABC
Compute 2 ненулевых не являющиеся параллельными векторами на плоскости
Это легко просто вычитать любой 2 пары вершин, например:
U.x=B.x-A.x
U.y=B.y-A.y
V.x=C.x-A.x
V.y=C.y-A.y
и сделать их единицы в размерах, чтобы разделить их по размеру
ul=sqrt((U.x*U.x)+(U.y*U.y))
vl=sqrt((V.x*V.x)+(V.y*V.y))
U.x/=ul
U.y/=ul
V.x/=vl
V.y/=vl
сделать их перпендикулярно
Так оставил один вектор, как это (например U
) и вычислить другой поэтому он перпендикулярен. Для этого вы можете использовать кросс-продукт. Перекрестное произведение двух единичных векторов - это новый единичный вектор, перпендикулярный обоим. Какой из них от 2 возможностей зависит только от порядка операндов ((U x V) = - (V x U)
) так, например:
// W is perpendicular to U,V
W.x=(U.y*V.z)-(U.z*V.y)
W.y=(U.z*V.x)-(U.x*V.z)
W.z=(U.x*V.y)-(U.y*V.x)
// V is perpendicular to U,W
V.x=(U.y*W.z)-(U.z*W.y)
V.y=(U.z*W.x)-(U.x*W.z)
V.z=(U.x*W.y)-(U.y*W.x)
W
является лишь временным вектором (в изображении его называют V'
) кстати это вектор нормали к поверхность.
размер и выравнивание
Теперь, когда у меня нет больше информации о вашей сетке я не знаю, его форму, размер и т.д. ... Идеальный случай, если сетки прямоугольная и U,V
векторы выровнены по краям. В таком случае вы просто нормализуете координаты по размеру прямоугольника в каждом направлении (как в предыдущем изображении слева).
Если сетка не нравится, и вы вычисления U,V
от лица этого подхода, то результат не может быть выровнены по краям вообще (они могут быть повернуты на любой угол) ...
Если такого случая нельзя избежать (выбирая углы лица), то угловые точки вашей формы будут иметь различные координатные пределы вдоль каждого ребра. И вам необходимо интерполировать или сопоставить их с правильным сферическим интервалом в некотором смысле в полном объеме (не может быть более конкретным, поскольку у меня нет идеи, что именно вы делаете).
Для почти прямоугольных форм иногда достаточно использовать края как U,V
, даже если они не идеально перпендикулярны друг другу.
[Edit2] C++ пример
Ну, если вы получили идеально выровнены квадратную форму сетки с некоторым шумом в оси Z (например, карты высот), то это, как я хотел бы сделать преобразование сетки:
//---------------------------------------------------------------------------
struct _pnt // points
{
double xyz[3];
_pnt(){}; _pnt(_pnt& a){ *this=a; }; ~_pnt(){}; _pnt* operator = (const _pnt *a) { *this=*a; return this; }; /*_pnt* operator = (const _pnt &a) { ...copy... return this; };*/
};
struct _fac // faces (triangles)
{
int i0,i1,i2;
double nor[3];
_fac(){}; _fac(_fac& a){ *this=a; }; ~_fac(){}; _fac* operator = (const _fac *a) { *this=*a; return this; }; /*_fac* operator = (const _fac &a) { ...copy... return this; };*/
};
// dynamic mesh
List<_pnt> pnt;
List<_fac> fac;
//---------------------------------------------------------------------------
void mesh_normals() // compute normals
{
int i;
_fac *f;
double a[3],b[3];
for (f=&fac[0],i=0;i<fac.num;i++,f++)
{
vector_sub(a,pnt[f->i1].xyz,pnt[f->i0].xyz); // a = pnt1 - pnt0
vector_sub(b,pnt[f->i2].xyz,pnt[f->i0].xyz); // b = pnt2 - pnt0
vector_mul(a,a,b); // a = a x b
vector_one(f->nor,a); // nor = a/|a|
}
}
//---------------------------------------------------------------------------
void mesh_init() // generate plane mesh (your square with some z noise)
{
int u,v,n=40; // 40x40 points
double d=2.0/double(n-1);
_pnt p;
_fac f;
Randomize();
RandSeed=13;
// create point list
pnt.allocate(n*n); pnt.num=0; // preallocate list size to avoid realocation
for (p.xyz[0]=-1.0,u=0;u<n;u++,p.xyz[0]+=d) // x=<-1.0,+1.0>
for (p.xyz[1]=-1.0,v=0;v<n;v++,p.xyz[1]+=d)// y=<-1.0,+1.0>
{
p.xyz[2]=0.0+(0.05*Random()); // z = <0.0,0.05> noise
pnt.add(p);
}
// create face list
vector_ld(f.nor,0.0,0.0,1.0);
for (u=1;u<n;u++)
for (v=1;v<n;v++)
{
f.i0=(v-1)+((u-1)*n);
f.i1=(v-1)+((u )*n);
f.i2=(v )+((u-1)*n);
fac.add(f);
f.i0=(v )+((u-1)*n);
f.i1=(v-1)+((u )*n);
f.i2=(v )+((u )*n);
fac.add(f);
}
mesh_normals();
}
//---------------------------------------------------------------------------
void mesh_sphere() // convert to sphere
{
int i;
_pnt *p;
double u,v,lon,lat,r,R=1.0;
// I know my generated mesh is aligned so:
double U[3]={ 1.0,0.0,0.0 };
double V[3]={ 0.0,1.0,0.0 };
for (p=&pnt[0],i=0;i<pnt.num;i++,p++) // process all points
{
// get the u,v coordinates
u=vector_mul(p->xyz,U);
v=vector_mul(p->xyz,V);
// I also know the limits are <-1,+1> so conversion to spherical angles:
lon=M_PI*(u+1.0); // <-1.0,+1.0> -> <0.0,6.28>
lat=M_PI*v*0.5; // <-1.0,+1.0> -> <-1.57,+1.57>
// compute spherical position (superponate z to r preserve noise)
r=R+p->xyz[2];
p->xyz[0]=r*cos(lat)*cos(lon);
p->xyz[1]=r*cos(lat)*sin(lon);
p->xyz[2]=r*sin(lat);
}
mesh_normals();
}
//---------------------------------------------------------------------------
void mesh_draw() // render
{
int i;
_fac *f;
glColor3f(0.2,0.2,0.2);
glBegin(GL_TRIANGLES);
for (f=&fac[0],i=0;i<fac.num;i++,f++)
{
glNormal3dv(f->nor);
glVertex3dv(pnt[f->i0].xyz);
glVertex3dv(pnt[f->i1].xyz);
glVertex3dv(pnt[f->i2].xyz);
}
glEnd();
}
//---------------------------------------------------------------------------
Я использовал мой динамический шаблон списка так:
List<double> xxx;
таких же, как double xxx[];
xxx.add(5);
добавляет 5
в конце списка
xxx[7]
доступа к массиву (безопасный)
xxx.dat[7]
доступа элемент массива (небезопасный, но быстро прямой доступ)
xxx.num
фактический используемого размер массива
xxx.reset()
очищает массив и установить xxx.num = 0
xxx.allocate(100)
пространство для предварительно выделить 100
жет мс
Использование это так:
mesh_init();
mesh_sphere();
Здесь результаты:
Слева генерируемый плоской сетки с шумом и справа от результат после преобразования.
Код отражает все перечисленное выше + добавляет Z-шум к радиусу сферы для сохранения функций. Нормали пересчитываются из геометрии стандартным образом. Для всей матрицы TBN вам нужна информация о соединении из топологии и пересчитайте ее (или используйте геометрию сферы и используйте TBN из нее.
Кстати, если вы хотите отображать сферу вместо преобразования сетки, вы должны взглянуть на QA s:
Вы когда-нибудь пробовали обернуть мяч прямоугольник бумажке? Это ** не может работать **, и вам нужно выбрать свой компромисс. – Amit
Я думаю [это] (http://stackoverflow.com/questions/38712632/morphing-sphere-into-plane/38777667#38777667) и [это] (http://stackoverflow.com/questions/33065204/how- to-create-sphere-using-multiple-objects/33086141 # 33086141) содержит некоторую полезную информацию. – mlkn