Meshmerizer.cs 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
  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.Region.Physics.Manager;
  31. namespace OpenSim.Region.Physics.Meshing
  32. {
  33. public class MeshmerizerPlugin : IMeshingPlugin
  34. {
  35. public MeshmerizerPlugin()
  36. {
  37. }
  38. public string GetName()
  39. {
  40. return "Meshmerizer";
  41. }
  42. public IMesher GetMesher()
  43. {
  44. return new Meshmerizer();
  45. }
  46. }
  47. public class Meshmerizer : IMesher
  48. {
  49. //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  50. // Setting baseDir to a path will enable the dumping of raw files
  51. // raw files can be imported by blender so a visual inspection of the results can be done
  52. // const string baseDir = "rawFiles";
  53. private const string baseDir = null; //"rawFiles";
  54. private const float DEG_TO_RAD = 0.01745329238f;
  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.HalfCircle:
  175. case ProfileShape.Circle:
  176. if (pbs.PathCurve == (byte)Extrusion.Straight)
  177. {
  178. if (hshape == HollowShape.Same)
  179. {
  180. hshape = HollowShape.Circle;
  181. }
  182. }
  183. break;
  184. default:
  185. if (hshape == HollowShape.Same)
  186. hshape= HollowShape.Square;
  187. break;
  188. }
  189. SimpleHull holeHull = null;
  190. if (hshape == HollowShape.Square)
  191. {
  192. float hollowFactorF = (float)fhollowFactor / (float)50000;
  193. Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
  194. Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
  195. Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
  196. Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
  197. holeHull = new SimpleHull();
  198. holeHull.AddVertex(IMM);
  199. holeHull.AddVertex(IMP);
  200. holeHull.AddVertex(IPP);
  201. holeHull.AddVertex(IPM);
  202. }
  203. if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  204. {
  205. float hollowFactorF = (float)fhollowFactor / (float)50000;
  206. Vertex IQ1Q15 = new Vertex(-0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
  207. Vertex IQ1Q16 = new Vertex(-0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
  208. Vertex IQ1Q17 = new Vertex(-0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
  209. Vertex IQ1Q18 = new Vertex(-0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
  210. Vertex IQ1Q19 = new Vertex(-0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
  211. Vertex IQ2Q10 = new Vertex(+0.0f * hollowFactorF, -0.50f * hollowFactorF, 0.0f);
  212. Vertex IQ2Q11 = new Vertex(+0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
  213. Vertex IQ2Q12 = new Vertex(+0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
  214. Vertex IQ2Q13 = new Vertex(+0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
  215. Vertex IQ2Q14 = new Vertex(+0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
  216. Vertex IQ2Q15 = new Vertex(+0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
  217. Vertex IQ2Q16 = new Vertex(+0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
  218. Vertex IQ2Q17 = new Vertex(+0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
  219. Vertex IQ2Q18 = new Vertex(+0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
  220. Vertex IQ2Q19 = new Vertex(+0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
  221. Vertex IQ2Q20 = new Vertex(+0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
  222. Vertex IQ2Q21 = new Vertex(+0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
  223. Vertex IQ2Q22 = new Vertex(+0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
  224. Vertex IQ2Q23 = new Vertex(+0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
  225. Vertex IQ2Q24 = new Vertex(+0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
  226. Vertex IQ2Q25 = new Vertex(+0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
  227. Vertex IQ2Q26 = new Vertex(+0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
  228. Vertex IQ2Q27 = new Vertex(+0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
  229. Vertex IQ2Q28 = new Vertex(+0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
  230. Vertex IQ2Q29 = new Vertex(+0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
  231. Vertex IQ1Q20 = new Vertex(+0.0f * hollowFactorF, +0.50f * hollowFactorF, 0.0f);
  232. Vertex IQ1Q21 = new Vertex(-0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
  233. Vertex IQ1Q22 = new Vertex(-0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
  234. Vertex IQ1Q23 = new Vertex(-0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
  235. Vertex IQ1Q24 = new Vertex(-0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
  236. Vertex IQ1Q25 = new Vertex(-0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
  237. Vertex IQ1Q26 = new Vertex(-0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
  238. Vertex IQ1Q27 = new Vertex(-0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
  239. Vertex IQ1Q28 = new Vertex(-0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
  240. Vertex IQ1Q29 = new Vertex(-0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
  241. Vertex IQ1Q10 = new Vertex(-0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
  242. Vertex IQ1Q11 = new Vertex(-0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
  243. Vertex IQ1Q12 = new Vertex(-0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
  244. Vertex IQ1Q13 = new Vertex(-0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
  245. Vertex IQ1Q14 = new Vertex(-0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
  246. //Counter clockwise around the quadrants
  247. holeHull = new SimpleHull();
  248. holeHull.AddVertex(IQ1Q15);
  249. holeHull.AddVertex(IQ1Q14);
  250. holeHull.AddVertex(IQ1Q13);
  251. holeHull.AddVertex(IQ1Q12);
  252. holeHull.AddVertex(IQ1Q11);
  253. holeHull.AddVertex(IQ1Q10);
  254. holeHull.AddVertex(IQ1Q29);
  255. holeHull.AddVertex(IQ1Q28);
  256. holeHull.AddVertex(IQ1Q27);
  257. holeHull.AddVertex(IQ1Q26);
  258. holeHull.AddVertex(IQ1Q25);
  259. holeHull.AddVertex(IQ1Q24);
  260. holeHull.AddVertex(IQ1Q23);
  261. holeHull.AddVertex(IQ1Q22);
  262. holeHull.AddVertex(IQ1Q21);
  263. holeHull.AddVertex(IQ1Q20);
  264. holeHull.AddVertex(IQ2Q29);
  265. holeHull.AddVertex(IQ2Q28);
  266. holeHull.AddVertex(IQ2Q27);
  267. holeHull.AddVertex(IQ2Q26);
  268. holeHull.AddVertex(IQ2Q25);
  269. holeHull.AddVertex(IQ2Q24);
  270. holeHull.AddVertex(IQ2Q23);
  271. holeHull.AddVertex(IQ2Q22);
  272. holeHull.AddVertex(IQ2Q21);
  273. holeHull.AddVertex(IQ2Q20);
  274. holeHull.AddVertex(IQ2Q19);
  275. holeHull.AddVertex(IQ2Q18);
  276. holeHull.AddVertex(IQ2Q17);
  277. holeHull.AddVertex(IQ2Q16);
  278. holeHull.AddVertex(IQ2Q15);
  279. holeHull.AddVertex(IQ2Q14);
  280. holeHull.AddVertex(IQ2Q13);
  281. holeHull.AddVertex(IQ2Q12);
  282. holeHull.AddVertex(IQ2Q11);
  283. holeHull.AddVertex(IQ2Q10);
  284. holeHull.AddVertex(IQ1Q19);
  285. holeHull.AddVertex(IQ1Q18);
  286. holeHull.AddVertex(IQ1Q17);
  287. holeHull.AddVertex(IQ1Q16);
  288. }
  289. if (hshape == HollowShape.Triangle)
  290. {
  291. float hollowFactorF = (float)fhollowFactor / (float)50000;
  292. Vertex IMM = new Vertex(-0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f);
  293. Vertex IPM = new Vertex(+0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f);
  294. Vertex IPP = new Vertex(-0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f);
  295. holeHull = new SimpleHull();
  296. holeHull.AddVertex(IMM);
  297. holeHull.AddVertex(IPP);
  298. holeHull.AddVertex(IPM);
  299. }
  300. return holeHull;
  301. }
  302. private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  303. // Builds the z (+ and -) surfaces of a box shaped prim
  304. {
  305. UInt16 hollowFactor = primShape.ProfileHollow;
  306. UInt16 profileBegin = primShape.ProfileBegin;
  307. UInt16 profileEnd = primShape.ProfileEnd;
  308. UInt16 taperX = primShape.PathScaleX;
  309. UInt16 taperY = primShape.PathScaleY;
  310. UInt16 pathShearX = primShape.PathShearX;
  311. UInt16 pathShearY = primShape.PathShearY;
  312. Int16 twistTop = primShape.PathTwistBegin;
  313. Int16 twistBot = primShape.PathTwist;
  314. //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
  315. //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
  316. //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
  317. //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
  318. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  319. // of a block are basically the same
  320. // They may be warped differently but the shape is identical
  321. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  322. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  323. // The mapping to Scene space is done later during the "extrusion" phase
  324. // Base
  325. Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
  326. Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
  327. Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
  328. Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
  329. SimpleHull outerHull = new SimpleHull();
  330. outerHull.AddVertex(MM);
  331. outerHull.AddVertex(PM);
  332. outerHull.AddVertex(PP);
  333. outerHull.AddVertex(MP);
  334. // Deal with cuts now
  335. if ((profileBegin != 0) || (profileEnd != 0))
  336. {
  337. double fProfileBeginAngle = profileBegin/50000.0*360.0;
  338. // In degree, for easier debugging and understanding
  339. fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  340. double fProfileEndAngle = 360.0 - profileEnd/50000.0*360.0; // Pathend comes as complement to 1.0
  341. fProfileEndAngle -= (90.0 + 45.0);
  342. if (fProfileBeginAngle < fProfileEndAngle)
  343. fProfileEndAngle -= 360.0;
  344. // Note, that we don't want to cut out a triangle, even if this is a
  345. // good approximation for small cuts. Indeed we want to cut out an arc
  346. // and we approximate this arc by a polygon chain
  347. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  348. // So it can easily be subtracted from the outer hull
  349. int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5);
  350. // how many steps do we need with approximately 45 degree
  351. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps;
  352. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  353. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  354. SimpleHull cutHull = new SimpleHull();
  355. cutHull.AddVertex(origin);
  356. for (int i = 0; i < iSteps; i++)
  357. {
  358. double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!!
  359. Vertex v = Vertex.FromAngle(angle*Math.PI/180.0);
  360. cutHull.AddVertex(v);
  361. }
  362. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0);
  363. // Calculated separately to avoid errors
  364. cutHull.AddVertex(legEnd);
  365. //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  366. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  367. outerHull = cuttedHull;
  368. }
  369. // Deal with the hole here
  370. if (hollowFactor > 0)
  371. {
  372. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  373. if (holeHull != null)
  374. {
  375. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  376. outerHull = hollowedHull;
  377. }
  378. }
  379. Mesh m = new Mesh();
  380. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  381. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  382. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  383. m.Add(Seed1);
  384. m.Add(Seed2);
  385. m.Add(Seed3);
  386. m.Add(new Triangle(Seed1, Seed2, Seed3));
  387. m.Add(outerHull.getVertices());
  388. InsertVertices(m.vertices, 3, m.triangles);
  389. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  390. m.Remove(Seed1);
  391. m.Remove(Seed2);
  392. m.Remove(Seed3);
  393. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  394. m.RemoveTrianglesOutside(outerHull);
  395. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  396. foreach (Triangle t in m.triangles)
  397. {
  398. PhysicsVector n = t.getNormal();
  399. if (n.Z < 0.0)
  400. t.invertNormal();
  401. }
  402. Extruder extr = new Extruder();
  403. extr.size = size;
  404. if (taperX != 100)
  405. {
  406. if (taperX > 100)
  407. {
  408. extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
  409. //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  410. }
  411. else
  412. {
  413. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  414. //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  415. }
  416. }
  417. if (taperY != 100)
  418. {
  419. if (taperY > 100)
  420. {
  421. extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
  422. //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  423. }
  424. else
  425. {
  426. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  427. //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  428. }
  429. }
  430. if (pathShearX != 0)
  431. {
  432. if (pathShearX > 50) {
  433. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  434. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  435. // m_log.Warn("pushX: " + extr.pushX);
  436. }
  437. else
  438. {
  439. extr.pushX = (float)pathShearX / 100;
  440. // m_log.Warn("pushX: " + extr.pushX);
  441. }
  442. }
  443. if (pathShearY != 0)
  444. {
  445. if (pathShearY > 50) {
  446. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  447. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  448. //m_log.Warn("pushY: " + extr.pushY);
  449. }
  450. else
  451. {
  452. extr.pushY = (float)pathShearY / 100;
  453. //m_log.Warn("pushY: " + extr.pushY);
  454. }
  455. }
  456. if (twistTop != 0)
  457. {
  458. extr.twistTop = 180 * ((float)twistTop / 100);
  459. if (extr.twistTop > 0)
  460. {
  461. extr.twistTop = 360 - (-1 * extr.twistTop);
  462. }
  463. extr.twistTop = (float)(extr.twistTop * DEG_TO_RAD);
  464. }
  465. float twistMid = ((twistTop + twistBot) * 0.5f);
  466. if (twistMid != 0)
  467. {
  468. extr.twistMid = 180 * ((float)twistMid / 100);
  469. if (extr.twistMid > 0)
  470. {
  471. extr.twistMid = 360 - (-1 * extr.twistMid);
  472. }
  473. extr.twistMid = (float)(extr.twistMid * DEG_TO_RAD);
  474. }
  475. if (twistBot != 0)
  476. {
  477. extr.twistBot = 180 * ((float)twistBot / 100);
  478. if (extr.twistBot > 0)
  479. {
  480. extr.twistBot = 360 - (-1 * extr.twistBot);
  481. }
  482. extr.twistBot = (float)(extr.twistBot * DEG_TO_RAD);
  483. }
  484. Mesh result = extr.Extrude(m);
  485. result.DumpRaw(baseDir, primName, "Z extruded");
  486. return result;
  487. }
  488. private static Mesh CreateCyllinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  489. // Builds the z (+ and -) surfaces of a box shaped prim
  490. {
  491. UInt16 hollowFactor = primShape.ProfileHollow;
  492. UInt16 profileBegin = primShape.ProfileBegin;
  493. UInt16 profileEnd = primShape.ProfileEnd;
  494. UInt16 taperX = primShape.PathScaleX;
  495. UInt16 taperY = primShape.PathScaleY;
  496. UInt16 pathShearX = primShape.PathShearX;
  497. UInt16 pathShearY = primShape.PathShearY;
  498. Int16 twistBot = primShape.PathTwist;
  499. Int16 twistTop = primShape.PathTwistBegin;
  500. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  501. // of a block are basically the same
  502. // They may be warped differently but the shape is identical
  503. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  504. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  505. // The mapping to Scene space is done later during the "extrusion" phase
  506. // Base
  507. // Q1Q15 = Quadrant 1, Quadrant1, Vertex 5
  508. Vertex Q1Q15 = new Vertex(-0.35f, -0.35f, 0.0f);
  509. Vertex Q1Q16 = new Vertex(-0.30f, -0.40f, 0.0f);
  510. Vertex Q1Q17 = new Vertex(-0.24f, -0.43f, 0.0f);
  511. Vertex Q1Q18 = new Vertex(-0.18f, -0.46f, 0.0f);
  512. Vertex Q1Q19 = new Vertex(-0.11f, -0.48f, 0.0f);
  513. Vertex Q2Q10 = new Vertex(+0.0f, -0.50f, 0.0f);
  514. Vertex Q2Q11 = new Vertex(+0.11f, -0.48f, 0.0f);
  515. Vertex Q2Q12 = new Vertex(+0.18f, -0.46f, 0.0f);
  516. Vertex Q2Q13 = new Vertex(+0.24f, -0.43f, 0.0f);
  517. Vertex Q2Q14 = new Vertex(+0.30f, -0.40f, 0.0f);
  518. Vertex Q2Q15 = new Vertex(+0.35f, -0.35f, 0.0f);
  519. Vertex Q2Q16 = new Vertex(+0.40f, -0.30f, 0.0f);
  520. Vertex Q2Q17 = new Vertex(+0.43f, -0.24f, 0.0f);
  521. Vertex Q2Q18 = new Vertex(+0.46f, -0.18f, 0.0f);
  522. Vertex Q2Q19 = new Vertex(+0.48f, -0.11f, 0.0f);
  523. Vertex Q2Q20 = new Vertex(+0.50f, +0.0f, 0.0f);
  524. Vertex Q2Q21 = new Vertex(+0.48f, +0.11f, 0.0f);
  525. Vertex Q2Q22 = new Vertex(+0.46f, +0.18f, 0.0f);
  526. Vertex Q2Q23 = new Vertex(+0.43f, +0.24f, 0.0f);
  527. Vertex Q2Q24 = new Vertex(+0.40f, +0.30f, 0.0f);
  528. Vertex Q2Q25 = new Vertex(+0.35f, +0.35f, 0.0f);
  529. Vertex Q2Q26 = new Vertex(+0.30f, +0.40f, 0.0f);
  530. Vertex Q2Q27 = new Vertex(+0.24f, +0.43f, 0.0f);
  531. Vertex Q2Q28 = new Vertex(+0.18f, +0.46f, 0.0f);
  532. Vertex Q2Q29 = new Vertex(+0.11f, +0.48f, 0.0f);
  533. Vertex Q1Q20 = new Vertex(+0.0f, +0.50f, 0.0f);
  534. Vertex Q1Q21 = new Vertex(-0.11f, +0.48f, 0.0f);
  535. Vertex Q1Q22 = new Vertex(-0.18f, +0.46f, 0.0f);
  536. Vertex Q1Q23 = new Vertex(-0.24f, +0.43f, 0.0f);
  537. Vertex Q1Q24 = new Vertex(-0.30f, +0.40f, 0.0f);
  538. Vertex Q1Q25 = new Vertex(-0.35f, +0.35f, 0.0f);
  539. Vertex Q1Q26 = new Vertex(-0.40f, +0.30f, 0.0f);
  540. Vertex Q1Q27 = new Vertex(-0.43f, +0.24f, 0.0f);
  541. Vertex Q1Q28 = new Vertex(-0.46f, +0.18f, 0.0f);
  542. Vertex Q1Q29 = new Vertex(-0.48f, +0.11f, 0.0f);
  543. Vertex Q1Q10 = new Vertex(-0.50f, +0.0f, 0.0f);
  544. Vertex Q1Q11 = new Vertex(-0.48f, -0.11f, 0.0f);
  545. Vertex Q1Q12 = new Vertex(-0.46f, -0.18f, 0.0f);
  546. Vertex Q1Q13 = new Vertex(-0.43f, -0.24f, 0.0f);
  547. Vertex Q1Q14 = new Vertex(-0.40f, -0.30f, 0.0f);
  548. SimpleHull outerHull = new SimpleHull();
  549. //Clockwise around the quadrants
  550. outerHull.AddVertex(Q1Q15);
  551. outerHull.AddVertex(Q1Q16);
  552. outerHull.AddVertex(Q1Q17);
  553. outerHull.AddVertex(Q1Q18);
  554. outerHull.AddVertex(Q1Q19);
  555. outerHull.AddVertex(Q2Q10);
  556. outerHull.AddVertex(Q2Q11);
  557. outerHull.AddVertex(Q2Q12);
  558. outerHull.AddVertex(Q2Q13);
  559. outerHull.AddVertex(Q2Q14);
  560. outerHull.AddVertex(Q2Q15);
  561. outerHull.AddVertex(Q2Q16);
  562. outerHull.AddVertex(Q2Q17);
  563. outerHull.AddVertex(Q2Q18);
  564. outerHull.AddVertex(Q2Q19);
  565. outerHull.AddVertex(Q2Q20);
  566. outerHull.AddVertex(Q2Q21);
  567. outerHull.AddVertex(Q2Q22);
  568. outerHull.AddVertex(Q2Q23);
  569. outerHull.AddVertex(Q2Q24);
  570. outerHull.AddVertex(Q2Q25);
  571. outerHull.AddVertex(Q2Q26);
  572. outerHull.AddVertex(Q2Q27);
  573. outerHull.AddVertex(Q2Q28);
  574. outerHull.AddVertex(Q2Q29);
  575. outerHull.AddVertex(Q1Q20);
  576. outerHull.AddVertex(Q1Q21);
  577. outerHull.AddVertex(Q1Q22);
  578. outerHull.AddVertex(Q1Q23);
  579. outerHull.AddVertex(Q1Q24);
  580. outerHull.AddVertex(Q1Q25);
  581. outerHull.AddVertex(Q1Q26);
  582. outerHull.AddVertex(Q1Q27);
  583. outerHull.AddVertex(Q1Q28);
  584. outerHull.AddVertex(Q1Q29);
  585. outerHull.AddVertex(Q1Q10);
  586. outerHull.AddVertex(Q1Q11);
  587. outerHull.AddVertex(Q1Q12);
  588. outerHull.AddVertex(Q1Q13);
  589. outerHull.AddVertex(Q1Q14);
  590. // Deal with cuts now
  591. if ((profileBegin != 0) || (profileEnd != 0))
  592. {
  593. double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
  594. // In degree, for easier debugging and understanding
  595. //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  596. double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
  597. //fProfileEndAngle -= (90.0 + 45.0);
  598. if (fProfileBeginAngle < fProfileEndAngle)
  599. fProfileEndAngle -= 360.0;
  600. // Note, that we don't want to cut out a triangle, even if this is a
  601. // good approximation for small cuts. Indeed we want to cut out an arc
  602. // and we approximate this arc by a polygon chain
  603. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  604. // So it can easily be subtracted from the outer hull
  605. int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
  606. // how many steps do we need with approximately 45 degree
  607. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
  608. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  609. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  610. SimpleHull cutHull = new SimpleHull();
  611. cutHull.AddVertex(origin);
  612. for (int i = 0; i < iSteps; i++)
  613. {
  614. double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
  615. Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
  616. cutHull.AddVertex(v);
  617. }
  618. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
  619. // Calculated separately to avoid errors
  620. cutHull.AddVertex(legEnd);
  621. // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  622. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  623. outerHull = cuttedHull;
  624. }
  625. // Deal with the hole here
  626. if (hollowFactor > 0)
  627. {
  628. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  629. if (holeHull != null)
  630. {
  631. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  632. outerHull = hollowedHull;
  633. }
  634. }
  635. Mesh m = new Mesh();
  636. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  637. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  638. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  639. m.Add(Seed1);
  640. m.Add(Seed2);
  641. m.Add(Seed3);
  642. m.Add(new Triangle(Seed1, Seed2, Seed3));
  643. m.Add(outerHull.getVertices());
  644. InsertVertices(m.vertices, 3, m.triangles);
  645. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  646. m.Remove(Seed1);
  647. m.Remove(Seed2);
  648. m.Remove(Seed3);
  649. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  650. m.RemoveTrianglesOutside(outerHull);
  651. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  652. foreach (Triangle t in m.triangles)
  653. {
  654. PhysicsVector n = t.getNormal();
  655. if (n.Z < 0.0)
  656. t.invertNormal();
  657. }
  658. Extruder extr = new Extruder();
  659. extr.size = size;
  660. //System.Console.WriteLine("taperFactorX: " + taperX.ToString());
  661. //System.Console.WriteLine("taperFactorY: " + taperY.ToString());
  662. if (taperX != 100)
  663. {
  664. if (taperX > 100)
  665. {
  666. extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100);
  667. //System.Console.WriteLine("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  668. }
  669. else
  670. {
  671. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  672. //System.Console.WriteLine("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  673. }
  674. }
  675. if (taperY != 100)
  676. {
  677. if (taperY > 100)
  678. {
  679. extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 200);
  680. // System.Console.WriteLine("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  681. }
  682. else
  683. {
  684. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  685. //System.Console.WriteLine("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  686. }
  687. }
  688. if (pathShearX != 0)
  689. {
  690. if (pathShearX > 50)
  691. {
  692. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  693. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  694. //m_log.Warn("pushX: " + extr.pushX);
  695. }
  696. else
  697. {
  698. extr.pushX = (float)pathShearX / 100;
  699. //m_log.Warn("pushX: " + extr.pushX);
  700. }
  701. }
  702. if (pathShearY != 0)
  703. {
  704. if (pathShearY > 50)
  705. {
  706. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  707. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  708. //m_log.Warn("pushY: " + extr.pushY);
  709. }
  710. else
  711. {
  712. extr.pushY = (float)pathShearY / 100;
  713. //m_log.Warn("pushY: " + extr.pushY);
  714. }
  715. }
  716. if (twistTop != 0)
  717. {
  718. extr.twistTop = 180 * ((float)twistTop / 100);
  719. if (extr.twistTop > 0)
  720. {
  721. extr.twistTop = 360 - (-1 * extr.twistTop);
  722. }
  723. extr.twistTop = (float)(extr.twistTop * DEG_TO_RAD);
  724. }
  725. float twistMid = ((twistTop + twistBot) * 0.5f);
  726. if (twistMid != 0)
  727. {
  728. extr.twistMid = 180 * ((float)twistMid / 100);
  729. if (extr.twistMid > 0)
  730. {
  731. extr.twistMid = 360 - (-1 * extr.twistMid);
  732. }
  733. extr.twistMid = (float)(extr.twistMid * DEG_TO_RAD);
  734. }
  735. if (twistBot != 0)
  736. {
  737. extr.twistBot = 180 * ((float)twistBot / 100);
  738. if (extr.twistBot > 0)
  739. {
  740. extr.twistBot = 360 - (-1 * extr.twistBot);
  741. }
  742. extr.twistBot = (float)(extr.twistBot * DEG_TO_RAD);
  743. }
  744. //System.Console.WriteLine("[MESH]: twistTop = " + twistTop.ToString() + "|" + extr.twistTop.ToString() + ", twistMid = " + twistMid.ToString() + "|" + extr.twistMid.ToString() + ", twistbot = " + twistBot.ToString() + "|" + extr.twistBot.ToString());
  745. Mesh result = extr.Extrude(m);
  746. result.DumpRaw(baseDir, primName, "Z extruded");
  747. return result;
  748. }
  749. private static Mesh CreatePrismMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  750. // Builds the z (+ and -) surfaces of a box shaped prim
  751. {
  752. UInt16 hollowFactor = primShape.ProfileHollow;
  753. UInt16 profileBegin = primShape.ProfileBegin;
  754. UInt16 profileEnd = primShape.ProfileEnd;
  755. UInt16 taperX = primShape.PathScaleX;
  756. UInt16 taperY = primShape.PathScaleY;
  757. UInt16 pathShearX = primShape.PathShearX;
  758. UInt16 pathShearY = primShape.PathShearY;
  759. Int16 twistTop = primShape.PathTwistBegin;
  760. Int16 twistBot = primShape.PathTwist;
  761. //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
  762. //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
  763. //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
  764. //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
  765. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  766. // of a block are basically the same
  767. // They may be warped differently but the shape is identical
  768. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  769. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  770. // The mapping to Scene space is done later during the "extrusion" phase
  771. // Base
  772. Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
  773. Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
  774. Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
  775. SimpleHull outerHull = new SimpleHull();
  776. outerHull.AddVertex(MM);
  777. outerHull.AddVertex(PM);
  778. outerHull.AddVertex(PP);
  779. // Deal with cuts now
  780. if ((profileBegin != 0) || (profileEnd != 0))
  781. {
  782. double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
  783. // In degree, for easier debugging and understanding
  784. //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  785. double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
  786. //fProfileEndAngle -= (90.0 + 45.0);
  787. if (fProfileBeginAngle < fProfileEndAngle)
  788. fProfileEndAngle -= 360.0;
  789. // Note, that we don't want to cut out a triangle, even if this is a
  790. // good approximation for small cuts. Indeed we want to cut out an arc
  791. // and we approximate this arc by a polygon chain
  792. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  793. // So it can easily be subtracted from the outer hull
  794. int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
  795. // how many steps do we need with approximately 45 degree
  796. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
  797. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  798. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  799. SimpleHull cutHull = new SimpleHull();
  800. cutHull.AddVertex(origin);
  801. for (int i = 0; i < iSteps; i++)
  802. {
  803. double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
  804. Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
  805. cutHull.AddVertex(v);
  806. }
  807. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
  808. // Calculated separately to avoid errors
  809. cutHull.AddVertex(legEnd);
  810. //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  811. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  812. outerHull = cuttedHull;
  813. }
  814. // Deal with the hole here
  815. if (hollowFactor > 0)
  816. {
  817. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  818. if (holeHull != null)
  819. {
  820. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  821. outerHull = hollowedHull;
  822. }
  823. }
  824. Mesh m = new Mesh();
  825. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  826. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  827. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  828. m.Add(Seed1);
  829. m.Add(Seed2);
  830. m.Add(Seed3);
  831. m.Add(new Triangle(Seed1, Seed2, Seed3));
  832. m.Add(outerHull.getVertices());
  833. InsertVertices(m.vertices, 3, m.triangles);
  834. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  835. m.Remove(Seed1);
  836. m.Remove(Seed2);
  837. m.Remove(Seed3);
  838. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  839. m.RemoveTrianglesOutside(outerHull);
  840. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  841. foreach (Triangle t in m.triangles)
  842. {
  843. PhysicsVector n = t.getNormal();
  844. if (n.Z < 0.0)
  845. t.invertNormal();
  846. }
  847. Extruder extr = new Extruder();
  848. extr.size = size;
  849. if (taperX != 100)
  850. {
  851. if (taperX > 100)
  852. {
  853. extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
  854. //System.Console.WriteLine("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  855. }
  856. else
  857. {
  858. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  859. //System.Console.WriteLine("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  860. }
  861. }
  862. if (taperY != 100)
  863. {
  864. if (taperY > 100)
  865. {
  866. extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
  867. //System.Console.WriteLine("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  868. }
  869. else
  870. {
  871. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  872. //System.Console.WriteLine("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  873. }
  874. }
  875. if (pathShearX != 0)
  876. {
  877. if (pathShearX > 50)
  878. {
  879. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  880. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  881. // m_log.Warn("pushX: " + extr.pushX);
  882. }
  883. else
  884. {
  885. extr.pushX = (float)pathShearX / 100;
  886. // m_log.Warn("pushX: " + extr.pushX);
  887. }
  888. }
  889. if (pathShearY != 0)
  890. {
  891. if (pathShearY > 50)
  892. {
  893. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  894. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  895. //m_log.Warn("pushY: " + extr.pushY);
  896. }
  897. else
  898. {
  899. extr.pushY = (float)pathShearY / 100;
  900. //m_log.Warn("pushY: " + extr.pushY);
  901. }
  902. }
  903. if (twistTop != 0)
  904. {
  905. extr.twistTop = 180 * ((float)twistTop / 100);
  906. if (extr.twistTop > 0)
  907. {
  908. extr.twistTop = 360 - (-1 * extr.twistTop);
  909. }
  910. extr.twistTop = (float)(extr.twistTop * DEG_TO_RAD);
  911. }
  912. float twistMid = ((twistTop + twistBot) * 0.5f);
  913. if (twistMid != 0)
  914. {
  915. extr.twistMid = 180 * ((float)twistMid / 100);
  916. if (extr.twistMid > 0)
  917. {
  918. extr.twistMid = 360 - (-1 * extr.twistMid);
  919. }
  920. extr.twistMid = (float)(extr.twistMid * DEG_TO_RAD);
  921. }
  922. if (twistBot != 0)
  923. {
  924. extr.twistBot = 180 * ((float)twistBot / 100);
  925. if (extr.twistBot > 0)
  926. {
  927. extr.twistBot = 360 - (-1 * extr.twistBot);
  928. }
  929. extr.twistBot = (float)(extr.twistBot * DEG_TO_RAD);
  930. }
  931. Mesh result = extr.Extrude(m);
  932. result.DumpRaw(baseDir, primName, "Z extruded");
  933. return result;
  934. }
  935. private static Mesh CreateSphereMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  936. {
  937. // Builds an icosahedral geodesic sphere
  938. // based on an article by Paul Bourke
  939. // http://local.wasp.uwa.edu.au/~pbourke/
  940. // articles:
  941. // http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonmesh/
  942. // and
  943. // http://local.wasp.uwa.edu.au/~pbourke/geometry/polyhedra/index.html
  944. // Still have more to do here.
  945. UInt16 hollowFactor = primShape.ProfileHollow;
  946. UInt16 profileBegin = primShape.ProfileBegin;
  947. UInt16 profileEnd = primShape.ProfileEnd;
  948. UInt16 taperX = primShape.PathScaleX;
  949. UInt16 taperY = primShape.PathScaleY;
  950. UInt16 pathShearX = primShape.PathShearX;
  951. UInt16 pathShearY = primShape.PathShearY;
  952. Mesh m = new Mesh();
  953. float LOD = 0.2f;
  954. float diameter = 0.5f;// Our object will result in -0.5 to 0.5
  955. float sq5 = (float) Math.Sqrt(5.0);
  956. float phi = (1 + sq5) * 0.5f;
  957. float rat = (float) Math.Sqrt(10f + (2f * sq5)) / (4f * phi);
  958. float a = (diameter / rat) * 0.5f;
  959. float b = (diameter / rat) / (2.0f * phi);
  960. // 12 Icosahedron vertexes
  961. Vertex v1 = new Vertex(0f, b, -a);
  962. Vertex v2 = new Vertex(b, a, 0f);
  963. Vertex v3 = new Vertex(-b, a, 0f);
  964. Vertex v4 = new Vertex(0f, b, a);
  965. Vertex v5 = new Vertex(0f, -b, a);
  966. Vertex v6 = new Vertex(-a, 0f, b);
  967. Vertex v7 = new Vertex(0f, -b, -a);
  968. Vertex v8 = new Vertex(a, 0f, -b);
  969. Vertex v9 = new Vertex(a, 0f, b);
  970. Vertex v10 = new Vertex(-a, 0f, -b);
  971. Vertex v11 = new Vertex(b, -a, 0);
  972. Vertex v12 = new Vertex(-b, -a, 0);
  973. // Base Faces of the Icosahedron (20)
  974. SphereLODTriangle(v1, v2, v3, diameter, LOD, m);
  975. SphereLODTriangle(v4, v3, v2, diameter, LOD, m);
  976. SphereLODTriangle(v4, v5, v6, diameter, LOD, m);
  977. SphereLODTriangle(v4, v9, v5, diameter, LOD, m);
  978. SphereLODTriangle(v1, v7, v8, diameter, LOD, m);
  979. SphereLODTriangle(v1, v10, v7, diameter, LOD, m);
  980. SphereLODTriangle(v5, v11, v12, diameter, LOD, m);
  981. SphereLODTriangle(v7, v12, v11, diameter, LOD, m);
  982. SphereLODTriangle(v3, v6, v10, diameter, LOD, m);
  983. SphereLODTriangle(v12, v10, v6, diameter, LOD, m);
  984. SphereLODTriangle(v2, v8, v9, diameter, LOD, m);
  985. SphereLODTriangle(v11, v9, v8, diameter, LOD, m);
  986. SphereLODTriangle(v4, v6, v3, diameter, LOD, m);
  987. SphereLODTriangle(v4, v2, v9, diameter, LOD, m);
  988. SphereLODTriangle(v1, v3, v10, diameter, LOD, m);
  989. SphereLODTriangle(v1, v8, v2, diameter, LOD, m);
  990. SphereLODTriangle(v7, v10, v12, diameter, LOD, m);
  991. SphereLODTriangle(v7, v11, v8, diameter, LOD, m);
  992. SphereLODTriangle(v5, v12, v6, diameter, LOD, m);
  993. SphereLODTriangle(v5, v9, v11, diameter, LOD, m);
  994. // Scale the mesh based on our prim scale
  995. foreach (Vertex v in m.vertices)
  996. {
  997. v.X *= size.X;
  998. v.Y *= size.Y;
  999. v.Z *= size.Z;
  1000. }
  1001. // This was built with the normals pointing inside..
  1002. // therefore we have to invert the normals
  1003. foreach (Triangle t in m.triangles)
  1004. {
  1005. t.invertNormal();
  1006. }
  1007. // Dump the faces for visualization in blender.
  1008. m.DumpRaw(baseDir, primName, "Icosahedron");
  1009. return m;
  1010. }
  1011. public static void CalcNormals(Mesh mesh)
  1012. {
  1013. int iTriangles = mesh.triangles.Count;
  1014. mesh.normals = new float[iTriangles*3];
  1015. int i = 0;
  1016. foreach (Triangle t in mesh.triangles)
  1017. {
  1018. float ux, uy, uz;
  1019. float vx, vy, vz;
  1020. float wx, wy, wz;
  1021. ux = t.v1.X;
  1022. uy = t.v1.Y;
  1023. uz = t.v1.Z;
  1024. vx = t.v2.X;
  1025. vy = t.v2.Y;
  1026. vz = t.v2.Z;
  1027. wx = t.v3.X;
  1028. wy = t.v3.Y;
  1029. wz = t.v3.Z;
  1030. // Vectors for edges
  1031. float e1x, e1y, e1z;
  1032. float e2x, e2y, e2z;
  1033. e1x = ux - vx;
  1034. e1y = uy - vy;
  1035. e1z = uz - vz;
  1036. e2x = ux - wx;
  1037. e2y = uy - wy;
  1038. e2z = uz - wz;
  1039. // Cross product for normal
  1040. float nx, ny, nz;
  1041. nx = e1y*e2z - e1z*e2y;
  1042. ny = e1z*e2x - e1x*e2z;
  1043. nz = e1x*e2y - e1y*e2x;
  1044. // Length
  1045. float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz);
  1046. // Normalized "normal"
  1047. nx /= l;
  1048. ny /= l;
  1049. nz /= l;
  1050. mesh.normals[i] = nx;
  1051. mesh.normals[i + 1] = ny;
  1052. mesh.normals[i + 2] = nz;
  1053. i += 3;
  1054. }
  1055. }
  1056. public static Vertex midUnitRadialPoint(Vertex a, Vertex b, float radius)
  1057. {
  1058. Vertex midpoint = new Vertex(a + b) * 0.5f;
  1059. return (midpoint.normalize() * radius);
  1060. }
  1061. public static void SphereLODTriangle(Vertex a, Vertex b, Vertex c, float diameter, float LOD, Mesh m)
  1062. {
  1063. Vertex aa = a - b;
  1064. Vertex ba = b - c;
  1065. Vertex da = c - a;
  1066. if (((aa.length() < LOD) && (ba.length() < LOD) && (da.length() < LOD)))
  1067. {
  1068. // We don't want duplicate verticies. Duplicates cause the scale algorithm to produce a spikeball
  1069. // spikes are novel, but we want ellipsoids.
  1070. if (!m.vertices.Contains(a))
  1071. m.Add(a);
  1072. if (!m.vertices.Contains(b))
  1073. m.Add(b);
  1074. if (!m.vertices.Contains(c))
  1075. m.Add(c);
  1076. // Add the triangle to the mesh
  1077. Triangle t = new Triangle(a, b, c);
  1078. m.Add(t);
  1079. }
  1080. else
  1081. {
  1082. Vertex ab = midUnitRadialPoint(a, b, diameter);
  1083. Vertex bc = midUnitRadialPoint(b, c, diameter);
  1084. Vertex ca = midUnitRadialPoint(c, a, diameter);
  1085. // Recursive! Splits the triangle up into 4 smaller triangles
  1086. SphereLODTriangle(a, ab, ca, diameter, LOD, m);
  1087. SphereLODTriangle(ab, b, bc, diameter, LOD, m);
  1088. SphereLODTriangle(ca, bc, c, diameter, LOD, m);
  1089. SphereLODTriangle(ab, bc, ca, diameter, LOD, m);
  1090. }
  1091. }
  1092. public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  1093. {
  1094. Mesh mesh = null;
  1095. switch (primShape.ProfileShape)
  1096. {
  1097. case ProfileShape.Square:
  1098. mesh = CreateBoxMesh(primName, primShape, size);
  1099. CalcNormals(mesh);
  1100. break;
  1101. case ProfileShape.Circle:
  1102. if (primShape.PathCurve == (byte)Extrusion.Straight)
  1103. {
  1104. mesh = CreateCyllinderMesh(primName, primShape, size);
  1105. CalcNormals(mesh);
  1106. }
  1107. break;
  1108. case ProfileShape.HalfCircle:
  1109. if (primShape.PathCurve == (byte)Extrusion.Curve1)
  1110. {
  1111. mesh = CreateSphereMesh(primName, primShape, size);
  1112. CalcNormals(mesh);
  1113. }
  1114. break;
  1115. case ProfileShape.EquilateralTriangle:
  1116. mesh = CreatePrismMesh(primName, primShape, size);
  1117. CalcNormals(mesh);
  1118. break;
  1119. default:
  1120. mesh = CreateBoxMesh(primName, primShape, size);
  1121. CalcNormals(mesh);
  1122. //Set default mesh to cube otherwise it'll return
  1123. // null and crash on the 'setMesh' method in the physics plugins.
  1124. //mesh = null;
  1125. break;
  1126. }
  1127. return mesh;
  1128. }
  1129. }
  1130. }