Render Server Objects
by Michel De Messieres · 01/31/2007 (2:41 pm) · 4 comments
The basic plan is to add a link between every server object and client object and then use this to render the server when the client renders. You can use this link for other debugging purposes as well but this code will just set up rendering.
Eventually you may want to wrap the code in TORQUE_DEBUG #ifdef statements.
First we'll add a link variable to NetObject.
Add to the public variables of netObject.h:
Add this to the netObject::netObject() constructor at the top of netObject.cc
Now to form the link as objects are added. Modify onAdd() in netObject.cc
Now we want the objects to render - I use ShapeBase.cc as the entry point
Add the following code to the very beginning of ShapeBase::prepRenderImage() in ShapeBase.cc
Now a little further down in prepRenderImage() is a call to animate(), change it to be like this:
The reason for the above is you definitely do not want the server object to change itself from the render calls - normally it won't get those calls and you want to see how the server object is behaving when the debug feature is off. There may be other places in your code you'll need to make adjustments to make sure prepRenderImage is not letting your server object update.
Add the following code to the very beginning of ShapeBase::renderObject() in ShapeBase.cc
Now we have to fix a few things that will crash if you try to render a server object.
First, the server object won't have materials, which is ok since they will just render a nice ghostly gray and that will make it easy to tell it apart from the client. We just have to make a small fix so it won't crash.
In tsMesh.cc find the following code. I added the first line to check if materials is NULL
Another spot is sceneState.cc - server objects won't have a valid zone - I have not investigated this carefully and someone with experience here can probably suggest a cleaner method.
Find the following line
and change it to
Last thing is to add a console option so you can toggle the system on and off
Add to tsShapeInstance.cc at the bottom of TSShapeInstance::init()
Add to tsMesh.h after the comment shown below
/// on load...optionally convert primitives to other form
Add the following line to tsMesh.cc before this line:
bool TSMesh::smUseTriangles = false; // convert all primitives to triangle lists on load
Now link it up in the script - I have it mapped to the g key
Add to default.binds.cs
And finally add to the config.cs file
Now you should be able to haunt your game with server objects by pressing g.
Eventually you may want to wrap the code in TORQUE_DEBUG #ifdef statements.
First we'll add a link variable to NetObject.
Add to the public variables of netObject.h:
NetObject *m_myLocalPartner; // direct link to local ghost/server object for debugging
Add this to the netObject::netObject() constructor at the top of netObject.cc
m_myLocalPartner = NULL; // direct link to local ghost/server object for debugging
Now to form the link as objects are added. Modify onAdd() in netObject.cc
bool NetObject::onAdd()
{
if(mNetFlags.test(ScopeAlways))
setScopeAlways();
// this debug code will only run on the server machine
if( isClientObject() && !m_myLocalPartner )
if( NetConnection::getConnectionToServer() )
if( NetConnection::getLocalClientConnection() )
{
S32 ghostIndex = NetConnection::getConnectionToServer()->getGhostIndex( this );
NetObject * pMatch = NetConnection::getLocalClientConnection()->resolveObjectFromGhostIndex( ghostIndex );
m_myLocalPartner = pMatch;
if( pMatch )
pMatch->m_myLocalPartner = this;
}
return Parent::onAdd();
}Now we want the objects to render - I use ShapeBase.cc as the entry point
Add the following code to the very beginning of ShapeBase::prepRenderImage() in ShapeBase.cc
if( TSMesh::smRenderServer )
{
if( m_myLocalPartner && isClientObject() )
( (ShapeBase*) m_myLocalPartner )->prepRenderImage( state, stateKey, startZone, modifyBaseState );
}Now a little further down in prepRenderImage() is a call to animate(), change it to be like this:
if (mShapeInstance && isClientObject() )
mShapeInstance->animate();The reason for the above is you definitely do not want the server object to change itself from the render calls - normally it won't get those calls and you want to see how the server object is behaving when the debug feature is off. There may be other places in your code you'll need to make adjustments to make sure prepRenderImage is not letting your server object update.
Add the following code to the very beginning of ShapeBase::renderObject() in ShapeBase.cc
if( TSMesh::smRenderServer )
{
if( m_myLocalPartner && isClientObject() )
( (ShapeBase*) m_myLocalPartner )->renderObject( state, image );
}Now we have to fix a few things that will crash if you try to render a server object.
First, the server object won't have materials, which is ok since they will just render a nice ghostly gray and that will make it easy to tell it apart from the client. We just have to make a small fix so it won't crash.
In tsMesh.cc find the following code. I added the first line to check if materials is NULL
if( materials ) // Added this line
if ( ((TSShapeInstance::smRenderData.materialIndex ^ draw.matIndex) &
(TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial)) != 0)
setMaterial(draw.matIndex,materials);Another spot is sceneState.cc - server objects won't have a valid zone - I have not investigated this carefully and someone with experience here can probably suggest a cleaner method.
Find the following line
AssertFatal(pWalk != NULL, "Error, object must exist in at least one zone to call this!");
and change it to
if( !pWalk ) return; // debug rendering a ghosted object so this is ok AssertFatal(pWalk != NULL, "Error, object must exist in at least one zone to call this!");
Last thing is to add a console option so you can toggle the system on and off
Add to tsShapeInstance.cc at the bottom of TSShapeInstance::init()
Con::addVariable("$pref::TS::RenderServer", TypeBool, &TSMesh::smRenderServer); // RenderServerAdd to tsMesh.h after the comment shown below
/// on load...optionally convert primitives to other form
static bool smRenderServer;
Add the following line to tsMesh.cc before this line:
bool TSMesh::smUseTriangles = false; // convert all primitives to triangle lists on load
bool TSMesh::smRenderServer = false; // render all the server objects
Now link it up in the script - I have it mapped to the g key
Add to default.binds.cs
moveMap.bind(keyboard, "g", toggleRenderServer ); // RenderServer
function toggleRenderServer(%val) // RenderServer
{
if( %val )
{
if( $pref::TS::RenderServer )
$pref::TS::RenderServer = false;
else
$pref::TS::RenderServer = true;
}
}And finally add to the config.cs file
moveMap.bind(keyboard, "g", toggleRenderServer);
Now you should be able to haunt your game with server objects by pressing g.
#2
I have a mounted image and I receive fatal errors from Player::renderMountedImage() with this resource.
03/06/2007 (9:13 pm)
Michel:I have a mounted image and I receive fatal errors from Player::renderMountedImage() with this resource.
#3
I never used mount objects so I missed something that needs to be turned off.
You might just try adding a check to not render that function if it's the server object - that should fix it - but will probably need some tweaking to actually get mount objects to render.
Unfortunately Im back in school right now so my Torque days are done, at least till summer time.
Michel
03/07/2007 (4:47 pm)
hi,I never used mount objects so I missed something that needs to be turned off.
You might just try adding a check to not render that function if it's the server object - that should fix it - but will probably need some tweaking to actually get mount objects to render.
Unfortunately Im back in school right now so my Torque days are done, at least till summer time.
Michel
#4
One crash that I had (and resolved) was to do with shadow rendering.
Inside of:
There was another use of the "materials" pointer which needed a NULL check on, so you need to change:
to
07/05/2007 (3:08 am)
Cool resource :) It would be nice to change it so that you can easily specify which type of network objects you would like rendered (ie. TSStatics vs. Players vs. Vehicles, etc.).One crash that I had (and resolved) was to do with shadow rendering.
Inside of:
TSMesh::renderShadow()
There was another use of the "materials" pointer which needed a NULL check on, so you need to change:
if (!(primitives[0].matIndex & TSDrawPrimitive::NoMaterial) && (TSMaterialList::Translucent & materials->getFlags(primitives[0].matIndex & TSDrawPrimitive::MaterialMask)))
// if no material...it would be nice to just exit...but may have some real polys back there...
return;to
if ((!materials) || (!(primitives[0].matIndex & TSDrawPrimitive::NoMaterial) && (TSMaterialList::Translucent & materials->getFlags(primitives[0].matIndex & TSDrawPrimitive::MaterialMask))))
// if no material...it would be nice to just exit...but may have some real polys back there...
return;
Torque Owner kingkong