Пример #1
0
        public static void Update(ModelViewHierarchyUpdater hierarchy, RenderModel renderModel, int slot)
        {
            var boneMatrices = staticBoneMatrices;

            var meshes = renderModel.RenderMeshesList[slot];
            {
                if (meshes == null)
                {
                    return;
                }

                foreach (var renderMesh in meshes)
                {
                    var mesh     = renderMesh.Mesh;
                    var skinning = mesh.Skinning;

                    if (skinning == null)
                    {
                        // For unskinned meshes, use the original bounding box
                        var boundingBoxExt = (BoundingBoxExt)mesh.BoundingBox;
                        boundingBoxExt.Transform(renderMesh.WorldMatrix);
                        renderMesh.BoundingBox = boundingBoxExt;

                        continue;
                    }

                    var bones = skinning.Bones;

                    // Make sure there is enough spaces in boneMatrices
                    if (boneMatrices == null || bones.Length > boneMatrices.Length)
                    {
                        staticBoneMatrices = boneMatrices = new Matrix[bones.Length];
                    }

                    var bindPoseBoundingBox = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
                    renderMesh.BoundingBox = BoundingBoxExt.Empty;

                    for (int index = 0; index < bones.Length; index++)
                    {
                        var nodeIndex = bones[index].NodeIndex;

                        // Compute bone matrix
                        Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref hierarchy.NodeTransformations[nodeIndex].WorldMatrix, out boneMatrices[index]);

                        // Calculate and extend bounding box for each bone
                        // TODO: Move runtime bounding box into ModelViewHierarchyUpdater?

                        // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                        // Compute transformed AABB (by world)
                        var boundingBoxExt = bindPoseBoundingBox;
                        boundingBoxExt.Transform(boneMatrices[index]);
                        BoundingBoxExt.Merge(ref renderMesh.BoundingBox, ref boundingBoxExt, out renderMesh.BoundingBox);
                    }

                    // Upload bones
                    renderMesh.Parameters.Set(TransformationSkinningKeys.BlendMatrixArray, boneMatrices, 0, bones.Length);
                }
            }
        }
Пример #2
0
        public static void Update(ModelViewHierarchyUpdater hierarchy, RenderModel renderModel, int slot)
        {
            var boneMatrices = staticBoneMatrices;

            var meshes = renderModel.RenderMeshesList[slot];
            {
                if (meshes == null)
                {
                    return;
                }

                foreach (var renderMesh in meshes)
                {
                    var mesh = renderMesh.Mesh;
                    var skinning = mesh.Skinning;

                    if (skinning == null)
                    {
                        // For unskinned meshes, use the original bounding box
                        var boundingBoxExt = (BoundingBoxExt)mesh.BoundingBox;
                        boundingBoxExt.Transform(renderMesh.WorldMatrix);
                        renderMesh.BoundingBox = boundingBoxExt;

                        continue;
                    }

                    var bones = skinning.Bones;

                    // Make sure there is enough spaces in boneMatrices
                    if (boneMatrices == null || bones.Length > boneMatrices.Length)
                        staticBoneMatrices = boneMatrices = new Matrix[bones.Length];

                    var bindPoseBoundingBox = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
                    renderMesh.BoundingBox = BoundingBoxExt.Empty;

                    for (int index = 0; index < bones.Length; index++)
                    {
                        var nodeIndex = bones[index].NodeIndex;

                        // Compute bone matrix
                        Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref hierarchy.NodeTransformations[nodeIndex].WorldMatrix, out boneMatrices[index]);

                        // Calculate and extend bounding box for each bone
                        // TODO: Move runtime bounding box into ModelViewHierarchyUpdater?

                        // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                        // Compute transformed AABB (by world)
                        var boundingBoxExt = bindPoseBoundingBox;
                        boundingBoxExt.Transform(boneMatrices[index]);
                        BoundingBoxExt.Merge(ref renderMesh.BoundingBox, ref boundingBoxExt, out renderMesh.BoundingBox);
                    }

                    // Upload bones
                    renderMesh.Parameters.Set(TransformationSkinningKeys.BlendMatrixArray, boneMatrices, 0, bones.Length);
                }
            }
        }
