예제 #1
0
        public void TestInit()
        {
            m_rigRepo         = A.Fake <IRigRepository>();
            m_equipmentRepo   = A.Fake <IEquipmentRepository>();
            m_rigTemplateRepo = A.Fake <IRigTemplateRepository>();

            m_testSubject = new RigGenerator(m_rigRepo, m_equipmentRepo, m_rigTemplateRepo);
        }
예제 #2
0
    // TODO (mogens) move this to RigConversion in animation package ?
    public static BlobAssetReference <RigDefinition> ConvertRig(RigComponent rigComponent)
    {
        var skeletonNodes = RigGenerator.ExtractSkeletonNodesFromRigComponent(rigComponent);
        var channels      = RigGenerator.ExtractAnimationChannelFromRigComponent(rigComponent);
        var rigDefinition = RigBuilder.CreateRigDefinition(skeletonNodes, null, channels);

        return(rigDefinition);
    }
예제 #3
0
    public override void PreProcessData <T>(T data)
    {
        if (data is RigComponent)
        {
            var rig = data as RigComponent;

            for (var boneIter = 0; boneIter < rig.Bones.Length; boneIter++)
            {
                if (MotionName == rig.Bones[boneIter].name)
                {
                    m_MotionId = RigGenerator.ComputeRelativePath(rig.Bones[boneIter], rig.transform);
                }
            }
        }
    }
예제 #4
0
    /// <summary>
    /// From the transform's name, find the path in the rig that will later be converted to
    /// a hash, and then the hash will be used to find an index in the AnimationStream.
    /// </summary>
    public ChannelWeightQuery CreateFeatherBlendQuery(RigComponent rig, List <FeatherBlend> blendMap)
    {
        string status = "";

        List <ChannelWeightMap> channels = new List <ChannelWeightMap>();

        for (var mapIter = 0; mapIter < blendMap.Count; mapIter++)
        {
            bool success = false;

            for (var srcBoneIter = 0; srcBoneIter < rig.Bones.Length; srcBoneIter++)
            {
                if (blendMap[mapIter].Id == rig.Bones[srcBoneIter].name)
                {
                    var srcPath = RigGenerator.ComputeRelativePath(rig.Bones[srcBoneIter], rig.transform);

                    channels.Add(new ChannelWeightMap()
                    {
                        Id = srcPath, Weight = blendMap[mapIter].Weight
                    });
                }

                success = true;
            }

            if (!success)
            {
                status = status + mapIter + " ";
            }
        }

        ChannelWeightQuery featherBlendQuery = new ChannelWeightQuery();

        featherBlendQuery.Channels = new ChannelWeightMap[channels.Count];

        for (var iter = 0; iter < channels.Count; iter++)
        {
            featherBlendQuery.Channels[iter] = channels[iter];
        }

        if (!string.IsNullOrEmpty(status))
        {
            UnityEngine.Debug.LogError("Faulty Entries : " + status);
        }

        return(featherBlendQuery);
    }
예제 #5
0
        public static void BuildRigDefinitionBlobAsset(string path)
        {
            var gameObject = AssetDatabase.LoadMainAssetAtPath(path) as GameObject;

            if (gameObject == null)
            {
                throw new NullReferenceException($"Asset '{path}' not found");
            }

            var blobPath = GetBlobAssetPath(path);

            var skeletonNode = RigGenerator.ExtractSkeletonNodesFromGameObject(gameObject);

            var rigDefinition = RigBuilder.CreateRigDefinition(skeletonNode);

            BlobFile.WriteBlobAsset(ref rigDefinition, blobPath);
        }
예제 #6
0
        public void GenerateJackupRig_RigAndEquipment_Created_Correctly()
        {
            // arrange
            IFileSystem fIleSystem = new FileSystem();
            ISerializer serializer = new EmmockJsonSerializer();

            IRigRepository         rigRepo         = new FileRigStore(fIleSystem, serializer);
            IEquipmentRepository   equipmentRepo   = new FileEquipmentStore(fIleSystem, serializer);
            IRigTemplateRepository rigTemplateRepo = new FileRigTemplateStore(fIleSystem, serializer);

            RigTemplate rigTemplate = rigTemplateRepo.GetRigTemplate("Jackup");

            // act
            RigGenerator rigGenerator = new RigGenerator(rigRepo, equipmentRepo, rigTemplateRepo);
            Rig          generatedRig = rigGenerator.GenerateRig("Jackup", "Rig For Test", "");

            Rig actualRig = rigRepo.GetAll().FirstOrDefault(r => r.Id == generatedRig.Id);

            // assert
            Assert.IsNotNull(actualRig);
            Assert.AreEqual(generatedRig.Name, actualRig.Name);

            // TODO: Much deeper check around equipment created from generator
        }
