forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   3D-программирование (http://forum.boolean.name/forumdisplay.php?f=12)
-   -   Скрытие объектов за стенами (http://forum.boolean.name/showthread.php?t=17312)

Кирпи4 26.09.2012 23:46

Скрытие объектов за стенами
 
Народ, выручайте....
Пробовал браться за это, но выходит либо сущая говнота, либо просто знаний матана не хватает...
Может есть какие - нибудь либы для этого? Рад буду даже хоть самому алгоритму...

Mr_F_ 27.09.2012 00:00

Ответ: Скрытие объектов за стенами
 
гугли по словам occlusion culling, способов много.

Nex 27.09.2012 00:02

Ответ: Скрытие объектов за стенами
 
Эм. "пик" встретит стену. И думаю тема не полностью раскрыта.

Кирпи4 27.09.2012 00:10

Ответ: Скрытие объектов за стенами
 
Окей, раскрываю
У меня есть меш за стеной, и, допустим, баундинг бокс в виде куба.
Нужно сделать так, чтобы меш хайдился, если баундинг бокс полностью загорожен. EntityVisible - вообще убило меня, так как он проверяет на видимость ЦЕНТР ентити - бред...

Platon 27.09.2012 07:32

Ответ: Скрытие объектов за стенами
 
Цитата:

Сообщение от Кирпи4 (Сообщение 239240)
Окей, раскрываю
У меня есть меш за стеной, и, допустим, баундинг бокс в виде куба.
Нужно сделать так, чтобы меш хайдился, если баундинг бокс полностью загорожен. EntityVisible - вообще убило меня, так как он проверяет на видимость ЦЕНТР ентити - бред...

юзать порталы и\или антипорталы (оклудеры).

порталы, грубо говоря, это полигоны описывающие проемы в стенах.

их можно построить в дерево.
т.е. определить какие порталы видны из другого и запилить иерархию.
это можно сделать либо вручную в редакторе, либо автоматически, примерно так ( как вариант ):
берем каждый портал
определяем какие порталы находятся с одной стороны, а какие с другой, и так-же делим геометрию сцены
для каждой стороны
"рисуем" геометрию в буфер глубины
"рисуем" другие порталы в буфер без записи, но с тестом и определяем виден он или нет
добавляем видимые порталы, соответственно стороне, в две ветки текущего портала
и т.д.
для "рисовать", я бы набросал софтварный растеризатор простейший, от него впринципе требуется только 32 битное значение глубины интерполировать, так что там все просто. ( это можно например оформить в тулзу, которая будет хавать сцену, а высирать построеную иерархию как файлик )

от каждого портала можно построить фрустум, т.е.
берем по паре вершин от полигона портала (по его ребрам)
строим пару векторов от камеры до этих вершин
векторно перемножаем, нормализовываем и получаем нормаль плоскости
скалярное прозведение этой нормали с вектором "камера-центр координат" даст четвертую компоненту плоскости.
в результате получишь несколько плоскостей которые и будут фрустумом

соответственно как происходит кулинг сцены:
пробегаем по порталам по иерархии видимости
режем полигон портала фрустумом ( ибо он можнт быть виден только частично, и чтобы правильный фрустум через него построить, нужно определить видимую часть этого портала )
строим новый фрустум из урезанного полигона

насчет "режем полигон"
можно заюзать например алгоритм сазерленда-ходжмана
суть его примерно такова:
проходим по полигону, через его ребра
с помощью двух скалярных произведений пары вершин ребра и плоскости, которой этот полигон режется, определяем три ситуации:
1 оба произведения отрицательны - обе вершины находятся с отсеченной стороны плоскости
2 одно из произведений положительно - одна вершина с одной стороны плоскости, другая - с другой, значит ребро пересекает плоскость - один вертекс ( который с положительным произведением ) помещаем в результирующий полигон, а второй вертекс - точка пересечения ребра с плоскостью, ее находим и тоже в результируюй полигон
3 оба произведения положительны - обе вершины с отсекаемой стороны плоскости, добавляем обе в результирующий полигон
в результате получится полигон, урезанный плоскостью
для обрезки по фрустуму - просто режем полигон последовательно всеми плоскостями фрустума.

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

по хорошему надо строить например какое-нить октарное дерево, делить геометрию сцены между узлами этого дерева, и порталы соответственно тоже, чтобы не колбасить лишнего.

антипорталами может выступать любая геометрия. Принцип тот же самый - строим через окклудер фрустум, и все что в него входит уже наоборот - скрывается. Если геометрия окклудера сложная ( т.е. не просто полигон, а например куб ), то сначала надо определить силуэтные вершины ( минимальные\максимальные по проекции на плоскость камеры ), и по ним уже построить фрустум так-же, как описал выше для портала.

ЗЫ
извиняюсь за этот поток сознания :) писал в спешке, попзжа подробнее опишу, если надо конечно.

Кирпи4 27.09.2012 18:40

Ответ: Скрытие объектов за стенами
 
Надо, надо, конечно надо =)

