PointCachePlayer.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace VertexAnimationTools_30 {
  5. [ExecuteInEditMode]
  6. [RequireComponent(typeof(SkinnedMeshRenderer))]
  7. [DisallowMultipleComponent]
  8. [DefaultExecutionOrder(100)]
  9. [HelpURL("https://polyflow.studio/VertexAnimationToolsDocumentation/VertexAnimationTools30_Documentation.html#PointCachePlayer")]
  10. public class PointCachePlayer : MonoBehaviour {
  11. #region GIZMOS_COLORS
  12. public static Color[] GizmosClipColors = new Color[8] {
  13. new Color(1, 0, 0, 1f),
  14. new Color(0.2f, 0.2f, 1f, 1f),
  15. new Color(0, 1f, 0f, 1f),
  16. new Color(1, 0.37f, 0, 1),
  17. new Color(0, 1f, 1f, 1),
  18. new Color(1f, 0, 1f, 1),
  19. new Color(1, 1, 0, 1),
  20. new Color(1, 0, 0, 1)
  21. };
  22. #endregion
  23. [System.Serializable]
  24. public class Clip {
  25. public int Idx;
  26. public PointCachePlayer Player;
  27. public AutoPlaybackTypeEnum AutoPlaybackType = AutoPlaybackTypeEnum.Repeat;
  28. public float DurationInSeconds = 1f;
  29. public bool DrawMotionPath;
  30. public float MotionPathIconSize = 0.1f;
  31. public float NormalizedTime {
  32. get {
  33. switch (Idx) {
  34. case 0: return Player.Clip0NormalizedTime;
  35. case 1: return Player.Clip1NormalizedTime;
  36. case 2: return Player.Clip2NormalizedTime;
  37. case 3: return Player.Clip3NormalizedTime;
  38. case 4: return Player.Clip4NormalizedTime;
  39. case 5: return Player.Clip5NormalizedTime;
  40. case 6: return Player.Clip6NormalizedTime;
  41. case 7: return Player.Clip7NormalizedTime;
  42. default:
  43. return -1;
  44. }
  45. }
  46. set {
  47. switch (Idx) {
  48. case 0: Player.Clip0NormalizedTime = value; break;
  49. case 1: Player.Clip1NormalizedTime = value; break;
  50. case 2: Player.Clip2NormalizedTime = value; break;
  51. case 3: Player.Clip3NormalizedTime = value; break;
  52. case 4: Player.Clip4NormalizedTime = value; break;
  53. case 5: Player.Clip5NormalizedTime = value; break;
  54. case 6: Player.Clip6NormalizedTime = value; break;
  55. case 7: Player.Clip7NormalizedTime = value; break;
  56. default: break;
  57. }
  58. }
  59. }
  60. public float Weight {
  61. get {
  62. switch (Idx) {
  63. case 0: return Player.Clip0Weight;
  64. case 1: return Player.Clip1Weight;
  65. case 2: return Player.Clip2Weight;
  66. case 3: return Player.Clip3Weight;
  67. case 4: return Player.Clip4Weight;
  68. case 5: return Player.Clip5Weight;
  69. case 6: return Player.Clip6Weight;
  70. case 7: return Player.Clip7Weight;
  71. default:
  72. return -1;
  73. }
  74. }
  75. set {
  76. switch (Idx) {
  77. case 0: Player.Clip0Weight = value; break;
  78. case 1: Player.Clip1Weight = value; break;
  79. case 2: Player.Clip2Weight = value; break;
  80. case 3: Player.Clip3Weight = value; break;
  81. case 4: Player.Clip4Weight = value; break;
  82. case 5: Player.Clip5Weight = value; break;
  83. case 6: Player.Clip6Weight = value; break;
  84. case 7: Player.Clip7Weight = value; break;
  85. default: break;
  86. }
  87. }
  88. }
  89. public Clip(int idx) {
  90. Idx = idx;
  91. }
  92. }
  93. [System.Serializable]
  94. public class Constraint {
  95. public string Name;
  96. public Transform Tr;
  97. public PFU utm;
  98. public void Apply(Matrix4x4 tm) {
  99. if (Tr != null) {
  100. utm = utm * tm;
  101. Tr.position = utm.P;
  102. Tr.rotation = Quaternion.LookRotation(utm.F, utm.U);
  103. }
  104. }
  105. }
  106. public bool UseTimescale = true;
  107. public PlayerUpdateMode UpdateMode = PlayerUpdateMode.LateUpdate;
  108. float timeDirection = 1;
  109. public int ActiveMesh;
  110. public MeshCollider MCollider;
  111. public Mesh ColliderMesh;
  112. public Clip[] Clips = new Clip[8] { new Clip(0), new Clip(1), new Clip(2), new Clip(3), new Clip(4), new Clip(5), new Clip(6), new Clip(7) };
  113. public float Clip0NormalizedTime;
  114. public float Clip0Weight;
  115. public float Clip1NormalizedTime;
  116. public float Clip1Weight;
  117. public float Clip2NormalizedTime;
  118. public float Clip2Weight;
  119. public float Clip3NormalizedTime;
  120. public float Clip3Weight;
  121. public float Clip4NormalizedTime;
  122. public float Clip4Weight;
  123. public float Clip5NormalizedTime;
  124. public float Clip5Weight;
  125. public float Clip6NormalizedTime;
  126. public float Clip6Weight;
  127. public float Clip7NormalizedTime;
  128. public float Clip7Weight;
  129. public PointCache pointCache;
  130. public SkinnedMeshRenderer smr;
  131. public Constraint[] Constraints = new Constraint[0];
  132. private int PreparedMeshCollider;
  133. public bool DrawMeshGizmo;
  134. void OnEnable() {
  135. Init();
  136. }
  137. public void Init() {
  138. for (int i = 0; i < Clips.Length; i++) {
  139. Clips[i].Player = this;
  140. }
  141. if (pointCache != null) {
  142. if (smr == null) {
  143. smr = GetComponent<SkinnedMeshRenderer>();
  144. }
  145. smr.sharedMesh = pointCache.Meshes[0].mesh;
  146. Constraint[] nconstraints = new Constraint[pointCache.PostConstraints.Length];
  147. for (int i = 0; i < nconstraints.Length; i++) {
  148. nconstraints[i] = new Constraint();
  149. nconstraints[i].Name = pointCache.PostConstraints[i].Name;
  150. if (i < Constraints.Length) {
  151. nconstraints[i].Tr = Constraints[i].Tr;
  152. }
  153. }
  154. Constraints = nconstraints;
  155. }
  156. }
  157. void Update() {
  158. if (UpdateMode == PlayerUpdateMode.Update) {
  159. UpdatePlayback();
  160. }
  161. }
  162. void LateUpdate() {
  163. if (UpdateMode == PlayerUpdateMode.LateUpdate) {
  164. UpdatePlayback();
  165. }
  166. }
  167. public void UpdatePlayback() {
  168. if (pointCache != null) {
  169. ActiveMesh = Mathf.Clamp(ActiveMesh, 0, pointCache.PostImport.UsedMeshesCount);
  170. PointCache.PolygonMesh polygonMesh = pointCache.Meshes[ActiveMesh];
  171. if (polygonMesh.mesh == null) {
  172. return;
  173. }
  174. smr.sharedMesh = polygonMesh.mesh;
  175. if (pointCache.PostImport.GenerateMaterials) {
  176. smr.sharedMaterials = polygonMesh.Materials;
  177. }
  178. int totalFramesCount = smr.sharedMesh.blendShapeCount;
  179. for (int i = 0; i < totalFramesCount; i++) {
  180. smr.SetBlendShapeWeight(i, 0);
  181. }
  182. for (int cn = 0; cn < Constraints.Length; cn++) {
  183. Constraints[cn].utm = pointCache.PostConstraints[cn].ObjSpace;
  184. }
  185. for (int c = 0; c < pointCache.PostImport.UsedClipsCount; c++) {
  186. Clip clip = Clips[c];
  187. PointCache.Clip pcclip = pointCache.Clips[c];
  188. int clipFramesCount = pcclip.PostImport.FramesCount;
  189. int framesOffset = pcclip.PostImport.FrameIdxOffset;
  190. if (clipFramesCount <= 0) {
  191. continue;
  192. }
  193. int idxA = -1;
  194. int idxB = -1;
  195. float weightB = 0;
  196. float weightA = 0;
  197. clip.NormalizedTime = Mathf.Clamp01(clip.NormalizedTime);
  198. if (pcclip.PostImport.IsLoop) {
  199. float time = clip.NormalizedTime * clipFramesCount;
  200. float lv = time - Mathf.Floor(time);
  201. idxA = (int)(time % clipFramesCount);
  202. idxB = (int)((time + 1) % clipFramesCount);
  203. weightB = lv * clip.Weight;
  204. weightA = (1f - lv) * clip.Weight;
  205. smr.SetBlendShapeWeight(framesOffset + idxB, weightB * 100);
  206. smr.SetBlendShapeWeight(framesOffset + idxA, weightA * 100);
  207. } else {
  208. float time = clip.NormalizedTime * (clipFramesCount - 1);
  209. float lv = time - Mathf.Floor(time);
  210. int lastFrame = clipFramesCount - 1;
  211. idxA = Mathf.Clamp(Mathf.FloorToInt(time), 0, lastFrame);
  212. idxB = Mathf.Clamp(idxA + 1, 0, lastFrame);
  213. weightA = (1f - lv) * clip.Weight;
  214. weightB = lv * clip.Weight;
  215. smr.SetBlendShapeWeight(framesOffset + idxB, weightB * 100);
  216. smr.SetBlendShapeWeight(framesOffset + idxA, weightA * 100);
  217. }
  218. for (int cn = 0; cn < Constraints.Length; cn++) {
  219. PointCache.PostImportConstraint iconstraint = pointCache.PostConstraints[cn];
  220. Constraint constraint = Constraints[cn];
  221. constraint.utm = constraint.utm + (iconstraint.Clips[c].Frames[idxA] * weightA) + (iconstraint.Clips[c].Frames[idxB] * weightB);
  222. }
  223. if ( Application.isPlaying ) {
  224. float dt = (UseTimescale ? Time.deltaTime : Time.unscaledDeltaTime) / clip.DurationInSeconds * timeDirection ;
  225. if (clip.AutoPlaybackType == AutoPlaybackTypeEnum.Repeat) {
  226. clip.NormalizedTime += dt;
  227. if (clip.NormalizedTime > 1f) {
  228. clip.NormalizedTime = clip.NormalizedTime - Mathf.Floor(clip.NormalizedTime);
  229. }
  230. } else if (clip.AutoPlaybackType == AutoPlaybackTypeEnum.Once) {
  231. clip.NormalizedTime += dt;
  232. if (clip.NormalizedTime > 1f) {
  233. clip.NormalizedTime = 1f;
  234. clip.AutoPlaybackType = AutoPlaybackTypeEnum.None;
  235. }
  236. } else if (clip.AutoPlaybackType == AutoPlaybackTypeEnum.PingPong) {
  237. clip.NormalizedTime += dt;
  238. if (clip.NormalizedTime > 1f) {
  239. clip.NormalizedTime = 1f - (clip.NormalizedTime - Mathf.Floor(clip.NormalizedTime));
  240. timeDirection = -1;
  241. } else if (clip.NormalizedTime < 0) {
  242. clip.NormalizedTime = -clip.NormalizedTime;
  243. timeDirection = 1;
  244. }
  245. }
  246. }
  247. }
  248. }
  249. Matrix4x4 ltw = transform.localToWorldMatrix;
  250. for (int cn = 0; cn < Constraints.Length; cn++) {
  251. Constraints[cn].Apply(ltw);
  252. }
  253. PreparedMeshCollider = -1;
  254. }
  255. void OnDrawGizmos() {
  256. if (pointCache == null) {
  257. return;
  258. }
  259. Matrix4x4 ltw = transform.localToWorldMatrix;
  260. Gizmos.matrix = ltw;
  261. for (int c = 0; c < pointCache.PostImport.UsedClipsCount; c++) {
  262. Clip clip = Clips[c];
  263. if (!clip.DrawMotionPath) {
  264. continue;
  265. }
  266. PointCache.Clip pcclip = pointCache.Clips[c];
  267. Gizmos.color = GizmosClipColors[c];
  268. Vector3 cubeScale = Vector3.one ;
  269. float iconSize = clip.MotionPathIconSize;
  270. for (int p = 0; p < pcclip.MotionPathsCount; p++) {
  271. //first frame icon
  272. Vector3 v0;
  273. Vector3 v1;
  274. Vector3 v2;
  275. Vector3 v3;
  276. Vector3 a ;
  277. Vector3 b ;
  278. if (iconSize > 0) {
  279. a = pcclip.GetGizmoPoint(p, 0);
  280. b = pcclip.GetGizmoPoint(p, 1);
  281. Vector3 dir = b - a;
  282. float magnitude = dir.magnitude;
  283. dir = dir / magnitude;
  284. dir *= iconSize * 4;
  285. v0 = a + Vector3.Cross(dir, Vector3.up);
  286. v1 = a + Vector3.Cross(dir, Vector3.left);
  287. v2 = a + Vector3.Cross(dir, Vector3.down);
  288. v3 = a + Vector3.Cross(dir, Vector3.right);
  289. Gizmos.DrawLine(v0, v1);
  290. Gizmos.DrawLine(v1, v2);
  291. Gizmos.DrawLine(v2, v3);
  292. Gizmos.DrawLine(v3, v0);
  293. //last frame arrow icon
  294. a = pcclip.GetGizmoPoint(p, pcclip.PostImport.ImportRangeLength - 2);
  295. b = pcclip.GetGizmoPoint(p, pcclip.PostImport.ImportRangeLength - 1);
  296. dir = b - a;
  297. magnitude = dir.magnitude;
  298. dir = dir / magnitude;
  299. dir *= iconSize * 4;
  300. a = b - dir * 4;
  301. v0 = a + Vector3.Cross(dir, Vector3.up);
  302. v1 = a + Vector3.Cross(dir, Vector3.left);
  303. v2 = a + Vector3.Cross(dir, Vector3.down);
  304. v3 = a + Vector3.Cross(dir, Vector3.right);
  305. Gizmos.DrawLine(v0, v1);
  306. Gizmos.DrawLine(v1, v2);
  307. Gizmos.DrawLine(v2, v3);
  308. Gizmos.DrawLine(v3, v0);
  309. Gizmos.DrawLine(v0, b);
  310. Gizmos.DrawLine(v1, b);
  311. Gizmos.DrawLine(v2, b);
  312. Gizmos.DrawLine(v3, b);
  313. for (int f = 0; f < pcclip.PostImport.FramesCount; f++) {
  314. a = pcclip.GetGizmoPoint(p, f);
  315. b = pcclip.GetGizmoPoint(p, f + 1);
  316. Vector3 h0 = a + new Vector3(iconSize, 0, 0);
  317. Vector3 h1 = a + new Vector3(0, 0, iconSize);
  318. Vector3 h2 = a + new Vector3(-iconSize, 0, 0);
  319. Vector3 h3 = a + new Vector3(0, 0, -iconSize);
  320. v0 = a + new Vector3(0, iconSize, 0);
  321. v1 = a + new Vector3(0, -iconSize, 0);
  322. Gizmos.DrawLine(h0, h1);
  323. Gizmos.DrawLine(h1, h2);
  324. Gizmos.DrawLine(h2, h3);
  325. Gizmos.DrawLine(h3, h0);
  326. Gizmos.DrawLine(h0, v0);
  327. Gizmos.DrawLine(h1, v0);
  328. Gizmos.DrawLine(h2, v0);
  329. Gizmos.DrawLine(h3, v0);
  330. Gizmos.DrawLine(h0, v1);
  331. Gizmos.DrawLine(h1, v1);
  332. Gizmos.DrawLine(h2, v1);
  333. Gizmos.DrawLine(h3, v1);
  334. Gizmos.DrawLine(a, b);
  335. }
  336. } else {
  337. for (int f = 0; f < pcclip.PostImport.FramesCount; f++) {
  338. a = pcclip.GetGizmoPoint(p, f);
  339. b = pcclip.GetGizmoPoint(p, f + 1);
  340. Gizmos.DrawLine(a, b);
  341. }
  342. }
  343. }
  344. }
  345. if (DrawMeshGizmo && pointCache.Meshes[ActiveMesh].mesh != null) {
  346. Gizmos.color = new Color(0, 1f, 0.5f, 0.15f);
  347. Gizmos.DrawMesh(pointCache.Meshes[ActiveMesh].mesh);
  348. Gizmos.color = new Color(0, 1f, 0.5f, 0.05f);
  349. Gizmos.DrawWireMesh(pointCache.Meshes[ActiveMesh].mesh);
  350. }
  351. }
  352. public IEnumerable<TaskInfo> ImportIE() {
  353. yield return new TaskInfo("Preparing import", 0);
  354. smr = GetComponent<SkinnedMeshRenderer>();
  355. if (smr == null) {
  356. yield return new TaskInfo("Missing Skinned Mesh Render component", -1);
  357. yield break;
  358. }
  359. PointCache pc = pointCache;
  360. pc.SetMaterialsUnused();
  361. if (ProjectionSamples.Get == null) {
  362. yield return new TaskInfo("Missing Projection Samples asset. Reinstal Vertex Animation Tools package", -1);
  363. yield break;
  364. }
  365. #region BUILD_TASK_STACK
  366. TasksStack ts = new TasksStack(string.Format("Importing {0}", pc.name));
  367. for (int i = 0; i < pointCache.PreImport.UsedMeshesCount; i++) {
  368. ts.Add(string.Format("Building mesh #{0}", i), 1, 0.01f);
  369. }
  370. ts.Add("Building binding helper", 1, 0.05f);
  371. ts.Add("Binding constraints", pc.PreConstraints.Count, 0.01f);
  372. for (int m = 0; m < pc.PreImport.UsedMeshesCount; m++) {
  373. ts.Add(string.Format("Mesh #{0} binding", m), 1, 0.75f);
  374. }
  375. for (int c = 0; c < pc.PreImport.UsedClipsCount; c++) {
  376. ts.Add(string.Format("Building clip #{0}", c ), 1, 2f);
  377. ts.Add(string.Format("Applying clip #{0} frames", c ), 1, 0.2f);
  378. }
  379. ts.Add("Set meshes compression", pc.PreImport.UsedMeshesCount, 0.1f);
  380. ts.Add("Optimize meshes", pc.PreImport.UsedMeshesCount, 0.1f);
  381. ts.Add("Storing changes and cleanup", 1, 0.1f);
  382. ts.Normalize();
  383. //ts.PrintDebugInfo();
  384. #endregion
  385. #region VALIDATE_MAIN_MESH
  386. if (!pc.Meshes[0].CheckAndUpdateInfo()) {
  387. yield return new TaskInfo( string.Format( "Main mesh not valid: {0}", pc.Meshes[0].Info), -1f);
  388. }
  389. #endregion
  390. #region VALIDATE_CLIPS
  391. for (int c = 0; c < pc.PreImport.UsedClipsCount; c++) {
  392. if (!pc.Clips[c].PreImport.CheckAndUpdateInfo(pc.Meshes[0].VertsCount)) {
  393. yield return new TaskInfo(string.Format("Clip {0} not valid: {1}", c, pc.Clips[c].PreImport.FileInfo), -1f);
  394. yield break;
  395. }
  396. }
  397. #endregion
  398. #region LOAD_MESHES
  399. for (int i = 0; i < pointCache.PreImport.UsedMeshesCount; i++) {
  400. pointCache.Meshes[i].CheckAndUpdateInfo();
  401. if (pointCache.Meshes[i].VertsCount < 0) {
  402. yield return new TaskInfo(string.Format("LODs {0} not valid {1}", i, pointCache.Meshes[i].Info), -1f);
  403. yield break;
  404. }
  405. if (pointCache.Meshes[i].mesh == null) {
  406. Mesh newMesh = new Mesh();
  407. newMesh.name = string.Format("LOD{0}", i);
  408. pointCache.Meshes[i].mesh = newMesh;
  409. }
  410. PointCache.PolygonMesh lod = pointCache.Meshes[i];
  411. lod.od = new ObjData(lod.Path);
  412. SetIndexFormat(pointCache.Meshes[i].od, pc);
  413. lod.od.FlipNormals = pc.PreImport.FlipNormals;
  414. lod.od.SmoothingGroupsMode = pc.PreImport.SmoothingGroupImportMode;
  415. lod.od.NormalsRecalculationMode = pc.PreImport.NormalRecalculationMode;
  416. lod.od.ImportUV = true;
  417. lod.od.CalculateNormals = true;
  418. lod.od.CalculateTangents = true;
  419. SetIndexFormat(lod.od, pc);
  420. lod.od.Build();
  421. lod.od.Apply(pc.PreImport.SwapYZAxis, pc.PreImport.ScaleFactor);
  422. lod.od.CopyTo(lod.mesh);
  423. if (pc.PreImport.GenerateMaterials) {
  424. lod.Materials = pc.GetPolygonalMeshMaterials(lod.od.SubMeshes.GetNames());
  425. }
  426. lod.od.SetBindPoseFrameVertices();
  427. yield return ts[string.Format("Building mesh #{0}", i)].GetInfo(1);
  428. }
  429. #endregion
  430. PointCache.PolygonMesh lod0 = pointCache.Meshes[0];
  431. Bounds bindPoseBounds = lod0.od.UM_Bounds;
  432. #region BUILD_BINDING_HELPER
  433. yield return ts["Building binding helper"].GetInfo(0);
  434. BindingHelper bh = new BindingHelper(pc.Meshes[0].mesh, transform);
  435. bh.SetVertices(pointCache.Meshes[0].od.UM_vertices, pointCache.Meshes[0].od.UM_normals, pointCache.Meshes[0].od.UM_v3tangents);
  436. #endregion
  437. #region BUILD_CONSTRAINTS
  438. pc.PostConstraints = new PointCache.PostImportConstraint[pc.PreConstraints.Count];
  439. for (int co = 0; co < pc.PreConstraints.Count; co++) {
  440. yield return ts["Binding constraints"].GetInfo(co);
  441. PointCache.PreImportConstraint pre = pc.PreConstraints[co];
  442. bh.Bind(pre.ObjSpace, ref pre.BI);
  443. pc.PostConstraints[co] = new PointCache.PostImportConstraint();
  444. pc.PostConstraints[co].Name = pc.PreConstraints[co].Name;
  445. pc.PostConstraints[co].ObjSpace = pc.PreConstraints[co].ObjSpace;
  446. pc.PostConstraints[co].Clips = new ConstraintClip[pc.PreImport.UsedClipsCount];
  447. }
  448. #endregion
  449. #region BIND_GEOMETRY
  450. for (int m = 1; m < pointCache.PreImport.UsedMeshesCount; m++) {
  451. PointCache.PolygonMesh lod = pointCache.Meshes[m];
  452. string taskName = string.Format("Mesh #{0} binding", m);
  453. foreach (TaskInfo ti in lod.od.BindIE(bh)) {
  454. yield return ts[taskName].GetInfo( ti.Persentage );
  455. }
  456. }
  457. #endregion
  458. bool boundsIsCreated = false;
  459. Bounds bounds = new Bounds();
  460. int blendshapesCounter = 0;
  461. for (int c = 0; c < pc.PreImport.UsedClipsCount; c++) {
  462. PointCache.Clip clip = pc.Clips[c];
  463. string taskStackName = string.Format("Building clip #{0}", c);
  464. PointCacheData pcdata = new PointCacheData(clip, pc, lod0.od.Vertices.Count);
  465. foreach ( TaskInfo ti in pcdata.Build() ) {
  466. if (ti.Persentage < 0) {
  467. bh.Delete();
  468. yield return new TaskInfo(ti.Name, -1f);
  469. yield break;
  470. }
  471. TaskInfo totalInfo = ts[taskStackName].GetInfo(ti.Persentage);
  472. totalInfo.Name = taskStackName + " / " + ti.Name;
  473. yield return totalInfo;
  474. }
  475. taskStackName = string.Format("Applying clip #{0} frames", c);
  476. clip.PreImport.FrameIdxOffset = blendshapesCounter;
  477. for (int co = 0; co < pc.PreConstraints.Count; co++) {
  478. pc.PostConstraints[co].Clips[c] = new ConstraintClip(clip.PreImport.ImportRangeLength);
  479. }
  480. for (int f = 0; f < pcdata.Frames.Count; f++) {
  481. yield return ts[taskStackName].GetInfo(f / (float)pcdata.Frames.Count);
  482. lod0.od.VerticesToSet = pcdata.GetFrameVertices(f);
  483. lod0.od.Apply(false, 1);
  484. if (!boundsIsCreated) {
  485. bounds = lod0.od.UM_Bounds;
  486. boundsIsCreated = true;
  487. } else {
  488. bounds.Encapsulate(lod0.od.UM_Bounds);
  489. }
  490. Vector3[] posDelta = lod0.od.GetPosDeltas();
  491. Vector3[] normDelta = lod0.od.GetNormsDeltas();
  492. Vector3[] tanDelta = lod0.od.GetTansDeltas();
  493. bh.SetVertices(lod0.od.UM_vertices, lod0.od.UM_normals, lod0.od.UM_v3tangents );
  494. string shapeName = string.Format("c{0}f{1}", c, f);
  495. lod0.mesh.AddBlendShapeFrame(shapeName, 100, posDelta, normDelta, tanDelta);
  496. for (int co = 0; co < pc.PreConstraints.Count; co++) {
  497. PFU frameObjSpace = pc.PreConstraints[co].GetFrame(bh);
  498. pc.PostConstraints[co].Clips[c].Frames[f] = frameObjSpace - pc.PreConstraints[co].ObjSpace;
  499. }
  500. for (int l = 1; l< pointCache.PreImport.UsedMeshesCount; l++) {
  501. pc.Meshes[l].od.ApplyBinded(bh);
  502. pc.Meshes[l].mesh.AddBlendShapeFrame(shapeName, 100, pc.Meshes[l].od.GetPosDeltas(), pc.Meshes[l].od.GetNormsDeltas(), pc.Meshes[l].od.GetTansDeltas());
  503. }
  504. blendshapesCounter++;
  505. }
  506. }
  507. yield return ts["Storing changes and cleanup"].GetInfo(0);
  508. bh.Delete();
  509. if (!boundsIsCreated) {
  510. bounds = bindPoseBounds;
  511. }
  512. smr.localBounds = bounds;
  513. for (int c = 0; c < pc.Clips.Length; c++) {
  514. pc.Clips[c].PostImport = pc.Clips[c].PreImport;
  515. }
  516. pc.PostImport = pc.PreImport;
  517. pc.ImportSettingsIsDirtyFlag = false;
  518. pc.ClearUnusedMaterials();
  519. Init();
  520. yield return ts.Done;
  521. }
  522. void SetIndexFormat(ObjData od, PointCache pc ) {
  523. #if UNITY_2017_3_OR_NEWER
  524. od.IndexFormat = pc.PreImport.IndexFormat;
  525. #endif
  526. }
  527. void PrepareMeshCollider( int meshIdx, bool convex ) {
  528. if (meshIdx == PreparedMeshCollider) {
  529. return;
  530. }
  531. if (pointCache == null) {
  532. return;
  533. }
  534. if (MCollider == null) {
  535. MCollider = GetComponent<MeshCollider>();
  536. if (MCollider == null) {
  537. MCollider = gameObject.AddComponent<MeshCollider>();
  538. }
  539. if (ColliderMesh == null) {
  540. ColliderMesh = new Mesh();
  541. ColliderMesh.name = "ColliderMesh";
  542. }
  543. }
  544. MCollider.convex = convex;
  545. meshIdx = Mathf.Clamp(meshIdx, 0, pointCache.PostImport.UsedMeshesCount);
  546. smr.sharedMesh = pointCache.Meshes[meshIdx].mesh;
  547. smr.BakeMesh(ColliderMesh);
  548. MCollider.sharedMesh = ColliderMesh;
  549. smr.sharedMesh = pointCache.Meshes[ActiveMesh].mesh;
  550. PreparedMeshCollider = meshIdx;
  551. }
  552. public bool Raycast(Ray ray, out RaycastHit hit, float maxDistance, int meshIdx, bool convex) {
  553. Matrix4x4 wtl = transform.worldToLocalMatrix;
  554. hit = new RaycastHit();
  555. Ray localRay = new Ray(wtl.MultiplyPoint3x4(ray.origin), wtl.MultiplyVector(ray.direction));
  556. if (smr.localBounds.IntersectRay(localRay)) {
  557. PrepareMeshCollider(meshIdx, false);
  558. return MCollider.Raycast(ray, out hit, maxDistance);
  559. } else {
  560. return false;
  561. }
  562. }
  563. public void CopyPlaybackParams( PointCachePlayer source ) {
  564. for (int i = 0; i<8; i++) {
  565. Clips[i].NormalizedTime = source.Clips[i].NormalizedTime;
  566. Clips[i].Weight = source.Clips[i].Weight;
  567. Clips[i].AutoPlaybackType = source.Clips[i].AutoPlaybackType;
  568. Clips[i].DurationInSeconds = source.Clips[i].DurationInSeconds;
  569. }
  570. }
  571. }
  572. }