3D flex, вращение вокруг случайной точки для контейнера (с частичным решением!)

Я пытаюсь найти лучший способ повернуть контейнер (или что-то еще в этом отношении), используя функции matrix3D во flash 10 для гибкости.

Мне удалось заставить контейнер вращаться вокруг точки, которая не является его точкой регистрации, но я справился с этим, только отключив обрезку на контейнере, а затем поместив содержимое в другое место, кроме (0,0,0). Это работает, но не очень интуитивно понятно и отстой, когда вы пытаетесь разместить несколько элементов или даже если вам нужно переместить точку вращения.

Использование класса matrix3D кажется правильным решением, но я не уверен, как именно.

Ваше здоровье

Дополнительная информация. Если мой контейнер находится в точке (0,0,0) на сцене, и я хочу повернуться вокруг средней координаты X контейнера, я перевожу на container.width / 2 для X, затем снова вращаю и перевожу обратно. Это прекрасно работает. НО, если мой контейнер находится в (10, 0, 0), то, если я переведу то же самое, что и выше, и добавлю дополнительные 10, это не сработает.

Soloution (это полная чушь - объясните, если можете). Как было предложено, вам нужно перевести, повернуть, а затем -traslate. Я знал это, но это никогда не работало.
НО, посмотрите решение ниже, я не понимаю. (панель - это объект, который я вращаю, я вызываю функцию both ())

private function rotateOnly() : void {
        panel.transform.matrix3D.appendRotation(36, Vector3D.Y_AXIS);
}

private var valueToMove : Number = 300;
private var translateUpOrDown : Boolean = false;
private function translateOnly() : void {
    if(translateUpOrDown){
            panel.transform.matrix3D.appendTranslation(valueToMove, 0, 0);
    translateUpOrDown = false;
} else {
    panel.transform.matrix3D.appendTranslation(-valueToMove, -0,0);
    translateUpOrDown = true;
}
 }

 //I do not run both chunks of code here at once, this is only to show what I've tried   
 private function both() : void {
     //IF I call this function and call this chunk then the rotation works
        translateOnly();
        rotateOnly();
        translateOnly(); 


     //If I call this chunk which does the exact same as the above it does NOT work!!
        panel.transform.matrix3D.appendTranslation(valueToMove, 0,0);
panel.transform.matrix3D.appendRotation(36, Vector3D.Y_AXIS);
panel.transform.matrix3D.appendTranslation(-valueToMove, 0,0); 
 }

person kenneth    schedule 09.03.2009    source источник
comment
ваш второй фрагмент кода имеет неправильные переводы - первый перевод должен быть отрицательным, затем вращаться, затем положительный перевод (согласно моему ответу)   -  person Alnitak    schedule 11.03.2009
comment
Угу, ваше право, это то, что происходит, когда вы слишком долго смотрите на проблему! Вначале я также использовал для перевода ширину, высоту, x и y контейнеров, что сбивало с толку, так как я не ожидал, что они изменятся. Это испортило общий вид. Ваше здоровье.   -  person kenneth    schedule 12.03.2009


Ответы (3)


Матрицы вращения всегда вращаются вокруг начала координат.

Для вращения объекта вокруг произвольной точки P обычно требуется:

  1. перевод объекта -P
  2. поворот объекта по мере необходимости
  3. перевод объекта P
person Alnitak    schedule 09.03.2009
comment
Ага, я пробовал это. Я взял matrix3D контейнера, сделал appendTranslation (-x, -y, -z), затем сделал appendRotation, затем еще один appendTranslation (x, y, z). Я пробовал другие варианты с использованием класса matrix3D, но не могу понять это правильно. - person kenneth; 10.03.2009
comment
Решение Alnitak предполагает, что объект находится в исходной точке. - person Andy Li; 06.03.2010

Хорошо, решение было бы -

1 - создайте свой собственный компонент с переменными для исходных X, Y, Z, а также ширины и высоты. Они будут использоваться для удобства, чтобы сэкономить дополнительные операции с матрицей. Например, расширите класс Box и просто добавьте те var в новый класс.

2 - добавить компонент в приложение, как показано ниже. (Значения ориджина обусловлены тем, что фактические значения x, y, z и т. д. будут меняться во время вращения, но вам необходимо установить значения ориджина для расчета правильного вращения.

<local:RotationContainer 
        id="movingBox" 
        width="50"
        origWidth="50"
        height="60"
        origHeight="60"
        x="80"
        origX="80"
        y="70"
        origY="70"
        z="0"
        origZ="0"
        enterFrame="rotateObject(event)"
        />

3 - используйте следующий код при вращении, вызовите указанное выше событие enterFrame

private var translateUpOrDown : Boolean = false;
        private function translateOnly(obj : Object, valueToMoveX : Number,  valueToMoveY : Number) : void {

            if(translateUpOrDown){
                obj.transform.matrix3D.appendTranslation(valueToMoveX, valueToMoveY, 0);
                translateUpOrDown = false;
            } else {
                obj.transform.matrix3D.appendTranslation(-valueToMoveX, -valueToMoveY, 0);
                translateUpOrDown = true;
            }
        }

        private function rotateOnly(obj : Object) : void {
            obj.transform.matrix3D.appendRotation(rotationAmount, Vector3D.Y_AXIS);
        }

        private function rotateObject(event : Event) : void {

            var offsetX : Number = (event.currentTarget.origWidth / 2) + event.currentTarget.origX;
            var offsetY : Number = (event.currentTarget.origHeight / 2) + event.currentTarget.origY;

            translateOnly(event.currentTarget, offsetX, offsetY);
            rotateOnly(event.currentTarget);
            translateOnly(event.currentTarget, offsetX, offsetY);
        }

4 - вот и все. Он будет вращаться вокруг центральной точки по оси Y. Измените значения смещения для разных точек вращения.

ОБНОВЛЕНИЕ Как уже указывалось, вам не нужно перемещать вызовы в отдельную функцию, но вам нужно будет использовать указанное выше, чтобы вы могли получить исходную ширину, высоту, x и y (при условии, что вы не жестко кодируете все значения)

person kenneth    schedule 11.03.2009

Вы думали о простом перемещении вектора поворота?

var matrix:Matrix3d = new Matrix3d();
matrix.appendRotation(degrees, axis, new Vector3d(container.width/2,container.height/2,0));
person Theo.T    schedule 11.03.2009
comment
Я действительно пробовал это, и это дало некоторые неожиданные результаты (во всяком случае, не те результаты, которых я добивался). Liveocs действительно нужна дополнительная информация или примеры, чтобы показать работу 3D, поскольку вы не можете получить исходный код класса matrix3D (если я не ошибаюсь, но я не мог). - person kenneth; 11.03.2009