diff options
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Meshmerizer.cs')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 786 |
1 files changed, 393 insertions, 393 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index da4ee58..9c35f81 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -1,393 +1,393 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSim Project nor the | 12 | * * Neither the name of the OpenSim Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | 28 | ||
29 | using System; | 29 | using System; |
30 | using System.IO; | 30 | using System.IO; |
31 | using System.Globalization; | 31 | using System.Globalization; |
32 | using System.Diagnostics; | 32 | using System.Diagnostics; |
33 | using System.Collections.Generic; | 33 | using System.Collections.Generic; |
34 | using System.Runtime.InteropServices; | 34 | using System.Runtime.InteropServices; |
35 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
36 | using OpenSim.Framework.Console; | 36 | using OpenSim.Framework.Console; |
37 | using OpenSim.Region.Physics.Manager; | 37 | using OpenSim.Region.Physics.Manager; |
38 | 38 | ||
39 | namespace OpenSim.Region.Physics.Meshing | 39 | namespace OpenSim.Region.Physics.Meshing |
40 | { | 40 | { |
41 | 41 | ||
42 | public class MeshmerizerPlugin : IMeshingPlugin | 42 | public class MeshmerizerPlugin : IMeshingPlugin |
43 | { | 43 | { |
44 | public MeshmerizerPlugin() | 44 | public MeshmerizerPlugin() |
45 | { | 45 | { |
46 | } | 46 | } |
47 | 47 | ||
48 | public string GetName() | 48 | public string GetName() |
49 | { | 49 | { |
50 | return "Meshmerizer"; | 50 | return "Meshmerizer"; |
51 | } | 51 | } |
52 | 52 | ||
53 | public IMesher GetMesher() | 53 | public IMesher GetMesher() |
54 | { | 54 | { |
55 | return new Meshmerizer(); | 55 | return new Meshmerizer(); |
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | public class Meshmerizer : IMesher | 59 | public class Meshmerizer : IMesher |
60 | { | 60 | { |
61 | // Setting baseDir to a path will enable the dumping of raw files | 61 | // Setting baseDir to a path will enable the dumping of raw files |
62 | // raw files can be imported by blender so a visual inspection of the results can be done | 62 | // raw files can be imported by blender so a visual inspection of the results can be done |
63 | // const string baseDir = "rawFiles"; | 63 | // const string baseDir = "rawFiles"; |
64 | const string baseDir = null; | 64 | const string baseDir = null; |
65 | 65 | ||
66 | static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu) | 66 | static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu) |
67 | { | 67 | { |
68 | // p1, p2, points on the straight | 68 | // p1, p2, points on the straight |
69 | // r1, r2, directional vectors of the straight. Not necessarily of length 1! | 69 | // r1, r2, directional vectors of the straight. Not necessarily of length 1! |
70 | // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, | 70 | // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, |
71 | // thus allowing to decide whether an intersection is between two points | 71 | // thus allowing to decide whether an intersection is between two points |
72 | 72 | ||
73 | float r1x = r1.X; | 73 | float r1x = r1.X; |
74 | float r1y = r1.Y; | 74 | float r1y = r1.Y; |
75 | float r2x = r2.X; | 75 | float r2x = r2.X; |
76 | float r2y = r2.Y; | 76 | float r2y = r2.Y; |
77 | 77 | ||
78 | float denom = r1y*r2x - r1x*r2y; | 78 | float denom = r1y*r2x - r1x*r2y; |
79 | 79 | ||
80 | if (denom == 0.0) | 80 | if (denom == 0.0) |
81 | { | 81 | { |
82 | lambda = Single.NaN; | 82 | lambda = Single.NaN; |
83 | mu = Single.NaN; | 83 | mu = Single.NaN; |
84 | return; | 84 | return; |
85 | } | 85 | } |
86 | 86 | ||
87 | float p1x = p1.X; | 87 | float p1x = p1.X; |
88 | float p1y = p1.Y; | 88 | float p1y = p1.Y; |
89 | float p2x = p2.X; | 89 | float p2x = p2.X; |
90 | float p2y = p2.Y; | 90 | float p2y = p2.Y; |
91 | lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom; | 91 | lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom; |
92 | mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom; | 92 | mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom; |
93 | 93 | ||
94 | } | 94 | } |
95 | 95 | ||
96 | private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v) | 96 | private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v) |
97 | { | 97 | { |
98 | List<Triangle> influenced = new List<Triangle>(); | 98 | List<Triangle> influenced = new List<Triangle>(); |
99 | foreach (Triangle t in triangles) | 99 | foreach (Triangle t in triangles) |
100 | { | 100 | { |
101 | if (t.isInCircle(v.X, v.Y)) | 101 | if (t.isInCircle(v.X, v.Y)) |
102 | { | 102 | { |
103 | influenced.Add(t); | 103 | influenced.Add(t); |
104 | } | 104 | } |
105 | } | 105 | } |
106 | return influenced; | 106 | return influenced; |
107 | } | 107 | } |
108 | 108 | ||
109 | 109 | ||
110 | private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles) | 110 | private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles) |
111 | { | 111 | { |
112 | // This is a variant of the delaunay algorithm | 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 | 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 | 114 | // and replaced by new ones including the new vertex |
115 | // It is not very time efficient but easy to implement. | 115 | // It is not very time efficient but easy to implement. |
116 | 116 | ||
117 | int iCurrentVertex; | 117 | int iCurrentVertex; |
118 | int iMaxVertex = vertices.Count; | 118 | int iMaxVertex = vertices.Count; |
119 | for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++) | 119 | for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++) |
120 | { | 120 | { |
121 | // Background: A triangle mesh fulfills the delaunay condition if (iff!) | 121 | // Background: A triangle mesh fulfills the delaunay condition if (iff!) |
122 | // each circumlocutory circle (i.e. the circle that touches all three corners) | 122 | // each circumlocutory circle (i.e. the circle that touches all three corners) |
123 | // of each triangle is empty of other vertices. | 123 | // of each triangle is empty of other vertices. |
124 | // Obviously a single (seeding) triangle fulfills this condition. | 124 | // Obviously a single (seeding) triangle fulfills this condition. |
125 | // If we now add one vertex, we need to reconstruct all triangles, that | 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 | 126 | // do not fulfill this condition with respect to the new triangle |
127 | 127 | ||
128 | // Find the triangles that are influenced by the new vertex | 128 | // Find the triangles that are influenced by the new vertex |
129 | Vertex v=vertices[iCurrentVertex]; | 129 | Vertex v=vertices[iCurrentVertex]; |
130 | if (v == null) | 130 | if (v == null) |
131 | continue; // Null is polygon stop marker. Ignore it | 131 | continue; // Null is polygon stop marker. Ignore it |
132 | List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v); | 132 | List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v); |
133 | 133 | ||
134 | List<Simplex> simplices = new List<Simplex>(); | 134 | List<Simplex> simplices = new List<Simplex>(); |
135 | 135 | ||
136 | // Reconstruction phase. First step, dissolve each triangle into it's simplices, | 136 | // Reconstruction phase. First step, dissolve each triangle into it's simplices, |
137 | // i.e. it's "border lines" | 137 | // i.e. it's "border lines" |
138 | // Goal is to find "inner" borders and delete them, while the hull gets conserved. | 138 | // Goal is to find "inner" borders and delete them, while the hull gets conserved. |
139 | // Inner borders are special in the way that they always come twice, which is how we detect them | 139 | // Inner borders are special in the way that they always come twice, which is how we detect them |
140 | foreach (Triangle t in influencedTriangles) | 140 | foreach (Triangle t in influencedTriangles) |
141 | { | 141 | { |
142 | List<Simplex> newSimplices = t.GetSimplices(); | 142 | List<Simplex> newSimplices = t.GetSimplices(); |
143 | simplices.AddRange(newSimplices); | 143 | simplices.AddRange(newSimplices); |
144 | triangles.Remove(t); | 144 | triangles.Remove(t); |
145 | } | 145 | } |
146 | // Now sort the simplices. That will make identical ones reside side by side in the list | 146 | // Now sort the simplices. That will make identical ones reside side by side in the list |
147 | simplices.Sort(); | 147 | simplices.Sort(); |
148 | 148 | ||
149 | // Look for duplicate simplices here. | 149 | // Look for duplicate simplices here. |
150 | // Remember, they are directly side by side in the list right now, | 150 | // Remember, they are directly side by side in the list right now, |
151 | // So we only check directly neighbours | 151 | // So we only check directly neighbours |
152 | int iSimplex; | 152 | int iSimplex; |
153 | List<Simplex> innerSimplices = new List<Simplex>(); | 153 | List<Simplex> innerSimplices = new List<Simplex>(); |
154 | for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards | 154 | for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards |
155 | { | 155 | { |
156 | if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0) | 156 | if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0) |
157 | { | 157 | { |
158 | innerSimplices.Add(simplices[iSimplex - 1]); | 158 | innerSimplices.Add(simplices[iSimplex - 1]); |
159 | innerSimplices.Add(simplices[iSimplex]); | 159 | innerSimplices.Add(simplices[iSimplex]); |
160 | } | 160 | } |
161 | } | 161 | } |
162 | 162 | ||
163 | foreach (Simplex s in innerSimplices) | 163 | foreach (Simplex s in innerSimplices) |
164 | { | 164 | { |
165 | simplices.Remove(s); | 165 | simplices.Remove(s); |
166 | } | 166 | } |
167 | 167 | ||
168 | // each simplex still in the list belongs to the hull of the region in question | 168 | // each simplex still in the list belongs to the hull of the region in question |
169 | // The new vertex (yes, we still deal with verices here :-) ) forms a triangle | 169 | // The new vertex (yes, we still deal with verices here :-) ) forms a triangle |
170 | // with each of these simplices. Build the new triangles and add them to the list | 170 | // with each of these simplices. Build the new triangles and add them to the list |
171 | foreach (Simplex s in simplices) | 171 | foreach (Simplex s in simplices) |
172 | { | 172 | { |
173 | Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); | 173 | Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); |
174 | if (!t.isDegraded()) | 174 | if (!t.isDegraded()) |
175 | { | 175 | { |
176 | triangles.Add(t); | 176 | triangles.Add(t); |
177 | } | 177 | } |
178 | } | 178 | } |
179 | } | 179 | } |
180 | 180 | ||
181 | } | 181 | } |
182 | 182 | ||
183 | 183 | ||
184 | static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | 184 | static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) |
185 | // Builds the z (+ and -) surfaces of a box shaped prim | 185 | // Builds the z (+ and -) surfaces of a box shaped prim |
186 | { | 186 | { |
187 | UInt16 hollowFactor = primShape.ProfileHollow; | 187 | UInt16 hollowFactor = primShape.ProfileHollow; |
188 | UInt16 profileBegin = primShape.ProfileBegin; | 188 | UInt16 profileBegin = primShape.ProfileBegin; |
189 | UInt16 profileEnd = primShape.ProfileEnd; | 189 | UInt16 profileEnd = primShape.ProfileEnd; |
190 | 190 | ||
191 | // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface | 191 | // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface |
192 | // of a block are basically the same | 192 | // of a block are basically the same |
193 | // They may be warped differently but the shape is identical | 193 | // They may be warped differently but the shape is identical |
194 | // So we only create one surface as a model and derive both plus and minus surface of the block from it | 194 | // So we only create one surface as a model and derive both plus and minus surface of the block from it |
195 | // This is done in a model space where the block spans from -.5 to +.5 in X and Y | 195 | // This is done in a model space where the block spans from -.5 to +.5 in X and Y |
196 | // The mapping to Scene space is done later during the "extrusion" phase | 196 | // The mapping to Scene space is done later during the "extrusion" phase |
197 | 197 | ||
198 | // Base | 198 | // Base |
199 | Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f); | 199 | Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f); |
200 | Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f); | 200 | Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f); |
201 | Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f); | 201 | Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f); |
202 | Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f); | 202 | Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f); |
203 | 203 | ||
204 | Meshing.SimpleHull outerHull = new SimpleHull(); | 204 | Meshing.SimpleHull outerHull = new SimpleHull(); |
205 | outerHull.AddVertex(MM); | 205 | outerHull.AddVertex(MM); |
206 | outerHull.AddVertex(PM); | 206 | outerHull.AddVertex(PM); |
207 | outerHull.AddVertex(PP); | 207 | outerHull.AddVertex(PP); |
208 | outerHull.AddVertex(MP); | 208 | outerHull.AddVertex(MP); |
209 | 209 | ||
210 | // Deal with cuts now | 210 | // Deal with cuts now |
211 | if ((profileBegin != 0) || (profileEnd != 0)) | 211 | if ((profileBegin != 0) || (profileEnd != 0)) |
212 | { | 212 | { |
213 | double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding | 213 | double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding |
214 | fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y | 214 | fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y |
215 | double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 | 215 | double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 |
216 | fProfileEndAngle -= (90.0 + 45.0); | 216 | fProfileEndAngle -= (90.0 + 45.0); |
217 | if (fProfileBeginAngle < fProfileEndAngle) | 217 | if (fProfileBeginAngle < fProfileEndAngle) |
218 | fProfileEndAngle -= 360.0; | 218 | fProfileEndAngle -= 360.0; |
219 | 219 | ||
220 | // Note, that we don't want to cut out a triangle, even if this is a | 220 | // Note, that we don't want to cut out a triangle, even if this is a |
221 | // good approximation for small cuts. Indeed we want to cut out an arc | 221 | // good approximation for small cuts. Indeed we want to cut out an arc |
222 | // and we approximate this arc by a polygon chain | 222 | // and we approximate this arc by a polygon chain |
223 | // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space | 223 | // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space |
224 | // So it can easily be subtracted from the outer hull | 224 | // So it can easily be subtracted from the outer hull |
225 | int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree | 225 | int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree |
226 | double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps; | 226 | double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps; |
227 | 227 | ||
228 | Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); | 228 | Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); |
229 | 229 | ||
230 | // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull | 230 | // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull |
231 | SimpleHull cutHull = new SimpleHull(); | 231 | SimpleHull cutHull = new SimpleHull(); |
232 | cutHull.AddVertex(origin); | 232 | cutHull.AddVertex(origin); |
233 | for (int i=0; i<iSteps; i++) { | 233 | for (int i=0; i<iSteps; i++) { |
234 | double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!! | 234 | double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!! |
235 | Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); | 235 | Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); |
236 | cutHull.AddVertex(v); | 236 | cutHull.AddVertex(v); |
237 | } | 237 | } |
238 | Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors | 238 | Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors |
239 | cutHull.AddVertex(legEnd); | 239 | cutHull.AddVertex(legEnd); |
240 | 240 | ||
241 | MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName); | 241 | MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName); |
242 | SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); | 242 | SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); |
243 | 243 | ||
244 | outerHull = cuttedHull; | 244 | outerHull = cuttedHull; |
245 | } | 245 | } |
246 | 246 | ||
247 | // Deal with the hole here | 247 | // Deal with the hole here |
248 | if (hollowFactor > 0) | 248 | if (hollowFactor > 0) |
249 | { | 249 | { |
250 | float hollowFactorF = (float) hollowFactor/(float) 50000; | 250 | float hollowFactorF = (float) hollowFactor/(float) 50000; |
251 | Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); | 251 | Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); |
252 | Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); | 252 | Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); |
253 | Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); | 253 | Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); |
254 | Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); | 254 | Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); |
255 | 255 | ||
256 | SimpleHull holeHull = new SimpleHull(); | 256 | SimpleHull holeHull = new SimpleHull(); |
257 | 257 | ||
258 | holeHull.AddVertex(IMM); | 258 | holeHull.AddVertex(IMM); |
259 | holeHull.AddVertex(IMP); | 259 | holeHull.AddVertex(IMP); |
260 | holeHull.AddVertex(IPP); | 260 | holeHull.AddVertex(IPP); |
261 | holeHull.AddVertex(IPM); | 261 | holeHull.AddVertex(IPM); |
262 | 262 | ||
263 | SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); | 263 | SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); |
264 | 264 | ||
265 | outerHull = hollowedHull; | 265 | outerHull = hollowedHull; |
266 | 266 | ||
267 | } | 267 | } |
268 | 268 | ||
269 | Mesh m = new Mesh(); | 269 | Mesh m = new Mesh(); |
270 | 270 | ||
271 | Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); | 271 | Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); |
272 | Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); | 272 | Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); |
273 | Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); | 273 | Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); |
274 | 274 | ||
275 | m.Add(Seed1); | 275 | m.Add(Seed1); |
276 | m.Add(Seed2); | 276 | m.Add(Seed2); |
277 | m.Add(Seed3); | 277 | m.Add(Seed3); |
278 | 278 | ||
279 | m.Add(new Triangle(Seed1, Seed2, Seed3)); | 279 | m.Add(new Triangle(Seed1, Seed2, Seed3)); |
280 | m.Add(outerHull.getVertices()); | 280 | m.Add(outerHull.getVertices()); |
281 | 281 | ||
282 | InsertVertices(m.vertices, 3, m.triangles); | 282 | InsertVertices(m.vertices, 3, m.triangles); |
283 | m.DumpRaw(baseDir, primName, "Proto first Mesh"); | 283 | m.DumpRaw(baseDir, primName, "Proto first Mesh"); |
284 | 284 | ||
285 | m.Remove(Seed1); | 285 | m.Remove(Seed1); |
286 | m.Remove(Seed2); | 286 | m.Remove(Seed2); |
287 | m.Remove(Seed3); | 287 | m.Remove(Seed3); |
288 | m.DumpRaw(baseDir, primName, "Proto seeds removed"); | 288 | m.DumpRaw(baseDir, primName, "Proto seeds removed"); |
289 | 289 | ||
290 | m.RemoveTrianglesOutside(outerHull); | 290 | m.RemoveTrianglesOutside(outerHull); |
291 | m.DumpRaw(baseDir, primName, "Proto outsides removed"); | 291 | m.DumpRaw(baseDir, primName, "Proto outsides removed"); |
292 | 292 | ||
293 | foreach (Triangle t in m.triangles) | 293 | foreach (Triangle t in m.triangles) |
294 | { | 294 | { |
295 | PhysicsVector n = t.getNormal(); | 295 | PhysicsVector n = t.getNormal(); |
296 | if (n.Z < 0.0) | 296 | if (n.Z < 0.0) |
297 | t.invertNormal(); | 297 | t.invertNormal(); |
298 | } | 298 | } |
299 | 299 | ||
300 | Extruder extr = new Extruder(); | 300 | Extruder extr = new Extruder(); |
301 | 301 | ||
302 | extr.size = size; | 302 | extr.size = size; |
303 | 303 | ||
304 | Mesh result = extr.Extrude(m); | 304 | Mesh result = extr.Extrude(m); |
305 | result.DumpRaw(baseDir, primName, "Z extruded"); | 305 | result.DumpRaw(baseDir, primName, "Z extruded"); |
306 | return result; | 306 | return result; |
307 | } | 307 | } |
308 | 308 | ||
309 | public static void CalcNormals(Mesh mesh) | 309 | public static void CalcNormals(Mesh mesh) |
310 | { | 310 | { |
311 | int iTriangles = mesh.triangles.Count; | 311 | int iTriangles = mesh.triangles.Count; |
312 | 312 | ||
313 | mesh.normals = new float[iTriangles*3]; | 313 | mesh.normals = new float[iTriangles*3]; |
314 | 314 | ||
315 | int i = 0; | 315 | int i = 0; |
316 | foreach (Triangle t in mesh.triangles) | 316 | foreach (Triangle t in mesh.triangles) |
317 | { | 317 | { |
318 | float ux, uy, uz; | 318 | float ux, uy, uz; |
319 | float vx, vy, vz; | 319 | float vx, vy, vz; |
320 | float wx, wy, wz; | 320 | float wx, wy, wz; |
321 | 321 | ||
322 | ux = t.v1.X; | 322 | ux = t.v1.X; |
323 | uy = t.v1.Y; | 323 | uy = t.v1.Y; |
324 | uz = t.v1.Z; | 324 | uz = t.v1.Z; |
325 | 325 | ||
326 | vx = t.v2.X; | 326 | vx = t.v2.X; |
327 | vy = t.v2.Y; | 327 | vy = t.v2.Y; |
328 | vz = t.v2.Z; | 328 | vz = t.v2.Z; |
329 | 329 | ||
330 | wx = t.v3.X; | 330 | wx = t.v3.X; |
331 | wy = t.v3.Y; | 331 | wy = t.v3.Y; |
332 | wz = t.v3.Z; | 332 | wz = t.v3.Z; |
333 | 333 | ||
334 | 334 | ||
335 | // Vectors for edges | 335 | // Vectors for edges |
336 | float e1x, e1y, e1z; | 336 | float e1x, e1y, e1z; |
337 | float e2x, e2y, e2z; | 337 | float e2x, e2y, e2z; |
338 | 338 | ||
339 | e1x = ux - vx; | 339 | e1x = ux - vx; |
340 | e1y = uy - vy; | 340 | e1y = uy - vy; |
341 | e1z = uz - vz; | 341 | e1z = uz - vz; |
342 | 342 | ||
343 | e2x = ux - wx; | 343 | e2x = ux - wx; |
344 | e2y = uy - wy; | 344 | e2y = uy - wy; |
345 | e2z = uz - wz; | 345 | e2z = uz - wz; |
346 | 346 | ||
347 | 347 | ||
348 | // Cross product for normal | 348 | // Cross product for normal |
349 | float nx, ny, nz; | 349 | float nx, ny, nz; |
350 | nx = e1y*e2z - e1z*e2y; | 350 | nx = e1y*e2z - e1z*e2y; |
351 | ny = e1z*e2x - e1x*e2z; | 351 | ny = e1z*e2x - e1x*e2z; |
352 | nz = e1x*e2y - e1y*e2x; | 352 | nz = e1x*e2y - e1y*e2x; |
353 | 353 | ||
354 | // Length | 354 | // Length |
355 | float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz); | 355 | float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz); |
356 | 356 | ||
357 | // Normalized "normal" | 357 | // Normalized "normal" |
358 | nx /= l; | 358 | nx /= l; |
359 | ny /= l; | 359 | ny /= l; |
360 | nz /= l; | 360 | nz /= l; |
361 | 361 | ||
362 | mesh.normals[i] = nx; | 362 | mesh.normals[i] = nx; |
363 | mesh.normals[i + 1] = ny; | 363 | mesh.normals[i + 1] = ny; |
364 | mesh.normals[i + 2] = nz; | 364 | mesh.normals[i + 2] = nz; |
365 | 365 | ||
366 | i += 3; | 366 | i += 3; |
367 | } | 367 | } |
368 | } | 368 | } |
369 | 369 | ||
370 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | 370 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) |
371 | { | 371 | { |
372 | Mesh mesh = null; | 372 | Mesh mesh = null; |
373 | 373 | ||
374 | switch (primShape.ProfileShape) | 374 | switch (primShape.ProfileShape) |
375 | { | 375 | { |
376 | case ProfileShape.Square: | 376 | case ProfileShape.Square: |
377 | mesh=CreateBoxMesh(primName, primShape, size); | 377 | mesh=CreateBoxMesh(primName, primShape, size); |
378 | CalcNormals(mesh); | 378 | CalcNormals(mesh); |
379 | break; | 379 | break; |
380 | default: | 380 | default: |
381 | mesh = CreateBoxMesh(primName, primShape, size); | 381 | mesh = CreateBoxMesh(primName, primShape, size); |
382 | CalcNormals(mesh); | 382 | CalcNormals(mesh); |
383 | //Set default mesh to cube otherwise it'll return | 383 | //Set default mesh to cube otherwise it'll return |
384 | // null and crash on the 'setMesh' method in the physics plugins. | 384 | // null and crash on the 'setMesh' method in the physics plugins. |
385 | //mesh = null; | 385 | //mesh = null; |
386 | break; | 386 | break; |
387 | } | 387 | } |
388 | 388 | ||
389 | return mesh; | 389 | return mesh; |
390 | } | 390 | } |
391 | } | 391 | } |
392 | 392 | ||
393 | } | 393 | } |