예제 #7
0
    public RigRemapQuery CreateRemapQuery(RigComponent srcRig, RigComponent dstRig, List<string> retargetMap)
    {
        string status = "";

        List<ChannelMap> translationChannels = new List<ChannelMap>();
        List<ChannelMap> rotationChannels = new List<ChannelMap>();
        List<RigTranslationOffset> translationOffsets = new List<RigTranslationOffset>();
        List<RigRotationOffset> rotationOffsets = new List<RigRotationOffset>();

        for (var mapIter = 0; mapIter < retargetMap.Count; mapIter++)
        {
            bool success = false;

            string[] splitMap = retargetMap[mapIter].Split(new char[] { ' ' }, 3);

            for (var srcBoneIter = 0; srcBoneIter < srcRig.Bones.Length; srcBoneIter++)
            {
                if (splitMap.Length > 0 && splitMap[0] == srcRig.Bones[srcBoneIter].name)
                {
                    for (var dstBoneIter = 0; dstBoneIter < dstRig.Bones.Length; dstBoneIter++)
                    {
                        if (splitMap.Length > 1 && splitMap[1] == dstRig.Bones[dstBoneIter].name)
                        {
                            if (splitMap.Length > 2)
                            {
                                var srcPath = RigGenerator.ComputeRelativePath(srcRig.Bones[srcBoneIter], srcRig.transform);
                                var dstPath = RigGenerator.ComputeRelativePath(dstRig.Bones[dstBoneIter], dstRig.transform);

                                if (splitMap[2] == "TR" || splitMap[2] == "T")
                                {
                                    var translationOffset = new RigTranslationOffset();

                                    // heuristic that computes retarget scale based on translation node (ex: hips) height (assumed to be y)
                                    translationOffset.Scale = dstRig.Bones[dstBoneIter].position.y / srcRig.Bones[srcBoneIter].position.y;
                                    
                                    translationOffset.Rotation = mathex.mul(math.conjugate(dstRig.Bones[dstBoneIter].parent.rotation), srcRig.Bones[srcBoneIter].parent.rotation);

                                    translationOffsets.Add(translationOffset);
                                    translationChannels.Add(new ChannelMap() { SourceId = srcPath, DestinationId = dstPath, OffsetIndex = translationOffsets.Count });
                                }

                                if (splitMap[2] == "TR" || splitMap[2] == "R")
                                {
                                    var rotationOffset = new RigRotationOffset();

                                    rotationOffset.PreRotation = mathex.mul(math.conjugate(dstRig.Bones[dstBoneIter].parent.rotation), srcRig.Bones[srcBoneIter].parent.rotation);
                                    rotationOffset.PostRotation = mathex.mul(math.conjugate(srcRig.Bones[srcBoneIter].rotation), dstRig.Bones[dstBoneIter].rotation);

                                    rotationOffsets.Add(rotationOffset);
                                    rotationChannels.Add(new ChannelMap() { SourceId = srcPath, DestinationId = dstPath, OffsetIndex = rotationOffsets.Count });
                                }

                                success = true;
                            }
                        }
                    }
                }
            }

            if (!success)
            {
                status = status + mapIter + " ";
            }
        }

        RigRemapQuery rigRemapQuery = new RigRemapQuery();

        rigRemapQuery.TranslationChannels = new ChannelMap[translationChannels.Count];

        for (var iter = 0; iter < translationChannels.Count; iter++)
        {
            rigRemapQuery.TranslationChannels[iter] = translationChannels[iter];
        }

        rigRemapQuery.TranslationOffsets = new RigTranslationOffset[translationOffsets.Count + 1];
        rigRemapQuery.TranslationOffsets[0] = new RigTranslationOffset();

        for (var iter = 0; iter < translationOffsets.Count; iter++)
        {
            rigRemapQuery.TranslationOffsets[iter + 1] = translationOffsets[iter];
        }

        rigRemapQuery.RotationChannels = new ChannelMap[rotationChannels.Count];

        for (var iter = 0; iter < rotationChannels.Count; iter++)
        {
            rigRemapQuery.RotationChannels[iter] = rotationChannels[iter];
        }

        rigRemapQuery.RotationOffsets = new RigRotationOffset[rotationOffsets.Count + 1];
        rigRemapQuery.RotationOffsets[0] = new RigRotationOffset();

        for (var iter = 0; iter < rotationOffsets.Count; iter++)
        {
            rigRemapQuery.RotationOffsets[iter + 1] = rotationOffsets[iter];
        }

        if (!string.IsNullOrEmpty(status))
        {
            UnityEngine.Debug.LogError("Faulty Entries : " + status);
        }

        return rigRemapQuery;
    }
    private RigRemapQuery CreateRemapQuery(RigComponent srcRig, RigComponent dstRig, List <string> retargetMap)
    {
        var status = "";

        var translationChannels = new List <ChannelMap>();
        var rotationChannels    = new List <ChannelMap>();
        var translationOffsets  = new List <RigTranslationOffset>();
        var rotationOffsets     = new List <RigRotationOffset>();

        //Inverse Quaternion = (x * -1, y * -1, z * -1, w)
        var srcRootRotInv = math.inverse(srcRig.transform.rotation);
        var dstRootRotInv = math.inverse(dstRig.transform.rotation);

        //We are iterating through the retargetMap collection..
        for (var mapIter = 0; mapIter < retargetMap.Count; mapIter++)
        {
            var successFlag = false;

            //Splitting the element in each array when there a space. Three element
            //ex. "First Second Third" = ["First", "Second", "Third"]
            var splitMap = retargetMap[mapIter].Split(new[] { ' ' }, 3);

            //We are iterating through the for loop on the number of bones the srcPrefab.
            for (var srcBoneIter = 0; srcBoneIter < srcRig.Bones.Length; srcBoneIter++)
            {
                //We are checking if the splitMap element has atleast one element and if the first element matches any bone name of the srcRig prefab bone
                if (splitMap.Length > 0 && splitMap[0] == srcRig.Bones[srcBoneIter].name)
                {
                    //We are iterating through the for loop on the number of bones we have on the gameObject attached to this script.
                    for (var dstBoneIter = 0; dstBoneIter < dstRig.Bones.Length; dstBoneIter++)
                    {
                        //We are checking if the splitMap element has atleast two element and if the second element matches any bone name of this gameObject
                        if (splitMap.Length > 1 && splitMap[1] == dstRig.Bones[dstBoneIter].name)
                        {
                            //We are checking if the splitMap has atleast three element
                            if (splitMap.Length > 2)
                            {
                                //We are getting all the parent gameObject name of the current srcRig bone at srcBoneIter up until and excluding the srcRig.transform
                                //Ex.
                                // if srcRig.Bones[srcBoneIter] = Chest
                                // then the srcPath = Skeleton/Root/Spine/Chest (it traverse the hierarchy and get the parent up until the srcRig.transform)
                                var srcPath =
                                    RigGenerator.ComputeRelativePath(srcRig.Bones[srcBoneIter], srcRig.transform);
                                var dstPath
                                    = RigGenerator.ComputeRelativePath(dstRig.Bones[dstBoneIter], dstRig.transform);

                                if (splitMap[2] == "TR" || splitMap[2] == "T")
                                {
                                    var translationOffset = new RigTranslationOffset();

                                    //self bone position.y / target bone position.y to get the average height of the bone (assumed to be y/ standing up right)
                                    translationOffset.Scale = dstRig.Bones[dstBoneIter].position.y /
                                                              srcRig.Bones[srcBoneIter].position.y;

                                    var dstParentRot =
                                        math.mul(dstRootRotInv, dstRig.Bones[dstBoneIter].parent.rotation);
                                    var srcParentRot =
                                        math.mul(srcRootRotInv, srcRig.Bones[srcBoneIter].parent.rotation);

                                    translationOffset.Rotation = mathex.mul(math.inverse(dstParentRot), srcParentRot);

                                    translationOffsets.Add(translationOffset);
                                    translationChannels.Add(new ChannelMap
                                    {
                                        SourceId    = srcPath, DestinationId = dstPath,
                                        OffsetIndex = translationOffsets.Count
                                    });
                                }

                                if (splitMap[2] == "TR" || splitMap[2] == "R")
                                {
                                    var rotationOffset = new RigRotationOffset();

                                    var dstParentRot = math.mul(dstRootRotInv,
                                                                dstRig.Bones[dstBoneIter].parent.transform.rotation);
                                    var srcParentRot = math.mul(srcRootRotInv,
                                                                srcRig.Bones[srcBoneIter].parent.transform.rotation);

                                    var dstRot = math.mul(dstRootRotInv,
                                                          dstRig.Bones[dstBoneIter].transform.rotation);
                                    var srcRot = math.mul(srcRootRotInv,
                                                          srcRig.Bones[srcBoneIter].transform.rotation);

                                    rotationOffset.PreRotation  = mathex.mul(math.inverse(dstParentRot), srcParentRot);
                                    rotationOffset.PostRotation = mathex.mul(math.inverse(srcRot), dstRot);

                                    rotationOffsets.Add(rotationOffset);
                                    rotationChannels.Add(new ChannelMap
                                    {
                                        SourceId = srcPath, DestinationId = dstPath, OffsetIndex = rotationOffsets.Count
                                    });
                                }

                                successFlag = true;
                            }
                        }
                    }
                }
            }

            if (!successFlag)
            {
                status = status + mapIter + " ";
            }
        }

        var rigRemapQuery = new RigRemapQuery();

        rigRemapQuery.TranslationChannels = new ChannelMap[translationChannels.Count];

        for (var iter = 0; iter < translationChannels.Count; iter++)
        {
            rigRemapQuery.TranslationChannels[iter] = translationChannels[iter];
        }

        rigRemapQuery.TranslationOffsets    = new RigTranslationOffset[translationOffsets.Count + 1];
        rigRemapQuery.TranslationOffsets[0] = new RigTranslationOffset();

        for (var iter = 0; iter < translationOffsets.Count; iter++)
        {
            rigRemapQuery.TranslationOffsets[iter + 1] = translationOffsets[iter];
        }

        rigRemapQuery.RotationChannels = new ChannelMap[rotationChannels.Count];

        for (var iter = 0; iter < rotationChannels.Count; iter++)
        {
            rigRemapQuery.RotationChannels[iter] = rotationChannels[iter];
        }

        rigRemapQuery.RotationOffsets    = new RigRotationOffset[rotationOffsets.Count + 1];
        rigRemapQuery.RotationOffsets[0] = new RigRotationOffset();

        for (var iter = 0; iter < rotationOffsets.Count; iter++)
        {
            rigRemapQuery.RotationOffsets[iter + 1] = rotationOffsets[iter];
        }

        if (!string.IsNullOrEmpty(status))
        {
            Debug.LogError("Faulty Entries : " + status);
        }

        return(rigRemapQuery);
    }
