Я кодирую механику, которая позволяет пользователю перемещаться по поверхности сферы. Положение на сфере в настоящее время сохраняется как theta
и phi
, где theta
- угол между осью z и проекцией xz текущей позиции (то есть вращение вокруг оси y), и phi
является углом от оси y к этой позиции. Я объяснил это плохо, но это по сути theta = yaw
,phi = pitch
Vector3 position = new Vector3(0,0,1);
position.X = (float)Math.Sin(phi) * (float)Math.Sin(theta);
position.Y = (float)Math.Sin(phi) * (float)Math.Cos(theta);
position.Z = (float)Math.Cos(phi);
position *= r;
Я считаю, что это точно, однако я могу ошибаться. Мне нужно иметь возможность перемещаться в произвольном псевдо-двумерном направлении вокруг поверхности сферы в начале мирового пространства с радиусом r
. Например, удержание Wдолжно двигаться вокруг сферы в направлении вверх относительно ориентации игрока.
Я считаю, что я должен использовать кватернион для представления положения / ориентации на сфере, но я не могу придумать правильный способ сделать это. Сферическая геометрия не моя сильная сторона.
По сути, мне нужно заполнить следующий блок:
public void Move(Direction dir)
{
switch (dir)
{
case Direction.Left:
// update quaternion to rotate left
break;
case Direction.Right:
// update quaternion to rotate right
break;
case Direction.Up:
// update quaternion to rotate upward
break;
case Direction.Down:
// update quaternion to rotate downward
break;
}
}
(1,1,1)
удерживающийся влево, будет вращаться вокруг сферы, проходя через(~1.2,0,~-1.2)
, затем(-1,-1,-1)
, затем(~-1.2,0,~1.2)
и обратно(1,1,1)
.theta
иphi
обновлять свою позицию, вы делаете свою проблему излишне сложной. Гораздо проще просто рассчитать 2 оси вращения каждого кадра (одна из которых (рыскание) никогда не меняется) иVector3.Transorm
вокруг сферы. Это упростит вашу проблему, но заставит вас отключиться отphi
&theta
.Ответы:
На самом деле, оказывается, что вы не можете иметь «оба пути»: если вы не хотите ощущать «абсолютную ориентацию» на сфере (то есть, если игроки не всегда, например, обращены к полюсам) ), тогда вам нужно иметь представление об ориентации игрока. Это потому, что, вопреки тому, что может предположить интуиция, движение на сфере совсем не похоже на движение на плоскости, даже локально (совсем); Внутренняя кривизна сферы означает, что игроки могут выполнять действия, которые будут вращаться сами!
Для самого экстремального примера из того, о чем я говорю, представьте, что игрок начинает с точки на экваторе (для удобства мы представим циферблат часов, нанесенный сверху на экватор, и поместим игрока в 6 часов). ) лицом вверх, то есть к Северному полюсу. Предположим, игрок проходит весь путь до Северного полюса; тогда они будут направлены прямо к точке 12 часов. Теперь позвольте игроку двигаться прямо направо от Северного полюса обратно к экватору; они окажутся в точке 3 часа - но потому что их лицо не меняется, когда они движутся вправо(идея в том, что их облик не меняется независимо от того, как они двигаются), они все равно будут стоять перед точкой 12 часов - теперь они смотрят вдоль экватора! Теперь позвольте им двигаться «назад» назад к их начальной точке (6 часов); тогда они будут по-прежнему обращены вдоль экватора, поэтому они будут направлены к точке 3 часа - простое движение по сфере без изменения их «личной» ориентации заставило их повернуть лицом к северному полюсу в направлении лицом вдоль экватора! В некотором смысле, это продолжение старой шутки «охотник движется на милю к югу, на милю к западу, а затем на милю к северу» - но здесь мы пользуемся искривлением сферы, чтобы изменить направление. Обратите внимание, что тот же эффект все еще происходит даже в гораздо меньших масштабах;
К счастью, кватернионы (как вы сами отметили) справляются с этой ситуацией; поскольку кватернион представляет собой произвольное вращение, он фактически представляет произвольную «точку плюс ориентация» на сфере: представьте, что вы начинаете с «трехосной оси» в начале координат и задаете ей произвольное вращение, а затем перемещаете одну единицу в любом направлении, в котором повернуты оси ». Точки оси Z; небольшая мысль убедит вас в том, что это приведет вас к точке на сферной единице с некоторой «ориентацией» (т. е. некоторым расположением осей X и Y вашей трехоси) и что вы можете добраться до каждой точки + ориентации на единичная сфера таким образом (просто назначьте свою ось Z так, чтобы она указывала вдоль линии от начала координат до точки на сфере, а затем перенесите ваши триаксы обратно в начало координат вдоль этой линии). Более того, поскольку умножение кватернионов соответствует составу вращений, каждая из описываемых вами операций может быть представлена путем умножения вашей «текущей ориентации» на соответствующим образом выбранный кватернион: в частности, поскольку (единичный) кватернион (qx, qy, qz, qw) означает «повернуть вокруг оси (qx, qy, qz) на arccos (qw)», затем (в зависимости от вашего конкретного выбора системы координат и позволить c_a быть cos (alpha) и s_a sin (alpha)) двумя из три кватерниона M_x = (s_a, 0, 0, c_a), M_y = (0, s_a, 0, c_a) и M_z = (0, 0, s_a, c_a) будут представлять 'вращаться (т.е. двигаться) в направлении I Сейчас я нахожусь лицом к альфе »и« вращаюсь в направлении, перпендикулярном тому, с которым я сейчас сталкиваюсь альфа ». (Третий из этих кватернионов будет представлять «вращать моего персонажа вокруг своей оси»
Cur_q = M_x * Cur_q
если игрок нажал вверх, илиCur_q = M_y * Cur_q
если игрок нажал вправо (или, возможно, что-то вроде,Cur_q = M_yinv * Cur_q
если игрок нажал влево, где M_yinv - это «инверсия» кватерниона M_y, представляющая вращение в другом направлении). Обратите внимание, что вы должны быть осторожны, к какой «стороне» вы применяете поворот, будь то предварительное или повторное умножение; Откровенно говоря, это может быть проще всего решить методом проб и ошибок, попробовав умножения и выяснив, какие из них работают.Переход от обновленного кватерниона к точке на сфере (и к ориентации вашего персонажа) также относительно прост: в соответствии с последним параграфом все, что вам нужно сделать, это использовать свой кватернион на базисных векторах (1, 0,0), (0,1,0) и (0,0,1) вашего кадра с помощью операции «повернуть вектор по кватерниону» v → qvq -1 (где умножения здесь являются умножениями на кватернионы, и мы идентифицируем вектор v = (x, y, z) с «вырожденным кватернионом» (x, y, z, 0)). Например, положение на единичной сфере определяется простым преобразованием вектора z: pos = (qx, qy, qz, qw) * (0, 0, 1, 0) * (-qx, -qy, -qz, qw) = (qx, qy, qz, qw) * (qy, -qx, qw, qz) = (2 (qy * qw + qz * qx), 2 (qz * qy-qw * qx), (qz ^ 2 + qw ^ 2) - (qx ^ 2 + qy ^ 2), 0), поэтому
(2(qy*qw+qz*qx), 2(qz*qy-qw*qx), (qz^2+qw^2)-(qx^2+qy^2))
будут координаты «преобразованного» пользователя на единичной сфере (и, чтобы получить координаты на произвольной сфере, конечно, вы просто умножите их на радиус сферы); аналогичные расчеты работают для других осей, например, для определения направления движения пользователя.источник
Move()
процедуру, но чтобы получить нормализованную ось (т.е. мою позицию), я бы просто взял(sin(qx),sin(qy),sin(qw)) * r
?Я думаю, вы хотите что-то похожее на это http://www.youtube.com/watch?v=L2YRZbRSD1k
Я разработал это для 48-часового игрового джема ... вы можете загрузить код здесь ... http://archive.globalgamejam.org/2011/evil-god
Я использовал что-то похожее на ваш код, чтобы получить трехмерные координаты ... но я повернул планету, и игрок находился в том же положении, я думаю, что вы заинтересованы в движении существа, это:
источник