예제 #1
0
        public override void Render(ViewControl vc)
        {
            Matrix4F normWorld = GetManipulatorMatrix();

            if (normWorld == null)
            {
                return;
            }

            Camera camera = vc.Camera;
            float  s;

            Util.CalcAxisLengths(camera, normWorld.Translation, out s);
            m_translatorControl.Render(normWorld, s);

            Matrix4F sc  = new Matrix4F();
            Vec3F    pos = normWorld.Translation;

            s /= 12.0f;
            sc.Scale(s);

            Matrix4F bl = new Matrix4F();

            Util.CreateBillboard(bl, pos, camera.WorldEye, camera.Up, camera.LookAt);

            Matrix4F recXform = new Matrix4F();

            Matrix4F.Multiply(sc, bl, recXform);

            Util3D.DrawPivot(recXform, Color.Yellow);
        }
예제 #2
0
        public override void Render(DeviceContext graphics, ref Matrix4F matrix, Vector3D renderOrigin, Entity entity,
                                    AvatarController avatarController, Timestep renderTimestep, RenderMode renderMode)
        {
            if (entity.Logic is BorderEntityLogic borderLogic)
            {
                if (!ClientContext.PlayerFacade.IsLocalPlayer(borderLogic.Owner))
                {
                    return;
                }

                var cube = borderLogic.Cube;

                if (cube != null)
                {
                    var boxMatrix = Matrix.CreateFromYawPitchRoll(0, 0, 0).ToMatrix4F();

                    var boxMatrix1 = Matrix4F.Multiply(
                        boxMatrix.Translate((cube.OrigStart.ToVector3F() - renderOrigin.ToVector3F()) +
                                            borderLogic.Selection1.Components.Get <TileEntityComponent>().TileOffset),
                        matrix);

                    borderLogic.Selection1.Icon.Matrix()
                    .Scale(borderLogic.Selection1.Components.Get <TileEntityComponent>().Scale)
                    .Render(graphics, ref boxMatrix1);

                    var boxMatrix2 = Matrix4F.Multiply(boxMatrix.Translate(
                                                           (cube.OrigEnd.ToVector3F() - renderOrigin.ToVector3F()) + borderLogic.Selection2.Components
                                                           .Get <TileEntityComponent>().TileOffset), matrix);

                    borderLogic.Selection2.Icon.Matrix().Scale(borderLogic.Selection2.Components.Get <TileEntityComponent>().Scale).Render(graphics, ref boxMatrix2);
                }
            }
        }
        /// <summary>
        /// Render the item icons
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="matrix"></param>
        /// <param name="renderOrigin"></param>
        /// <param name="avatar"></param>
        /// <param name="avatarPainter"></param>
        /// <param name="universe"></param>
        public void DrawItemVoxels(DeviceContext graphics, Matrix4F matrix, Entity avatar)
        {
            if (!this.IsShowing)
            {
                return;
            }

            graphics.PushRenderState();
            Matrix4F projectionMatrix = graphics.GetProjectionMatrix();
            Matrix4F overlayMatrix    = graphics.GetOverlayMatrix();

            graphics.PushShader();
            graphics.SetShader(graphics.GetShader("VoxelOverlayStipple"));

            double rotation    = ClientContext.OverlayController.IsMenuOpen() ? 0 : (DateTime.UtcNow - new DateTime(0L)).TotalMilliseconds * 0.001 % 6.2831853071795862;
            int    activeIndex = avatar.Inventory.ActiveItemIndex();

            for (int i = 0; i < 10; i++)
            {
                ItemStack item = avatar.Inventory.GetHotbarItem(i);
                if (item.Item != Item.NullItem)
                {
                    Vector2F p = HotbarManager.Instance.Controller.GetSlotPosition(i);
                    p *= Constants.UIZoomFactor;

                    Vector2F pp           = graphics.ScreenPosToProjectionPos(p);
                    Matrix4F movedMatrix2 = Matrix4F.CreateTranslation(new Vector3F(pp.X, pp.Y, 0f));
                    movedMatrix2 = Matrix4F.Multiply(overlayMatrix, movedMatrix2);
                    graphics.SetProjectionMatrix(movedMatrix2);

                    Vector2I viewPortSize = graphics.GetViewPortSize();
                    float    itemScale    = Constants.ItemRenderingScale;
                    itemScale *= Constants.UIZoomFactor / ((float)viewPortSize.Y / Constants.ViewPortScaleThreshold.Y);

                    if (i == activeIndex)
                    {
                        graphics.SetShader(graphics.GetShader("VoxelOverlay"));
                    }

                    ClientContext.ItemRendererManager.RenderIcon(item.Item, graphics, Matrix4F.CreateScale(itemScale).Rotate((float)rotation, Vector3F.Up).Rotate(-0.35f, Vector3F.Left)
                                                                 .Translate(new Vector3F(0f, 0f, -0.2f))
                                                                 .Multiply(matrix));

                    if (i == activeIndex)
                    {
                        graphics.SetShader(graphics.GetShader("VoxelOverlayStipple"));
                    }
                }
            }

            graphics.PopShader();
            graphics.SetProjectionMatrix(projectionMatrix);
            graphics.PopRenderState();
        }
