/// <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);
        }
Beispiel #2
0
 /// <summary>
 /// Transform the vectors in the given array.
 /// </summary>
 /// <param name="vectors">An array of vectors to transform.</param>
 /// <param name="transformation">The transformation.</param>
 /// <remarks>
 /// This method changes the vector values in the <paramref name="vectors"/> array.
 /// </remarks>
 public static void TransformArray(Vector3FArrayList vectors, Matrix4F transformation)
 {
     for (int i = 0; i < vectors.Count; i++)
     {
         vectors[i] = Matrix4F.Transform(transformation, vectors[i]);
     }
 }
Beispiel #3
0
 /// <summary>
 /// Transform the vectors in the given array and put the result in another array.
 /// </summary>
 /// <param name="vectors">An array of vectors to transform.</param>
 /// <param name="transformation">The transformation.</param>
 /// <param name="result">An array of vectors to put the transformation results in (should be empty).</param>
 public static void TransformArray(Vector3FArrayList vectors, Matrix4F transformation, Vector3FArrayList result)
 {
     for (int i = 0; i < vectors.Count; i++)
     {
         result.Add(Matrix4F.Transform(transformation, vectors[i]));
     }
 }
Beispiel #4
0
        /// <summary>
        /// Sorts the provided list by camera space z distance.
        /// Assumes a right-handed coordinate system, so the farthest nodes have the most negative values.</summary>
        /// <param name="list">List of alpha TraverseNodes to sort</param>
        /// <param name="viewMatrix">Current view matrix to transform bounding box centroids by</param>
        public static void SortByCameraSpaceDepth(List <TraverseNode> list, Matrix4F viewMatrix)
        {
            KeyValuePair <float, TraverseNode>[] camSpaceDistances =
                new KeyValuePair <float, TraverseNode> [list.Count];

            for (int i = 0; i < list.Count; ++i)
            {
                TraverseNode node = list[i];
                Vec3F        worldSpaceCentroid = node.WorldSpaceBoundingBox.Centroid;

                Vec3F centerPointInCameraSpace;
                viewMatrix.Transform(worldSpaceCentroid, out centerPointInCameraSpace);

                camSpaceDistances[i] = new KeyValuePair <float, TraverseNode>(centerPointInCameraSpace.Z, node);
            }

            Array.Sort(camSpaceDistances, new CamSpaceDistanceComparer());

            list.Clear();

            foreach (KeyValuePair <float, TraverseNode> entry in camSpaceDistances)
            {
                list.Add(entry.Value);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Compute new transform using
        /// position of all the control points</summary>
        internal void ComputeTranslation()
        {
            if (m_computingTranslation)
            {
                return;
            }
            try
            {
                m_computingTranslation = true;
                var points = ControlPoints;
                if (points.Count == 0)
                {
                    return;
                }

                // center in local space.
                Vec3F localcenter = points[0].Translation;

                ITransformable xformcurve    = this.As <ITransformable>();
                Matrix4F       localToParent = xformcurve.Transform;
                // center in parent space.
                Vec3F center;
                localToParent.Transform(localcenter, out center);
                xformcurve.Translation = center;
                foreach (var cpt in points)
                {
                    cpt.Translation -= localcenter;
                }
            }
            finally
            {
                m_computingTranslation = false;
            }
        }
Beispiel #6
0
        /// <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;
        }
Beispiel #7
0
        private DomNode CreatePrototype(IEnumerable <IGameObject> gobs)
        {
            DomNode[] originals = new DomNode[1];

            List <IGameObject> copyList = new List <IGameObject>();
            AABB bound = new AABB();

            foreach (IGameObject gameObject in SelectedGobs)
            {
                IBoundable boundable = gameObject.As <IBoundable>();
                bound.Extend(boundable.BoundingBox);
                Matrix4F world = TransformUtils.ComputeWorldTransform(gameObject);
                originals[0] = gameObject.As <DomNode>();
                DomNode[]   copies = DomNode.Copy(originals);
                IGameObject copy   = copies[0].As <IGameObject>();
                TransformUtils.SetTransform(copy, world);
                copyList.Add(copy);
            }

            DomNode gobchild = null;

            if (copyList.Count > 1)
            {// create group
                IGame            game     = m_contextRegistry.GetActiveContext <IGame>();
                IGameObjectGroup gobgroup = game.CreateGameObjectGroup();
                gobgroup.Translation = bound.Center;
                gobgroup.UpdateTransform();
                Matrix4F worldInv = new Matrix4F();
                worldInv.Invert(gobgroup.Transform);
                foreach (IGameObject gob in copyList)
                {
                    Vec3F translate = gob.Translation;
                    worldInv.Transform(ref translate);
                    gob.Translation = translate;
                    gob.UpdateTransform();
                    gobgroup.GameObjects.Add(gob);
                }
                gobchild = gobgroup.As <DomNode>();
            }
            else
            {
                gobchild = copyList[0].As <DomNode>();
            }

            gobchild.InitializeExtensions();
            gobchild.As <IGameObject>().Translation = new Vec3F(0, 0, 0);

            DomNode prototype = null;

            if (gobchild != null)
            {
                prototype = new DomNode(Schema.prototypeType.Type, Schema.prototypeRootElement);
                prototype.SetChild(Schema.prototypeType.gameObjectChild, gobchild);
            }
            return(prototype);
        }
Beispiel #8
0
        /// <summary>
        /// project the v from 3d space to viewport space
        /// using the given wvp matrix.
        /// </summary>
        public Point Project(Matrix4F wvp, Vec3F v)
        {
            float w = v.X * wvp.M14 + v.Y * wvp.M24 + v.Z * wvp.M34 + wvp.M44;

            wvp.Transform(ref v);
            v = v / w;
            Point pt = new Point();

            pt.X = (int)((v.X + 1) * 0.5f * Width);
            pt.Y = (int)((1.0f - v.Y) * 0.5f * Height);
            return(pt);
        }
        /// <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));
        }
