Пример #1
0
        public static Vec3F CalcSnapFromOffset(ITransformable node, SnapFromMode snapFrom)
        {
            // AABB in local space.
            AABB box = node.As <IBoundable>().LocalBoundingBox;

            Vec3F offsetLocal = box.Center;

            switch (snapFrom)
            {
            case SnapFromMode.Pivot:
                offsetLocal = node.Pivot;
                break;

            case SnapFromMode.Origin:
                offsetLocal = box.Center;
                break;

            case SnapFromMode.TopCenter:
                offsetLocal.Y = box.Max.Y;
                break;

            case SnapFromMode.BottomCenter:
                offsetLocal.Y = box.Min.Y;
                break;

            case SnapFromMode.FrontCenter:
                offsetLocal.Z = box.Max.Z;
                break;

            case SnapFromMode.BackCenter:
                offsetLocal.Z = box.Min.Z;
                break;

            case SnapFromMode.LeftCenter:
                offsetLocal.X = box.Min.X;
                break;

            case SnapFromMode.RightCenter:
                offsetLocal.X = box.Max.X;
                break;

            default:
                throw new ArgumentOutOfRangeException("Invalid snap-from node");
            }

            Path <DomNode> path    = new Path <DomNode>(node.Cast <DomNode>().GetPath());
            Matrix4F       toWorld = TransformUtils.CalcPathTransform(path, path.Count - 1);

            Vec3F offset;

            toWorld.TransformVector(offsetLocal, out offset); //local-to-world
            return(offset);                                   //world
        }
Пример #2
0
        /// <summary>
        /// For an object 'node' that is being manipulated, this function returns
        /// the offset (in world space) from the object's origin to to the point that is being
        /// "snapped from". This calculation is determined by the snapping modes.</summary>
        /// <param name="node">The object that is being snapped-to some other object</param>
        /// <param name="snapFromMode">The "snap from" mode, as an enum</param>
        /// <param name="axisType">Axis system type (y or z is up)</param>
        /// <param name="pivot">Pass in either node.RotatePivot or node.ScalePivot</param>
        /// <returns>Offset from this object's origin to the "snap from" point, in world space</returns>
        /// <remarks>Must be kept in sync with SnapFromModes property.</remarks>
        public static Vec3F CalcSnapFromOffset(
            ITransformable node,
            SnapFromMode snapFromMode,
            AxisSystemType axisType, Vec3F pivot)
        {
            switch (snapFromMode)
            {
            case SnapFromMode.Pivot:
            {
                Vec3F          offset;
                Path <DomNode> path          = new Path <DomNode>(node.Cast <DomNode>().Ancestry);
                Matrix4F       parentToWorld = TransformUtils.CalcPathTransform(path, path.Count - 2);
                node.Transform.TransformVector(pivot, out offset); //local-to-parent
                parentToWorld.TransformVector(offset, out offset); //parent-to-world
                return(offset);                                    //world
            }

            case SnapFromMode.Origin:
                return(new Vec3F(0, 0, 0));

            case SnapFromMode.BottomCenter:
            {
                Box   box = node.BoundingBox;
                Vec3F btmWorld;
                if (axisType == AxisSystemType.YIsUp)
                {
                    btmWorld = new Vec3F(
                        (box.Min.X + box.Max.X) * 0.5f,
                        box.Min.Y,
                        (box.Min.Z + box.Max.Z) * 0.5f);
                }
                else
                {
                    btmWorld = new Vec3F(
                        (box.Min.X + box.Max.X) * 0.5f,
                        (box.Min.Y + box.Max.Y) * 0.5f,
                        box.Min.Z);
                }
                Vec3F origin = node.Transform.Translation;
                Vec3F offset = btmWorld - origin;         //local space offset

                Path <DomNode> path          = new Path <DomNode>(node.Cast <DomNode>().GetPath());
                Matrix4F       parentToWorld = TransformUtils.CalcPathTransform(path, path.Count - 2);
                parentToWorld.TransformVector(offset, out offset);

                return(offset);
            }

            default:
                throw new ArgumentException("Invalid snap-from node");
            }
        }
