/// <summary> /// Handles key-down events</summary> /// <param name="sender">Control that raised original event</param> /// <param name="e">Event args</param> /// <returns>true, if controller handled the event</returns> public override bool KeyDown(object sender, KeyEventArgs e) { m_keyMap[e.KeyValue] = true; ControlScheme controlSchm = InputScheme.ActiveControlScheme; // W A S D for forward, strafe left, backward, strafe right, is the default Vec3F dir = new Vec3F(); if (m_keyMap[(int)controlSchm.Left1] || m_keyMap[(int)controlSchm.Left2]) dir = dir - Camera.Right; if (m_keyMap[(int)controlSchm.Right1] || m_keyMap[(int)controlSchm.Right2]) dir = dir + Camera.Right; if (m_keyMap[(int)controlSchm.Forward1] || m_keyMap[(int)controlSchm.Forward2]) dir = dir + Camera.LookAt; if (m_keyMap[(int)controlSchm.Back1] || m_keyMap[(int)controlSchm.Back2]) dir = dir - Camera.LookAt; bool handled = controlSchm.IsControllingCamera(Control.ModifierKeys, e); if (handled) { dir.Normalize(); Camera.Set(Camera.Eye + dir * m_scale); } return handled; }
/// <summary> /// Extends sphere to enclose another sphere</summary> /// <param name="sphere">Sphere to enclose</param> /// <returns>Extended sphere</returns> public Sphere3F Extend(Sphere3F sphere) { if (!m_initialized) { Center = sphere.Center; Radius = sphere.Radius; m_initialized = true; } else if (!Contains(sphere)) { if (Center == sphere.Center) { Radius = sphere.Radius; } else { Vec3F normal = Vec3F.Normalize(sphere.Center - Center); Vec3F p1 = sphere.Center + (normal * sphere.Radius); Vec3F p2 = Center - (normal * Radius); Radius = (p2 - p1).Length / 2.0f; Center = (p1 + p2) / 2.0f; } } return this; }
private void TestToStringWithCulture(CultureInfo culture) { CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = culture; try { string listSeparator = culture.TextInfo.ListSeparator; string decimalSeparator = culture.NumberFormat.NumberDecimalSeparator; var o = new BezierSpline(); var controlPoint1 = new Vec3F(1.1f, 2.2f, 3.3f); var controlPoint2 = new Vec3F(4.4f, 5.5f, 6.6f); var controlPoint3 = new Vec3F(7.7f, 8.8f, 9.9f); var incomingTangent = new Vec3F(-1.0f, -2.0f, -3.0f); var outgoingTangent = new Vec3F(1.0f, 2.0f, 3.0f); o.Add(new BezierPoint(controlPoint1, incomingTangent, outgoingTangent)); o.Add(new BezierPoint(controlPoint2, incomingTangent, outgoingTangent)); o.Add(new BezierPoint(controlPoint3, incomingTangent, outgoingTangent)); string s = o.ToString(null, null); TestToStringResults(o, s, listSeparator, decimalSeparator); string s2 = o.ToString(); Assert.AreEqual(s, s2); s = o.ToString("G", culture); TestToStringResults(o, s, listSeparator, decimalSeparator); s = o.ToString("R", culture); TestToStringResults(o, s, listSeparator, decimalSeparator); } finally { Thread.CurrentThread.CurrentCulture = originalCulture; } }
/// <summary> /// Handles key-down events</summary> /// <param name="sender">Control that raised original event</param> /// <param name="e">Event args</param> /// <returns>True if controller handled the event</returns> public override bool KeyDown(object sender, KeyEventArgs e) { m_keyMap[e.KeyValue] = true; // W A S D for forward, strafe left, backward, strafe right, is the default Vec3F dir = new Vec3F(); if (m_keyMap[(int)CanvasControl3D.ControlScheme.Left1] || m_keyMap[(int)CanvasControl3D.ControlScheme.Left2]) dir = dir - Camera.Right; if (m_keyMap[(int)CanvasControl3D.ControlScheme.Right1] || m_keyMap[(int)CanvasControl3D.ControlScheme.Right2]) dir = dir + Camera.Right; if (m_keyMap[(int)CanvasControl3D.ControlScheme.Forward1] || m_keyMap[(int)CanvasControl3D.ControlScheme.Forward2]) dir = dir + Camera.LookAt; if (m_keyMap[(int)CanvasControl3D.ControlScheme.Back1] || m_keyMap[(int)CanvasControl3D.ControlScheme.Back2]) dir = dir - Camera.LookAt; bool handled = CanvasControl3D.ControlScheme.IsControllingCamera(Control.ModifierKeys, e); if (handled) { dir.Normalize(); Vec3F p = Camera.Eye; float y = p.Y; p += dir * m_scale; p.Y = y; Camera.Set(p); } return handled; }
/// <summary> /// Finds the intersection point of the ray with the given plane. Checks /// for the ray being parallel with the plane or the ray pointing away /// from the plane</summary> /// <param name="plane">Must be constructed "by the rules" of Plane3F</param> /// <param name="intersectionPoint">The resulting intersection point or /// the zero-point if there was no intersection</param> /// <returns>True if the ray points towards the plane and intersects it</returns> public bool IntersectPlane(Plane3F plane, out Vec3F intersectionPoint) { // both the normal and direction must be unit vectors. float cos = Vec3F.Dot(plane.Normal, Direction); if (Math.Abs(cos) > 0.0001f) { // dist > 0 means "on the same side as the normal", aka, "the front". float dist = plane.SignedDistance(Origin); // There are two cases for the ray shooting away from the plane: // 1. If the ray is in front of the plane and pointing away, // then 'cos' and 'dist' are both > 0. // 2. If the ray is in back of the plane and pointing away, // then 'cos' and 'dist' are both < 0. // So, if the signs are the same, then there's no intersection. // So, if 'cos' * 'dist' is positive, then there's no intersection. if (cos * dist < 0.0) { // There are two cases for the ray hitting the plane: // 1. Origin is behind the plane, so the ray and normal are aligned // and 'dist' is < 0. We need to negate 'dist'. // 2. Origin is in front of the plane, so the ray needs to be negated // so that cos(angle-180) is calculated. 'dist' is > 0. // Either way, we've got a -1 thrown into the mix. Tricky! float t = -dist / cos; intersectionPoint = Origin + (Direction * t); return true; } } intersectionPoint = new Vec3F(0, 0, 0); return false; }
private void TestToStringWithCulture(CultureInfo culture) { CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = culture; try { string listSeparator = culture.TextInfo.ListSeparator; string decimalSeparator = culture.NumberFormat.NumberDecimalSeparator; var corner1 = new Vec3F(1.1f, 2.2f, 3.3f); var corner2 = new Vec3F(4.4f, 5.5f, 6.6f); var o = new Box(corner1, corner2); string s = o.ToString(null, null); TestToStringResults(o, s, listSeparator, decimalSeparator); s = o.ToString("G", culture); TestToStringResults(o, s, listSeparator, decimalSeparator); s = o.ToString("R", culture); TestToStringResults(o, s, listSeparator, decimalSeparator); } finally { Thread.CurrentThread.CurrentCulture = originalCulture; } }
private void TestToStringWithCulture(CultureInfo culture) { CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = culture; try { string listSeparator = culture.TextInfo.ListSeparator; string decimalSeparator = culture.NumberFormat.NumberDecimalSeparator; var normal = new Vec3F(1.1f, 2.2f, 3.3f); normal.Normalize(); var o = new Plane3F(normal, 4.4f); string s = o.ToString(null, null); TestToStringResults(o, s, listSeparator, decimalSeparator); string s2 = o.ToString(); Assert.AreEqual(s, s2); s = o.ToString("G", culture); TestToStringResults(o, s, listSeparator, decimalSeparator); s = o.ToString("R", culture); TestToStringResults(o, s, listSeparator, decimalSeparator); } finally { Thread.CurrentThread.CurrentCulture = originalCulture; } }
/// <summary> /// Snaps the given point to the nearest grid vertex</summary> /// <param name="pt">Point to snap, in world space</param> /// <returns>Point, from given point, snapped to grid, in world space</returns> public Vec3F SnapPoint(Vec3F pt) { float segment = Size / (float)Subdivisions; Vec3F snap = new Vec3F((int)(pt.X / segment), 0, (int)(pt.Z / segment)); snap = snap * segment; snap.Y = Height; return snap; }
/// <summary> /// Draws a colored line from point 1 to point 2</summary> /// <param name="p1">Point 1</param> /// <param name="p2">Point 2</param> public static void DrawLine(Vec3F p1, Vec3F p2) { Gl.glBegin(Gl.GL_LINES); Gl.glVertex3d(p1.X, p1.Y, p1.Z); Gl.glVertex3d(p2.X, p2.Y, p2.Z); Gl.glEnd(); Util3D.RenderStats.VertexCount += 2; }
/// <summary> /// Constructs a plane from 3 non-linear points on the plane, such that /// Normal * p = Distance</summary> /// <param name="p1">First point</param> /// <param name="p2">Second point</param> /// <param name="p3">Third point</param> public Plane3F(Vec3F p1, Vec3F p2, Vec3F p3) { Vec3F d12 = p2 - p1; Vec3F d13 = p3 - p1; Vec3F normal = Vec3F.Cross(d12, d13); Normal = Vec3F.Normalize(normal); Distance = Vec3F.Dot(Normal, p1); }
/// <summary> /// Decomposes the given matrix to translation, scale, /// and rotation and set them to given Transformable node. /// </summary> public static void SetTransform(ITransformable xform, Matrix4F mtrx) { xform.Translation = mtrx.Translation; xform.Scale = mtrx.GetScale(); Vec3F rot = new Vec3F(); mtrx.GetEulerAngles(out rot.X, out rot.Y, out rot.Z); xform.Rotation = rot; xform.UpdateTransform(); }
/// <summary> /// Draws a colored line from point 1 to point 2</summary> /// <param name="p1">Point 1</param> /// <param name="p2">Point 2</param> /// <param name="color">Line color</param> public static void DrawLine(Vec3F p1, Vec3F p2, Color color) { Gl.glBegin(Gl.GL_LINES); Gl.glColor3ub(color.R, color.G, color.B); Gl.glVertex3d(p1.X, p1.Y, p1.Z); Gl.glVertex3d(p2.X, p2.Y, p2.Z); Gl.glEnd(); Util3D.RenderStats.VertexCount += 2; }
/// <summary> /// Evaluate the curve on parameter t [0,1]</summary> /// <param name="t">Parameter</param> /// <returns>Resulting 3D vector</returns> public Vec3F Evaluate(float t) { Vec3F result = new Vec3F(); float tSquared = t * t; float tCubed = tSquared * t; result = (m_coefficients[0] * tCubed) + (m_coefficients[1] * tSquared) + (m_coefficients[2] * t) + m_ctrlPoints[0]; return result; }
// creates grid unit grid. public void CreateVertices() { DeleteVertexBuffer(); IGrid grid = this.As<IGrid>(); m_subDiv = grid.Subdivisions; float corner = 0.5f; // grid.Size / 2.0f; float step = 1.0f / (float)m_subDiv; // grid.Size / (float)subDiv; int numLines = (m_subDiv + 1) * 2; int numVerts = numLines * 2; var vertices = new Vec3F[numVerts]; int index = 0; float s = -corner; // Create vertical lines for (int i = 0; i <= m_subDiv; i++) { vertices[index] = new Vec3F(s, 0, corner); vertices[index + 1] = new Vec3F(s, 0, -corner); index += 2; s += step; } // Create horizontal lines s = -corner; for (int i = 0; i <= m_subDiv; i++) { vertices[index] = new Vec3F(corner, 0, s); vertices[index + 1] = new Vec3F(-corner, 0, s); index += 2; s += step; } m_gridVBId = GameEngine.CreateVertexBuffer(vertices); m_gridVertexCount = (uint)vertices.Length; { var vs = new VertexPC[6]; vs[0] = new VertexPC( 0.0f, 0.0f, 0.0f, 0xff0000ff); vs[1] = new VertexPC(corner, 0.0f, 0.0f, 0xff0000ff); vs[2] = new VertexPC( 0.0f, 0.0f, 0.0f, 0xff00ff00); vs[3] = new VertexPC( 0.0f, corner, 0.0f, 0xff00ff00); vs[4] = new VertexPC( 0.0f, 0.0f, 0.0f, 0xffff0000); vs[5] = new VertexPC( 0.0f, 0.0f, corner, 0xffff0000); m_basisAxesVBId = GameEngine.CreateVertexBuffer(vs); m_basisAxesVertexCount = (uint)vs.Length; } }
/// <summary> /// Construct a Bezier curve from 4 control points</summary> /// <param name="controlPoints">Array of control points</param> public BezierCurve(Vec3F[] controlPoints) { m_ctrlPoints = controlPoints; // Calcualte coefficients m_coefficients = new Vec3F[3]; m_coefficients[2] = 3.0f * (m_ctrlPoints[1] - m_ctrlPoints[0]); m_coefficients[1] = 3.0f * (m_ctrlPoints[2] - m_ctrlPoints[1]) - m_coefficients[2]; m_coefficients[0] = m_ctrlPoints[3] - m_ctrlPoints[0] - m_coefficients[2] - m_coefficients[1]; }
/// <summary> /// Gets the DomNode attribute as a Vec3F and returns true, or returns false if the attribute /// doesn't exist</summary> /// <param name="domNode">DomNode holding the attribute</param> /// <param name="attribute">Attribute of the DomNode that contains the data</param> /// <param name="result">The resulting Vec3F. Is (0,0,0) if the attribute couldn't be found</param> /// <returns>True iff the attribute was found and was converted to a Vec3F</returns> public static bool GetVector(DomNode domNode, AttributeInfo attribute, out Vec3F result) { float[] floats = domNode.GetAttribute(attribute) as float[]; if (floats != null) { result = new Vec3F(floats); return true; } result = new Vec3F(); return false; }
public override void OnBeginDrag() { if (m_hitRegion == HitRegion.None || !CanManipulate(m_node)) return; var transactionContext = DesignView.Context.As<ITransactionContext>(); transactionContext.Begin("Move".Localize()); m_originalPivot = m_node.Pivot; Path<DomNode> path = new Path<DomNode>(m_node.Cast<DomNode>().GetPath()); Matrix4F localToWorld = TransformUtils.CalcPathTransform(path, path.Count - 1); m_worldToLocal = new Matrix4F(); m_worldToLocal.Invert(localToWorld); }
private void TestToStringResults(Vec3F o, string s, string listSeparator, string decimalSeparator) { string[] results = s.Split(new[] { listSeparator }, StringSplitOptions.RemoveEmptyEntries); Assert.AreEqual(results.Length, 3); foreach (string oneFloatString in results) Assert.True(oneFloatString.Contains(decimalSeparator)); Assert.AreEqual(float.Parse(results[0]), o.X); Assert.AreEqual(float.Parse(results[1]), o.Y); Assert.AreEqual(float.Parse(results[2]), o.Z); Vec3F roundTrip = Vec3F.Parse(s); Assert.AreEqual(roundTrip.X, o.X); Assert.AreEqual(roundTrip.Y, o.Y); Assert.AreEqual(roundTrip.Z, o.Z); }
public Point WorldToSurfaceSpace(Vec3F posW) { Point result = new Point(); TerrainGob terrain = this.GetParentAs<TerrainGob>(); ImageData hmImg = terrain.GetSurface(); ImageData mpImg = GetSurface(); Point posH = terrain.WorldToSurfaceSpace(posW); float dx = (float)mpImg.Width / (float)hmImg.Width; float dy = (float)mpImg.Height / (float)hmImg.Height; result.X = (int)Math.Round(posH.X * dx); result.Y = (int)Math.Round(posH.Y * dy); return result; }
/// <summary> /// Draws a 3D arrow from point 1 to point 2 using an OpenGL display list for greatly improved /// performance. This method must not be called in between Gl.glNewList and Gl.glEndList.</summary> /// <param name="p1">Point 1</param> /// <param name="p2">Point 2</param> /// <param name="coneSize">Arrow head base diameter</param> public static void DrawArrowDisplayList(Vec3F p1, Vec3F p2, float coneSize) { Gl.glBegin(Gl.GL_LINES); Gl.glVertex3f(p1.X, p1.Y, p1.Z); Gl.glVertex3f(p2.X, p2.Y, p2.Z); Gl.glEnd(); Gl.glPushMatrix(); Gl.glTranslatef(p2.X, p2.Y, p2.Z); Gl.glPushMatrix(); Util3D.glMultMatrixf(LookAtMatrix(p2 - p1)); DrawConeDisplayList(coneSize, coneSize * 2, RenderStyle.Solid); Gl.glPopMatrix(); Gl.glPopMatrix(); Util3D.RenderStats.VertexCount += 2; }
/// <summary> /// Sets this frustum to frustum represented by the given values</summary> /// <param name="fovY">Y field-of-view</param> /// <param name="aspectRatio">Aspect ration of frustum cross section</param> /// <param name="near">Near plane distance</param> /// <param name="far">Far plane distance</param> public void SetPerspective(float fovY, float aspectRatio, float near, float far) { float tanY = (float)Math.Tan((double)fovY / 2.0); float tanX = tanY * aspectRatio; Vec3F xAxis = new Vec3F(-1, 0, -tanX); Vec3F yAxis = new Vec3F(0, -1, -tanY); float nX = xAxis.Length; float nY = yAxis.Length; // The view coordinate system has +y pointing up, +x to the right, +z out of the screen. m_planes[iRight].Set(new Vec3F(-1, 0, -tanX) / nX, 0.0f); m_planes[iLeft].Set(new Vec3F(1, 0, -tanX) / nX, 0.0f); m_planes[iTop].Set(new Vec3F(0, -1, -tanY) / nY, 0.0f); m_planes[iBottom].Set(new Vec3F(0, 1, -tanY) / nY, 0.0f); m_planes[iNear].Set(new Vec3F(0, 0, -1), near); m_planes[iFar].Set(new Vec3F(0, 0, 1), -far); }
/// <summary> /// Extends box to contain the given point, or if this box is uninitialized, the box is /// initialized from the point</summary> /// <param name="p">Point</param> /// <returns>Extended box</returns> public void Extend(Vec3F p) { if (m_initialized == false) { Min = Max = p; m_initialized = true; } else { Min.X = Math.Min(Min.X, p.X); Min.Y = Math.Min(Min.Y, p.Y); Min.Z = Math.Min(Min.Z, p.Z); Max.X = Math.Max(Max.X, p.X); Max.Y = Math.Max(Max.Y, p.Y); Max.Z = Math.Max(Max.Z, p.Z); } }
/// <summary> /// Handles mouse-down events</summary> /// <param name="sender">Control that raised original event</param> /// <param name="e">Event args</param> /// <returns>true, if controller handled the event</returns> public override bool MouseDown(object sender, MouseEventArgs e) { if (InputScheme.ActiveControlScheme.IsControllingCamera(Control.ModifierKeys, e)) { m_lastMousePoint = e.Location; m_dragging = true; Control c = sender as Control; m_width = c.Width; m_height = c.Height; // get initial rotation m_firstPoint = ProjectToArcball(m_lastMousePoint); return true; } return base.MouseDown(sender, e); }
/// <summary> /// Gets all the data required to completely represent this camera's state, so that it can /// later be restored by calling SetState(). Note that the aspect ratio is not saved and /// restored, because it should be set depending on the aspect ratio of the viewport; it would /// be wrong to restore the camera's aspect ratio after the user has resized the window, for example.</summary> /// <param name="perspective">Camera view type</param> /// <param name="eye">Eye point in "world view" space</param> /// <param name="lookAtPoint">Camera look-at point in "world view" space</param> /// <param name="upVector">Camera up direction in "world view" space</param> /// <param name="yFov">Y-field-of-view in radians</param> /// <param name="nearZ">Current near plane distance value for the current projection type</param> /// <param name="farZ">Current far plane distance value for the current projection type</param> /// <param name="focusRadius">Focus radius around the "look at" point</param> public void GetState( out ViewTypes perspective, out Vec3F eye, out Vec3F lookAtPoint, out Vec3F upVector, out float yFov, out float nearZ, out float farZ, out float focusRadius) { perspective = m_viewType; eye = Eye; lookAtPoint = LookAtPoint; upVector = Up; yFov = YFov; nearZ = NearZ; farZ = FarZ; focusRadius = FocusRadius; }
/// <summary> /// Calculates required scale such that when it applied to an /// object. The object maintain a constant size in pixel regardless of /// its distance from camera. /// Used for computing size of 3d manipulators.</summary> /// <param name="camera"></param> /// <param name="objectPosW"></param> /// <param name="sizeInPixels"></param> /// <param name="viewHeight"></param> public static float CalcAxisScale(Camera camera, Vec3F objectPosW, float sizeInPixels, float viewHeight) { float worldHeight; // World height on origin's z value if (camera.Frustum.IsOrtho) { worldHeight = (camera.Frustum.Top - camera.Frustum.Bottom); } else { Matrix4F view = camera.ViewMatrix; Vec3F objPosV; view.Transform(objectPosW, out objPosV); worldHeight = 2.0f * Math.Abs(objPosV.Z) * (float)Math.Tan(camera.Frustum.FovY / 2.0f); } return sizeInPixels * (worldHeight / viewHeight); }
public IControlPoint InsertPoint(uint index, float x, float y, float z) { IControlPoint cpt = CreateControlPoint(); int numSteps = GetAttribute<int>(Schema.curveType.stepsAttribute); int interpolationType = GetAttribute<int>(Schema.curveType.interpolationTypeAttribute); if (interpolationType != 0 && numSteps > 0) { index = index / (uint)numSteps; } Path<DomNode> path = new Path<DomNode>(DomNode.GetPath()); Matrix4F toworld = TransformUtils.CalcPathTransform(path, path.Count - 1); Matrix4F worldToLocal = new Matrix4F(); worldToLocal.Invert(toworld); Vec3F pos = new Vec3F(x, y, z); worldToLocal.Transform(ref pos); cpt.Translation = pos; ControlPoints.Insert((int)index + 1, cpt); return cpt; }
private static float CalcAngle(Vec3F v0, Vec3F v1, Vec3F axis, float snapAngle) { const float twoPi = (float)(2.0 * Math.PI); float angle = Vec3F.Dot(v0, v1); if (angle > 1.0f) { angle = 1.0f; } else if (angle <= -1.0f) { angle = 1.0f; } angle = (float)Math.Acos(angle); // Check if v0 is left of v1 Vec3F cross = Vec3F.Cross(v0, v1); if (Vec3F.Dot(cross, axis) < 0) { angle = twoPi - angle; } // round to nearest multiple of preference if (snapAngle > 0) { if (angle >= 0) { int n = (int)((angle + snapAngle * 0.5f) / snapAngle); angle = n * snapAngle; } else { int n = (int)((angle - snapAngle * 0.5f) / snapAngle); angle = n * snapAngle; } } // const float epsilone = (float)1e-7; // if (twoPi - angle <= epsilone) angle = 0.0f; return(angle); }
/// <summary> /// Handles mouse-move events</summary> /// <param name="sender">Control that raised original event</param> /// <param name="e">Event args</param> /// <returns>true, if controller handled the event</returns> public override bool MouseMove(object sender, MouseEventArgs e) { if (m_dragging && InputScheme.ActiveControlScheme.IsControllingCamera(Control.ModifierKeys, e)) { float dx = (float)(e.X - m_lastMousePoint.X) / 150.0f; float dy = (float)(e.Y - m_lastMousePoint.Y) / 150.0f; if (InputScheme.ActiveControlScheme.IsElevating(Control.ModifierKeys, e)) { // move camera up/down Vec3F p = Camera.Eye; p.Y += (dy < 0) ? m_scale : -m_scale; Camera.Set(p); } else if (InputScheme.ActiveControlScheme.IsTurning(Control.ModifierKeys, e)) { // pitch and yaw camera Matrix4F mat = Matrix4F.RotAxisRH(Camera.Right, -dy); // pitch along camera right Matrix4F yaw = new Matrix4F(); yaw.RotY(-dx); mat.Mul(yaw, mat); Vec3F lookAt = Camera.LookAt; Vec3F up = Camera.Up; mat.Transform(ref lookAt); mat.Transform(ref up); Vec3F position = Camera.Eye; float d = Camera.DistanceFromLookAt; Camera.Set(position, position + lookAt * d, up); } m_lastMousePoint = e.Location; return(true); } return(base.MouseMove(sender, e)); }
private static float CalcAngle(Vec3F v0, Vec3F v1, Vec3F axis, float snapAngle) { float angle = Vec3F.Dot(v0, v1); if (angle > 1.0f) { angle = 1.0f; } else if (angle < -1.0f) { angle = 1.0f; } angle = (float)Math.Acos(angle); // Check if v0 is left of v1 Vec3F cross = Vec3F.Cross(v0, v1); if (Vec3F.Dot(cross, axis) < 0) { angle = -angle; } // round to nearest multiple of preference if (snapAngle > 0) { if (angle >= 0) { int n = (int)((angle + snapAngle * 0.5) / snapAngle); angle = n * snapAngle; } else { int n = (int)((angle - snapAngle * 0.5) / snapAngle); angle = n * snapAngle; } } return(angle); }
/// <summary> /// Sets this cammera's state completely. Complements GetState().</summary> /// <param name="root">The XML element containing the state of a camera</param> /// <param name="xmlDoc">The XML document that owns 'root'</param> public void SetState(XmlElement root, XmlDocument xmlDoc) { ViewTypes viewType; Vec3F eye; Vec3F lookAtPoint; Vec3F upVector; float yFov; float nearZ; float farZ; float focusRadius; string value; value = root.GetAttribute("viewType"); viewType = (ViewTypes)int.Parse(value, NumberStyles.AllowHexSpecifier); value = root.GetAttribute("eye"); eye = Vec3F.Parse(value); value = root.GetAttribute("lookAtPoint"); lookAtPoint = Vec3F.Parse(value); value = root.GetAttribute("upVector"); upVector = Vec3F.Parse(value); value = root.GetAttribute("yFov"); yFov = float.Parse(value); value = root.GetAttribute("nearZ"); nearZ = float.Parse(value); value = root.GetAttribute("farZ"); farZ = float.Parse(value); value = root.GetAttribute("focusRadius"); focusRadius = float.Parse(value); SetState(viewType, eye, lookAtPoint, upVector, yFov, nearZ, farZ, focusRadius); }
public override void OnEndDrag(ViewControl vc, Point scrPt) { if (NodeList.Count > 0) { for (int k = 0; k < NodeList.Count; k++) { IManipulatorNotify notifier = NodeList[k].As <IManipulatorNotify>(); if (notifier != null) { notifier.OnEndDrag(); } } var transactionContext = DesignView.Context.As <ITransactionContext>(); try { if (transactionContext.InTransaction) { transactionContext.End(); } } catch (InvalidTransactionException ex) { if (transactionContext.InTransaction) { transactionContext.Cancel(); } if (ex.ReportError) { Outputs.WriteLine(OutputMessageType.Error, ex.Message); } } } NodeList.Clear(); m_originalValues = null; m_hitRegion = HitRegion.None; m_scale = new Vec3F(1, 1, 1); }
/// <summary> /// Handles key-down events</summary> /// <param name="sender">Control that raised original event</param> /// <param name="e">Event args</param> /// <returns>True if controller handled the event</returns> public override bool KeyDown(object sender, KeyEventArgs e) { m_keyMap[e.KeyValue] = true; // W A S D for forward, strafe left, backward, strafe right, is the default Vec3F dir = new Vec3F(); if (m_keyMap[(int)CanvasControl3D.ControlScheme.Left1] || m_keyMap[(int)CanvasControl3D.ControlScheme.Left2]) { dir = dir - Camera.Right; } if (m_keyMap[(int)CanvasControl3D.ControlScheme.Right1] || m_keyMap[(int)CanvasControl3D.ControlScheme.Right2]) { dir = dir + Camera.Right; } if (m_keyMap[(int)CanvasControl3D.ControlScheme.Forward1] || m_keyMap[(int)CanvasControl3D.ControlScheme.Forward2]) { dir = dir + Camera.LookAt; } if (m_keyMap[(int)CanvasControl3D.ControlScheme.Back1] || m_keyMap[(int)CanvasControl3D.ControlScheme.Back2]) { dir = dir - Camera.LookAt; } bool handled = CanvasControl3D.ControlScheme.IsControllingCamera(Control.ModifierKeys, e); if (handled) { dir.Normalize(); Camera.Set(Camera.Eye + dir * m_scale); } return(handled); }
private void UpdateGeometry() { // create orthornormal basis from lookAt and up vectors m_lookAt = m_lookAtPoint - m_eye; m_lookAt.Normalize(); m_right = Vec3F.Cross(m_lookAt, m_up); m_right.Normalize(); m_up = Vec3F.Cross(m_right, m_lookAt); //m_up.Normalize(); // m_right is already unit length m_lookAtDistance = Vec3F.Distance(m_eye, m_lookAtPoint); if (ProjectionType == ProjectionType.Orthographic) { SetOrthographic(m_lookAtDistance); } else { OnCameraChanged(EventArgs.Empty); } }
/// <summary> /// Sets this cammera's state completely. Complements GetState().</summary> /// <param name="viewType">Camera view type</param> /// <param name="eye">Eye point in "world view" space</param> /// <param name="lookAtPoint">Camera look-at point in "world view" space</param> /// <param name="upVector">Camera up direction in "world view" space</param> /// <param name="yFov">Y-field-of-view in radians</param> /// <param name="nearZ">Current near plane distance value for the current projection type</param> /// <param name="farZ">Current far plane distance value for the current projection type</param> /// <param name="focusRadius">Focus radius around the "look at" point</param> public void SetState( ViewTypes viewType, Vec3F eye, Vec3F lookAtPoint, Vec3F upVector, float yFov, float nearZ, float farZ, float focusRadius) { // to avoid duplicate camera events, let's batch up all the changes. m_changingCamera = true; try { m_viewType = viewType; Set(eye, lookAtPoint, upVector); if (viewType == ViewTypes.Perspective) { SetPerspective(yFov, m_aspectRatio, nearZ, farZ); } else { float d = DistanceFromLookAt; SetOrthographic(d * m_aspectRatio / 2, -d * m_aspectRatio / 2, d / 2, -d / 2, nearZ, farZ); } } finally { m_changingCamera = false; } OnCameraChanged(EventArgs.Empty); }
public override bool Pick(ViewControl vc, Point scrPt) { m_hitRegion = HitRegion.None; if (base.Pick(vc, scrPt) == false) return false; Camera camera = vc.Camera; Matrix4F view = camera.ViewMatrix; Matrix4F vp = view * camera.ProjectionMatrix; Matrix4F wvp = HitMatrix * vp; Ray3F rayL = vc.GetRay(scrPt,wvp); float s = Util.CalcAxisScale(vc.Camera, HitMatrix.Translation, AxisLength, vc.Height); // There's only one hot-spot for this manipulator: // a square at the manipulator origin. Vec3F min = new Vec3F(-0.5f, -0.5f, -0.5f); Vec3F max = new Vec3F(0.5f, 0.5f, 0.5f); AABB box = new AABB(min, max); float centerCubeScale = s * CenterCubeSize; Matrix4F centerCubeXform = new Matrix4F(); centerCubeXform.Scale(centerCubeScale); centerCubeXform.Invert(centerCubeXform); Ray3F ray = rayL; ray.Transform(centerCubeXform); if (box.Intersect(ray)) { m_hitRegion = HitRegion.XYSquare; return true; } m_hitRegion = HitRegion.None; return false; }
/// <summary> /// Synchronizes the camera to the controller's current state</summary> /// <param name="camera">Camera</param> protected override void ControllerToCamera(Camera camera) { Vec3F lookAt = camera.LookAt; Vec3F right = camera.Right; Vec3F up = camera.Up; if (camera.ViewType == ViewTypes.Perspective) { Camera.PerspectiveNearZ = CalculatePerspectiveNearZ(); // override the camera's frame of reference float sinPhi = (float)Math.Sin(m_elevation); float cosPhi = (float)Math.Cos(m_elevation); float sinTheta = (float)Math.Sin(m_azimuth); float cosTheta = (float)Math.Cos(m_azimuth); lookAt = new Vec3F(-cosPhi * sinTheta, -sinPhi, -cosPhi * cosTheta); right = new Vec3F(cosTheta, 0, -sinTheta); up = Vec3F.Cross(right, lookAt); // TODO compute from sin/cos values } float lookAtOffset = 0; if (m_distanceFromLookAt < m_dollyThreshold) // do we need to start dollying? { lookAtOffset = m_distanceFromLookAt - m_dollyThreshold; } float eyeOffset = m_distanceFromLookAt; Camera.Set( m_lookAtPoint - (eyeOffset * lookAt), // eye point m_lookAtPoint - (lookAtOffset * lookAt), // look-at point up); // up vector base.ControllerToCamera(camera); }
/// <summary> /// Calculates the transformation matrix corresponding to the given transform components /// </summary> /// <param name="translation">Translation</param> /// <param name="rotation">Rotation</param> /// <param name="scale">Scale</param> /// <param name="scalePivot">Translation to origin of scaling</param> /// <param name="scalePivotTranslate">Translation after scaling</param> /// <param name="rotatePivot">Translation to origin of rotation</param> /// <param name="rotatePivotTranslate">Translation after rotation</param> /// <returns>transformation matrix corresponding to the given transform components</returns> public static Matrix4F CalcTransform( Vec3F translation, Vec3F rotation, Vec3F scale, Vec3F pivot) { Matrix4F M = new Matrix4F(); Matrix4F temp = new Matrix4F(); M.Set(-pivot); temp.Scale(scale); M.Mul(M, temp); if (rotation.X != 0) { temp.RotX(rotation.X); M.Mul(M, temp); } if (rotation.Y != 0) { temp.RotY(rotation.Y); M.Mul(M, temp); } if (rotation.Z != 0) { temp.RotZ(rotation.Z); M.Mul(M, temp); } temp.Set(pivot + translation); M.Mul(M, temp); return(M); }
public override void Render(ViewControl vc) { Matrix4F normWorld = GetManipulatorMatrix(); if (normWorld == null) { return; } Util3D.RenderFlag = BasicRendererFlags.WireFrame | BasicRendererFlags.DisableDepthTest; Color xcolor = (m_hitRegion == HitRegion.XAxis) ? Color.LightSalmon : Color.Red; Color ycolor = (m_hitRegion == HitRegion.YAxis) ? Color.LightGreen : Color.Green; Color Zcolor = (m_hitRegion == HitRegion.ZAxis) ? Color.LightBlue : Color.Blue; float s; Util.CalcAxisLengths(vc.Camera, normWorld.Translation, out s); Vec3F axScale = new Vec3F(s, s, s); Matrix4F scale = new Matrix4F(); scale.Scale(axScale); Matrix4F xform = scale * normWorld; Util3D.DrawCircle(xform, Zcolor); Matrix4F rot = new Matrix4F(); rot.RotY(MathHelper.PiOver2); xform = scale * rot * normWorld; Util3D.DrawCircle(xform, xcolor); rot.RotX(MathHelper.PiOver2); xform = scale * rot * normWorld; Util3D.DrawCircle(xform, ycolor); }
/// <summary> /// Intersects the specified client point with the scene, knowing that the given /// HitRecords were the result of having called Dispatch with these same client points</summary> /// <param name="x">Client x coordinate</param> /// <param name="y">Client y coordinate</param> /// <param name="hits">The hits</param> /// <param name="pt">The intersection point</param> /// <param name="surfaceNormal">The surface normal of the target object at the intersection /// point, or the zero vector if the surface normal could not be found. Check against /// Vec3F.ZeroVector before using.</param> /// <returns>True iff client point intersects scene</returns> protected bool Intersect(int x, int y, HitRecord[] hits, ref Vec3F pt, out Vec3F surfaceNormal) { surfaceNormal = new Vec3F(); if (hits.Length == 0) { return(false); } HitRecord hit = hits[0]; if (hit.HasNormal) { surfaceNormal = hit.Normal; } if (hit.HasWorldIntersection) { pt = hit.WorldIntersection; return(true); } return(false); }
public override void OnBeginDrag() { if (m_hitRegion == HitRegion.None) return; m_cancelDrag = false; Clear(); // cached values. var op = new ManipulatorActiveOperation( "Move", DesignView.Context.As<ISelectionContext>(), (ITransformable node) => (node.TransformationType & TransformationTypes.Translation) != 0, Control.ModifierKeys == m_duplicateKey); m_originalValues = new Vec3F[op.NodeList.Count]; m_originalRotations = new Vec3F[op.NodeList.Count]; for (int k = 0; k < op.NodeList.Count; k++) { ITransformable node = op.NodeList[k]; m_originalValues[k] = node.Translation; m_originalRotations[k] = node.Rotation; } m_activeOp = op; }
public IControlPoint InsertPoint(uint index, float x, float y, float z) { IControlPoint cpt = CreateControlPoint(); int numSteps = GetAttribute <int>(Schema.curveType.stepsAttribute); int interpolationType = GetAttribute <int>(Schema.curveType.interpolationTypeAttribute); if (interpolationType != 0 && numSteps > 0) { index = index / (uint)numSteps; } Path <DomNode> path = new Path <DomNode>(DomNode.GetPath()); Matrix4F toworld = TransformUtils.CalcPathTransform(path, path.Count - 1); Matrix4F worldToLocal = new Matrix4F(); worldToLocal.Invert(toworld); Vec3F pos = new Vec3F(x, y, z); worldToLocal.Transform(ref pos); cpt.Translation = pos; ControlPoints.Insert((int)index + 1, cpt); return(cpt); }
/// <summary> /// Projects the specified x and y, in normalized window coordinates, onto the grid, /// and snaps it to the nearest grid vertex if necessary. /// Normalized window coordinates are in the range [-0.5,0.5] with +x pointing to the /// right and +y pointing up.</summary> /// <param name="x">Window x in normalized window coords</param> /// <param name="y">Window y in normalized window coords</param> /// <param name="camera">Camera</param> /// <returns>Projection of x and y onto the grid, in world space.</returns> public Vec3F Project(float x, float y, Camera camera) { Ray3F ray = camera.CreateRay(x, y); Matrix4F V = new Matrix4F(camera.ViewMatrix); V.Mul(m_invAxisSystem, V); if (camera.Frustum.IsOrtho) { V = new Matrix4F(m_V); V.Translation = camera.ViewMatrix.Translation; } // origin Vec3F delta = new Vec3F(0, Height, 0); V.Transform(delta, out delta); Vec3F o = delta; // Up vec Vec3F axis = V.YAxis; Vec3F projPt = ray.IntersectPlane(axis, -Vec3F.Dot(o, axis)); // Transform back into world space Matrix4F Inv = new Matrix4F(); Inv.Invert(camera.ViewMatrix); Inv.Transform(projPt, out projPt); if (Snap) { projPt = SnapPoint(projPt); } return(projPt); }
/// <summary> /// Creates Billboard matrix from the given parameters.</summary> public static void CreateBillboard(Matrix4F matrix, Vec3F objectPos, Vec3F camPos, Vec3F camUp, Vector3 camLook) { Vector3 look = objectPos - camPos; float len = look.LengthSquared; if (len < 0.0001f) { look = -camLook; } else { look.Normalize(); } Vector3 right = Vec3F.Cross(camUp, look); right.Normalize(); Vector3 up = Vec3F.Cross(look, right); matrix.M11 = right.X; matrix.M12 = right.Y; matrix.M13 = right.Z; matrix.M14 = 0f; matrix.M21 = up.X; matrix.M22 = up.Y; matrix.M23 = up.Z; matrix.M24 = 0f; matrix.M31 = look.X; matrix.M32 = look.Y; matrix.M33 = look.Z; matrix.M34 = 0f; matrix.M41 = objectPos.X; matrix.M42 = objectPos.Y; matrix.M43 = objectPos.Z; matrix.M44 = 1f; }
private Vec3F ProjectToArcball(Point point) { float x = (float)point.X / (m_width / 2); // Scale so bounds map to [0,0] - [2,2] float y = (float)point.Y / (m_height / 2); x = x - 1; // Translate 0,0 to the center y = 1 - y; // Flip so +Y is up if (x < -1) x = -1; else if (x > 1) x = 1; if (y < -1) y = -1; else if (y > 1) y = 1; float z2 = 1 - x * x - y * y; // z^2 = 1 - x^2 - y^2 float z = z2 > 0 ? (float)Math.Sqrt(z2) : 0; Vec3F p = new Vec3F(x, y, z); p.Normalize(); return p; }
/// <summary> /// Synchronizes the camera to the controller's current state</summary> /// <param name="camera">Camera</param> protected override void ControllerToCamera(Camera camera) { Vec3F lookAt = Camera.LookAt; Vec3F up = Camera.Up; if (camera.ViewType == ViewTypes.Perspective) { QuatF rotation = m_rotation * m_currentRotation; rotation = rotation.Inverse; Matrix4F transform = new Matrix4F(rotation); lookAt = new Vec3F(0, 0, -1); up = new Vec3F(0, 1, 0); transform.Transform(ref lookAt); transform.Transform(ref up); } float eyeOffset = m_distanceFromLookAt; float lookAtOffset = 0; if (m_distanceFromLookAt < m_dollyThreshold) // do we need to start dollying? { eyeOffset = m_distanceFromLookAt; lookAtOffset = m_distanceFromLookAt - m_dollyThreshold; } Camera.Set( m_lookAtPoint - (eyeOffset * lookAt), // eye m_lookAtPoint - (lookAtOffset * lookAt), // lookAt up); // up base.ControllerToCamera(camera); }
private bool CalculateTerrainIntersection(ViewControl vc, Ray3F ray, GUILayer.IntersectionTestSceneWrapper testScene, out Vec3F result) { var nativeVC = vc as NativeDesignControl; if (nativeVC == null) { result = Vec3F.ZeroVector; return(false); } var pick = XLEBridgeUtils.Picking.RayPick(nativeVC.Adapter, ray, XLEBridgeUtils.Picking.Flags.Terrain); if (pick != null && pick.Length > 0) { result = pick[0].hitPt; return(true); } result = Vec3F.ZeroVector; return(false); }
public Entity Spawn(UpperString type, Vec3F position, BitAngle angle = default) { ActorDefinition definition = DecorateManager.Find(type); return(Spawn(definition, position, angle)); }
private void RenderProperties(GUILayer.SimpleRenderingContext context, IEnumerable <object> objects, bool renderCaption, bool renderBound, bool renderPivot) { if (renderCaption || renderBound) { Util3D.SetRenderFlag(context, BasicRendererFlags.WireFrame); Matrix4F vp = Camera.ViewMatrix * Camera.ProjectionMatrix; foreach (object obj in objects) { IBoundable bnode = obj.As <IBoundable>(); if (bnode == null || bnode.BoundingBox.IsEmpty || obj.Is <IGameObjectFolder>()) { continue; } INameable nnode = obj.As <INameable>(); ITransformable trans = obj.As <ITransformable>(); if (renderBound) { Util3D.DrawAABB(context, bnode.BoundingBox); } if (renderCaption && nnode != null) { Vec3F topCenter = bnode.BoundingBox.Center; topCenter.Y = bnode.BoundingBox.Max.Y; Point pt = Project(vp, topCenter); GameEngine.DrawText2D(nnode.Name, Util3D.CaptionFont, pt.X, pt.Y, Color.White); } } } if (renderPivot) { Util3D.SetRenderFlag(context, BasicRendererFlags.WireFrame | BasicRendererFlags.DisableDepthTest); // create few temp matrics to Matrix4F toWorld = new Matrix4F(); Matrix4F PV = new Matrix4F(); Matrix4F sc = new Matrix4F(); Matrix4F bl = new Matrix4F(); Matrix4F recXform = new Matrix4F(); foreach (object obj in objects) { ITransformable trans = obj.As <ITransformable>(); IBoundable bnode = obj.As <IBoundable>(); if (trans == null || bnode == null || bnode.BoundingBox.IsEmpty || obj.Is <IGameObjectFolder>()) { continue; } Path <DomNode> path = new Path <DomNode>(trans.Cast <DomNode>().GetPath()); toWorld.Set(Vec3F.ZeroVector); TransformUtils.CalcPathTransform(toWorld, path, path.Count - 1); // Offset by pivot PV.Set(trans.Pivot); toWorld.Mul(PV, toWorld); Vec3F pos = toWorld.Translation; const float pivotDiameter = 16; // in pixels float s = Util.CalcAxisScale(Camera, pos, pivotDiameter, Height); sc.Scale(s); Util.CreateBillboard(bl, pos, Camera.WorldEye, Camera.Up, Camera.LookAt); recXform = sc * bl; Util3D.DrawPivot(context, recXform, Color.Yellow); } } }
public override void OnBeginDrag() { if (m_hitRegion == HitRegion.None) { return; } m_cancelDrag = false; Clear(); // cached values. var selectionContext = DesignView.Context.As <ISelectionContext>(); var selection = selectionContext.Selection; var transactionContext = DesignView.Context.As <ITransactionContext>(); IEnumerable <DomNode> rootDomNodes = DomNode.GetRoots(selection.AsIEnumerable <DomNode>()); m_duplicating = Control.ModifierKeys == m_duplicateKey; if (m_duplicating) { List <DomNode> originals = new List <DomNode>(); foreach (DomNode node in rootDomNodes) { ITransformable transformable = node.As <ITransformable>(); if (!CanManipulate(transformable)) { continue; } originals.Add(node); } if (originals.Count > 0) { DomNode[] copies = DomNode.Copy(originals); transactionContext.Begin("Copy And Move".Localize()); List <object> newSelection = new List <object>(); // re-parent copy for (int i = 0; i < copies.Length; i++) { DomNode copy = copies[i]; DomNode original = originals[i]; ChildInfo chInfo = original.ChildInfo; if (chInfo.IsList) { original.Parent.GetChildList(chInfo).Add(copy); } else { original.Parent.SetChild(chInfo, copy); } newSelection.Add(Util.AdaptDomPath(copy)); copy.InitializeExtensions(); } selectionContext.SetRange(newSelection); NodeList.AddRange(copies.AsIEnumerable <ITransformable>()); } } else { foreach (DomNode node in rootDomNodes) { ITransformable transformable = node.As <ITransformable>(); if (!CanManipulate(transformable)) { continue; } NodeList.Add(transformable); } if (NodeList.Count > 0) { transactionContext.Begin("Move".Localize()); } } m_originalValues = new Vec3F[NodeList.Count]; m_originalRotations = new Vec3F[NodeList.Count]; for (int k = 0; k < NodeList.Count; k++) { ITransformable node = NodeList[k]; IManipulatorNotify notifier = node.As <IManipulatorNotify>(); if (notifier != null) { notifier.OnBeginDrag(); } m_originalValues[k] = node.Translation; m_originalRotations[k] = node.Rotation; } }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_cancelDrag || m_hitRegion == HitRegion.None || NodeList.Count == 0) { return; } bool hitAxis = m_hitRegion == HitRegion.XAxis || m_hitRegion == HitRegion.YAxis || m_hitRegion == HitRegion.ZAxis; Matrix4F view = vc.Camera.ViewMatrix; Matrix4F proj = vc.Camera.ProjectionMatrix; Matrix4F vp = view * proj; // create ray in world space. Ray3F rayW = vc.GetRay(scrPt, vp); // create ray in view space. Ray3F rayV = vc.GetRay(scrPt, proj); Vec3F translate = m_translatorControl.OnDragging(rayV); ISnapSettings snapSettings = (ISnapSettings)DesignView; bool snapToGeom = Control.ModifierKeys == m_snapGeometryKey; if (snapToGeom) { Vec3F manipPos = HitMatrix.Translation; Vec3F manipMove; if (hitAxis) { //Make rayw to point toward moving axis and starting // from manipulator’s world position. rayW.Direction = Vec3F.Normalize(translate); rayW.Origin = manipPos; manipMove = Vec3F.ZeroVector; m_cancelDrag = true; //stop further snap-to's } else { manipMove = rayW.ProjectPoint(manipPos) - manipPos; } for (int i = 0; i < NodeList.Count; i++) { ITransformable node = NodeList[i]; Vec3F snapOffset = TransformUtils.CalcSnapFromOffset(node, snapSettings.SnapFrom); Path <DomNode> path = new Path <DomNode>(Adapters.Cast <DomNode>(node).GetPath()); Matrix4F parentLocalToWorld = TransformUtils.CalcPathTransform(path, path.Count - 2); Vec3F orgPosW; parentLocalToWorld.Transform(m_originalValues[i], out orgPosW); Matrix4F parentWorldToLocal = new Matrix4F(); parentWorldToLocal.Invert(parentLocalToWorld); rayW.MoveToIncludePoint(orgPosW + snapOffset + manipMove); HitRecord[] hits = GameEngine.RayPick(view, proj, rayW, true); bool cansnap = false; HitRecord target = new HitRecord(); if (hits.Length > 0) { // find hit record. foreach (var hit in hits) { if (m_snapFilter.CanSnapTo(node, GameEngine.GetAdapterFromId(hit.instanceId))) { target = hit; cansnap = true; break; } } } if (cansnap) { Vec3F pos; if (target.hasNearestVert && snapSettings.SnapVertex) { pos = target.nearestVertex; } else { pos = target.hitPt; } pos -= snapOffset; parentWorldToLocal.Transform(ref pos); Vec3F diff = pos - node.Transform.Translation; node.Translation += diff; bool rotateOnSnap = snapSettings.RotateOnSnap && target.hasNormal && (node.TransformationType & TransformationTypes.Rotation) != 0; if (rotateOnSnap) { Vec3F localSurfaceNormal; parentWorldToLocal.TransformNormal(target.normal, out localSurfaceNormal); node.Rotation = TransformUtils.RotateToVector( m_originalRotations[i], localSurfaceNormal, AxisSystemType.YIsUp); } } } } else { IGrid grid = DesignView.Context.Cast <IGame>().Grid; bool snapToGrid = Control.ModifierKeys == m_snapGridKey && grid.Visible && vc.Camera.ViewType == ViewTypes.Perspective; float gridHeight = grid.Height; // translate. for (int i = 0; i < NodeList.Count; i++) { ITransformable node = NodeList[i]; Path <DomNode> path = new Path <DomNode>(Adapters.Cast <DomNode>(node).GetPath()); Matrix4F parentLocalToWorld = TransformUtils.CalcPathTransform(path, path.Count - 2); Matrix4F parentWorldToLocal = new Matrix4F(); parentWorldToLocal.Invert(parentLocalToWorld); Vec3F localTranslation; parentWorldToLocal.TransformVector(translate, out localTranslation); Vec3F trans = m_originalValues[i] + localTranslation; if (snapToGrid) { if (grid.Snap) { trans = grid.SnapPoint(trans); } else { trans.Y = gridHeight; } } node.Translation = trans; } } }
public override void Render(ViewControl vc) { BasicRendererFlags solid = BasicRendererFlags.Solid | BasicRendererFlags.DisableDepthTest; BasicRendererFlags wire = BasicRendererFlags.WireFrame | BasicRendererFlags.DisableDepthTest; Matrix4F normWorld = GetManipulatorMatrix(); if (normWorld == null) { return; } Camera camera = vc.Camera; int axis = (int)m_hitRegion; // axis colors Color saveColor = m_axisColor[axis]; m_axisColor[axis] = m_highlightColor; Color xcolor = m_axisColor[(int)HitRegion.XAxis]; Color ycolor = m_axisColor[(int)HitRegion.YAxis]; Color zcolor = m_axisColor[(int)HitRegion.ZAxis]; Color nxcolor = m_axisColor[(int)HitRegion.NegXAxis]; Color nycolor = m_axisColor[(int)HitRegion.NegYAxis]; Color nzcolor = m_axisColor[(int)HitRegion.NegZAxis]; m_axisColor[axis] = saveColor; Vec3F deltaTrans = Vec3F.ZeroVector; if (m_hitRegion != HitRegion.None) { normWorld.Translation = HitMatrix.Translation; } Vec3F pos = normWorld.Translation; float s; Util.CalcAxisLengths(vc.Camera, pos, out s); Vec3F sv = new Vec3F(s, s, s); Vec3F axscale = new Vec3F(s, s, s); Vec3F negAxscale = new Vec3F(-s, -s, -s); bool negativeAxis = m_hitRegion == HitRegion.NegXAxis || m_hitRegion == HitRegion.NegYAxis || m_hitRegion == HitRegion.NegZAxis; if (negativeAxis) { negAxscale.X *= Math.Abs(m_scale.X); negAxscale.Y *= Math.Abs(m_scale.Y); negAxscale.Z *= Math.Abs(m_scale.Z); } else { axscale.X *= Math.Abs(m_scale.X); axscale.Y *= Math.Abs(m_scale.Y); axscale.Z *= Math.Abs(m_scale.Z); } Matrix4F scale = new Matrix4F(); scale.Scale(axscale); Matrix4F xform = scale * normWorld; Util3D.RenderFlag = wire; Util3D.DrawX(xform, xcolor); Util3D.DrawY(xform, ycolor); Util3D.DrawZ(xform, zcolor); scale.Scale(negAxscale); xform = scale * normWorld; Util3D.DrawX(xform, nxcolor); Util3D.DrawY(xform, nycolor); Util3D.DrawZ(xform, nzcolor); Vec3F handle = sv * HandleRatio; float handleWidth = handle.X / 2; scale.Scale(handle); Matrix4F trans = new Matrix4F(); Util3D.RenderFlag = solid; // X handle trans.Translation = new Vec3F(axscale.X - handleWidth, 0, 0); xform = scale * trans * normWorld; Util3D.DrawCube(xform, xcolor); // y handle trans.Translation = new Vec3F(0, axscale.Y - handleWidth, 0); xform = scale * trans * normWorld; Util3D.DrawCube(xform, ycolor); // z handle trans.Translation = new Vec3F(0, 0, axscale.Z - handleWidth); xform = scale * trans * normWorld; Util3D.DrawCube(xform, zcolor); // -x handle trans.Translation = new Vec3F(negAxscale.X + handleWidth, 0, 0); xform = scale * trans * normWorld; Util3D.DrawCube(xform, nxcolor); // -y handle trans.Translation = new Vec3F(0, negAxscale.Y + handleWidth, 0); xform = scale * trans * normWorld; Util3D.DrawCube(xform, nycolor); // -z handle trans.Translation = new Vec3F(0, 0, negAxscale.Z + handleWidth); xform = scale * trans * normWorld; Util3D.DrawCube(xform, nzcolor); }
public override void OnBeginDrag() { if (m_hitRegion == HitRegion.None) { return; } var selection = DesignView.Context.As <ISelectionContext>().Selection; var transactionContext = DesignView.Context.As <ITransactionContext>(); NodeList.Clear(); m_isUniformScaling = false; IEnumerable <DomNode> rootDomNodes = DomNode.GetRoots(selection.AsIEnumerable <DomNode>()); foreach (DomNode node in rootDomNodes) { ITransformable transNode = node.As <ITransformable>(); if (transNode == null || (transNode.TransformationType & TransformationTypes.Scale) == 0) { continue; } IVisible vn = node.As <IVisible>(); if (!vn.Visible) { continue; } ILockable lockable = node.As <ILockable>(); if (lockable.IsLocked) { continue; } // force uniform scaling if any node requires it if ((transNode.TransformationType & TransformationTypes.UniformScale) == TransformationTypes.UniformScale) { m_isUniformScaling = true; } NodeList.Add(transNode); IManipulatorNotify notifier = transNode.As <IManipulatorNotify>(); if (notifier != null) { notifier.OnBeginDrag(); } } // to compute offset use bounding box in local space. Vec3F offset = Vec3F.ZeroVector;// 0.5f; // use bounding box in local space switch (m_hitRegion) { case HitRegion.XAxis: case HitRegion.YAxis: case HitRegion.ZAxis: offset = new Vec3F(-1, -1, -1); break; case HitRegion.NegXAxis: case HitRegion.NegYAxis: case HitRegion.NegZAxis: offset = new Vec3F(1, 1, 1); break; default: break; } m_originalScales = new Vec3F[NodeList.Count]; m_originalTranslations = new Vec3F[NodeList.Count]; m_pivotOffset = new Vec3F[NodeList.Count]; int k = 0; foreach (ITransformable node in NodeList) { IBoundable boundable = node.As <IBoundable>(); Vec3F pivot = Vec3F.Mul(boundable.LocalBoundingBox.Radius, offset); m_pivotOffset[k] = pivot; m_originalScales[k] = node.Scale; Matrix4F mtrx = TransformUtils.CalcTransform( Vec3F.ZeroVector, node.Rotation, node.Scale, pivot ); m_originalTranslations[k] = node.Translation - mtrx.Translation; k++; } if (NodeList.Count > 0) { transactionContext.Begin("Extend".Localize()); } }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None || m_activeOp == null || m_activeOp.NodeList.Count == 0) { return; } Matrix4F view = vc.Camera.ViewMatrix; // compute world * view Matrix4F wv = new Matrix4F(); wv.Mul(HitMatrix, view); // create ray in view space. Ray3F rayV = vc.GetRay(scrPt, vc.Camera.ProjectionMatrix); Vec3F xAxis = wv.XAxis; Vec3F yAxis = wv.YAxis; Vec3F zAxis = wv.ZAxis; Vec3F origin = wv.Translation; m_scale = new Vec3F(1, 1, 1); float scale = 1; float a1, a2; switch (m_hitRegion) { case HitRegion.XAxis: case HitRegion.NegXAxis: { a1 = Math.Abs(Vec3F.Dot(HitRayV.Direction, yAxis)); a2 = Math.Abs(Vec3F.Dot(HitRayV.Direction, zAxis)); Vec3F axis = (a1 > a2 ? yAxis : zAxis); Vec3F p0 = HitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), xAxis); if (m_hitRegion == HitRegion.NegXAxis) { dragAmount *= -1; } m_scale.X = 1.0f + dragAmount / m_hitScale; scale = m_scale.X; } break; case HitRegion.YAxis: case HitRegion.NegYAxis: { a1 = Math.Abs(Vec3F.Dot(HitRayV.Direction, zAxis)); a2 = Math.Abs(Vec3F.Dot(HitRayV.Direction, xAxis)); Vec3F axis = (a1 > a2 ? zAxis : xAxis); Vec3F p0 = HitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), yAxis); if (m_hitRegion == HitRegion.NegYAxis) { dragAmount *= -1; } m_scale.Y = 1.0f + dragAmount / m_hitScale; scale = m_scale.Y; } break; case HitRegion.ZAxis: case HitRegion.NegZAxis: { a1 = Math.Abs(Vec3F.Dot(HitRayV.Direction, xAxis)); a2 = Math.Abs(Vec3F.Dot(HitRayV.Direction, yAxis)); Vec3F axis = (a1 > a2 ? xAxis : yAxis); Vec3F p0 = HitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), zAxis); if (m_hitRegion == HitRegion.NegZAxis) { dragAmount *= -1; } m_scale.Z = 1.0f + dragAmount / m_hitScale; scale = m_scale.Z; } break; default: throw new ArgumentOutOfRangeException(); } if (m_isUniformScaling) { m_scale = new Vec3F(scale, scale, scale); } // scale for (int i = 0; i < m_activeOp.NodeList.Count; i++) { ITransformable node = m_activeOp.NodeList[i]; node.Scale = Vec3F.Mul(m_originalScales[i], m_scale); Matrix4F mtrx = TransformUtils.CalcTransform( Vec3F.ZeroVector, node.Rotation, node.Scale, m_pivotOffset[i]); node.Translation = m_originalTranslations[i] + mtrx.Translation; } }
public override void OnBeginDrag(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None) { return; } m_activeOp = null; var op = new ManipulatorActiveOperation( "Extend", DesignView.Context.As <ISelectionContext>(), (ITransformable node) => (node.TransformationType & TransformationTypes.Scale) != 0, false); // to compute offset use bounding box in local space. Vec3F offset = Vec3F.ZeroVector;// 0.5f; // use bounding box in local space switch (m_hitRegion) { case HitRegion.XAxis: case HitRegion.YAxis: case HitRegion.ZAxis: offset = new Vec3F(-1, -1, -1); break; case HitRegion.NegXAxis: case HitRegion.NegYAxis: case HitRegion.NegZAxis: offset = new Vec3F(1, 1, 1); break; default: break; } m_isUniformScaling = false; m_originalScales = new Vec3F[op.NodeList.Count]; m_originalTranslations = new Vec3F[op.NodeList.Count]; m_pivotOffset = new Vec3F[op.NodeList.Count]; int k = 0; foreach (ITransformable node in op.NodeList) { // if any of the selected nodes are marked as "UniformScale", then the // entire operation must be a uniform scale operaion if ((node.TransformationType & TransformationTypes.UniformScale) == TransformationTypes.UniformScale) { m_isUniformScaling = true; } IBoundable boundable = node.As <IBoundable>(); Vec3F pivot = Vec3F.Mul(boundable.LocalBoundingBox.Radius, offset); m_pivotOffset[k] = pivot; m_originalScales[k] = node.Scale; Matrix4F mtrx = TransformUtils.CalcTransform( Vec3F.ZeroVector, node.Rotation, node.Scale, pivot ); m_originalTranslations[k] = node.Translation - mtrx.Translation; k++; } m_activeOp = op; }
public override void Render(object opaqueContext, ViewControl vc) { Matrix4F normWorld = GetManipulatorMatrix(); if (normWorld == null) { return; } var context = opaqueContext as GUILayer.SimpleRenderingContext; if (context == null) { return; } int axis = (int)m_hitRegion; // axis colors Color saveColor = m_axisColor[axis]; m_axisColor[axis] = m_highlightColor; Color xcolor = m_axisColor[(int)HitRegion.XAxis]; Color ycolor = m_axisColor[(int)HitRegion.YAxis]; Color zcolor = m_axisColor[(int)HitRegion.ZAxis]; Color nxcolor = m_axisColor[(int)HitRegion.NegXAxis]; Color nycolor = m_axisColor[(int)HitRegion.NegYAxis]; Color nzcolor = m_axisColor[(int)HitRegion.NegZAxis]; m_axisColor[axis] = saveColor; if (m_hitRegion != HitRegion.None) { normWorld.Translation = HitMatrix.Translation; } Vec3F pos = normWorld.Translation; float s = Util.CalcAxisScale(vc.Camera, pos, AxisLength, vc.Height); Vec3F sv = new Vec3F(s, s, s); Vec3F axscale = new Vec3F(s * AxisThickness, s, s * AxisThickness); bool negativeAxis = m_hitRegion == HitRegion.NegXAxis || m_hitRegion == HitRegion.NegYAxis || m_hitRegion == HitRegion.NegZAxis; Vec3F dragScale = new Vec3F(Math.Abs(m_scale.X), Math.Abs(m_scale.Y), Math.Abs(m_scale.Z)); Matrix4F rot = new Matrix4F(); Matrix4F scale = new Matrix4F(); axscale.Y = negativeAxis ? s : s * dragScale.X; scale.Scale(axscale); rot.RotZ(-MathHelper.PiOver2); Matrix4F xform = scale * rot * normWorld; Util3D.DrawCylinder(context, xform, xcolor); axscale.Y = negativeAxis ? s : s * dragScale.Y; scale.Scale(axscale); xform = scale * normWorld; Util3D.DrawCylinder(context, xform, ycolor); axscale.Y = negativeAxis ? s : s * dragScale.Z; scale.Scale(axscale); rot.RotX(MathHelper.PiOver2); xform = scale * rot * normWorld; Util3D.DrawCylinder(context, xform, zcolor); rot.RotZ(MathHelper.PiOver2); axscale.Y = negativeAxis ? s * dragScale.X : s; scale.Scale(axscale); xform = scale * rot * normWorld; Util3D.DrawCylinder(context, xform, nxcolor); rot.RotZ(MathHelper.Pi); axscale.Y = negativeAxis ? s * dragScale.Y : s; scale.Scale(axscale); xform = scale * rot * normWorld; Util3D.DrawCylinder(context, xform, nycolor); rot.RotX(-MathHelper.PiOver2); axscale.Y = negativeAxis ? s * dragScale.Z : s; scale.Scale(axscale); xform = scale * rot * normWorld; Util3D.DrawCylinder(context, xform, nzcolor); // draw center cube scale.Scale(s * (1.0f / 16.0f)); xform = scale * normWorld; Util3D.DrawCube(context, xform, Color.White); Vec3F handle = sv * AxisHandle; float handleWidth = handle.X / 2; scale.Scale(handle); Matrix4F trans = new Matrix4F(); // X handle float drag = m_hitRegion == HitRegion.XAxis ? dragScale.X : 1.0f; trans.Translation = new Vec3F(drag * sv.X - handleWidth, 0, 0); xform = scale * trans * normWorld; Util3D.DrawCube(context, xform, xcolor); // y handle drag = m_hitRegion == HitRegion.YAxis ? dragScale.Y : 1.0f; trans.Translation = new Vec3F(0, drag * sv.Y - handleWidth, 0); xform = scale * trans * normWorld; Util3D.DrawCube(context, xform, ycolor); // z handle drag = m_hitRegion == HitRegion.ZAxis ? dragScale.Z : 1.0f; trans.Translation = new Vec3F(0, 0, drag * sv.Z - handleWidth); xform = scale * trans * normWorld; Util3D.DrawCube(context, xform, zcolor); // -x handle drag = m_hitRegion == HitRegion.NegXAxis ? dragScale.X : 1.0f; trans.Translation = new Vec3F(-sv.X * drag + handleWidth, 0, 0); xform = scale * trans * normWorld; Util3D.DrawCube(context, xform, nxcolor); // -y handle drag = m_hitRegion == HitRegion.NegYAxis ? dragScale.Y : 1.0f; trans.Translation = new Vec3F(0, -sv.Y * drag + handleWidth, 0); xform = scale * trans * normWorld; Util3D.DrawCube(context, xform, nycolor); // -z handle drag = m_hitRegion == HitRegion.NegZAxis ? dragScale.Z : 1.0f; trans.Translation = new Vec3F(0, 0, -sv.Z * drag + handleWidth); xform = scale * trans * normWorld; Util3D.DrawCube(context, xform, nzcolor); }
/// <summary> /// Constructor</summary> /// <param name="angleLimits">Maximum angle values in radians</param> /// <param name="channels">Axes (x, y, and/or z) of 'angleLimits' that are valid</param> public EulerAngleLimits(Vec3F angleLimits, EulerAngleChannels channels) { m_angleLimits = angleLimits; m_channels = channels; }
/// <summary> /// Constructor</summary> /// <param name="angles">Array of 3 floats containing the maximum angle values in radians</param> /// <param name="channels">Axes (x, y, and/or z) of 'angles' that are valid</param> public EulerAngleLimits(float[] angles, EulerAngleChannels channels) { m_angleLimits = new Vec3F(angles); m_channels = channels; }
public override ManipulatorPickResult Pick(ViewControl vc, Point scrPt) { m_hitRegion = HitRegion.None; if (base.Pick(vc, scrPt) == ManipulatorPickResult.Miss) { return(ManipulatorPickResult.Miss); } Camera camera = vc.Camera; float s = Util.CalcAxisScale(vc.Camera, HitMatrix.Translation, AxisLength, vc.Height); Matrix4F vp = camera.ViewMatrix * camera.ProjectionMatrix; Matrix4F wvp = HitMatrix * vp; // get ray in object space space. Ray3F rayL = vc.GetRay(scrPt, wvp); m_scale = new Vec3F(1, 1, 1); m_hitScale = s; Vec3F min = new Vec3F(-0.5f, -0.5f, -0.5f); Vec3F max = new Vec3F(0.5f, 0.5f, 0.5f); AABB box = new AABB(min, max); Matrix4F boxScale = new Matrix4F(); Matrix4F boxTrans = new Matrix4F(); Matrix4F BoxMtrx = new Matrix4F(); float handleScale = s * AxisHandle; // +X axis boxScale.Scale(new Vec3F(s, handleScale, handleScale)); boxTrans.Translation = new Vec3F(s / 2, 0, 0); BoxMtrx = boxScale * boxTrans; Ray3F ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.XAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // -X boxTrans.Translation = new Vec3F(-s / 2, 0, 0); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.NegXAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // y axis boxScale.Scale(new Vec3F(handleScale, s, handleScale)); boxTrans.Translation = new Vec3F(0, s / 2, 0); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.YAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // -Y boxTrans.Translation = new Vec3F(0, -s / 2, 0); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.NegYAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // z axis boxScale.Scale(new Vec3F(handleScale, handleScale, s)); boxTrans.Translation = new Vec3F(0, 0, s / 2); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.ZAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // -Z boxTrans.Translation = new Vec3F(0, 0, -s / 2); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.NegZAxis; return(ManipulatorPickResult.DeferredBeginDrag); } return(ManipulatorPickResult.Miss); }
public Entity Spawn(int editorID, Vec3F position, BitAngle angle = default) { ActorDefinition definition = DecorateManager.Find(editorID); return(Spawn(definition, position, angle)); }