Черный крыс 28.09.2012 02:46

Ответ: Скрытие объектов за стенами
 
Мне кажется, аффтар больше половины из сказаного не понял.

Mr_F_ 28.09.2012 11:06

Ответ: Скрытие объектов за стенами
 
Цитата:

"рисуем" геометрию в буфер глубины
"рисуем" другие порталы в буфер без записи, но с тестом и определяем виден он или нет
добавляем видимые порталы, соответственно стороне, в две ветки текущего портала
рисовать придётся видимо не 1 раз? т.к. даже если с огромным фовом отрендерить кадр в направлении портала, не факт что у нас в нём растеризуются другие порталы, которые очень по бокам.
наверное надо будет 5 раз рендерить, аля полукуб, чтобы со всех сторон потенциально видимые увидеть.
алсо, вместо софтварного растеризатора, эффективнее было бы юзать occlusion queries.
Цитата:

насчет "режем полигон"
хм, я тупо делал фрустум из позиции камеры и точек портала (их было всегда 4), в принципе достаточно получить описывающий прямоугольник портала в экране и поплющить направление/фов фрустума, чтобы через него шёл.

Platon 28.09.2012 12:37

Ответ: Скрытие объектов за стенами
 
Вложений: 2
Цитата:

Сообщение от Кирпи4 (Сообщение 239294)
Надо, надо, конечно надо =)

Я ожидал что будут какие-то вопросы направляющие, а то я вот даже незнаю что подробнее объяснить :)

Цитата:

Сообщение от Mr_F_ (Сообщение 239330)
рисовать придётся видимо не 1 раз? т.к. даже если с огромным фовом отрендерить кадр в направлении портала, не факт что у нас в нём растеризуются другие порталы, которые очень по бокам.
наверное надо будет 5 раз рендерить, аля полукуб, чтобы со всех сторон потенциально видимые увидеть.
алсо, вместо софтварного растеризатора, эффективнее было бы юзать occlusion queries.

Рисовать 1 раз, ибо рисуем не через фрустум, а просто все что с одной стороны портала ( определяем чо с какой стороны находится относительно плоскости портала, как для BSP разделяющая плоскость короче ).
Насчет окклюжн квери - хороший вариант, но я предпочитаю велосипеды :))

Цитата:

Сообщение от Mr_F_ (Сообщение 239330)
хм, я тупо делал фрустум из позиции камеры и точек портала (их было всегда 4)

Если портал виден чуть-чуть, то получишь оверхед, ибо фрустум будет через весь портал, и соответственно будет рисоваться то что не видно из камеры. Для маленьких порталов может и лучше будет, не надо будет тратить время на обрезку, и через такой портальчик :) видно мало. Но для больших порталов уже сомнительно.

Цитата:

Сообщение от Mr_F_ (Сообщение 239330)
в принципе достаточно получить описывающий прямоугольник портала в экране и поплющить направление/фов фрустума, чтобы через него шёл.

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

ЗЫ
Пока парочку картинок прикреплю для топикстартера, надеюсь они немного прояснят хрень в 5ой мессаге :)

На первой изображены некоторые варианты кулинга через порталы:
рис. 1 - порталов нет, обычный вариант кулинга через камеру
рис. 2 - один портал, полностью виден из камеры, темно-синим виден новый фрустум построеный через портал
рис. 3 - тот же вариант, только камеру немного повернули, портал теперь виден частично, ярко-красным - портал обрезаный фрустумом камеры
рис. 4 - вариант посложнее, тут уже проглядывается иерархия порталов

на второй схематично построение фрустума через полигон портала
p0 - точка камеры
p1 .. p6 - точки полигона портала
E1 .. E6 - ребра полигона, проходясь по которым строим плоскости фрустума
V1 .. V6 - вектора, построенные через точки портала от точки камеры
для каждой плоскости фрустума надо найти нормаль ( направление плоскости ) и смещение относительно центра координат.
внизу справа изображено что из себя представляет нормаль и смещение на примере треугольника ( которые и получаются по ходу расчета фрустума )
внизу слева - как считается

Ну а вообще всю эту тему можно долго мусолить, поэтому желательно чтобы были какие-то вопросы конкретные :)

HolyDel 28.09.2012 14:03

Ответ: Скрытие объектов за стенами
 
чем ребристее фрустум - тем дольше будет проходить проверка на принадлежность ему. прилегких дипах может быть дешевле брать четырехугольные фрустумы.

Кирпи4 28.09.2012 18:15

Ответ: Скрытие объектов за стенами
 
