public PointCacheData(PointCache.Clip _clip, PointCache _pointCache, int _geometryVerticesCount) { clip = _clip; cis = clip.PreImport; pointCache = _pointCache; geometryVerticesCount = _geometryVerticesCount; IsMeshSequence = Path.GetExtension(cis.FilePath) == ".obj"; tstack = new TasksStack(string.Format("Build clip {0} data", cis.Name)); if (IsMeshSequence) { MeshSequenceInfo msi = new MeshSequenceInfo(cis.FilePath, MeshSequenceInfo.SortModeEnum.ByNumber); tstack.Add("Read .obj sequence", msi.infos.Length + cis.TransitionFramesCount, 3f); } else { tstack.Add("Read .pc2 file", cis.ImportRangeLength + cis.TransitionFramesCount); } if (cis.ChangeFramesCount) { tstack.Add("Change frames count", cis.ClampedCustomFramesCount); } if (cis.EnableMotionSmoothing) { tstack.Add("Motion smoothing", geometryVerticesCount); } if (cis.EnableNormalizeSpeed) { tstack.Add("Normalize speed", geometryVerticesCount); } if (cis.GenerageMotionPaths) { tstack.Add("Generage Motion Paths", geometryVerticesCount); } tstack.Normalize(); }
public IEnumerable <TaskInfo> ImportIE() { yield return(new TaskInfo("Preparing import", 0)); smr = GetComponent <SkinnedMeshRenderer>(); if (smr == null) { yield return(new TaskInfo("Missing Skinned Mesh Render component", -1)); yield break; } PointCache pc = pointCache; pc.SetMaterialsUnused(); if (ProjectionSamples.Get == null) { yield return(new TaskInfo("Missing Projection Samples asset. Reinstal Vertex Animation Tools package", -1)); yield break; } #region BUILD_TASK_STACK TasksStack ts = new TasksStack(string.Format("Importing {0}", pc.name)); for (int i = 0; i < pointCache.PreImport.UsedMeshesCount; i++) { ts.Add(string.Format("Building mesh #{0}", i), 1, 0.01f); } ts.Add("Building binding helper", 1, 0.05f); ts.Add("Binding constraints", pc.PreConstraints.Count, 0.01f); for (int m = 0; m < pc.PreImport.UsedMeshesCount; m++) { ts.Add(string.Format("Mesh #{0} binding", m), 1, 0.75f); } for (int c = 0; c < pc.PreImport.UsedClipsCount; c++) { ts.Add(string.Format("Building clip #{0}", c), 1, 2f); ts.Add(string.Format("Applying clip #{0} frames", c), 1, 0.2f); } ts.Add("Set meshes compression", pc.PreImport.UsedMeshesCount, 0.1f); ts.Add("Optimize meshes", pc.PreImport.UsedMeshesCount, 0.1f); ts.Add("Storing changes and cleanup", 1, 0.1f); ts.Normalize(); //ts.PrintDebugInfo(); #endregion #region VALIDATE_MAIN_MESH if (!pc.Meshes[0].CheckAndUpdateInfo()) { yield return(new TaskInfo(string.Format("Main mesh not valid: {0}", pc.Meshes[0].Info), -1f)); } #endregion #region VALIDATE_CLIPS for (int c = 0; c < pc.PreImport.UsedClipsCount; c++) { if (!pc.Clips[c].PreImport.CheckAndUpdateInfo(pc.Meshes[0].VertsCount)) { yield return(new TaskInfo(string.Format("Clip {0} not valid: {1}", c, pc.Clips[c].PreImport.FileInfo), -1f)); yield break; } } #endregion #region LOAD_MESHES for (int i = 0; i < pointCache.PreImport.UsedMeshesCount; i++) { pointCache.Meshes[i].CheckAndUpdateInfo(); if (pointCache.Meshes[i].VertsCount < 0) { yield return(new TaskInfo(string.Format("LODs {0} not valid {1}", i, pointCache.Meshes[i].Info), -1f)); yield break; } if (pointCache.Meshes[i].mesh == null) { Mesh newMesh = new Mesh(); newMesh.name = string.Format("LOD{0}", i); pointCache.Meshes[i].mesh = newMesh; } PointCache.PolygonMesh lod = pointCache.Meshes[i]; lod.od = new ObjData(lod.Path); SetIndexFormat(pointCache.Meshes[i].od, pc); lod.od.FlipNormals = pc.PreImport.FlipNormals; lod.od.SmoothingGroupsMode = pc.PreImport.SmoothingGroupImportMode; lod.od.NormalsRecalculationMode = pc.PreImport.NormalRecalculationMode; lod.od.ImportUV = true; lod.od.CalculateNormals = true; lod.od.CalculateTangents = true; SetIndexFormat(lod.od, pc); lod.od.Build(); lod.od.Apply(pc.PreImport.SwapYZAxis, pc.PreImport.ScaleFactor); lod.od.CopyTo(lod.mesh); if (pc.PreImport.GenerateMaterials) { lod.Materials = pc.GetPolygonalMeshMaterials(lod.od.SubMeshes.GetNames()); } lod.od.SetBindPoseFrameVertices(); yield return(ts[string.Format("Building mesh #{0}", i)].GetInfo(1)); } #endregion PointCache.PolygonMesh lod0 = pointCache.Meshes[0]; Bounds bindPoseBounds = lod0.od.UM_Bounds; #region BUILD_BINDING_HELPER yield return(ts["Building binding helper"].GetInfo(0)); BindingHelper bh = new BindingHelper(pc.Meshes[0].mesh, transform); bh.SetVertices(pointCache.Meshes[0].od.UM_vertices, pointCache.Meshes[0].od.UM_normals, pointCache.Meshes[0].od.UM_v3tangents); #endregion #region BUILD_CONSTRAINTS pc.PostConstraints = new PointCache.PostImportConstraint[pc.PreConstraints.Count]; for (int co = 0; co < pc.PreConstraints.Count; co++) { yield return(ts["Binding constraints"].GetInfo(co)); PointCache.PreImportConstraint pre = pc.PreConstraints[co]; bh.Bind(pre.ObjSpace, ref pre.BI); pc.PostConstraints[co] = new PointCache.PostImportConstraint(); pc.PostConstraints[co].Name = pc.PreConstraints[co].Name; pc.PostConstraints[co].ObjSpace = pc.PreConstraints[co].ObjSpace; pc.PostConstraints[co].Clips = new ConstraintClip[pc.PreImport.UsedClipsCount]; } #endregion #region BIND_GEOMETRY for (int m = 1; m < pointCache.PreImport.UsedMeshesCount; m++) { PointCache.PolygonMesh lod = pointCache.Meshes[m]; string taskName = string.Format("Mesh #{0} binding", m); foreach (TaskInfo ti in lod.od.BindIE(bh)) { yield return(ts[taskName].GetInfo(ti.Persentage)); } } #endregion bool boundsIsCreated = false; Bounds bounds = new Bounds(); int blendshapesCounter = 0; for (int c = 0; c < pc.PreImport.UsedClipsCount; c++) { PointCache.Clip clip = pc.Clips[c]; string taskStackName = string.Format("Building clip #{0}", c); PointCacheData pcdata = new PointCacheData(clip, pc, lod0.od.Vertices.Count); foreach (TaskInfo ti in pcdata.Build()) { if (ti.Persentage < 0) { bh.Delete(); yield return(new TaskInfo(ti.Name, -1f)); yield break; } TaskInfo totalInfo = ts[taskStackName].GetInfo(ti.Persentage); totalInfo.Name = taskStackName + " / " + ti.Name; yield return(totalInfo); } taskStackName = string.Format("Applying clip #{0} frames", c); clip.PreImport.FrameIdxOffset = blendshapesCounter; for (int co = 0; co < pc.PreConstraints.Count; co++) { pc.PostConstraints[co].Clips[c] = new ConstraintClip(clip.PreImport.ImportRangeLength); } for (int f = 0; f < pcdata.Frames.Count; f++) { yield return(ts[taskStackName].GetInfo(f / (float)pcdata.Frames.Count)); lod0.od.VerticesToSet = pcdata.GetFrameVertices(f); lod0.od.Apply(false, 1); if (!boundsIsCreated) { bounds = lod0.od.UM_Bounds; boundsIsCreated = true; } else { bounds.Encapsulate(lod0.od.UM_Bounds); } Vector3[] posDelta = lod0.od.GetPosDeltas(); Vector3[] normDelta = lod0.od.GetNormsDeltas(); Vector3[] tanDelta = lod0.od.GetTansDeltas(); bh.SetVertices(lod0.od.UM_vertices, lod0.od.UM_normals, lod0.od.UM_v3tangents); string shapeName = string.Format("c{0}f{1}", c, f); lod0.mesh.AddBlendShapeFrame(shapeName, 100, posDelta, normDelta, tanDelta); for (int co = 0; co < pc.PreConstraints.Count; co++) { PFU frameObjSpace = pc.PreConstraints[co].GetFrame(bh); pc.PostConstraints[co].Clips[c].Frames[f] = frameObjSpace - pc.PreConstraints[co].ObjSpace; } for (int l = 1; l < pointCache.PreImport.UsedMeshesCount; l++) { pc.Meshes[l].od.ApplyBinded(bh); pc.Meshes[l].mesh.AddBlendShapeFrame(shapeName, 100, pc.Meshes[l].od.GetPosDeltas(), pc.Meshes[l].od.GetNormsDeltas(), pc.Meshes[l].od.GetTansDeltas()); } blendshapesCounter++; } } yield return(ts["Storing changes and cleanup"].GetInfo(0)); bh.Delete(); if (!boundsIsCreated) { bounds = bindPoseBounds; } smr.localBounds = bounds; for (int c = 0; c < pc.Clips.Length; c++) { pc.Clips[c].PostImport = pc.Clips[c].PreImport; } pc.PostImport = pc.PreImport; pc.ImportSettingsIsDirtyFlag = false; pc.ClearUnusedMaterials(); Init(); yield return(ts.Done); }
void OnDrawGizmos() { if (pointCache == null) { return; } Matrix4x4 ltw = transform.localToWorldMatrix; Gizmos.matrix = ltw; for (int c = 0; c < pointCache.PostImport.UsedClipsCount; c++) { Clip clip = Clips[c]; if (!clip.DrawMotionPath) { continue; } PointCache.Clip pcclip = pointCache.Clips[c]; Gizmos.color = GizmosClipColors[c]; Vector3 cubeScale = Vector3.one; float iconSize = clip.MotionPathIconSize; for (int p = 0; p < pcclip.MotionPathsCount; p++) { //first frame icon Vector3 v0; Vector3 v1; Vector3 v2; Vector3 v3; Vector3 a; Vector3 b; if (iconSize > 0) { a = pcclip.GetGizmoPoint(p, 0); b = pcclip.GetGizmoPoint(p, 1); Vector3 dir = b - a; float magnitude = dir.magnitude; dir = dir / magnitude; dir *= iconSize * 4; v0 = a + Vector3.Cross(dir, Vector3.up); v1 = a + Vector3.Cross(dir, Vector3.left); v2 = a + Vector3.Cross(dir, Vector3.down); v3 = a + Vector3.Cross(dir, Vector3.right); Gizmos.DrawLine(v0, v1); Gizmos.DrawLine(v1, v2); Gizmos.DrawLine(v2, v3); Gizmos.DrawLine(v3, v0); //last frame arrow icon a = pcclip.GetGizmoPoint(p, pcclip.PostImport.ImportRangeLength - 2); b = pcclip.GetGizmoPoint(p, pcclip.PostImport.ImportRangeLength - 1); dir = b - a; magnitude = dir.magnitude; dir = dir / magnitude; dir *= iconSize * 4; a = b - dir * 4; v0 = a + Vector3.Cross(dir, Vector3.up); v1 = a + Vector3.Cross(dir, Vector3.left); v2 = a + Vector3.Cross(dir, Vector3.down); v3 = a + Vector3.Cross(dir, Vector3.right); Gizmos.DrawLine(v0, v1); Gizmos.DrawLine(v1, v2); Gizmos.DrawLine(v2, v3); Gizmos.DrawLine(v3, v0); Gizmos.DrawLine(v0, b); Gizmos.DrawLine(v1, b); Gizmos.DrawLine(v2, b); Gizmos.DrawLine(v3, b); for (int f = 0; f < pcclip.PostImport.FramesCount; f++) { a = pcclip.GetGizmoPoint(p, f); b = pcclip.GetGizmoPoint(p, f + 1); Vector3 h0 = a + new Vector3(iconSize, 0, 0); Vector3 h1 = a + new Vector3(0, 0, iconSize); Vector3 h2 = a + new Vector3(-iconSize, 0, 0); Vector3 h3 = a + new Vector3(0, 0, -iconSize); v0 = a + new Vector3(0, iconSize, 0); v1 = a + new Vector3(0, -iconSize, 0); Gizmos.DrawLine(h0, h1); Gizmos.DrawLine(h1, h2); Gizmos.DrawLine(h2, h3); Gizmos.DrawLine(h3, h0); Gizmos.DrawLine(h0, v0); Gizmos.DrawLine(h1, v0); Gizmos.DrawLine(h2, v0); Gizmos.DrawLine(h3, v0); Gizmos.DrawLine(h0, v1); Gizmos.DrawLine(h1, v1); Gizmos.DrawLine(h2, v1); Gizmos.DrawLine(h3, v1); Gizmos.DrawLine(a, b); } } else { for (int f = 0; f < pcclip.PostImport.FramesCount; f++) { a = pcclip.GetGizmoPoint(p, f); b = pcclip.GetGizmoPoint(p, f + 1); Gizmos.DrawLine(a, b); } } } } if (DrawMeshGizmo && pointCache.Meshes[ActiveMesh].mesh != null) { Gizmos.color = new Color(0, 1f, 0.5f, 0.15f); Gizmos.DrawMesh(pointCache.Meshes[ActiveMesh].mesh); Gizmos.color = new Color(0, 1f, 0.5f, 0.05f); Gizmos.DrawWireMesh(pointCache.Meshes[ActiveMesh].mesh); } }
public void UpdatePlayback() { if (pointCache != null) { ActiveMesh = Mathf.Clamp(ActiveMesh, 0, pointCache.PostImport.UsedMeshesCount); PointCache.PolygonMesh polygonMesh = pointCache.Meshes[ActiveMesh]; if (polygonMesh.mesh == null) { return; } smr.sharedMesh = polygonMesh.mesh; if (pointCache.PostImport.GenerateMaterials) { smr.sharedMaterials = polygonMesh.Materials; } int totalFramesCount = smr.sharedMesh.blendShapeCount; for (int i = 0; i < totalFramesCount; i++) { smr.SetBlendShapeWeight(i, 0); } for (int cn = 0; cn < Constraints.Length; cn++) { Constraints[cn].utm = pointCache.PostConstraints[cn].ObjSpace; } for (int c = 0; c < pointCache.PostImport.UsedClipsCount; c++) { Clip clip = Clips[c]; PointCache.Clip pcclip = pointCache.Clips[c]; int clipFramesCount = pcclip.PostImport.FramesCount; int framesOffset = pcclip.PostImport.FrameIdxOffset; if (clipFramesCount <= 0) { continue; } int idxA = -1; int idxB = -1; float weightB = 0; float weightA = 0; clip.NormalizedTime = Mathf.Clamp01(clip.NormalizedTime); if (pcclip.PostImport.IsLoop) { float time = clip.NormalizedTime * clipFramesCount; float lv = time - Mathf.Floor(time); idxA = (int)(time % clipFramesCount); idxB = (int)((time + 1) % clipFramesCount); weightB = lv * clip.Weight; weightA = (1f - lv) * clip.Weight; smr.SetBlendShapeWeight(framesOffset + idxB, weightB * 100); smr.SetBlendShapeWeight(framesOffset + idxA, weightA * 100); } else { float time = clip.NormalizedTime * (clipFramesCount - 1); float lv = time - Mathf.Floor(time); int lastFrame = clipFramesCount - 1; idxA = Mathf.Clamp(Mathf.FloorToInt(time), 0, lastFrame); idxB = Mathf.Clamp(idxA + 1, 0, lastFrame); weightA = (1f - lv) * clip.Weight; weightB = lv * clip.Weight; smr.SetBlendShapeWeight(framesOffset + idxB, weightB * 100); smr.SetBlendShapeWeight(framesOffset + idxA, weightA * 100); } for (int cn = 0; cn < Constraints.Length; cn++) { PointCache.PostImportConstraint iconstraint = pointCache.PostConstraints[cn]; Constraint constraint = Constraints[cn]; constraint.utm = constraint.utm + (iconstraint.Clips[c].Frames[idxA] * weightA) + (iconstraint.Clips[c].Frames[idxB] * weightB); } if (Application.isPlaying) { float dt = (UseTimescale ? Time.deltaTime : Time.unscaledDeltaTime) / clip.DurationInSeconds * timeDirection; if (clip.AutoPlaybackType == AutoPlaybackTypeEnum.Repeat) { clip.NormalizedTime += dt; if (clip.NormalizedTime > 1f) { clip.NormalizedTime = clip.NormalizedTime - Mathf.Floor(clip.NormalizedTime); } } else if (clip.AutoPlaybackType == AutoPlaybackTypeEnum.Once) { clip.NormalizedTime += dt; if (clip.NormalizedTime > 1f) { clip.NormalizedTime = 1f; clip.AutoPlaybackType = AutoPlaybackTypeEnum.None; } } else if (clip.AutoPlaybackType == AutoPlaybackTypeEnum.PingPong) { clip.NormalizedTime += dt; if (clip.NormalizedTime > 1f) { clip.NormalizedTime = 1f - (clip.NormalizedTime - Mathf.Floor(clip.NormalizedTime)); timeDirection = -1; } else if (clip.NormalizedTime < 0) { clip.NormalizedTime = -clip.NormalizedTime; timeDirection = 1; } } } } } Matrix4x4 ltw = transform.localToWorldMatrix; for (int cn = 0; cn < Constraints.Length; cn++) { Constraints[cn].Apply(ltw); } PreparedMeshCollider = -1; }