MWaterCoverage bug
by Ian Omroth Hardingham · in Torque Game Engine · 10/02/2004 (10:10 am) · 13 replies
Hey everyone.
I have a problem with Player::mWaterCoverage, and a quick forum search has come up with nothing. I'm posting on the bugs forum because I got the impression from IRC that this was a general problem, so if it's not and it's just my dodgy build I apologise.
Player::mWaterCoverage seems to be zero when I'm underwater. It works fine at the top of the water block, for instance if I'm only half in it shows 0.5 etc, but after a few feet down it suddenly switches to zero.
If this is a general problem, does anyone know how to fix it?
Any help is much appreciated.
Ian
I have a problem with Player::mWaterCoverage, and a quick forum search has come up with nothing. I'm posting on the bugs forum because I got the impression from IRC that this was a general problem, so if it's not and it's just my dodgy build I apologise.
Player::mWaterCoverage seems to be zero when I'm underwater. It works fine at the top of the water block, for instance if I'm only half in it shows 0.5 etc, but after a few feet down it suddenly switches to zero.
If this is a general problem, does anyone know how to fix it?
Any help is much appreciated.
Ian
About the author
Designer and lead programmer on Frozen Synapse, Frozen Endzone, and Determinance. Co-owner of Mode 7 Games.
#2
12/18/2007 (7:56 am)
NOTE: This is really a problem with the findObjects() function. So in that respect, even after this patch the engine is still somewhat broken. You can expect that any other place in the engine that uses the Container::findObjects() to find water in a similar fashion should also fail.
#3
12/18/2007 (8:19 am)
Hi Kent, thanks for the three-year-late help ;)
#4
Replying here was easier (for me) than figuring out where to post it as a new issue.
12/19/2007 (6:39 pm)
Hey, better late than never!Replying here was easier (for me) than figuring out where to post it as a new issue.
#6
03/02/2008 (3:41 pm)
Does this need to be done in TGEA?
#7
03/16/2008 (11:40 pm)
Nobody got an answer? Or tried this for TGEA?
#8
03/17/2008 (3:08 am)
Yes it applies to TGEA, Ron.
#9
isPointSubmergedSimple
getViscosity
getDensity
getSurfaceHeight
Have you managed to get these back into the TGEA waterblock? If so could you send me a copy?
RJNelson68@cox.net
03/17/2008 (1:02 pm)
Stefan, there are a few differences in this from the current TGEA code. There are no longer certain functions like:isPointSubmergedSimple
getViscosity
getDensity
getSurfaceHeight
Have you managed to get these back into the TGEA waterblock? If so could you send me a copy?
RJNelson68@cox.net
#10
04/15/2008 (4:44 am)
I'm interested in this as well for TGEA 1.7. Do you guys have any news on this?
#11
04/15/2008 (5:26 pm)
Yeah my attempt at adding this just got the player to shake aorund alot. Obviously I did something wrong.
#12
05/20/2008 (2:55 pm)
Anyone done this yet in TGEA?
Torque Owner Kent Butler
The failure is really in the shapebase::updateContainer() function. This seems to only detect the waterblock if you are actually intersecting the surface. This happens with any ShapeBase derived object class - I tested with the Item class. It makes the entire bouyency/drag system fail(bouyancy becomes 0 beneath the surface). I made this patch to fix it at the shapebase level.
if you want to try this, MAKE A BACKUP ... ok now,
in ShapeBase.h add the line in BOLD
/// Update bouyency and drag properties void updateContainer(); [b] bool checkInLiquid(); // KGB: So that the updateContainer function works [/b] /// @name Events /// @{ virtual void onDeleteNotify(SimObject*);Next, in shapeBase.cc, find:
Now you want to REPLACE THIS AND EVERYTHING DOWN TO THE NEXT
This should be just before the "void ShapeBase::applyRepair(F32 amount)" function.
Replace the entire section with this:
//---------------------------------------------------------------------------- void physicalZoneFind(SceneObject* obj, void *key) { ShapeBase* shape = reinterpret_cast<ShapeBase*>(key); PhysicalZone* pz = dynamic_cast<PhysicalZone*>(obj); AssertFatal(pz != NULL, "Error, not a physical zone!"); if (pz == NULL || pz->testObject(shape) == false) { return; } if (pz->isActive()) { shape->mGravityMod *= pz->getGravityMod(); shape->mAppliedForce += pz->getForce(); } } // KGB: Bug fix - Modified this function to check for water differently. The // "findObjects" method only seemed to work when the player actually intersected // the water surface - standing on the bottom of the lake, the player::pointInWater // function said "yes", but this function said "no" (well, mWaterCoverage = 0). // // Player::pointInWater() was combined with ShapeBase::waterFind() to make // a new ShapeBase::checkInLiquid() function. I'm not great at C, so I kind of hacked // the water out of the findObjects loop and eliminated the findRouter function because // findObjects() is now only looking for physical zones - why route? (seems to work) void ShapeBase::updateContainer() { // Update container drag and buoyancy properties mDrag = mDataBlock->drag; mBuoyancy = 0; mWaterCoverage = 0; mLiquidType = 0; mLiquidHeight = 0.0f; mGravityMod = 1.0; mAppliedForce.set(0, 0, 0); mContainer->findObjects(getWorldBox(), PhysicalZoneObjectType,physicalZoneFind,this); checkInLiquid(); } // KGB: // This is based on the player::pointInWater function. It gets a list of all water blocks, // and checks each to see if the object is in the water. If so, it sets up the various // water-related variables like the old waterFind()/updateContainer() functions. // bool ShapeBase::checkInLiquid() { SimpleQueryList sql; if (isServerObject()) gServerSceneGraph->getWaterObjectList(sql); else gClientSceneGraph->getWaterObjectList(sql); for (U32 i = 0; i < sql.mList.size(); i++) { WaterBlock* pBlock = dynamic_cast<WaterBlock*>(sql.mList[i]); if (pBlock) { Point3F pos = getPosition(); if (pBlock->isPointSubmergedSimple(pos)){ // This is the water block we are submerged in. Do the calculations - and drop them // into the object variables const Box3F& wbox = pBlock->getWorldBox(); // Waterblock box to compare with const Box3F& sbox = getWorldBox(); // Object box and see if the object's if (wbox.max.z < sbox.max.z) // top is higher than the waterblock's // If so - figure out how deep we are mWaterCoverage = mClampF((wbox.max.z - sbox.min.z) / (sbox.max.z - sbox.min.z),0,1); else // Otherwise, we're over our head mWaterCoverage = 1.0f; if (mWaterCoverage >= 0.1f) { // If we are deep enough - calculate the density and viscocity F32 viscosity = pBlock->getViscosity(); F32 density = pBlock->getDensity(); mDrag = mDataBlock->drag * viscosity * mWaterCoverage; mBuoyancy = (density / mDataBlock->density) * mWaterCoverage; } // Look up the liquid's particulars for the object's pleasure. mLiquidType = pBlock->getLiquidType(); mLiquidHeight = pBlock->getSurfaceHeight(); return true; } } } return false; } //----------------------------------------------------------------------------OK, that's it - now jump from the top of that cliff, and pop right back up to the surface (if your density/mass ratio so allows). Don't blame me if you can't move ;-)
Update: fixed stupid typos