Форум программистов, компьютерный форум, киберфорум
Наши страницы
3D моделирование
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/24: Рейтинг темы: голосов - 24, средняя оценка - 5.00
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
1

Как математически зная только вектор вычислить кватернион?

20.04.2015, 22:15. Просмотров 4600. Ответов 154
Метки нет (Все метки)

Создаю направленный источник света в максе.
Свойством dir в MAXSctipt судя по справке, я получаю нормализованный вектор направления.
Также есть свойство rotation которое возвращает углы вращения в кватернионах.
По сути эти два свойства определяют одно и тоже - куда будет смотреть проектор. Изменяя одно из них, видны изменения и в другом.
Вопрос в том, как математически зная только вектор вычислить кватернион?
У меня есть записи свойств объектов на подобии SpotLight из которых известны только позиция и вектор направления. Эту информацию нужно конвертировать в другой редактор, который работает только с позицией и кватернионом.
Кароче, как из трех чисел получить четыре?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.04.2015, 22:15
Ответы с готовыми решениями:

Как отправить файл на сервер через FTP не зная имени а зная только расширение файла?
Доброго времени суток! Очень нужна ваша помощь форумчане.. Пытаюсь отправить файл через FTP на...

Найти вектор x,зная что вектор x перпендикулярен вектору a
3)Найти вектор x,зная что вектор x перпендикулярен вектору a,a=(1;0;1),вектор x перпендикулярен...

вычислить площадь и периметр равнобедренного треугольника зная только его катеты
задача очень лёгкая но у меня не получается))) я начинающий тока..... вычислить площадь (S) и...

Как найти вектор направления тела, зная угол поворота?
Как найти вектор направления\смещения по осям тела, зная угол его поворота.

Вычислить и отнормировать вектор, полученный как произведение матрицы A на вектор B
Вычислить вектор , равный произведению матрицы А(15,15) и вектора B(b1,..b15) полученный вектор...

154
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
20.04.2015, 22:44 2
Цитата Сообщение от Constantius24 Посмотреть сообщение
Кароче, как из трех чисел получить четыре?
Из каких именно трех? и какие именно четыре? Кватернион это ось вращения и поворот относительно нее. К какой локальной оси объекта он должен быть привязан? Насколько понимаю он привязывается к Direction т.е есть, и надо найти крен. rotation какие именно углы возвращает? не он ли искомое четвертое число?

Добавлено через 7 минут
Цитата Сообщение от Constantius24 Посмотреть сообщение
Вопрос в том, как математически зная только вектор вычислить кватернион?
Никак. крен может быть любой вокруг оси направления. т.е - есть ось, а угла вращения нету, соответсвенно повернуто сохраняя это же направление может быть как угодно (на все 360).

Добавлено через 3 минуты
вообще для однозначного определения положения в простанстве нужны либо 2 неколлинеарных вектора либо один вектор и угол поворота относительно него.
1
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 09:18  [ТС] 3
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
для однозначного определения положения в простанстве нужны либо 2 неколлинеарных вектора либо один вектор и угол поворота относительно него.
Я тоже был в этом убежден, но как оказалось это не так.
Вообщем есть информация о моделях и скрипт для макса, который их импортирует. Внутри модели хранится информация о множестве источников света и их расположению относительно родителя(локальная система координат). Так вот глядя в процес построения максовского источника света на основе исходного задаются только свойства pos и dir. Оба это значения XYZ. И только на основе этого проекторы смотрят туда куда надо.
Я пишу на C# и мне нужно вручную вычислить вращение объекта в пространстве в кватернионах на основе вектора правления. Вопрос в том по какой формуле это сделать.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Из каких именно трех? и какие именно четыре? Кватернион это ось вращения и поворот относительно нее.
Есть XYZ расположения объекта и XYZ вектора направления. Нужно получить XYZW (кватернион).
0
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 09:24  [ТС] 4
Для наглядности:
Как математически зная только вектор вычислить кватернион?
0
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
21.04.2015, 17:34 5
Цитата Сообщение от Constantius24 Посмотреть сообщение
Есть XYZ расположения объекта и XYZ вектора направления. Нужно получить XYZW (кватернион).
НУ если как второй вектор использовать сам радиус-вектор позиции то. можно попробовать, но не факт что ориентация в пространстве будет такая как задуманна и соответственно есть пара ограничений: объект не может быть рассположенв центре ГСК, объект не должен смотреть в центр ГСК.
Векторно умножаешь Direction на Position, получаешь вторую ось, нормализуешь ее, потом эту вторую ось умножаешь векторно на Direction вот тебе три оси (а соответсвенно и матрица поворота из которой можно получить кватернион). наклон второй оси относительно плоскости xoz (z в глубину) можно использовать как угол крена. В принципе как угол крена можно использовать и угол между радиус-вектором позиции и xoz но отсчет начала угла будет поверутна 90 градусов.

