Points inside an ellipse, in PB terrain, and in OpenGL
Posted: Thu Oct 09, 2014 2:45 pm
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.

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
*************************************************************************************************
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:
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:

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

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++
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.

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:
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:

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

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