Святыыыыыыыыыыееее щииииии....
Ну что я могу сказать - технология охренительная, но не по блицевским меркам это. Вобщем, буду говнокодить или чего-нибудь думать, если выйдет что-либо стоящее, то запощу.
Есть одна идейка, но она лютое говно , так как каждый кадр предполагается дохрена лайнпиков. Вроде бы есть выход - это физ враппер, там вроде лучи быстрее выполняются, но это уже слишком.

А, ещё вот: можно ли как-нибудь произвести пик из DLL на пуряке?

Черный крыс 28.09.2012 18:57

Ответ: Скрытие объектов за стенами
 
Цитата:

Сообщение от Кирпи4 (Сообщение 239339)
А, ещё вот: можно ли как-нибудь произвести пик из DLL на пуряке?

Вытащить адрес нужной функции с последующим вызовом.

Mr_F_ 28.09.2012 21:28

Ответ: Скрытие объектов за стенами
 
Цитата:

Ну что я могу сказать - технология охренительная, но не по блицевским меркам это.
да ну, я как раз первый раз делал их именно на блице)
прирост фпс - был (кроме блица участвовал ксорс, толстые шейдеры и слабая видюха).

Черный крыс 30.09.2012 08:57

Ответ: Скрытие объектов за стенами
 
На блице разумнее всего сделать секторную систему, библиотека есть где то, ее написал Мад-Медик.

А насчет остального - зачем обьяснять такие вещи если всеравно на блице этого не реализовать ? Остальное будет либо геморой либо в виду закрытости движка будет вообще нереализуемо.

Mr_F_ 30.09.2012 17:34

Ответ: Скрытие объектов за стенами
 
Цитата:

на блице этого не реализовать
если руки кривые, то да.

Черный крыс 30.09.2012 18:23

Ответ: Скрытие объектов за стенами
 
Цитата:

Сообщение от Mr_F_ (Сообщение 239437)
если руки кривые, то да.

А для кого то в кайф заниматся извратом, прикручивая самокату колеса от самосвала.

Mr_F_ 30.09.2012 19:06

Ответ: Скрытие объектов за стенами
 
я тебя разочарую, но уравнение плоскости, построение фрустума из плоскостей, обрезание полигонов плоскостью - это математика, и её где угодно тебе придётся писать одинаково.
единсвтенный минус блица тут - неудобно работать покомпонентно с векторами во всех вычислениях.

Черный крыс 30.09.2012 19:46

Ответ: Скрытие объектов за стенами
 
Цитата:

Сообщение от Mr_F_ (Сообщение 239445)
я тебя разочарую, но уравнение плоскости, построение фрустума из плоскостей, обрезание полигонов плоскостью - это математика, и её где угодно тебе придётся писать одинаково.

Да? Я тебя разочарую, но одними плясками с фрустумом камеры ты мало чего добьешься. И почему же до сих пор на блице я не видел ничего вразумительного кроме Секторной системы и Q3BSP ?! Ну если у тебя есть реализация на блице хотя бы Октри в самом примитивном виде - так выкладывай! Зачем же здесь впустую воздух сотрясать?

Короче

Не морочь людям мозги.

Аффтару в руки либо БСП либо Сектора, лучше последнее.

Цитата:

Сообщение от Mr_F_ (Сообщение 239445)
единсвтенный минус блица

У него минусов гораздо больше одной штуки.

HolyDel 30.09.2012 20:45

Ответ: Скрытие объектов за стенами
 
оверхед блицовой математики

Platon 30.09.2012 22:27

Ответ: Скрытие объектов за стенами
 
На чистом блице все это дело можно написать и оно будет давать буст, гарантирую :) я б набросал специально для неверующих, но мне чето пока лень возиться :) в выходные попробую, пофигу даже если неактуально уже будет.

Diablo1909
BSP-то тут причем? Оно для рендера только ради сортировки, для кулинга там PVS.

Черный крыс 01.10.2012 00:05

Ответ: Скрытие объектов за стенами
 
Цитата:

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

Цитата:

BSP-то тут причем?
Автор топика вроде как спросил "Скрытие объектов за стенами", оно великолепно с этим справляется, правда в блице как всегда все урезано, и даже нельзя цеплять свои полики в дерево.

burovalex 02.11.2012 00:42

Ответ: Скрытие объектов за стенами
 
Однажды набрёл на команду в блитс1.98, честно - лень было проверять, но помоему есть стандартное решение.

MeshCullBox mesh,x#,y#,z#,width#,height#,depth#
Parameters mesh - mesh handle
x# - x position of far bottom left corner of bounding box
y# - y position of far bottom left corner of bounding box
z# - z position of far bottom left corner of bounding box
width# - width of bounding box (x distance)
height# - height of bounding box (y distance)
depth# - depth of bounding box (z distance)

Description This command allows the adjustment of the culling box used by the Blitz3D renderer when deciding if the mesh is outside the view of a camera.