Beispiel #10
0
        /// <summary>
        /// Groups the specified GameObjects</summary>
        /// <param name="gobs">GameObjects to be grouped</param>
        /// <remarks>Creates a new GameObjectGroup and moves all
        /// the GameObjects into it.</remarks>
        public IGameObjectGroup Group(IEnumerable <IGameObject> gobs)
        {
            // extra check.
            if (!CanGroup(gobs))
            {
                return(null);
            }

            IGame game     = null;
            AABB  groupBox = new AABB();
            List <IGameObject> gameObjects = new List <IGameObject>();

            foreach (IGameObject gameObject in gobs)
            {
                if (game == null)
                {
                    game = gameObject.As <DomNode>().GetRoot().As <IGame>();
                }

                gameObjects.Add(gameObject);

                IBoundable boundable = gameObject.As <IBoundable>();
                groupBox.Extend(boundable.BoundingBox);
            }

            IGameObjectGroup group = game.CreateGameObjectGroup();
            DomNode          node  = group.As <DomNode>();

            node.InitializeExtensions();
            ITransformable transformable = node.As <ITransformable>();

            transformable.Translation = groupBox.Center;

            Matrix4F invWorld = new Matrix4F();

            invWorld.Invert(transformable.Transform);

            game.RootGameObjectFolder.GameObjects.Add(group);

            foreach (IGameObject gameObject in gameObjects)
            {
                ITransformable xformable = gameObject.As <ITransformable>();
                Matrix4F       world     = ComputeWorldTransform(xformable);
                SetTransform(xformable, world);
                group.GameObjects.Add(gameObject);
                Vec3F trans = world.Translation;
                invWorld.Transform(ref trans);
                xformable.Translation = trans;
            }

            return(group);
        }
Beispiel #11
0
        /// <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;
        }