예제 #4
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;
        }
예제 #5
0
        public override void Render(DeviceContext graphics, ref Matrix4F matrix, Vector3D renderOrigin, Entity entity,
                                    AvatarController avatarController, Timestep renderTimestep, RenderMode renderMode)
        {
            if (!_botTileCode.IsNullOrEmpty())
            {
                if (entity.Logic is BotEntityLogic logic)
                {
                    var pos = entity.Physics.Position.ToVector3F();
                    if (pos.Y + _add >= pos.Y + 0.125)
                    {
                        _up = false;
                    }

                    if (pos.Y + _add <= pos.Y + 0)
                    {
                        _up = true;
                    }

                    _add   = _up ? _add + 0.0015F : _add - 0.0015F;
                    pos.Y += _add;

                    var botMatrix = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(logic.Rotation), 0, 0).ToMatrix4F();

                    botMatrix = Matrix4F.Multiply(botMatrix.Translate(pos.X - (float)renderOrigin.X, pos.Y - (float)renderOrigin.Y, pos.Z - (float)renderOrigin.Z), matrix);

                    _bot.Render(graphics, ref botMatrix);

                    var bladeMatrix = Matrix
                                      .CreateFromYawPitchRoll(
                        (float)((DateTime.UtcNow - _created).TotalMilliseconds * 0.003 % (2 * Math.PI)), 0, 0)
                                      .ToMatrix4F();

                    for (var i = 0; i < logic.BotComponent.BladeLocations.Count; i++)
                    {
                        var currentPosition    = pos + logic.BotComponent.BladeLocations[i].Item1.ToVector3F();
                        var currentBladeMatrix = Matrix4F.Multiply(bladeMatrix.Translate(
                                                                       currentPosition.X - (float)renderOrigin.X, currentPosition.Y - (float)renderOrigin.Y,
                                                                       currentPosition.Z - (float)renderOrigin.Z), matrix);

                        _bladeTile.Configuration.Icon.Matrix().Scale(logic.BotComponent.BladeLocations[i].Item2).Render(graphics, ref currentBladeMatrix);
                    }
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Ungroups the specified gameobjects.</summary>
        public IEnumerable <ITransformable> Ungroup(IEnumerable <object> gobs)
        {
            if (!CanUngroup(gobs))
            {
                return(EmptyArray <ITransformable> .Instance);
            }

            List <ITransformable> ungrouplist = new List <ITransformable>();

            foreach (var group in gobs.AsIEnumerable <ITransformableGroup>())
            {
                // try to move the children into the parent of the group
                var node = group.As <DomNode>();
                if (node == null)
                {
                    continue;
                }
                var insertParent = node.Lineage.Skip(1).AsIEnumerable <IHierarchical>().FirstOrDefault();
                if (insertParent == null)
                {
                    continue;
                }

                var groupTransform = group.Transform;
                var objects        = new List <ITransformable>(group.Objects); // (copy, because we'll remove as we go through)
                foreach (var child in objects)
                {
                    if (insertParent.AddChild(child))
                    {
                        child.Transform = Matrix4F.Multiply(child.Transform, groupTransform);
                        ungrouplist.Add(child);
                    }
                }

                if (group.Objects.Count == 0)
                {
                    group.Cast <DomNode>().RemoveFromParent();
                }
            }
            return(ungrouplist);
        }
예제 #7
0
        /// <summary>
        /// Traverses the specified graph path</summary>
        /// <param name="graphPath">The graph path</param>
        /// <param name="action">The render action</param>
        /// <param name="camera">The camera</param>
        /// <param name="list">The list</param>
        /// <returns></returns>
        public override TraverseState Traverse(Stack <SceneNode> graphPath, IRenderAction action, Camera camera, ICollection <TraverseNode> list)
        {
            // Get the "top matrix" before we push a new matrix on to it, just in case we need
            //  it for the bounding box test.
            Matrix4F parentToWorld = action.TopMatrix;

            // Push matrix onto the matrix stack even if we're not visible because this class
            //  implements the marker interface ISetsLocalTransform.
            action.PushMatrix(m_node.Transform, true);

            // If node is invisible then cull
            if (!m_node.Visible)
            {
                return(TraverseState.Cull);
            }

            TraverseState dResult = action.TraverseState;

            if (dResult == TraverseState.None)
            {
                // Test if bounding sphere is contained in frustum
                if (s_enableVFCull)
                {
                    // Construct bounding box
                    Box box = new Box();
                    box.Extend(m_node.BoundingBox);

                    // Transform the bounding box into view space
                    Matrix4F localToView = Matrix4F.Multiply(parentToWorld, camera.ViewMatrix);
                    box.Transform(localToView);

                    if (!camera.Frustum.Contains(box))
                    {
                        dResult = TraverseState.Cull;
                    }
                }
            }
            return(dResult);
        }
예제 #8
0
        public override void Render(ViewControl vc)
        {
            BasicRendererFlags solid = BasicRendererFlags.Solid
                                       | BasicRendererFlags.DisableDepthTest;
            BasicRendererFlags wire = BasicRendererFlags.WireFrame
                                      | BasicRendererFlags.DisableDepthTest;


            Matrix4F normWorld = GetManipulatorMatrix();

            if (normWorld == null)
            {
                return;
            }

            Camera camera = vc.Camera;
            Vec3F  pos    = normWorld.Translation;
            float  s;

            Util.CalcAxisLengths(vc.Camera, pos, out s);

            Vec3F sv      = new Vec3F(s, s, s);
            Vec3F axscale = new Vec3F(Math.Abs(s * m_scale.X), Math.Abs(s * m_scale.Y), Math.Abs(s * m_scale.Z));

            Color xcolor   = (m_hitRegion == HitRegion.XAxis || m_hitRegion == HitRegion.FreeRect) ? Color.Gold : Color.Red;
            Color ycolor   = (m_hitRegion == HitRegion.YAxis || m_hitRegion == HitRegion.FreeRect) ? Color.Gold : Color.Green;
            Color Zcolor   = (m_hitRegion == HitRegion.ZAxis || m_hitRegion == HitRegion.FreeRect) ? Color.Gold : Color.Blue;
            Color freeRect = (m_hitRegion == HitRegion.FreeRect) ? Color.Gold : Color.White;


            Matrix4F scale = new Matrix4F();

            scale.Scale(axscale);
            Matrix4F xform = scale * normWorld;

            Util3D.RenderFlag = wire;
            Util3D.DrawX(xform, xcolor);
            Util3D.DrawY(xform, ycolor);
            Util3D.DrawZ(xform, Zcolor);

            Vec3F rectScale = sv * FreeRectRatio;

            scale.Scale(rectScale);
            Matrix4F b        = Util.CreateBillboard(pos, camera.WorldEye, camera.Up, camera.LookAt);
            Matrix4F recXform = Matrix4F.Multiply(scale, b);

            Util3D.DrawRect(recXform, freeRect);

            Vec3F handle      = sv * HandleRatio;
            float handleWidth = handle.X / 2;

            scale.Scale(handle);
            Matrix4F trans = new Matrix4F();

            trans.Translation = new Vec3F(axscale.X - handleWidth, 0, 0);
            xform             = scale * trans * normWorld;

            Util3D.RenderFlag = solid;

            Util3D.DrawCube(xform, xcolor);

            trans.Translation = new Vec3F(0, axscale.Y - handleWidth, 0);
            xform             = scale * trans * normWorld;
            Util3D.DrawCube(xform, ycolor);

            trans.Translation = new Vec3F(0, 0, axscale.Z - handleWidth);
            xform             = scale * trans * normWorld;
            Util3D.DrawCube(xform, Zcolor);
        }
예제 #9
0
        public void Render(Camera cam)
        {
            GameEngine.SetRendererFlag(BasicRendererFlags.WireFrame);
            IGrid grid = this.As <IGrid>();

            if (grid.Visible == false)
            {
                return;
            }

            float s = grid.Size;

            Matrix4F scale = new Matrix4F();

            scale.Scale(new Vec3F(s, s, s));

            Matrix4F gridXform = new Matrix4F();

            if (cam.Frustum.IsOrtho)
            {
                float     dist = cam.ViewMatrix.Translation.Z;
                ViewTypes vt   = cam.ViewType;
                if (vt == ViewTypes.Top)
                {
                    gridXform.Translation
                        = new Vec3F(0, dist, 0);
                }
                else if (vt == ViewTypes.Bottom)
                {
                    gridXform.Translation
                        = new Vec3F(0, -dist, 0);
                }
                else if (vt == ViewTypes.Right)
                {
                    gridXform.RotZ(MathHelper.PiOver2);
                    gridXform.Translation
                        = new Vec3F(dist, 0, 0);
                }
                else if (vt == ViewTypes.Left)
                {
                    gridXform.RotZ(MathHelper.PiOver2);
                    gridXform.Translation
                        = new Vec3F(-dist, 0, 0);
                }
                else if (vt == ViewTypes.Front)
                {
                    gridXform.RotX(MathHelper.PiOver2);
                    gridXform.Translation
                        = new Vec3F(0, 0, dist);
                }
                else if (vt == ViewTypes.Back)
                {
                    gridXform.RotX(MathHelper.PiOver2);
                    gridXform.Translation
                        = new Vec3F(0, 0, -dist);
                }
                gridXform.Mul(scale, gridXform);
            }
            else
            {
                Matrix4F trans = new Matrix4F();
                trans.Translation = new Vec3F(0, grid.Height, 0);
                gridXform         = Matrix4F.Multiply(scale, trans);
            }

            GameEngine.DrawPrimitive(PrimitiveType.LineList, m_gridVBId, 0, m_gridVertexCount, Color.LightGray,
                                     gridXform);
        }
예제 #10
0
        private void RenderProperties(IEnumerable <object> objects, bool renderCaption, bool renderBound, bool renderPivot)
        {
            bool renderAny = renderCaption || renderBound || renderPivot;

            if (renderAny == false)
            {
                return;
            }

            Util3D.RenderFlag = BasicRendererFlags.WireFrame;
            Matrix4F vp = Camera.ViewMatrix * Camera.ProjectionMatrix;

            foreach (object obj in objects)
            {
                IBoundable bnode = obj.As <IBoundable>();
                if (bnode == null || bnode.BoundingBox.IsEmpty || obj.Is <IGameObjectFolder>())
                {
                    continue;
                }

                INameable      nnode = obj.As <INameable>();
                ITransformable trans = obj.As <ITransformable>();

                if (renderBound)
                {
                    Util3D.DrawAABB(bnode.BoundingBox);
                }
                if (renderCaption && nnode != null)
                {
                    Vec3F topCenter = bnode.BoundingBox.Center;
                    topCenter.Y = bnode.BoundingBox.Max.Y;
                    Point pt = Project(vp, topCenter);
                    GameEngine.DrawText2D(nnode.Name, Util3D.CaptionFont, pt.X, pt.Y, Color.White);
                }
            }

            if (renderPivot)
            {
                Util3D.RenderFlag = BasicRendererFlags.WireFrame
                                    | BasicRendererFlags.DisableDepthTest;

                // create few temp matrics to
                Matrix4F toWorld  = new Matrix4F();
                Matrix4F PV       = new Matrix4F();
                Matrix4F sc       = new Matrix4F();
                Matrix4F bl       = new Matrix4F();
                Matrix4F recXform = new Matrix4F();
                foreach (object obj in objects)
                {
                    ITransformable trans = obj.As <ITransformable>();
                    IBoundable     bnode = obj.As <IBoundable>();
                    if (trans == null || bnode == null || bnode.BoundingBox.IsEmpty || obj.Is <IGameObjectFolder>())
                    {
                        continue;
                    }

                    Path <DomNode> path = new Path <DomNode>(trans.Cast <DomNode>().GetPath());
                    toWorld.Set(Vec3F.ZeroVector);
                    TransformUtils.CalcPathTransform(toWorld, path, path.Count - 1);

                    // Offset by pivot
                    PV.Set(trans.Pivot);
                    toWorld.Mul(PV, toWorld);
                    Vec3F pos = toWorld.Translation;

                    float s;
                    Util.CalcAxisLengths(Camera, pos, out s);
                    s /= 12.0f;
                    sc.Scale(s);
                    Util.CreateBillboard(bl, pos, Camera.WorldEye, Camera.Up, Camera.LookAt);

                    Matrix4F.Multiply(sc, bl, recXform);

                    Util3D.DrawPivot(recXform, Color.Yellow);
                }
            }
        }
예제 #11
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 ITransformableGroup Group(IEnumerable <object> gobs)
        {
            // extra check.
            if (!CanGroup(gobs))
            {
                return(null);
            }

            IGameObjectFolder root = null;
            var gameObjects        = new List <ITransformable>();

            foreach (var gameObject in gobs)
            {
                ITransformable trans = gameObject.As <ITransformable>();
                if (trans == null)
                {
                    continue;
                }
                var node = gameObject.As <DomNode>();
                if (node == null)
                {
                    continue;
                }

                gameObjects.Add(trans);
                var root1 = GetObjectFolder(node);
                if (root != null && root != root1)
                {
                    return(null);
                }
                root = root1;
            }

            // sort from shallowest in the tree to deepest. Then remove any nodes that
            // are already children of other nodes in the list
            gameObjects.Sort(
                (lhs, rhs) => { return(lhs.As <DomNode>().Lineage.Count().CompareTo(rhs.As <DomNode>().Lineage.Count())); });

            // awkward iteration here... Maybe there's a better way to traverse this list..?
            for (int c = 0; c < gameObjects.Count;)
            {
                var  n      = gameObjects[c].As <DomNode>();
                bool remove = false;
                for (int c2 = 0; c2 < c; ++c2)
                {
                    if (n.IsDescendantOf(gameObjects[c2].As <DomNode>()))
                    {
                        remove = true;
                        break;
                    }
                }

                if (remove)
                {
                    gameObjects.RemoveAt(c);
                }
                else
                {
                    ++c;
                }
            }

            // finally, we must have at least 2 valid objects to perform the grouping operation
            if (gameObjects.Count < 2)
            {
                return(null);
            }

            AABB groupBox = new AABB();

            foreach (var gameObject in gameObjects.AsIEnumerable <IBoundable>())
            {
                groupBox.Extend(gameObject.BoundingBox);
            }

            var group = root.CreateGroup();

            if (group == null)
            {
                return(null);
            }

            group.As <DomNode>().InitializeExtensions();

            // try to add the group to the parent of the shallowest item
            var  groupParent        = gameObjects[0].As <DomNode>().Parent.AsAll <IHierarchical>();
            bool addedToGroupParent = false;

            foreach (var h in groupParent)
            {
                if (h.AddChild(group))
                {
                    addedToGroupParent = true; break;
                }
            }
            if (!addedToGroupParent)
            {
                return(null);
            }

            // arrange the transform for the group so that it's origin is in the center of the objects
            var groupParentTransform = new Matrix4F();

            if (groupParent.Is <ITransformable>())
            {
                groupParentTransform = groupParent.As <ITransformable>().LocalToWorld;
            }

            Matrix4F invgroupParentTransform = new Matrix4F();

            invgroupParentTransform.Invert(groupParentTransform);
            group.Transform = Matrix4F.Multiply(new Matrix4F(groupBox.Center), invgroupParentTransform);

            Matrix4F invWorld = new Matrix4F();

            invWorld.Invert(group.Transform);

            // now try to actually add the objects to the group
            var hier = group.AsAll <IHierarchical>();

            foreach (var gameObject in gameObjects)
            {
                Matrix4F oldWorld = gameObject.LocalToWorld;

                bool addedToGroup = false;
                foreach (var h in hier)
                {
                    if (h.AddChild(gameObject))
                    {
                        addedToGroup = true;  break;
                    }
                }

                if (addedToGroup)
                {
                    gameObject.Transform = Matrix4F.Multiply(oldWorld, invWorld);
                }
            }

            return(group);
        }
예제 #12
0
        void Update(Component_Skeleton skeleton, Component_SkeletonAnimationTrack animationTrack, double time)
        {
            if (time != calculatedForTime)
            {
                //update general data
                calculatedForTime = time;
                bones             = skeleton.GetBones();

                //calculate bone transforms
                if (boneTransforms == null || boneTransforms.Length != bones.Length)
                {
                    boneTransforms = new Component_SkeletonAnimationTrack.CalculateBoneTransformsItem[bones.Length];
                }
                animationTrack?.CalculateBoneTransforms(time, boneTransforms);
                CalculateBoneTransforms?.Invoke(this, boneTransforms);

                //calculate transformMatrixRelativeToSkin, transformRelativeToSkin, boneGlobalTransforms, hasScale

                if (transformMatrixRelativeToSkin == null || transformMatrixRelativeToSkin.Length != bones.Length)
                {
                    transformMatrixRelativeToSkin = new Matrix4F[bones.Length];
                }

                if (transformRelativeToSkin == null || transformRelativeToSkin.Length != bones.Length)
                {
                    transformRelativeToSkin = new Component_SkeletonAnimationTrack.CalculateBoneTransformsItem[bones.Length];
                }

                if (boneGlobalTransforms == null || boneGlobalTransforms.Length != bones.Length)
                {
                    boneGlobalTransforms = new BoneGlobalTransformItem[bones.Length];
                }
                var matrixZero = Matrix4F.Zero;
                for (int i = 0; i < bones.Length; i++)
                {
                    boneGlobalTransforms[i] = new BoneGlobalTransformItem(false, ref matrixZero);
                }

                foreach (var b in bones)
                {
                    GetBoneGlobalTransformRecursive(skeleton, b);
                }

                hasScale = false;

                for (int i = 0; i < bones.Length; i++)
                {
                    var bone = bones[i];

                    Matrix4F m;
                    if (bone != null)
                    {
                        Matrix4F.Multiply(ref GetBoneGlobalTransformRecursive(skeleton, bone), ref bone.GetTransformMatrixInverse(), out m);
                    }
                    else
                    {
                        m = Matrix4F.Identity;
                    }
                    transformMatrixRelativeToSkin[i] = m;

                    m.Decompose(out Vector3F t, out QuaternionF r, out Vector3F s);

                    transformRelativeToSkin[i] = new Component_SkeletonAnimationTrack.CalculateBoneTransformsItem {
                        Position = t, Rotation = r, Scale = s
                    };

                    //if the scale differs from 1.0 more than this value, then the scaling is present and DualQuaternionSkinning can not be used.
                    const float EpsilonForScale = 1e-3f;
                    if (Math.Abs(1.0f - s.X) > EpsilonForScale || Math.Abs(1.0f - s.Y) > EpsilonForScale || Math.Abs(1.0f - s.Y) > EpsilonForScale)
                    {
                        hasScale = true;
                    }
                }
            }
        }
예제 #13
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;
        }
예제 #14
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++;
            }
        }