Obscure WaterBlock bug
by James Urquhart · in Torque Game Engine · 07/07/2004 (10:06 am) · 12 replies
Whilst looking around the waterblock functions, i noticed this rather odd piece of code :
Whats wrong with it?
1) If the point is above the surface, its ok. If its below the whole waterblock, it will in theory be always submerged by this test. (so no stacking of waterblocks)
2) This function is called from WaterBlock::isPointSubmerged
3) I assume that the player object, aswell as others will inevitably call this function to determine if they are in water. But of course, they could still possibly use the castRay() function.
bool WaterBlock::isPointSubmergedSimple(const Point3F &pos, bool worldSpace) const
{
Point3F Pos = pos;
if( Pos.z > mSurfaceZ )
return( false );
if( worldSpace )
{
Pos.x += 1024.0f;
Pos.y += 1024.0f;
}
return( mFluid.IsFluidAtXY( Pos.x, Pos.y ) );
}Whats wrong with it?
1) If the point is above the surface, its ok. If its below the whole waterblock, it will in theory be always submerged by this test. (so no stacking of waterblocks)
2) This function is called from WaterBlock::isPointSubmerged
3) I assume that the player object, aswell as others will inevitably call this function to determine if they are in water. But of course, they could still possibly use the castRay() function.
About the author
#2
I think a better solution would be to test if the eye point is within the object box of the waterblock. It gets more complicated though when we want to consult the accept mask of accepted 'blocks' of water.
Checking against the object box would be a better early out condition then just checking the surface level overall though.
07/07/2004 (11:58 am)
I agree with you completely. I'm actually in the process of updating waterblock/fluid code. I think a better solution would be to test if the eye point is within the object box of the waterblock. It gets more complicated though when we want to consult the accept mask of accepted 'blocks' of water.
Checking against the object box would be a better early out condition then just checking the surface level overall though.
#3
Lets take a look at WaterBlock::prepRenderImage :
This code works fine if you use the regular whacko'd object box, but if you change the box to be (0,0,0) (1,1,1), you start to run into problems (waterblock dissapearing, etc).
IMO it would be computationally less expensive if you just used mWorldBox instead (since thats already in world space, right?).
Well, i've changed it to check if the point is above or below the waterblock's position (taking into account water height of course), *then* check the X/Y with the fluid class. But i guess it would be even better if i checked the sides too :)
07/07/2004 (1:01 pm)
Next bug,Lets take a look at WaterBlock::prepRenderImage :
image->sortType = SceneRenderImage::Plane;
image->plane = PlaneF(0, 0, 1, -mSurfaceZ);
image->poly[0] = Point3F(mObjBox.min.x, mObjBox.min.y, 1);
image->poly[1] = Point3F(mObjBox.min.x, mObjBox.max.y, 1);
image->poly[2] = Point3F(mObjBox.max.x, mObjBox.max.y, 1);
image->poly[3] = Point3F(mObjBox.max.x, mObjBox.min.y, 1);
for (U32 i = 0; i < 4; i++)
{
image->poly[i].convolve(mObjScale);
getTransform().mulP(image->poly[i]);
}This code works fine if you use the regular whacko'd object box, but if you change the box to be (0,0,0) (1,1,1), you start to run into problems (waterblock dissapearing, etc).
IMO it would be computationally less expensive if you just used mWorldBox instead (since thats already in world space, right?).
Quote:
I think a better solution would be to test if the eye point is within the object box of the waterblock. It gets more complicated though when we want to consult the accept mask of accepted 'blocks' of water.
Well, i've changed it to check if the point is above or below the waterblock's position (taking into account water height of course), *then* check the X/Y with the fluid class. But i guess it would be even better if i checked the sides too :)
#4
07/08/2004 (9:51 am)
You dont want to just use mWorldBox because what about arbitrarily sized water blocks ?
#6
07/14/2004 (3:02 pm)
Robert was taking a look at this last I heard.
#7
I noticed that when i make a waterblock, i position the block and set the z, and all is good. Water as depth, it works right. However, throughout the entire level, regardless of the x and y sizes of the block, if u are on level with that water, u will act as if ur submerged. Not sure if thats a good enuff explaination, hope so.. if not, i'll try to reword it. Is this something im doing wrong myself, or a bug?
07/24/2004 (7:01 pm)
Hate bumping threads, but since water was being talked of here, thought i'd mention a bug with it i noticed, make sure its not something im doing.I noticed that when i make a waterblock, i position the block and set the z, and all is good. Water as depth, it works right. However, throughout the entire level, regardless of the x and y sizes of the block, if u are on level with that water, u will act as if ur submerged. Not sure if thats a good enuff explaination, hope so.. if not, i'll try to reword it. Is this something im doing wrong myself, or a bug?
#8
Has anyone gotten any further with this? It seems like changing the following code:
to:
fixes one issue (your player thinking it is submerge when it is not) but introduces another (the waterblock disappears when its center-point goes out of view).
Someone also suggested somewhere to simply make waterblocks have a depth greater than the terrain it is covering... this doesn't work either...
Thanks in advance for any help or direction anyone can provide!!
Stephane
08/10/2005 (12:35 pm)
Another bump on this thread... Water blocks still disappear!!Has anyone gotten any further with this? It seems like changing the following code:
if (!mRemoveWetEdges) {
mObjBox.min.set(-1e4, -1e4, 0);
mObjBox.max.set( 1e4, 1e4, 1);
}to:
if (!mRemoveWetEdges) {
mObjBox.min.set( 0, 0, 0);
mObjBox.max.set( 1, 1, 1);
}fixes one issue (your player thinking it is submerge when it is not) but introduces another (the waterblock disappears when its center-point goes out of view).
Someone also suggested somewhere to simply make waterblocks have a depth greater than the terrain it is covering... this doesn't work either...
Thanks in advance for any help or direction anyone can provide!!
Stephane
#9
Rather than trying to frig around with getting the object box working for the water, I changed around the way we checked to see if we were submerged or not (that way we can keep the object box to the gross 1e4 values and keep the waterblocks from disappearing :))
All you need to do is change the waterFind function in shapebase.cc to this:
That'll ensure that things like speed reduction and splash sounds work appropriately while the bounding box of the waterblock can be anything!
Cheers!
08/12/2005 (1:06 am)
Alright... came up with a solution... its not elegant, but it'll certainly work in a pinch.Rather than trying to frig around with getting the object box working for the water, I changed around the way we checked to see if we were submerged or not (that way we can keep the object box to the gross 1e4 values and keep the waterblocks from disappearing :))
All you need to do is change the waterFind function in shapebase.cc to this:
static void waterFind(SceneObject* obj, void* key)
{
ShapeBase* shape = reinterpret_cast<ShapeBase*>(key);
WaterBlock* wb = dynamic_cast<WaterBlock*>(obj);
AssertFatal(wb != NULL, "Error, not a water block!");
if (wb == NULL)
{
sWaterCoverage = 0;
return;
}
if (wb->isPointSubmergedSimple(shape->getPosition()))
{
const Box3F& wbox = obj->getWorldBox();
const Box3F& sbox = shape->getWorldBox();
sWaterType = wb->getLiquidType();
if (wbox.max.z < sbox.max.z)
sWaterCoverage = (wbox.max.z - sbox.min.z) / (sbox.max.z - sbox.min.z);
else
sWaterCoverage = 1;
sWaterViscosity = wb->getViscosity();
sWaterDensity = wb->getDensity();
sWaterHeight = wb->getSurfaceHeight();
}
}That'll ensure that things like speed reduction and splash sounds work appropriately while the bounding box of the waterblock can be anything!
Cheers!
#10
08/15/2005 (10:50 am)
Nice fix. Issue #291.
#11
08/19/2005 (12:41 am)
And it's in. Nice.
#12
sadly I don't have time to look into the why atm, but from my perspective this one's a non-fix :( sorry.
03/28/2006 (3:48 am)
Ok, I've just gone through the process of converting our small game from 1.3 to 1.4. My waterblock code is unmodified from 1.4 code. This extra line intermittantly causes my object to not register as entering water.sadly I don't have time to look into the why atm, but from my perspective this one's a non-fix :( sorry.
Associate James Urquhart
Specifically, this code in fluid::RunQuadTree( bool& EyeSubmerged ):
// Determine where fluid surface is directly above (or above) the eye. sSurfaceAtEye = m_SurfaceZ + (SINE( (m_Eye.X * 0.05f) + m_Seconds ) + SINE( (m_Eye.Y * 0.05f) + m_Seconds )) * m_WaveFactor; // Set a flag to be returned to the caller. EyeSubmerged = (m_Eye.Z < sSurfaceAtEye) && IsFluidAtXY( m_Eye.X, m_Eye.Y );There should be some code to determine if the camera is *below* the waterblock.