Пример #1
0
bool CFeature::UpdatePosition()
{
	const float3 oldPos = pos;
	// const float4 oldSpd = speed;

	if (moveCtrl.enabled) {
		// raw movement; not masked or clamped
		UpdateQuadFieldPosition(speed = (moveCtrl.velVector += moveCtrl.accVector));
	} else {
		const float3 dragAccel = GetDragAccelerationVec(float4(mapInfo->atmosphere.fluidDensity, mapInfo->water.fluidDensity, 1.0f, 0.1f));
		const float3 gravAccel = UpVector * mapInfo->map.gravity;

		// horizontal movement
		if (UpdateVelocity(dragAccel, gravAccel, moveCtrl.movementMask, moveCtrl.velocityMask))
			UpdateQuadFieldPosition((speed * XZVector) * moveCtrl.movementMask);

		// vertical movement
		Move((speed * UpVector) * moveCtrl.movementMask, true);
		// adjusting vertical speed won't help if the ground moved and buried us
		Move(UpVector * (std::max(CGround::GetHeightReal(pos.x, pos.z), pos.y) - pos.y), true);

		// clamp final position
		if (!pos.IsInBounds()) {
			Move(pos.cClampInBounds(), false);

			// ensure that no more horizontal movement is done
			CWorldObject::SetVelocity((speed * UpVector) * moveCtrl.velocityMask);
		}
	}

	UpdateTransformAndPhysState(); // updates speed.w and BIT_MOVING
	Block(); // does the check if wanted itself

	// use an exact comparison for the y-component (gravity is small)
	if (!pos.equals(oldPos, float3(float3::cmp_eps(), 0.0f, float3::cmp_eps()))) {
		eventHandler.FeatureMoved(this, oldPos);
		return true;
	}

	return (moveCtrl.enabled);
}
Пример #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());
}