Beispiel #12
0
        /// <summary>
        /// Transforms the given world or local point into viewport (Windows) coordinates</summary>
        /// <param name="localPoint">World or local point to be transformed</param>
        /// <param name="localToScreen">Tranformation matrix composed of object-to-world times
        /// world-to-view times view-to-projection</param>
        /// <param name="viewportWidth">The viewport width, for example Control.Width or
        /// IRenderAction.ViewportWidth</param>
        /// <param name="viewportHeight">The viewport height, for example Control.Height or
        /// IRenderAction.ViewportHeight</param>
        /// <returns>The viewport or Window coordinate in the range [0,Width] and [0,Height]
        /// where the origin is the upper left corner of the viewport. The coordinate could be
        /// outside of this range if localPoint is not visible.</returns>
        /// <example>
        /// To calculate localToScreen using an object's local-to-world and a Camera:
        ///     localToScreen = Matrix4F.Multiply(localToWorld, camera.ViewMatrix);
        ///     localToScreen.Mul(localToScreen, camera.ProjectionMatrix);
        /// </example>
        public static Vec2F TransformToViewport(
            Vec3F localPoint,
            Matrix4F localToScreen,
            float viewportWidth,
            float viewportHeight)
        {
            // transform to clip space and do perspective divide. Result is in range of [-1, 1]
            Vec4F xScreen = new Vec4F(localPoint);

            localToScreen.Transform(xScreen, out xScreen);
            xScreen = Vec4F.Mul(xScreen, 1.0f / xScreen.W);

            // get viewport coordinates. Convert [-1, 1] to [0, view size]
            Vec2F xViewport = new Vec2F(
                (xScreen.X + 1) * 0.5f * viewportWidth,
                (1 - (xScreen.Y + 1) * 0.5f) * viewportHeight);

            return(xViewport);
        }
Beispiel #13
0
        /// <summary>
        /// unproject vector from screen space to object space.
        /// </summary>
        public Vec3F Unproject(Vec3F scrPt, Matrix4F wvp)
        {
            float    width  = ClientSize.Width;
            float    height = ClientSize.Height;
            Matrix4F invWVP = new Matrix4F();

            invWVP.Invert(wvp);
            Vec3F worldPt = new Vec3F();

            worldPt.X = scrPt.X / width * 2.0f - 1f;
            worldPt.Y = -(scrPt.Y / height * 2.0f - 1f);
            worldPt.Z = scrPt.Z;

            float w = worldPt.X * invWVP.M14 + worldPt.Y * invWVP.M24 + worldPt.Z * invWVP.M34 + invWVP.M44;

            invWVP.Transform(ref worldPt);
            worldPt = worldPt / w;
            return(worldPt);
        }
Beispiel #14
0
        public static void CalcAxisLengths(Camera camera, Vec3F objectPosW, out float s)
        {
            float axisRatio = 0.24f;

            float worldHeight;

            // World height on origin's z value
            if (camera.Frustum.IsOrtho)
            {
                worldHeight = (camera.Frustum.Top - camera.Frustum.Bottom) / 2;
            }
            else
            {
                Matrix4F view = camera.ViewMatrix;
                Vec3F    objPosV;
                view.Transform(objectPosW, out objPosV);
                worldHeight = -objPosV.Z * (float)Math.Tan(camera.Frustum.FovY / 2.0f);
            }
            s = (axisRatio * worldHeight);
        }
Beispiel #15
0
        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;
        }