The culling box of a mesh is automatically calculated, however in some instances an animated mesh may stretch beyond this region resulting in it visually popping out of view incorrectly. The MeshCullBox command allows a mesh culling box to be manually adjusted to correct this problem.

Черный крыс 23.11.2012 20:22

Ответ: Скрытие объектов за стенами
 
Это отсечение меша по боксу. Если бокс не входит во фрустум камеры то меш не рисуется.

Кирпи4 02.01.2013 15:51

Ответ: Скрытие объектов за стенами
 
Извинтюляюсь за можно сказать некропост, но у меня хорошие новости.
Вот хороший код отсечения, но минус один - окклюдеры должны быть выпуклыми. А так всё замечательно работает, отсекает как надо. :)

Код:


Graphics3D 800,600
SetBuffer BackBuffer()

;WireFrame True

; Types and variables for Edgelist
Type Edge
Field A,B
Field Surf
Field Tri1        ; The triangle the edge belongs To
Field Tri2        ; The adjacent triangle, if one exist
Field X1,Y1,X2,Y2
Field Visible
Field PlaneDist#        ; The edgelist also contains the planes
Field PlaneNX#
Field PlaneNY#
Field PlaneNZ#
Field Parent
End Type

Type vector
Field x#
Field y#
Field z#
End Type
Global CProd.vector=New vector
Global DProd#

Type Occluder
Field Mesh
Field ID
End Type

Type Entity
Field Entity
Field Occluded
Field Radius#
End Type

box = CreateMesh()
surf=CreateSurface(box)
v0=AddVertex(surf,-1,1,1)
v1=AddVertex(surf,1,1,1)
v2=AddVertex(surf,1,1,-1)
v3=AddVertex(surf,-1,1,-1)
v4=AddVertex(surf,-1,-1,1)
v5=AddVertex(surf,1,-1,1)
v6=AddVertex(surf,1,-1,-1)
v7=AddVertex(surf,-1,-1,-1)
AddTriangle(surf,v0,v1,v3)
AddTriangle(surf,v1,v2,v3)
AddTriangle(surf,v4,v7,v5)
AddTriangle(surf,v7,v6,v5)
AddTriangle(surf,v3,v2,v7)
AddTriangle(surf,v2,v6,v7)
AddTriangle(surf,v4,v1,v0)
AddTriangle(surf,v4,v5,v1)
AddTriangle(surf,v2,v1,v6)
AddTriangle(surf,v1,v5,v6)
AddTriangle(surf,v0,v3,v4)
AddTriangle(surf,v3,v7,v4)
;
HideEntity box

; Cams & Meshes
camera = CreateCamera()
PositionEntity camera,0,0,-5
CameraClsColor camera,150,150,220

Global EdgeList.Edge
; Create occluder
Global OccludeList.Occluder
OccludeList.Occluder = New Occluder
OccludeList\ID = 1
OccludeList\Mesh = CopyEntity(box)
PositionEntity OccludeList\mesh,-6,0,0
EntityAlpha OccludeList\mesh,0.8

OccludeList.Occluder = New Occluder
OccludeList\ID = 2
OccludeList\Mesh = CopyEntity(box)
PositionEntity OccludeList\mesh,-3,0,0
EntityAlpha OccludeList\mesh,0.8

OccludeList.Occluder = New Occluder
OccludeList\ID = 3
OccludeList\Mesh = CopyEntity(box)
PositionEntity OccludeList\mesh,0,0,0
EntityAlpha OccludeList\mesh,0.8

OccludeList.Occluder = New Occluder
OccludeList\ID = 4
OccludeList\Mesh = CopyEntity(box)
PositionEntity OccludeList\mesh,3,0,0
EntityAlpha OccludeList\mesh,0.8

OccludeList.Occluder = New Occluder
OccludeList\ID = 5
OccludeList\Mesh = CopyEntity(box)
PositionEntity OccludeList\mesh,6,0,0
EntityAlpha OccludeList\mesh,0.8


; Create ordinary objects
Global EntityList.Entity

For v=0 To 50
EntityList.Entity = New Entity
EntityList\Entity = CreateSphere(16)
EntityList\Radius# = 0.5
PositionEntity EntityList\Entity,Rnd(-5,5),Rnd(-5,5),Rnd(100,5)
EntityColor EntityList\Entity,Rnd(50,255),Rnd(50,255),Rnd(50,255)
Next

CenterPivot=CreatePivot()
light = CreateLight()
PositionEntity light,15,10,-15
PointEntity light,CenterPivot

; Build the Edgelists
For OccludeList.Occluder = Each Occluder
BuildEdgeList OccludeList\ID,OccludeList\mesh
Next

; The mainloop
LastTime=MilliSecs()
Color 0,0,0
UseOcclusion=0

While Not KeyDown(1)
FrameCount=FrameCount+1

If KeyHit(57) Then
UseOcclusion=1-UseOcclusion

