Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > Общие вопросы о Flash (не затрагивающие ActionScript)

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 15.11.2012, 14:51
AlexLucas вне форума Посмотреть профиль Отправить личное сообщение для AlexLucas Найти все сообщения от AlexLucas
  № 1  
Ответить с цитированием
AlexLucas
 
Аватар для AlexLucas

Регистрация: Feb 2011
Сообщений: 431
По умолчанию Группировка объектов

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

И в принципе есть два решения :

1) Засовывать их в новый Sprite. Это облегчит существенно процесс вращения и растягивания, но для того чтобы добавить элемент в группу, нужно будет его "изъять" со сцены (заморочка с add(remove)Element / add(remove)Child во флексе) и добавить в мувик, при этом подгонять ему новые координаты чтобы визуально он остался на той же позиции. А в случае с вложенными группами это может превратиться в нехилый геморрой. Также что касается растягивания (поэкспериментировал со спрайтами) , то тоже всё автоматом будет сжиматься / растягиваться.

2) Объединять их в группы с помощью ассоциативных массивов. Т.е. каждому элементу задать свой groupID, и при клике на него, выделять всю группу (перетаскивать / вращать итд).
Существенно упрощает работу с координатами, в принципе я реализовал в этом случае всё кроме вращения.
Но при вращении придётся вращать каждый элемент вокруг своей оси и вокруг центра тяжести группы (который можно будет перетаскивать), что обещает доставить немало хлопот. При растягивании придётся учитывать смещение по x и y и изменение ширины/высоты. Кроме того, при операциях с целой группой придётся в цикле проматывать все элементы : скажем, при перетаскивании придётся обновлять координаты всех элементов группы, и элементов вложенных групп, итд.

У меня вопрос - какой из вариантов будет жрать меньше ресурсов? Конечно многое зависит от реализации, но всё же?
И может есть третий вариант, который намного проще и я попусту бьюсь головой об батарею ?
Заранее спасибо.


Последний раз редактировалось AlexLucas; 15.11.2012 в 15:01.
Старый 16.11.2012, 02:31
maxkar вне форума Посмотреть профиль Отправить личное сообщение для maxkar Найти все сообщения от maxkar
  № 2  
Ответить с цитированием
maxkar

Регистрация: Nov 2010
Сообщений: 497
Цитата:
Сообщение от AlexLucas Посмотреть сообщение
Но при вращении придётся вращать каждый элемент вокруг своей оси и вокруг центра тяжести группы (который можно будет перетаскивать), что обещает доставить немало хлопот.
Почему? Это банальное домножение матриц трансформации на одну и ту же матрицу. Если не ошибаюсь, домножать нужно будет слева.
Цитата:
У меня вопрос - какой из вариантов будет жрать меньше ресурсов? Конечно многое зависит от реализации, но всё же?
Сколько у вас будет элементов? Групп? Глубина вложенных групп? Количество перемещений? Количество вращений? У меня есть сильные подозрения, что основные проблемы доставит рендеринг вашего хозяйства на экран после перемещения, а не сам проход по элементам в группе (если там сильно не накосячить). А разницы между движением через спрайт и каждого отдельного спрайта особой не будет. Там в одном случае умножение на матрицу-трансформатор будет делать флеш-плеер, а во втором - то же самое вы вручную. В общем, на отдельных объектах будет на одно умножение меньше (что не принципиальнь, если только у вас нет вложенности в несколько тысяч групп, на дне которой всего один элемент). Ну и техники вроде cacheAsBitmap вы для группы использовать не сможете на отдельных спрайтах.
В вашем случае правильное решение не заботится пока о быстродействии отрисовки, но принять меры для возможности замены способа отображения (спрайт или отедльные спрайты на экране) без изменения остальной логики. Простыми словами, отделить Model+Controller от View. Model от изменения способа отображения у вас измениться не должен. А потом уже по месту решать, что делать со view.
Цитата:
И может есть третий вариант, который намного проще и я попусту бьюсь головой об батарею?
Ну так матрицы же. Ключевые слова: линейная алгебра, аналитическая геометрия, линейное пространство, операторы над линейными пространствами. Первый курс (технические вузы). ЛинАл и АнГем в нужном объеме идут обычно в одном учебнике. Какие-то вещи можно пропустить (не нужны определители, метрические пространства и все, что с ними связано, кривые второго порядка).
Все ваши действия делаются элементарным домножением слева на матрицу трансформации. Т.е. была у объекта матрица Mo, стала Mt*Mo, где Mt - матрица преобразования. Для поворотов/сдвигов строится легко. Для перекоса (skew) повернутой группы (в координатах группы) чуть-чуть сложнее (добавится обратная матрица текущего преобразования группы). Соответственно, если у вас объекты собраны в одну группу, умножается только матрица группы. Если разобрана - матрицы отдельных элементов группы. Mt в этом случае - одна для всех таких элементов вне зависимости от вложенности!
Ну и на всякий случай - никакой магии там нет. Эффективная матрица для объектов в группе строится путем умножения на внешние матрицы групп . Т.е. в одном случае у вас было Mg1*Mg2*Mob=Mobj1 (g1, g2 - группы, Mob- матрица трансформации объекта в группе g2, Mg2 - трансформация группы g2 относительно g1, Mg1 - трансформация g1 относительно сцены, Mobj1 - трансформация объекта относительно сцены). Очевидно, что из этого следует, что (Mt*Mg1)*(Mg2*Mob)=Mt*(Mg1*Mg2*Mob)=Mt*Mobj1, так что с точки зрения чистой математики без разницы, кого на что домножать.
С точки зрения реализации я бы хранил отдельные матрицы трансформации для групп и объектов внутри группы. Для визуализации - как угодно. Можно складывать в спрайты (может быть, ставить им cacheAsBitmap). Можно раскладывать индивидуальные листья, вычисляя эффективную матрицу. Для трансформаций есть небольшое отличие, связанное с точностью вычислений. При использовании индивидуальных матриц из-за потери точности объекты внутри группы могут начать "разъезжаться" относительно друг друга. Т.е. после какого-то количества поворотов, например, квадрат перекосится. Причем вернуть объекты "в исходное состояние" уже не получится. А в группе (с отдельной матрицей) можно будет сбросить трансформацию группы и объекты станут квадратными. Хотя вы артефакты из-за точности вряд ли заметите, чтобы что-то накопилось, нужно быть или очень везучим (чтобы сразу создать матрицу трансформации, которая даст артефакт), или очень долго и нудно крутить объект (миллионы и миллиарды раз).

