void CFeature::UpdateTransformAndPhysState() { UpdateDirVectors(!def->upright); UpdateTransform(pos, true); UpdatePhysicalStateBit(CSolidObject::PSTATE_BIT_MOVING, (SetSpeed(speed) != 0.0f)); UpdatePhysicalState(0.1f); }
bool CFeature::UpdatePosition() { const float3 oldPos = pos; if (udef != NULL) { // we are a wreck of a dead unit, possibly with residual impulse // in this case we do not care about <finalHeight> and are always // affected by gravity // note that def->floating is unreliable (eg. it can be true for // ground-unit wrecks), so just assume wrecks always sink in water // even if their "owner" was a floating object (as is the case for // ships anyway) if (IsMoving()) { const float realGroundHeight = ground->GetHeightReal(pos.x, pos.z); const bool reachedWater = ( pos.y <= 0.1f); const bool reachedGround = ((pos.y - realGroundHeight) <= 0.1f); // NOTE: // all these calls use the base-class because FeatureHandler::Update // iterates over updateFeatures and our ::SetVelocity will insert us // into that CWorldObject::SetVelocity(speed + GetDragAccelerationVec(float4(mapInfo->atmosphere.fluidDensity, mapInfo->water.fluidDensity, 1.0f, 0.1f))); if (speed.SqLength2D() > 0.01f) { UnBlock(); quadField->RemoveFeature(this); // update our forward speed (and quadfield // position) if it is still greater than 0 Move(speed, true); quadField->AddFeature(this); Block(); } else { CWorldObject::SetVelocity(speed * UpVector); } if (!reachedGround) { if (!reachedWater) { // quadratic acceleration if not in water CWorldObject::SetVelocity(speed + (UpVector * mapInfo->map.gravity)); } else { // constant downward speed otherwise CWorldObject::SetVelocity((speed * XZVector) + (UpVector * mapInfo->map.gravity)); } Move(UpVector * speed.y, true); } else { CWorldObject::SetVelocity(speed * XZVector); // last Update() may have sunk us into // ground if pos.y was only marginally // larger than ground height, correct Move(UpVector * (realGroundHeight - pos.y), true); } if (!pos.IsInBounds()) { pos.ClampInBounds(); // ensure that no more forward-speed updates are done // (prevents wrecks floating in mid-air at edge of map // due to gravity no longer being applied either) CWorldObject::SetVelocity(ZeroVector); } eventHandler.FeatureMoved(this, oldPos); CalculateTransform(); } } else { // any feature that is not a dead unit (ie. rocks, trees, ...) // these never move in the xz-plane no matter how much impulse // is applied, only gravity affects them (FIXME: arbitrary..?) if (pos.y > finalHeight) { if (pos.y > 0.0f) { CWorldObject::SetVelocity(speed + (UpVector * mapInfo->map.gravity)); } else { CWorldObject::SetVelocity((speed * XZVector) + (UpVector * mapInfo->map.gravity)); } // stop falling when we reach our finalHeight // (which can be arbitrary, even below ground) Move(UpVector * std::min(pos.y - finalHeight, speed.y), true); eventHandler.FeatureMoved(this, oldPos); } else if (pos.y < finalHeight) { // stop vertical movement and teleport up CWorldObject::SetVelocity(speed * XZVector); Move(UpVector * (finalHeight - pos.y), true); eventHandler.FeatureMoved(this, oldPos); } transMatrix[13] = pos.y; } UpdatePhysicalStateBit(CSolidObject::PSTATE_BIT_MOVING, ((SetSpeed(speed) != 0.0f) || (std::fabs(pos.y - finalHeight) >= 0.01f))); UpdatePhysicalState(0.1f); return (IsMoving()); }