If UseOcclusion=0 Then
For EntityList.Entity = Each Entity
ShowEntity EntityList\Entity
Next
EndIf

EndIf

;TurnEntity mesh,0,0.5,0

If KeyDown(200) Then
MoveEntity Camera,0,0.01,0
EndIf       
If KeyDown(208) Then
MoveEntity Camera,0,-0.01,0
EndIf       
If KeyDown(205) Then
MoveEntity Camera,0.01,0,0
EndIf       
If KeyDown(203) Then
MoveEntity Camera,-0.01,0,0
EndIf       
If KeyDown(201) Then
MoveEntity Camera,0,0,0.01
EndIf       
If KeyDown(209) Then
MoveEntity Camera,0,0,-0.01
EndIf       

RenderWorld

;Just for showing that the occluder doesn't need
;to be a static object
For OccludeList.Occluder = Each Occluder
TurnEntity OccludeList\Mesh,0,0.1,0
Next


If UseOcclusion=1 Then
For EntityList.Entity = Each Entity
EntityList\Occluded=False
Next
For OccludeList.Occluder = Each Occluder
; Skip Updating the occluder if it is out of the view
If EntityInView(OccludeList\Mesh,Camera) Then
UpdateOccluderPlanes OccludeList\ID,OccludeList\Mesh,Camera
EndIf
Next

For EntityList.Entity = Each Entity
; Skip to check if entity already is out of the viewfrustum
If EntityInView(EntityList\Entity,Camera) Then
OccludeEntity(EntityList,Camera)
EndIf
Next

EndIf

TimeTaken=MilliSecs()-LastTime
If TimeTaken>=1000 Then
LastTime=MilliSecs()
FPS=FrameCount
FrameCount=0
EndIf

Text 0,10,"FPS:" + Str(FPS)
If UseOcclusion=0 Then
Text 0,20,"Occlusion = " + "Off"
Else
Text 0,20,"Occlusion = " + "On"
EndIf
Text 0,30,"Rendered Tris:" + TrisRendered()
Text 0,40,"Press Space To Toggle Occlusion"


Flip False
Wend

End

; Functions

Function UpdateOccluderPlanes(OccID,occMesh,Cam)
; Loop through all Edges...
FirstRun=True
For EdgeList.Edge = Each Edge

If EdgeList\Parent=OccID Then

TriVis1 = TriVisible(Cam,occMesh,EdgeList\surf,EdgeList\Tri1)
TriVis2 = TriVisible(Cam,occMesh,EdgeList\surf,EdgeList\Tri2)

If TriVis1 Xor TriVis2 = True Then ; draw edge only if one triangle is visible and the other is hidden

x#=VertexX#(EdgeList\Surf,EdgeList\A)
y#=VertexY#(EdgeList\Surf,EdgeList\A)
z#=VertexZ#(EdgeList\Surf,EdgeList\A)
TFormPoint x#,y#,z#,occMesh,0
CameraProject Cam,TFormedX#(),TFormedY#(),TFormedZ#()       
EdgeList\X1=ProjectedX()
EdgeList\Y1=ProjectedY()

If FirstRun=True Then
MaxX=EdgeList\X1:MinX=EdgeList\X1
MaxY=EdgeList\Y1:MinY=EdgeList\Y1
FirstRun=False
Else
If EdgeList\X1>MaxX Then MaxX=EdgeList\X1
If EdgeList\X1<MinX Then MinX=EdgeList\X1
If EdgeList\Y1>MaxY Then MaxY=EdgeList\Y1
If EdgeList\Y1<MinY Then MinY=EdgeList\Y1
EndIf

x#=VertexX#(EdgeList\Surf,EdgeList\B)
y#=VertexY#(EdgeList\Surf,EdgeList\B)
z#=VertexZ#(EdgeList\Surf,EdgeList\B)
TFormPoint x#,y#,z#,occMesh,0
CameraProject Cam,TFormedX#(),TFormedY#(),TFormedZ#()       
EdgeList\X2=ProjectedX()
EdgeList\Y2=ProjectedY()

If EdgeList\X2>MaxX Then MaxX=EdgeList\X2
If EdgeList\X2<MinX Then MinX=EdgeList\X2
If EdgeList\Y2>MaxY Then MaxY=EdgeList\Y2
If EdgeList\Y2<MinY Then MinY=EdgeList\Y2

EdgeList\Visible=True
;Line EdgeList\X1,EdgeList\Y1,EdgeList\X2,EdgeList\Y2
Else
EdgeList\Visible=False
EndIf
EndIf
Next

; Calculate Midpoint
MidPointX=(MinX+MaxX)/2
MidPointY=(MinY+MaxY)/2

; Make sure every edge is in clockwise order, if not, swap the edges vertices
For EdgeList.Edge = Each Edge
If EdgeList\Parent=OccID Then
If EdgeList\Visible=True Then

