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

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

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

Регистрация: Mar 2009
Адрес: Kazakhstan, Almaty
Сообщений: 121
Arrow 5 Вопросов по 3D-графике и AS3

Изменение оси вращения

Допустим есть объект, состоящий из 6-ти спрайтов, каждый из которых имеет св-ва x, y, z, rotationX, rotationY, rotationZ, таким образом из них составлен куб, как показано на рис. Все эти шесть сторон куба помещены в контейнер «cube» Этот куб вращаю вокруг оси Y X или Z так:

Код AS3:
cube.rotationX+=0.7;
Но при попытке повернуть куб например сначала по оси Z на 30 градусов, а потом каждый кадр вращать по оси Y, допустим на 1,0 получается совсем не то, что ожидалось, как я понял при вращении объекта его оси не вращаются и остаются на месте, и это правильно.
Но тогда возникает вопрос, а как вращать объект по другой оси, назовем ее «A», она отличается от осей Z X и У.
Пробовал вращать по одной оси быстрее, по другой медленнее:

Код AS3:
cube.rotationZ+=0.7;
cube.rotationX+=0.3;
Получается тоже нечто очень странное.

Вопрос 1: Как вращать объект по оси «A» ? см. рисунок.



Вращение через Matrix3D

Возьмем к примеру тот же самый cube из предыдущего вопроса.
Каждый кадр поворачиваю его с помощью Matrix3D:

Код AS3:
var matrixCube:Matrix3D = cube.transform.matrix3D;
matrixCube.appendRotation(0.7, Vector3D.Y_AXIS);
cube.transform.matrix3D = matrixCube;
Все понятно, кроме одного. Куб вращается не вокруг своей оси и не вокруг точки регистрации, а вокруг точки, которая находится далеко от куба, неизвестно где.

Вопрос 2: Что это за точка? Как изменить эту точку? Или я что-то делаю неправильно?

Z-сортировка между плоскостью и другой плоскостью большего размера

Происходит сортировка всех плоскостей по величине Z.
Вот функция, вызывается каждый кадр.

Код AS3:
function sortByZMatrix(c:DisplayObjectContainer):void {
	var sortArray:Array = new Array();
	var objectsCount:int = c.numChildren;
 
	for (var i:int = 0; i < objectsCount; i++){
		var currentFace:DisplayObject = c.getChildAt(i);
 
		var m:Matrix3D = currentFace.transform.matrix3D.clone();
		m.append(c.transform.matrix3D);
 
		sortArray[i] = { obj:currentFace, z:m.position.z };
	}
 
	sortArray.sortOn("z", Array.NUMERIC | Array.DESCENDING);
 
	for (i = 0; i < objectsCount; i++){
		c.setChildIndex(sortArray[i].obj, i);
	}
 
	sortArray = null;
}//sort
Все работает замечательно, без глюков.
Но только в том случае, если все плоскости одинакового размера и не пересекаются между собой.
Если же сделать одну большую плоскость, допустим это каменный пол комнаты, то не всегда получается нужный результат.
Например на этом рисунке координата Z плоскости находится от нас дальше в глубь, чем координаты плоскостей куба, обведенного красным цветом → childIndex плоскостей куба больше чем childIndex плоскости пола и все отображается нормально.



Но если повернуть контейнер, в котором размещены все объекты, то...
Координаты Z плоскостей куба стали дальше, чем Z плоскости пола → плоскость пола отображается поверх плоскостей куба. Все логично, НО. Куб есть, а его не видно.



Можно решить эту проблему, создав пол из кучи таких же маленьких плоскостей, и тогда все отображается нормально.
Но колисчество плоскостей значительно возрастает
(10 х 10 плиток пола = 100 плоскостей)
И все начинает жутко тормозить.

Вопрос 3: Можно ли организовать сортировку таким образом,
чтобы она корректно работала с разными размерами плоскостей и не возникало ситуаций, описанных выше?
Если можно, то как примерно она должна быть устроена?
Или же все-таки остается собирать из маленьких плоскостей?
Каков вообще правильный подход к решению таких задач?



