fxFoliageReplicator CreateFoliage() being called before objects are fully loaded
by Thomas -elfprince13- Dickerson · in Torque Game Engine · 10/26/2009 (2:16 am) · 24 replies
(continuing the discussion from my blog post here: http://www.garagegames.com/community/blogs/view/18603)

When I declare my 2 fxFoliageReplicators, I set the following flags
As you can see from the picture, this doesn't seem to be working, however I noticed that when I open the World Editor and select one of them (without applying any sort of changes) the foliage in the water disappears. Stepping through the code in a debugger, it appears that both times packUpdate is called on the foliage replicators, mAllowOnWater is false, as expected. This means the problem has to be happening here, in CreateFoliage (which is called directly from unpackUpdate)....but ONLY on the first update (which happens during mission loading).
This suggests to me that somehow the foliage is being loaded BEFORE the waterblock and thus allowing the water to evade the call to CastRay. Oddly enough, the waterblock is defined BEFORE the foliage in my mission file. Has anyone run into this before?

When I declare my 2 fxFoliageReplicators, I set the following flags
AllowOnTerrain = "1";
AllowOnInteriors = "0";
AllowOnStatics = "0";
AllowOnWater = "0";
AllowWaterSurface = "0";As you can see from the picture, this doesn't seem to be working, however I noticed that when I open the World Editor and select one of them (without applying any sort of changes) the foliage in the water disappears. Stepping through the code in a debugger, it appears that both times packUpdate is called on the foliage replicators, mAllowOnWater is false, as expected. This means the problem has to be happening here, in CreateFoliage (which is called directly from unpackUpdate)....but ONLY on the first update (which happens during mission loading).
// Perform Ray Cast Collision on Client.
CollisionResult = gClientContainer.castRay( FoliageStart, FoliageEnd, FXFOLIAGEREPLICATOR_COLLISION_MASK, &RayEvent);
// Did we hit anything?
if (CollisionResult)
{
// For now, let's pretend we didn't get a collision.
CollisionResult = false;
// Yes, so get it's type.
U32 CollisionType = RayEvent.object->getTypeMask();
// Check Illegal Placements, fail if we hit a disallowed type.
if (((CollisionType & TerrainObjectType) && !mFieldData.mAllowOnTerrain) ||
((CollisionType & InteriorObjectType) && !mFieldData.mAllowOnInteriors) ||
((CollisionType & StaticTSObjectType) && !mFieldData.mAllowStatics) ||
((CollisionType & WaterObjectType) && !mFieldData.mAllowOnWater) ) continue;
// If we collided with water and are not allowing on the water surface then let's find the
// terrain underneath and pass this on as the original collision else fail.
if ((CollisionType & WaterObjectType) && !mFieldData.mAllowWaterSurface &&
!gClientContainer.castRay( FoliageStart, FoliageEnd, FXFOLIAGEREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue;
// We passed with flying colour so carry on.
CollisionResult = true;
}This suggests to me that somehow the foliage is being loaded BEFORE the waterblock and thus allowing the water to evade the call to CastRay. Oddly enough, the waterblock is defined BEFORE the foliage in my mission file. Has anyone run into this before?
About the author
C.S. PhD student at Brown University. Project lead for FreeBuild. Administrator, Cemetech tech community. Webmaster for the Village2Village Projects and the Vermont Sustainable Heating Initiative.
#2
10/28/2009 (2:55 pm)
I haven't, only because I also declare terrain before either, and if it was reading backwards I would think that calls to castray would fail for terrain collision as well. My thought might be some sort of asynchronicity in the waterblock loading, but I suppose it's worth a shot.
#3
Digging further, it looks like CreateFoliage() is called also by the function StartFoliageReplication(), which is called from clientCmdMissionStartPhase3() (common/client/missionDownload.cs) as part of the loading procedure. This is done after the ghost system has been started in phase 2.
So it looks like the foliage replicator has actually been designed to avoid just the type of error you are experiencing. Have you made any changes to missionDownload.cs or any changes to the mission loading sequence that might have disrupted this process?
10/28/2009 (4:08 pm)
Ah yes. That makes sense, so that's probably not it. Digging further, it looks like CreateFoliage() is called also by the function StartFoliageReplication(), which is called from clientCmdMissionStartPhase3() (common/client/missionDownload.cs) as part of the loading procedure. This is done after the ghost system has been started in phase 2.
So it looks like the foliage replicator has actually been designed to avoid just the type of error you are experiencing. Have you made any changes to missionDownload.cs or any changes to the mission loading sequence that might have disrupted this process?
#4
10/28/2009 (4:56 pm)
I diff'd (and visually checked) my missionDownload.cs and everything looks normal, but I think we're on the right track now, because if I call StartFoliageReplication from the console, in-game all the in-water foliage disappears. Which just leaves me wondering why the first call doesn't fix things...I'll play around with it though, and hopefully figure something out.
#5
10/29/2009 (12:44 pm)
I found this thread, where someone else was having the same issues with replication timing. I've moved all my trees over to fxShapeReplicators so they look a bit nicer, and it's the same thing. One suggestion in that-^ thread was to put Start[Client/Foliage]Replication() calls after the scene lighting is complete, because you can guarantee that all objects have loaded, but obviously this doesn't work for something like fxShapeReplicators where you want proper shadowing.
#6
1) Start Ghost system > all ghostAlways objects now exist on the client
2) Start Replication > additional replicator objects are added
3) Light Scene
What's the hold up on the water block I wonder? Now I'm curious. I'm going to test this on my system.
10/29/2009 (2:07 pm)
What bothers me is that a WaterBlock is somehow not ready to go (at least for ray casting) by the time the initial ghosting is done. It should be: 1) Start Ghost system > all ghostAlways objects now exist on the client
2) Start Replication > additional replicator objects are added
3) Light Scene
What's the hold up on the water block I wonder? Now I'm curious. I'm going to test this on my system.
#7
10/29/2009 (2:19 pm)
huh. Well that didn't prove anything. It's broken even worse in my engine. After reloading the mission, I can't get the foliage replicator to recognize the water blocks at all. o_O
#8
10/30/2009 (9:56 am)
I 'm goimg to try adding some debug output to the console so I can see when it DOES get added.
#9
11/02/2009 (11:48 pm)
Scott, did you ever make headway on this? I'm pretty much at a loss.
#10
11/03/2009 (4:37 am)
Sorry, no. Had no time to look at it over the weekend. Unfortunately, I'm pretty sure my problems are due to a bug I introduced that I still haven't sorted out RE waterblocks. I'll have to solve that first before I can conduct any meaningful tests.
#11
11/13/2009 (12:15 pm)
Assuming you haven't solved this yet? I'm poking around some more.. What version of TGE are you using? Seems minor changes have been made to the waterblock in each version.
#12
11/13/2009 (12:33 pm)
I'm using 1.5.2, with the waterblock resource to allow variable-sized terrain blocks.
#13
FWIW my fxFoliage now works fine with my waterblocks. That doesn't help you directly since I'm running a highly modified torque 1.3, but it does give me a working model to compare to other versions.
11/13/2009 (1:29 pm)
Hmm. Perhaps you could send me your waterblock.cc so I might have a look at it? net. scottris at gamedev <- reverse it.FWIW my fxFoliage now works fine with my waterblocks. That doesn't help you directly since I'm running a highly modified torque 1.3, but it does give me a working model to compare to other versions.
#14
11/13/2009 (2:17 pm)
Should be in your inbox now-ish. Thanks for all the help!
#15
11/13/2009 (4:05 pm)
Ok. Try this: See line 454 says "resetWorldBox();"? Try changing that to "Parent::setTransform(getTransform());" (it's in WaterBlock::onAdd)
#16
11/13/2009 (4:48 pm)
This didn't seem to change anything.
#17
at the end of the function WaterBlock::onAdd()
11/13/2009 (4:57 pm)
hmm. bummer. alright.. what do you get if you place this:Con::printf("%s %i (in %p): [%f %f %f, %f %f %f, %f %f %f][%f %f %f] (%f %f %f, %f %f %f)",
isClientObject() ? "CLIENT" : "SERVER", getId(), mContainer,
mObjToWorld(0,0),
mObjToWorld(1,0),
mObjToWorld(2,0),
mObjToWorld(0,1),
mObjToWorld(1,1),
mObjToWorld(2,1),
mObjToWorld(0,2),
mObjToWorld(1,2),
mObjToWorld(2,2),
mObjToWorld(0,3),
mObjToWorld(1,3),
mObjToWorld(2,3),
mWorldBox.min.x,
mWorldBox.min.y,
mWorldBox.min.z,
mWorldBox.max.x,
mWorldBox.max.y,
mWorldBox.max.z);at the end of the function WaterBlock::onAdd()
#18
and
11/13/2009 (5:08 pm)
SERVER 2777 (in 0x0): [1.000000 0.000000 0.000000, 0.000000 1.000000 0.000000, 0.000000 0.000000 1.000000][-24.000000 24.000000 112.382004] (-10024.000000 -9976.000000 112.382004, 9976.000000 10024.000000 113.382004)
and
CLIENT 2798 (in 0x0): [1.000000 0.000000 0.000000, 0.000000 1.000000 0.000000, 0.000000 0.000000 1.000000][-24.000000 24.000000 112.382004] (-10024.000000 -9976.000000 112.382004, 9976.000000 10024.000000 113.382004)
#19
11/13/2009 (5:24 pm)
Curious. mContainer is null. Did you add that before or after the call to "addToScene()" on line 460?
#20
and
11/13/2009 (5:46 pm)
Ah, whoops, lemme take another shot at that.SERVER 2781 (in 0x3ed240): [1.000000 0.000000 0.000000, 0.000000 1.000000 0.000000, 0.000000 0.000000 1.000000][-24.000000 24.000000 112.382004] (-10024.000000 -9976.000000 112.382004, 9976.000000 10024.000000 113.382004)
and
CLIENT 2802 (in 0x3ed1e0): [1.000000 0.000000 0.000000, 0.000000 1.000000 0.000000, 0.000000 0.000000 1.000000][-24.000000 24.000000 112.382004] (-10024.000000 -9976.000000 112.382004, 9976.000000 10024.000000 113.382004)
Torque 3D Owner Scott Richards