HelperTypes.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Diagnostics;
  30. using System.Globalization;
  31. using OpenSim.Region.Physics.Manager;
  32. using OpenSim.Region.Physics.Meshing;
  33. public class Quaternion
  34. {
  35. public float x = 0;
  36. public float y = 0;
  37. public float z = 0;
  38. public float w = 1;
  39. public Quaternion()
  40. {
  41. }
  42. public Quaternion(float x1, float y1, float z1, float w1)
  43. {
  44. x = x1; y = y1; z = z1; w = w1;
  45. }
  46. public Quaternion(Vertex axis, float angle)
  47. {
  48. // using (* 0.5) instead of (/2)
  49. w = (float)Math.Cos(angle * 0.5f);
  50. x = axis.X * (float)Math.Sin(angle * 0.5f);
  51. y = axis.Y * (float)Math.Sin(angle * 0.5f);
  52. z = axis.Z * (float)Math.Sin(angle * 0.5f);
  53. normalize();
  54. }
  55. public static Quaternion operator *(Quaternion a, Quaternion b)
  56. {
  57. Quaternion c = new Quaternion();
  58. c.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y;
  59. c.y = a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z;
  60. c.z = a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x;
  61. c.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;
  62. return c;
  63. }
  64. public Matrix4 computeMatrix()
  65. {
  66. return new Matrix4(this);
  67. }
  68. public void normalize()
  69. {
  70. float mag = length();
  71. w /= mag;
  72. x /= mag;
  73. y /= mag;
  74. z /= mag;
  75. }
  76. public float length()
  77. {
  78. return (float)Math.Sqrt(w * w + x * x + y * y + z * z);
  79. }
  80. }
  81. public class Matrix4
  82. {
  83. public float m00 = 0;
  84. public float m01 = 0;
  85. public float m02 = 0;
  86. public float m03 = 0;
  87. public float m10 = 0;
  88. public float m11 = 0;
  89. public float m12 = 0;
  90. public float m13 = 0;
  91. public float m20 = 0;
  92. public float m21 = 0;
  93. public float m22 = 0;
  94. public float m23 = 0;
  95. public float m30 = 0;
  96. public float m31 = 0;
  97. public float m32 = 0;
  98. public float m33 = 1;
  99. public Matrix4(float m001, float m011, float m021, float m031, float m101, float m111, float m121, float m131, float m201, float m211, float m221, float m231, float m301, float m311, float m321, float m331)
  100. {
  101. m00 = m001;
  102. m01 = m011;
  103. m02 = m021;
  104. m03 = m031;
  105. m10 = m101;
  106. m11 = m111;
  107. m12 = m121;
  108. m13 = m131;
  109. m20 = m201;
  110. m21 = m211;
  111. m22 = m221;
  112. m23 = m231;
  113. m30 = m301;
  114. m31 = m311;
  115. m32 = m321;
  116. m33 = m331;
  117. }
  118. public Matrix4()
  119. {
  120. }
  121. public Matrix4(Quaternion r)
  122. {
  123. m00 = 1 - (2 * (r.y * r.y)) - (2 * (r.z * r.z));
  124. m01 = (r.x * r.y * 2) - (r.w * r.z * 2);
  125. m02 = (r.x * r.z * 2) + (r.w * r.y * 2);
  126. m03 = 0f;
  127. m10 = (r.x * r.y * 2) + (r.w * r.z * 2);
  128. m11 = 1 - (2 * (r.x * r.x)) - (2 * (r.z * r.z));
  129. m12 = (r.y * r.z * 2) - (r.w * r.x * 2);
  130. m13 = 0f;
  131. m20 = (r.x * r.z * 2) - (r.w * r.y * 2);
  132. m21 = (r.y * r.z * 2) - (r.w * r.x * 2);
  133. m22 = 1 - (2 * (r.x * r.x)) - (2 * (r.y * r.y));
  134. m23 = 0f;
  135. m30 = 0f;
  136. m31 = 0f;
  137. m32 = 0f;
  138. m33 = 1f;
  139. }
  140. public Vertex transform(Vertex o)
  141. {
  142. Vertex r = new Vertex(0,0,0);
  143. // w value implicitly 1 therefore the last + m3x actually represents (m3x * o.W) = m3x
  144. // in calculating the dot product.
  145. r.X = (m00 * o.X) + (m10 * o.Y) + (m20 * o.Z) + m30;
  146. r.Y = (m01 * o.X) + (m11 * o.Y) + (m21 * o.Z) + m31;
  147. r.Z = (m02 * o.X) + (m12 * o.Y) + (m22 * o.Z) + m32;
  148. return r;
  149. }
  150. }
  151. public class Vertex : PhysicsVector, IComparable<Vertex>
  152. {
  153. public Vertex(float x, float y, float z)
  154. : base(x, y, z)
  155. {
  156. }
  157. public Vertex normalize()
  158. {
  159. float tlength = length();
  160. if (tlength != 0)
  161. {
  162. return new Vertex(X / tlength, Y / tlength, Z / tlength);
  163. }
  164. else
  165. {
  166. return new Vertex(0, 0, 0);
  167. }
  168. }
  169. public Vertex cross(Vertex v)
  170. {
  171. return new Vertex(Y * v.Z - Z * v.Y, Z * v.X - X * v.Z, X * v.Y - Y * v.X);
  172. }
  173. public static Vertex operator *(Vertex v, Quaternion q)
  174. {
  175. Matrix4 tm = q.computeMatrix();
  176. return tm.transform(v);
  177. }
  178. public static Vertex operator +(Vertex v1, Vertex v2)
  179. {
  180. return new Vertex(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
  181. }
  182. public static Vertex operator -(Vertex v1, Vertex v2)
  183. {
  184. return new Vertex(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
  185. }
  186. public static Vertex operator *(Vertex v1, Vertex v2)
  187. {
  188. return new Vertex(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z);
  189. }
  190. public static Vertex operator +(Vertex v1, float am)
  191. {
  192. v1.X += am;
  193. v1.Y += am;
  194. v1.Z += am;
  195. return v1;
  196. }
  197. public static Vertex operator -(Vertex v1, float am)
  198. {
  199. v1.X -= am;
  200. v1.Y -= am;
  201. v1.Z -= am;
  202. return v1;
  203. }
  204. public static Vertex operator *(Vertex v1, float am)
  205. {
  206. v1.X *= am;
  207. v1.Y *= am;
  208. v1.Z *= am;
  209. return v1;
  210. }
  211. public static Vertex operator /(Vertex v1, float am)
  212. {
  213. if (am == 0f)
  214. {
  215. return new Vertex(0f,0f,0f);
  216. }
  217. v1.X /= am;
  218. v1.Y /= am;
  219. v1.Z /= am;
  220. return v1;
  221. }
  222. public float dot(Vertex v)
  223. {
  224. return X * v.X + Y * v.Y + Z * v.Z;
  225. }
  226. public Vertex(PhysicsVector v)
  227. : base(v.X, v.Y, v.Z)
  228. {
  229. }
  230. public Vertex Clone()
  231. {
  232. return new Vertex(X, Y, Z);
  233. }
  234. public static Vertex FromAngle(double angle)
  235. {
  236. return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f);
  237. }
  238. public virtual bool Equals(Vertex v, float tolerance)
  239. {
  240. PhysicsVector diff = this - v;
  241. float d = diff.length();
  242. if (d < tolerance)
  243. return true;
  244. return false;
  245. }
  246. public int CompareTo(Vertex other)
  247. {
  248. if (X < other.X)
  249. return -1;
  250. if (X > other.X)
  251. return 1;
  252. if (Y < other.Y)
  253. return -1;
  254. if (Y > other.Y)
  255. return 1;
  256. if (Z < other.Z)
  257. return -1;
  258. if (Z > other.Z)
  259. return 1;
  260. return 0;
  261. }
  262. public static bool operator >(Vertex me, Vertex other)
  263. {
  264. return me.CompareTo(other) > 0;
  265. }
  266. public static bool operator <(Vertex me, Vertex other)
  267. {
  268. return me.CompareTo(other) < 0;
  269. }
  270. public String ToRaw()
  271. {
  272. // Why this stuff with the number formatter?
  273. // Well, the raw format uses the english/US notation of numbers
  274. // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1.
  275. // The german notation uses these characters exactly vice versa!
  276. // The Float.ToString() routine is a localized one, giving different results depending on the country
  277. // settings your machine works with. Unusable for a machine readable file format :-(
  278. NumberFormatInfo nfi = new NumberFormatInfo();
  279. nfi.NumberDecimalSeparator = ".";
  280. nfi.NumberDecimalDigits = 3;
  281. String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi);
  282. return s1;
  283. }
  284. }
  285. public class Triangle
  286. {
  287. public Vertex v1;
  288. public Vertex v2;
  289. public Vertex v3;
  290. private float radius_square;
  291. private float cx;
  292. private float cy;
  293. public Triangle(Vertex _v1, Vertex _v2, Vertex _v3)
  294. {
  295. v1 = _v1;
  296. v2 = _v2;
  297. v3 = _v3;
  298. CalcCircle();
  299. }
  300. public bool isInCircle(float x, float y)
  301. {
  302. float dx, dy;
  303. float dd;
  304. dx = x - cx;
  305. dy = y - cy;
  306. dd = dx*dx + dy*dy;
  307. if (dd < radius_square)
  308. return true;
  309. else
  310. return false;
  311. }
  312. public bool isDegraded()
  313. {
  314. // This means, the vertices of this triangle are somewhat strange.
  315. // They either line up or at least two of them are identical
  316. return (radius_square == 0.0);
  317. }
  318. private void CalcCircle()
  319. {
  320. // Calculate the center and the radius of a circle given by three points p1, p2, p3
  321. // It is assumed, that the triangles vertices are already set correctly
  322. double p1x, p2x, p1y, p2y, p3x, p3y;
  323. // Deviation of this routine:
  324. // A circle has the general equation (M-p)^2=r^2, where M and p are vectors
  325. // this gives us three equations f(p)=r^2, each for one point p1, p2, p3
  326. // putting respectively two equations together gives two equations
  327. // f(p1)=f(p2) and f(p1)=f(p3)
  328. // bringing all constant terms to one side brings them to the form
  329. // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors)
  330. // and c1, c2 are scalars (Naming conventions like the variables below)
  331. // Now using the equations that are formed by the components of the vectors
  332. // and isolate Mx lets you make one equation that only holds My
  333. // The rest is straight forward and eaasy :-)
  334. //
  335. /* helping variables for temporary results */
  336. double c1, c2;
  337. double v1x, v1y, v2x, v2y;
  338. double z, n;
  339. double rx, ry;
  340. // Readout the three points, the triangle consists of
  341. p1x = v1.X;
  342. p1y = v1.Y;
  343. p2x = v2.X;
  344. p2y = v2.Y;
  345. p3x = v3.X;
  346. p3y = v3.Y;
  347. /* calc helping values first */
  348. c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2;
  349. c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2;
  350. v1x = p1x - p2x;
  351. v1y = p1y - p2y;
  352. v2x = p1x - p3x;
  353. v2y = p1y - p3y;
  354. z = (c1*v2x - c2*v1x);
  355. n = (v1y*v2x - v2y*v1x);
  356. if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location
  357. {
  358. radius_square = 0.0f;
  359. return;
  360. }
  361. cy = (float) (z/n);
  362. if (v2x != 0.0)
  363. {
  364. cx = (float) ((c2 - v2y*cy)/v2x);
  365. }
  366. else if (v1x != 0.0)
  367. {
  368. cx = (float) ((c1 - v1y*cy)/v1x);
  369. }
  370. else
  371. {
  372. Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */
  373. }
  374. rx = (p1x - cx);
  375. ry = (p1y - cy);
  376. radius_square = (float) (rx*rx + ry*ry);
  377. }
  378. public List<Simplex> GetSimplices()
  379. {
  380. List<Simplex> result = new List<Simplex>();
  381. Simplex s1 = new Simplex(v1, v2);
  382. Simplex s2 = new Simplex(v2, v3);
  383. Simplex s3 = new Simplex(v3, v1);
  384. result.Add(s1);
  385. result.Add(s2);
  386. result.Add(s3);
  387. return result;
  388. }
  389. public override String ToString()
  390. {
  391. NumberFormatInfo nfi = new NumberFormatInfo();
  392. nfi.CurrencyDecimalDigits = 2;
  393. nfi.CurrencyDecimalSeparator = ".";
  394. String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">";
  395. String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">";
  396. String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">";
  397. return s1 + ";" + s2 + ";" + s3;
  398. }
  399. public PhysicsVector getNormal()
  400. {
  401. // Vertices
  402. // Vectors for edges
  403. PhysicsVector e1;
  404. PhysicsVector e2;
  405. e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
  406. e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
  407. // Cross product for normal
  408. PhysicsVector n = PhysicsVector.cross(e1, e2);
  409. // Length
  410. float l = n.length();
  411. // Normalized "normal"
  412. n = n/l;
  413. return n;
  414. }
  415. public void invertNormal()
  416. {
  417. Vertex vt;
  418. vt = v1;
  419. v1 = v2;
  420. v2 = vt;
  421. }
  422. // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and
  423. // debugging purposes
  424. public String ToStringRaw()
  425. {
  426. String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw();
  427. return output;
  428. }
  429. }