Exemplo n.º 1
0
void CFeature::UpdateTransformAndPhysState()
{
	UpdateDirVectors(!def->upright);
	UpdateTransform(pos, true);

	UpdatePhysicalStateBit(CSolidObject::PSTATE_BIT_MOVING, (SetSpeed(speed) != 0.0f));
	UpdatePhysicalState(0.1f);
}
Exemplo n.º 2
0
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());
}