Пример #3
0
        public override void OnDragging(ViewControl vc, Point scrPt)
        {
            if (m_hitRegion == HitRegion.None || m_activeOp == null || m_activeOp.NodeList.Count == 0)
            {
                return;
            }

            // create ray in view space.
            Ray3F rayV = vc.GetWorldRay(scrPt);

            using (var intersectionScene = GameEngine.GetEditorSceneManager().GetIntersectionScene())
            {
                Vec3F intersectionPt;
                if (!CalculateTerrainIntersection(vc, rayV, intersectionScene, out intersectionPt))
                {
                    return;
                }

                if (m_pendingStartPt)
                {
                    m_startPt        = intersectionPt;
                    m_pendingStartPt = false;
                }
                else
                {
                    bool  clampToSurface = Control.ModifierKeys == Keys.Shift;
                    Vec3F translate      = new Vec3F(intersectionPt.X - m_startPt.X, intersectionPt.Y - m_startPt.Y, 0.0f);
                    for (int i = 0; i < m_activeOp.NodeList.Count; i++)
                    {
                        ITransformable node = m_activeOp.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 newWorldPos   = m_originalTranslations[i] + translate;
                        float terrainHeight = 0.0f;
                        if (GUILayer.EditorInterfaceUtils.GetTerrainHeight(
                                out terrainHeight, intersectionScene, newWorldPos.X, newWorldPos.Y))
                        {
                            newWorldPos.Z = terrainHeight + (clampToSurface ? 0.0f : m_originalHeights[i]);
                            Vec3F localTranslation;
                            parentWorldToLocal.TransformVector(newWorldPos, out localTranslation);
                            node.Translation = localTranslation;
                        }
                    }
                }
            }
        }
        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;
                }
            }
        }
Пример #5
0
 /// <summary>
 /// Transforms the ray by the given matrix. The Direction member will be normalized. There are
 /// no particular restrictions on M. Any transformation done to a point in world space or
 /// object space can be done on this ray, including any combination of rotations, translations,
 /// uniform scales, non-uniform scales, etc.</summary>
 /// <param name="M">Transformation matrix</param>
 public void Transform(Matrix4F M)
 {
     M.Transform(Origin, out Origin);
     M.TransformVector(Direction, out Direction);
     Direction.Normalize();
 }
Пример #6
0
        public override void OnDragging(ViewControl vc, Point scrPt)
        {
            if (m_hitRegion == HitRegion.None || m_activeOp == null || m_activeOp.NodeList.Count == 0)
                return;

                // create ray in view space.
            Ray3F rayV = vc.GetWorldRay(scrPt);

            using (var intersectionScene = GameEngine.GetEditorSceneManager().GetIntersectionScene())
            {
                Vec3F intersectionPt;
                if (!CalculateTerrainIntersection(vc, rayV, intersectionScene, out intersectionPt))
                    return;

                if (m_pendingStartPt)
                {
                    m_startPt = intersectionPt;
                    m_pendingStartPt = false;
                }
                else
                {
                    bool clampToSurface = Control.ModifierKeys == Keys.Shift;
                    Vec3F translate = new Vec3F(intersectionPt.X - m_startPt.X, intersectionPt.Y - m_startPt.Y, 0.0f);
                    for (int i = 0; i < m_activeOp.NodeList.Count; i++)
                    {
                        ITransformable node = m_activeOp.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 newWorldPos = m_originalTranslations[i] + translate;
                        float terrainHeight = 0.0f;
                        if (GUILayer.EditorInterfaceUtils.GetTerrainHeight(
                            out terrainHeight, intersectionScene, newWorldPos.X, newWorldPos.Y)) {

                            newWorldPos.Z = terrainHeight + (clampToSurface ? 0.0f : m_originalHeights[i]);
                            Vec3F localTranslation;
                            parentWorldToLocal.TransformVector(newWorldPos, out localTranslation);
                            node.Translation = localTranslation;
                        }
                    }
                }
            }
        }
