Example #1
0
        public Boolean ProcessRefSkeletonFromAssetContext(H1SkeletalContext.JointNode node, ref H1ReferenceSkeleton refSkeleton)
        {
            H1SkeletalContext.Joint jointData = null; // node.JointData;

            // add mesh bone info
            H1MeshBoneInfo meshBoneInfo = new H1MeshBoneInfo();

            //meshBoneInfo.Name = jointData.JointName;

            if (refSkeleton.NameToIndexMapIsEmpty())
            {
                // should be root node, so parent index is '0'
                meshBoneInfo.ParentIndex = 0;
            }
            else if (node.Parent == null)
            {
                // should be sub-root node, so parent index is '0' (root motion node)
                meshBoneInfo.ParentIndex = refSkeleton.GetIndexByBoneName("RootMotionNode");
            }
            else
            //meshBoneInfo.ParentIndex = refSkeleton.GetIndexByBoneName(node.Parent.JointData.JointName);

            if (meshBoneInfo.ParentIndex == -1)
            {
                return(false);
            }

            // the new index should be same with RefBoneBases
            Int32 newBoneInfoIndex = refSkeleton.RefBoneInfoList.Count;
            Int32 newBoneBaseIndex = refSkeleton.RefBoneBases.Count;

            if (newBoneBaseIndex != newBoneInfoIndex)
            {
                return(false);
            }

            refSkeleton.RefBoneInfoList.Add(meshBoneInfo);

            // add bone base
            H1Transform boneBase = new H1Transform();

            boneBase.Translation = jointData.OffsetTransformation.Translation;
            boneBase.Scaling     = jointData.OffsetTransformation.Scaling;
            boneBase.Rotation    = jointData.OffsetTransformation.Rotation;

            refSkeleton.RefBoneBases.Add(boneBase);

            // add NameToIndex
            refSkeleton.AddNameToIndexPair(meshBoneInfo.Name, newBoneInfoIndex);

            return(true);
        }
