Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Еще раз про z-сортировку (http://www.flasher.ru/forum/showthread.php?t=173657)

djyamato 08.01.2012 16:27

Еще раз про z-сортировку
 
Вложений: 1
Здравствуйте, друзья
Поздравляю всех с Новым Годом и Рождеством, удачи и здоровья, успеха в проектах и всех начинаниях

Я хочу попросить взглянуть на мою проблему с z-сортировкой
http://divisionby0.org/web_Portfolio/3DSpace/Main.html
Для того чтобы посмотреть исходники нажмите правой кнопкой по флэшке и выберите View Source

Класс построения фигуры com.div0._3D.primitives.NAnglePrimitive.as

Фигура строится по точкам
Сначала добавляется спрайт НИЗ-а, на нем рисуется линия из точек
Затем добавляется спрайт ВЕРХ-а, на нем рисуется линия из точек
В цикле добавляются спрайты граней

Если покрутить по x или по y видно что неверно сортируются грани куба
Грани куба это класс Plane, наследник Sprite-а
Для сортировки я использую такой механизм:

Нахожу точку в 3д пространстве (Vector3D) позиции смотрящего
Код AS3:

observerPos.x=root.transform.perspectiveProjection.projectionCenter.x;
observerPos.y=root.transform.perspectiveProjection.projectionCenter.y;
observerPos.z=-root.transform.perspectiveProjection.focalLength;

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

Код AS3:

private function sortFaces():void 
                {
                        var i:int;
                        var index:int = 0;
                        var distArray:Array=[];
                        var curMid:Vector3D;
                        var curDist:Number;
                        var vo : SortVO;
                        var observerPos:Vector3D=new Vector3D();
 
                        observerPos.x=root.transform.perspectiveProjection.projectionCenter.x;
                        observerPos.y=root.transform.perspectiveProjection.projectionCenter.y;
                        observerPos.z=-root.transform.perspectiveProjection.focalLength;
                        trace("\nobserver pos "+observerPos);
 
                        var totalFaces:int=_faces.length;
 
                        for(i=0;i<totalFaces;i++)
                        {
                                var currFace:Plane=(_faces[i] as Plane);
                                trace("centerSprite="+currFace.centerSprite.transform.getRelativeMatrix3D(root).position.clone());
                                //curMid=currFace.transform.getRelativeMatrix3D(root).position.clone();
 
                                curMid=currFace.centerSprite.transform.getRelativeMatrix3D(root).position.clone();
 
                                curDist=Math.sqrt(Math.pow(curMid.x-observerPos.x,2)+Math.pow(curMid.y-observerPos.y,2)+Math.pow(curMid.z-observerPos.z,2));
 
                                var sortVO:SortVO=new SortVO();
                                sortVO.object=currFace;
                                sortVO.observerPointDistance=curDist;
                                trace("face "+currFace.id+" dist "+sortVO.observerPointDistance);
                                distArray.push(sortVO);
                        }
                        distArray.sortOn("observerPointDistance", Array.NUMERIC | Array.DESCENDING);
 
                        for each(vo in distArray)
                        {
                                setChildIndex(vo.object, index++);
                        }
                }

Где я ошибся ?

expl 08.01.2012 17:07

Вообще простая сортировка по одной из выбранных точек грани _не_ должна работать в общем случае.
На счёт кубика не уверен.
Попробуйте поискать отличия вашего и этого творения:
http://www.silin.su/#AS3/zod/simple/bin

silin 08.01.2012 19:42

не уверен, но возможно ошибка в определении координат центра грани в руте
Код AS3:

curMid = currFace.centerSprite.transform.getRelativeMatrix3D(root).position.clone();

попробуй вот так
Код AS3:

curMid = Utils3D.projectVector(currFace.centerSprite.transform.getRelativeMatrix3D(root), new Vector3D());


djyamato 08.01.2012 20:41

Спасибо за ответы
К сожалению, Utils3D не меняет ничего, также ошибается алгоритм

silin 08.01.2012 21:02

вот не могу ничего вменяемого сказать, не разобрался с этим до конца, сори
только transform.getRelativeMatrix3D(root).position это совсем не координаты в системе рута, которые здесь нужны (проверяется самыми простыми тестами)
вот такой еще вариант у меня еще 'правильно показывал', в моей схеме он так остался как последний
Код AS3:

var mtrx:Matrix3D = root.transform.getRelativeMatrix3D(obj);
mtrx.invert();
curMid = mtrx.position;

но почему неверно обратное (obj.transform.getRelativeMatrix3D(root) ) опять же не могу сказать..

PS. тема такого 3D и изначально не очень-то цвела, а теперь и совсем никчемушной выглядит, не ?

djyamato 08.01.2012 21:16

Спасибо, щас попробую

Цитата:

Сообщение от silin (Сообщение 1055618)
PS. тема такого 3D и изначально не очень-то цвела, а теперь и совсем никчемушной выглядит, не ?

У меня нет выхода - данные приходят именно под такую отрисовку объектов в 3д мире

expl 09.01.2012 01:07

А вообще, куб - этож выпуклая фигура. Выставляем граням, у которых обход против часовой стрелки на экране получается visible=false и все. Правда для полупрозрачных граней работать не будет.

djyamato 09.01.2012 04:35

Ну, это может быть и не куб вовсе, я могу передать хоть 10 точек
нижняя и верхняя грани отрисуются по этим точкам + в цикле добавятся "боковые" грани
+ мне обязательно нужн учесть полупрозрачность

Друзья, а кто-нибудь работал с BPS деревьями ?

Zebestov 09.01.2012 05:22

Цитата:

Сообщение от djyamato (Сообщение 1055665)
Друзья, а кто-нибудь работал с BPS деревьями?

Только они BSP-деревья.

expl 09.01.2012 14:43

Больше всех с ними, кажется, Alternativa работала
Я делал некоторые эксперименты с BSP, если потребуется, могу накидать сюда исходников (но это эксперименты, на практических применениях не реализованные)

Но если есть движущиеся части, то BSP не поможет (помешают низкая производительность и артефакты разрезки полигонов).

P.S. Скачал куб silin'a, пытался его растянуть, придать ориентацию как на вашем скриншоте - не похоже, чтобы лажало, если лаги и есть - то в 1,5 пикселя отсилы. Но Вы говорите, вам не только куб нужен.

djyamato 09.01.2012 15:00

Вложений: 1
Это типа комнаты
Пол всегда есть
Крыши может и не быть
У меня приходит набор точек, по которым я рисую на грани bottom фигуру (пол)
Затем, если нужно, отрисовываю крышу, причем, на полу и на крыше может лежать текстура (Bitmap)
К примеру "комната" на скрине

expl, был бы признателен, если бы Вы показали исходники BSP-деревьев

expl 09.01.2012 15:45

Вложений: 1
Да, для комнаты bsp должно быть оптимальным вариантом, там же надо нет движущихся частей - один раз разбил на дерево и все.

Вложение 27426
Суть такая:
- дерево перестраивается на каждом кадре. Вам достаточно его построить один раз. Оно и в моем примере не нужно, просто планы были наполеоновскими :)
- написано на haXe. Не производительности ради, а просто язык мне нравится. Если портируете на as3 - производительность сильно упасть не должна (ну в 2 раза из-за отсутствия inline - это потолок, т.е. можно не обращать внимания).

