diff --git a/OpenSim/Region/Physics/Meshing/Extruder.cs b/OpenSim/Region/Physics/Meshing/Extruder.cs index c7dcf33a8f..480ffda2e3 100644 --- a/OpenSim/Region/Physics/Meshing/Extruder.cs +++ b/OpenSim/Region/Physics/Meshing/Extruder.cs @@ -47,6 +47,21 @@ namespace OpenSim.Region.Physics.Meshing public float twistTop = 0; public float twistBot = 0; public float twistMid = 0; + public float pathScaleX = 1.0f; + public float pathScaleY = 0.5f; + public float skew = 0.0f; + public float radius = 0.0f; + public float revolutions = 1.0f; + + public float pathCutBegin = 0.0f; + public float pathCutEnd = 1.0f; + + public ushort pathBegin = 0; + public ushort pathEnd = 0; + + public float pathTaperX = 0.0f; + public float pathTaperY = 0.0f; + public Mesh Extrude(Mesh m) { @@ -230,5 +245,201 @@ namespace OpenSim.Region.Physics.Meshing } return result; } + public Mesh ExtrudeCircularPath(Mesh m) + { + //startParameter = float.MinValue; + //stopParameter = float.MaxValue; + // Currently only works for iSteps=1; + Mesh result = new Mesh(); + + Quaternion tt = new Quaternion(); + Vertex v2 = new Vertex(0, 0, 0); + + Mesh newLayer; + Mesh lastLayer = null; + + int start = 0; + int step; + int steps = 24; + + float twistTotal = twistTop - twistBot; + if (System.Math.Abs(twistTotal) > (float)System.Math.PI * 1.5) steps *= 2; + if (System.Math.Abs(twistTotal) > (float)System.Math.PI * 3.0) steps *= 2; + + double percentOfPathMultiplier = 1.0 / steps; + double angleStepMultiplier = System.Math.PI * 2.0 / steps; + + //System.Console.WriteLine("twistTop: " + twistTop.ToString() + " twistbot: " + twistBot.ToString() + " twisttotal: " + twistTotal.ToString()); + + float yPathScale = pathScaleY * 0.5f; + float skewStart = -skew; + float skewOffset = 0.0f; + float totalSkew = skew * 2.0f; + + + float startAngle = (float)(System.Math.PI * 2.0 * pathCutBegin * revolutions); + float endAngle = (float)(System.Math.PI * 2.0 * pathCutEnd * revolutions); + float stepSize = (float)0.2617993878; // 2*PI / 24 segments + step = (int)(startAngle / stepSize); + float angle = startAngle; + + float xProfileScale = 1.0f; + float yProfileScale = 1.0f; + + //System.Console.WriteLine("startAngle: " + startAngle.ToString() + " endAngle: " + endAngle.ToString() + " step: " + step.ToString()); + bool done = false; + + //System.Console.WriteLine(" PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString()); + + //System.Console.WriteLine("taperBotFactorX: " + taperBotFactorX.ToString() + " taperBotFactorY: " + taperBotFactorY.ToString() + // + " taperTopFactorX: " + taperTopFactorX.ToString() + " taperTopFactorY: " + taperTopFactorY.ToString()); + + + + do + { + float percentOfPath = 1.0f; + + percentOfPath = (angle - startAngle) / (endAngle - startAngle); // endAngle should always be larger than startAngle + + // System.Console.WriteLine("angle: " + angle.ToString() + " percentOfPath: " + percentOfPath.ToString()); + + if (pathTaperX > 0.001f) // can't really compare to 0.0f as the value passed is never exactly zero + xProfileScale = 1.0f - percentOfPath * pathTaperX; + else if (pathTaperX < -0.001f) + xProfileScale = 1.0f + (1.0f - percentOfPath) * pathTaperX; + else xProfileScale = 1.0f; + + if (pathTaperY > 0.001f) + yProfileScale = 1.0f - percentOfPath * pathTaperY; + else if (pathTaperY < -0.001f) + yProfileScale = 1.0f + (1.0f - percentOfPath) * pathTaperY; + else yProfileScale = 1.0f; + + float radiusScale; + + if (radius > 0.001f) + radiusScale = 1.0f - radius * percentOfPath; + else if (radius < 0.001f) + radiusScale = 1.0f + radius * (1.0f - percentOfPath); + else radiusScale = 1.0f; + + //radiusScale = 1.0f; + + //System.Console.WriteLine("Extruder: radius: " + radius.ToString() + " radiusScale: " + radiusScale.ToString()); + + + + + + float twist = twistBot + (twistTotal * (float)percentOfPath); + + float zOffset = (float)(System.Math.Sin(angle) * (0.5f - yPathScale)) * radiusScale; + float yOffset = (float)(System.Math.Cos(angle) * (0.5f - yPathScale)) * radiusScale; + float xOffset = 0.5f * (skewStart + totalSkew * (float)percentOfPath); + + newLayer = m.Clone(); + + Vertex vTemp = new Vertex(0.0f, 0.0f, 0.0f); + + if (twistTotal != 0.0f || twistBot != 0.0f) + { + Quaternion profileRot = new Quaternion(new Vertex(0.0f, 0.0f, -1.0f), twist); + foreach (Vertex v in newLayer.vertices) + { + if (v != null) + { + vTemp = v * profileRot; + v.X = vTemp.X; + v.Y = vTemp.Y; + v.Z = vTemp.Z; + } + } + } + + Quaternion layerRot = new Quaternion(new Vertex(-1.0f, 0.0f, 0.0f), (float)angle); + foreach (Vertex v in newLayer.vertices) + { + if (v != null) + { + vTemp = v * layerRot; + v.X = xProfileScale * vTemp.X + xOffset; + v.Y = yProfileScale * vTemp.Y + yOffset; + v.Z = vTemp.Z + zOffset; + } + } + + if (angle == startAngle) // last layer, invert normals + foreach (Triangle t in newLayer.triangles) + { + t.invertNormal(); + } + + result.Append(newLayer); + + int iLastNull = 0; + + if (lastLayer != null) + { + int i, count = newLayer.vertices.Count; + + for (i = 0; i < count; i++) + { + int iNext = (i + 1); + + if (lastLayer.vertices[i] == null) // cant make a simplex here + iLastNull = i + 1; + else + { + if (i == count - 1) // End of list + iNext = iLastNull; + + if (lastLayer.vertices[iNext] == null) // Null means wrap to begin of last segment + iNext = iLastNull; + + result.Add(new Triangle(newLayer.vertices[i], lastLayer.vertices[i], newLayer.vertices[iNext])); + result.Add(new Triangle(newLayer.vertices[iNext], lastLayer.vertices[i], lastLayer.vertices[iNext])); + } + } + } + lastLayer = newLayer; + + + + + + + + + // calc next angle + + if (angle >= endAngle) + done = true; + else + { + angle = stepSize * ++step; + if (angle > endAngle) + angle = endAngle; + } + } + while (!done); + + + + // scale the mesh to the desired size + float xScale = size.X; + float yScale = size.Y; + float zScale = size.Z; + + foreach (Vertex v in result.vertices) + if (v != null) + { + v.X *= xScale; + v.Y *= yScale; + v.Z *= zScale; + } + + return result; + } } } diff --git a/OpenSim/Region/Physics/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/Meshing/HelperTypes.cs index 584133cb6f..f031fb6451 100644 --- a/OpenSim/Region/Physics/Meshing/HelperTypes.cs +++ b/OpenSim/Region/Physics/Meshing/HelperTypes.cs @@ -51,9 +51,13 @@ public class Quaternion { // using (* 0.5) instead of (/2) w = (float)Math.Cos(angle * 0.5f); - x = axis.X * (float)Math.Sin(angle * 0.5f); - y = axis.Y * (float)Math.Sin(angle * 0.5f); - z = axis.Z * (float)Math.Sin(angle * 0.5f); + float sin = (float)Math.Sin(angle * 0.5f); + //x = axis.X * (float)Math.Sin(angle * 0.5f); + //y = axis.Y * (float)Math.Sin(angle * 0.5f); + //z = axis.Z * (float)Math.Sin(angle * 0.5f); + x = axis.X * sin; + y = axis.Y * sin; + z = axis.Z * sin; normalize(); } public static Quaternion operator *(Quaternion a, Quaternion b) @@ -73,12 +77,18 @@ public class Quaternion } public void normalize() { - float mag = length(); + //float mag = length(); - w /= mag; - x /= mag; - y /= mag; - z /= mag; + //w /= mag; + //x /= mag; + //y /= mag; + //z /= mag; + float iMag = 1.0f / length(); + + w *= iMag; + x *= iMag; + y *= iMag; + z *= iMag; } public float length() { @@ -169,7 +179,8 @@ public class Vertex : PhysicsVector, IComparable float tlength = length(); if (tlength != 0) { - return new Vertex(X / tlength, Y / tlength, Z / tlength); + float mul = 1.0f / tlength; + return new Vertex(X * mul, Y * mul, Z * mul); } else { @@ -230,9 +241,10 @@ public class Vertex : PhysicsVector, IComparable { return new Vertex(0f,0f,0f); } - v1.X /= am; - v1.Y /= am; - v1.Z /= am; + float mul = 1.0f / am; + v1.X *= mul; + v1.Y *= mul; + v1.Z *= mul; return v1; } diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index ba4f94103d..5ef392c284 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; +using libsecondlife; namespace OpenSim.Region.Physics.Meshing { @@ -253,7 +254,8 @@ namespace OpenSim.Region.Physics.Meshing holeHull.AddVertex(IPP); holeHull.AddVertex(IPM); } - if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + //if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + if ( hshape == HollowShape.Circle ) { float hollowFactorF = (float)fhollowFactor / (float)50000; @@ -576,7 +578,6 @@ namespace OpenSim.Region.Physics.Meshing } } - if (pathShearX != 0) { if (pathShearX > 50) @@ -647,7 +648,7 @@ namespace OpenSim.Region.Physics.Meshing return result; } - private static Mesh CreateCyllinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + private static Mesh CreateCylinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) // Builds the z (+ and -) surfaces of a box shaped prim { @@ -1318,6 +1319,317 @@ namespace OpenSim.Region.Physics.Meshing return sm; } + + private static Mesh CreateCircularProfileMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + { + + 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; + Int16 twistBot = primShape.PathTwist; + Int16 twistTop = primShape.PathTwistBegin; + HollowShape hollowShape = primShape.HollowShape; + + //Console.WriteLine("pathTwist: " + primShape.PathTwist.ToString() + " pathTwistBegin: " + primShape.PathTwistBegin.ToString()); + + SimpleHull outerHull = new SimpleHull(); + + //Console.WriteLine("primShape.ProfileCurve & 0x07: " + Convert.ToString(primShape.ProfileCurve & 0x07)); + + if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) + + //if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle + // || (primShape.ProfileCurve & 0x07) == (byte) ProfileShape.Square) + { + //Console.WriteLine("Meshmerizer thinks " + primName + " is a TORUS"); + if ( hollowShape == HollowShape.Same ) + hollowShape = HollowShape.Circle; + + // build the profile shape + // counter-clockwise around the quadrants, start at 45 degrees + + outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees + outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees + outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees + outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees + outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees + outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees + outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees + outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees + outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees + outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees + outerHull.AddVertex(new Vertex(-0.482963f, -0.129410f, 0.0f)); // 195 degrees + outerHull.AddVertex(new Vertex(-0.433013f, -0.250000f, 0.0f)); // 210 degrees + outerHull.AddVertex(new Vertex(-0.353553f, -0.353553f, 0.0f)); // 225 degrees + outerHull.AddVertex(new Vertex(-0.250000f, -0.433013f, 0.0f)); // 240 degrees + outerHull.AddVertex(new Vertex(-0.129410f, -0.482963f, 0.0f)); // 255 degrees + outerHull.AddVertex(new Vertex(0.000000f, -0.500000f, 0.0f)); // 270 degrees + outerHull.AddVertex(new Vertex(0.129410f, -0.482963f, 0.0f)); // 285 degrees + outerHull.AddVertex(new Vertex(0.250000f, -0.433013f, 0.0f)); // 300 degrees + outerHull.AddVertex(new Vertex(0.353553f, -0.353553f, 0.0f)); // 315 degrees + outerHull.AddVertex(new Vertex(0.433013f, -0.250000f, 0.0f)); // 330 degrees + outerHull.AddVertex(new Vertex(0.482963f, -0.129410f, 0.0f)); // 345 degrees + outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees + outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees + outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees + } + + else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) // a ring + { + //Console.WriteLine("Meshmerizer thinks " + primName + " is a TUBE"); + if ( hollowShape == HollowShape.Same ) + hollowShape = HollowShape.Square; + + outerHull.AddVertex(new Vertex(+0.5f, +0.5f, 0.0f)); + outerHull.AddVertex(new Vertex(-0.5f, +0.5f, 0.0f)); + outerHull.AddVertex(new Vertex(-0.5f, -0.5f, 0.0f)); + outerHull.AddVertex(new Vertex(+0.5f, -0.5f, 0.0f)); + } + + else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) + { + //Console.WriteLine("Meshmerizer thinks " + primName + " is a RING"); + if ( hollowShape == HollowShape.Same ) + hollowShape = HollowShape.Triangle; + + outerHull.AddVertex(new Vertex(+0.255f, -0.375f, 0.0f)); + outerHull.AddVertex(new Vertex(+0.25f, +0.375f, 0.0f)); + outerHull.AddVertex(new Vertex(-0.5f, +0.0f, 0.0f)); + + } + + else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) + { + //Console.WriteLine("Meshmerizer thinks " + primName + " is a SPHERE"); + if (hollowShape == HollowShape.Same) + hollowShape = HollowShape.Circle; + + // not implemented here, use old routine + return CreateSphereMesh(primName, primShape, size); + } + + // 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); + + if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) + { + Quaternion zFlip = new Quaternion(new Vertex(0.0f, 0.0f, 1.0f), (float)Math.PI); + Vertex vTmp = new Vertex(0.0f, 0.0f, 0.0f); + foreach (Vertex v in cuttedHull.getVertices()) + if (v != null) + { + vTmp = v * zFlip; + v.X = vTmp.X; + v.Y = vTmp.Y; + v.Z = vTmp.Z; + } + } + + outerHull = cuttedHull; + } + + // Deal with the hole here + if (hollowFactor > 0) + { + SimpleHull holeHull; + + if (hollowShape == HollowShape.Triangle) + { + holeHull = new SimpleHull(); + + float hollowFactorF = (float) hollowFactor / 50000.0f; + + if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) + { + holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, -0.1875f * hollowFactorF, 0.0f)); + holeHull.AddVertex(new Vertex(-0.25f * hollowFactorF, -0f * hollowFactorF, 0.0f)); + holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, +0.1875f * hollowFactorF, 0.0f)); + } + else + { + holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f)); + holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, -0f * hollowFactorF, 0.0f)); + holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f)); + + ////holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, -0f * hollowFactorF, 0.0f)); + + ////holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f)); + + ////holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f)); + + //holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f)); + //holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f)); + //holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f)); + ////holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f)); + } + } + else + { + 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) + t.invertNormal(); + + Vertex vTemp = new Vertex(0.0f, 0.0f, 0.0f); + + //Console.WriteLine("primShape.PathScaleX: " + primShape.PathScaleX.ToString() + " primShape.PathScaleY: " + primShape.PathScaleY.ToString()); + //Console.WriteLine("primShape.PathSkew: " + primShape.PathSkew.ToString() + " primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString() + " primShape.pathRevolutions: " + primShape.PathRevolutions.ToString()); + + float skew = primShape.PathSkew * 0.01f; + float pathScaleX = (float)(200 - primShape.PathScaleX) * 0.01f; + float pathScaleY = (float)(200 - primShape.PathScaleY) * 0.01f; + //Console.WriteLine("PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString()); + + float profileXComp = pathScaleX * (1.0f - Math.Abs(skew)); + foreach (Vertex v in m.vertices) + if (v != null) + { + v.X *= profileXComp; + v.Y *= pathScaleY; + //v.Y *= 0.5f; // torus profile is scaled in y axis + } + + Extruder extr = new Extruder(); + + extr.size = size; + extr.pathScaleX = pathScaleX; + extr.pathScaleY = pathScaleY; + extr.pathCutBegin = 0.00002f * primShape.PathBegin; + extr.pathCutEnd = 0.00002f * (50000 - primShape.PathEnd); + extr.pathBegin = primShape.PathBegin; + extr.pathEnd = primShape.PathEnd; + extr.skew = skew; + extr.revolutions = 1.0f + (float)primShape.PathRevolutions * 3.0f / 200.0f; + + //System.Console.WriteLine("primShape.PathBegin: " + primShape.PathBegin.ToString() + " primShape.PathEnd: " + primShape.PathEnd.ToString()); + //System.Console.WriteLine("extr.pathCutBegin: " + extr.pathCutBegin.ToString() + " extr.pathCutEnd: " + extr.pathCutEnd.ToString()); + //System.Console.WriteLine("extr.revolutions: " + extr.revolutions.ToString()); + + //System.Console.WriteLine("primShape.PathTaperX: " + primShape.PathTaperX.ToString()); + //System.Console.WriteLine("primShape.PathTaperY: " + primShape.PathTaperY.ToString()); + + extr.pathTaperX = 0.01f * (float)primShape.PathTaperX; + extr.pathTaperY = 0.01f * (float)primShape.PathTaperY; + + extr.radius = 0.01f * (float)primShape.PathRadiusOffset; + //System.Console.WriteLine("primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.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); + } + + } + + extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.02f; + extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.02f; + + //System.Console.WriteLine("[MESH]: twistTop = " + twistTop.ToString() + "|" + extr.twistTop.ToString() + ", twistMid = " + twistMid.ToString() + "|" + extr.twistMid.ToString() + ", twistbot = " + twistBot.ToString() + "|" + extr.twistBot.ToString()); + Mesh result = extr.ExtrudeCircularPath(m); + result.DumpRaw(baseDir, primName, "Z extruded"); + return result; + } + public static void CalcNormals(Mesh mesh) { int iTriangles = mesh.triangles.Count; @@ -1432,43 +1744,111 @@ namespace OpenSim.Region.Physics.Meshing mesh = (Mesh)smesh; CalcNormals(mesh); } - else + else if ((primShape.ProfileCurve & (byte)ProfileShape.Square) == (byte)ProfileShape.Square) { - 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.HalfCircle: - if (primShape.PathCurve == (byte)Extrusion.Curve1) - { - mesh = CreateSphereMesh(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; + if (primShape.PathCurve == (byte)LLObject.PathCurve.Line) + { // its a box + mesh = CreateBoxMesh(primName, primShape, size); + CalcNormals(mesh); + } + else if (primShape.PathCurve == (byte)LLObject.PathCurve.Circle) + { // tube + // do a cylinder for now + //mesh = CreateCylinderMesh(primName, primShape, size); + mesh = CreateCircularProfileMesh(primName, primShape, size); + CalcNormals(mesh); } } + else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) + { + if (primShape.PathCurve == (byte)Extrusion.Straight) + { + mesh = CreateCylinderMesh(primName, primShape, size); + CalcNormals(mesh); + } + + // look at LLObject.cs in libsecondlife for how to know the prim type + // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits + else if (primShape.PathCurve == (byte) Extrusion.Curve1 && LLObject.UnpackPathScale(primShape.PathScaleY) <= 0.75f) + { // dahlia's favorite, a torus :) + mesh = CreateCircularProfileMesh(primName, primShape, size); + CalcNormals(mesh); + } + } + else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) + { + if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte) Extrusion.Curve2) + { + mesh = CreateSphereMesh(primName, primShape, size); + CalcNormals(mesh); + } + } + else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) + { + if (primShape.PathCurve == (byte)Extrusion.Straight) + { + mesh = CreatePrismMesh(primName, primShape, size); + CalcNormals(mesh); + } + else if (primShape.PathCurve == (byte) Extrusion.Curve1) + { // a ring - do a cylinder for now + //mesh = CreateCylinderMesh(primName, primShape, size); + mesh = CreateCircularProfileMesh(primName, primShape, size); + CalcNormals(mesh); + } + } + else // just do a box + { + mesh = CreateBoxMesh(primName, primShape, size); + CalcNormals(mesh); + } + + //else + //{ + // switch (primShape.ProfileShape) + // { + // case ProfileShape.Square: + // mesh = CreateBoxMesh(primName, primShape, size); + // CalcNormals(mesh); + // break; + // case ProfileShape.Circle: + // if (primShape.PathCurve == (byte)Extrusion.Straight) + // { + // mesh = CreateCylinderMesh(primName, primShape, size); + // CalcNormals(mesh); + // } + + // // look at LLObject.cs in libsecondlife for how to know the prim type + // // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits + // else if ((primShape.ProfileCurve & 0x07) == (byte)LLObject.ProfileCurve.Circle && LLObject.UnpackPathScale(primShape.PathScaleY) <= 0.75f) + // { // dahlia's favorite, a torus :) + // mesh = CreateCylinderMesh(primName, primShape, size); + // CalcNormals(mesh); + // } + + // break; + // case ProfileShape.HalfCircle: + // if (primShape.PathCurve == (byte)Extrusion.Curve1) + // { + // mesh = CreateSphereMesh(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; } diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index e43a1ac298..5078f031f0 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -36,6 +36,7 @@ using Nini.Config; using Ode.NET; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; +using libsecondlife; //using OpenSim.Region.Physics.OdePlugin.Meshing; @@ -1512,6 +1513,8 @@ namespace OpenSim.Region.Physics.OdePlugin /// public bool needsMeshing(PrimitiveBaseShape pbs) { + //if (pbs.PathCurve == (byte)LLObject.PathCurve.Circle && pbs.ProfileCurve == (byte)LLObject.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f) + //Console.WriteLine("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + LLObject.UnpackPathScale(pbs.PathScaleY).ToString()); if (pbs.SculptEntry && !meshSculptedPrim) { return false; @@ -1537,6 +1540,22 @@ namespace OpenSim.Region.Physics.OdePlugin if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) return true; + // test for torus + if (pbs.PathCurve == (byte)LLObject.PathCurve.Circle + && (pbs.ProfileCurve & 0x07) == (byte)LLObject.ProfileCurve.Circle + && LLObject.UnpackPathScale(pbs.PathScaleY) <= 0.75f) + return true; + + // test for tube + if (pbs.PathCurve == (byte)LLObject.PathCurve.Circle + && (pbs.ProfileCurve & 0x07) == (byte)LLObject.ProfileCurve.EqualTriangle) + return true; + + // test for ring + if (pbs.PathCurve == (byte)LLObject.PathCurve.Circle + && (pbs.ProfileCurve & 0x07) == (byte)LLObject.ProfileCurve.EqualTriangle) + return true; + if (pbs.ProfileShape == ProfileShape.EquilateralTriangle) return true;