public static SMesh BakeMesh(Transform transform, Mesh mesh, bool rendererEnabled, SVector3Array customVertices = null) { SMesh surrogate = new SMesh(transform, mesh.name, mesh.GetInstanceID(), transform.gameObject.activeInHierarchy && rendererEnabled); surrogate.header.type = SMesh.Type.full; CopyMeshData(mesh, surrogate, customVertices); return surrogate; }
public static bool CheckMeshKeyFrame(SMesh mesh) { return mesh != null && mesh.vertices != null && mesh.vertices.count > 0 && mesh.triangles != null && mesh.triangles.Length > 0; }
private void OnDestroy(){ if (this.mesh != null) UnityEngine.Object.DestroyImmediate(this.mesh); DisposeMaterials(); materials = null; mesh = null; meshFilter = null; keyframeMesh = null; previousMesh = null; }
public void GetResultEOF(ref int streamPriority, GameObject go, MeshCaptureMethod captureMethod, bool forceKeyframe, List<SMesh> storeTo) { MeshFilter[] filters = go.GetComponentsInChildren<MeshFilter>(true); //Debug.Log("found: " + go.name + ", count: " + filters.Length); foreach (MeshFilter filter in filters) { MeshRenderer renderer = filter.gameObject.GetComponent<MeshRenderer>(); if (renderer == null) continue; Mesh mesh = null; SMesh surrogate = null; switch (captureMethod) { case MeshCaptureMethod.smartMesh: mesh = SceneHierarchyCache.GetMesh(filter); //mesh = filter.sharedMesh != null ? filter.sharedMesh : filter.mesh; if (mesh != null) { if (forceKeyframe) { surrogate = MeshGrabberHelper.BakeMesh(filter.transform, mesh, renderer.enabled); streamPriority ++; } else { surrogate = new SMesh(filter.transform, mesh.name, mesh.GetInstanceID(), filter.gameObject.activeInHierarchy && renderer.enabled); } } else { if (vBug.settings.general.debugMode) Debug.LogWarning("Mesh == Null"); } break; case MeshCaptureMethod.fullMesh: mesh = filter.sharedMesh != null ? filter.sharedMesh : filter.mesh; if (mesh != null) { surrogate = MeshGrabberHelper.BakeMesh(filter.transform, mesh, renderer.enabled); streamPriority++; } else { if (vBug.settings.general.debugMode) Debug.LogWarning("Mesh == Null"); } break; } if (surrogate != null) { if (surrogate.subMeshes != null) surrogate.subMeshes.materialIDs = MaterialDataGrabber.RegisterMaterials(renderer); storeTo.Add(surrogate); } else { if (vBug.settings.general.debugMode) Debug.Log(go.name + "_" + filter.name + " has no SMesh!!! " + captureMethod + ", changed? " + MeshDataChangeDetector.DetectChange(filter.GetInstanceID(), mesh, filter.transform)); } } }
public static SMesh BakeBonesOnly(SkinnedMeshRenderer source) { if (source == null) return null; Mesh mesh = SceneHierarchyCache.GetMesh(source); if (mesh == null) return null; Renderer renderer = source.gameObject.GetComponent<Renderer>(); SMesh surrogate = new SMesh(source.transform, mesh.name, mesh.GetInstanceID(), source.gameObject.activeInHierarchy && (renderer != null && renderer.enabled)); surrogate.header.type = SMesh.Type.bonesOnly; CopyBoneTransform(source, surrogate); return surrogate; }
public void SetCurrentFrame(int frameNumber){ if (frameNumber == currentFrameNumber) return; SMesh currentMesh = GetClosestAvailableMesh(frameNumber, false, vBugEditorSettings.PlaybackMeshSearchRange); if (SceneVisualsHelper.CheckMeshKeyFrame(currentMesh)) //if we can use this as a keyframe-mesh keyframeMesh = currentMesh; if(keyframeMesh == null)//Check if not previously set keyframeMesh = GetClosestAvailableMesh(frameNumber, true, vBugEditorSettings.PlaybackMeshSearchRange); //if unusable and still null if (currentMesh == null || keyframeMesh == null) return; if (DetectChanges(currentMesh)) ApplyMeshData(frameNumber, currentMesh); currentFrameNumber = frameNumber; previousMesh = currentMesh; }
private static void CopyMeshData(Mesh mesh, SMesh destination, SVector3Array customVertices = null) { destination.triangles = mesh.triangles; destination.subMeshes = new SSubMeshArray(mesh); if (customVertices != null) { destination.vertices = customVertices; } else { destination.vertices = new SVector3Array(mesh.vertices); } if (mesh.uv != null) destination.uv = new SVector2Array(mesh.uv); #if UNITY_4_6 if (mesh.uv1 != null) destination.uv1 = new SVector2Array(mesh.uv1); #endif if (mesh.uv2 != null) destination.uv2 = new SVector2Array(mesh.uv2); #if !UNITY_4_6 if (mesh.uv3 != null) destination.uv3 = new SVector2Array(mesh.uv3); if (mesh.uv4 != null) destination.uv4 = new SVector2Array(mesh.uv4); #endif }
private static void CopyBoneWeights(Mesh source, SMesh destination) { BoneWeight[] weights = SceneHierarchyCache.GetBoneWeights(source); if (weights == null) return; destination.boneWeights = new SBoneWeightArray(weights); }
private static void CopyBoneTransform(SkinnedMeshRenderer source, SMesh destination) { Transform[] bones = source.bones; if (bones == null) return; int rootID = -1; if (source.rootBone != null) source.rootBone.GetInstanceID(); destination.bones = new SBonesArray(bones, rootID); }
private Vector3[] GetMeshVertices(SMesh mesh) { int vMax = mesh.vertices.count; Vector3[] result = new Vector3[vMax]; int v = vMax; while (--v > -1) result[v] = keyframeMesh.vertices.GetVertex(v); return result; }
public Vector3[] ApplyBoneWeights(SMesh keyframeMesh, SMesh currentMesh) { if (keyframeMesh == null || currentMesh == null) { if (vBugEditorSettings.DebugMode) Debug.LogError("Error: keyframeMesh || currentMesh null: " + currentMesh + ", " + keyframeMesh); return null; } //--------------- Get Bones Matrix -------------------- SBoneWeightArray boneWeights = (keyframeMesh.boneWeights != null && keyframeMesh.boneWeights.count > 0) ? keyframeMesh.boneWeights : currentMesh.boneWeights; if (boneWeights == null) { if (vBugEditorSettings.DebugMode) Debug.LogError("Error @ " + currentMesh.header.parentName + ": boneWeight null"); return null; } int bMax = boneWeights.count; BoneWeight[] weights = new BoneWeight[bMax]; int b = bMax; while (--b > -1) weights[b] = boneWeights.GetBoneWeight(b); //--------------- Get Bones Matrix -------------------- //--------------- Init -------------------- if (currentMesh.bones == null || currentMesh.bones.count == 0 || weights.Length == 0) { if (vBugEditorSettings.DebugMode) Debug.LogError("Error @ " + currentMesh.header.parentName + ": currentMesh.bones null || currentMesh.bones.count == 0 || weights.Length == 0"); return null; } int vMax = keyframeMesh.vertices.count; Vector3[] result = new Vector3[vMax]; Vector3[] vertices = GetMeshVertices(keyframeMesh); if (weights.Length != vertices.Length || keyframeMesh.bindPoses.count != currentMesh.bones.count) {// should not happen, but anyways if (vBugEditorSettings.DebugMode) Debug.LogError("Error: " + weights.Length + ", " + currentMesh.bindPoses.count + ", " + currentMesh.bones.count); return ApplyMeshMatrix(keyframeMesh, currentMesh); } Matrix4x4[] boneMatrices = new Matrix4x4[currentMesh.bones.count]; int i = currentMesh.bones.count; while (--i > -1) boneMatrices[i] = currentMesh.bones.matrices.GetMatrix(i) * keyframeMesh.bindPoses.GetMatrix(i); i = 0; int iMax = vertices.Length; //--------------- Init -------------------- //--------------- Apply influences -------------------- while (i < iMax) { BoneWeight boneWeight = weights[i]; Vector3 oV = vertices[i]; Vector3 v = oV; float wTotal = 0f; float weight0 = boneWeight.weight0; float weight1 = boneWeight.weight1; float weight2 = boneWeight.weight2; float weight3 = boneWeight.weight3; if (weight0 > 0f) { v = boneMatrices[boneWeight.boneIndex0].MultiplyPoint3x4(oV) * weight0; wTotal = weight0; } if (weight1 > 0f) { v += boneMatrices[boneWeight.boneIndex1].MultiplyPoint3x4(oV) * weight1; wTotal += weight1; } if (weight2 > 0f) { v += boneMatrices[boneWeight.boneIndex2].MultiplyPoint3x4(oV) * weight2; wTotal += weight2; } if (weight3 > 0f) { v += boneMatrices[boneWeight.boneIndex3].MultiplyPoint3x4(oV) * weight3; wTotal += weight3; } if (wTotal < 1f) v /= wTotal; result[i++] = v; } //--------------- Apply influences -------------------- return result; }
private Vector3[] ApplyMeshMatrix(SMesh keyframeMesh, SMesh currentMesh) { int vMax = keyframeMesh.vertices.count; Vector3[] result = new Vector3[vMax]; Matrix4x4 matrix = currentMesh.header.matrix; int v = vMax; while (--v > -1) result[v] = matrix.MultiplyPoint(keyframeMesh.vertices.GetVertex(v)); return result; }
//--------------------------------------- DETECT CHANGE PERFORMANCE OPTIMIZE -------------------------------------- //--------------------------------------- DETECT CHANGE PERFORMANCE OPTIMIZE -------------------------------------- //--------------------------------------- APPLY BONES TO VERTICES -------------------------------------- //--------------------------------------- APPLY BONES TO VERTICES -------------------------------------- #region APPLY BONES TO VERTICES private void ApplyMeshData(int frameNumber, SMesh currentMesh) { if (!currentMesh.header.activeInHierarchy) { isEnabled = false; } else { isEnabled = true; int vMax = keyframeMesh.vertices.count; //--------------- Vertices -------------------- Vector3[] vertices = new Vector3[vMax]; if (currentMesh.header.type == SMesh.Type.full || currentMesh.bones == null || currentMesh.bones.count == 0) { vertices = ApplyMeshMatrix(keyframeMesh, currentMesh); } else { vertices = ApplyBoneWeights(keyframeMesh, currentMesh); } //--------------- Vertices -------------------- if (vertices != null && vertices.Length > 0) { //--------------- Set mesh-data -------------------- if (this.mesh != null) { this.mesh.Clear(); this.mesh.vertices = vertices; this.mesh.triangles = keyframeMesh.triangles; if (keyframeMesh.uv != null && keyframeMesh.uv.count > 0) this.mesh.uv = keyframeMesh.uv.GetVertexArray(); #if UNITY_4_6 if (keyframeMesh.uv1 != null && keyframeMesh.uv1.count > 0) this.mesh.uv1 = keyframeMesh.uv1.GetVertexArray(); #endif if (keyframeMesh.uv2 != null && keyframeMesh.uv2.count > 0) this.mesh.uv2 = keyframeMesh.uv2.GetVertexArray(); #if !UNITY_4_6 if (keyframeMesh.uv3 != null && keyframeMesh.uv3.count > 0) this.mesh.uv3 = keyframeMesh.uv3.GetVertexArray(); if (keyframeMesh.uv4 != null && keyframeMesh.uv4.count > 0) this.mesh.uv4 = keyframeMesh.uv4.GetVertexArray(); #endif this.mesh.RecalculateNormals(); this.mesh.tangents = CalculateCheapTangents(keyframeMesh.triangles, vertices, mesh.normals); //this.mesh.Optimize(); } //--------------- Set mesh-data -------------------- //--------------- Set submesh-data -------------------- if (keyframeMesh.subMeshes != null) { if (keyframeMesh.subMeshes.triangles != null) { int i = keyframeMesh.subMeshes.triangles.Length; this.mesh.subMeshCount = i; while (--i > -1) this.mesh.SetTriangles(keyframeMesh.subMeshes.triangles[i], i); } if (keyframeMesh.subMeshes.materialIDs != null) { DisposeMaterials(); Material[] materials = EditorMaterialHelper.GetClosestAvailableMaterialsByID(keyframeMesh.subMeshes.materialIDs, frameNumber); if (materials != null && materials.Length > 0) this.meshRenderer.sharedMaterials = materials; EditorMaterialHelper.SetFallbackMaterial(this.meshRenderer); } } //--------------- Set submesh-data -------------------- //--------------- Set currentframe boundingbox for clipping -------------------- if (!boundsPerFrame.ContainsKey(frameNumber)) AddMeshBounds(frameNumber, vertices); //--------------- Set currentframe boundingbox for clipping -------------------- } } this.meshRenderer.enabled = isVisible && isEnabled; }
//--------------------------------------- Get mesh data -------------------------------------- //--------------------------------------- Get mesh data -------------------------------------- //--------------------------------------- DETECT CHANGE PERFORMANCE OPTIMIZE -------------------------------------- //--------------------------------------- DETECT CHANGE PERFORMANCE OPTIMIZE -------------------------------------- #region DETECT CHANGE PERFORMANCE OPTIMIZE private bool DetectChanges(SMesh currentMesh) { if (currentMesh == null) return false; if (previousMesh == null || currentMesh.header.type == SMesh.Type.full || currentMesh == keyframeMesh) //if first frame, full meshcapture or equal to the keyframe... then update! return true; if (previousMesh.header.matrix != currentMesh.header.matrix) // if position changed return true; if (previousMesh.bones != null && currentMesh.bones != null && previousMesh.bones.count == currentMesh.bones.count) { int i = previousMesh.bones.count; while (--i > -1) { if (previousMesh.bones.matrices.GetMatrix(i) != currentMesh.bones.matrices.GetMatrix(i)) //if bones differ, it changed! return true; } return false; //At this point, all the bones are the same! } else { // no bone data to test, must be a meshfilter if ( (previousMesh.vertices.count != currentMesh.vertices.count) || (previousMesh.triangles.Length != currentMesh.triangles.Length)) { return true; } } return false; //Nothing to see, so nothing changed }
public static SMesh Deserialize(byte[] input) { SMesh result = new SMesh(); ComposedByteStream stream = ComposedByteStream.FromByteArray(input); result.header = SMesh.HeaderData.Deserialize(stream.ReadNextStream<byte>()); result.subMeshes = SSubMeshArray.Deserialize(stream.ReadNextStream<byte>()); result.triangles = stream.ReadNextStream<int>(); result.vertices = new SVector3Array(stream.ReadNextStream<float>()); result.uv = new SVector2Array(stream.ReadNextStream<float>()); result.uv1 = new SVector2Array(stream.ReadNextStream<float>()); result.uv2 = new SVector2Array(stream.ReadNextStream<float>()); result.uv3 = new SVector2Array(stream.ReadNextStream<float>()); result.uv4 = new SVector2Array(stream.ReadNextStream<float>()); result.bindPoses = new SMatrix4x4Array(stream.ReadNextStream<float>()); result.bones = SBonesArray.Deserialize(stream.ReadNextStream<byte>()); result.boneWeights = SBoneWeightArray.Deserialize(stream.ReadNextStream<byte>()); stream.Dispose(); return result; }
//--------------- Sub classes / enums -------------------- //--------------- Serialize / Deserialize -------------------- public static byte[] Serialize(SMesh input) { ComposedByteStream stream = ComposedByteStream.FetchStream(10); stream.AddStream(SMesh.HeaderData.Serialize(input.header)); stream.AddStream(SSubMeshArray.Serialize(input.subMeshes)); stream.AddStream(input.triangles); stream.AddStream(input.vertices != null ? input.vertices.vectorData : null); stream.AddStream(input.uv != null ? input.uv.vectorData : null); stream.AddStream(input.uv1 != null ? input.uv1.vectorData : null); stream.AddStream(input.uv2 != null ? input.uv2.vectorData : null); stream.AddStream(input.uv3 != null ? input.uv3.vectorData : null); stream.AddStream(input.uv4 != null ? input.uv4.vectorData : null); stream.AddStream(input.bindPoses != null ? input.bindPoses.matrixData : null); stream.AddStream(SBonesArray.Serialize(input.bones)); stream.AddStream(SBoneWeightArray.Serialize(input.boneWeights)); return stream.Compose(); }
private static void CopyBoneBindPoses(Mesh source, SMesh destination) { Matrix4x4[] bindPoses = source.bindposes; if (bindPoses == null) return; destination.bindPoses = new SMatrix4x4Array(bindPoses); }