mirror of
https://github.com/opensim/opensim.git
synced 2026-08-09 18:55:58 +08:00
Merge of ubitworkvarnew with opensim/master as of 20150905.
This integrates the OpenSim refactoring to make physics, etc into modules. AVN physics hasn't been moved to new location. Does not compile yet. Merge branch 'osmaster' into mbworknew1
This commit is contained in:
436
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs
Normal file
436
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs
Normal file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* 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.PhysicsModules.Meshing;
|
||||
|
||||
public class Vertex : IComparable<Vertex>
|
||||
{
|
||||
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 = 3;
|
||||
|
||||
String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi);
|
||||
|
||||
return s1;
|
||||
}
|
||||
}
|
||||
|
||||
public class Triangle
|
||||
{
|
||||
public Vertex v1;
|
||||
public Vertex v2;
|
||||
public Vertex v3;
|
||||
|
||||
private float radius_square;
|
||||
private float cx;
|
||||
private float cy;
|
||||
|
||||
public Triangle(Vertex _v1, Vertex _v2, Vertex _v3)
|
||||
{
|
||||
v1 = _v1;
|
||||
v2 = _v2;
|
||||
v3 = _v3;
|
||||
|
||||
CalcCircle();
|
||||
}
|
||||
|
||||
public bool isInCircle(float x, float y)
|
||||
{
|
||||
float dx, dy;
|
||||
float dd;
|
||||
|
||||
dx = x - cx;
|
||||
dy = y - cy;
|
||||
|
||||
dd = dx*dx + dy*dy;
|
||||
if (dd < radius_square)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool isDegraded()
|
||||
{
|
||||
// This means, the vertices of this triangle are somewhat strange.
|
||||
// They either line up or at least two of them are identical
|
||||
return (radius_square == 0.0);
|
||||
}
|
||||
|
||||
private void CalcCircle()
|
||||
{
|
||||
// Calculate the center and the radius of a circle given by three points p1, p2, p3
|
||||
// It is assumed, that the triangles vertices are already set correctly
|
||||
double p1x, p2x, p1y, p2y, p3x, p3y;
|
||||
|
||||
// Deviation of this routine:
|
||||
// A circle has the general equation (M-p)^2=r^2, where M and p are vectors
|
||||
// this gives us three equations f(p)=r^2, each for one point p1, p2, p3
|
||||
// putting respectively two equations together gives two equations
|
||||
// f(p1)=f(p2) and f(p1)=f(p3)
|
||||
// bringing all constant terms to one side brings them to the form
|
||||
// M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors)
|
||||
// and c1, c2 are scalars (Naming conventions like the variables below)
|
||||
// Now using the equations that are formed by the components of the vectors
|
||||
// and isolate Mx lets you make one equation that only holds My
|
||||
// The rest is straight forward and eaasy :-)
|
||||
//
|
||||
|
||||
/* helping variables for temporary results */
|
||||
double c1, c2;
|
||||
double v1x, v1y, v2x, v2y;
|
||||
|
||||
double z, n;
|
||||
|
||||
double rx, ry;
|
||||
|
||||
// Readout the three points, the triangle consists of
|
||||
p1x = v1.X;
|
||||
p1y = v1.Y;
|
||||
|
||||
p2x = v2.X;
|
||||
p2y = v2.Y;
|
||||
|
||||
p3x = v3.X;
|
||||
p3y = v3.Y;
|
||||
|
||||
/* calc helping values first */
|
||||
c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2;
|
||||
c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2;
|
||||
|
||||
v1x = p1x - p2x;
|
||||
v1y = p1y - p2y;
|
||||
|
||||
v2x = p1x - p3x;
|
||||
v2y = p1y - p3y;
|
||||
|
||||
z = (c1*v2x - c2*v1x);
|
||||
n = (v1y*v2x - v2y*v1x);
|
||||
|
||||
if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location
|
||||
{
|
||||
radius_square = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
cy = (float) (z/n);
|
||||
|
||||
if (v2x != 0.0)
|
||||
{
|
||||
cx = (float) ((c2 - v2y*cy)/v2x);
|
||||
}
|
||||
else if (v1x != 0.0)
|
||||
{
|
||||
cx = (float) ((c1 - v1y*cy)/v1x);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */
|
||||
}
|
||||
|
||||
rx = (p1x - cx);
|
||||
ry = (p1y - cy);
|
||||
|
||||
radius_square = (float) (rx*rx + ry*ry);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
408
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
Normal file
408
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace OpenSim.Region.PhysicsModules.Meshing
|
||||
{
|
||||
public class Mesh : IMesh
|
||||
{
|
||||
private Dictionary<Vertex, int> m_vertices;
|
||||
private List<Triangle> m_triangles;
|
||||
GCHandle m_pinnedVertexes;
|
||||
GCHandle m_pinnedIndex;
|
||||
IntPtr m_verticesPtr = IntPtr.Zero;
|
||||
int m_vertexCount = 0;
|
||||
IntPtr m_indicesPtr = IntPtr.Zero;
|
||||
int m_indexCount = 0;
|
||||
public float[] m_normals;
|
||||
Vector3 _centroid;
|
||||
int _centroidDiv;
|
||||
|
||||
private class vertexcomp : IEqualityComparer<Vertex>
|
||||
{
|
||||
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_vertices = new Dictionary<Vertex, int>(vcomp);
|
||||
m_triangles = new List<Triangle>();
|
||||
_centroid = Vector3.Zero;
|
||||
_centroidDiv = 0;
|
||||
}
|
||||
|
||||
public Mesh Clone()
|
||||
{
|
||||
Mesh result = new Mesh();
|
||||
|
||||
foreach (Triangle t in m_triangles)
|
||||
{
|
||||
result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
|
||||
}
|
||||
result._centroid = _centroid;
|
||||
result._centroidDiv = _centroidDiv;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Add(Triangle triangle)
|
||||
{
|
||||
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
|
||||
throw new NotSupportedException("Attempt to Add to a pinned Mesh");
|
||||
// If a vertex of the triangle is not yet in the vertices list,
|
||||
// add it and set its index to the current index count
|
||||
// vertex == seems broken
|
||||
// skip colapsed triangles
|
||||
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_vertices.Count == 0)
|
||||
{
|
||||
_centroidDiv = 0;
|
||||
_centroid = Vector3.Zero;
|
||||
}
|
||||
|
||||
if (!m_vertices.ContainsKey(triangle.v1))
|
||||
{
|
||||
m_vertices[triangle.v1] = m_vertices.Count;
|
||||
_centroid.X += triangle.v1.X;
|
||||
_centroid.Y += triangle.v1.Y;
|
||||
_centroid.Z += triangle.v1.Z;
|
||||
_centroidDiv++;
|
||||
}
|
||||
if (!m_vertices.ContainsKey(triangle.v2))
|
||||
{
|
||||
m_vertices[triangle.v2] = m_vertices.Count;
|
||||
_centroid.X += triangle.v2.X;
|
||||
_centroid.Y += triangle.v2.Y;
|
||||
_centroid.Z += triangle.v2.Z;
|
||||
_centroidDiv++;
|
||||
}
|
||||
if (!m_vertices.ContainsKey(triangle.v3))
|
||||
{
|
||||
m_vertices[triangle.v3] = m_vertices.Count;
|
||||
_centroid.X += triangle.v3.X;
|
||||
_centroid.Y += triangle.v3.Y;
|
||||
_centroid.Z += triangle.v3.Z;
|
||||
_centroidDiv++;
|
||||
}
|
||||
m_triangles.Add(triangle);
|
||||
}
|
||||
|
||||
public Vector3 GetCentroid()
|
||||
{
|
||||
if (_centroidDiv > 0)
|
||||
return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv);
|
||||
else
|
||||
return Vector3.Zero;
|
||||
}
|
||||
|
||||
// not functional
|
||||
public Vector3 GetOBB()
|
||||
{
|
||||
return new Vector3(0.5f, 0.5f, 0.5f);
|
||||
}
|
||||
|
||||
public void CalcNormals()
|
||||
{
|
||||
int iTriangles = m_triangles.Count;
|
||||
|
||||
this.m_normals = new float[iTriangles * 3];
|
||||
|
||||
int i = 0;
|
||||
foreach (Triangle t in m_triangles)
|
||||
{
|
||||
float ux, uy, uz;
|
||||
float vx, vy, vz;
|
||||
float wx, wy, wz;
|
||||
|
||||
ux = t.v1.X;
|
||||
uy = t.v1.Y;
|
||||
uz = t.v1.Z;
|
||||
|
||||
vx = t.v2.X;
|
||||
vy = t.v2.Y;
|
||||
vz = t.v2.Z;
|
||||
|
||||
wx = t.v3.X;
|
||||
wy = t.v3.Y;
|
||||
wz = t.v3.Z;
|
||||
|
||||
|
||||
// Vectors for edges
|
||||
float e1x, e1y, e1z;
|
||||
float e2x, e2y, e2z;
|
||||
|
||||
e1x = ux - vx;
|
||||
e1y = uy - vy;
|
||||
e1z = uz - vz;
|
||||
|
||||
e2x = ux - wx;
|
||||
e2y = uy - wy;
|
||||
e2z = uz - wz;
|
||||
|
||||
|
||||
// Cross product for normal
|
||||
float nx, ny, nz;
|
||||
nx = e1y * e2z - e1z * e2y;
|
||||
ny = e1z * e2x - e1x * e2z;
|
||||
nz = e1x * e2y - e1y * e2x;
|
||||
|
||||
// Length
|
||||
float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz);
|
||||
float lReciprocal = 1.0f / l;
|
||||
|
||||
// Normalized "normal"
|
||||
//nx /= l;
|
||||
//ny /= l;
|
||||
//nz /= l;
|
||||
|
||||
m_normals[i] = nx * lReciprocal;
|
||||
m_normals[i + 1] = ny * lReciprocal;
|
||||
m_normals[i + 2] = nz * lReciprocal;
|
||||
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Vector3> getVertexList()
|
||||
{
|
||||
List<Vector3> result = new List<Vector3>();
|
||||
foreach (Vertex v in m_vertices.Keys)
|
||||
{
|
||||
result.Add(new Vector3(v.X, v.Y, v.Z));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public float[] getVertexListAsFloat()
|
||||
{
|
||||
if (m_vertices == null)
|
||||
throw new NotSupportedException();
|
||||
float[] result = new float[m_vertices.Count * 3];
|
||||
foreach (KeyValuePair<Vertex, int> kvp in 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()
|
||||
{
|
||||
if (m_pinnedVertexes.IsAllocated)
|
||||
return (float[])(m_pinnedVertexes.Target);
|
||||
|
||||
float[] result = getVertexListAsFloat();
|
||||
m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
|
||||
// Inform the garbage collector of this unmanaged allocation so it can schedule
|
||||
// the next GC round more intelligently
|
||||
GC.AddMemoryPressure(Buffer.ByteLength(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
float[] vertexList = getVertexListAsFloat();
|
||||
// Each vertex is 3 elements (floats)
|
||||
m_vertexCount = vertexList.Length / 3;
|
||||
int byteCount = m_vertexCount * vertexStride;
|
||||
m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
|
||||
System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
|
||||
}
|
||||
vertices = m_verticesPtr;
|
||||
vertexCount = m_vertexCount;
|
||||
}
|
||||
|
||||
public int[] getIndexListAsInt()
|
||||
{
|
||||
if (m_triangles == null)
|
||||
throw new NotSupportedException();
|
||||
int[] result = new int[m_triangles.Count * 3];
|
||||
for (int i = 0; i < m_triangles.Count; i++)
|
||||
{
|
||||
Triangle t = m_triangles[i];
|
||||
result[3 * i + 0] = m_vertices[t.v1];
|
||||
result[3 * i + 1] = m_vertices[t.v2];
|
||||
result[3 * i + 2] = m_vertices[t.v3];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// creates a list of index values that defines triangle faces. THIS METHOD FREES ALL NON-PINNED MESH DATA
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int[] getIndexListAsIntLocked()
|
||||
{
|
||||
if (m_pinnedIndex.IsAllocated)
|
||||
return (int[])(m_pinnedIndex.Target);
|
||||
|
||||
int[] result = getIndexListAsInt();
|
||||
m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
|
||||
// Inform the garbage collector of this unmanaged allocation so it can schedule
|
||||
// the next GC round more intelligently
|
||||
GC.AddMemoryPressure(Buffer.ByteLength(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int[] indexList = getIndexListAsInt();
|
||||
m_indexCount = indexList.Length;
|
||||
int byteCount = m_indexCount * sizeof(int);
|
||||
m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
|
||||
System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
|
||||
}
|
||||
// A triangle is 3 ints (indices)
|
||||
triStride = 3 * sizeof(int);
|
||||
indices = m_indicesPtr;
|
||||
indexCount = m_indexCount;
|
||||
}
|
||||
|
||||
public void releasePinned()
|
||||
{
|
||||
if (m_pinnedVertexes.IsAllocated)
|
||||
m_pinnedVertexes.Free();
|
||||
if (m_pinnedIndex.IsAllocated)
|
||||
m_pinnedIndex.Free();
|
||||
if (m_verticesPtr != IntPtr.Zero)
|
||||
{
|
||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
|
||||
m_verticesPtr = IntPtr.Zero;
|
||||
}
|
||||
if (m_indicesPtr != IntPtr.Zero)
|
||||
{
|
||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
|
||||
m_indicesPtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// frees up the source mesh data to minimize memory - call this method after calling get*Locked() functions
|
||||
/// </summary>
|
||||
public void releaseSourceMeshData()
|
||||
{
|
||||
m_triangles = null;
|
||||
m_vertices = null;
|
||||
}
|
||||
|
||||
public void Append(IMesh newMesh)
|
||||
{
|
||||
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || 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_triangles)
|
||||
Add(t);
|
||||
}
|
||||
|
||||
// Do a linear transformation of mesh.
|
||||
public void TransformLinear(float[,] matrix, float[] offset)
|
||||
{
|
||||
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
|
||||
throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
|
||||
|
||||
foreach (Vertex v in 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;
|
||||
String fileName = name + "_" + title + ".raw";
|
||||
String completePath = System.IO.Path.Combine(path, fileName);
|
||||
StreamWriter sw = new StreamWriter(completePath);
|
||||
foreach (Triangle t in m_triangles)
|
||||
{
|
||||
String s = t.ToStringRaw();
|
||||
sw.WriteLine(s);
|
||||
}
|
||||
sw.Close();
|
||||
}
|
||||
|
||||
public void TrimExcess()
|
||||
{
|
||||
m_triangles.TrimExcess();
|
||||
}
|
||||
}
|
||||
}
|
||||
1027
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs
Normal file
1027
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs
Normal file
File diff suppressed because it is too large
Load Diff
2324
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/PrimMesher.cs
Normal file
2324
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/PrimMesher.cs
Normal file
File diff suppressed because it is too large
Load Diff
197
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs
Normal file
197
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// to build without references to System.Drawing, comment this out
|
||||
#define SYSTEM_DRAWING
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
#if SYSTEM_DRAWING
|
||||
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 smallMap = bmW * bmH <= numLodPixels;
|
||||
bool needsScaling = 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)
|
||||
{
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
}
|
||||
|
||||
int numBytes = (width + 1) * (height + 1);
|
||||
redBytes = new byte[numBytes];
|
||||
greenBytes = new byte[numBytes];
|
||||
blueBytes = new byte[numBytes];
|
||||
|
||||
int byteNdx = 0;
|
||||
|
||||
try
|
||||
{
|
||||
for (int y = 0; y <= height; y++)
|
||||
{
|
||||
for (int x = 0; x <= width; x++)
|
||||
{
|
||||
Color c;
|
||||
|
||||
if (smallMap)
|
||||
c = bm.GetPixel(x < width ? x : x - 1,
|
||||
y < height ? y : y - 1);
|
||||
else
|
||||
c = bm.GetPixel(x < width ? x * 2 : x * 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<List<Coord>> ToRows(bool mirror)
|
||||
{
|
||||
int numRows = height;
|
||||
int numCols = width;
|
||||
|
||||
List<List<Coord>> rows = new List<List<Coord>>(numRows);
|
||||
|
||||
float pixScale = 1.0f / 255;
|
||||
|
||||
int rowNdx, colNdx;
|
||||
int smNdx = 0;
|
||||
|
||||
|
||||
for (rowNdx = 0; rowNdx < numRows; rowNdx++)
|
||||
{
|
||||
List<Coord> row = new List<Coord>(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;
|
||||
float xscale = srcImage.Width / destWidth;
|
||||
float yscale = srcImage.Height / destHeight;
|
||||
|
||||
float sy = 0.5f;
|
||||
for (int y = 0; y < destHeight; y++)
|
||||
{
|
||||
float sx = 0.5f;
|
||||
for (int x = 0; x < destWidth; 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;
|
||||
}
|
||||
sy += yscale;
|
||||
}
|
||||
srcImage.Dispose();
|
||||
return scaledImage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
646
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMesh.cs
Normal file
646
OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMesh.cs
Normal file
@@ -0,0 +1,646 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// to build without references to System.Drawing, comment this out
|
||||
#define SYSTEM_DRAWING
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
#if SYSTEM_DRAWING
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
#endif
|
||||
|
||||
namespace PrimMesher
|
||||
{
|
||||
|
||||
public class SculptMesh
|
||||
{
|
||||
public List<Coord> coords;
|
||||
public List<Face> faces;
|
||||
|
||||
public List<ViewerFace> viewerFaces;
|
||||
public List<Coord> normals;
|
||||
public List<UVCoord> uvs;
|
||||
|
||||
public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
|
||||
|
||||
#if SYSTEM_DRAWING
|
||||
|
||||
public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode)
|
||||
{
|
||||
Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
|
||||
SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode);
|
||||
bitmap.Dispose();
|
||||
return sculptMesh;
|
||||
}
|
||||
|
||||
|
||||
public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert)
|
||||
{
|
||||
Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
|
||||
_SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0);
|
||||
bitmap.Dispose();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications
|
||||
/// Construct a sculpt mesh from a 2D array of floats
|
||||
/// </summary>
|
||||
/// <param name="zMap"></param>
|
||||
/// <param name="xBegin"></param>
|
||||
/// <param name="xEnd"></param>
|
||||
/// <param name="yBegin"></param>
|
||||
/// <param name="yEnd"></param>
|
||||
/// <param name="viewerMode"></param>
|
||||
public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode)
|
||||
{
|
||||
float xStep, yStep;
|
||||
float uStep, vStep;
|
||||
|
||||
int numYElements = zMap.GetLength(0);
|
||||
int numXElements = zMap.GetLength(1);
|
||||
|
||||
try
|
||||
{
|
||||
xStep = (xEnd - xBegin) / (float)(numXElements - 1);
|
||||
yStep = (yEnd - yBegin) / (float)(numYElements - 1);
|
||||
|
||||
uStep = 1.0f / (numXElements - 1);
|
||||
vStep = 1.0f / (numYElements - 1);
|
||||
}
|
||||
catch (DivideByZeroException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
coords = new List<Coord>();
|
||||
faces = new List<Face>();
|
||||
normals = new List<Coord>();
|
||||
uvs = new List<UVCoord>();
|
||||
|
||||
viewerFaces = new List<ViewerFace>();
|
||||
|
||||
int p1, p2, p3, p4;
|
||||
|
||||
int x, y;
|
||||
int xStart = 0, yStart = 0;
|
||||
|
||||
for (y = yStart; y < numYElements; y++)
|
||||
{
|
||||
int rowOffset = y * numXElements;
|
||||
|
||||
for (x = xStart; x < numXElements; x++)
|
||||
{
|
||||
/*
|
||||
* p1-----p2
|
||||
* | \ f2 |
|
||||
* | \ |
|
||||
* | f1 \|
|
||||
* p3-----p4
|
||||
*/
|
||||
|
||||
p4 = rowOffset + x;
|
||||
p3 = p4 - 1;
|
||||
|
||||
p2 = p4 - numXElements;
|
||||
p1 = p3 - numXElements;
|
||||
|
||||
Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]);
|
||||
this.coords.Add(c);
|
||||
if (viewerMode)
|
||||
{
|
||||
this.normals.Add(new Coord());
|
||||
this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y));
|
||||
}
|
||||
|
||||
if (y > 0 && x > 0)
|
||||
{
|
||||
Face f1, f2;
|
||||
|
||||
if (viewerMode)
|
||||
{
|
||||
f1 = new Face(p1, p4, p3, p1, p4, p3);
|
||||
f1.uv1 = p1;
|
||||
f1.uv2 = p4;
|
||||
f1.uv3 = p3;
|
||||
|
||||
f2 = new Face(p1, p2, p4, p1, p2, p4);
|
||||
f2.uv1 = p1;
|
||||
f2.uv2 = p2;
|
||||
f2.uv3 = p4;
|
||||
}
|
||||
else
|
||||
{
|
||||
f1 = new Face(p1, p4, p3);
|
||||
f2 = new Face(p1, p2, p4);
|
||||
}
|
||||
|
||||
this.faces.Add(f1);
|
||||
this.faces.Add(f2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (viewerMode)
|
||||
calcVertexNormals(SculptType.plane, numXElements, numYElements);
|
||||
}
|
||||
|
||||
#if SYSTEM_DRAWING
|
||||
public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode)
|
||||
{
|
||||
_SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false);
|
||||
}
|
||||
|
||||
public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
|
||||
{
|
||||
_SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert);
|
||||
}
|
||||
#endif
|
||||
|
||||
public SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
|
||||
{
|
||||
_SculptMesh(rows, sculptType, viewerMode, mirror, invert);
|
||||
}
|
||||
|
||||
#if SYSTEM_DRAWING
|
||||
/// <summary>
|
||||
/// converts a bitmap to a list of lists of coords, while scaling the image.
|
||||
/// the scaling is done in floating point so as to allow for reduced vertex position
|
||||
/// quantization as the position will be averaged between pixel values. this routine will
|
||||
/// likely fail if the bitmap width and height are not powers of 2.
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="scale"></param>
|
||||
/// <param name="mirror"></param>
|
||||
/// <returns></returns>
|
||||
private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror)
|
||||
{
|
||||
int numRows = bitmap.Height / scale;
|
||||
int numCols = bitmap.Width / scale;
|
||||
List<List<Coord>> rows = new List<List<Coord>>(numRows);
|
||||
|
||||
float pixScale = 1.0f / (scale * scale);
|
||||
pixScale /= 255;
|
||||
|
||||
int imageX, imageY = 0;
|
||||
|
||||
int rowNdx, colNdx;
|
||||
|
||||
for (rowNdx = 0; rowNdx < numRows; rowNdx++)
|
||||
{
|
||||
List<Coord> row = new List<Coord>(numCols);
|
||||
for (colNdx = 0; colNdx < numCols; colNdx++)
|
||||
{
|
||||
imageX = colNdx * scale;
|
||||
int imageYStart = rowNdx * scale;
|
||||
int imageYEnd = imageYStart + scale;
|
||||
int imageXEnd = imageX + scale;
|
||||
float rSum = 0.0f;
|
||||
float gSum = 0.0f;
|
||||
float bSum = 0.0f;
|
||||
for (; imageX < imageXEnd; imageX++)
|
||||
{
|
||||
for (imageY = imageYStart; imageY < imageYEnd; imageY++)
|
||||
{
|
||||
Color c = bitmap.GetPixel(imageX, imageY);
|
||||
if (c.A != 255)
|
||||
{
|
||||
bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
|
||||
c = bitmap.GetPixel(imageX, imageY);
|
||||
}
|
||||
rSum += c.R;
|
||||
gSum += c.G;
|
||||
bSum += c.B;
|
||||
}
|
||||
}
|
||||
if (mirror)
|
||||
row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
|
||||
else
|
||||
row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
|
||||
|
||||
}
|
||||
rows.Add(row);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror)
|
||||
{
|
||||
int numRows = bitmap.Height / scale;
|
||||
int numCols = bitmap.Width / scale;
|
||||
List<List<Coord>> rows = new List<List<Coord>>(numRows);
|
||||
|
||||
float pixScale = 1.0f / 256.0f;
|
||||
|
||||
int imageX, imageY = 0;
|
||||
|
||||
int rowNdx, colNdx;
|
||||
|
||||
for (rowNdx = 0; rowNdx <= numRows; rowNdx++)
|
||||
{
|
||||
List<Coord> row = new List<Coord>(numCols);
|
||||
imageY = rowNdx * scale;
|
||||
if (rowNdx == numRows) imageY--;
|
||||
for (colNdx = 0; colNdx <= numCols; colNdx++)
|
||||
{
|
||||
imageX = colNdx * scale;
|
||||
if (colNdx == numCols) imageX--;
|
||||
|
||||
Color c = bitmap.GetPixel(imageX, imageY);
|
||||
if (c.A != 255)
|
||||
{
|
||||
bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
|
||||
c = bitmap.GetPixel(imageX, imageY);
|
||||
}
|
||||
|
||||
if (mirror)
|
||||
row.Add(new Coord(-(c.R * pixScale - 0.5f), c.G * pixScale - 0.5f, c.B * pixScale - 0.5f));
|
||||
else
|
||||
row.Add(new Coord(c.R * pixScale - 0.5f, c.G * pixScale - 0.5f, c.B * pixScale - 0.5f));
|
||||
|
||||
}
|
||||
rows.Add(row);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
|
||||
{
|
||||
_SculptMesh(new SculptMap(sculptBitmap, lod).ToRows(mirror), sculptType, viewerMode, mirror, invert);
|
||||
}
|
||||
#endif
|
||||
|
||||
void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
|
||||
{
|
||||
coords = new List<Coord>();
|
||||
faces = new List<Face>();
|
||||
normals = new List<Coord>();
|
||||
uvs = new List<UVCoord>();
|
||||
|
||||
sculptType = (SculptType)(((int)sculptType) & 0x07);
|
||||
|
||||
if (mirror)
|
||||
invert = !invert;
|
||||
|
||||
viewerFaces = new List<ViewerFace>();
|
||||
|
||||
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<Coord> topPoleRow = new List<Coord>(count);
|
||||
List<Coord> bottomPoleRow = new List<Coord>(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<Coord> topPoleRow = rows[0];
|
||||
List<Coord> 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;
|
||||
// int lastColumn = coordsAcross - 1;
|
||||
|
||||
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 (viewerMode)
|
||||
{
|
||||
this.normals.Add(new Coord());
|
||||
this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY));
|
||||
}
|
||||
|
||||
if (imageY > 0 && imageX > 0)
|
||||
{
|
||||
Face f1, f2;
|
||||
|
||||
if (viewerMode)
|
||||
{
|
||||
if (invert)
|
||||
{
|
||||
f1 = new Face(p1, p4, p3, p1, p4, p3);
|
||||
f1.uv1 = p1;
|
||||
f1.uv2 = p4;
|
||||
f1.uv3 = p3;
|
||||
|
||||
f2 = new Face(p1, p2, p4, p1, p2, p4);
|
||||
f2.uv1 = p1;
|
||||
f2.uv2 = p2;
|
||||
f2.uv3 = p4;
|
||||
}
|
||||
else
|
||||
{
|
||||
f1 = new Face(p1, p3, p4, p1, p3, p4);
|
||||
f1.uv1 = p1;
|
||||
f1.uv2 = p3;
|
||||
f1.uv3 = p4;
|
||||
|
||||
f2 = new Face(p1, p4, p2, p1, p4, p2);
|
||||
f2.uv1 = p1;
|
||||
f2.uv2 = p4;
|
||||
f2.uv3 = p2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (viewerMode)
|
||||
calcVertexNormals(sculptType, coordsAcross, coordsDown);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Duplicates a SculptMesh object. All object properties are copied by value, including lists.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SculptMesh Copy()
|
||||
{
|
||||
return new SculptMesh(this);
|
||||
}
|
||||
|
||||
public SculptMesh(SculptMesh sm)
|
||||
{
|
||||
coords = new List<Coord>(sm.coords);
|
||||
faces = new List<Face>(sm.faces);
|
||||
viewerFaces = new List<ViewerFace>(sm.viewerFaces);
|
||||
normals = new List<Coord>(sm.normals);
|
||||
uvs = new List<UVCoord>(sm.uvs);
|
||||
}
|
||||
|
||||
private void calcVertexNormals(SculptType sculptType, int xSize, int ySize)
|
||||
{ // compute vertex normals by summing all the surface normals of all the triangles sharing
|
||||
// each vertex and then normalizing
|
||||
int numFaces = this.faces.Count;
|
||||
for (int i = 0; i < numFaces; i++)
|
||||
{
|
||||
Face face = this.faces[i];
|
||||
Coord surfaceNormal = face.SurfaceNormal(this.coords);
|
||||
this.normals[face.n1] += surfaceNormal;
|
||||
this.normals[face.n2] += surfaceNormal;
|
||||
this.normals[face.n3] += surfaceNormal;
|
||||
}
|
||||
|
||||
int numNormals = this.normals.Count;
|
||||
for (int i = 0; i < numNormals; i++)
|
||||
this.normals[i] = this.normals[i].Normalize();
|
||||
|
||||
if (sculptType != SculptType.plane)
|
||||
{ // blend the vertex normals at the cylinder seam
|
||||
for (int y = 0; y < ySize; y++)
|
||||
{
|
||||
int rowOffset = y * xSize;
|
||||
|
||||
this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Face face in this.faces)
|
||||
{
|
||||
ViewerFace vf = new ViewerFace(0);
|
||||
vf.v1 = this.coords[face.v1];
|
||||
vf.v2 = this.coords[face.v2];
|
||||
vf.v3 = this.coords[face.v3];
|
||||
|
||||
vf.coordIndex1 = face.v1;
|
||||
vf.coordIndex2 = face.v2;
|
||||
vf.coordIndex3 = face.v3;
|
||||
|
||||
vf.n1 = this.normals[face.n1];
|
||||
vf.n2 = this.normals[face.n2];
|
||||
vf.n3 = this.normals[face.n3];
|
||||
|
||||
vf.uv1 = this.uvs[face.uv1];
|
||||
vf.uv2 = this.uvs[face.uv2];
|
||||
vf.uv3 = this.uvs[face.uv3];
|
||||
|
||||
this.viewerFaces.Add(vf);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a value to each XYZ vertex coordinate in the mesh
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="z"></param>
|
||||
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;
|
||||
}
|
||||
|
||||
if (this.viewerFaces != null)
|
||||
{
|
||||
int numViewerFaces = this.viewerFaces.Count;
|
||||
|
||||
for (i = 0; i < numViewerFaces; i++)
|
||||
{
|
||||
ViewerFace v = this.viewerFaces[i];
|
||||
v.AddPos(x, y, z);
|
||||
this.viewerFaces[i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the mesh
|
||||
/// </summary>
|
||||
/// <param name="q"></param>
|
||||
public void AddRot(Quat q)
|
||||
{
|
||||
int i;
|
||||
int numVerts = this.coords.Count;
|
||||
|
||||
for (i = 0; i < numVerts; i++)
|
||||
this.coords[i] *= q;
|
||||
|
||||
int numNormals = this.normals.Count;
|
||||
for (i = 0; i < numNormals; i++)
|
||||
this.normals[i] *= q;
|
||||
|
||||
if (this.viewerFaces != null)
|
||||
{
|
||||
int numViewerFaces = this.viewerFaces.Count;
|
||||
|
||||
for (i = 0; i < numViewerFaces; i++)
|
||||
{
|
||||
ViewerFace v = this.viewerFaces[i];
|
||||
v.v1 *= q;
|
||||
v.v2 *= q;
|
||||
v.v3 *= q;
|
||||
|
||||
v.n1 *= q;
|
||||
v.n2 *= q;
|
||||
v.n3 *= q;
|
||||
|
||||
this.viewerFaces[i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (this.viewerFaces != null)
|
||||
{
|
||||
int numViewerFaces = this.viewerFaces.Count;
|
||||
for (i = 0; i < numViewerFaces; i++)
|
||||
{
|
||||
ViewerFace v = this.viewerFaces[i];
|
||||
v.v1 *= m;
|
||||
v.v2 *= m;
|
||||
v.v3 *= m;
|
||||
this.viewerFaces[i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
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.PhysicsModules.Meshing")]
|
||||
[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.PhysicsModules.Meshing", OpenSim.VersionInfo.VersionNumber)]
|
||||
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
||||
145
OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs
Normal file
145
OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.Reflection;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.PhysicsModules.SharedBase;
|
||||
using OpenMetaverse;
|
||||
using Nini.Config;
|
||||
using Mono.Addins;
|
||||
using log4net;
|
||||
|
||||
/*
|
||||
* This is the zero mesher.
|
||||
* Whatever you want him to mesh, he can't, telling you that by responding with a null pointer.
|
||||
* Effectivly this is for switching off meshing and for testing as each physics machine should deal
|
||||
* with the null pointer situation.
|
||||
* But it's also a convenience thing, as physics machines can rely on having a mesher in any situation, even
|
||||
* if it's a dump one like this.
|
||||
* Note, that this mesher is *not* living in a module but in the manager itself, so
|
||||
* it's always availabe and thus the default in case of configuration errors
|
||||
*/
|
||||
|
||||
namespace OpenSim.Region.PhysicsModules.Meshing
|
||||
{
|
||||
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ZeroMesher")]
|
||||
public class ZeroMesher : IMesher, INonSharedRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private bool m_Enabled = false;
|
||||
|
||||
#region INonSharedRegionModule
|
||||
public string Name
|
||||
{
|
||||
get { return "ZeroMesher"; }
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void Initialise(IConfigSource source)
|
||||
{
|
||||
// TODO: Move this out of Startup
|
||||
IConfig config = source.Configs["Startup"];
|
||||
if (config != null)
|
||||
{
|
||||
// This is the default Mesher
|
||||
string mesher = config.GetString("meshing", Name);
|
||||
if (mesher == Name)
|
||||
m_Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
scene.RegisterModuleInterface<IMesher>(this);
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
scene.UnregisterModuleInterface<IMesher>(this);
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IMesher
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, 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);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex,bool forOde)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, false);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
|
||||
{
|
||||
// Remove the reference to the encoded JPEG2000 data so it can be GCed
|
||||
primShape.SculptData = OpenMetaverse.Utils.EmptyBytes;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ReleaseMesh(IMesh mesh) { }
|
||||
public void ExpireReleaseMeshs() { }
|
||||
public void ExpireFileCache() { }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user