Tools.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Windows.Forms;
  6. using Autodesk.Max;
  7. using SharpDX;
  8. namespace Max2Babylon
  9. {
  10. public static class Tools
  11. {
  12. public const float Epsilon = 0.001f;
  13. public static IPoint3 XAxis { get { return Loader.Global.Point3.Create(1, 0, 0); } }
  14. public static IPoint3 YAxis { get { return Loader.Global.Point3.Create(0, 1, 0); } }
  15. public static IPoint3 ZAxis { get { return Loader.Global.Point3.Create(0, 0, 1); } }
  16. public static IPoint3 Origin { get { return Loader.Global.Point3.Create(0, 0, 0); } }
  17. public static IInterval Forever
  18. {
  19. get { return Loader.Global.Interval.Create(int.MinValue, int.MaxValue); }
  20. }
  21. public static IMatrix3 Identity { get { return Loader.Global.Matrix3.Create(XAxis, YAxis, ZAxis, Origin); } }
  22. public static bool IsTextureCube(string filepath)
  23. {
  24. try
  25. {
  26. if (Path.GetExtension(filepath).ToLower() != ".dds")
  27. {
  28. return false;
  29. }
  30. var data = File.ReadAllBytes(filepath);
  31. var intArray = new int[data.Length / 4];
  32. Buffer.BlockCopy(data, 0, intArray, 0, data.Length);
  33. return (intArray[28] & 0x200) == 0x200;
  34. }
  35. catch
  36. {
  37. return false;
  38. }
  39. }
  40. public static Vector3 ToEulerAngles(this IQuat q)
  41. {
  42. // Store the Euler angles in radians
  43. var pitchYawRoll = new Vector3();
  44. double sqw = q.W * q.W;
  45. double sqx = q.X * q.X;
  46. double sqy = q.Y * q.Y;
  47. double sqz = q.Z * q.Z;
  48. // If quaternion is normalised the unit is one, otherwise it is the correction factor
  49. double unit = sqx + sqy + sqz + sqw;
  50. double test = q.X * q.Y + q.Z * q.W;
  51. if (test > 0.4999f * unit) // 0.4999f OR 0.5f - EPSILON
  52. {
  53. // Singularity at north pole
  54. pitchYawRoll.Y = 2f * (float)Math.Atan2(q.X, q.W); // Yaw
  55. pitchYawRoll.X = (float)Math.PI * 0.5f; // Pitch
  56. pitchYawRoll.Z = 0f; // Roll
  57. return pitchYawRoll;
  58. }
  59. if (test < -0.4999f * unit) // -0.4999f OR -0.5f + EPSILON
  60. {
  61. // Singularity at south pole
  62. pitchYawRoll.Y = -2f * (float)Math.Atan2(q.X, q.W); // Yaw
  63. pitchYawRoll.X = -(float)Math.PI * 0.5f; // Pitch
  64. pitchYawRoll.Z = 0f; // Roll
  65. return pitchYawRoll;
  66. }
  67. pitchYawRoll.Y = (float)Math.Atan2(2f * q.Y * q.W - 2f * q.X * q.Z, sqx - sqy - sqz + sqw); // Yaw
  68. pitchYawRoll.X = (float)Math.Asin(2f * test / unit); // Pitch
  69. pitchYawRoll.Z = (float)Math.Atan2(2f * q.X * q.W - 2f * q.Y * q.Z, -sqx + sqy - sqz + sqw); // Roll
  70. return pitchYawRoll;
  71. }
  72. public static void PreparePipeline(IINode node, bool deactivate)
  73. {
  74. var obj = node.ObjectRef;
  75. if (obj == null || obj.SuperClassID != SClass_ID.GenDerivob)
  76. {
  77. return;
  78. }
  79. var derivedObject = obj as IIDerivedObject;
  80. if (derivedObject == null)
  81. {
  82. return;
  83. }
  84. for (var index = 0; index < derivedObject.NumModifiers; index++)
  85. {
  86. var modifier = derivedObject.GetModifier(index);
  87. //if (modifier.ClassID.PartA == 9815843 && modifier.ClassID.PartB == 87654) // Skin
  88. //{
  89. // if (deactivate)
  90. // {
  91. // modifier.DisableMod();
  92. // }
  93. // else
  94. // {
  95. // modifier.EnableMod();
  96. // }
  97. //}
  98. }
  99. }
  100. public static VNormal[] ComputeNormals(IMesh mesh, bool optimize)
  101. {
  102. var vnorms = new VNormal[mesh.NumVerts];
  103. var fnorms = new Vector3[mesh.NumFaces];
  104. for (var index = 0; index < mesh.NumVerts; index++)
  105. {
  106. vnorms[index] = new VNormal();
  107. }
  108. for (var index = 0; index < mesh.NumFaces; index++)
  109. {
  110. var face = mesh.Faces[index];
  111. Vector3 v0 = mesh.Verts[(int)face.V[0]].ToVector3();
  112. Vector3 v1 = mesh.Verts[(int)face.V[1]].ToVector3();
  113. Vector3 v2 = mesh.Verts[(int)face.V[2]].ToVector3();
  114. fnorms[index] = Vector3.Cross((v1 - v0), (v2 - v1));
  115. for (var j = 0; j < 3; j++)
  116. {
  117. vnorms[(int)face.V[j]].AddNormal(fnorms[index], optimize ? 1 : face.SmGroup);
  118. }
  119. fnorms[index].Normalize();
  120. }
  121. for (var index = 0; index < mesh.NumVerts; index++)
  122. {
  123. vnorms[index].Normalize();
  124. }
  125. return vnorms;
  126. }
  127. public static bool IsEqualTo(this float[] value, float[] other)
  128. {
  129. if (value.Length != other.Length)
  130. {
  131. return false;
  132. }
  133. return !value.Where((t, i) => Math.Abs(t - other[i]) > Epsilon).Any();
  134. }
  135. public static float[] ToArray(this IMatrix3 value)
  136. {
  137. var row0 = value.GetRow(0).ToArraySwitched();
  138. var row1 = value.GetRow(1).ToArraySwitched();
  139. var row2 = value.GetRow(2).ToArraySwitched();
  140. var row3 = value.GetRow(3).ToArraySwitched();
  141. return new[]
  142. {
  143. row0[0], row0[1], row0[2], 0,
  144. row2[0], row2[1], row2[2], 0,
  145. row1[0], row1[1], row1[2], 0,
  146. row3[0], row3[1], row3[2], 1
  147. };
  148. }
  149. public static IPoint3 ToPoint3(this Vector3 value)
  150. {
  151. return Loader.Global.Point3.Create(value.X, value.Y, value.Z);
  152. }
  153. public static Vector3 ToVector3(this IPoint3 value)
  154. {
  155. return new Vector3(value.X, value.Y, value.Z);
  156. }
  157. public static Quaternion ToQuat(this IQuat value)
  158. {
  159. return new Quaternion(value.X, value.Z, value.Y, value.W);
  160. }
  161. public static float[] ToArray(this IQuat value)
  162. {
  163. return new[] { value.X, value.Z, value.Y, value.W };
  164. }
  165. public static float[] Scale(this IColor value, float scale)
  166. {
  167. return new[] { value.R * scale, value.G * scale, value.B * scale };
  168. }
  169. public static float[] ToArray(this IPoint4 value)
  170. {
  171. return new[] { value.X, value.Y, value.Z, value.W };
  172. }
  173. public static float[] ToArray(this IPoint3 value)
  174. {
  175. return new[] { value.X, value.Y, value.Z };
  176. }
  177. public static float[] ToArray(this IPoint2 value)
  178. {
  179. return new[] { value.X, value.Y };
  180. }
  181. public static float[] ToArraySwitched(this IPoint2 value)
  182. {
  183. return new[] { value.X, 1.0f - value.Y };
  184. }
  185. public static float[] ToArraySwitched(this IPoint3 value)
  186. {
  187. return new[] { value.X, value.Z, value.Y };
  188. }
  189. public static float[] ToArray(this IColor value)
  190. {
  191. return new[] { value.R, value.G, value.B };
  192. }
  193. public static IEnumerable<IINode> Nodes(this IINode node)
  194. {
  195. for (int i = 0; i < node.NumberOfChildren; ++i)
  196. if (node.GetChildNode(i) != null)
  197. yield return node.GetChildNode(i);
  198. }
  199. public static IEnumerable<IINode> NodeTree(this IINode node)
  200. {
  201. foreach (var x in node.Nodes())
  202. {
  203. foreach (var y in x.NodeTree())
  204. yield return y;
  205. yield return x;
  206. }
  207. }
  208. public static IEnumerable<IINode> NodesListBySuperClass(this IINode rootNode, SClass_ID sid)
  209. {
  210. return from n in rootNode.NodeTree() where n.ObjectRef != null && n.EvalWorldState(0, false).Obj.SuperClassID == sid select n;
  211. }
  212. public static IEnumerable<IINode> NodesListBySuperClasses(this IINode rootNode, SClass_ID[] sids)
  213. {
  214. return from n in rootNode.NodeTree() where n.ObjectRef != null && sids.Any(sid => n.EvalWorldState(0, false).Obj.SuperClassID == sid) select n;
  215. }
  216. public static float ConvertFov(float fov)
  217. {
  218. return (float)(2.0f * Math.Atan(Math.Tan(fov / 2.0f) / Loader.Core.ImageAspRatio));
  219. }
  220. public static bool HasParent(this IINode node)
  221. {
  222. return node.ParentNode != null && node.ParentNode.ObjectRef != null;
  223. }
  224. public static Guid GetGuid(this IAnimatable node)
  225. {
  226. var uidData = node.GetAppDataChunk(Loader.Class_ID, SClass_ID.Basenode, 0);
  227. Guid uid;
  228. if (uidData != null)
  229. {
  230. uid = new Guid(uidData.Data);
  231. }
  232. else
  233. {
  234. uid = Guid.NewGuid();
  235. node.AddAppDataChunk(Loader.Class_ID, SClass_ID.Basenode, 0, uid.ToByteArray());
  236. }
  237. return uid;
  238. }
  239. public static string GetLocalData(this IAnimatable node)
  240. {
  241. var uidData = node.GetAppDataChunk(Loader.Class_ID, SClass_ID.Basenode, 1);
  242. if (uidData != null)
  243. {
  244. return System.Text.Encoding.UTF8.GetString(uidData.Data);
  245. }
  246. return "";
  247. }
  248. public static void SetLocalData(this IAnimatable node, string value)
  249. {
  250. var uidData = node.GetAppDataChunk(Loader.Class_ID, SClass_ID.Basenode, 1);
  251. if (uidData != null)
  252. {
  253. node.RemoveAppDataChunk(Loader.Class_ID, SClass_ID.Basenode, 1);
  254. }
  255. node.AddAppDataChunk(Loader.Class_ID, SClass_ID.Basenode, 1, System.Text.Encoding.UTF8.GetBytes(value));
  256. }
  257. public static IMatrix3 GetWorldMatrix(this IINode node, int t, bool parent)
  258. {
  259. var tm = node.GetNodeTM(t, Forever);
  260. var ptm = node.ParentNode.GetNodeTM(t, Forever);
  261. if (!parent)
  262. return tm;
  263. if (node.ParentNode.SuperClassID == SClass_ID.Camera)
  264. {
  265. var r = ptm.GetRow(3);
  266. ptm.IdentityMatrix();
  267. ptm.SetRow(3, r);
  268. }
  269. ptm.Invert();
  270. return tm.Multiply(ptm);
  271. }
  272. public static ITriObject GetMesh(this IObject obj)
  273. {
  274. var triObjectClassId = Loader.Global.Class_ID.Create(0x0009, 0);
  275. if (obj.CanConvertToType(triObjectClassId) == 0)
  276. return null;
  277. return obj.ConvertToType(0, triObjectClassId) as ITriObject;
  278. }
  279. public static bool IsAlmostEqualTo(this IPoint4 current, IPoint4 other, float epsilon)
  280. {
  281. if (Math.Abs(current.X - other.X) > epsilon)
  282. {
  283. return false;
  284. }
  285. if (Math.Abs(current.Y - other.Y) > epsilon)
  286. {
  287. return false;
  288. }
  289. if (Math.Abs(current.Z - other.Z) > epsilon)
  290. {
  291. return false;
  292. }
  293. if (Math.Abs(current.W - other.W) > epsilon)
  294. {
  295. return false;
  296. }
  297. return true;
  298. }
  299. public static bool IsAlmostEqualTo(this IPoint3 current, IPoint3 other, float epsilon)
  300. {
  301. if (Math.Abs(current.X - other.X) > epsilon)
  302. {
  303. return false;
  304. }
  305. if (Math.Abs(current.Y - other.Y) > epsilon)
  306. {
  307. return false;
  308. }
  309. if (Math.Abs(current.Z - other.Z) > epsilon)
  310. {
  311. return false;
  312. }
  313. return true;
  314. }
  315. public static bool IsAlmostEqualTo(this IPoint2 current, IPoint2 other, float epsilon)
  316. {
  317. if (Math.Abs(current.X - other.X) > epsilon)
  318. {
  319. return false;
  320. }
  321. if (Math.Abs(current.Y - other.Y) > epsilon)
  322. {
  323. return false;
  324. }
  325. return true;
  326. }
  327. public static bool GetBoolProperty(this IINode node, string propertyName, int defaultState = 0)
  328. {
  329. int state = defaultState;
  330. node.GetUserPropBool(ref propertyName, ref state);
  331. return state == 1;
  332. }
  333. public static float GetFloatProperty(this IINode node, string propertyName, float defaultState = 0)
  334. {
  335. float state = defaultState;
  336. node.GetUserPropFloat(ref propertyName, ref state);
  337. return state;
  338. }
  339. public static float[] GetVector3Property(this IINode node, string propertyName)
  340. {
  341. float state0 = 0;
  342. string name = propertyName + "_x";
  343. node.GetUserPropFloat(ref name, ref state0);
  344. float state1 = 0;
  345. name = propertyName + "_y";
  346. node.GetUserPropFloat(ref name, ref state1);
  347. float state2 = 0;
  348. name = propertyName + "_z";
  349. node.GetUserPropFloat(ref name, ref state2);
  350. return new[] { state0, state1, state2 };
  351. }
  352. public static bool PrepareCheckBox(CheckBox checkBox, IINode node, string propertyName, int defaultState = 0)
  353. {
  354. var state = node.GetBoolProperty(propertyName, defaultState);
  355. if (checkBox.CheckState == CheckState.Indeterminate)
  356. {
  357. checkBox.CheckState = state ? CheckState.Checked : CheckState.Unchecked;
  358. }
  359. else
  360. {
  361. if (!state && checkBox.CheckState == CheckState.Checked ||
  362. state && checkBox.CheckState == CheckState.Unchecked)
  363. {
  364. checkBox.CheckState = CheckState.Indeterminate;
  365. return true;
  366. }
  367. }
  368. return false;
  369. }
  370. public static void PrepareCheckBox(CheckBox checkBox, List<IINode> nodes, string propertyName, int defaultState = 0)
  371. {
  372. checkBox.CheckState = CheckState.Indeterminate;
  373. foreach (var node in nodes)
  374. {
  375. if (PrepareCheckBox(checkBox, node, propertyName, defaultState))
  376. {
  377. break;
  378. }
  379. }
  380. }
  381. public static void UpdateCheckBox(CheckBox checkBox, IINode node, string propertyName)
  382. {
  383. if (checkBox.CheckState != CheckState.Indeterminate)
  384. {
  385. node.SetUserPropBool(ref propertyName, checkBox.CheckState == CheckState.Checked);
  386. }
  387. }
  388. public static void UpdateCheckBox(CheckBox checkBox, List<IINode> nodes, string propertyName)
  389. {
  390. foreach (var node in nodes)
  391. {
  392. UpdateCheckBox(checkBox, node, propertyName);
  393. }
  394. }
  395. public static void PrepareNumericUpDown(NumericUpDown nup, List<IINode> nodes, string propertyName, float defaultState = 0)
  396. {
  397. nup.Value = (decimal)nodes[0].GetFloatProperty(propertyName, defaultState);
  398. }
  399. public static void UpdateNumericUpDown(NumericUpDown nup, List<IINode> nodes, string propertyName)
  400. {
  401. foreach (var node in nodes)
  402. {
  403. node.SetUserPropFloat(ref propertyName, (float)nup.Value);
  404. }
  405. }
  406. public static void PrepareVector3Control(Vector3Control vector3Control, IINode node, string propertyName, float defaultX = 0, float defaultY = 0, float defaultZ = 0)
  407. {
  408. vector3Control.X = node.GetFloatProperty(propertyName + "_x", defaultX);
  409. vector3Control.Y = node.GetFloatProperty(propertyName + "_y", defaultY);
  410. vector3Control.Z = node.GetFloatProperty(propertyName + "_z", defaultZ);
  411. }
  412. public static void UpdateVector3Control(Vector3Control vector3Control, IINode node, string propertyName)
  413. {
  414. string name = propertyName + "_x";
  415. node.SetUserPropFloat(ref name, vector3Control.X);
  416. name = propertyName + "_y";
  417. node.SetUserPropFloat(ref name, vector3Control.Y);
  418. name = propertyName + "_z";
  419. node.SetUserPropFloat(ref name, vector3Control.Z);
  420. }
  421. public static void UpdateVector3Control(Vector3Control vector3Control, List<IINode> nodes, string propertyName)
  422. {
  423. foreach (var node in nodes)
  424. {
  425. UpdateVector3Control(vector3Control, node, propertyName);
  426. }
  427. }
  428. }
  429. }