Esempio n. 1
0
        public void AddMotionMatchingData(MotionMatchingData[] data, MotionDataGroup group)
        {
            group.animationData.AddRange(data);

            switch (this.stateType)
            {
            case MotionMatchingStateType.MotionMatching:
                break;

            case MotionMatchingStateType.SingleAnimation:
                for (int i = 0; i < data.Length; i++)
                {
                    whereCanFindingNextPose.Add(new float2(
                                                    0f,
                                                    data[i].contactPoints.Count > 0 ? data[i].contactPoints[0].startTime : data[i].animationLength * 0.5f
                                                    ));
                }
                break;

            case MotionMatchingStateType.ContactAnimationState:
                for (int i = 0; i < data.Length; i++)
                {
                    whereCanFindingNextPose.Add(new float2(
                                                    0f,
                                                    data[i].contactPoints.Count > 0 ? data[i].contactPoints[0].startTime : data[i].animationLength * 0.5f
                                                    ));
                }
                break;
            }

            UpdateTransitions();
        }
Esempio n. 2
0
        public void RemoveMotionMatchingData(int index, MotionDataGroup group)
        {
            group.animationData.RemoveAt(index);

            switch (this.stateType)
            {
            case MotionMatchingStateType.MotionMatching:
                break;

            case MotionMatchingStateType.SingleAnimation:
                break;

            case MotionMatchingStateType.ContactAnimationState:
                whereCanFindingNextPose.RemoveAt(index);
                break;
            }
            UpdateTransitions(index);
        }
Esempio n. 3
0
 public void ClearMotionMatchingData(MotionDataGroup group)
 {
     group.animationData.Clear();
     whereCanFindingNextPose.Clear();
     UpdateTransitions();
 }
