2
0

Helper3D.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Helper3D.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Text;
  13. using Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.Graphics;
  15. #endregion
  16. namespace RobotGameData.Helper
  17. {
  18. /// <summary>
  19. /// a triangle structure
  20. /// </summary>
  21. public struct Triangle
  22. {
  23. public Vector3 v1;
  24. public Vector3 v2;
  25. public Vector3 v3;
  26. public Triangle(Vector3 point1, Vector3 point2, Vector3 point3)
  27. {
  28. v1 = point1;
  29. v2 = point2;
  30. v3 = point3;
  31. }
  32. public void Clear()
  33. {
  34. v1 = Vector3.Zero;
  35. v2 = Vector3.Zero;
  36. v3 = Vector3.Zero;
  37. }
  38. }
  39. /// <summary>
  40. /// Useful functions about 3D dimension.
  41. /// </summary>
  42. public static class Helper3D
  43. {
  44. public const float Epsilon = 1E-5f; //for numerical imprecision
  45. /// <summary>
  46. /// Checks whether a ray intersects a triangle
  47. /// </summary>
  48. /// <returns>closest intersection point</returns>
  49. public static float? RayIntersectTriangle(Ray ray, Vector3[] vertices,
  50. Matrix transform, out Triangle triangle)
  51. {
  52. triangle.v1 = triangle.v2 = triangle.v3 = Vector3.Zero;
  53. // Keep track of the closest triangle we found so far,
  54. // so we can always return the closest one.
  55. float? closestIntersection = null;
  56. Vector3 v1 = Vector3.Zero;
  57. Vector3 v2 = Vector3.Zero;
  58. Vector3 v3 = Vector3.Zero;
  59. // Loop over the vertex data, 3 at a time (3 vertices = 1 triangle).
  60. for (int i = 0; i < vertices.Length; i += 3)
  61. {
  62. // Perform a ray to triangle intersection test.
  63. float? intersection;
  64. // Transform the three vertex positions into world space
  65. v1 = Vector3.Transform(vertices[i], transform);
  66. v2 = Vector3.Transform(vertices[i + 1], transform);
  67. v3 = Vector3.Transform(vertices[i + 2], transform);
  68. RayIntersectsTriangle(ray, v1, v2, v3, out intersection);
  69. // Does the ray intersect this triangle?
  70. if (intersection != null)
  71. {
  72. // If so, is it closer than any other previous triangle?
  73. if ((closestIntersection == null) ||
  74. (intersection < closestIntersection))
  75. {
  76. // Store the distance to this triangle.
  77. closestIntersection = intersection;
  78. // Store the three vertex positions into the vertex parameters.
  79. triangle.v1 = v1;
  80. triangle.v2 = v2;
  81. triangle.v3 = v3;
  82. }
  83. }
  84. }
  85. return closestIntersection;
  86. }
  87. /// <summary>
  88. /// Checks whether a ray intersects a model. This method needs to access
  89. /// the model vertex data,
  90. /// Returns the distance along the ray to the point of intersection, or null
  91. /// if there is no intersection.
  92. /// </summary>
  93. /// <returns>closest intersection point</returns>
  94. public static float? RayIntersectModel(Ray ray, Model model,
  95. Matrix worldTransform, out bool insideBoundingSphere, out Triangle triangle)
  96. {
  97. triangle.v1 = triangle.v2 = triangle.v3 = Vector3.Zero;
  98. // Look up our custom collision data from the Tag property of the model.
  99. Dictionary<string, object> tagData = (Dictionary<string, object>)model.Tag;
  100. if (tagData == null)
  101. {
  102. throw new InvalidOperationException(
  103. "Model.Tag is not set correctly. Make sure your model " +
  104. "was built using the custom CollideProcessor.");
  105. }
  106. // Start off with a fast bounding sphere test.
  107. BoundingSphere boundingSphere = (BoundingSphere)tagData["BoundingSphere"];
  108. if (boundingSphere.Intersects(ray) == null)
  109. {
  110. // If the ray does not intersect the bounding sphere, we cannot
  111. // possibly have picked this model, so there is no need to even
  112. // bother looking at the individual triangle data.
  113. insideBoundingSphere = false;
  114. return null;
  115. }
  116. else
  117. {
  118. // The bounding sphere test passed, so we need to do a full
  119. // triangle picking test.
  120. insideBoundingSphere = true;
  121. // Keep track of the closest triangle we found so far,
  122. // so we can always return the closest one.
  123. float? closestIntersection = null;
  124. // Loop over the vertex data, 3 at a time (3 vertices = 1 triangle).
  125. Vector3[] vertices = (Vector3[])tagData["Vertices"];
  126. for (int i = 0; i < vertices.Length; i += 3)
  127. {
  128. // Perform a ray to triangle intersection test.
  129. float? intersection;
  130. RayIntersectsTriangle(ray,
  131. vertices[i],
  132. vertices[i + 1],
  133. vertices[i + 2],
  134. out intersection);
  135. // Does the ray intersect this triangle?
  136. if (intersection != null)
  137. {
  138. // If so, is it closer than any other previous triangle?
  139. if ((closestIntersection == null) ||
  140. (intersection < closestIntersection))
  141. {
  142. // Store the distance to this triangle.
  143. closestIntersection = intersection;
  144. // Transform the three vertex positions into world space,
  145. // and store them into the output vertex parameters.
  146. triangle.v1
  147. = Vector3.Transform(vertices[i], worldTransform);
  148. triangle.v2
  149. = Vector3.Transform(vertices[i + 1], worldTransform);
  150. triangle.v3
  151. = Vector3.Transform(vertices[i + 2], worldTransform);
  152. }
  153. }
  154. }
  155. return closestIntersection;
  156. }
  157. }
  158. /// <summary>
  159. /// Checks whether a ray intersects a triangle.
  160. /// This method is implemented using the pass-by-reference versions of the
  161. /// XNA math functions. Using these overloads is generally not recommended,
  162. /// because they make the code less readable than the normal pass-by-value
  163. /// versions. This method can be called very frequently in a tight inner loop,
  164. /// however, so in this particular case the performance benefits from passing
  165. /// everything by reference outweigh the loss of readability.
  166. /// </summary>
  167. public static void RayIntersectsTriangle( Ray ray,
  168. Vector3 vertex1,
  169. Vector3 vertex2,
  170. Vector3 vertex3,
  171. out float? result)
  172. {
  173. // Compute vectors along two edges of the triangle.
  174. Vector3 edge1 = Vector3.Subtract(vertex2, vertex1);
  175. Vector3 edge2 = Vector3.Subtract(vertex3, vertex1);
  176. // Compute the determinant.
  177. Vector3 directionCrossEdge2 = Vector3.Cross(ray.Direction, edge2);
  178. float determinant = Vector3.Dot(edge1, directionCrossEdge2);
  179. // If the ray is parallel to the triangle plane, there is no collision.
  180. if (determinant > -float.Epsilon && determinant < float.Epsilon)
  181. {
  182. result = null;
  183. return;
  184. }
  185. float inverseDeterminant = 1.0f / determinant;
  186. // Calculate the U parameter of the intersection point.
  187. Vector3 distanceVector = Vector3.Subtract(ray.Position, vertex1);
  188. float triangleU = Vector3.Dot(distanceVector, directionCrossEdge2);
  189. triangleU *= inverseDeterminant;
  190. // Make sure it is inside the triangle.
  191. if (triangleU < 0 || triangleU > 1)
  192. {
  193. result = null;
  194. return;
  195. }
  196. // Calculate the V parameter of the intersection point.
  197. Vector3 distanceCrossEdge1 = Vector3.Cross(distanceVector, edge1);
  198. float triangleV = Vector3.Dot(ray.Direction, distanceCrossEdge1);
  199. triangleV *= inverseDeterminant;
  200. // Make sure it is inside the triangle.
  201. if (triangleV < 0 || triangleU + triangleV > 1)
  202. {
  203. result = null;
  204. return;
  205. }
  206. // Compute the distance along the ray to the triangle.
  207. float rayDistance = Vector3.Dot(edge2, distanceCrossEdge1);
  208. rayDistance *= inverseDeterminant;
  209. // Is the triangle behind the ray origin?
  210. if (rayDistance < 0)
  211. {
  212. result = null;
  213. return;
  214. }
  215. result = rayDistance;
  216. }
  217. public static Plane TransformPlane(ref Plane plane, ref Matrix matrix)
  218. {
  219. Vector3 normal = plane.Normal;
  220. normal.Normalize();
  221. Vector3 planeCenter = Vector3.Zero + plane.D * normal;
  222. Vector3 newCenter = Vector3.Transform(planeCenter, matrix);
  223. Vector3 centerToOrigin = Vector3.Zero - newCenter;
  224. float newDistance = Math.Abs(centerToOrigin.Length());
  225. Vector3 newNormal = Vector3.TransformNormal(normal, matrix);
  226. newNormal.Normalize();
  227. return new Plane(newNormal, newDistance);
  228. }
  229. /// <summary>
  230. /// Intersect point inside triangle.
  231. /// </summary>
  232. /// <param name="vA">vertex 1</param>
  233. /// <param name="vB">vertex 2</param>
  234. /// <param name="vC">vertex 3</param>
  235. /// <param name="p">point</param>
  236. /// <returns></returns>
  237. public static bool PointInsidePoly(Vector3 vectorA, Vector3 vectorB,
  238. Vector3 vectorC, Vector3 point)
  239. {
  240. int positives = 0;
  241. int negatives = 0;
  242. Vector3[] verts = { vectorA, vectorB, vectorC };
  243. Plane plane = new Plane(vectorA, vectorB, vectorC);
  244. uint v0 = 3 - 1;
  245. for (uint v1 = 0; v1 < 3; v0 = v1, ++v1)
  246. {
  247. Vector3 point0 = verts[v0];
  248. Vector3 point1 = verts[v1];
  249. // Generate a normal for this edge
  250. Vector3 normal = Vector3.Cross(point1 - point0, plane.Normal);
  251. // Which side of this edge-plane is the point?
  252. float halfPlane = Vector3.Dot(point, normal) -
  253. Vector3.Dot(point0, normal);
  254. // Keep track of positives and negatives
  255. //(but not zeros -- which means it's on the edge)
  256. if (halfPlane > Epsilon) positives++;
  257. else if (halfPlane < -Epsilon) negatives++;
  258. // Early-out
  259. if ((positives | negatives) != 0) return false;
  260. }
  261. // If they're ALL positive, or ALL negative, then it's inside
  262. if ((positives | negatives) == 0) return true;
  263. // Must not be inside, because some were pos and some were neg
  264. return false;
  265. }
  266. /// <summary>
  267. /// It calculates the perpendicular point of the specified point and the line.
  268. /// </summary>
  269. public static bool GetPerpendicularPoint(Vector3 vector1, Vector3 vector2,
  270. Vector3 point,
  271. out Vector3 perpendicular, out float t)
  272. {
  273. Vector3 vector12 = vector2 - vector1;
  274. Vector3 vector10 = point - vector1;
  275. Vector3 norm = Vector3.Normalize(vector12);
  276. perpendicular = Vector3.Zero;
  277. t = 0.0f;
  278. float num = Vector3.Dot(norm, vector10);
  279. float den = Vector3.Dot(norm, vector12);
  280. if (den * den < 1E-15f * num * num)
  281. return false;
  282. t = num / den;
  283. perpendicular = vector1 + (vector12 * t);
  284. if (t > 0.0f && t < 1.0f) return true;
  285. return false;
  286. }
  287. /// <summary>
  288. /// Calculates whether a line intersects a triangle
  289. /// </summary>
  290. public static bool LineIntersectSphere(Vector3 vector1, Vector3 vector2,
  291. Vector3 center, float radius, out Vector3 intersect, out float t)
  292. {
  293. Vector3 len = Vector3.Zero;
  294. if (GetPerpendicularPoint(vector1, vector2, center, out intersect, out t))
  295. {
  296. len = intersect - center;
  297. if (len.Length() < radius) return true;
  298. return false;
  299. }
  300. len = vector2 - center;
  301. if (len.Length() < radius)
  302. {
  303. intersect = vector2;
  304. t = 1.0f;
  305. return true;
  306. }
  307. len = vector1 - center;
  308. if (len.Length() < radius)
  309. {
  310. intersect = vector1;
  311. t = 0.0f;
  312. return true;
  313. }
  314. return false;
  315. }
  316. /// <summary>
  317. /// Calculates whether a sphere intersects a triangle
  318. /// </summary>
  319. public static bool SphereIntersectTriangle(Vector3 center, float radius,
  320. Vector3 vector1, Vector3 vector2,
  321. Vector3 vector3,
  322. out Vector3 interset, out float t)
  323. {
  324. Vector3 normal =
  325. Vector3.Normalize(Vector3.Cross(vector3 - vector1, vector2 - vector1));
  326. float dot = Math.Abs(Vector3.Dot(center - vector1, normal));
  327. interset = Vector3.Zero;
  328. t = dot;
  329. if (dot < radius)
  330. {
  331. Vector3 projCenter = normal * -dot;
  332. projCenter += center;
  333. // Colliding center
  334. if (PointInsidePoly(vector1, vector2, vector3, center))
  335. {
  336. interset = projCenter;
  337. t = dot - radius;
  338. return true;
  339. }
  340. // Colliding edge
  341. Vector3 intersect1 = Vector3.Zero;
  342. Vector3 intersect2 = Vector3.Zero;
  343. Vector3 intersect3 = Vector3.Zero;
  344. float t1 = 0.0f;
  345. float t2 = 0.0f;
  346. float t3 = 0.0f;
  347. bool bHit1 = LineIntersectSphere(vector1, vector2, center, radius,
  348. out intersect1, out t1);
  349. bool bHit2 = LineIntersectSphere(vector1, vector3, center, radius,
  350. out intersect2, out t2);
  351. bool bHit3 = LineIntersectSphere(vector2, vector3, center, radius,
  352. out intersect3, out t3);
  353. if (bHit1 || bHit2 || bHit3)
  354. {
  355. float min = (t1 < t2 ? (t1 < t3 ? t1 : t3) : (t2 < t3 ? t2 : t3));
  356. if (t1 == min)
  357. interset = intersect1;
  358. else if (t2 == min)
  359. interset = intersect2;
  360. else if (t3 == min)
  361. interset = intersect3;
  362. Vector3 len = center - interset;
  363. t = len.Length();
  364. return true;
  365. }
  366. }
  367. return false;
  368. }
  369. /// <summary>
  370. /// Calculates whether a ray intersects a triangle
  371. /// </summary>
  372. public static bool RayTriangleIntersect(Vector3 rayOrigin, Vector3 rayDirection,
  373. Vector3 vertex0, Vector3 vertex1, Vector3 vertex2,
  374. out float t, out float u, out float v)
  375. {
  376. t = 0; u = 0; v = 0;
  377. Vector3 edge1 = vertex1 - vertex0;
  378. Vector3 edge2 = vertex2 - vertex0;
  379. Vector3 tvec, pvec, qvec;
  380. float det, inv_det;
  381. Vector3.Cross(ref rayDirection, ref edge2, out pvec);
  382. det = Vector3.Dot(edge1, pvec);
  383. if (det > -0.00001f)
  384. return false;
  385. inv_det = 1.0f / det;
  386. tvec = rayOrigin - vertex0;
  387. u = Vector3.Dot(tvec, pvec) * inv_det;
  388. if (u < -0.001f || u > 1.001f)
  389. return false;
  390. qvec = Vector3.Cross(tvec, edge1);
  391. v = Vector3.Dot(rayDirection, qvec) * inv_det;
  392. if (v < -0.001f || u + v > 1.001f)
  393. return false;
  394. t = Vector3.Dot(edge2, qvec) * inv_det;
  395. if (t <= 0)
  396. return false;
  397. return true;
  398. }
  399. /// <summary>
  400. /// Calculates whether a ray intersects a triangle
  401. /// </summary>
  402. public static bool RayTriangleIntersect(Vector3 origin, Vector3 direction,
  403. Vector3 vertex0, Vector3 vertex1,
  404. Vector3 vertex2,
  405. out float t, out float u, out float v,
  406. bool testCull)
  407. {
  408. // Make sure the "out" params are set.
  409. t = 0; u = 0; v = 0;
  410. // Get vectors for the two edges that share vert0
  411. Vector3 edge1 = vertex1 - vertex0;
  412. Vector3 edge2 = vertex2 - vertex0;
  413. Vector3 tvec, pvec, qvec;
  414. float det, inv_det;
  415. // Begin calculating determinant
  416. pvec = Vector3.Cross(direction, edge2);
  417. // If the determinant is near zero, ray lies in plane of triangle
  418. det = Vector3.Dot(edge1, pvec);
  419. if (testCull)
  420. {
  421. if (det < Helper3D.Epsilon)
  422. return false;
  423. tvec = origin - vertex0;
  424. u = Vector3.Dot(tvec, pvec);
  425. if (u < 0.0 || u > det)
  426. return false;
  427. qvec = Vector3.Cross(tvec, edge1);
  428. v = Vector3.Dot(direction, qvec);
  429. if (v < 0.0f || u + v > det)
  430. return false;
  431. t = Vector3.Dot(edge2, qvec);
  432. inv_det = 1.0f / det;
  433. t *= inv_det;
  434. u *= inv_det;
  435. v *= inv_det;
  436. }
  437. else
  438. {
  439. // Account for Float rounding errors / inaccuracies.
  440. if (det > -Helper3D.Epsilon && det < Helper3D.Epsilon)
  441. return false;
  442. // Get the inverse determinant
  443. inv_det = 1.0f / det;
  444. // Calculate distance from vert0 to ray origin
  445. tvec = origin - vertex0;
  446. // Calculate U parameter and test bounds
  447. u = Vector3.Dot(tvec, pvec) * inv_det;
  448. if (u < 0.0f || u > 1.0f)
  449. return false;
  450. // Prepare for v
  451. qvec = Vector3.Cross(tvec, edge1);
  452. // Calculate V parameter and test bounds
  453. v = Vector3.Dot(direction, qvec) * inv_det;
  454. if (v < 0.0f || u + v > 1.0f)
  455. return false;
  456. // Calculate t, ray intersects triangle.
  457. t = Vector3.Dot(edge2, qvec) * inv_det;
  458. }
  459. return true;
  460. }
  461. /// <summary>
  462. /// ray intersect face and return intersection distance, point and normal.
  463. /// </summary>
  464. public static bool PointIntersect(Vector3 rayOrigin, Vector3 rayDirection,
  465. Triangle triangle, out float intersectDistance,
  466. out Vector3 intersectPosition, out Vector3 intersectNormal)
  467. {
  468. intersectDistance = 0.0f;
  469. intersectPosition = rayOrigin;
  470. intersectNormal = Vector3.Zero;
  471. Vector3 uvt = Vector3.Zero;
  472. if (RayTriangleIntersect(rayOrigin, rayDirection,
  473. triangle.v1, triangle.v2, triangle.v3,
  474. out uvt.Z, out uvt.X, out uvt.Y))
  475. {
  476. intersectDistance = uvt.Z;
  477. intersectPosition = (1.0f - uvt.X - uvt.Y) * triangle.v1 + uvt.X *
  478. triangle.v2 + uvt.Y * triangle.v3;
  479. intersectNormal = Vector3.Normalize(
  480. Vector3.Cross(triangle.v3 - triangle.v1, triangle.v2 - triangle.v1));
  481. return true;
  482. }
  483. return false;
  484. }
  485. /// <summary>
  486. /// Calculates a world space ray starting at the camera's
  487. /// "eye" and pointing in the direction of 2D screen position.
  488. /// Viewport.Unproject is used to accomplish this.
  489. /// </summary>
  490. public static Ray ScreenPositionToRay(Vector2 screenPosition,
  491. Matrix projectionMatrix, Matrix viewMatrix,
  492. GraphicsDevice device)
  493. {
  494. // create 2 positions in screenspace using the cursor position. 0 is as
  495. // close as possible to the camera, 1 is as far away as possible.
  496. Vector3 nearSource = new Vector3(screenPosition, 0f);
  497. Vector3 farSource = new Vector3(screenPosition, 1f);
  498. // use Viewport.Unproject to tell what those two screen space positions
  499. // would be in world space. we'll need the projection matrix and view
  500. // matrix, which we have saved as member variables. We also need a world
  501. // matrix, which can just be identity.
  502. Vector3 nearPoint = device.Viewport.Unproject(nearSource,
  503. projectionMatrix, viewMatrix, Matrix.Identity);
  504. Vector3 farPoint = device.Viewport.Unproject(farSource,
  505. projectionMatrix, viewMatrix, Matrix.Identity);
  506. // find the direction vector that goes from the nearPoint to the farPoint
  507. // and normalize it....
  508. Vector3 direction = farPoint - nearPoint;
  509. direction.Normalize();
  510. // and then create a new ray using nearPoint as the source.
  511. return new Ray(nearPoint, direction);
  512. }
  513. static Vector3[] axis3x3 = new Vector3[3]
  514. {
  515. new Vector3(1.0f, 0.0f, 0.0f),
  516. new Vector3(0.0f, 1.0f, 0.0f),
  517. new Vector3(0.0f, 0.0f, 1.0f),
  518. };
  519. public static Matrix MakeMatrixWithUp(Vector3 up, Vector3 at)
  520. {
  521. Matrix matrix = Matrix.Identity;
  522. matrix.Up = Vector3.Normalize(up);
  523. float dot = Vector3.Dot(matrix.Up, at);
  524. if (Math.Abs(dot) >= 1.0f - Epsilon)
  525. {
  526. for (int i = 0; (i < 3) && (Math.Abs(dot) >= 1.0f - Epsilon); i++)
  527. {
  528. dot = Vector3.Dot(matrix.Up, axis3x3[i]);
  529. if (Math.Abs(dot) < 1.0f - Epsilon)
  530. {
  531. matrix.Right = Vector3.Cross(axis3x3[i], matrix.Up);
  532. matrix.Right.Normalize();
  533. break;
  534. }
  535. }
  536. }
  537. else
  538. {
  539. matrix.Right = Vector3.Cross(at, matrix.Up);
  540. matrix.Right.Normalize();
  541. }
  542. matrix.Forward = Vector3.Cross(matrix.Right, matrix.Up);
  543. matrix.Forward.Normalize();
  544. matrix.Translation = Vector3.Zero;
  545. return matrix;
  546. }
  547. public static Matrix MakeMatrixWithAt(Vector3 at, Vector3 up)
  548. {
  549. Matrix matrix = Matrix.Identity;
  550. matrix.Forward = Vector3.Normalize(at);
  551. float dot = Vector3.Dot(matrix.Forward, up);
  552. if (Math.Abs(dot) >= 1.0f - Epsilon)
  553. {
  554. for (int i = 0; (i < 3) && (Math.Abs(dot) >= 1.0f - Epsilon); i++)
  555. {
  556. dot = Vector3.Dot(matrix.Forward, axis3x3[i]);
  557. if (Math.Abs(dot) < 1.0f - Epsilon)
  558. {
  559. matrix.Right = Vector3.Cross(matrix.Forward, axis3x3[i]);
  560. matrix.Right.Normalize();
  561. break;
  562. }
  563. }
  564. }
  565. else
  566. {
  567. matrix.Right = Vector3.Cross(matrix.Forward, up);
  568. matrix.Right.Normalize();
  569. }
  570. matrix.Up = Vector3.Cross(matrix.Forward, matrix.Right);
  571. matrix.Up.Normalize();
  572. matrix.Translation = Vector3.Zero;
  573. return matrix;
  574. }
  575. public static Vector3 TransformCoord(Vector3 vector, Matrix matrix)
  576. {
  577. float x = 0.0f, y = 0.0f, z = 0.0f, w = 0.0f;
  578. x = (matrix.M11 * vector.X) + (matrix.M21 * vector.Y) +
  579. (matrix.M31 * vector.Z) + matrix.M41;
  580. y = (matrix.M12 * vector.X) + (matrix.M22 * vector.Y) +
  581. (matrix.M32 * vector.Z) + matrix.M42;
  582. z = (matrix.M13 * vector.X) + (matrix.M23 * vector.Y) +
  583. (matrix.M33 * vector.Z) + matrix.M43;
  584. w = (matrix.M14 * vector.X) + (matrix.M24 * vector.Y) +
  585. (matrix.M34 * vector.Z) + matrix.M44;
  586. return new Vector3((x / w), (y / w), (z / w));
  587. }
  588. /// <summary>
  589. /// Transposes the rows and columns of a matrix.
  590. /// It only has the rotation value.
  591. /// </summary>
  592. public static Matrix Transpose(Matrix matrix)
  593. {
  594. Matrix temp = matrix;
  595. Matrix transpose = Matrix.Transpose(matrix);
  596. temp.Right = transpose.Right;
  597. temp.Up = transpose.Up;
  598. temp.Forward = transpose.Forward;
  599. return temp;
  600. }
  601. public static Matrix PreScale(Matrix matrix, Vector3 vector)
  602. {
  603. matrix.M11 = matrix.M11 * vector.X;
  604. matrix.M12 = matrix.M12 * vector.X;
  605. matrix.M13 = matrix.M13 * vector.X;
  606. matrix.M14 = matrix.M14 * vector.X;
  607. matrix.M21 = matrix.M21 * vector.Y;
  608. matrix.M22 = matrix.M22 * vector.Y;
  609. matrix.M23 = matrix.M23 * vector.Y;
  610. matrix.M24 = matrix.M24 * vector.Y;
  611. matrix.M31 = matrix.M31 * vector.Z;
  612. matrix.M32 = matrix.M32 * vector.Z;
  613. matrix.M33 = matrix.M33 * vector.Z;
  614. matrix.M34 = matrix.M34 * vector.Z;
  615. return matrix;
  616. }
  617. public static Matrix PostScale(Matrix matrix, Vector3 vector)
  618. {
  619. matrix.M11 = matrix.M11 * vector.X;
  620. matrix.M21 = matrix.M21 * vector.X;
  621. matrix.M31 = matrix.M31 * vector.X;
  622. matrix.M41 = matrix.M41 * vector.X;
  623. matrix.M12 = matrix.M12 * vector.Y;
  624. matrix.M22 = matrix.M22 * vector.Y;
  625. matrix.M32 = matrix.M32 * vector.Y;
  626. matrix.M42 = matrix.M42 * vector.Y;
  627. matrix.M13 = matrix.M13 * vector.Z;
  628. matrix.M23 = matrix.M23 * vector.Z;
  629. matrix.M33 = matrix.M33 * vector.Z;
  630. matrix.M43 = matrix.M43 * vector.Z;
  631. return matrix;
  632. }
  633. }
  634. }