Beispiel #16
0
        /// <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));
        }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        /// <summary>
        /// Dispatches untyped items. Replaces DispatchNotTyped(). To get the same behavior as
        /// the old DispatchNotTyped(), set the TypeFilter property to null prior to calling.</summary>
        /// <param name="traverseList">The traverse list</param>
        /// <param name="camera">The camera</param>
        protected void DispatchTraverseList(ICollection <TraverseNode> traverseList, Camera camera)
        {
            // Prepare for geometric picking -- create the ray in world space and reset geometric hit-list.
            // First create the ray in viewing coordinates and transform to world coordinates.
            float    nx          = (m_x / (float)m_width) - 0.5f;  //normalized x
            float    ny          = 0.5f - (m_y / (float)m_height); //normalized y
            Ray3F    rayWorld    = camera.CreateRay(nx, ny);
            Matrix4F worldToView = camera.ViewMatrix;
            Matrix4F viewToWorld = new Matrix4F();

            viewToWorld.Invert(worldToView);
            rayWorld.Transform(viewToWorld);
            ClearHitList();

            // for geometric picking. will be cleared for each HitRecord.
            List <uint> userData = new List <uint>(1);

            // Dispatch traverse list
            int index = 0;

            foreach (TraverseNode node in traverseList)
            {
                // First test for filtering.
                IRenderObject renderObject = node.RenderObject;
                if (FilterByType(renderObject))
                {
                    IIntersectable intersectable = renderObject.GetIntersectable();
                    IGeometricPick geometricPick = intersectable as IGeometricPick;
                    if (geometricPick != null)
                    {
                        // Picking by geometry.
                        Matrix4F objToWorld = new Matrix4F(node.Transform);
                        Matrix4F worldToObj = new Matrix4F();
                        worldToObj.Invert(objToWorld);
                        Matrix4F viewToObj = Matrix4F.Multiply(viewToWorld, worldToObj);

                        if (m_frustumPick)
                        {
                            //The pick frustum is in view space. Transform to world space then object space.
                            Frustum frustumObj = new Frustum(m_viewFrust0);
                            frustumObj.Transform(viewToObj);

                            //Multi-pick. Get everything in the pick frustum (m_viewFrust0).
                            Vec3F eyeObj;
                            worldToObj.Transform(camera.Eye, out eyeObj);
                            userData.Clear();

                            if (geometricPick.IntersectFrustum(frustumObj, eyeObj, node.RenderState, userData))
                            {
                                // Prepare a multi-pick HitRecord, as if OpenGL had calculated this.
                                HitRecord hit = new HitRecord(
                                    node.GraphPath,
                                    renderObject,
                                    objToWorld,
                                    userData.ToArray());

                                m_geoHitList.Add(hit);
                            }
                        }
                        else
                        {                            //Single pick. We care about distance from camera eye.
                            //Make a copy of the ray in world-space and tranform it to object space.
                            Ray3F rayObj = rayWorld; //remember, Ray3F is a value type, not a reference type.
                            rayObj.Transform(worldToObj);

                            // Do the intersection test in object space.
                            userData.Clear();
                            Vec3F intersectionPt, surfaceNormal;
                            Vec3F nearestVert;
                            bool  intersected;
                            intersected = geometricPick.IntersectRay(
                                rayObj, camera, node.RenderState, objToWorld, this,
                                out intersectionPt, out nearestVert, out surfaceNormal, userData);

                            if (intersected)
                            {
                                // Transform to world space and then to screen space.
                                objToWorld.Transform(intersectionPt, out intersectionPt);
                                objToWorld.Transform(nearestVert, out nearestVert);
                                // Prepare a single-pick HitRecord, as if OpenGL had calculated this.
                                HitRecord hit = new HitRecord(
                                    node.GraphPath,
                                    renderObject,
                                    objToWorld,
                                    userData.ToArray());

                                // This is the one difference from OpenGL pick. We have the world pt already.
                                hit.WorldIntersection = intersectionPt;
                                hit.NearestVert       = nearestVert;

                                // Another difference is that it's possible to get the surface normal.
                                if (surfaceNormal != Vec3F.ZeroVector)
                                {
                                    objToWorld.TransformNormal(surfaceNormal, out surfaceNormal);
                                    surfaceNormal.Normalize();
                                    hit.Normal = surfaceNormal;
                                }

                                m_geoHitList.Add(hit);
                            }
                        }
                    }
                    else
                    {
                        // Picking by "rendering", using OpenGL pick.
                        PushMatrix(node.Transform, false);
                        Gl.glPushName(index);
                        IRenderPick pickInterface = renderObject as IRenderPick;
                        if (pickInterface != null)
                        {
                            pickInterface.PickDispatch(node.GraphPath, node.RenderState, this, camera);
                        }
                        else
                        {
                            renderObject.Dispatch(node.GraphPath, node.RenderState, this, camera);
                        }
                        Gl.glPopName();
                        PopMatrix();
                    }
                }

                index++;
            }
        }