Голос разума говорит, что надо использовать обкатанные движки типа alternativa.
(Единственное, они код закрыли и требуют свой значёк впихивать, но, наверно есть и открытые либы с BSP-деревом. Наверно)

djyamato 09.01.2012 16:09

Спасибо, попробую разобраться
У меня условие - все должно быть нарисовано нативными средствами флэша, так что движки отпадают сразу :(

expl 09.01.2012 17:01

Странное условие, если это не тестовое задание. Ибо чем самопальный код должен быть лучше обкатанного.
По сути:
у меня там треугольники режутся. Для случая комнаты (наверно) будет лучше резать стены не произвольными плоскостями, а плоскостями, перпендикуляными полу. Таким образом будет проще разрезать прямогольную стенку на 2 тоже прямоугольных. Плюс добавить 2 режущие плоскости, чтобы одна совпадала с потолком, другая - с полом и таким образом правильно отобразить потолок и пол.

Для начала можно, конечно порезать прямоугольники на 2 треугольника и посмотреть что получится впринципе (даже пока не портируя на as3). Потом попробовать отрисовать эти треугольники с учётом перспективы (api flashplayer 10 позволяет). А потом уже попробовать использовать прямоугьльники и жонглировать порядком отображения этих спрайтов, а не просто рисовать по порядку фигуры.

djyamato 09.01.2012 18:25

Вложений: 1
Цитата:

Сообщение от expl (Сообщение 1055710)
Странное условие, если это не тестовое задание. Ибо чем самопальный код должен быть лучше обкатанного.

Есть отрендеренная картинка этажа здания
На нее нужно наложить этот 3д мир с комнатами, стенами
Координаты стен и комнат (по сути, точки) приходят в данных
Затем нужно эту всю огромную конструкцию таскать мышкой (вместе с бэкграундом-картинкой этажа)
В Альтернативе я застопорился на ограниченности размера 3д сцены (или View, не помню уже) по ширине и высоте

-------------------------------------------------------------

Вроде получилось без BSP дерева
Но иногда при вращении сортировка все равно ошибается
Я вытащил все грани из контейнера и напрямую кладу их в спрайт, который кручу в 3Д

Код AS3:

public static function sort(container3D:Sprite, figures:Vector.<*>):void
                {
                        var observerPos:Vector3D=new Vector3D();
                        var vo : SortVO;
                        var index:int = 0;
 
                        observerPos.x=container3D.transform.perspectiveProjection.projectionCenter.x;
                        observerPos.y=container3D.transform.perspectiveProjection.projectionCenter.y;
                        observerPos.z=-container3D.transform.perspectiveProjection.focalLength;
 
                        trace("\nobserverPos "+observerPos);
 
                        var faces:Vector.<Plane>=new Vector.<Plane>();
                        var distArray:Array=new Array();
 
                        for(var i:int=0;i<figures.length;i++)
                        {
                                if(figures[i] is NAnglePrimitive)
                                {
                                        var currFigure:NAnglePrimitive=figures[i] as NAnglePrimitive;
                                        for(var j:int=0;j<currFigure.faces.length;j++)
                                        {
                                                faces.push(currFigure.faces[j]);
                                        }
                                }
                                else if(figures[i] is Plane)
                                {
                                        faces.push(figures[i] as Plane);
                                }
                        }
 
                        var totalFaces:int=faces.length;
                        for(i=0;i<totalFaces;i++)
                        {
                                var currFace:Plane=faces[i];
 
                                var mtrx:Matrix3D = container3D.transform.getRelativeMatrix3D(currFace);
                                mtrx.invert();
                                var curMid:Vector3D = mtrx.position;
 
                                // середина 3д спрайта относительно спрайта, который крутится в 3Д
                                curMid = Utils3D.projectVector(currFace.centerSprite.transform.getRelativeMatrix3D(container3D.parent), new Vector3D());
 
                                // дистанция от середины 3д спрайта до точки обзора в 3д (трансформируется контейнер а не stage или root)
                                var curDist:Number=Math.sqrt(Math.pow(curMid.x-observerPos.x,2)+Math.pow(curMid.y-observerPos.y,2)+Math.pow(curMid.z-observerPos.z,2));
 
                                trace("face "+currFace.id+" MID "+curMid+" distance "+curDist);
                                var sortVO:SortVO=new SortVO();
                                sortVO.object=currFace;
                                sortVO.observerPointDistance=curDist;
                                distArray.push(sortVO);
                        }
                        distArray.sortOn("observerPointDistance", Array.NUMERIC | Array.DESCENDING);
 
                        for each(vo in distArray)
                        {
                                container3D.setChildIndex(vo.object, index++);
                        }
 
                        trace("самая близкая грань "+distArray[0].object.id);
                }


djyamato 16.01.2012 03:54

Вложений: 1
Нет
Все таки сильно лагает механизм и чтобы не создавать еще одну тему я "апну" эту, извините

вот я разбил отрезки друг другом и "продолжалками" (на скрине)
как дальше BSP дерево сформировать
Или я вообще не правильно понял идею ?

-De- 16.01.2012 04:01

Вопрос про BSP в 2D?
Выбираем отрезок. Этот отрезок делит остальные отрезки на две группы - одна рендерится до него, другая после него. В этих группах тоже выбираем по отрезку и делим и т.д. http://www.gamedev.ru/code/articles/BSP
Ещё раз скажу про движки, негоже таким страдать %)

djyamato 16.01.2012 04:08

Цитата:

Сообщение от -De- (Сообщение 1057179)
Вопрос про BSP в 2D?

Ну, я расчитывал хоть как-то упростить себе задачу поэтому разбивал в 2D

expl 16.01.2012 12:11

В вашем случае с комнатой в 2d разбить как раз будет эффективнее.


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

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