I'm startting to implement an octree but it's not finished. the code is not finished and developped with bmax and minib3d.
SuperStrict
Import "../Inc/Inc_Minib3d.bmx"
Const LE_MESH:String = "media\Patmaba.b3d"
'Profondeur toujours >= 1
Const LA_PROFONDEUR:Int = 4
' -----------------------
' Variable(s) globale(s)
' -----------------------
Global cam:TCamera
Global D:TMesh
Global Light1:TLight
Global m:TMesh
Global gi_CubeSize:Float = 0.0
'------------------------
'Freelook cam Var
'------------------------
Global Mouse_X_Speed:Float
Global Mouse_Y_Speed:Float
Global Camera_VelX:Float
Global Camera_VelZ:Float
Global Camera_Pitch:Float
Global Camera_Yaw:Float
Global oldmx:Int
Global oldmy:Int
Const AppFPS:Int = 50
Global FramePeriod:Int = 1000 / AppFPS
Global FrameTime:Int = MilliSecs () - FramePeriod
Global FrameElapsed:Int
Global FrameTicks:Int
Global FrameTween:Float
' ---------------
' Init la scene
' ---------------
InitScene()
' ---------------
' Init les Agents
' ---------------
Initoctree()
' -------------------------------------
' Variables pour la gestion du fps
' -------------------------------------
Local old_ms:Int=MilliSecs()
Local renders:Int
Local fps:Int
Global countbox:Int=0
Repeat
' --------------------------
' Frame rate limiting
' --------------------------
Repeat
FrameElapsed = MilliSecs () - FrameTime
Until FrameElapsed
FrameTicks = FrameElapsed / FramePeriod
FrameTween:Float = Float (FrameElapsed Mod FramePeriod) / Float (FramePeriod)
' -----------------------
' Update tweening
' -----------------------
For Local FrameLimit:Int = 1 To FrameTicks
FrameTime = FrameTime + FramePeriod
UpdateGame ()
UpdateWorld
Next
' -------------------
' Redraw world
' -------------------
RenderWorld
' ---------------------
' FPS Displaying
' ---------------------
' Proc_CinemaStrip()
debugtext 10,10,"octree"
debugtext 10,25," Use arrow keys"
cube( -meshwidth(m)/2,meshwidth(m)/2,-meshheight(m)/2, meshheight(m)/2,-meshdepth(m)/2,meshdepth(m)/2)
Flip False
Until KeyHit (KEY_ESCAPE)
Function UpdateGame()
Proc_Freelook(1.03,0.03)
PointEntity cam, m
EndFunction
' ---------------------------------
' InitScene()
' Description de la scene
' ---------------------------------
Function InitScene()
Graphics3D 800,600,32,0
' -------------------------------------
' Setup camera
' -------------------------------------
cam=CreateCamera()
PositionEntity cam,-11,70,-125
CameraRange cam,1,250000
CameraZoom cam,0.9
' -------------------------------------
' Setup Light and ambiance
' -------------------------------------
Light1=CreateLight(2)
PositionEntity Light1,-1630,1630,1630
LightColor Light1,155,220,255
LightRange Light1,5500
EndFunction
' ---------------------------------
' InitAgent()
' Description des agents IA
' ---------------------------------
Function Initoctree()
m:TMesh = LoadMesh(LE_MESH)
gi_CubeSize = 0.0
gi_CubeSize = MeshWidth( m )
If gi_CubeSize < MeshHeight( m ) Then gi_CubeSize = MeshHeight( m )
If gi_CubeSize < MeshDepth( m ) Then gi_CubeSize = MeshDepth( m )
PositionEntity cam,-gi_CubeSize /2,gi_CubeSize /2,-gi_CubeSize /2
PointEntity cam, m
dessine_octree()
DebugLog "countbox="+countbox
End Function
' -------------------------------------------------------------------------------------------------------------------
' This Function returns True If a point is inside an Object's oriented bounding box, and false if it is not.
' -------------------------------------------------------------------------------------------------------------------
Function Point_Inside_Box:Int(ThisEntity:TMesh, min_x:Float, max_x:Float, min_y:Float, max_y:Float, min_z:Float, max_z:Float )
' Calculate the bounding box (in Object space) For this Object.
' You can precalculate this For every Object in your game For a huge speed increase!
Local Surfaces:Int = CountSurfaces(ThisEntity)
Local t:Int=0
For Local LOOP_Surface:Int = 1 To Surfaces
Local Surface_Handle:TSurface = GetSurface(ThisEntity, LOOP_Surface)
Local Verts:Int = CountVertices(Surface_Handle) - 1
For Local LOOP_Verts:Int = 0 To Verts-1
Local vx:Float = VertexX#(Surface_Handle, LOOP_Verts)
Local vy:Float = VertexY#(Surface_Handle, LOOP_Verts)
Local Vz:Float = VertexZ#(Surface_Handle, LOOP_Verts)
' Determine If the point (in Object space) is inside the bounding box (in Object space).
If (vx# > min_x#) And (vx# < max_x#) And (vy# > min_y#) And (vy# < max_y#) And (Vz# > min_z#) And (vz# < max_z#)
'DebugLog "TRUE"
Return True
EndIf
Next
Next
'DebugLog "FALSE"
Return False
EndFunction
'------------------------
'Camera freelook
'------------------------
Function Proc_Freelook(Velocity:Float,Speed:Float)
Local flag:Int=False
Mouse_X_Speed=(MouseXSpeed())*0.5
Mouse_Y_Speed=(MouseYSpeed())*0.5
MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
Camera_Pitch=Camera_Pitch+Mouse_Y_Speed
Camera_Yaw=Camera_Yaw+Mouse_X_Speed
If flag=True
RotateEntity cam,Camera_Pitch,-Camera_Yaw,0
EndIf
If KeyDown(KEY_LEFT) Then
Camera_VelX=Camera_VelX-Speed
ElseIf KeyDown(KEY_RIGHT)
Camera_VelX=Camera_VelX+Speed
EndIf
If KeyDown(KEY_DOWN) Then
Camera_VelZ=Camera_VelZ-Speed
ElseIf KeyDown(KEY_UP)
Camera_VelZ=Camera_VelZ+Speed
EndIf
Camera_VelX=Camera_VelX/Velocity
Camera_VelZ=Camera_VelZ/Velocity
MoveEntity cam,Camera_VelX,0,Camera_VelZ
If KeyDown(KEY_UP) Then
MoveEntity cam,0,0,Speed
EndIf
If KeyDown(KEY_DOWN) Then
MoveEntity cam,0,0,-Speed
EndIf
If KeyDown(KEY_RIGHT) Then
MoveEntity cam,Speed,0,0
EndIf
If KeyDown(KEY_LEFT) Then
MoveEntity cam,-Speed,0,0
EndIf
End Function
Function cube (x0:Float, x1:Float, y0:Float, y1:Float, z0:Float, z1:Float)
glBegin (GL_LINE_STRIP);
glVertex3f (x0, y0, z0);
glVertex3f (x1, y0, z0);
glVertex3f (x1, y1, z0);
glVertex3f (x0, y1, z0);
glVertex3f (x0, y0, z0);
glVertex3f (x0, y0, z1);
glVertex3f (x1, y0, z1);
glVertex3f (x1, y0, z0);
glVertex3f (x1, y0, z1);
glVertex3f (x1, y1, z1);
glVertex3f (x1, y1, z0);
glVertex3f (x1, y1, z1);
glVertex3f (x0, y1, z1);
glVertex3f (x0, y1, z0);
glVertex3f (x0, y1, z1);
glVertex3f (x0, y0, z1);
glEnd ();
EndFunction
' dessine l'octree recursivement
Function dessine_8_cubes (lxmin:Float, lxmax:Float, lymin:Float, lymax:Float, lzmin:Float, lzmax:Float, pMaxLevel:Int, pCurrentLevel:Int, the_list:TList)
Local lb_val:Int
'lb_val:Int = Point_Inside_Box(m, lxmin, lxmax, lymin, lymax, lzmin, lzmax )
Local my_list:TList = Point_Inside_List(lxmin, lxmax, lymin, lymax, lzmin, lzmax, the_list )
If my_list.count() = 0
lb_val = False
Else
lb_val = True
EndIf
' si on est un noeud terminal on s'arrete
If (pMaxLevel=pCurrentLevel) And ( lb_val = True)
cube (lxmin, lxmax, lymin, lymax, lzmin, lzmax)
' Local c:TMesh = CreateCube()
' EntityAlpha c, 0.4
' PositionEntity c, (lxmin + lxmax) / 2,(lymin + lymax) / 2,(lzmin + lzmax) / 2
' ScaleEntity c, 1/MeshWidth(c)*(lxmax-lxmin), 1/MeshHeight(c)*(lymax-lymin), 1/MeshDepth(c)*(lzmax-lzmin)
Local s:TMesh = CreateSphere()
EntityAlpha s, 0.4
PositionEntity s, (lxmin + lxmax) / 2,(lymin + lymax) / 2,(lzmin + lzmax) / 2
ScaleEntity s, 1/MeshWidth(s)*(lxmax-lxmin), 1/MeshHeight(s)*(lymax-lymin), 1/MeshDepth(s)*(lzmax-lzmin)
countbox=countbox+1
Return
EndIf
If lb_val= True And lb_val
' on rappelle rcursivement pour les 8 fils
dessine_8_cubes (lxmin, (lxmin + lxmax) / 2, lymin, (lymin + lymax) / 2, lzmin, (lzmin + lzmax) / 2, pMaxLevel, pCurrentLevel + 1, my_list )
dessine_8_cubes (lxmin, (lxmin + lxmax) / 2, lymin, (lymin + lymax) / 2, (lzmin + lzmax) / 2, lzmax, pMaxLevel, pCurrentLevel + 1, my_list )
dessine_8_cubes (lxmin, (lxmin + lxmax) / 2, (lymin + lymax) / 2, lymax, lzmin, (lzmin + lzmax) / 2, pMaxLevel, pCurrentLevel + 1, my_list )
dessine_8_cubes (lxmin, (lxmin + lxmax) / 2, (lymin + lymax) / 2, lymax, (lzmin + lzmax) / 2, lzmax, pMaxLevel, pCurrentLevel + 1, my_list )
dessine_8_cubes ((lxmin + lxmax) / 2, lxmax, lymin, (lymin + lymax) / 2, lzmin, (lzmin + lzmax) / 2, pMaxLevel, pCurrentLevel + 1, my_list )
dessine_8_cubes ((lxmin + lxmax) / 2, lxmax, lymin, (lymin + lymax) / 2, (lzmin + lzmax) / 2, lzmax, pMaxLevel, pCurrentLevel + 1, my_list )
dessine_8_cubes ((lxmin + lxmax) / 2, lxmax, (lymin + lymax) / 2, lymax, lzmin, (lzmin + lzmax) / 2, pMaxLevel, pCurrentLevel + 1, my_list )
dessine_8_cubes ((lxmin + lxmax) / 2, lxmax, (lymin + lymax) / 2, lymax, (lzmin + lzmax) / 2, lzmax, pMaxLevel, pCurrentLevel + 1, my_list )
EndIf
EndFunction
Function dessine_octree ()
Local my_list:TList
my_list = New TList
glDisable (GL_TEXTURE_2D);
glColor3ub (50, 255, 50);
my_list = GetPointIntoList(m)
dessine_8_cubes (-(gi_CubeSize/2), (gi_CubeSize/2), -(gi_CubeSize/2), (gi_CubeSize/2), -(gi_CubeSize/2), (gi_CubeSize/2),LA_PROFONDEUR, 1, my_list)
glColor3ub (255, 255, 255);
glEnable (GL_TEXTURE_2D);
EndFunction
Type TVertexInfo
Field SurfIndex:Int
Field VertIndex:Int
EndType
Function GetPointIntoList:TList(ThisEntity:TMesh )
' Calculate the bounding box (in Object space) For this Object.
' You can precalculate this For every Object in your game For a huge speed increase!
Local Surfaces:Int = CountSurfaces(ThisEntity)
Local my_list:TList = New TList
Local t:Int=0
For Local LOOP_Surface:Int = 1 To Surfaces
Local Surface_Handle:TSurface = GetSurface(ThisEntity, LOOP_Surface)
Local Verts:Int = CountVertices(Surface_Handle) - 1
For Local LOOP_Verts:Int = 0 To Verts-1
Local my_vi:TVertexInfo = New TVertexInfo
my_vi.SurfIndex = LOOP_Surface
my_vi.VertIndex = Loop_Verts
my_list.AddLast my_vi
Next
Next
Return my_list
EndFunction
Function Point_Inside_List:TList( min_x:Float, max_x:Float, min_y:Float, max_y:Float, min_z:Float, max_z:Float, thelist:TList )
Local my_list:TList = New TList
For Local L:TVertexInfo = EachIn thelist
Local Surface_Handle:TSurface = GetSurface(m, L.SurfIndex)
Local vx:Float = VertexX#(Surface_Handle, L.VertIndex)
Local vy:Float = VertexY#(Surface_Handle, L.VertIndex)
Local Vz:Float = VertexZ#(Surface_Handle, L.VertIndex)
' Determine If the point (in Object space) is inside the bounding box (in Object space).
If (vx# > min_x#) And (vx# < max_x#) And (vy# > min_y#) And (vy# < max_y#) And (Vz# > min_z#) And (vz# < max_z#)
Local my_vi:TVertexInfo = New TVertexInfo
my_vi.SurfIndex = L.SurfIndex
my_vi.VertIndex = L.VertIndex
my_list.AddLast my_vi
EndIf
Next
Return my_list
EndFunction
'f_bCheckSphereIntersect
'Return True If the two spheres intersect
Function f_bCheckSphereIntersect:Int( p_fXCenter1:Float, p_fYCenter1:Float, p_fZCenter1:Float, p_fRadius1:Float, p_fXCenter2:Float, p_fYCenter2:Float, p_fZCenter2:Float, p_fRadius2:Float )
Local l_fXDiff:Float
Local l_fYDiff:Float
Local l_fZDiff:Float
Local l_fDistance:Float
' Calculate distance between center points
l_fXDiff = Abs(p_fXCenter2-p_fXCenter1)
l_fYDiff = Abs(p_fYCenter2-p_fYCenter1)
l_fZDiff = Abs(p_fZCenter2-p_fZCenter1)
l_fDistance = Sqr(l_fXDiff*l_fXDiff+l_fYDiff*l_fYDiff+l_fZDiff*l_fZDiff)
'Return True If the two spheres intersect
If(l_fDistance <= (p_fRadius1+p_fRadius2)) Then Return True
'No intersection
Return False
EndFunction
|