1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections.Generic;
- using OpenSim.Framework;
- using OpenSim.Framework.Console;
- using OpenSim.Region.Physics.Manager;
- namespace OpenSim.Region.Physics.Meshing
- {
- public class MeshmerizerPlugin : IMeshingPlugin
- {
- public MeshmerizerPlugin()
- {
- }
- public string GetName()
- {
- return "Meshmerizer";
- }
- public IMesher GetMesher()
- {
- return new Meshmerizer();
- }
- }
- public class Meshmerizer : IMesher
- {
- //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
- // Setting baseDir to a path will enable the dumping of raw files
- // raw files can be imported by blender so a visual inspection of the results can be done
- // const string baseDir = "rawFiles";
- private const string baseDir = null; //"rawFiles";
- // TODO: unused
- // private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2,
- // PhysicsVector r2, ref float lambda, ref float mu)
- // {
- // // p1, p2, points on the straight
- // // r1, r2, directional vectors of the straight. Not necessarily of length 1!
- // // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
- // // thus allowing to decide whether an intersection is between two points
- // float r1x = r1.X;
- // float r1y = r1.Y;
- // float r2x = r2.X;
- // float r2y = r2.Y;
- // float denom = r1y*r2x - r1x*r2y;
- // if (denom == 0.0)
- // {
- // lambda = Single.NaN;
- // mu = Single.NaN;
- // return;
- // }
- // float p1x = p1.X;
- // float p1y = p1.Y;
- // float p2x = p2.X;
- // float p2y = p2.Y;
- // lambda = (-p2x*r2y + p1x*r2y + (p2y - p1y)*r2x)/denom;
- // mu = (-p2x*r1y + p1x*r1y + (p2y - p1y)*r1x)/denom;
- // }
- private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
- {
- List<Triangle> influenced = new List<Triangle>();
- foreach (Triangle t in triangles)
- {
- if (t.isInCircle(v.X, v.Y))
- {
- influenced.Add(t);
- }
- }
- return influenced;
- }
- private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
- {
- // This is a variant of the delaunay algorithm
- // each time a new vertex is inserted, all triangles that are influenced by it are deleted
- // and replaced by new ones including the new vertex
- // It is not very time efficient but easy to implement.
- int iCurrentVertex;
- int iMaxVertex = vertices.Count;
- for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
- {
- // Background: A triangle mesh fulfills the delaunay condition if (iff!)
- // each circumlocutory circle (i.e. the circle that touches all three corners)
- // of each triangle is empty of other vertices.
- // Obviously a single (seeding) triangle fulfills this condition.
- // If we now add one vertex, we need to reconstruct all triangles, that
- // do not fulfill this condition with respect to the new triangle
- // Find the triangles that are influenced by the new vertex
- Vertex v = vertices[iCurrentVertex];
- if (v == null)
- continue; // Null is polygon stop marker. Ignore it
- List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v);
- List<Simplex> simplices = new List<Simplex>();
- // Reconstruction phase. First step, dissolve each triangle into it's simplices,
- // i.e. it's "border lines"
- // Goal is to find "inner" borders and delete them, while the hull gets conserved.
- // Inner borders are special in the way that they always come twice, which is how we detect them
- foreach (Triangle t in influencedTriangles)
- {
- List<Simplex> newSimplices = t.GetSimplices();
- simplices.AddRange(newSimplices);
- triangles.Remove(t);
- }
- // Now sort the simplices. That will make identical ones reside side by side in the list
- simplices.Sort();
- // Look for duplicate simplices here.
- // Remember, they are directly side by side in the list right now,
- // So we only check directly neighbours
- int iSimplex;
- List<Simplex> innerSimplices = new List<Simplex>();
- for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
- {
- if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0)
- {
- innerSimplices.Add(simplices[iSimplex - 1]);
- innerSimplices.Add(simplices[iSimplex]);
- }
- }
- foreach (Simplex s in innerSimplices)
- {
- simplices.Remove(s);
- }
- // each simplex still in the list belongs to the hull of the region in question
- // The new vertex (yes, we still deal with verices here :-) ) forms a triangle
- // with each of these simplices. Build the new triangles and add them to the list
- foreach (Simplex s in simplices)
- {
- Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
- if (!t.isDegraded())
- {
- triangles.Add(t);
- }
- }
- }
- }
- private static SimpleHull BuildHoleHull(PrimitiveBaseShape pbs, ProfileShape pshape, HollowShape hshape, UInt16 hollowFactor)
- {
- // Tackle HollowShape.Same
- float fhollowFactor = (float)hollowFactor;
- switch (pshape)
- {
- case ProfileShape.Square:
- if (hshape == HollowShape.Same)
- hshape= HollowShape.Square;
- break;
- case ProfileShape.EquilateralTriangle:
- fhollowFactor = ((float)hollowFactor / 1.9f);
- if (hshape == HollowShape.Same)
- {
- hshape = HollowShape.Triangle;
- }
- break;
- case ProfileShape.Circle:
- if (pbs.PathCurve == (byte)Extrusion.Straight)
- {
- if (hshape == HollowShape.Same)
- {
- hshape = HollowShape.Circle;
- }
- }
- break;
- default:
- if (hshape == HollowShape.Same)
- hshape= HollowShape.Square;
- break;
- }
-
- SimpleHull holeHull = null;
- if (hshape == HollowShape.Square)
- {
- float hollowFactorF = (float)fhollowFactor / (float)50000;
- Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
- Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
- Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
- Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
- holeHull = new SimpleHull();
- holeHull.AddVertex(IMM);
- holeHull.AddVertex(IMP);
- holeHull.AddVertex(IPP);
- holeHull.AddVertex(IPM);
- }
- if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
- {
- float hollowFactorF = (float)fhollowFactor / (float)50000;
- Vertex IQ1Q15 = new Vertex(-0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
- Vertex IQ1Q16 = new Vertex(-0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
- Vertex IQ1Q17 = new Vertex(-0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
- Vertex IQ1Q18 = new Vertex(-0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
- Vertex IQ1Q19 = new Vertex(-0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
- Vertex IQ2Q10 = new Vertex(+0.0f * hollowFactorF, -0.50f * hollowFactorF, 0.0f);
- Vertex IQ2Q11 = new Vertex(+0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
- Vertex IQ2Q12 = new Vertex(+0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
- Vertex IQ2Q13 = new Vertex(+0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
- Vertex IQ2Q14 = new Vertex(+0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
- Vertex IQ2Q15 = new Vertex(+0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
- Vertex IQ2Q16 = new Vertex(+0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
- Vertex IQ2Q17 = new Vertex(+0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
- Vertex IQ2Q18 = new Vertex(+0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
- Vertex IQ2Q19 = new Vertex(+0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
- Vertex IQ2Q20 = new Vertex(+0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
- Vertex IQ2Q21 = new Vertex(+0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
- Vertex IQ2Q22 = new Vertex(+0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
- Vertex IQ2Q23 = new Vertex(+0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
- Vertex IQ2Q24 = new Vertex(+0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
- Vertex IQ2Q25 = new Vertex(+0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
- Vertex IQ2Q26 = new Vertex(+0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
- Vertex IQ2Q27 = new Vertex(+0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
- Vertex IQ2Q28 = new Vertex(+0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
- Vertex IQ2Q29 = new Vertex(+0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
- Vertex IQ1Q20 = new Vertex(+0.0f * hollowFactorF, +0.50f * hollowFactorF, 0.0f);
- Vertex IQ1Q21 = new Vertex(-0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
- Vertex IQ1Q22 = new Vertex(-0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
- Vertex IQ1Q23 = new Vertex(-0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
- Vertex IQ1Q24 = new Vertex(-0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
- Vertex IQ1Q25 = new Vertex(-0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
- Vertex IQ1Q26 = new Vertex(-0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
- Vertex IQ1Q27 = new Vertex(-0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
- Vertex IQ1Q28 = new Vertex(-0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
- Vertex IQ1Q29 = new Vertex(-0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
- Vertex IQ1Q10 = new Vertex(-0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
- Vertex IQ1Q11 = new Vertex(-0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
- Vertex IQ1Q12 = new Vertex(-0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
- Vertex IQ1Q13 = new Vertex(-0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
- Vertex IQ1Q14 = new Vertex(-0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
- //Counter clockwise around the quadrants
- holeHull = new SimpleHull();
- holeHull.AddVertex(IQ1Q15);
- holeHull.AddVertex(IQ1Q14);
- holeHull.AddVertex(IQ1Q13);
- holeHull.AddVertex(IQ1Q12);
- holeHull.AddVertex(IQ1Q11);
- holeHull.AddVertex(IQ1Q10);
- holeHull.AddVertex(IQ1Q29);
- holeHull.AddVertex(IQ1Q28);
- holeHull.AddVertex(IQ1Q27);
- holeHull.AddVertex(IQ1Q26);
- holeHull.AddVertex(IQ1Q25);
- holeHull.AddVertex(IQ1Q24);
- holeHull.AddVertex(IQ1Q23);
- holeHull.AddVertex(IQ1Q22);
- holeHull.AddVertex(IQ1Q21);
- holeHull.AddVertex(IQ1Q20);
- holeHull.AddVertex(IQ2Q29);
- holeHull.AddVertex(IQ2Q28);
- holeHull.AddVertex(IQ2Q27);
- holeHull.AddVertex(IQ2Q26);
- holeHull.AddVertex(IQ2Q25);
- holeHull.AddVertex(IQ2Q24);
- holeHull.AddVertex(IQ2Q23);
- holeHull.AddVertex(IQ2Q22);
- holeHull.AddVertex(IQ2Q21);
- holeHull.AddVertex(IQ2Q20);
- holeHull.AddVertex(IQ2Q19);
- holeHull.AddVertex(IQ2Q18);
- holeHull.AddVertex(IQ2Q17);
- holeHull.AddVertex(IQ2Q16);
- holeHull.AddVertex(IQ2Q15);
- holeHull.AddVertex(IQ2Q14);
- holeHull.AddVertex(IQ2Q13);
- holeHull.AddVertex(IQ2Q12);
- holeHull.AddVertex(IQ2Q11);
- holeHull.AddVertex(IQ2Q10);
- holeHull.AddVertex(IQ1Q19);
- holeHull.AddVertex(IQ1Q18);
- holeHull.AddVertex(IQ1Q17);
- holeHull.AddVertex(IQ1Q16);
- }
- if (hshape == HollowShape.Triangle)
- {
- float hollowFactorF = (float)fhollowFactor / (float)50000;
- Vertex IMM = new Vertex(-0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f);
- Vertex IPM = new Vertex(+0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f);
- Vertex IPP = new Vertex(-0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f);
- holeHull = new SimpleHull();
- holeHull.AddVertex(IMM);
- holeHull.AddVertex(IPP);
- holeHull.AddVertex(IPM);
- }
- return holeHull;
- }
- private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
- // Builds the z (+ and -) surfaces of a box shaped prim
- {
- UInt16 hollowFactor = primShape.ProfileHollow;
- UInt16 profileBegin = primShape.ProfileBegin;
- UInt16 profileEnd = primShape.ProfileEnd;
- UInt16 taperX = primShape.PathScaleX;
- UInt16 taperY = primShape.PathScaleY;
- UInt16 pathShearX = primShape.PathShearX;
- UInt16 pathShearY = primShape.PathShearY;
-
- //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
- //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
- //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
- //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
-
- // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
- // of a block are basically the same
- // They may be warped differently but the shape is identical
- // So we only create one surface as a model and derive both plus and minus surface of the block from it
- // This is done in a model space where the block spans from -.5 to +.5 in X and Y
- // The mapping to Scene space is done later during the "extrusion" phase
- // Base
- Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
- Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
- Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
- Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
- SimpleHull outerHull = new SimpleHull();
- outerHull.AddVertex(MM);
- outerHull.AddVertex(PM);
- outerHull.AddVertex(PP);
- outerHull.AddVertex(MP);
- // Deal with cuts now
- if ((profileBegin != 0) || (profileEnd != 0))
- {
- double fProfileBeginAngle = profileBegin/50000.0*360.0;
- // In degree, for easier debugging and understanding
- fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
- double fProfileEndAngle = 360.0 - profileEnd/50000.0*360.0; // Pathend comes as complement to 1.0
- fProfileEndAngle -= (90.0 + 45.0);
- if (fProfileBeginAngle < fProfileEndAngle)
- fProfileEndAngle -= 360.0;
- // Note, that we don't want to cut out a triangle, even if this is a
- // good approximation for small cuts. Indeed we want to cut out an arc
- // and we approximate this arc by a polygon chain
- // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
- // So it can easily be subtracted from the outer hull
- int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5);
- // how many steps do we need with approximately 45 degree
- double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps;
- Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
- // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
- SimpleHull cutHull = new SimpleHull();
- cutHull.AddVertex(origin);
- for (int i = 0; i < iSteps; i++)
- {
- double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!!
- Vertex v = Vertex.FromAngle(angle*Math.PI/180.0);
- cutHull.AddVertex(v);
- }
- Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0);
- // Calculated separately to avoid errors
- cutHull.AddVertex(legEnd);
- //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
- SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
- outerHull = cuttedHull;
- }
- // Deal with the hole here
- if (hollowFactor > 0)
- {
- SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
- if (holeHull != null)
- {
- SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
- outerHull = hollowedHull;
- }
- }
- Mesh m = new Mesh();
- Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
- Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
- Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
- m.Add(Seed1);
- m.Add(Seed2);
- m.Add(Seed3);
- m.Add(new Triangle(Seed1, Seed2, Seed3));
- m.Add(outerHull.getVertices());
- InsertVertices(m.vertices, 3, m.triangles);
- m.DumpRaw(baseDir, primName, "Proto first Mesh");
- m.Remove(Seed1);
- m.Remove(Seed2);
- m.Remove(Seed3);
- m.DumpRaw(baseDir, primName, "Proto seeds removed");
- m.RemoveTrianglesOutside(outerHull);
- m.DumpRaw(baseDir, primName, "Proto outsides removed");
- foreach (Triangle t in m.triangles)
- {
- PhysicsVector n = t.getNormal();
- if (n.Z < 0.0)
- t.invertNormal();
- }
- Extruder extr = new Extruder();
- extr.size = size;
- if (taperX != 100)
- {
- if (taperX > 100)
- {
- extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
- //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
- }
- else
- {
- extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
- //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
- }
-
- }
- if (taperY != 100)
- {
- if (taperY > 100)
- {
- extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
- //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
- }
- else
- {
- extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
- //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
- }
- }
-
-
- if (pathShearX != 0)
- {
- if (pathShearX > 50) {
- // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
- extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
- // m_log.Warn("pushX: " + extr.pushX);
- }
- else
- {
- extr.pushX = (float)pathShearX / 100;
- // m_log.Warn("pushX: " + extr.pushX);
- }
- }
- if (pathShearY != 0)
- {
- if (pathShearY > 50) {
- // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
- extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
- //m_log.Warn("pushY: " + extr.pushY);
- }
- else
- {
- extr.pushY = (float)pathShearY / 100;
- //m_log.Warn("pushY: " + extr.pushY);
- }
- }
-
- Mesh result = extr.Extrude(m);
- result.DumpRaw(baseDir, primName, "Z extruded");
- return result;
- }
- private static Mesh CreateCyllinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
- // Builds the z (+ and -) surfaces of a box shaped prim
- {
- UInt16 hollowFactor = primShape.ProfileHollow;
- UInt16 profileBegin = primShape.ProfileBegin;
- UInt16 profileEnd = primShape.ProfileEnd;
- UInt16 taperX = primShape.PathScaleX;
- UInt16 taperY = primShape.PathScaleY;
- UInt16 pathShearX = primShape.PathShearX;
- UInt16 pathShearY = primShape.PathShearY;
- // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
- // of a block are basically the same
- // They may be warped differently but the shape is identical
- // So we only create one surface as a model and derive both plus and minus surface of the block from it
- // This is done in a model space where the block spans from -.5 to +.5 in X and Y
- // The mapping to Scene space is done later during the "extrusion" phase
- // Base
- // Q1Q15 = Quadrant 1, Quadrant1, Vertex 5
- Vertex Q1Q15 = new Vertex(-0.35f, -0.35f, 0.0f);
- Vertex Q1Q16 = new Vertex(-0.30f, -0.40f, 0.0f);
- Vertex Q1Q17 = new Vertex(-0.24f, -0.43f, 0.0f);
- Vertex Q1Q18 = new Vertex(-0.18f, -0.46f, 0.0f);
- Vertex Q1Q19 = new Vertex(-0.11f, -0.48f, 0.0f);
- Vertex Q2Q10 = new Vertex(+0.0f, -0.50f, 0.0f);
- Vertex Q2Q11 = new Vertex(+0.11f, -0.48f, 0.0f);
- Vertex Q2Q12 = new Vertex(+0.18f, -0.46f, 0.0f);
- Vertex Q2Q13 = new Vertex(+0.24f, -0.43f, 0.0f);
- Vertex Q2Q14 = new Vertex(+0.30f, -0.40f, 0.0f);
- Vertex Q2Q15 = new Vertex(+0.35f, -0.35f, 0.0f);
- Vertex Q2Q16 = new Vertex(+0.40f, -0.30f, 0.0f);
- Vertex Q2Q17 = new Vertex(+0.43f, -0.24f, 0.0f);
- Vertex Q2Q18 = new Vertex(+0.46f, -0.18f, 0.0f);
- Vertex Q2Q19 = new Vertex(+0.48f, -0.11f, 0.0f);
- Vertex Q2Q20 = new Vertex(+0.50f, +0.0f, 0.0f);
- Vertex Q2Q21 = new Vertex(+0.48f, +0.11f, 0.0f);
- Vertex Q2Q22 = new Vertex(+0.46f, +0.18f, 0.0f);
- Vertex Q2Q23 = new Vertex(+0.43f, +0.24f, 0.0f);
- Vertex Q2Q24 = new Vertex(+0.40f, +0.30f, 0.0f);
- Vertex Q2Q25 = new Vertex(+0.35f, +0.35f, 0.0f);
- Vertex Q2Q26 = new Vertex(+0.30f, +0.40f, 0.0f);
- Vertex Q2Q27 = new Vertex(+0.24f, +0.43f, 0.0f);
- Vertex Q2Q28 = new Vertex(+0.18f, +0.46f, 0.0f);
- Vertex Q2Q29 = new Vertex(+0.11f, +0.48f, 0.0f);
- Vertex Q1Q20 = new Vertex(+0.0f, +0.50f, 0.0f);
- Vertex Q1Q21 = new Vertex(-0.11f, +0.48f, 0.0f);
- Vertex Q1Q22 = new Vertex(-0.18f, +0.46f, 0.0f);
- Vertex Q1Q23 = new Vertex(-0.24f, +0.43f, 0.0f);
- Vertex Q1Q24 = new Vertex(-0.30f, +0.40f, 0.0f);
- Vertex Q1Q25 = new Vertex(-0.35f, +0.35f, 0.0f);
- Vertex Q1Q26 = new Vertex(-0.40f, +0.30f, 0.0f);
- Vertex Q1Q27 = new Vertex(-0.43f, +0.24f, 0.0f);
- Vertex Q1Q28 = new Vertex(-0.46f, +0.18f, 0.0f);
- Vertex Q1Q29 = new Vertex(-0.48f, +0.11f, 0.0f);
- Vertex Q1Q10 = new Vertex(-0.50f, +0.0f, 0.0f);
- Vertex Q1Q11 = new Vertex(-0.48f, -0.11f, 0.0f);
- Vertex Q1Q12 = new Vertex(-0.46f, -0.18f, 0.0f);
- Vertex Q1Q13 = new Vertex(-0.43f, -0.24f, 0.0f);
- Vertex Q1Q14 = new Vertex(-0.40f, -0.30f, 0.0f);
-
- SimpleHull outerHull = new SimpleHull();
- //Clockwise around the quadrants
- outerHull.AddVertex(Q1Q15);
- outerHull.AddVertex(Q1Q16);
- outerHull.AddVertex(Q1Q17);
- outerHull.AddVertex(Q1Q18);
- outerHull.AddVertex(Q1Q19);
- outerHull.AddVertex(Q2Q10);
- outerHull.AddVertex(Q2Q11);
- outerHull.AddVertex(Q2Q12);
- outerHull.AddVertex(Q2Q13);
- outerHull.AddVertex(Q2Q14);
- outerHull.AddVertex(Q2Q15);
- outerHull.AddVertex(Q2Q16);
- outerHull.AddVertex(Q2Q17);
- outerHull.AddVertex(Q2Q18);
- outerHull.AddVertex(Q2Q19);
- outerHull.AddVertex(Q2Q20);
- outerHull.AddVertex(Q2Q21);
- outerHull.AddVertex(Q2Q22);
- outerHull.AddVertex(Q2Q23);
- outerHull.AddVertex(Q2Q24);
- outerHull.AddVertex(Q2Q25);
- outerHull.AddVertex(Q2Q26);
- outerHull.AddVertex(Q2Q27);
- outerHull.AddVertex(Q2Q28);
- outerHull.AddVertex(Q2Q29);
- outerHull.AddVertex(Q1Q20);
- outerHull.AddVertex(Q1Q21);
- outerHull.AddVertex(Q1Q22);
- outerHull.AddVertex(Q1Q23);
- outerHull.AddVertex(Q1Q24);
- outerHull.AddVertex(Q1Q25);
- outerHull.AddVertex(Q1Q26);
- outerHull.AddVertex(Q1Q27);
- outerHull.AddVertex(Q1Q28);
- outerHull.AddVertex(Q1Q29);
- outerHull.AddVertex(Q1Q10);
- outerHull.AddVertex(Q1Q11);
- outerHull.AddVertex(Q1Q12);
- outerHull.AddVertex(Q1Q13);
- outerHull.AddVertex(Q1Q14);
- // Deal with cuts now
- if ((profileBegin != 0) || (profileEnd != 0))
- {
- double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
- // In degree, for easier debugging and understanding
- //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
- double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
- //fProfileEndAngle -= (90.0 + 45.0);
- if (fProfileBeginAngle < fProfileEndAngle)
- fProfileEndAngle -= 360.0;
- // Note, that we don't want to cut out a triangle, even if this is a
- // good approximation for small cuts. Indeed we want to cut out an arc
- // and we approximate this arc by a polygon chain
- // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
- // So it can easily be subtracted from the outer hull
- int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
- // how many steps do we need with approximately 45 degree
- double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
- Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
- // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
- SimpleHull cutHull = new SimpleHull();
- cutHull.AddVertex(origin);
- for (int i = 0; i < iSteps; i++)
- {
- double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
- Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
- cutHull.AddVertex(v);
- }
- Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
- // Calculated separately to avoid errors
- cutHull.AddVertex(legEnd);
- // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
- SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
- outerHull = cuttedHull;
- }
- // Deal with the hole here
- if (hollowFactor > 0)
- {
- SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
- if (holeHull != null)
- {
- SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
- outerHull = hollowedHull;
- }
- }
- Mesh m = new Mesh();
- Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
- Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
- Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
- m.Add(Seed1);
- m.Add(Seed2);
- m.Add(Seed3);
- m.Add(new Triangle(Seed1, Seed2, Seed3));
- m.Add(outerHull.getVertices());
- InsertVertices(m.vertices, 3, m.triangles);
- m.DumpRaw(baseDir, primName, "Proto first Mesh");
- m.Remove(Seed1);
- m.Remove(Seed2);
- m.Remove(Seed3);
- m.DumpRaw(baseDir, primName, "Proto seeds removed");
- m.RemoveTrianglesOutside(outerHull);
- m.DumpRaw(baseDir, primName, "Proto outsides removed");
- foreach (Triangle t in m.triangles)
- {
- PhysicsVector n = t.getNormal();
- if (n.Z < 0.0)
- t.invertNormal();
- }
- Extruder extr = new Extruder();
- extr.size = size;
- if (taperX != 100)
- {
- if (taperX > 100)
- {
- extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
- //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
- }
- else
- {
- extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
- //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
- }
- }
- if (taperY != 100)
- {
- if (taperY > 100)
- {
- extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
- //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
- }
- else
- {
- extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
- //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
- }
- }
- if (pathShearX != 0)
- {
- if (pathShearX > 50)
- {
- // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
- extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
- //m_log.Warn("pushX: " + extr.pushX);
- }
- else
- {
- extr.pushX = (float)pathShearX / 100;
- //m_log.Warn("pushX: " + extr.pushX);
- }
- }
- if (pathShearY != 0)
- {
- if (pathShearY > 50)
- {
- // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
- extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
- //m_log.Warn("pushY: " + extr.pushY);
- }
- else
- {
- extr.pushY = (float)pathShearY / 100;
- //m_log.Warn("pushY: " + extr.pushY);
- }
- }
- Mesh result = extr.Extrude(m);
- result.DumpRaw(baseDir, primName, "Z extruded");
- return result;
- }
- private static Mesh CreatePrismMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
- // Builds the z (+ and -) surfaces of a box shaped prim
- {
- UInt16 hollowFactor = primShape.ProfileHollow;
- UInt16 profileBegin = primShape.ProfileBegin;
- UInt16 profileEnd = primShape.ProfileEnd;
- UInt16 taperX = primShape.PathScaleX;
- UInt16 taperY = primShape.PathScaleY;
- UInt16 pathShearX = primShape.PathShearX;
- UInt16 pathShearY = primShape.PathShearY;
- //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
- //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
- //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
- //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
- // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
- // of a block are basically the same
- // They may be warped differently but the shape is identical
- // So we only create one surface as a model and derive both plus and minus surface of the block from it
- // This is done in a model space where the block spans from -.5 to +.5 in X and Y
- // The mapping to Scene space is done later during the "extrusion" phase
- // Base
- Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
- Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
- Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
-
- SimpleHull outerHull = new SimpleHull();
- outerHull.AddVertex(MM);
- outerHull.AddVertex(PM);
- outerHull.AddVertex(PP);
-
- // Deal with cuts now
- if ((profileBegin != 0) || (profileEnd != 0))
- {
- double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
- // In degree, for easier debugging and understanding
- //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
- double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
- //fProfileEndAngle -= (90.0 + 45.0);
- if (fProfileBeginAngle < fProfileEndAngle)
- fProfileEndAngle -= 360.0;
- // Note, that we don't want to cut out a triangle, even if this is a
- // good approximation for small cuts. Indeed we want to cut out an arc
- // and we approximate this arc by a polygon chain
- // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
- // So it can easily be subtracted from the outer hull
- int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
- // how many steps do we need with approximately 45 degree
- double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
- Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
- // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
- SimpleHull cutHull = new SimpleHull();
- cutHull.AddVertex(origin);
- for (int i = 0; i < iSteps; i++)
- {
- double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
- Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
- cutHull.AddVertex(v);
- }
- Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
- // Calculated separately to avoid errors
- cutHull.AddVertex(legEnd);
- //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
- SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
- outerHull = cuttedHull;
- }
- // Deal with the hole here
- if (hollowFactor > 0)
- {
- SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
- if (holeHull != null)
- {
- SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
- outerHull = hollowedHull;
- }
- }
- Mesh m = new Mesh();
- Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
- Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
- Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
- m.Add(Seed1);
- m.Add(Seed2);
- m.Add(Seed3);
- m.Add(new Triangle(Seed1, Seed2, Seed3));
- m.Add(outerHull.getVertices());
- InsertVertices(m.vertices, 3, m.triangles);
- m.DumpRaw(baseDir, primName, "Proto first Mesh");
- m.Remove(Seed1);
- m.Remove(Seed2);
- m.Remove(Seed3);
- m.DumpRaw(baseDir, primName, "Proto seeds removed");
- m.RemoveTrianglesOutside(outerHull);
- m.DumpRaw(baseDir, primName, "Proto outsides removed");
- foreach (Triangle t in m.triangles)
- {
- PhysicsVector n = t.getNormal();
- if (n.Z < 0.0)
- t.invertNormal();
- }
- Extruder extr = new Extruder();
- extr.size = size;
- if (taperX != 100)
- {
- if (taperX > 100)
- {
- extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
- //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
- }
- else
- {
- extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
- //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
- }
- }
- if (taperY != 100)
- {
- if (taperY > 100)
- {
- extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
- //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
- }
- else
- {
- extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
- //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
- }
- }
- if (pathShearX != 0)
- {
- if (pathShearX > 50)
- {
- // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
- extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
- // m_log.Warn("pushX: " + extr.pushX);
- }
- else
- {
- extr.pushX = (float)pathShearX / 100;
- // m_log.Warn("pushX: " + extr.pushX);
- }
- }
- if (pathShearY != 0)
- {
- if (pathShearY > 50)
- {
- // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
- extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
- //m_log.Warn("pushY: " + extr.pushY);
- }
- else
- {
- extr.pushY = (float)pathShearY / 100;
- //m_log.Warn("pushY: " + extr.pushY);
- }
- }
- Mesh result = extr.Extrude(m);
- result.DumpRaw(baseDir, primName, "Z extruded");
- return result;
- }
- public static void CalcNormals(Mesh mesh)
- {
- int iTriangles = mesh.triangles.Count;
- mesh.normals = new float[iTriangles*3];
- int i = 0;
- foreach (Triangle t in mesh.triangles)
- {
- float ux, uy, uz;
- float vx, vy, vz;
- float wx, wy, wz;
- ux = t.v1.X;
- uy = t.v1.Y;
- uz = t.v1.Z;
- vx = t.v2.X;
- vy = t.v2.Y;
- vz = t.v2.Z;
- wx = t.v3.X;
- wy = t.v3.Y;
- wz = t.v3.Z;
- // Vectors for edges
- float e1x, e1y, e1z;
- float e2x, e2y, e2z;
- e1x = ux - vx;
- e1y = uy - vy;
- e1z = uz - vz;
- e2x = ux - wx;
- e2y = uy - wy;
- e2z = uz - wz;
- // Cross product for normal
- float nx, ny, nz;
- nx = e1y*e2z - e1z*e2y;
- ny = e1z*e2x - e1x*e2z;
- nz = e1x*e2y - e1y*e2x;
- // Length
- float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz);
- // Normalized "normal"
- nx /= l;
- ny /= l;
- nz /= l;
- mesh.normals[i] = nx;
- mesh.normals[i + 1] = ny;
- mesh.normals[i + 2] = nz;
- i += 3;
- }
- }
- public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
- {
- Mesh mesh = null;
- switch (primShape.ProfileShape)
- {
- case ProfileShape.Square:
- mesh = CreateBoxMesh(primName, primShape, size);
- CalcNormals(mesh);
- break;
- case ProfileShape.Circle:
- if (primShape.PathCurve == (byte)Extrusion.Straight)
- {
- mesh = CreateCyllinderMesh(primName, primShape, size);
- CalcNormals(mesh);
- }
- break;
- case ProfileShape.EquilateralTriangle:
- mesh = CreatePrismMesh(primName, primShape, size);
- CalcNormals(mesh);
- break;
- default:
- mesh = CreateBoxMesh(primName, primShape, size);
- CalcNormals(mesh);
- //Set default mesh to cube otherwise it'll return
- // null and crash on the 'setMesh' method in the physics plugins.
- //mesh = null;
- break;
- }
- return mesh;
- }
- }
- }
|