I've recently started a fresh DLL based OpenGL engine project with a friend of mine. He's a 2D artist so I've begun by concentrating on orthographic tile-animated sprites for a start.
The current code is heavily based on NeHe tutorial#17 (the masm source for that is not correct but it works) - a DisplayList of orthographic rectangles is created and used as a "charactermap", like a font.
Anyone interested, a small demo was posted at http://homer.ultrano.com/dllStuff.rar
Have a nice day :)
The current code is heavily based on NeHe tutorial#17 (the masm source for that is not correct but it works) - a DisplayList of orthographic rectangles is created and used as a "charactermap", like a font.
Anyone interested, a small demo was posted at http://homer.ultrano.com/dllStuff.rar
Have a nice day :)
The 2D part of the engine now sports the following components:
-Sprite class instances are managed using one or more instances of "SpriteManager" class (a collection container of sorts)
-SpriteAnimation class instances are stored in a global SpriteAnimationManager class instance, and shared by all instances of Sprite class
SpriteAnimations support the following "FinalAction" values:
_DIE_ - sprite will mark itself for destruction when animation finishes
_PAUSE_ - sprite will use last animation frame when animation finishes
_LOOP_ - Animation will loop
pUserFunction - CallBack to UserFunction when animation finishes
Animation speed is floating point in fps, and negative speed is ok.
At the moment, only 16x16 cells per image are allowed (256 animation framecells per bmp) and this will be the next restriction to be addressed.
I will soon post another demo showing some of this further work.
Any feedback would be appreciated, especially error reports :)
-Sprite class instances are managed using one or more instances of "SpriteManager" class (a collection container of sorts)
-SpriteAnimation class instances are stored in a global SpriteAnimationManager class instance, and shared by all instances of Sprite class
SpriteAnimations support the following "FinalAction" values:
_DIE_ - sprite will mark itself for destruction when animation finishes
_PAUSE_ - sprite will use last animation frame when animation finishes
_LOOP_ - Animation will loop
pUserFunction - CallBack to UserFunction when animation finishes
Animation speed is floating point in fps, and negative speed is ok.
At the moment, only 16x16 cells per image are allowed (256 animation framecells per bmp) and this will be the next restriction to be addressed.
I will soon post another demo showing some of this further work.
Any feedback would be appreciated, especially error reports :)
I've added a SuperBmp class which encapsulates a 2d scrolling tilemap stored as an array of bytes which represent Tiles from a font-bmp (If you've done your homework, you understand what a font-bmp is)
The Engine provides a scrollable "foreground" as well as methods to get and set the scroll position.
I've also implemented the following CallBacks, as well as procs to set them from your user code:
CALLBACK_PREINIT ()
CALLBACK_POSTINIT ()
CALLBACK_RENDER ()
CALLBACK_UPDATE (fElapsed)
CALLBACK_KEYBOARD (pKeys)
The full list of functions exported by the DLL (without param info):
WinMain
SetPreInitCallBack
SetPostInitCallBack
SetRenderCallBack
SetUpdateCallBack
SetKeyboardCallBack
GetTileAddress
GetScrollX
SetScrollX
GetScrollY
GetSizeX
GetSizeY
glPrint
You will appreciate this is a work in progress, but already here is my test exe source so you can see what this project offers you:
Seriously, this thing will make 2d gamedev a lot easier, and support for 3D is inherently available since the 2d is really 3D-Assisted.
No interest out there?
The Engine provides a scrollable "foreground" as well as methods to get and set the scroll position.
I've also implemented the following CallBacks, as well as procs to set them from your user code:
CALLBACK_PREINIT ()
CALLBACK_POSTINIT ()
CALLBACK_RENDER ()
CALLBACK_UPDATE (fElapsed)
CALLBACK_KEYBOARD (pKeys)
The full list of functions exported by the DLL (without param info):
WinMain
SetPreInitCallBack
SetPostInitCallBack
SetRenderCallBack
SetUpdateCallBack
SetKeyboardCallBack
GetTileAddress
GetScrollX
SetScrollX
GetScrollY
GetSizeX
GetSizeY
glPrint
You will appreciate this is a work in progress, but already here is my test exe source so you can see what this project offers you:
;----------------------------------------------------------------------------------------------------------------------------------------
.486
.model flat, stdcall
option casemap:none
;----------------------------------------------------------------------------------------------------------------------------------------
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib NoConsoleDLL.lib ;The lib for the Engine DLL
include \masm32\include\macros.inc
;----------------------------------------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------------------------------------
;PROTOTYPES FOR DLL FUNCTIONS
;----------------------------------------------------------------------------------------------------------------------------------------
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
SetPreInitCallBack PROTO :DWORD
SetPostInitCallBack PROTO :DWORD
SetUpdateCallBack PROTO :DWORD
SetRenderCallBack PROTO :DWORD
SetKeyboardCallBack PROTO :DWORD
GetTileAddress PROTO :DWORD,:DWORD
GetScrollX PROTO
SetScrollX PROTO :DWORD
GetScrollY PROTO
GetSizeX PROTO
glPrint PROTO :DWORD, :DWORD, :DWORD, :UINT
;----------------------------------------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------------------------------------
.code
;----------------------------------------------------------------------------------------------------------------------------------------
;The User must provide a WndProc function, it MUST process WM_CLOSE as shown.
;Any other messages of interest may be processed by the user as normal if they wish.
;----------------------------------------------------------------------------------------------------------------------------------------
WndProc proc hWind:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.if uMsg==WM_CLOSE
invoke PostQuitMessage,0
xor eax,eax
ret
.endif
invoke DefWindowProc,hWind,uMsg,wParam,lParam
ret
WndProc endp
;----------------------------------------------------------------------------------------------------------------------------------------
;The User may provide several key CallBack functions:
;Update is called from the main loop just after the Time is updated
;and Elapsed Time calculated, the Elapsed Time is passed as the
;only parameter for the procedure.
;Render is called from the internal rendering code, which occurs
;after Update but before keyboard processing. It requires NO parameters.
;PreInit and PostInit CallBacks require no params.
;They are called either side of the Window Creation code at startup
;and never again - they are onetime callbacks.
;They will not be called again if the window is "recreated" for any reason.
;Keyboard VallBack expects one param, it's ptr to keys array
;----------------------------------------------------------------------------------------------------------------------------------------
Pre proc
;Message "pre"
ret
Pre endp
Post proc
;Message "post"
ret
Post endp
Update proc fTimeElapsed
ret
Update endp
Render proc
local buf [256]:BYTE
local ex
local why
invoke GetScrollX
mov ex,eax
invoke GetScrollY
mov why,eax
invoke wsprintf, addr buf,CTEXT("ScrollPosition: X=%lu Y=%lu"),ex, why
invoke glPrint, 0, 0, addr buf, 1
ret
Render endp
;=====================================
Keys proc uses esi pKeys:DWORD
local ex
local sighsex
mov esi,pKeys
.if byte ptr [esi+VK_LEFT]
mov byte ptr [esi+VK_LEFT],0
invoke GetSizeX
mov sighsex,eax
invoke GetScrollX
mov ex,eax
.if eax<sighsex
inc ex
invoke SetScrollX, ex
.endif
.endif
.if byte ptr [esi+VK_RIGHT]
mov byte ptr [esi+VK_RIGHT],0
invoke GetSizeX
mov sighsex,eax
invoke GetScrollX
mov ex,eax
.if ex!=0
dec ex
invoke SetScrollX, ex
.endif
.endif
ret
Keys endp
;=====================================
;----------------------------------------------------------------------------------------------------------------------------------------
start:
; Check if we should start in full screen
invoke MessageBox,NULL,CTEXT("Do you want to run in fullscreen?"),CTEXT("Graphics mode"),MB_YESNO or MB_ICONQUESTION
.IF eax == IDNO
push FALSE
.ELSE
push TRUE
.ENDIF
invoke SetPreInitCallBack, addr Pre ;Tell Engine about my OneTime proc
invoke SetPostInitCallBack, addr Post ;Tell Engine about my OneTime proc
invoke SetUpdateCallBack, addr Update ;Tell Engine about my Update proc
invoke SetRenderCallBack, addr Render ;Tell Engine about my Render proc
invoke SetKeyboardCallBack, addr Keys ;Tell Engine about my Keys proc
invoke GetModuleHandle,0
pop ebx
invoke WinMain,eax,addr WndProc,ebx,0 ;params are hInstance , address of User WndProc , bWindowed
invoke ExitProcess, eax ;returnvalue from WinMain is exitcode
;----------------------------------------------------------------------------------------------------------------------------------------
end start
Seriously, this thing will make 2d gamedev a lot easier, and support for 3D is inherently available since the 2d is really 3D-Assisted.
No interest out there?
I no have real clue on game developevement or engine :S, I whant to watch :P
What I'm writing is a DLL that contains all the "boring" parts of a 2D or 3D game, supplying the would-be gamedev with a solid foundation to build a real game without having to stare at the housekeeping code.
Not much progress to report except for the following improvement to keyboard processing:
I no longer catch and process keyboard related WMs, I now call GetKeyboardState. The reason is that the former method does not allow us to check for multiple simultaneous keypresses because a keypress is processed as soon as it is detected.. the latter method although more expensive allows us to much more cleanly detect for example the UP and LEFT cursor keys both at once.
I no longer catch and process keyboard related WMs, I now call GetKeyboardState. The reason is that the former method does not allow us to check for multiple simultaneous keypresses because a keypress is processed as soon as it is detected.. the latter method although more expensive allows us to much more cleanly detect for example the UP and LEFT cursor keys both at once.
The code for the Timer has been replaced with HighPerformanceTimer code which was ungraciously stolen from Scronty's DX8 includes :)
All the Timer related functions return Time as a floating point QWORD on the fpu stack.
Any mention of GetTickCount has been removed.
If your hardware does not support the HighPerformanceTimer, the Timer code will use timeGetTime calls instead.
All the Timer related functions return Time as a floating point QWORD on the fpu stack.
Any mention of GetTickCount has been removed.
If your hardware does not support the HighPerformanceTimer, the Timer code will use timeGetTime calls instead.
The engine now boasts its first instanced 3d object - a textured cube.
The cube object is encapulated within the Cube class.
Another class, CubeManager, has been instanced within the engine to manage an array of pointers to live instances of the Cube object.
(That means you can have as many Cubes as you like.)
A function has been exported to allow the User to create managed Cube instances. It is recommended that you call CubeManager methods in preference to calling Cube methods.
Far cooler than the Cube stuff is the MousePick code I've implemented.
It uses the OpenGL NameStack, so that means the Cube class (and any future 3dobject classes) has TWO render methods - Selectable and Non Selectable.
Since a "Name" in OpenGL is just a DWORD, I'm using the pointer to the Cube instance as the "Name" during Select-rendering.
This is the "ID" I am returned by my "What The Hell Did I Click On" function (called in response to left mouse down).
A decent start :)
The cube object is encapulated within the Cube class.
Another class, CubeManager, has been instanced within the engine to manage an array of pointers to live instances of the Cube object.
(That means you can have as many Cubes as you like.)
A function has been exported to allow the User to create managed Cube instances. It is recommended that you call CubeManager methods in preference to calling Cube methods.
Far cooler than the Cube stuff is the MousePick code I've implemented.
It uses the OpenGL NameStack, so that means the Cube class (and any future 3dobject classes) has TWO render methods - Selectable and Non Selectable.
Since a "Name" in OpenGL is just a DWORD, I'm using the pointer to the Cube instance as the "Name" during Select-rendering.
This is the "ID" I am returned by my "What The Hell Did I Click On" function (called in response to left mouse down).
A decent start :)
I for one know next to nothing about graphic related programming (such as your project). Any idea if there will be documentation/tutorial(s) and perhaps even a sample (if that's not too much work) game/program once the library is complete?
Of course - complete and verbose documentation and examples will both be provided in good time. You won't need to know a lot of heavy programming or 3d math to create cool and fast 3d games and applications with this library - its purpose is to do all the dirty work for you, leaving you to worry about the nuts and bolts of your app.
Yesterday I wrote Fustrum Culling code, and today I wrote a Camera class. These will probably both be implemented by tomorrow :)
Yesterday I wrote Fustrum Culling code, and today I wrote a Camera class. These will probably both be implemented by tomorrow :)
Yesterday I wrote Fustrum Culling code, and today I wrote a Camera class.
No idea what that is but your project definitely seems pretty cool. Keep up the great work :-D
If I am mentioning subjects which seem alien to you, and you are interested in this topic (gamedev), then it might pay to look them up :)
A fustrum is a pyramid with a rectangular base , and with the point sliced off so that it resembles a cube with tapered sides.
A view fustrum is an imaginary pyramid which is being projected from your eyeball , the point of the fustrum would be in your eye. The view fustrum is the area of 3D world that you can see.. imagine theres a pyramid coming out of an eyeball and moving about in the 3D world ... if we can figure out what stuff is inside the fustrum, we can draw that stuff on the screen, and we don't have to draw anything else. If its not partially or fully inside the fustrum, its OFFSCREEN AND NOT VISIBLE !!
So this fustrum culling concept is simply an attempt to not have to draw stuff thats not visible anyway :)
If you had a complex and large 3D world made of 3 and a half zillion triangles, but only 20 triangles are visible, then throwing 3 and a half zillion triangles at your graphic card 30 or times a second starts to sound as silly as it is... if we can mathematically eliminate stuff thats simply not visible at the time, we can render much faster.
As for the Camera class... when I mention 'class' that refers to oop (object oriented programming) - in essence what this means is you can if you like make infinite number of cameras and put them where u like or even attatch them to other objects... like a player model or a flying missile..say, that oop stuff sounds ok, doesn't it? :)
A fustrum is a pyramid with a rectangular base , and with the point sliced off so that it resembles a cube with tapered sides.
A view fustrum is an imaginary pyramid which is being projected from your eyeball , the point of the fustrum would be in your eye. The view fustrum is the area of 3D world that you can see.. imagine theres a pyramid coming out of an eyeball and moving about in the 3D world ... if we can figure out what stuff is inside the fustrum, we can draw that stuff on the screen, and we don't have to draw anything else. If its not partially or fully inside the fustrum, its OFFSCREEN AND NOT VISIBLE !!
So this fustrum culling concept is simply an attempt to not have to draw stuff thats not visible anyway :)
If you had a complex and large 3D world made of 3 and a half zillion triangles, but only 20 triangles are visible, then throwing 3 and a half zillion triangles at your graphic card 30 or times a second starts to sound as silly as it is... if we can mathematically eliminate stuff thats simply not visible at the time, we can render much faster.
As for the Camera class... when I mention 'class' that refers to oop (object oriented programming) - in essence what this means is you can if you like make infinite number of cameras and put them where u like or even attatch them to other objects... like a player model or a flying missile..say, that oop stuff sounds ok, doesn't it? :)
Hi EvilHomer2k, how do you do frustum culling? do you check every vertex? or maybe check one vertex per object? is it even considerable to perform 'every-vertex' checking? i'm following this thread, because i plan do write 3d engine for direct3d9 with custom shaders. i understand whole DX architecture, and know how to do things using it, but first i'd like to collect some experience :)
Well that's a good question, and it depends what you want to cull, but the general answer to that question is that you should surround chunks of geometry in an imaginary bounding cube or sphere.
For "3d objects", these can be defined with as little as a single Radius value (given that your "object" already has position vector)
Your fustrum checks should be performed not against the geometry itself but against imaginary container geometries... if the container is not partially within the fustrum, then you know its contents aren't visible.
When it comes to fustrum culling of "static world geometry" like maybe a 3d terrain or a castle ruin, you should be using some kind of "space partitioning" to containerize chunks of the world geometry in EXACTLY the same way as described above, the only difference being that the bounding geometry may need to be explicitly defined in order to achive "tighter fits".
If you can picture a world full of objects that are encapsulated by glass fishtanks of simple geometry, you can see that you only need to be culling the fishtanks, not the fish :)
Having done that you can perform lowlevel culling on the fish if you like, but by this time there's not many half-visible fish left to worry about and its absolutely ok to not bother..
Hope you liked my analogy :)
For "3d objects", these can be defined with as little as a single Radius value (given that your "object" already has position vector)
Your fustrum checks should be performed not against the geometry itself but against imaginary container geometries... if the container is not partially within the fustrum, then you know its contents aren't visible.
When it comes to fustrum culling of "static world geometry" like maybe a 3d terrain or a castle ruin, you should be using some kind of "space partitioning" to containerize chunks of the world geometry in EXACTLY the same way as described above, the only difference being that the bounding geometry may need to be explicitly defined in order to achive "tighter fits".
If you can picture a world full of objects that are encapsulated by glass fishtanks of simple geometry, you can see that you only need to be culling the fishtanks, not the fish :)
Having done that you can perform lowlevel culling on the fish if you like, but by this time there's not many half-visible fish left to worry about and its absolutely ok to not bother..
Hope you liked my analogy :)
I ought to point out now that there's a very efficient way of extracting the fustrum planes from the current view, rather than defining the fustrum as a cube and then deforming it into a view fustrum using matrices, we can extract the planes of the fustrum from the current view mathematically.
thanx :) now i got it. so i need to encapsulate my very_complicated_object_consisting_of_999999999_triangles into simple cube (or sphere) and check wheter the cube is inside the frustum. to do that i extract 6 frustum planes (left, right, top, bottom, near, far), and do plane equation with cube's vertices, right?
That's right :)
If you want to go further, you can divide the imaginary cube into cubelets, and divide the object geometry among the cubelets, now surround the cubelets with the original cube and you have hierarchical octal space partitioning, which if you like can be N deep - split the cubelets !! Stop when some minimum triangles are in a cubelet :)
Just stuff to make you think, if your models are VERY complex, its worth applying osp to the models themselves as you would to an entire world :)
In such a system - if the mother cube is visible, check all its babies - for each visible baby cube, check its babies... all the geometry is stored in the lowest nodes (smallest cubes) of such a tree, so you only have to render when the cube is visible, has no visible babies, and contains triangles :)
If you want to go further, you can divide the imaginary cube into cubelets, and divide the object geometry among the cubelets, now surround the cubelets with the original cube and you have hierarchical octal space partitioning, which if you like can be N deep - split the cubelets !! Stop when some minimum triangles are in a cubelet :)
Just stuff to make you think, if your models are VERY complex, its worth applying osp to the models themselves as you would to an entire world :)
In such a system - if the mother cube is visible, check all its babies - for each visible baby cube, check its babies... all the geometry is stored in the lowest nodes (smallest cubes) of such a tree, so you only have to render when the cube is visible, has no visible babies, and contains triangles :)
Camera class has been implemented - YAY :)
Thanks to ti_mo_n for noticing my silly fpu overflow !!
Now debugging my Frustum class , which encapsulates Frustum Culling of Point, Sphere and Cube entities :-D :-D :-D
Thanks to ti_mo_n for noticing my silly fpu overflow !!
Now debugging my Frustum class , which encapsulates Frustum Culling of Point, Sphere and Cube entities :-D :-D :-D
Frustum class has been debugged, I'm trying to decide now how to best implement it.
I am thinking seriously about making it a dynamic subclass of the Camera class .. ie, a Camera instance owns a Frustum instance which is strongly associated with THAT Camera instance only.
Every Camera owns a Frustum, we simply call the culling methods of the active camera instance :) Sound ok?
I am thinking seriously about making it a dynamic subclass of the Camera class .. ie, a Camera instance owns a Frustum instance which is strongly associated with THAT Camera instance only.
Every Camera owns a Frustum, we simply call the culling methods of the active camera instance :) Sound ok?
Now the "active Camera" needs to take responsibility not just for setting up the View, but also for culling stuff during rending... should I simply move the call to RenderScene inside the Camera class, so that the Active Camera does all the rending in its own context? Anyone have a better idea which doesnt involve throwing stuff at the Camera to deal with?