Points inside an ellipse, in PB terrain, and in OpenGL

Everything related to 3D programming
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Points inside an ellipse, in PB terrain, and in OpenGL

Post by applePi »

an application of the problem how to know which points are inside an ellipse
using PB Ogre terrain, and OpenGL
we just stretch the y coordinates of every point inside the ellipse.
the point is inside an ellipse if it satisfy the following condition:
value.f = Pow(x-xcenter,2)/(a*a) + Pow(y-ycenter,2)/(b*b)
if value < 1 then the point is inside the ellipse.
look http://www.mathopenref.com/coordgeneralellipse.html
x,y is the position of the point , xcenter and ycenter is the ellipse center
a is the ellipse radius across the x axis
b is the ellipse radius across the y axis
note that (a*a) or use Pow(a,2) since i have spent 2 days getting erroneous values because i have used Pow(x-xcenter,2)/a*a + Pow(y-ycenter,2)/b*b . i have forgotten that the division have a priority over multiplication.
if you want a hole change 50 to -50 in the line:
SetTerrainTileHeightAtPoint(0, 0, 0, x, y, 50)
but note that the sphere does not touch the hole bottom, it is floating slightly over the bottom.
Image

notes:
1) that if you want circular edifice make a = b , while for the elliptical edifice a > b
2) the terrain size is 129 on x and y

Code: Select all

Declare DrawEllipse(xcenter, ycenter)

Enumeration
   #TEXTURE = 200
   #MATERIAL
   #ENTITY
   #CAMERA
   #ground
  
EndEnumeration

#CameraSpeed = 4

Define.f KeyX, KeyY, MouseX, MouseY
  

InitEngine3D()

Add3DArchive(".", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures/"       , #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures/nvidia" , #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts"         , #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/GUI"           , #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/desert.zip", #PB_3DArchive_Zip)
    
Parse3DScripts()

ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)

InitSprite()
  InitKeyboard()
  InitMouse()
  
OpenWindow(0, 0, 0, DesktopW, DesktopH, "use mouse and keys to move camera")
OpenWindowedScreen(WindowID(0), 0, 0, DesktopW, DesktopH, 0, 0, 0)

GetScriptMaterial(2, "Color/Red")
CreateMaterial(6, LoadTexture(2, "soil_wall.jpg"))
CreateMaterial(3, LoadTexture(3, "terrain_detail.jpg"))


