Open GL 3D Engine

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Open GL 3D Engine

Post by BackupUser »

Restored from previous forum. Originally posted by LJ.

Code: Select all

; OpenGL 3D Engine
; Based on NeHe Lesson 6 OpenGL Texture Tutorial
; by Lance Jepsen
; Instructions: Use arrow keys to move around

IncludeFile "OpenGL.pbi"

Global texture
Global rquad.f
Global zoom.f
Global turn.f

zoom = -7.0
turn = 0.0

Procedure _CreateTexture(pData.l, mode.s, mipmapping.b, bmpWidth.l, bmpHeight.l)

  If pData = 0
    MessageBox_(0, "unable to load texture", ":PBglLib", #MB_OK | #MB_ICONERROR)
  Else

  glGenTextures_(1, @texture)
  glBindTexture_(#GL_TEXTURE_2D, texture)
  glTexEnvi_(#GL_TEXTURE_ENV, #GL_TEXTURE_ENV_MODE, #GL_MODULATE)       ; Texture blends with object background
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)  ; only first two can be used
  
  If mipmapping = 1
    glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR_MIPMAP_LINEAR)  ; all of the above can be used
  Else
    glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)  ; all of the above can be used
  EndIf

  Select mode
    Case LCase("rgb")
      If mipmapping = 1
        gluBuild2DMipmaps_(#GL_TEXTURE_2D, #GL_RGB, bmpWidth, bmpHeight, #GL_RGB, #GL_UNSIGNED_BYTE, pData):
      Else
        glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGB, bmpWidth, bmpHeight, 0, #GL_RGB, #GL_UNSIGNED_BYTE, pData)   ; Use when not wanting mipmaps to be built by openGL
      EndIf
    
    Case LCase("rgba")
      If mipmapping = 1
        gluBuild2DMipmaps_(#GL_TEXTURE_2D, #GL_RGBA, bmpWidth, bmpHeight, #GL_RGBA, #GL_UNSIGNED_BYTE, pData)   ;
      Else
        glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGBA, bmpWidth, bmpHeight, 0, #GL_RGBA, #GL_UNSIGNED_BYTE, pData)   ; Use when not wanting mipmaps to be built by openGL
      EndIf

    Case LCase("luminance")
      If mipmapping = 1
        gluBuild2DMipmaps_(#GL_TEXTURE_2D, #GL_LUMINANCE, bmpWidth, bmpHeight, #GL_LUMINANCE, #GL_UNSIGNED_BYTE, pData)
      Else
        glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_LUMINANCE, bmpWidth, bmpHeight, 0, #GL_LUMINANCE, #GL_UNSIGNED_BYTE, pData)   ; Use when not wanting mipmaps to be built by openGL
      EndIf
      
  EndSelect

  EndIf

  ProcedureReturn texture
EndProcedure
;
; load BMPs from memory-locations (IncludeBinary)
; loads 8, 16 and 24bit bmps
;
Procedure loadBMPTextureMem(memloc.l, mode.s, mipmapping.b)
  FileHeader.BITMAPFILEHEADER
  InfoHeader.BITMAPINFOHEADER

  ; read the bitmap file header
  FileHeader\bfType                 = PeekW(memloc +0) ;2
  FileHeader\bfSize                 = PeekL(memloc +2) ;4
  FileHeader\bfReserved1            = PeekW(memloc +6) ;2
  FileHeader\bfReserved2            = PeekW(memloc +  ;2
  FileHeader\bfOffBits              = PeekL(memloc+10) ;4

  ; check if it's a valid bmp-file
  If FileHeader\bfType  $4D42
    ; MessageBox_(0, "invalid bmpfile @"+Str(memlocation), ":PBglLib", #MB_OK)
    ProcedureReturn 0
  EndIf

  ; read the bitmap information header
  InfoHeader\biSize          = PeekL(memloc+14) ;4
  InfoHeader\biWidth         = PeekL(memloc+1  ;4
  InfoHeader\biHeight        = PeekL(memloc+22) ;4
  InfoHeader\biPlanes        = PeekW(memloc+26) ;2
  InfoHeader\biBitCount      = PeekW(memloc+2  ;2
  InfoHeader\biCompression   = PeekL(memloc+30) ;4
  InfoHeader\biSizeImage     = PeekL(memloc+34) ;4
  InfoHeader\biXPelsPerMeter = PeekL(memloc+3  ;4
  InfoHeader\biYPelsPerMeter = PeekL(memloc+42) ;4
  InfoHeader\biClrUsed       = PeekL(memloc+46) ;4
  InfoHeader\biClrImportant  = PeekL(memloc+50) ;4

  If InfoHeader\biSizeImage = 0
    InfoHeader\biSizeImage = (InfoHeader\biWidth * InfoHeader\biHeight * InfoHeader\biBitCount /  
  EndIf

; allocate enough mem to store the bitmap
;  Dim bitmapImage.b (InfoHeader\biSizeImage)
AllocateMemory(0, InfoHeader\biSizeImage+2, 0)

  ; read in the bitmap image data
For i.l=FileHeader\bfOffBits To InfoHeader\biSizeImage
   CopyMemory(memloc+i, UseMemory(0)+i2, 1)
   i2.l+1
Next

If InfoHeader\biBitCount>8
    ; swap BGR to RGB
    AllocateMemory(1,1,0)
    
    For i.l=0 To InfoHeader\biSizeImage Step 3
      CopyMemory(UseMemory(0)+i, UseMemory(1), 1)
      CopyMemory(UseMemory(0)+i+2, UseMemory(0)+i, 1)
      CopyMemory(UseMemory(1), UseMemory(0)+i+2, 1)
    Next

EndIf 

; create texture
  texture = _CreateTexture(UseMemory(0), mode.s, mipmapping.b, InfoHeader\biWidth, InfoHeader\biHeight)

; cleanup
FreeMemory(0)

  ProcedureReturn texture
EndProcedure

Procedure InitGL()
glClearColor_(0.0, 0.0, 0.0, 0.0)
glDepthFunc_(#GL_LESS)
glEnable_(#GL_DEPTH_TEST)
glEnable_(#GL_TEXTURE_2D);
glShadeModel_(#GL_SMOOTH)
glMatrixMode_(#GL_PROJECTION)
glLoadIdentity_()
gluPerspectivef_(45.0, 640/480, 0.1, 100.0)
glMatrixMode_(#GL_MODELVIEW)
EndProcedure

Procedure DrawScene(hDC)
glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
glLoadIdentity_();
glTranslatef_(turn,0.0, zoom);			// Move Right And Into The Screen
glRotatef_(rquad,1.0,1.0,1.0);		// Rotate The Cube On X, Y & Z
glBindTexture_(#GL_TEXTURE_2D, texture);
glBegin_(#GL_QUADS);
 ; // Front Face
  glTexCoord2f_(0.0, 0.0): glVertex3f_(-1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
  glTexCoord2f_(1.0, 0.0): glVertex3f_( 1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
  glTexCoord2f_(1.0, 1.0): glVertex3f_( 1.0,  1.0,  1.0);	// Top Right Of The Texture and Quad
  glTexCoord2f_(0.0, 1.0): glVertex3f_(-1.0,  1.0,  1.0);	// Top Left Of The Texture and Quad
  ;// Back Face
  glTexCoord2f_(1.0, 0.0): glVertex3f_(-1.0, -1.0, -1.0);	// Bottom Right Of The Texture and Quad
  glTexCoord2f_(1.0, 1.0): glVertex3f_(-1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
  glTexCoord2f_(0.0, 1.0): glVertex3f_( 1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
  glTexCoord2f_(0.0, 0.0): glVertex3f_( 1.0, -1.0, -1.0);	// Bottom Left Of The Texture and Quad
  ;// Top Face
  glTexCoord2f_(0.0, 1.0): glVertex3f_(-1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
  glTexCoord2f_(0.0, 0.0): glVertex3f_(-1.0,  1.0,  1.0);	// Bottom Left Of The Texture and Quad
  glTexCoord2f_(1.0, 0.0): glVertex3f_( 1.0,  1.0,  1.0);	// Bottom Right Of The Texture and Quad
  glTexCoord2f_(1.0, 1.0): glVertex3f_( 1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
  ;// Bottom Face
  glTexCoord2f_(1.0, 1.0): glVertex3f_(-1.0, -1.0, -1.0);	// Top Right Of The Texture and Quad
  glTexCoord2f_(0.0, 1.0): glVertex3f_( 1.0, -1.0, -1.0);	// Top Left Of The Texture and Quad
  glTexCoord2f_(0.0, 0.0): glVertex3f_( 1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
  glTexCoord2f_(1.0, 0.0): glVertex3f_(-1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
  ;// Right face
  glTexCoord2f_(1.0, 0.0): glVertex3f_( 1.0, -1.0, -1.0);	// Bottom Right Of The Texture and Quad
  glTexCoord2f_(1.0, 1.0): glVertex3f_( 1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
  glTexCoord2f_(0.0, 1.0): glVertex3f_( 1.0,  1.0,  1.0);	// Top Left Of The Texture and Quad
  glTexCoord2f_(0.0, 0.0): glVertex3f_( 1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
  ;// Left Face
  glTexCoord2f_(0.0, 0.0): glVertex3f_(-1.0, -1.0, -1.0);	// Bottom Left Of The Texture and Quad
  glTexCoord2f_(1.0, 0.0): glVertex3f_(-1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
  glTexCoord2f_(1.0, 1.0): glVertex3f_(-1.0,  1.0,  1.0);	// Top Right Of The Texture and Quad
  glTexCoord2f_(0.0, 1.0): glVertex3f_(-1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
 glEnd_();

rquad = rquad - 0.75;			// Decrease The Rotation Variable For The Quad 

EndProcedure

pfd.PIXELFORMATDESCRIPTOR
hWnd = OpenWindow(0, 0, 0, 800, 580, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "NeHe OpenGL Lesson 6")
hdc = GetDC_(hWnd)
pfd\nSize        = SizeOf(PIXELFORMATDESCRIPTOR)
pfd\nVersion     = 1
pfd\dwFlags      = #PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER | #PFD_DRAW_TO_WINDOW
pfd\iLayerType  = #PFD_MAIN_PLANE
pfd\iPixelType   = #PFD_TYPE_RGBA
pfd\cColorBits   = 24
pfd\cDepthBits   = 16   

pixformat = ChoosePixelFormat_(hdc, pfd)
SetPixelFormat_(hdc, pixformat, pfd)
hrc = wglCreateContext_(hdc)
wglMakeCurrent_(hdc,hrc)

InitGL()

texture = LoadBMPTextureMem(?texlabel, "rgb", 0)
AddKeyboardShortcut(0, #PB_Shortcut_Up, 1)
AddKeyboardShortcut(0, #PB_Shortcut_Down, 2)
AddKeyboardShortcut(0, #PB_Shortcut_Left, 3)
AddKeyboardShortcut(0, #PB_Shortcut_Right, 4)

Repeat
  EventID = WindowEvent()
    If EventID = #PB_EventMenu
      Select EventMenuID()
        
        Case 1
        zoom = zoom + 0.2
        
        Case 2
        zoom = zoom - 0.2
        
        Case 3
        turn = turn - 0.2
        
        Case 4
        turn = turn + 0.2
        
    EndSelect
  EndIf
  
  DrawScene(hDC)
  SwapBuffers_(hDC)

Until EventID=#PB_EventCloseWindow
End


texlabel:
IncludeBinary "NeHe.bmp"
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by LJ.

3D OpenGL engine compiles to a 13K .exe
With NeHe.bmp, 208K .exe

Needs NeHe.bmp texture to run. Get NeHe.bmp at:
http://www.acethemsat.com/NeHe.bmp
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.

Sorry LJ, nothing to see :cry:
OS: w2000 sp3
Graphic: Matrox G400 32MB

I have also problems with some examples posted some days ago...

BTW: would be nice to have a 3D Engine for technical purposes (serious CAD/EDA stuff).
OGRE is only good for games. There are no commands for 3D lines, 3D circles, 3D ellipses, 3D splines etc.


Have a nice day...

Franco
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by MAGI.

:)
BTW: would be nice to have a 3D Engine for technical purposes (serious CAD/EDA stuff).
Add my vote to that.

Marc
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by raphael.
Originally posted by Franco

Sorry LJ, nothing to see :cry:
i also don't see anything. it works fine, if you change
the 'gluPerspectivef_(45.0, 640/480, 0.1, 100.0)'
to 'gluPerspective(45.0, 640/480, 0.1, 100.0)' - using traumatics 'glwrapper-lib' (link posted in another thread).
seems like the other lib doesn't work correctly.

btw. where's the engine? :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by LJ.

You need the GLUT32F file. I think you can get this on the PB resource site. This is why I don't like using user libraries, for exchanging code it's a real pain. We should keep the OpenGL as pure as possible.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by raphael.
You need the GLUT32F file.
i have it. that's why i can say it doesn't work. otherwise i would get an error about unknown command or something...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by raphael.
Originally posted by LJ
We should keep the OpenGL as pure as possible.
this isnt' possible as purebasic doesn't support doubles that some ogl-commands require
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.
Originally posted by raphael
Originally posted by Franco

Sorry LJ, nothing to see :cry:
i also don't see anything. it works fine, if you change
the 'gluPerspectivef_(45.0, 640/480, 0.1, 100.0)'
to 'gluPerspective(45.0, 640/480, 0.1, 100.0)' - using traumatics 'glwrapper-lib' (link posted in another thread).
seems like the other lib doesn't work correctly.

btw. where's the engine? :)
Thanks Raphael your changes work fine :)

Have a nice day...

Franco
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.
Originally posted by raphael
You need the GLUT32F file.
i have it. that's why i can say it doesn't work. otherwise i would get an error about unknown command or something...
Same here no error message.
But I have a LIB named glu32f with the size 4474 bytes dated June 28 2002.
(And not a glut32f...)

Have a nice day...

Franco
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by LJ.

Good. Glad you guys got it working.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.

Under WinXP there is a strange behaviour:
After starting the code (compiled or as exe) there is no button in the taskbar.
But after 5 seconds one button will show up - strange isn't it ?

Also the cpu usage is always 100%. How can it be reduced to normal level :)
A Delay command in the event loop changes nothing.

Also strange: with this code I can't change the code to use the OGLContext library...
(as with the OpenGL_Pyramid code)

Have a nice day...

Franco
Post Reply