TGEA 1.7.1 Bug: sgShadowProjector bad pointer after db swap
by Guy Allard · in Torque Game Engine Advanced · 09/04/2008 (1:02 pm) · 3 replies
We've been dealing with some crashes recently that occur after changing an objects datablock using setDatablock() from script. I've finally managed to track the crashes down to sgShadowProjector::sgRenderShape. It appears that after a shapebase objects datablock is changed, the shapeInst referenced in sgShadowProjector::sgRenderShape may no longer be valid.
This must be because ShapeBase::onNewDataBlock deletes and reinitializes the shapeInstance, and I'm guessing that the shadow projector doesn't know this has happened, and is still pointing at the deleted shape.
The crash does not occur predictably, and it seems easier to make it happen using a DEBUG build, as one of the asserts in sgShadowProjector::shRenderShape crashes because shape->details is not a valid pointer.
I have managed to make stock TGEA 1.7.1 crash with this error repeatably by doing the following:
1) Compile a DEBUG build of the T3D game example.
2) Put the following code somewhere in server\scripts\players\player.cs
3) Run T3D_DEBUG.exe, load the default mission, pull up the console and type dbTest() and hit return.
4) Wait for TGEA to crash.
Some more info -
This crash only happens for animated shadows (shadowCanAnimate=true).
Release builds don't crash as easily, but it does still happen.
The project I'm working on is an RTS and relies on setDataBlock extensively, so this is a bit of a show stopper. Any ideas for a quick fix would be greatly appreciated :)
This must be because ShapeBase::onNewDataBlock deletes and reinitializes the shapeInstance, and I'm guessing that the shadow projector doesn't know this has happened, and is still pointing at the deleted shape.
The crash does not occur predictably, and it seems easier to make it happen using a DEBUG build, as one of the asserts in sgShadowProjector::shRenderShape crashes because shape->details is not a valid pointer.
I have managed to make stock TGEA 1.7.1 crash with this error repeatably by doing the following:
1) Compile a DEBUG build of the T3D game example.
2) Put the following code somewhere in server\scripts\players\player.cs
function dbTest()
{
spawnBob();
schedule(500, 0, "swapBlock");
}
function spawnBob()
{
new AIPlayer(Bob) {
datablock = "spaceSuitData";
position = LocalClientConnection.camera.getPosition();
};
}
function swapBlock()
{
%dbID = getRandom(3);
switch(%dbID)
{
case 0:
%db = BoomBotData;
break;
case 1:
%db = ElfData;
break;
case 2:
%db = SpaceSuitData;
break;
default:
%db = SpaceOrcData;
}
if(isObject(bob))
{
bob.setDataBlock(%db);
schedule(500, 0, "swapBlock");
}
}3) Run T3D_DEBUG.exe, load the default mission, pull up the console and type dbTest() and hit return.
4) Wait for TGEA to crash.
Some more info -
This crash only happens for animated shadows (shadowCanAnimate=true).
Release builds don't crash as easily, but it does still happen.
The project I'm working on is an RTS and relies on setDataBlock extensively, so this is a bit of a show stopper. Any ideas for a quick fix would be greatly appreciated :)
About the author
Recent Threads
#2
in ShapeBase::onNewDataBlock
after:
mShapeInstance = new TSShapeInstance(mDataBlock->shape, isClientObject());
insert:
09/16/2008 (8:34 am)
The following fix appears to be stable for me:in ShapeBase::onNewDataBlock
after:
mShapeInstance = new TSShapeInstance(mDataBlock->shape, isClientObject());
insert:
if(mLightPlugin)
{
SAFE_DELETE(mLightPlugin); // delete the current light plugin
smSceneObjectAdd.trigger(this); // triggering this signal creates a new light plugin for this object
}
#3
Think rather than triggering a fake SceneObjectAdd signal, though, it's cleaner to add a 'reset()' method to SceneObjectLightingPlugin and do a
at the end of ShapeBase::onNewDataBlock. The light plugins can then simply purge cached information, but leave all their connection to the associated SceneObject in place.
Did this for HEAD.
11/06/2008 (6:47 am)
Thanks a lot for tracing this.Think rather than triggering a fake SceneObjectAdd signal, though, it's cleaner to add a 'reset()' method to SceneObjectLightingPlugin and do a
if( mLightPlugin ) mLightPlugin->reset();
at the end of ShapeBase::onNewDataBlock. The light plugins can then simply purge cached information, but leave all their connection to the associated SceneObject in place.
Did this for HEAD.
Torque 3D Owner Novack
CyberianSoftware