[EDIT 2: Arg, Mabie I should have
Dark Basic Pro SDK instead of
Dark Basic SDK in the title
]
[EDIT: Note that you will currently have to compile the dark basic sdk with this code yourself to use these commands if needed ]
Hi,
I didn't want to let this die out on my hard drive as I don't know when I will use it for a project. Also, this isn't something I would necessarily propose to be included into the next Dark Basic Pro's update as these commands have no usefulness to DBPro users alone. But, these commands are aimed at third party dll developers who would like to create their own 3d objects directly with DriectX functions and would like to display them correctly with each camera and be z-sorted along with the other dbpro objects. As for example, I want to create a terrain directly with DirectX functions to build/manipulate the terrain mesh with. These commands will allow me to show the terrain in the dbpro's camera(s) of my choosing and not have to worry about z-sorting.
So, I present the code here for people who know how to set up the Dark Basic SDK and compile it on their machine. If these functions happen to get included in the next DBPro update then all the better( for me at least
). But as with the new PERFFREQ command, I don't have the equivalent dark gdk command code as I don't have dark gdk setup( being lazy ).
New Commands:
MANUAL SYNC BEGIN FastSync
MANUAL CAMERA SYNC BEGIN Returns: Current Camera
MANUAL CAMERA SYNC END Returns: boolean
MANUAL SYNC END
These four functions are used instead of the SYNC command ( Actually, these four functions were created from dividing up the SYNC command itself into four parts ). First call the MANUAL SYNC BEGIN command with a parameter of 0 or 1 ( 1 to use FastSync ). In this Dark Basic SDK code, the camera numbering starts at 1 instead of 0. So when calling MANUAL CAMERA SYNC BEGIN next, it will return the current camera+1 it's processing for rendering. Just get it's return value and subtract one to get the current camera you want to deal with. After doing what you want to do with this current camera, call MANUAL CAMERA SYNC END. MANUAL CAMERA SYNC END returns a value of 0 or 1. If it returns 1, then there will be another camera that needs to be processed for rendering. Call MANUAL CAMERA SYNC BEGIN again to process it. When MANUAL CAMERA SYNC END returns a 0 then call MANUAL SYNC END to end the whole sync. Short code snippet below shows an example on how I used it in the attached demo:
MANUAL SYNC BEGIN 0
repeat
CurrentCamera=MANUAL CAMERA SYNC BEGIN()
if CurrentCamera>1
if CurrentCamera=2 and hide3DObj1=0
GMMT DRAW 3D OBJECT CurrentCamera-1
endif
if CurrentCamera=3 and hide3DObj2=0
GMMT DRAW 3D OBJECT CurrentCamera-1
endif
endif
NextCamera=MANUAL CAMERA SYNC END()
until NextCamera=0
MANUAL SYNC END
The attached demo demostrates drawing a triangle mesh directly made with DirectX functions via a little test dll that I made. The two functions in the code below, GMMT INIT and GMMT DRAW 3D OBJECT , are made from the test dll( I have no intentions to release this dll as it is only a test dll. This post isn't intended on how to create a third party dll so I will not include it here ).
Here's what the full DBPro source looks like for this Demo:
rem Manual Sync Test
rem GLOBALS
GLOBAL Global_RightMouseClick as INTEGER
rem ### SET UP DISPLAY ###
set window on
set display mode DESKTOP WIDTH(),DESKTOP HEIGHT(),0, 0
Set Window Position 0,0
Set Window Layout 0,0,0
Maximize Window
sync on
sync rate 60
rem set cameras
make camera 1
set camera view 1,0,0,DESKTOP WIDTH(),DESKTOP HEIGHT()/2
position camera 1,0,0,-1000
color backdrop 1, rgb(32,64,64)
set camera fov 1,45
make camera 2
set camera view 2,0,DESKTOP HEIGHT()/2,DESKTOP WIDTH(),DESKTOP HEIGHT()
position camera 2,0,0,-1000
color backdrop 2, rgb(64,32,64)
set camera fov 2,45
GMMT INIT
make object sphere 1,50
CamID=1
hide3DObj1=0
hide3DObj2=0
key_3=0
key_4=0
repeat
rem press key 1
if keystate(2)=1 then CamID=1
rem press key 2
if keystate(3)=1 then CamID=2
MovementControls(CamID)
rem press key 3
if keystate(4)=1 and key_3=0
key_3=1
hide3DObj1=1-hide3DObj1
endif
if keystate(4)=0 and key_3=1
key_3=0
endif
rem press key 4
if keystate(5)=1 and key_4=0
key_4=1
hide3DObj2=1-hide3DObj2
endif
if keystate(5)=0 and key_4=1
key_4=0
endif
text 10,10,"Currently controlling camera "+str$(CamID)
text 10,30,"W/S moves Forward/Backward"
text 10,50,"Click right mouse button to rotate current camera"
text 10,70,"Press 1 to control cam 1"
text 10,90,"Press 2 to control cam 2"
text 10,110,"Press 3 to hide/show DirectX object in cam 1"
text 10,130,"Press 4 to hide/show DirectX object in cam 2"
text 10,150,"Press ESC to end program"
MANUAL SYNC BEGIN 0
repeat
CurrentCamera=MANUAL CAMERA SYNC BEGIN()
if CurrentCamera>1
if CurrentCamera=2 and hide3DObj1=0
GMMT DRAW 3D OBJECT CurrentCamera-1
endif
if CurrentCamera=3 and hide3DObj2=0
GMMT DRAW 3D OBJECT CurrentCamera-1
endif
endif
NextCamera=MANUAL CAMERA SYNC END()
until NextCamera=0
MANUAL SYNC END
until escapekey()=1
minimize window
end
` User Input
Function MovementControls(CamID as INTEGER)
LOCAL local_CameraAngleX as FLOAT
LOCAL local_CameraAngleY as FLOAT
LOCAL local_mmovex as INTEGER
LOCAL local_mmovex as INTEGER
local_mmovex = mousemovex()
local_mmovey = mousemovey()
` Camera Control:
` Move Camera Position
`W=17
if (keystate(17)=1)
Move Camera CamID,10
endif
`S=31
if (keystate(31)=1)
Move Camera CamID,-10
endif
`A=30
if (keystate(30)=1)
`
endif
`D=32
if (keystate(32)=1)
`
endif
` Rotate camera on right click
if mouseclick()=2
if Global_RightMouseClick = 0
Global_RightMouseClick = 1
hide mouse
endif
` keep mouse centered when rotating camera
position mouse screen width()/2, screen height()/2
` Get Current Anlges
local_CameraAngleX = Camera Angle X(CamID)
local_CameraAngleY = Camera Angle Y(CamID)
` create a rotation axis based on controller movement
local_CameraAngleX = WrapValue ( local_CameraAngleX + (local_mmovey) )
local_CameraAngleY = WrapValue ( local_CameraAngleY + (local_mmovex) )
` rotate camera and lock x-axis between 0 and 90
if ((( local_CameraAngleX >= 0 ) and ( local_CameraAngleX <= 90 )) or (( local_CameraAngleX >= 270 ) and ( local_CameraAngleX < 360 )))
XRotate Camera CamID, local_CameraAngleX
endif
YRotate Camera CamID, local_CameraAngleY
else
if mouseclick()=0 and Global_RightMouseClick = 1
Global_RightMouseClick = 0
position mouse screen width()/2, screen height()/2
show mouse
endif
endif
EndFunction
A demo is attached so you can see what it does. It will show two cameras, one on top and the other on bottom like a multiplayer type view. My GMMT DRAW 3D OBJECT command draws a triangle made with directx functions from the dll in each window with a dbpro sphere object showing in the center of it. Instructions will be displayed when running the program.
Here is the full c/c++ source code for these manual sync commands.
I added them after the function
DARKSDK void ConstantNonDisplayUpdate(void) in the DBDLLCore.cpp file.
If you want to add them in a different place, go for it.
/*
## Added in DBDLLCore resource string table
MANUAL SYNC BEGIN%L%?ManualSyncBegin@@YAXH@Z%FastSync
MANUAL CAMERA SYNC BEGIN[%L%?ManualCameraSyncBegin@@YAHXZ%Returns: Current Camera
MANUAL CAMERA SYNC END[%L%?ManualCameraSyncEnd@@YAHXZ%Returns: boolean
MANUAL SYNC END%0%?ManualSyncEnd@@YAXXZ
*/
// Added after DARKSDK void ConstantNonDisplayUpdate(void)
// In DBDLLCore.cpp
bool g_bSuspendScreenOperations;
bool g_bDetermineIfNextCameraNeedsRenderTargetPrepared;
int g_iSkipSyncRateCodeAkaFastSync;
//DARKSDK void ManualSyncBegin(int iSkipSyncRateCodeAkaFastSync);
//DARKSDK int ManualCameraSyncBegin();
//DARKSDK int ManualCameraSyncEnd();
//DARKSDK void ManualSyncEnd();
DARKSDK void ManualSyncBegin(int iSkipSyncRateCodeAkaFastSync)
{
// Skip this phase if app has been shut down (always active off)
if ( g_bAlwaysActiveOneOff )
return;
g_iSkipSyncRateCodeAkaFastSync = iSkipSyncRateCodeAkaFastSync;
// V111 - 110608 - FASTSYNC should not use sync delay!
if ( iSkipSyncRateCodeAkaFastSync==0 )
{
AccurateTimer Timer;
// Skip refreshes causing even faster FPS rates!
if(g_dwManualSuperStepSetting>0)
{
if(Timer.Get()-g_dwRecordedTimer<g_dwManualSuperStepSetting)
return;
}
// Force FPS
if(g_dwSyncRateSettingSize>0)
{
DWORD dwDifference = GetNextSyncDelay();
while(Timer.Get()-g_dwRecordedTimer < dwDifference)
if(ProcessMessagesOnly()==1) return;
}
else
{
// Need to ad least process these monitors
ConstantNonDisplayUpdate();
}
// u74b7 - Only update the sync timer if not using fastsync
// Record time of update
g_dwRecordedTimer = Timer.Last();
}
// leefix - 260604 - u54 - in case input wants single data-grab functionality
if(g_Input_ClearData) g_Input_ClearData();
// If using External Graphics API
if(g_bExternalDisplayActive)
{
// leeadd - 160306 - u60 - camera zero off suspends normal operations
g_bSuspendScreenOperations = false;
if ( !(g_dwSyncMask & 1) )
{
// flag the suspension of regular screen zero activity
g_bSuspendScreenOperations = true;
}
if ( g_bSuspendScreenOperations==false )
{
// If BSP used, compute responses
if(g_World3D_End) g_World3D_End();
if(g_Basic3D_AutomaticCollisionEnd) g_Basic3D_AutomaticCollisionEnd();
// Draw Phase : Store backbuffer before any 3D is drawn..
if(g_Sprites_SaveBack) g_Sprites_SaveBack();
// Draw Phase : Draw Sprites Last
if(g_bDrawSpritesFirst==false)
if(g_Sprites_Update)
g_Sprites_Update();
// Ensures AutoStuff is first to be rendered
if(g_bDrawAutoStuffFirst==true)
{
if(g_bSceneStarted)
{
// leeadd - 071108 - U71 - render quad if flagged
if ( g_bDrawQuadInSync )
{
if(g_Basic3D_RenderQuad)
{
if(g_Basic3D_RenderQuad(0)==1)
{
g_Camera3D_RunCode ( 0 );
g_Basic3D_RenderQuad(1);
}
}
}
g_GFX_End();
if ( g_bCanRenderNow )
g_GFX_Render();
}
g_bSceneStarted=true;
g_GFX_Begin();
// restore before-Sprites-drawn on new screen render
if(g_Sprites_RestoreBack) g_Sprites_RestoreBack();
}
// Draw Phase : Draw Sprites First
if(g_bDrawSpritesFirst==true)
if(g_Sprites_Update)
g_Sprites_Update();
}
// Draw Phase : Draw 3D Gemoetry
if( g_Camera3D_StartSceneInt )
{
// Reset polycount and drawprim count
if ( g_pGlob ) g_pGlob->dwNumberOfPolygonsDrawn=0;
if ( g_pGlob ) g_pGlob->dwNumberOfPrimCalls=0;
// Disable backdrop if camera zero disabled
int iMode = 0; if ( g_bSuspendScreenOperations ) iMode = 1;
// U75 - 080410 - ensure animation in scene only calculated once (on SYNC)
if ( iSkipSyncRateCodeAkaFastSync==0 )
if(g_Basic3D_UpdateAnimationCycle)
g_Basic3D_UpdateAnimationCycle();
// Draw all 3D - all cameras loop
g_Camera3D_StartSceneInt ( iMode );
}
}
}
DARKSDK int ManualCameraSyncBegin()
{
if(g_bExternalDisplayActive)
{
// Draw Phase : Draw 3D Gemoetry
if( g_Camera3D_StartSceneInt )
{
// leeadd - 150306 - u60b3 - sync mask excludes cameras fom rendering
bool bDetermineIfNextCameraNeedsRenderTargetPrepared = true;
int iThisCamera = 1 + g_Camera3D_GetRenderCamera();
if ( iThisCamera <= 32 )
{
// camera 0 - 31 can be masked
DWORD dwCamBit = 1;
if ( iThisCamera > 1 ) dwCamBit = dwCamBit << (DWORD)(iThisCamera-1);
dwCamBit = dwCamBit & g_dwSyncMask;
int iNextCamera = iThisCamera;
if ( dwCamBit==0 ) iThisCamera = 0;
// leefix - 130906 - u63 - discovered when using many SYNC MASKS, a later pass would wipe out camera render targets at the FinishStop
DWORD dwNextCamBit = 1;
dwNextCamBit = dwNextCamBit << (DWORD)(iNextCamera);
dwNextCamBit = dwNextCamBit & g_dwSyncMask;
if ( dwNextCamBit==0 )
{
// the next camera does NOT render anything, so skip preparing the render target for it (at the Finish step)
bDetermineIfNextCameraNeedsRenderTargetPrepared=false;
}
}
g_bDetermineIfNextCameraNeedsRenderTargetPrepared = bDetermineIfNextCameraNeedsRenderTargetPrepared;
if ( iThisCamera > 0 )
{
// Push all polygons for 3D components
for(g_pGlob->dwRedrawPhase=0; g_pGlob->dwRedrawPhase<g_pGlob->dwRedrawCount; g_pGlob->dwRedrawPhase++)
{
// u74b8 - replace hard-coded calls with a dynamic list of function pointers
ExecuteRenderList();
}
}
return iThisCamera;
}
}
return -1;
}
DARKSDK int ManualCameraSyncEnd()
{
if(g_bExternalDisplayActive)
{
// Draw Phase : Draw 3D Gemoetry
if( g_Camera3D_StartSceneInt )
{
// Next camera or finish..
if(g_Camera3D_FinishSceneEx(g_bDetermineIfNextCameraNeedsRenderTargetPrepared)==0)
{
// Another camera view must be rendered, render current one now
return 1;
}
else
{
// No more camera views to render
//break;
return 0;
}
}
}
return 0;
}
DARKSDK void ManualSyncEnd()
{
// If using External Graphics API
if(g_bExternalDisplayActive)
{
// Draw Phase : Draw 3D Gemoetry
if( g_Camera3D_StartSceneInt )
{
// leeadd - 071107 - U71 - after 3D operations, direct whether SPRITES/2D/IMAGE
// drawing is to take place by default (bitmap or camera zero)
if ( g_bDrawEntirelyToCamera==true ) g_Camera3D_RunCode ( 1 );
}
if ( g_bSuspendScreenOperations==false )
{
// Ensures AutoStuff is last to be rendered
if(g_bDrawAutoStuffFirst==false)
{
if(g_bSceneStarted)
{
// leeadd - 071108 - U71 - render quad if flagged
if ( g_bDrawQuadInSync )
{
if(g_Basic3D_RenderQuad)
{
if(g_Basic3D_RenderQuad(0)==1)
{
g_Camera3D_RunCode ( 0 );
g_Basic3D_RenderQuad(1);
}
}
}
g_GFX_End();
if ( g_bCanRenderNow )
g_GFX_Render();
}
g_bSceneStarted=true;
g_GFX_Begin();
// restore before-Sprites-drawn on new screen render
if(g_Sprites_RestoreBack) g_Sprites_RestoreBack();
}
// If BSP used, set response check
if(g_World3D_Start) g_World3D_Start();
if(g_Basic3D_AutomaticCollisionStart) g_Basic3D_AutomaticCollisionStart();
}
}
if (g_iSkipSyncRateCodeAkaFastSync>0)
{
//V111 - 110608 - no need for this as FASTSYNC just used to render cameras (main SYNC handles proper update per cycle)
//ConstantNonDisplayUpdate(); // lee - 100208 - moved from ConstantNonDisplayUpdate(), added by Mike in 2005
g_bCanRenderNow = true;
}
else
{
ProcessMessagesOnly();
ConstantNonDisplayUpdate();
g_bCanRenderNow = true;
}
}