//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); }
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); }