Статус:
Offline
Реєстрація: 14.06.2007
Повідом.: 13582
Реєстрація: 14.06.2007
Повідом.: 13582
Преобразовать Кватернион в Сферические углы
Короче нужно написать функции преобразования кватерниона в сферические углы вращения. И обратно
Почитал инет, написал, но работает не правильно, хз почему
Может кто-то поможет разобраться? 
Вот код, как видно из теста, одно значение угла вычисляется правильно, но без знака, и оно может попадать не на ту ось вращения... Остальные вообще не соответствуют...
:
вывод:
Значения после слова TEST - это реальные значения сферических углов.
Quat - это реальное значение кватерниона (взяты отладчиком из 3D игрушки).
Далее идет строка с вычисленными из кватерниона сферическими координатами.
И последняя строка - кватернион расчитанный на базе вычисленных сферических координат.
Короче нужно написать функции преобразования кватерниона в сферические углы вращения. И обратно

Почитал инет, написал, но работает не правильно, хз почему


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

Код:
using System;
public class Vec3
{
public float x, y, z;
public Vec3(float vx, float vy, float vz)
{
x = vx;
y = vy;
z = vz;
}
public override string ToString()
{
return string.Format("[x={0},y={1},z={2}]", x, y, z);
}
}
public class Quat
{
public Vec3 v;
public float w;
public Quat(Vec3 vv, float vw)
{
v = vv;
w = vw;
}
public Quat(Spheric s)
{
float radians = (float)(180.0D / Math.PI);
float sin_a = (float)Math.Sin( s.angle / (2.0f * radians));
float cos_a = (float)Math.Cos( s.angle / (2.0f * radians));
float sin_lat = (float)Math.Sin( s.latitude/radians );
float cos_lat = (float)Math.Cos( s.latitude / radians);
float sin_long = (float)Math.Sin( s.longitude / radians);
float cos_long = (float)Math.Cos( s.longitude / radians);
float X = sin_a * cos_lat * sin_long;
float Y = sin_a * sin_lat;
float Z = sin_a * sin_lat * cos_long;
float W = cos_a;
v = new Vec3(X, Y, Z);
w = W;
}
public Spheric ToSpheric()
{
return new Spheric(this);
}
public override string ToString()
{
return string.Format("[v={0}, w={1}]", v, w);
}
}
public class Spheric
{
public float latitude;
public float longitude;
public float angle;
public Spheric(Quat q)
{
float radians = (float)(180.0D / Math.PI);
float cos_angle = q.w;
float sin_angle = (float)(Math.Acos(cos_angle) * 2 * radians);
angle = (float)(Math.Acos(cos_angle) * 2 * radians);
if (Math.Abs(sin_angle) < 0.0005f)
sin_angle = 1.0f; //?? sa
float tx = q.v.x / sin_angle; //?? sa
float ty = q.v.y / sin_angle; //?? sa
float tz = q.v.z / sin_angle; //?? sa
latitude = (float)-Math.Asin(ty);
longitude = 0.0f;
if (tx * tx + tz * tz >= 0.0005)
longitude = (float)(Math.Atan2(tx, tz) * radians);
if (longitude < 0)
longitude += 360.0f;
}
public Quat ToQuat()
{
return new Quat(this);
}
public override string ToString()
{
return string.Format("[lat={0}, long={1}, ang={2}]", latitude, longitude, angle);
}
}
public class Program
{
static void Main()
{
showData(new Quat(new Vec3(-0.007F, 0.0F, -0.006F), 1.0F), "0, 0, 0");
showData(new Quat(new Vec3(0.0F, -0.007F, 1.0F), 0.0F), "0, 0, 180");
showData(new Quat(new Vec3(0.0F, 0.0F, -0.709F), 0.705F), "0, 0, -90");
showData(new Quat(new Vec3(0.0F, 0.0F, 0.707F), 0.706F), "0, 0, 90");
showData(new Quat(new Vec3(0.385F, 0.0F, 0.0F), 0.923F), "45, 0, 0");
showData(new Quat(new Vec3(-0.389F, 0.0F, 0.0F), 0.921F), "-45, 0, 0");
showData(new Quat(new Vec3(0.0F, -0.385F, 0.923F), 0.001F), "-45, 0, 180");
//showData(new Quat(new Vec3(0.0001F, -0.007F, 0.9999F), 0.0001F));
//showData(new Quat(new Vec3(0.385F, 0.0001F, 0.0001F), 0.923F));
}
static void showData(Quat q, string realData)
{
Console.WriteLine("TEST {0}", realData);
Console.WriteLine("Quat={0}", q);
Console.WriteLine("{0}", q.ToSpheric());
Console.WriteLine("{0}", q.ToSpheric().ToQuat());
Console.WriteLine();
}
}
вывод:
TEST 0, 0, 0
Quat=[v=[x=-0.007,y=0,z=-0.006], w=1]
[lat=0, long=0, ang=0]
[v=[x=0,y=0,z=0], w=1]
TEST 0, 0, 180
Quat=[v=[x=0,y=-0.007,z=1], w=0]
[lat=3.888889E-05, long=0, ang=180]
[v=[x=0,y=6.787392E-07,z=6.787392E-07], w=1.83356E-08]
TEST 0, 0, -90
Quat=[v=[x=0,y=0,z=-0.709], w=0.705]
[lat=0, long=0, ang=90.34091]
[v=[x=0,y=0,z=0], w=0.705]
Значения после слова TEST - это реальные значения сферических углов.
Quat - это реальное значение кватерниона (взяты отладчиком из 3D игрушки).
Далее идет строка с вычисленными из кватерниона сферическими координатами.
И последняя строка - кватернион расчитанный на базе вычисленных сферических координат.