Производительность

Делаю следующим образом:
Собираю из плоскостей трехмерные объекты путем размещения и поворота этих плоскостей.
Каждая плоскость — это Shape, создается следующей функцией:

Код AS3:
function createPlane(ox:Number = 0, oy:Number = 0, oz:Number = 0, rtx:Number = 0, rty:Number = 
 
0,rtz:Number=0,b:BitmapData=null,size:Number=0):void {
	stor = new Shape();
	stor.graphics.beginFill(0xFFFFFF);
	stor.graphics.beginBitmapFill(b);
	stor.graphics.lineStyle(1, 0x000000, 1.0);
	stor.graphics.drawTriangles(
Vector.<Number>([-50-size, -50-size, 50+size, -50-size, -50+size, 50+size, 50+size, 50+size]),
Vector.<int>([0, 1, 2, 1, 3, 2]))
stor.x = ox; stor.y = oy; stor.z = oz; 
stor.rotationX = rtx; stor.rotationY = rty; stor.rotationZ = rtz;
	cube.addChild(stor);
	stors.push(stor);
	stc++;
}
Такой функцией строится куб:

Код AS3:
function createBox(ox:Number = 0,oy:Number=0,oz:Number=0):void {
	createPlane(ox+0, oy+0, oz+-50, 0, 0, 0,textureBitmapData);
	createPlane(ox+0, oy+0, oz+50, 0, 0, 0,textureBitmapData);
	createPlane(ox+50, oy+0, oz+0, 0, 90, 0,textureBitmapData);
	createPlane(ox+-50, oy+0, oz+0, 0, 90, 0,textureBitmapData);
	createPlane(ox+0, oy+50, oz+0, 90, 0, 0,textureBitmapData);
	createPlane(ox+0, oy+-50, oz+0, 90, 0, 0,textureBitmapData);
}
Создаю 10 кубов. В итоге получается 60 плоскостей. При 31 кадр/сек
все работает нормально, без подвисаний.

Код AS3:
for (t = 0; t < 10;t++){
createBox(-500+Math.random()*1000,-500+Math.random()*1000,-500+Math.random()*1000);
}
Но если создать 100 кубиков — все начинает жутко тормозить.

Вопрос 4: Нужно ли создавать каждую плоскость как отдельный Shape?
Как вообще можно повысить скорость отрисовки всего этого?
Ясно, что-то я делаю неправильно, как будет сделать разумнее и оптимизировать хоть как-то все это?




Каков правильный подход

Все яснее становится, что используя готовые классы Shape или там Sprite и создавая трехмерность таким образом, как описано выше — неправильный путь.

Вопрос 5: Так каков же тогда правильный путь? Писать все 3D вручную?
Как вообще устроены простейшие 3D-движки на флеше?

И если уж все идет на то, что нужно писать все самому, какую литературу посоветуете?
Я уже нашел статьи, но хочется именно книгу, в которой бы описывалось программирование 3D-графики с азов.

Ну, конечно, кроме учебников по математике и геометрии

Старый 18.01.2010, 13:51
wvxvw вне форума Посмотреть профиль Отправить личное сообщение для wvxvw Найти все сообщения от wvxvw
  № 2  
Ответить с цитированием
wvxvw
Modus ponens
 
Аватар для wvxvw

модератор форума
Регистрация: Jul 2006
Адрес: #1=(list #1#)
Сообщений: 8,049
Записей в блоге: 38
>> Вопрос 2: Что это за точка? Как изменить эту точку? Или я что-то делаю неправильно?
Пожалуй единственное, на что смогу ответить - смотрите в сторону projectionCenter.
А в остальном - на сколько я понимаю, использовать практически любой из существующих 3Д фреймворков в смысле производительности гораздо лучше родного 3Д...
Если задача сделать что-то именно используя флешевые возможности - посмотрите сюда:
http://www.flasher.ru/forum/blog.php?b=123
__________________
Hell is the possibility of sanity

