Meshmerizer.cs 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  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 OpenSim.Framework;
  30. using OpenSim.Framework.Console;
  31. using OpenSim.Region.Physics.Manager;
  32. namespace OpenSim.Region.Physics.Meshing
  33. {
  34. public class MeshmerizerPlugin : IMeshingPlugin
  35. {
  36. public MeshmerizerPlugin()
  37. {
  38. }
  39. public string GetName()
  40. {
  41. return "Meshmerizer";
  42. }
  43. public IMesher GetMesher()
  44. {
  45. return new Meshmerizer();
  46. }
  47. }
  48. public class Meshmerizer : IMesher
  49. {
  50. //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  51. // Setting baseDir to a path will enable the dumping of raw files
  52. // raw files can be imported by blender so a visual inspection of the results can be done
  53. // const string baseDir = "rawFiles";
  54. private const string baseDir = null; //"rawFiles";
  55. // TODO: unused
  56. // private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2,
  57. // PhysicsVector r2, ref float lambda, ref float mu)
  58. // {
  59. // // p1, p2, points on the straight
  60. // // r1, r2, directional vectors of the straight. Not necessarily of length 1!
  61. // // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
  62. // // thus allowing to decide whether an intersection is between two points
  63. // float r1x = r1.X;
  64. // float r1y = r1.Y;
  65. // float r2x = r2.X;
  66. // float r2y = r2.Y;
  67. // float denom = r1y*r2x - r1x*r2y;
  68. // if (denom == 0.0)
  69. // {
  70. // lambda = Single.NaN;
  71. // mu = Single.NaN;
  72. // return;
  73. // }
  74. // float p1x = p1.X;
  75. // float p1y = p1.Y;
  76. // float p2x = p2.X;
  77. // float p2y = p2.Y;
  78. // lambda = (-p2x*r2y + p1x*r2y + (p2y - p1y)*r2x)/denom;
  79. // mu = (-p2x*r1y + p1x*r1y + (p2y - p1y)*r1x)/denom;
  80. // }
  81. private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
  82. {
  83. List<Triangle> influenced = new List<Triangle>();
  84. foreach (Triangle t in triangles)
  85. {
  86. if (t.isInCircle(v.X, v.Y))
  87. {
  88. influenced.Add(t);
  89. }
  90. }
  91. return influenced;
  92. }
  93. private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
  94. {
  95. // This is a variant of the delaunay algorithm
  96. // each time a new vertex is inserted, all triangles that are influenced by it are deleted
  97. // and replaced by new ones including the new vertex
  98. // It is not very time efficient but easy to implement.
  99. int iCurrentVertex;
  100. int iMaxVertex = vertices.Count;
  101. for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
  102. {
  103. // Background: A triangle mesh fulfills the delaunay condition if (iff!)
  104. // each circumlocutory circle (i.e. the circle that touches all three corners)
  105. // of each triangle is empty of other vertices.
  106. // Obviously a single (seeding) triangle fulfills this condition.
  107. // If we now add one vertex, we need to reconstruct all triangles, that
  108. // do not fulfill this condition with respect to the new triangle
  109. // Find the triangles that are influenced by the new vertex
  110. Vertex v = vertices[iCurrentVertex];
  111. if (v == null)
  112. continue; // Null is polygon stop marker. Ignore it
  113. List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v);
  114. List<Simplex> simplices = new List<Simplex>();
  115. // Reconstruction phase. First step, dissolve each triangle into it's simplices,
  116. // i.e. it's "border lines"
  117. // Goal is to find "inner" borders and delete them, while the hull gets conserved.
  118. // Inner borders are special in the way that they always come twice, which is how we detect them
  119. foreach (Triangle t in influencedTriangles)
  120. {
  121. List<Simplex> newSimplices = t.GetSimplices();
  122. simplices.AddRange(newSimplices);
  123. triangles.Remove(t);
  124. }
  125. // Now sort the simplices. That will make identical ones reside side by side in the list
  126. simplices.Sort();
  127. // Look for duplicate simplices here.
  128. // Remember, they are directly side by side in the list right now,
  129. // So we only check directly neighbours
  130. int iSimplex;
  131. List<Simplex> innerSimplices = new List<Simplex>();
  132. for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
  133. {
  134. if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0)
  135. {
  136. innerSimplices.Add(simplices[iSimplex - 1]);
  137. innerSimplices.Add(simplices[iSimplex]);
  138. }
  139. }
  140. foreach (Simplex s in innerSimplices)
  141. {
  142. simplices.Remove(s);
  143. }
  144. // each simplex still in the list belongs to the hull of the region in question
  145. // The new vertex (yes, we still deal with verices here :-) ) forms a triangle
  146. // with each of these simplices. Build the new triangles and add them to the list
  147. foreach (Simplex s in simplices)
  148. {
  149. Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
  150. if (!t.isDegraded())
  151. {
  152. triangles.Add(t);
  153. }
  154. }
  155. }
  156. }
  157. private static SimpleHull BuildHoleHull(PrimitiveBaseShape pbs, ProfileShape pshape, HollowShape hshape, UInt16 hollowFactor)
  158. {
  159. // Tackle HollowShape.Same
  160. float fhollowFactor = (float)hollowFactor;
  161. switch (pshape)
  162. {
  163. case ProfileShape.Square:
  164. if (hshape == HollowShape.Same)
  165. hshape= HollowShape.Square;
  166. break;
  167. case ProfileShape.EquilateralTriangle:
  168. fhollowFactor = ((float)hollowFactor / 1.9f);
  169. if (hshape == HollowShape.Same)
  170. {
  171. hshape = HollowShape.Triangle;
  172. }
  173. break;
  174. case ProfileShape.Circle:
  175. if (pbs.PathCurve == (byte)Extrusion.Straight)
  176. {
  177. if (hshape == HollowShape.Same)
  178. {
  179. hshape = HollowShape.Circle;
  180. }
  181. }
  182. break;
  183. default:
  184. if (hshape == HollowShape.Same)
  185. hshape= HollowShape.Square;
  186. break;
  187. }
  188. SimpleHull holeHull = null;
  189. if (hshape == HollowShape.Square)
  190. {
  191. float hollowFactorF = (float)fhollowFactor / (float)50000;
  192. Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
  193. Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
  194. Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
  195. Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
  196. holeHull = new SimpleHull();
  197. holeHull.AddVertex(IMM);
  198. holeHull.AddVertex(IMP);
  199. holeHull.AddVertex(IPP);
  200. holeHull.AddVertex(IPM);
  201. }
  202. if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  203. {
  204. float hollowFactorF = (float)fhollowFactor / (float)50000;
  205. Vertex IQ1Q15 = new Vertex(-0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
  206. Vertex IQ1Q16 = new Vertex(-0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
  207. Vertex IQ1Q17 = new Vertex(-0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
  208. Vertex IQ1Q18 = new Vertex(-0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
  209. Vertex IQ1Q19 = new Vertex(-0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
  210. Vertex IQ2Q10 = new Vertex(+0.0f * hollowFactorF, -0.50f * hollowFactorF, 0.0f);
  211. Vertex IQ2Q11 = new Vertex(+0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
  212. Vertex IQ2Q12 = new Vertex(+0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
  213. Vertex IQ2Q13 = new Vertex(+0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
  214. Vertex IQ2Q14 = new Vertex(+0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
  215. Vertex IQ2Q15 = new Vertex(+0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
  216. Vertex IQ2Q16 = new Vertex(+0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
  217. Vertex IQ2Q17 = new Vertex(+0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
  218. Vertex IQ2Q18 = new Vertex(+0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
  219. Vertex IQ2Q19 = new Vertex(+0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
  220. Vertex IQ2Q20 = new Vertex(+0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
  221. Vertex IQ2Q21 = new Vertex(+0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
  222. Vertex IQ2Q22 = new Vertex(+0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
  223. Vertex IQ2Q23 = new Vertex(+0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
  224. Vertex IQ2Q24 = new Vertex(+0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
  225. Vertex IQ2Q25 = new Vertex(+0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
  226. Vertex IQ2Q26 = new Vertex(+0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
  227. Vertex IQ2Q27 = new Vertex(+0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
  228. Vertex IQ2Q28 = new Vertex(+0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
  229. Vertex IQ2Q29 = new Vertex(+0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
  230. Vertex IQ1Q20 = new Vertex(+0.0f * hollowFactorF, +0.50f * hollowFactorF, 0.0f);
  231. Vertex IQ1Q21 = new Vertex(-0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
  232. Vertex IQ1Q22 = new Vertex(-0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
  233. Vertex IQ1Q23 = new Vertex(-0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
  234. Vertex IQ1Q24 = new Vertex(-0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
  235. Vertex IQ1Q25 = new Vertex(-0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
  236. Vertex IQ1Q26 = new Vertex(-0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
  237. Vertex IQ1Q27 = new Vertex(-0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
  238. Vertex IQ1Q28 = new Vertex(-0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
  239. Vertex IQ1Q29 = new Vertex(-0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
  240. Vertex IQ1Q10 = new Vertex(-0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
  241. Vertex IQ1Q11 = new Vertex(-0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
  242. Vertex IQ1Q12 = new Vertex(-0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
  243. Vertex IQ1Q13 = new Vertex(-0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
  244. Vertex IQ1Q14 = new Vertex(-0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
  245. //Counter clockwise around the quadrants
  246. holeHull = new SimpleHull();
  247. holeHull.AddVertex(IQ1Q15);
  248. holeHull.AddVertex(IQ1Q14);
  249. holeHull.AddVertex(IQ1Q13);
  250. holeHull.AddVertex(IQ1Q12);
  251. holeHull.AddVertex(IQ1Q11);
  252. holeHull.AddVertex(IQ1Q10);
  253. holeHull.AddVertex(IQ1Q29);
  254. holeHull.AddVertex(IQ1Q28);
  255. holeHull.AddVertex(IQ1Q27);
  256. holeHull.AddVertex(IQ1Q26);
  257. holeHull.AddVertex(IQ1Q25);
  258. holeHull.AddVertex(IQ1Q24);
  259. holeHull.AddVertex(IQ1Q23);
  260. holeHull.AddVertex(IQ1Q22);
  261. holeHull.AddVertex(IQ1Q21);
  262. holeHull.AddVertex(IQ1Q20);
  263. holeHull.AddVertex(IQ2Q29);
  264. holeHull.AddVertex(IQ2Q28);
  265. holeHull.AddVertex(IQ2Q27);
  266. holeHull.AddVertex(IQ2Q26);
  267. holeHull.AddVertex(IQ2Q25);
  268. holeHull.AddVertex(IQ2Q24);
  269. holeHull.AddVertex(IQ2Q23);
  270. holeHull.AddVertex(IQ2Q22);
  271. holeHull.AddVertex(IQ2Q21);
  272. holeHull.AddVertex(IQ2Q20);
  273. holeHull.AddVertex(IQ2Q19);
  274. holeHull.AddVertex(IQ2Q18);
  275. holeHull.AddVertex(IQ2Q17);
  276. holeHull.AddVertex(IQ2Q16);
  277. holeHull.AddVertex(IQ2Q15);
  278. holeHull.AddVertex(IQ2Q14);
  279. holeHull.AddVertex(IQ2Q13);
  280. holeHull.AddVertex(IQ2Q12);
  281. holeHull.AddVertex(IQ2Q11);
  282. holeHull.AddVertex(IQ2Q10);
  283. holeHull.AddVertex(IQ1Q19);
  284. holeHull.AddVertex(IQ1Q18);
  285. holeHull.AddVertex(IQ1Q17);
  286. holeHull.AddVertex(IQ1Q16);
  287. }
  288. if (hshape == HollowShape.Triangle)
  289. {
  290. float hollowFactorF = (float)fhollowFactor / (float)50000;
  291. Vertex IMM = new Vertex(-0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f);
  292. Vertex IPM = new Vertex(+0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f);
  293. Vertex IPP = new Vertex(-0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f);
  294. holeHull = new SimpleHull();
  295. holeHull.AddVertex(IMM);
  296. holeHull.AddVertex(IPP);
  297. holeHull.AddVertex(IPM);
  298. }
  299. return holeHull;
  300. }
  301. private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  302. // Builds the z (+ and -) surfaces of a box shaped prim
  303. {
  304. UInt16 hollowFactor = primShape.ProfileHollow;
  305. UInt16 profileBegin = primShape.ProfileBegin;
  306. UInt16 profileEnd = primShape.ProfileEnd;
  307. UInt16 taperX = primShape.PathScaleX;
  308. UInt16 taperY = primShape.PathScaleY;
  309. UInt16 pathShearX = primShape.PathShearX;
  310. UInt16 pathShearY = primShape.PathShearY;
  311. //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
  312. //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
  313. //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
  314. //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
  315. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  316. // of a block are basically the same
  317. // They may be warped differently but the shape is identical
  318. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  319. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  320. // The mapping to Scene space is done later during the "extrusion" phase
  321. // Base
  322. Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
  323. Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
  324. Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
  325. Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
  326. SimpleHull outerHull = new SimpleHull();
  327. outerHull.AddVertex(MM);
  328. outerHull.AddVertex(PM);
  329. outerHull.AddVertex(PP);
  330. outerHull.AddVertex(MP);
  331. // Deal with cuts now
  332. if ((profileBegin != 0) || (profileEnd != 0))
  333. {
  334. double fProfileBeginAngle = profileBegin/50000.0*360.0;
  335. // In degree, for easier debugging and understanding
  336. fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  337. double fProfileEndAngle = 360.0 - profileEnd/50000.0*360.0; // Pathend comes as complement to 1.0
  338. fProfileEndAngle -= (90.0 + 45.0);
  339. if (fProfileBeginAngle < fProfileEndAngle)
  340. fProfileEndAngle -= 360.0;
  341. // Note, that we don't want to cut out a triangle, even if this is a
  342. // good approximation for small cuts. Indeed we want to cut out an arc
  343. // and we approximate this arc by a polygon chain
  344. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  345. // So it can easily be subtracted from the outer hull
  346. int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5);
  347. // how many steps do we need with approximately 45 degree
  348. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps;
  349. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  350. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  351. SimpleHull cutHull = new SimpleHull();
  352. cutHull.AddVertex(origin);
  353. for (int i = 0; i < iSteps; i++)
  354. {
  355. double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!!
  356. Vertex v = Vertex.FromAngle(angle*Math.PI/180.0);
  357. cutHull.AddVertex(v);
  358. }
  359. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0);
  360. // Calculated separately to avoid errors
  361. cutHull.AddVertex(legEnd);
  362. //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  363. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  364. outerHull = cuttedHull;
  365. }
  366. // Deal with the hole here
  367. if (hollowFactor > 0)
  368. {
  369. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  370. if (holeHull != null)
  371. {
  372. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  373. outerHull = hollowedHull;
  374. }
  375. }
  376. Mesh m = new Mesh();
  377. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  378. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  379. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  380. m.Add(Seed1);
  381. m.Add(Seed2);
  382. m.Add(Seed3);
  383. m.Add(new Triangle(Seed1, Seed2, Seed3));
  384. m.Add(outerHull.getVertices());
  385. InsertVertices(m.vertices, 3, m.triangles);
  386. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  387. m.Remove(Seed1);
  388. m.Remove(Seed2);
  389. m.Remove(Seed3);
  390. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  391. m.RemoveTrianglesOutside(outerHull);
  392. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  393. foreach (Triangle t in m.triangles)
  394. {
  395. PhysicsVector n = t.getNormal();
  396. if (n.Z < 0.0)
  397. t.invertNormal();
  398. }
  399. Extruder extr = new Extruder();
  400. extr.size = size;
  401. if (taperX != 100)
  402. {
  403. if (taperX > 100)
  404. {
  405. extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
  406. //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  407. }
  408. else
  409. {
  410. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  411. //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  412. }
  413. }
  414. if (taperY != 100)
  415. {
  416. if (taperY > 100)
  417. {
  418. extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
  419. //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  420. }
  421. else
  422. {
  423. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  424. //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  425. }
  426. }
  427. if (pathShearX != 0)
  428. {
  429. if (pathShearX > 50) {
  430. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  431. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  432. // m_log.Warn("pushX: " + extr.pushX);
  433. }
  434. else
  435. {
  436. extr.pushX = (float)pathShearX / 100;
  437. // m_log.Warn("pushX: " + extr.pushX);
  438. }
  439. }
  440. if (pathShearY != 0)
  441. {
  442. if (pathShearY > 50) {
  443. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  444. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  445. //m_log.Warn("pushY: " + extr.pushY);
  446. }
  447. else
  448. {
  449. extr.pushY = (float)pathShearY / 100;
  450. //m_log.Warn("pushY: " + extr.pushY);
  451. }
  452. }
  453. Mesh result = extr.Extrude(m);
  454. result.DumpRaw(baseDir, primName, "Z extruded");
  455. return result;
  456. }
  457. private static Mesh CreateCyllinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  458. // Builds the z (+ and -) surfaces of a box shaped prim
  459. {
  460. UInt16 hollowFactor = primShape.ProfileHollow;
  461. UInt16 profileBegin = primShape.ProfileBegin;
  462. UInt16 profileEnd = primShape.ProfileEnd;
  463. UInt16 taperX = primShape.PathScaleX;
  464. UInt16 taperY = primShape.PathScaleY;
  465. UInt16 pathShearX = primShape.PathShearX;
  466. UInt16 pathShearY = primShape.PathShearY;
  467. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  468. // of a block are basically the same
  469. // They may be warped differently but the shape is identical
  470. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  471. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  472. // The mapping to Scene space is done later during the "extrusion" phase
  473. // Base
  474. // Q1Q15 = Quadrant 1, Quadrant1, Vertex 5
  475. Vertex Q1Q15 = new Vertex(-0.35f, -0.35f, 0.0f);
  476. Vertex Q1Q16 = new Vertex(-0.30f, -0.40f, 0.0f);
  477. Vertex Q1Q17 = new Vertex(-0.24f, -0.43f, 0.0f);
  478. Vertex Q1Q18 = new Vertex(-0.18f, -0.46f, 0.0f);
  479. Vertex Q1Q19 = new Vertex(-0.11f, -0.48f, 0.0f);
  480. Vertex Q2Q10 = new Vertex(+0.0f, -0.50f, 0.0f);
  481. Vertex Q2Q11 = new Vertex(+0.11f, -0.48f, 0.0f);
  482. Vertex Q2Q12 = new Vertex(+0.18f, -0.46f, 0.0f);
  483. Vertex Q2Q13 = new Vertex(+0.24f, -0.43f, 0.0f);
  484. Vertex Q2Q14 = new Vertex(+0.30f, -0.40f, 0.0f);
  485. Vertex Q2Q15 = new Vertex(+0.35f, -0.35f, 0.0f);
  486. Vertex Q2Q16 = new Vertex(+0.40f, -0.30f, 0.0f);
  487. Vertex Q2Q17 = new Vertex(+0.43f, -0.24f, 0.0f);
  488. Vertex Q2Q18 = new Vertex(+0.46f, -0.18f, 0.0f);
  489. Vertex Q2Q19 = new Vertex(+0.48f, -0.11f, 0.0f);
  490. Vertex Q2Q20 = new Vertex(+0.50f, +0.0f, 0.0f);
  491. Vertex Q2Q21 = new Vertex(+0.48f, +0.11f, 0.0f);
  492. Vertex Q2Q22 = new Vertex(+0.46f, +0.18f, 0.0f);
  493. Vertex Q2Q23 = new Vertex(+0.43f, +0.24f, 0.0f);
  494. Vertex Q2Q24 = new Vertex(+0.40f, +0.30f, 0.0f);
  495. Vertex Q2Q25 = new Vertex(+0.35f, +0.35f, 0.0f);
  496. Vertex Q2Q26 = new Vertex(+0.30f, +0.40f, 0.0f);
  497. Vertex Q2Q27 = new Vertex(+0.24f, +0.43f, 0.0f);
  498. Vertex Q2Q28 = new Vertex(+0.18f, +0.46f, 0.0f);
  499. Vertex Q2Q29 = new Vertex(+0.11f, +0.48f, 0.0f);
  500. Vertex Q1Q20 = new Vertex(+0.0f, +0.50f, 0.0f);
  501. Vertex Q1Q21 = new Vertex(-0.11f, +0.48f, 0.0f);
  502. Vertex Q1Q22 = new Vertex(-0.18f, +0.46f, 0.0f);
  503. Vertex Q1Q23 = new Vertex(-0.24f, +0.43f, 0.0f);
  504. Vertex Q1Q24 = new Vertex(-0.30f, +0.40f, 0.0f);
  505. Vertex Q1Q25 = new Vertex(-0.35f, +0.35f, 0.0f);
  506. Vertex Q1Q26 = new Vertex(-0.40f, +0.30f, 0.0f);
  507. Vertex Q1Q27 = new Vertex(-0.43f, +0.24f, 0.0f);
  508. Vertex Q1Q28 = new Vertex(-0.46f, +0.18f, 0.0f);
  509. Vertex Q1Q29 = new Vertex(-0.48f, +0.11f, 0.0f);
  510. Vertex Q1Q10 = new Vertex(-0.50f, +0.0f, 0.0f);
  511. Vertex Q1Q11 = new Vertex(-0.48f, -0.11f, 0.0f);
  512. Vertex Q1Q12 = new Vertex(-0.46f, -0.18f, 0.0f);
  513. Vertex Q1Q13 = new Vertex(-0.43f, -0.24f, 0.0f);
  514. Vertex Q1Q14 = new Vertex(-0.40f, -0.30f, 0.0f);
  515. SimpleHull outerHull = new SimpleHull();
  516. //Clockwise around the quadrants
  517. outerHull.AddVertex(Q1Q15);
  518. outerHull.AddVertex(Q1Q16);
  519. outerHull.AddVertex(Q1Q17);
  520. outerHull.AddVertex(Q1Q18);
  521. outerHull.AddVertex(Q1Q19);
  522. outerHull.AddVertex(Q2Q10);
  523. outerHull.AddVertex(Q2Q11);
  524. outerHull.AddVertex(Q2Q12);
  525. outerHull.AddVertex(Q2Q13);
  526. outerHull.AddVertex(Q2Q14);
  527. outerHull.AddVertex(Q2Q15);
  528. outerHull.AddVertex(Q2Q16);
  529. outerHull.AddVertex(Q2Q17);
  530. outerHull.AddVertex(Q2Q18);
  531. outerHull.AddVertex(Q2Q19);
  532. outerHull.AddVertex(Q2Q20);
  533. outerHull.AddVertex(Q2Q21);
  534. outerHull.AddVertex(Q2Q22);
  535. outerHull.AddVertex(Q2Q23);
  536. outerHull.AddVertex(Q2Q24);
  537. outerHull.AddVertex(Q2Q25);
  538. outerHull.AddVertex(Q2Q26);
  539. outerHull.AddVertex(Q2Q27);
  540. outerHull.AddVertex(Q2Q28);
  541. outerHull.AddVertex(Q2Q29);
  542. outerHull.AddVertex(Q1Q20);
  543. outerHull.AddVertex(Q1Q21);
  544. outerHull.AddVertex(Q1Q22);
  545. outerHull.AddVertex(Q1Q23);
  546. outerHull.AddVertex(Q1Q24);
  547. outerHull.AddVertex(Q1Q25);
  548. outerHull.AddVertex(Q1Q26);
  549. outerHull.AddVertex(Q1Q27);
  550. outerHull.AddVertex(Q1Q28);
  551. outerHull.AddVertex(Q1Q29);
  552. outerHull.AddVertex(Q1Q10);
  553. outerHull.AddVertex(Q1Q11);
  554. outerHull.AddVertex(Q1Q12);
  555. outerHull.AddVertex(Q1Q13);
  556. outerHull.AddVertex(Q1Q14);
  557. // Deal with cuts now
  558. if ((profileBegin != 0) || (profileEnd != 0))
  559. {
  560. double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
  561. // In degree, for easier debugging and understanding
  562. //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  563. double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
  564. //fProfileEndAngle -= (90.0 + 45.0);
  565. if (fProfileBeginAngle < fProfileEndAngle)
  566. fProfileEndAngle -= 360.0;
  567. // Note, that we don't want to cut out a triangle, even if this is a
  568. // good approximation for small cuts. Indeed we want to cut out an arc
  569. // and we approximate this arc by a polygon chain
  570. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  571. // So it can easily be subtracted from the outer hull
  572. int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
  573. // how many steps do we need with approximately 45 degree
  574. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
  575. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  576. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  577. SimpleHull cutHull = new SimpleHull();
  578. cutHull.AddVertex(origin);
  579. for (int i = 0; i < iSteps; i++)
  580. {
  581. double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
  582. Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
  583. cutHull.AddVertex(v);
  584. }
  585. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
  586. // Calculated separately to avoid errors
  587. cutHull.AddVertex(legEnd);
  588. // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  589. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  590. outerHull = cuttedHull;
  591. }
  592. // Deal with the hole here
  593. if (hollowFactor > 0)
  594. {
  595. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  596. if (holeHull != null)
  597. {
  598. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  599. outerHull = hollowedHull;
  600. }
  601. }
  602. Mesh m = new Mesh();
  603. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  604. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  605. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  606. m.Add(Seed1);
  607. m.Add(Seed2);
  608. m.Add(Seed3);
  609. m.Add(new Triangle(Seed1, Seed2, Seed3));
  610. m.Add(outerHull.getVertices());
  611. InsertVertices(m.vertices, 3, m.triangles);
  612. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  613. m.Remove(Seed1);
  614. m.Remove(Seed2);
  615. m.Remove(Seed3);
  616. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  617. m.RemoveTrianglesOutside(outerHull);
  618. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  619. foreach (Triangle t in m.triangles)
  620. {
  621. PhysicsVector n = t.getNormal();
  622. if (n.Z < 0.0)
  623. t.invertNormal();
  624. }
  625. Extruder extr = new Extruder();
  626. extr.size = size;
  627. if (taperX != 100)
  628. {
  629. if (taperX > 100)
  630. {
  631. extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
  632. //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  633. }
  634. else
  635. {
  636. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  637. //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  638. }
  639. }
  640. if (taperY != 100)
  641. {
  642. if (taperY > 100)
  643. {
  644. extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
  645. //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  646. }
  647. else
  648. {
  649. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  650. //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  651. }
  652. }
  653. if (pathShearX != 0)
  654. {
  655. if (pathShearX > 50)
  656. {
  657. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  658. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  659. //m_log.Warn("pushX: " + extr.pushX);
  660. }
  661. else
  662. {
  663. extr.pushX = (float)pathShearX / 100;
  664. //m_log.Warn("pushX: " + extr.pushX);
  665. }
  666. }
  667. if (pathShearY != 0)
  668. {
  669. if (pathShearY > 50)
  670. {
  671. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  672. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  673. //m_log.Warn("pushY: " + extr.pushY);
  674. }
  675. else
  676. {
  677. extr.pushY = (float)pathShearY / 100;
  678. //m_log.Warn("pushY: " + extr.pushY);
  679. }
  680. }
  681. Mesh result = extr.Extrude(m);
  682. result.DumpRaw(baseDir, primName, "Z extruded");
  683. return result;
  684. }
  685. private static Mesh CreatePrismMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  686. // Builds the z (+ and -) surfaces of a box shaped prim
  687. {
  688. UInt16 hollowFactor = primShape.ProfileHollow;
  689. UInt16 profileBegin = primShape.ProfileBegin;
  690. UInt16 profileEnd = primShape.ProfileEnd;
  691. UInt16 taperX = primShape.PathScaleX;
  692. UInt16 taperY = primShape.PathScaleY;
  693. UInt16 pathShearX = primShape.PathShearX;
  694. UInt16 pathShearY = primShape.PathShearY;
  695. //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
  696. //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
  697. //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
  698. //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
  699. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  700. // of a block are basically the same
  701. // They may be warped differently but the shape is identical
  702. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  703. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  704. // The mapping to Scene space is done later during the "extrusion" phase
  705. // Base
  706. Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
  707. Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
  708. Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
  709. SimpleHull outerHull = new SimpleHull();
  710. outerHull.AddVertex(MM);
  711. outerHull.AddVertex(PM);
  712. outerHull.AddVertex(PP);
  713. // Deal with cuts now
  714. if ((profileBegin != 0) || (profileEnd != 0))
  715. {
  716. double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
  717. // In degree, for easier debugging and understanding
  718. //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  719. double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
  720. //fProfileEndAngle -= (90.0 + 45.0);
  721. if (fProfileBeginAngle < fProfileEndAngle)
  722. fProfileEndAngle -= 360.0;
  723. // Note, that we don't want to cut out a triangle, even if this is a
  724. // good approximation for small cuts. Indeed we want to cut out an arc
  725. // and we approximate this arc by a polygon chain
  726. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  727. // So it can easily be subtracted from the outer hull
  728. int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
  729. // how many steps do we need with approximately 45 degree
  730. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
  731. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  732. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  733. SimpleHull cutHull = new SimpleHull();
  734. cutHull.AddVertex(origin);
  735. for (int i = 0; i < iSteps; i++)
  736. {
  737. double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
  738. Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
  739. cutHull.AddVertex(v);
  740. }
  741. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
  742. // Calculated separately to avoid errors
  743. cutHull.AddVertex(legEnd);
  744. //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  745. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  746. outerHull = cuttedHull;
  747. }
  748. // Deal with the hole here
  749. if (hollowFactor > 0)
  750. {
  751. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  752. if (holeHull != null)
  753. {
  754. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  755. outerHull = hollowedHull;
  756. }
  757. }
  758. Mesh m = new Mesh();
  759. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  760. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  761. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  762. m.Add(Seed1);
  763. m.Add(Seed2);
  764. m.Add(Seed3);
  765. m.Add(new Triangle(Seed1, Seed2, Seed3));
  766. m.Add(outerHull.getVertices());
  767. InsertVertices(m.vertices, 3, m.triangles);
  768. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  769. m.Remove(Seed1);
  770. m.Remove(Seed2);
  771. m.Remove(Seed3);
  772. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  773. m.RemoveTrianglesOutside(outerHull);
  774. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  775. foreach (Triangle t in m.triangles)
  776. {
  777. PhysicsVector n = t.getNormal();
  778. if (n.Z < 0.0)
  779. t.invertNormal();
  780. }
  781. Extruder extr = new Extruder();
  782. extr.size = size;
  783. if (taperX != 100)
  784. {
  785. if (taperX > 100)
  786. {
  787. extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
  788. //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  789. }
  790. else
  791. {
  792. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  793. //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  794. }
  795. }
  796. if (taperY != 100)
  797. {
  798. if (taperY > 100)
  799. {
  800. extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
  801. //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  802. }
  803. else
  804. {
  805. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  806. //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  807. }
  808. }
  809. if (pathShearX != 0)
  810. {
  811. if (pathShearX > 50)
  812. {
  813. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  814. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  815. // m_log.Warn("pushX: " + extr.pushX);
  816. }
  817. else
  818. {
  819. extr.pushX = (float)pathShearX / 100;
  820. // m_log.Warn("pushX: " + extr.pushX);
  821. }
  822. }
  823. if (pathShearY != 0)
  824. {
  825. if (pathShearY > 50)
  826. {
  827. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  828. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  829. //m_log.Warn("pushY: " + extr.pushY);
  830. }
  831. else
  832. {
  833. extr.pushY = (float)pathShearY / 100;
  834. //m_log.Warn("pushY: " + extr.pushY);
  835. }
  836. }
  837. Mesh result = extr.Extrude(m);
  838. result.DumpRaw(baseDir, primName, "Z extruded");
  839. return result;
  840. }
  841. public static void CalcNormals(Mesh mesh)
  842. {
  843. int iTriangles = mesh.triangles.Count;
  844. mesh.normals = new float[iTriangles*3];
  845. int i = 0;
  846. foreach (Triangle t in mesh.triangles)
  847. {
  848. float ux, uy, uz;
  849. float vx, vy, vz;
  850. float wx, wy, wz;
  851. ux = t.v1.X;
  852. uy = t.v1.Y;
  853. uz = t.v1.Z;
  854. vx = t.v2.X;
  855. vy = t.v2.Y;
  856. vz = t.v2.Z;
  857. wx = t.v3.X;
  858. wy = t.v3.Y;
  859. wz = t.v3.Z;
  860. // Vectors for edges
  861. float e1x, e1y, e1z;
  862. float e2x, e2y, e2z;
  863. e1x = ux - vx;
  864. e1y = uy - vy;
  865. e1z = uz - vz;
  866. e2x = ux - wx;
  867. e2y = uy - wy;
  868. e2z = uz - wz;
  869. // Cross product for normal
  870. float nx, ny, nz;
  871. nx = e1y*e2z - e1z*e2y;
  872. ny = e1z*e2x - e1x*e2z;
  873. nz = e1x*e2y - e1y*e2x;
  874. // Length
  875. float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz);
  876. // Normalized "normal"
  877. nx /= l;
  878. ny /= l;
  879. nz /= l;
  880. mesh.normals[i] = nx;
  881. mesh.normals[i + 1] = ny;
  882. mesh.normals[i + 2] = nz;
  883. i += 3;
  884. }
  885. }
  886. public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  887. {
  888. Mesh mesh = null;
  889. switch (primShape.ProfileShape)
  890. {
  891. case ProfileShape.Square:
  892. mesh = CreateBoxMesh(primName, primShape, size);
  893. CalcNormals(mesh);
  894. break;
  895. case ProfileShape.Circle:
  896. if (primShape.PathCurve == (byte)Extrusion.Straight)
  897. {
  898. mesh = CreateCyllinderMesh(primName, primShape, size);
  899. CalcNormals(mesh);
  900. }
  901. break;
  902. case ProfileShape.EquilateralTriangle:
  903. mesh = CreatePrismMesh(primName, primShape, size);
  904. CalcNormals(mesh);
  905. break;
  906. default:
  907. mesh = CreateBoxMesh(primName, primShape, size);
  908. CalcNormals(mesh);
  909. //Set default mesh to cube otherwise it'll return
  910. // null and crash on the 'setMesh' method in the physics plugins.
  911. //mesh = null;
  912. break;
  913. }
  914. return mesh;
  915. }
  916. }
  917. }