protected override Matrix4F GetManipulatorMatrix() { ITransformable node = GetManipulatorNode(TransformationTypes.Scale); if (node == null) { return(null); } Path <DomNode> path = new Path <DomNode>(node.Cast <DomNode>().GetPath()); Matrix4F localToWorld = TransformUtils.CalcPathTransform(path, path.Count - 1); // local transform Matrix4F toworld = new Matrix4F(localToWorld); // Offset by pivot Matrix4F P = new Matrix4F(); P.Translation = node.Pivot; toworld.Mul(P, toworld); // Normalize toworld.Normalize(toworld); return(toworld); }
protected override Matrix4F GetManipulatorMatrix() { ITransformable node = GetManipulatorNode(TransformationTypes.Translation); if (node == null) { return(null); } ISnapSettings snapSettings = (ISnapSettings)DesignView; Path <DomNode> path = new Path <DomNode>(node.Cast <DomNode>().GetPath()); Matrix4F localToWorld = TransformUtils.CalcPathTransform(path, path.Count - 1); Matrix4F toworld = new Matrix4F(); if (snapSettings.ManipulateLocalAxis) { toworld.Set(localToWorld); toworld.Normalize(toworld); } else { toworld.Translation = localToWorld.Translation; } Vec3F offset = TransformUtils.CalcSnapFromOffset(node, snapSettings.SnapFrom); // Offset by pivot Matrix4F P = new Matrix4F(); P.Translation = offset; toworld.Mul(toworld, P); return(toworld); }
/// <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> /// Computes world transformation matrix for the given /// Transformable node.</summary> public static Matrix4F ComputeWorldTransform(ITransformable xform) { Matrix4F world = new Matrix4F(); DomNode node = xform.As<DomNode>(); foreach (DomNode n in node.Lineage) { ITransformable xformNode = n.As<ITransformable>(); if (xformNode != null) { world.Mul(world, xformNode.Transform); } } return world; }
/// <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); }
/// <summary> /// Computes world transformation matrix for the given /// Transformable node.</summary> public static Matrix4F ComputeWorldTransform(ITransformable xform) { Matrix4F world = new Matrix4F(); DomNode node = xform.As <DomNode>(); foreach (DomNode n in node.Lineage) { ITransformable xformNode = n.As <ITransformable>(); if (xformNode != null) { world.Mul(world, xformNode.Transform); } } return(world); }
/// <summary> /// Calculates the world space matrix of the given path</summary> /// <param name="path">The path</param> /// <param name="start">Starting index</param> /// <param name="M">the world matrix</param> public static void CalcPathTransform(Matrix4F M, Path <DomNode> path, int start) { for (int i = start; i >= 0; i--) { if (path[i] != null) { ITransformable renderable = path[i].As <ITransformable>(); if (renderable != null) { M.Mul(M, renderable.Transform); } } } }
/// <summary> /// Calculates the world space matrix of the given path</summary> /// <param name="path">The path</param> /// <param name="start">Starting index</param> /// <param name="M">the world matrix</param> public static void CalcPathTransform(Matrix4F M, Path<DomNode> path, int start) { for (int i = start; i >= 0; i--) { if (path[i] != null) { ITransformable renderable = path[i].As<ITransformable>(); if (renderable != null) { M.Mul(M, renderable.Transform); } } } }
/// <summary> /// Adjusts child transform, making it the concatenation with its parent's transform. /// Is recursive, looking for parents that also implement IRenderableNode.</summary> /// <param name="parent">Parent node</param> /// <param name="child">Child node</param> public static void RemoveChild(ITransformable parent, ITransformable child) { Path <DomNode> path = new Path <DomNode>(parent.Cast <DomNode>().GetPath()); Matrix4F parentMatrix = TransformUtils.CalcPathTransform(path, path.Count - 1); Matrix4F childMatrix = child.Transform; Matrix4F newChildMatrix = Matrix4F.Multiply(childMatrix, parentMatrix); Vec3F newTranslation = child.Translation; parentMatrix.Transform(ref newTranslation); Vec3F newRotation = new Vec3F(); newChildMatrix.GetEulerAngles(out newRotation.X, out newRotation.Y, out newRotation.Z); child.Rotation = newRotation; Vec3F newScale = newChildMatrix.GetScale(); child.Scale = newScale; // We can compose together all of the separate transformations now. Matrix4F newTransform = CalcTransform( newTranslation, newRotation, newScale, child.ScalePivot, child.ScalePivotTranslation, child.RotatePivot, child.RotatePivotTranslation); // However, the composed matrix may not equal newChildMatrix due to rotating // or scaling around a pivot. In the general case, it may be impossible to // decompose newChildMatrix into all of these separate components. For example, // a sheer transformation cannot be reproduced by a single rotation and scale. // But for common cases, only the translation is out-of-sync now, so apply a fix. Vec3F desiredTranslation = newChildMatrix.Translation; Vec3F currentTranslation = newTransform.Translation; Vec3F fixupTranslation = desiredTranslation - currentTranslation; Matrix4F fixupTransform = new Matrix4F(fixupTranslation); newTransform.Mul(newTransform, fixupTransform); // Save the fix and the final transform. child.Translation = newTranslation + fixupTranslation; child.Transform = newTransform; }
/// <summary> /// Calculates the width and height of the view frustum at the given 3D location</summary> /// <param name="camera">The camera</param> /// <param name="globalTransform">The world space matrix specifying a position</param> /// <param name="h">The height of the view frustum at the given position</param> /// <param name="w">The width of the view frustum at the given position</param> public static void CalcWorldDimensions(Camera camera, Matrix4F globalTransform, out float h, out float w) { Matrix4F W = new Matrix4F(); W.Mul(globalTransform, camera.ViewMatrix); // World height on origin's z value if (camera.Frustum.IsOrtho) { w = camera.Frustum.Right - camera.Frustum.Left; h = camera.Frustum.Top - camera.Frustum.Bottom; } else { float minusZ = -W.Translation.Z; h = minusZ * (float)Math.Tan(camera.Frustum.FovY / 2.0f) * 2.0f; w = minusZ * (float)Math.Tan(camera.Frustum.FovX / 2.0f) * 2.0f; } }
/// <summary> /// Gets the view matrix corresponding to a "look at" point</summary> /// <param name="azimuth">Camera pan, in radians</param> /// <param name="elevation">Camera tilt, in radians</param> /// <param name="lookAt">"Look at" direction</param> /// <param name="dolly">Distance from "look at" point</param> /// <returns>View matrix corresponding to the "look at" point</returns> public static Matrix4F LookAtMatrix(float azimuth, float elevation, Vec3F lookAt, float dolly) { Matrix4F R = LookAtRotationMatrix(azimuth, elevation, lookAt); R.ZTranslation = -dolly; Matrix4F T = new Matrix4F ( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -lookAt.X, -lookAt.Y, -lookAt.Z, 1 ); Matrix4F result = new Matrix4F(); result.Mul(T, R); return(result); }
/// <summary> /// Calculates the world space matrix of the given SceneNode path, starting from a given index</summary> /// <param name="path">The SceneNode path</param> /// <param name="start">Starting index within the path</param> /// <returns>The world space matrix</returns> public static Matrix4F CalcPathTransform(SceneNode[] path, int start) { Matrix4F M = new Matrix4F(); for (int i = start; i < path.Length; i++) { if (path[i].Source != null) { ITransformable renderable = path[i].Source.As <ITransformable>(); if (renderable != null) { M.Mul(M, renderable.Transform); } } } return(M); }
/// <summary> /// Calculates the world space matrix of the given SceneNode path, starting from a given index</summary> /// <param name="path">The SceneNode path</param> /// <param name="start">Starting index within the path</param> /// <returns>The world space matrix</returns> public static Matrix4F CalcPathTransform(SceneNode[] path, int start) { Matrix4F M = new Matrix4F(); for (int i = start; i < path.Length; i++) { if (path[i].Source != null) { ITransformable renderable = path[i].Source.As<ITransformable>(); if (renderable != null) { M.Mul(M, renderable.Transform); } } } return M; }
/// <summary> /// Calculates the world space matrix of the given path /// </summary> /// <param name="path">The path</param> /// <param name="start">Starting index</param> /// <returns>The world space matrix</returns> public static Matrix4F CalcPathTransform(Path <DomNode> path, int start) { Matrix4F M = new Matrix4F(); for (int i = start; i >= 0; i--) { if (path[i] != null) { ITransformable renderable = path[i].As <ITransformable>(); if (renderable != null) { M.Mul(M, renderable.Transform); } } } return(M); }
protected override Matrix4F GetManipulatorMatrix() { ITransformable node = GetManipulatorNode(TransformationTypes.Pivot); if (node == null) { return(null); } Path <DomNode> path = new Path <DomNode>(node.Cast <DomNode>().GetPath()); Matrix4F localToWorld = TransformUtils.CalcPathTransform(path, path.Count - 1); // Offset by pivot Matrix4F Pv = new Matrix4F(); Pv.Set(node.Pivot); localToWorld.Mul(Pv, localToWorld); localToWorld.OrthoNormalize(localToWorld); return(new Matrix4F(localToWorld.Translation)); }
/// <summary> /// Calculates the world space matrix of the given path /// </summary> /// <param name="path">The path</param> /// <param name="start">Starting index</param> /// <returns>The world space matrix</returns> public static Matrix4F CalcPathTransform(Path<DomNode> path, int start) { Matrix4F M = new Matrix4F(); for (int i = start; i >= 0; i--) { if (path[i] != null) { ITransformable renderable = path[i].As<ITransformable>(); if (renderable != null) { M.Mul(M, renderable.Transform); } } } return M; }
/// <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 void CalcAxisLengths(Camera camera, Matrix4F globalTransform, out float s1, out float s2, out float s3) { float worldHeight; // Calc view space matrix Matrix4F V = new Matrix4F(); V.Mul(globalTransform, camera.ViewMatrix); // World height on origin's z value if (camera.Frustum.IsOrtho) { worldHeight = (camera.Frustum.Top - camera.Frustum.Bottom) / 2; } else { worldHeight = -V.ZTranslation * (float)Math.Tan(camera.Frustum.FovY / 2.0f); } s1 = (m_axisRatio * worldHeight) / V.XAxis.Length; s2 = (m_axisRatio * worldHeight) / V.YAxis.Length; s3 = (m_axisRatio * worldHeight) / V.ZAxis.Length; }
/// <summary> /// Pushes a matrix onto the matrix stack</summary> /// <param name="matrix">The matrix</param> /// <param name="multiply">If true, multiply matrix by top matrix</param> public void PushMatrix(Matrix4F matrix, bool multiply) { if (m_matrixStackFreeze) { throw new InvalidOperationException( "the IRenderObject does not implement ISetsLocalTransform"); } int count = m_matrixStack.Count; Matrix4F topMatrix = (count > 0) ? m_matrixStack[count - 1] : Matrix4F.Identity; Matrix4F newMatrix = new Matrix4F(); if (multiply) { newMatrix.Mul(matrix, topMatrix); } else { newMatrix.Set(matrix); } m_matrixStack.Add(newMatrix); }
/// <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; }
/// <summary> /// Adjusts child transform, making it relative to new parent node's transform. /// Is recursive, looking for parents that also implement IRenderableNode.</summary> /// <param name="parent">Parent node</param> /// <param name="child">Child node</param> public static void AddChild(ITransformable parent, ITransformable child) { Path <DomNode> path = new Path <DomNode>(parent.Cast <DomNode>().GetPath()); Matrix4F parentToWorld = TransformUtils.CalcPathTransform(path, path.Count - 1); // We want 'child' to appear in the same place in the world after adding to 'parent'. // local-point * original-local-to-world = world-point // new-local-point * new-local-to-parent * parent-to-world = world-point // ==> new-local-to-parent * parent-to-world = original-local-to-world // (multiply both sides by inverse of parent-to-world; call it world-to-parent) // ==> new-local-to-parent = original-local-to-world * world-to-parent Matrix4F worldToParent = new Matrix4F(); worldToParent.Invert(parentToWorld); Matrix4F originalLocalToWorld = child.Transform; Matrix4F newLocalToParent = Matrix4F.Multiply(originalLocalToWorld, worldToParent); // The translation component of newLocalToParent consists of pivot translation // as well as the child.Translation. So, start with the original child.Translation // and transform it into our new space. Vec3F newTranslation = child.Translation; worldToParent.Transform(ref newTranslation); // There's only one way of getting rotation info, so get it straight from matrix. Vec3F newRotation = new Vec3F(); newLocalToParent.GetEulerAngles(out newRotation.X, out newRotation.Y, out newRotation.Z); child.Rotation = newRotation; // Likewise with scale. Vec3F newScale = newLocalToParent.GetScale(); child.Scale = newScale; // We can compose together all of the separate transformations now. Matrix4F newTransform = CalcTransform( newTranslation, newRotation, newScale, child.ScalePivot, child.ScalePivotTranslation, child.RotatePivot, child.RotatePivotTranslation); // However, the composed matrix may not equal newLocalToParent due to rotating // or scaling around a pivot. In the general case, it may be impossible to // decompose newLocalToParent into all of these separate components. For example, // a sheer transformation cannot be reproduced by a single rotation and scale. // But for common cases, only the translation is out-of-sync now, so apply a fix. Vec3F desiredTranslation = newLocalToParent.Translation; Vec3F currentTranslation = newTransform.Translation; Vec3F fixupTranslation = desiredTranslation - currentTranslation; Matrix4F fixupTransform = new Matrix4F(fixupTranslation); newTransform.Mul(newTransform, fixupTransform); // Save the fix and the final transform. Storing the fix in RotatePivotTranslation // is done elsewhere, as well. child.Translation = newTranslation + fixupTranslation; child.Transform = newTransform; }
private void RenderProperties(IEnumerable <object> objects, bool renderCaption, bool renderBound, bool renderPivot) { bool renderAny = renderCaption || renderBound || renderPivot; if (renderAny == false) { return; } Util3D.RenderFlag = 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(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.RenderFlag = 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; float s; Util.CalcAxisLengths(Camera, pos, out s); s /= 12.0f; sc.Scale(s); Util.CreateBillboard(bl, pos, Camera.WorldEye, Camera.Up, Camera.LookAt); Matrix4F.Multiply(sc, bl, recXform); Util3D.DrawPivot(recXform, Color.Yellow); } } }
/// <summary> /// Performs actions during control drag</summary> /// <param name="hit">Hit record</param> /// <param name="x">Mouse x position</param> /// <param name="y">Mouse y position</param> /// <param name="action">Render action</param> /// <param name="camera">Camera</param> /// <param name="transform">Transform</param> /// <returns>Translation, in world coordinates</returns> public Vec3F OnDrag(HitRecord hit, float x, float y, IRenderAction action, Camera camera, Matrix4F transform) { float a1, a2; Matrix4F W = new Matrix4F(); W.Mul(transform, camera.ViewMatrix); // Setup rays, in view space. (-z goes into the screen.) Ray3F ray0 = camera.CreateRay(m_iX, m_iY); Ray3F ray = camera.CreateRay(x, y); // Build axis and origin in view space Vec3F xAxis = W.XAxis; Vec3F yAxis = W.YAxis; Vec3F zAxis = W.ZAxis; Vec3F origin = W.Translation; Vec3F trans = new Vec3F(); // Choose the best projection plane according to the projection angle switch ((HitElement)hit.RenderObjectData[1]) { case HitElement.X_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, yAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, zAxis)); Vec3F axis = (a1 > a2 ? yAxis : zAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(xAxis, p1 - p0); Vec3F xLocal = transform.XAxis; trans = dragAmount * xLocal; } break; case HitElement.Y_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, zAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, xAxis)); Vec3F axis = (a1 > a2 ? zAxis : xAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(yAxis, p1 - p0); Vec3F yLocal = transform.YAxis; trans = dragAmount * yLocal; } break; case HitElement.Z_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, xAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, yAxis)); Vec3F axis = (a1 > a2 ? xAxis : yAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(zAxis, p1 - p0); Vec3F zLocal = transform.ZAxis; trans = dragAmount * zLocal; } break; case HitElement.XY_SQUARE: { Vec3F p0 = ray0.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin)); Vec3F p1 = ray.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragX = Vec3F.Dot(xAxis, deltaLocal); float dragY = Vec3F.Dot(yAxis, deltaLocal); Vec3F xLocal = transform.XAxis; Vec3F yLocal = transform.YAxis; trans = dragX * xLocal + dragY * yLocal; } break; case HitElement.YZ_SQUARE: { Vec3F p0 = ray0.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin)); Vec3F p1 = ray.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragY = Vec3F.Dot(yAxis, deltaLocal); float dragZ = Vec3F.Dot(zAxis, deltaLocal); Vec3F yLocal = transform.YAxis; Vec3F zLocal = transform.ZAxis; trans = dragY * yLocal + dragZ * zLocal; } break; case HitElement.XZ_SQUARE: { Vec3F p0 = ray0.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin)); Vec3F p1 = ray.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragX = Vec3F.Dot(xAxis, deltaLocal); float dragZ = Vec3F.Dot(zAxis, deltaLocal); Vec3F xLocal = transform.XAxis; Vec3F zLocal = transform.ZAxis; trans = dragX * xLocal + dragZ * zLocal; } break; } return(trans); }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None || m_activeOp == null || m_activeOp.NodeList.Count == 0) return; Camera cam = vc.Camera; Matrix4F view = cam.ViewMatrix; Matrix4F proj = cam.ProjectionMatrix; Matrix4F axisMtrx = HitMatrix * view; Ray3F hitRay = HitRayV; Ray3F dragRay = vc.GetRay(scrPt, proj); Vec3F xAxis = axisMtrx.XAxis; Vec3F yAxis = axisMtrx.YAxis; Vec3F zAxis = axisMtrx.ZAxis; Vec3F origin = axisMtrx.Translation; Vec3F rotAxis = new Vec3F(); float theta = 0; float snapAngle = ((ISnapSettings)DesignView).SnapAngle; switch (m_hitRegion) { case HitRegion.XAxis: { Plane3F xplane = new Plane3F(xAxis, origin); theta = CalcAngle(origin, xplane, hitRay, dragRay, snapAngle); rotAxis = HitMatrix.XAxis; } break; case HitRegion.YAxis: { Plane3F yplane = new Plane3F(yAxis, origin); theta = CalcAngle(origin, yplane, hitRay, dragRay, snapAngle); rotAxis = HitMatrix.YAxis; } break; case HitRegion.ZAxis: { Plane3F zplane = new Plane3F(zAxis, origin); theta = CalcAngle(origin, zplane, hitRay, dragRay, snapAngle); rotAxis = HitMatrix.ZAxis; } break; case HitRegion.LookAxis: { // for billboard objects the look vector is object's negative position in viewspace. Vec3F lookAxis = Vec3F.Normalize(-origin); Plane3F plane = new Plane3F(lookAxis, origin); theta = CalcAngle(origin, plane, hitRay, dragRay, snapAngle); rotAxis = m_lookAxisHitMtrx.ZAxis; } break; default: throw new ArgumentOutOfRangeException(); } AngleAxisF axf = new AngleAxisF(-theta, rotAxis); Matrix4F deltaMtrx = new Matrix4F(axf); Matrix4F rotMtrx = new Matrix4F(); for (int i = 0; i < m_activeOp.NodeList.Count; i++) { ITransformable node = m_activeOp.NodeList[i]; rotMtrx.Mul(m_rotations[i], deltaMtrx); float ax, ay, az; rotMtrx.GetEulerAngles(out ax, out ay, out az); node.Rotation = new Vec3F(ax, ay, az); } }
private void RenderProperties(IEnumerable<object> objects, bool renderCaption, bool renderBound, bool renderPivot) { if (renderCaption || renderBound) { Util3D.RenderFlag = 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(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.RenderFlag = 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(recXform, Color.Yellow); } } }
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; } }
protected override Matrix4F GetManipulatorMatrix() { ITransformable node = GetManipulatorNode(TransformationTypes.Translation); if (node == null ) return null; ISnapSettings snapSettings = (ISnapSettings)DesignView; Path<DomNode> path = new Path<DomNode>(node.Cast<DomNode>().GetPath()); Matrix4F localToWorld = TransformUtils.CalcPathTransform(path, path.Count - 1); Matrix4F toworld = new Matrix4F(); if (snapSettings.ManipulateLocalAxis) { toworld.Set(localToWorld); toworld.Normalize(toworld); } else { toworld.Translation = localToWorld.Translation; } Vec3F offset = TransformUtils.CalcSnapFromOffset(node, snapSettings.SnapFrom); // Offset by pivot Matrix4F P = new Matrix4F(); P.Translation = offset; toworld.Mul(toworld,P); return toworld; }
/// <summary> /// Performs actions during control drag</summary> /// <param name="hit">Hit record</param> /// <param name="x">Mouse x position</param> /// <param name="y">Mouse y position</param> /// <param name="action">Render action</param> /// <param name="camera">Camera</param> /// <param name="transform">Transform</param> /// <returns>Translation, in world coordinates</returns> public Vec3F OnDrag(HitRecord hit, float x, float y, IRenderAction action, Camera camera, Matrix4F transform) { float a1, a2; Matrix4F W = new Matrix4F(); W.Mul(transform, camera.ViewMatrix); // Setup rays, in view space. (-z goes into the screen.) Ray3F ray0 = camera.CreateRay(m_iX, m_iY); Ray3F ray = camera.CreateRay(x, y); // Build axis and origin in view space Vec3F xAxis = W.XAxis; Vec3F yAxis = W.YAxis; Vec3F zAxis = W.ZAxis; Vec3F origin = W.Translation; Vec3F trans = new Vec3F(); // Choose the best projection plane according to the projection angle switch ((HitElement)hit.RenderObjectData[1]) { case HitElement.X_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, yAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, zAxis)); Vec3F axis = (a1 > a2 ? yAxis : zAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(xAxis, p1 - p0); Vec3F xLocal = transform.XAxis; trans = dragAmount * xLocal; } break; case HitElement.Y_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, zAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, xAxis)); Vec3F axis = (a1 > a2 ? zAxis : xAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(yAxis, p1 - p0); Vec3F yLocal = transform.YAxis; trans = dragAmount * yLocal; } break; case HitElement.Z_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, xAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, yAxis)); Vec3F axis = (a1 > a2 ? xAxis : yAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(zAxis, p1 - p0); Vec3F zLocal = transform.ZAxis; trans = dragAmount * zLocal; } break; case HitElement.XY_SQUARE: { Vec3F p0 = ray0.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin)); Vec3F p1 = ray.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragX = Vec3F.Dot(xAxis, deltaLocal); float dragY = Vec3F.Dot(yAxis, deltaLocal); Vec3F xLocal = transform.XAxis; Vec3F yLocal = transform.YAxis; trans = dragX * xLocal + dragY * yLocal; } break; case HitElement.YZ_SQUARE: { Vec3F p0 = ray0.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin)); Vec3F p1 = ray.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragY = Vec3F.Dot(yAxis, deltaLocal); float dragZ = Vec3F.Dot(zAxis, deltaLocal); Vec3F yLocal = transform.YAxis; Vec3F zLocal = transform.ZAxis; trans = dragY * yLocal + dragZ * zLocal; } break; case HitElement.XZ_SQUARE: { Vec3F p0 = ray0.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin)); Vec3F p1 = ray.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragX = Vec3F.Dot(xAxis, deltaLocal); float dragZ = Vec3F.Dot(zAxis, deltaLocal); Vec3F xLocal = transform.XAxis; Vec3F zLocal = transform.ZAxis; trans = dragX * xLocal + dragZ * zLocal; } break; } return trans; }
public void Render(Camera cam) { GameEngine.SetRendererFlag(BasicRendererFlags.WireFrame); IGrid grid = this.As<IGrid>(); if (grid.Visible == false) return; float s = grid.Size; Matrix4F scale = new Matrix4F(); scale.Scale(new Vec3F(s, s, s)); Matrix4F gridXform = new Matrix4F(); if (cam.Frustum.IsOrtho) { float dist = cam.ViewMatrix.Translation.Z; ViewTypes vt = cam.ViewType; if (vt == ViewTypes.Top) { gridXform.Translation = new Vec3F(0, dist, 0); } else if (vt == ViewTypes.Bottom) { gridXform.Translation = new Vec3F(0, -dist, 0); } else if (vt == ViewTypes.Right) { gridXform.RotZ(MathHelper.PiOver2); gridXform.Translation = new Vec3F(dist, 0, 0); } else if (vt == ViewTypes.Left) { gridXform.RotZ(MathHelper.PiOver2); gridXform.Translation = new Vec3F(-dist, 0, 0); } else if (vt == ViewTypes.Front) { gridXform.RotX(MathHelper.PiOver2); gridXform.Translation = new Vec3F(0, 0, dist); } else if (vt == ViewTypes.Back) { gridXform.RotX(MathHelper.PiOver2); gridXform.Translation = new Vec3F(0, 0, -dist); } gridXform.Mul(scale, gridXform); } else { Matrix4F trans = new Matrix4F(); trans.Translation = new Vec3F(0, grid.Height, 0); gridXform = Matrix4F.Multiply(scale, trans); } GameEngine.DrawPrimitive(PrimitiveType.LineList, m_gridVBId, 0, m_gridVertexCount, Color.LightGray, Matrix4F.Multiply(gridXform, cam.AxisSystem)); GameEngine.DrawPrimitive(PrimitiveType.LineList, m_basisAxesVBId, 0, m_basisAxesVertexCount, Color.White, gridXform); }
/// <summary> /// Pushes a matrix onto the matrix stack</summary> /// <param name="matrix">The matrix</param> /// <param name="multiply">If true, multiply matrix by top matrix</param> public void PushMatrix(Matrix4F matrix, bool multiply) { if (m_matrixStackFreeze) throw new InvalidOperationException( "the IRenderObject does not implement ISetsLocalTransform"); int count = m_matrixStack.Count; Matrix4F topMatrix = (count > 0) ? m_matrixStack[count - 1] : Matrix4F.Identity; Matrix4F newMatrix = new Matrix4F(); if (multiply) newMatrix.Mul(matrix, topMatrix); else newMatrix.Set(matrix); m_matrixStack.Add(newMatrix); }
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; //Vec3F pos; m_scale = new Vec3F(1, 1, 1); float scale = 1; float a1, a2; switch (m_hitRegion) { case HitRegion.XAxis: { 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); m_scale.X = 1.0f + dragAmount / m_hitScale; scale = m_scale.X; } break; case HitRegion.YAxis: { 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); m_scale.Y = 1.0f + dragAmount / m_hitScale; scale = m_scale.Y; } break; case HitRegion.ZAxis: { 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); m_scale.Z = 1.0f + dragAmount / m_hitScale; scale = m_scale.Z; } break; case HitRegion.CenterCube: { Vec3F axis = new Vec3F(0, 0, 1); Vec3F p0 = HitRayV.IntersectPlane(axis, -origin.Z); Vec3F p1 = rayV.IntersectPlane(axis, -origin.Z); Vec3F dragVec = p1 - p0; float dragAmount = 1.0f + dragVec.X / m_hitScale; m_scale.X = dragAmount ; m_scale.Y = dragAmount ; m_scale.Z = dragAmount ; scale = m_scale.X; } 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 transformable = m_activeOp.NodeList[i]; transformable.Scale = Vec3F.Mul(m_originalValues[i], m_scale); } }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None || NodeList.Count == 0) return; Camera cam = vc.Camera; Matrix4F view = cam.ViewMatrix; Matrix4F mtrx = cam.ProjectionMatrix; Matrix4F axisMtrx = HitMatrix * view; Ray3F hitRay = HitRayV; Ray3F dragRay = vc.GetRay(scrPt, mtrx); Vec3F xAxis = axisMtrx.XAxis; Vec3F yAxis = axisMtrx.YAxis; Vec3F zAxis = axisMtrx.ZAxis; Vec3F origin = axisMtrx.Translation; Vec3F rotAxis = new Vec3F(); float theta = 0; switch (m_hitRegion) { case HitRegion.XAxis: { Plane3F xplane = new Plane3F(xAxis, origin); theta = CalcAngle(origin, xplane, hitRay, dragRay); rotAxis = HitMatrix.XAxis; } break; case HitRegion.YAxis: { Plane3F yplane = new Plane3F(yAxis, origin); theta = CalcAngle(origin, yplane, hitRay, dragRay); rotAxis = HitMatrix.YAxis; } break; case HitRegion.ZAxis: { Plane3F zplane = new Plane3F(zAxis, origin); theta = CalcAngle(origin, zplane, hitRay, dragRay); rotAxis = HitMatrix.ZAxis; } break; default: throw new ArgumentOutOfRangeException(); } AngleAxisF axf = new AngleAxisF(-theta, rotAxis); Matrix4F deltaMtrx = new Matrix4F(axf); Matrix4F rotMtrx = new Matrix4F(); for (int i = 0; i < NodeList.Count; i++) { ITransformable node = NodeList[i]; rotMtrx.Set(m_rotations[i]); rotMtrx.Mul(rotMtrx, deltaMtrx); float ax, ay, az; rotMtrx.GetEulerAngles(out ax, out ay, out az); node.Rotation = new Vec3F(ax,ay,az); } }
/// <summary> /// Performs initialization when the adapter's node is set. /// This method is called each time the adapter is connected to its underlying node. /// Typically overridden by creators of DOM adapters.</summary> protected override void OnNodeSet() { base.OnNodeSet(); // get trans, scale, and rot. foreach (DomNode domNode in this.DomNode.GetChildList(Schema.node.scaleChild)) { m_scale = Tools.GetVector3(domNode, Schema.TargetableFloat3.Attribute); break; } foreach (DomNode domNode in this.DomNode.GetChildList(Schema.node.translateChild)) { m_translation = Tools.GetVector3(domNode, Schema.TargetableFloat3.Attribute); break; } const float PiOver180 = (float)(Math.PI / 180.0f); foreach (DomNode node in DomNode.GetChildList(Schema.node.rotateChild)) { double[] arr = (double[])node.GetAttribute(Schema.rotate.Attribute); float angle = (float)arr[3] * PiOver180; string sid = node.GetAttribute(Schema.rotate.sidAttribute) as string; if (string.IsNullOrEmpty(sid)) { continue; } if (sid == "rotateX") { m_rotation.X = angle; } else if (sid == "rotateY") { m_rotation.Y = angle; } else if (sid == "rotateZ") { m_rotation.Z = angle; } } Matrix4F M = new Matrix4F(); Matrix4F temp = new Matrix4F(); temp.Scale(Scale); M.Mul(M, temp); if (m_rotation.X != 0) { temp.RotX(m_rotation.X); M.Mul(M, temp); } if (m_rotation.Y != 0) { temp.RotY(m_rotation.Y); M.Mul(M, temp); } if (m_rotation.Z != 0) { temp.RotZ(m_rotation.Z); M.Mul(M, temp); } temp.Set(Translation); M.Mul(M, temp); Transform = M; m_boundingBox = new Cached <Box>(CalculateBoundingBox); Visible = true; }
public void Render(Camera cam) { GameEngine.SetRendererFlag(BasicRendererFlags.WireFrame); IGrid grid = this.As <IGrid>(); if (grid.Visible == false) { return; } float s = grid.Size; Matrix4F scale = new Matrix4F(); scale.Scale(new Vec3F(s, s, s)); Matrix4F gridXform = new Matrix4F(); if (cam.Frustum.IsOrtho) { float dist = cam.ViewMatrix.Translation.Z; ViewTypes vt = cam.ViewType; if (vt == ViewTypes.Top) { gridXform.Translation = new Vec3F(0, dist, 0); } else if (vt == ViewTypes.Bottom) { gridXform.Translation = new Vec3F(0, -dist, 0); } else if (vt == ViewTypes.Right) { gridXform.RotZ(MathHelper.PiOver2); gridXform.Translation = new Vec3F(dist, 0, 0); } else if (vt == ViewTypes.Left) { gridXform.RotZ(MathHelper.PiOver2); gridXform.Translation = new Vec3F(-dist, 0, 0); } else if (vt == ViewTypes.Front) { gridXform.RotX(MathHelper.PiOver2); gridXform.Translation = new Vec3F(0, 0, dist); } else if (vt == ViewTypes.Back) { gridXform.RotX(MathHelper.PiOver2); gridXform.Translation = new Vec3F(0, 0, -dist); } gridXform.Mul(scale, gridXform); } else { Matrix4F trans = new Matrix4F(); trans.Translation = new Vec3F(0, grid.Height, 0); gridXform = Matrix4F.Multiply(scale, trans); } GameEngine.DrawPrimitive(PrimitiveType.LineList, m_gridVBId, 0, m_gridVertexCount, Color.LightGray, gridXform); }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None || 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; //Vec3F pos; m_scale = new Vec3F(1, 1, 1); float scale = 1; float a1, a2; switch (m_hitRegion) { case HitRegion.XAxis: { 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); m_scale.X = 1.0f + dragAmount / m_hitScale; scale = m_scale.X; } break; case HitRegion.YAxis: { 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); m_scale.Y = 1.0f + dragAmount / m_hitScale; scale = m_scale.Y; } break; case HitRegion.ZAxis: { 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); m_scale.Z = 1.0f + dragAmount / m_hitScale; scale = m_scale.Z; } break; case HitRegion.FreeRect: { Vec3F axis = new Vec3F(0, 0, 1); Vec3F p0 = HitRayV.IntersectPlane(axis, -origin.Z); Vec3F p1 = rayV.IntersectPlane(axis, -origin.Z); Vec3F dragVec = p1 - p0; float dragAmount = 1.0f + dragVec.X / m_hitScale; m_scale.X = dragAmount; m_scale.Y = dragAmount; m_scale.Z = dragAmount; scale = m_scale.X; } break; default: throw new ArgumentOutOfRangeException(); } if (m_isUniformScaling) { m_scale = new Vec3F(scale, scale, scale); } // scale for (int i = 0; i < NodeList.Count; i++) { ITransformable transformable = NodeList[i]; transformable.Scale = Vec3F.Mul(m_originalValues[i], m_scale); } }
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 OnDragging(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None || NodeList.Count == 0) { return; } Camera cam = vc.Camera; Matrix4F view = cam.ViewMatrix; Matrix4F mtrx = cam.ProjectionMatrix; Matrix4F axisMtrx = HitMatrix * view; Ray3F hitRay = HitRayV; Ray3F dragRay = vc.GetRay(scrPt, mtrx); Vec3F xAxis = axisMtrx.XAxis; Vec3F yAxis = axisMtrx.YAxis; Vec3F zAxis = axisMtrx.ZAxis; Vec3F origin = axisMtrx.Translation; Vec3F rotAxis = new Vec3F(); float theta = 0; float snapAngle = ((ISnapSettings)DesignView).SnapAngle; switch (m_hitRegion) { case HitRegion.XAxis: { Plane3F xplane = new Plane3F(xAxis, origin); theta = CalcAngle(origin, xplane, hitRay, dragRay, snapAngle); rotAxis = HitMatrix.XAxis; } break; case HitRegion.YAxis: { Plane3F yplane = new Plane3F(yAxis, origin); theta = CalcAngle(origin, yplane, hitRay, dragRay, snapAngle); rotAxis = HitMatrix.YAxis; } break; case HitRegion.ZAxis: { Plane3F zplane = new Plane3F(zAxis, origin); theta = CalcAngle(origin, zplane, hitRay, dragRay, snapAngle); rotAxis = HitMatrix.ZAxis; } break; default: throw new ArgumentOutOfRangeException(); } AngleAxisF axf = new AngleAxisF(-theta, rotAxis); Matrix4F deltaMtrx = new Matrix4F(axf); Matrix4F rotMtrx = new Matrix4F(); for (int i = 0; i < NodeList.Count; i++) { ITransformable node = NodeList[i]; rotMtrx.Mul(m_rotations[i], deltaMtrx); float ax, ay, az; rotMtrx.GetEulerAngles(out ax, out ay, out az); node.Rotation = new Vec3F(ax, ay, az); } }
protected override Matrix4F GetManipulatorMatrix() { ITransformable node = GetManipulatorNode(TransformationTypes.Rotation); if (node == null ) return null; Path<DomNode> path = new Path<DomNode>(node.Cast<DomNode>().GetPath()); Matrix4F localToWorld = TransformUtils.CalcPathTransform(path, path.Count - 1); // local transform Matrix4F toworld = new Matrix4F(localToWorld); // Offset by rotate pivot Matrix4F P = new Matrix4F(); P.Translation = node.Pivot; toworld.Mul(P, toworld); // Normalize toworld.Normalize(toworld); return toworld; }
/// <summary> /// Performs initialization when the adapter's node is set. /// This method is called each time the adapter is connected to its underlying node. /// Typically overridden by creators of DOM adapters.</summary> protected override void OnNodeSet() { base.OnNodeSet(); // get trans, scale, and rot. foreach (DomNode domNode in this.DomNode.GetChildList(Schema.node.scaleChild)) { m_scale = Tools.GetVector3(domNode, Schema.TargetableFloat3.Attribute); break; } foreach (DomNode domNode in this.DomNode.GetChildList(Schema.node.translateChild)) { m_translation = Tools.GetVector3(domNode, Schema.TargetableFloat3.Attribute); break; } const float PiOver180 = (float)(Math.PI / 180.0f); foreach (DomNode node in DomNode.GetChildList(Schema.node.rotateChild)) { double[] arr = (double[])node.GetAttribute(Schema.rotate.Attribute); float angle = (float)arr[3] * PiOver180; string sid = node.GetAttribute(Schema.rotate.sidAttribute) as string; if (string.IsNullOrEmpty(sid)) continue; if (sid == "rotateX") m_rotation.X = angle; else if (sid == "rotateY") m_rotation.Y = angle; else if (sid == "rotateZ") m_rotation.Z = angle; } Matrix4F M = new Matrix4F(); Matrix4F temp = new Matrix4F(); temp.Scale(Scale); M.Mul(M, temp); if (m_rotation.X != 0) { temp.RotX(m_rotation.X); M.Mul(M, temp); } if (m_rotation.Y != 0) { temp.RotY(m_rotation.Y); M.Mul(M, temp); } if (m_rotation.Z != 0) { temp.RotZ(m_rotation.Z); M.Mul(M, temp); } temp.Set(Translation); M.Mul(M, temp); Transform = M; m_boundingBox = new Cached<Box>(CalculateBoundingBox); Visible = true; }
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); } } }
/// <summary> /// Gets the view matrix corresponding to a "look at" point</summary> /// <param name="azimuth">Camera pan, in radians</param> /// <param name="elevation">Camera tilt, in radians</param> /// <param name="lookAt">"Look at" direction</param> /// <param name="dolly">Distance from "look at" point</param> /// <returns>View matrix corresponding to the "look at" point</returns> public static Matrix4F LookAtMatrix(float azimuth, float elevation, Vec3F lookAt, float dolly) { Matrix4F R = LookAtRotationMatrix(azimuth, elevation, lookAt); R.ZTranslation = -dolly; Matrix4F T = new Matrix4F ( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -lookAt.X, -lookAt.Y, -lookAt.Z, 1 ); Matrix4F result = new Matrix4F(); result.Mul(T, R); return result; }