From 7fbe942792b57c6867f3a7b98475c6c1a5cc56c8 Mon Sep 17 00:00:00 2001 From: Dahlia Trimble Date: Fri, 10 Oct 2008 08:22:13 +0000 Subject: refactoring PrimMesher to add viewer compatable features and some code cleanup --- OpenSim/Region/Physics/Meshing/PrimMesher.cs | 308 +++++++++++++++++++-------- 1 file changed, 218 insertions(+), 90 deletions(-) (limited to 'OpenSim/Region/Physics/Meshing/PrimMesher.cs') diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs index 5e08fdf..caf5966 100644 --- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs +++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs @@ -27,12 +27,77 @@ using System; using System.Collections.Generic; +using System.Text; using System.IO; -using OpenSim.Region.Physics.Manager; -using OpenMetaverse; -namespace OpenSim.Region.Physics.Meshing +namespace PrimMesher { + public struct Quat + { + /// X value + public float X; + /// Y value + public float Y; + /// Z value + public float Z; + /// W value + public float W; + + public Quat(float x, float y, float z, float w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + public Quat(Coord axis, float angle) + { + axis = axis.Normalize(); + + angle *= 0.5f; + float c = (float)Math.Cos(angle); + float s = (float)Math.Sin(angle); + + X = axis.X * s; + Y = axis.Y * s; + Z = axis.Z * s; + W = c; + + Normalize(); + } + + public float Length() + { + return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W); + } + + public Quat Normalize() + { + const float MAG_THRESHOLD = 0.0000001f; + float mag = Length(); + + // Catch very small rounding errors when normalizing + if (mag > MAG_THRESHOLD) + { + float oomag = 1f / mag; + X *= oomag; + Y *= oomag; + Z *= oomag; + W *= oomag; + } + else + { + X = 0f; + Y = 0f; + Z = 0f; + W = 1f; + } + + return this; + } + } + public struct Coord { public float X; @@ -46,23 +111,119 @@ namespace OpenSim.Region.Physics.Meshing this.Z = z; } + public float Length() + { + return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z); + } + + public Coord Normalize() + { + const float MAG_THRESHOLD = 0.0000001f; + float mag = Length(); + + // Catch very small rounding errors when normalizing + if (mag > MAG_THRESHOLD) + { + float oomag = 1.0f / mag; + this.X *= oomag; + this.Y *= oomag; + this.Z *= oomag; + } + else + { + this.X = 0.0f; + this.Y = 0.0f; + this.Z = 0.0f; + } + + return this; + } + public override string ToString() { return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString(); } + + public static Coord Cross(Coord c1, Coord c2) + { + return new Coord( + c1.Y * c2.Z - c2.Y * c1.Z, + c1.Z * c2.X - c2.Z * c1.X, + c1.X * c2.Y - c2.X * c1.Y + ); + } + + public static Coord operator *(Coord v, Quat q) + { + // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ + + Coord c2 = new Coord(0.0f, 0.0f, 0.0f); + + c2.X = q.W * q.W * v.X + + 2f * q.Y * q.W * v.Z - + 2f * q.Z * q.W * v.Y + + q.X * q.X * v.X + + 2f * q.Y * q.X * v.Y + + 2f * q.Z * q.X * v.Z - + q.Z * q.Z * v.X - + q.Y * q.Y * v.X; + + c2.Y = + 2f * q.X * q.Y * v.X + + q.Y * q.Y * v.Y + + 2f * q.Z * q.Y * v.Z + + 2f * q.W * q.Z * v.X - + q.Z * q.Z * v.Y + + q.W * q.W * v.Y - + 2f * q.X * q.W * v.Z - + q.X * q.X * v.Y; + + c2.Z = + 2f * q.X * q.Z * v.X + + 2f * q.Y * q.Z * v.Y + + q.Z * q.Z * v.Z - + 2f * q.W * q.Y * v.X - + q.Y * q.Y * v.Z + + 2f * q.W * q.X * v.Y - + q.X * q.X * v.Z + + q.W * q.W * v.Z; + + return c2; + } } public struct Face { + // vertices public int v1; public int v2; public int v3; + //normals + public int n1; + public int n2; + public int n3; + public Face(int v1, int v2, int v3) { this.v1 = v1; this.v2 = v2; this.v3 = v3; + + this.n1 = 0; + this.n2 = 0; + this.n3 = 0; + } + + public Face(int v1, int v2, int v3, int n1, int n2, int n3) + { + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + + this.n1 = n1; + this.n2 = n2; + this.n3 = n3; } } @@ -80,81 +241,6 @@ namespace OpenSim.Region.Physics.Meshing } } - //internal float angles3[][] = [ - //[0.0f, 1.0f, 0.0f], - //[0.33333333333333331f, -0.49999999999999978f, 0.86602540378443871f], - //[0.66666666666666663f, -0.50000000000000044f, -0.86602540378443837f], - //[1.0f, 1.0f, -2.4492127076447545e-016f]]; - /* -angles3 = [ - [0.0, 1.0, 0.0], - [0.33333333333333331, -0.49999999999999978, 0.86602540378443871], - [0.66666666666666663, -0.50000000000000044, -0.86602540378443837], - [1.0, 1.0, -2.4492127076447545e-016]] - -angles4 = [ - [0.0, 1.0, 0.0], - [0.25, 0.0, 1.0], - [0.5, -1.0, 0.0], - [0.75, 0.0, -1.0], - [1.0, 1.0, 0.0]] - -angles24 = [ - [0.0, 0.5, 0.0], - [0.041666666666666664, 0.48296291314453416, 0.12940952255126037], - [0.083333333333333329, 0.43301270189221935, 0.25], - [0.125, 0.35355339059327379, 0.35355339059327373], - [0.16666666666666666, 0.25, 0.4330127018922193], - [0.20833333333333331, 0.12940952255126048, 0.4829629131445341], - [0.25, 0.0, 0.5], - [0.29166666666666663, -0.12940952255126031, 0.48296291314453416], - [0.33333333333333331, -0.25, 0.43301270189221935], - [0.375, -0.35355339059327373, 0.35355339059327379], - [0.41666666666666663, -0.43301270189221924, 0.25], - [0.45833333333333331, -0.4829629131445341, 0.12940952255126051], - [0.5, -0.5, 0.0], - [0.54166666666666663, -0.48296291314453421, -0.12940952255126018], - [0.58333333333333326, -0.43301270189221941, -0.25], - [0.62499999999999989, -0.35355339059327395, -0.35355339059327356], - [0.66666666666666663, -0.25, -0.43301270189221919], - [0.70833333333333326, -0.12940952255126076, -0.48296291314453405], - [0.75, 0.0, -0.5], - [0.79166666666666663, 0.12940952255126015, -0.48296291314453421], - [0.83333333333333326, 0.25, -0.43301270189221952], - [0.875, 0.35355339059327368, -0.35355339059327384], - [0.91666666666666663, 0.43301270189221919, -0.25], - [0.95833333333333326, 0.48296291314453405, -0.12940952255126079], - [1.0, 0.5, 0.0]] - -angles24 = [ - [0.0, 1.0, 0.0], - [0.041666666666666664, 0.96592582628906831, 0.25881904510252074], - [0.083333333333333329, 0.86602540378443871, 0.5], - [0.125, 0.70710678118654757, 0.70710678118654746], - [0.16666666666666667, 0.5, 0.8660254037844386], - [0.20833333333333331, 0.25881904510252096, 0.9659258262890682], - [0.25, 6.1230317691118863e-017, 1.0], - [0.29166666666666663, -0.25881904510252063, 0.96592582628906831], - [0.33333333333333333, -0.5, 0.86602540378443871], - [0.375, -0.70710678118654746, 0.70710678118654757], - [0.41666666666666663, -0.86602540378443849, 0.5], - [0.45833333333333331, -0.9659258262890682, 0.25881904510252102], - [0.5, -1.0, 1.2246063538223773e-016], - [0.54166666666666663, -0.96592582628906842, -0.25881904510252035], - [0.58333333333333326, -0.86602540378443882, -0.5], - [0.62499999999999989, -0.70710678118654791, -0.70710678118654713], - [0.66666666666666667, -0.5, -0.86602540378443837], - [0.70833333333333326, -0.25881904510252152, -0.96592582628906809], - [0.75, -1.8369095307335659e-016, -1.0], - [0.79166666666666663, 0.2588190451025203, -0.96592582628906842], - [0.83333333333333326, 0.5, -0.86602540378443904], - [0.875, 0.70710678118654735, -0.70710678118654768], - [0.91666666666666663, 0.86602540378443837, -0.5], - [0.95833333333333326, 0.96592582628906809, -0.25881904510252157], - [1.0, 1.0, -2.4492127076447545e-016]] - - */ - internal class AngleList { private float iX, iY; // intersection point @@ -226,7 +312,7 @@ angles24 = [ internal List angles; - internal void makeAngles( int sides, float startAngle, float stopAngle ) + internal void makeAngles(int sides, float startAngle, float stopAngle) { angles = new List(); double twoPi = System.Math.PI * 2.0; @@ -556,7 +642,7 @@ angles24 = [ } } - public void AddRot(Quaternion q) + public void AddRot(Quat q) { int i; int numVerts = this.coords.Count; @@ -565,7 +651,7 @@ angles24 = [ for (i = 0; i < numVerts; i++) { vert = this.coords[i]; - Vertex v = new Vertex(vert.X, vert.Y, vert.Z) * q; + Coord v = new Coord(vert.X, vert.Y, vert.Z) * q; vert.X = v.X; vert.Y = v.Y; @@ -646,6 +732,7 @@ angles24 = [ private const float twoPi = 2.0f * (float)Math.PI; public List coords; + public List normals; public List faces; public int sides = 4; @@ -712,7 +799,7 @@ angles24 = [ if (sides < 3) this.sides = 3; - if ( hollowSides < 3) + if (hollowSides < 3) this.hollowSides = 3; if (profileStart < 0.0f) this.profileStart = 0.0f; @@ -795,7 +882,7 @@ angles24 = [ Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true); if (initialProfileRot != 0.0f) - profile.AddRot(Quaternion.CreateFromAxisAngle(new Vector3(0.0f, 0.0f, 1.0f), initialProfileRot)); + profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); bool done = false; while (!done) @@ -819,7 +906,7 @@ angles24 = [ float twist = twistBegin + twistTotal * percentOfPath; if (twist != 0.0f) - newLayer.AddRot(Quaternion.CreateFromAxisAngle(new Vector3(0.0f, 0.0f, 1.0f), twist)); + newLayer.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), twist)); newLayer.AddPos(xOffset, yOffset, zOffset); @@ -972,7 +1059,7 @@ angles24 = [ Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, needEndFaces); if (initialProfileRot != 0.0f) - profile.AddRot(Quaternion.CreateFromAxisAngle(new Vector3(0.0f, 0.0f, 1.0f), initialProfileRot)); + profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); bool done = false; while (!done) // loop through the length of the path and add the layers @@ -980,7 +1067,7 @@ angles24 = [ bool isEndLayer = false; if (angle == startAngle || angle >= endAngle) isEndLayer = true; - + Profile newLayer = profile.Clone(isEndLayer && needEndFaces); float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX; @@ -1019,12 +1106,12 @@ angles24 = [ // next apply twist rotation to the profile layer if (twistTotal != 0.0f || twistBegin != 0.0f) - newLayer.AddRot(Quaternion.CreateFromAxisAngle(new Vector3(0.0f, 0.0f, 1.0f), twist)); + newLayer.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), twist)); // now orient the rotation of the profile layer relative to it's position on the path // adding taperY to the angle used to generate the quat appears to approximate the viewer //newLayer.AddRot(new Quaternion(new Vertex(1.0f, 0.0f, 0.0f), angle + this.topShearY * 0.9f)); - newLayer.AddRot(Quaternion.CreateFromAxisAngle(new Vector3(1.0f, 0.0f, 0.0f), angle + this.topShearY)); + newLayer.AddRot(new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY)); newLayer.AddPos(xOffset, yOffset, zOffset); if (angle == startAngle) @@ -1084,6 +1171,47 @@ angles24 = [ } } + public Coord SurfaceNormal(int faceIndex) + { + int numFaces = faces.Count; + if (faceIndex < 0 || faceIndex >= faces.Count) + return new Coord(0.0f, 0.0f, 0.0f); + + Face face = faces[faceIndex]; + Coord c1 = coords[face.v1]; + Coord c2 = coords[face.v2]; + Coord c3 = coords[face.v3]; + + Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); + Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); + + Coord normal = Coord.Cross(edge1, edge2); + + normal.Normalize(); + + return normal; + } + + public void CalcNormals() + { + int numFaces = faces.Count; + this.normals = new List(); + + for (int i = 0; i < numFaces; i++) + { + Face face = faces[i]; + + this.normals.Add(SurfaceNormal(i).Normalize()); + + int normIndex = normals.Count - 1; + face.n1 = normIndex; + face.n2 = normIndex; + face.n3 = normIndex; + + this.faces[i] = face; + } + } + public void AddPos(float x, float y, float z) { int i; @@ -1100,7 +1228,7 @@ angles24 = [ } } - public void AddRot(Quaternion q) + public void AddRot(Quat q) { int i; int numVerts = this.coords.Count; @@ -1109,7 +1237,7 @@ angles24 = [ for (i = 0; i < numVerts; i++) { vert = this.coords[i]; - Vertex v = new Vertex(vert.X, vert.Y, vert.Z) * q; + Coord v = new Coord(vert.X, vert.Y, vert.Z) * q; vert.X = v.X; vert.Y = v.Y; -- cgit v1.1