예제 #9
0
        void ConvertSkinnedMeshRenderes(RigBasedAssetAuthoring assetAuthoring, Entity assetEntity,
                                        RigComponent rigComponent)
        {
            var skinnedMeshRenderers = assetAuthoring.GetComponentsInChildren <SkinnedMeshRenderer>();

            if (skinnedMeshRenderers.Length > 0)
            {
                DstEntityManager.AddBuffer <RigBasedAsset.SkinnedMeshRenderer>(assetEntity);
            }
            foreach (var meshRenderer in skinnedMeshRenderers)
            {
                var skinEntity = GetPrimaryEntity(meshRenderer.gameObject);
                //var skinEntity = conversionSystem.CreateAdditionalEntity(meshRenderer);
    #if UNITY_EDITOR
                DstEntityManager.SetName(skinEntity, "Entity " + skinEntity.Index + " Skin_" + meshRenderer.gameObject.name);
    #endif

                var skinRendererBuffer = DstEntityManager.GetBuffer <RigBasedAsset.SkinnedMeshRenderer>(assetEntity);
                skinRendererBuffer.Add(new RigBasedAsset.SkinnedMeshRenderer {
                    Value = skinEntity,
                });

                //var rigEntity = GetPrimaryEntity(src.Rig);
                //DstEntityManager.AddComponentData(entity, new SkinnedMeshComponentData { RigEntity = rigEntity });
                DstEntityManager.AddComponentData(skinEntity, new SkinnedMeshRigEntity {
                    Value = assetEntity
                });
                DstEntityManager.AddComponentData(skinEntity, new LocalToWorld());
                DstEntityManager.AddComponentData(skinEntity, new BoneIndexOffset());

                DstEntityManager.AddBuffer <SkinnedMeshToRigIndex>(skinEntity);
                DstEntityManager.AddBuffer <BindPose>(skinEntity);
                DstEntityManager.AddBuffer <SkinMatrix>(skinEntity);

                var skeletonIndexArray = DstEntityManager.GetBuffer <SkinnedMeshToRigIndex>(skinEntity);
                var bindPoseArray      = DstEntityManager.GetBuffer <BindPose>(skinEntity);
                var skinMatrices       = DstEntityManager.GetBuffer <SkinMatrix>(skinEntity);

                var smBones = meshRenderer.bones;
                skeletonIndexArray.ResizeUninitialized(smBones.Length);
                bindPoseArray.ResizeUninitialized(smBones.Length);
                skinMatrices.ResizeUninitialized(smBones.Length);

                //GameDebug.Log("skin smBones");
                //for (int i = 0; i < smBones.Length; i++)
                //{
                //    var relativePath = RigGenerator.ComputeRelativePath(smBones[i], transform);
                //    var id = (StringHash)relativePath;
                //    GameDebug.Log("  " + i + ":" + id.Id + " path:" + relativePath);
                //}

                for (int j = 0; j != smBones.Length; ++j)
                {
                    var remap = new SkinnedMeshToRigIndex {
                        Value = -1
                    };

                    var smBoneRelativePath = RigGenerator.ComputeRelativePath(smBones[j], assetAuthoring.transform);
                    var smBoneId           = (StringHash)smBoneRelativePath;

                    for (int k = 0; k != rigComponent.Bones.Length; ++k)
                    {
                        var relativePath = RigGenerator.ComputeRelativePath(rigComponent.Bones[k], rigComponent.transform);
                        var id           = (StringHash)relativePath;

                        if (smBoneId.Equals(id))
                        {
                            remap.Value = k;
                            break;
                        }
                    }
                    skeletonIndexArray[j] = remap;

                    var bindPose = meshRenderer.sharedMesh.bindposes[j];
                    bindPoseArray[j] = new BindPose {
                        Value = bindPose
                    };

                    var skinMat = math.mul(meshRenderer.bones[j].localToWorldMatrix, bindPose);
                    skinMatrices[j] = new SkinMatrix {
                        Value = new float3x4(skinMat.c0.xyz, skinMat.c1.xyz, skinMat.c2.xyz, skinMat.c3.xyz)
                    };
                }
            }
        }
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        if (Clips == null || BlendThresholds == null)
        {
            return;
        }

        if (!dstManager.HasComponent <Rig>(entity))
        {
            throw new System.InvalidOperationException("RigComponent must be converted before this component.");
        }

        if (Clips.Length != BlendThresholds.Length)
        {
            throw new System.InvalidOperationException("You must have the same number of clips and blendthresholds.");
        }

        var        rigComponent = GetComponent <RigComponent>() as RigComponent;
        StringHash motionId     = "";

        for (var boneIter = 0; boneIter < rigComponent.Bones.Length; boneIter++)
        {
            if (MotionJointName == rigComponent.Bones[boneIter].name)
            {
                motionId = RigGenerator.ComputeRelativePath(rigComponent.Bones[boneIter], rigComponent.transform);
            }
        }

        var rigDefinition     = dstManager.GetComponentData <Rig>(entity);
        var clipConfiguration = new ClipConfiguration();

        clipConfiguration.Mask     = ClipConfigurationMask.LoopTime | ClipConfigurationMask.LoopValues | ClipConfigurationMask.CycleRootMotion | ClipConfigurationMask.DeltaRootMotion;
        clipConfiguration.MotionID = motionId;

        var denseClips = new NativeArray <SampleClip>(Clips.Length, Allocator.Temp);
        var durations  = new NativeArray <SampleClipDuration>(Clips.Length, Allocator.Temp);
        var thresholds = new NativeArray <SampleClipBlendThreshold>(Clips.Length, Allocator.Temp);

        for (int i = 0; i < Clips.Length; i++)
        {
            conversionSystem.DeclareAssetDependency(gameObject, Clips[i]);

            denseClips[i] = new SampleClip
            {
                Clip = UberClipNode.Bake(rigDefinition.Value, Clips[i].ToDenseClip(), clipConfiguration, 60.0f)
            };
            durations[i] = new SampleClipDuration {
                Value = denseClips[i].Clip.Value.Duration
            };
            thresholds[i] = new SampleClipBlendThreshold {
                Value = BlendThresholds[i]
            };
        }

        var synchronizeMotions = dstManager.AddBuffer <SampleClip>(entity);

        synchronizeMotions.CopyFrom(denseClips);

        var synchronizeMotionDurations = dstManager.AddBuffer <SampleClipDuration>(entity);

        synchronizeMotionDurations.CopyFrom(durations);

        var synchronizeMotionThresholds = dstManager.AddBuffer <SampleClipBlendThreshold>(entity);

        synchronizeMotionThresholds.CopyFrom(thresholds);

        dstManager.AddComponentData(entity, new WeightComponent
        {
            Value = 0.0f
        });

        denseClips.Dispose();
        durations.Dispose();
        thresholds.Dispose();
    }
    private RigRemapQuery CreateAutoRemapQuery([NotNull] RigComponent srcRig, [NotNull] RigComponent dstRig)
    {
        var translationChannels = new List <ChannelMap>();
        var rotationChannels    = new List <ChannelMap>();

        var translationOffsets = new List <RigTranslationOffset>();
        var rotationOffsets    = new List <RigRotationOffset>();

        var srcRootRotInv = math.inverse(srcRig.transform.rotation);
        var dstRootRotInv = math.inverse(dstRig.transform.rotation);

        for (var boneIter = 0; boneIter < srcRig.Bones.Length; boneIter++)
        {
            if (srcRig.Bones[boneIter].parent != null)
            {
                if (srcRig.Bones[boneIter].name == dstRig.Bones[boneIter].name)
                {
                    var srcPath = RigGenerator.ComputeRelativePath(srcRig.Bones[boneIter], srcRig.transform);
                    var dstPath = RigGenerator.ComputeRelativePath(dstRig.Bones[boneIter], dstRig.transform);

                    var dstParentRot = math.mul(dstRootRotInv, dstRig.Bones[boneIter].parent.transform.rotation);
                    var srcParentRot = math.mul(srcRootRotInv, srcRig.Bones[boneIter].parent.transform.rotation);
                    var rotation     = mathex.mul(math.inverse(dstParentRot), srcParentRot);

                    //Got to calculate the translation.
                    //Only applying translationOffset to the first bone (most cases the hips)
                    if (boneIter == 1)
                    {
                        var translationOffset = new RigTranslationOffset
                        {
                            Scale    = dstRig.Bones[boneIter].position.y / srcRig.Bones[boneIter].position.y,
                            Rotation = rotation
                        };

                        translationOffsets.Add(translationOffset);
                        translationChannels.Add(new ChannelMap
                        {
                            DestinationId = dstPath, SourceId = srcPath, OffsetIndex = translationOffsets.Count
                        });
                    }

                    //Got to calculate the rotation.
                    var dstRot = math.mul(dstRootRotInv, dstRig.Bones[boneIter].transform.rotation);
                    var srcRot = math.mul(srcRootRotInv, srcRig.Bones[boneIter].transform.rotation);

                    var rotationOffset = new RigRotationOffset
                    {
                        PreRotation  = rotation,
                        PostRotation = mathex.mul(math.inverse(srcRot), dstRot)
                    };

                    rotationOffsets.Add(rotationOffset);
                    rotationChannels.Add(new ChannelMap
                    {
                        SourceId = srcPath, DestinationId = dstPath, OffsetIndex = rotationOffsets.Count
                    });
                }
            }
        }

        var rigRemapQuery = new RigRemapQuery
        {
            TranslationChannels = new ChannelMap[translationChannels.Count],
            RotationChannels    = new ChannelMap[rotationChannels.Count],
            TranslationOffsets  = new RigTranslationOffset[translationChannels.Count + 1],
            RotationOffsets     = new RigRotationOffset[rotationChannels.Count + 1]
        };

        rigRemapQuery.TranslationOffsets[0] = new RigTranslationOffset();
        rigRemapQuery.RotationOffsets[0]    = new RigRotationOffset();

        for (var iter = 0; iter < translationChannels.Count; iter++)
        {
            rigRemapQuery.TranslationChannels[iter]    = translationChannels[iter];
            rigRemapQuery.TranslationOffsets[iter + 1] = translationOffsets[iter];
        }

        for (var iter = 0; iter < rotationChannels.Count; iter++)
        {
            rigRemapQuery.RotationChannels[iter]    = rotationChannels[iter];
            rigRemapQuery.RotationOffsets[iter + 1] = rotationOffsets[iter];
        }

        return(rigRemapQuery);
    }