Author Topic: GL clipping  (Read 5688 times)

0 Members and 1 Guest are viewing this topic.

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
GL clipping
« on: April 04, 2007 »
right im working on a game right now that has lots of objects on the map the problem is though that after about fifty 3d objects i start to get really bad slow down so i need some sort of way of not sending opengl my objects as soon as they have falling out side the veiwing rect i thought this would have been easy enough and went something like this.

x = objxpos * halfscrx
y = objypos * halfscry

if x+objwidth < screenx or x-objwidth>screenx blah blah

but i was forgetting about the projection ie the edges of the veiwing rect 10 units in might be 2 or 3 so i was wondering if there is a way to unproject an object to test it against the borders of the screen.

cheers.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: GL clipping
« Reply #1 on: April 04, 2007 »
Most people use bounding cubes or bounding spheres to do this.  A bounding sphere is a sphere which just encloses the whole object.  If the sphere lies outside the view then don't print any of the polygons in the object.  What you then have to do is check the sphere against your view.  If your viewing angle is 90degrees, then any point where the x or y is > z is outside the view.
So, if your object is at (x,y,z) and has radius r then it's offscreen if
z<r - the object is behind the camera

x-r<-z - the object is off to the left
x+r<z - the object is off to the right
y-r<-z - the object is off to the bottom
y+r<z - the object is off to the top
That works for viewing angles of 90deg only, but it can be fixed up to work with any angle.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #2 on: April 04, 2007 »
cheers jim my game uses bounding boxes for collisions so ill just use those for boundary checking im currently using a 45 deg viewing    angle and i am not sure how to work this in.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: GL clipping
« Reply #3 on: April 04, 2007 »
I bet you mean 45degrees is half the viewing angle.  So 90 from left to right.  You can do the same check I put above for each point on a bounding box, if you want to use that instead of spheres.  If any point on the box is inside the view then you need to print the object.
This will all need some tweaking by the way.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #4 on: April 04, 2007 »
sorry jim i dont quite understand i have a 45 fov if i translate my object -10 into the screen then a simple bounding check against the clipping planes isnt going to be possible as the distance to the clipping planes change dippending on the object z position.

i need some way of incorporating the view angles and the objects z pos into the bounding checks.

cheers
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: GL clipping
« Reply #5 on: April 04, 2007 »
You compare x and y of the vertex with z of the same vertex.
Imagine a square-based pyramid with the apex point at 0,0,0 and the z axis running from the apex to the middle of the base.  This is your view volume.  Any (x,y,z) points inside that view volume have x and y coordinates less than their z coordinates.  Any points outside it have x or y coordinates bigger than z.  That's for 90degress.  Set your fov to 90 to try it out.
So all you need to do for any point you want to check to see if it's in or out of the view, subtract away the camera position and compare the x and y with z.  So
Code: [Select]
px,py,pz = point to check
cx,cy,cz = camera position

dx = px - cx
dy = py - cy
dz = py - cz

if (dx < -dz || dx > dz)
..outside

if (dy <-dz || dy > dz)
..outside

else
..inside

