Meshmerizer.cs 101 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250
  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. //#define SPAM
  28. using System;
  29. using System.Collections.Generic;
  30. using OpenSim.Framework;
  31. using OpenSim.Region.Physics.Manager;
  32. using libsecondlife;
  33. namespace OpenSim.Region.Physics.Meshing
  34. {
  35. public class MeshmerizerPlugin : IMeshingPlugin
  36. {
  37. public MeshmerizerPlugin()
  38. {
  39. }
  40. public string GetName()
  41. {
  42. return "Meshmerizer";
  43. }
  44. public IMesher GetMesher()
  45. {
  46. return new Meshmerizer();
  47. }
  48. }
  49. public class Meshmerizer : IMesher
  50. {
  51. //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  52. // Setting baseDir to a path will enable the dumping of raw files
  53. // raw files can be imported by blender so a visual inspection of the results can be done
  54. #if SPAM
  55. const string baseDir = "rawFiles";
  56. #else
  57. private const string baseDir = null; //"rawFiles";
  58. #endif
  59. private const float DEG_TO_RAD = 0.01745329238f;
  60. private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
  61. // TODO: unused
  62. // private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2,
  63. // PhysicsVector r2, ref float lambda, ref float mu)
  64. // {
  65. // // p1, p2, points on the straight
  66. // // r1, r2, directional vectors of the straight. Not necessarily of length 1!
  67. // // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
  68. // // thus allowing to decide whether an intersection is between two points
  69. // float r1x = r1.X;
  70. // float r1y = r1.Y;
  71. // float r2x = r2.X;
  72. // float r2y = r2.Y;
  73. // float denom = r1y*r2x - r1x*r2y;
  74. // if (denom == 0.0)
  75. // {
  76. // lambda = Single.NaN;
  77. // mu = Single.NaN;
  78. // return;
  79. // }
  80. // float p1x = p1.X;
  81. // float p1y = p1.Y;
  82. // float p2x = p2.X;
  83. // float p2y = p2.Y;
  84. // lambda = (-p2x*r2y + p1x*r2y + (p2y - p1y)*r2x)/denom;
  85. // mu = (-p2x*r1y + p1x*r1y + (p2y - p1y)*r1x)/denom;
  86. // }
  87. private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
  88. {
  89. List<Triangle> influenced = new List<Triangle>();
  90. foreach (Triangle t in triangles)
  91. {
  92. if (t.isInCircle(v.X, v.Y))
  93. {
  94. influenced.Add(t);
  95. }
  96. }
  97. return influenced;
  98. }
  99. private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
  100. {
  101. // This is a variant of the delaunay algorithm
  102. // each time a new vertex is inserted, all triangles that are influenced by it are deleted
  103. // and replaced by new ones including the new vertex
  104. // It is not very time efficient but easy to implement.
  105. int iCurrentVertex;
  106. int iMaxVertex = vertices.Count;
  107. for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
  108. {
  109. // Background: A triangle mesh fulfills the delaunay condition if (iff!)
  110. // each circumlocutory circle (i.e. the circle that touches all three corners)
  111. // of each triangle is empty of other vertices.
  112. // Obviously a single (seeding) triangle fulfills this condition.
  113. // If we now add one vertex, we need to reconstruct all triangles, that
  114. // do not fulfill this condition with respect to the new triangle
  115. // Find the triangles that are influenced by the new vertex
  116. Vertex v = vertices[iCurrentVertex];
  117. if (v == null)
  118. continue; // Null is polygon stop marker. Ignore it
  119. List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v);
  120. List<Simplex> simplices = new List<Simplex>();
  121. // Reconstruction phase. First step, dissolve each triangle into it's simplices,
  122. // i.e. it's "border lines"
  123. // Goal is to find "inner" borders and delete them, while the hull gets conserved.
  124. // Inner borders are special in the way that they always come twice, which is how we detect them
  125. foreach (Triangle t in influencedTriangles)
  126. {
  127. List<Simplex> newSimplices = t.GetSimplices();
  128. simplices.AddRange(newSimplices);
  129. triangles.Remove(t);
  130. }
  131. // Now sort the simplices. That will make identical ones reside side by side in the list
  132. simplices.Sort();
  133. // Look for duplicate simplices here.
  134. // Remember, they are directly side by side in the list right now,
  135. // So we only check directly neighbours
  136. int iSimplex;
  137. List<Simplex> innerSimplices = new List<Simplex>();
  138. for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
  139. {
  140. if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0)
  141. {
  142. innerSimplices.Add(simplices[iSimplex - 1]);
  143. innerSimplices.Add(simplices[iSimplex]);
  144. }
  145. }
  146. foreach (Simplex s in innerSimplices)
  147. {
  148. simplices.Remove(s);
  149. }
  150. // each simplex still in the list belongs to the hull of the region in question
  151. // The new vertex (yes, we still deal with verices here :-)) forms a triangle
  152. // with each of these simplices. Build the new triangles and add them to the list
  153. foreach (Simplex s in simplices)
  154. {
  155. Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
  156. if (!t.isDegraded())
  157. {
  158. triangles.Add(t);
  159. }
  160. }
  161. }
  162. }
  163. private static SimpleHull BuildHoleHull(PrimitiveBaseShape pbs, ProfileShape pshape, HollowShape hshape, UInt16 hollowFactor)
  164. {
  165. // Tackle HollowShape.Same
  166. float fhollowFactor = (float)hollowFactor;
  167. switch (pshape)
  168. {
  169. case ProfileShape.Square:
  170. if (hshape == HollowShape.Same)
  171. hshape= HollowShape.Square;
  172. break;
  173. case ProfileShape.EquilateralTriangle:
  174. fhollowFactor = ((float)hollowFactor / 1.9f);
  175. if (hshape == HollowShape.Same)
  176. {
  177. hshape = HollowShape.Triangle;
  178. }
  179. break;
  180. case ProfileShape.HalfCircle:
  181. case ProfileShape.Circle:
  182. if (pbs.PathCurve == (byte)Extrusion.Straight)
  183. {
  184. if (hshape == HollowShape.Same)
  185. {
  186. hshape = HollowShape.Circle;
  187. }
  188. }
  189. break;
  190. default:
  191. if (hshape == HollowShape.Same)
  192. hshape= HollowShape.Square;
  193. break;
  194. }
  195. SimpleHull holeHull = null;
  196. if (hshape == HollowShape.Square)
  197. {
  198. float hollowFactorF = (float)fhollowFactor / (float)50000;
  199. Vertex IMM;
  200. Vertex IPM;
  201. Vertex IPP;
  202. Vertex IMP;
  203. if (pshape == ProfileShape.Circle)
  204. { // square cutout in cylinder is 45 degress rotated
  205. IMM = new Vertex(0.0f, -0.707f * hollowFactorF, 0.0f);
  206. IPM = new Vertex(0.707f * hollowFactorF, 0.0f, 0.0f);
  207. IPP = new Vertex(0.0f, 0.707f * hollowFactorF, 0.0f);
  208. IMP = new Vertex(-0.707f * hollowFactorF, 0.0f, 0.0f);
  209. }
  210. else if (pshape == ProfileShape.EquilateralTriangle)
  211. {
  212. IMM = new Vertex(0.0f, -0.667f * hollowFactorF, 0.0f);
  213. IPM = new Vertex(0.667f * hollowFactorF, 0.0f, 0.0f);
  214. IPP = new Vertex(0.0f, 0.667f * hollowFactorF, 0.0f);
  215. IMP = new Vertex(-0.667f * hollowFactorF, 0.0f, 0.0f);
  216. }
  217. else
  218. {
  219. IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
  220. IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
  221. IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
  222. IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
  223. }
  224. holeHull = new SimpleHull();
  225. holeHull.AddVertex(IMM);
  226. holeHull.AddVertex(IMP);
  227. holeHull.AddVertex(IPP);
  228. holeHull.AddVertex(IPM);
  229. }
  230. //if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  231. if (hshape == HollowShape.Circle)
  232. {
  233. float hollowFactorF = (float)fhollowFactor / (float)50000;
  234. //Vertex IQ1Q15 = new Vertex(-0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
  235. //Vertex IQ1Q16 = new Vertex(-0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
  236. //Vertex IQ1Q17 = new Vertex(-0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
  237. //Vertex IQ1Q18 = new Vertex(-0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
  238. //Vertex IQ1Q19 = new Vertex(-0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
  239. //Vertex IQ2Q10 = new Vertex(+0.0f * hollowFactorF, -0.50f * hollowFactorF, 0.0f);
  240. //Vertex IQ2Q11 = new Vertex(+0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
  241. //Vertex IQ2Q12 = new Vertex(+0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
  242. //Vertex IQ2Q13 = new Vertex(+0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
  243. //Vertex IQ2Q14 = new Vertex(+0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
  244. //Vertex IQ2Q15 = new Vertex(+0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
  245. //Vertex IQ2Q16 = new Vertex(+0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
  246. //Vertex IQ2Q17 = new Vertex(+0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
  247. //Vertex IQ2Q18 = new Vertex(+0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
  248. //Vertex IQ2Q19 = new Vertex(+0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
  249. //Vertex IQ2Q20 = new Vertex(+0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
  250. //Vertex IQ2Q21 = new Vertex(+0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
  251. //Vertex IQ2Q22 = new Vertex(+0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
  252. //Vertex IQ2Q23 = new Vertex(+0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
  253. //Vertex IQ2Q24 = new Vertex(+0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
  254. //Vertex IQ2Q25 = new Vertex(+0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
  255. //Vertex IQ2Q26 = new Vertex(+0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
  256. //Vertex IQ2Q27 = new Vertex(+0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
  257. //Vertex IQ2Q28 = new Vertex(+0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
  258. //Vertex IQ2Q29 = new Vertex(+0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
  259. //Vertex IQ1Q20 = new Vertex(+0.0f * hollowFactorF, +0.50f * hollowFactorF, 0.0f);
  260. //Vertex IQ1Q21 = new Vertex(-0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
  261. //Vertex IQ1Q22 = new Vertex(-0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
  262. //Vertex IQ1Q23 = new Vertex(-0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
  263. //Vertex IQ1Q24 = new Vertex(-0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
  264. //Vertex IQ1Q25 = new Vertex(-0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
  265. //Vertex IQ1Q26 = new Vertex(-0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
  266. //Vertex IQ1Q27 = new Vertex(-0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
  267. //Vertex IQ1Q28 = new Vertex(-0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
  268. //Vertex IQ1Q29 = new Vertex(-0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
  269. //Vertex IQ1Q10 = new Vertex(-0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
  270. //Vertex IQ1Q11 = new Vertex(-0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
  271. //Vertex IQ1Q12 = new Vertex(-0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
  272. //Vertex IQ1Q13 = new Vertex(-0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
  273. //Vertex IQ1Q14 = new Vertex(-0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
  274. //Counter clockwise around the quadrants
  275. holeHull = new SimpleHull();
  276. //holeHull.AddVertex(IQ1Q15);
  277. //holeHull.AddVertex(IQ1Q14);
  278. //holeHull.AddVertex(IQ1Q13);
  279. //holeHull.AddVertex(IQ1Q12);
  280. //holeHull.AddVertex(IQ1Q11);
  281. //holeHull.AddVertex(IQ1Q10);
  282. //holeHull.AddVertex(IQ1Q29);
  283. //holeHull.AddVertex(IQ1Q28);
  284. //holeHull.AddVertex(IQ1Q27);
  285. //holeHull.AddVertex(IQ1Q26);
  286. //holeHull.AddVertex(IQ1Q25);
  287. //holeHull.AddVertex(IQ1Q24);
  288. //holeHull.AddVertex(IQ1Q23);
  289. //holeHull.AddVertex(IQ1Q22);
  290. //holeHull.AddVertex(IQ1Q21);
  291. //holeHull.AddVertex(IQ1Q20);
  292. //holeHull.AddVertex(IQ2Q29);
  293. //holeHull.AddVertex(IQ2Q28);
  294. //holeHull.AddVertex(IQ2Q27);
  295. //holeHull.AddVertex(IQ2Q26);
  296. //holeHull.AddVertex(IQ2Q25);
  297. //holeHull.AddVertex(IQ2Q24);
  298. //holeHull.AddVertex(IQ2Q23);
  299. //holeHull.AddVertex(IQ2Q22);
  300. //holeHull.AddVertex(IQ2Q21);
  301. //holeHull.AddVertex(IQ2Q20);
  302. //holeHull.AddVertex(IQ2Q19);
  303. //holeHull.AddVertex(IQ2Q18);
  304. //holeHull.AddVertex(IQ2Q17);
  305. //holeHull.AddVertex(IQ2Q16);
  306. //holeHull.AddVertex(IQ2Q15);
  307. //holeHull.AddVertex(IQ2Q14);
  308. //holeHull.AddVertex(IQ2Q13);
  309. //holeHull.AddVertex(IQ2Q12);
  310. //holeHull.AddVertex(IQ2Q11);
  311. //holeHull.AddVertex(IQ2Q10);
  312. //holeHull.AddVertex(IQ1Q19);
  313. //holeHull.AddVertex(IQ1Q18);
  314. //holeHull.AddVertex(IQ1Q17);
  315. //holeHull.AddVertex(IQ1Q16);
  316. holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 45 degrees
  317. holeHull.AddVertex(new Vertex(0.433013f * hollowFactorF, 0.250000f * hollowFactorF, 0.0f)); // 30 degrees
  318. holeHull.AddVertex(new Vertex(0.482963f * hollowFactorF, 0.129410f * hollowFactorF, 0.0f)); // 15 degrees
  319. holeHull.AddVertex(new Vertex(0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 0 degrees
  320. holeHull.AddVertex(new Vertex(0.482963f * hollowFactorF, -0.129410f * hollowFactorF, 0.0f)); // 345 degrees
  321. holeHull.AddVertex(new Vertex(0.433013f * hollowFactorF, -0.250000f * hollowFactorF, 0.0f)); // 330 degrees
  322. holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, -0.353553f * hollowFactorF, 0.0f)); // 315 degrees
  323. holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, -0.433013f * hollowFactorF, 0.0f)); // 300 degrees
  324. holeHull.AddVertex(new Vertex(0.129410f * hollowFactorF, -0.482963f * hollowFactorF, 0.0f)); // 285 degrees
  325. holeHull.AddVertex(new Vertex(0.000000f * hollowFactorF, -0.500000f * hollowFactorF, 0.0f)); // 270 degrees
  326. holeHull.AddVertex(new Vertex(-0.129410f * hollowFactorF, -0.482963f * hollowFactorF, 0.0f)); // 255 degrees
  327. holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, -0.433013f * hollowFactorF, 0.0f)); // 240 degrees
  328. holeHull.AddVertex(new Vertex(-0.353553f * hollowFactorF, -0.353553f * hollowFactorF, 0.0f)); // 225 degrees
  329. holeHull.AddVertex(new Vertex(-0.433013f * hollowFactorF, -0.250000f * hollowFactorF, 0.0f)); // 210 degrees
  330. holeHull.AddVertex(new Vertex(-0.482963f * hollowFactorF, -0.129410f * hollowFactorF, 0.0f)); // 195 degrees
  331. holeHull.AddVertex(new Vertex(-0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 180 degrees
  332. holeHull.AddVertex(new Vertex(-0.482963f * hollowFactorF, 0.129410f * hollowFactorF, 0.0f)); // 165 degrees
  333. holeHull.AddVertex(new Vertex(-0.433013f * hollowFactorF, 0.250000f * hollowFactorF, 0.0f)); // 150 degrees
  334. holeHull.AddVertex(new Vertex(-0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 135 degrees
  335. holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 120 degrees
  336. holeHull.AddVertex(new Vertex(-0.129410f * hollowFactorF, 0.482963f * hollowFactorF, 0.0f)); // 105 degrees
  337. holeHull.AddVertex(new Vertex(0.000000f * hollowFactorF, 0.500000f * hollowFactorF, 0.0f)); // 90 degrees
  338. holeHull.AddVertex(new Vertex(0.129410f * hollowFactorF, 0.482963f * hollowFactorF, 0.0f)); // 75 degrees
  339. holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 60 degrees
  340. holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 45 degrees
  341. }
  342. if (hshape == HollowShape.Triangle)
  343. {
  344. float hollowFactorF = (float)fhollowFactor / (float)50000;
  345. Vertex IMM;
  346. Vertex IPM;
  347. Vertex IPP;
  348. if (pshape == ProfileShape.Square)
  349. {
  350. // corner points are at 345, 105, and 225 degrees for the triangle within a box
  351. //IMM = new Vertex(((float)Math.Cos(345.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(345.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f);
  352. //IPM = new Vertex(((float)Math.Cos(105.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(105.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f);
  353. //IPP = new Vertex(((float)Math.Cos(225.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(225.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f);
  354. // hard coded here for speed, the equations are in the commented out lines above
  355. IMM = new Vertex(0.48296f * hollowFactorF, -0.12941f * hollowFactorF, 0.0f);
  356. IPM = new Vertex(-0.12941f * hollowFactorF, 0.48296f * hollowFactorF, 0.0f);
  357. IPP = new Vertex(-0.35355f * hollowFactorF, -0.35355f * hollowFactorF, 0.0f);
  358. }
  359. else
  360. {
  361. IMM = new Vertex(-0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f);
  362. IPM = new Vertex(+0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f);
  363. IPP = new Vertex(-0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f);
  364. }
  365. holeHull = new SimpleHull();
  366. holeHull.AddVertex(IMM);
  367. holeHull.AddVertex(IPP);
  368. holeHull.AddVertex(IPM);
  369. }
  370. return holeHull;
  371. }
  372. /// <summary>
  373. /// creates a simple box mesh of the specified size
  374. /// </summary>
  375. /// <param name="minX"></param>
  376. /// <param name="maxX"></param>
  377. /// <param name="minY"></param>
  378. /// <param name="maxY"></param>
  379. /// <param name="minZ"></param>
  380. /// <param name="maxZ"></param>
  381. /// <returns></returns>
  382. private static Mesh CreateSimpleBoxMesh(float minX, float maxX, float minY, float maxY, float minZ, float maxZ)
  383. {
  384. Mesh box = new Mesh();
  385. // bottom
  386. //box.Add(new Vertex(maxX, maxY, minZ));
  387. //box.Add(new Vertex(minX, maxY, minZ));
  388. //box.Add(new Vertex(minX, minY, minZ));
  389. //box.Add(new Vertex(maxX, minY, minZ));
  390. box.Add(new Vertex(minX, maxY, minZ));
  391. box.Add(new Vertex(maxX, maxY, minZ));
  392. box.Add(new Vertex(maxX, minY, minZ));
  393. box.Add(new Vertex(minX, minY, minZ));
  394. box.Add(new Triangle(box.vertices[0], box.vertices[1], box.vertices[2]));
  395. box.Add(new Triangle(box.vertices[0], box.vertices[2], box.vertices[3]));
  396. // top
  397. box.Add(new Vertex(maxX, maxY, maxZ));
  398. box.Add(new Vertex(minX, maxY, maxZ));
  399. box.Add(new Vertex(minX, minY, maxZ));
  400. box.Add(new Vertex(maxX, minY, maxZ));
  401. box.Add(new Triangle(box.vertices[4], box.vertices[5], box.vertices[6]));
  402. box.Add(new Triangle(box.vertices[4], box.vertices[6], box.vertices[7]));
  403. // sides
  404. box.Add(new Triangle(box.vertices[5], box.vertices[0], box.vertices[3]));
  405. box.Add(new Triangle(box.vertices[5], box.vertices[3], box.vertices[6]));
  406. box.Add(new Triangle(box.vertices[1], box.vertices[0], box.vertices[5]));
  407. box.Add(new Triangle(box.vertices[1], box.vertices[5], box.vertices[4]));
  408. box.Add(new Triangle(box.vertices[7], box.vertices[1], box.vertices[4]));
  409. box.Add(new Triangle(box.vertices[7], box.vertices[2], box.vertices[1]));
  410. box.Add(new Triangle(box.vertices[3], box.vertices[2], box.vertices[7]));
  411. box.Add(new Triangle(box.vertices[3], box.vertices[7], box.vertices[6]));
  412. return box;
  413. }
  414. /// <summary>
  415. /// Creates a simple bounding box mesh for a complex input mesh
  416. /// </summary>
  417. /// <param name="meshIn"></param>
  418. /// <returns></returns>
  419. private static Mesh CreateBoundingBoxMesh(Mesh meshIn)
  420. {
  421. float minX = float.MaxValue;
  422. float maxX = float.MinValue;
  423. float minY = float.MaxValue;
  424. float maxY = float.MinValue;
  425. float minZ = float.MaxValue;
  426. float maxZ = float.MinValue;
  427. foreach (Vertex v in meshIn.vertices)
  428. {
  429. if (v != null)
  430. {
  431. if (v.X < minX) minX = v.X;
  432. if (v.Y < minY) minY = v.Y;
  433. if (v.Z < minZ) minZ = v.Z;
  434. if (v.X > maxX) maxX = v.X;
  435. if (v.Y > maxY) maxY = v.Y;
  436. if (v.Z > maxZ) maxZ = v.Z;
  437. }
  438. }
  439. return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ);
  440. }
  441. private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  442. // Builds the z (+ and -) surfaces of a box shaped prim
  443. {
  444. UInt16 hollowFactor = primShape.ProfileHollow;
  445. UInt16 profileBegin = primShape.ProfileBegin;
  446. UInt16 profileEnd = primShape.ProfileEnd;
  447. UInt16 taperX = primShape.PathScaleX;
  448. UInt16 taperY = primShape.PathScaleY;
  449. UInt16 pathShearX = primShape.PathShearX;
  450. UInt16 pathShearY = primShape.PathShearY;
  451. // Int16 twistTop = primShape.PathTwistBegin;
  452. // Int16 twistBot = primShape.PathTwist;
  453. #if SPAM
  454. reportPrimParams("[BOX] " + primName, primShape);
  455. #endif
  456. //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
  457. //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
  458. //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
  459. //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
  460. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  461. // of a block are basically the same
  462. // They may be warped differently but the shape is identical
  463. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  464. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  465. // The mapping to Scene space is done later during the "extrusion" phase
  466. // Base
  467. Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
  468. Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
  469. Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
  470. Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
  471. SimpleHull outerHull = new SimpleHull();
  472. //outerHull.AddVertex(MM);
  473. //outerHull.AddVertex(PM);
  474. //outerHull.AddVertex(PP);
  475. //outerHull.AddVertex(MP);
  476. outerHull.AddVertex(PP);
  477. outerHull.AddVertex(MP);
  478. outerHull.AddVertex(MM);
  479. outerHull.AddVertex(PM);
  480. // Deal with cuts now
  481. if ((profileBegin != 0) || (profileEnd != 0))
  482. {
  483. double fProfileBeginAngle = profileBegin/50000.0*360.0;
  484. // In degree, for easier debugging and understanding
  485. fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  486. double fProfileEndAngle = 360.0 - profileEnd/50000.0*360.0; // Pathend comes as complement to 1.0
  487. fProfileEndAngle -= (90.0 + 45.0);
  488. // avoid some problem angles until the hull subtraction routine is fixed
  489. if ((fProfileBeginAngle + 45.0f) % 90.0f == 0.0f)
  490. fProfileBeginAngle += 5.0f;
  491. if ((fProfileEndAngle + 45.0f) % 90.0f == 0.0f)
  492. fProfileEndAngle -= 5.0f;
  493. if (fProfileBeginAngle % 90.0f == 0.0f)
  494. fProfileBeginAngle += 1.0f;
  495. if (fProfileEndAngle % 90.0f == 0.0f)
  496. fProfileEndAngle -= 1.0f;
  497. if (fProfileBeginAngle < fProfileEndAngle)
  498. fProfileEndAngle -= 360.0;
  499. #if SPAM
  500. Console.WriteLine("Meshmerizer: fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString());
  501. #endif
  502. // Note, that we don't want to cut out a triangle, even if this is a
  503. // good approximation for small cuts. Indeed we want to cut out an arc
  504. // and we approximate this arc by a polygon chain
  505. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  506. // So it can easily be subtracted from the outer hull
  507. int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5);
  508. // how many steps do we need with approximately 45 degree
  509. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps;
  510. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  511. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  512. SimpleHull cutHull = new SimpleHull();
  513. cutHull.AddVertex(origin);
  514. for (int i = 0; i < iSteps; i++)
  515. {
  516. double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!!
  517. Vertex v = Vertex.FromAngle(angle*Math.PI/180.0);
  518. cutHull.AddVertex(v);
  519. }
  520. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0);
  521. // Calculated separately to avoid errors
  522. cutHull.AddVertex(legEnd);
  523. //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  524. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  525. outerHull = cuttedHull;
  526. }
  527. // Deal with the hole here
  528. if (hollowFactor > 0)
  529. {
  530. if (hollowFactor < 1000)
  531. hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines
  532. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  533. if (holeHull != null)
  534. {
  535. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  536. outerHull = hollowedHull;
  537. }
  538. }
  539. Mesh m = new Mesh();
  540. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  541. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  542. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  543. m.Add(Seed1);
  544. m.Add(Seed2);
  545. m.Add(Seed3);
  546. m.Add(new Triangle(Seed1, Seed2, Seed3));
  547. m.Add(outerHull.getVertices());
  548. InsertVertices(m.vertices, 3, m.triangles);
  549. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  550. m.Remove(Seed1);
  551. m.Remove(Seed2);
  552. m.Remove(Seed3);
  553. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  554. m.RemoveTrianglesOutside(outerHull);
  555. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  556. foreach (Triangle t in m.triangles)
  557. {
  558. PhysicsVector n = t.getNormal();
  559. if (n.Z < 0.0)
  560. t.invertNormal();
  561. }
  562. Extruder extr = new Extruder();
  563. extr.size = size;
  564. if (taperX != 100)
  565. {
  566. if (taperX > 100)
  567. {
  568. extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100);
  569. //System.Console.WriteLine("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  570. }
  571. else
  572. {
  573. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  574. //System.Console.WriteLine("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  575. }
  576. }
  577. if (taperY != 100)
  578. {
  579. if (taperY > 100)
  580. {
  581. extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100);
  582. //System.Console.WriteLine("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  583. }
  584. else
  585. {
  586. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  587. //System.Console.WriteLine("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  588. }
  589. }
  590. if (pathShearX != 0)
  591. {
  592. //System.Console.WriteLine("pushX: " + pathShearX.ToString());
  593. if (pathShearX > 50)
  594. {
  595. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  596. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  597. //System.Console.WriteLine("pushX: " + extr.pushX);
  598. }
  599. else
  600. {
  601. extr.pushX = (float)pathShearX / 100;
  602. //System.Console.WriteLine("pushX: " + extr.pushX);
  603. }
  604. }
  605. if (pathShearY != 0)
  606. {
  607. if (pathShearY > 50)
  608. {
  609. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  610. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  611. //System.Console.WriteLine("pushY: " + extr.pushY);
  612. }
  613. else
  614. {
  615. extr.pushY = (float)pathShearY / 100;
  616. //System.Console.WriteLine("pushY: " + extr.pushY);
  617. }
  618. }
  619. //if (twistTop != 0)
  620. //{
  621. // extr.twistTop = 180 * ((float)twistTop / 100);
  622. // if (extr.twistTop > 0)
  623. // {
  624. // extr.twistTop = 360 - (-1 * extr.twistTop);
  625. // }
  626. // extr.twistTop = (float)(extr.twistTop * DEG_TO_RAD);
  627. //}
  628. //float twistMid = ((twistTop + twistBot) * 0.5f);
  629. //if (twistMid != 0)
  630. //{
  631. // extr.twistMid = 180 * ((float)twistMid / 100);
  632. // if (extr.twistMid > 0)
  633. // {
  634. // extr.twistMid = 360 - (-1 * extr.twistMid);
  635. // }
  636. // extr.twistMid = (float)(extr.twistMid * DEG_TO_RAD);
  637. //}
  638. //if (twistBot != 0)
  639. //{
  640. // extr.twistBot = 180 * ((float)twistBot / 100);
  641. // if (extr.twistBot > 0)
  642. // {
  643. // extr.twistBot = 360 - (-1 * extr.twistBot);
  644. // }
  645. // extr.twistBot = (float)(extr.twistBot * DEG_TO_RAD);
  646. //}
  647. extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f;
  648. extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f;
  649. extr.pathBegin = primShape.PathBegin;
  650. extr.pathEnd = primShape.PathEnd;
  651. //Mesh result = extr.Extrude(m);
  652. Mesh result = extr.ExtrudeLinearPath(m);
  653. result.DumpRaw(baseDir, primName, "Z extruded");
  654. #if SPAM
  655. int vCount = 0;
  656. foreach (Vertex v in result.vertices)
  657. if (v != null)
  658. vCount++;
  659. System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
  660. #endif
  661. return result;
  662. }
  663. private static Mesh CreateCylinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  664. // Builds the z (+ and -) surfaces of a box shaped prim
  665. {
  666. UInt16 hollowFactor = primShape.ProfileHollow;
  667. UInt16 profileBegin = primShape.ProfileBegin;
  668. UInt16 profileEnd = primShape.ProfileEnd;
  669. UInt16 taperX = primShape.PathScaleX;
  670. UInt16 taperY = primShape.PathScaleY;
  671. UInt16 pathShearX = primShape.PathShearX;
  672. UInt16 pathShearY = primShape.PathShearY;
  673. // Int16 twistBot = primShape.PathTwist;
  674. // Int16 twistTop = primShape.PathTwistBegin;
  675. #if SPAM
  676. reportPrimParams("[CYLINDER] " + primName, primShape);
  677. #endif
  678. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  679. // of a block are basically the same
  680. // They may be warped differently but the shape is identical
  681. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  682. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  683. // The mapping to Scene space is done later during the "extrusion" phase
  684. // Base
  685. // Q1Q15 = Quadrant 1, Quadrant1, Vertex 5
  686. //Vertex Q1Q15 = new Vertex(-0.35f, -0.35f, 0.0f);
  687. //Vertex Q1Q16 = new Vertex(-0.30f, -0.40f, 0.0f);
  688. //Vertex Q1Q17 = new Vertex(-0.24f, -0.43f, 0.0f);
  689. //Vertex Q1Q18 = new Vertex(-0.18f, -0.46f, 0.0f);
  690. //Vertex Q1Q19 = new Vertex(-0.11f, -0.48f, 0.0f);
  691. //Vertex Q2Q10 = new Vertex(+0.0f, -0.50f, 0.0f);
  692. //Vertex Q2Q11 = new Vertex(+0.11f, -0.48f, 0.0f);
  693. //Vertex Q2Q12 = new Vertex(+0.18f, -0.46f, 0.0f);
  694. //Vertex Q2Q13 = new Vertex(+0.24f, -0.43f, 0.0f);
  695. //Vertex Q2Q14 = new Vertex(+0.30f, -0.40f, 0.0f);
  696. //Vertex Q2Q15 = new Vertex(+0.35f, -0.35f, 0.0f);
  697. //Vertex Q2Q16 = new Vertex(+0.40f, -0.30f, 0.0f);
  698. //Vertex Q2Q17 = new Vertex(+0.43f, -0.24f, 0.0f);
  699. //Vertex Q2Q18 = new Vertex(+0.46f, -0.18f, 0.0f);
  700. //Vertex Q2Q19 = new Vertex(+0.48f, -0.11f, 0.0f);
  701. //Vertex Q2Q20 = new Vertex(+0.50f, +0.0f, 0.0f);
  702. //Vertex Q2Q21 = new Vertex(+0.48f, +0.11f, 0.0f);
  703. //Vertex Q2Q22 = new Vertex(+0.46f, +0.18f, 0.0f);
  704. //Vertex Q2Q23 = new Vertex(+0.43f, +0.24f, 0.0f);
  705. //Vertex Q2Q24 = new Vertex(+0.40f, +0.30f, 0.0f);
  706. //Vertex Q2Q25 = new Vertex(+0.35f, +0.35f, 0.0f);
  707. //Vertex Q2Q26 = new Vertex(+0.30f, +0.40f, 0.0f);
  708. //Vertex Q2Q27 = new Vertex(+0.24f, +0.43f, 0.0f);
  709. //Vertex Q2Q28 = new Vertex(+0.18f, +0.46f, 0.0f);
  710. //Vertex Q2Q29 = new Vertex(+0.11f, +0.48f, 0.0f);
  711. //Vertex Q1Q20 = new Vertex(+0.0f, +0.50f, 0.0f);
  712. //Vertex Q1Q21 = new Vertex(-0.11f, +0.48f, 0.0f);
  713. //Vertex Q1Q22 = new Vertex(-0.18f, +0.46f, 0.0f);
  714. //Vertex Q1Q23 = new Vertex(-0.24f, +0.43f, 0.0f);
  715. //Vertex Q1Q24 = new Vertex(-0.30f, +0.40f, 0.0f);
  716. //Vertex Q1Q25 = new Vertex(-0.35f, +0.35f, 0.0f);
  717. //Vertex Q1Q26 = new Vertex(-0.40f, +0.30f, 0.0f);
  718. //Vertex Q1Q27 = new Vertex(-0.43f, +0.24f, 0.0f);
  719. //Vertex Q1Q28 = new Vertex(-0.46f, +0.18f, 0.0f);
  720. //Vertex Q1Q29 = new Vertex(-0.48f, +0.11f, 0.0f);
  721. //Vertex Q1Q10 = new Vertex(-0.50f, +0.0f, 0.0f);
  722. //Vertex Q1Q11 = new Vertex(-0.48f, -0.11f, 0.0f);
  723. //Vertex Q1Q12 = new Vertex(-0.46f, -0.18f, 0.0f);
  724. //Vertex Q1Q13 = new Vertex(-0.43f, -0.24f, 0.0f);
  725. //Vertex Q1Q14 = new Vertex(-0.40f, -0.30f, 0.0f);
  726. SimpleHull outerHull = new SimpleHull();
  727. //Clockwise around the quadrants
  728. //outerHull.AddVertex(Q1Q15);
  729. //outerHull.AddVertex(Q1Q16);
  730. //outerHull.AddVertex(Q1Q17);
  731. //outerHull.AddVertex(Q1Q18);
  732. //outerHull.AddVertex(Q1Q19);
  733. //outerHull.AddVertex(Q2Q10);
  734. //outerHull.AddVertex(Q2Q11);
  735. //outerHull.AddVertex(Q2Q12);
  736. //outerHull.AddVertex(Q2Q13);
  737. //outerHull.AddVertex(Q2Q14);
  738. //outerHull.AddVertex(Q2Q15);
  739. //outerHull.AddVertex(Q2Q16);
  740. //outerHull.AddVertex(Q2Q17);
  741. //outerHull.AddVertex(Q2Q18);
  742. //outerHull.AddVertex(Q2Q19);
  743. //outerHull.AddVertex(Q2Q20);
  744. //outerHull.AddVertex(Q2Q21);
  745. //outerHull.AddVertex(Q2Q22);
  746. //outerHull.AddVertex(Q2Q23);
  747. //outerHull.AddVertex(Q2Q24);
  748. //outerHull.AddVertex(Q2Q25);
  749. //outerHull.AddVertex(Q2Q26);
  750. //outerHull.AddVertex(Q2Q27);
  751. //outerHull.AddVertex(Q2Q28);
  752. //outerHull.AddVertex(Q2Q29);
  753. //outerHull.AddVertex(Q1Q20);
  754. //outerHull.AddVertex(Q1Q21);
  755. //outerHull.AddVertex(Q1Q22);
  756. //outerHull.AddVertex(Q1Q23);
  757. //outerHull.AddVertex(Q1Q24);
  758. //outerHull.AddVertex(Q1Q25);
  759. //outerHull.AddVertex(Q1Q26);
  760. //outerHull.AddVertex(Q1Q27);
  761. //outerHull.AddVertex(Q1Q28);
  762. //outerHull.AddVertex(Q1Q29);
  763. //outerHull.AddVertex(Q1Q10);
  764. //outerHull.AddVertex(Q1Q11);
  765. //outerHull.AddVertex(Q1Q12);
  766. //outerHull.AddVertex(Q1Q13);
  767. //outerHull.AddVertex(Q1Q14);
  768. // counter-clockwise around the quadrants, start at 45 degrees
  769. outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees
  770. outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees
  771. outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees
  772. outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees
  773. outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees
  774. outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees
  775. outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees
  776. outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees
  777. outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees
  778. outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees
  779. outerHull.AddVertex(new Vertex(-0.482963f, -0.129410f, 0.0f)); // 195 degrees
  780. outerHull.AddVertex(new Vertex(-0.433013f, -0.250000f, 0.0f)); // 210 degrees
  781. outerHull.AddVertex(new Vertex(-0.353553f, -0.353553f, 0.0f)); // 225 degrees
  782. outerHull.AddVertex(new Vertex(-0.250000f, -0.433013f, 0.0f)); // 240 degrees
  783. outerHull.AddVertex(new Vertex(-0.129410f, -0.482963f, 0.0f)); // 255 degrees
  784. outerHull.AddVertex(new Vertex(0.000000f, -0.500000f, 0.0f)); // 270 degrees
  785. outerHull.AddVertex(new Vertex(0.129410f, -0.482963f, 0.0f)); // 285 degrees
  786. outerHull.AddVertex(new Vertex(0.250000f, -0.433013f, 0.0f)); // 300 degrees
  787. outerHull.AddVertex(new Vertex(0.353553f, -0.353553f, 0.0f)); // 315 degrees
  788. outerHull.AddVertex(new Vertex(0.433013f, -0.250000f, 0.0f)); // 330 degrees
  789. outerHull.AddVertex(new Vertex(0.482963f, -0.129410f, 0.0f)); // 345 degrees
  790. outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees
  791. outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees
  792. outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees
  793. // Deal with cuts now
  794. if ((profileBegin != 0) || (profileEnd != 0))
  795. {
  796. double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
  797. // In degree, for easier debugging and understanding
  798. //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  799. double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
  800. //fProfileEndAngle -= (90.0 + 45.0);
  801. #if SPAM
  802. Console.WriteLine("Extruder: Cylinder fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString());
  803. #endif
  804. if (fProfileBeginAngle > 270.0f && fProfileBeginAngle < 271.8f) // a problem angle for the hull subtract routine :(
  805. fProfileBeginAngle = 271.8f; // workaround - use the smaller slice
  806. if (fProfileBeginAngle < fProfileEndAngle)
  807. fProfileEndAngle -= 360.0;
  808. #if SPAM
  809. Console.WriteLine("Extruder: Cylinder fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString());
  810. #endif
  811. // Note, that we don't want to cut out a triangle, even if this is a
  812. // good approximation for small cuts. Indeed we want to cut out an arc
  813. // and we approximate this arc by a polygon chain
  814. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  815. // So it can easily be subtracted from the outer hull
  816. int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
  817. // how many steps do we need with approximately 45 degree
  818. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
  819. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  820. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  821. SimpleHull cutHull = new SimpleHull();
  822. cutHull.AddVertex(origin);
  823. for (int i = 0; i < iSteps; i++)
  824. {
  825. double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
  826. Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
  827. cutHull.AddVertex(v);
  828. }
  829. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
  830. // Calculated separately to avoid errors
  831. cutHull.AddVertex(legEnd);
  832. // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  833. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  834. outerHull = cuttedHull;
  835. }
  836. // Deal with the hole here
  837. if (hollowFactor > 0)
  838. {
  839. if (hollowFactor < 1000)
  840. hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines
  841. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  842. if (holeHull != null)
  843. {
  844. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  845. outerHull = hollowedHull;
  846. }
  847. }
  848. Mesh m = new Mesh();
  849. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  850. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  851. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  852. m.Add(Seed1);
  853. m.Add(Seed2);
  854. m.Add(Seed3);
  855. m.Add(new Triangle(Seed1, Seed2, Seed3));
  856. m.Add(outerHull.getVertices());
  857. InsertVertices(m.vertices, 3, m.triangles);
  858. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  859. m.Remove(Seed1);
  860. m.Remove(Seed2);
  861. m.Remove(Seed3);
  862. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  863. m.RemoveTrianglesOutside(outerHull);
  864. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  865. foreach (Triangle t in m.triangles)
  866. {
  867. PhysicsVector n = t.getNormal();
  868. if (n.Z < 0.0)
  869. t.invertNormal();
  870. }
  871. Extruder extr = new Extruder();
  872. extr.size = size;
  873. //System.Console.WriteLine("taperFactorX: " + taperX.ToString());
  874. //System.Console.WriteLine("taperFactorY: " + taperY.ToString());
  875. if (taperX != 100)
  876. {
  877. if (taperX > 100)
  878. {
  879. extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100);
  880. //System.Console.WriteLine("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  881. }
  882. else
  883. {
  884. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  885. //System.Console.WriteLine("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  886. }
  887. }
  888. if (taperY != 100)
  889. {
  890. if (taperY > 100)
  891. {
  892. extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100);
  893. // System.Console.WriteLine("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  894. }
  895. else
  896. {
  897. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  898. //System.Console.WriteLine("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  899. }
  900. }
  901. if (pathShearX != 0)
  902. {
  903. if (pathShearX > 50)
  904. {
  905. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  906. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  907. //m_log.Warn("pushX: " + extr.pushX);
  908. }
  909. else
  910. {
  911. extr.pushX = (float)pathShearX / 100;
  912. //m_log.Warn("pushX: " + extr.pushX);
  913. }
  914. }
  915. if (pathShearY != 0)
  916. {
  917. if (pathShearY > 50)
  918. {
  919. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  920. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  921. //m_log.Warn("pushY: " + extr.pushY);
  922. }
  923. else
  924. {
  925. extr.pushY = (float)pathShearY / 100;
  926. //m_log.Warn("pushY: " + extr.pushY);
  927. }
  928. }
  929. //if (twistTop != 0)
  930. //{
  931. // extr.twistTop = 180 * ((float)twistTop / 100);
  932. // if (extr.twistTop > 0)
  933. // {
  934. // extr.twistTop = 360 - (-1 * extr.twistTop);
  935. // }
  936. // extr.twistTop = (float)(extr.twistTop * DEG_TO_RAD);
  937. //}
  938. //float twistMid = ((twistTop + twistBot) * 0.5f);
  939. //if (twistMid != 0)
  940. //{
  941. // extr.twistMid = 180 * ((float)twistMid / 100);
  942. // if (extr.twistMid > 0)
  943. // {
  944. // extr.twistMid = 360 - (-1 * extr.twistMid);
  945. // }
  946. // extr.twistMid = (float)(extr.twistMid * DEG_TO_RAD);
  947. //}
  948. //if (twistBot != 0)
  949. //{
  950. // extr.twistBot = 180 * ((float)twistBot / 100);
  951. // if (extr.twistBot > 0)
  952. // {
  953. // extr.twistBot = 360 - (-1 * extr.twistBot);
  954. // }
  955. // extr.twistBot = (float)(extr.twistBot * DEG_TO_RAD);
  956. //}
  957. extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f;
  958. extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f;
  959. extr.pathBegin = primShape.PathBegin;
  960. extr.pathEnd = primShape.PathEnd;
  961. //System.Console.WriteLine("[MESH]: twistTop = " + twistTop.ToString() + "|" + extr.twistTop.ToString() + ", twistMid = " + twistMid.ToString() + "|" + extr.twistMid.ToString() + ", twistbot = " + twistBot.ToString() + "|" + extr.twistBot.ToString());
  962. //Mesh result = extr.Extrude(m);
  963. Mesh result = extr.ExtrudeLinearPath(m);
  964. result.DumpRaw(baseDir, primName, "Z extruded");
  965. #if SPAM
  966. int vCount = 0;
  967. foreach (Vertex v in result.vertices)
  968. if (v != null)
  969. vCount++;
  970. System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
  971. #endif
  972. return result;
  973. }
  974. private static Mesh CreatePrismMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  975. // Builds the z (+ and -) surfaces of a box shaped prim
  976. {
  977. UInt16 hollowFactor = primShape.ProfileHollow;
  978. UInt16 profileBegin = primShape.ProfileBegin;
  979. UInt16 profileEnd = primShape.ProfileEnd;
  980. UInt16 taperX = primShape.PathScaleX;
  981. UInt16 taperY = primShape.PathScaleY;
  982. UInt16 pathShearX = primShape.PathShearX;
  983. UInt16 pathShearY = primShape.PathShearY;
  984. // Int16 twistTop = primShape.PathTwistBegin;
  985. // Int16 twistBot = primShape.PathTwist;
  986. #if SPAM
  987. reportPrimParams("[PRISM] " + primName, primShape);
  988. #endif
  989. //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
  990. //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
  991. //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
  992. //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
  993. // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
  994. // of a block are basically the same
  995. // They may be warped differently but the shape is identical
  996. // So we only create one surface as a model and derive both plus and minus surface of the block from it
  997. // This is done in a model space where the block spans from -.5 to +.5 in X and Y
  998. // The mapping to Scene space is done later during the "extrusion" phase
  999. // Base
  1000. Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
  1001. Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
  1002. Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
  1003. SimpleHull outerHull = new SimpleHull();
  1004. //outerHull.AddVertex(MM);
  1005. //outerHull.AddVertex(PM);
  1006. //outerHull.AddVertex(PP);
  1007. outerHull.AddVertex(PP);
  1008. outerHull.AddVertex(MM);
  1009. outerHull.AddVertex(PM);
  1010. // Deal with cuts now
  1011. if ((profileBegin != 0) || (profileEnd != 0))
  1012. {
  1013. double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
  1014. // In degree, for easier debugging and understanding
  1015. //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  1016. double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
  1017. //fProfileEndAngle -= (90.0 + 45.0);
  1018. if (fProfileBeginAngle < fProfileEndAngle)
  1019. fProfileEndAngle -= 360.0;
  1020. // Note, that we don't want to cut out a triangle, even if this is a
  1021. // good approximation for small cuts. Indeed we want to cut out an arc
  1022. // and we approximate this arc by a polygon chain
  1023. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  1024. // So it can easily be subtracted from the outer hull
  1025. int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
  1026. // how many steps do we need with approximately 45 degree
  1027. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
  1028. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  1029. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  1030. SimpleHull cutHull = new SimpleHull();
  1031. cutHull.AddVertex(origin);
  1032. for (int i = 0; i < iSteps; i++)
  1033. {
  1034. double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
  1035. Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
  1036. cutHull.AddVertex(v);
  1037. }
  1038. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
  1039. // Calculated separately to avoid errors
  1040. cutHull.AddVertex(legEnd);
  1041. //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  1042. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  1043. outerHull = cuttedHull;
  1044. }
  1045. // Deal with the hole here
  1046. if (hollowFactor > 0)
  1047. {
  1048. if (hollowFactor < 1000)
  1049. hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines
  1050. SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
  1051. if (holeHull != null)
  1052. {
  1053. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  1054. outerHull = hollowedHull;
  1055. }
  1056. }
  1057. Mesh m = new Mesh();
  1058. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  1059. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  1060. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  1061. m.Add(Seed1);
  1062. m.Add(Seed2);
  1063. m.Add(Seed3);
  1064. m.Add(new Triangle(Seed1, Seed2, Seed3));
  1065. m.Add(outerHull.getVertices());
  1066. InsertVertices(m.vertices, 3, m.triangles);
  1067. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  1068. m.Remove(Seed1);
  1069. m.Remove(Seed2);
  1070. m.Remove(Seed3);
  1071. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  1072. m.RemoveTrianglesOutside(outerHull);
  1073. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  1074. foreach (Triangle t in m.triangles)
  1075. {
  1076. PhysicsVector n = t.getNormal();
  1077. if (n.Z < 0.0)
  1078. t.invertNormal();
  1079. }
  1080. Extruder extr = new Extruder();
  1081. extr.size = size;
  1082. if (taperX != 100)
  1083. {
  1084. if (taperX > 100)
  1085. {
  1086. extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100);
  1087. //System.Console.WriteLine("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  1088. }
  1089. else
  1090. {
  1091. extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
  1092. //System.Console.WriteLine("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  1093. }
  1094. }
  1095. if (taperY != 100)
  1096. {
  1097. if (taperY > 100)
  1098. {
  1099. extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100);
  1100. // System.Console.WriteLine("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  1101. }
  1102. else
  1103. {
  1104. extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
  1105. //System.Console.WriteLine("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  1106. }
  1107. }
  1108. if (pathShearX != 0)
  1109. {
  1110. if (pathShearX > 50)
  1111. {
  1112. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  1113. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  1114. // m_log.Warn("pushX: " + extr.pushX);
  1115. }
  1116. else
  1117. {
  1118. extr.pushX = (float)pathShearX / 100;
  1119. // m_log.Warn("pushX: " + extr.pushX);
  1120. }
  1121. }
  1122. if (pathShearY != 0)
  1123. {
  1124. if (pathShearY > 50)
  1125. {
  1126. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  1127. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  1128. //m_log.Warn("pushY: " + extr.pushY);
  1129. }
  1130. else
  1131. {
  1132. extr.pushY = (float)pathShearY / 100;
  1133. //m_log.Warn("pushY: " + extr.pushY);
  1134. }
  1135. }
  1136. //if (twistTop != 0)
  1137. //{
  1138. // extr.twistTop = 180 * ((float)twistTop / 100);
  1139. // if (extr.twistTop > 0)
  1140. // {
  1141. // extr.twistTop = 360 - (-1 * extr.twistTop);
  1142. // }
  1143. // extr.twistTop = (float)(extr.twistTop * DEG_TO_RAD);
  1144. //}
  1145. //float twistMid = ((twistTop + twistBot) * 0.5f);
  1146. //if (twistMid != 0)
  1147. //{
  1148. // extr.twistMid = 180 * ((float)twistMid / 100);
  1149. // if (extr.twistMid > 0)
  1150. // {
  1151. // extr.twistMid = 360 - (-1 * extr.twistMid);
  1152. // }
  1153. // extr.twistMid = (float)(extr.twistMid * DEG_TO_RAD);
  1154. //}
  1155. //if (twistBot != 0)
  1156. //{
  1157. // extr.twistBot = 180 * ((float)twistBot / 100);
  1158. // if (extr.twistBot > 0)
  1159. // {
  1160. // extr.twistBot = 360 - (-1 * extr.twistBot);
  1161. // }
  1162. // extr.twistBot = (float)(extr.twistBot * DEG_TO_RAD);
  1163. //}
  1164. extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f;
  1165. extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f;
  1166. extr.pathBegin = primShape.PathBegin;
  1167. extr.pathEnd = primShape.PathEnd;
  1168. //System.Console.WriteLine("[MESH]: twistTop = " + twistTop.ToString() + "|" + extr.twistTop.ToString() + ", twistMid = " + twistMid.ToString() + "|" + extr.twistMid.ToString() + ", twistbot = " + twistBot.ToString() + "|" + extr.twistBot.ToString());
  1169. //Mesh result = extr.Extrude(m);
  1170. Mesh result = extr.ExtrudeLinearPath(m);
  1171. result.DumpRaw(baseDir, primName, "Z extruded");
  1172. #if SPAM
  1173. int vCount = 0;
  1174. foreach (Vertex v in result.vertices)
  1175. if (v != null)
  1176. vCount++;
  1177. System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
  1178. #endif
  1179. return result;
  1180. }
  1181. /// <summary>
  1182. /// builds an icosahedral geodesic sphere - used as default in place of problem meshes
  1183. /// </summary>
  1184. /// <param name="primName"></param>
  1185. /// <param name="primShape"></param>
  1186. /// <param name="size"></param>
  1187. /// <returns></returns>
  1188. private static Mesh CreateSphereMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  1189. {
  1190. // Builds an icosahedral geodesic sphere
  1191. // based on an article by Paul Bourke
  1192. // http://local.wasp.uwa.edu.au/~pbourke/
  1193. // articles:
  1194. // http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonmesh/
  1195. // and
  1196. // http://local.wasp.uwa.edu.au/~pbourke/geometry/polyhedra/index.html
  1197. // Still have more to do here.
  1198. // UInt16 hollowFactor = primShape.ProfileHollow;
  1199. // UInt16 profileBegin = primShape.ProfileBegin;
  1200. // UInt16 profileEnd = primShape.ProfileEnd;
  1201. // UInt16 taperX = primShape.PathScaleX;
  1202. // UInt16 taperY = primShape.PathScaleY;
  1203. // UInt16 pathShearX = primShape.PathShearX;
  1204. // UInt16 pathShearY = primShape.PathShearY;
  1205. Mesh m = new Mesh();
  1206. #if SPAM
  1207. reportPrimParams("[SPHERE] " + primName, primShape);
  1208. #endif
  1209. float LOD = 0.2f;
  1210. float diameter = 0.5f;// Our object will result in -0.5 to 0.5
  1211. float sq5 = (float) Math.Sqrt(5.0);
  1212. float phi = (1 + sq5) * 0.5f;
  1213. float rat = (float) Math.Sqrt(10f + (2f * sq5)) / (4f * phi);
  1214. float a = (diameter / rat) * 0.5f;
  1215. float b = (diameter / rat) / (2.0f * phi);
  1216. // 12 Icosahedron vertexes
  1217. Vertex v1 = new Vertex(0f, b, -a);
  1218. Vertex v2 = new Vertex(b, a, 0f);
  1219. Vertex v3 = new Vertex(-b, a, 0f);
  1220. Vertex v4 = new Vertex(0f, b, a);
  1221. Vertex v5 = new Vertex(0f, -b, a);
  1222. Vertex v6 = new Vertex(-a, 0f, b);
  1223. Vertex v7 = new Vertex(0f, -b, -a);
  1224. Vertex v8 = new Vertex(a, 0f, -b);
  1225. Vertex v9 = new Vertex(a, 0f, b);
  1226. Vertex v10 = new Vertex(-a, 0f, -b);
  1227. Vertex v11 = new Vertex(b, -a, 0);
  1228. Vertex v12 = new Vertex(-b, -a, 0);
  1229. // Base Faces of the Icosahedron (20)
  1230. SphereLODTriangle(v1, v2, v3, diameter, LOD, m);
  1231. SphereLODTriangle(v4, v3, v2, diameter, LOD, m);
  1232. SphereLODTriangle(v4, v5, v6, diameter, LOD, m);
  1233. SphereLODTriangle(v4, v9, v5, diameter, LOD, m);
  1234. SphereLODTriangle(v1, v7, v8, diameter, LOD, m);
  1235. SphereLODTriangle(v1, v10, v7, diameter, LOD, m);
  1236. SphereLODTriangle(v5, v11, v12, diameter, LOD, m);
  1237. SphereLODTriangle(v7, v12, v11, diameter, LOD, m);
  1238. SphereLODTriangle(v3, v6, v10, diameter, LOD, m);
  1239. SphereLODTriangle(v12, v10, v6, diameter, LOD, m);
  1240. SphereLODTriangle(v2, v8, v9, diameter, LOD, m);
  1241. SphereLODTriangle(v11, v9, v8, diameter, LOD, m);
  1242. SphereLODTriangle(v4, v6, v3, diameter, LOD, m);
  1243. SphereLODTriangle(v4, v2, v9, diameter, LOD, m);
  1244. SphereLODTriangle(v1, v3, v10, diameter, LOD, m);
  1245. SphereLODTriangle(v1, v8, v2, diameter, LOD, m);
  1246. SphereLODTriangle(v7, v10, v12, diameter, LOD, m);
  1247. SphereLODTriangle(v7, v11, v8, diameter, LOD, m);
  1248. SphereLODTriangle(v5, v12, v6, diameter, LOD, m);
  1249. SphereLODTriangle(v5, v9, v11, diameter, LOD, m);
  1250. // Scale the mesh based on our prim scale
  1251. foreach (Vertex v in m.vertices)
  1252. {
  1253. v.X *= size.X;
  1254. v.Y *= size.Y;
  1255. v.Z *= size.Z;
  1256. }
  1257. // This was built with the normals pointing inside..
  1258. // therefore we have to invert the normals
  1259. foreach (Triangle t in m.triangles)
  1260. {
  1261. t.invertNormal();
  1262. }
  1263. // Dump the faces for visualization in blender.
  1264. m.DumpRaw(baseDir, primName, "Icosahedron");
  1265. #if SPAM
  1266. int vCount = 0;
  1267. foreach (Vertex v in m.vertices)
  1268. if (v != null)
  1269. vCount++;
  1270. System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
  1271. #endif
  1272. return m;
  1273. }
  1274. private SculptMesh CreateSculptMesh(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod)
  1275. {
  1276. #if SPAM
  1277. reportPrimParams("[SCULPT] " + primName, primShape);
  1278. #endif
  1279. SculptMesh sm = new SculptMesh(primShape.SculptData, lod);
  1280. // Scale the mesh based on our prim scale
  1281. foreach (Vertex v in sm.vertices)
  1282. {
  1283. v.X *= 0.5f;
  1284. v.Y *= 0.5f;
  1285. v.Z *= 0.5f;
  1286. v.X *= size.X;
  1287. v.Y *= size.Y;
  1288. v.Z *= size.Z;
  1289. }
  1290. // This was built with the normals pointing inside..
  1291. // therefore we have to invert the normals
  1292. foreach (Triangle t in sm.triangles)
  1293. {
  1294. t.invertNormal();
  1295. }
  1296. sm.DumpRaw(baseDir, primName, "Sculpt");
  1297. return sm;
  1298. }
  1299. /// <summary>
  1300. /// Creates a mesh for prim types torus, ring, tube, and sphere
  1301. /// </summary>
  1302. /// <param name="primName"></param>
  1303. /// <param name="primShape"></param>
  1304. /// <param name="size"></param>
  1305. /// <returns></returns>
  1306. private static Mesh CreateCircularPathMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
  1307. {
  1308. UInt16 hollowFactor = primShape.ProfileHollow;
  1309. UInt16 profileBegin = primShape.ProfileBegin;
  1310. UInt16 profileEnd = primShape.ProfileEnd;
  1311. // UInt16 taperX = primShape.PathScaleX;
  1312. // UInt16 taperY = primShape.PathScaleY;
  1313. UInt16 pathShearX = primShape.PathShearX;
  1314. UInt16 pathShearY = primShape.PathShearY;
  1315. // Int16 twistBot = primShape.PathTwist;
  1316. // Int16 twistTop = primShape.PathTwistBegin;
  1317. HollowShape hollowShape = primShape.HollowShape;
  1318. #if SPAM
  1319. reportPrimParams("[CIRCULAR PATH PRIM] " + primName, primShape);
  1320. Console.WriteLine("pathTwist: " + primShape.PathTwist.ToString() + " pathTwistBegin: " + primShape.PathTwistBegin.ToString());
  1321. Console.WriteLine("primShape.ProfileCurve & 0x07: " + Convert.ToString(primShape.ProfileCurve & 0x07));
  1322. #endif
  1323. SimpleHull outerHull = new SimpleHull();
  1324. if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
  1325. {
  1326. #if SPAM
  1327. Console.WriteLine("Meshmerizer thinks " + primName + " is a TORUS");
  1328. #endif
  1329. if (hollowShape == HollowShape.Same)
  1330. hollowShape = HollowShape.Circle;
  1331. // build the profile shape
  1332. // counter-clockwise around the quadrants, start at 45 degrees
  1333. outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees
  1334. outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees
  1335. outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees
  1336. outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees
  1337. outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees
  1338. outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees
  1339. outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees
  1340. outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees
  1341. outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees
  1342. outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees
  1343. outerHull.AddVertex(new Vertex(-0.482963f, -0.129410f, 0.0f)); // 195 degrees
  1344. outerHull.AddVertex(new Vertex(-0.433013f, -0.250000f, 0.0f)); // 210 degrees
  1345. outerHull.AddVertex(new Vertex(-0.353553f, -0.353553f, 0.0f)); // 225 degrees
  1346. outerHull.AddVertex(new Vertex(-0.250000f, -0.433013f, 0.0f)); // 240 degrees
  1347. outerHull.AddVertex(new Vertex(-0.129410f, -0.482963f, 0.0f)); // 255 degrees
  1348. outerHull.AddVertex(new Vertex(0.000000f, -0.500000f, 0.0f)); // 270 degrees
  1349. outerHull.AddVertex(new Vertex(0.129410f, -0.482963f, 0.0f)); // 285 degrees
  1350. outerHull.AddVertex(new Vertex(0.250000f, -0.433013f, 0.0f)); // 300 degrees
  1351. outerHull.AddVertex(new Vertex(0.353553f, -0.353553f, 0.0f)); // 315 degrees
  1352. outerHull.AddVertex(new Vertex(0.433013f, -0.250000f, 0.0f)); // 330 degrees
  1353. outerHull.AddVertex(new Vertex(0.482963f, -0.129410f, 0.0f)); // 345 degrees
  1354. outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees
  1355. outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees
  1356. outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees
  1357. }
  1358. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) // a ring
  1359. {
  1360. #if SPAM
  1361. Console.WriteLine("Meshmerizer thinks " + primName + " is a TUBE");
  1362. #endif
  1363. if (hollowShape == HollowShape.Same)
  1364. hollowShape = HollowShape.Square;
  1365. outerHull.AddVertex(new Vertex(+0.5f, +0.5f, 0.0f));
  1366. outerHull.AddVertex(new Vertex(-0.5f, +0.5f, 0.0f));
  1367. outerHull.AddVertex(new Vertex(-0.5f, -0.5f, 0.0f));
  1368. outerHull.AddVertex(new Vertex(+0.5f, -0.5f, 0.0f));
  1369. }
  1370. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
  1371. {
  1372. #if SPAM
  1373. Console.WriteLine("Meshmerizer thinks " + primName + " is a RING");
  1374. #endif
  1375. if (hollowShape == HollowShape.Same)
  1376. hollowShape = HollowShape.Triangle;
  1377. outerHull.AddVertex(new Vertex(+0.255f, -0.375f, 0.0f));
  1378. outerHull.AddVertex(new Vertex(+0.25f, +0.375f, 0.0f));
  1379. outerHull.AddVertex(new Vertex(-0.5f, +0.0f, 0.0f));
  1380. }
  1381. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  1382. {
  1383. #if SPAM
  1384. Console.WriteLine("Meshmerizer thinks " + primName + " is a SPHERE");
  1385. #endif
  1386. // sanity check here... some spheres have inverted normals which can trap avatars
  1387. // so for now if the shape parameters are such that this may happen, revert to the
  1388. // geodesic sphere mesh.. the threshold is arbitrary as it seems any twist on a sphere
  1389. // will create some inverted normals
  1390. if (
  1391. (System.Math.Abs(primShape.PathTwist - primShape.PathTwistBegin) > 65)
  1392. || (primShape.PathBegin == 0
  1393. && primShape.PathEnd == 0
  1394. && primShape.PathTwist == 0
  1395. && primShape.PathTwistBegin == 0
  1396. && primShape.ProfileBegin == 0
  1397. && primShape.ProfileEnd == 0
  1398. && hollowFactor == 0
  1399. ) // simple sphere, revert to geodesic shape
  1400. )
  1401. {
  1402. #if SPAM
  1403. System.Console.WriteLine("reverting to geodesic sphere for prim: " + primName);
  1404. #endif
  1405. return CreateSphereMesh(primName, primShape, size);
  1406. }
  1407. if (hollowFactor == 0)
  1408. {
  1409. // the hull triangulator is happier with a minimal hollow
  1410. hollowFactor = 2000;
  1411. }
  1412. if (hollowShape == HollowShape.Same)
  1413. hollowShape = HollowShape.Circle;
  1414. outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees
  1415. outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees
  1416. outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees
  1417. outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees
  1418. outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees
  1419. outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees
  1420. outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees
  1421. outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees
  1422. outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees
  1423. outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees
  1424. outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees
  1425. outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees
  1426. outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees
  1427. }
  1428. // Deal with cuts now
  1429. if ((profileBegin != 0) || (profileEnd != 0))
  1430. {
  1431. double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
  1432. // In degree, for easier debugging and understanding
  1433. //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
  1434. double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
  1435. //fProfileEndAngle -= (90.0 + 45.0);
  1436. if (fProfileBeginAngle < fProfileEndAngle)
  1437. fProfileEndAngle -= 360.0;
  1438. if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  1439. { // dimpled sphere uses profile cut but since it's a half circle the angles are smaller
  1440. fProfileBeginAngle = 0.0036f * (float)primShape.ProfileBegin;
  1441. fProfileEndAngle = 180.0f - 0.0036f * (float)primShape.ProfileEnd;
  1442. if (fProfileBeginAngle < fProfileEndAngle)
  1443. fProfileEndAngle -= 360.0f;
  1444. // a cut starting at 0 degrees with a hollow causes an infinite loop so move the start angle
  1445. // past it into the empty part of the circle to avoid this condition
  1446. if (fProfileBeginAngle == 0.0f) fProfileBeginAngle = -10.0f;
  1447. #if SPAM
  1448. Console.WriteLine("Sphere dimple: fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString());
  1449. #endif
  1450. }
  1451. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
  1452. { // tube profile cut is offset 45 degrees from other prim types
  1453. fProfileBeginAngle += 45.0f;
  1454. fProfileEndAngle += 45.0f;
  1455. if (fProfileBeginAngle < fProfileEndAngle)
  1456. fProfileEndAngle -= 360.0;
  1457. }
  1458. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
  1459. { // ring profile cut is offset 180 degrees from other prim types
  1460. fProfileBeginAngle += 180.0f;
  1461. fProfileEndAngle += 180.0f;
  1462. if (fProfileBeginAngle < fProfileEndAngle)
  1463. fProfileEndAngle -= 360.0;
  1464. }
  1465. // Note, that we don't want to cut out a triangle, even if this is a
  1466. // good approximation for small cuts. Indeed we want to cut out an arc
  1467. // and we approximate this arc by a polygon chain
  1468. // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
  1469. // So it can easily be subtracted from the outer hull
  1470. int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
  1471. // how many steps do we need with approximately 45 degree
  1472. double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
  1473. Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
  1474. // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
  1475. SimpleHull cutHull = new SimpleHull();
  1476. cutHull.AddVertex(origin);
  1477. for (int i = 0; i < iSteps; i++)
  1478. {
  1479. double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
  1480. Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
  1481. cutHull.AddVertex(v);
  1482. }
  1483. Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
  1484. // Calculated separately to avoid errors
  1485. cutHull.AddVertex(legEnd);
  1486. // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
  1487. SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
  1488. if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
  1489. {
  1490. Quaternion zFlip = new Quaternion(new Vertex(0.0f, 0.0f, 1.0f), (float)Math.PI);
  1491. Vertex vTmp = new Vertex(0.0f, 0.0f, 0.0f);
  1492. foreach (Vertex v in cuttedHull.getVertices())
  1493. if (v != null)
  1494. {
  1495. vTmp = v * zFlip;
  1496. v.X = vTmp.X;
  1497. v.Y = vTmp.Y;
  1498. v.Z = vTmp.Z;
  1499. }
  1500. }
  1501. outerHull = cuttedHull;
  1502. }
  1503. // Deal with the hole here
  1504. if (hollowFactor > 0)
  1505. {
  1506. SimpleHull holeHull;
  1507. if (hollowShape == HollowShape.Triangle)
  1508. {
  1509. holeHull = new SimpleHull();
  1510. float hollowFactorF = (float)hollowFactor * 2.0e-5f;
  1511. if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
  1512. {
  1513. holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, -0.1875f * hollowFactorF, 0.0f));
  1514. holeHull.AddVertex(new Vertex(-0.25f * hollowFactorF, -0f * hollowFactorF, 0.0f));
  1515. holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, +0.1875f * hollowFactorF, 0.0f));
  1516. }
  1517. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  1518. {
  1519. holeHull.AddVertex(new Vertex(-0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 180 degrees
  1520. holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 120 degrees
  1521. holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 60 degrees
  1522. holeHull.AddVertex(new Vertex(0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 0 degrees
  1523. }
  1524. else
  1525. {
  1526. holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f));
  1527. holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, -0f * hollowFactorF, 0.0f));
  1528. holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f));
  1529. }
  1530. }
  1531. else if (hollowShape == HollowShape.Square && (primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  1532. {
  1533. holeHull = new SimpleHull();
  1534. float hollowFactorF = (float)hollowFactor * 2.0e-5f;
  1535. holeHull.AddVertex(new Vertex(-0.707f * hollowFactorF, 0.0f, 0.0f)); // 180 degrees
  1536. holeHull.AddVertex(new Vertex(0.0f, 0.707f * hollowFactorF, 0.0f)); // 120 degrees
  1537. holeHull.AddVertex(new Vertex(0.707f * hollowFactorF, 0.0f, 0.0f)); // 60 degrees
  1538. }
  1539. else
  1540. {
  1541. holeHull = BuildHoleHull(primShape, primShape.ProfileShape, hollowShape, hollowFactor);
  1542. }
  1543. if (holeHull != null)
  1544. {
  1545. SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
  1546. outerHull = hollowedHull;
  1547. }
  1548. }
  1549. Mesh m = new Mesh();
  1550. Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
  1551. Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
  1552. Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
  1553. m.Add(Seed1);
  1554. m.Add(Seed2);
  1555. m.Add(Seed3);
  1556. m.Add(new Triangle(Seed1, Seed2, Seed3));
  1557. m.Add(outerHull.getVertices());
  1558. InsertVertices(m.vertices, 3, m.triangles);
  1559. m.DumpRaw(baseDir, primName, "Proto first Mesh");
  1560. m.Remove(Seed1);
  1561. m.Remove(Seed2);
  1562. m.Remove(Seed3);
  1563. m.DumpRaw(baseDir, primName, "Proto seeds removed");
  1564. m.RemoveTrianglesOutside(outerHull);
  1565. m.DumpRaw(baseDir, primName, "Proto outsides removed");
  1566. foreach (Triangle t in m.triangles)
  1567. t.invertNormal();
  1568. // Vertex vTemp = new Vertex(0.0f, 0.0f, 0.0f);
  1569. float skew = primShape.PathSkew * 0.01f;
  1570. float pathScaleX = (float)(200 - primShape.PathScaleX) * 0.01f;
  1571. float pathScaleY = (float)(200 - primShape.PathScaleY) * 0.01f;
  1572. float profileXComp = pathScaleX * (1.0f - Math.Abs(skew));
  1573. #if SPAM
  1574. //Console.WriteLine("primShape.PathScaleX: " + primShape.PathScaleX.ToString() + " primShape.PathScaleY: " + primShape.PathScaleY.ToString());
  1575. //Console.WriteLine("primShape.PathSkew: " + primShape.PathSkew.ToString() + " primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString() + " primShape.pathRevolutions: " + primShape.PathRevolutions.ToString());
  1576. Console.WriteLine("PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString());
  1577. Console.WriteLine("skew: " + skew.ToString() + " profileXComp: " + profileXComp.ToString());
  1578. #endif
  1579. foreach (Vertex v in m.vertices)
  1580. if (v != null)
  1581. {
  1582. v.X *= profileXComp;
  1583. v.Y *= pathScaleY;
  1584. //v.Y *= 0.5f; // torus profile is scaled in y axis
  1585. }
  1586. Extruder extr = new Extruder();
  1587. extr.size = size;
  1588. extr.pathScaleX = pathScaleX;
  1589. extr.pathScaleY = pathScaleY;
  1590. extr.pathCutBegin = 0.00002f * primShape.PathBegin;
  1591. extr.pathCutEnd = 0.00002f * (50000 - primShape.PathEnd);
  1592. extr.pathBegin = primShape.PathBegin;
  1593. extr.pathEnd = primShape.PathEnd;
  1594. extr.skew = skew;
  1595. extr.revolutions = 1.0f + (float)primShape.PathRevolutions * 3.0f / 200.0f;
  1596. extr.pathTaperX = 0.01f * (float)primShape.PathTaperX;
  1597. extr.pathTaperY = 0.01f * (float)primShape.PathTaperY;
  1598. extr.radius = 0.01f * (float)primShape.PathRadiusOffset;
  1599. #if SPAM
  1600. //System.Console.WriteLine("primShape.PathBegin: " + primShape.PathBegin.ToString() + " primShape.PathEnd: " + primShape.PathEnd.ToString());
  1601. System.Console.WriteLine("extr.pathCutBegin: " + extr.pathCutBegin.ToString() + " extr.pathCutEnd: " + extr.pathCutEnd.ToString());
  1602. System.Console.WriteLine("extr.revolutions: " + extr.revolutions.ToString());
  1603. //System.Console.WriteLine("primShape.PathTaperX: " + primShape.PathTaperX.ToString());
  1604. //System.Console.WriteLine("primShape.PathTaperY: " + primShape.PathTaperY.ToString());
  1605. //System.Console.WriteLine("primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString());
  1606. #endif
  1607. if (pathShearX != 0)
  1608. {
  1609. if (pathShearX > 50)
  1610. {
  1611. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  1612. extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
  1613. //m_log.Warn("pushX: " + extr.pushX);
  1614. }
  1615. else
  1616. {
  1617. extr.pushX = (float)pathShearX / 100;
  1618. //m_log.Warn("pushX: " + extr.pushX);
  1619. }
  1620. }
  1621. if (pathShearY != 0)
  1622. {
  1623. if (pathShearY > 50)
  1624. {
  1625. // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
  1626. extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
  1627. //m_log.Warn("pushY: " + extr.pushY);
  1628. }
  1629. else
  1630. {
  1631. extr.pushY = (float)pathShearY / 100;
  1632. //m_log.Warn("pushY: " + extr.pushY);
  1633. }
  1634. }
  1635. extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.02f;
  1636. extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.02f;
  1637. //System.Console.WriteLine("[MESH]: twistTop = " + twistTop.ToString() + "|" + extr.twistTop.ToString() + ", twistMid = " + twistMid.ToString() + "|" + extr.twistMid.ToString() + ", twistbot = " + twistBot.ToString() + "|" + extr.twistBot.ToString());
  1638. Mesh result = extr.ExtrudeCircularPath(m);
  1639. result.DumpRaw(baseDir, primName, "Z extruded");
  1640. #if SPAM
  1641. int vCount = 0;
  1642. foreach (Vertex v in result.vertices)
  1643. {
  1644. if (v != null)
  1645. vCount++;
  1646. }
  1647. System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
  1648. #endif
  1649. return result;
  1650. }
  1651. public static void CalcNormals(Mesh mesh)
  1652. {
  1653. int iTriangles = mesh.triangles.Count;
  1654. mesh.normals = new float[iTriangles*3];
  1655. int i = 0;
  1656. foreach (Triangle t in mesh.triangles)
  1657. {
  1658. float ux, uy, uz;
  1659. float vx, vy, vz;
  1660. float wx, wy, wz;
  1661. ux = t.v1.X;
  1662. uy = t.v1.Y;
  1663. uz = t.v1.Z;
  1664. vx = t.v2.X;
  1665. vy = t.v2.Y;
  1666. vz = t.v2.Z;
  1667. wx = t.v3.X;
  1668. wy = t.v3.Y;
  1669. wz = t.v3.Z;
  1670. // Vectors for edges
  1671. float e1x, e1y, e1z;
  1672. float e2x, e2y, e2z;
  1673. e1x = ux - vx;
  1674. e1y = uy - vy;
  1675. e1z = uz - vz;
  1676. e2x = ux - wx;
  1677. e2y = uy - wy;
  1678. e2z = uz - wz;
  1679. // Cross product for normal
  1680. float nx, ny, nz;
  1681. nx = e1y*e2z - e1z*e2y;
  1682. ny = e1z*e2x - e1x*e2z;
  1683. nz = e1x*e2y - e1y*e2x;
  1684. // Length
  1685. float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz);
  1686. // Normalized "normal"
  1687. nx /= l;
  1688. ny /= l;
  1689. nz /= l;
  1690. mesh.normals[i] = nx;
  1691. mesh.normals[i + 1] = ny;
  1692. mesh.normals[i + 2] = nz;
  1693. i += 3;
  1694. }
  1695. }
  1696. public static Vertex midUnitRadialPoint(Vertex a, Vertex b, float radius)
  1697. {
  1698. Vertex midpoint = new Vertex(a + b) * 0.5f;
  1699. return (midpoint.normalize() * radius);
  1700. }
  1701. public static void SphereLODTriangle(Vertex a, Vertex b, Vertex c, float diameter, float LOD, Mesh m)
  1702. {
  1703. Vertex aa = a - b;
  1704. Vertex ba = b - c;
  1705. Vertex da = c - a;
  1706. if (((aa.length() < LOD) && (ba.length() < LOD) && (da.length() < LOD)))
  1707. {
  1708. // We don't want duplicate verticies. Duplicates cause the scale algorithm to produce a spikeball
  1709. // spikes are novel, but we want ellipsoids.
  1710. if (!m.vertices.Contains(a))
  1711. m.Add(a);
  1712. if (!m.vertices.Contains(b))
  1713. m.Add(b);
  1714. if (!m.vertices.Contains(c))
  1715. m.Add(c);
  1716. // Add the triangle to the mesh
  1717. Triangle t = new Triangle(a, b, c);
  1718. m.Add(t);
  1719. }
  1720. else
  1721. {
  1722. Vertex ab = midUnitRadialPoint(a, b, diameter);
  1723. Vertex bc = midUnitRadialPoint(b, c, diameter);
  1724. Vertex ca = midUnitRadialPoint(c, a, diameter);
  1725. // Recursive! Splits the triangle up into 4 smaller triangles
  1726. SphereLODTriangle(a, ab, ca, diameter, LOD, m);
  1727. SphereLODTriangle(ab, b, bc, diameter, LOD, m);
  1728. SphereLODTriangle(ca, bc, c, diameter, LOD, m);
  1729. SphereLODTriangle(ab, bc, ca, diameter, LOD, m);
  1730. }
  1731. }
  1732. public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod)
  1733. {
  1734. return CreateMesh(primName, primShape, size, lod, false);
  1735. }
  1736. public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod, bool isPhysical)
  1737. {
  1738. Mesh mesh = null;
  1739. if (primShape.SculptEntry && primShape.SculptType != (byte)0 && primShape.SculptData.Length > 0)
  1740. {
  1741. SculptMesh smesh = CreateSculptMesh(primName, primShape, size, lod);
  1742. mesh = (Mesh)smesh;
  1743. CalcNormals(mesh);
  1744. }
  1745. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
  1746. {
  1747. if (primShape.PathCurve == (byte)LLObject.PathCurve.Line)
  1748. { // its a box
  1749. mesh = CreateBoxMesh(primName, primShape, size);
  1750. CalcNormals(mesh);
  1751. }
  1752. else if (primShape.PathCurve == (byte)LLObject.PathCurve.Circle)
  1753. { // tube
  1754. // do a cylinder for now
  1755. //mesh = CreateCylinderMesh(primName, primShape, size);
  1756. mesh = CreateCircularPathMesh(primName, primShape, size);
  1757. CalcNormals(mesh);
  1758. }
  1759. }
  1760. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
  1761. {
  1762. if (primShape.PathCurve == (byte)Extrusion.Straight)
  1763. {
  1764. mesh = CreateCylinderMesh(primName, primShape, size);
  1765. CalcNormals(mesh);
  1766. }
  1767. // look at LLObject.cs in libsecondlife for how to know the prim type
  1768. // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
  1769. else if (primShape.PathCurve == (byte) Extrusion.Curve1 && LLObject.UnpackPathScale(primShape.PathScaleY) <= 0.75f)
  1770. { // dahlia's favorite, a torus :)
  1771. mesh = CreateCircularPathMesh(primName, primShape, size);
  1772. CalcNormals(mesh);
  1773. }
  1774. }
  1775. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  1776. {
  1777. if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte) Extrusion.Curve2)
  1778. {
  1779. //mesh = CreateSphereMesh(primName, primShape, size);
  1780. mesh = CreateCircularPathMesh(primName, primShape, size);
  1781. CalcNormals(mesh);
  1782. }
  1783. }
  1784. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
  1785. {
  1786. if (primShape.PathCurve == (byte)Extrusion.Straight)
  1787. {
  1788. mesh = CreatePrismMesh(primName, primShape, size);
  1789. CalcNormals(mesh);
  1790. }
  1791. else if (primShape.PathCurve == (byte) Extrusion.Curve1)
  1792. { // a ring - do a cylinder for now
  1793. //mesh = CreateCylinderMesh(primName, primShape, size);
  1794. mesh = CreateCircularPathMesh(primName, primShape, size);
  1795. CalcNormals(mesh);
  1796. }
  1797. }
  1798. else // just do a box
  1799. {
  1800. mesh = CreateBoxMesh(primName, primShape, size);
  1801. CalcNormals(mesh);
  1802. }
  1803. //else
  1804. //{
  1805. // switch (primShape.ProfileShape)
  1806. // {
  1807. // case ProfileShape.Square:
  1808. // mesh = CreateBoxMesh(primName, primShape, size);
  1809. // CalcNormals(mesh);
  1810. // break;
  1811. // case ProfileShape.Circle:
  1812. // if (primShape.PathCurve == (byte)Extrusion.Straight)
  1813. // {
  1814. // mesh = CreateCylinderMesh(primName, primShape, size);
  1815. // CalcNormals(mesh);
  1816. // }
  1817. // // look at LLObject.cs in libsecondlife for how to know the prim type
  1818. // // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
  1819. // else if ((primShape.ProfileCurve & 0x07) == (byte)LLObject.ProfileCurve.Circle && LLObject.UnpackPathScale(primShape.PathScaleY) <= 0.75f)
  1820. // { // dahlia's favorite, a torus :)
  1821. // mesh = CreateCylinderMesh(primName, primShape, size);
  1822. // CalcNormals(mesh);
  1823. // }
  1824. // break;
  1825. // case ProfileShape.HalfCircle:
  1826. // if (primShape.PathCurve == (byte)Extrusion.Curve1)
  1827. // {
  1828. // mesh = CreateSphereMesh(primName, primShape, size);
  1829. // CalcNormals(mesh);
  1830. // }
  1831. // break;
  1832. // case ProfileShape.EquilateralTriangle:
  1833. // mesh = CreatePrismMesh(primName, primShape, size);
  1834. // CalcNormals(mesh);
  1835. // break;
  1836. // default:
  1837. // mesh = CreateBoxMesh(primName, primShape, size);
  1838. // CalcNormals(mesh);
  1839. // //Set default mesh to cube otherwise it'll return
  1840. // // null and crash on the 'setMesh' method in the physics plugins.
  1841. // //mesh = null;
  1842. // break;
  1843. // }
  1844. //}
  1845. if (mesh != null)
  1846. {
  1847. if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh)
  1848. {
  1849. #if SPAM
  1850. Console.WriteLine("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " + minSizeForComplexMesh.ToString() + " - creating simple bounding box" );
  1851. #endif
  1852. mesh = CreateBoundingBoxMesh(mesh);
  1853. mesh.DumpRaw(baseDir, primName, "Z extruded");
  1854. }
  1855. // trim the vertex and triangle lists to free up memory
  1856. mesh.vertices.TrimExcess();
  1857. mesh.triangles.TrimExcess();
  1858. //int vertCount = 0;
  1859. //foreach (Vertex v in mesh.vertices)
  1860. // if (v != null)
  1861. // vertCount++;
  1862. //mesh.vertices.Capacity = vertCount;
  1863. //int triCount = 0;
  1864. //foreach (Triangle t in mesh.triangles)
  1865. // if (t != null)
  1866. // triCount++;
  1867. //mesh.triangles.Capacity = triCount;
  1868. }
  1869. return mesh;
  1870. }
  1871. #if SPAM
  1872. // please dont comment this out until I'm done with this module - dahlia
  1873. private static void reportPrimParams(string name, PrimitiveBaseShape primShape)
  1874. {
  1875. float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
  1876. float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
  1877. float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
  1878. float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
  1879. float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
  1880. float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
  1881. Console.WriteLine("********************* PrimitiveBaseShape Parameters *******************\n"
  1882. + "Name.............: " + name.ToString() + "\n"
  1883. + "HollowShape......: " + primShape.HollowShape.ToString() + "\n"
  1884. + "PathBegin........: " + primShape.PathBegin.ToString() + " " + pathBegin.ToString() + "\n"
  1885. + "PathCurve........: " + primShape.PathCurve.ToString() + "\n"
  1886. + "PathEnd..........: " + primShape.PathEnd.ToString() + " " + pathEnd.ToString() + "\n"
  1887. + "PathRadiusOffset.: " + primShape.PathRadiusOffset.ToString() + "\n"
  1888. + "PathRevolutions..: " + primShape.PathRevolutions.ToString() + "\n"
  1889. + "PathScaleX.......: " + primShape.PathScaleX.ToString() + "\n"
  1890. + "PathScaleY.......: " + primShape.PathScaleY.ToString() + "\n"
  1891. + "PathShearX.......: " + primShape.PathShearX.ToString() + " (" + pathShearX.ToString() + ")\n"
  1892. + "PathShearY.......: " + primShape.PathShearY.ToString() + " (" + pathShearY.ToString() + ")\n"
  1893. + "PathSkew.........: " + primShape.PathSkew.ToString() + "\n"
  1894. + "PathTaperX.......: " + primShape.PathTaperX.ToString() + "\n"
  1895. + "PathTaperY.......: " + primShape.PathTaperY.ToString() + "\n"
  1896. + "PathTwist........: " + primShape.PathTwist.ToString() + "\n"
  1897. + "PathTwistBegin...: " + primShape.PathTwistBegin.ToString() + "\n"
  1898. + "ProfileBegin.....: " + primShape.ProfileBegin.ToString() + " " + profileBegin.ToString() + "\n"
  1899. + "ProfileCurve.....: " + primShape.ProfileCurve.ToString() + "\n"
  1900. + "ProfileEnd.......: " + primShape.ProfileEnd.ToString() + " " + profileEnd.ToString() + "\n"
  1901. + "ProfileHollow....: " + primShape.ProfileHollow.ToString() + "\n"
  1902. + "ProfileShape.....: " + primShape.ProfileShape.ToString() + "\n"
  1903. );
  1904. }
  1905. #endif
  1906. }
  1907. }