public InstanceAnimationInfo FindAnimationInfo(string cfgName, AnimationInstancing instance) { // Debug.Assert(prefab != null); InstanceAnimationInfo info = null; if (m_animationInfo.TryGetValue(cfgName, out info)) { return(info); } //#if UNITY_IPHONE || UNITY_ANDROID // Debug.Assert(m_useBundle); // if (m_mainBundle == null) // Debug.LogError("You should call LoadAnimationAssetBundle first."); //#endif if (m_useBundle) { CreateAnimationRequest request = new CreateAnimationRequest(); request.cfgName = cfgName; request.instance = instance; if (m_mainBundle != null) { StartCoroutine(LoadAnimationInfoFromAssetBundle(request)); } else { m_requestList.Add(request); } return(null); } else { return(CreateAnimationInfoFromFile(cfgName)); } }
public void AddInstance(GameObject obj) { AnimationInstancing script = obj.GetComponent <AnimationInstancing>(); Debug.Assert(script != null); if (script == null) { Debug.LogError("The prefab you created doesn't attach the script 'AnimationInstancing'."); Destroy(obj); return; } try { bool success = script.InitializeAnimation(); if (success) { aniInstancingList.Add(script); } } catch (Exception e) { Debug.LogError(e.Message); Debug.Log("Initialize animation failed. Please check out the backed animation infos and regenerate it."); script.enabled = false; } }
public void Deattach(AnimationInstancing attachment) { attachment.visible = false; attachment.parentInstance = null; RefreshAttachmentAnimation(-1); listAttachment.Remove(attachment); }
public void UpdateAnimation() { if (aniInfo == null || curAnimation == null) { return; } curFrame += playSpeed * Time.deltaTime * curAnimation.fps; int totalFrame = curAnimation.totalFrame; if (loop) { if (curFrame < 0f) { curFrame += (totalFrame - 1); } else if (curFrame > totalFrame - 1) { curFrame -= (totalFrame - 1); } } curFrame = Mathf.Clamp(curFrame, 0f, totalFrame - 1); for (int i = 0; i != listAttachment.Count; ++i) { AnimationInstancing attachment = listAttachment[i]; attachment.transform.position = transform.position; attachment.transform.rotation = transform.rotation; } UpdateAnimationEvent(); CheckProgress(); // add by chenbin }
public GameObject CreateInstance(GameObject prefab) { Debug.Assert(prefab != null); GameObject obj = Instantiate(prefab, Vector3.zero, Quaternion.identity); AnimationInstancing script = obj.GetComponent <AnimationInstancing>(); script.prefab = prefab; return(obj); }
private void OnDestroy() { if (!AnimationInstancingMgr.IsDestroy()) { AnimationInstancingMgr.Instance.RemoveInstance(this); } if (parentInstance != null) { parentInstance.Deattach(this); parentInstance = null; } }
// Use this for initialization void Start() { if (!AnimationInstancing.AnimationInstancingMgr.Instance.UseInstancing) { avatar = GetComponent <Animator>(); } else { instancing = GetComponent <AnimationInstancing.AnimationInstancing>(); Debug.Assert(instancing); if (instancing == null) { gameObject.SetActive(false); } } }
public void RemoveInstance(AnimationInstancing instance) { Debug.Assert(aniInstancingList != null); bool removed = aniInstancingList.Remove(instance); if (removed) { --usedBoundingSphereCount; cullingGroup.SetBoundingSphereCount(usedBoundingSphereCount); Debug.Assert(usedBoundingSphereCount >= 0); if (usedBoundingSphereCount < 0) { Debug.DebugBreak(); } } }
static void DrawGizmo(AnimationInstancing instance, GizmoType gizmoType) { //Gizmos.DrawSphere(instance.gameObject.transform.position, 3); if (!instance.enabled) return; if (EditorApplication.isPlaying) return; GameObject obj = instance.gameObject; SkinnedMeshRenderer[] render = obj.GetComponentsInChildren<SkinnedMeshRenderer>(); for (int i = 0; i != render.Length; ++i) { Gizmos.DrawMesh(render[i].sharedMesh, obj.transform.position, obj.transform.rotation); } }
public void clear() { if (!AnimationInstancingMgr.IsDestroy()) { AnimationInstancingMgr.Instance.RemoveInstance(this); AnimationInstancingMgr.Instance.RemoveMeshVertex(this, lodInfo); } if (parentInstance != null) { parentInstance.Deattach(this); parentInstance = null; } Stop(); // playSpeed = 1.0f; // lodFrequencyCount = 0; }
private void RefreshAttachmentAnimation(int index) { for (int k = 0; k != listAttachment.Count; ++k) { AnimationInstancing attachment = listAttachment[k]; for (int i = 0; i != attachment.lodInfo.Length; ++i) { LodInfo info = attachment.lodInfo[i]; for (int j = 0; j != info.meshRenderer.Length; ++j) { //MeshRenderer render = info.meshRenderer[j]; AnimationInstancingMgr.VertexCache cache = info.vertexCacheList[info.skinnedMeshRenderer.Length + j]; cache.boneTextureIndex = index; } } } }
void Update() { // the attaching should be after the master's initialize, so we put it in the first update. if (!initialize) { initialize = true; AnimationInstancing.AnimationInstancing instance = GetComponent <AnimationInstancing.AnimationInstancing>(); if (instance) { int count = instance.GetAnimationCount(); instance.PlayAnimation(Random.Range(0, count)); AnimationInstancing.AnimationInstancing attachmentScript = attachment.GetComponent <AnimationInstancing.AnimationInstancing>(); instance.Attach("ik_hand_r", attachmentScript); // Deattach the attachment // instance.Deattach(attachmentScript); } } }
private void ApplyRootMotion(AnimationInstancing instance) { AnimationInfo info = instance.GetCurrentAnimationInfo(); if (info == null || !info.rootMotion) { return; } int preSampleFrame = (int)instance.curFrame; int nextSampleFrame = (int)(instance.curFrame + 1.0f); if (nextSampleFrame >= info.totalFrame) { return; } Vector3 preVelocity = info.velocity[preSampleFrame]; Vector3 nextVelocity = info.velocity[nextSampleFrame]; Vector3 velocity = Vector3.Lerp(preVelocity, nextVelocity, instance.curFrame - preSampleFrame); Vector3 angularVelocity = Vector3.Lerp(info.angularVelocity[preSampleFrame], info.angularVelocity[nextSampleFrame], instance.curFrame - preSampleFrame); { Quaternion localQuaternion = instance.worldTransform.localRotation; Quaternion delta = Quaternion.Euler(angularVelocity * Time.deltaTime); localQuaternion = localQuaternion * delta; Vector3 offset = velocity * Time.deltaTime; offset = localQuaternion * offset; //offset.y = 0.0f; Vector3 localPosition = instance.worldTransform.localPosition; localPosition += offset; #if UNITY_5_6_OR_NEWER instance.worldTransform.SetPositionAndRotation(localPosition, localQuaternion); #else instance.worldTransform.localPosition = localPosition; instance.worldTransform.localRotation = localQuaternion; #endif } }
void CreateObjInstancing() { //LoadAB(); Vector3 pos = new Vector3(); int width = (int)UnityEngine.Mathf.Sqrt((int)InstancingCount); for (int i = 0; i != InstancingCount; ++i) { GameObject prefab = m_instancingList[Random.Range(0, m_instancingList.Length)]; GameObject obj = AnimationInstancingMgr.GetInstance().CreateInstance(prefab); GameObject attachment = null; if (m_testAttachment != null) { attachment = AnimationInstancingMgr.GetInstance().CreateInstance(m_testAttachment); } Transform trans = obj.GetComponent <Transform>(); trans.SetPositionAndRotation(pos, Quaternion.identity); //trans.Rotate(new Vector3(0, 45, 0)); pos.x += 1.5f; if (pos.x > width * 1.5f) { pos.x = 0.0f; pos.z += 1.5f; } AnimationInstancing script = obj.GetComponent <AnimationInstancing>(); //script.PlayAnimation(Random.Range(0, script.m_aniInfo.Count)); AnimationInstancing attachmentScript = null; if (attachment) { attachmentScript = GetComponent <AnimationInstancing>(); } StartCoroutine(RandomPlayAnimation(script, attachmentScript)); //StartCoroutine(RandomPlayAnimation(script)); m_objs.Add(obj); } }
IEnumerator RandomPlayAnimation(AnimationInstancing script, AnimationInstancing attachment = null) { if (wait2Play == null) { wait2Play = new WaitForSeconds(2.0f); } yield return(wait2Play); script.PlayAnimation(Random.Range(0, script.GetAnimationCount())); //script.PlayAnimation(5); if (attachment != null) { //string name = Random.Range(0, 100)>50 ? "RightHand" : "LeftHand"; string name = "Prop"; script.Attach(name, attachment); //script.Attach("Neck", attachment); } if (attachment != null) { //StartCoroutine(TestDetach(script, attachment)); } }
void ApplyBoneMatrix() { Vector3 cameraPosition = cameraTransform.position; for (int i = 0; i != aniInstancingList.Count; ++i) { AnimationInstancing instance = aniInstancingList[i]; if (!instance.IsPlaying()) { continue; } if (instance.aniIndex < 0 && instance.parentInstance == null) { continue; } if (instance.applyRootMotion) { ApplyRootMotion(instance); } instance.UpdateAnimation(); instance.boundingSpere.position = instance.transform.position; boundingSphere[i] = instance.boundingSpere; if (!instance.visible) { continue; } instance.UpdateLod(cameraPosition); AnimationInstancing.LodInfo lod = instance.lodInfo[instance.lodLevel]; int aniTextureIndex = -1; if (instance.parentInstance != null) { aniTextureIndex = instance.parentInstance.aniTextureIndex; } else { aniTextureIndex = instance.aniTextureIndex; } for (int j = 0; j != lod.vertexCacheList.Length; ++j) { VertexCache cache = lod.vertexCacheList[j]; MaterialBlock block = lod.materialBlockList[j]; Debug.Assert(block != null); int packageIndex = block.runtimePackageIndex[aniTextureIndex]; Debug.Assert(packageIndex < block.packageList[aniTextureIndex].Count); InstancingPackage package = block.packageList[aniTextureIndex][packageIndex]; if (package.instancingCount + 1 > instancingPackageSize) { ++block.runtimePackageIndex[aniTextureIndex]; packageIndex = block.runtimePackageIndex[aniTextureIndex]; if (packageIndex >= block.packageList[aniTextureIndex].Count) { InstancingPackage newPackage = CreatePackage(block.instanceData, cache.mesh, cache.materials, aniTextureIndex); block.packageList[aniTextureIndex].Add(newPackage); PreparePackageMaterial(newPackage, cache, aniTextureIndex); newPackage.instancingCount = 1; } block.packageList[aniTextureIndex][packageIndex].instancingCount = 1; } else { ++package.instancingCount; } { VertexCache vertexCache = cache; InstanceData data = block.instanceData; int index = block.runtimePackageIndex[aniTextureIndex]; InstancingPackage pkg = block.packageList[aniTextureIndex][index]; int count = pkg.instancingCount - 1; if (count >= 0) { Matrix4x4 worldMat = instance.worldTransform.localToWorldMatrix; Matrix4x4[] arrayMat = data.worldMatrix[aniTextureIndex][index]; arrayMat[count].m00 = worldMat.m00; arrayMat[count].m01 = worldMat.m01; arrayMat[count].m02 = worldMat.m02; arrayMat[count].m03 = worldMat.m03; arrayMat[count].m10 = worldMat.m10; arrayMat[count].m11 = worldMat.m11; arrayMat[count].m12 = worldMat.m12; arrayMat[count].m13 = worldMat.m13; arrayMat[count].m20 = worldMat.m20; arrayMat[count].m21 = worldMat.m21; arrayMat[count].m22 = worldMat.m22; arrayMat[count].m23 = worldMat.m23; arrayMat[count].m30 = worldMat.m30; arrayMat[count].m31 = worldMat.m31; arrayMat[count].m32 = worldMat.m32; arrayMat[count].m33 = worldMat.m33; float frameIndex = 0, preFrameIndex = -1, transition = 0f; if (instance.parentInstance != null) { frameIndex = instance.parentInstance.aniInfo[instance.parentInstance.aniIndex].animationIndex + instance.parentInstance.curFrame; if (instance.parentInstance.preAniIndex >= 0) { preFrameIndex = instance.parentInstance.aniInfo[instance.parentInstance.preAniIndex].animationIndex + instance.parentInstance.preAniFrame; } transition = instance.parentInstance.transitionProgress; } else { frameIndex = instance.aniInfo[instance.aniIndex].animationIndex + instance.curFrame; if (instance.preAniIndex >= 0) { preFrameIndex = instance.aniInfo[instance.preAniIndex].animationIndex + instance.preAniFrame; } transition = instance.transitionProgress; } data.frameIndex[aniTextureIndex][index][count] = frameIndex; data.preFrameIndex[aniTextureIndex][index][count] = preFrameIndex; data.transitionProgress[aniTextureIndex][index][count] = transition; } } } } }
IEnumerator TestDetach(AnimationInstancing script, AnimationInstancing attachment) { yield return(wait2Play); script.Deattach(attachment); }
public void Attach(string boneName, AnimationInstancing attachment) { int index = -1; int hashBone = boneName.GetHashCode(); for (int i = 0; i != allTransforms.Length; ++i) { if (allTransforms[i].name.GetHashCode() == hashBone) { index = i; break; } } //Debug.Assert(index >= 0); if (index < 0) { Debug.LogError("Can't find the bone."); return; } if (attachment.lodInfo[0].meshRenderer.Length == 0 && attachment.lodInfo[0].skinnedMeshRenderer.Length == 0) { Debug.LogError("The attachment doesn't have a Renderer"); return; } attachment.parentInstance = this; AnimationInstancingMgr.VertexCache parentCache = AnimationInstancingMgr.Instance.FindVertexCache(lodInfo[0].skinnedMeshRenderer[0].name.GetHashCode()); listAttachment.Add(attachment); int nameCode = boneName.GetHashCode(); nameCode += attachment.lodInfo[0].meshRenderer.Length > 0? attachment.lodInfo[0].meshRenderer[0].name.GetHashCode(): 0; if (attachment.lodInfo[0].meshRenderer.Length == 0) { //todo, to support the attachment that has skinnedMeshRenderer; int skinnedMeshRenderCount = attachment.lodInfo[0].skinnedMeshRenderer.Length; nameCode += skinnedMeshRenderCount > 0? attachment.lodInfo[0].skinnedMeshRenderer[0].name.GetHashCode(): 0; } AnimationInstancingMgr.VertexCache cache = AnimationInstancingMgr.Instance.FindVertexCache(nameCode); // if we can reuse the VertexCache, we don't need to create one if (cache != null) { cache.boneTextureIndex = parentCache.boneTextureIndex; return; } AnimationInstancingMgr.Instance.AddMeshVertex(attachment.prototype.name, attachment.lodInfo, null, null, attachment.bonePerVertex, boneName); for (int i = 0; i != attachment.lodInfo.Length; ++i) { LodInfo info = attachment.lodInfo[i]; for (int j = 0; j != info.meshRenderer.Length; ++j) { cache = info.vertexCacheList[info.skinnedMeshRenderer.Length + j]; //Debug.Assert(cache != null); if (cache == null) { Debug.LogError("Can't find the VertexCache."); continue; } //Debug.Assert(cache.boneTextureIndex < 0 || cache.boneIndex[0].x != index); AnimationInstancingMgr.Instance.BindAttachment(parentCache, cache, info.meshFilter[j].sharedMesh, index); AnimationInstancingMgr.Instance.SetupAdditionalData(cache); cache.boneTextureIndex = parentCache.boneTextureIndex; } } }
public void UpdateAnimation() { if (aniInfo == null || IsPause()) { return; } if (isInTransition) { transitionTimer += Time.deltaTime; float weight = transitionTimer / transitionDuration; transitionProgress = Mathf.Min(weight, 1.0f); if (transitionProgress >= 1.0f) { isInTransition = false; preAniIndex = -1; preAniFrame = -1; } } float speed = playSpeed * speedParameter; curFrame += speed * Time.deltaTime * aniInfo[aniIndex].fps; int totalFrame = aniInfo[aniIndex].totalFrame; switch (wrapMode) { case WrapMode.Loop: { if (curFrame < 0f) { curFrame += (totalFrame - 1); } else if (curFrame > totalFrame - 1) { curFrame -= (totalFrame - 1); } break; } case WrapMode.PingPong: { if (curFrame < 0f) { speedParameter = Mathf.Abs(speedParameter); curFrame = Mathf.Abs(curFrame); } else if (curFrame > totalFrame - 1) { speedParameter = -Mathf.Abs(speedParameter); curFrame = 2 * (totalFrame - 1) - curFrame; } break; } case WrapMode.Default: case WrapMode.Once: { if (curFrame < 0f || curFrame > totalFrame - 1.0f) { Pause(); } break; } } curFrame = Mathf.Clamp(curFrame, 0f, totalFrame - 1); for (int i = 0; i != listAttachment.Count; ++i) { AnimationInstancing attachment = listAttachment[i]; attachment.transform.position = transform.position; attachment.transform.rotation = transform.rotation; } UpdateAnimationEvent(); }
void BakeAnimation() { #if UNITY_ANDROID || UNITY_IPHONE Debug.LogError("You can't bake animations on IOS or Android. Please switch to PC."); return; #endif if (generatedPrefab != null) { GameObject obj = Instantiate(generatedPrefab); obj.transform.position = Vector3.zero; obj.transform.rotation = Quaternion.identity; Animator animator = obj.GetComponentInChildren <Animator>(); AnimationInstancing script = obj.GetComponent <AnimationInstancing>(); Debug.Assert(script); SkinnedMeshRenderer[] meshRender = obj.GetComponentsInChildren <SkinnedMeshRenderer>(); List <Matrix4x4> bindPose = new List <Matrix4x4>(150); Transform[] boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose); Reset(); AddMeshVertex2Generate(meshRender, boneTransform, bindPose.ToArray()); Transform rootNode = meshRender[0].rootBone; for (int j = 0; j != meshRender.Length; ++j) { meshRender[j].enabled = true; } int frames = 0; var clips = GetClips(true); foreach (AnimationClip animClip in clips) { //float lastFrameTime = 0; int aniName = animClip.name.GetHashCode(); int bakeFrames = Mathf.CeilToInt(animClip.length * aniFps); AnimationInfo info = new AnimationInfo(); info.animationNameHash = aniName; info.animationIndex = frames; info.totalFrame = bakeFrames; //bool rotationRootMotion = false, positionRootMotion = false; //for (int i = 0; i < bakeFrames; i += 1) //{ // float bakeDelta = Mathf.Clamp01(((float)i / bakeFrames)); // float animationTime = bakeDelta * animClip.length; // animClip.SampleAnimation(obj, animationTime); // info.position[i] = rootNode.localPosition; // info.rotation[i] = rootNode.localRotation; // if (i > 0 && info.position[i] != info.position[i - 1]) // { // positionRootMotion = true; // } // if (i > 0 && info.rotation[i] != info.rotation[i - 1]) // { // rotationRootMotion = true; // } //} //info.rootMotion = positionRootMotion; Matrix4x4 rootMatrix1stFrame = Matrix4x4.identity; animator.applyRootMotion = true; animator.Play("TestState", 0); // animator.StartRecording(bakeFrames); // for (int i = 0; i < bakeFrames; i += 1) // { // animator.Update(1.0f / m_fps); // } // animator.StopRecording(); // // animator.StartPlayback(); // animator.playbackTime = 0; //AnimationInstancing script = m_prefab.GetComponent<AnimationInstancing>(); for (int i = 0; i < bakeFrames; i += 1) { //float bakeDelta = Mathf.Clamp01(((float)i / bakeFrames)); //float animationTime = bakeDelta * animClip.length; //float normalizedTime = animationTime / animClip.length; //UnityEditor.Animations.AnimatorController ac = animator.runtimeAnimatorController; //UnityEditorInternal.StateMachine sm = ac.GetLayerStateMachine(0); //AnimatorStateInfo nameInfo = animator.GetCurrentAnimatorStateInfo(0); // if (lastFrameTime == 0) // { // float nextBakeDelta = Mathf.Clamp01(((float)(i + 1) / bakeFrames)); // float nextAnimationTime = nextBakeDelta * animClip.length; // lastFrameTime = animationTime - nextAnimationTime; // } // animator.Update(animationTime - lastFrameTime); // lastFrameTime = animationTime; animator.Update(1.0f / bakeFrames); //animClip.SampleAnimation(obj, animationTime); //if (i == 0) //{ // rootMatrix1stFrame = boneTransform[0].localToWorldMatrix; //} for (int j = 0; j != meshRender.Length; ++j) { GenerateBoneMatrix(meshRender[j].name.GetHashCode(), aniName, i, rootMatrix1stFrame, info.rootMotion); } } aniInfo.Add(info); frames += bakeFrames; SetupAnimationTexture(aniInfo); } //AnimationInstancingMgr.Instance.ExportBoneTexture(m_prefab.name); SaveAnimationInfo(generatedPrefab.name); DestroyImmediate(obj); } }
void ApplyBoneMatrix() { Vector3 cameraPosition = cameraTransform.position; for (int i = 0; i != aniInstancingList.Count; ++i) { AnimationInstancing instance = aniInstancingList[i]; if (!instance.IsPlaying()) { continue; } if (instance.aniIndex < 0 && instance.parentInstance == null) { continue; } instance.UpdateAnimation(); if (!instance.visible) { continue; } if (instance.applyRootMotion) { ApplyRootMotion(instance); } instance.UpdateLod(cameraPosition); AnimationInstancing.LodInfo lod = instance.lodInfo[instance.lodLevel]; #if USE_CONSTANT_BUFFER VertexCache vertexCache = lod.vertexCacheList[0]; InstanceData data = vertexCache.instanceData; int aniTextureIndex = -1; if (instance.parentInstance != null) { aniTextureIndex = instance.parentInstance.aniTextureIndex; } else { aniTextureIndex = instance.aniTextureIndex; } int index = vertexCache.runtimePackageIndex[aniTextureIndex]; VertexCache.InstancingPackage pkg = vertexCache.packageList[aniTextureIndex][index]; int count = pkg.instancingCount - 1; if (count >= 0) { Matrix4x4 worldMat = instance.worldTransform.localToWorldMatrix; Matrix4x4[] arrayMat = data.worldMatrix[aniTextureIndex][index]; arrayMat[count].m00 = worldMat.m00; arrayMat[count].m01 = worldMat.m01; arrayMat[count].m02 = worldMat.m02; arrayMat[count].m03 = worldMat.m03; arrayMat[count].m10 = worldMat.m10; arrayMat[count].m11 = worldMat.m11; arrayMat[count].m12 = worldMat.m12; arrayMat[count].m13 = worldMat.m13; arrayMat[count].m20 = worldMat.m20; arrayMat[count].m21 = worldMat.m21; arrayMat[count].m22 = worldMat.m22; arrayMat[count].m23 = worldMat.m23; arrayMat[count].m30 = worldMat.m30; arrayMat[count].m31 = worldMat.m31; arrayMat[count].m32 = worldMat.m32; arrayMat[count].m33 = worldMat.m33; float frameIndex = 0; if (instance.parentInstance != null) { frameIndex = instance.parentInstance.aniInfo[instance.parentInstance.aniIndex].animationIndex + instance.parentInstance.curFrame; } else { frameIndex = instance.aniInfo[instance.aniIndex].animationIndex + instance.curFrame; } data.frameIndex[aniTextureIndex][index][count] = frameIndex; instance.boundingSpere.position.x = worldMat.m03; instance.boundingSpere.position.y = worldMat.m13; instance.boundingSpere.position.z = worldMat.m23; boundingSphere[i] = instance.boundingSpere; } for (int j = 0; j != lod.vertexCacheList.Length; ++j) { VertexCache cache = lod.vertexCacheList[j] as VertexCache; int packageIndex = cache.runtimePackageIndex[aniTextureIndex]; Debug.Assert(packageIndex < cache.packageList[aniTextureIndex].Count); VertexCache.InstancingPackage package = cache.packageList[aniTextureIndex][packageIndex]; if (package.instancingCount + 1 > instancingPackageSize) { ++cache.runtimePackageIndex[aniTextureIndex]; packageIndex = cache.runtimePackageIndex[aniTextureIndex]; if (packageIndex >= cache.packageList[aniTextureIndex].Count) { VertexCache.InstancingPackage newPackage = CreatePackage(cache.instanceData, cache.mesh, vertexCache.materials, aniTextureIndex); cache.packageList[aniTextureIndex].Add(newPackage); PreparePackageMaterial(newPackage, cache, aniTextureIndex); newPackage.instancingCount = 1; } } else { ++package.instancingCount; } } #else for (int j = 0; j != lod.vertexCacheList.Length; ++j) { VertexCache cache = lod.vertexCacheList[j] as VertexCache; if (cache.instancingData == null) { cache.instancingData = new InstancingData[cache.instancingCount]; cache.bufInstance = new ComputeBuffer((int)cache.instancingCount, 64 + 4 + 4 + 8); } Matrix4x4 worldMat = instance.worldTransform.localToWorldMatrix; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m00 = worldMat.m00; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m01 = worldMat.m01; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m02 = worldMat.m02; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m03 = worldMat.m03; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m10 = worldMat.m10; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m11 = worldMat.m11; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m12 = worldMat.m12; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m13 = worldMat.m13; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m20 = worldMat.m20; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m21 = worldMat.m21; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m22 = worldMat.m22; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m23 = worldMat.m23; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m30 = worldMat.m30; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m31 = worldMat.m31; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m32 = worldMat.m32; cache.instancingData[cache.currentInstancingIndex].worldMatrix.m33 = worldMat.m33; cache.instancingData[cache.currentInstancingIndex].frameIndex = instance.aniInfo[animationIndex].animationIndex + instance.curFrame; cache.instancingData[cache.currentInstancingIndex].animationIndex = 0; ++cache.currentInstancingIndex; } #endif } }
void BakeWithAnimator() { #if UNITY_ANDROID || UNITY_IPHONE Debug.LogError("You can't bake animations on IOS or Android. Please switch to PC."); return; #endif if (generatedPrefab != null) { generatedObject = Instantiate(generatedPrefab); generatedObject.transform.position = Vector3.zero; generatedObject.transform.rotation = Quaternion.identity; Animator animator = generatedObject.GetComponentInChildren <Animator>(); AnimationInstancing script = generatedObject.GetComponent <AnimationInstancing>(); Debug.Assert(script); SkinnedMeshRenderer[] meshRender = generatedObject.GetComponentsInChildren <SkinnedMeshRenderer>(); List <Matrix4x4> bindPose = new List <Matrix4x4>(150); Transform[] boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose); // calculate the bindpose of attached points if (generatedFbx) { List <Transform> listExtra = new List <Transform>(); Transform[] trans = generatedFbx.GetComponentsInChildren <Transform>(); Transform[] bakedTrans = generatedObject.GetComponentsInChildren <Transform>(); foreach (var obj in selectExtraBone) { if (!obj.Value) { continue; } for (int i = 0; i != trans.Length; ++i) { Transform tran = trans[i] as Transform; if (tran.name == obj.Key) { bindPose.Add(tran.localToWorldMatrix); listExtra.Add(bakedTrans[i]); } } } Transform[] totalTransform = new Transform[boneTransform.Length + listExtra.Count]; System.Array.Copy(boneTransform, totalTransform, boneTransform.Length); System.Array.Copy(listExtra.ToArray(), 0, totalTransform, boneTransform.Length, listExtra.Count); boneTransform = totalTransform; //boneTransform = boneTransform; extraBoneInfo = new ExtraBoneInfo(); extraBoneInfo.extraBone = new string[listExtra.Count]; extraBoneInfo.extraBindPose = new Matrix4x4[listExtra.Count]; for (int i = 0; i != listExtra.Count; ++i) { extraBoneInfo.extraBone[i] = listExtra[i].name; extraBoneInfo.extraBindPose[i] = bindPose[bindPose.Count - listExtra.Count + i]; } } Reset(); AddMeshVertex2Generate(meshRender, boneTransform, bindPose.ToArray()); Transform rootNode = meshRender[0].rootBone; for (int j = 0; j != meshRender.Length; ++j) { meshRender[j].enabled = true; } animator.applyRootMotion = true; totalFrame = 0; UnityEditor.Animations.AnimatorController controller = animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController; Debug.Assert(controller.layers.Length > 0); cacheTransition.Clear(); cacheAnimationEvent.Clear(); UnityEditor.Animations.AnimatorControllerLayer layer = controller.layers[0]; AnalyzeStateMachine(layer.stateMachine, animator, meshRender, 0, aniFps, 0); generateCount = generateInfo.Count; } }
void AnalyzeStateMachine(UnityEditor.Animations.AnimatorStateMachine stateMachine, Animator animator, SkinnedMeshRenderer[] meshRender, int layer, int bakeFPS, int animationIndex) { AnimationInstancing instance = generatedPrefab.GetComponent <AnimationInstancing>(); if (instance == null) { Debug.LogError("You should select a prefab with AnimationInstancing component."); return; } if (string.IsNullOrEmpty(instance.cfgName)) { instance.cfgName = generatedPrefab.name; } for (int i = 0; i != stateMachine.states.Length; ++i) { ChildAnimatorState state = stateMachine.states[i]; if (state.state == null || state.state.motion == null) // add by chenbin { continue; // add by chenbin } // add by chenbin bool needBake = false; if (!generateAnims.TryGetValue(state.state.motion.name, out needBake)) { continue; } foreach (var obj in generateInfo) { if (obj.info.animationName == state.state.motion.name) { needBake = false; break; } } if (!needBake) { continue; } AnimationBakeInfo bake = new AnimationBakeInfo(); bake.length = state.state.motion.averageDuration; bake.animator = animator; bake.animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; bake.meshRender = meshRender; bake.layer = layer; bake.info = new AnimationInfo(); bake.info.animationName = state.state.motion.name; bake.info.animationNameHash = state.state.nameHash; bake.info.animationIndex = animationIndex; bake.info.totalFrame = (int)(state.state.motion.averageDuration * bakeFPS); bake.info.fps = bakeFPS; bake.info.rootMotion = true; if (bake.info.rootMotion) { bake.info.velocity = new Vector3[bake.info.totalFrame]; bake.info.angularVelocity = new Vector3[bake.info.totalFrame]; } generateInfo.Add(bake); animationIndex += bake.info.totalFrame; totalFrame += bake.info.totalFrame; bake.info.eventList = new List <AnimationEvent>(); AnimationClip clip = state.state.motion as AnimationClip; foreach (var evt in clip.events) { AnimationEvent aniEvent = new AnimationEvent(); aniEvent.function = evt.functionName; aniEvent.floatParameter = evt.floatParameter; aniEvent.intParameter = evt.intParameter; aniEvent.stringParameter = evt.stringParameter; aniEvent.time = evt.time; if (evt.objectReferenceParameter != null) { aniEvent.objectParameter = evt.objectReferenceParameter.name; } else { aniEvent.objectParameter = ""; } bake.info.eventList.Add(aniEvent); } cacheTransition.Add(state.state, state.state.transitions); state.state.transitions = null; cacheAnimationEvent.Add(clip, clip.events); UnityEngine.AnimationEvent[] tempEvent = new UnityEngine.AnimationEvent[0]; UnityEditor.AnimationUtility.SetAnimationEvents(clip, tempEvent); } for (int i = 0; i != stateMachine.stateMachines.Length; ++i) { AnalyzeStateMachine(stateMachine.stateMachines[i].stateMachine, animator, meshRender, layer, bakeFPS, animationIndex); } }
public void AddBoundingSphere(AnimationInstancing instance) { boundingSphere[usedBoundingSphereCount++] = instance.boundingSpere; cullingGroup.SetBoundingSphereCount(usedBoundingSphereCount); instance.visible = cullingGroup.IsVisible(usedBoundingSphereCount - 1); }
public void Attach(string boneName, AnimationInstancing attachment) { int index = -1; int hashBone = boneName.GetHashCode(); for (int i = 0; i != allTransforms.Length; ++i) { if (allTransforms[i].name.GetHashCode() == hashBone) { index = i; break; } } Debug.Assert(index >= 0); if (index < 0) { Debug.LogError("Can't find the bone."); return; } attachment.parentInstance = this; // string vertexName = lodInfo[0].skinnedMeshRenderer[0].name.GetHashCode() +"_" + lodInfo[0].skinnedMeshRenderer[0].sharedMaterial.name.GetHashCode() + "_0"; AnimationInstancingMgr.VertexCache parentCache = AnimationInstancingMgr.Instance.FindVertexCache(AnimationInstancingMgr.getVertexName(lodInfo[0].skinnedMeshRenderer[0])); listAttachment.Add(attachment); int skinnedMeshRenderCount = attachment.lodInfo[0].skinnedMeshRenderer.Length; // int nameCode = attachment.lodInfo[0].meshRenderer[0].name.GetHashCode() + boneName.GetHashCode(); string nameCode = AnimationInstancingMgr.getVertexName(attachment.lodInfo[0].meshRenderer[0]); AnimationInstancingMgr.VertexCache cache = AnimationInstancingMgr.Instance.FindVertexCache(nameCode); // if we can reuse the VertexCache, we don't need to create one if (cache != null && cache.boneTextureIndex >= 0 && cache.boneTextureIndex == parentCache.boneTextureIndex && cache.boneIndex[0].x == index) { for (int i = 0; i != attachment.lodInfo.Length; ++i) { LodInfo info = attachment.lodInfo[i]; for (int j = 0; j != info.meshRenderer.Length; ++j) { nameCode = AnimationInstancingMgr.getVertexName(info.meshRenderer[j], boneName.GetHashCode()); cache = AnimationInstancingMgr.Instance.FindVertexCache(nameCode); info.vertexCacheList[info.skinnedMeshRenderer.Length + j] = cache; } } return; } AnimationInstancingMgr.Instance.AddMeshVertex(attachment, attachment.lodInfo, null, null, attachment.bonePerVertex, boneName); for (int i = 0; i != attachment.lodInfo.Length; ++i) { LodInfo info = attachment.lodInfo[i]; for (int j = 0; j != info.meshRenderer.Length; ++j) { cache = info.vertexCacheList[info.skinnedMeshRenderer.Length + j]; Debug.Assert(cache != null); if (cache == null) { Debug.LogError("Can't find the VertexCache."); continue; } Debug.Assert(cache.boneTextureIndex < 0 || cache.boneIndex[0].x != index); AnimationInstancingMgr.Instance.BindAttachment(parentCache, info.meshFilter[j].sharedMesh, index); AnimationInstancingMgr.Instance.SetupAdditionalData(cache); cache.boneTextureIndex = parentCache.boneTextureIndex; } } }