CreateCamera(#Camera, 0, 0, 100, 100)
MoveCamera(#Camera,0,100,300, #PB_Absolute)
CameraLookAt(#Camera,0,0,0)


CreateLight(0, $FFFFFF, 1500, 800, 500)
AmbientColor(RGB(200,200,200))

SkyBox("desert07.jpg")

CreateCube(1, 1)

SetupTerrains(LightID(0), 3000, #PB_Terrain_NormalMapping)
; initialize terrain 

;Result = CreateTerrain(#Terrain, Size, WorldSize, Scale, NbLayers, Filename$, Extension$)
CreateTerrain(0, 129, 200, 1, 3, "TerrainHeight", "dat")
; set all texture will be use when terrrain will be constructed 
AddTerrainTexture(0,  0, 100, "dirt_grayrocky_diffusespecular.jpg",  "dirt_grayrocky_normalheight.jpg")
AddTerrainTexture(0,  1,  30, "grass_green-01_diffusespecular.jpg", "grass_green-01_normalheight.jpg")
AddTerrainTexture(0,  2, 200, "growth_weirdfungus-03_diffusespecular.jpg", "growth_weirdfungus-03_normalheight.jpg")
;- define terrains
DefineTerrainTile(0, 0, 0, "terrain.png", 0, 0)     
BuildTerrain(0)  
TerrainPhysicBody(0, 0.5, 1)
UpdateTerrain(0)
; SkyBox
SkyBox("desert07.jpg")

EnableWorldPhysics(1)
EnableWorldCollisions(1)

Result = TerrainTileSize(0, 0, 0)
;SetTerrainTileHeightAtPoint(#Terrain, TileX, TileY, x, y, Height)
;SetTerrainTileHeightAtPoint(0, 0, 0, 0, 0, 50) 
TerrainPhysicBody(0, 2, 1) 
UpdateTerrain(0)

CreateSphere(2,4)

CreateEntity(2,MeshID(2), #PB_Material_None ,0,70,0)
EntityPhysicBody(2, #PB_Entity_SphereBody,1, 0.3, 1)
EnableWorldPhysics(1)
EnableWorldCollisions(1)

DrawEllipse(64, 64)

Repeat
  event = WindowEvent()
  If ExamineMouse()
        MouseX = -MouseDeltaX()/20 
        MouseY = -MouseDeltaY()/20
      EndIf
          
        If ExamineKeyboard()
         
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed
        Else
          KeyY = 0
        EndIf
        
                    
      EndIf
     
      
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
  
  RenderWorld()   
  FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape)

Procedure DrawEllipse(xcenter, ycenter)
  a.f=20:b.f=10
  
  xcenter = xcenter: ycenter = ycenter
    
  For y = ycenter-b To ycenter+b ; check only the points inside the rectangle
  For x = xcenter-a To xcenter+a ;  around the ellipse
  
    value.f = Pow(x-xcenter,2)/(a*a) + Pow(y-ycenter,2)/(b*b)
   
    If value < 1 
            
      SetTerrainTileHeightAtPoint(0, 0, 0, x, y, 50)
      TerrainPhysicBody(0, 2, 1)
      UpdateTerrain(0) 
         
    EndIf
        

  Next
Next

      
EndProcedure
*************************************************************************************************

OpenGL code
now the same above problem in OpenGL
we move the point inside the ellipse vertically by 10
Point3D(x,z)\y = 10
we make the figure compact by multiplying with 0.2
Point3D(x,z)\x = x*0.2
Point3D(x,z)\y = 10
Point3D(x,z)\z = z*0.2
here you see the elliptical HAT shape:
Image
let a=b (ellipse radiuses) and you have a circular hat shape

change 10 in "Point3D(x,z)\y = 10" to 1 and you will have this shape:
Image

now in line 81: glDrawArrays_(#GL_LINE_STRIP, (NbX+1) * i, NbX) use #GL_POINTS and you will see the ellipse floating over the (terrain) by 10
Image

Centering the Graphics:
the problem is that the Graphics are not centered , it does not rotate around its center, so i have applied the mesh centering procedure posted by Comtois for PB Ogre mesh here
http://purebasic.fr/english/viewtopic.p ... 15#p417666
and it works. to see how it rotate without centering comment the line 65 ChangeGraphic()
note the using of gluLookAt function to imitate the camera, so your eye look in a suitable position to the 3D Graphic, a good description for the gluLookAt is this: (Bob is hanging upside down from a branch, looking at Alice, lying on the grass with a book): look here: http://www.gamedev.net/topic/211831-can ... glulookat/
needs PB 5.30++

Code: Select all

Structure Point3D
  x.f
  y.f
  z.f
  r.f
  g.f
  b.f
EndStructure


Define event, quit
Declare ChangeGraphic() ; a procedure for centering the Graphics

OpenWindow(0, 0, 0, 800, 600, "OpenGL demo .. points inside ellipse")
SetWindowColor(0, RGB(200,220,200))
OpenGLGadget(0, 20, 10, WindowWidth(0)-40 , WindowHeight(0)-20)

glLoadIdentity_();
gluPerspective_(45.0, 800/600, 1.0, 100.0)
glEnable_(#GL_DEPTH_TEST)

Global NbX = 129
Global NbZ = 129
xcenter=64 : ycenter=64

Global Dim Point3D.Point3D(NbX,NbZ)

a=40: b=20  ; a is radius over x axis, b is radius over y axix, let a=b and we get a circle
  For z=0 To NbZ
   
    For x=0 To NbX
    
      
      y.f = Pow(x-xcenter,2)/(a*a) + Pow(z-ycenter,2)/(b*b)
      
      
      If y < 1
       
      Point3D(x,z)\x = x*0.2
      Point3D(x,z)\y = 10 ; try changing it to 1 
      Point3D(x,z)\z = z*0.2
      Point3D(x,z)\r = 0.0 :Point3D(x,z)\g = 1.0 :Point3D(x,z)\b = 0 
    Else
      
        Point3D(x,z)\x = x*0.2
        Point3D(x,z)\y = 1
        Point3D(x,z)\z = z*0.2
        Point3D(x,z)\r = 1.0 :Point3D(x,z)\g = 0.0 :Point3D(x,z)\b = 0 
        
      EndIf
         
     
    Next x
   
  Next z
  ;arrayLength = ArraySize(Point3D())
  
 ;=================================================================================
rot.f = 1
glTranslatef_(0.0, 0.0, -50)
;the following is the camera or your eye
gluLookAt_( 0, 5, 0,
           -5,  -5, -20,
            0, 1,  0 )
ChangeGraphic() ; centering the mesh procedure
Repeat
  
  glViewport_(0, 0, WindowWidth(0), WindowHeight(0))
  ;glClearColor_(1.0, 1.0, 1.0, 1)
  glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
  glEnableClientState_(#GL_VERTEX_ARRAY )
  glEnableClientState_(#GL_COLOR_ARRAY)
  glRotatef_(rot, 0, 1, 0);
 
  glVertexPointer_(3, #GL_FLOAT,SizeOf(Point3D),Point3D(0,0))
  glColorPointer_(3, #GL_FLOAT, SizeOf(Point3D), @Point3D(0,0)\r)
  
  
  For i = 0 To NbX
    ;glDrawArrays_(#GL_POINTS, (NbX+1) * i, NbX)
    glDrawArrays_(#GL_LINE_STRIP, (NbX+1) * i, NbX)
  Next

  glDisableClientState_(#GL_VERTEX_ARRAY);
  glDisableClientState_(#GL_COLOR_ARRAY)
  
 Repeat
    event = WindowEvent()
    If event = #PB_Event_CloseWindow
      quit = #True
    EndIf
  Until event = 0 Or quit = #True
  SetGadgetAttribute(0, #PB_OpenGL_FlipBuffers, #True)
  Delay(10)
Until quit = #True


Procedure ChangeGraphic()
  ;this procedure are by Comtois
  Protected.f minx, miny, minz, maxx, maxy, maxz
  Protected.f corx, cory, corz
  minx =  99999
  miny =  99999
  minz =  99999
  maxx = -99999
  maxy = -99999
  maxz = -99999
  
  For z=0 To NbZ
    For x=0 To NbX
  
    If Point3D(x,z)\x > maxx
      maxx = Point3D(x,z)\x
    EndIf
    If Point3D(x,z)\x < minx
      minx = Point3D(x,z)\x
    EndIf    
    If Point3D(x,z)\y > maxy
      maxy = Point3D(x,z)\y
    EndIf
    If Point3D(x,z)\y < miny
      miny = Point3D(x,z)\y
    EndIf   
    If Point3D(x,z)\z > maxz
      maxz = Point3D(x,z)\z
    EndIf
    If Point3D(x,z)\z < minz
      minz = Point3D(x,z)\z
    EndIf       
  Next 
  Next
  corx = (-maxx - minx) /2.0
  cory = (-maxy - miny) /2.0
  corz = (-maxz - minz) /2.0
  
  For z=0 To NbZ
    For x=0 To NbX
    Point3D(x,z)\x + corx
    Point3D(x,z)\y + cory
    Point3D(x,z)\z + corz     
  Next 
Next

EndProcedure