Hello All
Im not sure about everybody, but I have had issues using Cloggy's D3DFunc GDK version with any version of DarkGDK from the November2008 upgrade to present 7.4. I actually resolved the issues myself by porting the parts of Cloggy's source code for DBPro to GDK.
But it has come to my attention that other users were having trouble getting it to work with the latest version of DarkGDK aswell, so I thought I would port the whole thing over into a set of easy to use classes.
All of the Functionality of D3DFunc 3.7.1 is wrapped into the classes, aswell as a bunch of extras that I have only just begun wrapping into it. These include Coloured Positionable Shadowed AA Text, and some Direct Image Access drawing functions that were written originally be Sephnroth.
The entire thing is contained in a derived class called "D3DLIB".
I have prefixed all of the function names, primarily to group them together inside intellisense so its a little more intuitive to find the functions. The Prefixes are as follows :
B3D_ - Batch 3D Drawing Functions
B2D_ - Batch 2D Drawing Functions
F3D_ - Normal 3D Drawing Functions
F2D_ - Normal 2D Drawing Functions
TXT_ - All of the AA Text Functions
IMG_ - All of the Direct Image Access functions
GDK_ - All of the "CORE" functions, camera, object creation and helpers.
There is a demonstration app that I have included in with the source code to demonstrate usage of all the major parts of the lib.
The Lib has some basic documentation with it, in the form of fairly extensive code comments, and I have setup the intellisense "docs" where it will show you the comment for the function you have highlighted.
I would like this to be considered as something similar to a "beta" release of D3DLIB. I would like to get some people to test it for me if possible and let me know any bugs they find so I can track them down and hopefully fix them. I also have a bunch of other classes that I am adding to D3DLIB, to extend it even further. There is a Terrain Generation class, that is built with DX meshes, it supports generating its own Alpha Maps, Environment Maps, has a built in set of A* Pathfinding functions and can handle "objects" placed on it, it stores where they are etc. There is a perlin noise image generation class, which doubles as the heightmap generator for the terrain class, its capable of generating its own normals maps for the noise maps it makes and can load and save its images, Plus various other classes that contain more or less "helper" functions, designed to make repetitive tasks simpler.
Here are some screenies of the demo :
Here is the Demo Program's source code(its in the attachement aswell, its just here so you can see how everything is working)
// DarkGDK Header file
#include "DarkGDK.h"
// D3DLib Header File - this is the only header from the lib that needs to be included in a project
#include "D3DLib.h"
// pointer to our D3DLIB class
D3DLIB* CC;
// general prototypes
void DrawNormals(int iObj, float fScale);
void PControl(float p_fMoveSpeed, float p_fMoveFastSpeed, float p_fTurnSpeed, float p_fPitchSpeed, float p_fTimeElapsedFloat);
void DarkGDK ( void )
{
// BASIC GDK SETUP
dbSyncOn ( );
dbSyncRate ( 60 );
if(dbAntiAliasAvailable())
{
dbSetDisplayModeAntialias(1024, 768, 32, 1, 4, 0);
}
else
{
dbSetDisplayModeVSync(1024, 768, 32, 1);
}
dbSetWindowPosition(0, 0);
dbSetWindowTitle(" -- D3DLIB -- D3DFUNC 3.7.1 DBPro version Ported to GDK 7.3/7.4 + Extras -- Combined Usage Demo ");
dbSetCameraRange(0, 1.0, 20000);
dbSetAmbientLight(25);
dbSetPointLight(0, 0, 50, -50);
dbSetLightRange(0, 200);
dbMakeLight(1);
dbSetPointLight(1, 0, 10, 8);
dbColorLight(1, dbRGB(200, 125, 50));
dbSetLightRange(1, 500);
dbMakeLight(2);
dbSetPointLight(2, 5, 10, 2);
dbColorLight(2, dbRGB(50, 225, 150));
dbSetLightRange(2, 400);
// This is where D3DLIB is initialized. You MUST instance the object, though you dont
// nessecarily have to use the heap, I cant guarentee this wont overrun your stack
// memory..
// Once you have instantiated the object, you need to call InitD3DLib next. This function
// is overloaded, you can either call it as it, and have a default of 20 fonts to work with
// and setup, or you can call it passing in the number of fonts you want.
CC = new D3DLIB();
CC->GDK_InitD3DLib();
// SETUP INITIAL BATCH 3D DOTS
CC->B3D_SetBatchSizeDot3D(11650);
for(int i = 0; i <= 11649; ++i)
{
CC->B3D_AddBatchDot3D(125-dbRnd(255), 125-dbRnd(255), 125-dbRnd(255));
}
// SETUP BATCH 2D DOTS - NOTE THESE CANT BE SEEN AT THE MOMENT THROUGH THE
// BACKDROP, TURNING IT OFF HOWEVER LOOKS NASTY(but you can see em then lol), SO IM WORKING ON FIXING THESE FUNC's
// DRAW ORDER SO THEY CAN BE SEEN IN 3D MODE..
CC->B2D_SetBatchSizeDot2D(1650);
for(int i = 0; i <= 1649; ++i)
{
CC->B2D_ColourAddBatchDot2D(dbRnd(1000), dbRnd(750), dbRGB(100+dbRnd(155), 100+dbRnd(155), 100+dbRnd(155)));
}
// SETUP 3D GDK OBJECTS
CC->F3D_MakeObjectTeapot(2);
dbColorObject(2, dbRGB(225, 155, 25));
dbSetObjectSpecular(2, dbRGB(225, 155, 25));
dbSetObjectSpecularPower(2, 26);
CC->F3D_MakeObjectPyramid(3, 5.0, 10.0, 5.0);
dbColorObject(3, dbRGB(225, 25, 125));
dbSetObjectSpecular(3, dbRGB(225, 25, 125));
dbSetObjectSpecularPower(3, 26);
CC->F3D_MakeObjectTorus(4, 2.0, 5.0, 32, 32);
dbColorObject(4, dbRGB(225, 155, 25));
dbSetObjectSpecular(4, dbRGB(225, 155, 25));
dbSetObjectSpecularPower(4, 26);
dbSetObjectEmissive(4, dbRGB(225, 155, 25));
dbSetObjectLight(4, true);
dbSetObjectAmbient(4, true);
dbGhostObjectOn(4, 2);
dbFadeObject(4, 65);
// SETUP 3D TEXT
CC->TXT_Text3D(10, 1, "HELLO WORLD !!", 0.75, 2, 1);
dbColorObject(10, dbRGB(225, 155, 25));
dbSetObjectSpecular(10, dbRGB(225, 25, 155));
dbSetObjectSpecularPower(10, 24);
dbSetObjectAmbient(10, true);
dbSetObjectLight(10, true);
dbPositionObject(2, 0, 10, -5);
dbPositionObject(3, -15, 2, -5);
dbPositionObject(4, 15, 2, -5);
// THIS IS THE IMAGE THAT WILL BE USED FOR THE PROGRESS BAR, IT IS GENERATED USING THE
// ExtendedImage_GPU funcations that Sephnroth wrote.
int x = 0;
dbMakeImageUsage(5, 256, 256, 1 );
CC->IMG_StartNew2dImageLineBatch();
CC->IMG_ClearImage(5, 0, 0, 0);
for(int i = 0; i <= 750; ++i)
{
CC->IMG_Add2dLineToImageBatch_GPU(dbRnd(255), dbRnd(255), dbRnd(255), dbRnd(255), dbRGB(dbRnd(255), dbRnd(255), dbRnd(255)), dbRGB(dbRnd(255), dbRnd(255), dbRnd(255)));
CC->IMG_DrawImageLine2D_GPU(5, dbRnd(0), dbRnd(0), dbRnd(255), dbRnd(255), 0xFF00FF00, 0xFFFF0000);
}
CC->IMG_Draw2dLineImageBatch_GPU(5);
// debug text, dont remember why it's here...
char* txt1 = new char[156];
strcpy(txt1, "This text is written with the TXT_BoxText function and will wrap text around as much as you like, just make the box big enough in the command");
// setup camera and local loop vars
dbPositionCamera(0, 0, 0);
dbRotateCamera(0, 0, 0);
dbPositionCamera(0, 10, -26);
dbXRotateCamera(14);
int nopress = 0;
int shownorm = 1;
float TxtX = 0.0;
float TxtY = 0.0;
float TxtZ = 0.0;
int dTxtX = 0.0;
int dTxtY = 0.0;
while ( LoopGDK ( ) )
{
// TEXT MOVEMENT
TxtX = 0 - (dbCos(dbTimer() / 40.0) * 25.0);
TxtY = 0 + (dbSin(dbTimer() / 50.0) * 50.0);
TxtZ = 55;
dTxtX = 480 + (dbCos(dbTimer() / 80.0) * 45.0);
dTxtY = 450 + (dbSin(dbTimer() / 55.0) * 45.0);
// Key Checks for input
if(dbKeyState(Key_1) && nopress == 0)
{
CC->GDK_SetOrthoProjectionZero(64);
nopress = 1;
}
if(dbKeyState(Key_2) && nopress == 0)
{
CC->GDK_RestoreCameraZero();
nopress = 1;
}
if(dbKeyState(Key_N) && nopress == 0)
{
++shownorm;
if(shownorm > 1) shownorm = 0;
nopress = 1;
}
if(dbKeyState(Key_T) && nopress == 0)
{
CC->B3D_SetBatchSizeDot3D(12650);
for(int i = 0; i <= 12649; ++i)
{
CC->B3D_AddBatchDot3D(125-dbRnd(255), 125-dbRnd(255), 125-dbRnd(255));
}
nopress = 1;
}
if(dbKeyState(Key_C) && nopress == 0)
{
CC->IMG_ClearImage(5, 0, 0, 0);
nopress = 1;
}
// check for movement key presses and set nopress as appropriate
if(dbKeyState(Key_W) || dbKeyState(Key_S) || dbKeyState(Key_A) || dbKeyState(Key_D))
{
nopress = 1;
}
// reset keypress checker
if(dbScanCode() == 0) nopress = 0;
// 3D DRAWING
CC->B3D_BatchDrawDot3D(0, 1, 0, 2);
dbPasteImage(5, 0, dbScreenHeight()-dbGetImageHeight(5), 1);
CC->F3D_Circle3DCZ(10.0, 15, 15, 15, 25, 25, 25, 0xFF00FF00, 0xFFFF0000);
CC->F3D_Ellipse3DCZ(10.0, 15, 15, 15, 15, 25, 25, 25, 0xFF00FF00, 0xFFFF0000);
dbPositionObject(4, TxtX, TxtY, TxtZ);
// Draw our Object Normals if we are told to
if(shownorm == 1)
{
DrawNormals(2, 0.15);
DrawNormals(10, 0.05);
DrawNormals(3, 1.0);
DrawNormals(4, 1.5);
}
//debug text
char* progTik = new char[64];
strcpy(progTik, "Progress Bar Sprite % : ");
strcat(progTik, dbStr(x));
char* buf = new char[1024];
strcpy(buf, "Frames Per Second : ");
strcat(buf, dbStr(dbScreenFPS()));
strcat(buf, "nCamera Pos X : ");
strcat(buf, dbStr(dbCameraPositionX(0)));
strcat(buf, "nCamera Pos Y : ");
strcat(buf, dbStr(dbCameraPositionY(0)));
strcat(buf, "nCamera Pos Z : ");
strcat(buf, dbStr(dbCameraPositionZ(0)));
strcat(buf, "nCamera Ang X : ");
strcat(buf, dbStr(dbCameraAngleX(0)));
strcat(buf, "nCamera Ang Y : ");
strcat(buf, dbStr(dbCameraAngleY(0)));
strcat(buf, "nCamera Ang Z : ");
strcat(buf, dbStr(dbCameraAngleZ(0)));
strcat(buf, "nn[WSAD]+[Mouse] - Camera Movement");
strcat(buf, "nn[1] - Set Orthogonal Camera View(3D Dots become 'Layered')");
strcat(buf, "n[2] - Set Normal Camera View(3D Dots become 'Normal')");
strcat(buf, "n[N] - Show/Hide 3D Object Normals");
strcat(buf, "n[T] - Insta-Redraw 12,000 3D Dots Randomly");
strcat(buf, "n[C] - Clear ExtendedImage - watch redraw");
strcat(buf, "nn");
strcat(buf, "This is nice AntiAliased Text :)");
strcat(buf, "nAll of the commands are contained in derived class - D3DLIB");
strcat(buf, "nUse Intellisense to check them out, they have all been prefixed");
strcat(buf, "nto group them together specifically for intellisense.");
strcat(buf, "nF2D - 2D Functions -- B2D - 2D Batch Functions");
strcat(buf, "nF3D - 3D Functions -- B3D - 3D Batch Functions");
strcat(buf, "nTXT - AA Text Functions -- IMG - DXImage Access Functions");
strcat(buf, "nGDK - Core Functions, Cameras and Helpers");
// 2D DRAWING
CC->B2D_BatchDrawDot2D(0);
CC->F2D_PolygonColour(750, 100, 25, 8, 1, 55.0, dbRGB(100+dbRnd(155), 100+dbRnd(155), 100+dbRnd(155)));
CC->F2D_RoundRectangle(360, 550, 560, 750, 25, 1);
CC->F2D_GradientBox(0, 0, 400, 400, dbRGB(255, 0, 0), dbRGB(0, 255, 0), dbRGB(0, 0, 255), dbRGB(155, 155, 155));
CC->F2D_Polygon2Radius(1000, 650, 75, 100, 32, 1, 90);
// PROGRESS BAR
++x;
if(x > 99) x = 0;
CC->F2D_ProgressBar(50, 350, 256, 20, 0, 99, x, 5);
//IMAGE REDRAW
CC->IMG_DrawImageLine2D_GPU(5, 0, 0, dbRnd(255), dbRnd(255), 0xFF00FF00, 0xFFFF0000);
CC->IMG_DrawImageLine2D_GPU(5, 255, 0, 255-dbRnd(255), dbRnd(255), dbRGB(200, 0, 200), dbRGB(255, 255, 0));
// TEXT BLOCK
CC->TXT_StartText();
CC->TXT_DrawAAText(3, dbObjectScreenX(4)-50, dbObjectScreenY(4)-50, ALIGN_LEFT, "Ghosted Torus");
CC->TXT_DrawAAText(3, dbObjectScreenX(10)-70, dbObjectScreenY(10)-25, ALIGN_LEFT, "3D Object Based Text");
CC->TXT_DrawAAText(3, dbObjectScreenX(2)-50, dbObjectScreenY(2)-50, ALIGN_LEFT, "Token Teapot");
CC->TXT_DrawAAText(3, dbObjectScreenX(3)-70, dbObjectScreenY(3)-70, ALIGN_LEFT, "4-Side Pyramid Primitive");
CC->TXT_DrawAATextShadow(3, 50, 330, ALIGN_LEFT, progTik, 3, 2, dbRGB(50, 50, 50));
CC->TXT_DrawAATextShadow(3, 0, dbScreenHeight()-dbGetImageHeight(5)-20, ALIGN_LEFT, "Progress Bar - Generated Image(w/Red Shadow)", 3, 2, dbRGB(255, 0, 0));
CC->TXT_DrawAATextColour(2, 0, 0, ALIGN_LEFT, buf, dbRGB(255, 225, 50));
CC->TXT_BoxText(1, 512, 0, 300, 300, ALIGN_CENTER, ALIGN_CENTER, txt1);
CC->TXT_DrawAATextColourShadow(3, dTxtX, dTxtY, ALIGN_LEFT, "IM MEANT TO BE MOVING AROUND !!(w/Green Shadow)", dbRGB(100+dbRND(155), 100+dbRND(155), 100+dbRND(155)), 2, 1, dbRGB(20, 155, 20));
CC->TXT_BoxTextColourShadow(3, 360, 550, 200, 200, ALIGN_CENTER, ALIGN_CENTER, "All of these blocks of text that are displayed at the moment, were created essentially through an 'ID3DXSprite' object ! They can have coloured shadows too !!", dbRGB(255, 25, 25), 2, 1, dbRGB(50, 255, 250));
CC->TXT_EndText();
//WSAD+Mouse to move
PControl(0.05, 0.1, 0.05, 0.05, 20.0);
dbSync ( );
delete []buf;
delete []progTik;
}
// CLEANUP
// TODO - check device needs to be release on exit or does GDK do it if we have captured it ??
delete []txt1;
delete CC;
return;
}
// cheap movement controls - FPS style, hold shift for move faster.. WSAD+Mouse to move
void PControl(float p_fMoveSpeed, float p_fMoveFastSpeed, float p_fTurnSpeed, float p_fPitchSpeed, float p_fTimeElapsedFloat)
{
float fMoveSpeed = p_fMoveSpeed * p_fTimeElapsedFloat;
float fMoveFastSpeed= p_fMoveFastSpeed * p_fTimeElapsedFloat;
float fTurnSpeed = p_fTurnSpeed * p_fTimeElapsedFloat;
float fPitchSpeed = p_fPitchSpeed * p_fTimeElapsedFloat;
int MX=dbMouseMoveX();
int MY=dbMouseMoveY();
dbRotateCamera(0, (dbCameraAngleX()+(MY*fPitchSpeed*0.1)), (dbCameraAngleY()+(MX*fTurnSpeed*0.1)), dbCameraAngleZ());
// forwards
if(dbKeyState(Key_W))
{ // fast speed
if(dbKeyState(Key_LShift))
{
dbMoveCamera(fMoveFastSpeed);
}
else // normal speed
{
dbMoveCamera(fMoveSpeed);
};
};
// backwards
if(dbKeyState(Key_S))
{
if(dbKeyState(Key_LShift))
{
dbMoveCamera(0-fMoveFastSpeed);
}
else
{
dbMoveCamera(0-fMoveSpeed);
};
};
// strafe left
if(dbKeyState(Key_A))
{
if(dbKeyState(Key_LShift))
{
dbMoveCameraLeft(0, fMoveFastSpeed);
}
else
{
dbMoveCameraLeft(0, fMoveSpeed);
};
};
//strafe right
if(dbKeyState(Key_D))
{
if(dbKeyState(Key_LShift))
{
dbMoveCameraRight(0, fMoveFastSpeed);
}
else
{
dbMoveCameraRight(0, fMoveSpeed);
};
};
if(dbKeyState(Key_Num8))
{ //fwd
dbMoveCamera(fMoveSpeed);
};
if(dbKeyState(Key_NumForwardSlash))
{//fwd fast
dbMoveCamera(fMoveFastSpeed);
};
if(dbKeyState(Key_Num2))
{//backward
dbMoveCamera(-fMoveSpeed);
};
if(dbKeyState(Key_Num0))
{//backward fast
dbMoveCamera(-fMoveFastSpeed);
};
if(dbKeyState(Key_Num4))
{//turn left
dbRotateCamera(dbCameraAngleX(), dbWrapValue(dbCameraAngleY()-fTurnSpeed), dbCameraAngleZ());
};
if(dbKeyState(Key_Num6))
{//turn right
dbRotateCamera(dbCameraAngleX(), dbWrapValue(dbCameraAngleY()+fTurnSpeed), dbCameraAngleZ());
};
if(dbKeyState(Key_NumLock))
{//Roll Left
dbRollCameraLeft(fTurnSpeed);
};
if(dbKeyState(Key_NumLock))
{//Roll Right
dbRollCameraRight(fTurnSpeed);
};
if(dbKeyState(Key_Num9))
{//Up
dbPitchCameraUp(90);
dbMoveCamera(fMoveSpeed);
dbPitchCameraDown(90);
};
if(dbKeyState(Key_NumStar))
{//Up Fast
dbPitchCameraUp(90);
dbMoveCamera(fMoveFastSpeed);
dbPitchCameraDown(90);
};
if(dbKeyState(Key_Num3))
{//Down
dbPitchCameraDown(90);
dbMoveCamera(fMoveSpeed);
dbPitchCameraUp(90);
};
if(dbKeyState(Key_NumPeriod))
{//Down Fast
dbPitchCameraDown(90);
dbMoveCamera(fMoveFastSpeed);
dbPitchCameraUp(90);
};
if(dbKeyState(Key_Num7))
{//Pitch down
dbRotateCamera(dbWrapValue(dbCameraAngleX()+fPitchSpeed),dbCameraAngleY(), dbCameraAngleZ());
};
if(dbKeyState(Key_Num1))
{//Pitch Up
dbRotateCamera(dbWrapValue(dbCameraAngleX()-fPitchSpeed),dbCameraAngleY(), dbCameraAngleZ());
};
if(dbKeyState(Key_NumLock))
{//Roll Left
dbRollCameraLeft(fPitchSpeed);
};
if(dbKeyState(Key_NumMinus))
{//Roll Right
dbRollCameraRight(fPitchSpeed);
};
if(dbKeyState(Key_Num5))
{// Resets the camera to 0, 0, 0 and looking straight ahead, good if you stuff up the look angles with rotation
dbRotateCamera(0,0,0);
};
};
// need to get total amount of verts for 3dline batch b4 we draw them, might be an idea to
// get the positions at the same time and store them in an array, well see which works best
// this function will draw 1 "batch" for each limb at the moment, need to optimize it
// to only use 1 batch no matter how many limbs the object has, this will be achieved through having
// to iterate through the object twice, and probaly doing it the first time from an "InitDrawNormals"
// function, which would get the total amount of verts in the objects limbs, so we can set the batch size
// then just add each limbs vert norm/data positions to the batch, with a single draw call at the end
// It will speed up the drawtime.
void DrawNormals(int iObj, float fScale)
{
// Amount of scale applied to drawn normals
float scale = fScale;
// Limb Number tracker
int LimbNum = 0;
// Object we are working on, must be valid, no checks are performed here
int ObjID = iObj;
// Repeat for each limb in the object, start at limb zero
while(dbLimbExist(ObjID, LimbNum))
{
// Lock Mesh
dbLockVertexDataForLimb(ObjID, LimbNum);
// Vertex count
int vCount = dbGetVertexDataVertexCount() - 1;
// Setup batch
CC->B3D_SetBatchSizeLine3D(vCount + 1);
// Loop through verts
for(int i = 0; i <= vCount; ++i)
{
// Read current vertex position + Object Position
float vX = dbGetVertexDataPositionX(i) + (dbObjectPositionX(ObjID));
float vY = dbGetVertexDataPositionY(i) + (dbObjectPositionY(ObjID));
float vZ = dbGetVertexDataPositionZ(i) + (dbObjectPositionZ(ObjID));
// Read current vertex normals (and scale)
float vNX = dbGetVertexDataNormalsX(i) * scale;
float vNY = dbGetVertexDataNormalsY(i) * scale;
float vNZ = dbGetVertexDataNormalsZ(i) * scale;
// Add to batch
CC->B3D_AddBatchLine3DGC(vX, vY, vZ, vX + vNX, vY + vNY, vZ + vNZ, 0xFF00FF00, 0xFFFF0000);
}
//` Unlock mesh
dbUnlockVertexData();
CC->B3D_BatchDrawLine3D(0, 1, 0, 2);
++LimbNum;
}
}
As you can see, the usage of all of the functions is achieved through the D3DLIB derived class, which inherits from all of the others and maintains all of the global variables etc. It is also quite simple an intuitive. Plus the speed is simply amazing, to do all of the drawing operations in this demo, using GDK commands alone would result in it crawling at a snail's pace.....
Attachment ZIP contains all of the source code for the library, aswell as the source code for the DEMO program and the actual project that I compiled the DEMO from, so you can see how I have it setup, just add the D3DLIB.vcproj to an existing solution.
Note that the EXE in the attachment was compiled with DarkGDK 7.4 and most of the testing I did was also using that version of GDK.
I hope this helps a few people. Ill be posting any updates to the library here in this thread, ill update the attachement in this post so you will always find the latest version here.
Please note, you do not have to use the included classes, the way everything is working together is quite simple, and it would not be very hard to extract the functions from the classes and use them on their own if you wish to.
EDIT : A new attachment as of 28th Auguest, it fixes the following :
* GDK_GetDesktopWidth();
* GDK_GetDesktopHeight();
* GDK_GetDesktopDespth();
Those functions are basically empty in cloggy's library, they return NULL values, hence the 0's. I just made a couple of WinAPI calls to get the desktop res data like this :
// Get a handle to the desktop window
g_hDesktop = GetDesktopWindow();
// Get the size of screen to the variable desktop
GetWindowRect(g_hDesktop, &g_DesktopSize);
DEVMODE DispDev;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DispDev);
g_DesktopDepth = (int)DispDev.dmBitsPerPel;
g_hDesktop is a HWND handle to the desktop and is global if you want to use it... the DEVMODE structure is local and will go out of scope after the lib is instanced.
If it ain't broke.... DONT FIX IT !!!