Всякие rotation/scaleX/scaleY/x/y у визуального объекта вам не нужны. Совсем. Вам нужны матрицы. При желании преводить координаты из одних систем в другие (ну мало ли где нужно, для вывода на экран, например) используются те же матрицы преобразования объектов. В матрицах все прекрасно пишется и работает. Прием все операции (повотот, сдвиг, масштабирование, перекос (skew)) - все это домножения на матрицы, только матрицы разные. Соответственно, выбор и формирование матрицы делается при выборе операции, а затем на модель просто применяется операция (applyTransform(Matrix), например).

Старый 16.11.2012, 18:57
AlexLucas вне форума Посмотреть профиль Отправить личное сообщение для AlexLucas Найти все сообщения от AlexLucas
  № 3  
Ответить с цитированием
AlexLucas
 
Аватар для AlexLucas

Регистрация: Feb 2011
Сообщений: 431
Ну архитектура моего приложения скорее MVP чем MVC.
А что касается матриц, ведь всё кроме skew и shear можно осуществить элементарным rotation / x / y / scale.

Вы видимо объяснили мне как растягивать пропорционально целую группу элементов, но я так и не понял :
К примеру растягиваем группу с width 200 и height 300 так что в итоге её width изменяется на 10, height на 20.
Какую матрицу применить ко всем элементам этой группы чтобы они также пропорционально растянулись ?

Сделал но при scaleX и Y текстовых полей текст искажается ( в растре) / меняет размер шрифта (в векторе)


Последний раз редактировалось AlexLucas; 16.11.2012 в 20:25.
Старый 17.11.2012, 16:06
maxkar вне форума Посмотреть профиль Отправить личное сообщение для maxkar Найти все сообщения от maxkar
  № 4  
Ответить с цитированием
maxkar

Регистрация: Nov 2010
Сообщений: 497
Конкретная архитектура не слишком принципиальна. Главное, чтобы вид был отделен от модели и его было просто поменять. Матрицами проще работать, чем scale/x/y/rotation. Через них все преобразования делаются единообразно и комбинации преобразований тоже легко выражаются. Через x/y/scale/rotation повотор вокруг произвольной точки, например, не так просто делается (для уже повернутого объекта).

Со скейлом все просто. Пусть мы скейлим относительно точки x, y. Тогда матрица будет
Код:
|1 0 x|   |sx 0  0|   |1 0 -x|
|0 1 y| * |0  sy 0| * |0 1 -y| = Ms
|0 0 1|   |0  0  1|   |0 0  1|
sx = 210 / 200, sy = 320 / 300
Соответственно, там все нужно умножить. X и Y при этом параллельны X и Y соответствующей области. Если мы скейлим повернутую группу, там все похоже. Если группа имеет трансформацию относительно сцены Mgt, то указанный скейл в координатах группы (визуально повернутый прямоугольник растягивается) будет Mgt*Ms*(Mgt^-1). Т.е на эту матрицу тоже можно умножать все объекты из группы и они попадут в правильную позицию (но тогда на матрицу группы мы отдельные элементы для получения эффективной матрицы не умножаем, естественно).

С текстом не совсем понятно, что именно вы хотите. Я бы как раз ожидал, что после скейла текст пропорционально уменьшится вместе со всеми остальными объектами группы. А иначе я нарисую кнопку, поскейлю, и она разъедется. Хотя вообще это тоже не большая проблема. Тоже решается матрицами . Пусть Mf - эффективная матрица текстового поля (либо просто матрица, либо произведение всег групп на собственную матрицу, если работать с раздельными матрицами). Тогда вычисляем "систему координат" текстового поля в экранных координатах.
Код:
          |1|        |0|            |0|        |0|       |x' 0  0|
xs = Mf * |0| - Mf * |0|, ys = Mf * |1| - Mf * |0|, Mt = |0  y' 0|
          |1|        |1|            |1|        |1|       |0  0  1|
x' = 1/sqrt(xs*xs), y' = 1/sqrt(ys*ys)
xs, ys - единичные вектора текстового поля в экранной системе координат. x', y' - нормирующие коэффициенты (вы же хотите, чтобы длины единичных отрезков сохранялись, поэтому они так и выбраны). Поэтому нужно еще домножить матрицу трансформации справа (именно справа!) на Mt. А еще умножить "исходную" ширину текстового поля на x' и высоту на y' (потому что относительно текста они изменились). Итоговая матрица для вывода текста будет (Mf * Mt). Все преобразования меняют только Mf! Mt (а также x' и y') вычисляются только в момент вывода текста на экран (при рендеринге) и пересчитывается при изменении Mf. Очевидно, что текст "относительно группы" при таких требованиях может выглядеть совершенно не так, как относительно экрана.


Последний раз редактировалось maxkar; 17.11.2012 в 16:21.
Создать новую тему Ответ Часовой пояс GMT +4, время: 10:48.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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