Пример #7
0
        public static void CreateTorus(float innerRadius,
                                       float outerRadius,
                                       uint rings,
                                       uint sides,
                                       List <Vec3F> pos,
                                       List <Vec3F> nor,
                                       List <Vec2F> tex,
                                       List <uint> indices)
        {
            uint ringStride = rings + 1;
            uint sideStride = sides + 1;

            // radiusC: distance to center of the ring
            float radiusC = (innerRadius + outerRadius) * 0.5f;

            //radiusR: the radius of the ring
            float radiusR = (outerRadius - radiusC);

            for (uint i = 0; i <= rings; i++)
            {
                float u = (float)i / rings;

                float outerAngle = i * MathHelper.TwoPi / rings;

                // xform from ring space to torus space.
                Matrix4F trans = new Matrix4F();
                trans.Translation = new Vec3F(radiusC, 0, 0);
                Matrix4F roty = new Matrix4F();
                roty.RotY(outerAngle);
                Matrix4F transform = trans * roty;

                // create vertices for each ring.
                for (uint j = 0; j <= sides; j++)
                {
                    float v = (float)j / sides;

                    float innerAngle = j * MathHelper.TwoPi / sides + MathHelper.Pi;
                    float dx         = (float)Math.Cos(innerAngle);
                    float dy         = (float)Math.Sin(innerAngle);

                    // normal, position ,and texture coordinates
                    Vec3F n = new Vec3F(dx, dy, 0);
                    Vec3F p = n * radiusR;

                    if (tex != null)
                    {
                        Vec2F t = new Vec2F(u, v);
                        tex.Add(t);
                    }

                    transform.Transform(ref p);
                    transform.TransformVector(n, out n);

                    pos.Add(p);
                    nor.Add(n);


                    // And create indices for two triangles.
                    uint nextI = (i + 1) % ringStride;
                    uint nextJ = (j + 1) % sideStride;

                    indices.Add(nextI * sideStride + j);
                    indices.Add(i * sideStride + nextJ);
                    indices.Add(i * sideStride + j);

                    indices.Add(nextI * sideStride + j);
                    indices.Add(nextI * sideStride + nextJ);
                    indices.Add(i * sideStride + nextJ);
                }
            }
        }
        public override void OnDragging(ViewControl vc, Point scrPt)
        {
            if (m_hitRegion == HitRegion.None || m_activeOp == null || m_activeOp.NodeList.Count == 0)
            {
                return;
            }

            // create ray in view space.
            Ray3F rayV = vc.GetWorldRay(scrPt);

            using (var intersectionScene = GameEngine.GetEditorSceneManager().GetIntersectionScene())
            {
                PickResult intersectionPt;
                if (!CalculateTerrainIntersection(vc, rayV, intersectionScene, out intersectionPt))
                {
                    return;
                }

                if (m_pendingStartPt)
                {
                    m_startPt        = intersectionPt._pt.Value;
                    m_pendingStartPt = false;
                }
                else
                {
                    ISnapSettings snapSettings = (ISnapSettings)DesignView;

                    bool  clampToSurface = Control.ModifierKeys == Keys.Shift;
                    var   pt             = intersectionPt._pt.Value;
                    Vec3F translate      = new Vec3F(pt.X - m_startPt.X, pt.Y - m_startPt.Y, 0.0f);
                    for (int i = 0; i < m_activeOp.NodeList.Count; i++)
                    {
                        ITransformable node = m_activeOp.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            newWorldPos   = m_originalTranslations[i] + translate;
                        float            terrainHeight = 0.0f;
                        GUILayer.Vector3 terrainNormal;
                        if (GUILayer.EditorInterfaceUtils.GetTerrainHeightAndNormal(
                                out terrainHeight, out terrainNormal,
                                intersectionScene, newWorldPos.X, newWorldPos.Y))
                        {
                            newWorldPos.Z = terrainHeight + (clampToSurface ? 0.0f : m_originalHeights[i]);
                            Vec3F localTranslation;
                            parentWorldToLocal.TransformVector(newWorldPos, out localTranslation);
                            node.Translation = localTranslation;

                            // There are two ways to orient the "up" vector of the object.
                            // One way is to decompose the 3x3 rotation matrix into a up vector + a rotation around
                            // that vector. Then we retain the rotation, and just move the up vector.
                            // Another way is to take the 3x3 matrix, and adjust it's up vector. Then just perform
                            // the Gram–Schmidt algorithm to re-orthogonalize it.
                            // We'll use the code from the SCEE level editor. This isn't the ideal math (there's a
                            // lot of room for floating point creep) but it should work.
                            var currentUp = node.Transform.ZAxis;
                            if (snapSettings.TerrainAlignment == TerrainAlignmentMode.TerrainUp)
                            {
                                node.Rotation = TransformUtils.RotateToVector(
                                    node.Rotation, new Vec3F(terrainNormal.X, terrainNormal.Y, terrainNormal.Z),
                                    AxisSystemType.ZIsUp);
                            }
                            else
                            if (snapSettings.TerrainAlignment == TerrainAlignmentMode.WorldUp)
                            {
                                // Prevent the change if the normal is already very close to straight up
                                if (Math.Abs(currentUp.X - 0.0f) > 1e-4f || Math.Abs(currentUp.Y - 0.0f) > 1e-4f || Math.Abs(currentUp.Z - 1.0f) > 1e-4f)
                                {
                                    node.Rotation = TransformUtils.RotateToVector(
                                        node.Rotation, new Vec3F(0.0f, 0.0f, 1.0f),
                                        AxisSystemType.ZIsUp);
                                }
                            }

                            node.UpdateTransform();
                        }
                    }
                }
            }
        }
Пример #9
0
        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;
                }                
            }
        }