Старый 18.01.2010, 15:19
gr_crd вне форума Посмотреть профиль Отправить личное сообщение для gr_crd Посетить домашнюю страницу gr_crd Найти все сообщения от gr_crd
  № 3  
Ответить с цитированием
gr_crd
 
Аватар для gr_crd

Регистрация: Mar 2009
Адрес: Kazakhstan, Almaty
Сообщений: 121
насчет вопроса 2. projectionCenter не помогло, однако при вращении

Код AS3:
matrixCube.appendRotation(0.7, Vector3D.Y_AXIS);
можно задавать третий параметр тоже Vector3D, который определяет то ли ось, то ли точку вращения..

Код AS3:
matrixCube.appendRotation(0.7, Vector3D.Y_AXIS, some3DVector);
попробовал применить - кубик помахал мне ручкой и по спирали улетел куда-то очень далеко.
вопрос однако остался в силе...

а тот фреймворк по ссылке достаточно резвенько работает

Старый 18.01.2010, 15:53
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 4  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
1,2: все верно, вращать надо за счет преобразований transform.matrix3D
но чтобы получить адкватный результат (вращение относительно точки регистрации, например) надо мадрицу привести в "исходное" сотояние по координатам, там повернуть и снова вернуть в прежние координаты
Код AS3:
var matrixCube:Matrix3D = cube.transform.matrix3D;
var pos:Vector3D = matrixCube.position;
matrixCube.appendTranslation(-pos.x, -pos.y, -pos.z);
matrixCube.appendRotation(0.7, Vector3D.Y_AXIS);
matrixCube.appendTranslation(pos.x, pos.y, pos.z);
cube.transform.matrix3D = matrixCube;
3: сортировка - очень мутная тема в такой схеме хотя бы уже потому, что пересечься частями объекты никак не могут, потому что части эти обычно в разных конейнерах живут
остается шаманство со складыванием частей разных объектов в один контейнер с общей сортировкой,
естественно чем мельче фрагмены, тем адекватнее они отсортируются, но увлекаться этим тоже не выходит из-за неизбежных тормозов
еще нюанс: сортировать по z-координате в общем случаем неправильно, надо сортировать по расстоянию до наблюдателя (transform.perspectiveProjection)

4,5: насчет производительности и правльных направлений мне нечего сказать, грустно все..
рисовательные движки (инфинити, альтернатива, PV3D..), которые выводят этот 3D мир за счет отрисовки полигонов, предварительно спроектированных в экран, выигрывают, конечно же в производительности, но выигрыш этот не таков, чтобы говорить о каком-то съедобном 3D, имхо
а для ерунды можно и нативными костылями обойтись

Старый 18.01.2010, 16:11
Alex Lexcuk вне форума Посмотреть профиль Отправить личное сообщение для Alex Lexcuk Посетить домашнюю страницу Alex Lexcuk Найти все сообщения от Alex Lexcuk
  № 5  
Ответить с цитированием
Alex Lexcuk

блогер
Регистрация: Mar 2008
Адрес: Донецк_city
Сообщений: 1,094
Записей в блоге: 5
Вот то-же самоделка по бездвиговому рисованию 3Д (нативными drawTriangles)
http://www.murmadillo.tut.su/3d/draw...es-sort-z.html
__________________
Гоночка

Старый 18.01.2010, 16:18
gr_crd вне форума Посмотреть профиль Отправить личное сообщение для gr_crd Посетить домашнюю страницу gr_crd Найти все сообщения от gr_crd
  № 6  
Ответить с цитированием
gr_crd
 
Аватар для gr_crd

Регистрация: Mar 2009
Адрес: Kazakhstan, Almaty
Сообщений: 121
Цитата:
но чтобы получить адкватный результат (вращение относительно точки регистрации, например) надо мадрицу привести в "исходное" сотояние по координатам, там повернуть и снова вернуть в прежние координаты
Спасибо, помогло! Вопросы 1 и 2 решены.

3 - т.е. я понял у perspectiveProjection есть св-во или метод, который определяет расстояние до наблюдателя?

