public void Init() { if (player != null) { return; } if (anim != null && mesh != null && mtrl != null && textureRawData != null) { GPUSkinningPlayerResources res = null; if (Application.isPlaying) { playerManager.Register(anim, mesh, mtrl, textureRawData, this, out res); } else { res = new GPUSkinningPlayerResources(); res.anim = anim; res.mesh = mesh; res.mtrl = new Material(mtrl); res.texture = GPUSkinningUtil.CreateTexture2D(textureRawData, anim); res.mtrl.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor; res.texture.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor; } player = new GPUSkinningPlayer(gameObject, res); player.RootMotionEnabled = Application.isPlaying ? rootMotionEnabled : false; if (anim != null && anim.clips != null && anim.clips.Length > 0) { player.Play(anim.clips[Mathf.Clamp(defaultPlayingClipIndex, 0, anim.clips.Length)].name); } } }
public override void Init(GPUSkinning gpuSkinning) { base.Init(gpuSkinning); newLodMesh = new Mesh(); newLodMesh.vertices = lodMesh.vertices; newLodMesh.uv = lodMesh.uv; newLodMesh.triangles = lodMesh.triangles; newLodMesh.tangents = GPUSkinningUtil.ExtractBoneWeights(lodMesh); additionalVertexStreames = new GPUSkinning_AdditionalVertexStreames(newLodMesh); // Bounding Sphere lodBoundingSpheres = new BoundingSphere[gpuSkinning.model.spawnObjects.Length]; for (int i = 0; i < lodBoundingSpheres.Length; ++i) { lodBoundingSpheres[i] = new BoundingSphere(gpuSkinning.model.spawnObjects[i].transform.position, 1f); } // Culling Group lodCullingGroup = new CullingGroup(); lodCullingGroup.targetCamera = Camera.main; lodCullingGroup.SetBoundingSpheres(lodBoundingSpheres); lodCullingGroup.SetBoundingSphereCount(lodBoundingSpheres.Length); lodCullingGroup.SetBoundingDistances(new float[] { 10, 15, 25, 40 }); lodCullingGroup.SetDistanceReferencePoint(Camera.main.transform); lodCullingGroup.onStateChanged = OnLodCullingGroupOnStateChangedHandler; newLodMesh.UploadMeshData(true); }
public void Register(GPUSkinningAnimation anim, Mesh mesh, Material originalMtrl, TextAsset textureRawData, GPUSkinningPlayerMono player, out GPUSkinningPlayerResources resources) { resources = null; if (anim == null || originalMtrl == null || textureRawData == null || player == null) { return; } GPUSkinningPlayerResources item = null; int numItems = items.Count; for (int i = 0; i < numItems; ++i) { if (items[i].anim.guid == anim.guid) { item = items[i]; break; } } if (item == null) { item = new GPUSkinningPlayerResources(); items.Add(item); } if (item.anim == null) { item.anim = anim; } if (item.mesh == null) { item.mesh = mesh; } if (item.mtrl == null) { item.mtrl = new Material(originalMtrl); } if (item.texture == null) { item.texture = GPUSkinningUtil.CreateTexture2D(textureRawData, anim); } if (!item.players.Contains(player)) { item.players.Add(player); } resources = item; }
private void GenerateBonesGUID(GPUSkinningBone[] bones) { int numBones = bones == null ? 0 : bones.Length; for (int i = 0; i < numBones; ++i) { string boneHierarchyPath = GPUSkinningUtil.BoneHierarchyPath(bones, i); string guid = GPUSkinningUtil.MD5(boneHierarchyPath); bones[i].guid = guid; } }
/// <summary> /// 初始化PlayerMono设置: /// 创建/查询对应的GPUSkinningPlayerResources,通过GPUSkinningPlayerManager管理 /// fzy remark:初始化存在潜在的开销问题,在首次生成PlayerMono时,Creating CullingBounds会产生较大的开销 /// </summary> public void Init() { //player != null 表示已经初始化,return结束执行 if (player != null) { return; } GPUSkinningPlayerResources res = null; //所有属性设置完毕,开始初始化 if (anim != null && mesh != null && mtrl != null && textureRawData != null) { //运行时,注册蒙皮网格、动画、材质等数据 if (Application.isPlaying) { playerManager.Register(anim, mesh, mtrl, textureRawData, this, out res); } else { //编辑时,创建蒙皮网格资源实例,保存数据 res = new GPUSkinningPlayerResources(); res.anim = anim; res.mesh = mesh; res.texture = GPUSkinningUtil.CreateTexture2D(textureRawData, anim); res.texture.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor; //初始化Material(一共有6种Material) //创建的Material和Texture不保存(游戏运行时在Project视图无法找到索引,游戏运行后销毁) res.InitMaterial(mtrl, HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor); } player = new GPUSkinningPlayer(gameObject, res); // 非运行状态设置为false(preview) player.RootMotionEnabled = Application.isPlaying ? rootMotionEnabled : false; player.LODEnabled = Application.isPlaying ? lodEnabled : false; // 动画片段播放的设置 player.CullingMode = cullingMode; if (anim != null && anim.clips != null && anim.clips.Length > 0) { player.Play(anim.clips[Mathf.Clamp(defaultPlayingClipIndex, 0, anim.clips.Length)].name); } } // fzy add: myRes = res; mf = GetComponent <MeshFilter>(); mf.sharedMesh = mesh; mr = GetComponent <MeshRenderer>(); SetMaterial(GPUSkinningPlayerResources.MaterialState.RootOff_BlendOff); mpb = new MaterialPropertyBlock(); }
public void Init() { if (player != null) { return; } if (anim != null && mesh != null && mtrl != null && textureRawData != null) { GPUSkinningPlayerResources res = null; if (Application.isPlaying) { //if (EZ.Global.gApp.CurScene != null && EZ.Global.gApp.CurScene.GetPlayerMgr() != null) if (EZ.Global.gApp.CurScene != null) { m_PlayerMonoManager.Register(anim, mesh, mtrl, textureRawData, this, out res); } else { return; } } else { res = new GPUSkinningPlayerResources(); res.anim = anim; res.mesh = mesh; res.InitMaterial(mtrl, HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor); res.texture = GPUSkinningUtil.CreateTexture2D(textureRawData, anim); res.texture.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor; } player = new GPUSkinningPlayer(gameObject, res); //player.RootMotionEnabled = Application.isPlaying ? rootMotionEnabled : false; player.RootMotionEnabled = false; //player.LODEnabled = Application.isPlaying ? lodEnabled : false; player.LODEnabled = false; player.CullingMode = cullingMode; if (anim != null && anim.clips != null && anim.clips.Length > 0) { player.Play(anim.clips[Mathf.Clamp(defaultPlayingClipIndex, 0, anim.clips.Length)].name); } } }
private void BakeAnimationsToTexture() { if (matricesTex != null) { Color[] colorBuffer = matricesTex.GetPixels(); int colorBufferIndex = 0; hierarchyMatrices = new Matrix4x4[colorBuffer.Length / 3]; int hierarchyMatrixIndex = 0; GPUSkinningUtil.ExtractBoneAnimMatrix( gpuSkinning, gpuSkinning.model.boneAnimations[0], (animMat, hierarchyMat) => { hierarchyMatrices[hierarchyMatrixIndex++] = hierarchyMat; Color c = colorBuffer[colorBufferIndex]; c.r = animMat.m00; c.g = animMat.m01; c.b = animMat.m02; c.a = animMat.m03; colorBuffer[colorBufferIndex++] = c; c = colorBuffer[colorBufferIndex]; c.r = animMat.m10; c.g = animMat.m11; c.b = animMat.m12; c.a = animMat.m13; colorBuffer[colorBufferIndex++] = c; c = colorBuffer[colorBufferIndex]; c.r = animMat.m20; c.g = animMat.m21; c.b = animMat.m22; c.a = animMat.m23; colorBuffer[colorBufferIndex++] = c; }, (frameIndex) => { if (frameIndex == 0) { numHierarchyMatricesPerFrame = hierarchyMatrixIndex; numPixelsPerFrame = colorBufferIndex; } } ); matricesTex.SetPixels(colorBuffer); matricesTex.Apply(false, true); } }
private void DeleteInvalidJoints(GPUSkinningPlayerJoint[] joints) { if (joints != null) { for (int i = 0; i < joints.Length; ++i) { if (joints[i] != null) { for (int j = 0; j < joints[i].transform.childCount; ++j) { Transform child = joints[i].transform.GetChild(j); child.parent = go.transform; child.localPosition = Vector3.zero; } Object.DestroyImmediate(joints[i].transform.gameObject); GPUSkinningUtil.MarkAllScenesDirty(); } } } }
public override void Init(GPUSkinning gpuSkinning) { base.Init(gpuSkinning); if (!SystemInfo.supportsComputeShaders) { return; } shaderPropID_Time = Shader.PropertyToID("_GameTime"); // Material Shader shader = Shader.Find("Unlit/ProceduralModel"); if (!shader.isSupported) { return; } proceduralModelMaterial = new Material(shader); proceduralModelMaterial.mainTexture = gpuSkinning.model.newMtrl.mainTexture; // Vertices int[] indices = gpuSkinning.model.newMesh.triangles; Vector3[] vertices = gpuSkinning.model.newMesh.vertices; Vector4[] tangents = gpuSkinning.model.newMesh.tangents; Vector2[] uv = gpuSkinning.model.newMesh.uv; verticesComputeBuffer = new ComputeBuffer(indices.Length, GPUSkinning_ComputeShader_Vertex.size); var data = new GPUSkinning_ComputeShader_Vertex[indices.Length]; for (int i = 0; i < indices.Length; ++i) { var item = new GPUSkinning_ComputeShader_Vertex(); item.vertex = vertices[indices[i]]; item.tangents = tangents[indices[i]]; item.uv = uv[indices[i]]; data[i] = item; } verticesComputeBuffer.SetData(data); numVertices_computeBuffer = data.Length; // Global Data var globalData = new GPUSkinning_CompueteShader_GlobalData(); globalData.fps = gpuSkinning.model.boneAnimations[0].fps; globalData.animLength = gpuSkinning.model.boneAnimations[0].length; // Bone Animation Matrices List <GPUSkinning_ComputeShader_Matrix> cbMatricesList = new List <GPUSkinning_ComputeShader_Matrix>(); int matIndex = 0; GPUSkinningUtil.ExtractBoneAnimMatrix( gpuSkinning, gpuSkinning.model.boneAnimations[0], (animMat, hierarchyMat) => { var matData = new GPUSkinning_ComputeShader_Matrix(); matData.mat = animMat; cbMatricesList.Add(matData); ++matIndex; }, (frameIndex) => { if (frameIndex == 0) { globalData.oneFrameMatricesStride = matIndex; } } ); matricesComputeBuffer = new ComputeBuffer(cbMatricesList.Count, GPUSkinning_ComputeShader_Matrix.size); matricesComputeBuffer.SetData(cbMatricesList.ToArray()); // Global Data globalDataComputeBuffer = new ComputeBuffer(1, GPUSkinning_CompueteShader_GlobalData.size); globalDataComputeBuffer.SetData(new GPUSkinning_CompueteShader_GlobalData[] { globalData }); // Procedural Model Data var modelData = new GPUSkinning_ComputeShader_Model[numProceduralInstances]; int numProceduralModelsPerRow = (int)Mathf.Sqrt(numProceduralInstances); for (int i = 0; i < numProceduralInstances; ++i) { var aModelData = new GPUSkinning_ComputeShader_Model(); int row = i / numProceduralModelsPerRow; int col = i - row * numProceduralModelsPerRow; aModelData.pos = new Vector3(-row * proceduralModelGap, -1, -col * proceduralModelGap); aModelData.time = Random.Range(0.0f, 10.0f); modelData[i] = aModelData; } modelDataComputeBuffer = new ComputeBuffer(numProceduralInstances, GPUSkinning_ComputeShader_Model.size); modelDataComputeBuffer.SetData(modelData); // Draw Procedural Model GPUSkinning_Camera.instance.onPostRender += Draw; }
public override void Init(GPUSkinning gpuSkinning) { base.Init(gpuSkinning); shaderPropID_Time = Shader.PropertyToID("_GameTime"); smr = gpuSkinning.GetComponentInChildren <SkinnedMeshRenderer>(); mesh = smr.sharedMesh; // Init Bones int numBones = smr.bones.Length; bones = new GPUSkinning_Bone[numBones]; for (int i = 0; i < numBones; ++i) { GPUSkinning_Bone bone = new GPUSkinning_Bone(); bones[i] = bone; bone.transform = smr.bones[i]; bone.name = bone.transform.gameObject.name; bone.bindpose = mesh.bindposes[i] /*smr to bone*/; } // Construct Hierarchy for (int i = 0; i < numBones; ++i) { if (bones[i].transform == smr.rootBone) { rootBoneIndex = i; break; } } System.Action <GPUSkinning_Bone> CollectChildren = null; CollectChildren = (currentBone) => { List <GPUSkinning_Bone> children = new List <GPUSkinning_Bone>(); for (int j = 0; j < currentBone.transform.childCount; ++j) { Transform childTransform = currentBone.transform.GetChild(j); GPUSkinning_Bone childBone = GetBoneByTransform(childTransform); if (childBone != null) { childBone.parent = currentBone; children.Add(childBone); CollectChildren(childBone); } } currentBone.children = children.ToArray(); }; CollectChildren(bones[rootBoneIndex]); // New MeshFilter MeshRenderer mf = gpuSkinning.gameObject.AddComponent <MeshFilter>(); mr = gpuSkinning.gameObject.AddComponent <MeshRenderer>(); newMtrl = new Material(Shader.Find("Unlit/GPUSkinning")); newMtrl.CopyPropertiesFromMaterial(smr.sharedMaterial); mr.sharedMaterial = newMtrl; // New Mesh newMesh = new Mesh(); newMesh.vertices = mesh.vertices; newMesh.tangents = GPUSkinningUtil.ExtractBoneWeights(mesh); newMesh.uv = mesh.uv; newMesh.triangles = mesh.triangles; mf.sharedMesh = newMesh; #if UNITY_EDITOR // Extract bone animation data int boneAnimationsCount = 0; boneAnimations = new GPUSkinning_BoneAnimation[gpuSkinning.GetComponent <Animator>().runtimeAnimatorController.animationClips.Length]; foreach (AnimationClip animClip in gpuSkinning.GetComponent <Animator>().runtimeAnimatorController.animationClips) { GPUSkinning_BoneAnimation boneAnimation = ScriptableObject.CreateInstance <GPUSkinning_BoneAnimation>(); boneAnimation.fps = 60; boneAnimation.animName = animClip.name; boneAnimation.frames = new GPUSkinning_BoneAnimationFrame[(int)(animClip.length * boneAnimation.fps)]; boneAnimation.length = animClip.length; boneAnimations[boneAnimationsCount++] = boneAnimation; for (int frameIndex = 0; frameIndex < boneAnimation.frames.Length; ++frameIndex) { GPUSkinning_BoneAnimationFrame frame = new GPUSkinning_BoneAnimationFrame(); boneAnimation.frames[frameIndex] = frame; float second = (float)(frameIndex) / (float)boneAnimation.fps; List <GPUSkinning_Bone> bones2 = new List <GPUSkinning_Bone>(); List <Matrix4x4> matrices = new List <Matrix4x4>(); List <string> bonesHierarchyNames = null; if (boneAnimation.bonesHierarchyNames == null) { bonesHierarchyNames = new List <string>(); } EditorCurveBinding[] curvesBinding = AnimationUtility.GetCurveBindings(animClip); foreach (var curveBinding in curvesBinding) { GPUSkinning_Bone bone = GetBoneByHierarchyName(curveBinding.path); if (bones2.Contains(bone)) { continue; } bones2.Add(bone); if (bonesHierarchyNames != null) { bonesHierarchyNames.Add(GetBoneHierarchyName(bone)); } AnimationCurve curveRX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.x"); AnimationCurve curveRY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.y"); AnimationCurve curveRZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.z"); AnimationCurve curveRW = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.w"); AnimationCurve curvePX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.x"); AnimationCurve curvePY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.y"); AnimationCurve curvePZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.z"); float curveRX_v = curveRX.Evaluate(second); float curveRY_v = curveRY.Evaluate(second); float curveRZ_v = curveRZ.Evaluate(second); float curveRW_v = curveRW.Evaluate(second); float curvePX_v = curvePX.Evaluate(second); float curvePY_v = curvePY.Evaluate(second); float curvePZ_v = curvePZ.Evaluate(second); Vector3 translation = new Vector3(curvePX_v, curvePY_v, curvePZ_v); Quaternion rotation = new Quaternion(curveRX_v, curveRY_v, curveRZ_v, curveRW_v); NormalizeQuaternion(ref rotation); matrices.Add( Matrix4x4.TRS(translation, rotation, Vector3.one) ); } frame.bones = bones2.ToArray(); frame.matrices = matrices.ToArray(); if (boneAnimation.bonesHierarchyNames == null) { boneAnimation.bonesHierarchyNames = bonesHierarchyNames.ToArray(); } } } // Save as ScriptableObject AssetDatabase.CreateAsset(boneAnimations[0], "Assets/GPUSkinning/Resources/anim0.asset"); AssetDatabase.Refresh(); #else // Read from ScriptableObject directly boneAnimations = new GPUSkinning_BoneAnimation[] { Resources.Load("anim0") as GPUSkinning_BoneAnimation }; foreach (var boneAnimation in boneAnimations) { foreach (var frame in boneAnimation.frames) { int numBones2 = boneAnimation.bonesHierarchyNames.Length; frame.bones = new GPUSkinning_Bone[numBones2]; for (int i = 0; i < numBones2; ++i) { frame.bones[i] = GetBoneByHierarchyName(boneAnimation.bonesHierarchyNames[i]); } } } #endif // Spawn many models if (spawnPoints != null) { List <GPUSkinning_SpawnObject> list = new List <GPUSkinning_SpawnObject>(); for (int i = 0; i < spawnPoints.Length; ++i) { for (int j = 0; j < spawnPoints[i].childCount; ++j) { GPUSkinning_SpawnObject spawnObject = new GPUSkinning_SpawnObject(); list.Add(spawnObject); spawnObject.transform = spawnPoints[i].GetChild(j); spawnObject.mf = spawnObject.transform.gameObject.AddComponent <MeshFilter>(); spawnObject.mr = spawnObject.transform.gameObject.AddComponent <MeshRenderer>(); spawnObject.mr.sharedMaterial = newMtrl; spawnObject.mf.sharedMesh = newMesh; } } spawnObjects = list.ToArray(); } }
private void ConstructJoints() { if (joints == null) { GPUSkinningPlayerJoint[] existingJoints = go.GetComponentsInChildren <GPUSkinningPlayerJoint>(); GPUSkinningBone[] bones = res.anim.bones; int numBones = bones == null ? 0 : bones.Length; for (int i = 0; i < numBones; ++i) { GPUSkinningBone bone = bones[i]; if (bone.isExposed) { if (joints == null) { joints = new List <GPUSkinningPlayerJoint>(); } bool inTheExistingJoints = false; if (existingJoints != null) { for (int j = 0; j < existingJoints.Length; ++j) { if (existingJoints[j] != null && existingJoints[j].BoneGUID == bone.guid) { if (existingJoints[j].BoneIndex != i) { existingJoints[j].Init(i, bone.guid); GPUSkinningUtil.MarkAllScenesDirty(); } joints.Add(existingJoints[j]); existingJoints[j] = null; inTheExistingJoints = true; break; } } } if (!inTheExistingJoints) { GameObject jointGo = new GameObject(bone.name); jointGo.transform.parent = go.transform; jointGo.transform.localPosition = Vector3.zero; jointGo.transform.localScale = Vector3.one; GPUSkinningPlayerJoint joint = jointGo.AddComponent <GPUSkinningPlayerJoint>(); joints.Add(joint); joint.Init(i, bone.guid); GPUSkinningUtil.MarkAllScenesDirty(); } } } if (!Application.isPlaying) { #if UNITY_EDITOR UnityEditor.EditorApplication.CallbackFunction DelayCall = null; DelayCall = () => { UnityEditor.EditorApplication.delayCall -= DelayCall; DeleteInvalidJoints(existingJoints); }; UnityEditor.EditorApplication.delayCall += DelayCall; #endif } else { DeleteInvalidJoints(existingJoints); } } }
//注册需要渲染的模型种类 public void Register(GPUSkinningAnimation anim, Mesh mesh, Material originalMtrl, TextAsset textureRawData, GPUSkinningPlayerMono player, out GPUSkinningPlayerResources resources) { resources = null; if (anim == null || originalMtrl == null || textureRawData == null || player == null) { return; } // item完成初始化后赋值给resources GPUSkinningPlayerResources item = null; int numItems = items.Count; //查询该anim是否已注册,根据guid(唯一标识符)判断 for (int i = 0; i < numItems; ++i) { if (items[i].anim.guid == anim.guid) { //找到已注册的Resources,赋值给item item = items[i]; break; } } #region 未找到,初始化赋值 if (item == null) { item = new GPUSkinningPlayerResources(); //Debug.Log("new"); items.Add(item); } if (item.anim == null) { item.anim = anim; } if (item.mesh == null) { item.mesh = mesh; } if (item.texture == null) { item.texture = GPUSkinningUtil.CreateTexture2D(textureRawData, anim); } item.InitMaterial(originalMtrl, HideFlags.None); #endregion //为player设置CullingBounds(在CullingGroup中) if (!item.players.Contains(player)) { item.players.Add(player); // fzy delete:culling //item.AddCullingBounds(); } resources = item; }