If TriArea(EdgeList\X1,EdgeList\Y1,EdgeList\X2,EdgeList\Y2,MidPointX,MidPointY)<0 Then
TempHoldVertex=EdgeList\A
TempHoldX=EdgeList\X1
TempHoldY=EdgeList\Y1

EdgeList\A=EdgeList\B
EdgeList\X1=EdgeList\X2
EdgeList\Y1=EdgeList\Y2
EdgeList\B=TempHoldVertex
EdgeList\X2=TempHoldX
EdgeList\Y2=TempHoldY
EndIf

; Now calculate plane...
TFormPoint VertexX#(EdgeList\Surf,EdgeList\A),VertexY#(EdgeList\Surf,EdgeList\A),VertexZ#(EdgeList\Surf,EdgeList\A),occMesh,0
Vec1x#=EntityX#(Cam)-TFormedX#()
Vec1y#=EntityY#(Cam)-TFormedY#()
Vec1z#=EntityZ#(Cam)-TFormedZ#()
TFormPoint VertexX#(EdgeList\Surf,EdgeList\B),VertexY#(EdgeList\Surf,EdgeList\B),VertexZ#(EdgeList\Surf,EdgeList\B),occMesh,0
Vec2x#=EntityX#(Cam)-TFormedX#()
Vec2y#=EntityY#(Cam)-TFormedY#()
Vec2z#=EntityZ#(Cam)-TFormedZ#()
;        CrossProduct Vec1x#,Vec1y#,Vec1z#,Vec2x#,Vec2y#,Vec2z#
Cpx#=(Vec1y#*Vec2z#)-(Vec1z#*Vec2y#)
Cpy#=(Vec1z#*Vec2x#)-(Vec1x#*Vec2z#)
Cpz#=(Vec1x#*Vec2y#)-(Vec1y#*Vec2x#)
;Normalize
TempDist#= Sqr(Cpx#*Cpx# + Cpy#*Cpy# + Cpz#*Cpz#)
Cpx#=Cpx#/TempDist#
Cpy#=Cpy#/TempDist#
Cpz#=Cpz#/TempDist#
EdgeList\PlaneNX#=Cpx#
EdgeList\PlaneNY#=Cpy#
EdgeList\PlaneNZ#=Cpz#

;EdgeList1\PlaneDist#=DotProduct(TFormedX#(),TFormedY#(),TFormedZ#(),CProd\x#,CProd\y#,CProd\z#)
EdgeList\PlaneDist#=((TFormedX#()*Cpx#)+(TFormedY#()*Cpy#)+(TFormedZ#()*Cpz#))

EndIf
EndIf
Next

End Function

Function OccludeEntity(CurrentEntity.Entity,Camera)
; Now check if object is occluded or not...

If CurrentEntity\Occluded=False Then ; If entity already is occluded, then skip this...

