From e9a56d5e194b9b80f8adf5d1ce5d9ab3f5f7bfdd Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 12 Sep 2015 21:38:26 +0100 Subject: rename Ubit physics modules --- .../PhysicsModules/UbitMeshing/HelperTypes.cs | 340 ---- OpenSim/Region/PhysicsModules/UbitMeshing/Mesh.cs | 601 ------- .../PhysicsModules/UbitMeshing/Meshmerizer.cs | 1458 ----------------- .../PhysicsModules/UbitMeshing/PrimMesher.cs | 1708 -------------------- .../UbitMeshing/Properties/AssemblyInfo.cs | 36 - .../Region/PhysicsModules/UbitMeshing/SculptMap.cs | 244 --- .../PhysicsModules/UbitMeshing/SculptMesh.cs | 220 --- 7 files changed, 4607 deletions(-) delete mode 100644 OpenSim/Region/PhysicsModules/UbitMeshing/HelperTypes.cs delete mode 100644 OpenSim/Region/PhysicsModules/UbitMeshing/Mesh.cs delete mode 100644 OpenSim/Region/PhysicsModules/UbitMeshing/Meshmerizer.cs delete mode 100644 OpenSim/Region/PhysicsModules/UbitMeshing/PrimMesher.cs delete mode 100644 OpenSim/Region/PhysicsModules/UbitMeshing/Properties/AssemblyInfo.cs delete mode 100644 OpenSim/Region/PhysicsModules/UbitMeshing/SculptMap.cs delete mode 100644 OpenSim/Region/PhysicsModules/UbitMeshing/SculptMesh.cs (limited to 'OpenSim/Region/PhysicsModules/UbitMeshing') diff --git a/OpenSim/Region/PhysicsModules/UbitMeshing/HelperTypes.cs b/OpenSim/Region/PhysicsModules/UbitMeshing/HelperTypes.cs deleted file mode 100644 index fb38cdb..0000000 --- a/OpenSim/Region/PhysicsModules/UbitMeshing/HelperTypes.cs +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using OpenMetaverse; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Region.PhysicsModule.UbitMeshing; - -public class Vertex : IComparable -{ - Vector3 vector; - - public float X - { - get { return vector.X; } - set { vector.X = value; } - } - - public float Y - { - get { return vector.Y; } - set { vector.Y = value; } - } - - public float Z - { - get { return vector.Z; } - set { vector.Z = value; } - } - - public Vertex(float x, float y, float z) - { - vector.X = x; - vector.Y = y; - vector.Z = z; - } - - public Vertex normalize() - { - float tlength = vector.Length(); - if (tlength != 0f) - { - float mul = 1.0f / tlength; - return new Vertex(vector.X * mul, vector.Y * mul, vector.Z * mul); - } - else - { - return new Vertex(0f, 0f, 0f); - } - } - - public Vertex cross(Vertex v) - { - 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); - } - - // disable warning: mono compiler moans about overloading - // operators hiding base operator but should not according to C# - // language spec -#pragma warning disable 0108 - public static Vertex operator *(Vertex v, Quaternion q) - { - // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ - - Vertex v2 = new Vertex(0f, 0f, 0f); - - v2.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; - - v2.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; - - v2.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 v2; - } - - public static Vertex operator +(Vertex v1, Vertex v2) - { - return new Vertex(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z); - } - - public static Vertex operator -(Vertex v1, Vertex v2) - { - return new Vertex(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); - } - - public static Vertex operator *(Vertex v1, Vertex v2) - { - return new Vertex(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z); - } - - public static Vertex operator +(Vertex v1, float am) - { - v1.X += am; - v1.Y += am; - v1.Z += am; - return v1; - } - - public static Vertex operator -(Vertex v1, float am) - { - v1.X -= am; - v1.Y -= am; - v1.Z -= am; - return v1; - } - - public static Vertex operator *(Vertex v1, float am) - { - v1.X *= am; - v1.Y *= am; - v1.Z *= am; - return v1; - } - - public static Vertex operator /(Vertex v1, float am) - { - if (am == 0f) - { - return new Vertex(0f,0f,0f); - } - float mul = 1.0f / am; - v1.X *= mul; - v1.Y *= mul; - v1.Z *= mul; - return v1; - } -#pragma warning restore 0108 - - - public float dot(Vertex v) - { - return X * v.X + Y * v.Y + Z * v.Z; - } - - public Vertex(Vector3 v) - { - vector = v; - } - - public Vertex Clone() - { - return new Vertex(X, Y, Z); - } - - public static Vertex FromAngle(double angle) - { - return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f); - } - - public float Length() - { - return vector.Length(); - } - - public virtual bool Equals(Vertex v, float tolerance) - { - Vertex diff = this - v; - float d = diff.Length(); - if (d < tolerance) - return true; - - return false; - } - - - public int CompareTo(Vertex other) - { - if (X < other.X) - return -1; - - if (X > other.X) - return 1; - - if (Y < other.Y) - return -1; - - if (Y > other.Y) - return 1; - - if (Z < other.Z) - return -1; - - if (Z > other.Z) - return 1; - - return 0; - } - - public static bool operator >(Vertex me, Vertex other) - { - return me.CompareTo(other) > 0; - } - - public static bool operator <(Vertex me, Vertex other) - { - return me.CompareTo(other) < 0; - } - - public String ToRaw() - { - // Why this stuff with the number formatter? - // Well, the raw format uses the english/US notation of numbers - // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1. - // The german notation uses these characters exactly vice versa! - // The Float.ToString() routine is a localized one, giving different results depending on the country - // settings your machine works with. Unusable for a machine readable file format :-( - NumberFormatInfo nfi = new NumberFormatInfo(); - nfi.NumberDecimalSeparator = "."; - nfi.NumberDecimalDigits = 6; - - String s1 = X.ToString(nfi) + " " + Y.ToString(nfi) + " " + Z.ToString(nfi); - - return s1; - } -} - -public class Triangle -{ - public Vertex v1; - public Vertex v2; - public Vertex v3; - - public Triangle(Vertex _v1, Vertex _v2, Vertex _v3) - { - v1 = _v1; - v2 = _v2; - v3 = _v3; - } - - public Triangle(float _v1x,float _v1y,float _v1z, - float _v2x,float _v2y,float _v2z, - float _v3x,float _v3y,float _v3z) - { - v1 = new Vertex(_v1x, _v1y, _v1z); - v2 = new Vertex(_v2x, _v2y, _v2z); - v3 = new Vertex(_v3x, _v3y, _v3z); - } - - public override String ToString() - { - NumberFormatInfo nfi = new NumberFormatInfo(); - nfi.CurrencyDecimalDigits = 2; - nfi.CurrencyDecimalSeparator = "."; - - String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">"; - String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">"; - String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">"; - - return s1 + ";" + s2 + ";" + s3; - } - - public Vector3 getNormal() - { - // Vertices - - // Vectors for edges - Vector3 e1; - Vector3 e2; - - e1 = new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); - e2 = new Vector3(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z); - - // Cross product for normal - Vector3 n = Vector3.Cross(e1, e2); - - // Length - float l = n.Length(); - - // Normalized "normal" - n = n/l; - - return n; - } - - public void invertNormal() - { - Vertex vt; - vt = v1; - v1 = v2; - v2 = vt; - } - - // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and - // debugging purposes - public String ToStringRaw() - { - String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw(); - return output; - } -} diff --git a/OpenSim/Region/PhysicsModules/UbitMeshing/Mesh.cs b/OpenSim/Region/PhysicsModules/UbitMeshing/Mesh.cs deleted file mode 100644 index e3bfe77..0000000 --- a/OpenSim/Region/PhysicsModules/UbitMeshing/Mesh.cs +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.InteropServices; -using OpenSim.Region.PhysicsModules.SharedBase; -using PrimMesher; -using OpenMetaverse; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters.Binary; - -namespace OpenSim.Region.PhysicsModule.UbitMeshing -{ - public class MeshBuildingData - { - public Dictionary m_vertices; - public List m_triangles; - public float m_obbXmin; - public float m_obbXmax; - public float m_obbYmin; - public float m_obbYmax; - public float m_obbZmin; - public float m_obbZmax; - public Vector3 m_centroid; - public int m_centroidDiv; - } - - [Serializable()] - public class Mesh : IMesh - { - float[] vertices; - int[] indexes; - Vector3 m_obb; - Vector3 m_obboffset; - [NonSerialized()] - MeshBuildingData m_bdata; - [NonSerialized()] - GCHandle vhandler; - [NonSerialized()] - GCHandle ihandler; - [NonSerialized()] - IntPtr m_verticesPtr = IntPtr.Zero; - [NonSerialized()] - IntPtr m_indicesPtr = IntPtr.Zero; - [NonSerialized()] - int m_vertexCount = 0; - [NonSerialized()] - int m_indexCount = 0; - - public int RefCount { get; set; } - public AMeshKey Key { get; set; } - - private class vertexcomp : IEqualityComparer - { - public bool Equals(Vertex v1, Vertex v2) - { - if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z) - return true; - else - return false; - } - public int GetHashCode(Vertex v) - { - int a = v.X.GetHashCode(); - int b = v.Y.GetHashCode(); - int c = v.Z.GetHashCode(); - return (a << 16) ^ (b << 8) ^ c; - } - } - - public Mesh() - { - vertexcomp vcomp = new vertexcomp(); - - m_bdata = new MeshBuildingData(); - m_bdata.m_vertices = new Dictionary(vcomp); - m_bdata.m_triangles = new List(); - m_bdata.m_centroid = Vector3.Zero; - m_bdata.m_centroidDiv = 0; - m_bdata.m_obbXmin = float.MaxValue; - m_bdata.m_obbXmax = float.MinValue; - m_bdata.m_obbYmin = float.MaxValue; - m_bdata.m_obbYmax = float.MinValue; - m_bdata.m_obbZmin = float.MaxValue; - m_bdata.m_obbZmax = float.MinValue; - m_obb = new Vector3(0.5f, 0.5f, 0.5f); - m_obboffset = Vector3.Zero; - } - - - public Mesh Scale(Vector3 scale) - { - if (m_verticesPtr == null || m_indicesPtr == null) - return null; - - Mesh result = new Mesh(); - - float x = scale.X; - float y = scale.Y; - float z = scale.Z; - - result.m_obb.X = m_obb.X * x; - result.m_obb.Y = m_obb.Y * y; - result.m_obb.Z = m_obb.Z * z; - result.m_obboffset.X = m_obboffset.X * x; - result.m_obboffset.Y = m_obboffset.Y * y; - result.m_obboffset.Z = m_obboffset.Z * z; - - result.vertices = new float[vertices.Length]; - int j = 0; - for (int i = 0; i < m_vertexCount; i++) - { - result.vertices[j] = vertices[j] * x; - j++; - result.vertices[j] = vertices[j] * y; - j++; - result.vertices[j] = vertices[j] * z; - j++; - } - - result.indexes = new int[indexes.Length]; - indexes.CopyTo(result.indexes,0); - - result.pinMemory(); - - return result; - } - - public Mesh Clone() - { - Mesh result = new Mesh(); - - if (m_bdata != null) - { - result.m_bdata = new MeshBuildingData(); - foreach (Triangle t in m_bdata.m_triangles) - { - result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); - } - result.m_bdata.m_centroid = m_bdata.m_centroid; - result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv; - result.m_bdata.m_obbXmin = m_bdata.m_obbXmin; - result.m_bdata.m_obbXmax = m_bdata.m_obbXmax; - result.m_bdata.m_obbYmin = m_bdata.m_obbYmin; - result.m_bdata.m_obbYmax = m_bdata.m_obbYmax; - result.m_bdata.m_obbZmin = m_bdata.m_obbZmin; - result.m_bdata.m_obbZmax = m_bdata.m_obbZmax; - } - result.m_obb = m_obb; - result.m_obboffset = m_obboffset; - return result; - } - - public void addVertexLStats(Vertex v) - { - float x = v.X; - float y = v.Y; - float z = v.Z; - - m_bdata.m_centroid.X += x; - m_bdata.m_centroid.Y += y; - m_bdata.m_centroid.Z += z; - m_bdata.m_centroidDiv++; - - if (x > m_bdata.m_obbXmax) - m_bdata.m_obbXmax = x; - else if (x < m_bdata.m_obbXmin) - m_bdata.m_obbXmin = x; - - if (y > m_bdata.m_obbYmax) - m_bdata.m_obbYmax = y; - else if (y < m_bdata.m_obbYmin) - m_bdata.m_obbYmin = y; - - if (z > m_bdata.m_obbZmax) - m_bdata.m_obbZmax = z; - else if (z < m_bdata.m_obbZmin) - m_bdata.m_obbZmin = z; - - } - - public void Add(Triangle triangle) - { - if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) - throw new NotSupportedException("Attempt to Add to a pinned Mesh"); - - - triangle.v1.X = (float)Math.Round(triangle.v1.X, 6); - triangle.v1.Y = (float)Math.Round(triangle.v1.Y, 6); - triangle.v1.Z = (float)Math.Round(triangle.v1.Z, 6); - triangle.v2.X = (float)Math.Round(triangle.v2.X, 6); - triangle.v2.Y = (float)Math.Round(triangle.v2.Y, 6); - triangle.v2.Z = (float)Math.Round(triangle.v2.Z, 6); - triangle.v3.X = (float)Math.Round(triangle.v3.X, 6); - triangle.v3.Y = (float)Math.Round(triangle.v3.Y, 6); - triangle.v3.Z = (float)Math.Round(triangle.v3.Z, 6); - - if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z) - || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z) - || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z) - ) - { - return; - } - - if (m_bdata.m_vertices.Count == 0) - { - m_bdata.m_centroidDiv = 0; - m_bdata.m_centroid = Vector3.Zero; - } - - if (!m_bdata.m_vertices.ContainsKey(triangle.v1)) - { - m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count; - addVertexLStats(triangle.v1); - } - if (!m_bdata.m_vertices.ContainsKey(triangle.v2)) - { - m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count; - addVertexLStats(triangle.v2); - } - if (!m_bdata.m_vertices.ContainsKey(triangle.v3)) - { - m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count; - addVertexLStats(triangle.v3); - } - m_bdata.m_triangles.Add(triangle); - } - - public Vector3 GetCentroid() - { - return m_obboffset; - - } - - public Vector3 GetOBB() - { - return m_obb; - float x, y, z; - if (m_bdata.m_centroidDiv > 0) - { - x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f; - y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f; - z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f; - } - else // ?? - { - x = 0.5f; - y = 0.5f; - z = 0.5f; - } - return new Vector3(x, y, z); - } - - public List getVertexList() - { - List result = new List(); - foreach (Vertex v in m_bdata.m_vertices.Keys) - { - result.Add(new Vector3(v.X, v.Y, v.Z)); - } - return result; - } - - public float[] getVertexListAsFloat() - { - if (m_bdata.m_vertices == null) - throw new NotSupportedException(); - float[] result = new float[m_bdata.m_vertices.Count * 3]; - foreach (KeyValuePair kvp in m_bdata.m_vertices) - { - Vertex v = kvp.Key; - int i = kvp.Value; - result[3 * i + 0] = v.X; - result[3 * i + 1] = v.Y; - result[3 * i + 2] = v.Z; - } - return result; - } - - public float[] getVertexListAsFloatLocked() - { - return null; - } - - public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount) - { - // A vertex is 3 floats - vertexStride = 3 * sizeof(float); - - // If there isn't an unmanaged array allocated yet, do it now - if (m_verticesPtr == IntPtr.Zero && m_bdata != null) - { - vertices = getVertexListAsFloat(); - // Each vertex is 3 elements (floats) - m_vertexCount = vertices.Length / 3; - vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned); - m_verticesPtr = vhandler.AddrOfPinnedObject(); - GC.AddMemoryPressure(Buffer.ByteLength(vertices)); - } - _vertices = m_verticesPtr; - vertexCount = m_vertexCount; - } - - public int[] getIndexListAsInt() - { - if (m_bdata.m_triangles == null) - throw new NotSupportedException(); - int[] result = new int[m_bdata.m_triangles.Count * 3]; - for (int i = 0; i < m_bdata.m_triangles.Count; i++) - { - Triangle t = m_bdata.m_triangles[i]; - result[3 * i + 0] = m_bdata.m_vertices[t.v1]; - result[3 * i + 1] = m_bdata.m_vertices[t.v2]; - result[3 * i + 2] = m_bdata.m_vertices[t.v3]; - } - return result; - } - - /// - /// creates a list of index values that defines triangle faces. THIS METHOD FREES ALL NON-PINNED MESH DATA - /// - /// - public int[] getIndexListAsIntLocked() - { - return null; - } - - public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount) - { - // If there isn't an unmanaged array allocated yet, do it now - if (m_indicesPtr == IntPtr.Zero && m_bdata != null) - { - indexes = getIndexListAsInt(); - m_indexCount = indexes.Length; - ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned); - m_indicesPtr = ihandler.AddrOfPinnedObject(); - GC.AddMemoryPressure(Buffer.ByteLength(indexes)); - } - // A triangle is 3 ints (indices) - triStride = 3 * sizeof(int); - indices = m_indicesPtr; - indexCount = m_indexCount; - } - - public void releasePinned() - { - if (m_verticesPtr != IntPtr.Zero) - { - vhandler.Free(); - vertices = null; - m_verticesPtr = IntPtr.Zero; - } - if (m_indicesPtr != IntPtr.Zero) - { - ihandler.Free(); - indexes = null; - m_indicesPtr = IntPtr.Zero; - } - } - - /// - /// frees up the source mesh data to minimize memory - call this method after calling get*Locked() functions - /// - public void releaseSourceMeshData() - { - if (m_bdata != null) - { - m_bdata.m_triangles = null; - m_bdata.m_vertices = null; - } - } - - public void releaseBuildingMeshData() - { - if (m_bdata != null) - { - m_bdata.m_triangles = null; - m_bdata.m_vertices = null; - m_bdata = null; - } - } - - public void Append(IMesh newMesh) - { - if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) - throw new NotSupportedException("Attempt to Append to a pinned Mesh"); - - if (!(newMesh is Mesh)) - return; - - foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles) - Add(t); - } - - // Do a linear transformation of mesh. - public void TransformLinear(float[,] matrix, float[] offset) - { - if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) - throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh"); - - foreach (Vertex v in m_bdata.m_vertices.Keys) - { - if (v == null) - continue; - float x, y, z; - x = v.X*matrix[0, 0] + v.Y*matrix[1, 0] + v.Z*matrix[2, 0]; - y = v.X*matrix[0, 1] + v.Y*matrix[1, 1] + v.Z*matrix[2, 1]; - z = v.X*matrix[0, 2] + v.Y*matrix[1, 2] + v.Z*matrix[2, 2]; - v.X = x + offset[0]; - v.Y = y + offset[1]; - v.Z = z + offset[2]; - } - } - - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - if (m_bdata == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - foreach (Triangle t in m_bdata.m_triangles) - { - String s = t.ToStringRaw(); - sw.WriteLine(s); - } - sw.Close(); - } - - public void TrimExcess() - { - m_bdata.m_triangles.TrimExcess(); - } - - public void pinMemory() - { - m_vertexCount = vertices.Length / 3; - vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned); - m_verticesPtr = vhandler.AddrOfPinnedObject(); - GC.AddMemoryPressure(Buffer.ByteLength(vertices)); - - m_indexCount = indexes.Length; - ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned); - m_indicesPtr = ihandler.AddrOfPinnedObject(); - GC.AddMemoryPressure(Buffer.ByteLength(indexes)); - } - - public void PrepForOde() - { - // If there isn't an unmanaged array allocated yet, do it now - if (m_verticesPtr == IntPtr.Zero) - vertices = getVertexListAsFloat(); - - // If there isn't an unmanaged array allocated yet, do it now - if (m_indicesPtr == IntPtr.Zero) - indexes = getIndexListAsInt(); - - pinMemory(); - - float x, y, z; - - if (m_bdata.m_centroidDiv > 0) - { - m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv); - x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f; - y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f; - z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f; - } - - else - { - m_obboffset = Vector3.Zero; - x = 0.5f; - y = 0.5f; - z = 0.5f; - } - m_obb = new Vector3(x, y, z); - - releaseBuildingMeshData(); - } - public bool ToStream(Stream st) - { - if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero) - return false; - - BinaryWriter bw = new BinaryWriter(st); - bool ok = true; - - try - { - - bw.Write(m_vertexCount); - bw.Write(m_indexCount); - - for (int i = 0; i < 3 * m_vertexCount; i++) - bw.Write(vertices[i]); - for (int i = 0; i < m_indexCount; i++) - bw.Write(indexes[i]); - bw.Write(m_obb.X); - bw.Write(m_obb.Y); - bw.Write(m_obb.Z); - bw.Write(m_obboffset.X); - bw.Write(m_obboffset.Y); - bw.Write(m_obboffset.Z); - } - catch - { - ok = false; - } - - if (bw != null) - { - bw.Flush(); - bw.Close(); - } - - return ok; - } - - public static Mesh FromStream(Stream st, AMeshKey key) - { - Mesh mesh = new Mesh(); - mesh.releaseBuildingMeshData(); - - BinaryReader br = new BinaryReader(st); - - bool ok = true; - try - { - mesh.m_vertexCount = br.ReadInt32(); - mesh.m_indexCount = br.ReadInt32(); - - int n = 3 * mesh.m_vertexCount; - mesh.vertices = new float[n]; - for (int i = 0; i < n; i++) - mesh.vertices[i] = br.ReadSingle(); - - mesh.indexes = new int[mesh.m_indexCount]; - for (int i = 0; i < mesh.m_indexCount; i++) - mesh.indexes[i] = br.ReadInt32(); - - mesh.m_obb.X = br.ReadSingle(); - mesh.m_obb.Y = br.ReadSingle(); - mesh.m_obb.Z = br.ReadSingle(); - - mesh.m_obboffset.X = br.ReadSingle(); - mesh.m_obboffset.Y = br.ReadSingle(); - mesh.m_obboffset.Z = br.ReadSingle(); - } - catch - { - ok = false; - } - - br.Close(); - - if (ok) - { - mesh.pinMemory(); - - mesh.Key = key; - mesh.RefCount = 1; - - return mesh; - } - - mesh.vertices = null; - mesh.indexes = null; - return null; - } - } -} diff --git a/OpenSim/Region/PhysicsModules/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/UbitMeshing/Meshmerizer.cs deleted file mode 100644 index 58a93a1..0000000 --- a/OpenSim/Region/PhysicsModules/UbitMeshing/Meshmerizer.cs +++ /dev/null @@ -1,1458 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -//#define SPAM - -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO.Compression; -using PrimMesher; -using log4net; -using Nini.Config; -using System.Reflection; -using System.IO; -using ComponentAce.Compression.Libs.zlib; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters.Binary; - -using Mono.Addins; - -namespace OpenSim.Region.PhysicsModule.UbitMeshing -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UbitMeshmerizer")] - public class UbitMeshmerizer : IMesher, INonSharedRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // Setting baseDir to a path will enable the dumping of raw files - // raw files can be imported by blender so a visual inspection of the results can be done - - private bool m_Enabled = false; - - public object diskLock = new object(); - - public bool doMeshFileCache = true; - - public string cachePath = "MeshCache"; - public TimeSpan CacheExpire; - public bool doCacheExpire = true; - -// const string baseDir = "rawFiles"; - private const string baseDir = null; //"rawFiles"; - - private bool useMeshiesPhysicsMesh = false; - - private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh - - private Dictionary m_uniqueMeshes = new Dictionary(); - private Dictionary m_uniqueReleasedMeshes = new Dictionary(); - - #region INonSharedRegionModule - public string Name - { - get { return "UbitMeshmerizer"; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void Initialise(IConfigSource config) - { - IConfig start_config = config.Configs["Startup"]; - - string mesher = start_config.GetString("meshing", string.Empty); - if (mesher == Name) - { - float fcache = 48.0f; - // float fcache = 0.02f; - - IConfig mesh_config = config.Configs["Mesh"]; - if (mesh_config != null) - { - useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); - if (useMeshiesPhysicsMesh) - { - doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache); - cachePath = mesh_config.GetString("MeshFileCachePath", cachePath); - fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache); - doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire); - } - else - { - doMeshFileCache = false; - doCacheExpire = false; - } - - m_Enabled = true; - } - - CacheExpire = TimeSpan.FromHours(fcache); - - } - } - - public void Close() - { - } - - public void AddRegion(Scene scene) - { - if (!m_Enabled) - return; - - scene.RegisterModuleInterface(this); - } - - public void RemoveRegion(Scene scene) - { - if (!m_Enabled) - return; - - scene.UnregisterModuleInterface(this); - } - - public void RegionLoaded(Scene scene) - { - if (!m_Enabled) - return; - } - - #endregion - - /// - /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may - /// be useful as a backup proxy when level of detail is not needed or when more complex meshes fail - /// for some reason - /// - /// - /// - /// - /// - /// - /// - /// - private static Mesh CreateSimpleBoxMesh(float minX, float maxX, float minY, float maxY, float minZ, float maxZ) - { - Mesh box = new Mesh(); - List vertices = new List(); - // bottom - - vertices.Add(new Vertex(minX, maxY, minZ)); - vertices.Add(new Vertex(maxX, maxY, minZ)); - vertices.Add(new Vertex(maxX, minY, minZ)); - vertices.Add(new Vertex(minX, minY, minZ)); - - box.Add(new Triangle(vertices[0], vertices[1], vertices[2])); - box.Add(new Triangle(vertices[0], vertices[2], vertices[3])); - - // top - - vertices.Add(new Vertex(maxX, maxY, maxZ)); - vertices.Add(new Vertex(minX, maxY, maxZ)); - vertices.Add(new Vertex(minX, minY, maxZ)); - vertices.Add(new Vertex(maxX, minY, maxZ)); - - box.Add(new Triangle(vertices[4], vertices[5], vertices[6])); - box.Add(new Triangle(vertices[4], vertices[6], vertices[7])); - - // sides - - box.Add(new Triangle(vertices[5], vertices[0], vertices[3])); - box.Add(new Triangle(vertices[5], vertices[3], vertices[6])); - - box.Add(new Triangle(vertices[1], vertices[0], vertices[5])); - box.Add(new Triangle(vertices[1], vertices[5], vertices[4])); - - box.Add(new Triangle(vertices[7], vertices[1], vertices[4])); - box.Add(new Triangle(vertices[7], vertices[2], vertices[1])); - - box.Add(new Triangle(vertices[3], vertices[2], vertices[7])); - box.Add(new Triangle(vertices[3], vertices[7], vertices[6])); - - return box; - } - - /// - /// Creates a simple bounding box mesh for a complex input mesh - /// - /// - /// - private static Mesh CreateBoundingBoxMesh(Mesh meshIn) - { - float minX = float.MaxValue; - float maxX = float.MinValue; - float minY = float.MaxValue; - float maxY = float.MinValue; - float minZ = float.MaxValue; - float maxZ = float.MinValue; - - foreach (Vector3 v in meshIn.getVertexList()) - { - if (v.X < minX) minX = v.X; - if (v.Y < minY) minY = v.Y; - if (v.Z < minZ) minZ = v.Z; - - if (v.X > maxX) maxX = v.X; - if (v.Y > maxY) maxY = v.Y; - if (v.Z > maxZ) maxZ = v.Z; - } - - return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ); - } - - private void ReportPrimError(string message, string primName, PrimMesh primMesh) - { - m_log.Error(message); - m_log.Error("\nPrim Name: " + primName); - m_log.Error("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString()); - } - - /// - /// Add a submesh to an existing list of coords and faces. - /// - /// - /// Size of entire object - /// - /// - private void AddSubMesh(OSDMap subMeshData, List coords, List faces) - { - // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); - - // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level - // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no - // geometry for this submesh. - if (subMeshData.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshData["NoGeometry"])) - return; - - OpenMetaverse.Vector3 posMax; - OpenMetaverse.Vector3 posMin; - if (subMeshData.ContainsKey("PositionDomain")) - { - posMax = ((OSDMap)subMeshData["PositionDomain"])["Max"].AsVector3(); - posMin = ((OSDMap)subMeshData["PositionDomain"])["Min"].AsVector3(); - } - else - { - posMax = new Vector3(0.5f, 0.5f, 0.5f); - posMin = new Vector3(-0.5f, -0.5f, -0.5f); - } - - ushort faceIndexOffset = (ushort)coords.Count; - - byte[] posBytes = subMeshData["Position"].AsBinary(); - for (int i = 0; i < posBytes.Length; i += 6) - { - ushort uX = Utils.BytesToUInt16(posBytes, i); - ushort uY = Utils.BytesToUInt16(posBytes, i + 2); - ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); - - Coord c = new Coord( - Utils.UInt16ToFloat(uX, posMin.X, posMax.X), - Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y), - Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z)); - - coords.Add(c); - } - - byte[] triangleBytes = subMeshData["TriangleList"].AsBinary(); - for (int i = 0; i < triangleBytes.Length; i += 6) - { - ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i) + faceIndexOffset); - ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2) + faceIndexOffset); - ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4) + faceIndexOffset); - Face f = new Face(v1, v2, v3); - faces.Add(f); - } - } - - /// - /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type. - /// - /// - /// - /// - /// - /// - private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex) - { -// m_log.DebugFormat( -// "[MESH]: Creating physics proxy for {0}, shape {1}", -// primName, (OpenMetaverse.SculptType)primShape.SculptType); - - List coords; - List faces; - - if (primShape.SculptEntry) - { - if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) - { - if (!useMeshiesPhysicsMesh) - return null; - - if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex)) - return null; - } - else - { - if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces)) - return null; - } - } - else - { - if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces)) - return null; - } - - primShape.SculptData = Utils.EmptyBytes; - - int numCoords = coords.Count; - int numFaces = faces.Count; - - Mesh mesh = new Mesh(); - // Add the corresponding triangles to the mesh - for (int i = 0; i < numFaces; i++) - { - Face f = faces[i]; - mesh.Add(new Triangle(coords[f.v1].X, coords[f.v1].Y, coords[f.v1].Z, - coords[f.v2].X, coords[f.v2].Y, coords[f.v2].Z, - coords[f.v3].X, coords[f.v3].Y, coords[f.v3].Z)); - } - - coords.Clear(); - faces.Clear(); - - return mesh; - } - - /// - /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim. - /// - /// - /// - /// - /// Coords are added to this list by the method. - /// Faces are added to this list by the method. - /// true if coords and faces were successfully generated, false if not - private bool GenerateCoordsAndFacesFromPrimMeshData( - string primName, PrimitiveBaseShape primShape, out List coords, out List faces, bool convex) - { -// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); - - bool usemesh = false; - - coords = new List(); - faces = new List(); - OSD meshOsd = null; - - if (primShape.SculptData.Length <= 0) - { -// m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName); - return false; - } - - long start = 0; - using (MemoryStream data = new MemoryStream(primShape.SculptData)) - { - try - { - OSD osd = OSDParser.DeserializeLLSDBinary(data); - if (osd is OSDMap) - meshOsd = (OSDMap)osd; - else - { - m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap"); - return false; - } - } - catch (Exception e) - { - m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString()); - } - - start = data.Position; - } - - if (meshOsd is OSDMap) - { - OSDMap physicsParms = null; - OSDMap map = (OSDMap)meshOsd; - - if (!convex) - { - if (map.ContainsKey("physics_shape")) - physicsParms = (OSDMap)map["physics_shape"]; // old asset format - else if (map.ContainsKey("physics_mesh")) - physicsParms = (OSDMap)map["physics_mesh"]; // new asset format - - if (physicsParms != null) - usemesh = true; - } - - if(!usemesh && (map.ContainsKey("physics_convex"))) - physicsParms = (OSDMap)map["physics_convex"]; - - - if (physicsParms == null) - { - m_log.Warn("[MESH]: unknown mesh type"); - return false; - } - - int physOffset = physicsParms["offset"].AsInteger() + (int)start; - int physSize = physicsParms["size"].AsInteger(); - - if (physOffset < 0 || physSize == 0) - return false; // no mesh data in asset - - OSD decodedMeshOsd = new OSD(); - byte[] meshBytes = new byte[physSize]; - System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); - - try - { - using (MemoryStream inMs = new MemoryStream(meshBytes)) - { - using (MemoryStream outMs = new MemoryStream()) - { - using (ZOutputStream zOut = new ZOutputStream(outMs)) - { - byte[] readBuffer = new byte[2048]; - int readLen = 0; - while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) - { - zOut.Write(readBuffer, 0, readLen); - } - zOut.Flush(); - outMs.Seek(0, SeekOrigin.Begin); - - byte[] decompressedBuf = outMs.GetBuffer(); - - decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); - } - } - } - } - catch (Exception e) - { - m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); - return false; - } - - if (usemesh) - { - OSDArray decodedMeshOsdArray = null; - - // physics_shape is an array of OSDMaps, one for each submesh - if (decodedMeshOsd is OSDArray) - { -// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); - - decodedMeshOsdArray = (OSDArray)decodedMeshOsd; - foreach (OSD subMeshOsd in decodedMeshOsdArray) - { - if (subMeshOsd is OSDMap) - AddSubMesh(subMeshOsd as OSDMap, coords, faces); - } - } - } - else - { - OSDMap cmap = (OSDMap)decodedMeshOsd; - if (cmap == null) - return false; - - byte[] data; - - List vs = new List(); - PHullResult hullr = new PHullResult(); - float3 f3; - Coord c; - Face f; - Vector3 range; - Vector3 min; - - const float invMaxU16 = 1.0f / 65535f; - int t1; - int t2; - int t3; - int i; - int nverts; - int nindexs; - - if (cmap.ContainsKey("Max")) - range = cmap["Max"].AsVector3(); - else - range = new Vector3(0.5f, 0.5f, 0.5f); - - if (cmap.ContainsKey("Min")) - min = cmap["Min"].AsVector3(); - else - min = new Vector3(-0.5f, -0.5f, -0.5f); - - range = range - min; - range *= invMaxU16; - - if (!convex && cmap.ContainsKey("HullList") && cmap.ContainsKey("Positions")) - { - List hsizes = new List(); - int totalpoints = 0; - data = cmap["HullList"].AsBinary(); - for (i = 0; i < data.Length; i++) - { - t1 = data[i]; - if (t1 == 0) - t1 = 256; - totalpoints += t1; - hsizes.Add(t1); - } - - data = cmap["Positions"].AsBinary(); - int ptr = 0; - int vertsoffset = 0; - - if (totalpoints == data.Length / 6) // 2 bytes per coord, 3 coords per point - { - foreach (int hullsize in hsizes) - { - for (i = 0; i < hullsize; i++ ) - { - t1 = data[ptr++]; - t1 += data[ptr++] << 8; - t2 = data[ptr++]; - t2 += data[ptr++] << 8; - t3 = data[ptr++]; - t3 += data[ptr++] << 8; - - f3 = new float3((t1 * range.X + min.X), - (t2 * range.Y + min.Y), - (t3 * range.Z + min.Z)); - vs.Add(f3); - } - - if(hullsize <3) - { - vs.Clear(); - continue; - } - - if (hullsize <5) - { - foreach (float3 point in vs) - { - c.X = point.x; - c.Y = point.y; - c.Z = point.z; - coords.Add(c); - } - f = new Face(vertsoffset, vertsoffset + 1, vertsoffset + 2); - faces.Add(f); - - if (hullsize == 4) - { - // not sure about orientation.. - f = new Face(vertsoffset, vertsoffset + 2, vertsoffset + 3); - faces.Add(f); - f = new Face(vertsoffset, vertsoffset + 3, vertsoffset + 1); - faces.Add(f); - f = new Face(vertsoffset + 3, vertsoffset + 2, vertsoffset + 1); - faces.Add(f); - } - vertsoffset += vs.Count; - vs.Clear(); - continue; - } - - if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f)) - { - vs.Clear(); - continue; - } - - nverts = hullr.Vertices.Count; - nindexs = hullr.Indices.Count; - - if (nindexs % 3 != 0) - { - vs.Clear(); - continue; - } - - for (i = 0; i < nverts; i++) - { - c.X = hullr.Vertices[i].x; - c.Y = hullr.Vertices[i].y; - c.Z = hullr.Vertices[i].z; - coords.Add(c); - } - - for (i = 0; i < nindexs; i += 3) - { - t1 = hullr.Indices[i]; - if (t1 > nverts) - break; - t2 = hullr.Indices[i + 1]; - if (t2 > nverts) - break; - t3 = hullr.Indices[i + 2]; - if (t3 > nverts) - break; - f = new Face(vertsoffset + t1, vertsoffset + t2, vertsoffset + t3); - faces.Add(f); - } - vertsoffset += nverts; - vs.Clear(); - } - } - if (coords.Count > 0 && faces.Count > 0) - return true; - } - - vs.Clear(); - - if (cmap.ContainsKey("BoundingVerts")) - { - data = cmap["BoundingVerts"].AsBinary(); - - for (i = 0; i < data.Length; ) - { - t1 = data[i++]; - t1 += data[i++] << 8; - t2 = data[i++]; - t2 += data[i++] << 8; - t3 = data[i++]; - t3 += data[i++] << 8; - - f3 = new float3((t1 * range.X + min.X), - (t2 * range.Y + min.Y), - (t3 * range.Z + min.Z)); - vs.Add(f3); - } - - if (vs.Count < 3) - { - vs.Clear(); - return false; - } - - if (vs.Count < 5) - { - foreach (float3 point in vs) - { - c.X = point.x; - c.Y = point.y; - c.Z = point.z; - coords.Add(c); - } - f = new Face(0, 1, 2); - faces.Add(f); - - if (vs.Count == 4) - { - f = new Face(0, 2, 3); - faces.Add(f); - f = new Face(0, 3, 1); - faces.Add(f); - f = new Face( 3, 2, 1); - faces.Add(f); - } - vs.Clear(); - return true; - } - - if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f)) - return false; - - nverts = hullr.Vertices.Count; - nindexs = hullr.Indices.Count; - - if (nindexs % 3 != 0) - return false; - - for (i = 0; i < nverts; i++) - { - c.X = hullr.Vertices[i].x; - c.Y = hullr.Vertices[i].y; - c.Z = hullr.Vertices[i].z; - coords.Add(c); - } - for (i = 0; i < nindexs; i += 3) - { - t1 = hullr.Indices[i]; - if (t1 > nverts) - break; - t2 = hullr.Indices[i + 1]; - if (t2 > nverts) - break; - t3 = hullr.Indices[i + 2]; - if (t3 > nverts) - break; - f = new Face(t1, t2, t3); - faces.Add(f); - } - - if (coords.Count > 0 && faces.Count > 0) - return true; - } - else - return false; - } - } - - return true; - } - - /// - /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. - /// - /// - /// - /// - /// - /// Coords are added to this list by the method. - /// Faces are added to this list by the method. - /// true if coords and faces were successfully generated, false if not - private bool GenerateCoordsAndFacesFromPrimSculptData( - string primName, PrimitiveBaseShape primShape, float lod, out List coords, out List faces) - { - coords = new List(); - faces = new List(); - PrimMesher.SculptMesh sculptMesh; - Image idata = null; - - if (primShape.SculptData == null || primShape.SculptData.Length == 0) - return false; - - try - { - OpenMetaverse.Imaging.ManagedImage unusedData; - OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata); - - unusedData = null; - - if (idata == null) - { - // In some cases it seems that the decode can return a null bitmap without throwing - // an exception - m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName); - return false; - } - } - catch (DllNotFoundException) - { - m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed. Often times this is because of an old version of GLIBC. You must have version 2.4 or above!"); - return false; - } - catch (IndexOutOfRangeException) - { - m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed"); - return false; - } - catch (Exception ex) - { - m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message); - return false; - } - - PrimMesher.SculptMesh.SculptType sculptType; - // remove mirror and invert bits - OpenMetaverse.SculptType pbsSculptType = ((OpenMetaverse.SculptType)(primShape.SculptType & 0x3f)); - switch (pbsSculptType) - { - case OpenMetaverse.SculptType.Cylinder: - sculptType = PrimMesher.SculptMesh.SculptType.cylinder; - break; - case OpenMetaverse.SculptType.Plane: - sculptType = PrimMesher.SculptMesh.SculptType.plane; - break; - case OpenMetaverse.SculptType.Torus: - sculptType = PrimMesher.SculptMesh.SculptType.torus; - break; - case OpenMetaverse.SculptType.Sphere: - sculptType = PrimMesher.SculptMesh.SculptType.sphere; - break; - default: - sculptType = PrimMesher.SculptMesh.SculptType.plane; - break; - } - - bool mirror = ((primShape.SculptType & 128) != 0); - bool invert = ((primShape.SculptType & 64) != 0); - - sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, mirror, invert); - - idata.Dispose(); - -// sculptMesh.DumpRaw(baseDir, primName, "primMesh"); - - coords = sculptMesh.coords; - faces = sculptMesh.faces; - - return true; - } - - /// - /// Generate the co-ords and faces necessary to construct a mesh from the shape data the accompanies a prim. - /// - /// - /// - /// - /// Coords are added to this list by the method. - /// Faces are added to this list by the method. - /// true if coords and faces were successfully generated, false if not - private bool GenerateCoordsAndFacesFromPrimShapeData( - string primName, PrimitiveBaseShape primShape, float lod, out List coords, out List faces) - { - PrimMesh primMesh; - coords = new List(); - faces = new List(); - - float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f; - float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f; - float pathBegin = (float)primShape.PathBegin * 2.0e-5f; - float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f; - float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f; - float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f; - - float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f; - float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f; - - if (profileBegin < 0.0f) - profileBegin = 0.0f; - - if (profileEnd < 0.02f) - profileEnd = 0.02f; - else if (profileEnd > 1.0f) - profileEnd = 1.0f; - - if (profileBegin >= profileEnd) - profileBegin = profileEnd - 0.02f; - - float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f; - if (profileHollow > 0.95f) - profileHollow = 0.95f; - - int sides = 4; - LevelOfDetail iLOD = (LevelOfDetail)lod; - byte profshape = (byte)(primShape.ProfileCurve & 0x07); - - if (profshape == (byte)ProfileShape.EquilateralTriangle - || profshape == (byte)ProfileShape.IsometricTriangle - || profshape == (byte)ProfileShape.RightTriangle) - sides = 3; - else if (profshape == (byte)ProfileShape.Circle) - { - switch (iLOD) - { - case LevelOfDetail.High: sides = 24; break; - case LevelOfDetail.Medium: sides = 12; break; - case LevelOfDetail.Low: sides = 6; break; - case LevelOfDetail.VeryLow: sides = 3; break; - default: sides = 24; break; - } - } - else if (profshape == (byte)ProfileShape.HalfCircle) - { // half circle, prim is a sphere - switch (iLOD) - { - case LevelOfDetail.High: sides = 24; break; - case LevelOfDetail.Medium: sides = 12; break; - case LevelOfDetail.Low: sides = 6; break; - case LevelOfDetail.VeryLow: sides = 3; break; - default: sides = 24; break; - } - - profileBegin = 0.5f * profileBegin + 0.5f; - profileEnd = 0.5f * profileEnd + 0.5f; - } - - int hollowSides = sides; - if (primShape.HollowShape == HollowShape.Circle) - { - switch (iLOD) - { - case LevelOfDetail.High: hollowSides = 24; break; - case LevelOfDetail.Medium: hollowSides = 12; break; - case LevelOfDetail.Low: hollowSides = 6; break; - case LevelOfDetail.VeryLow: hollowSides = 3; break; - default: hollowSides = 24; break; - } - } - else if (primShape.HollowShape == HollowShape.Square) - hollowSides = 4; - else if (primShape.HollowShape == HollowShape.Triangle) - { - if (profshape == (byte)ProfileShape.HalfCircle) - hollowSides = 6; - else - hollowSides = 3; - } - - primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides); - - if (primMesh.errorMessage != null) - if (primMesh.errorMessage.Length > 0) - m_log.Error("[ERROR] " + primMesh.errorMessage); - - primMesh.topShearX = pathShearX; - primMesh.topShearY = pathShearY; - primMesh.pathCutBegin = pathBegin; - primMesh.pathCutEnd = pathEnd; - - if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible) - { - primMesh.twistBegin = (primShape.PathTwistBegin * 18) / 10; - primMesh.twistEnd = (primShape.PathTwist * 18) / 10; - primMesh.taperX = pathScaleX; - primMesh.taperY = pathScaleY; - -#if SPAM - m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString()); -#endif - try - { - primMesh.ExtrudeLinear(); - } - catch (Exception ex) - { - ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); - return false; - } - } - else - { - primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f; - primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f; - primMesh.radius = 0.01f * primShape.PathRadiusOffset; - primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions; - primMesh.skew = 0.01f * primShape.PathSkew; - primMesh.twistBegin = (primShape.PathTwistBegin * 36) / 10; - primMesh.twistEnd = (primShape.PathTwist * 36) / 10; - primMesh.taperX = primShape.PathTaperX * 0.01f; - primMesh.taperY = primShape.PathTaperY * 0.01f; - -#if SPAM - m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString()); -#endif - try - { - primMesh.ExtrudeCircular(); - } - catch (Exception ex) - { - ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); - return false; - } - } - -// primMesh.DumpRaw(baseDir, primName, "primMesh"); - - coords = primMesh.coords; - faces = primMesh.faces; - - return true; - } - - public AMeshKey GetMeshUniqueKey(PrimitiveBaseShape primShape, Vector3 size, byte lod, bool convex) - { - AMeshKey key = new AMeshKey(); - Byte[] someBytes; - - key.hashB = 5181; - key.hashC = 5181; - ulong hash = 5381; - - if (primShape.SculptEntry) - { - key.uuid = primShape.SculptTexture; - key.hashC = mdjb2(key.hashC, primShape.SculptType); - key.hashC = mdjb2(key.hashC, primShape.PCode); - } - else - { - hash = mdjb2(hash, primShape.PathCurve); - hash = mdjb2(hash, (byte)primShape.HollowShape); - hash = mdjb2(hash, (byte)primShape.ProfileShape); - hash = mdjb2(hash, primShape.PathBegin); - hash = mdjb2(hash, primShape.PathEnd); - hash = mdjb2(hash, primShape.PathScaleX); - hash = mdjb2(hash, primShape.PathScaleY); - hash = mdjb2(hash, primShape.PathShearX); - key.hashA = hash; - hash = key.hashB; - hash = mdjb2(hash, primShape.PathShearY); - hash = mdjb2(hash, (byte)primShape.PathTwist); - hash = mdjb2(hash, (byte)primShape.PathTwistBegin); - hash = mdjb2(hash, (byte)primShape.PathRadiusOffset); - hash = mdjb2(hash, (byte)primShape.PathTaperX); - hash = mdjb2(hash, (byte)primShape.PathTaperY); - hash = mdjb2(hash, primShape.PathRevolutions); - hash = mdjb2(hash, (byte)primShape.PathSkew); - hash = mdjb2(hash, primShape.ProfileBegin); - hash = mdjb2(hash, primShape.ProfileEnd); - hash = mdjb2(hash, primShape.ProfileHollow); - hash = mdjb2(hash, primShape.PCode); - key.hashB = hash; - } - - hash = key.hashC; - - hash = mdjb2(hash, lod); - - if (size == m_MeshUnitSize) - { - hash = hash << 8; - hash |= 8; - } - else - { - someBytes = size.GetBytes(); - for (int i = 0; i < someBytes.Length; i++) - hash = mdjb2(hash, someBytes[i]); - hash = hash << 8; - } - - if (convex) - hash |= 4; - - if (primShape.SculptEntry) - { - hash |= 1; - if (primShape.SculptType == (byte)SculptType.Mesh) - hash |= 2; - } - - key.hashC = hash; - - return key; - } - - private ulong mdjb2(ulong hash, byte c) - { - return ((hash << 5) + hash) + (ulong)c; - } - - private ulong mdjb2(ulong hash, ushort c) - { - hash = ((hash << 5) + hash) + (ulong)((byte)c); - return ((hash << 5) + hash) + (ulong)(c >> 8); - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) - { - return CreateMesh(primName, primShape, size, lod, false,false,false); - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) - { - return CreateMesh(primName, primShape, size, lod, false,false,false); - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde) - { - return CreateMesh(primName, primShape, size, lod, false, false, false); - } - - public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) - { - Mesh mesh = null; - - if (size.X < 0.01f) size.X = 0.01f; - if (size.Y < 0.01f) size.Y = 0.01f; - if (size.Z < 0.01f) size.Z = 0.01f; - - AMeshKey key = GetMeshUniqueKey(primShape, size, (byte)lod, convex); - lock (m_uniqueMeshes) - { - m_uniqueMeshes.TryGetValue(key, out mesh); - - if (mesh != null) - { - mesh.RefCount++; - return mesh; - } - - // try to find a identical mesh on meshs recently released - lock (m_uniqueReleasedMeshes) - { - m_uniqueReleasedMeshes.TryGetValue(key, out mesh); - if (mesh != null) - { - m_uniqueReleasedMeshes.Remove(key); - try - { - m_uniqueMeshes.Add(key, mesh); - } - catch { } - mesh.RefCount = 1; - return mesh; - } - } - } - return null; - } - - private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f); - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde) - { -#if SPAM - m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); -#endif - - Mesh mesh = null; - - if (size.X < 0.01f) size.X = 0.01f; - if (size.Y < 0.01f) size.Y = 0.01f; - if (size.Z < 0.01f) size.Z = 0.01f; - - // try to find a identical mesh on meshs in use - - AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex); - - lock (m_uniqueMeshes) - { - m_uniqueMeshes.TryGetValue(key, out mesh); - - if (mesh != null) - { - mesh.RefCount++; - return mesh; - } - - // try to find a identical mesh on meshs recently released - lock (m_uniqueReleasedMeshes) - { - m_uniqueReleasedMeshes.TryGetValue(key, out mesh); - if (mesh != null) - { - m_uniqueReleasedMeshes.Remove(key); - try - { - m_uniqueMeshes.Add(key, mesh); - } - catch { } - mesh.RefCount = 1; - return mesh; - } - } - } - - Mesh UnitMesh = null; - AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex); - - lock (m_uniqueReleasedMeshes) - { - m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh); - if (UnitMesh != null) - { - UnitMesh.RefCount = 1; - } - } - - if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache) - UnitMesh = GetFromFileCache(unitKey); - - if (UnitMesh == null) - { - UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex); - - if (UnitMesh == null) - return null; - - UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z"); - - if (forOde) - { - // force pinned mem allocation - UnitMesh.PrepForOde(); - } - else - UnitMesh.TrimExcess(); - - UnitMesh.Key = unitKey; - UnitMesh.RefCount = 1; - - if (doMeshFileCache && primShape.SculptEntry) - StoreToFileCache(unitKey, UnitMesh); - - lock (m_uniqueReleasedMeshes) - { - try - { - m_uniqueReleasedMeshes.Add(unitKey, UnitMesh); - } - catch { } - } - } - - mesh = UnitMesh.Scale(size); - mesh.Key = key; - mesh.RefCount = 1; - lock (m_uniqueMeshes) - { - try - { - m_uniqueMeshes.Add(key, mesh); - } - catch { } - } - - return mesh; - } - - public void ReleaseMesh(IMesh imesh) - { - if (imesh == null) - return; - - Mesh mesh = (Mesh)imesh; - - lock (m_uniqueMeshes) - { - int curRefCount = mesh.RefCount; - curRefCount--; - - if (curRefCount > 0) - { - mesh.RefCount = curRefCount; - return; - } - - mesh.RefCount = 0; - m_uniqueMeshes.Remove(mesh.Key); - lock (m_uniqueReleasedMeshes) - { - try - { - m_uniqueReleasedMeshes.Add(mesh.Key, mesh); - } - catch { } - } - } - } - - public void ExpireReleaseMeshs() - { - if (m_uniqueReleasedMeshes.Count == 0) - return; - - List meshstodelete = new List(); - int refcntr; - - lock (m_uniqueReleasedMeshes) - { - foreach (Mesh m in m_uniqueReleasedMeshes.Values) - { - refcntr = m.RefCount; - refcntr--; - if (refcntr > -6) - m.RefCount = refcntr; - else - meshstodelete.Add(m); - } - - foreach (Mesh m in meshstodelete) - { - m_uniqueReleasedMeshes.Remove(m.Key); - m.releaseBuildingMeshData(); - m.releasePinned(); - } - } - } - - public void FileNames(AMeshKey key, out string dir,out string fullFileName) - { - string id = key.ToString(); - string init = id.Substring(0, 1); - dir = System.IO.Path.Combine(cachePath, init); - fullFileName = System.IO.Path.Combine(dir, id); - } - - public string FullFileName(AMeshKey key) - { - string id = key.ToString(); - string init = id.Substring(0,1); - id = System.IO.Path.Combine(init, id); - id = System.IO.Path.Combine(cachePath, id); - return id; - } - - private Mesh GetFromFileCache(AMeshKey key) - { - Mesh mesh = null; - string filename = FullFileName(key); - bool ok = true; - - lock (diskLock) - { - if (File.Exists(filename)) - { - FileStream stream = null; - try - { - stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); - BinaryFormatter bformatter = new BinaryFormatter(); - - mesh = Mesh.FromStream(stream, key); - - } - catch (Exception e) - { - ok = false; - m_log.ErrorFormat( - "[MESH CACHE]: Failed to get file {0}. Exception {1} {2}", - filename, e.Message, e.StackTrace); - } - - if (stream != null) - stream.Close(); - - if (mesh == null || !ok) - File.Delete(filename); - else - File.SetLastAccessTimeUtc(filename, DateTime.UtcNow); - } - } - - return mesh; - } - - private void StoreToFileCache(AMeshKey key, Mesh mesh) - { - Stream stream = null; - bool ok = false; - - // Make sure the target cache directory exists - string dir = String.Empty; - string filename = String.Empty; - - FileNames(key, out dir, out filename); - - lock (diskLock) - { - try - { - if (!Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - - stream = File.Open(filename, FileMode.Create); - ok = mesh.ToStream(stream); - } - catch (IOException e) - { - m_log.ErrorFormat( - "[MESH CACHE]: Failed to write file {0}. Exception {1} {2}.", - filename, e.Message, e.StackTrace); - ok = false; - } - - if (stream != null) - stream.Close(); - - if (File.Exists(filename)) - { - if (ok) - File.SetLastAccessTimeUtc(filename, DateTime.UtcNow); - else - File.Delete(filename); - } - } - } - - public void ExpireFileCache() - { - if (!doCacheExpire) - return; - - string controlfile = System.IO.Path.Combine(cachePath, "cntr"); - - lock (diskLock) - { - try - { - if (File.Exists(controlfile)) - { - int ndeleted = 0; - int totalfiles = 0; - int ndirs = 0; - DateTime OlderTime = File.GetLastAccessTimeUtc(controlfile) - CacheExpire; - File.SetLastAccessTimeUtc(controlfile, DateTime.UtcNow); - - foreach (string dir in Directory.GetDirectories(cachePath)) - { - try - { - foreach (string file in Directory.GetFiles(dir)) - { - try - { - if (File.GetLastAccessTimeUtc(file) < OlderTime) - { - File.Delete(file); - ndeleted++; - } - } - catch { } - totalfiles++; - } - } - catch { } - ndirs++; - } - - if (ndeleted == 0) - m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, no expires", - totalfiles,ndirs); - else - m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, expired {2} files accessed before {3}", - totalfiles,ndirs, ndeleted, OlderTime.ToString()); - } - else - { - m_log.Info("[MESH CACHE]: Expire delayed to next startup"); - FileStream fs = File.Create(controlfile,4096,FileOptions.WriteThrough); - fs.Close(); - } - } - catch { } - } - } - } -} diff --git a/OpenSim/Region/PhysicsModules/UbitMeshing/PrimMesher.cs b/OpenSim/Region/PhysicsModules/UbitMeshing/PrimMesher.cs deleted file mode 100644 index 8eb136b..0000000 --- a/OpenSim/Region/PhysicsModules/UbitMeshing/PrimMesher.cs +++ /dev/null @@ -1,1708 +0,0 @@ -/* - * Copyright (c) Contributors - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.IO; - -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 static Quat operator *(Quat q1, Quat q2) - { - float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y; - float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X; - float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W; - float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z; - return new Quat(x, y, z, w); - } - - public override string ToString() - { - return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">"; - } - } - - public struct Coord - { - public float X; - public float Y; - public float Z; - - public Coord(float x, float y, float z) - { - this.X = x; - this.Y = y; - this.Z = z; - } - - public float Length() - { - return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z); - } - - public Coord Invert() - { - this.X = -this.X; - this.Y = -this.Y; - this.Z = -this.Z; - - return this; - } - - 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, Coord a) - { - return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z); - } - - public static Coord operator *(Coord v, Coord m) - { - return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z); - } - - 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 - { - public int primFace; - - // vertices - public int v1; - public int v2; - public int v3; - - public Face(int v1, int v2, int v3) - { - primFace = 0; - - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - - } - - public Coord SurfaceNormal(List coordList) - { - Coord c1 = coordList[this.v1]; - Coord c2 = coordList[this.v2]; - Coord c3 = coordList[this.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); - - return Coord.Cross(edge1, edge2).Normalize(); - } - } - - internal struct Angle - { - internal float angle; - internal float X; - internal float Y; - - internal Angle(float angle, float x, float y) - { - this.angle = angle; - this.X = x; - this.Y = y; - } - } - - internal class AngleList - { - private float iX, iY; // intersection point - - private static Angle[] angles3 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), - new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private static Angle[] angles4 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.25f, 0.0f, 1.0f), - new Angle(0.5f, -1.0f, 0.0f), - new Angle(0.75f, 0.0f, -1.0f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private static Angle[] angles6 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f), - new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), - new Angle(0.5f, -1.0f, 0.0f), - new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), - new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private static Angle[] angles12 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f), - new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f), - new Angle(0.25f, 0.0f, 1.0f), - new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), - new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f), - new Angle(0.5f, -1.0f, 0.0f), - new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f), - new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), - new Angle(0.75f, 0.0f, -1.0f), - new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f), - new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private static Angle[] angles24 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f), - new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f), - new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f), - new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f), - new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f), - new Angle(0.25f, 0.0f, 1.0f), - new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f), - new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), - new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f), - new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f), - new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f), - new Angle(0.5f, -1.0f, 0.0f), - new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f), - new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f), - new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f), - new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), - new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f), - new Angle(0.75f, 0.0f, -1.0f), - new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f), - new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f), - new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f), - new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f), - new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private Angle interpolatePoints(float newPoint, Angle p1, Angle p2) - { - float m = (newPoint - p1.angle) / (p2.angle - p1.angle); - return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y)); - } - - private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) - { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ - double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); - double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); - - if (denom != 0.0) - { - double ua = uaNumerator / denom; - iX = (float)(x1 + ua * (x2 - x1)); - iY = (float)(y1 + ua * (y2 - y1)); - } - } - - internal List angles; - - internal void makeAngles(int sides, float startAngle, float stopAngle, bool hasCut) - { - angles = new List(); - - const double twoPi = System.Math.PI * 2.0; - const float twoPiInv = (float)(1.0d / twoPi); - - if (sides < 1) - throw new Exception("number of sides not greater than zero"); - if (stopAngle <= startAngle) - throw new Exception("stopAngle not greater than startAngle"); - - if ((sides == 3 || sides == 4 || sides == 6 || sides == 12 || sides == 24)) - { - startAngle *= twoPiInv; - stopAngle *= twoPiInv; - - Angle[] sourceAngles; - switch (sides) - { - case 3: - sourceAngles = angles3; - break; - case 4: - sourceAngles = angles4; - break; - case 6: - sourceAngles = angles6; - break; - case 12: - sourceAngles = angles12; - break; - default: - sourceAngles = angles24; - break; - } - - int startAngleIndex = (int)(startAngle * sides); - int endAngleIndex = sourceAngles.Length - 1; - - if (hasCut) - { - if (stopAngle < 1.0f) - endAngleIndex = (int)(stopAngle * sides) + 1; - if (endAngleIndex == startAngleIndex) - endAngleIndex++; - - for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++) - { - angles.Add(sourceAngles[angleIndex]); - } - - if (startAngle > 0.0f) - angles[0] = interpolatePoints(startAngle, angles[0], angles[1]); - - if (stopAngle < 1.0f) - { - int lastAngleIndex = angles.Count - 1; - angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]); - } - } - else - { - for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex; angleIndex++) - angles.Add(sourceAngles[angleIndex]); - } - } - else - { - double stepSize = twoPi / sides; - - int startStep = (int)(startAngle / stepSize); - double angle = stepSize * startStep; - int step = startStep; - double stopAngleTest = stopAngle; - if (stopAngle < twoPi) - { - stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1); - if (stopAngleTest < stopAngle) - stopAngleTest += stepSize; - if (stopAngleTest > twoPi) - stopAngleTest = twoPi; - } - - while (angle <= stopAngleTest) - { - Angle newAngle; - newAngle.angle = (float)angle; - newAngle.X = (float)System.Math.Cos(angle); - newAngle.Y = (float)System.Math.Sin(angle); - angles.Add(newAngle); - step += 1; - angle = stepSize * step; - } - - if (startAngle > angles[0].angle) - { - Angle newAngle; - intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle)); - newAngle.angle = startAngle; - newAngle.X = iX; - newAngle.Y = iY; - angles[0] = newAngle; - } - - int index = angles.Count - 1; - if (stopAngle < angles[index].angle) - { - Angle newAngle; - intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle)); - newAngle.angle = stopAngle; - newAngle.X = iX; - newAngle.Y = iY; - angles[index] = newAngle; - } - } - } - } - - /// - /// generates a profile for extrusion - /// - public class Profile - { - private const float twoPi = 2.0f * (float)Math.PI; - - public string errorMessage = null; - - public List coords; - public List faces; - - // use these for making individual meshes for each prim face - public List outerCoordIndices = null; - public List hollowCoordIndices = null; - - public int numOuterVerts = 0; - public int numHollowVerts = 0; - - public int outerFaceNumber = -1; - public int hollowFaceNumber = -1; - - public int bottomFaceNumber = 0; - public int numPrimFaces = 0; - - public Profile() - { - this.coords = new List(); - this.faces = new List(); - } - - public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool hasProfileCut, bool createFaces) - { - const float halfSqr2 = 0.7071067811866f; - - this.coords = new List(); - this.faces = new List(); - - List hollowCoords = new List(); - - bool hasHollow = (hollow > 0.0f); - - AngleList angles = new AngleList(); - AngleList hollowAngles = new AngleList(); - - float xScale = 0.5f; - float yScale = 0.5f; - if (sides == 4) // corners of a square are sqrt(2) from center - { - xScale = halfSqr2; - yScale = halfSqr2; - } - - float startAngle = profileStart * twoPi; - float stopAngle = profileEnd * twoPi; - - try { angles.makeAngles(sides, startAngle, stopAngle,hasProfileCut); } - catch (Exception ex) - { - - errorMessage = "makeAngles failed: Exception: " + ex.ToString() - + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); - - return; - } - - this.numOuterVerts = angles.angles.Count; - - Angle angle; - Coord newVert = new Coord(); - - // flag to create as few triangles as possible for 3 or 4 side profile - bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut); - - if (hasHollow) - { - if (sides == hollowSides) - hollowAngles = angles; - else - { - try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle, hasProfileCut); } - catch (Exception ex) - { - errorMessage = "makeAngles failed: Exception: " + ex.ToString() - + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); - - return; - } - - int numHollowAngles = hollowAngles.angles.Count; - for (int i = 0; i < numHollowAngles; i++) - { - angle = hollowAngles.angles[i]; - newVert.X = hollow * xScale * angle.X; - newVert.Y = hollow * yScale * angle.Y; - newVert.Z = 0.0f; - - hollowCoords.Add(newVert); - } - } - this.numHollowVerts = hollowAngles.angles.Count; - } - else if (!simpleFace) - { - Coord center = new Coord(0.0f, 0.0f, 0.0f); - this.coords.Add(center); - } - - int numAngles = angles.angles.Count; - bool hollowsame = (hasHollow && hollowSides == sides); - - for (int i = 0; i < numAngles; i++) - { - angle = angles.angles[i]; - newVert.X = angle.X * xScale; - newVert.Y = angle.Y * yScale; - newVert.Z = 0.0f; - this.coords.Add(newVert); - if (hollowsame) - { - newVert.X *= hollow; - newVert.Y *= hollow; - hollowCoords.Add(newVert); - } - } - - if (hasHollow) - { - hollowCoords.Reverse(); - this.coords.AddRange(hollowCoords); - - if (createFaces) - { - int numTotalVerts = this.numOuterVerts + this.numHollowVerts; - - if (this.numOuterVerts == this.numHollowVerts) - { - Face newFace = new Face(); - - for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++) - { - newFace.v1 = coordIndex; - newFace.v2 = coordIndex + 1; - newFace.v3 = numTotalVerts - coordIndex - 1; - this.faces.Add(newFace); - - newFace.v1 = coordIndex + 1; - newFace.v2 = numTotalVerts - coordIndex - 2; - newFace.v3 = numTotalVerts - coordIndex - 1; - this.faces.Add(newFace); - } - if (!hasProfileCut) - { - newFace.v1 = this.numOuterVerts - 1; - newFace.v2 = 0; - newFace.v3 = this.numOuterVerts; - this.faces.Add(newFace); - - newFace.v1 = 0; - newFace.v2 = numTotalVerts - 1; - newFace.v3 = this.numOuterVerts; - this.faces.Add(newFace); - } - } - else if (this.numOuterVerts < this.numHollowVerts) - { - Face newFace = new Face(); - int j = 0; // j is the index for outer vertices - int i; - int maxJ = this.numOuterVerts - 1; - float curHollowAngle = 0; - for (i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices - { - curHollowAngle = hollowAngles.angles[i].angle; - if (j < maxJ) - { - if (angles.angles[j + 1].angle - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f) - { - newFace.v1 = numTotalVerts - i - 1; - newFace.v2 = j; - newFace.v3 = j + 1; - this.faces.Add(newFace); - j++; - } - } - else - { - if (1.0f - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f) - break; - } - - newFace.v1 = j; - newFace.v2 = numTotalVerts - i - 2; - newFace.v3 = numTotalVerts - i - 1; - - this.faces.Add(newFace); - } - - if (!hasProfileCut) - { - if (i == this.numHollowVerts) - { - newFace.v1 = numTotalVerts - this.numHollowVerts; - newFace.v2 = maxJ; - newFace.v3 = 0; - - this.faces.Add(newFace); - } - else - { - if (1.0f - curHollowAngle < curHollowAngle - angles.angles[maxJ].angle + 0.000001f) - { - newFace.v1 = numTotalVerts - i - 1; - newFace.v2 = maxJ; - newFace.v3 = 0; - - this.faces.Add(newFace); - } - - for (; i < this.numHollowVerts - 1; i++) - { - newFace.v1 = 0; - newFace.v2 = numTotalVerts - i - 2; - newFace.v3 = numTotalVerts - i - 1; - - this.faces.Add(newFace); - } - } - - newFace.v1 = 0; - newFace.v2 = numTotalVerts - this.numHollowVerts; - newFace.v3 = numTotalVerts - 1; - this.faces.Add(newFace); - } - } - else // numHollowVerts < numOuterVerts - { - Face newFace = new Face(); - int j = 0; // j is the index for inner vertices - int maxJ = this.numHollowVerts - 1; - for (int i = 0; i < this.numOuterVerts; i++) - { - if (j < maxJ) - if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f) - { - newFace.v1 = i; - newFace.v2 = numTotalVerts - j - 2; - newFace.v3 = numTotalVerts - j - 1; - - this.faces.Add(newFace); - j += 1; - } - - newFace.v1 = numTotalVerts - j - 1; - newFace.v2 = i; - newFace.v3 = i + 1; - - this.faces.Add(newFace); - } - - if (!hasProfileCut) - { - int i = this.numOuterVerts - 1; - - if (hollowAngles.angles[0].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[maxJ].angle + 0.000001f) - { - newFace.v1 = 0; - newFace.v2 = numTotalVerts - maxJ - 1; - newFace.v3 = numTotalVerts - 1; - - this.faces.Add(newFace); - } - - newFace.v1 = numTotalVerts - maxJ - 1; - newFace.v2 = i; - newFace.v3 = 0; - - this.faces.Add(newFace); - } - } - } - - } - - else if (createFaces) - { - if (simpleFace) - { - if (sides == 3) - this.faces.Add(new Face(0, 1, 2)); - else if (sides == 4) - { - this.faces.Add(new Face(0, 1, 2)); - this.faces.Add(new Face(0, 2, 3)); - } - } - else - { - for (int i = 1; i < numAngles ; i++) - { - Face newFace = new Face(); - newFace.v1 = 0; - newFace.v2 = i; - newFace.v3 = i + 1; - this.faces.Add(newFace); - } - if (!hasProfileCut) - { - Face newFace = new Face(); - newFace.v1 = 0; - newFace.v2 = numAngles; - newFace.v3 = 1; - this.faces.Add(newFace); - } - } - } - - - hollowCoords = null; - } - - - public Profile Copy() - { - return this.Copy(true); - } - - public Profile Copy(bool needFaces) - { - Profile copy = new Profile(); - - copy.coords.AddRange(this.coords); - - if (needFaces) - copy.faces.AddRange(this.faces); - - copy.numOuterVerts = this.numOuterVerts; - copy.numHollowVerts = this.numHollowVerts; - - return copy; - } - - public void AddPos(Coord v) - { - this.AddPos(v.X, v.Y, v.Z); - } - - public void AddPos(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X += x; - vert.Y += y; - vert.Z += z; - this.coords[i] = vert; - } - } - - public void AddRot(Quat q) - { - int i; - int numVerts = this.coords.Count; - - for (i = 0; i < numVerts; i++) - this.coords[i] *= q; - } - - public void Scale(float x, float y) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X *= x; - vert.Y *= y; - this.coords[i] = vert; - } - } - - /// - /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices - /// - public void FlipNormals() - { - int i; - int numFaces = this.faces.Count; - Face tmpFace; - int tmp; - - for (i = 0; i < numFaces; i++) - { - tmpFace = this.faces[i]; - tmp = tmpFace.v3; - tmpFace.v3 = tmpFace.v1; - tmpFace.v1 = tmp; - this.faces[i] = tmpFace; - } - } - - public void AddValue2FaceVertexIndices(int num) - { - int numFaces = this.faces.Count; - Face tmpFace; - for (int i = 0; i < numFaces; i++) - { - tmpFace = this.faces[i]; - tmpFace.v1 += num; - tmpFace.v2 += num; - tmpFace.v3 += num; - - this.faces[i] = tmpFace; - } - } - - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } - - public struct PathNode - { - public Coord position; - public Quat rotation; - public float xScale; - public float yScale; - public float percentOfPath; - } - - public enum PathType { Linear = 0, Circular = 1, Flexible = 2 } - - public class Path - { - public List pathNodes = new List(); - - public float twistBegin = 0.0f; - public float twistEnd = 0.0f; - public float topShearX = 0.0f; - public float topShearY = 0.0f; - public float pathCutBegin = 0.0f; - public float pathCutEnd = 1.0f; - public float dimpleBegin = 0.0f; - public float dimpleEnd = 1.0f; - public float skew = 0.0f; - public float holeSizeX = 1.0f; // called pathScaleX in pbs - public float holeSizeY = 0.25f; - public float taperX = 0.0f; - public float taperY = 0.0f; - public float radius = 0.0f; - public float revolutions = 1.0f; - public int stepsPerRevolution = 24; - - private const float twoPi = 2.0f * (float)Math.PI; - - public void Create(PathType pathType, int steps) - { - if (this.taperX > 0.999f) - this.taperX = 0.999f; - if (this.taperX < -0.999f) - this.taperX = -0.999f; - if (this.taperY > 0.999f) - this.taperY = 0.999f; - if (this.taperY < -0.999f) - this.taperY = -0.999f; - - if (pathType == PathType.Linear || pathType == PathType.Flexible) - { - int step = 0; - - float length = this.pathCutEnd - this.pathCutBegin; - float twistTotal = twistEnd - twistBegin; - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number - - float start = -0.5f; - float stepSize = length / (float)steps; - float percentOfPathMultiplier = stepSize * 0.999999f; - float xOffset = this.topShearX * this.pathCutBegin; - float yOffset = this.topShearY * this.pathCutBegin; - float zOffset = start; - float xOffsetStepIncrement = this.topShearX * length / steps; - float yOffsetStepIncrement = this.topShearY * length / steps; - - float percentOfPath = this.pathCutBegin; - zOffset += percentOfPath; - - // sanity checks - - bool done = false; - - while (!done) - { - PathNode newNode = new PathNode(); - - newNode.xScale = 1.0f; - if (this.taperX == 0.0f) - newNode.xScale = 1.0f; - else if (this.taperX > 0.0f) - newNode.xScale = 1.0f - percentOfPath * this.taperX; - else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX; - - newNode.yScale = 1.0f; - if (this.taperY == 0.0f) - newNode.yScale = 1.0f; - else if (this.taperY > 0.0f) - newNode.yScale = 1.0f - percentOfPath * this.taperY; - else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY; - - float twist = twistBegin + twistTotal * percentOfPath; - - newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); - newNode.position = new Coord(xOffset, yOffset, zOffset); - newNode.percentOfPath = percentOfPath; - - pathNodes.Add(newNode); - - if (step < steps) - { - step += 1; - percentOfPath += percentOfPathMultiplier; - xOffset += xOffsetStepIncrement; - yOffset += yOffsetStepIncrement; - zOffset += stepSize; - if (percentOfPath > this.pathCutEnd) - done = true; - } - else done = true; - } - } // end of linear path code - - else // pathType == Circular - { - float twistTotal = twistEnd - twistBegin; - - // if the profile has a lot of twist, add more layers otherwise the layers may overlap - // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't - // accurately match the viewer - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - { - if (twistTotalAbs > Math.PI * 1.5f) - steps *= 2; - if (twistTotalAbs > Math.PI * 3.0f) - steps *= 2; - } - - float yPathScale = this.holeSizeY * 0.5f; - float pathLength = this.pathCutEnd - this.pathCutBegin; - float totalSkew = this.skew * 2.0f * pathLength; - float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew; - float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY)); - float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f; - - // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end - // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used - // to calculate the sine for generating the path radius appears to approximate it's effects there - // too, but there are some subtle differences in the radius which are noticeable as the prim size - // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on - // the meshes generated with this technique appear nearly identical in shape to the same prims when - // displayed by the viewer. - - float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f; - float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f; - float stepSize = twoPi / this.stepsPerRevolution; - - int step = (int)(startAngle / stepSize); - float angle = startAngle; - - bool done = false; - while (!done) // loop through the length of the path and add the layers - { - PathNode newNode = new PathNode(); - - float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX; - float yProfileScale = this.holeSizeY; - - float percentOfPath = angle / (twoPi * this.revolutions); - float percentOfAngles = (angle - startAngle) / (endAngle - startAngle); - - if (this.taperX > 0.01f) - xProfileScale *= 1.0f - percentOfPath * this.taperX; - else if (this.taperX < -0.01f) - xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX; - - if (this.taperY > 0.01f) - yProfileScale *= 1.0f - percentOfPath * this.taperY; - else if (this.taperY < -0.01f) - yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY; - - newNode.xScale = xProfileScale; - newNode.yScale = yProfileScale; - - float radiusScale = 1.0f; - if (this.radius > 0.001f) - radiusScale = 1.0f - this.radius * percentOfPath; - else if (this.radius < 0.001f) - radiusScale = 1.0f + this.radius * (1.0f - percentOfPath); - - float twist = twistBegin + twistTotal * percentOfPath; - - float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles); - xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor; - - float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale; - - float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale; - - newNode.position = new Coord(xOffset, yOffset, zOffset); - - // 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 - - newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY); - - // next apply twist rotation to the profile layer - if (twistTotal != 0.0f || twistBegin != 0.0f) - newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); - - newNode.percentOfPath = percentOfPath; - - pathNodes.Add(newNode); - - // calculate terms for next iteration - // calculate the angle for the next iteration of the loop - - if (angle >= endAngle - 0.01) - done = true; - else - { - step += 1; - angle = stepSize * step; - if (angle > endAngle) - angle = endAngle; - } - } - } - } - } - - public class PrimMesh - { - public string errorMessage = ""; - private const float twoPi = 2.0f * (float)Math.PI; - - public List coords; -// public List normals; - public List faces; - - private int sides = 4; - private int hollowSides = 4; - private float profileStart = 0.0f; - private float profileEnd = 1.0f; - private float hollow = 0.0f; - public int twistBegin = 0; - public int twistEnd = 0; - public float topShearX = 0.0f; - public float topShearY = 0.0f; - public float pathCutBegin = 0.0f; - public float pathCutEnd = 1.0f; - public float dimpleBegin = 0.0f; - public float dimpleEnd = 1.0f; - public float skew = 0.0f; - public float holeSizeX = 1.0f; // called pathScaleX in pbs - public float holeSizeY = 0.25f; - public float taperX = 0.0f; - public float taperY = 0.0f; - public float radius = 0.0f; - public float revolutions = 1.0f; - public int stepsPerRevolution = 24; - - private bool hasProfileCut = false; - private bool hasHollow = false; - - public int numPrimFaces = 0; - - /// - /// Human readable string representation of the parameters used to create a mesh. - /// - /// - public string ParamsToDisplayString() - { - string s = ""; - s += "sides..................: " + this.sides.ToString(); - s += "\nhollowSides..........: " + this.hollowSides.ToString(); - s += "\nprofileStart.........: " + this.profileStart.ToString(); - s += "\nprofileEnd...........: " + this.profileEnd.ToString(); - s += "\nhollow...............: " + this.hollow.ToString(); - s += "\ntwistBegin...........: " + this.twistBegin.ToString(); - s += "\ntwistEnd.............: " + this.twistEnd.ToString(); - s += "\ntopShearX............: " + this.topShearX.ToString(); - s += "\ntopShearY............: " + this.topShearY.ToString(); - s += "\npathCutBegin.........: " + this.pathCutBegin.ToString(); - s += "\npathCutEnd...........: " + this.pathCutEnd.ToString(); - s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString(); - s += "\ndimpleEnd............: " + this.dimpleEnd.ToString(); - s += "\nskew.................: " + this.skew.ToString(); - s += "\nholeSizeX............: " + this.holeSizeX.ToString(); - s += "\nholeSizeY............: " + this.holeSizeY.ToString(); - s += "\ntaperX...............: " + this.taperX.ToString(); - s += "\ntaperY...............: " + this.taperY.ToString(); - s += "\nradius...............: " + this.radius.ToString(); - s += "\nrevolutions..........: " + this.revolutions.ToString(); - s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString(); - s += "\nhasProfileCut........: " + this.hasProfileCut.ToString(); - s += "\nhasHollow............: " + this.hasHollow.ToString(); - - return s; - } - - public bool HasProfileCut - { - get { return hasProfileCut; } - set { hasProfileCut = value; } - } - - public bool HasHollow - { - get { return hasHollow; } - } - - - /// - /// Constructs a PrimMesh object and creates the profile for extrusion. - /// - /// - /// - /// - /// - /// - /// - public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides) - { - this.coords = new List(); - this.faces = new List(); - - this.sides = sides; - this.profileStart = profileStart; - this.profileEnd = profileEnd; - this.hollow = hollow; - this.hollowSides = hollowSides; - - if (sides < 3) - this.sides = 3; - if (hollowSides < 3) - this.hollowSides = 3; - if (profileStart < 0.0f) - this.profileStart = 0.0f; - if (profileEnd > 1.0f) - this.profileEnd = 1.0f; - if (profileEnd < 0.02f) - this.profileEnd = 0.02f; - if (profileStart >= profileEnd) - this.profileStart = profileEnd - 0.02f; - if (hollow > 0.99f) - this.hollow = 0.99f; - if (hollow < 0.0f) - this.hollow = 0.0f; - } - - /// - /// Extrudes a profile along a path. - /// - public void Extrude(PathType pathType) - { - bool needEndFaces = false; - - this.coords = new List(); - this.faces = new List(); - - int steps = 1; - - float length = this.pathCutEnd - this.pathCutBegin; - - this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f; - - this.hasHollow = (this.hollow > 0.001f); - - float twistBegin = this.twistBegin / 360.0f * twoPi; - float twistEnd = this.twistEnd / 360.0f * twoPi; - float twistTotal = twistEnd - twistBegin; - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number - - float hollow = this.hollow; - - if (pathType == PathType.Circular) - { - needEndFaces = false; - if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f) - needEndFaces = true; - else if (this.taperX != 0.0f || this.taperY != 0.0f) - needEndFaces = true; - else if (this.skew != 0.0f) - needEndFaces = true; - else if (twistTotal != 0.0f) - needEndFaces = true; - else if (this.radius != 0.0f) - needEndFaces = true; - } - else needEndFaces = true; - - // sanity checks - float initialProfileRot = 0.0f; - if (pathType == PathType.Circular) - { - if (this.sides == 3) - { - initialProfileRot = (float)Math.PI; - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow *= 0.707f; - } - else hollow *= 0.5f; - } - else if (this.sides == 4) - { - initialProfileRot = 0.25f * (float)Math.PI; - if (this.hollowSides != 4) - hollow *= 0.707f; - } - else if (this.sides > 4) - { - initialProfileRot = (float)Math.PI; - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow /= 0.7f; - } - } - } - else - { - if (this.sides == 3) - { - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow *= 0.707f; - } - else hollow *= 0.5f; - } - else if (this.sides == 4) - { - initialProfileRot = 1.25f * (float)Math.PI; - if (this.hollowSides != 4) - hollow *= 0.707f; - } - else if (this.sides == 24 && this.hollowSides == 4) - hollow *= 1.414f; - } - - Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, this.hasProfileCut,true); - this.errorMessage = profile.errorMessage; - - this.numPrimFaces = profile.numPrimFaces; - - if (initialProfileRot != 0.0f) - { - profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); - } - - float thisV = 0.0f; - float lastV = 0.0f; - - Path path = new Path(); - path.twistBegin = twistBegin; - path.twistEnd = twistEnd; - path.topShearX = topShearX; - path.topShearY = topShearY; - path.pathCutBegin = pathCutBegin; - path.pathCutEnd = pathCutEnd; - path.dimpleBegin = dimpleBegin; - path.dimpleEnd = dimpleEnd; - path.skew = skew; - path.holeSizeX = holeSizeX; - path.holeSizeY = holeSizeY; - path.taperX = taperX; - path.taperY = taperY; - path.radius = radius; - path.revolutions = revolutions; - path.stepsPerRevolution = stepsPerRevolution; - - path.Create(pathType, steps); - - int lastNode = path.pathNodes.Count -1; - - for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) - { - PathNode node = path.pathNodes[nodeIndex]; - Profile newLayer = profile.Copy(); - - newLayer.Scale(node.xScale, node.yScale); - newLayer.AddRot(node.rotation); - newLayer.AddPos(node.position); - - if (needEndFaces && nodeIndex == 0) - { - newLayer.FlipNormals(); - } // if (nodeIndex == 0) - - // append this layer - - int coordsLen = this.coords.Count; - newLayer.AddValue2FaceVertexIndices(coordsLen); - - this.coords.AddRange(newLayer.coords); - - if (needEndFaces) - { - if (nodeIndex == 0) - this.faces.AddRange(newLayer.faces); - else if (nodeIndex == lastNode) - { - if (node.xScale > 1e-6 && node.yScale > 1e-6) - this.faces.AddRange(newLayer.faces); - } - } - - // fill faces between layers - - int numVerts = newLayer.coords.Count; - Face newFace1 = new Face(); - Face newFace2 = new Face(); - - thisV = 1.0f - node.percentOfPath; - - if (nodeIndex > 0) - { - int startVert = coordsLen; - int endVert = this.coords.Count; - if (!this.hasProfileCut) - { - int i = startVert; - for (int l = 0; l < profile.numOuterVerts - 1; l++) - { - newFace1.v1 = i; - newFace1.v2 = i - numVerts; - newFace1.v3 = i + 1; - this.faces.Add(newFace1); - - newFace2.v1 = i + 1; - newFace2.v2 = i - numVerts; - newFace2.v3 = i + 1 - numVerts; - this.faces.Add(newFace2); - i++; - } - - newFace1.v1 = i; - newFace1.v2 = i - numVerts; - newFace1.v3 = startVert; - this.faces.Add(newFace1); - - newFace2.v1 = startVert; - newFace2.v2 = i - numVerts; - newFace2.v3 = startVert - numVerts; - this.faces.Add(newFace2); - - if (this.hasHollow) - { - startVert = ++i; - for (int l = 0; l < profile.numHollowVerts - 1; l++) - { - newFace1.v1 = i; - newFace1.v2 = i - numVerts; - newFace1.v3 = i + 1; - this.faces.Add(newFace1); - - newFace2.v1 = i + 1; - newFace2.v2 = i - numVerts; - newFace2.v3 = i + 1 - numVerts; - this.faces.Add(newFace2); - i++; - } - - newFace1.v1 = i; - newFace1.v2 = i - numVerts; - newFace1.v3 = startVert; - this.faces.Add(newFace1); - - newFace2.v1 = startVert; - newFace2.v2 = i - numVerts; - newFace2.v3 = startVert - numVerts; - this.faces.Add(newFace2); - } - - - } - else - { - for (int i = startVert; i < endVert; i++) - { - int iNext = i + 1; - if (i == endVert - 1) - iNext = startVert; - - newFace1.v1 = i; - newFace1.v2 = i - numVerts; - newFace1.v3 = iNext; - this.faces.Add(newFace1); - - newFace2.v1 = iNext; - newFace2.v2 = i - numVerts; - newFace2.v3 = iNext - numVerts; - this.faces.Add(newFace2); - - } - } - } - - lastV = thisV; - - } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) - - } - - - /// - /// DEPRICATED - use Extrude(PathType.Linear) instead - /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. - /// - /// - public void ExtrudeLinear() - { - this.Extrude(PathType.Linear); - } - - - /// - /// DEPRICATED - use Extrude(PathType.Circular) instead - /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring. - /// - /// - public void ExtrudeCircular() - { - this.Extrude(PathType.Circular); - } - - - private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3) - { - 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; - } - - private Coord SurfaceNormal(Face face) - { - return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]); - } - - /// - /// Calculate the surface normal for a face in the list of faces - /// - /// - /// - public Coord SurfaceNormal(int faceIndex) - { - int numFaces = this.faces.Count; - if (faceIndex < 0 || faceIndex >= numFaces) - throw new Exception("faceIndex out of range"); - - return SurfaceNormal(this.faces[faceIndex]); - } - - /// - /// Duplicates a PrimMesh object. All object properties are copied by value, including lists. - /// - /// - public PrimMesh Copy() - { - PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides); - copy.twistBegin = this.twistBegin; - copy.twistEnd = this.twistEnd; - copy.topShearX = this.topShearX; - copy.topShearY = this.topShearY; - copy.pathCutBegin = this.pathCutBegin; - copy.pathCutEnd = this.pathCutEnd; - copy.dimpleBegin = this.dimpleBegin; - copy.dimpleEnd = this.dimpleEnd; - copy.skew = this.skew; - copy.holeSizeX = this.holeSizeX; - copy.holeSizeY = this.holeSizeY; - copy.taperX = this.taperX; - copy.taperY = this.taperY; - copy.radius = this.radius; - copy.revolutions = this.revolutions; - copy.stepsPerRevolution = this.stepsPerRevolution; - - copy.numPrimFaces = this.numPrimFaces; - copy.errorMessage = this.errorMessage; - - copy.coords = new List(this.coords); - copy.faces = new List(this.faces); - - return copy; - } - - /// - /// Adds a value to each XYZ vertex coordinate in the mesh - /// - /// - /// - /// - public void AddPos(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X += x; - vert.Y += y; - vert.Z += z; - this.coords[i] = vert; - } - } - - /// - /// Rotates the mesh - /// - /// - public void AddRot(Quat q) - { - int i; - int numVerts = this.coords.Count; - - for (i = 0; i < numVerts; i++) - this.coords[i] *= q; - } - -#if VERTEX_INDEXER - public VertexIndexer GetVertexIndexer() - { - return null; - } -#endif - - /// - /// Scales the mesh - /// - /// - /// - /// - public void Scale(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - //Coord vert; - - Coord m = new Coord(x, y, z); - for (i = 0; i < numVerts; i++) - this.coords[i] *= m; - } - - /// - /// Dumps the mesh to a Blender compatible "Raw" format file - /// - /// - /// - /// - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } -} diff --git a/OpenSim/Region/PhysicsModules/UbitMeshing/Properties/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/UbitMeshing/Properties/AssemblyInfo.cs deleted file mode 100644 index 6881e26..0000000 --- a/OpenSim/Region/PhysicsModules/UbitMeshing/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Mono.Addins; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("OpenSim.Region.PhysicsModule.UbitMeshing")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("http://opensimulator.org")] -[assembly: AssemblyProduct("OpenSim")] -[assembly: AssemblyCopyright("OpenSimulator developers")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("4b7e35c2-a9dd-4b10-b778-eb417f4f6884")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("0.8.2.*")] - -[assembly: Addin("OpenSim.Region.PhysicsModule.UbitMeshing", OpenSim.VersionInfo.VersionNumber)] -[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Region/PhysicsModules/UbitMeshing/SculptMap.cs b/OpenSim/Region/PhysicsModules/UbitMeshing/SculptMap.cs deleted file mode 100644 index 1c75db6..0000000 --- a/OpenSim/Region/PhysicsModules/UbitMeshing/SculptMap.cs +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) Contributors - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -using System.Drawing; -using System.Drawing.Imaging; - -namespace PrimMesher -{ - public class SculptMap - { - public int width; - public int height; - public byte[] redBytes; - public byte[] greenBytes; - public byte[] blueBytes; - - public SculptMap() - { - } - - public SculptMap(Bitmap bm, int lod) - { - int bmW = bm.Width; - int bmH = bm.Height; - - if (bmW == 0 || bmH == 0) - throw new Exception("SculptMap: bitmap has no data"); - - int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image - - bool needsScaling = false; - bool smallMap = false; - - width = bmW; - height = bmH; - - while (width * height > numLodPixels * 4) - { - width >>= 1; - height >>= 1; - needsScaling = true; - } - - try - { - if (needsScaling) - bm = ScaleImage(bm, width, height); - } - - catch (Exception e) - { - throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); - } - - if (width * height > numLodPixels) - { - smallMap = false; - width >>= 1; - height >>= 1; - } - else - smallMap = true; - - int numBytes = (width + 1) * (height + 1); - redBytes = new byte[numBytes]; - greenBytes = new byte[numBytes]; - blueBytes = new byte[numBytes]; - - int byteNdx = 0; - Color c; - - try - { - for (int y = 0; y <= height; y++) - { - for (int x = 0; x < width; x++) - { - if (smallMap) - c = bm.GetPixel(x, y < height ? y : y - 1); - else - c = bm.GetPixel(x * 2, y < height ? y * 2 : y * 2 - 1); - - redBytes[byteNdx] = c.R; - greenBytes[byteNdx] = c.G; - blueBytes[byteNdx] = c.B; - - ++byteNdx; - } - - if (smallMap) - c = bm.GetPixel(width - 1, y < height ? y : y - 1); - else - c = bm.GetPixel(width * 2 - 1, y < height ? y * 2 : y * 2 - 1); - - redBytes[byteNdx] = c.R; - greenBytes[byteNdx] = c.G; - blueBytes[byteNdx] = c.B; - - ++byteNdx; - } - } - catch (Exception e) - { - throw new Exception("Caught exception processing byte arrays in SculptMap(): e: " + e.ToString()); - } - - width++; - height++; - } - - public List> ToRows(bool mirror) - { - int numRows = height; - int numCols = width; - - List> rows = new List>(numRows); - - float pixScale = 1.0f / 255; - - int rowNdx, colNdx; - int smNdx = 0; - - for (rowNdx = 0; rowNdx < numRows; rowNdx++) - { - List row = new List(numCols); - for (colNdx = 0; colNdx < numCols; colNdx++) - { - - if (mirror) - row.Add(new Coord(-((float)redBytes[smNdx] * pixScale - 0.5f), ((float)greenBytes[smNdx] * pixScale - 0.5f), (float)blueBytes[smNdx] * pixScale - 0.5f)); - else - row.Add(new Coord((float)redBytes[smNdx] * pixScale - 0.5f, (float)greenBytes[smNdx] * pixScale - 0.5f, (float)blueBytes[smNdx] * pixScale - 0.5f)); - - ++smNdx; - } - rows.Add(row); - } - return rows; - } - - private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight) - { - - Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb); - - Color c; - - - // will let last step to be eventually diferent, as seems to be in sl - - float xscale = (float)srcImage.Width / (float)destWidth; - float yscale = (float)srcImage.Height / (float)destHeight; - - int lastsx = srcImage.Width - 1; - int lastsy = srcImage.Height - 1; - int lastdx = destWidth - 1; - int lastdy = destHeight - 1; - - float sy = 0.5f; - float sx; - - for (int y = 0; y < lastdy; y++) - { - sx = 0.5f; - for (int x = 0; x < lastdx; x++) - { - try - { - c = srcImage.GetPixel((int)(sx), (int)(sy)); - scaledImage.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B)); - } - catch (IndexOutOfRangeException) - { - } - sx += xscale; - } - try - { - c = srcImage.GetPixel(lastsx, (int)(sy)); - scaledImage.SetPixel(lastdx, y, Color.FromArgb(c.R, c.G, c.B)); - } - catch (IndexOutOfRangeException) - { - } - - sy += yscale; - } - - sx = 0.5f; - for (int x = 0; x < lastdx; x++) - { - try - { - c = srcImage.GetPixel((int)(sx), lastsy); - scaledImage.SetPixel(x, lastdy, Color.FromArgb(c.R, c.G, c.B)); - } - catch (IndexOutOfRangeException) - { - } - - sx += xscale; - } - try - { - c = srcImage.GetPixel(lastsx, lastsy); - scaledImage.SetPixel(lastdx, lastdy, Color.FromArgb(c.R, c.G, c.B)); - } - catch (IndexOutOfRangeException) - { - } - - srcImage.Dispose(); - return scaledImage; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/PhysicsModules/UbitMeshing/SculptMesh.cs b/OpenSim/Region/PhysicsModules/UbitMeshing/SculptMesh.cs deleted file mode 100644 index bc1375b..0000000 --- a/OpenSim/Region/PhysicsModules/UbitMeshing/SculptMesh.cs +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) Contributors - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.IO; - -using System.Drawing; -using System.Drawing.Imaging; - -namespace PrimMesher -{ - - public class SculptMesh - { - public List coords; - public List faces; - - public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; - - - public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool mirror, bool invert) - { - if (mirror) - invert = !invert; - - SculptMap smap = new SculptMap(sculptBitmap, lod); - - List> rows = smap.ToRows(mirror); - - _SculptMesh(rows, sculptType, invert); - } - - private void _SculptMesh(List> rows, SculptType sculptType, bool invert) - { - coords = new List(); - faces = new List(); - - sculptType = (SculptType)(((int)sculptType) & 0x07); - - int width = rows[0].Count; - - int p1, p2, p3, p4; - - int imageX, imageY; - - if (sculptType != SculptType.plane) - { - if (rows.Count % 2 == 0) - { - for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++) - rows[rowNdx].Add(rows[rowNdx][0]); - } - else - { - int lastIndex = rows[0].Count - 1; - - for (int i = 0; i < rows.Count; i++) - rows[i][0] = rows[i][lastIndex]; - } - } - - Coord topPole = rows[0][width / 2]; - Coord bottomPole = rows[rows.Count - 1][width / 2]; - - if (sculptType == SculptType.sphere) - { - if (rows.Count % 2 == 0) - { - int count = rows[0].Count; - List topPoleRow = new List(count); - List bottomPoleRow = new List(count); - - for (int i = 0; i < count; i++) - { - topPoleRow.Add(topPole); - bottomPoleRow.Add(bottomPole); - } - rows.Insert(0, topPoleRow); - rows.Add(bottomPoleRow); - } - else - { - int count = rows[0].Count; - - List topPoleRow = rows[0]; - List bottomPoleRow = rows[rows.Count - 1]; - - for (int i = 0; i < count; i++) - { - topPoleRow[i] = topPole; - bottomPoleRow[i] = bottomPole; - } - } - } - - if (sculptType == SculptType.torus) - rows.Add(rows[0]); - - int coordsDown = rows.Count; - int coordsAcross = rows[0].Count; - - float widthUnit = 1.0f / (coordsAcross - 1); - float heightUnit = 1.0f / (coordsDown - 1); - - for (imageY = 0; imageY < coordsDown; imageY++) - { - int rowOffset = imageY * coordsAcross; - - for (imageX = 0; imageX < coordsAcross; imageX++) - { - /* - * p1-----p2 - * | \ f2 | - * | \ | - * | f1 \| - * p3-----p4 - */ - - p4 = rowOffset + imageX; - p3 = p4 - 1; - - p2 = p4 - coordsAcross; - p1 = p3 - coordsAcross; - - this.coords.Add(rows[imageY][imageX]); - - if (imageY > 0 && imageX > 0) - { - Face f1, f2; - - if (invert) - { - f1 = new Face(p1, p4, p3); - f2 = new Face(p1, p2, p4); - } - else - { - f1 = new Face(p1, p3, p4); - f2 = new Face(p1, p4, p2); - } - - this.faces.Add(f1); - this.faces.Add(f2); - } - } - } - } - - /// - /// Duplicates a SculptMesh object. All object properties are copied by value, including lists. - /// - /// - public SculptMesh Copy() - { - return new SculptMesh(this); - } - - public SculptMesh(SculptMesh sm) - { - coords = new List(sm.coords); - faces = new List(sm.faces); - } - - public void Scale(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - - Coord m = new Coord(x, y, z); - for (i = 0; i < numVerts; i++) - this.coords[i] *= m; - } - - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } -} -- cgit v1.1