/// <summary> /// Only creates coord system. Call only on client in reaction on server create. /// </summary> /// <param name="transform">Origin of the coord system.</param> /// <param name="coordSysId">Coord system id that should be used in creation.</param> private void CreateCoordSys_ClientInternal(ref MyTransformD transform, long coordSysId) { MyLocalCoordSys localCoordSys = new MyLocalCoordSys(transform); localCoordSys.Id = coordSysId; m_localCoordSystems.Add(coordSysId, localCoordSys); }
public void ServerResponse(uint timeStamp, ref MyTransformD serverPositionAndOrientation) { if (timeStamp < m_lastTSFromServer) { return; } if (m_timeStampData.ContainsKey(timeStamp) == false) { m_entity.PositionComp.SetWorldMatrix(serverPositionAndOrientation.TransformMatrix, null, true); return; } MyTimeStampValues cachedData = m_timeStampData[timeStamp]; var mat = m_entity.WorldMatrix; MyTransformD delta = UpdateValues(m_entity, ref serverPositionAndOrientation, ref cachedData); mat.Translation = serverPositionAndOrientation.Position; m_entity.PositionComp.SetWorldMatrix(mat, null, true); UpdateDeltaPosition(timeStamp, ref delta); m_lastTSFromServer = timeStamp; }
void ClientRead(VRage.Library.Collections.BitStream stream) { uint timeStamp = stream.ReadUInt32(); m_lastRecievedTimeStamp = timeStamp; Vector3 serverLinearVelocity = stream.ReadVector3(); Vector3 serverAngularVelocity = stream.ReadVector3(); MyTimeStampValues?clientData = m_timestamp.GetTransform(timeStamp); if (clientData.HasValue) { Vector3D linearDelta = serverLinearVelocity / MyEntityPhysicsStateGroup.EffectiveSimulationRatio - clientData.Value.LinearVelocity; Entity.Physics.LinearVelocity += Vector3D.Round(linearDelta, 2); Vector3D angularDelta = serverAngularVelocity / MyEntityPhysicsStateGroup.EffectiveSimulationRatio - clientData.Value.AngularVelocity; Entity.Physics.AngularVelocity += Vector3D.Round(angularDelta, 2); m_timestamp.UpdateDeltaVelocities(timeStamp, ref linearDelta, ref angularDelta); } bool isUpdate = stream.ReadBool(); if (isUpdate) { MyTransformD serverTransform = new MyTransformD(); serverTransform.Position = stream.ReadVector3D(); serverTransform.Rotation = stream.ReadQuaternion(); serverTransform.Rotation = Quaternion.Identity; CustomClientRead(timeStamp, ref serverTransform, stream); } }
protected override bool IsPositionValid(MyTransformD clientDelta) { if (m_character.Physics != null && m_character.Physics.CharacterProxy != null) { float offset = 2 * MyPerGameSettings.PhysicsConvexRadius + 0.03f; float width = (m_character.Definition.CharacterCollisionWidth * m_character.Definition.CharacterCollisionScale) - offset; float height = (m_character.Definition.CharacterCollisionHeight - m_character.Definition.CharacterCollisionWidth * m_character.Definition.CharacterCollisionScale) - offset; HkCapsuleShape capsule = new HkCapsuleShape(Vector3.Up * height / 2.0f, Vector3.Down * height / 2.0f, width / 2.0f); m_results.Clear(); clientDelta.Position = clientDelta.Position + m_character.WorldMatrix.Up * (m_character.Definition.CharacterCollisionHeight / 2 + offset); MyPhysics.GetPenetrationsShape(capsule, ref clientDelta.Position, ref clientDelta.Rotation, m_results, MyPhysics.CollisionLayers.DefaultCollisionLayer); bool otherFound = false; foreach (var colision in m_results) { if (colision.Body.Quality == HkCollidableQualityType.Character) { continue; } otherFound = true; } return(!otherFound); } return(false); }
protected virtual void CustomClientRead(uint timeStamp, ref MyTransformD serverPositionAndOrientation, VRage.Library.Collections.BitStream stream) { if (m_timestamp != null) { m_timestamp.ServerResponse(timeStamp, ref serverPositionAndOrientation); } }
private static void CoordSysCreated_Client(MyCreateCoordSysBuffer createBuffer) { MyTransformD origin = new MyTransformD(); origin.Position = createBuffer.Position; origin.Rotation = createBuffer.Rotation; MyCoordinateSystem.Static.CreateCoordSys_ClientInternal(ref origin, createBuffer.Id); }
void UpdateData(uint i, ref MyTransformD delta) { if (m_timeStampData.ContainsKey(i)) { MyTimeStampValues cachedData = m_timeStampData[i]; cachedData.Transform.Position += delta.Position; Quaternion.Multiply(ref delta.Rotation, ref cachedData.Transform.Rotation, out cachedData.Transform.Rotation); m_timeStampData[i] = cachedData; } }
public void UpdateDeltaPosition(uint timestamp, ref MyTransformD data) { if (m_timeStampData.Count <= 0) { return; } for (uint i = timestamp; i <= m_currentTimestamp; ++i) { UpdateData(i, ref data); } }
public MyLocalCoordSys(MyTransformD origin, int size = 1000) { m_origin = origin; Vector3 halfSize = new Vector3(size / 2, size / 2, size / 2); BoundingBoxD tempBB = new BoundingBoxD(-halfSize, halfSize); m_boundingBox = new MyOrientedBoundingBoxD(tempBB, m_origin.TransformMatrix); m_boundingBox.GetCorners(m_corners, 0); RenderColor = this.GenerateRandomColor(); }
public MyLocalCoordSys() { m_origin = new MyTransformD(MatrixD.Identity); float halfSizeFloat = LOCAL_COORD_SIZE / 2.0f; Vector3 halfSize = new Vector3(halfSizeFloat, halfSizeFloat, halfSizeFloat); BoundingBoxD tempBB = new BoundingBoxD(-halfSize, halfSize); m_boundingBox = new MyOrientedBoundingBoxD(tempBB, m_origin.TransformMatrix); m_boundingBox.GetCorners(m_corners, 0); RenderColor = this.GenerateRandomColor(); }
/// <summary> /// Creates coord system and sends it to clients. Should be called only on server. /// </summary> /// <param name="cubeGrid">Cube grid that is an origin.</param> /// <param name="staticGridAlignToCenter">Indcates if grid should be aligned to center or no.</param> public void CreateCoordSys(MyCubeGrid cubeGrid, bool staticGridAlignToCenter, bool sync = false) { //In me this system is not working for now (will change after implementing planets there) //if(MyPerGameSettings.Game == GameEnum.ME_GAME) //{ // return; //} Debug.Assert(Sync.IsServer, "Called on client. This method should be called only on server."); MyTransformD origin = new MyTransformD(cubeGrid.PositionComp.WorldMatrix); origin.Rotation.Normalize(); float gridSize = cubeGrid.GridSize; if (!staticGridAlignToCenter) { origin.Position -= (origin.Rotation.Forward + origin.Rotation.Right + origin.Rotation.Up) * gridSize * 0.5f; } MyLocalCoordSys localCoordSys = new MyLocalCoordSys(origin, m_coorsSystemSize); long newId = m_lastCoordSysId++; // Just raise by one. There wont be so much id's for long to be overflooded. localCoordSys.Id = newId; m_localCoordSystems.Add(newId, localCoordSys); if (cubeGrid.LocalCoordSystem != 0) { this.UnregisterCubeGrid(cubeGrid); } this.RegisterCubeGrid(cubeGrid, localCoordSys); MyCreateCoordSysBuffer createCoordSysBuffer = new MyCreateCoordSysBuffer(); createCoordSysBuffer.Position = origin.Position; createCoordSysBuffer.Rotation = origin.Rotation; createCoordSysBuffer.Id = newId; if (sync) { MyMultiplayer.RaiseStaticEvent(x => CoordSysCreated_Client, createCoordSysBuffer); } }
MyTransformD UpdateValues(MyEntity entity, ref MyTransformD serverPositionAndOrientation, ref MyTimeStampValues cachedData) { MyTransformD delta = new MyTransformD(); delta.Position = serverPositionAndOrientation.Position - cachedData.Transform.Position; cachedData.Transform.Rotation = Quaternion.Inverse(cachedData.Transform.Rotation); Quaternion.Multiply(ref serverPositionAndOrientation.Rotation, ref cachedData.Transform.Rotation, out delta.Rotation); delta.Rotation = Quaternion.Identity; MatrixD matrix = entity.WorldMatrix; matrix.Translation = Vector3D.Zero; MatrixD correctionMatrix = MatrixD.Multiply(matrix, delta.TransformMatrix); correctionMatrix.Translation += entity.WorldMatrix.Translation; entity.PositionComp.SetWorldMatrix(correctionMatrix, null, true); return(delta); }
public override void Init(MyObjectBuilder_SessionComponent sessionComponent) { base.Init(sessionComponent); var coordSysBuilder = sessionComponent as MyObjectBuilder_CoordinateSystem; this.m_lastCoordSysId = coordSysBuilder.LastCoordSysId; foreach (var coordSys in coordSysBuilder.CoordSystems) { MyTransformD origin = new MyTransformD(); origin.Position = coordSys.Position; origin.Rotation = coordSys.Rotation; MyLocalCoordSys newCoordSys = new MyLocalCoordSys(origin); newCoordSys.Id = coordSys.Id; newCoordSys.EntityConuter = coordSys.EntityCount; m_localCoordSystems.Add(coordSys.Id, newCoordSys); } }
protected override void CustomClientRead(uint timeStamp, ref MyTransformD serverPositionAndOrientation, VRage.Library.Collections.BitStream stream) { bool hasSupport = stream.ReadBool(); if (hasSupport) { long entityId = stream.ReadInt64(); Vector3D serverSupportPos = stream.ReadVector3D(); if (!MyEntities.EntityExists(entityId)) { return; } MyEntity support = MyEntities.GetEntityById(entityId); MyTimeStampValues?clientTransform = m_timestamp.GetTransform(timeStamp); Vector3D clientPosition = Vector3D.Zero; Vector3D clientSupportPosition = Vector3D.Zero; Quaternion rotationComp = Quaternion.Identity; if (clientTransform != null) { if (m_supportTimeStamp == null) { return; } MyTimeStampValues?supportTransform = m_supportTimeStamp.GetTransform(timeStamp); Vector3D supportPosition = support.PositionComp.WorldMatrix.Translation; if (supportTransform.HasValue) { supportPosition = supportTransform.Value.Transform.Position; if (supportTransform.Value.EntityId != entityId) { return; } } clientPosition = clientTransform.Value.Transform.Position; clientSupportPosition = supportPosition; rotationComp = Quaternion.Inverse(clientTransform.Value.Transform.Rotation); } else { m_character.PositionComp.SetWorldMatrix(serverPositionAndOrientation.TransformMatrix, null, true); return; } MyTransformD delta = new MyTransformD(); delta.Rotation = Quaternion.Identity; Vector3D characterDelta = serverPositionAndOrientation.Position - clientPosition; Vector3D supportDelta = serverSupportPos - clientSupportPosition; delta.Position = characterDelta - supportDelta; m_character.CacheMoveDelta(ref delta.Position); m_timestamp.UpdateDeltaPosition(timeStamp, ref delta); } else { base.CustomClientRead(timeStamp, ref serverPositionAndOrientation, stream); } }
/// <summary> /// Converts world position to be snapped to closest grid. /// </summary> /// <param name="worldPos">World position.</param> /// <param name="gridSize">Grid size.</param> /// <param name="staticGridAlignToCenter">Is grid align to static.</param> /// <returns></returns> public CoordSystemData SnapWorldPosToClosestGrid(ref Vector3D worldPos, double gridSize, bool staticGridAlignToCenter) { m_lastSelectedCoordSys = m_selectedCoordSys; MyLocalCoordSys localCoordSys = null; localCoordSys = this.GetClosestCoordSys(ref worldPos); // If no coord sys found, return origin(0,0,0) with no rotation! if (localCoordSys == null) { localCoordSys = new MyLocalCoordSys(m_coorsSystemSize); m_selectedCoordSys = 0; } else { m_selectedCoordSys = localCoordSys.Id; } if (m_selectedCoordSys == 0) { m_localCoordExist = false; } else { m_localCoordExist = true; } if (m_selectedCoordSys != m_lastSelectedCoordSys) { m_selectionChanged = true; if (OnCoordinateChange != null) { OnCoordinateChange(); } } else { m_selectionChanged = false; } //if (!m_localCoordExist && m_selectionChanged) //{ // this.Disable(); //} //else if (m_selectionChanged && m_lastSelectedCoordSys == 0) //{ // this.Enable(); //} CoordSystemData coordData = new CoordSystemData(); Quaternion rotation = localCoordSys.Origin.Rotation; Quaternion invRotation = Quaternion.Inverse(rotation); Vector3D position = localCoordSys.Origin.Position; Vector3D vec = worldPos - position; vec = Vector3D.Transform(vec, invRotation); MyCoordinateSystem.GetPosRoundedToGrid(ref vec, gridSize, staticGridAlignToCenter); coordData.LocalSnappedPos = vec; vec = Vector3D.Transform(vec, rotation); MyTransformD localCoordsTransform = new MyTransformD(); localCoordsTransform.Position = position + vec; localCoordsTransform.Rotation = rotation; coordData.SnappedTransform = localCoordsTransform; coordData.Origin = localCoordSys.Origin; return(coordData); }
protected virtual bool IsPositionValid(MyTransformD clientPos) { return(true); }
void ServerWrite(VRage.Library.Collections.BitStream stream, ulong clientId) { bool clientUpdate = m_clientUpdateFlag[clientId]; stream.WriteBool(clientUpdate); if (clientUpdate) { ClientData clientData = m_serverClientData[clientId]; m_clientUpdateFlag[clientId] = false; stream.WriteUInt32(clientData.TimeStamp); MyTransformD serverData = new MyTransformD(Entity.WorldMatrix); //rotation is calculated same way for both Quaternion serverRotation = serverData.Rotation; serverRotation.Normalize(); clientData.Transform.Rotation.Normalize(); MyTimeStampValues delta = new MyTimeStampValues(); serverRotation = Quaternion.Inverse(serverRotation); Quaternion.Multiply(ref clientData.Transform.Rotation, ref serverRotation, out delta.Transform.Rotation); bool applyRotation = false; double eps = 0.001; if (Math.Abs(Quaternion.Dot(clientData.Transform.Rotation, serverData.Rotation)) < 1 - eps) { applyRotation = true; } bool isValidPosition = true; bool correctServerPosition = false; CalculatePositionDifference(clientId, out isValidPosition, out correctServerPosition, out delta.Transform.Position); bool isValidClientPosition = isValidPosition; if ((correctServerPosition && isValidPosition) || applyRotation) { MatrixD matrix = Entity.WorldMatrix; MatrixD correctionMatrix = MatrixD.Multiply(matrix.GetOrientation(), delta.Transform.TransformMatrix); correctionMatrix.Translation += Entity.WorldMatrix.Translation; if (correctServerPosition) { isValidClientPosition = IsPositionValid(new MyTransformD(correctionMatrix)); } if (isValidClientPosition) { Entity.PositionComp.SetWorldMatrix(correctionMatrix, null, true); MyEntityPhysicsStateGroup support = MySupportHelper.FindPhysics(Entity); if (support != null && support.MoveHandler != null) { support.MoveHandler(ref matrix, ref correctionMatrix); } } else if (applyRotation) { correctionMatrix.Translation = Entity.WorldMatrix.Translation; Entity.PositionComp.SetWorldMatrix(correctionMatrix, null, true); } } stream.WriteBool(!isValidClientPosition); if (!isValidClientPosition) { serverData = new MyTransformD(Entity.WorldMatrix); stream.Write(serverData.Position); CustomServerWrite(m_serverClientData[clientId].TimeStamp, clientId, stream); } } stream.Write(Entity.Physics != null ? Entity.Physics.LinearVelocity * MyEntityPhysicsStateGroup.EffectiveSimulationRatio : Vector3.Zero); stream.Write(Entity.Physics != null ? Entity.Physics.AngularVelocity * MyEntityPhysicsStateGroup.EffectiveSimulationRatio : Vector3.Zero); }
public SetInstruction(MyTransformD transform) { Value = null; Transform = transform; }
/// <summary> /// Converts world position to be snapped to closest grid. /// </summary> /// <param name="worldPos">World position.</param> /// <param name="gridSize">Grid size.</param> /// <param name="staticGridAlignToCenter">Is grid align to static.</param> /// <returns></returns> public MyTransformD SnapWorldPosToClosestGrid(ref Vector3D worldPos, double gridSize, bool staticGridAlignToCenter) { m_lastSelectedCoordSys = m_selectedCoordSys; MyLocalCoordSys localCoordSys = null; localCoordSys = this.GetClosestCoordSys(ref worldPos); // If no coord sys found, return origin(0,0,0) with no transformation! if (localCoordSys == null) { localCoordSys = new MyLocalCoordSys(); m_selectedCoordSys = 0; } else { m_selectedCoordSys = localCoordSys.Id; } if (m_selectedCoordSys == 0) { m_isSelection = false; } else { m_isSelection = true; } if (m_selectedCoordSys != m_lastSelectedCoordSys) { m_selectionChanged = true; } else { m_selectionChanged = false; } //if (!m_isSelection && m_selectionChanged) //{ // this.Disable(); //} //else if (m_selectionChanged && m_lastSelectedCoordSys == 0) //{ // this.Enable(); //} Quaternion rotation = localCoordSys.Origin.Rotation; Quaternion invRotation = Quaternion.Inverse(rotation); Vector3D position = localCoordSys.Origin.Position; Vector3D vec = worldPos - position; vec = Vector3D.Transform(vec, invRotation); MyCoordinateSystem.GetPosRoundedToGrid(ref vec, gridSize, staticGridAlignToCenter); vec = Vector3D.Transform(vec, rotation); MyTransformD localCoordsTransform = new MyTransformD(); localCoordsTransform.Position = position + vec; localCoordsTransform.Rotation = rotation; return(localCoordsTransform); }