Extruder.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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 OpenSim.Region.Physics.Manager;
  28. namespace OpenSim.Region.Physics.Meshing
  29. {
  30. internal class Extruder
  31. {
  32. public float startParameter;
  33. public float stopParameter;
  34. public PhysicsVector size;
  35. public float taperTopFactorX = 1f;
  36. public float taperTopFactorY = 1f;
  37. public float taperBotFactorX = 1f;
  38. public float taperBotFactorY = 1f;
  39. public float pushX = 0f;
  40. public float pushY = 0f;
  41. // twist amount in radians. NOT DEGREES.
  42. public float twistTop = 0;
  43. public float twistBot = 0;
  44. public float twistMid = 0;
  45. public Mesh Extrude(Mesh m)
  46. {
  47. startParameter = float.MinValue;
  48. stopParameter = float.MaxValue;
  49. // Currently only works for iSteps=1;
  50. Mesh result = new Mesh();
  51. Mesh workingPlus = m.Clone();
  52. Mesh workingMiddle = m.Clone();
  53. Mesh workingMinus = m.Clone();
  54. Quaternion tt = new Quaternion();
  55. Vertex v2 = new Vertex(0, 0, 0);
  56. foreach (Vertex v in workingPlus.vertices)
  57. {
  58. if (v == null)
  59. continue;
  60. // This is the top
  61. // Set the Z + .5 to match the rest of the scale of the mesh
  62. // Scale it by Size, and Taper the scaling
  63. v.Z = +.5f;
  64. v.X *= (size.X * taperTopFactorX);
  65. v.Y *= (size.Y * taperTopFactorY);
  66. v.Z *= size.Z;
  67. //Push the top of the object over by the Top Shear amount
  68. v.X += pushX * size.X;
  69. v.Y += pushY * size.X;
  70. if (twistTop != 0)
  71. {
  72. // twist and shout
  73. tt = new Quaternion(new Vertex(0, 0, 1), twistTop);
  74. v2 = v * tt;
  75. v.X = v2.X;
  76. v.Y = v2.Y;
  77. v.Z = v2.Z;
  78. }
  79. }
  80. foreach (Vertex v in workingMiddle.vertices)
  81. {
  82. if (v == null)
  83. continue;
  84. // This is the top
  85. // Set the Z + .5 to match the rest of the scale of the mesh
  86. // Scale it by Size, and Taper the scaling
  87. v.Z *= size.Z;
  88. v.X *= (size.X * ((taperTopFactorX + taperBotFactorX) /2));
  89. v.Y *= (size.Y * ((taperTopFactorY + taperBotFactorY) / 2));
  90. v.X += (pushX / 2) * size.X;
  91. v.Y += (pushY / 2) * size.X;
  92. //Push the top of the object over by the Top Shear amount
  93. if (twistMid != 0)
  94. {
  95. // twist and shout
  96. tt = new Quaternion(new Vertex(0, 0, 1), twistMid);
  97. v2 = v * tt;
  98. v.X = v2.X;
  99. v.Y = v2.Y;
  100. v.Z = v2.Z;
  101. }
  102. }
  103. foreach (Vertex v in workingMinus.vertices)
  104. {
  105. if (v == null)
  106. continue;
  107. // This is the bottom
  108. v.Z = -.5f;
  109. v.X *= (size.X * taperBotFactorX);
  110. v.Y *= (size.Y * taperBotFactorY);
  111. v.Z *= size.Z;
  112. if (twistBot != 0)
  113. {
  114. // twist and shout
  115. tt = new Quaternion(new Vertex(0, 0, 1), twistBot);
  116. v2 = v * tt;
  117. v.X = v2.X;
  118. v.Y = v2.Y;
  119. v.Z = v2.Z;
  120. }
  121. }
  122. foreach (Triangle t in workingMinus.triangles)
  123. {
  124. t.invertNormal();
  125. }
  126. result.Append(workingMinus);
  127. result.Append(workingMiddle);
  128. int iLastNull = 0;
  129. for (int i = 0; i < workingMiddle.vertices.Count; i++)
  130. {
  131. int iNext = (i + 1);
  132. if (workingMiddle.vertices[i] == null) // Can't make a simplex here
  133. {
  134. iLastNull = i + 1;
  135. continue;
  136. }
  137. if (i == workingMiddle.vertices.Count - 1) // End of list
  138. {
  139. iNext = iLastNull;
  140. }
  141. if (workingMiddle.vertices[iNext] == null) // Null means wrap to begin of last segment
  142. {
  143. iNext = iLastNull;
  144. }
  145. Triangle tSide;
  146. tSide = new Triangle(workingMiddle.vertices[i], workingMinus.vertices[i], workingMiddle.vertices[iNext]);
  147. result.Add(tSide);
  148. tSide =
  149. new Triangle(workingMiddle.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]);
  150. result.Add(tSide);
  151. }
  152. //foreach (Triangle t in workingPlus.triangles)
  153. //{
  154. //t.invertNormal();
  155. // }
  156. result.Append(workingPlus);
  157. iLastNull = 0;
  158. for (int i = 0; i < workingPlus.vertices.Count; i++)
  159. {
  160. int iNext = (i + 1);
  161. if (workingPlus.vertices[i] == null) // Can't make a simplex here
  162. {
  163. iLastNull = i + 1;
  164. continue;
  165. }
  166. if (i == workingPlus.vertices.Count - 1) // End of list
  167. {
  168. iNext = iLastNull;
  169. }
  170. if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment
  171. {
  172. iNext = iLastNull;
  173. }
  174. Triangle tSide;
  175. tSide = new Triangle(workingPlus.vertices[i], workingMiddle.vertices[i], workingPlus.vertices[iNext]);
  176. result.Add(tSide);
  177. tSide =
  178. new Triangle(workingPlus.vertices[iNext], workingMiddle.vertices[i], workingMiddle.vertices[iNext]);
  179. result.Add(tSide);
  180. }
  181. if (twistMid != 0)
  182. {
  183. foreach (Vertex v in result.vertices)
  184. {
  185. // twist and shout
  186. if (v != null)
  187. {
  188. tt = new Quaternion(new Vertex(0, 0, -1), twistMid*2);
  189. v2 = v * tt;
  190. v.X = v2.X;
  191. v.Y = v2.Y;
  192. v.Z = v2.Z;
  193. }
  194. }
  195. }
  196. return result;
  197. }
  198. }
  199. }