Beispiel #19
0
        /// <summary>
        /// Dispatches untyped items. Replaces DispatchNotTyped(). To get the same behavior as
        /// the old DispatchNotTyped(), set the TypeFilter property to null prior to calling.</summary>
        /// <param name="traverseList">The traverse list</param>
        /// <param name="camera">The camera</param>
        protected void DispatchTraverseList(ICollection<TraverseNode> traverseList, Camera camera)
        {
            // Prepare for geometric picking -- create the ray in world space and reset geometric hit-list.
            // First create the ray in viewing coordinates and transform to world coordinates.
            float nx = (m_x / (float)m_width) - 0.5f;//normalized x
            float ny = 0.5f - (m_y / (float)m_height);//normalized y
            Ray3F rayWorld = camera.CreateRay(nx, ny);
            Matrix4F worldToView = camera.ViewMatrix;
            Matrix4F viewToWorld = new Matrix4F();
            viewToWorld.Invert(worldToView);
            rayWorld.Transform(viewToWorld);
            ClearHitList();

            // for geometric picking. will be cleared for each HitRecord.
            List<uint> userData = new List<uint>(1);

            // Dispatch traverse list
            int index = 0;
            foreach (TraverseNode node in traverseList)
            {
                // First test for filtering. 
                IRenderObject renderObject = node.RenderObject;
                if (FilterByType(renderObject))
                {
                    IIntersectable intersectable = renderObject.GetIntersectable();
                    IGeometricPick geometricPick = intersectable as IGeometricPick;
                    if (geometricPick != null)
                    {
                        // Picking by geometry.
                        Matrix4F objToWorld = new Matrix4F(node.Transform);
                        Matrix4F worldToObj = new Matrix4F();
                        worldToObj.Invert(objToWorld);
                        Matrix4F viewToObj = Matrix4F.Multiply(viewToWorld, worldToObj);

                        if (m_frustumPick)
                        {
                            //The pick frustum is in view space. Transform to world space then object space.
                            Frustum frustumObj = new Frustum(m_viewFrust0);
                            frustumObj.Transform(viewToObj);

                            //Multi-pick. Get everything in the pick frustum (m_viewFrust0).
                            Vec3F eyeObj;
                            worldToObj.Transform(camera.Eye, out eyeObj);
                            userData.Clear();

                            if (geometricPick.IntersectFrustum(frustumObj, eyeObj, node.RenderState, userData))
                            {
                                // Prepare a multi-pick HitRecord, as if OpenGL had calculated this.
                                HitRecord hit = new HitRecord(
                                    node.GraphPath,
                                    renderObject,
                                    objToWorld,
                                    userData.ToArray());

                                m_geoHitList.Add(hit);
                            }
                        }
                        else
                        {   //Single pick. We care about distance from camera eye.
                            //Make a copy of the ray in world-space and tranform it to object space.
                            Ray3F rayObj = rayWorld; //remember, Ray3F is a value type, not a reference type.
                            rayObj.Transform(worldToObj);

                            // Do the intersection test in object space.
                            userData.Clear();
                            Vec3F intersectionPt, surfaceNormal;
                            Vec3F nearestVert;
                            bool intersected;
                            intersected = geometricPick.IntersectRay(
                                rayObj, camera, node.RenderState, objToWorld, this,
                                out intersectionPt, out nearestVert, out surfaceNormal, userData);

                            if (intersected)
                            {
                                // Transform to world space and then to screen space.
                                objToWorld.Transform(intersectionPt, out intersectionPt);
                                objToWorld.Transform(nearestVert, out nearestVert);
                                // Prepare a single-pick HitRecord, as if OpenGL had calculated this.
                                HitRecord hit = new HitRecord(
                                    node.GraphPath,
                                    renderObject,
                                    objToWorld,
                                    userData.ToArray());

                                // This is the one difference from OpenGL pick. We have the world pt already.
                                hit.WorldIntersection = intersectionPt;
                                hit.NearestVert = nearestVert;

                                // Another difference is that it's possible to get the surface normal.
                                if (surfaceNormal != Vec3F.ZeroVector)
                                {
                                    objToWorld.TransformNormal(surfaceNormal, out surfaceNormal);
                                    surfaceNormal.Normalize();
                                    hit.Normal = surfaceNormal;
                                }

                                m_geoHitList.Add(hit);
                            }
                        }
                    }
                    else
                    {
                        // Picking by "rendering", using OpenGL pick.
                        PushMatrix(node.Transform, false);
                        Gl.glPushName(index);
                        IRenderPick pickInterface = renderObject as IRenderPick;
                        if (pickInterface != null)
                        {
                            pickInterface.PickDispatch(node.GraphPath, node.RenderState, this, camera);
                        }
                        else
                        {
                            renderObject.Dispatch(node.GraphPath, node.RenderState, this, camera);
                        }
                        Gl.glPopName();
                        PopMatrix();
                    }
                }

                index++;
            }
        }
        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 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;
                }                
            }
        }