Esempio n. 4
0
        //private void CreateImpactData(
        //    int trajectoryCount,
        //    int poseCount,
        //    int maxFramesForJob
        //    )
        //{
        //    // Obliczenie ilości wszystkich klatek do sprawdzenia
        //    allFramesCount = 0;
        //    for (int i = 0; i < animationData.Count; i++)
        //    {
        //        for (int frameIndex = 0; frameIndex < animationData[i].frames.Count; frameIndex++)
        //        {
        //            if (animationData[i][frameIndex].contactPoints.Length == 1)
        //            {
        //                allFramesCount++;
        //            }
        //        }
        //    }

        //    // Obliczanie odpowiedniej ilości jobów
        //    int availableThreads = SystemInfo.processorCount;
        //    if (availableThreads > 4)
        //    {
        //        availableThreads = availableThreads - 1;
        //    }

        //    int bestThreadsCount = (int)math.ceil((float)allFramesCount / (float)maxFramesForJob);

        //    if (bestThreadsCount >= availableThreads)
        //    {
        //        maxJobsCount = availableThreads;
        //    }
        //    else
        //    {
        //        maxJobsCount = bestThreadsCount;
        //    }

        //    trajectoryPointsPerJob = new NativeArray<TrajectoryPoint>[maxJobsCount];
        //    bonesPerJob = new NativeArray<BoneData>[maxJobsCount];
        //    framesInfoPerJob = new NativeArray<FrameDataInfo>[maxJobsCount];

        //    int[] framesPerJob = new int[maxJobsCount];

        //    int framesForOneJob = Mathf.FloorToInt((float)allFramesCount / (float)maxJobsCount);

        //    for (int i = 0; i < maxJobsCount - 1; i++)
        //    {
        //        framesPerJob[i] = framesForOneJob;
        //    }

        //    framesPerJob[maxJobsCount - 1] = allFramesCount - (framesForOneJob * (maxJobsCount - 1));

        //    for (int i = 0; i < maxJobsCount; i++)
        //    {
        //        trajectoryPointsPerJob[i] = new NativeArray<TrajectoryPoint>(framesPerJob[i] * trajectoryCount, Allocator.Persistent);
        //        bonesPerJob[i] = new NativeArray<BoneData>(framesPerJob[i] * poseCount, Allocator.Persistent);
        //        framesInfoPerJob[i] = new NativeArray<FrameDataInfo>(framesPerJob[i], Allocator.Persistent);
        //    }

        //    contactPointsPerJob = new NativeArray<FrameContact>[maxJobsCount];
        //    for (int i = 0; i < maxJobsCount; i++)
        //    {
        //        contactPointsPerJob[i] = new NativeArray<FrameContact>(
        //            framesPerJob[i],
        //            Allocator.Persistent
        //            );
        //    }

        //    int jobIndex = 0;
        //    int frameInfoIndex = 0;
        //    int jobTrajectoryPointIndex = 0;
        //    int jobBoneIndex = 0;
        //    int cpIndex = 0;

        //    for (int clipIndex = 0; clipIndex < animationData.Count; clipIndex++)
        //    {
        //        for (int frameIndex = 0; frameIndex < animationData[clipIndex].numberOfFrames; frameIndex++)
        //        {
        //            if (animationData[clipIndex][frameIndex].contactPoints.Length == 1)
        //            {
        //                // Making native array trajectory points
        //                for (int pointIndex = 0; pointIndex < animationData[clipIndex][frameIndex].trajectory.Length; pointIndex++)
        //                {
        //                    trajectoryPointsPerJob[jobIndex][jobTrajectoryPointIndex] = animationData[clipIndex][frameIndex].trajectory.GetPoint(pointIndex);
        //                    jobTrajectoryPointIndex++;
        //                }

        //                // Making native array bones
        //                for (int boneIndex = 0; boneIndex < animationData[clipIndex][frameIndex].pose.Count; boneIndex++)
        //                {
        //                    bonesPerJob[jobIndex][jobBoneIndex] = animationData[clipIndex][frameIndex].pose.GetBoneData(boneIndex);
        //                    jobBoneIndex++;
        //                }

        //                // Making native array Impacts

        //                contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
        //                               animationData[clipIndex][frameIndex].contactPoints[0].position,
        //                               animationData[clipIndex][frameIndex].contactPoints[0].normal,
        //                               animationData[clipIndex][frameIndex].contactPoints[0].forward
        //                               );
        //                cpIndex++;


        //                // Making native array frame info
        //                framesInfoPerJob[jobIndex][frameInfoIndex] = new FrameDataInfo(
        //                    clipIndex,
        //                    animationData[clipIndex][frameIndex].localTime,
        //                    animationData[clipIndex][frameIndex].sections
        //                    );
        //                frameInfoIndex++;

        //                if (frameInfoIndex == framesPerJob[jobIndex])
        //                {
        //                    jobIndex++;
        //                    frameInfoIndex = 0;
        //                    jobTrajectoryPointIndex = 0;
        //                    jobBoneIndex = 0;
        //                    cpIndex = 0;
        //                }
        //            }
        //        }
        //    }
        //}

        private void CreateFrameDataForMotionGroups(
            MotionDataGroup group,
            float maxFramesPerJob,
            int trajectoryCount,
            int poseCount
            )
        {
            // Obliczenie ilości wszystkich klatek do sprawdzenia
            group.calculatedFramesCount = 0;
            for (int i = 0; i < group.animationData.Count; i++)
            {
                group.calculatedFramesCount += group.animationData[i].usedFrameCount;
            }

            // Obliczanie odpowiedniej ilości jobów
            int availableThreads = SystemInfo.processorCount;

            if (availableThreads > 4)
            {
                availableThreads = availableThreads - 1;
            }

            int bestThreadsCount = (int)math.ceil((float)group.calculatedFramesCount / (float)maxFramesPerJob);

            if (bestThreadsCount >= availableThreads)
            {
                group.jobsCount = availableThreads;
            }
            else
            {
                group.jobsCount = bestThreadsCount;
            }

            group.trajectoryPointsPerJob = new NativeArray <TrajectoryPoint> [group.jobsCount];
            group.bonesPerJob            = new NativeArray <BoneData> [group.jobsCount];
            group.framesInfoPerJob       = new NativeArray <FrameDataInfo> [group.jobsCount];

            int[] framesPerJob = new int[group.jobsCount];

            int framesForOneJob = Mathf.FloorToInt((float)group.calculatedFramesCount / (float)group.jobsCount);

            for (int i = 0; i < group.jobsCount - 1; i++)
            {
                framesPerJob[i] = framesForOneJob;
            }

            framesPerJob[group.jobsCount - 1] = group.calculatedFramesCount - (framesForOneJob * (group.jobsCount - 1));
            for (int i = 0; i < group.jobsCount; i++)
            {
                group.trajectoryPointsPerJob[i] = new NativeArray <TrajectoryPoint>(framesPerJob[i] * trajectoryCount, Allocator.Persistent);
                group.bonesPerJob[i]            = new NativeArray <BoneData>(framesPerJob[i] * poseCount, Allocator.Persistent);
                group.framesInfoPerJob[i]       = new NativeArray <FrameDataInfo>(framesPerJob[i], Allocator.Persistent);
            }

            int jobIndex                = 0;
            int frameInfoIndex          = 0;
            int jobTrajectoryPointIndex = 0;
            int jobBoneIndex            = 0;

            for (int clipIndex = 0; clipIndex < group.animationData.Count; clipIndex++)
            {
                for (int frameIndex = 0; frameIndex < group.animationData[clipIndex].numberOfFrames; frameIndex++)
                {
                    if (group.animationData[clipIndex].CanUseFrame(frameIndex))
                    {
                        // Making native array trajectory points
                        for (int pointIndex = 0; pointIndex < trajectoryCount; pointIndex++)
                        {
                            group.trajectoryPointsPerJob[jobIndex][jobTrajectoryPointIndex] = group.animationData[clipIndex][frameIndex].trajectory.GetPoint(pointIndex);
                            jobTrajectoryPointIndex++;
                        }

                        // Making native array bones
                        for (int boneIndex = 0; boneIndex < poseCount; boneIndex++)
                        {
                            group.bonesPerJob[jobIndex][jobBoneIndex] = group.animationData[clipIndex][frameIndex].pose.GetBoneData(boneIndex);
                            jobBoneIndex++;
                        }

                        // Making native array frame info
                        group.framesInfoPerJob[jobIndex][frameInfoIndex] = new FrameDataInfo(
                            clipIndex,
                            group.animationData[clipIndex][frameIndex].localTime,
                            group.animationData[clipIndex][frameIndex].sections
                            );
                        frameInfoIndex++;

                        if (frameInfoIndex == framesPerJob[jobIndex])
                        {
                            jobIndex++;
                            frameInfoIndex          = 0;
                            jobTrajectoryPointIndex = 0;
                            jobBoneIndex            = 0;
                        }
                    }
                }
            }


            if (this.stateType == MotionMatchingStateType.ContactAnimationState && this.csFeatures.contactStateType == ContactStateType.NormalContacts)
            {
                CreateContactPointsData(group, framesPerJob);
            }
        }
