clockwerk-opensim-stable – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 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 OpenSimulator 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 | |||
28 | using System; |
||
29 | using System.Collections.Generic; |
||
30 | using System.Diagnostics; |
||
31 | using System.Globalization; |
||
32 | using OpenMetaverse; |
||
33 | using OpenSim.Region.Physics.Manager; |
||
34 | using OpenSim.Region.Physics.Meshing; |
||
35 | |||
36 | public class Vertex : IComparable<Vertex> |
||
37 | { |
||
38 | Vector3 vector; |
||
39 | |||
40 | public float X |
||
41 | { |
||
42 | get { return vector.X; } |
||
43 | set { vector.X = value; } |
||
44 | } |
||
45 | |||
46 | public float Y |
||
47 | { |
||
48 | get { return vector.Y; } |
||
49 | set { vector.Y = value; } |
||
50 | } |
||
51 | |||
52 | public float Z |
||
53 | { |
||
54 | get { return vector.Z; } |
||
55 | set { vector.Z = value; } |
||
56 | } |
||
57 | |||
58 | public Vertex(float x, float y, float z) |
||
59 | { |
||
60 | vector.X = x; |
||
61 | vector.Y = y; |
||
62 | vector.Z = z; |
||
63 | } |
||
64 | |||
65 | public Vertex normalize() |
||
66 | { |
||
67 | float tlength = vector.Length(); |
||
68 | if (tlength != 0f) |
||
69 | { |
||
70 | float mul = 1.0f / tlength; |
||
71 | return new Vertex(vector.X * mul, vector.Y * mul, vector.Z * mul); |
||
72 | } |
||
73 | else |
||
74 | { |
||
75 | return new Vertex(0f, 0f, 0f); |
||
76 | } |
||
77 | } |
||
78 | |||
79 | public Vertex cross(Vertex v) |
||
80 | { |
||
81 | return new Vertex(vector.Y * v.Z - vector.Z * v.Y, vector.Z * v.X - vector.X * v.Z, vector.X * v.Y - vector.Y * v.X); |
||
82 | } |
||
83 | |||
84 | // disable warning: mono compiler moans about overloading |
||
85 | // operators hiding base operator but should not according to C# |
||
86 | // language spec |
||
87 | #pragma warning disable 0108 |
||
88 | public static Vertex operator *(Vertex v, Quaternion q) |
||
89 | { |
||
90 | // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ |
||
91 | |||
92 | Vertex v2 = new Vertex(0f, 0f, 0f); |
||
93 | |||
94 | v2.X = q.W * q.W * v.X + |
||
95 | 2f * q.Y * q.W * v.Z - |
||
96 | 2f * q.Z * q.W * v.Y + |
||
97 | q.X * q.X * v.X + |
||
98 | 2f * q.Y * q.X * v.Y + |
||
99 | 2f * q.Z * q.X * v.Z - |
||
100 | q.Z * q.Z * v.X - |
||
101 | q.Y * q.Y * v.X; |
||
102 | |||
103 | v2.Y = |
||
104 | 2f * q.X * q.Y * v.X + |
||
105 | q.Y * q.Y * v.Y + |
||
106 | 2f * q.Z * q.Y * v.Z + |
||
107 | 2f * q.W * q.Z * v.X - |
||
108 | q.Z * q.Z * v.Y + |
||
109 | q.W * q.W * v.Y - |
||
110 | 2f * q.X * q.W * v.Z - |
||
111 | q.X * q.X * v.Y; |
||
112 | |||
113 | v2.Z = |
||
114 | 2f * q.X * q.Z * v.X + |
||
115 | 2f * q.Y * q.Z * v.Y + |
||
116 | q.Z * q.Z * v.Z - |
||
117 | 2f * q.W * q.Y * v.X - |
||
118 | q.Y * q.Y * v.Z + |
||
119 | 2f * q.W * q.X * v.Y - |
||
120 | q.X * q.X * v.Z + |
||
121 | q.W * q.W * v.Z; |
||
122 | |||
123 | return v2; |
||
124 | } |
||
125 | |||
126 | public static Vertex operator +(Vertex v1, Vertex v2) |
||
127 | { |
||
128 | return new Vertex(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z); |
||
129 | } |
||
130 | |||
131 | public static Vertex operator -(Vertex v1, Vertex v2) |
||
132 | { |
||
133 | return new Vertex(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); |
||
134 | } |
||
135 | |||
136 | public static Vertex operator *(Vertex v1, Vertex v2) |
||
137 | { |
||
138 | return new Vertex(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z); |
||
139 | } |
||
140 | |||
141 | public static Vertex operator +(Vertex v1, float am) |
||
142 | { |
||
143 | v1.X += am; |
||
144 | v1.Y += am; |
||
145 | v1.Z += am; |
||
146 | return v1; |
||
147 | } |
||
148 | |||
149 | public static Vertex operator -(Vertex v1, float am) |
||
150 | { |
||
151 | v1.X -= am; |
||
152 | v1.Y -= am; |
||
153 | v1.Z -= am; |
||
154 | return v1; |
||
155 | } |
||
156 | |||
157 | public static Vertex operator *(Vertex v1, float am) |
||
158 | { |
||
159 | v1.X *= am; |
||
160 | v1.Y *= am; |
||
161 | v1.Z *= am; |
||
162 | return v1; |
||
163 | } |
||
164 | |||
165 | public static Vertex operator /(Vertex v1, float am) |
||
166 | { |
||
167 | if (am == 0f) |
||
168 | { |
||
169 | return new Vertex(0f,0f,0f); |
||
170 | } |
||
171 | float mul = 1.0f / am; |
||
172 | v1.X *= mul; |
||
173 | v1.Y *= mul; |
||
174 | v1.Z *= mul; |
||
175 | return v1; |
||
176 | } |
||
177 | #pragma warning restore 0108 |
||
178 | |||
179 | |||
180 | public float dot(Vertex v) |
||
181 | { |
||
182 | return X * v.X + Y * v.Y + Z * v.Z; |
||
183 | } |
||
184 | |||
185 | public Vertex(Vector3 v) |
||
186 | { |
||
187 | vector = v; |
||
188 | } |
||
189 | |||
190 | public Vertex Clone() |
||
191 | { |
||
192 | return new Vertex(X, Y, Z); |
||
193 | } |
||
194 | |||
195 | public static Vertex FromAngle(double angle) |
||
196 | { |
||
197 | return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f); |
||
198 | } |
||
199 | |||
200 | public float Length() |
||
201 | { |
||
202 | return vector.Length(); |
||
203 | } |
||
204 | |||
205 | public virtual bool Equals(Vertex v, float tolerance) |
||
206 | { |
||
207 | Vertex diff = this - v; |
||
208 | float d = diff.Length(); |
||
209 | if (d < tolerance) |
||
210 | return true; |
||
211 | |||
212 | return false; |
||
213 | } |
||
214 | |||
215 | |||
216 | public int CompareTo(Vertex other) |
||
217 | { |
||
218 | if (X < other.X) |
||
219 | return -1; |
||
220 | |||
221 | if (X > other.X) |
||
222 | return 1; |
||
223 | |||
224 | if (Y < other.Y) |
||
225 | return -1; |
||
226 | |||
227 | if (Y > other.Y) |
||
228 | return 1; |
||
229 | |||
230 | if (Z < other.Z) |
||
231 | return -1; |
||
232 | |||
233 | if (Z > other.Z) |
||
234 | return 1; |
||
235 | |||
236 | return 0; |
||
237 | } |
||
238 | |||
239 | public static bool operator >(Vertex me, Vertex other) |
||
240 | { |
||
241 | return me.CompareTo(other) > 0; |
||
242 | } |
||
243 | |||
244 | public static bool operator <(Vertex me, Vertex other) |
||
245 | { |
||
246 | return me.CompareTo(other) < 0; |
||
247 | } |
||
248 | |||
249 | public String ToRaw() |
||
250 | { |
||
251 | // Why this stuff with the number formatter? |
||
252 | // Well, the raw format uses the english/US notation of numbers |
||
253 | // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1. |
||
254 | // The german notation uses these characters exactly vice versa! |
||
255 | // The Float.ToString() routine is a localized one, giving different results depending on the country |
||
256 | // settings your machine works with. Unusable for a machine readable file format :-( |
||
257 | NumberFormatInfo nfi = new NumberFormatInfo(); |
||
258 | nfi.NumberDecimalSeparator = "."; |
||
259 | nfi.NumberDecimalDigits = 3; |
||
260 | |||
261 | String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi); |
||
262 | |||
263 | return s1; |
||
264 | } |
||
265 | } |
||
266 | |||
267 | public class Triangle |
||
268 | { |
||
269 | public Vertex v1; |
||
270 | public Vertex v2; |
||
271 | public Vertex v3; |
||
272 | |||
273 | private float radius_square; |
||
274 | private float cx; |
||
275 | private float cy; |
||
276 | |||
277 | public Triangle(Vertex _v1, Vertex _v2, Vertex _v3) |
||
278 | { |
||
279 | v1 = _v1; |
||
280 | v2 = _v2; |
||
281 | v3 = _v3; |
||
282 | |||
283 | CalcCircle(); |
||
284 | } |
||
285 | |||
286 | public bool isInCircle(float x, float y) |
||
287 | { |
||
288 | float dx, dy; |
||
289 | float dd; |
||
290 | |||
291 | dx = x - cx; |
||
292 | dy = y - cy; |
||
293 | |||
294 | dd = dx*dx + dy*dy; |
||
295 | if (dd < radius_square) |
||
296 | return true; |
||
297 | else |
||
298 | return false; |
||
299 | } |
||
300 | |||
301 | public bool isDegraded() |
||
302 | { |
||
303 | // This means, the vertices of this triangle are somewhat strange. |
||
304 | // They either line up or at least two of them are identical |
||
305 | return (radius_square == 0.0); |
||
306 | } |
||
307 | |||
308 | private void CalcCircle() |
||
309 | { |
||
310 | // Calculate the center and the radius of a circle given by three points p1, p2, p3 |
||
311 | // It is assumed, that the triangles vertices are already set correctly |
||
312 | double p1x, p2x, p1y, p2y, p3x, p3y; |
||
313 | |||
314 | // Deviation of this routine: |
||
315 | // A circle has the general equation (M-p)^2=r^2, where M and p are vectors |
||
316 | // this gives us three equations f(p)=r^2, each for one point p1, p2, p3 |
||
317 | // putting respectively two equations together gives two equations |
||
318 | // f(p1)=f(p2) and f(p1)=f(p3) |
||
319 | // bringing all constant terms to one side brings them to the form |
||
320 | // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors) |
||
321 | // and c1, c2 are scalars (Naming conventions like the variables below) |
||
322 | // Now using the equations that are formed by the components of the vectors |
||
323 | // and isolate Mx lets you make one equation that only holds My |
||
324 | // The rest is straight forward and eaasy :-) |
||
325 | // |
||
326 | |||
327 | /* helping variables for temporary results */ |
||
328 | double c1, c2; |
||
329 | double v1x, v1y, v2x, v2y; |
||
330 | |||
331 | double z, n; |
||
332 | |||
333 | double rx, ry; |
||
334 | |||
335 | // Readout the three points, the triangle consists of |
||
336 | p1x = v1.X; |
||
337 | p1y = v1.Y; |
||
338 | |||
339 | p2x = v2.X; |
||
340 | p2y = v2.Y; |
||
341 | |||
342 | p3x = v3.X; |
||
343 | p3y = v3.Y; |
||
344 | |||
345 | /* calc helping values first */ |
||
346 | c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2; |
||
347 | c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2; |
||
348 | |||
349 | v1x = p1x - p2x; |
||
350 | v1y = p1y - p2y; |
||
351 | |||
352 | v2x = p1x - p3x; |
||
353 | v2y = p1y - p3y; |
||
354 | |||
355 | z = (c1*v2x - c2*v1x); |
||
356 | n = (v1y*v2x - v2y*v1x); |
||
357 | |||
358 | if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location |
||
359 | { |
||
360 | radius_square = 0.0f; |
||
361 | return; |
||
362 | } |
||
363 | |||
364 | cy = (float) (z/n); |
||
365 | |||
366 | if (v2x != 0.0) |
||
367 | { |
||
368 | cx = (float) ((c2 - v2y*cy)/v2x); |
||
369 | } |
||
370 | else if (v1x != 0.0) |
||
371 | { |
||
372 | cx = (float) ((c1 - v1y*cy)/v1x); |
||
373 | } |
||
374 | else |
||
375 | { |
||
376 | Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */ |
||
377 | } |
||
378 | |||
379 | rx = (p1x - cx); |
||
380 | ry = (p1y - cy); |
||
381 | |||
382 | radius_square = (float) (rx*rx + ry*ry); |
||
383 | } |
||
384 | |||
385 | public override String ToString() |
||
386 | { |
||
387 | NumberFormatInfo nfi = new NumberFormatInfo(); |
||
388 | nfi.CurrencyDecimalDigits = 2; |
||
389 | nfi.CurrencyDecimalSeparator = "."; |
||
390 | |||
391 | String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">"; |
||
392 | String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">"; |
||
393 | String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">"; |
||
394 | |||
395 | return s1 + ";" + s2 + ";" + s3; |
||
396 | } |
||
397 | |||
398 | public Vector3 getNormal() |
||
399 | { |
||
400 | // Vertices |
||
401 | |||
402 | // Vectors for edges |
||
403 | Vector3 e1; |
||
404 | Vector3 e2; |
||
405 | |||
406 | e1 = new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); |
||
407 | e2 = new Vector3(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z); |
||
408 | |||
409 | // Cross product for normal |
||
410 | Vector3 n = Vector3.Cross(e1, e2); |
||
411 | |||
412 | // Length |
||
413 | float l = n.Length(); |
||
414 | |||
415 | // Normalized "normal" |
||
416 | n = n/l; |
||
417 | |||
418 | return n; |
||
419 | } |
||
420 | |||
421 | public void invertNormal() |
||
422 | { |
||
423 | Vertex vt; |
||
424 | vt = v1; |
||
425 | v1 = v2; |
||
426 | v2 = vt; |
||
427 | } |
||
428 | |||
429 | // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and |
||
430 | // debugging purposes |
||
431 | public String ToStringRaw() |
||
432 | { |
||
433 | String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw(); |
||
434 | return output; |
||
435 | } |
||
436 | } |