Beispiel #22
0
        /// <summary>
        /// Transforms a sphere by the given matrix</summary>
        /// <param name="m">Matrix</param>
        /// <returns>Transformed sphere</returns>
        public Sphere3F Transform(Matrix4F m)
        {
            m.Transform(Center, out Center);

            // Calculate the scale
            float l1 = m.XAxis.Length;
            float l2 = m.YAxis.Length;
            float l3 = m.ZAxis.Length;

            float scale = l1;
            if (scale < l2)
            {
                scale = l2;
            }
            if (scale < l3)
            {
                scale = l3;
            }

            Radius *= scale;

            return this;
        }
Beispiel #23
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();
 }
Beispiel #24
0
        /// <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;
        }
Beispiel #25
0
        /// <summary>
        /// Groups the specified GameObjects</summary>
        /// <param name="gobs">GameObjects to be grouped</param>
        /// <remarks>Creates a new GameObjectGroup and moves all 
        /// the GameObjects into it.</remarks>
        public IGameObjectGroup Group(IEnumerable<IGameObject> gobs)
        {
            // extra check.
            if (!CanGroup(gobs)) return null;

            IGame game = null;
            AABB groupBox = new AABB();
            List<IGameObject> gameObjects = new List<IGameObject>();
            foreach (IGameObject gameObject in gobs)
            {
                if (game == null)
                {
                    game = gameObject.As<DomNode>().GetRoot().As<IGame>();
                }

                gameObjects.Add(gameObject);

                IBoundable boundable = gameObject.As<IBoundable>();
                groupBox.Extend(boundable.BoundingBox);                
            }

            IGameObjectGroup group = game.CreateGameObjectGroup();
            DomNode node = group.As<DomNode>();
            node.InitializeExtensions();
            ITransformable transformable = node.As<ITransformable>();
            transformable.Translation = groupBox.Center;
            
            Matrix4F invWorld = new Matrix4F();
            invWorld.Invert(transformable.Transform);

            game.RootGameObjectFolder.GameObjects.Add(group);

            foreach (IGameObject gameObject in gameObjects)
            {
                ITransformable xformable = gameObject.As<ITransformable>();
                Matrix4F world = ComputeWorldTransform(xformable);
                SetTransform(xformable, world);
                group.GameObjects.Add(gameObject);
                Vec3F trans = world.Translation;
                invWorld.Transform(ref trans);
                xformable.Translation = trans;
            }

            return group;            
        }
Beispiel #26
0
        /// <summary>
        /// Transforms the given world or local point into viewport (Windows) coordinates</summary>
        /// <param name="localPoint">World or local point to be transformed</param>
        /// <param name="localToScreen">Tranformation matrix composed of object-to-world times
        /// world-to-view times view-to-projection</param>
        /// <param name="viewportWidth">The viewport width, for example Control.Width or
        /// IRenderAction.ViewportWidth</param>
        /// <param name="viewportHeight">The viewport height, for example Control.Height or
        /// IRenderAction.ViewportHeight</param>
        /// <returns>The viewport or Window coordinate in the range [0,Width] and [0,Height]
        /// where the origin is the upper left corner of the viewport. The coordinate could be
        /// outside of this range if localPoint is not visible.</returns>
        /// <example>
        /// To calculate localToScreen using an object's local-to-world and a Camera:
        ///     localToScreen = Matrix4F.Multiply(localToWorld, camera.ViewMatrix);
        ///     localToScreen.Mul(localToScreen, camera.ProjectionMatrix);
        /// </example>
        public static Vec2F TransformToViewport(
            Vec3F localPoint,
            Matrix4F localToScreen,
            float viewportWidth,
            float viewportHeight)
        {
            // transform to clip space and do perspective divide. Result is in range of [-1, 1]
            Vec4F xScreen = new Vec4F(localPoint);
            localToScreen.Transform(xScreen, out xScreen);
            xScreen = Vec4F.Mul(xScreen, 1.0f / xScreen.W);

            // get viewport coordinates. Convert [-1, 1] to [0, view size]
            Vec2F xViewport = new Vec2F(
                (xScreen.X + 1) * 0.5f * viewportWidth,
                (1 - (xScreen.Y + 1) * 0.5f) * viewportHeight);

            return xViewport;
        }
Beispiel #27
0
        /// <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;
        }