Пример #3
0
        /// <inheritdoc/>
        public override void ComputeMatrix(bool recursive, out Matrix matrix)
        {
            // If model is not in the parent, we might want to force recursive update (since parentModelComponent might not be updated yet)
            if (forceRecursive || recursive)
            {
                parentModelComponent.Entity.Transform.UpdateWorldMatrix();
            }

            // Updated? (rare slow path)
            if (parentModelComponent.ModelViewHierarchy != modelViewHierarchy)
            {
                modelViewHierarchy = parentModelComponent.ModelViewHierarchy;
                if (modelViewHierarchy == null)
                {
                    goto failed;
                }

                // Find our node index
                nodeIndex = int.MaxValue;
                for (int index = 0; index < modelViewHierarchy.Nodes.Length; index++)
                {
                    var node = modelViewHierarchy.Nodes[index];
                    if (node.Name == nodeName)
                    {
                        nodeIndex = index;
                    }
                }
            }

            var nodes = modelViewHierarchy.Nodes;
            var nodeTransformations = modelViewHierarchy.NodeTransformations;
            if (nodeIndex >= nodes.Length)
            {
                goto failed;
            }

            // Hopefully, if ref locals gets merged in roslyn, this code can be refactored
            // Compute
            matrix = nodeTransformations[nodeIndex].WorldMatrix;
            return;

        failed:
            // Fallback to TransformComponent
            matrix = parentModelComponent.Entity.Transform.WorldMatrix;
            return;
        }
Пример #4
0
        public unsafe void Update(ModelViewHierarchyUpdater hierarchy, AnimationClipResult result)
        {
            // Check if we need to regenerate "update channels" (i.e. how to copy data from result to hierarchy)
            if (updateChannels == null || // First time?...
                currentSourceChannels != result.Channels || // ... or changed?
                currentSourceChannels.Count != currentSourceChannelCount)    // .. or modified? (could only append channel)
            {
                RegenerateUpdateChannels(hierarchy, result.Channels);
                currentSourceChannels     = result.Channels;
                currentSourceChannelCount = currentSourceChannels.Count;
            }

            // Copy results to node hierarchy
            fixed(byte *structures = result.Data)
            {
                foreach (var updateChannel in updateChannels)
                {
                    var structureData = (float *)(structures + updateChannel.Offset);
                    var factor        = *structureData++;
                    if (factor == 0.0f)
                    {
                        continue;
                    }

                    switch (updateChannel.Type)
                    {
                    case ChannelType.Translation:
                        Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Translation);
                        break;

                    case ChannelType.Rotation:
                        Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Rotation);
                        break;

                    case ChannelType.Scaling:
                        Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Scaling);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }
        }
Пример #5
0
        private void RegenerateUpdateChannels(ModelViewHierarchyUpdater hierarchy, List <AnimationBlender.Channel> channels)
        {
            var newUpdateChannels = new List <UpdateChannel>();

            // TODO: Temporary implementation due to lack of time before first release.
            foreach (var channel in channels)
            {
                string nodeName = channel.NodeName;
                if (nodeName == null)
                {
                    continue;
                }

                var updateChannel = new UpdateChannel();
                updateChannel.Index = -1;

                var hierarchyNodes = hierarchy.Nodes;
                for (int i = 0; i < hierarchyNodes.Length; ++i)
                {
                    var node = hierarchyNodes[i];
                    if (node.Name == nodeName)
                    {
                        updateChannel.Index = i;
                        break;
                    }
                }

                if (updateChannel.Index == -1)
                {
                    // TODO: Warning?
                    //throw new InvalidOperationException(string.Format("Could not find matching node in animation for {0}", nodeName));
                    continue;
                }

                updateChannel.Offset = channel.Offset;
                updateChannel.Type   = channel.Type;

                newUpdateChannels.Add(updateChannel);
            }

            updateChannels = newUpdateChannels.ToArray();
        }
Пример #6
0
        public static void Update(ModelViewHierarchyUpdater hierarchy, RenderModel renderModel, int slot)
        {
            var boneMatrices = staticBoneMatrices;

            var meshes = renderModel.RenderMeshesList[slot];
            {
                if (meshes == null)
                {
                    return;
                }

                foreach (var renderMesh in meshes)
                {
                    var mesh     = renderMesh.Mesh;
                    var skinning = mesh.Skinning;
                    if (skinning == null)
                    {
                        continue;
                    }

                    var bones = skinning.Bones;

                    // Make sure there is enough spaces in boneMatrices
                    if (boneMatrices == null || bones.Length > boneMatrices.Length)
                    {
                        staticBoneMatrices = boneMatrices = new Matrix[bones.Length];
                    }

                    for (int index = 0; index < bones.Length; index++)
                    {
                        var nodeIndex = bones[index].NodeIndex;

                        // Compute bone matrix
                        Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref hierarchy.NodeTransformations[nodeIndex].WorldMatrix, out boneMatrices[index]);
                    }

                    // Upload bones
                    renderMesh.Parameters.Set(TransformationSkinningKeys.BlendMatrixArray, boneMatrices, 0, bones.Length);
                }
            }
        }
