diff options
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/Meshing\/HelperTypes.cs | 279 | ||||
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/Meshing\/Meshmerizer.cs | 560 |
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 @@ | |||
1 | using System; | ||
2 | using System.Globalization; | ||
3 | using System.Diagnostics; | ||
4 | using System.Collections.Generic; | ||
5 | |||
6 | using OpenSim.Region.Physics.Manager; | ||
7 | |||
8 | public 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 | |||
55 | public 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 | |||
100 | public 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 @@ | |||
1 | using System; | ||
2 | using System.Globalization; | ||
3 | using System.Diagnostics; | ||
4 | using System.Collections.Generic; | ||
5 | using System.Text; | ||
6 | using System.Runtime.InteropServices; | ||
7 | |||
8 | using OpenSim.Framework.Types; | ||
9 | using OpenSim.Region.Physics.Manager; | ||
10 | |||
11 | namespace 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 | |||