Beispiel #28
0
        /// <summary>
        /// Transforms this frustum by the given matrix</summary>
        /// <param name="m">Transformation matrix. Can be a nearly-general transform and include non-uniform
        /// scaling and shearing.</param>
        public void Transform(Matrix4F m)
        {
            Matrix4F transposeOfInverse = new Matrix4F(m);
            transposeOfInverse.Invert(transposeOfInverse);
            transposeOfInverse.Transpose(transposeOfInverse);

            for (int i = 0; i < 6; i++)
            {
                m.Transform(m_planes[i], transposeOfInverse, out m_planes[i]);
            }
        }
Beispiel #29
0
        private DomNode CreatePrototype(IEnumerable<IGameObject> gobs)
        {
            DomNode[] originals = new DomNode[1];

            List<IGameObject> copyList = new List<IGameObject>();
            AABB bound = new AABB();
            foreach (IGameObject gameObject in SelectedGobs)
            {
                IBoundable boundable = gameObject.As<IBoundable>();
                bound.Extend(boundable.BoundingBox);
                Matrix4F world = TransformUtils.ComputeWorldTransform(gameObject);
                originals[0] = gameObject.As<DomNode>();
                DomNode[] copies = DomNode.Copy(originals);
                IGameObject copy = copies[0].As<IGameObject>();
                TransformUtils.SetTransform(copy, world);
                copyList.Add(copy);
            }

            DomNode gobchild = null;
            if (copyList.Count > 1)
            {// create group
                IGame game = m_contextRegistry.GetActiveContext<IGame>();
                IGameObjectGroup gobgroup = game.CreateGameObjectGroup();
                gobgroup.Translation = bound.Center;
                gobgroup.UpdateTransform();
                Matrix4F worldInv = new Matrix4F();
                worldInv.Invert(gobgroup.Transform);
                foreach (IGameObject gob in copyList)
                {
                    Vec3F translate = gob.Translation;
                    worldInv.Transform(ref translate);
                    gob.Translation = translate;
                    gob.UpdateTransform();
                    gobgroup.GameObjects.Add(gob);
                }
                gobchild = gobgroup.As<DomNode>();                
            }
            else
            {
                gobchild = copyList[0].As<DomNode>();                
            }

            gobchild.InitializeExtensions();
            gobchild.As<IGameObject>().Translation = new Vec3F(0, 0, 0);

            DomNode prototype = null;
            if (gobchild != null)
            {
                prototype = new DomNode(Schema.prototypeType.Type, Schema.prototypeRootElement);
                prototype.SetChild(Schema.prototypeType.gameObjectChild, gobchild);
            }
            return prototype;
        }
Beispiel #30
0
        /// <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;
        }
 protected Vector4F mul(Vector4F vector, Matrix4F transform)
 {
     return(Matrix4F.Transform(transform, vector));
     //return Vector4F.Transform(vector, transform);
 }
Beispiel #32
0
        /// <summary>
        /// unproject vector from screen space to object space.
        /// </summary>        
        public Vec3F Unproject(Vec3F scrPt, Matrix4F wvp)
        {
            float width = ClientSize.Width;
            float height = ClientSize.Height;
            Matrix4F invWVP = new Matrix4F();
            invWVP.Invert(wvp);
            Vec3F worldPt = new Vec3F();
            worldPt.X = scrPt.X / width * 2.0f - 1f;
            worldPt.Y = -(scrPt.Y / height * 2.0f - 1f);
            worldPt.Z = scrPt.Z;

            float w = worldPt.X * invWVP.M14 + worldPt.Y * invWVP.M24 + worldPt.Z * invWVP.M34 + invWVP.M44;
            invWVP.Transform(ref worldPt);
            worldPt = worldPt / w;
            return worldPt;
        }
Beispiel #33
0
        /// <summary>
        /// project the v from 3d space to viewport space
        /// using the given wvp matrix.
        /// </summary>        
        public Point Project(Matrix4F wvp, Vec3F v)
        {

            float w = v.X * wvp.M14 + v.Y * wvp.M24 + v.Z * wvp.M34 + wvp.M44;
            wvp.Transform(ref v);
            v = v / w;
            Point pt = new Point();
            pt.X = (int)((v.X + 1) * 0.5f * Width);
            pt.Y = (int)((1.0f - v.Y) * 0.5f * Height);
            return pt;
        }
        /// <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);
        }
Beispiel #35
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);
                }
            }
        }