//public int GetWorldIndex(MWB_DummyObjectList world)
    //{
    //    return forkedDummyObjectLists.FindIndex(x => x.GetHashCode() == world.GetHashCode());
    //}

    public void Preview(MWB_Path selectedPath, int frameIndex)
    {
        if (frameIndex < 0 || frameIndex > SimulateFrameCount + 1)
        {
            Debug.LogWarning("frameIndex invalid!");
            return;
        }

        if (selectedPath == null)
        {
            Debug.LogWarning("selectedPath invalid!");
            return;
        }

        var world = selectedPath.SourceDummyObject.correspondingDummyList;

        foreach (MWB_DummyObject dummy in world.MWB_DummyObjects)
        {
            Stack <TransformDataSegment> dataSegmentStack   = new Stack <TransformDataSegment>();
            TransformDataSegment         currentDataSegment = dummy.transformDataSegment;

            while (currentDataSegment != null)
            {
                dataSegmentStack.Push(currentDataSegment);
                // travese upward in fork tree
                currentDataSegment = currentDataSegment.previousSegment;
            }

            int currentFrameIndex = 0;

            while (dataSegmentStack.Count > 0)
            {
                currentDataSegment = dataSegmentStack.Pop();
                if (currentDataSegment == null)
                {
                    break;
                }

                if (currentFrameIndex + currentDataSegment.transformData.Count > frameIndex)
                {
                    //TODO set the objects' transform
                    dummy.objectSource.transform.localPosition = currentDataSegment.transformData[frameIndex - currentFrameIndex].localPosition;
                    dummy.objectSource.transform.localRotation = currentDataSegment.transformData[frameIndex - currentFrameIndex].localRotation;
                    dummy.objectSource.transform.localScale    = currentDataSegment.transformData[frameIndex - currentFrameIndex].localScale;
                    break;
                }
                else
                {
                    currentFrameIndex += currentDataSegment.transformData.Count;
                }
            }
        }
    }
    private MWB_DummyObjectList ForkDummyObjects(MWB_DummyObjectList dummyObjectList, bool isInitializedAsAble, int worldIndex = 0)
    {
        //Debug.Log("Forking");
        GameObject parent = new GameObject("collide-forked dummy parent"); // this will also instantiate

        // !!! IMPORTANT : set the transform data of dummys' parent to the same as original objects'
        parent.transform.parent = dummyMasterParent.transform;
        // parent, which is the MWB_SYSTEM
        parent.transform.localPosition = transform.localPosition;
        parent.transform.localRotation = transform.localRotation;
        parent.transform.localScale    = transform.localScale;
        // add parent to dummyParent list for clean up !
        dummyParentList.Add(parent);

        MWB_DummyObjectList forkedDummyObjectList = new MWB_DummyObjectList();

        foreach (MWB_DummyObject mwbDummyObject in dummyObjectList.MWB_DummyObjects)
        {
            GameObject forkedObject = Instantiate(mwbDummyObject.gameObject, parent.transform);

            // Set layer
            forkedObject.layer = MWBWaitingLayer;
            forkedObject.SetActive(isInitializedAsAble);
            // initilize as kinematic
            forkedObject.GetComponent <Rigidbody>().isKinematic       = true;
            forkedObject.gameObject.GetComponent <Renderer>().enabled = false;
            //
            Destroy(forkedObject.GetComponent <MWB_Object>());

            MWB_DummyObject forkedDummy = forkedObject.GetComponent <MWB_DummyObject>();

            forkedDummy.Manager = this;
            // record object source
            forkedDummy.objectSource = mwbDummyObject.objectSource;
            // record fork source ( initial object has null )
            forkedDummy.forkedSource = mwbDummyObject;
            // record corresponding dummy list
            forkedDummy.correspondingDummyList = forkedDummyObjectList;

            // record previous transform data segment (initial dummy object has null)
            TransformDataSegment parentSegment = mwbDummyObject.transformDataSegment;
            forkedDummy.transformDataSegment.previousSegment = parentSegment;
            mwbDummyObject.transformDataSegment = new TransformDataSegment(parentSegment);

            // use main path to generate two sub
            MWB_Path parentPath = mwbDummyObject.dummyMainPath;

            //mwbDummyObject.RecordPosition(); // !!! Record position to avoid broken line segment

            mwbDummyObject.SetSubPath(parentPath);

            //mwbDummyObject.RecordPosition(); // !!! Record position to avoid broken line segment

            forkedDummy.SetSubPath(parentPath);

            // assign reference of dummy to path
            mwbDummyObject.dummyMainPath.SourceDummyObject = mwbDummyObject;
            forkedDummy.dummyMainPath.SourceDummyObject    = forkedDummy;
            //

            // set pathIndex
            //forkedDummy.pathIndex = mwbDummyObject.pathIndex;

            //
            Vector3 additionalImpulse;
            if (m_collidingDummyObjects.ContainsKey(mwbDummyObject))
            {
                // TODO : add a logical additional pulse, rather than just random a force

                Collision collision = m_collidingDummyObjects[mwbDummyObject];

                //additionalImpulse = Vector3.Cross(collision.impulse, Vector3.up) * collision.impulse.magnitude * 5f;
                //additionalImpulse = new Vector3(UnityEngine.Random.Range(-100, 100), 0, UnityEngine.Random.Range(-100, 100));

                Vector3 origin  = Vector3.zero;
                int     counter = 0;
                foreach (var contactPoint in collision.contacts)
                {
                    origin += contactPoint.point;
                    counter++;
                }
                origin /= counter;

                List <Vector3> perturbation = SinDistributionUtility.CalculatePerturbation(origin, collision.impulse);

                if (perturbation.Count > worldIndex)
                {
                    additionalImpulse = perturbation[worldIndex];
                }
                else
                {
                    additionalImpulse = perturbation[perturbation.Count - 1];
                }
            }
            else
            {
                additionalImpulse = Vector3.zero;
            }
            //

            // maintain rigidbody info , otherwise it'll only copy variables info but not state info
            RigidbodyState rigidbodyState = new RigidbodyState(mwbDummyObject.GetComponent <Rigidbody>(), additionalImpulse);
            forkedDummy.rigidbodyState = rigidbodyState;
            forkedDummyObjectList.AddToDummyObjectList(forkedDummy);
            //
        }

        return(forkedDummyObjectList);
    }