Example #2
0
        // @TODO - change this delivering directly command list from the renderer after implementing overall rendering system
        public void SkeletonDebugDrawing(SharpDX.Direct3D12.GraphicsCommandList commandList, Boolean bDebugDraw = true)
        {
            // @TODO - temporary to check if animation is working
            H1SkeletalMeshComponent skeletalMeshComponent = H1Global <H1World> .Instance.PersistentLevel.GetActor(0).GetActorComponent <H1SkeletalMeshComponent>();

            List <H1AnimInstance.InterpolatedLocalTransform> interpolatedLocalTransforms = new List <H1AnimInstance.InterpolatedLocalTransform>();

            for (Int32 boneIndex = 0; boneIndex < m_Skeleton.RefSkeleton.RefBoneInfoList.Count; ++boneIndex)
            {
                H1AnimInstance.InterpolatedLocalTransform interpolatedLocalTransform = new H1AnimInstance.InterpolatedLocalTransform();
                H1MeshBoneInfo meshBoneInfo = m_Skeleton.RefSkeleton.RefBoneInfoList[boneIndex];

                interpolatedLocalTransform.BoneName       = meshBoneInfo.Name;
                interpolatedLocalTransform.LocalTransform = m_Skeleton.RefSkeleton.RefBoneBases[boneIndex];

                interpolatedLocalTransforms.Add(interpolatedLocalTransform);
            }

            // extract interpolated local transforms
            skeletalMeshComponent.AnimScriptInstance.ExtractInterpolatedLocalTransform(0.0f, ref interpolatedLocalTransforms);

            H1Transform[] globalTransforms = new H1Transform[m_Skeleton.RefSkeleton.RefBoneBases.Count];
            // tracking only upper parent index by one
            Int32[] transformParentIndices = new Int32[m_Skeleton.RefSkeleton.RefBoneBases.Count];

            for (Int32 boneIndex = 0; boneIndex < m_Skeleton.RefSkeleton.RefBoneInfoList.Count; ++boneIndex)
            {
                H1MeshBoneInfo meshBoneInfo = m_Skeleton.RefSkeleton.RefBoneInfoList[boneIndex];

                //H1Transform localTransform = m_Skeleton.RefSkeleton.RefBoneBases[boneIndex];
                H1Transform localTransform = interpolatedLocalTransforms[boneIndex].LocalTransform;

                // extract parent locals
                List <H1Transform> parentLocalTransforms = new List <H1Transform>();
                H1MeshBoneInfo     currMeshBoneInfo      = meshBoneInfo;
                while (currMeshBoneInfo.ParentIndex != -1)
                {
                    //parentLocalTransforms.Add(m_Skeleton.RefSkeleton.RefBoneBases[currMeshBoneInfo.ParentIndex]);
                    parentLocalTransforms.Add(interpolatedLocalTransforms[currMeshBoneInfo.ParentIndex].LocalTransform);
                    currMeshBoneInfo = m_Skeleton.RefSkeleton.RefBoneInfoList[currMeshBoneInfo.ParentIndex];
                }

                // generate global transform for current bone space
                // 1. start to transform current local transformation matrix
                Matrix globalTransformMtx = localTransform.Transformation;
                // 2. from curr bone space to root space by going up to each parent node space
                for (Int32 index = 0; index < parentLocalTransforms.Count; ++index)
                {
                    Matrix parentLocalTransformMtx = parentLocalTransforms[index].Transformation;
                    globalTransformMtx = Matrix.Multiply(globalTransformMtx, parentLocalTransformMtx);
                }

                // decompose global matrix and generate H1Transform
                Vector3    translation;
                Vector3    scale;
                Quaternion rotate;
                globalTransformMtx.Decompose(out scale, out rotate, out translation);

                H1Transform globalTransform = new H1Transform();
                globalTransform.Translation = translation;
                globalTransform.Scaling     = scale;
                globalTransform.Rotation    = rotate;

                globalTransforms[boneIndex]       = globalTransform;
                transformParentIndices[boneIndex] = meshBoneInfo.ParentIndex;
            }

            // set bone matrices
            Int32 currGlobalBoneIndex = 0;

            foreach (H1Transform boneTransform in globalTransforms)
            {
                // @TODO - temporary scaling to match when we importing vertices in H1AssimpImporter
                //boneTransform.Scaling = boneTransform.Scaling * 0.01f;

                // get global offset matrices
                Matrix globalOffsetMatrix = m_Skeleton.RefSkeleton.RefOffsetBases[currGlobalBoneIndex].Transformation;

                // pass multiplied global offset matrices and animated global matrices
                H1Global <H1ManagedRenderer> .Instance.SetBoneMatrix(currGlobalBoneIndex, Matrix.Multiply(globalOffsetMatrix, boneTransform.Transformation));

                currGlobalBoneIndex++;
            }

            // when debug draw is enabled
            if (bDebugDraw == true)
            {
                for (Int32 boneIndex = 0; boneIndex < globalTransforms.Count(); ++boneIndex)
                {
                    Int32 parentIndex = transformParentIndices[boneIndex];
                    if (parentIndex < 0)
                    {
                        continue;
                    }

                    H1Transform parentBoneTransform = globalTransforms[parentIndex];
                    H1Transform boneTransform       = globalTransforms[boneIndex];

                    Vector3 parentLoc = parentBoneTransform.Translation * 0.005f;
                    Vector3 currLoc   = boneTransform.Translation * 0.005f;

                    float length = (currLoc - parentLoc).Length();
                    if (length < 0.001f)
                    {
                        continue;
                    }

                    Vector3 zAxis = Vector3.Normalize(currLoc - parentLoc);

                    Matrix  pitchMtx     = Matrix.RotationYawPitchRoll(0, 0.1f, 0);
                    Vector4 rotatedZAxis = Vector3.Transform(zAxis, pitchMtx);
                    rotatedZAxis /= rotatedZAxis.W;

                    Vector3 yAxis = Vector3.Normalize(Vector3.Cross(zAxis, Vector3.Normalize(new Vector3(rotatedZAxis.X, rotatedZAxis.Y, rotatedZAxis.Z))));
                    Vector3 xAxis = Vector3.Normalize(Vector3.Cross(zAxis, yAxis));

                    //H1RenderUtils.DrawCapsule(commandList, parentLoc, xAxis, yAxis, zAxis, 0.03f, length / 2.0f, 16);
                    H1RenderUtils.DrawDashedLine(commandList, parentLoc, currLoc, 2.0f);
                    //H1RenderUtils.DrawWireStar(commandList, currLoc, 0.03f);
                }
            }
        }
