aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs21
-rw-r--r--OpenSim/Region/Physics/Meshing/PrimMesher.cs326
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs135
3 files changed, 275 insertions, 207 deletions
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index 91252f7..df5ac92 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
@@ -111,6 +111,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
111 asset = assetService.GetCached(cacheID.ToString()); 111 asset = assetService.GetCached(cacheID.ToString());
112 if (asset != null) 112 if (asset != null)
113 { 113 {
114// m_log.DebugFormat(
115// "[TERRAIN SPLAT]: Got asset service cached terrain texture {0} {1}", i, asset.ID);
116
114 try 117 try
115 { 118 {
116 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) 119 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
@@ -129,6 +132,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
129 asset = assetService.Get(textureIDs[i].ToString()); 132 asset = assetService.Get(textureIDs[i].ToString());
130 if (asset != null) 133 if (asset != null)
131 { 134 {
135// m_log.DebugFormat(
136// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
137
132 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } 138 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
133 catch (Exception ex) 139 catch (Exception ex)
134 { 140 {
@@ -137,15 +143,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
137 } 143 }
138 144
139 if (detailTexture[i] != null) 145 if (detailTexture[i] != null)
140 { 146 {
141 Bitmap bitmap = detailTexture[i];
142
143 // Make sure this texture is the correct size, otherwise resize 147 // Make sure this texture is the correct size, otherwise resize
144 if (bitmap.Width != 256 || bitmap.Height != 256) 148 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
145 { 149 {
146 using (Bitmap origBitmap = bitmap) 150 using (Bitmap origBitmap = detailTexture[i])
147 { 151 {
148 bitmap = ImageUtils.ResizeImage(origBitmap, 256, 256); 152 detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
149 } 153 }
150 } 154 }
151 155
@@ -153,7 +157,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
153 byte[] data; 157 byte[] data;
154 using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) 158 using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
155 { 159 {
156 bitmap.Save(stream, ImageFormat.Png); 160 detailTexture[i].Save(stream, ImageFormat.Png);
157 data = stream.ToArray(); 161 data = stream.ToArray();
158 } 162 }
159 163
@@ -185,6 +189,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
185 { 189 {
186 if (detailTexture[i] == null) 190 if (detailTexture[i] == null)
187 { 191 {
192// m_log.DebugFormat(
193// "[TERRAIN SPLAT]: Generating solid colour for missing texture {0}", i);
194
188 // Create a solid color texture for this layer 195 // Create a solid color texture for this layer
189 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); 196 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
190 using (Graphics gfx = Graphics.FromImage(detailTexture[i])) 197 using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
index 53022ad..4049ee1 100644
--- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
@@ -236,6 +236,13 @@ namespace PrimMesher
236 this.U = u; 236 this.U = u;
237 this.V = v; 237 this.V = v;
238 } 238 }
239
240 public UVCoord Flip()
241 {
242 this.U = 1.0f - this.U;
243 this.V = 1.0f - this.V;
244 return this;
245 }
239 } 246 }
240 247
241 public struct Face 248 public struct Face
@@ -603,40 +610,40 @@ namespace PrimMesher
603 /// <summary> 610 /// <summary>
604 /// generates a profile for extrusion 611 /// generates a profile for extrusion
605 /// </summary> 612 /// </summary>
606 internal class Profile 613 public class Profile
607 { 614 {
608 private const float twoPi = 2.0f * (float)Math.PI; 615 private const float twoPi = 2.0f * (float)Math.PI;
609 616
610 internal string errorMessage = null; 617 public string errorMessage = null;
611 618
612 internal List<Coord> coords; 619 public List<Coord> coords;
613 internal List<Face> faces; 620 public List<Face> faces;
614 internal List<Coord> vertexNormals; 621 public List<Coord> vertexNormals;
615 internal List<float> us; 622 public List<float> us;
616 internal List<UVCoord> faceUVs; 623 public List<UVCoord> faceUVs;
617 internal List<int> faceNumbers; 624 public List<int> faceNumbers;
618 625
619 // use these for making individual meshes for each prim face 626 // use these for making individual meshes for each prim face
620 internal List<int> outerCoordIndices = null; 627 public List<int> outerCoordIndices = null;
621 internal List<int> hollowCoordIndices = null; 628 public List<int> hollowCoordIndices = null;
622 internal List<int> cut1CoordIndices = null; 629 public List<int> cut1CoordIndices = null;
623 internal List<int> cut2CoordIndices = null; 630 public List<int> cut2CoordIndices = null;
624 631
625 internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); 632 public Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f);
626 internal Coord cutNormal1 = new Coord(); 633 public Coord cutNormal1 = new Coord();
627 internal Coord cutNormal2 = new Coord(); 634 public Coord cutNormal2 = new Coord();
628 635
629 internal int numOuterVerts = 0; 636 public int numOuterVerts = 0;
630 internal int numHollowVerts = 0; 637 public int numHollowVerts = 0;
631 638
632 internal int outerFaceNumber = -1; 639 public int outerFaceNumber = -1;
633 internal int hollowFaceNumber = -1; 640 public int hollowFaceNumber = -1;
634 641
635 internal bool calcVertexNormals = false; 642 public bool calcVertexNormals = false;
636 internal int bottomFaceNumber = 0; 643 public int bottomFaceNumber = 0;
637 internal int numPrimFaces = 0; 644 public int numPrimFaces = 0;
638 645
639 internal Profile() 646 public Profile()
640 { 647 {
641 this.coords = new List<Coord>(); 648 this.coords = new List<Coord>();
642 this.faces = new List<Face>(); 649 this.faces = new List<Face>();
@@ -646,7 +653,7 @@ namespace PrimMesher
646 this.faceNumbers = new List<int>(); 653 this.faceNumbers = new List<int>();
647 } 654 }
648 655
649 internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) 656 public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals)
650 { 657 {
651 this.calcVertexNormals = calcVertexNormals; 658 this.calcVertexNormals = calcVertexNormals;
652 this.coords = new List<Coord>(); 659 this.coords = new List<Coord>();
@@ -657,7 +664,6 @@ namespace PrimMesher
657 this.faceNumbers = new List<int>(); 664 this.faceNumbers = new List<int>();
658 665
659 Coord center = new Coord(0.0f, 0.0f, 0.0f); 666 Coord center = new Coord(0.0f, 0.0f, 0.0f);
660 //bool hasCenter = false;
661 667
662 List<Coord> hollowCoords = new List<Coord>(); 668 List<Coord> hollowCoords = new List<Coord>();
663 List<Coord> hollowNormals = new List<Coord>(); 669 List<Coord> hollowNormals = new List<Coord>();
@@ -682,8 +688,8 @@ namespace PrimMesher
682 float yScale = 0.5f; 688 float yScale = 0.5f;
683 if (sides == 4) // corners of a square are sqrt(2) from center 689 if (sides == 4) // corners of a square are sqrt(2) from center
684 { 690 {
685 xScale = 0.707f; 691 xScale = 0.707107f;
686 yScale = 0.707f; 692 yScale = 0.707107f;
687 } 693 }
688 694
689 float startAngle = profileStart * twoPi; 695 float startAngle = profileStart * twoPi;
@@ -724,7 +730,6 @@ namespace PrimMesher
724 else if (!simpleFace) 730 else if (!simpleFace)
725 { 731 {
726 this.coords.Add(center); 732 this.coords.Add(center);
727 //hasCenter = true;
728 if (this.calcVertexNormals) 733 if (this.calcVertexNormals)
729 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); 734 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f));
730 this.us.Add(0.0f); 735 this.us.Add(0.0f);
@@ -752,7 +757,10 @@ namespace PrimMesher
752 else 757 else
753 hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); 758 hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));
754 759
755 hollowUs.Add(angle.angle * hollow); 760 if (hollowSides == 4)
761 hollowUs.Add(angle.angle * hollow * 0.707107f);
762 else
763 hollowUs.Add(angle.angle * hollow);
756 } 764 }
757 } 765 }
758 } 766 }
@@ -829,9 +837,6 @@ namespace PrimMesher
829 837
830 if (createFaces) 838 if (createFaces)
831 { 839 {
832 //int numOuterVerts = this.coords.Count;
833 //numOuterVerts = this.coords.Count;
834 //int numHollowVerts = hollowCoords.Count;
835 int numTotalVerts = this.numOuterVerts + this.numHollowVerts; 840 int numTotalVerts = this.numOuterVerts + this.numHollowVerts;
836 841
837 if (this.numOuterVerts == this.numHollowVerts) 842 if (this.numOuterVerts == this.numHollowVerts)
@@ -993,11 +998,7 @@ namespace PrimMesher
993 if (startVert > 0) 998 if (startVert > 0)
994 this.faceNumbers.Add(-1); 999 this.faceNumbers.Add(-1);
995 for (int i = 0; i < this.numOuterVerts - 1; i++) 1000 for (int i = 0; i < this.numOuterVerts - 1; i++)
996 //this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum); 1001 this.faceNumbers.Add(sides < 5 && i <= sides ? faceNum++ : faceNum);
997 this.faceNumbers.Add(sides < 5 && i < sides ? faceNum++ : faceNum);
998
999 //if (!hasHollow && !hasProfileCut)
1000 // this.bottomFaceNumber = faceNum++;
1001 1002
1002 this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++); 1003 this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++);
1003 1004
@@ -1014,8 +1015,7 @@ namespace PrimMesher
1014 1015
1015 this.hollowFaceNumber = faceNum++; 1016 this.hollowFaceNumber = faceNum++;
1016 } 1017 }
1017 //if (hasProfileCut || hasHollow) 1018
1018 // this.bottomFaceNumber = faceNum++;
1019 this.bottomFaceNumber = faceNum++; 1019 this.bottomFaceNumber = faceNum++;
1020 1020
1021 if (hasHollow && hasProfileCut) 1021 if (hasHollow && hasProfileCut)
@@ -1030,19 +1030,19 @@ namespace PrimMesher
1030 1030
1031 } 1031 }
1032 1032
1033 internal void MakeFaceUVs() 1033 public void MakeFaceUVs()
1034 { 1034 {
1035 this.faceUVs = new List<UVCoord>(); 1035 this.faceUVs = new List<UVCoord>();
1036 foreach (Coord c in this.coords) 1036 foreach (Coord c in this.coords)
1037 this.faceUVs.Add(new UVCoord(0.5f + c.X, 0.5f - c.Y)); 1037 this.faceUVs.Add(new UVCoord(1.0f - (0.5f + c.X), 1.0f - (0.5f - c.Y)));
1038 } 1038 }
1039 1039
1040 internal Profile Copy() 1040 public Profile Copy()
1041 { 1041 {
1042 return this.Copy(true); 1042 return this.Copy(true);
1043 } 1043 }
1044 1044
1045 internal Profile Copy(bool needFaces) 1045 public Profile Copy(bool needFaces)
1046 { 1046 {
1047 Profile copy = new Profile(); 1047 Profile copy = new Profile();
1048 1048
@@ -1071,12 +1071,12 @@ namespace PrimMesher
1071 return copy; 1071 return copy;
1072 } 1072 }
1073 1073
1074 internal void AddPos(Coord v) 1074 public void AddPos(Coord v)
1075 { 1075 {
1076 this.AddPos(v.X, v.Y, v.Z); 1076 this.AddPos(v.X, v.Y, v.Z);
1077 } 1077 }
1078 1078
1079 internal void AddPos(float x, float y, float z) 1079 public void AddPos(float x, float y, float z)
1080 { 1080 {
1081 int i; 1081 int i;
1082 int numVerts = this.coords.Count; 1082 int numVerts = this.coords.Count;
@@ -1092,7 +1092,7 @@ namespace PrimMesher
1092 } 1092 }
1093 } 1093 }
1094 1094
1095 internal void AddRot(Quat q) 1095 public void AddRot(Quat q)
1096 { 1096 {
1097 int i; 1097 int i;
1098 int numVerts = this.coords.Count; 1098 int numVerts = this.coords.Count;
@@ -1113,7 +1113,7 @@ namespace PrimMesher
1113 } 1113 }
1114 } 1114 }
1115 1115
1116 internal void Scale(float x, float y) 1116 public void Scale(float x, float y)
1117 { 1117 {
1118 int i; 1118 int i;
1119 int numVerts = this.coords.Count; 1119 int numVerts = this.coords.Count;
@@ -1131,7 +1131,7 @@ namespace PrimMesher
1131 /// <summary> 1131 /// <summary>
1132 /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices 1132 /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices
1133 /// </summary> 1133 /// </summary>
1134 internal void FlipNormals() 1134 public void FlipNormals()
1135 { 1135 {
1136 int i; 1136 int i;
1137 int numFaces = this.faces.Count; 1137 int numFaces = this.faces.Count;
@@ -1171,7 +1171,7 @@ namespace PrimMesher
1171 } 1171 }
1172 } 1172 }
1173 1173
1174 internal void AddValue2FaceVertexIndices(int num) 1174 public void AddValue2FaceVertexIndices(int num)
1175 { 1175 {
1176 int numFaces = this.faces.Count; 1176 int numFaces = this.faces.Count;
1177 Face tmpFace; 1177 Face tmpFace;
@@ -1186,7 +1186,7 @@ namespace PrimMesher
1186 } 1186 }
1187 } 1187 }
1188 1188
1189 internal void AddValue2FaceNormalIndices(int num) 1189 public void AddValue2FaceNormalIndices(int num)
1190 { 1190 {
1191 if (this.calcVertexNormals) 1191 if (this.calcVertexNormals)
1192 { 1192 {
@@ -1204,7 +1204,7 @@ namespace PrimMesher
1204 } 1204 }
1205 } 1205 }
1206 1206
1207 internal void DumpRaw(String path, String name, String title) 1207 public void DumpRaw(String path, String name, String title)
1208 { 1208 {
1209 if (path == null) 1209 if (path == null)
1210 return; 1210 return;
@@ -1261,6 +1261,15 @@ namespace PrimMesher
1261 1261
1262 public void Create(PathType pathType, int steps) 1262 public void Create(PathType pathType, int steps)
1263 { 1263 {
1264 if (this.taperX > 0.999f)
1265 this.taperX = 0.999f;
1266 if (this.taperX < -0.999f)
1267 this.taperX = -0.999f;
1268 if (this.taperY > 0.999f)
1269 this.taperY = 0.999f;
1270 if (this.taperY < -0.999f)
1271 this.taperY = -0.999f;
1272
1264 if (pathType == PathType.Linear || pathType == PathType.Flexible) 1273 if (pathType == PathType.Linear || pathType == PathType.Flexible)
1265 { 1274 {
1266 int step = 0; 1275 int step = 0;
@@ -1273,12 +1282,12 @@ namespace PrimMesher
1273 1282
1274 float start = -0.5f; 1283 float start = -0.5f;
1275 float stepSize = length / (float)steps; 1284 float stepSize = length / (float)steps;
1276 float percentOfPathMultiplier = stepSize; 1285 float percentOfPathMultiplier = stepSize * 0.999999f;
1277 float xOffset = 0.0f; 1286 float xOffset = this.topShearX * this.pathCutBegin;
1278 float yOffset = 0.0f; 1287 float yOffset = this.topShearY * this.pathCutBegin;
1279 float zOffset = start; 1288 float zOffset = start;
1280 float xOffsetStepIncrement = this.topShearX / steps; 1289 float xOffsetStepIncrement = this.topShearX * length / steps;
1281 float yOffsetStepIncrement = this.topShearY / steps; 1290 float yOffsetStepIncrement = this.topShearY * length / steps;
1282 1291
1283 float percentOfPath = this.pathCutBegin; 1292 float percentOfPath = this.pathCutBegin;
1284 zOffset += percentOfPath; 1293 zOffset += percentOfPath;
@@ -1573,13 +1582,6 @@ namespace PrimMesher
1573 this.hollow = 0.99f; 1582 this.hollow = 0.99f;
1574 if (hollow < 0.0f) 1583 if (hollow < 0.0f)
1575 this.hollow = 0.0f; 1584 this.hollow = 0.0f;
1576
1577 //if (sphereMode)
1578 // this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f;
1579 //else
1580 // //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f);
1581 // this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1582 //this.hasHollow = (this.hollow > 0.001f);
1583 } 1585 }
1584 1586
1585 /// <summary> 1587 /// <summary>
@@ -1614,10 +1616,9 @@ namespace PrimMesher
1614 steps = (int)(steps * 4.5 * length); 1616 steps = (int)(steps * 4.5 * length);
1615 } 1617 }
1616 1618
1617 if (sphereMode) 1619 if (this.sphereMode)
1618 this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f; 1620 this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f;
1619 else 1621 else
1620 //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f);
1621 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f; 1622 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1622 this.hasHollow = (this.hollow > 0.001f); 1623 this.hasHollow = (this.hollow > 0.001f);
1623 1624
@@ -1630,6 +1631,22 @@ namespace PrimMesher
1630 1631
1631 float hollow = this.hollow; 1632 float hollow = this.hollow;
1632 1633
1634 if (pathType == PathType.Circular)
1635 {
1636 needEndFaces = false;
1637 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
1638 needEndFaces = true;
1639 else if (this.taperX != 0.0f || this.taperY != 0.0f)
1640 needEndFaces = true;
1641 else if (this.skew != 0.0f)
1642 needEndFaces = true;
1643 else if (twistTotal != 0.0f)
1644 needEndFaces = true;
1645 else if (this.radius != 0.0f)
1646 needEndFaces = true;
1647 }
1648 else needEndFaces = true;
1649
1633 // sanity checks 1650 // sanity checks
1634 float initialProfileRot = 0.0f; 1651 float initialProfileRot = 0.0f;
1635 if (pathType == PathType.Circular) 1652 if (pathType == PathType.Circular)
@@ -1689,20 +1706,13 @@ namespace PrimMesher
1689 1706
1690 this.numPrimFaces = profile.numPrimFaces; 1707 this.numPrimFaces = profile.numPrimFaces;
1691 1708
1692 //profileOuterFaceNumber = profile.faceNumbers[0]; 1709 int cut1FaceNumber = profile.bottomFaceNumber + 1;
1693 //if (!needEndFaces) 1710 int cut2FaceNumber = cut1FaceNumber + 1;
1694 // profileOuterFaceNumber--; 1711 if (!needEndFaces)
1695 //profileOuterFaceNumber = needEndFaces ? 1 : 0; 1712 {
1696 1713 cut1FaceNumber -= 2;
1697 1714 cut2FaceNumber -= 2;
1698 //if (hasHollow) 1715 }
1699 //{
1700 // if (needEndFaces)
1701 // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts + 1];
1702 // else
1703 // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts] - 1;
1704 //}
1705
1706 1716
1707 profileOuterFaceNumber = profile.outerFaceNumber; 1717 profileOuterFaceNumber = profile.outerFaceNumber;
1708 if (!needEndFaces) 1718 if (!needEndFaces)
@@ -1732,7 +1742,8 @@ namespace PrimMesher
1732 1742
1733 Coord lastCutNormal1 = new Coord(); 1743 Coord lastCutNormal1 = new Coord();
1734 Coord lastCutNormal2 = new Coord(); 1744 Coord lastCutNormal2 = new Coord();
1735 float lastV = 1.0f; 1745 float thisV = 0.0f;
1746 float lastV = 0.0f;
1736 1747
1737 Path path = new Path(); 1748 Path path = new Path();
1738 path.twistBegin = twistBegin; 1749 path.twistBegin = twistBegin;
@@ -1754,23 +1765,6 @@ namespace PrimMesher
1754 1765
1755 path.Create(pathType, steps); 1766 path.Create(pathType, steps);
1756 1767
1757
1758 if (pathType == PathType.Circular)
1759 {
1760 needEndFaces = false;
1761 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
1762 needEndFaces = true;
1763 else if (this.taperX != 0.0f || this.taperY != 0.0f)
1764 needEndFaces = true;
1765 else if (this.skew != 0.0f)
1766 needEndFaces = true;
1767 else if (twistTotal != 0.0f)
1768 needEndFaces = true;
1769 else if (this.radius != 0.0f)
1770 needEndFaces = true;
1771 }
1772 else needEndFaces = true;
1773
1774 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) 1768 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1775 { 1769 {
1776 PathNode node = path.pathNodes[nodeIndex]; 1770 PathNode node = path.pathNodes[nodeIndex];
@@ -1784,7 +1778,7 @@ namespace PrimMesher
1784 { 1778 {
1785 newLayer.FlipNormals(); 1779 newLayer.FlipNormals();
1786 1780
1787 // add the top faces to the viewerFaces list here 1781 // add the bottom faces to the viewerFaces list
1788 if (this.viewerMode) 1782 if (this.viewerMode)
1789 { 1783 {
1790 Coord faceNormal = newLayer.faceNormal; 1784 Coord faceNormal = newLayer.faceNormal;
@@ -1811,6 +1805,13 @@ namespace PrimMesher
1811 newViewerFace.uv2 = newLayer.faceUVs[face.v2]; 1805 newViewerFace.uv2 = newLayer.faceUVs[face.v2];
1812 newViewerFace.uv3 = newLayer.faceUVs[face.v3]; 1806 newViewerFace.uv3 = newLayer.faceUVs[face.v3];
1813 1807
1808 if (pathType == PathType.Linear)
1809 {
1810 newViewerFace.uv1.Flip();
1811 newViewerFace.uv2.Flip();
1812 newViewerFace.uv3.Flip();
1813 }
1814
1814 this.viewerFaces.Add(newViewerFace); 1815 this.viewerFaces.Add(newViewerFace);
1815 } 1816 }
1816 } 1817 }
@@ -1835,7 +1836,10 @@ namespace PrimMesher
1835 // fill faces between layers 1836 // fill faces between layers
1836 1837
1837 int numVerts = newLayer.coords.Count; 1838 int numVerts = newLayer.coords.Count;
1838 Face newFace = new Face(); 1839 Face newFace1 = new Face();
1840 Face newFace2 = new Face();
1841
1842 thisV = 1.0f - node.percentOfPath;
1839 1843
1840 if (nodeIndex > 0) 1844 if (nodeIndex > 0)
1841 { 1845 {
@@ -1853,14 +1857,23 @@ namespace PrimMesher
1853 1857
1854 int whichVert = i - startVert; 1858 int whichVert = i - startVert;
1855 1859
1856 newFace.v1 = i; 1860 newFace1.v1 = i;
1857 newFace.v2 = i - numVerts; 1861 newFace1.v2 = i - numVerts;
1858 newFace.v3 = iNext - numVerts; 1862 newFace1.v3 = iNext;
1859 this.faces.Add(newFace); 1863
1864 newFace1.n1 = newFace1.v1;
1865 newFace1.n2 = newFace1.v2;
1866 newFace1.n3 = newFace1.v3;
1867 this.faces.Add(newFace1);
1860 1868
1861 newFace.v2 = iNext - numVerts; 1869 newFace2.v1 = iNext;
1862 newFace.v3 = iNext; 1870 newFace2.v2 = i - numVerts;
1863 this.faces.Add(newFace); 1871 newFace2.v3 = iNext - numVerts;
1872
1873 newFace2.n1 = newFace2.v1;
1874 newFace2.n2 = newFace2.v2;
1875 newFace2.n3 = newFace2.v3;
1876 this.faces.Add(newFace2);
1864 1877
1865 if (this.viewerMode) 1878 if (this.viewerMode)
1866 { 1879 {
@@ -1873,10 +1886,16 @@ namespace PrimMesher
1873 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); 1886 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum);
1874 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); 1887 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum);
1875 1888
1876 float u1 = newLayer.us[whichVert]; 1889 int uIndex = whichVert;
1890 if (!hasHollow && sides > 4 && uIndex < newLayer.us.Count - 1)
1891 {
1892 uIndex++;
1893 }
1894
1895 float u1 = newLayer.us[uIndex];
1877 float u2 = 1.0f; 1896 float u2 = 1.0f;
1878 if (whichVert < newLayer.us.Count - 1) 1897 if (uIndex < (int)newLayer.us.Count - 1)
1879 u2 = newLayer.us[whichVert + 1]; 1898 u2 = newLayer.us[uIndex + 1];
1880 1899
1881 if (whichVert == cut1Vert || whichVert == cut2Vert) 1900 if (whichVert == cut1Vert || whichVert == cut2Vert)
1882 { 1901 {
@@ -1894,13 +1913,22 @@ namespace PrimMesher
1894 u1 -= (int)u1; 1913 u1 -= (int)u1;
1895 if (u2 < 0.1f) 1914 if (u2 < 0.1f)
1896 u2 = 1.0f; 1915 u2 = 1.0f;
1897 //this.profileOuterFaceNumber = primFaceNum;
1898 } 1916 }
1899 else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1) 1917 }
1918
1919 if (this.sphereMode)
1920 {
1921 if (whichVert != cut1Vert && whichVert != cut2Vert)
1900 { 1922 {
1901 u1 *= 2.0f; 1923 u1 = u1 * 2.0f - 1.0f;
1902 u2 *= 2.0f; 1924 u2 = u2 * 2.0f - 1.0f;
1903 //this.profileHollowFaceNumber = primFaceNum; 1925
1926 if (whichVert >= newLayer.numOuterVerts)
1927 {
1928 u1 -= hollow;
1929 u2 -= hollow;
1930 }
1931
1904 } 1932 }
1905 } 1933 }
1906 1934
@@ -1908,37 +1936,39 @@ namespace PrimMesher
1908 newViewerFace1.uv2.U = u1; 1936 newViewerFace1.uv2.U = u1;
1909 newViewerFace1.uv3.U = u2; 1937 newViewerFace1.uv3.U = u2;
1910 1938
1911 newViewerFace1.uv1.V = 1.0f - node.percentOfPath; 1939 newViewerFace1.uv1.V = thisV;
1912 newViewerFace1.uv2.V = lastV; 1940 newViewerFace1.uv2.V = lastV;
1913 newViewerFace1.uv3.V = lastV; 1941 newViewerFace1.uv3.V = thisV;
1914 1942
1915 newViewerFace2.uv1.U = u1; 1943 newViewerFace2.uv1.U = u2;
1916 newViewerFace2.uv2.U = u2; 1944 newViewerFace2.uv2.U = u1;
1917 newViewerFace2.uv3.U = u2; 1945 newViewerFace2.uv3.U = u2;
1918 1946
1919 newViewerFace2.uv1.V = 1.0f - node.percentOfPath; 1947 newViewerFace2.uv1.V = thisV;
1920 newViewerFace2.uv2.V = lastV; 1948 newViewerFace2.uv2.V = lastV;
1921 newViewerFace2.uv3.V = 1.0f - node.percentOfPath; 1949 newViewerFace2.uv3.V = lastV;
1922 1950
1923 newViewerFace1.v1 = this.coords[i]; 1951 newViewerFace1.v1 = this.coords[newFace1.v1];
1924 newViewerFace1.v2 = this.coords[i - numVerts]; 1952 newViewerFace1.v2 = this.coords[newFace1.v2];
1925 newViewerFace1.v3 = this.coords[iNext - numVerts]; 1953 newViewerFace1.v3 = this.coords[newFace1.v3];
1926 1954
1927 newViewerFace2.v1 = this.coords[i]; 1955 newViewerFace2.v1 = this.coords[newFace2.v1];
1928 newViewerFace2.v2 = this.coords[iNext - numVerts]; 1956 newViewerFace2.v2 = this.coords[newFace2.v2];
1929 newViewerFace2.v3 = this.coords[iNext]; 1957 newViewerFace2.v3 = this.coords[newFace2.v3];
1930 1958
1931 newViewerFace1.coordIndex1 = i; 1959 newViewerFace1.coordIndex1 = newFace1.v1;
1932 newViewerFace1.coordIndex2 = i - numVerts; 1960 newViewerFace1.coordIndex2 = newFace1.v2;
1933 newViewerFace1.coordIndex3 = iNext - numVerts; 1961 newViewerFace1.coordIndex3 = newFace1.v3;
1934 1962
1935 newViewerFace2.coordIndex1 = i; 1963 newViewerFace2.coordIndex1 = newFace2.v1;
1936 newViewerFace2.coordIndex2 = iNext - numVerts; 1964 newViewerFace2.coordIndex2 = newFace2.v2;
1937 newViewerFace2.coordIndex3 = iNext; 1965 newViewerFace2.coordIndex3 = newFace2.v3;
1938 1966
1939 // profile cut faces 1967 // profile cut faces
1940 if (whichVert == cut1Vert) 1968 if (whichVert == cut1Vert)
1941 { 1969 {
1970 newViewerFace1.primFaceNumber = cut1FaceNumber;
1971 newViewerFace2.primFaceNumber = cut1FaceNumber;
1942 newViewerFace1.n1 = newLayer.cutNormal1; 1972 newViewerFace1.n1 = newLayer.cutNormal1;
1943 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1; 1973 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
1944 1974
@@ -1947,10 +1977,14 @@ namespace PrimMesher
1947 } 1977 }
1948 else if (whichVert == cut2Vert) 1978 else if (whichVert == cut2Vert)
1949 { 1979 {
1980 newViewerFace1.primFaceNumber = cut2FaceNumber;
1981 newViewerFace2.primFaceNumber = cut2FaceNumber;
1950 newViewerFace1.n1 = newLayer.cutNormal2; 1982 newViewerFace1.n1 = newLayer.cutNormal2;
1951 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2; 1983 newViewerFace1.n2 = lastCutNormal2;
1984 newViewerFace1.n3 = lastCutNormal2;
1952 1985
1953 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2; 1986 newViewerFace2.n1 = newLayer.cutNormal2;
1987 newViewerFace2.n3 = newLayer.cutNormal2;
1954 newViewerFace2.n2 = lastCutNormal2; 1988 newViewerFace2.n2 = lastCutNormal2;
1955 } 1989 }
1956 1990
@@ -1963,13 +1997,13 @@ namespace PrimMesher
1963 } 1997 }
1964 else 1998 else
1965 { 1999 {
1966 newViewerFace1.n1 = this.normals[i]; 2000 newViewerFace1.n1 = this.normals[newFace1.n1];
1967 newViewerFace1.n2 = this.normals[i - numVerts]; 2001 newViewerFace1.n2 = this.normals[newFace1.n2];
1968 newViewerFace1.n3 = this.normals[iNext - numVerts]; 2002 newViewerFace1.n3 = this.normals[newFace1.n3];
1969 2003
1970 newViewerFace2.n1 = this.normals[i]; 2004 newViewerFace2.n1 = this.normals[newFace2.n1];
1971 newViewerFace2.n2 = this.normals[iNext - numVerts]; 2005 newViewerFace2.n2 = this.normals[newFace2.n2];
1972 newViewerFace2.n3 = this.normals[iNext]; 2006 newViewerFace2.n3 = this.normals[newFace2.n3];
1973 } 2007 }
1974 } 2008 }
1975 2009
@@ -1982,14 +2016,13 @@ namespace PrimMesher
1982 2016
1983 lastCutNormal1 = newLayer.cutNormal1; 2017 lastCutNormal1 = newLayer.cutNormal1;
1984 lastCutNormal2 = newLayer.cutNormal2; 2018 lastCutNormal2 = newLayer.cutNormal2;
1985 lastV = 1.0f - node.percentOfPath; 2019 lastV = thisV;
1986 2020
1987 if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) 2021 if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode)
1988 { 2022 {
1989 // add the top faces to the viewerFaces list here 2023 // add the top faces to the viewerFaces list here
1990 Coord faceNormal = newLayer.faceNormal; 2024 Coord faceNormal = newLayer.faceNormal;
1991 ViewerFace newViewerFace = new ViewerFace(); 2025 ViewerFace newViewerFace = new ViewerFace(0);
1992 newViewerFace.primFaceNumber = 0;
1993 int numFaces = newLayer.faces.Count; 2026 int numFaces = newLayer.faces.Count;
1994 List<Face> faces = newLayer.faces; 2027 List<Face> faces = newLayer.faces;
1995 2028
@@ -2012,6 +2045,13 @@ namespace PrimMesher
2012 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen]; 2045 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen];
2013 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen]; 2046 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen];
2014 2047
2048 if (pathType == PathType.Linear)
2049 {
2050 newViewerFace.uv1.Flip();
2051 newViewerFace.uv2.Flip();
2052 newViewerFace.uv3.Flip();
2053 }
2054
2015 this.viewerFaces.Add(newViewerFace); 2055 this.viewerFaces.Add(newViewerFace);
2016 } 2056 }
2017 } 2057 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index fed3122..a43a8bb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -517,15 +517,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
517 return LSL_Vector.Norm(v); 517 return LSL_Vector.Norm(v);
518 } 518 }
519 519
520 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) 520 private double VecDist(LSL_Vector a, LSL_Vector b)
521 { 521 {
522 m_host.AddScriptLPS(1);
523 double dx = a.x - b.x; 522 double dx = a.x - b.x;
524 double dy = a.y - b.y; 523 double dy = a.y - b.y;
525 double dz = a.z - b.z; 524 double dz = a.z - b.z;
526 return Math.Sqrt(dx * dx + dy * dy + dz * dz); 525 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
527 } 526 }
528 527
528 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
529 {
530 m_host.AddScriptLPS(1);
531 return VecDist(a, b);
532 }
533
529 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 534 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
530 535
531 // Utility function for llRot2Euler 536 // Utility function for llRot2Euler
@@ -1391,6 +1396,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1391 } 1396 }
1392 } 1397 }
1393 1398
1399 private bool IsPhysical()
1400 {
1401 return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics);
1402 }
1403
1394 public LSL_Integer llGetStatus(int status) 1404 public LSL_Integer llGetStatus(int status)
1395 { 1405 {
1396 m_host.AddScriptLPS(1); 1406 m_host.AddScriptLPS(1);
@@ -1398,11 +1408,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1398 switch (status) 1408 switch (status)
1399 { 1409 {
1400 case ScriptBaseClass.STATUS_PHYSICS: 1410 case ScriptBaseClass.STATUS_PHYSICS:
1401 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics) 1411 return IsPhysical() ? 1 : 0;
1402 {
1403 return 1;
1404 }
1405 return 0;
1406 1412
1407 case ScriptBaseClass.STATUS_PHANTOM: 1413 case ScriptBaseClass.STATUS_PHANTOM:
1408 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom) 1414 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
@@ -2155,11 +2161,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2155 { 2161 {
2156 m_host.AddScriptLPS(1); 2162 m_host.AddScriptLPS(1);
2157 2163
2158 SetPos(m_host, pos); 2164 SetPos(m_host, pos, true);
2159 2165
2160 ScriptSleep(200); 2166 ScriptSleep(200);
2161 } 2167 }
2162 2168
2169 /// <summary>
2170 /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos
2171 /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into.
2172 /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking.
2173 /// </summary>
2174 /// <param name="pos"></param>
2175 /// <returns>1 if successful, 0 otherwise.</returns>
2176 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2177 {
2178 m_host.AddScriptLPS(1);
2179
2180 // BEGIN WORKAROUND
2181 // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
2182 //
2183 // This workaround is to prevent silent failure of this function.
2184 // According to the specification on the SL Wiki, providing a position outside of the
2185 if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize)
2186 {
2187 return 0;
2188 }
2189 // END WORK AROUND
2190 else if ( // this is not part of the workaround if-block because it's not related to the workaround.
2191 IsPhysical() ||
2192 m_host.ParentGroup.IsAttachment || // return FALSE if attachment
2193 (
2194 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
2195 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2196 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2197 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2198 pos.z > 4096 // return FALSE if altitude than 4096m
2199 )
2200 )
2201 {
2202 return 0;
2203 }
2204
2205 // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range.
2206 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
2207
2208 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
2209 LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y);
2210 LandData there = World.GetLandData((float)pos.x, (float)pos.y);
2211
2212 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
2213
2214 bool sameParcel = here.GlobalID == there.GlobalID;
2215
2216 if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)))
2217 {
2218 return 0;
2219 }
2220
2221 SetPos(m_host.ParentGroup.RootPart, pos, false);
2222
2223 return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0;
2224 }
2225
2163 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2226 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2164 // note linked setpos is capped "differently" 2227 // note linked setpos is capped "differently"
2165 private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end) 2228 private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
@@ -2191,55 +2254,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2191 return real_vec; 2254 return real_vec;
2192 } 2255 }
2193 2256
2194 public LSL_Integer llSetRegionPos(LSL_Vector pos) 2257 /// <summary>
2195 { 2258 /// set object position, optionally capping the distance.
2196 return new LSL_Integer(SetRegionPos(m_host, pos)); 2259 /// </summary>
2197 } 2260 /// <param name="part"></param>
2198 2261 /// <param name="targetPos"></param>
2199 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos) 2262 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
2200 { 2263 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2201 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2202 return 0;
2203
2204 SceneObjectGroup grp = part.ParentGroup;
2205
2206 if (grp.IsAttachment)
2207 return 0;
2208
2209 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2210 return 0;
2211
2212 if (targetPos.x < -10.0f || targetPos.x >= (float)Constants.RegionSize || targetPos.y < -10.0f || targetPos.y >= (float)Constants.RegionSize || targetPos.z < 0 || targetPos.z >= 4096.0f)
2213 return 0;
2214
2215 float constrainedX = (float)targetPos.x;
2216 float constrainedY = (float)targetPos.y;
2217
2218 if (constrainedX < 0.0f)
2219 constrainedX = 0.0f;
2220 if (constrainedY < 0.0f)
2221 constrainedY = 0.0f;
2222 if (constrainedX >= (float)Constants.RegionSize)
2223 constrainedX = (float)Constants.RegionSize - 0.1f;
2224 if (constrainedY >= (float)Constants.RegionSize)
2225 constrainedY = (float)Constants.RegionSize -0.1f;
2226
2227 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2228
2229 if (targetPos.z < ground)
2230 targetPos.z = ground;
2231
2232 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2233
2234 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2235 return 0;
2236
2237 grp.UpdateGroupPosition(dest);
2238
2239 return 1;
2240 }
2241
2242 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
2243 { 2264 {
2244 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 2265 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2245 return; 2266 return;