![]() |
|
|
|||||
Регистрация: Mar 2009
Адрес: Kazakhstan, Almaty
Сообщений: 121
|
![]() Изменение оси вращения Допустим есть объект, состоящий из 6-ти спрайтов, каждый из которых имеет св-ва x, y, z, rotationX, rotationY, rotationZ, таким образом из них составлен куб, как показано на рис. Все эти шесть сторон куба помещены в контейнер «cube» Этот куб вращаю вокруг оси Y X или Z так: Но при попытке повернуть куб например сначала по оси Z на 30 градусов, а потом каждый кадр вращать по оси Y, допустим на 1,0 получается совсем не то, что ожидалось, как я понял при вращении объекта его оси не вращаются и остаются на месте, и это правильно. Но тогда возникает вопрос, а как вращать объект по другой оси, назовем ее «A», она отличается от осей Z X и У. Пробовал вращать по одной оси быстрее, по другой медленнее: Получается тоже нечто очень странное. Вопрос 1: Как вращать объект по оси «A» ? см. рисунок. ![]() Вращение через Matrix3D Возьмем к примеру тот же самый cube из предыдущего вопроса. Каждый кадр поворачиваю его с помощью Matrix3D: var matrixCube:Matrix3D = cube.transform.matrix3D; matrixCube.appendRotation(0.7, Vector3D.Y_AXIS); cube.transform.matrix3D = matrixCube; Вопрос 2: Что это за точка? Как изменить эту точку? Или я что-то делаю неправильно? Z-сортировка между плоскостью и другой плоскостью большего размера Происходит сортировка всех плоскостей по величине Z. Вот функция, вызывается каждый кадр. 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, создается следующей функцией: 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++; } 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); } все работает нормально, без подвисаний. for (t = 0; t < 10;t++){ createBox(-500+Math.random()*1000,-500+Math.random()*1000,-500+Math.random()*1000); } Вопрос 4: Нужно ли создавать каждую плоскость как отдельный Shape? Как вообще можно повысить скорость отрисовки всего этого? Ясно, что-то я делаю неправильно, как будет сделать разумнее и оптимизировать хоть как-то все это? Каков правильный подход Все яснее становится, что используя готовые классы Shape или там Sprite и создавая трехмерность таким образом, как описано выше — неправильный путь. Вопрос 5: Так каков же тогда правильный путь? Писать все 3D вручную? Как вообще устроены простейшие 3D-движки на флеше? И если уж все идет на то, что нужно писать все самому, какую литературу посоветуете? Я уже нашел статьи, но хочется именно книгу, в которой бы описывалось программирование 3D-графики с азов. Ну, конечно, кроме учебников по математике и геометрии ![]() |
|
|||||
Modus ponens
|
>> Вопрос 2: Что это за точка? Как изменить эту точку? Или я что-то делаю неправильно?
Пожалуй единственное, на что смогу ответить - смотрите в сторону projectionCenter. А в остальном - на сколько я понимаю, использовать практически любой из существующих 3Д фреймворков в смысле производительности гораздо лучше родного 3Д... Если задача сделать что-то именно используя флешевые возможности - посмотрите сюда: http://www.flasher.ru/forum/blog.php?b=123
__________________
Hell is the possibility of sanity |
|
|||||
Регистрация: Mar 2009
Адрес: Kazakhstan, Almaty
Сообщений: 121
|
насчет вопроса 2. projectionCenter не помогло, однако при вращении
можно задавать третий параметр тоже Vector3D, который определяет то ли ось, то ли точку вращения.. попробовал применить - кубик помахал мне ручкой и по спирали улетел куда-то очень далеко. вопрос однако остался в силе... а тот фреймворк по ссылке достаточно резвенько работает ![]() |
|
|||||
1,2: все верно, вращать надо за счет преобразований transform.matrix3D
но чтобы получить адкватный результат (вращение относительно точки регистрации, например) надо мадрицу привести в "исходное" сотояние по координатам, там повернуть и снова вернуть в прежние координаты 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; остается шаманство со складыванием частей разных объектов в один контейнер с общей сортировкой, естественно чем мельче фрагмены, тем адекватнее они отсортируются, но увлекаться этим тоже не выходит из-за неизбежных тормозов еще нюанс: сортировать по z-координате в общем случаем неправильно, надо сортировать по расстоянию до наблюдателя (transform.perspectiveProjection) 4,5: насчет производительности и правльных направлений мне нечего сказать, грустно все.. рисовательные движки (инфинити, альтернатива, PV3D..), которые выводят этот 3D мир за счет отрисовки полигонов, предварительно спроектированных в экран, выигрывают, конечно же в производительности, но выигрыш этот не таков, чтобы говорить о каком-то съедобном 3D, имхо а для ерунды можно и нативными костылями обойтись |
|
|||||
Вот то-же самоделка по бездвиговому рисованию 3Д (нативными drawTriangles)
http://www.murmadillo.tut.su/3d/draw...es-sort-z.html
__________________
Гоночка |
|
|||||
Регистрация: Mar 2009
Адрес: Kazakhstan, Almaty
Сообщений: 121
|
Цитата:
3 - т.е. я понял у perspectiveProjection есть св-во или метод, который определяет расстояние до наблюдателя? Добавлено через 4 минуты Цитата:
|
|
|||||
я понял у perspectiveProjection есть св-во или метод, который определяет расстояние до наблюдателя?
не напрямую, но узнать его координаты в 3D-мире можно у меня сейчас работает такой вариант: /** * расстояние до наблюдателя в руте */ 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; } |
|
|||||
Про сортировку плоскостей разного размера:
Если есть много времени и желания, читайте про BSP-деревья Если нет желания делать через BSP - алгоритм Ньюэла-Ньюэла-Санча к Вашим услугам. В него можно врубиться и он полностью решает эту задачу. Про производительность: Я пришел к тому, что нужно сделать буфер шейпов в одном спрайте (спрайт - это Viewport, каждый шейп - ViewportLayer). В каждый шейп нужно рисовать определенную глубину (от и до) методом drawTriangles(). В один шейп должен попадать только один объект (а значит - одна текстура => одна заливка), более того - только участок объекта, не пересекающийся с другими по глубине (при этом по x и y пересечения допустимы). По поводу учебников по математике и геометрии - алгоритмов пруд пруди. Правда их придется все понять =) ЗЫ Про вращение кубика вокруг непонятной точки - а какие координаты у объекта Cube вы выставляете изначально?
__________________
...вселенская грусть Последний раз редактировалось gloomyBrain; 18.01.2010 в 17:21. |
|
|||||
Регистрация: Mar 2009
Адрес: Kazakhstan, Almaty
Сообщений: 121
|
Цитата:
|
|
|||||
Регистрация: Jul 2008
Сообщений: 912
|
если кому нужно могу выложить несколько классов, которые будут отображать 3D с z сортировкой более продуктивно. Начал писать движок 3D, но пока нет времени на него.
|
![]() |
![]() |
Часовой пояс GMT +4, время: 09:55. |
|
« Предыдущая тема | Следующая тема » |
Теги |
3d , графика , движок , программирование , учебники |
Опции темы | |
Опции просмотра | |
|
|