Добавлено через 5 минут
Ну и простое решение - расставь крен 0. для источника света если он не проектор крен не важен. Опять же использовать будешь в редакторе, там по результату можно крен подправить.
1
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 18:07  [ТС] 6
Fulcrum_013, код на C#:
C#
1
2
3
4
5
6
            Vector3D position = new Vector3D(0.00335693, 11.41830000, 0.08299210);
            Vector3D direction = new Vector3D(-0.00000092, -0.98480800, 0.17364800);
 
            Vector3D temp = Vector3D.CrossProduct(position, direction); // Векторно умножаешь Direction на Position, получаешь вторую ось,
            temp.Normalize(); // нормализуешь ее,
            temp = Vector3D.CrossProduct(temp, direction); // потом эту вторую ось умножаешь векторно на Direction
Дальше
вот тебе три оси (а соответсвенно и матрица поворота из которой можно получить кватернион).
Как его получить?
0
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
21.04.2015, 18:15 7
Как его получить? Должна быть функция которая из матрицы ЛСК делает кватернион сейчас в DXSDK залезу посмотрю. Direction тоже должна быть предварительно нормализована.

Добавлено через 4 минуты
D3DXQuaternionRotationMatrix функция называется из матрицы поворота ЛСК делает кватернион. Полученные три вектора и есть столбцы матрицы поворота.
1
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 18:16  [ТС] 8
Fulcrum_013, в сторонних библиотеках типа XNA есть подобные штуки, но это слишком громоздко для такого мелкого решения, оптимальный вариант самим написать функцию. Как математически это вычисляется?

Добавлено через 1 минуту
Fulcrum_013, это оно - http://www.euclideanspace.com/maths/...xToQuaternion/ ?
0
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
21.04.2015, 18:19 9
ну а вообще если там аналога нету - то делаешь проекцию второй оси на xoz, и находишь угол между осью и ее проекцией это и есть угол кватерниона (в зависимости от того с какой из двух найденных осей находишь углол относительно XOZ отсчет угла сдвигается на 90 градусов)
1
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 18:28  [ТС] 10
Попытался поработать с матрицей:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
double[,] m = new double[3, 3];
            m[0, 0] = position.X;
            m[0, 1] = position.Y;
            m[0, 2] = position.Z;
            m[1, 0] = direction.X;
            m[1, 1] = direction.Y;
            m[1, 2] = direction.Z;
            m[2, 0] = temp.X;
            m[2, 1] = temp.Y;
            m[2, 2] = temp.Z;
 
            double w, x, y, z;
            w = Math.Sqrt(1 + m[0, 0] + m[1, 1] + m[2, 2]) / 2;
            x = (m[2, 1] - m[1, 2]) / 4 * w;
            y = (m[0, 2] - m[2, 0]) / 4 * w;
            z = (m[1, 0] - m[0, 1]) / 4 * w;