Beispiel #3
0
        public static AnimationClip GenerateClipFromDummyList(MWB_DummyObjectList dummyList)
        {
            AnimationClip clip = new AnimationClip();

            foreach (MWB_DummyObject dummy in dummyList.MWB_DummyObjects)
            {
                // stack from dummy itself to its root forked source, and reverse create clips
                Stack <TransformDataSegment> dataSegmentStack   = new Stack <TransformDataSegment>();
                TransformDataSegment         currentDataSegment = dummy.transformDataSegment;

                while (currentDataSegment != null)
                {
                    dataSegmentStack.Push(currentDataSegment);
                    // travese upward in fork tree
                    currentDataSegment = currentDataSegment.previousSegment;
                }

                // for each recorded Transform data, the time interval is Time.fixedDeltaTime
                float currentRelativeTime = 0f;
                // create curves base on the dummys in the stack

                AnimationCurve localPositionXCurve = new AnimationCurve();
                AnimationCurve localPositionYCurve = new AnimationCurve();
                AnimationCurve localPositionZCurve = new AnimationCurve();

                AnimationCurve localRotationXCurve = new AnimationCurve();
                AnimationCurve localRotationYCurve = new AnimationCurve();
                AnimationCurve localRotationZCurve = new AnimationCurve();
                AnimationCurve localRotationWCurve = new AnimationCurve();

                AnimationCurve localScaleXCurve = new AnimationCurve();
                AnimationCurve localScaleYCurve = new AnimationCurve();
                AnimationCurve localScaleZCurve = new AnimationCurve();

                while (dataSegmentStack.Count > 0)
                {
                    currentDataSegment = dataSegmentStack.Pop();
                    if (currentDataSegment == null)
                    {
                        break;
                    }

                    for (int i = 0; i < currentDataSegment.transformData.Count; i++)
                    {
                        localPositionXCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localPosition.x);
                        localPositionYCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localPosition.y);
                        localPositionZCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localPosition.z);

                        localRotationXCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localRotation.x);
                        localRotationYCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localRotation.y);
                        localRotationZCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localRotation.z);
                        localRotationWCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localRotation.w);

                        localScaleXCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localScale.x);
                        localScaleYCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localScale.y);
                        localScaleZCurve.AddKey(currentRelativeTime, currentDataSegment.transformData[i].localScale.z);

                        currentRelativeTime += Time.fixedDeltaTime;
                    }
                }
                //
                //Debug.Log("max frame = " + currentRelativeTime / Time.fixedDeltaTime);

                // set curve into the animation clip
                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localPosition.x", localPositionXCurve);
                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localPosition.y", localPositionYCurve);
                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localPosition.z", localPositionZCurve);

                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localRotation.x", localRotationXCurve);
                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localRotation.y", localRotationYCurve);
                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localRotation.z", localRotationZCurve);
                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localRotation.w", localRotationWCurve);

                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localScale.x", localScaleXCurve);
                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localScale.y", localScaleYCurve);
                clip.SetCurve(dummy.objectSource.hierachyName, typeof(Transform), "localScale.z", localScaleZCurve);
            }
            return(clip);
        }