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)

Черный крыс 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-графике нет такого гемороя, все легко бьется и отсекается. =)


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

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