Trackball Camera for OpenGLGadget()

Everything related to 3D programming
User avatar
StarBootics
Addict
Addict
Posts: 984
Joined: Sun Jul 07, 2013 11:35 am
Location: Canada

Trackball Camera for OpenGLGadget()

Post by StarBootics »

Hello everyone,

I would to say this a 100% working trackball camera but it's not the case. From time to time the rotation stop event if the mouse left button is hold down. I don't understand why, if someone find a solution let me know.

Edit 1 : Thanks to Demivec for the hint about #PB_OpenGL_WheelDelta, now the zoom function work fine.
I have also deleted my Feature request since it was complete useless. (I should learn how to read :oops: )

Edit 2 : Some optimization, renaming IncrementDistance() --> Zooming(), removing unused procedures.

Edit 3 : Change the far value for gluPerspective_() the cube no longer disappear behind the camera far plane

Best regards
StarBootics

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project name : Trackball Camera for OpenGLGadget()
; File Name : Camera - Module.pb
; File version: 0.9.9
; Programming : OK +/-
; Programmed by : StarBootics
; Date : 29-05-2016
; Last Update : 29-05-2016
; PureBasic code : V5.42 LTS
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;
; This code is free to be use where ever you like
; but you use it at your own risk.
;
; The author can in no way be held responsible
; for data loss, damage or other annoying
; situations that may occur.
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

DeclareModule Camera
 
  Declare.d GetMotionSensitivity()
  Declare.d GetScrollSensitivity()
  Declare.d GetDistance()
  Declare.d GetMinDistance()
  Declare SetMotionSensitivity(P_MotionSensitivity.d)
  Declare SetScrollSensitivity(P_ScrollSensitivity.d)
  Declare SetDistance(P_Distance.d)
  Declare SetMinDistance(P_MinDistance.d)
  Declare Initialize()
  Declare Reset()
  Declare PerspectiveView()
  Declare FrontView()
  Declare BackView()
  Declare RightView()
  Declare LeftView()
  Declare TopView()
  Declare BottomView()
  Declare TrackBallLookAt()
  Declare Zooming(P_Direction.d)
  Declare StartRotation(P_x.l, P_y.l)
  Declare StopRotation()
  Declare TrackRotation(P_x.l, P_y.l)
 
EndDeclareModule

