aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin/Meshing
diff options
context:
space:
mode:
authordan miller2007-11-05 12:25:53 +0000
committerdan miller2007-11-05 12:25:53 +0000
commitfdb57b28b164f239de0f976b967b79dc2ca5f6ae (patch)
treee998ae9c7dd6e248e794e35ca19678e3b6f6fad1 /OpenSim/Region/Physics/OdePlugin/Meshing
parentChanged it so opensim.exe should scan for new application plugins every time ... (diff)
downloadopensim-SC_OLD-fdb57b28b164f239de0f976b967b79dc2ca5f6ae.zip
opensim-SC_OLD-fdb57b28b164f239de0f976b967b79dc2ca5f6ae.tar.gz
opensim-SC_OLD-fdb57b28b164f239de0f976b967b79dc2ca5f6ae.tar.bz2
opensim-SC_OLD-fdb57b28b164f239de0f976b967b79dc2ca5f6ae.tar.xz
prim cuts in ODE
Much thanks to Gerhard! Merged with Darok's recent changes re: physical prims
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/Meshing')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs158
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs514
2 files changed, 238 insertions, 434 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs
index 13184e2..3b20af7 100644
--- a/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs
+++ b/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs
@@ -30,37 +30,63 @@ using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; 31using System.Diagnostics;
32using System.Globalization; 32using System.Globalization;
33using OpenSim.Framework.Console;
33using OpenSim.Region.Physics.Manager; 34using OpenSim.Region.Physics.Manager;
34 35
35public class Vertex : IComparable<Vertex> 36using OpenSim.Region.Physics.OdePlugin.Meshing;
37
38public class Vertex : PhysicsVector, IComparable<Vertex>
36{ 39{
37 public String name; 40 public Vertex(float x, float y, float z)
38 public PhysicsVector point; 41 : base(x, y, z)
42 {
43 }
44
45 public Vertex(PhysicsVector v)
46 : base(v.X, v.Y, v.Z)
47 {
48 }
49
50 public Vertex Clone()
51 {
52 return new Vertex(X, Y, Z);
53 }
54
55 public static Vertex FromAngle(double angle)
56 {
57 return new Vertex((float)Math.Cos(angle), (float)Math.Sin(angle), 0.0f);
58 }
59
39 60
40 public Vertex(String name, float x, float y, float z) 61 public virtual bool Equals(Vertex v, float tolerance)
41 { 62 {
42 this.name = name; 63 PhysicsVector diff = this - v;
43 point = new PhysicsVector(x, y, z); 64 float d = diff.length();
65 if (d < tolerance)
66 return true;
67
68 return false;
44 } 69 }
45 70
71
46 public int CompareTo(Vertex other) 72 public int CompareTo(Vertex other)
47 { 73 {
48 if (point.X < other.point.X) 74 if (X < other.X)
49 return -1; 75 return -1;
50 76
51 if (point.X > other.point.X) 77 if (X > other.X)
52 return 1; 78 return 1;
53 79
54 if (point.Y < other.point.Y) 80 if (Y < other.Y)
55 return -1; 81 return -1;
56 82
57 if (point.Y > other.point.Y) 83 if (Y > other.Y)
58 return 1; 84 return 1;
59 85
60 if (point.Z < other.point.Z) 86 if (Z < other.Z)
61 return -1; 87 return -1;
62 88
63 if (point.Z > other.point.Z) 89 if (Z > other.Z)
64 return 1; 90 return 1;
65 91
66 return 0; 92 return 0;
@@ -75,51 +101,24 @@ public class Vertex : IComparable<Vertex>
75 { 101 {
76 return me.CompareTo(other) < 0; 102 return me.CompareTo(other) < 0;
77 } 103 }
78} 104 public String ToRaw()
79
80public class Simplex : IComparable<Simplex>
81{
82 public Vertex v1;
83 public Vertex v2;
84
85 public Simplex(Vertex _v1, Vertex _v2)
86 {
87 // Presort indices to make sorting (comparing) easier
88 if (_v1 > _v2)
89 {
90 v1 = _v1;
91 v2 = _v2;
92 }
93 else
94 {
95 v1 = _v2;
96 v2 = _v1;
97 }
98 }
99
100 public int CompareTo(Simplex other)
101 { 105 {
102 if (v1 > other.v1) 106 // Why this stuff with the number formatter?
103 { 107 // Well, the raw format uses the english/US notation of numbers
104 return 1; 108 // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1.
105 } 109 // The german notation uses these characters exactly vice versa!
106 if (v1 < other.v1) 110 // The Float.ToString() routine is a localized one, giving different results depending on the country
107 { 111 // settings your machine works with. Unusable for a machine readable file format :-(
108 return -1; 112 NumberFormatInfo nfi = new NumberFormatInfo();
109 } 113 nfi.NumberDecimalSeparator = ".";
114 nfi.NumberDecimalDigits = 3;
110 115
111 if (v2 > other.v2) 116 String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi);
112 {
113 return 1;
114 }
115 if (v2 < other.v2)
116 {
117 return -1;
118 }
119 117
120 return 0; 118 return s1;
121 } 119 }
122} ; 120
121}
123 122
124public class Triangle 123public class Triangle
125{ 124{
@@ -155,6 +154,12 @@ public class Triangle
155 return false; 154 return false;
156 } 155 }
157 156
157 public bool isDegraded()
158 {
159 // This means, the vertices of this triangle are somewhat strange.
160 // They either line up or at least two of them are identical
161 return (radius_square == 0.0);
162 }
158 163
159 private void CalcCircle() 164 private void CalcCircle()
160 { 165 {
@@ -184,14 +189,14 @@ public class Triangle
184 double rx, ry; 189 double rx, ry;
185 190
186 // Readout the three points, the triangle consists of 191 // Readout the three points, the triangle consists of
187 p1x = v1.point.X; 192 p1x = v1.X;
188 p1y = v1.point.Y; 193 p1y = v1.Y;
189 194
190 p2x = v2.point.X; 195 p2x = v2.X;
191 p2y = v2.point.Y; 196 p2y = v2.Y;
192 197
193 p3x = v3.point.X; 198 p3x = v3.X;
194 p3y = v3.point.Y; 199 p3y = v3.Y;
195 200
196 /* calc helping values first */ 201 /* calc helping values first */
197 c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2; 202 c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2;
@@ -253,12 +258,9 @@ public class Triangle
253 nfi.CurrencyDecimalDigits = 2; 258 nfi.CurrencyDecimalDigits = 2;
254 nfi.CurrencyDecimalSeparator = "."; 259 nfi.CurrencyDecimalSeparator = ".";
255 260
256 String s1 = "<" + v1.point.X.ToString(nfi) + "," + v1.point.Y.ToString(nfi) + "," + v1.point.Z.ToString(nfi) + 261 String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">";
257 ">"; 262 String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">";
258 String s2 = "<" + v2.point.X.ToString(nfi) + "," + v2.point.Y.ToString(nfi) + "," + v2.point.Z.ToString(nfi) + 263 String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">";
259 ">";
260 String s3 = "<" + v3.point.X.ToString(nfi) + "," + v3.point.Y.ToString(nfi) + "," + v3.point.Z.ToString(nfi) +
261 ">";
262 264
263 return s1 + ";" + s2 + ";" + s3; 265 return s1 + ";" + s2 + ";" + s3;
264 } 266 }
@@ -271,23 +273,17 @@ public class Triangle
271 PhysicsVector e1; 273 PhysicsVector e1;
272 PhysicsVector e2; 274 PhysicsVector e2;
273 275
274 e1 = new PhysicsVector(v1.point.X - v2.point.X, v1.point.Y - v2.point.Y, v1.point.Z - v2.point.Z); 276 e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
275 e2 = new PhysicsVector(v1.point.X - v3.point.X, v1.point.Y - v3.point.Y, v1.point.Z - v3.point.Z); 277 e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
276 278
277 // Cross product for normal 279 // Cross product for normal
278 PhysicsVector n = new PhysicsVector(); 280 PhysicsVector n = PhysicsVector.cross(e1, e2);
279 float nx, ny, nz;
280 n.X = e1.Y*e2.Z - e1.Z*e2.Y;
281 n.Y = e1.Z*e2.X - e1.X*e2.Z;
282 n.Z = e1.X*e2.Y - e1.Y*e2.X;
283 281
284 // Length 282 // Length
285 float l = (float) Math.Sqrt(n.X*n.X + n.Y*n.Y + n.Z*n.Z); 283 float l = n.length();
286 284
287 // Normalized "normal" 285 // Normalized "normal"
288 n.X /= l; 286 n = n / l;
289 n.Y /= l;
290 n.Z /= l;
291 287
292 return n; 288 return n;
293 } 289 }
@@ -299,4 +295,12 @@ public class Triangle
299 v1 = v2; 295 v1 = v2;
300 v2 = vt; 296 v2 = vt;
301 } 297 }
302} \ No newline at end of file 298
299 // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and
300 // debugging purposes
301 public String ToStringRaw()
302 {
303 String output = v1.ToRaw() + " " + v2.ToRaw() + " " +v3.ToRaw();
304 return output;
305 }
306}
diff --git a/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
index 46de15e..2a304cb 100644
--- a/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
@@ -27,109 +27,70 @@
27*/ 27*/
28 28
29using System; 29using System;
30using System.IO;
31using System.Globalization;
32using System.Diagnostics;
30using System.Collections.Generic; 33using System.Collections.Generic;
31using System.Runtime.InteropServices; 34using System.Runtime.InteropServices;
32using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Console;
33using OpenSim.Region.Physics.Manager; 37using OpenSim.Region.Physics.Manager;
34 38
35namespace OpenSim.Region.Physics.OdePlugin 39namespace OpenSim.Region.Physics.OdePlugin.Meshing
36{ 40{
37 public class Mesh
38 {
39 public List<Vertex> vertices;
40 public List<Triangle> triangles;
41
42 public float[] normals;
43
44 public Mesh()
45 {
46 vertices = new List<Vertex>();
47 triangles = new List<Triangle>();
48 }
49
50 public void Add(Triangle triangle)
51 {
52 int i;
53 i = vertices.IndexOf(triangle.v1);
54 if (i < 0)
55 throw new ArgumentException("Vertex v1 not known to mesh");
56 i = vertices.IndexOf(triangle.v2);
57 if (i < 0)
58 throw new ArgumentException("Vertex v2 not known to mesh");
59 i = vertices.IndexOf(triangle.v3);
60 if (i < 0)
61 throw new ArgumentException("Vertex v3 not known to mesh");
62
63 triangles.Add(triangle);
64 }
65
66 public void Add(Vertex v)
67 {
68 vertices.Add(v);
69 }
70
71
72 public float[] getVertexListAsFloat()
73 {
74 float[] result = new float[vertices.Count*3];
75 for (int i = 0; i < vertices.Count; i++)
76 {
77 Vertex v = vertices[i];
78 PhysicsVector point = v.point;
79 result[3*i + 0] = point.X;
80 result[3*i + 1] = point.Y;
81 result[3*i + 2] = point.Z;
82 }
83 GCHandle.Alloc(result, GCHandleType.Pinned);
84 return result;
85 }
86 41
87 public int[] getIndexListAsInt() 42 public class Meshmerizer
88 { 43 {
89 int[] result = new int[triangles.Count*3]; 44 // Setting baseDir to a path will enable the dumping of raw files
90 for (int i = 0; i < triangles.Count; i++) 45 // raw files can be imported by blender so a visual inspection of the results can be done
46 // const string baseDir = "rawFiles";
47 const string baseDir = null;
48
49 static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
50 {
51 // p1, p2, points on the straight
52 // r1, r2, directional vectors of the straight. Not necessarily of length 1!
53 // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
54 // thus allowing to decide whether an intersection is between two points
55
56 float r1x = r1.X;
57 float r1y = r1.Y;
58 float r2x = r2.X;
59 float r2y = r2.Y;
60
61 float denom = r1y*r2x - r1x*r2y;
62
63 if (denom == 0.0)
91 { 64 {
92 Triangle t = triangles[i]; 65 lambda = Single.NaN;
93 result[3*i + 0] = vertices.IndexOf(t.v1); 66 mu = Single.NaN;
94 result[3*i + 1] = vertices.IndexOf(t.v2); 67 return;
95 result[3*i + 2] = vertices.IndexOf(t.v3);
96 } 68 }
97 GCHandle.Alloc(result, GCHandleType.Pinned);
98 return result;
99 }
100
101 69
102 public void Append(Mesh newMesh) 70 float p1x = p1.X;
103 { 71 float p1y = p1.Y;
104 foreach (Vertex v in newMesh.vertices) 72 float p2x = p2.X;
105 vertices.Add(v); 73 float p2y = p2.Y;
106 74 lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom;
107 foreach (Triangle t in newMesh.triangles) 75 mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom;
108 Add(t); 76
109 } 77 }
110 }
111
112 78
113 public class Meshmerizer
114 {
115 private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v) 79 private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
116 { 80 {
117 List<Triangle> influenced = new List<Triangle>(); 81 List<Triangle> influenced = new List<Triangle>();
118 foreach (Triangle t in triangles) 82 foreach (Triangle t in triangles)
119 { 83 {
120 float dx, dy; 84 if (t.isInCircle(v.X, v.Y))
121
122 if (t.isInCircle(v.point.X, v.point.Y))
123 { 85 {
124 influenced.Add(t); 86 influenced.Add(t);
125 } 87 }
126 } 88 }
127 return influenced; 89 return influenced;
128 } 90 }
129 91
130 92
131 private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles, 93 private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
132 List<int> innerBorders)
133 { 94 {
134 // This is a variant of the delaunay algorithm 95 // This is a variant of the delaunay algorithm
135 // each time a new vertex is inserted, all triangles that are influenced by it are deleted 96 // each time a new vertex is inserted, all triangles that are influenced by it are deleted
@@ -148,8 +109,10 @@ namespace OpenSim.Region.Physics.OdePlugin
148 // do not fulfill this condition with respect to the new triangle 109 // do not fulfill this condition with respect to the new triangle
149 110
150 // Find the triangles that are influenced by the new vertex 111 // Find the triangles that are influenced by the new vertex
151 Vertex v = vertices[iCurrentVertex]; 112 Vertex v=vertices[iCurrentVertex];
152 List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v); 113 if (v == null)
114 continue; // Null is polygon stop marker. Ignore it
115 List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v);
153 116
154 List<Simplex> simplices = new List<Simplex>(); 117 List<Simplex> simplices = new List<Simplex>();
155 118
@@ -163,11 +126,12 @@ namespace OpenSim.Region.Physics.OdePlugin
163 simplices.AddRange(newSimplices); 126 simplices.AddRange(newSimplices);
164 triangles.Remove(t); 127 triangles.Remove(t);
165 } 128 }
166 // Now sort the simplices. That will make identical ones side by side in the list 129 // Now sort the simplices. That will make identical ones reside side by side in the list
167 simplices.Sort(); 130 simplices.Sort();
168 131
169 // Look for duplicate simplices here. 132 // Look for duplicate simplices here.
170 // Remember, they are directly side by side in the list right now 133 // Remember, they are directly side by side in the list right now,
134 // So we only check directly neighbours
171 int iSimplex; 135 int iSimplex;
172 List<Simplex> innerSimplices = new List<Simplex>(); 136 List<Simplex> innerSimplices = new List<Simplex>();
173 for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards 137 for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
@@ -186,310 +150,145 @@ namespace OpenSim.Region.Physics.OdePlugin
186 150
187 // each simplex still in the list belongs to the hull of the region in question 151 // each simplex still in the list belongs to the hull of the region in question
188 // The new vertex (yes, we still deal with verices here :-) ) forms a triangle 152 // The new vertex (yes, we still deal with verices here :-) ) forms a triangle
189 // With each of these simplices. Build the new triangles and add them to the list 153 // with each of these simplices. Build the new triangles and add them to the list
190 foreach (Simplex s in simplices) 154 foreach (Simplex s in simplices)
191 { 155 {
192 Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); 156 Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
193 triangles.Add(t); 157 if (!t.isDegraded())
158 {
159 triangles.Add(t);
160 }
194 } 161 }
195 } 162 }
196 163
197 // At this point all vertices should be inserted into the mesh
198 // But the areas, that should be kept free still are filled with triangles
199 // We have to remove them. For this we have a list of indices to vertices.
200 // Each triangle that solemnly constists of vertices from the inner border
201 // are deleted
202
203 List<Triangle> innerTriangles = new List<Triangle>();
204 foreach (Triangle t in triangles)
205 {
206 if (
207 innerBorders.Contains(vertices.IndexOf(t.v1))
208 && innerBorders.Contains(vertices.IndexOf(t.v2))
209 && innerBorders.Contains(vertices.IndexOf(t.v3))
210 )
211 innerTriangles.Add(t);
212 }
213 foreach (Triangle t in innerTriangles)
214 {
215 triangles.Remove(t);
216 }
217 } 164 }
218 165
219 166
220 private static Mesh CreateBoxMeshX(PrimitiveBaseShape primShape, PhysicsVector size) 167 static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
221 // Builds the x (+ and -) surfaces of a box shaped prim 168 // Builds the z (+ and -) surfaces of a box shaped prim
222 { 169 {
223 UInt16 hollowFactor = primShape.ProfileHollow; 170 UInt16 hollowFactor = primShape.ProfileHollow;
224 Mesh meshMX = new Mesh(); 171 UInt16 profileBegin = primShape.ProfileBegin;
225 172 UInt16 profileEnd = primShape.ProfileEnd;
226 173
227 // Surface 0, -X 174 // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
228 meshMX.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f)); 175 // of a block are basically the same
229 meshMX.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f)); 176 // They may be warped differently but the shape is identical
230 meshMX.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f)); 177 // So we only create one surface as a model and derive both plus and minus surface of the block from it
231 meshMX.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f)); 178 // This is done in a model space where the block spans from -.5 to +.5 in X and Y
232 179 // The mapping to Scene space is done later during the "extrusion" phase
233 meshMX.Add(new Triangle(meshMX.vertices[0], meshMX.vertices[2], meshMX.vertices[1])); 180
234 meshMX.Add(new Triangle(meshMX.vertices[1], meshMX.vertices[2], meshMX.vertices[3])); 181 // Base
235 182 Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
236 183 Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
237 Mesh meshPX = new Mesh(); 184 Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
238 // Surface 1, +X 185 Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
239 meshPX.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f)); 186
240 meshPX.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f)); 187 Meshing.SimpleHull outerHull = new SimpleHull();
241 meshPX.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f)); 188 outerHull.AddVertex(MM);
242 meshPX.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f)); 189 outerHull.AddVertex(PM);
243 190 outerHull.AddVertex(PP);
244 191 outerHull.AddVertex(MP);
245 meshPX.Add(new Triangle(meshPX.vertices[0], meshPX.vertices[1], meshPX.vertices[2])); 192
246 meshPX.Add(new Triangle(meshPX.vertices[2], meshPX.vertices[1], meshPX.vertices[3])); 193 // Deal with cuts now
247 194 if ((profileBegin != 0) || (profileEnd != 0))
248
249 if (hollowFactor > 0)
250 { 195 {
251 float hollowFactorF = (float) hollowFactor/(float) 50000; 196 double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding
252 197 fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
253 Vertex IPP; 198 double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
254 Vertex IPM; 199 fProfileEndAngle -= (90.0 + 45.0);
255 Vertex IMP; 200 if (fProfileBeginAngle < fProfileEndAngle)
256 Vertex IMM; 201 fProfileEndAngle -= 360.0;
257 202
258 IPP = new Vertex("Inner-X+Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f); 203 // Note, that we don't want to cut out a triangle, even if this is a
259 IPM = new Vertex("Inner-X+Y-Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f); 204 // good approximation for small cuts. Indeed we want to cut out an arc
260 IMP = new Vertex("Inner-X-Y+Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f); 205 // and we approximate this arc by a polygon chain
261 IMM = new Vertex("Inner-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f); 206 // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
262 207 // So it can easily be subtracted from the outer hull
263 meshMX.Add(IPP); 208 int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree
264 meshMX.Add(IPM); 209 double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps;
265 meshMX.Add(IMP); 210
266 meshMX.Add(IMM); 211 Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
267 212
268 meshMX.Add(new Triangle(IPP, IMP, IPM)); 213 // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
269 meshMX.Add(new Triangle(IPM, IMP, IMM)); 214 SimpleHull cutHull = new SimpleHull();
270 215 cutHull.AddVertex(origin);
271 foreach (Triangle t in meshMX.triangles) 216 for (int i=0; i<iSteps; i++) {
272 { 217 double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!!
273 PhysicsVector n = t.getNormal(); 218 Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
219 cutHull.AddVertex(v);
274 } 220 }
221 Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors
222 cutHull.AddVertex(legEnd);
275 223
224 MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName);
225 SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
276 226
277 IPP = new Vertex("Inner+X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f); 227 outerHull = cuttedHull;
278 IPM = new Vertex("Inner+X+Y-Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
279 IMP = new Vertex("Inner+X-Y+Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
280 IMM = new Vertex("Inner+X-Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
281
282 meshPX.Add(IPP);
283 meshPX.Add(IPM);
284 meshPX.Add(IMP);
285 meshPX.Add(IMM);
286
287 meshPX.Add(new Triangle(IPP, IPM, IMP));
288 meshPX.Add(new Triangle(IMP, IPM, IMM));
289
290 foreach (Triangle t in meshPX.triangles)
291 {
292 PhysicsVector n = t.getNormal();
293 }
294 } 228 }
295 229
296 Mesh result = new Mesh(); 230 // Deal with the hole here
297 result.Append(meshMX);
298 result.Append(meshPX);
299
300 return result;
301 }
302
303
304 private static Mesh CreateBoxMeshY(PrimitiveBaseShape primShape, PhysicsVector size)
305 // Builds the y (+ and -) surfaces of a box shaped prim
306 {
307 UInt16 hollowFactor = primShape.ProfileHollow;
308
309 // (M)inus Y
310 Mesh MeshMY = new Mesh();
311 MeshMY.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
312 MeshMY.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
313 MeshMY.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
314 MeshMY.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
315
316 MeshMY.Add(new Triangle(MeshMY.vertices[0], MeshMY.vertices[1], MeshMY.vertices[2]));
317 MeshMY.Add(new Triangle(MeshMY.vertices[2], MeshMY.vertices[1], MeshMY.vertices[3]));
318
319 // (P)lus Y
320 Mesh MeshPY = new Mesh();
321
322 MeshPY.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
323 MeshPY.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
324 MeshPY.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
325 MeshPY.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
326
327 MeshPY.Add(new Triangle(MeshPY.vertices[1], MeshPY.vertices[0], MeshPY.vertices[2]));
328 MeshPY.Add(new Triangle(MeshPY.vertices[1], MeshPY.vertices[2], MeshPY.vertices[3]));
329
330 if (hollowFactor > 0) 231 if (hollowFactor > 0)
331 { 232 {
332 float hollowFactorF = (float) hollowFactor/(float) 50000; 233 float hollowFactorF = (float) hollowFactor/(float) 50000;
234 Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
235 Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
236 Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
237 Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
333 238
334 Vertex IPP; 239 SimpleHull holeHull = new SimpleHull();
335 Vertex IPM;
336 Vertex IMP;
337 Vertex IMM;
338 240
339 IPP = new Vertex("Inner+X-Y+Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f); 241 holeHull.AddVertex(IMM);
340 IPM = new Vertex("Inner+X-Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f); 242 holeHull.AddVertex(IMP);
341 IMP = new Vertex("Inner-X-Y+Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f); 243 holeHull.AddVertex(IPP);
342 IMM = new Vertex("Inner-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f); 244 holeHull.AddVertex(IPM);
343 245
344 MeshMY.Add(IPP); 246 SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
345 MeshMY.Add(IPM);
346 MeshMY.Add(IMP);
347 MeshMY.Add(IMM);
348 247
349 MeshMY.Add(new Triangle(IPP, IPM, IMP)); 248 outerHull = hollowedHull;
350 MeshMY.Add(new Triangle(IMP, IPM, IMM));
351 249
352 foreach (Triangle t in MeshMY.triangles)
353 {
354 PhysicsVector n = t.getNormal();
355 }
356
357
358 IPP = new Vertex("Inner+X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
359 IPM = new Vertex("Inner+X+Y-Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
360 IMP = new Vertex("Inner-X+Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
361 IMM = new Vertex("Inner-X+Y-Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
362
363 MeshPY.Add(IPP);
364 MeshPY.Add(IPM);
365 MeshPY.Add(IMP);
366 MeshPY.Add(IMM);
367
368 MeshPY.Add(new Triangle(IPM, IPP, IMP));
369 MeshPY.Add(new Triangle(IMP, IMM, IPM));
370
371 foreach (Triangle t in MeshPY.triangles)
372 {
373 PhysicsVector n = t.getNormal();
374 }
375 } 250 }
376 251
252 Mesh m = new Mesh();
377 253
378 Mesh result = new Mesh(); 254 Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
379 result.Append(MeshMY); 255 Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
380 result.Append(MeshPY); 256 Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
381
382 return result;
383 }
384
385 private static Mesh CreateBoxMeshZ(PrimitiveBaseShape primShape, PhysicsVector size)
386 // Builds the z (+ and -) surfaces of a box shaped prim
387 {
388 UInt16 hollowFactor = primShape.ProfileHollow;
389
390 // Base, i.e. outer shape
391 // (M)inus Z
392 Mesh MZ = new Mesh();
393
394 MZ.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
395 MZ.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
396 MZ.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
397 MZ.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
398 257
258 m.Add(Seed1);
259 m.Add(Seed2);
260 m.Add(Seed3);
399 261
400 MZ.Add(new Triangle(MZ.vertices[1], MZ.vertices[0], MZ.vertices[2])); 262 m.Add(new Triangle(Seed1, Seed2, Seed3));
401 MZ.Add(new Triangle(MZ.vertices[1], MZ.vertices[2], MZ.vertices[3])); 263 m.Add(outerHull.getVertices());
402 264
403 // (P)lus Z 265 InsertVertices(m.vertices, 3, m.triangles);
404 Mesh PZ = new Mesh(); 266 m.DumpRaw(baseDir, primName, "Proto first Mesh");
405 267
406 PZ.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, 0.0f)); 268 m.Remove(Seed1);
407 PZ.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, 0.0f)); 269 m.Remove(Seed2);
408 PZ.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, 0.0f)); 270 m.Remove(Seed3);
409 PZ.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, 0.0f)); 271 m.DumpRaw(baseDir, primName, "Proto seeds removed");
272
273 m.RemoveTrianglesOutside(outerHull);
274 m.DumpRaw(baseDir, primName, "Proto outsides removed");
410 275
411 // Surface 5, +Z 276 foreach (Triangle t in m.triangles)
412 PZ.Add(new Triangle(PZ.vertices[0], PZ.vertices[1], PZ.vertices[2]));
413 PZ.Add(new Triangle(PZ.vertices[2], PZ.vertices[1], PZ.vertices[3]));
414
415 if (hollowFactor > 0)
416 {
417 float hollowFactorF = (float) hollowFactor/(float) 50000;
418
419 MZ.Add(new Vertex("-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
420 MZ.Add(new Vertex("-X+Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
421 MZ.Add(new Vertex("-X-Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
422 MZ.Add(new Vertex("-X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
423
424 List<int> innerBorders = new List<int>();
425 innerBorders.Add(4);
426 innerBorders.Add(5);
427 innerBorders.Add(6);
428 innerBorders.Add(7);
429
430 InsertVertices(MZ.vertices, 4, MZ.triangles, innerBorders);
431
432 PZ.Add(new Vertex("-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
433 PZ.Add(new Vertex("-X+Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
434 PZ.Add(new Vertex("-X-Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
435 PZ.Add(new Vertex("-X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
436
437 innerBorders = new List<int>();
438 innerBorders.Add(4);
439 innerBorders.Add(5);
440 innerBorders.Add(6);
441 innerBorders.Add(7);
442
443 InsertVertices(PZ.vertices, 4, PZ.triangles, innerBorders);
444 }
445
446 foreach (Vertex v in PZ.vertices)
447 {
448 v.point.Z = size.Z/2.0f;
449 }
450 foreach (Vertex v in MZ.vertices)
451 {
452 v.point.Z = -size.Z/2.0f;
453 }
454
455 foreach (Triangle t in MZ.triangles)
456 {
457 PhysicsVector n = t.getNormal();
458 if (n.Z > 0.0)
459 t.invertNormal();
460 }
461
462 foreach (Triangle t in PZ.triangles)
463 { 277 {
464 PhysicsVector n = t.getNormal(); 278 PhysicsVector n = t.getNormal();
465 if (n.Z < 0.0) 279 if (n.Z < 0.0)
466 t.invertNormal(); 280 t.invertNormal();
467 } 281 }
468 282
469 Mesh result = new Mesh(); 283 Extruder extr = new Extruder();
470 result.Append(MZ);
471 result.Append(PZ);
472 284
473 return result; 285 extr.size = size;
474 }
475
476 private static Mesh CreateBoxMesh(PrimitiveBaseShape primShape, PhysicsVector size)
477 {
478 Mesh result = new Mesh();
479
480
481 Mesh MeshX = CreateBoxMeshX(primShape, size);
482 Mesh MeshY = CreateBoxMeshY(primShape, size);
483 Mesh MeshZ = CreateBoxMeshZ(primShape, size);
484
485 result.Append(MeshX);
486 result.Append(MeshY);
487 result.Append(MeshZ);
488 286
287 Mesh result = extr.Extrude(m);
288 result.DumpRaw(baseDir, primName, "Z extruded");
489 return result; 289 return result;
490 } 290 }
491 291
492
493 public static void CalcNormals(Mesh mesh) 292 public static void CalcNormals(Mesh mesh)
494 { 293 {
495 int iTriangles = mesh.triangles.Count; 294 int iTriangles = mesh.triangles.Count;
@@ -503,17 +302,18 @@ namespace OpenSim.Region.Physics.OdePlugin
503 float vx, vy, vz; 302 float vx, vy, vz;
504 float wx, wy, wz; 303 float wx, wy, wz;
505 304
506 ux = t.v1.point.X; 305 ux = t.v1.X;
507 uy = t.v1.point.Y; 306 uy = t.v1.Y;
508 uz = t.v1.point.Z; 307 uz = t.v1.Z;
308
309 vx = t.v2.X;
310 vy = t.v2.Y;
311 vz = t.v2.Z;
509 312
510 vx = t.v2.point.X; 313 wx = t.v3.X;
511 vy = t.v2.point.Y; 314 wy = t.v3.Y;
512 vz = t.v2.point.Z; 315 wz = t.v3.Z;
513 316
514 wx = t.v3.point.X;
515 wy = t.v3.point.Y;
516 wz = t.v3.point.Z;
517 317
518 // Vectors for edges 318 // Vectors for edges
519 float e1x, e1y, e1z; 319 float e1x, e1y, e1z;
@@ -550,14 +350,14 @@ namespace OpenSim.Region.Physics.OdePlugin
550 } 350 }
551 } 351 }
552 352
553 public static Mesh CreateMesh(PrimitiveBaseShape primShape, PhysicsVector size) 353 public static Mesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
554 { 354 {
555 Mesh mesh = null; 355 Mesh mesh = null;
556 356
557 switch (primShape.ProfileShape) 357 switch (primShape.ProfileShape)
558 { 358 {
559 case ProfileShape.Square: 359 case ProfileShape.Square:
560 mesh = CreateBoxMesh(primShape, size); 360 mesh=CreateBoxMesh(primName, primShape, size);
561 CalcNormals(mesh); 361 CalcNormals(mesh);
562 break; 362 break;
563 default: 363 default:
@@ -568,4 +368,4 @@ namespace OpenSim.Region.Physics.OdePlugin
568 return mesh; 368 return mesh;
569 } 369 }
570 } 370 }
571} \ No newline at end of file 371}