Game Development Community

Updating Water after RunTime Terrain Deformation..

by Jason Farmer · in Torque Game Engine · 08/03/2005 (6:55 am) · 7 replies

I'm using the TerrainDeformer object to dynamically alter the terrain from the resource www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7343

It's working great but I do have one problem. The water block I have has a shoreline and if I deform the terrain near the shoreline, the water block does not fill in the gap like I expected... The water block certainly is big enough to cover the hold I made. but what I end up with is a hole in the water where the terrain once was.

I'm thinking this must be something to do with the water block object.. Is there a way to tell it to update itself to the new terrain shape or should it be doing this on its own?

Anyone else had this problem?

#1
04/12/2006 (10:35 am)
I've just spent a few minutes looking into this for a project I'm working on, so I thought I'd let you know the way I've fixed it (well this is more for those that might come across your post as I'm assuming you've either fixed it or moved on by now based on the post date :)

The fix on the surface of it looks very simple, I've not fully tested it though so there may be a few gotchas remaining.

Assuming your water block is always called "Water", in processTick of the terrainDeformed you need to call

WaterBlock* water = dynamic_cast<WaterBlock*>(Sim::findObject("Water"));
water->UpdateFluidRegion();

The only cavet is to make sure you only do this only once, when the terrain has finished its deformation. In process tick there is a test against the flag mTerrainDeformed

if (!mTerrainDeformed) 
  {
    activateDeformation();
    //setProcessTick(false);
  }

Change this to

if (!mTerrainDeformed) 
  {
    activateDeformation();
    //setProcessTick(false);  // comment this out, we want to run for one more tick 
  }
  else
  {
    // insert object notification code here....
    // see later in post

    // update water block 
    WaterBlock* water = dynamic_cast<WaterBlock*>(Sim::findObject("Water"));
    water->UpdateFluidRegion();
    // we're done processing
    setProcessTick(false);
  }

You'll also need to locate any areas of code that set mTerrainDeformed = true, nearby these lines will be a call to disable process tick. Comment that process tick line out to ensure that process tick is always called one final time after the terrain is fully deformed.

One other item to note is that objects usually cache the terrain within thier working collision set, so if you deform terrain underneath a player, the player will float in the air unless you force the working set to invalidate. This is usually forced when the player moves, but stationary players remain floating.

To get around that, I added a quick loop in the else segment above that simply calls a function on each shapebase object that may be effected by the deformation eg

// The terrain has been deformed. As most objects will cache their working collision set
    // and only change it upon moving a certain amount we'll notify these objects of the 
    // terrain change and leave it up to them to invalidate their working sets.    
    Container *cont  = isServerObject() ? &gServerContainer : &gClientContainer;   
    Box3F queryBox(mPosition, mPosition);
    queryBox.min -= Point3F(mRadius, mRadius, mRadius);
    queryBox.max += Point3F(mRadius, mRadius, mRadius);
 
    SimpleQueryList queryList;
    cont->findObjects(queryBox, ShapeBaseObjectType, SimpleQueryList::insertionCallback, &queryList);
    for (U32 i = 0; i < queryList.mList.size(); i++) 
    {     
      ShapeBase* obj = static_cast<ShapeBase*>(queryList.mList[i]);
      obj->terrainDeformed();
    }

Obviously you'll need to extend shapebase to have a terrainDeformed method as well as overridding it for each subclass that needs extra processing.

Any problems, let me know. Especially if you find a problem with the two line water fix. Although it appears to work I've only spent a couple of minutes looking into that, so I may have missed something.
#2
08/11/2006 (7:26 am)
Hey Gary what did you use in ShapeBase::terrainDeformed() ?
#3
08/15/2006 (5:04 am)
TerrainDeformer?
Does that resource allow us to make craters from huge explosions that work over network?
#4
08/15/2006 (7:47 am)
Yes it does with an issue though that I have been working to fix. Any object within the radius of the deformation remain floating and do not fall into the crater because each object has a working collision cache that keeps the terrain cached until the object travels far enough to require a cache update. I still haven't gotten to the bottom of where that occurs completely yet. Any help you want to throw at it would be great.
#5
08/24/2006 (12:44 am)
How's the fix going?
#6
08/25/2006 (3:44 pm)
Not so good. Life is getting in the way. I will just have to get to it later.
#7
08/25/2006 (3:51 pm)
Okay..
There's just too much things happening in my life that I hardly have time for my own projects so I kinda understand you.