Module Camera
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Déclaration de la Structure <<<<<
 
  Structure Instance
   
    MotionSensitivity.d
    ScrollSensitivity.d
    Distance.d
    MinDistance.d
    RotationX.d
    RotationY.d
    MouseLeftButtonHold.b
    MouseX.l
    MouseY.l
   
  EndStructure
 
  Global Instance.Instance
 
  Procedure.f WrapAngleDeg(angle.f)
   
    ; <- wraps a value into [0,360) fringe
   
    ; Author : Psychophanta
   
    !fild dword[@f] ; <- now i have 360 into st0
    !fld dword[p.v_angle]
    !fprem
    !fadd st1,st0
    !fldz
    !fcomip st1
    !fcmovnbe st0,st1
    !fstp st1
    ProcedureReturn
    !@@:dd 360
  EndProcedure
 
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Les observateurs <<<<<
 
  Procedure.d GetMotionSensitivity()
   
    ProcedureReturn Instance\MotionSensitivity
  EndProcedure
 
  Procedure.d GetScrollSensitivity()
   
    ProcedureReturn Instance\ScrollSensitivity
  EndProcedure
 
  Procedure.d GetDistance()
   
    ProcedureReturn Instance\Distance
  EndProcedure
 
  Procedure.d GetMinDistance()
   
    ProcedureReturn Instance\MinDistance
  EndProcedure
 
  Procedure.d GetRotationX()
   
    ProcedureReturn Instance\RotationX
  EndProcedure
 
  Procedure.d GetRotationY()
   
    ProcedureReturn Instance\RotationY
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Les mutateurs <<<<<
 
  Procedure SetMotionSensitivity(P_MotionSensitivity.d)
   
    Instance\MotionSensitivity = P_MotionSensitivity
   
  EndProcedure
 
  Procedure SetScrollSensitivity(P_ScrollSensitivity.d)
   
    Instance\ScrollSensitivity = P_ScrollSensitivity
   
  EndProcedure
 
  Procedure SetDistance(P_Distance.d)
   
    Instance\Distance = P_Distance
   
  EndProcedure
 
  Procedure SetMinDistance(P_MinDistance.d)
   
    Instance\MinDistance = P_MinDistance
   
  EndProcedure
 
  Procedure SetRotationX(P_RotationX.d)
   
    Instance\RotationX = P_RotationX
   
  EndProcedure
 
  Procedure SetRotationY(P_RotationY.d)
   
    Instance\RotationY = P_RotationY
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< L'opérateur Initialize <<<<<
 
  Procedure Initialize()
   
    Instance\MotionSensitivity = 1.75
    Instance\ScrollSensitivity = 1.0
    Instance\Distance = 10.0
    Instance\MinDistance = 0.1
    Instance\RotationX = 30.0
    Instance\RotationY = -45.0
    Instance\MouseLeftButtonHold = 0
    Instance\MouseX = 0
    Instance\MouseY = 0
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< L'opérateur Reset <<<<<
 
  Procedure Reset()
   
    Instance\MotionSensitivity = 0.0
    Instance\ScrollSensitivity = 0.0
    Instance\Distance = 0.0
    Instance\MinDistance = 0.0
    Instance\RotationX = 0.0
    Instance\RotationY = 0.0
    Instance\MouseLeftButtonHold = 0
    Instance\MouseX = 0
    Instance\MouseY = 0
   
  EndProcedure
 
  Procedure PerspectiveView()
   
    Instance\RotationX = 30.0
    Instance\RotationY = -45.0
   
  EndProcedure
 
  Procedure FrontView()
   
    Instance\RotationX = 0.0
    Instance\RotationY = 0.0
   
  EndProcedure
 
  Procedure BackView()
   
    Instance\RotationX = 180.0
    Instance\RotationY = 0.0
   
  EndProcedure
 
  Procedure RightView()
   
    Instance\RotationX = 0.0
    Instance\RotationY = -90.0
   
  EndProcedure
 
  Procedure LeftView()
   
    Instance\RotationX = 0.0
    Instance\RotationY = 90.0
   
  EndProcedure
 
  Procedure TopView()
   
    Instance\RotationX = 90.0
    Instance\RotationY = 0.0
   
  EndProcedure
 
  Procedure BottomView()
   
    Instance\RotationX = -90.0
    Instance\RotationY = 0.0
   
  EndProcedure
 
  Procedure TrackBallLookAt()
   
    ;glMatrixMode(#GL_MODELVIEW)
    glLoadIdentity_()
    ; // la caméra regarde le centre (0,0,0) et est sur l'axe Z à une certaine distance du centre donc (0,0, distance)
    gluLookAt_(0, 0, Instance\Distance, 0, 0, 0, 0, 1, 0)
    glRotated_(Instance\RotationX, 1, 0, 0); //la scène est tournée autour de l'axe X
    glRotated_(Instance\RotationY, 0, 1, 0); //la scène est tournée autour de l'axe Y
   
  EndProcedure
 
  Procedure Zooming(P_Direction.d)
   
    Instance\Distance = Instance\Distance + P_Direction * Instance\ScrollSensitivity
   
    If Instance\Distance < Instance\MinDistance
      Instance\Distance = Instance\MinDistance
    EndIf
   
  EndProcedure
 
  Procedure StartRotation(P_x.l, P_y.l)
   
    Instance\MouseLeftButtonHold = #True
    Instance\MouseX = P_x
    Instance\MouseY = P_y
   
  EndProcedure
 
  Procedure StopRotation()
   
    Instance\MouseLeftButtonHold = #False
   
  EndProcedure
 
  Procedure TrackRotation(P_x.l, P_y.l)
   
    If Instance\MouseLeftButtonHold = #True
      Instance\RotationX = WrapAngleDeg(Instance\RotationX + Sign(P_y - Instance\MouseY) * Instance\MotionSensitivity)
      Instance\RotationY = WrapAngleDeg(Instance\RotationY + Sign(P_x - Instance\MouseX) * Instance\MotionSensitivity)
      Instance\MouseX = P_x
      Instance\MouseY = P_y
    EndIf
   
  EndProcedure
 
EndModule

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code généré en : 00.001 secondes (109000.00 lignes/seconde) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

CompilerIf #PB_Compiler_IsMainFile
 
 
  ; Global RollAxisX.f
  ; Global RollAxisY.f
  ; Global RollAxisZ.f
  ;
  ; Global RotateSpeedX.f = 1.0
  ; Global RotateSpeedY.f
  ; Global RotateSpeedZ.f = 1.0
  ;
  ; Global ZoomFactor.f = 1.0 ; Distance of the camera. Negative value = zoom back
 
  Procedure DrawCube(Gadget)
   
    SetGadgetAttribute(Gadget, #PB_OpenGL_SetContext, #True)
    Camera::TrackBallLookAt()
   
    glPushMatrix_()                  ; Save the original Matrix coordinates
    glMatrixMode_(#GL_MODELVIEW)
   
    ;   glTranslatef_(0, 0, ZoomFactor)  ;  move it forward a bit
    ;
    ;   glRotatef_ (RollAxisX, 1.0, 0, 0) ; rotate around X axis
    ;   glRotatef_ (RollAxisY, 0, 1.0, 0) ; rotate around Y axis
    ;   glRotatef_ (RollAxisZ, 0, 0, 1.0) ; rotate around Z axis
    ; 
    ;   RollAxisX + RotateSpeedX
    ;   RollAxisY + RotateSpeedY
    ;   RollAxisZ + RotateSpeedZ
   
    ; clear framebuffer And depth-buffer
   
    glClear_ (#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
   
    ; draw the faces of a cube
   
    ; draw colored faces
   
    glDisable_(#GL_LIGHTING)
    glBegin_  (#GL_QUADS)
   
    ; Build a face, composed of 4 vertex !
    ; glBegin() specify how the vertexes are considered. Here a group of
    ; 4 vertexes (GL_QUADS) form a rectangular surface.
   
    ; Now, the color stuff: It's r,v,b but with float values which
    ; can go from 0.0 To 1.0 (0 is .. zero And 1.0 is full intensity)
   
    glNormal3f_ (0,0,1.0)
    glColor3f_  (0,0,1.0)
    glVertex3f_ (0.5,0.5,0.5)   
    glColor3f_  (0,1.0,1.0)         
    glVertex3f_ (-0.5,0.5,0.5)
    glColor3f_  (1.0,1.0,1.0)
    glVertex3f_ (-0.5,-0.5,0.5)
    glColor3f_  (0,0,0)
    glVertex3f_ (0.5,-0.5,0.5)
   
    ; The other face is the same than the previous one
    ; except the colour which is nice blue To white gradiant
   
    glNormal3f_ (0,0,-1.0)
    glColor3f_  (0,0,1.0)
    glVertex3f_ (-0.5,-0.5,-0.5)
    glColor3f_  (0,0,1.0)
    glVertex3f_ (-0.5,0.5,-0.5)
    glColor3f_  (1.0,1.0,1.0)
    glVertex3f_ (0.5,0.5,-0.5)
    glColor3f_  (1.0,1.0,1.0)
    glVertex3f_ (0.5,-0.5,-0.5)
   
    glEnd_()
   
    ; draw shaded faces
   
    glEnable_(#GL_LIGHTING)
    glEnable_(#GL_LIGHT0)
    glBegin_ (#GL_QUADS)
   
    glNormal3f_ (   0, 1.0,   0)
    glVertex3f_ ( 0.5, 0.5, 0.5)
    glVertex3f_ ( 0.5, 0.5,-0.5)
    glVertex3f_ (-0.5, 0.5,-0.5)
    glVertex3f_ (-0.5, 0.5, 0.5)
   
    glNormal3f_ (0,-1.0,0)
    glVertex3f_ (-0.5,-0.5,-0.5)
    glVertex3f_ (0.5,-0.5,-0.5)
    glVertex3f_ (0.5,-0.5,0.5)
    glVertex3f_ (-0.5,-0.5,0.5)
   
    glNormal3f_ (1.0,0,0)
    glVertex3f_ (0.5,0.5,0.5)
    glVertex3f_ (0.5,-0.5,0.5)
    glVertex3f_ (0.5,-0.5,-0.5)
    glVertex3f_ (0.5,0.5,-0.5)
   
    glNormal3f_ (-1.0,   0,   0)
    glVertex3f_ (-0.5,-0.5,-0.5)
    glVertex3f_ (-0.5,-0.5, 0.5)
    glVertex3f_ (-0.5, 0.5, 0.5)
    glVertex3f_ (-0.5, 0.5,-0.5)
   
    glEnd_()
   
    glPopMatrix_()
    glFinish_()
   
    SetGadgetAttribute(Gadget, #PB_OpenGL_FlipBuffers, #True)
  EndProcedure
 
 
  Procedure SetupGL(Width, Height)
   
    glMatrixMode_(#GL_PROJECTION)
    gluPerspective_(45.0, Width/Height, 1.0, 500.0)
   
    ; position viewer
    glMatrixMode_(#GL_MODELVIEW)
   
    glTranslatef_(0, 0, -5.0)
   
    glEnable_(#GL_DEPTH_TEST)   ; Enabled, it slowdown a lot the rendering. It's to be sure than the
                                ; rendered objects are inside the z-buffer.
   
    glEnable_(#GL_CULL_FACE)    ; This will enhance the rendering speed as all the back face will be
                                ; ignored. This works only with CLOSED objects like a cube... Singles
                                ; planes surfaces will be visibles only on one side.
   
    glShadeModel_(#GL_SMOOTH)
  EndProcedure
 
 
  Procedure HandleError (Result, Text$)
    If Result = 0
      MessageRequester("Error", Text$, 0)
      End
    EndIf
  EndProcedure
 
 
  Procedure Reshape()
   
    ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0)-10, WindowHeight(0)-10)
   
    SetGadgetAttribute(0, #PB_OpenGL_SetContext, #True)
    glViewport_(0,0, GadgetWidth(0), GadgetHeight(0))
    glMatrixMode_(#GL_PROJECTION)
    glLoadIdentity_()
    gluPerspective_(30.0, GadgetWidth(0)/GadgetHeight(0), 1.0, 500.0)
    glMatrixMode_(#GL_MODELVIEW)
   
  EndProcedure
 
 
  OpenWindow(0, 0, 0, 800, 600, "OpenGL Gadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
 
  OpenGLGadget(0, 5, 5, 790, 590, #PB_OpenGL_Keyboard)
  SetupGL(790, 590)
  Camera::Initialize()
  Camera::TrackBallLookAt()
  AddWindowTimer(0, 1, 16) ; about 60 fps
 
  Repeat
    Event = WaitWindowEvent()
   
    Select Event
       
      Case #PB_Event_SizeWindow
        Reshape()
       
      Case #PB_Event_Timer
        If EventTimer() = 1
          DrawCube(0)
        EndIf
       
      Case #PB_Event_Gadget
       
        Select EventGadget()
           
          Case 0
           
            Select EventType()
               
              Case #PB_EventType_MouseWheel
                Camera::Zooming(GetGadgetAttribute(0, #PB_OpenGL_WheelDelta)) ;use the wheel delta to drive the zoom
               
              Case #PB_EventType_LeftButtonDown
                Camera::StartRotation(GetGadgetAttribute(0, #PB_OpenGL_MouseX), GetGadgetAttribute(0, #PB_OpenGL_MouseY))
               
              Case #PB_EventType_LeftButtonUp
                Camera::StopRotation()
               
              Case #PB_EventType_MouseMove
                Camera::TrackRotation(GetGadgetAttribute(0, #PB_OpenGL_MouseX), GetGadgetAttribute(0, #PB_OpenGL_MouseY))
               
            EndSelect
           
        EndSelect
       
    EndSelect
   
  Until Event = #PB_Event_CloseWindow
 
CompilerEndIf

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Last edited by StarBootics on Thu Jun 09, 2016 6:45 pm, edited 6 times in total.
The Stone Age did not end due to a shortage of stones !
User avatar
Demivec
Addict
Addict
Posts: 4086
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Trackball Camera for OpenGLGadget()

Post by Demivec »

StarBootics wrote:I would to say this a 100% working trackball camera but it's not the case. See me Feature Request here : http://www.purebasic.fr/english/viewtop ... =3&t=65824
Make these changes

Code: Select all

OpenGLGadget(0, 5, 5, 790, 590, #PB_OpenGL_Keyboard) ;declare with this flag for mouse wheel events

;in event loop use
Select EventType()
   Case #PB_EventType_MouseWheel 
      Camera::IncrementDistance(GetGadgetAttribute(0, #PB_OpenGL_WheelDelta)) ;use the wheel delta to drive the zoom
User avatar
Demivec
Addict
Addict
Posts: 4086
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Trackball Camera for OpenGLGadget()

Post by Demivec »

As an addendum to my previous post, from what I understand, the flag #PB_OpenGL_Keyboard is only needed for the Windows OS. The other OS's should report the wheel events even without focus.
User avatar
StarBootics
Addict
Addict
Posts: 984
Joined: Sun Jul 07, 2013 11:35 am
Location: Canada

Re: Trackball Camera for OpenGLGadget()

Post by StarBootics »

Hello everyone,

Is anybody have a continuous rotation of the camera ?

For me, it work, stop working, after several tries work again, out of the sudden stop working again. Very buggy under Ubuntu Gnome 16.04.

What about you guys ?

Best regards
StarBootics
The Stone Age did not end due to a shortage of stones !
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Trackball Camera for OpenGLGadget()

Post by #NULL »

i can rotate without problem until i release the mouse button, if that's what you mean. (windows 7, pb 5.42)
User avatar
StarBootics
Addict
Addict
Posts: 984
Joined: Sun Jul 07, 2013 11:35 am
Location: Canada

Re: Trackball Camera for OpenGLGadget()

Post by StarBootics »

#NULL wrote:i can rotate without problem until i release the mouse button, if that's what you mean. (windows 7, pb 5.42)
It work as expected under window.
Buggy under Ubuntu Gnome 16.04
Under Mac OS ???

Thanks for your reply
StarBootics
The Stone Age did not end due to a shortage of stones !
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Trackball Camera for OpenGLGadget()

Post by IdeasVacuum »

Windows 7 x86 PB 5.42LTS OpenGL 2.1.2 (old) Graphics Card: GeForce 7900 GT (old) Intel Core 2 CPU 6400 (old)

Both zoom and drag rotate work perfectly on my machine, despite it's age. Perhaps the problems in Ubuntu are Ubuntu settings?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Trackball Camera for OpenGLGadget()

Post by IdeasVacuum »

This Module works beautifully in an OpenGL gadget. Has anyone written the same for a Windowed Screen?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Post Reply