Example #3
0
        public H1StaticLODModel PrepareProcessAssetContext(H1SkeletalContext skeletalContext)
        {
            if (m_SkeletalMeshResource == null)
            {
                return(null);
            }

            // @TODO - temporary low LOD model, fix this
            H1StaticLODModel staticLODModel = m_SkeletalMeshResource.AddLODModel();

            // add root node that controls all animation motion
            H1ReferenceSkeleton refSkeleton = m_Skeleton.RefSkeleton;

            // construct refSkeleton
            List <H1SkeletalContext.JointNode> jointNodes = skeletalContext.JointNodes;

            // to construct local transforms for each bone
            List <BoneOffsetTransformSet> boneOffsetTransforms = new List <BoneOffsetTransformSet>();

            foreach (H1SkeletalContext.JointNode jointNode in jointNodes)
            {
                // if is not marked as bone node space, skip
                if (!jointNode.MarkedAsBoneSpace)
                {
                    continue;
                }

                // prepare data to process bone node
                H1MeshBoneInfo meshBoneInfo = new H1MeshBoneInfo();
                meshBoneInfo.Name = jointNode.JointName;

                // recursively find bone-space marked parent node (based on H1SkeletalContext.JointNode)
                // we need to reapply parent index based on 'refSkeleton.RefBoneInfoList'
                Int32 currParentIndex = jointNodes.FindIndex(x =>
                {
                    if (jointNode.Parent == null)
                    {
                        return(false);
                    }
                    return(x.JointName == jointNode.Parent.JointName);
                });
                while (currParentIndex != -1 && // if not reaching to root node
                       !jointNodes[currParentIndex].MarkedAsBoneSpace)  // and if is not marked by bone-space
                {
                    currParentIndex = jointNodes.FindIndex(x =>
                    {
                        if (jointNodes[currParentIndex].Parent == null)
                        {
                            return(false);
                        }
                        return(x.JointName == jointNodes[currParentIndex].Parent.JointName);
                    });
                }
                meshBoneInfo.ParentIndex = currParentIndex;

                // the new index should be same with RefBoneBases
                Int32 newBoneInfoIndex = refSkeleton.RefBoneInfoList.Count;
                Int32 newBoneBaseIndex = refSkeleton.RefBoneBases.Count;
                if (newBoneBaseIndex != newBoneInfoIndex)
                {
                    return(null);
                }

                refSkeleton.RefBoneInfoList.Add(meshBoneInfo);

                // what I learned from this disabled code section
                // 1. ASSIMP has separate node space and bone node space (transformation matrix)
                // 2. we need to handle those differently
                //  - vertices resided in particular node space (mesh space we called) should be transformed into root node space (world space)
                //  - localTransform in refSkeleton should be set by offsetMatrix in JointNode.JointData
                H1Transform boneBase = new H1Transform();
                boneBase.Translation = jointNode.NodeLocalTransform.Translation;
                boneBase.Scaling     = jointNode.NodeLocalTransform.Scaling;
                boneBase.Rotation    = jointNode.NodeLocalTransform.Rotation;

                // allocate the space in advance
                refSkeleton.RefBoneBases.Add(boneBase);

                refSkeleton.AddNameToIndexPair(meshBoneInfo.Name, newBoneInfoIndex);

                // add bone offset transform set
                boneOffsetTransforms.Add(new BoneOffsetTransformSet());

                // looping joint data
                foreach (H1SkeletalContext.Joint jointData in jointNode.JointDataList)
                {
                    H1Transform meshContextLocalToGlobalTransform = jointData.MeshContextLocalToGlobal;

                    // convert 'offsetTransformation' to H1Transform
                    H1SkeletalContext.Transformation offsetTransformation = jointData.OffsetTransformation;
                    H1Transform offsetTransform = new H1Transform();
                    offsetTransform.Translation = offsetTransformation.Translation;
                    offsetTransform.Rotation    = offsetTransformation.Rotation;
                    offsetTransform.Scaling     = offsetTransformation.Scaling;

                    // apply meshContextLocalToGlobal
                    Matrix     result = Matrix.Multiply(Matrix.Invert(meshContextLocalToGlobalTransform.Transformation), offsetTransform.Transformation);
                    Vector3    resultTranslation;
                    Vector3    resultScaling;
                    Quaternion resultRotation;
                    result.Decompose(out resultScaling, out resultRotation, out resultTranslation);

                    offsetTransform.Translation = resultTranslation;
                    offsetTransform.Rotation    = resultRotation;
                    offsetTransform.Scaling     = resultScaling;

                    boneOffsetTransforms.Last().BoneOffsetTransforms.Add(offsetTransform);
                }
            }

            // construct parent index for H1MeshBoneInfo
            foreach (H1MeshBoneInfo meshBoneInfo in refSkeleton.RefBoneInfoList)
            {
                if (meshBoneInfo.ParentIndex == -1) // not handling root node case
                {
                    continue;
                }

                String parentName = jointNodes[meshBoneInfo.ParentIndex].JointName;
                meshBoneInfo.ParentIndex = refSkeleton.RefBoneInfoList.FindIndex(x =>
                {
                    return(x.Name == parentName);
                });
            }

            // @TODO - handle multiple offset transformations
            // set offset matrix
            Int32 currBoneIndex = 0;

            foreach (H1MeshBoneInfo meshBoneInfo in refSkeleton.RefBoneInfoList)
            {
                // add to global offset transform
                H1Transform globalOffsetTransform = boneOffsetTransforms[currBoneIndex].BoneOffsetTransforms.Count > 0 ? boneOffsetTransforms[currBoneIndex].BoneOffsetTransforms[0] : new H1Transform();
                refSkeleton.RefOffsetBases.Add(globalOffsetTransform);

                currBoneIndex++;
            }

            return(staticLODModel);
        }