aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing/Extruder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Extruder.cs')
-rw-r--r--OpenSim/Region/Physics/Meshing/Extruder.cs472
1 files changed, 0 insertions, 472 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Extruder.cs b/OpenSim/Region/Physics/Meshing/Extruder.cs
deleted file mode 100644
index 1fc65e3..0000000
--- a/OpenSim/Region/Physics/Meshing/Extruder.cs
+++ /dev/null
@@ -1,472 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27//#define SPAM
28
29using OpenMetaverse;
30using OpenSim.Region.Physics.Manager;
31
32namespace OpenSim.Region.Physics.Meshing
33{
34 internal class Extruder
35 {
36 //public float startParameter;
37 //public float stopParameter;
38 public PhysicsVector size;
39
40 public float taperTopFactorX = 1f;
41 public float taperTopFactorY = 1f;
42 public float taperBotFactorX = 1f;
43 public float taperBotFactorY = 1f;
44
45 public float pushX = 0f;
46 public float pushY = 0f;
47
48 // twist amount in radians. NOT DEGREES.
49 public float twistTop = 0;
50 public float twistBot = 0;
51 public float twistMid = 0;
52 public float pathScaleX = 1.0f;
53 public float pathScaleY = 0.5f;
54 public float skew = 0.0f;
55 public float radius = 0.0f;
56 public float revolutions = 1.0f;
57
58 public float pathCutBegin = 0.0f;
59 public float pathCutEnd = 1.0f;
60
61 public ushort pathBegin = 0;
62 public ushort pathEnd = 0;
63
64 public float pathTaperX = 0.0f;
65 public float pathTaperY = 0.0f;
66
67 /// <summary>
68 /// Creates an extrusion of a profile along a linear path. Used to create prim types box, cylinder, and prism.
69 /// </summary>
70 /// <param name="m"></param>
71 /// <returns>A mesh of the extruded shape</returns>
72 public Mesh ExtrudeLinearPath(Mesh m)
73 {
74 Mesh result = new Mesh();
75
76 Mesh newLayer;
77 Mesh lastLayer = null;
78
79 int step = 0;
80 int steps = 1;
81
82 float twistTotal = twistTop - twistBot;
83 // if the profile has a lot of twist, add more layers otherwise the layers may overlap
84 // and the resulting mesh may be quite inaccurate. This method is arbitrary and may not
85 // accurately match the viewer
86 float twistTotalAbs = System.Math.Abs(twistTotal);
87 if (twistTotalAbs > 0.01)
88 steps += (int)(twistTotalAbs * 3.66f); // dahlia's magic number ;)
89
90#if SPAM
91 System.Console.WriteLine("ExtrudeLinearPath: twistTotalAbs: " + twistTotalAbs.ToString() + " steps: " + steps.ToString());
92#endif
93
94 double percentOfPathMultiplier = 1.0 / steps;
95
96 float start = -0.5f;
97
98 float stepSize = 1.0f / (float)steps;
99
100 float xProfileScale = 1.0f;
101 float yProfileScale = 1.0f;
102
103 float xOffset = 0.0f;
104 float yOffset = 0.0f;
105 float zOffset = start;
106
107 float xOffsetStepIncrement = pushX / steps;
108 float yOffsetStepIncrement = pushY / steps;
109
110#if SPAM
111 System.Console.WriteLine("Extruder: twistTop: " + twistTop.ToString() + " twistbot: " + twistBot.ToString() + " twisttotal: " + twistTotal.ToString());
112 System.Console.WriteLine("Extruder: taperBotFactorX: " + taperBotFactorX.ToString() + " taperBotFactorY: " + taperBotFactorY.ToString()
113 + " taperTopFactorX: " + taperTopFactorX.ToString() + " taperTopFactorY: " + taperTopFactorY.ToString());
114 System.Console.WriteLine("Extruder: PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString());
115#endif
116
117 //float percentOfPath = 0.0f;
118 float percentOfPath = (float)pathBegin * 2.0e-5f;
119 zOffset += percentOfPath;
120 bool done = false;
121 do // loop through the length of the path and add the layers
122 {
123 newLayer = m.Clone();
124
125 if (taperBotFactorX < 1.0f)
126 xProfileScale = 1.0f - (1.0f - percentOfPath) * (1.0f - taperBotFactorX);
127 else if (taperTopFactorX < 1.0f)
128 xProfileScale = 1.0f - percentOfPath * (1.0f - taperTopFactorX);
129 else xProfileScale = 1.0f;
130
131 if (taperBotFactorY < 1.0f)
132 yProfileScale = 1.0f - (1.0f - percentOfPath) * (1.0f - taperBotFactorY);
133 else if (taperTopFactorY < 1.0f)
134 yProfileScale = 1.0f - percentOfPath * (1.0f - taperTopFactorY);
135 else yProfileScale = 1.0f;
136
137#if SPAM
138 //System.Console.WriteLine("xProfileScale: " + xProfileScale.ToString() + " yProfileScale: " + yProfileScale.ToString());
139#endif
140 Vertex vTemp = new Vertex(0.0f, 0.0f, 0.0f);
141
142 // apply the taper to the profile before any rotations
143 if (xProfileScale != 1.0f || yProfileScale != 1.0f)
144 {
145 foreach (Vertex v in newLayer.vertices)
146 {
147 if (v != null)
148 {
149 v.X *= xProfileScale;
150 v.Y *= yProfileScale;
151 }
152 }
153 }
154
155
156 float twist = twistBot + (twistTotal * (float)percentOfPath);
157#if SPAM
158 System.Console.WriteLine("Extruder: percentOfPath: " + percentOfPath.ToString() + " zOffset: " + zOffset.ToString()
159 + " xProfileScale: " + xProfileScale.ToString() + " yProfileScale: " + yProfileScale.ToString());
160#endif
161
162 // apply twist rotation to the profile layer and position the layer in the prim
163
164 Quaternion profileRot = Quaternion.CreateFromAxisAngle(new Vector3(0.0f, 0.0f, 1.0f), twist);
165 foreach (Vertex v in newLayer.vertices)
166 {
167 if (v != null)
168 {
169 vTemp = v * profileRot;
170 v.X = vTemp.X + xOffset;
171 v.Y = vTemp.Y + yOffset;
172 v.Z = vTemp.Z + zOffset;
173 }
174 }
175
176 if (step == 0) // the first layer, invert normals
177 {
178 foreach (Triangle t in newLayer.triangles)
179 {
180 t.invertNormal();
181 }
182 }
183
184 result.Append(newLayer);
185
186 int iLastNull = 0;
187
188 if (lastLayer != null)
189 {
190 int i, count = newLayer.vertices.Count;
191
192 for (i = 0; i < count; i++)
193 {
194 int iNext = (i + 1);
195
196 if (lastLayer.vertices[i] == null) // cant make a simplex here
197 {
198 iLastNull = i + 1;
199 }
200 else
201 {
202 if (i == count - 1) // End of list
203 iNext = iLastNull;
204
205 if (lastLayer.vertices[iNext] == null) // Null means wrap to begin of last segment
206 iNext = iLastNull;
207
208 result.Add(new Triangle(newLayer.vertices[i], lastLayer.vertices[i], newLayer.vertices[iNext]));
209 result.Add(new Triangle(newLayer.vertices[iNext], lastLayer.vertices[i], lastLayer.vertices[iNext]));
210 }
211 }
212 }
213 lastLayer = newLayer;
214
215 // calc the step for the next interation of the loop
216
217 if (step < steps)
218 {
219 step++;
220 percentOfPath += (float)percentOfPathMultiplier;
221
222 xOffset += xOffsetStepIncrement;
223 yOffset += yOffsetStepIncrement;
224 zOffset += stepSize;
225
226 if (percentOfPath > 1.0f - (float)pathEnd * 2.0e-5f)
227 done = true;
228 }
229 else done = true;
230
231 } while (!done); // loop until all the layers in the path are completed
232
233 // scale the mesh to the desired size
234 float xScale = size.X;
235 float yScale = size.Y;
236 float zScale = size.Z;
237
238 foreach (Vertex v in result.vertices)
239 {
240 if (v != null)
241 {
242 v.X *= xScale;
243 v.Y *= yScale;
244 v.Z *= zScale;
245 }
246 }
247
248 return result;
249 }
250
251 /// <summary>
252 /// Extrudes a shape around a circular path. Used to create prim types torus, ring, and tube.
253 /// </summary>
254 /// <param name="m"></param>
255 /// <returns>a mesh of the extruded shape</returns>
256 public Mesh ExtrudeCircularPath(Mesh m)
257 {
258 Mesh result = new Mesh();
259
260 Mesh newLayer;
261 Mesh lastLayer = null;
262
263 int step;
264 int steps = 24;
265
266 float twistTotal = twistTop - twistBot;
267 // if the profile has a lot of twist, add more layers otherwise the layers may overlap
268 // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't
269 // accurately match the viewer
270 if (System.Math.Abs(twistTotal) > (float)System.Math.PI * 1.5f) steps *= 2;
271 if (System.Math.Abs(twistTotal) > (float)System.Math.PI * 3.0f) steps *= 2;
272
273 // double percentOfPathMultiplier = 1.0 / steps;
274 // double angleStepMultiplier = System.Math.PI * 2.0 / steps;
275
276 float yPathScale = pathScaleY * 0.5f;
277 float pathLength = pathCutEnd - pathCutBegin;
278 float totalSkew = skew * 2.0f * pathLength;
279 float skewStart = (-skew) + pathCutBegin * 2.0f * skew;
280
281 // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end
282 // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used
283 // to calculate the sine for generating the path radius appears to approximate it's effects there
284 // too, but there are some subtle differences in the radius which are noticeable as the prim size
285 // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on
286 // the meshes generated with this technique appear nearly identical in shape to the same prims when
287 // displayed by the viewer.
288
289
290 float startAngle = (float)(System.Math.PI * 2.0 * pathCutBegin * revolutions) - pushY * 0.9f;
291 float endAngle = (float)(System.Math.PI * 2.0 * pathCutEnd * revolutions) - pushY * 0.9f;
292 float stepSize = (float)0.2617993878; // 2*PI / 24 segments per revolution
293
294 step = (int)(startAngle / stepSize);
295 float angle = startAngle;
296
297 float xProfileScale = 1.0f;
298 float yProfileScale = 1.0f;
299
300
301#if SPAM
302 System.Console.WriteLine("Extruder: twistTop: " + twistTop.ToString() + " twistbot: " + twistBot.ToString() + " twisttotal: " + twistTotal.ToString());
303 System.Console.WriteLine("Extruder: startAngle: " + startAngle.ToString() + " endAngle: " + endAngle.ToString() + " step: " + step.ToString());
304 System.Console.WriteLine("Extruder: taperBotFactorX: " + taperBotFactorX.ToString() + " taperBotFactorY: " + taperBotFactorY.ToString()
305 + " taperTopFactorX: " + taperTopFactorX.ToString() + " taperTopFactorY: " + taperTopFactorY.ToString());
306 System.Console.WriteLine("Extruder: PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString());
307#endif
308
309 bool done = false;
310 do // loop through the length of the path and add the layers
311 {
312 newLayer = m.Clone();
313
314 float percentOfPath = (angle - startAngle) / (endAngle - startAngle); // endAngle should always be larger than startAngle
315
316 if (pathTaperX > 0.001f) // can't really compare to 0.0f as the value passed is never exactly zero
317 xProfileScale = 1.0f - percentOfPath * pathTaperX;
318 else if (pathTaperX < -0.001f)
319 xProfileScale = 1.0f + (1.0f - percentOfPath) * pathTaperX;
320 else xProfileScale = 1.0f;
321
322 if (pathTaperY > 0.001f)
323 yProfileScale = 1.0f - percentOfPath * pathTaperY;
324 else if (pathTaperY < -0.001f)
325 yProfileScale = 1.0f + (1.0f - percentOfPath) * pathTaperY;
326 else yProfileScale = 1.0f;
327
328#if SPAM
329 //System.Console.WriteLine("xProfileScale: " + xProfileScale.ToString() + " yProfileScale: " + yProfileScale.ToString());
330#endif
331 Vertex vTemp = new Vertex(0.0f, 0.0f, 0.0f);
332
333 // apply the taper to the profile before any rotations
334 if (xProfileScale != 1.0f || yProfileScale != 1.0f)
335 {
336 foreach (Vertex v in newLayer.vertices)
337 {
338 if (v != null)
339 {
340 v.X *= xProfileScale;
341 v.Y *= yProfileScale;
342 }
343 }
344 }
345
346 float radiusScale;
347
348 if (radius > 0.001f)
349 radiusScale = 1.0f - radius * percentOfPath;
350 else if (radius < 0.001f)
351 radiusScale = 1.0f + radius * (1.0f - percentOfPath);
352 else
353 radiusScale = 1.0f;
354
355#if SPAM
356 System.Console.WriteLine("Extruder: angle: " + angle.ToString() + " percentOfPath: " + percentOfPath.ToString()
357 + " radius: " + radius.ToString() + " radiusScale: " + radiusScale.ToString()
358 + " xProfileScale: " + xProfileScale.ToString() + " yProfileScale: " + yProfileScale.ToString());
359#endif
360
361 float twist = twistBot + (twistTotal * (float)percentOfPath);
362
363 float xOffset;
364 float yOffset;
365 float zOffset;
366
367 xOffset = 0.5f * (skewStart + totalSkew * (float)percentOfPath);
368 xOffset += (float) System.Math.Sin(angle) * pushX * 0.45f;
369 yOffset = (float)(System.Math.Cos(angle) * (0.5f - yPathScale)) * radiusScale;
370 zOffset = (float)(System.Math.Sin(angle + pushY * 0.9f) * (0.5f - yPathScale)) * radiusScale;
371
372 // next apply twist rotation to the profile layer
373 if (twistTotal != 0.0f || twistBot != 0.0f)
374 {
375 Quaternion profileRot = new Quaternion(new Vector3(0.0f, 0.0f, 1.0f), twist);
376 foreach (Vertex v in newLayer.vertices)
377 {
378 if (v != null)
379 {
380 vTemp = v * profileRot;
381 v.X = vTemp.X;
382 v.Y = vTemp.Y;
383 v.Z = vTemp.Z;
384 }
385 }
386 }
387
388 // now orient the rotation of the profile layer relative to it's position on the path
389 // adding pushY to the angle used to generate the quat appears to approximate the viewer
390 Quaternion layerRot = Quaternion.CreateFromAxisAngle(new Vector3(1.0f, 0.0f, 0.0f), (float)angle + pushY * 0.9f);
391 foreach (Vertex v in newLayer.vertices)
392 {
393 if (v != null)
394 {
395 vTemp = v * layerRot;
396 v.X = vTemp.X + xOffset;
397 v.Y = vTemp.Y + yOffset;
398 v.Z = vTemp.Z + zOffset;
399 }
400 }
401
402 if (angle == startAngle) // the first layer, invert normals
403 {
404 foreach (Triangle t in newLayer.triangles)
405 {
406 t.invertNormal();
407 }
408 }
409
410 result.Append(newLayer);
411
412 int iLastNull = 0;
413
414 if (lastLayer != null)
415 {
416 int i, count = newLayer.vertices.Count;
417
418 for (i = 0; i < count; i++)
419 {
420 int iNext = (i + 1);
421
422 if (lastLayer.vertices[i] == null) // cant make a simplex here
423 {
424 iLastNull = i + 1;
425 }
426 else
427 {
428 if (i == count - 1) // End of list
429 iNext = iLastNull;
430
431 if (lastLayer.vertices[iNext] == null) // Null means wrap to begin of last segment
432 iNext = iLastNull;
433
434 result.Add(new Triangle(newLayer.vertices[i], lastLayer.vertices[i], newLayer.vertices[iNext]));
435 result.Add(new Triangle(newLayer.vertices[iNext], lastLayer.vertices[i], lastLayer.vertices[iNext]));
436 }
437 }
438 }
439 lastLayer = newLayer;
440
441 // calc the angle for the next interation of the loop
442 if (angle >= endAngle)
443 {
444 done = true;
445 }
446 else
447 {
448 angle = stepSize * ++step;
449 if (angle > endAngle)
450 angle = endAngle;
451 }
452 } while (!done); // loop until all the layers in the path are completed
453
454 // scale the mesh to the desired size
455 float xScale = size.X;
456 float yScale = size.Y;
457 float zScale = size.Z;
458
459 foreach (Vertex v in result.vertices)
460 {
461 if (v != null)
462 {
463 v.X *= xScale;
464 v.Y *= yScale;
465 v.Z *= zScale;
466 }
467 }
468
469 return result;
470 }
471 }
472}