Я хочу сделать полёт объекта в воздухе. при этом он может вращаться влево/вправо, вверх/вниз и крутиться. мне нужно что-бы он проделывал все эти действия в зависимости от всех 3 углов то есть если он летит вертикально вниз то при повороте налево или направо он должен изменить своё направление вверх. Пожалуйста дайте формулу для расчёта такой угловой скорости. Вот что у меня уже есть но здесь повороты только по 2 углам и относительно не друг другу а относительно стандартной системы координат:
D3DXVECTOR3 CalcAS(float Ay, float Ax, float S) { float Sp, Ayp, Axp; D3DXVECTOR3 Vec; Ayp = Ay * 2 * 3.1416f / 360; Axp = Ax * 2 * 3.1416f / 360; Sp = S * cos( Axp); Vec.x = Sp * cos( Ayp); Vec.z = Sp * sin( Ayp); Vec.y = S * sin( Axp); return Vec; } Ay, Ax - углы вращения вокруг оси Y и X. S - скорость объекта. Ayp, Axp - углы Ax и Ay но в радианах. Sp - скорость трансформированная под угол Axp. Возвращается угловая скорость движения в X, Y и Z.
P.S. я только в 6 классе (перехожу в 7) поэтому не надо сложных тригонометрических выражений.
>В шестом классе? Пойду повешусь, я в таком возрасте только начинал на Delphi формошлепством заниматься...
speed -> velocity
Самое простое, что приходит в голову (чтобы не париться про динамику и не узнавать раньше времени про ОДУ) - дема от Марка Харриса/Ансельмо Ластры про облака. http://www.markmark.net/SkyWorks/
Там хоть и много косинусов, но зато просто мышкой можно поуправлять самолётом.
kroonk
Не используй углы вообще. Используй направляющие вектора. У самолёта есть три вектора - направление вперёд, вправо и вверх. Если хочешь повернуть направо(относительно самолёта), то вращай направления "вперёд" и "вправо" вокруг направления "вверх". Если хочешь повернуть вверх, вращай направления "вверх" и "вперёд" вокруг направления "вправо".
Если выписать координаты этих углов в три столбика, получится матрица 3х3 - матрица поворота.
Suslik
А как сделать перемещение и повороты векторами?
kroonk
> А как сделать перемещение
Перемещение как раз гораздо удобнее, чем углами. Просто прибавляешь к текущей координате самолёта вектор его направления "вперёд", умноженный на величину скорости и на величину шага времени.
То, как повернуть один вектор вокруг другого, предлагаю вывести самостоятельно.
Suslik
Я кажется сделал эти векторы а как их в матрицу записать?
Если тебе хочется получить из них матрицу поворота, то просто запиши их координаты как столбцы матрицы. Но переводить их в матрицу в принципе вообще не обязательно, разве что непосредственно для отрисовки - в остальных случаях с ними можно работать просто как с тройкой векторов.
Я не правильно поворачиваю векторы. Пожалуйста объясните как правильно как правильно повернуть 2 вектора вокруг третьего?
У тебя вообще с векторной математикой как? Игровая программерская математика - это не то, чему тебя учат в школе на уроках математике и не совсем то, чему тебя учат на уроках геометрии, это несколько своеобразный раздел, который, вообще говоря, не сложнее и не проще, просто его надо "прочувствовать", через практику.
Ты понимаешь, как реализуются базовые операции с векторами вроде проекции вектора на вектор, скалярное/векторное произведение, переход из одной системы координат в другую? Я вот, насколько помню, в шестом классе ещё не особо свободно в подобных вещах разбирался, поэтому если чувствуешь себя с ними не совсем свободно, попробуй сперва разобраться с тем, что попроще.
Suslik
> Ты понимаешь, как реализуются базовые операции с векторами вроде проекции
> вектора на вектор, скалярное/векторное произведение, переход из одной системы
> координат в другую?
Нет. Вы написали что вектор может переходить из одной системы координат в другую я вот что придумал, если нужно повернуть 2 вектора вокруг третьего надо создать систему координат в которой тот вектор вокруг которого вращают был в координатах(0, 1, 0), 1 вращаемый вектор в координатах(0, 0, 1), а 2 в координатах(1, 0, 0). потом повернуть эти 2 вектора вокруг того 3 вектора по какому-нибудь углу и потом все эти векторы перевести обратно в нормальную систему координат, такое возможно? Если да то как это реализовать.
вот вроде-бы смог реализовать свою идею, это будет работать?:
void PhisicModel::Rotate(char* RVec, float Angle) { float MemV[3][3]; float A1, A2, A3; float Sx1, Sz1; float Sx2, Sz2; A3 = Angle * 2 * 3.14f / 360; if( RVec == "X") { MemV[0][0] = 0.0f - VecX.x; MemV[0][1] = 1.0f - VecX.y; MemV[0][2] = 0.0f - VecX.z; VecX.x += MemV[0][0]; VecX.y += MemV[0][1]; VecX.z += MemV[0][2]; MemV[1][0] = -1.0f - VecY.x; MemV[1][1] = 0.0f - VecY.y; MemV[1][2] = 0.0f - VecY.z; VecY.x += MemV[1][0]; VecY.y += MemV[1][1]; VecY.z += MemV[1][2]; A1 = 270.0f; MemV[2][0] = 0.0f - VecZ.x; MemV[2][1] = 0.0f - VecZ.y; MemV[2][2] = 1.0f - VecZ.z; VecZ.x += MemV[2][0]; VecZ.y += MemV[2][1]; VecZ.z += MemV[2][2]; A2 = ( 0.0f * 2 * 3.14f / 360); Sx1 = 1.0f * cos( A1 + A3); Sz1 = 1.0f * sin( A1 + A3); Sx2 = 1.0f * cos( A2 + A3); Sz2 = 1.0f * sin( A2 + A3); VecY.x += Sx1; VecY.z += Sz1; VecZ.x += Sx2; VecZ.z += Sz2; VecX.x -= MemV[0][0]; VecX.y -= MemV[0][1]; VecX.z -= MemV[0][2]; VecY.x -= MemV[1][0]; VecY.y -= MemV[1][1]; VecY.z -= MemV[1][2]; VecZ.x -= MemV[2][0]; VecZ.y -= MemV[2][1]; VecZ.z -= MemV[2][2]; } if( RVec == "Y") { MemV[0][0] = 1.0f - VecX.x; MemV[0][1] = 0.0f - VecX.y; MemV[0][2] = 0.0f - VecX.z; VecX.x += MemV[0][0]; VecX.y += MemV[0][1]; VecX.z += MemV[0][2]; A1 = ( 90.0f * 2 * 3.14f / 360); MemV[1][0] = 0.0f - VecY.x; MemV[1][1] = 1.0f - VecY.y; MemV[1][2] = 0.0f - VecY.z; VecY.x += MemV[1][0]; VecY.y += MemV[1][1]; VecY.z += MemV[1][2]; MemV[2][0] = 0.0f - VecZ.x; MemV[2][1] = 0.0f - VecZ.y; MemV[2][2] = 1.0f - VecZ.z; VecZ.x += MemV[2][0]; VecZ.y += MemV[2][1]; VecZ.z += MemV[2][2]; A2 = ( 0.0f * 2 * 3.14f / 360); Sx1 = 1.0f * cos( A1 + A3); Sz1 = 1.0f * sin( A1 + A3); Sx2 = 1.0f * cos( A2 + A3); Sz2 = 1.0f * sin( A2 + A3); VecX.x += Sx1; VecX.z += Sz1; VecZ.x += Sx2; VecZ.z += Sz2; VecX.x -= MemV[0][0]; VecX.y -= MemV[0][1]; VecX.z -= MemV[0][2]; VecY.x -= MemV[1][0]; VecY.y -= MemV[1][1]; VecY.z -= MemV[1][2]; VecZ.x -= MemV[2][0]; VecZ.y -= MemV[2][1]; VecZ.z -= MemV[2][2]; } if( RVec == "Z") { MemV[0][0] = 1.0f - VecX.x; MemV[0][1] = 0.0f - VecX.y; MemV[0][2] = 0.0f - VecX.z; VecX.x += MemV[0][0]; VecX.y += MemV[0][1]; VecX.z += MemV[0][2]; A1 = ( 90.0f * 2 * 3.14f / 360); MemV[1][0] = 0.0f - VecY.x; MemV[1][1] = 0.0f - VecY.y; MemV[1][2] = -1.0f - VecY.z; VecY.x += MemV[1][0]; VecY.y += MemV[1][1]; VecY.z += MemV[1][2]; A2 = ( 180.0f * 2 * 3.14f / 360); MemV[2][0] = 0.0f - VecZ.x; MemV[2][1] = 1.0f - VecZ.y; MemV[2][2] = 0.0f - VecZ.z; VecZ.x += MemV[2][0]; VecZ.y += MemV[2][1]; VecZ.z += MemV[2][2]; Sx1 = 1.0f * cos( A1 + A3); Sz1 = 1.0f * sin( A1 + A3); Sx2 = 1.0f * cos( A2 + A3); Sz2 = 1.0f * sin( A2 + A3); VecX.x += Sx1; VecX.z += Sz1; VecY.x += Sx2; VecY.z += Sz2; VecX.x -= MemV[0][0]; VecX.y -= MemV[0][1]; VecX.z -= MemV[0][2]; VecY.x -= MemV[1][0]; VecY.y -= MemV[1][1]; VecY.z -= MemV[1][2]; VecZ.x -= MemV[2][0]; VecZ.y -= MemV[2][1]; VecZ.z -= MemV[2][2]; } } MemV - массив сохраняющий отличия положения векторов от новой системы координат. A1, A2 - уголы в радианах отображающие положения вращаемых векторов. A3 - угол в радианах обозначающий на сколько надо повернуть векторы. Sx1, Sz1 - угловая скорость первого вращаемого вектора. Sx2, Sz2 - угловая скорость второго вращаемого вектора.
kroonk
> это будет работать?
нет
строки нельзя сравнивать, сравнивая их их адреса, надо использовать функцию strcmp
kroonk
> Вы написали что вектор может переходить из одной системы координат в другую я
> вот что придумал, если нужно повернуть 2 вектора вокруг третьего надо создать
> систему координат в которой тот вектор вокруг которого вращают был в
> координатах(0, 1, 0), 1 вращаемый вектор в координатах(0, 0, 1), а 2 в
> координатах(1, 0, 0). потом повернуть эти 2 вектора вокруг того 3 вектора по
> какому-нибудь углу и потом все эти векторы перевести обратно в нормальную
> систему координат, такое возможно? Если да то как это реализовать.
В общем-то как ни странно идея почти правильная. реализация, конечно - сказочная ерунда. Короче несколько советов:
- Не используй градусы вообще нигде, кроме домашнего задания по геометрии. Мысли сразу в радианах, это гораздо удобнее, потому что в них производные синусов/косинусов, перевод из угловых скоростей в линейные и прочие частые операции получаются без нормировочных коэффициентов.
- Не используй отдельные координаты вектора, мысли о векторе как о целом, делай операции с вектором, как целым - скалярное умножение, сложение и прочее. Желательно разберись с перегрузкой операторов и перегрузи стандартные операции со своим велосипедным классом вектора.
- Старайся разбивать свою относительно большую задачу на подзадачи, которые можно решить и отладить отдельно и когда-нибудь потом это решение использовать. В твоём случае элементарная задача - поворот одного вектора вокруг другого, напиши функцию, которая это будет делать. Если ты хочешь повернуть всю модель, то просто вызови функцию поворота для каждого определяющего направления своей модели(суть - для каждого столбца матрицы поворота).
- Не используй то, что не совсем понимаешь, если это не необходимо. Матрицы в твоём случае не необходимы - не используй их.
В общем один из самых простых и эффективных способов повернуть вектор вокруг вектора:
Переходишь в двумерную систему координат, связанную с плоскостью, перпендикулярной оси поворота. В этой плоскости поворачиваешь двумерный вектор - проекция того вектора, который ты изначально хотел повернуть. Ну и потом восстанавливаешь из полученной новой двумерной проекции уже трёхмерный вектор.
Я умышленно не хочу постить готовый код, хочу, чтобы ты сам его вывел.
Тема в архиве.