aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin
diff options
context:
space:
mode:
authordan miller2007-09-29 04:08:33 +0000
committerdan miller2007-09-29 04:08:33 +0000
commitc1d3e93fbb3284b38b85294d43189001bfce5214 (patch)
treeb79de3dec16f268822463165040c3263b65bea66 /OpenSim/Region/Physics/OdePlugin
parentHollow prims (box only), thanks Gerard! Enjoy (diff)
downloadopensim-SC-c1d3e93fbb3284b38b85294d43189001bfce5214.zip
opensim-SC-c1d3e93fbb3284b38b85294d43189001bfce5214.tar.gz
opensim-SC-c1d3e93fbb3284b38b85294d43189001bfce5214.tar.bz2
opensim-SC-c1d3e93fbb3284b38b85294d43189001bfce5214.tar.xz
Hollow prims (box only), thanks Gerard! Enjoy
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Meshing\/HelperTypes.cs279
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Meshing\/Meshmerizer.cs560
2 files changed, 839 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/Meshing\/HelperTypes.cs b/OpenSim/Region/Physics/OdePlugin/Meshing\/HelperTypes.cs
new file mode 100644
index 0000000..3d40c04
--- /dev/null
+++ b/OpenSim/Region/Physics/OdePlugin/Meshing\/HelperTypes.cs
@@ -0,0 +1,279 @@
1using System;
2using System.Globalization;
3using System.Diagnostics;
4using System.Collections.Generic;
5
6using OpenSim.Region.Physics.Manager;
7
8public class Vertex : IComparable<Vertex>
9{
10 public String name;
11 public PhysicsVector point;
12
13 public Vertex(String name, float x, float y, float z)
14 {
15 this.name = name;
16 point = new PhysicsVector(x, y, z);
17 }
18
19 public int CompareTo(Vertex other)
20 {
21 if (point.X < other.point.X)
22 return -1;
23
24 if (point.X > other.point.X)
25 return 1;
26
27 if (point.Y < other.point.Y)
28 return -1;
29
30 if (point.Y > other.point.Y)
31 return 1;
32
33 if (point.Z < other.point.Z)
34 return -1;
35
36 if (point.Z > other.point.Z)
37 return 1;
38
39 return 0;
40 }
41
42 public static bool operator >(Vertex me, Vertex other)
43 {
44 return me.CompareTo(other) > 0;
45 }
46
47 public static bool operator <(Vertex me, Vertex other)
48 {
49 return me.CompareTo(other) < 0;
50 }
51
52
53}
54
55public class Simplex : IComparable<Simplex>
56{
57 public Vertex v1;
58 public Vertex v2;
59
60 public Simplex(Vertex _v1, Vertex _v2)
61 {
62 // Presort indices to make sorting (comparing) easier
63 if (_v1 > _v2)
64 {
65 v1 = _v1;
66 v2 = _v2;
67 }
68 else
69 {
70 v1 = _v2;
71 v2 = _v1;
72 }
73 }
74
75 public int CompareTo(Simplex other)
76 {
77 if (v1 > other.v1)
78 {
79 return 1;
80 }
81 if (v1 < other.v1)
82 {
83 return -1;
84 }
85
86 if (v2 > other.v2)
87 {
88 return 1;
89 }
90 if (v2 < other.v2)
91 {
92 return -1;
93 }
94
95 return 0;
96 }
97
98};
99
100public class Triangle
101{
102 public Vertex v1;
103 public Vertex v2;
104 public Vertex v3;
105
106 float radius_square;
107 float cx;
108 float cy;
109
110 public Triangle(Vertex _v1, Vertex _v2, Vertex _v3)
111 {
112 v1 = _v1;
113 v2 = _v2;
114 v3 = _v3;
115
116 CalcCircle();
117 }
118
119 public bool isInCircle(float x, float y)
120 {
121 float dx, dy;
122 float dd;
123
124 dx = x - this.cx;
125 dy = y - this.cy;
126
127 dd = dx * dx + dy * dy;
128 if (dd < this.radius_square)
129 return true;
130 else
131 return false;
132 }
133
134
135 void CalcCircle()
136 {
137 // Calculate the center and the radius of a circle given by three points p1, p2, p3
138 // It is assumed, that the triangles vertices are already set correctly
139 double p1x, p2x, p1y, p2y, p3x, p3y;
140
141 // Deviation of this routine:
142 // A circle has the general equation (M-p)^2=r^2, where M and p are vectors
143 // this gives us three equations f(p)=r^2, each for one point p1, p2, p3
144 // putting respectively two equations together gives two equations
145 // f(p1)=f(p2) and f(p1)=f(p3)
146 // bringing all constant terms to one side brings them to the form
147 // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors)
148 // and c1, c2 are scalars (Naming conventions like the variables below)
149 // Now using the equations that are formed by the components of the vectors
150 // and isolate Mx lets you make one equation that only holds My
151 // The rest is straight forward and eaasy :-)
152 //
153
154 /* helping variables for temporary results */
155 double c1, c2;
156 double v1x, v1y, v2x, v2y;
157
158 double z, n;
159
160 double rx, ry;
161
162 // Readout the three points, the triangle consists of
163 p1x = v1.point.X;
164 p1y = v1.point.Y;
165
166 p2x = v2.point.X;
167 p2y = v2.point.Y;
168
169 p3x = v3.point.X;
170 p3y = v3.point.Y;
171
172 /* calc helping values first */
173 c1 = (p1x * p1x + p1y * p1y - p2x * p2x - p2y * p2y) / 2;
174 c2 = (p1x * p1x + p1y * p1y - p3x * p3x - p3y * p3y) / 2;
175
176 v1x = p1x - p2x;
177 v1y = p1y - p2y;
178
179 v2x = p1x - p3x;
180 v2y = p1y - p3y;
181
182 z = (c1 * v2x - c2 * v1x);
183 n = (v1y * v2x - v2y * v1x);
184
185 if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location
186 {
187 radius_square = 0.0f;
188 return;
189 }
190
191 this.cy = (float)(z / n);
192
193 if (v2x != 0.0)
194 {
195 this.cx = (float)((c2 - v2y * this.cy) / v2x);
196 }
197 else if (v1x != 0.0)
198 {
199 this.cx = (float)((c1 - v1y * this.cy) / v1x);
200 }
201 else
202 {
203 Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */
204 }
205
206 rx = (p1x - this.cx);
207 ry = (p1y - this.cy);
208
209 this.radius_square = (float)(rx * rx + ry * ry);
210
211 }
212
213 public List<Simplex> GetSimplices()
214 {
215 List<Simplex> result = new List<Simplex>();
216 Simplex s1 = new Simplex(v1, v2);
217 Simplex s2 = new Simplex(v2, v3);
218 Simplex s3 = new Simplex(v3, v1);
219
220 result.Add(s1);
221 result.Add(s2);
222 result.Add(s3);
223
224 return result;
225 }
226
227 public override String ToString()
228 {
229
230 NumberFormatInfo nfi = new NumberFormatInfo();
231 nfi.CurrencyDecimalDigits = 2;
232 nfi.CurrencyDecimalSeparator = ".";
233
234 String s1 = "<" + v1.point.X.ToString(nfi) + "," + v1.point.Y.ToString(nfi) + "," + v1.point.Z.ToString(nfi) + ">";
235 String s2 = "<" + v2.point.X.ToString(nfi) + "," + v2.point.Y.ToString(nfi) + "," + v2.point.Z.ToString(nfi) + ">";
236 String s3 = "<" + v3.point.X.ToString(nfi) + "," + v3.point.Y.ToString(nfi) + "," + v3.point.Z.ToString(nfi) + ">";
237
238 return s1 + ";" + s2 + ";" + s3;
239
240 }
241
242 public PhysicsVector getNormal()
243 {
244 // Vertices
245
246 // Vectors for edges
247 PhysicsVector e1;
248 PhysicsVector e2;
249
250 e1 = new PhysicsVector(v1.point.X - v2.point.X, v1.point.Y - v2.point.Y, v1.point.Z - v2.point.Z);
251 e2 = new PhysicsVector(v1.point.X - v3.point.X, v1.point.Y - v3.point.Y, v1.point.Z - v3.point.Z);
252
253 // Cross product for normal
254 PhysicsVector n = new PhysicsVector();
255 float nx, ny, nz;
256 n.X = e1.Y * e2.Z - e1.Z * e2.Y;
257 n.Y = e1.Z * e2.X - e1.X * e2.Z;
258 n.Z = e1.X * e2.Y - e1.Y * e2.X;
259
260 // Length
261 float l = (float)Math.Sqrt(n.X * n.X + n.Y * n.Y + n.Z * n.Z);
262
263 // Normalized "normal"
264 n.X /= l;
265 n.Y /= l;
266 n.Z /= l;
267
268 return n;
269 }
270
271 public void invertNormal()
272 {
273 Vertex vt;
274 vt = v1;
275 v1 = v2;
276 v2 = vt;
277 }
278}
279
diff --git a/OpenSim/Region/Physics/OdePlugin/Meshing\/Meshmerizer.cs b/OpenSim/Region/Physics/OdePlugin/Meshing\/Meshmerizer.cs
new file mode 100644
index 0000000..28dca41
--- /dev/null
+++ b/OpenSim/Region/Physics/OdePlugin/Meshing\/Meshmerizer.cs
@@ -0,0 +1,560 @@
1using System;
2using System.Globalization;
3using System.Diagnostics;
4using System.Collections.Generic;
5using System.Text;
6using System.Runtime.InteropServices;
7
8using OpenSim.Framework.Types;
9using OpenSim.Region.Physics.Manager;
10
11namespace OpenSim.Region.Physics.OdePlugin
12{
13 public class Mesh
14 {
15 public List<Vertex> vertices;
16 public List<Triangle> triangles;
17
18 public float[] normals;
19
20 public Mesh()
21 {
22 vertices = new List<Vertex>();
23 triangles = new List<Triangle>();
24 }
25
26 public void Add(Triangle triangle)
27 {
28 int i;
29 i = vertices.IndexOf(triangle.v1);
30 if (i < 0)
31 throw new ArgumentException("Vertex v1 not known to mesh");
32 i = vertices.IndexOf(triangle.v2);
33 if (i < 0)
34 throw new ArgumentException("Vertex v2 not known to mesh");
35 i = vertices.IndexOf(triangle.v3);
36 if (i < 0)
37 throw new ArgumentException("Vertex v3 not known to mesh");
38
39 triangles.Add(triangle);
40 }
41
42 public void Add(Vertex v)
43 {
44 vertices.Add(v);
45 }
46
47
48 public float[] getVertexListAsFloat()
49 {
50 float[] result = new float[vertices.Count * 3];
51 for (int i = 0; i < vertices.Count; i++)
52 {
53 Vertex v = vertices[i];
54 PhysicsVector point = v.point;
55 result[3 * i + 0] = point.X;
56 result[3 * i + 1] = point.Y;
57 result[3 * i + 2] = point.Z;
58 }
59 GCHandle.Alloc(result, GCHandleType.Pinned);
60 return result;
61 }
62
63 public int[] getIndexListAsInt()
64 {
65 int[] result = new int[triangles.Count * 3];
66 for (int i = 0; i < triangles.Count; i++)
67 {
68 Triangle t = triangles[i];
69 result[3 * i + 0] = vertices.IndexOf(t.v1);
70 result[3 * i + 1] = vertices.IndexOf(t.v2);
71 result[3 * i + 2] = vertices.IndexOf(t.v3);
72 }
73 GCHandle.Alloc(result, GCHandleType.Pinned);
74 return result;
75 }
76
77
78 public void Append(Mesh newMesh)
79 {
80 foreach (Vertex v in newMesh.vertices)
81 vertices.Add(v);
82
83 foreach (Triangle t in newMesh.triangles)
84 Add(t);
85
86 }
87 }
88
89
90
91 public class Meshmerizer
92 {
93
94 static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
95 {
96 List<Triangle> influenced = new List<Triangle>();
97 foreach (Triangle t in triangles)
98 {
99 float dx, dy;
100
101 if (t.isInCircle(v.point.X, v.point.Y))
102 {
103 influenced.Add(t);
104 }
105 }
106 return influenced;
107 }
108
109
110 static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles, List<int> innerBorders)
111 {
112 // This is a variant of the delaunay algorithm
113 // each time a new vertex is inserted, all triangles that are influenced by it are deleted
114 // and replaced by new ones including the new vertex
115 // It is not very time efficient but easy to implement.
116
117 int iCurrentVertex;
118 int iMaxVertex=vertices.Count;
119 for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
120 {
121 // Background: A triangle mesh fulfills the delaunay condition if (iff!)
122 // each circumlocutory circle (i.e. the circle that touches all three corners)
123 // of each triangle is empty of other vertices.
124 // Obviously a single (seeding) triangle fulfills this condition.
125 // If we now add one vertex, we need to reconstruct all triangles, that
126 // do not fulfill this condition with respect to the new triangle
127
128 // Find the triangles that are influenced by the new vertex
129 Vertex v=vertices[iCurrentVertex];
130 List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v);
131
132 List<Simplex> simplices = new List<Simplex>();
133
134 // Reconstruction phase. First step, dissolve each triangle into it's simplices,
135 // i.e. it's "border lines"
136 // Goal is to find "inner" borders and delete them, while the hull gets conserved.
137 // Inner borders are special in the way that they always come twice, which is how we detect them
138 foreach (Triangle t in influencedTriangles)
139 {
140 List<Simplex> newSimplices = t.GetSimplices();
141 simplices.AddRange(newSimplices);
142 triangles.Remove(t);
143 }
144 // Now sort the simplices. That will make identical ones side by side in the list
145 simplices.Sort();
146
147 // Look for duplicate simplices here.
148 // Remember, they are directly side by side in the list right now
149 int iSimplex;
150 List<Simplex> innerSimplices=new List<Simplex>();
151 for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
152 {
153 if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex])==0)
154 {
155 innerSimplices.Add(simplices[iSimplex - 1]);
156 innerSimplices.Add(simplices[iSimplex]);
157 }
158 }
159
160 foreach (Simplex s in innerSimplices)
161 {
162 simplices.Remove(s);
163 }
164
165 // each simplex still in the list belongs to the hull of the region in question
166 // The new vertex (yes, we still deal with verices here :-) ) forms a triangle
167 // With each of these simplices. Build the new triangles and add them to the list
168 foreach (Simplex s in simplices)
169 {
170 Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
171 triangles.Add(t);
172 }
173 }
174
175 // At this point all vertices should be inserted into the mesh
176 // But the areas, that should be kept free still are filled with triangles
177 // We have to remove them. For this we have a list of indices to vertices.
178 // Each triangle that solemnly constists of vertices from the inner border
179 // are deleted
180
181 List<Triangle> innerTriangles = new List<Triangle>();
182 foreach (Triangle t in triangles)
183 {
184 if (
185 innerBorders.Contains(vertices.IndexOf(t.v1))
186 && innerBorders.Contains(vertices.IndexOf(t.v2))
187 && innerBorders.Contains(vertices.IndexOf(t.v3))
188 )
189 innerTriangles.Add(t);
190 }
191 foreach (Triangle t in innerTriangles)
192 {
193 triangles.Remove(t);
194 }
195 }
196
197
198 static Mesh CreateBoxMeshX(PrimitiveBaseShape primShape, PhysicsVector size)
199 // Builds the x (+ and -) surfaces of a box shaped prim
200 {
201 UInt16 hollowFactor = primShape.ProfileHollow;
202 Mesh meshMX = new Mesh();
203
204
205 // Surface 0, -X
206 meshMX.Add(new Vertex("-X-Y-Z", -size.X / 2.0f, -size.Y / 2.0f, -size.Z / 2.0f));
207 meshMX.Add(new Vertex("-X+Y-Z", -size.X / 2.0f, +size.Y / 2.0f, -size.Z / 2.0f));
208 meshMX.Add(new Vertex("-X-Y+Z", -size.X / 2.0f, -size.Y / 2.0f, +size.Z / 2.0f));
209 meshMX.Add(new Vertex("-X+Y+Z", -size.X / 2.0f, +size.Y / 2.0f, +size.Z / 2.0f));
210
211 meshMX.Add(new Triangle(meshMX.vertices[0], meshMX.vertices[2], meshMX.vertices[1]));
212 meshMX.Add(new Triangle(meshMX.vertices[1], meshMX.vertices[2], meshMX.vertices[3]));
213
214
215 Mesh meshPX = new Mesh();
216 // Surface 1, +X
217 meshPX.Add(new Vertex("+X-Y-Z", +size.X / 2.0f, -size.Y / 2.0f, -size.Z / 2.0f));
218 meshPX.Add(new Vertex("+X+Y-Z", +size.X / 2.0f, +size.Y / 2.0f, -size.Z / 2.0f));
219 meshPX.Add(new Vertex("+X-Y+Z", +size.X / 2.0f, -size.Y / 2.0f, +size.Z / 2.0f));
220 meshPX.Add(new Vertex("+X+Y+Z", +size.X / 2.0f, +size.Y / 2.0f, +size.Z / 2.0f));
221
222
223 meshPX.Add(new Triangle(meshPX.vertices[0], meshPX.vertices[1], meshPX.vertices[2]));
224 meshPX.Add(new Triangle(meshPX.vertices[2], meshPX.vertices[1], meshPX.vertices[3]));
225
226
227 if (hollowFactor > 0)
228 {
229 float hollowFactorF = (float)hollowFactor / (float)50000;
230
231 Vertex IPP;
232 Vertex IPM;
233 Vertex IMP;
234 Vertex IMM;
235
236 IPP = new Vertex("Inner-X+Y+Z", -size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, +size.Z / 2.0f);
237 IPM = new Vertex("Inner-X+Y-Z", -size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, -size.Z / 2.0f);
238 IMP = new Vertex("Inner-X-Y+Z", -size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, +size.Z / 2.0f);
239 IMM = new Vertex("Inner-X-Y-Z", -size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, -size.Z / 2.0f);
240
241 meshMX.Add(IPP);
242 meshMX.Add(IPM);
243 meshMX.Add(IMP);
244 meshMX.Add(IMM);
245
246 meshMX.Add(new Triangle(IPP, IMP, IPM));
247 meshMX.Add(new Triangle(IPM, IMP, IMM));
248
249 foreach (Triangle t in meshMX.triangles)
250 {
251 PhysicsVector n = t.getNormal();
252 }
253
254
255
256 IPP = new Vertex("Inner+X+Y+Z", +size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, +size.Z / 2.0f);
257 IPM = new Vertex("Inner+X+Y-Z", +size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, -size.Z / 2.0f);
258 IMP = new Vertex("Inner+X-Y+Z", +size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, +size.Z / 2.0f);
259 IMM = new Vertex("Inner+X-Y-Z", +size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, -size.Z / 2.0f);
260
261 meshPX.Add(IPP);
262 meshPX.Add(IPM);
263 meshPX.Add(IMP);
264 meshPX.Add(IMM);
265
266 meshPX.Add(new Triangle(IPP, IPM, IMP));
267 meshPX.Add(new Triangle(IMP, IPM, IMM));
268
269 foreach (Triangle t in meshPX.triangles)
270 {
271 PhysicsVector n = t.getNormal();
272 }
273 }
274
275 Mesh result = new Mesh();
276 result.Append(meshMX);
277 result.Append(meshPX);
278
279 return result;
280 }
281
282
283
284 static Mesh CreateBoxMeshY(PrimitiveBaseShape primShape, PhysicsVector size)
285 // Builds the y (+ and -) surfaces of a box shaped prim
286 {
287 UInt16 hollowFactor = primShape.ProfileHollow;
288
289 // (M)inus Y
290 Mesh MeshMY = new Mesh();
291 MeshMY.Add(new Vertex("-X-Y-Z", -size.X / 2.0f, -size.Y / 2.0f, -size.Z / 2.0f));
292 MeshMY.Add(new Vertex("+X-Y-Z", +size.X / 2.0f, -size.Y / 2.0f, -size.Z / 2.0f));
293 MeshMY.Add(new Vertex("-X-Y+Z", -size.X / 2.0f, -size.Y / 2.0f, +size.Z / 2.0f));
294 MeshMY.Add(new Vertex("+X-Y+Z", +size.X / 2.0f, -size.Y / 2.0f, +size.Z / 2.0f));
295
296 MeshMY.Add(new Triangle(MeshMY.vertices[0], MeshMY.vertices[1], MeshMY.vertices[2]));
297 MeshMY.Add(new Triangle(MeshMY.vertices[2], MeshMY.vertices[1], MeshMY.vertices[3]));
298
299 // (P)lus Y
300 Mesh MeshPY = new Mesh();
301
302 MeshPY.Add(new Vertex("-X+Y-Z", -size.X / 2.0f, +size.Y / 2.0f, -size.Z / 2.0f));
303 MeshPY.Add(new Vertex("+X+Y-Z", +size.X / 2.0f, +size.Y / 2.0f, -size.Z / 2.0f));
304 MeshPY.Add(new Vertex("-X+Y+Z", -size.X / 2.0f, +size.Y / 2.0f, +size.Z / 2.0f));
305 MeshPY.Add(new Vertex("+X+Y+Z", +size.X / 2.0f, +size.Y / 2.0f, +size.Z / 2.0f));
306
307 MeshPY.Add(new Triangle(MeshPY.vertices[1], MeshPY.vertices[0], MeshPY.vertices[2]));
308 MeshPY.Add(new Triangle(MeshPY.vertices[1], MeshPY.vertices[2], MeshPY.vertices[3]));
309
310 if (hollowFactor > 0)
311 {
312 float hollowFactorF = (float)hollowFactor / (float)50000;
313
314 Vertex IPP;
315 Vertex IPM;
316 Vertex IMP;
317 Vertex IMM;
318
319 IPP = new Vertex("Inner+X-Y+Z", +size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, +size.Z / 2.0f);
320 IPM = new Vertex("Inner+X-Y-Z", +size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, -size.Z / 2.0f);
321 IMP = new Vertex("Inner-X-Y+Z", -size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, +size.Z / 2.0f);
322 IMM = new Vertex("Inner-X-Y-Z", -size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, -size.Z / 2.0f);
323
324 MeshMY.Add(IPP);
325 MeshMY.Add(IPM);
326 MeshMY.Add(IMP);
327 MeshMY.Add(IMM);
328
329 MeshMY.Add(new Triangle(IPP, IPM, IMP));
330 MeshMY.Add(new Triangle(IMP, IPM, IMM));
331
332 foreach (Triangle t in MeshMY.triangles)
333 {
334 PhysicsVector n = t.getNormal();
335 }
336
337
338
339 IPP = new Vertex("Inner+X+Y+Z", +size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, +size.Z / 2.0f);
340 IPM=new Vertex("Inner+X+Y-Z", +size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, -size.Z / 2.0f);
341 IMP=new Vertex("Inner-X+Y+Z", -size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, +size.Z / 2.0f);
342 IMM=new Vertex("Inner-X+Y-Z", -size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, -size.Z / 2.0f);
343
344 MeshPY.Add(IPP);
345 MeshPY.Add(IPM);
346 MeshPY.Add(IMP);
347 MeshPY.Add(IMM);
348
349 MeshPY.Add(new Triangle(IPM, IPP, IMP));
350 MeshPY.Add(new Triangle(IMP, IMM, IPM));
351
352 foreach (Triangle t in MeshPY.triangles)
353 {
354 PhysicsVector n = t.getNormal();
355 }
356
357
358
359 }
360
361
362 Mesh result = new Mesh();
363 result.Append(MeshMY);
364 result.Append(MeshPY);
365
366 return result;
367 }
368
369 static Mesh CreateBoxMeshZ(PrimitiveBaseShape primShape, PhysicsVector size)
370 // Builds the z (+ and -) surfaces of a box shaped prim
371 {
372 UInt16 hollowFactor = primShape.ProfileHollow;
373
374 // Base, i.e. outer shape
375 // (M)inus Z
376 Mesh MZ = new Mesh();
377
378 MZ.Add(new Vertex("-X-Y-Z", -size.X / 2.0f, -size.Y / 2.0f, -size.Z / 2.0f));
379 MZ.Add(new Vertex("+X-Y-Z", +size.X / 2.0f, -size.Y / 2.0f, -size.Z / 2.0f));
380 MZ.Add(new Vertex("-X+Y-Z", -size.X / 2.0f, +size.Y / 2.0f, -size.Z / 2.0f));
381 MZ.Add(new Vertex("+X+Y-Z", +size.X / 2.0f, +size.Y / 2.0f, -size.Z / 2.0f));
382
383
384 MZ.Add(new Triangle(MZ.vertices[1], MZ.vertices[0], MZ.vertices[2]));
385 MZ.Add(new Triangle(MZ.vertices[1], MZ.vertices[2], MZ.vertices[3]));
386
387 // (P)lus Z
388 Mesh PZ = new Mesh();
389
390 PZ.Add(new Vertex("-X-Y+Z", -size.X / 2.0f, -size.Y / 2.0f, 0.0f));
391 PZ.Add(new Vertex("+X-Y+Z", +size.X / 2.0f, -size.Y / 2.0f, 0.0f));
392 PZ.Add(new Vertex("-X+Y+Z", -size.X / 2.0f, +size.Y / 2.0f, 0.0f));
393 PZ.Add(new Vertex("+X+Y+Z", +size.X / 2.0f, +size.Y / 2.0f, 0.0f));
394
395 // Surface 5, +Z
396 PZ.Add(new Triangle(PZ.vertices[0], PZ.vertices[1], PZ.vertices[2]));
397 PZ.Add(new Triangle(PZ.vertices[2], PZ.vertices[1], PZ.vertices[3]));
398
399 if (hollowFactor > 0)
400 {
401 float hollowFactorF = (float)hollowFactor / (float)50000;
402
403 MZ.Add(new Vertex("-X-Y-Z", -size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, 0.0f));
404 MZ.Add(new Vertex("-X+Y-Z", +size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, 0.0f));
405 MZ.Add(new Vertex("-X-Y+Z", -size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, 0.0f));
406 MZ.Add(new Vertex("-X+Y+Z", +size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, 0.0f));
407
408 List<int> innerBorders = new List<int>();
409 innerBorders.Add(4);
410 innerBorders.Add(5);
411 innerBorders.Add(6);
412 innerBorders.Add(7);
413
414 InsertVertices(MZ.vertices, 4, MZ.triangles, innerBorders);
415
416 PZ.Add(new Vertex("-X-Y-Z", -size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, 0.0f));
417 PZ.Add(new Vertex("-X+Y-Z", +size.X * hollowFactorF / 2.0f, -size.Y * hollowFactorF / 2.0f, 0.0f));
418 PZ.Add(new Vertex("-X-Y+Z", -size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, 0.0f));
419 PZ.Add(new Vertex("-X+Y+Z", +size.X * hollowFactorF / 2.0f, +size.Y * hollowFactorF / 2.0f, 0.0f));
420
421 innerBorders = new List<int>();
422 innerBorders.Add(4);
423 innerBorders.Add(5);
424 innerBorders.Add(6);
425 innerBorders.Add(7);
426
427 InsertVertices(PZ.vertices, 4, PZ.triangles, innerBorders);
428
429 }
430
431 foreach (Vertex v in PZ.vertices)
432 {
433 v.point.Z = size.Z / 2.0f;
434 }
435 foreach (Vertex v in MZ.vertices)
436 {
437 v.point.Z = -size.Z / 2.0f;
438 }
439
440 foreach (Triangle t in MZ.triangles)
441 {
442 PhysicsVector n = t.getNormal();
443 if (n.Z > 0.0)
444 t.invertNormal();
445 }
446
447 foreach (Triangle t in PZ.triangles)
448 {
449 PhysicsVector n = t.getNormal();
450 if (n.Z < 0.0)
451 t.invertNormal();
452 }
453
454 Mesh result = new Mesh();
455 result.Append(MZ);
456 result.Append(PZ);
457
458 return result;
459 }
460
461 static Mesh CreateBoxMesh(PrimitiveBaseShape primShape, PhysicsVector size)
462 {
463 Mesh result = new Mesh();
464
465
466
467 Mesh MeshX = Meshmerizer.CreateBoxMeshX(primShape, size);
468 Mesh MeshY = Meshmerizer.CreateBoxMeshY(primShape, size);
469 Mesh MeshZ = Meshmerizer.CreateBoxMeshZ(primShape, size);
470
471 result.Append(MeshX);
472 result.Append(MeshY);
473 result.Append(MeshZ);
474
475 return result;
476 }
477
478
479 public static void CalcNormals(Mesh mesh)
480 {
481 int iTriangles = mesh.triangles.Count;
482
483 mesh.normals = new float[iTriangles*3];
484
485 int i=0;
486 foreach (Triangle t in mesh.triangles)
487 {
488
489 float ux, uy, uz;
490 float vx, vy, vz;
491 float wx, wy, wz;
492
493 ux = t.v1.point.X;
494 uy = t.v1.point.Y;
495 uz = t.v1.point.Z;
496
497 vx = t.v2.point.X;
498 vy = t.v2.point.Y;
499 vz = t.v2.point.Z;
500
501 wx = t.v3.point.X;
502 wy = t.v3.point.Y;
503 wz = t.v3.point.Z;
504
505 // Vectors for edges
506 float e1x, e1y, e1z;
507 float e2x, e2y, e2z;
508
509 e1x = ux - vx;
510 e1y = uy - vy;
511 e1z = uz - vz;
512
513 e2x = ux - wx;
514 e2y = uy - wy;
515 e2z = uz - wz;
516
517
518 // Cross product for normal
519 float nx, ny, nz;
520 nx = e1y * e2z - e1z * e2y;
521 ny = e1z * e2x - e1x * e2z;
522 nz = e1x * e2y - e1y * e2x;
523
524 // Length
525 float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz);
526
527 // Normalized "normal"
528 nx /= l;
529 ny /= l;
530 nz /= l;
531
532 mesh.normals[i] = nx;
533 mesh.normals[i + 1] = ny;
534 mesh.normals[i + 2] = nz;
535
536 i+=3;
537 }
538 }
539
540 public static Mesh CreateMesh(PrimitiveBaseShape primShape, PhysicsVector size)
541 {
542 Mesh mesh = null;
543
544 switch (primShape.ProfileShape)
545 {
546 case ProfileShape.Square:
547 mesh=CreateBoxMesh(primShape, size);
548 CalcNormals(mesh);
549 break;
550 default:
551 mesh=null;
552 break;
553 }
554
555 return mesh;
556
557 }
558 }
559}
560