OpenGL doesn't provide any functions to retrieve the data after it's been through the modelview or the projection matrix.  So you're going to have to implement a matching rotation function which does the same as the gl_modelview.  You can grab the matrix code out of the pumpkin source if you like, and use glGetFloatv(GL_MODELVIEW_MATRIX) to retrieve the modelview matrix.  You can apply that matrix to a point to put it in camera space and then you can use the test above.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #6 on: April 05, 2007 »
ahh ok im with you now cheers jim.
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #7 on: April 05, 2007 »
i already have matrix math in the game my camera and object all have independent 4x4`s so does the matrix grabbing part go something like.

glloadidentity
rotatecameramatrix
translatecameramatrix
glloadmatrix(camera)

rotatemymatrix
gltranslatematrix
glmulmatrixd(object)
tempmatrix = glGetFloatv(GL_MODELVIEW_MATRIX)

does that look ok for that part.

now onto aplying a matrix onto a point is it the same as we do with our 2d engines something like this.

Code: [Select]
x = ( matrix(0,0) * x + matrix(0,1) * y + matrix(0,2) * z )   
y = ( matrix(1,0) * x + matrix(1,1) * y + matrix(1,2) * z )
z = ( matrix(2,0) * x + matrix(2,1) * y + matrix(2,2) * z )
         

« Last Edit: April 05, 2007 by ninogenio »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: GL clipping
« Reply #8 on: April 05, 2007 »
Since it's just a point, you only want the camera part of the matrix.
Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #9 on: April 05, 2007 »
right ive tryed to get this going but i think ive messed up the applying of the matrix onto the x,y,z of the object but im not sure.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: GL clipping
« Reply #10 on: April 05, 2007 »
No, you're really close actually.

The first problem is with GenioTransposeM(), the last 3 lines need to be negged, ie.
Code: [Select]
    object->matrix( m30 ) = -Tx
    object->matrix( m31 ) = -Ty
    object->matrix( m32 ) = -Tz
I hope that doesn't bugger up too much other stuff.  If it does, we can fix it later somewhere else.

Then the transformation you want to achieve is this one.
Matrix(3,...) is the camera position from the model matrix.  This is how I spotted the above problem.  If you don't want to change the transpose function, change it to minuses here.
Anyway, you need to take care the camera position before the rotation
Code: [Select]
Tmp1X = Cube->Position->X + Matrix(3,0)
Tmp1Y = Cube->Position->Y + Matrix(3,1)
Tmp1Z = Cube->Position->Z + Matrix(3,2)

      Tmp2X = ( Matrix(0,0) * Tmp1X + Matrix(0,1) * Tmp1Y + Matrix(0,2) * Tmp1Z )   
      Tmp2Y = ( Matrix(1,0) * Tmp1X + Matrix(1,1) * Tmp1Y + Matrix(1,2) * Tmp1Z )
      Tmp2Z = ( Matrix(2,0) * Tmp1X + Matrix(2,1) * Tmp1Y + Matrix(2,2) * Tmp1Z )

Then finally
Code: [Select]
Xvec = Tmp2X
Yvec = Tmp2Y
Zvec = -Tmp2Z
Z is negated because in OpenGL z is negative into the distance.  It pretty much works then.
Here's how I checked it
Code: [Select]
        If ( Xin And Yin ) Then
            DrawEntity( Cube )
OutputDebugString("In\n")
Else
OutputDebugString("Out\n")
        EndIf

    glDisable(GL_DEPTH_TEST)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glBegin(GL_POINTS)
glColor3f(1,0,0)
glVertex3f(Tmp2X, Tmp2Y, Tmp2Z)
glEnd()
    glEnable(GL_DEPTH_TEST)
What this does is draw an untransformed red dot (no zbuffer) so that I can see whether our rotation is indeed correct.  The red dot is always drawn over the centre of the square, so wahey!
I really encourage you (and everyone else) to learn to debug this way.  Visualising your data like this makes it far easier to find out wtf is wrong with complicated code.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #11 on: April 06, 2007 »
cool thanks jim!

negging the translation has only reversed my controlls around so it should be easy to fix.

i never thought about debugging that way but for sure ill be trying stuff like that from now. btw how do i see the output from outputdebugstring.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: GL clipping
« Reply #12 on: April 06, 2007 »
I use dbmon which is part of Visual Studio.  For me, that's located here
C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin\winnt
If you don't have VS, you can download dbmon replacements from lots of places.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #13 on: April 07, 2007 »
ive found a peculiar bug which i cant get fixed this works perfect if the object is inside camera space at start up but if i draw my object outside camera space i gant get it to appear even though my debug info says it should.

Code: [Select]
#include "GenioGl.Bi"



GenioGraphics( 800 , 600 , 32 , WINDOWED )



Type KeyTracker

      Key As Ubyte ptr

      Esckey as Uinteger
      Up As uinteger
      Down As Uinteger
      KLeft As Uinteger
      KRight As Uinteger
      Z As Uinteger

End Type


Declare     Sub     MoveCamera          ( Cam As GenioEntity PTR )
Declare     Sub     GenioCheckKeys      ( Keys As KeyTracker )

Dim     Shared  Camera   As     GenioEntity PTR
Dim     Shared  Key      As     KeyTracker
Dim     Shared  Cube     As     GenioEntity PTR

Cube = cube_mesh()
scale_entity( Cube , 0.5 , 0.5 , 0.5 )
set_entity_position( Cube , 20 , 0 , -10 )

camera = SetUpCamera

Dim Shared As Integer GenioLeftX = 1 , GenioRightX = 1 , GenioUpY = 1 , GenioDownY = 1

do
         Dim As Single TmpX , TmpY , TmpZ , Xvec , Yvec , Zvec

         GenioRender( Camera )
         GenioClear()
         GenioCheckKeys( Key )
       
         TmpX = ( Cube->Position->X - Camera->Matrix( m30 ) )
         TmpY = ( Cube->Position->Y - Camera->Matrix( m31 ) )
         TmpZ = ( Cube->Position->Z - Camera->Matrix( m32 ) )
       
         Print TmpX
         Print TmpY
         Print TmpZ
       
         Xvec = ( Camera->Matrix( m00 ) * TmpX + Camera->Matrix( m10 ) * TmpY + Camera->Matrix( m20 ) * TmpZ )   
         Yvec = ( Camera->Matrix( m01 ) * TmpX + Camera->Matrix( m11 ) * TmpY + Camera->Matrix( m21 ) * TmpZ )
         Zvec = -( Camera->Matrix( m02 ) * TmpX + Camera->Matrix( m12 ) * TmpY + Camera->Matrix( m22 ) * TmpZ )

         print xvec
         print yvec
         print zvec

         If ( Xvec <= -Zvec ) Then
               GenioLeftX = 0
         Else
               GenioLeftX = 1
         EndIf

         If ( Xvec >= Zvec ) Then
               GenioRightX = 0
         Else
               GenioRightX = 1
         EndIf

         If ( Yvec <= -Zvec ) Then
               GenioDownY = 0
         Else
               GenioDownY = 1
         EndIf

         If ( Yvec >= Zvec ) Then
               GenioUpY = 0
         Else
               GenioUpY = 1
         Endif

         If ( GenioLeftX And GenioRightX And GenioUpY And GenioDownY ) Then
               DrawEntity( Cube )
               glColor3f(0,1,0)
         Else
               glColor3f(1,0,0)
         EndIf

         glDisable(GL_DEPTH_TEST)
         glMatrixMode(GL_MODELVIEW)
         glLoadIdentity()
         glBegin(GL_POINTS)
               glVertex3f( 0 , 0 , -2 )
         glEnd()
         glEnable(GL_DEPTH_TEST)
         MoveCamera( Camera )

LOOP WHILE Key.esckey <> 1

DeleteCamera( Camera )
DestroyEntity( Cube )

SDL_Quit



SLEEP



sub GenioCheckKeys( Keys As KeyTracker )

      SDL_PumpEvents
      Keys.Key = SDL_GetKeyState(0)
      Keys.Esckey = Peek( Keys.Key + SDLK_ESCAPE )
      Keys.Up = peek( Keys.Key + SDLK_UP )
      Keys.Down = peek( Keys.Key + SDLK_DOWN )
      Keys.KLeft = peek( Keys.Key + SDLK_LEFT )
      Keys.KRight = peek( Keys.Key + SDLK_RIGHT )
      Keys.Z = peek( Keys.Key + SDLK_Z )

end sub



Sub MoveCamera( Cam As GenioEntity PTR )
         
    If Key.KLeft Then
            move_entity( Cam , -0.1 , 0 , 0 )
    ElseIf Key.KRight Then
            move_entity( Cam , 0.1 , 0 , 0 )
    EndIf
       
    If Key.Up Then
            move_entity( Cam , 0 , 0.1 , 0 )
    ElseIf Key.Down Then
            move_entity( Cam , 0 , -0.1 , 0 )
    EndIf
         
End Sub

<edit just went over this and in fact the only situation this works in is when my object is in the center of the veiw port when the object moves left or right by say 5 units the clipping planes move also>
« Last Edit: April 07, 2007 by ninogenio »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: GL clipping
« Reply #14 on: April 07, 2007 »
Why have you changed it from using the matrix you get from
        GLGETFLOATV( GL_MODELVIEW_MATRIX , @Matrix(0,0) )
to using the camera matrix?  Or have you changed GenioGL to store it away?

Here's my entire While loop after I'd finished (total mess, I left your stuff in there and added my own, but you can pick out the bits you need)
Code: [Select]
do
        Dim As Single Matrix( 0 To 3 , 0 To 3 )
        Dim As Single TmpX , TmpY , TmpZ , Xvec , Yvec , Zvec

        GenioRender( Camera )
        GenioClear()
        GenioCheckKeys( Key )

'        GLGETFLOATV( GL_MODELVIEW_MATRIX , @Matrix(0,0) )
glGetFloatv(GL_MODELVIEW_MATRIX, @Matrix(0,0))
       
        TmpX = ( Matrix(0,0) * Cube->Position->X + Matrix(0,1) * Cube->Position->Y + Matrix(0,2) * Cube->Position->Z )   
        TmpY = ( Matrix(1,0) * Cube->Position->X + Matrix(1,1) * Cube->Position->Y + Matrix(1,2) * Cube->Position->Z )
        TmpZ = ( Matrix(2,0) * Cube->Position->X + Matrix(2,1) * Cube->Position->Y + Matrix(2,2) * Cube->Position->Z )
       
       Xvec = TmpX - Camera->Position->X
        Yvec = TmpY - Camera->Position->Y
        Zvec = TmpZ - Camera->Position->Z

Dim as single Tmp1X,Tmp1Y,Tmp1Z,Tmp2X,Tmp2Y,Tmp2Z
Tmp1X = Cube->Position->X + Matrix(3,0)
Tmp1Y = Cube->Position->Y + Matrix(3,1)
Tmp1Z = Cube->Position->Z + Matrix(3,2)

      Tmp2X = ( Matrix(0,0) * Tmp1X + Matrix(0,1) * Tmp1Y + Matrix(0,2) * Tmp1Z )   
      Tmp2Y = ( Matrix(1,0) * Tmp1X + Matrix(1,1) * Tmp1Y + Matrix(1,2) * Tmp1Z )
      Tmp2Z = ( Matrix(2,0) * Tmp1X + Matrix(2,1) * Tmp1Y + Matrix(2,2) * Tmp1Z )

Xvec = Tmp2X
Yvec = Tmp2Y
Zvec = -Tmp2Z

        If ( Xvec < -Zvec Or Xvec > Zvec ) Then
            'Do Nothing
            Xin = 0
        Else
            Xin = 1
        EndIf

        If ( Yvec < -Zvec Or Yvec > Zvec ) Then
            'Do Nothing
            Yin = 0
        Else
            Yin = 1
        EndIf

        If ( Xin And Yin ) Then
            DrawEntity( Cube )
OutputDebugString("In"+Chr$(13)+Chr$(10))
Else
OutputDebugString("Out"+Chr$(13)+Chr$(10))
        EndIf

    glDisable(GL_DEPTH_TEST)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glBegin(GL_POINTS)
glColor3f(1,0,0)
glVertex3f(Tmp2X, Tmp2Y, Tmp2Z)
glEnd()
    glEnable(GL_DEPTH_TEST)

        MoveCamera( Camera )

LOOP WHILE Key.esckey <> 1

Jim
« Last Edit: April 07, 2007 by Jim »
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #15 on: April 07, 2007 »
ahha so its object + matrix

Code: [Select]
Tmp1X = Cube->Position->X + Matrix(3,0)
Tmp1Y = Cube->Position->Y + Matrix(3,1)
Tmp1Z = Cube->Position->Z + Matrix(3,2)

this works properly for me.

i dont think i need to get gl to retrieve the model veiw matrix as its just retreving my transposed camera matrix that i just loaded. ive tested it and it still seems to work so im sure thats the case.

cheers jim.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: GL clipping
« Reply #16 on: April 07, 2007 »
In this case, it's object + matrix because the camera position in the camera matrix is -ve (you're adding on a -ve number).
ie.
a + -5 = a - 5

You're right, the camera matrix you generate will be just fine.

In general, if you want to rotate something around something else (like this point around the camera) you have to subtract away the origin of the rotation (the point you're rotating about - in this case the camera) from the position of the object you want to rotate.  Then you can apply the rotation.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: GL clipping
« Reply #17 on: April 08, 2007 »
yeah i forgot i had negged the translation of the camera lol.

ive spent a good couple of hours trying to figure out where i had buggerd it up aswell!

thanks for the help jim and it really has made a diffrence in my game i recon ill get about 10x the amount of badguys into my level now.
Challenge Trophies Won: