void waterFind( SceneObject *obj, void *key ) { PROFILE_SCOPE( waterFind ); // This is called for each WaterObject the ShapeBase object is overlapping. ContainerQueryInfo *info = static_cast<ContainerQueryInfo*>(key); WaterObject *water = dynamic_cast<WaterObject*>(obj); AssertFatal( water != NULL, "containerQuery - waterFind(), passed object was not of class WaterObject!"); // Get point at the bottom/center of the box. Point3F testPnt = info->box.getCenter(); testPnt.z = info->box.minExtents.z; F32 coverage = water->getWaterCoverage(info->box); // Since a WaterObject can have global bounds we may get this call // even though we have zero coverage. If so we want to early out and // not save the water properties. if ( coverage == 0.0f ) return; // Add in flow force. Would be appropriate to try scaling it by coverage // thought. Or perhaps have getFlow do that internally and take // the box parameter. info->appliedForce += water->getFlow( testPnt ); // Only save the following properties for the WaterObject with the // greatest water coverage for this ShapeBase object. if ( coverage < info->waterCoverage ) return; info->waterCoverage = coverage; info->liquidType = water->getLiquidType(); info->waterViscosity = water->getViscosity(); info->waterDensity = water->getDensity(); info->waterHeight = water->getSurfaceHeight( Point2F(testPnt.x,testPnt.y) ); info->waterObject = water; }
//----------------------------------------------------------------------------- // // VActorPhysicsController::postTickUpdate( pDelta ); // // ... // //----------------------------------------------------------------------------- void VActorPhysicsController::postTickUpdate( const F32 &pDelta ) { switch( mControlState ) { case k_PathControlState : { AssertFatal( isPathing(), "VActorPhysicsController::postTickUpdate() - Invalid Path State." ); // Fetch Mount Transform. MatrixF transform; mMountedPath->getMountTransform( mObject->getMountNode(), getTransform(), &transform ); // Fetch Mount Position. const Point3F &mountPosition = transform.getPosition(); // Update X & Y Position. Point3F position = getPosition(); position.x = mountPosition.x; position.y = mountPosition.y; // In Water? bool underWater = false; if ( isInWater() ) { // Fetch Body of Water. WaterObject *waterBody = getWaterObject(); // Fetch Surface Position. const F32 &waterSurfacePosition = waterBody->getSurfaceHeight( Point2F( position.x, position.y ) ); // Fetch Submersion Position. const F32 sumbersionPosition = waterSurfacePosition - ( mObject->getWorldBox().len_z() * mObject->getDataBlock()->getSumbergeCoverage() ); // Choose a Z Value. // Note: This is done so that the Actor will either path under the // water, or it will swim along the water's surface. position.z = getMin( mountPosition.z, sumbersionPosition ); // Under Water? underWater = ( position.z < sumbersionPosition ); } // Under Water? if ( !underWater ) { // Fetch Y Column. VectorF forwardVector; transform.getColumn( 1, &forwardVector ); // Determine Angle. const F32 &angle = -mAtan2( -forwardVector.x, forwardVector.y ); // Reset Transform. transform.set( EulerF( 0.f, 0.f, angle ) ); // In the air? if ( !isOnGround() ) { // Apply z-axis force. position.z += ( getVelocity().z * pDelta ); } } // Update Transform. transform.setPosition( position ); // Apply Update. setTransform( transform ); } break; default : { // Fetch Transform. MatrixF transform = getTransform(); // Determine the Post-Tick Position. Point3F postTickPosition = getPosition() + ( getVelocity() * pDelta ); // Set the Post Tick Position. transform.setPosition( postTickPosition ); // Apply the Transform. setTransform( transform ); } break; } // Push Delta. mInterpController.pushDelta( getTransform() ); }