Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Прямая кинематика (http://www.flasher.ru/forum/showthread.php?t=210436)

faraday 15.03.2015 15:54

Прямая кинематика
 
День добрый, имеется массив точек, координаты и углы которых указаны относительно родителя.
Код AS3:

[{name:'root',x:0,y:0,angle:0},
{name:'branch1', x:0, y:100, angle:0, parent:'root'},
{name:'branch2', x:100, y:0, angle:10, parent:'branch1'}]

Задача - в каждый момент времени получить для каждой точки абсолютную матрицу трансформации(например относительно stage)
Объект Joint представляю себе примерно так:
Код AS3:

public function Joint(x:int,y:int,angle:Number, parent:Joint=null){
var parent:Joint=parent;
var transform:Matrix=new Matrix().createBox(1,1,angle||0,x||0,y||0);
}
public function getRelativeTranform(){
/*????*/
}

Можно было бы использовать вложенные displayObjectContainer(как рабоатет это там?), Но штука должна работать максимально быстро, и не хочется тянуть ничего лишнего.
p.s Относительные координаты постоянно меняются

Tails 15.03.2015 20:41

  1. Матрица трансформаций относится к экранному объекту в целом, а не к конкретной точке в его локальном пространстве.
  2. Получить абсолютную матрицу для экранного объекта можно путём перемножения всех матриц его родителей и его самого.
  3. Матрица каждого экранного объекта находится в его свойстве transform.

Я бы лучше посоветовал воспользовался готовыми методами: locatoToGlobal и globalToLocal для получения координат. В случае с самостоятельными расчётами, вам потом ещё придётся умножить конечные точки на абсолютную матрицу, что-бы получить итоговый результат.

faraday 15.03.2015 21:04

1.Это понятно, но у меня точка в пространстве и есть отдельный объект.
2.Видимо тут имеет значение порядок. Если перемножать рекурсивно сверху вниз, получаются косяки небольшие, но в целом похоже. Сейчас попробую снизу вверх.
Код AS3:

        public function calcChildTransform(parentTransform:Matrix,result:Object) {
var matrix:Matrix = parentTransform.clone();
matrix.rotate((baseTransform.r) * Math.PI / 180);
matrix.translate(baseTransform.x, baseTransform.y);
result[name]=matrix;
}

3. Это мне известно)

locatoToGlobal - вернет только x,y . Вращение все равно нужно будет вычислять вручную.
UPD , да обход снизу вверх - исправил ситуацию, Спасибо, теперь считается правильно. Смущает только то, что теперь нельзя обсчитать все за один обход( В ObjectContatiner это так же реализовано?

Zebestov 16.03.2015 16:04

Можно подробней про один проход, почему нельзя?

faraday 16.03.2015 18:51

Нужно подняться вверз из каждого узла. то есть многие узлы будут пройдены по несколько раз.

Zebestov 16.03.2015 19:27

Кэширование матриц решит. Допустим есть дерево, (root)-(parent)-(child1, child2, child3). Лишь первый раз мы рекурсивно пройдемся от child1 к root и в каждом элементе (хотя в данном случае это нужно только для parent, но мы же рассматриваем общий алгоритм) закэшируем полученный результат — матрицу относительно stage. После этого child2 и child3 уже не будут бегать вверх, а лишь используют кэшированную (прямую или обратную, в зависимости от задач) матрицу своего родителя — объекта parent.

Добавлено через 1 минуту
Разумеется, это лишь один из вариантов. Как правило подобное кэширование происходит сверху-вниз по инициативе родителя, когда он трансформируется, что и приводит к необходимости пересчитать stageMatrix у всех детей. Но это уже совсем общий подход. Можно сделать и так, чтобы сразу привыкать к хорошему :)

gloomyBrain 16.03.2015 22:40

Я бы вообще хранил 2 матрицы на объект - относительную и абсолютную. Ну и да, как правильно заметил Zebestov, кеширование не повредит.

faraday 17.03.2015 01:00

Да, спасибо. Но во время анмаиции каждый узел обновляется по enterFrame, соответтственно и пересчет в глобальные координаты. Так что кеширование тут не даст ощутимого результата.

Добавлено через 28 минут
И еще вопрос, как правильно в виде матрицы записать следующее преобразование:
Код AS3:

 
var attachment:Sprite = new Sprite();
var cont:Sprite = new Sprite();
cont.addChild(attachment);
attachment.x = -attachment.width / 2;
attachment.y = -attachment.height / 2;
cont.rotation = rotation;
cont.x = offsetX;
cont.y = offsetY;
cont.scaleY = -1;

То есть нужно повернуть по центру объект, а потом сместить его и флипнуть по высоте. Никак не могу понять правильный порядок операций

Zebestov 17.03.2015 01:47

Цитата:

Сообщение от faraday (Сообщение 1180141)
…кеширование тут не даст ощутимого результата

Вообще-то даст. И тем более ощутимым будет этот результат, чем больше будет детей и чем глубже будет вложенность.

Цитата:

Сообщение от faraday (Сообщение 1180141)
И еще вопрос … нужно повернуть по центру объект, а потом сместить его и флипнуть по высоте. Никак не могу понять правильный порядок операций

Код AS3:

// готовим матрицу
var matrix:Matrix = new Matrix();
    matrix.translate(-attachment.width / 2, -attachment.height / 2);
    matrix.scale(1, -1);    // если нужно сначала повернуть, а лишь потом флипнуть
    matrix.rotate(rotation); // следует поменять местами эти две строки
    matrix.translate(offsetX, offsetY);
 
// применяем матрицу (как видно, cont и не нужен вовсе)
attachment.transform.matrix = matrix;

Но это частный случай трансформации свежесозданного экранного объекта.
Более наглядно и, в то же время, подробно здесь.

faraday 17.03.2015 11:53

Спасибо)


Часовой пояс GMT +4, время: 20:50.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.