3D game on windows/linux | OpenGL hardware acceleration

Started by refrainrence, November 08, 2013, 09:54:00 AM

Previous topic - Next topic

refrainrence

I want to create a not too sophisticated but a real, playable 3D game in newlisp to run on win7 and linux.

I cannot get past firing up the teapot demo found here: http://www.newlisp.org/syntax.cgi?downloads/OpenGL/opengl-demo-ffi-lsp.txt">//http://www.newlisp.org/syntax.cgi?downloads/OpenGL/opengl-demo-ffi-lsp.txt.


(println (get-string (glGetString (| GL_VENDOR GL_RENDERER))))


gives me output similar to 'Windows Mesa DRI rendering'  on windows 7 while on slack 14 i get desired 'R300 ......' string. I assume this means i cannot have hardware rendering in win7. I think i must have it to develop a real 3D game, not just a proof of concept.



I tried to import glGetString from opengl32.dll shared library inside c:windowssystem32 dir but it returns 'problem loading library in function import...'

Why opengl32.dll from http://www.turtle.dds.nl/gl4newlisp/">http://www.turtle.dds.nl/gl4newlisp/ works, but dll provided by windows doesn't?

I also tried importing glfw3.dll function glfwInit but also ended receiving 'problem loading...' provided this dll file was copied into same dir.



I don't have a knowledge about ffi to even figure out how properly use glfw. I just thought i write an import in newlisp and it would work.



Please help, how to get opengl hardware rendering on windows 7 in newlisp?

refrainrence

I only figured out that importing 64 bit dll into 32 bit newlisp won't  work ( at least i hope i'm right about it :-P ) yet.

I gave up on glut to glfw library instead. I tried to translate this sample: http://www.glfw.org/documentation.html">//http://www.glfw.org/documentation.html into newlisp:



(import "glfw3.dll" "glfwCreateWindow")
(import "glfw3.dll" "glfwInit")
(import "glfw3.dll" "glfwTerminate")
(import "glfw3.dll" "glfwMakeContextCurrent")
(import "glfw3.dll" "glfwWindowShouldClose")
(import "glfw3.dll" "glfwSwapBuffers")
(import "glfw3.dll" "glfwPollEvents")

(if
(= (glfwInit))
(begin
(println "Error: glfwInit failed.")
(exit)))
(set 'window (glfwCreateWindow 640 480 "Hello World" nil nil))
(if
(nil? window)
(begin
(println "Error: glfwCreateWindow failed.")
(glfwTerminate)
(exit)))
(glfwMakeContextCurrent window)
(while
(= (int (glfwWindowShouldClose window)))
(glfwSwapBuffers window)
(glfwPollEvents))
(glfwTerminate)
(exit)



It still complains about missing function in opengl32.dll without having a mesa dll inside newlisp installation dir (which should result in using a windows version of opengl32.dll). But the point is even using mesa version of opengl this code hangs and 'program stopped working...' dialog appears. If i comment out the while loop the code exits without error in short time. Anyway it seems like something slightly blinks for a moment while firing the script.



Given the return type of glfwWindowShouldClose is int, is comparing to 0 done correctly in my code?

Astrobe

Quote from: "refrainrence" I think i must have it to develop a real 3D game, not just a proof of concept.


You have to be aware that Newlisp is a scripting language. Like most of the scripting languages it is likely to be too slow to perform directly 3D, real time rendering.



Rather, you should consider picking up an existing, full-blown 3D engine (like Irrlicht or Ogre 3D), and create Newlisp bindings for it. Newlisp in this scenario would drive what's to be drawn and delegate the drawing itself to the engine. That's what people do with Lua, another scripting language which is however very fast.

refrainrence

@Astrobe Thanks for the reply. Rather i will find me another project than continue with the game without newlisp. The goal is to use LISP-like language ( because typing 'for (..) {;;;}' by my own will in the spare time gives me a headache). At least this is what i think atm.



So what happened next on my journey with the game project? I replaced nil symbols/values in the argument list in the glfwCreateWindow call with 0's. This resulted in code running correctly ( from my observation) under slack 14 i386. By the way i couldn't find an example anywhere showing how to pass NULL as an argument of type 'pointer to struct' inside an imported function. Probably seems obvious to experts on c lang, but maybe it is worth to be put in the docs too? The code also worked on win7 AMD 64 after using http://sourceforge.net/projects/dxglwrap/">DirectX OpenGL Wrapper as opengl32.dll replacement. I then came to conclusion, that switching to the 'extended ffi' wouldn't hurt too, if i'm going to avoid unexpexted problems in the future. My code so far:



(if
  (find ostype '("Win32", "Cygwin"))
  (begin
    (set 'GL_LIB "opengl32.dll")
    (set 'GLFW_LIB "glfw3.dll"))
  (= ostype "Linux") ;; not tested
  (begin
    (set 'GL_LIB "libGL.so")
    (set 'GLFW_LIB "libglfw3.so"))
)

(import GLFW_LIB "glfwCreateWindow" "void*" "int" "int" "char*" "void*" "void*")
(import GLFW_LIB "glfwInit" "int")
(import GLFW_LIB "glfwTerminate" "void")
(import GLFW_LIB "glfwMakeContextCurrent" "void" "void*")
(import GLFW_LIB "glfwWindowShouldClose" "int" "void*")
(import GLFW_LIB "glfwSwapBuffers" "void" "void*")
(import GLFW_LIB "glfwPollEvents" "void")
(import GL_LIB "glGetString" "char*" "int")
(constant 'GL_VENDOR 0x1F00)
(constant 'GL_RENDERER 0x1F01)

(if
(= (glfwInit))
(begin
(println "Error: glfwInit failed.")
(exit)))
(set 'window (glfwCreateWindow 640 480 "Hello World" 0 0))
(if
(null? window)
(begin
(println "Error: glfwCreateWindow failed.")
(glfwTerminate)
(exit)))
(glfwMakeContextCurrent window)
(while
(= (glfwWindowShouldClose window))
true
(glfwSwapBuffers window)
(glfwPollEvents)
; (sleep 100)
)
(println (get-string (glGetString (| GL_VENDOR GL_RENDERER))))
(glfwTerminate)
(exit)



From the GLFW docs on glfwCreateWindow function:
Quote
Returns

    The handle of the created window, or NULL if an error occurred.

Is this a correct way to check for error:

(if
   (null? window)
   (begin
   (println "Error: glfwCreateWindow failed.")
   (glfwTerminate)
   (exit)))

?

TedWalther

Excellent project!  I heard that originally OpenGL binding was limited because of the way it used callback functions, and newlisp was limited to 10 callbacks.  But perhaps the new libffi stuff has removed that limitation?



I really hope so, and that you succeed.  I've also wanted to do this for a long time.  Thank you for posting your code, please keep at it!  If someone wants to post bindings to a 3d engine, of course they are welcome to, the more the merrier, but I also really like having low level access to stuff.  That is what puts newlisp way ahead of all other LISP variants for me.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

refrainrence

Thanks Ted for support. I insist that Newlisp is a part of my project, and i'm sure it will pay off in some time.

 Meanwhile, creating windows with OpenGL context turned out to be tricky using shared libraries under windows. I'm still not much closer to be an expert in this subject, so not much more to say. Under Linux these stuff just work.

 I also decided to use a game engine. Learning OpenGL takes too much time now. Without the engine i think i would end up writing my own shared libraries in c performing low level routines anyhow. But testing alternative game rulesets should be much easier using Newlisp, right? Below sample.c program from the http://raydium.org/">Raydium Engine rewritten in Newlisp.



(if
  (find ostype '("Win32", "Cygwin"))
  (begin
     (set 'RAYDIUM_LIB "raydium.dll"))
  (= ostype "Linux")
  (begin
    (set 'RAYDIUM_LIB "libraydium.so"))
)

(import RAYDIUM_LIB "raydium_clear_frame")
(import RAYDIUM_LIB "raydium_ode_draw_all")
(import RAYDIUM_LIB "raydium_rendering_finish")
 ;~ (import RAYDIUM_LIB "raydium_init_args")
(import RAYDIUM_LIB "raydium_init_load")
(import RAYDIUM_LIB "raydium_ode_ground_set_name")
(import RAYDIUM_LIB "raydium_callback")
(import RAYDIUM_LIB "raydium_camera_freemove")
(constant 'RAYDIUM_CAMERA_FREEMOVE_NORMAL 1)
(constant 'RAYDIUM_ODE_DRAW_NORMAL 0)

(define (display)
   (raydium_clear_frame)
   (raydium_camera_freemove RAYDIUM_CAMERA_FREEMOVE_NORMAL)
   (raydium_ode_draw_all RAYDIUM_ODE_DRAW_NORMAL)
    (raydium_rendering_finish))

(raydium_clear_frame)
(raydium_init_load "simple.conf")
(raydium_ode_ground_set_name "cocorobix.tri")
(raydium_callback (callback 0 'display))

(exit)



Works right out of the box under win7 AMD 64 and slack14 i386.

 It will take some time till the code would get interesting probably. The game will be in 2.5D environment and should run fine on older hardware.

TedWalther

I almost feel I could weep, I've been wanting to see this done in newLISP for years.  Thank you Lutz for putting the pieces together to make it happen, and thank you refrainrence for finally DOING it!



I cut and pasted the teapot GL demo onto my Linux box, and it worked!  I was so surprised.  No errors, just worked on the first try.  And now you show code that works on Win7 and Linux without alteration, without error, on the first try.  Wow!



Refrainrence, have you looked into libSDL?  Does that meet your needs?  I remember back when Loki Games specifically designed it for cross-platform game developement, and a lot of Linux games use it and those games run on Windows too.



A good set of libSDL bindings for newLISP would be the cats ass.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.