For OccludeList.Occluder = Each Occluder
; Skip the occluder if it's out of the viewfrustum
If EntityInView(OccludeList\Mesh,Camera)=False Then Goto SkipThisOccluder
EntityHidden=True
For EdgeList.Edge = Each Edge
If OccludeList\ID = EdgeList\Parent Then
If EdgeList\Visible=True Then
If ((EdgeList\PlaneNX#*EntityX#(CurrentEntity\Entity)+EdgeList\PlaneNY#*EntityY#(CurrentEntity\Entity)+EdgeList\PlaneNZ#*EntityZ#(CurrentEntity\Entity))-EdgeList\PlaneDist#+EntityList\Radius#)>-CurrentEntity\Radius# Then
EntityHidden=False
EndIf
EndIf
EndIf
Next

If EntityHidden=True Then
CurrentEntity\Occluded=True
;EntityColor EntityList\Entity,255,0,0
HideEntity CurrentEntity\Entity
Exit
Else
CurrentEntity\Occluded=False
ShowEntity CurrentEntity\Entity
EndIf
.SkipThisOccluder
Next

EndIf
End Function


; Function for filling the edgelist with edges
Function BuildEdgeList(OccID,Entity)
For Surfnr = 1 To CountSurfaces(Entity)
Surf=GetSurface(Entity,Surfnr)
For TriNr = 0 To CountTriangles(Surf)-1
EdgeA=TriangleVertex(Surf,Trinr,0)
EdgeB=TriangleVertex(Surf,Trinr,1)
AddEdge(OccID,Surf,TriNr,EdgeA,EdgeB)

EdgeA=TriangleVertex(Surf,Trinr,1)
EdgeB=TriangleVertex(Surf,Trinr,2)
AddEdge(OccID,Surf,TriNr,EdgeA,EdgeB)

EdgeA=TriangleVertex(Surf,Trinr,2)
EdgeB=TriangleVertex(Surf,Trinr,0)
AddEdge(OccID,Surf,TriNr,EdgeA,EdgeB)
Next
Next


End Function

Function AddEdge(OccID,Surf,TriNr,A,B)
EdgeFound = False
For EdgeList.Edge = Each Edge
If OccID = EdgeList\Parent Then       
; Check if the given edge already exist in the list
; In that case just supply the triangle index
; The mesh must have shared vertices
If ((EdgeList\A = A And EdgeList\B = B) Or (EdgeList\A = B And EdgeList\B = A)) Then
EdgeFound = True
EdgeList\Tri2=TriNr
Exit
EndIf
EndIf
Next

; If the edge wasn't found, add it
If EdgeFound = False Then
EdgeList.Edge = New Edge
EdgeList\A=A
EdgeList\B=B
EdgeList\Surf=Surf
EdgeList\Tri1=TriNr
EdgeList\Tri2=-1
EdgeList\Parent=OccID
EndIf

End Function


Function TriVisible(Camera,Entity,Surface,Triangle)

If Triangle=-1 Then
; This means that the edge has no adjacent triangle
; If this occurs the mesh isn't solid(closed)
Return False
EndIf

ax#=VertexX#(Surface,TriangleVertex(Surface,Triangle,0))
ay#=VertexY#(Surface,TriangleVertex(Surface,Triangle,0))
az#=VertexZ#(Surface,TriangleVertex(Surface,Triangle,0))
bx#=VertexX#(Surface,TriangleVertex(Surface,Triangle,1))
by#=VertexY#(Surface,TriangleVertex(Surface,Triangle,1))
bz#=VertexZ#(Surface,TriangleVertex(Surface,Triangle,1))
cx#=VertexX#(Surface,TriangleVertex(Surface,Triangle,2))
cy#=VertexY#(Surface,TriangleVertex(Surface,Triangle,2))
cz#=VertexZ#(Surface,TriangleVertex(Surface,Triangle,2))

; Get vectors
v1x#=ax#-bx#
v1y#=ay#-by#
v1z#=az#-bz#
v2x#=ax#-cx#
v2y#=ay#-cy#
v2z#=az#-cz#

; Get crossproduct
cpx#=(v1y#*v2z#)-(v1z#*v2y#)
cpy#=(v1z#*v2x#)-(v1x#*v2z#)
cpz#=(v1x#*v2y#)-(v1y#*v2x#)

; Transform vector according to entity and normalize
TFormNormal cpx#,cpy#,cpz#,Entity,0
cpx#=TFormedX#()
cpy#=TFormedY#()
cpz#=TFormedZ#()

; Now we got the triangles normal
; Take the DotProduct from above normal and a distance vector
; from the camera and one of the triangles vertices
TFormPoint ax#,ay#,az#,Entity,0
camvecx#=EntityX#(Camera)-TFormedX#()
camvecy#=EntityY#(Camera)-TFormedY#()
camvecz#=EntityZ#(Camera)-TFormedZ#()

dp#=((camvecx#*cpx#)+(camvecy#*cpy#)+(camvecz#*cpz#))

If dp#>0 Then
Return True
Else
Return False
EndIf

End Function

Function TriArea(X1,Y1,X2,Y2,X3,Y3)
D = X1*Y2 + X2*Y3 + X3*Y1 - X1*Y3 - X2*Y1 - X3*Y2
Return D
End Function

;
;Cross and DotProduct functions
Function CrossProduct(x1#,y1#,z1#,x2#,y2#,z2#)
CProd\x#=(y1#*z2#)-(z1#*y2#)
CProd\y#=(z1#*x2#)-(x1#*z2#)
CProd\z#=(x1#*y2#)-(y1#*x2#)
End Function
Function DotProduct#(x1#,y1#,z1#,x2#,y2#,z2#)
DProd=((x1*x2)+(y1*y2)+(z1*z2))
Return DProd
End Function


Кирпи4 03.01.2013 14:42

Ответ: Скрытие объектов за стенами
 
Хм, я ждал бурного обсуждения...

Arton 03.01.2013 17:37

Ответ: Скрытие объектов за стенами
 
Цитата:

Сообщение от Кирпи4 (Сообщение 248156)
Хм, я ждал бурного обсуждения...

Прикольно.
М... Может заюзать в моём быдлокоде... :crazy:

SBJoker 03.01.2013 18:32

Ответ: Скрытие объектов за стенами
 
Цитата:

Сообщение от Кирпи4 (Сообщение 248156)
Хм, я ждал бурного обсуждения...

Хорошим тоном считается прикрепить скриншот результата и/или скомпилированный экзешник ( не у все есть блитц!).

Кирпи4 03.01.2013 19:11

Ответ: Скрытие объектов за стенами
 
Вложений: 1
Дада, точно

SBJoker 03.01.2013 20:49

Ответ: Скрытие объектов за стенами
 
Ага работает, но откуда ограничение на выпуклость объектов?
По-моему достаточно по bounding-box отсекать.

Черный крыс 03.01.2013 21:04

Ответ: Скрытие объектов за стенами
 
Оно работает только если один цельный обьект перекрывает другой.

В ситуации, когда 2 обьекта комплементарно перекрывают третий - то алгоритм вынесет решение, что он виден. Поэтому с таким алгоритмом особо не разбежишься.

Сам алгоритм - тупой до безобразия, он не на много повысит производительность, так как рисование тупо заменяется довольно внушительной математикой. Его стоит применять в симбиозе с другими алгоритмами. В чистом виде он бесполезен.

Цитата:

По-моему достаточно по bounding-box отсекать.
А если меш имеет форму обруча - тоже будешь отсекать? А если на него наложен прозрачный материал ? Да даже куб, повернутый на 45 градусов по всем осям - отсекать по AABB уже не прокатит.

ЗЫ

Народ! Если игра предполагается в закрытых помещениях, лучший выбор - это порталы.
Ну а если открытые пространства, то все начинает сильно зависеть от жанра и специфики проекта.

ЗЗЫ Слава богу в 2D-графике нет такого гемороя, все легко бьется и отсекается. =)

Arton 03.01.2013 21:23

Ответ: Скрытие объектов за стенами
 
Я вообще вот таким пользовался.

Vobj2# - объект который надо скрывать
Cply2# - объект который "видит", например камера

Код:

Function ViziblObj2(Vobj2#,Cply2#,VcamRast#,Vrast2#)
;Плавное скрытее объекта, на расстояние или вне зоны камеры.
;EntityAutoFade Vobj2#,VcamRast#,Vrast2#
If EntityDistance(Cply2#,Vobj2#) > Vrast2# Or EntityInView(Vobj2#,Cply2#) = False Then HideEntity Vobj2# : Else ShowEntity Vobj2#

End Function

У меня вопрос. Этот код эффективен? Мне он помогал, но может быть он тормозной слишком?

Черный крыс 03.01.2013 21:36

Ответ: Скрытие объектов за стенами
 
Эффективен, если Vobj2 - является порталом.

В остальных случаях - нет.

Arton 03.01.2013 21:38

Ответ: Скрытие объектов за стенами
 
Цитата:

Сообщение от Diablo1909 (Сообщение 248215)
Эффективен, если Vobj2 - является порталом.

В остальных случаях - нет.

Порталом? Не понял? Поясни.

Но ведь разгрузка на полигоны в кадре есть.
Неужели этот код настолько неэффективен?

Wegox 05.01.2013 02:12

Ответ: Скрытие объектов за стенами
 
Цитата:

Сообщение от Arton (Сообщение 248216)
Порталом? Не понял? Поясни.

Но ведь разгрузка на полигоны в кадре есть.
Неужели этот код настолько неэффективен?

А что!? не портал что-ли :-)
Код:

Function OccludeEntity(CurrentEntity.Entity,Camera)
; Now check if object is occluded or not...

If CurrentEntity\Occluded=False Then ; If entity already is occluded, then skip this...

For OccludeList.Occluder = Each Occluder
; Skip the occluder if it's out of the viewfrustum
If EntityInView(OccludeList\Mesh,Camera)=False Then Goto SkipThisOccluder
EntityHidden=True
For EdgeList.Edge = Each Edge
If OccludeList\ID = EdgeList\Parent Then
If EdgeList\Visible=True Then
If  ((EdgeList\PlaneNX#*EntityX#(CurrentEntity\Entity)+EdgeList\PlaneNY#*EntityY#(CurrentEntity\Entity)+EdgeList\PlaneNZ#*EntityZ#(CurrentEntity\Entity))-EdgeList\PlaneDist#+EntityList\Radius#)>-CurrentEntity\Radius#  Then
EntityHidden=False
EndIf
EndIf
EndIf
Next

If EntityHidden=True Then
CurrentEntity\Occluded=True
;EntityColor EntityList\Entity,255,0,0
ShowEntity CurrentEntity\Entity

Exit
Else
CurrentEntity\Occluded=False
HideEntity CurrentEntity\Entity

EndIf
.SkipThisOccluder
Next

EndIf
End Function


Arton 05.01.2013 05:18

Ответ: Скрытие объектов за стенами
 
Wegox, твой код чего то не захотел работать, не в цикле, не так. Дебагер ругается "ерор тайп" Разбираться не хочется, да и программист из меня фиговый :-)

P. S. Нда, понаписал тут вопросов, а оказывается на первой странице объяснения есть...

Цитата:

Сообщение от Diablo1909 (Сообщение 248215)
Эффективен, если Vobj2 - является порталом.

В остальных случаях - нет.

А если к примеру куча деревьев, целый лес, 1000 штук, мой код эффективен? Полигоны то разгружает, но вот что насчёт скорости?


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

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot