many objects in one level/zones?

Blitz3D Forums/Blitz3D Programming/many objects in one level/zones?

b32(Posted 2007) [#1]
What methods are recommended for using many objects in one level ? I tried several methods allready: collapsing everything into one object with AddMesh and using CopyEntity instead of loading the same mesh over and over again.

I remember a code in the archives that stores only the object's coordinates and creates new meshes 'on the fly' when the camera gets in a certain range. Unf. I cannot find it anymore. But would that be a better method?

Here and there I've heard the term 'zones' in this context. What are zones ? Are they 'clusters' of meshes that are hidden/showed when the camera gets near ? What is the idea behind that ?
Thanks for any suggestions.


Naughty Alien(Posted 2007) [#2]
..maybe this can help..


; Definit le Frustum
Global p1x,p1y
Global p2x,p2y

; Enfants du Quadtree
Const CHILD00 = 0
Const CHILD01 = 1
Const CHILD11 = 2
Const CHILD10 = 3

; CAMERA
Type CAMERA
Field x,y ; Position de la camera
Field fov ; Angle de vue
End Type

; creation d'une camera
Function Camera.CAMERA(x,y,fov)
this.CAMERA = New CAMERA
this\x = x : this\y = y : this\fov = fov
Return this
End Function

; Renvoie True si un point est dans le plan Left du Frustum
Function PointInFrustumL(this.CAMERA,x,y)
Return ( -(x - this\x) * (p1y - this\y) + (y - this\y) * (p1x - this\x) >= 0)
End Function

; Renvoie True si un point est dans le plan Right du Frustum
Function PointInFrustumR(this.CAMERA,x,y)
Return ( -(x - this\x) * (p2y - this\y) + (y - this\y) * (p2x - this\x) <= 0)
End Function

; Renvoie True si un point est dans le plan Front du Frustum (pas utilisé ici)
Function PointInFrustumF(this.CAMERA,x,y)
Return ( -(x - this\x) * (p3y - this\y) + (y - this\y) * (p3x - this\x) >= 0)
End Function

; QUADTREE
Type QUADTREE
Field Child.QUADTREE[3] ; Les 4 enfants du quadtree
Field xmin,ymin ; Coordonnées du sommet haut gauche
Field xmax,ymax ; Coordonnées du sommet bas droite
End Type

; Creation d'un quadtree de profondeur depth
; et associé à un carré de cotés xmax-xmin, ymax-ymin
Function Quadtree.QUADTREE(xmin,ymin,xmax,ymax,depth)
this.QUADTREE = New QUADTREE
this\xmin = xmin
this\xmax = xmax
this\ymin = ymin
this\ymax = ymax

If (depth > 0)
; On crée 4 enfants
xmoy = (xmin+xmax) / 2
ymoy = (ymin+ymax) / 2
depth = depth - 1
this\Child[CHILD00] = Quadtree(xmin,ymin,xmoy,ymoy,depth) ; Haut gauche
this\Child[CHILD01] = Quadtree(xmin,ymoy,xmoy,ymax,depth) ; Bas gauche
this\Child[CHILD11] = Quadtree(xmoy,ymoy,xmax,ymax,depth) ; Bas droite
this\Child[CHILD10] = Quadtree(xmoy,ymin,xmax,ymoy,depth) ; Haut droite
EndIf
Return this
End Function

; On teste si un des 4 sommets du carré associé au quadtree
; est visible par la camera
Function QuadInFrustum(this.QUADTREE,cam.CAMERA)
Local nbPlansInterieur

; Plan de gauche
nbPlansInterieur = 0
nbPlansInterieur = nbPlansInterieur + PointInFrustumL(cam,this\xmin,this\ymin)
nbPlansInterieur = nbPlansInterieur + PointInFrustumL(cam,this\xmin,this\ymax)
nbPlansInterieur = nbPlansInterieur + PointInFrustumL(cam,this\xmax,this\ymin)
nbPlansInterieur = nbPlansInterieur + PointInFrustumL(cam,this\xmax,this\ymax)
If nbPlansInterieur = 0 Return False

; Plan de droite
nbPlansInterieur = 0
nbPlansInterieur = nbPlansInterieur + PointInFrustumR(cam,this\xmin,this\ymin)
nbPlansInterieur = nbPlansInterieur + PointInFrustumR(cam,this\xmin,this\ymax)
nbPlansInterieur = nbPlansInterieur + PointInFrustumR(cam,this\xmax,this\ymin)
nbPlansInterieur = nbPlansInterieur + PointInFrustumR(cam,this\xmax,this\ymax)
If nbPlansInterieur = 0 Return False

Return True
End Function

; Rendu du Quadtree
Function RenderQuadtree(this.QUADTREE,cam.CAMERA,depth)
If QuadInFrustum(this,cam)
If (depth > 1)
Color 128,128,128
Line (this\xmin+this\xmax)/2,this\ymin,(this\xmin+this\xmax)/2,this\ymax
Line this\xmin,(this\ymin+this\ymax)/2,this\xmax,(this\ymin+this\ymax)/2

depth = depth - 1

RenderQuadtree(this\Child[CHILD00],cam,depth)
RenderQuadtree(this\Child[CHILD01],cam,depth)
RenderQuadtree(this\Child[CHILD11],cam,depth)
RenderQuadtree(this\Child[CHILD10],cam,depth)
Else
Color 196,196,196
Rect this\xmin+1,this\ymin+1,this\xmax-this\xmin-1,this\ymax-this\ymin-1,True
EndIf
EndIf
End Function

;==============================================================================================
; EXAMPLE
;==============================================================================================

AppTitle "Simple Quadtree Demo - Seyhajin"
Graphics 512,512,0,2
SetBuffer BackBuffer()

; Variables de configuration
QuadDepth = 7 ; Profondeur du quadtree (nb de fois qu'on decoupe le plan)
QuadSize = 512 ; Taille initiale du quadtree
CamSpeed# = 2 ; Vitesse de deplacement de la camera
CamFOV# = 60.0 / 2.0 ; Angle de vue de la camera (default = 90)
ViewLine = 300 ; Taille de la ligne des plans

; Creation de la camera
cam.CAMERA = Camera(QuadSize/2,QuadSize/2,CamFOV)
; Creation du Quadtree principale
root.QUADTREE = Quadtree(0,0,QuadSize,QuadSize,QuadDepth)

;----------------------------------
; BOUCLE PRINCIPALE
;----------------------------------
While Not KeyHit(1)
Cls

; Update Camera position
If KeyDown(200) ; Up
cam\y = cam\y - CamSpeed#
ElseIf KeyDown(208) ; Down
cam\y = cam\y + CamSpeed#
EndIf
If KeyDown(203) ; Left
cam\x = cam\x - CamSpeed#
ElseIf KeyDown(205) ; Right
cam\x = cam\x + CamSpeed#
EndIf

; Rendu du quadtree
Color 255,255,255
Rect root\xmin,root\ymin,root\xmax,root\ymax,1
RenderQuadtree(root,cam,QuadDepth)


; Dessine la pyramide de vue (Frustum)
x# = MouseX() - cam\x
y# = MouseY() - cam\y
angle# = 180+ATan2(-y#,-x#)
Color 255,255,0
Line cam\x,cam\y,cam\x+(ViewLine/2)*Cos(angle#),cam\y+(ViewLine/2)*Sin(angle#)
Color 255,0,0
; Plan gauche
p1x = cam\x+ViewLine*Cos(angle#-CamFOV)
p1y = cam\y+ViewLine*Sin(angle#-CamFOV)
Line cam\x,cam\y,p1x,p1y
; Plan droit
p2x = cam\x+ViewLine*Cos(angle#+CamFOV)
p2y = cam\y+ViewLine*Sin(angle#+CamFOV)
Line cam\x,cam\y,p2x,p2y
; Dessine la camera
Color 0,0,255
Oval cam\x-3,cam\y-3,6,6,True

Flip
Wend

Delete Each CAMERA
Delete Each QUADTREE


b32(Posted 2007) [#3]
Thanks for the example. In a way, I understand what it does. But should I hide entites that are not in view?


Wings(Posted 2007) [#4]
use
Entity Auto Fade


GfK(Posted 2007) [#5]
But should I hide entites that are not in view?


use
Entity Auto Fade
o_O

Don't do anything. Blitz automatically doesn't render stuff that isn't in view.


jfk EO-11110(Posted 2007) [#6]
Some infos:

Blitz can only "hide" things that are (A) behind the camera or (B) out of the camera range IF they are individual entities. This means, if you have a big level that is loaded as one mesh and has say 20k triangles, then Blitz will always render 20k Triangles, no matter if you only watch a single wall or have a very low camera range.

So it may be important to cut the level in pieces. (See ClusterizeMesh in the archives)

While the fragmentation of a big level mesh may feel a little tricky, additional meshes in the scene will be hidden automaticly and efficiently, as long as they don't cover wide areas. Example: trees: not every tree should be an entity, nor should you add all trees to a single mesh. The golden middle way would be to add groups of trees to a grid of meshes using a polycount that makes sense.

If it's an indoor level then it's even easier, make sure the various level places are connected by fairly long tunnel systems, so you'll never render more than one place.

There are more systems to cull things and "optimize" the speed. VIS-Zones is one. BSP VIS Occlusion and more. A lot of people tried many things and there's a good chance that if you implement one of these complicated culling techniques then it will be slower than the unculled counterpart at the end of the day, so KISS, keep it simple.

If you use fragmentation and a low camera range then the speed is ok. All you have to do is to design the level with a low camerarange in mind.


b32(Posted 2007) [#7]
Thanks a lot