private SetCameraPacket.CameraBlock MakeCameraBlock(Vector3 position, Vector3 positionDelta, Rotation rotation, Rotation rotationDelta) { Rotation orientationOffset = new Rotation(Frame.Orientation.Pitch, -Frame.Orientation.Yaw); Vector3 lookAt = orientationOffset.LookAtVector * rotation.Quaternion; //Vector3 eyePos = new Vector3(Frame.Core.EyePosition.Y, Frame.Core.EyePosition.X, -Frame.Core.EyePosition.Z); Vector3 eyePos = Frame.Core.EyePosition; eyePos *= rotation.Quaternion; Vector3 offset = Offset * rotation.Quaternion; if (Frame.Core.ControlMode == ControlMode.Absolute) offset += eyePos / 1000f; Vector3 cameraUp = Vector3.UnitZ * rotation.Quaternion; Vector3 up = Vector3.UnitZ; if (orientationOffset.Yaw != 0.0) up = orientationOffset.Yaw < 0.0 ? Vector3.Cross(lookAt, rotation.LookAtVector) : Vector3.Cross(rotation.LookAtVector, lookAt); SetCameraPacket.CameraBlock block = new SetCameraPacket.CameraBlock(); block.Position = position + offset; block.PositionDelta = positionDelta; block.LookAt = lookAt; block.LookAtDelta = rotationDelta.LookAtVector; block.Up = up; block.TickLength = (uint) Frame.Core.TickLength * 1000; return block; }
public KinectControlState(string name, OverlayPlugin manager, bool avatar) : base(name, manager) { mInput = manager.Core.GetPlugin<KinectMovementPlugin>(); mAvatar = avatar; mStartOrientation = new Rotation(manager.Core.Orientation); mStartPosition = manager.Core.Position; }
public override void Move(Vector3 positionDelta, Rotation orientationDelta, float deltaScale) { RemoteControlPacket packet = new RemoteControlPacket(); packet.Delta.Position = positionDelta * deltaScale; if (!mAllowFly) packet.Delta.Position.Z = 0f; packet.Delta.Pitch = (float)(orientationDelta.Pitch * (Math.PI / 45.0)) * deltaScale; packet.Delta.Yaw = (float)(orientationDelta.Yaw * (Math.PI / 45.0)) * deltaScale; InjectPacket(packet); }
public ExploreState(OverlayPlugin manager, XmlNode node) : base(GetName(node, "explore state"), manager) { mAvatar = GetBool(node, false, "Avatar"); mSetOrientation = node.Attributes["Pitch"] != null || node.Attributes["Yaw"] != null; mSetPosition = node.Attributes["X"] != null && node.Attributes["Y"] != null && node.Attributes["Z"] != null; mStartOrientation = new Rotation(GetDouble(node, 0.0, "Pitch"), GetDouble(node, 0.0, "Yaw")); mStartPosition = new Vector3(GetFloat(node, 0f, "X"), GetFloat(node, 0f, "Y"), GetFloat(node, 0f, "Z")); }
public KinectControlState(OverlayPlugin manager, XmlNode node) : base(GetName(node, "kinect movement state"), manager, node) { //mInput = manager.Core.GetPlugin<KinectMovementPlugin>(); mAvatar = GetBool(node, true, "Avatar"); double pitch = GetDouble(node, manager.Core.Orientation.Pitch); double yaw = GetDouble(node, manager.Core.Orientation.Yaw); float x = GetFloat(node, manager.Core.Position.X, "X"); float y = GetFloat(node, manager.Core.Position.Y, "Y"); float z = GetFloat(node, manager.Core.Position.Z, "Z"); mStartOrientation = new Rotation(pitch, yaw); mStartPosition = new Vector3(x, y, z); mSetPosition = (node.Attributes["X"] != null && node.Attributes["Y"] != null && node.Attributes["Z"] != null) || node.Attributes["Pitch"] != null || node.Attributes["Yaw"] != null; }
public void SetCamera(Vector3 positionDelta, Rotation orientationDelta) { if (mViewerConfig.CheckForPause && mFrame.Core.ControlMode == ControlMode.Absolute) MarkUntracked(); //PrintTickInfo(); if (mViewerConfig.UseThread) { Packet p = ActualSetCamera(positionDelta, orientationDelta); lock (this) mCameraPacket = p; } else mProxy.InjectPacket(ActualSetCamera(positionDelta, orientationDelta), Direction.Incoming); }
public SpinFeature(OverlayPlugin manager, XmlNode node) { mCore = manager.Core; mDelta = new Rotation(0, 3); mFrame = GetManager(manager, node, "Spin Feature").Name; }
public abstract void Move(Vector3 positionDelta, Rotation orientationDelta, float scale);
/// <summary> /// Initialise the Rotation as read only with values transition the specified lookAt. /// </summary> /// <param name="mLookAtVector">Another lookAt to copy the values transition.</param> /// <param name="readonlyLock">Initialise the rotation with a lock object. The only way to update this rotation will be to use an Update method and pass in the same lock object.</param> public Rotation(object readonlyLock, Rotation rotation) : this(readonlyLock) { LookAtVector = rotation.LookAtVector; }
public EyeTrackerPlugin() { EyeTrackerConfig cfg = new EyeTrackerConfig(); mOrientationChangeHandler = new EventHandler(mKinectOrientation_Changed); mKinectPosition = cfg.Position; mKinectOrientation = new Rotation(cfg.Pitch, cfg.Yaw); mControlX = cfg.ControlX; mKinectOrientation.Changed += new EventHandler(mKinectOrientation_Changed); Nui.SkeletonLost += new SkeletonTrackDelegate(Nui_SkeletonLost); mHead = Nui.joint(Nui.Head); mHead.OnChange += new ChangeDelegate(mHead_OnChange); }
private void InitAvatarTracking() { mParseImprovedTerseObjectUpdatePackets = true; mAvatarPosition = Vector3.Zero; mAvatarOrientation = Rotation.Zero; mProxy.AddDelegate(PacketType.ImprovedTerseObjectUpdate, Direction.Incoming, mProxy_ImprovedTerseObjectUpdatePacketReceived); }
public SeeThroughMenuState(string name, OverlayPlugin manager, XmlNode node, Vector3 position, Rotation orientation) : base(name, manager, node) { mPosition = position; mOrientation = orientation; }
/// <summary> /// CreateWindowState a input. It is necessary to specify a unique name for the input. /// </summary> /// <param name="frameName">The name this input is known by within the system.</param> /// <param name="overlayAreas">The overlay areas mapped to this input.</param> public Frame(string frameName) { mName = frameName; mConfig = new FrameConfig(frameName); mMonitor = Screen.AllScreens.FirstOrDefault(s => s.DeviceName.Equals(mConfig.Monitor)); mWidth = mConfig.Width; mHeight = mConfig.Height; mTopLeft = mConfig.TopLeft; mOrientation = new Rotation(mConfig.Pitch, mConfig.Yaw); mCentre = Centre; mDraw = mConfig.Draw; mDrawEye = mConfig.DrawEye; mOrientation.Changed += mOrientation_Changed; if (mMonitor == null) mMonitor = Screen.PrimaryScreen; }
public void Init(Core core) { mCore = core; Disposed += new EventHandler(CoordinatorForm_Disposed); mCameraUpdatedListener = new Action<Core, CameraUpdateEventArgs>(mCoordinator_CameraUpdated); mDeltaUpdatedListener = new Action<Core, DeltaUpdateEventArgs>(mCoordinator_DeltaUpdated); mCameraModeChangedListener = new Action<Core, ControlMode>(mCoordinator_CameraModeChanged); mEyeUpdatedListener = new Action<Core, EventArgs>(mCoordinator_EyeUpdated); mClosedListener = new Action<Core, KeyEventArgs>(mCoordinator_Closed); mHeightmapChangedListener = new EventHandler<HeightmapChangedEventArgs>(mCoordinator_HeightmapChanged); mCore.ControlModeChanged += mCameraModeChangedListener; mCore.EnableUpdatesChanged += new Action(mCoordinator_EnableUpdatesChanged); mCore.CameraUpdated += mCameraUpdatedListener; mCore.DeltaUpdated += mDeltaUpdatedListener; mCore.EyeUpdated += mEyeUpdatedListener; mCore.Closed += mClosedListener; //mCoordinator.HeightmapChanged += mHeightmapChangedListener; mCore.FrameAdded += new Action<Frame,EventArgs>(mCoordinator_WindowAdded); mCoordinator_CameraModeChanged(core, core.ControlMode); Rotation orientation = new Rotation(mCore.Orientation); virtualPositionPanel.Value = mCore.Position; virtualOrientationPanel.Value = orientation; eyePositionPanel.Value = mCore.EyePosition; enableUpdates.Checked = mCore.EnableUpdates; InputUpdatesCheck.Checked = mCore.EnableInputUpdates; mHeightmap = new Bitmap(mCore.Heightmap.GetLength(0), mCore.Heightmap.GetLength(1), PixelFormat.Format24bppRgb); mHeightmapPerspective = new HeightmapPerspective(mCore, heightmapPanel); tickLengthPanel.Value = mCore.TickLength; /* #if DEBUG tickStatsPanel.Init(core.TickStatistics, core); tickListenersPanel.Init(StatisticsCollection.Collection, core); updateStatsPanel.Init(core.UpdateStatistics, core); cameraStatsPanel.Init(core.CameraStatistics, core); deltaStatsPanel.Init(core.DeltaStatistics, core); #endif */ foreach (var window in mCore.Frames) mCoordinator_WindowAdded(window, null); /* #if DEBUG pluginsTab.Controls.Remove(statisticsTab); #endif */ foreach (var plugin in mCore.Plugins) { TabPage inputTab = new TabPage(); CheckBox enableCheck = new CheckBox(); // // inputTab // inputTab.Controls.Add(enableCheck); inputTab.Controls.Add(plugin.ControlPanel); inputTab.Location = new System.Drawing.Point(4, 22); inputTab.Name = plugin.Name + "Tab"; inputTab.Padding = new System.Windows.Forms.Padding(3); inputTab.Size = new System.Drawing.Size(419, 239); inputTab.TabIndex = 0; inputTab.Text = plugin.Name; inputTab.UseVisualStyleBackColor = true; // // enableCheck // enableCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); enableCheck.AutoSize = true; enableCheck.BackColor = System.Drawing.Color.Transparent; enableCheck.Location = new System.Drawing.Point(355, 6); enableCheck.Name = "enable" + plugin.Name + "Check"; enableCheck.Size = new System.Drawing.Size(59, 17); enableCheck.TabIndex = 1; enableCheck.Text = plugin.Name; enableCheck.Checked = plugin.Enabled; enableCheck.CheckStateChanged += new EventHandler((source, args) => mCore.Plugins.First(i => enableCheck.Name.Equals("enable" + i.Name + "Check")).Enabled = enableCheck.Checked); //enableCheck.UseVisualStyleBackColor = false; // // inputPanel // plugin.ControlPanel.Dock = System.Windows.Forms.DockStyle.Fill; plugin.ControlPanel.Location = new System.Drawing.Point(3, 3); plugin.ControlPanel.Size = new System.Drawing.Size(413, 233); plugin.ControlPanel.TabIndex = 0; pluginsTab.Controls.Add(inputTab); plugin.EnabledChanged += (p, enabled) => Invoke(() => enableCheck.Checked = enabled); plugin.SetForm(this); } /* #if DEBUG pluginsTab.Controls.Add(statisticsTab); #endif */ }
public void SetOrientation(Rotation orientation) { if (mOrientation != null) mOrientation.Changed -= orientation_Changed; mOrientation = orientation; orientation.Changed += orientation_Changed; }
void mProxyController_PositionChanged(Vector3 position, Rotation rotation) { if (IsMaster && Mode == ControlMode.Delta) mFrame.Core.Update(position, Vector3.Zero, rotation, Rotation.Zero, ControlMode.Absolute); }
public void Init(Frame frame) { mFrame = frame; //TODO - this should be set properly - as a property mOrientation = Rotation.Zero; mOrientation.Changed += orientation_Changed; mFrame.Changed += (win, args) => ConfigureFromWindow(); mPlaneTopLeft = Vector.Create("PlanePoint", 1f, 1f, 0f); mPlaneNormal = Nui.normalize(Vector.Create("PlaneNormal", 0f, 0f, 1f)); mWorldW = Scalar.Create("WorldW", (float) mFrame.Width); mWorldH = Scalar.Create("WorldH", (float) mFrame.Height); mScreenW = Scalar.Create("ScreenW", mFrame.Monitor.Bounds.Width); mScreenH = Scalar.Create("ScreenH", mFrame.Monitor.Bounds.Height); Vector pointEnd = Nui.joint(Nui.Hand_Right) * SCALE; if (mTest) { mPointStart = Vector.Create("PointStart", 0f, 0f, 5f); mPointDir = Vector.Create("PointDir", 0f, 0f, -1f); } else { mPointStart = Nui.joint(Nui.Elbow_Right) * SCALE; mPointDir = Nui.normalize(mPointStart - pointEnd); } //Calculate the intersection of the plane defined by the point mPlaneTopLeft and the normal mPlaneNormal and the line defined by the point mPointStart and the direction mPointDir. Scalar numerator = Nui.dot(mPointStart - mPlaneTopLeft, mPlaneNormal); Scalar denominator = Nui.dot(mPlaneNormal, mPointDir); mIntersects = denominator != 0f; mIntersection = mPointStart + Nui.scale(mPointDir, Nui.ifScalar(mIntersects, numerator / denominator, 0f)); Vector vertical = Vector.Create(0f, 1f, 0f); // Vertical //Calculate a vector that represents the orientation of the top of the input. mTop = Nui.scale(Nui.cross(vertical, mPlaneNormal), mWorldW); //Calculate a vector that represents the orientation of the side of the input. mSide = Nui.scale(Nui.cross(mPlaneNormal, mTop), mWorldH); //Calculate the vector (running along the plane) between the top left corner and the point of intersection. Vector diff = mIntersection - mPlaneTopLeft; //Project the diff line onto the top and side vectors to get x and y values. Scalar kinectCoordX = Nui.project(diff, mTop); Scalar kinectCoordY = Nui.project(diff, mSide); Scalar x = (mWorldW - kinectCoordX) / mWorldW; Scalar y = (mWorldH - kinectCoordY) / mWorldH; mX = Nui.ifScalar(C.And(mIntersects, C.And(x >= 0f, x <= 1f)), x, -1f); mY = Nui.ifScalar(C.And(mIntersects, C.And(y >= 0f, y <= 1f)), y, -1f); mIntersection.Name = "Intersection"; mTop.Name = "Top"; mSide.Name = "Side"; mX.Name = "X"; mY.Name = "Y"; ConfigureFromWindow(); Nui.Tick += Tick; }
private void ConfigureWindow() { double alpha = Math.Atan2(mVOffset, mThrowRatio); double beta = Math.Atan2(mVOffset + mH, mThrowRatio); double h = mTargetH; double angleT = !mUpsideDown ? P + beta : P - alpha; double angleB = !mUpsideDown ? P + alpha : P - beta; double tan = Math.Tan(angleT) - Math.Tan(angleB); if (mLockHeight) { mD = h / tan; double offsetH = h * mVOffset / mH; double offsetZ = offsetH * Math.Cos(P); if (!mUpsideDown) { offsetZ += h; offsetZ *= -1.0; } Vector3 line = new Vector3((float)mD, 0f, 0f); line *= new Rotation(0.0, mFrame.Orientation.Yaw).Quaternion; Vector3 target = mFrame.Centre; double z = mD * Math.Tan(angleT); target.Z = mFrame.TopLeft.Z - (float) z; mPosition = (target - line) - mProjectorPlugin.RoomPosition; } else { mFrame.Height = mD * tan; double t = mD * Math.Tan(P + (mUpsideDown ? -alpha : beta)); Vector3 topLeft = new Vector3((float)mD, (float)(mFrame.Width / -2), (float)t); topLeft *= new Rotation(0.0, mOrientation.Yaw).Quaternion; topLeft += Origin; mFrame.TopLeft = topLeft; } mFrame.Width = CalculateW(); }
public Projector(Frame frame, ProjectorPlugin projectorPlugin) { mProjectorPlugin = projectorPlugin; mFrame = frame; mTargetH = frame.Height; ProjectorConfig cfg = new ProjectorConfig(frame.Name); mOrientation = new Rotation(cfg.ProjectorPitch, cfg.ProjectorYaw); //Constants mThrowRatio = cfg.ThrowRatio; mUpsideDown = cfg.UpsideDown; mVOffset = cfg.VOffset; mNativeAspectRatio = cfg.NativeAspectRatio; SetAspectRatio(cfg.AspectRatio); CalculateAngles(); mLock = cfg.Lock; if (mLock == LockedVariable.Position/* || mLock == LockedVariable.Nothing*/) { mPosition = cfg.ProjectorPosition; mD = cfg.WallDistance; mFrame.Orientation.Yaw = mOrientation.Yaw; } else { mD = mLock == LockedVariable.Width ? CalculateDFromW() :CalculateDFromH(); mPosition = CalculatePositionFromH(); mOrientation.Yaw = mFrame.Orientation.Yaw; } mOldW = mFrame.Width; mOldH = mFrame.Height; mDraw = cfg.Draw; mDrawLabels = cfg.DrawLabels; mProjectorPlugin.RoomChanged += new Action(mProjectorPlugin_RoomChanged); mOrientation.Changed += new EventHandler(mOrientation_Changed); frame.Changed += new Action<Frame,EventArgs>(frame_Changed); }
public bool Start() { if (mConfig == null) throw new ArgumentException("Unable to start proxy. No configuration specified."); try { mLoggedIn = false; mLastUpdatePacket = DateTime.UtcNow; mProxy = new Proxy(mConfig); mProxy.AddLoginResponseDelegate(mProxy_LoginResponse); mProxy.AddDelegate(PacketType.AgentUpdate, Direction.Outgoing, mProxy_AgentUpdatePacketReceived); if (mViewerConfig.GetLocalID) { mLocalID = 0; mProxy.AddDelegate(PacketType.ObjectUpdate, Direction.Incoming, mObjectUpdateListener); } ThisLogger.Info("Proxying " + mConfig.remoteLoginUri); mProxy.Start(); if (pPositionChanged != null) mProxy.AddDelegate(PacketType.AgentUpdate, Direction.Outgoing, mAgentUpdateListener); if (ProxyStarted != null) ProxyStarted(); stopping = false; mCanncelTockenSource = new CancellationTokenSource(); new Thread(() => { AgentUpdatePacket packet; while (!stopping) { try { packet = agentUpdatePacketQueue.Take(mCanncelTockenSource.Token); } catch (OperationCanceledException) { return; } Vector3 pos = packet.AgentData.CameraCenter; if (mFrame.Core.ControlMode == ControlMode.Absolute) { //new Thread(() => { if (mViewerConfig.CheckForPause) { string key = MakeKey(pos); lock (mUnackedUpdates) { if (mUnackedUpdates.ContainsKey(key)) mUnackedUpdates.Remove(key); } CheckForPause(); } //}).Start(); } if (pPositionChanged != null) pPositionChanged(pos, new Rotation(packet.AgentData.CameraAtAxis)); } }).Start(); new Thread(() => { ImprovedTerseObjectUpdatePacket packet; while (!stopping) { try { packet = objectUpdatePacketQueue.Take(mCanncelTockenSource.Token); } catch (OperationCanceledException) { return; } foreach (var block in packet.ObjectData) { uint localid = Utils.BytesToUInt(block.Data, 0); if (block.Data[0x5] != 0 && localid == mLocalID) { mAvatarPosition = new Vector3(block.Data, 0x16); mPositionOffset = mAvatarPosition - mFrame.Core.Position; Quaternion rotation = Quaternion.Identity; // Rotation (theta) rotation = new Quaternion( Utils.UInt16ToFloat(block.Data, 0x2E, -1.0f, 1.0f), Utils.UInt16ToFloat(block.Data, 0x2E + 2, -1.0f, 1.0f), Utils.UInt16ToFloat(block.Data, 0x2E + 4, -1.0f, 1.0f), Utils.UInt16ToFloat(block.Data, 0x2E + 6, -1.0f, 1.0f)); mAvatarOrientation = new Rotation(rotation); //mAvatarOrientation = Frame.Core.Orientation; } } } }).Start(); } catch (NullReferenceException e) { //Logger.Info("Unable to start proxy. " + e.Message); mProxy = null; return false; } return true; }
private Vector3 CalculatePositionFromH() { double offsetH = mFrame.Height * mVOffset / mH; double offsetZ = offsetH * Math.Cos(P); if (!mUpsideDown) { offsetZ += mFrame.Height; offsetZ *= -1.0; } double angleT = !mUpsideDown ? P + mBeta : P - mAlpha; Vector3 line = new Vector3((float)mD, 0f, 0f); line *= new Rotation(0.0, mFrame.Orientation.Yaw).Quaternion; Vector3 target = mFrame.Centre; double z = mD * Math.Tan(angleT); target.Z = mFrame.TopLeft.Z - (float)z; return (target - line) - mProjectorPlugin.RoomPosition; }
protected abstract Packet ActualSetCamera(Vector3 positionDelta, Rotation orientationDelta);
/// <summary> /// Initialise the Rotation transition the specified lookAt. /// </summary> /// <param name="mLookAtVector">Another lookAt to copy the values transition.</param> public Rotation(Rotation rotation) { LookAtVector = rotation.LookAtVector; }
public Camera(Vector3 vector3, Rotation rotation) { mPosition = vector3; mOrientation = rotation; }
private Vector3 CalculateTopLeft() { double t = mD * Math.Tan(P + (mUpsideDown ? -mAlpha : mBeta)); Vector3 topLeft = new Vector3((float)mD, (float)(mFrame.Width / -2), (float)t); topLeft *= new Rotation(0.0, mOrientation.Yaw).Quaternion; topLeft += Origin; return topLeft; }
/// <summary> /// Update a readonly rotation. /// </summary> /// <param name="readonlyLock">Lock object to update readonly rotation.</param> /// <param name="rotation">The quaternion to set the rotation to.</param> /// <param name="lookAt">Pitch to set to.</param> public void Update(object readonlyLock, Rotation rotation) { if (readonlyLock == mReadOnlyLock) Set(rotation.Pitch, rotation.Yaw); else throw new Exception("Unable to update readonly rotation, wrong authentication object."); }
public void Draw(Graphics g, Func<Vector3, Point> to2D, Action redraw, Perspective perspective) { if (mDraw) { Func<Vector3, Point> to2DR = v => to2D(Origin + (v * new Rotation(0.0, mOrientation.Yaw).Quaternion)); Point pos = to2DR(Vector3.Zero); double range = 12500.0; double y = range * Math.Tan(mGamma); double zt = range * Math.Tan(mUpsideDown ? -mAlpha : mBeta); double zb = range * Math.Tan(mUpsideDown ? -mBeta : mAlpha); Quaternion q = new Rotation(-mOrientation.Pitch, 0.0).Quaternion; Vector3 bse = new Vector3((float)range, 0f, 0f) * q; Vector3 tl = new Vector3((float)range, (float)-y, (float)zt) * q; Vector3 tr = new Vector3((float)range, (float)y, (float)zt) * q; Vector3 bl = new Vector3((float)range, (float)-y, (float)zb) * q; Vector3 br = new Vector3((float)range, (float)y, (float)zb) * q; g.DrawLine(Pens.Red, pos, to2DR(bse)); g.DrawLine(Pens.Green, pos, to2DR(bl)); g.DrawLine(Pens.Green, pos, to2DR(br)); g.DrawLine(Pens.Blue, pos, to2DR(tl)); g.DrawLine(Pens.Blue, pos, to2DR(tr)); g.DrawLine(Pens.Violet, to2DR(new Vector3((float)mD, 0f, (float)-range)), to2DR(new Vector3((float)mD, 0f, (float)range))); double betaH = mD / Math.Cos(P + mBeta); double alphaH = mD / Math.Cos(P + mAlpha); double betaY = mD * Math.Tan(P + mBeta); double alphaY = mD * Math.Tan(P + mAlpha); //g.DrawLine(Pens.Purple, pos, to2DR(new Vector3((float)mD, 0f, (float) betaY))); //g.DrawLine(Pens.Purple, pos, to2DR(new Vector3((float)mD, 0f, (float) alphaY))); //g.DrawLine(Pens.Purple, pos, to2DR(new Vector3((float)betaH, 0f, 0f) * new Rotation(((P + mBeta) * -180.0) / Math.PI, 0.0).Quaternion)); //g.DrawLine(Pens.Purple, pos, to2DR(new Vector3((float)alphaH, 0f, 0f) * new Rotation(((P + mAlpha) * -180.0) / Math.PI, 0.0).Quaternion)); if (mDrawLabels) { Vector3 toScreen = new Vector3((float) mD, 0f, 0f) * new Rotation(0.0, mOrientation.Yaw).Quaternion; Vector3 floor = new Vector3(0f, 0f, mProjectorPlugin.RoomPosition.Z + mProjectorPlugin.Small.Z); Vector3 clearance = new Vector3(0f, 0f, (float) Clearance); Vector3 toClearance = floor + clearance; Font font = SystemFonts.DefaultFont; using (Pen p2 = new Pen(Color.Black, 2f)) { g.DrawLine(p2, pos, to2D(mProjectorPlugin.RoomPosition + mPosition + toScreen)); g.DrawString(String.Format("To Screen: {0:.#}cm", D / 10f), font, Brushes.Black, to2D(mProjectorPlugin.RoomPosition + mPosition + (toScreen / 2f))); if (perspective == Perspective.X || perspective == Perspective.Y) { Vector3 toCeiling = new Vector3(0f, 0f, RelativePosition.Z); g.DrawString(String.Format("Z: {0:.#}cm", RelativePosition.Z / 10f), font, Brushes.Black, to2D(mProjectorPlugin.RoomPosition + mPosition + (toCeiling / 2f))); g.DrawLine(p2, pos, to2D(mProjectorPlugin.RoomPosition + mPosition + toCeiling)); g.DrawString(String.Format("Clearance: {0:.#}cm", Clearance / 10f), font, Brushes.Black, to2D(floor + (clearance / 2f))); g.DrawLine(p2, to2D(floor), to2D(toClearance)); } if (perspective == Perspective.X || perspective == Perspective.Z) { Vector3 toSide = new Vector3(0f, RelativePosition.Y, 0f); g.DrawString(String.Format("Y: {0:.#}cm", RelativePosition.Y / 10f), font, Brushes.Black, to2D(mProjectorPlugin.RoomPosition + mPosition + (toSide / 2f))); g.DrawLine(p2, pos, to2D(mProjectorPlugin.RoomPosition + mPosition + toSide)); } if (perspective == Perspective.Y || perspective == Perspective.Z) { Vector3 toFar = new Vector3(RelativePosition.X, 0f, 0f); g.DrawString(String.Format("X: {0:.#}cm", RelativePosition.X / 10f), font, Brushes.Black, to2D(mProjectorPlugin.RoomPosition + mPosition + (toFar / 2f))); g.DrawLine(p2, pos, to2D(mProjectorPlugin.RoomPosition + mPosition + toFar)); } } } } }