Пример #7
0
        private void RegenerateUpdateChannels(ModelViewHierarchyUpdater hierarchy, List<AnimationBlender.Channel> channels)
        {
            var newUpdateChannels = new List<UpdateChannel>();

            // TODO: Temporary implementation due to lack of time before first release.
            foreach (var channel in channels)
            {
                string nodeName = channel.NodeName;
                if (nodeName == null)
                    continue;

                var updateChannel = new UpdateChannel();
                updateChannel.Index = -1;

                var hierarchyNodes = hierarchy.Nodes;
                for (int i = 0; i < hierarchyNodes.Length; ++i)
                {
                    var node = hierarchyNodes[i];
                    if (node.Name == nodeName)
                    {
                        updateChannel.Index = i;
                        break;
                    }
                }

                if (updateChannel.Index == -1)
                {
                    // TODO: Warning?
                    //throw new InvalidOperationException(string.Format("Could not find matching node in animation for {0}", nodeName));
                    continue;
                }

                updateChannel.Offset = channel.Offset;
                updateChannel.Type = channel.Type;

                newUpdateChannels.Add(updateChannel);
            }

            updateChannels = newUpdateChannels.ToArray();
        }
Пример #8
0
        public unsafe void Update(ModelViewHierarchyUpdater hierarchy, AnimationClipResult result)
        {
            // Check if we need to regenerate "update channels" (i.e. how to copy data from result to hierarchy)
            if (updateChannels == null // First time?...
                || currentSourceChannels != result.Channels // ... or changed?
                || currentSourceChannels.Count != currentSourceChannelCount) // .. or modified? (could only append channel)
            {
                RegenerateUpdateChannels(hierarchy, result.Channels);
                currentSourceChannels = result.Channels;
                currentSourceChannelCount = currentSourceChannels.Count;
            }

            // Copy results to node hierarchy
            fixed (byte* structures = result.Data)
            {
                foreach (var updateChannel in updateChannels)
                {
                    var structureData = (float*)(structures + updateChannel.Offset);
                    var factor = *structureData++;
                    if (factor == 0.0f)
                        continue;

                    switch (updateChannel.Type)
                    {
                        case ChannelType.Translation:
                            Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Translation);
                            break;
                        case ChannelType.Rotation:
                            Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Rotation);
                            break;
                        case ChannelType.Scaling:
                            Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Scaling);
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }
            }
        }
Пример #9
0
        public static void Update(ModelViewHierarchyUpdater hierarchy, RenderModel renderModel, int slot)
        {
            var boneMatrices = staticBoneMatrices;

            var meshes = renderModel.RenderMeshesList[slot];
            {
                if (meshes == null)
                {
                    return;
                }

                foreach (var renderMesh in meshes)
                {
                    var mesh = renderMesh.Mesh;
                    var skinning = mesh.Skinning;
                    if (skinning == null)
                        continue;

                    var bones = skinning.Bones;

                    // Make sure there is enough spaces in boneMatrices
                    if (boneMatrices == null || bones.Length > boneMatrices.Length)
                        staticBoneMatrices = boneMatrices = new Matrix[bones.Length];

                    for (int index = 0; index < bones.Length; index++)
                    {
                        var nodeIndex = bones[index].NodeIndex;

                        // Compute bone matrix
                        Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref hierarchy.NodeTransformations[nodeIndex].WorldMatrix, out boneMatrices[index]);
                    }

                    // Upload bones
                    renderMesh.Parameters.Set(TransformationSkinningKeys.BlendMatrixArray, boneMatrices, 0, bones.Length);
                }
            }
        }
Пример #10
0
 private void ModelUpdated()
 {
     if (model != null)
     {
         if (modelViewHierarchy != null)
         {
             // Reuse previous ModelViewHierarchy
             modelViewHierarchy.Initialize(model);
         }
         else
         {
             modelViewHierarchy = new ModelViewHierarchyUpdater(model);
         }
     }
 }