// end Step private void MoveLinear(float pTimestep, WhiteCoreODEPhysicsScene _pParentScene, WhiteCoreODEPrim parent) { if (m_linearMotorDirection.LengthSquared() < 0.0001f) { m_linearMotorDirection = Vector3.Zero; m_newVelocity = Vector3.Zero; } else { Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale); m_lastLinearVelocityVector += (addAmount); m_linearMotorDirection *= (1.0f - 1.0f/m_linearMotorDecayTimescale); // convert requested object velocity to world-referenced vector d.Quaternion rot = d.BodyGetQuaternion(Body); Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object //Vector3 oldVelocity = m_newVelocity; m_newVelocity = m_lastLinearVelocityVector*rotq; // apply obj rotation to velocity vector //if (oldVelocity.Z == 0 && (Type != Vehicle.TYPE_AIRPLANE && Type != Vehicle.TYPE_BALLOON)) // m_newVelocity.Z += dvel_now.Z; // Preserve the accumulated falling velocity } //if (m_newVelocity.Z == 0 && (Type != Vehicle.TYPE_AIRPLANE && Type != Vehicle.TYPE_BALLOON)) // m_newVelocity.Z += dvel_now.Z; // Preserve the accumulated falling velocity d.Vector3 dpos = d.BodyGetPosition(Body); Vector3 pos = new Vector3(dpos.X, dpos.Y, dpos.Z); if (!(m_lastPositionVector.X == 0 && m_lastPositionVector.Y == 0 && m_lastPositionVector.Z == 0)) { // Only do this if we have a last position m_lastposChange.X = pos.X - m_lastPositionVector.X; m_lastposChange.Y = pos.Y - m_lastPositionVector.Y; m_lastposChange.Z = pos.Z - m_lastPositionVector.Z; } #region Blocking Change if (m_BlockingEndPoint != Vector3.Zero) { bool needUpdateBody = false; if (pos.X >= (m_BlockingEndPoint.X - 1)) { pos.X -= m_lastposChange.X + 1; needUpdateBody = true; } if (pos.Y >= (m_BlockingEndPoint.Y - 1)) { pos.Y -= m_lastposChange.Y + 1; needUpdateBody = true; } if (pos.Z >= (m_BlockingEndPoint.Z - 1)) { pos.Z -= m_lastposChange.Z + 1; needUpdateBody = true; } if (pos.X <= 0) { pos.X += m_lastposChange.X + 1; needUpdateBody = true; } if (pos.Y <= 0) { pos.Y += m_lastposChange.Y + 1; needUpdateBody = true; } if (needUpdateBody) d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); } #endregion #region Terrain checks float terrainHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); if (pos.Z < terrainHeight - 5) { pos.Z = terrainHeight + 2; m_lastPositionVector = pos; //Make sure that we don't have an explosion the next frame with the posChange d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); } else if (pos.Z < terrainHeight) m_newVelocity.Z += 1; #endregion #region Hover // Check if hovering if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) { // We should hover, get the target height if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) { m_VhoverTargetHeight = (float) _pParentScene.GetWaterLevel(pos.X, pos.Y) + m_VhoverHeight; } if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; } if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) { m_VhoverTargetHeight = m_VhoverHeight; } float tempHoverHeight = m_VhoverTargetHeight; if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) { // If body is aready heigher, use its height as target height if (pos.Z > tempHoverHeight) tempHoverHeight = pos.Z; } if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) { if ((pos.Z - tempHoverHeight) > .2 || (pos.Z - tempHoverHeight) < -.2) { float h = tempHoverHeight; float groundHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); if (groundHeight >= tempHoverHeight) h = groundHeight; d.BodySetPosition(Body, pos.X, pos.Y, h); } } else { float herr0 = pos.Z - tempHoverHeight; // Replace Vertical speed with correction figure if significant if (herr0 > 0.01f) { m_newVelocity.Z = -((herr0*50.0f)/m_VhoverTimescale); //KF: m_VhoverEfficiency is not yet implemented } else if (herr0 < -0.01f) { m_newVelocity.Z = -((herr0*50f)/m_VhoverTimescale); } else { m_newVelocity.Z = 0f; } } // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped // m_VhoverTimescale = 0f; // time to acheive height // pTimestep is time since last frame,in secs } #endregion #region No X,Y,Z if ((m_flags & (VehicleFlag.NO_X)) != 0) m_newVelocity.X = 0; if ((m_flags & (VehicleFlag.NO_Y)) != 0) m_newVelocity.Y = 0; if ((m_flags & (VehicleFlag.NO_Z)) != 0) m_newVelocity.Z = 0; #endregion #region Deal with tainted forces // KF: So far I have found no good method to combine a script-requested // .Z velocity and gravity. Therefore only 0g will used script-requested // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; Vector3 TaintedForce = new Vector3(); if (m_forcelist.Count != 0) { try { TaintedForce = m_forcelist.Aggregate(TaintedForce, (current, t) => current + (t)); } catch (IndexOutOfRangeException) { TaintedForce = Vector3.Zero; } catch (ArgumentOutOfRangeException) { TaintedForce = Vector3.Zero; } m_forcelist = new List<Vector3>(); } // force to deltaV m_newVelocity += TaintedForce*(pTimestep/Mass); #endregion #region Deflection //Forward is the prefered direction /*Vector3 deflectionamount = m_newVelocity / (m_linearDeflectionTimescale / pTimestep); //deflectionamount *= m_linearDeflectionEfficiency; if (deflectionamount != Vector3.Zero) { } Vector3 deflection = Vector3.One / deflectionamount; m_newVelocity /= deflection;*/ #endregion #region limitations if (m_newVelocity.LengthSquared() > 1e6f) { m_newVelocity /= m_newVelocity.Length(); m_newVelocity *= 1000f; } else if (m_newVelocity.LengthSquared() < 1e-6f) m_newVelocity = Vector3.Zero; #endregion m_lastPositionVector = parent.Position; float grav = -1*Mass*pTimestep; // Apply velocity if (m_newVelocity != Vector3.Zero) { if ((Type == Vehicle.TYPE_CAR || Type == Vehicle.TYPE_SLED) && !parent.LinkSetIsColliding) { //Force ODE gravity here!!! } else d.BodySetLinearVel(Body, m_newVelocity.X, m_newVelocity.Y, m_newVelocity.Z + grav); } // apply friction m_lastLinearVelocityVector.X *= (1.0f - 1/m_linearFrictionTimescale.X); m_lastLinearVelocityVector.Y *= (1.0f - 1/m_linearFrictionTimescale.Y); m_lastLinearVelocityVector.Z *= (1.0f - 1/m_linearFrictionTimescale.Z); }
public WhiteCoreODECharacter(String avName, WhiteCoreODEPhysicsScene parent_scene, Vector3 pos, Quaternion rotation, Vector3 size) { m_uuid = UUID.Random(); _parent_scene = parent_scene; m_taintRotation = rotation; if (pos.IsFinite()) { if (pos.Z > 9999999f || pos.Z < -90f) { pos.Z = _parent_scene.GetTerrainHeightAtXY(_parent_scene.Region.RegionSizeX*0.5f, _parent_scene.Region.RegionSizeY*0.5f) + 5.0f; } _position = pos; } else { _position.X = _parent_scene.Region.RegionSizeX*0.5f; _position.Y = _parent_scene.Region.RegionSizeY*0.5f; _position.Z = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + 10f; MainConsole.Instance.Warn("[PHYSICS]: Got NaN Position on Character Create"); } m_isPhysical = false; // current status: no ODE information exists Size = size; Name = avName; }