квадратный корень не вычисился, результата нет.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
делаешь проекцию второй оси на xoz, и находишь угол между осью и ее проекцией это и есть угол кватерниона
вообще ничего не понял(
у меня есть встроенный метод нахождения угла между двумя векторами, и к чему мне его применить?
0
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
21.04.2015, 18:40 11
Более простой вариант находишь угол между третьей осью и осью ОY (0,1,0). Скалярное произведение-косинус угла, векторное - синус. Ну а если с проекцией - то у заданной оси обнуляешь Y это и есть ее проекция на XOZ.

Добавлено через 6 минут
т.е. высчитал ось сделал
C#
1
2
Vector3D temp1=temp;
temp1.y=0;
угол находишь между temp1 и temp;
1
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 18:44  [ТС] 12
Теперь так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
            Vector3D position = new Vector3D(0.00335693, 11.41830000, 0.08299210);
            Vector3D direction = new Vector3D(-0.00000092, -0.98480800, 0.17364800);
 
            Vector3D temp = Vector3D.CrossProduct(position, direction); // Векторно умножаешь Direction на Position, получаешь вторую ось,
            temp.Normalize(); // нормализуешь ее,
            temp = Vector3D.CrossProduct(temp, direction); // потом эту вторую ось умножаешь векторно на Direction
 
            double angle = Vector3D.AngleBetween(temp, new Vector3D(0, 1, 0)); // находишь угол между третьей осью и осью ОY (0,1,0)
            double scalar = Math.Cos(angle); // Скалярное произведение-косинус угла,
            double vec = Math.Sin(angle); // векторное - синус.
 
            double x, y, z, w; // ???
даже не буду спрашивать, что и зачем мы вычисляли, тупо скажите, что куда подставить, чтобы получить XYZW кватерниона.
0
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
21.04.2015, 18:58 13
Ну соответсвенно x y z - из Direction, w = angle. т.е. кватернион это поворот относительно оси. Ось - direction. А поворот это угол наклона плоскости содержащей любую из остальных осей ЛСК и соответствующей ей плоскостью ГСК. И найти этот угол есть куча вариантов, если задана эта вторая ось.
Синус коснинус это на случай если нет функции нахождения угла между векторами. он находится как ArcTan2(abs(crossproduction()),dotproduction());
1
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 19:33  [ТС] 14
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Ну соответсвенно x y z - из Direction, w = angle.
Есть.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vector3D position = new Vector3D(0.00335693, 11.41830000, 0.08299210);
            Vector3D direction = new Vector3D(-0.00000092, -0.98480800, 0.17364800);
            direction.X *= -1;
            direction.Y *= -1;
            direction.Z *= -1;
 
            Vector3D temp = Vector3D.CrossProduct(position, direction);
            temp.Normalize();
            temp = Vector3D.CrossProduct(temp, direction);
 
            double angle = Vector3D.AngleBetween(temp, new Vector3D(0, 1, 0));
 
            Quaternion rotation = new Quaternion(direction, angle);
 
            Console.WriteLine(rotation);
Теперь проверяем:
Как математически зная только вектор вычислить кватернион?

Есть предположения, где косяк и почему результаты не сходятся?
0
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
21.04.2015, 21:15 15
Естественно есть - там Origin задан (это второй вектор), а у нас он практически с потолка берется.
1
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 21:27  [ТС] 16
Вот полный код построения источника света в максе:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
local light = freespot()
                light.usefaratten = true
                light.showfaratten = true
                light.farattenstart = 0     
                light.parent = light_root
                
                local light_bone = undefined
                if skel_obj != undefined then
                    light_bone = skel_obj.boneObjUsingGameId skel_obj.rootBone lights[i].BoneID
                if light_bone == undefined then
                    light_bone = light_root
                
                in coordsys light_bone
                (
                    light.dir = lights[i].Direction * -1
                    light.pos = lights[i].Position                  
                )               
                
                light.color = lights[i].Color
                light.farattenend = lights[i].Distance / 2
                light.multiplier = lights[i].Range / 10
                light.falloff = lights[i].Falloff
                
                local type = ofutils.lowercase(lights[i].Type)
                if type == "omni" then
                (
                    light.type = #omni
                ) else
                (
                    light.type = #freeSpot
                    light.hotspot = lights[i].HotSpot
                )
 
                setUserProp light "type" "light"
                setUserProp light "typeflags" lights[i].TypeFlags                   
                setUserProp light "coronasize" lights[i].CoronaSize
                setUserProp light "coronahash" ("\x22" + lights[i].CoronaHash + "\x22")
                setUserProp light "luminescencehash" ("\x22" + lights[i].LuminescenceHash + "\x22")
                setUserProp light "flags" lights[i].Flags
                setUserProp light "boneid" lights[i].BoneID
                
                setUserProp light "_f28" lights[i]._f28
                setUserProp light "_f2C" lights[i]._f2C
                setUserProp light "_f30" lights[i]._f30
                setUserProp light "_f58" lights[i]._f58
                setUserProp light "_f5C" lights[i]._f5C
                setUserProp light "_f60" lights[i]._f60             
                setUserProp light "_f66" lights[i]._f66
                
                lights[i].obj = light
Origin не используется...
Наткнулся на интересный пример кода: http://xboxforums.create.msdn.com/forums/p/5385/28215.aspx
Переписал под себя:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        static Quaternion GetRotationFromDirection(Vector3D direction)
        {
            Vector3D up = new Vector3D(0, 1, 0);
            Vector3D right = Vector3D.CrossProduct(up, direction);
            up = Vector3D.CrossProduct(direction, right);
 
            Matrix3D basis = new Matrix3D(
                right.X, right.Y, right.Z, 0,
                up.X, up.Y, up.Z, 0,
                direction.X, direction.Y, direction.Z, 0,
                0, 0, 0, 1);
 
            Quaternion quat = new Quaternion();
            quat.W = Math.Sqrt(1 + basis.M11 + basis.M22 + basis.M33) / 2;
            double wScale = quat.W * 4;
            quat.X = (basis.M32 - basis.M23) / wScale;
            quat.Y = (basis.M13 - basis.M31) / wScale;
            quat.Z = (basis.M21 - basis.M12) / wScale;
            return quat;
        }
0
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
21.04.2015, 21:28 17
То же самое, только за вектор Up берут ось Y (т.е - крен 0). у нас радиус вектор, т.е крен зависит от позиции.
0
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 21:31  [ТС] 18
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Естественно есть - там Origin задан (это второй вектор), а у нас он практически с потолка берется.
Думаю стоит забить на макс как на эталон и подсовывать напрямую в нужный мне редактор.
Давай все заного, но теперь с учетом третьего вектора.
Правильно ли я собрал матрицу?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Vector3D position = new Vector3D(0.00335693, 11.41830000, 0.08299210);
Vector3D direction = new Vector3D(-0.00000092, -0.98480800, 0.17364800);
Vector3D origin = new Vector3D(0.00000016, 0.17364800, 0.98480800);
 
// fix
direction.X *= -1;
direction.Y *= -1;
direction.Z *= -1;
 
Matrix3D matrix = new Matrix3D(
position.X, position.Y, position.Z, 0,
direction.X, direction.Y, direction.Z, 0,
origin.X, origin.Y, origin.Z, 0,
0, 0, 0, 1);
0
Fulcrum_013
1547 / 1194 / 139
Регистрация: 14.12.2014
Сообщений: 10,234
Завершенные тесты: 3
21.04.2015, 21:49 19
Лучший ответ Сообщение было отмечено Constantius24 как решение

Решение

Абсолютно нет. Direction - У тебя ось Z - т.е первые три элемента третьего столбца. Первый и второй столбцы - те два вектора которые получались умножением. второй столбец up*direction.Normalized. первый - произведение второго и третьего. Позиция в четвертой строке а не в первой, т.е 4 строка position.X, position.Y, position.Z, 1

Добавлено через 6 минут
Вот собственно говоря построение матрицы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// * - CrossProduct, % - DotProduct
inline TMatrix __fastcall LookAt(TVector Target, TVector Eye, TVector Up){
       TMatrix R;
 
       TVector zaxis = (Target-Eye);
       zaxis.Normalize();
       TVector xaxis = Up*zaxis;
       xaxis.Normalize();
       TVector yaxis = zaxis*xaxis;
       R.Identity();
       R.D[0][0]=xaxis.x;
       R.D[0][1]=yaxis.x;
       R.D[0][2]=zaxis.x;
 
       R.D[1][0]=xaxis.y;
       R.D[1][1]=yaxis.y;
       R.D[1][2]=zaxis.y;
 
       R.D[2][0]=xaxis.z;
       R.D[2][1]=yaxis.z;
       R.D[2][2]=zaxis.z;
 
       R.D[3][0]=-(xaxis%Eye);
       R.D[3][1]=-(yaxis%Eye);
       R.D[3][2]=-(zaxis%Eye);
       R.D[3][3]=1;
       return R;
};
1
Constantius24
67 / 67 / 42
Регистрация: 30.03.2015
Сообщений: 371
21.04.2015, 21:50  [ТС] 20
В моем случае Target это Position, Eye это Direction, а Up это Origin ?
0
21.04.2015, 21:50
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.04.2015, 21:50

Как удалить таблицу зная только половину её названия?
Как удалить таблицу зная только половину её названия в mysql?

Как удалить TImage* зная только его Hint?
Всем Привет!:senor: Появилась задачка. есть динамически созданные объекты типа TImage у них есть...

Как получить id элемента, зная только его класс?
Приветствую товарищи! Пожалуйста, помогите мне с решением одной задачи. У меня есть такой код: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru