Tuesday, September 14

Things I'd do if I had the time.

I want to write a game about an ecology of self illuminating metaballs that
fly over implausibly coloured and pulsating landscapes to feed from
spontaneously erupting particle fountains.


Monday, September 13

Software renderer in Lisp

I'm seized by the insane urge to write a software renderer in Lisp. I don't know where this came from: actually, I think I do - fond memories of Apple II shape tables and the disire to test the lisperati's claim that it's performace is parallel to that of C, and also a desire to find out exactly what high - performance lisp is like.


I've alread created an sbcl binding to the PTC. I really must stick it into a CVS repository somewhere - it may be useful for someone else.



Sunday, September 5

Building Graphics3D-CPP with Scons

G3d-cpp is an ideal (IMHO) library for working with when constructing 3d testbeds or demos: it doesn't aim to be an over-arching SDK that handles every last detail of OS/Game interaction (it delegates most of those tasks to the SDL), and it uses C++ very effectively in abstracting the render device, windows, geometry and all the things you normally have to deal with in finicky detail in C. If I have to deal with Bjarnes monster, this is the arena I'd chose to fight in :)


Here is the SConstruct. At present I'm supporting release build only: and my architecture optimisation flags are set for up an AMD64 and the resulting binary may not be happy on anything less than a P4/SSE2 capable - chip. It also assumes we are linking with a version of SDL & zlib built by the scripts in the two blog entries below.



#
# Sconstruct file for G3D
#
import sys

#
# microsoft tool kit environment
#
env = Environment(tools = [ 'mstoolkit' ])


env['CPPPATH'] = [ "#\\include\\", "#\\include\\G3D", "#\\include\\GLG3D", "#\\include\\glh", "#\\include\\zlib", "..\\SDL-1.2.7\\include" ]
env['LIBPATH'] = [ "#\\win32-lib", "..\\SDL-1.2.7", '..\\zlib' ]
env['LIBS'] = [ "kernel32.lib", "user32.lib", "gdi32.lib", "winspool.lib", "comdlg32.lib", "advapi32.lib", "shell32.lib", "ole32.lib", "oleaut32.lib", "uuid.lib", "winmm.lib", "opengl32.lib", "glu32.lib", "ddraw.lib", "dinput.lib", "dxguid.lib", "zlib.lib", "version.lib" ]

#if project_config == 'debug':
# env['LIBS'] = env['LIBS'] + [ "SDLd.lib", "SDLmaind.lib" ]
# program_name = [ "#\\demos\\GLG3D_DemoD.exe" ]
# library_name = [ "#\\win32-lib\GLG3D-debug.lib" ]
# graphics_library_name = [ "#\\win32-lib\G3D-debug.lib" ]
# env['CPPDEFINES'] = [ '_DEBUG', 'WIN32', '_WINDOWS', 'ENABLE_WINDIB', 'ENABLE_DIRECTX', '_WIN32_WINNT=0x0400', '_LIB' ]
# env['CCFLAGS'] = [ '/nologo', '/W3', '/Zi', '/Od', '/MTd' ]
# env['LINKFLAGS'] = [ '/subsystem:windows', '/machine:x86' ]

#if project_config == 'release':
# env['LIBS'] = env['LIBS'] + [ 'SDL.lib', 'SDLmain.lib' ] # [ "G3D", "GLG3D", "SDL.lib", "SDLmain.lib" ]

program_name = [ "#\demos\\GLG3D_Demo.exe" ]
library_name = [ "#\\win32-lib\GLG3D.lib" ]
graphics_library_name = [ "#\\win32-lib\G3D.lib" ]
jpeg_library_name = [ "#\\win32-lib\libjpeg.lib" ]

env['CPPDEFINES'] = [ 'NDEBUG', 'WIN32', '_WINDOWS', 'ENABLE_WINDIB', 'ENABLE_DIRECTX', '_WIN32_WINNT=0x0400' ]
env['CCFLAGS'] = [ '/nologo', '/W3', '/GF', '/G7', '/Ox', '/arch:SSE2', '/Gy', '/EHsc', '/MT' ]
env['LINKFLAGS'] = [ '/subsystem:windows', '/machine:x86' ]

#
# library
#
env.StaticLibrary( library_name, [
r".\GLG3Dcpp\Draw.cpp",
r".\GLG3Dcpp\edgeFeatures.cpp",
r".\GLG3Dcpp\G3DGameUnits.cpp",
r".\GLG3Dcpp\GApp.cpp",
r".\GLG3Dcpp\getOpenGLState.cpp",
r".\GLG3Dcpp\GFont.cpp",
r".\GLG3Dcpp\glcalls.cpp",
r".\GLG3Dcpp\GLCaps.cpp",
r".\GLG3Dcpp\glenumtostring.cpp",
r".\GLG3Dcpp\GPUProgram.cpp",
r".\GLG3Dcpp\IFSModel.cpp",
r".\GLG3Dcpp\LightingParameters.cpp",
r".\GLG3Dcpp\ManualCameraController.cpp",
r".\GLG3Dcpp\MD2Model.cpp",
r".\GLG3Dcpp\MD2Model_load.cpp",
r".\GLG3Dcpp\Milestone.cpp",
r".\GLG3Dcpp\PixelProgram.cpp",
r".\GLG3Dcpp\PosedModel.cpp",
r".\GLG3Dcpp\RenderDevice.cpp",
r".\GLG3Dcpp\SDLWindow.cpp",
r".\GLG3Dcpp\Shader.cpp",
r".\GLG3Dcpp\shadowVolume.cpp",
r".\GLG3Dcpp\Sky.cpp",
r".\GLG3Dcpp\tesselate.cpp",
r".\GLG3Dcpp\Texture.cpp",
r".\GLG3Dcpp\TextureFormat.cpp",
r".\GLG3Dcpp\TextureManager.cpp",
r".\GLG3Dcpp\UserInput.cpp",
r".\GLG3Dcpp\VAR.cpp",
r".\GLG3Dcpp\VARSystem.cpp"
])

env.StaticLibrary( graphics_library_name, [
r".\G3Dcpp\AABox.cpp",
r".\G3Dcpp\BinaryInput.cpp",
r".\G3Dcpp\BinaryOutput.cpp",
r".\G3Dcpp\Box.cpp",
r".\G3Dcpp\Capsule.cpp",
r".\G3Dcpp\CollisionDetection.cpp",
r".\G3Dcpp\Color3.cpp",
r".\G3Dcpp\Color3uint8.cpp",
r".\G3Dcpp\Color4.cpp",
r".\G3Dcpp\Color4uint8.cpp",
r".\G3Dcpp\Cone.cpp",
r".\G3Dcpp\ConvexPolyhedron.cpp",
r".\G3Dcpp\CoordinateFrame.cpp",
r".\G3Dcpp\debugAssert.cpp",
r".\G3Dcpp\Discovery.cpp",
r".\G3Dcpp\fileutils.cpp",
r".\G3Dcpp\format.cpp",
r".\G3Dcpp\g3derror.cpp",
r".\G3Dcpp\g3dmath.cpp",
r".\G3Dcpp\GCamera.cpp",
r".\G3Dcpp\GImage.cpp",
r".\G3Dcpp\GLight.cpp",
r".\G3Dcpp\license.cpp",
r".\G3Dcpp\Line.cpp",
r".\G3Dcpp\LineSegment.cpp",
r".\G3Dcpp\Log.cpp",
r".\G3Dcpp\Matrix3.cpp",
r".\G3Dcpp\Matrix4.cpp",
r".\G3Dcpp\MeshAlg.cpp",
r".\G3Dcpp\MeshAlgAdjacency.cpp",
r".\G3Dcpp\MeshAlgWeld.cpp",
r".\G3Dcpp\NetworkDevice.cpp",
r".\G3Dcpp\PhysicsFrame.cpp",
r".\G3Dcpp\Plane.cpp",
r".\G3Dcpp\prompt.cpp",
r".\G3Dcpp\Quat.cpp",
r".\G3Dcpp\Ray.cpp",
r".\G3Dcpp\Sphere.cpp",
r".\G3Dcpp\stringutils.cpp",
r".\G3Dcpp\System.cpp",
r".\G3Dcpp\TextInput.cpp",
r".\G3Dcpp\TextOutput.cpp",
r".\G3Dcpp\Triangle.cpp",
r".\G3Dcpp\Vector2.cpp",
r".\G3Dcpp\Vector2int16.cpp",
r".\G3Dcpp\Vector3.cpp",
r".\G3Dcpp\Vector3int16.cpp",
r".\G3Dcpp\Vector4.cpp"
])

env.StaticLibrary(jpeg_library_name,
[
r".\IJG\jcapimin.c",
r".\IJG\jcapistd.c",
r".\IJG\jccoefct.c",
r".\IJG\jccolor.c",
r".\IJG\jcdctmgr.c",
r".\IJG\jchuff.c",
r".\IJG\jcinit.c",
r".\IJG\jcmainct.c",
r".\IJG\jcmarker.c",
r".\IJG\jcmaster.c",
r".\IJG\jcomapi.c",
r".\IJG\jcparam.c",
r".\IJG\jcphuff.c",
r".\IJG\jcprepct.c",
r".\IJG\jcsample.c",
r".\IJG\jctrans.c",
r".\IJG\jdapimin.c",
r".\IJG\jdapistd.c",
r".\IJG\jdatadst.c",
r".\IJG\jdatasrc.c",
r".\IJG\jdcoefct.c",
r".\IJG\jdcolor.c",
r".\IJG\jddctmgr.c",
r".\IJG\jdhuff.c",
r".\IJG\jdinput.c",
r".\IJG\jdmainct.c",
r".\IJG\jdmarker.c",
r".\IJG\jdmaster.c",
r".\IJG\jdmerge.c",
r".\IJG\jdphuff.c",
r".\IJG\jdpostct.c",
r".\IJG\jdsample.c",
r".\IJG\jdtrans.c",
r".\IJG\jerror.c",
r".\IJG\jfdctflt.c",
r".\IJG\jfdctfst.c",
r".\IJG\jfdctint.c",
r".\IJG\jidctflt.c",
r".\IJG\jidctfst.c",
r".\IJG\jidctint.c",
r".\IJG\jidctred.c",
r".\IJG\jmemansi.c",
r".\IJG\jmemmgr.c",
r".\IJG\jquant1.c",
r".\IJG\jquant2.c",
r".\IJG\jutils.c"
])

env['LIBS'] = env['LIBS'] + [ "GLG3D.lib", "G3D.lib", "libjpeg.lib", "SDL.lib", "SDL_main.lib" ]

# demos
env.Program( program_name, [ r'#\demos\GLG3D_Demo\main.cpp' ] )


Building the SDL with SCons

Just as easy, another SConstruct in the root directory. Not SCons best practice, but certianly the simplest way and all that's needed for such relatively small (compared to say, the Linux Kernel) projects.

Note that I'm building static libraries - this is because the toolkit doesn't support the DLL versions of the C/C++ runtime libraries.


#
# Sconstruct file for SDL-1.2.7.
#
import sys

#
# microsoft tool kit environment
#
env = Environment(tools = [ 'mstoolkit' ])

#
# debug or release
#
project_config = ARGUMENTS.get('config', 'debug')
project_stdio = ARGUMENTS.get('stdio', 'yes' )

if not project_config in [ 'debug', 'release' ]:
print 'Invalid configuration - should be release or debug'
sys.exit(1)

if not project_stdio in [ 'yes', 'no' ]:
print 'Invalid stdio - must be yes or no'
sys.exit(1)

if project_config == 'debug':
library_names = [ "SDLd.lib", 'SDL_maind.lib' ]
env['CPPDEFINES'] = [ '_DEBUG', 'WIN32', '_WINDOWS', 'ENABLE_WINDIB', 'ENABLE_DIRECTX', '_WIN32_WINNT=0x0400' ]
env['CCFLAGS'] = [ '/nologo', '/W3', '/Zi', '/Od', '/MTd' ]
project_stdio = 'no'

if project_config == 'release':
library_names = [ "SDL.lib", 'SDL_main.lib' ]
env['CPPDEFINES'] = [ 'NDEBUG', 'WIN32', '_WINDOWS', 'ENABLE_WINDIB', 'ENABLE_DIRECTX', '_WIN32_WINNT=0x0400' ]
if project_stdio == 'no':
env['CPPDEFINES'] = env['CPPDEFINES'] + [ 'NO_STDIO_REDIRECT' ]
env['CCFLAGS'] = [ '/nologo', '/W3', '/GF', '/MT', '/G7', '/Ox', '/arch:SSE2', '/Gy' ]


env['CPPPATH'] = [ r'#\src', r'#\src\audio', r'#\src\video', r'src\video\wincommon', r'#\src\video\windx5',
r'#\src\events', r'#\src\joystick', r'#\src\cdrom', r'#\src\thread', r'#\src\thread\win32',
r'#\src\timer', r'#\include', r'#\include\SDL']

env.StaticLibrary( library_names[0], [
r"#\Src\SDL.c",
r"#\Src\Video\SDL_RLEaccel.c",
r"#\Src\Events\SDL_active.c",
r"#\Src\Audio\SDL_audio.c",
r"#\Src\Audio\SDL_audiocvt.c",
r"#\Src\Audio\SDL_audiomem.c",
r"#\Src\Video\SDL_blit.c",
r"#\Src\Video\SDL_blit_0.c",
r"#\Src\Video\SDL_blit_1.c",
r"#\Src\Video\SDL_blit_A.c",
r"#\Src\Video\SDL_blit_N.c",
r"#\Src\Video\SDL_bmp.c",
r"#\Src\Cdrom\SDL_cdrom.c",
r"#\Src\Cpuinfo\SDL_cpuinfo.c",
r"#\Src\Video\SDL_cursor.c",
r"#\src\audio\windib\SDL_dibaudio.c",
r"#\Src\Video\Windib\SDL_dibevents.c",
r"#\Src\Video\Windib\SDL_dibvideo.c",
r"#\src\audio\windx5\SDL_dx5audio.c",
r"#\Src\Video\Windx5\SDL_dx5events.c",
r"#\Src\Video\Windx5\SDL_dx5video.c",
r"#\src\video\windx5\SDL_dx5yuv.c",
r"#\Src\Endian\SDL_endian.c",
r"#\Src\SDL_error.c",
r"#\Src\Events\SDL_events.c",
r"#\Src\Events\SDL_expose.c",
r"#\Src\SDL_fatal.c",
r"#\src\video\SDL_gamma.c",
r"#\src\joystick\SDL_joystick.c",
r"#\Src\Events\SDL_keyboard.c",
r"#\Src\Audio\SDL_mixer.c",
r"#\src\joystick\win32\SDL_mmjoystick.c",
r"#\Src\Events\SDL_mouse.c",
r"#\Src\Video\SDL_pixels.c",
r"#\Src\Events\SDL_quit.c",
r"#\src\events\SDL_resize.c",
r"#\Src\File\SDL_rwops.c",
r"#\Src\Video\SDL_surface.c",
r"#\Src\Cdrom\Win32\SDL_syscdrom.c",
r"#\src\thread\generic\SDL_syscond.c",
r"#\Src\Video\wincommon\SDL_sysevents.c",
r"#\Src\Video\wincommon\SDL_sysmouse.c",
r"#\src\thread\win32\SDL_sysmutex.c",
r"#\src\thread\win32\SDL_syssem.c",
r"#\Src\Thread\Win32\SDL_systhread.c",
r"#\src\timer\win32\SDL_systimer.c",
r"#\Src\Video\wincommon\SDL_syswm.c",
r"#\Src\Thread\SDL_thread.c",
r"#\src\timer\SDL_timer.c",
r"#\Src\Video\SDL_video.c",
r"#\Src\Audio\SDL_wave.c",
r"#\src\video\wincommon\SDL_wingl.c",
r"#\src\video\SDL_yuv.c",
r"#\src\video\SDL_yuv_sw.c",
r"#\src\video\SDL_stretch.c" ] )

env.StaticLibrary(library_names[1], [ r"#\src\Main\Win32\SDL_win32_main.c" ])



Building Zlib With Scons

The First library we need: a lot of other packages link with it. I insall all my libaries under a single root directory (C:\Projects\libraries in my case) and the build scripts assume you do it, too. All it takes is a single SConstruct:


#
# Sconstruct file for SDL-1.2.7.
#
import sys

#cd
# microsoft tool kit environment
#
env = Environment(tools = [ 'mstoolkit' ])

#
# debug or release
#
project_config = ARGUMENTS.get('config', 'release')

if not project_config in [ 'debug', 'release' ]:
print 'Invalid configuration - should be release or debug'
sys.exit(1)


if project_config == 'debug':
library_name = [ "zlibd.lib" ]
env['CPPDEFINES'] = [ '_DEBUG', 'WIN32', '_WINDOWS', 'ENABLE_WINDIB', 'ENABLE_DIRECTX', '_WIN32_WINNT=0x0400' ]
env['CCFLAGS'] = [ '/nologo', '/W3', '/Zi', '/Od', '/MTd' ]

if project_config == 'release':
library_name = [ "zlib.lib" ]
env['CPPDEFINES'] = [ 'NDEBUG', 'WIN32', '_WINDOWS', 'ENABLE_WINDIB', 'ENABLE_DIRECTX', '_WIN32_WINNT=0x0400' ]
env['CCFLAGS'] = [ '/nologo', '/W3', '/GF', '/MT', '/G7', '/Ox', '/arch:SSE2', '/Gy' ]


env['CPPPATH'] = [ r'#' ]

env.StaticLibrary( library_name, [ "adler32.c", "compress.c", "crc32.c", "deflate.c", "gzio.c", "infback.c", "inffast.c", "inflate.c", "inftrees.c", "trees.c", "uncompr.c", "zutil.c" ])


Cut price Win32 Graphics Coding.

Ever since Microsoft released their VC/C++ 2003 compiler command line tools free (as in beer) I've been using it for my coding at home. I've built a number of ibraries with it on the Win32 system including g3d-cpp and the SDL. What follows is a quick HOWTO.


First, catch your hare. You will need the command line compiler itself. You will then need the SDKS that enable coding on Win32: The Platform SDK and the Direct X SDK. You could also get the .NET Framework while you were are at it, but I haven't used with any of the graphics libraries that I build.


Secondly, you will need the tools that you are going to build the libraries with Python (if you don't already have it) - any recent version will do and Scons via this link 0.96.1 . Scons is "a better make" - it's based on a classic perl build call Cons and builds just about anything on any platform with any tool. The developers have paid great attention to maintaining "build correctess: it pre-computes all the dependencies before building and rebuilds only exactly what needs to be build. In addition the build scripts it uses are signinficantly easier to use than make and it supports parallel building out of the box. It's gradually becoming the build tool of choice for a lot of projects."


Unzip the scons zip into an arbitary directory - we will call it %SCONS%. Scons doesn't support the vc toolkit "out of the box" just yet, but I've written an Scons tool script to support it which you need to copy to your %SCONS%\scons-0.96.1\engine\SCons\tool directory in the fresh Scons you just unzipped. Go to %SCONS%\scons-0.96.1 and type "python setup.py install" and it will all be installed. You should be all set for vc toolkit development with SCons.