/// <summary> /// Reset the third person camera "head" angles. /// </summary> /// <param name="headAngle">new head angle</param> public bool ResetViewerAngle(Vector2?headAngle) { if (!headAngle.HasValue) { return(false); } Game.Entities.IMyControllableEntity controlledEntity = MySession.Static.ControlledEntity; if (controlledEntity == null) { return(false); } controlledEntity.HeadLocalXAngle = headAngle.Value.X; controlledEntity.HeadLocalYAngle = headAngle.Value.Y; return(true); }
public void RecalibrateCameraPosition(bool isCharacter = false) { // if (m_lookAt != Vector3D.Zero) // return; IMyCameraController cameraController = MySession.Static.CameraController; if (!(cameraController is MyEntity)) // also checks for not null { return; } Game.Entities.IMyControllableEntity controlledEntity = MySession.Static.ControlledEntity; if (controlledEntity == null) { return; } // get latest head matrix if (!isCharacter) { var headMatrix = controlledEntity.GetHeadMatrix(true); m_targetOrientation = headMatrix.GetOrientation(); m_target = headMatrix.Translation; } // parent of hierarchy MyEntity topControlledEntity = ((MyEntity)cameraController).GetTopMostParent(); if (topControlledEntity.Closed) { return; } // calculate controlled object coordinates in parent space var worldToLocal = topControlledEntity.PositionComp.WorldMatrixNormalizedInv; Vector3D targetInLocal = Vector3D.Transform(m_target, worldToLocal); MatrixD orientationInLocal = m_targetOrientation * worldToLocal; var localAABBHr = topControlledEntity.PositionComp.LocalAABBHr; Vector3D centerToTarget = targetInLocal - localAABBHr.Center; Vector3D backVec = Vector3D.Normalize(orientationInLocal.Backward); // calculate offset for the double projectedCenterToTarget = Vector3D.Dot(centerToTarget, backVec); double projectedHalfExtent = Math.Abs(Vector3D.Dot(localAABBHr.HalfExtents, backVec)); double finalLength = projectedHalfExtent - projectedCenterToTarget; //Vector3D targetWithOffset = centerToTarget + (finalLength * backVec); double width = m_lookAtDefaultLength; // some default value if (Math.Abs(backVec.Z) > 0.0001) { width = localAABBHr.HalfExtents.X * 1.5f; } else if (Math.Abs(backVec.X) > 0.0001) { width = localAABBHr.HalfExtents.Z * 1.5f; } // calculate complete offset for controlled object double halfFovTan = Math.Tan(MySector.MainCamera.FieldOfView * 0.5); double offset = width / (2 * halfFovTan); offset += finalLength; double clampDist = MathHelper.Clamp(offset, MIN_VIEWER_DISTANCE, MAX_VIEWER_DISTANCE); Vector3D lookAt = m_lookAtDirection * clampDist; SetPositionAndLookAt(lookAt); }
// Updates spectator position (spring connected to desired position) public override void UpdateAfterSimulation() { Game.Entities.IMyControllableEntity genericControlledEntity = MySession.Static.ControlledEntity; if (genericControlledEntity == null) { return; } var remotelyControlledEntity = genericControlledEntity as MyRemoteControl; var controlledEntity = remotelyControlledEntity != null ? remotelyControlledEntity.Pilot : genericControlledEntity.Entity; while (controlledEntity.Parent is MyCockpit) { controlledEntity = controlledEntity.Parent; } if (controlledEntity != null && controlledEntity.PositionComp != null) { var positionComp = controlledEntity.PositionComp; float localY = positionComp.LocalAABB.Max.Y - positionComp.LocalAABB.Min.Y; Vector3D lastTarget = m_target; var headMatrix = remotelyControlledEntity == null?genericControlledEntity.GetHeadMatrix(true) : remotelyControlledEntity.Pilot.GetHeadMatrix(true); m_target = controlledEntity is MyCharacter ? ((positionComp.GetPosition() + (localY + m_lookAtOffsetY) * positionComp.WorldMatrix.Up)) : headMatrix.Translation; m_targetOrientation = headMatrix.GetOrientation(); m_targetUpVec = m_positionCurrentIsSafe ? (Vector3D)m_targetOrientation.Up : positionComp.WorldMatrix.Up; m_transformedLookAt = Vector3D.Transform(m_clampedlookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; m_position += m_target - lastTarget; // compensate character movement //m_position = m_desiredPosition; } else { var headMatrix = genericControlledEntity.GetHeadMatrix(true); m_target = headMatrix.Translation; m_targetOrientation = headMatrix.GetOrientation(); m_targetUpVec = m_targetOrientation.Up; m_transformedLookAt = Vector3D.Transform(m_clampedlookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; m_position = m_desiredPosition; } Vector3D stretch = m_position - m_desiredPosition; Vector3D force = -m_currentSpring.Stiffness * stretch - m_currentSpring.Dampening * m_velocity; force.AssertIsValid(); // Apply acceleration Vector3 acceleration = (Vector3)force / m_currentSpring.Mass; m_velocity += acceleration * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_velocity.AssertIsValid(); // Apply velocity m_position += m_velocity * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_position.AssertIsValid(); if (m_disableSpringThisFrame) { double smoothCoeff = 0.8; m_position = Vector3D.Lerp(m_position, m_desiredPosition, smoothCoeff); m_disableSpringThisFrame = false; } // Limit backward distance from target double backward = Vector3D.Dot(m_targetOrientation.Backward, (m_target - m_position)); if (backward > -m_backwardCutoff) { m_position += (Vector3D)m_targetOrientation.Backward * (backward + m_backwardCutoff); } // -------- raycast, prevent camera being inside things ------ if (controlledEntity != null) { if (!controlledEntity.Closed) { HandleIntersection(controlledEntity); } else { m_positionCurrentIsSafe = false; } } // ------- save current settings ------- if (m_saveSettings) { MySession.Static.SaveControlledEntityCameraSettings(false); m_saveSettings = false; } }