Esempio n. 5
0
        private void CreateImpactData(
            MotionDataGroup group,
            int trajectoryCount,
            int poseCount,
            int maxFramesForJob
            )
        {
            // Obliczenie ilości wszystkich klatek do sprawdzenia
            group.calculatedFramesCount = 0;
            for (int i = 0; i < group.animationData.Count; i++)
            {
                for (int frameIndex = 0; frameIndex < group.animationData[i].frames.Count; frameIndex++)
                {
                    if (group.animationData[i][frameIndex].contactPoints.Length == 1)
                    {
                        group.calculatedFramesCount++;
                    }
                }
            }

            // Obliczanie odpowiedniej ilości jobów
            int availableThreads = SystemInfo.processorCount;

            if (availableThreads > 4)
            {
                availableThreads = availableThreads - 1;
            }

            int bestThreadsCount = (int)math.ceil((float)group.calculatedFramesCount / (float)maxFramesForJob);

            if (bestThreadsCount >= availableThreads)
            {
                group.jobsCount = availableThreads;
            }
            else
            {
                group.jobsCount = bestThreadsCount;
            }

            group.trajectoryPointsPerJob = new NativeArray <TrajectoryPoint> [group.jobsCount];
            group.bonesPerJob            = new NativeArray <BoneData> [group.jobsCount];
            group.framesInfoPerJob       = new NativeArray <FrameDataInfo> [group.jobsCount];

            int[] framesPerJob = new int[group.jobsCount];

            int framesForOneJob = Mathf.FloorToInt((float)group.calculatedFramesCount / (float)group.jobsCount);

            for (int i = 0; i < group.jobsCount - 1; i++)
            {
                framesPerJob[i] = framesForOneJob;
            }

            framesPerJob[group.jobsCount - 1] = group.calculatedFramesCount - (framesForOneJob * (group.jobsCount - 1));

            for (int i = 0; i < group.jobsCount; i++)
            {
                group.trajectoryPointsPerJob[i] = new NativeArray <TrajectoryPoint>(framesPerJob[i] * trajectoryCount, Allocator.Persistent);
                group.bonesPerJob[i]            = new NativeArray <BoneData>(framesPerJob[i] * poseCount, Allocator.Persistent);
                group.framesInfoPerJob[i]       = new NativeArray <FrameDataInfo>(framesPerJob[i], Allocator.Persistent);
            }

            group.contactPointsPerJob = new NativeArray <FrameContact> [group.jobsCount];
            for (int i = 0; i < group.jobsCount; i++)
            {
                group.contactPointsPerJob[i] = new NativeArray <FrameContact>(
                    framesPerJob[i],
                    Allocator.Persistent
                    );
            }

            int jobIndex                = 0;
            int frameInfoIndex          = 0;
            int jobTrajectoryPointIndex = 0;
            int jobBoneIndex            = 0;
            int cpIndex = 0;

            for (int clipIndex = 0; clipIndex < group.animationData.Count; clipIndex++)
            {
                for (int frameIndex = 0; frameIndex < group.animationData[clipIndex].numberOfFrames; frameIndex++)
                {
                    if (group.animationData[clipIndex][frameIndex].contactPoints.Length == 1)
                    {
                        // Making native array trajectory points
                        for (int pointIndex = 0; pointIndex < trajectoryCount; pointIndex++)
                        {
                            group.trajectoryPointsPerJob[jobIndex][jobTrajectoryPointIndex] = group.animationData[clipIndex][frameIndex].trajectory.GetPoint(pointIndex);
                            jobTrajectoryPointIndex++;
                        }

                        // Making native array bones
                        for (int boneIndex = 0; boneIndex < poseCount; boneIndex++)
                        {
                            group.bonesPerJob[jobIndex][jobBoneIndex] = group.animationData[clipIndex][frameIndex].pose.GetBoneData(boneIndex);
                            jobBoneIndex++;
                        }

                        // Making native array Impacts

                        group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                            group.animationData[clipIndex][frameIndex].contactPoints[0].position,
                            group.animationData[clipIndex][frameIndex].contactPoints[0].normal
                            //group.animationData[clipIndex][frameIndex].contactPoints[0].forward
                            );
                        cpIndex++;


                        // Making native array frame info
                        group.framesInfoPerJob[jobIndex][frameInfoIndex] = new FrameDataInfo(
                            clipIndex,
                            group.animationData[clipIndex][frameIndex].localTime,
                            group.animationData[clipIndex][frameIndex].sections
                            );
                        frameInfoIndex++;

                        if (frameInfoIndex == framesPerJob[jobIndex])
                        {
                            jobIndex++;
                            frameInfoIndex          = 0;
                            jobTrajectoryPointIndex = 0;
                            jobBoneIndex            = 0;
                            cpIndex = 0;
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        private void CreateContactPointsData(MotionDataGroup group, int[] framesPerJob)
        {
            int groupJobsCount = framesPerJob.Length;

            switch (this.csFeatures.contactMovementType)
            {
            case ContactStateMovemetType.StartContact:
            case ContactStateMovemetType.ContactLand:
                foreach (MotionMatchingData d in group.animationData)
                {
                    if (group.animationData[0].contactPoints.Count < this.csFeatures.middleContactsCount)
                    {
                        throw new System.Exception(string.Format("In state {0} there are not enough contact points in data {1}", this.name, d.name));
                    }
                }
                break;

            case ContactStateMovemetType.StartContactLand:
                foreach (MotionMatchingData d in group.animationData)
                {
                    if (group.animationData[0].contactPoints.Count < 1 + this.csFeatures.middleContactsCount)
                    {
                        throw new System.Exception(string.Format("In state {0} there are not enough contact points in data {1}", this.name, d.name));
                    }
                }
                break;

            case ContactStateMovemetType.Contact:
                foreach (MotionMatchingData d in group.animationData)
                {
                    if (group.animationData[0].contactPoints.Count < this.csFeatures.middleContactsCount)
                    {
                        throw new System.Exception(string.Format("In state {0} there are not enough contact points in data {1}", this.name, d.name));
                    }
                }
                break;

            case ContactStateMovemetType.StartLand:
                foreach (MotionMatchingData d in group.animationData)
                {
                    if (group.animationData[0].contactPoints.Count < 2)
                    {
                        throw new System.Exception(string.Format("In state {0} there are not enough contact points in data {1}", this.name, d.name));
                    }
                }
                break;
            }

            group.contactPointsPerJob = new NativeArray <FrameContact> [framesPerJob.Length];

            switch (this.csFeatures.contactMovementType)
            {
            case ContactStateMovemetType.Contact:
                for (int i = 0; i < groupJobsCount; i++)
                {
                    group.contactPointsPerJob[i] = new NativeArray <FrameContact>(
                        framesPerJob[i] * this.csFeatures.middleContactsCount,
                        Allocator.Persistent
                        );
                }
                break;

            case ContactStateMovemetType.StartContact:
            case ContactStateMovemetType.ContactLand:
                for (int i = 0; i < groupJobsCount; i++)
                {
                    group.contactPointsPerJob[i] = new NativeArray <FrameContact>(
                        framesPerJob[i] * (this.csFeatures.middleContactsCount + 1),
                        Allocator.Persistent
                        );
                }
                break;

            case ContactStateMovemetType.StartContactLand:
                for (int i = 0; i < groupJobsCount; i++)
                {
                    group.contactPointsPerJob[i] = new NativeArray <FrameContact>(
                        framesPerJob[i] * (this.csFeatures.middleContactsCount + 2),
                        Allocator.Persistent
                        );
                }
                break;

            case ContactStateMovemetType.StartLand:
                for (int i = 0; i < groupJobsCount; i++)
                {
                    group.contactPointsPerJob[i] = new NativeArray <FrameContact>(
                        framesPerJob[i] * 2,
                        Allocator.Persistent
                        );
                }
                break;
            }

            int cpIndex  = 0;
            int jobIndex = 0;


            switch (this.csFeatures.contactMovementType)
            {
            case ContactStateMovemetType.Contact:
                for (int clipIndex = 0; clipIndex < group.animationData.Count; clipIndex++)
                {
                    for (int frameIndex = 0; frameIndex < group.animationData[clipIndex].numberOfFrames; frameIndex++)
                    {
                        if (group.animationData[clipIndex].CanUseFrame(frameIndex))
                        {
                            for (int i = 1; i <= this.csFeatures.middleContactsCount; i++)
                            {
                                group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                                    group.animationData[clipIndex][frameIndex].contactPoints[i].position,
                                    group.animationData[clipIndex][frameIndex].contactPoints[i].normal    //,
                                    //group.animationData[clipIndex][frameIndex].contactPoints[i].forward
                                    );
                                cpIndex++;
                            }

                            if (cpIndex >= framesPerJob[jobIndex] * csFeatures.middleContactsCount)
                            {
                                cpIndex = 0;
                                jobIndex++;
                            }
                        }
                    }
                }
                break;

            case ContactStateMovemetType.StartContact:
                for (int clipIndex = 0; clipIndex < group.animationData.Count; clipIndex++)
                {
                    for (int frameIndex = 0; frameIndex < group.animationData[clipIndex].numberOfFrames; frameIndex++)
                    {
                        if (group.animationData[clipIndex].CanUseFrame(frameIndex))
                        {
                            for (int i = 0; i <= this.csFeatures.middleContactsCount; i++)
                            {
                                group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                                    group.animationData[clipIndex][frameIndex].contactPoints[i].position,
                                    group.animationData[clipIndex][frameIndex].contactPoints[i].normal
                                    //group.animationData[clipIndex][frameIndex].contactPoints[i].forward
                                    );
                                cpIndex++;
                            }

                            if (cpIndex >= framesPerJob[jobIndex] * (csFeatures.middleContactsCount + 1))
                            {
                                cpIndex = 0;
                                jobIndex++;
                            }
                        }
                    }
                }
                break;

            case ContactStateMovemetType.ContactLand:
                for (int clipIndex = 0; clipIndex < group.animationData.Count; clipIndex++)
                {
                    for (int frameIndex = 0; frameIndex < group.animationData[clipIndex].numberOfFrames; frameIndex++)
                    {
                        if (group.animationData[clipIndex].CanUseFrame(frameIndex))
                        {
                            for (int i = 1; i <= this.csFeatures.middleContactsCount; i++)
                            {
                                group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                                    group.animationData[clipIndex][frameIndex].contactPoints[i].position,
                                    group.animationData[clipIndex][frameIndex].contactPoints[i].normal
                                    //group.animationData[clipIndex][frameIndex].contactPoints[i].forward
                                    );
                                cpIndex++;
                            }
                            int lastPoimtIndex = group.animationData[clipIndex][frameIndex].contactPoints.Length - 1;
                            group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                                group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].position,
                                group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].normal
                                //group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].forward
                                );
                            cpIndex++;

                            if (cpIndex >= framesPerJob[jobIndex] * (csFeatures.middleContactsCount + 1))
                            {
                                cpIndex = 0;
                                jobIndex++;
                            }
                        }
                    }
                }
                break;

            case ContactStateMovemetType.StartContactLand:
                for (int clipIndex = 0; clipIndex < group.animationData.Count; clipIndex++)
                {
                    for (int frameIndex = 0; frameIndex < group.animationData[clipIndex].numberOfFrames; frameIndex++)
                    {
                        if (group.animationData[clipIndex].CanUseFrame(frameIndex))
                        {
                            for (int i = 0; i <= this.csFeatures.middleContactsCount; i++)
                            {
                                //Debug.Log(string.Format("clipIndex: {0} frameIndex: {1} jobIndex: {2} cpIndex: {3} ", clipIndex, frameIndex, jobIndex, cpIndex));
                                group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                                    group.animationData[clipIndex][frameIndex].contactPoints[i].position,
                                    group.animationData[clipIndex][frameIndex].contactPoints[i].normal
                                    //group.animationData[clipIndex][frameIndex].contactPoints[i].forward
                                    );
                                cpIndex++;
                            }

                            int lastPoimtIndex = group.animationData[clipIndex][frameIndex].contactPoints.Length - 1;
                            group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                                group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].position,
                                group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].normal
                                //group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].forward
                                );
                            cpIndex++;

                            if (cpIndex >= framesPerJob[jobIndex] * (csFeatures.middleContactsCount + 2))
                            {
                                cpIndex = 0;
                                jobIndex++;
                            }
                        }
                    }
                }
                break;

            case ContactStateMovemetType.StartLand:
                for (int clipIndex = 0; clipIndex < group.animationData.Count; clipIndex++)
                {
                    for (int frameIndex = 0; frameIndex < group.animationData[clipIndex].numberOfFrames; frameIndex++)
                    {
                        if (group.animationData[clipIndex].CanUseFrame(frameIndex))
                        {
                            group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                                group.animationData[clipIndex][frameIndex].contactPoints[0].position,
                                group.animationData[clipIndex][frameIndex].contactPoints[0].normal
                                //group.animationData[clipIndex][frameIndex].contactPoints[0].forward
                                );
                            cpIndex++;

                            int lastPoimtIndex = group.animationData[clipIndex][frameIndex].contactPoints.Length - 1;
                            group.contactPointsPerJob[jobIndex][cpIndex] = new FrameContact(
                                group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].position,
                                group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].normal
                                //group.animationData[clipIndex][frameIndex].contactPoints[lastPoimtIndex].forward
                                );
                            cpIndex++;

                            if (cpIndex >= framesPerJob[jobIndex] * 2)
                            {
                                cpIndex = 0;
                                jobIndex++;
                            }
                        }
                    }
                }
                break;
            }
        }