Добавлено через 4 минуты
Цитата:
Вот то-же самоделка по бездвиговому рисованию 3Д (нативными drawTriangles)
спс, хорошая статья!

Старый 18.01.2010, 16:44
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 7  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
я понял у perspectiveProjection есть св-во или метод, который определяет расстояние до наблюдателя?
не напрямую, но узнать его координаты в 3D-мире можно
у меня сейчас работает такой вариант:
Код AS3:
/**
 * расстояние до наблюдателя в руте
 */
public function get viewDistance():Number 
{ 
	if (!stage) return Number.MAX_VALUE;
 
 
	//точка наблюдателя в руте
	var projection:PerspectiveProjection = root.transform.perspectiveProjection;
	var viewPoint:Vector3D = new Vector3D(projection.projectionCenter.x, projection.projectionCenter.y, -projection.focalLength);
 
	//расстояния до наблюдателя
	var distance:Number = Vector3D.distance(viewPoint, globalPosition);
 
	return sortingPriority * distance;//sortingPriority - костыль для одного мутного случая, а вообще 1.0
 
}
 
/**
 * координаты в руте
 */
public function get globalPosition():Vector3D 
{ 
	return stage ? Utils3D.projectVector(transform.getRelativeMatrix3D(root), new Vector3D() ) : null;
}

Старый 18.01.2010, 17:15
gloomyBrain вне форума Посмотреть профиль Отправить личное сообщение для gloomyBrain Найти все сообщения от gloomyBrain
  № 8  
Ответить с цитированием
gloomyBrain
 
Аватар для gloomyBrain

блогер
Регистрация: Mar 2008
Адрес: РФ, Санкт-Петербург
Сообщений: 2,272
Записей в блоге: 5
Отправить сообщение для gloomyBrain с помощью ICQ Отправить сообщение для gloomyBrain с помощью Skype™
Про сортировку плоскостей разного размера:
Если есть много времени и желания, читайте про BSP-деревья
Если нет желания делать через BSP - алгоритм Ньюэла-Ньюэла-Санча к Вашим услугам. В него можно врубиться и он полностью решает эту задачу.

Про производительность:
Я пришел к тому, что нужно сделать буфер шейпов в одном спрайте (спрайт - это Viewport, каждый шейп - ViewportLayer).
В каждый шейп нужно рисовать определенную глубину (от и до) методом drawTriangles(). В один шейп должен попадать только один объект (а значит - одна текстура => одна заливка), более того - только участок объекта, не пересекающийся с другими по глубине (при этом по x и y пересечения допустимы).

По поводу учебников по математике и геометрии - алгоритмов пруд пруди. Правда их придется все понять =)

ЗЫ
Про вращение кубика вокруг непонятной точки - а какие координаты у объекта Cube вы выставляете изначально?
__________________
...вселенская грусть


Последний раз редактировалось gloomyBrain; 18.01.2010 в 17:21.
Старый 27.02.2010, 13:18
gr_crd вне форума Посмотреть профиль Отправить личное сообщение для gr_crd Посетить домашнюю страницу gr_crd Найти все сообщения от gr_crd
  № 9  
Ответить с цитированием
gr_crd
 
Аватар для gr_crd

Регистрация: Mar 2009
Адрес: Kazakhstan, Almaty
Сообщений: 121
Цитата:
Про вращение кубика вокруг непонятной точки - а какие координаты у объекта Cube вы выставляете изначально?
Да там не из-за координат просто вместо appendRotation сделал prependRotation и все стало как надо.

Старый 14.01.2011, 10:53
Sintesis вне форума Посмотреть профиль Отправить личное сообщение для Sintesis Найти все сообщения от Sintesis
  № 10  
Ответить с цитированием
Sintesis
 
Аватар для Sintesis

Регистрация: Jul 2008
Сообщений: 912
если кому нужно могу выложить несколько классов, которые будут отображать 3D с z сортировкой более продуктивно. Начал писать движок 3D, но пока нет времени на него.

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

Теги
3d , графика , движок , программирование , учебники
Опции темы
Опции просмотра

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

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


 


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


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