set svn:eol-style

afrisby
Jeff Ames 2007-11-11 09:19:21 +00:00
parent 33ac0653a3
commit db174dfa20
15 changed files with 3037 additions and 3037 deletions

View File

@ -1,161 +1,161 @@
/*
Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru
Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
This file contains a class TriangleIndexVertexArray. I tried using the class with the same name
from the BulletX implementation and found it unusable for the purpose of using triangle meshes
within BulletX as the implementation was painfully incomplete.
The attempt to derive from the original class failed as viable members were hidden.
Fiddling around with BulletX itself was not my intention.
So I copied the class to the BulletX-plugin and modified it.
If you want to fiddle around with it it's up to you to move all this to BulletX.
If someone someday implements the missing functionality in BulletX, feel free to remove this class.
It's just an ugly hack.
*/
using System;
using System.Collections.Generic;
using System.Text;
using MonoXnaCompactMaths;
namespace OpenSim.Region.Physics.BulletXPlugin
{
/// <summary>
/// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements
/// instead of the number of indices, we pass the number of triangles
/// </summary>
public struct IndexedMesh
{
private int _numTriangles;
private int[] _triangleIndexBase;
private int _triangleIndexStride;
private int _numVertices;
private Vector3[] _vertexBase;
private int _vertexStride;
public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride)
{
_numTriangles = numTriangleIndices;
_triangleIndexBase = triangleIndexBase;
_triangleIndexStride = triangleIndexStride;
_vertexBase = vertexBase;
_numVertices = numVertices;
_vertexStride = vertexStride;
}
public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase)
{
_numTriangles = triangleIndexBase.Length;
_triangleIndexBase = triangleIndexBase;
_triangleIndexStride = 32;
_vertexBase = vertexBase;
_numVertices = vertexBase.Length;
_vertexStride = 24;
}
public int TriangleCount { get { return _numTriangles; } set { _numTriangles = value; } }
public int[] TriangleIndexBase { get { return _triangleIndexBase; } set { _triangleIndexBase = value; } }
public int TriangleIndexStride { get { return _triangleIndexStride; } set { _triangleIndexStride = value; } }
public int VertexCount { get { return _numVertices; } set { _numVertices = value; } }
public Vector3[] VertexBase { get { return _vertexBase; } set { _vertexBase = value; } }
public int VertexStride { get { return _vertexStride; } set { _vertexStride = value; } }
}
/// <summary>
/// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays.
/// Additional meshes can be added using addIndexedMesh
/// </summary>
public class TriangleIndexVertexArray : XnaDevRu.BulletX.StridingMeshInterface
{
List<IndexedMesh> _indexedMeshes = new List<IndexedMesh>();
public TriangleIndexVertexArray() { }
public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride)
{
IndexedMesh mesh = new IndexedMesh();
mesh.TriangleCount = numTriangleIndices;
mesh.TriangleIndexBase = triangleIndexBase;
mesh.TriangleIndexStride = triangleIndexStride;
mesh.VertexBase = vertexBase;
mesh.VertexCount = numVertices;
mesh.VertexStride = vertexStride;
AddIndexedMesh(mesh);
}
public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase)
: this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24) { }
public void AddIndexedMesh(IndexedMesh indexedMesh)
{
_indexedMeshes.Add(indexedMesh);
}
public override void GetLockedVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart)
{
throw new Exception("The method or operation is not implemented.");
}
public override void GetLockedReadOnlyVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart)
{
IndexedMesh m = _indexedMeshes[0];
Vector3[] vertexBase = m.VertexBase;
verts = new List<Vector3>();
foreach (Vector3 v in vertexBase)
{
verts.Add(v);
}
int[] indexBase = m.TriangleIndexBase;
indicies = new List<int>();
foreach (int i in indexBase)
{
indicies.Add(i);
}
numfaces = vertexBase.GetLength(0);
}
public override void UnLockVertexBase(int subpart)
{
throw new Exception("The method or operation is not implemented.");
}
public override void UnLockReadOnlyVertexBase(int subpart)
{
}
public override int SubPartsCount()
{
return _indexedMeshes.Count;
}
public override void PreallocateVertices(int numverts)
{
throw new Exception("The method or operation is not implemented.");
}
public override void PreallocateIndices(int numindices)
{
throw new Exception("The method or operation is not implemented.");
}
}
}
/*
Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru
Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
This file contains a class TriangleIndexVertexArray. I tried using the class with the same name
from the BulletX implementation and found it unusable for the purpose of using triangle meshes
within BulletX as the implementation was painfully incomplete.
The attempt to derive from the original class failed as viable members were hidden.
Fiddling around with BulletX itself was not my intention.
So I copied the class to the BulletX-plugin and modified it.
If you want to fiddle around with it it's up to you to move all this to BulletX.
If someone someday implements the missing functionality in BulletX, feel free to remove this class.
It's just an ugly hack.
*/
using System;
using System.Collections.Generic;
using System.Text;
using MonoXnaCompactMaths;
namespace OpenSim.Region.Physics.BulletXPlugin
{
/// <summary>
/// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements
/// instead of the number of indices, we pass the number of triangles
/// </summary>
public struct IndexedMesh
{
private int _numTriangles;
private int[] _triangleIndexBase;
private int _triangleIndexStride;
private int _numVertices;
private Vector3[] _vertexBase;
private int _vertexStride;
public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride)
{
_numTriangles = numTriangleIndices;
_triangleIndexBase = triangleIndexBase;
_triangleIndexStride = triangleIndexStride;
_vertexBase = vertexBase;
_numVertices = numVertices;
_vertexStride = vertexStride;
}
public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase)
{
_numTriangles = triangleIndexBase.Length;
_triangleIndexBase = triangleIndexBase;
_triangleIndexStride = 32;
_vertexBase = vertexBase;
_numVertices = vertexBase.Length;
_vertexStride = 24;
}
public int TriangleCount { get { return _numTriangles; } set { _numTriangles = value; } }
public int[] TriangleIndexBase { get { return _triangleIndexBase; } set { _triangleIndexBase = value; } }
public int TriangleIndexStride { get { return _triangleIndexStride; } set { _triangleIndexStride = value; } }
public int VertexCount { get { return _numVertices; } set { _numVertices = value; } }
public Vector3[] VertexBase { get { return _vertexBase; } set { _vertexBase = value; } }
public int VertexStride { get { return _vertexStride; } set { _vertexStride = value; } }
}
/// <summary>
/// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays.
/// Additional meshes can be added using addIndexedMesh
/// </summary>
public class TriangleIndexVertexArray : XnaDevRu.BulletX.StridingMeshInterface
{
List<IndexedMesh> _indexedMeshes = new List<IndexedMesh>();
public TriangleIndexVertexArray() { }
public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride)
{
IndexedMesh mesh = new IndexedMesh();
mesh.TriangleCount = numTriangleIndices;
mesh.TriangleIndexBase = triangleIndexBase;
mesh.TriangleIndexStride = triangleIndexStride;
mesh.VertexBase = vertexBase;
mesh.VertexCount = numVertices;
mesh.VertexStride = vertexStride;
AddIndexedMesh(mesh);
}
public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase)
: this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24) { }
public void AddIndexedMesh(IndexedMesh indexedMesh)
{
_indexedMeshes.Add(indexedMesh);
}
public override void GetLockedVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart)
{
throw new Exception("The method or operation is not implemented.");
}
public override void GetLockedReadOnlyVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart)
{
IndexedMesh m = _indexedMeshes[0];
Vector3[] vertexBase = m.VertexBase;
verts = new List<Vector3>();
foreach (Vector3 v in vertexBase)
{
verts.Add(v);
}
int[] indexBase = m.TriangleIndexBase;
indicies = new List<int>();
foreach (int i in indexBase)
{
indicies.Add(i);
}
numfaces = vertexBase.GetLength(0);
}
public override void UnLockVertexBase(int subpart)
{
throw new Exception("The method or operation is not implemented.");
}
public override void UnLockReadOnlyVertexBase(int subpart)
{
}
public override int SubPartsCount()
{
return _indexedMeshes.Count;
}
public override void PreallocateVertices(int numverts)
{
throw new Exception("The method or operation is not implemented.");
}
public override void PreallocateIndices(int numindices)
{
throw new Exception("The method or operation is not implemented.");
}
}
}

View File

@ -1,26 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenSim.Framework;
namespace OpenSim.Region.Physics.Manager
{
public interface IMesher
{
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size);
}
public interface IVertex {
}
public interface IMesh
{
List<PhysicsVector> getVertexList();
int[] getIndexListAsInt();
int[] getIndexListAsIntLocked();
float[] getVertexListAsFloatLocked();
}
}
using System;
using System.Collections.Generic;
using System.Text;
using OpenSim.Framework;
namespace OpenSim.Region.Physics.Manager
{
public interface IMesher
{
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size);
}
public interface IVertex {
}
public interface IMesh
{
List<PhysicsVector> getVertexList();
int[] getIndexListAsInt();
int[] getIndexListAsIntLocked();
float[] getVertexListAsFloatLocked();
}
}

View File

@ -1,83 +1,83 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenSim.Region.Physics.Meshing
{
class Extruder
{
public float startParameter;
public float stopParameter;
public Manager.PhysicsVector size;
public Mesh Extrude(Mesh m)
{
// Currently only works for iSteps=1;
Mesh result = new Mesh();
Mesh workingPlus = m.Clone();
Mesh workingMinus = m.Clone();
foreach (Vertex v in workingPlus.vertices)
{
if (v == null)
continue;
v.Z = +.5f;
v.X *= size.X;
v.Y *= size.Y;
v.Z *= size.Z;
}
foreach (Vertex v in workingMinus.vertices)
{
if (v == null)
continue;
v.Z = -.5f;
v.X *= size.X;
v.Y *= size.Y;
v.Z *= size.Z;
}
foreach (Triangle t in workingMinus.triangles)
{
t.invertNormal();
}
result.Append(workingMinus);
result.Append(workingPlus);
int iLastNull = 0;
for (int i = 0; i < workingPlus.vertices.Count; i++)
{
int iNext = (i + 1);
if (workingPlus.vertices[i] == null) // Can't make a simplex here
{
iLastNull = i+1;
continue;
}
if (i == workingPlus.vertices.Count-1) // End of list
{
iNext = iLastNull;
}
if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment
{
iNext = iLastNull;
}
Triangle tSide;
tSide = new Triangle(workingPlus.vertices[i], workingMinus.vertices[i], workingPlus.vertices[iNext]);
result.Add(tSide);
tSide = new Triangle(workingPlus.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]);
result.Add(tSide);
}
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenSim.Region.Physics.Meshing
{
class Extruder
{
public float startParameter;
public float stopParameter;
public Manager.PhysicsVector size;
public Mesh Extrude(Mesh m)
{
// Currently only works for iSteps=1;
Mesh result = new Mesh();
Mesh workingPlus = m.Clone();
Mesh workingMinus = m.Clone();
foreach (Vertex v in workingPlus.vertices)
{
if (v == null)
continue;
v.Z = +.5f;
v.X *= size.X;
v.Y *= size.Y;
v.Z *= size.Z;
}
foreach (Vertex v in workingMinus.vertices)
{
if (v == null)
continue;
v.Z = -.5f;
v.X *= size.X;
v.Y *= size.Y;
v.Z *= size.Z;
}
foreach (Triangle t in workingMinus.triangles)
{
t.invertNormal();
}
result.Append(workingMinus);
result.Append(workingPlus);
int iLastNull = 0;
for (int i = 0; i < workingPlus.vertices.Count; i++)
{
int iNext = (i + 1);
if (workingPlus.vertices[i] == null) // Can't make a simplex here
{
iLastNull = i+1;
continue;
}
if (i == workingPlus.vertices.Count-1) // End of list
{
iNext = iLastNull;
}
if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment
{
iNext = iLastNull;
}
Triangle tSide;
tSide = new Triangle(workingPlus.vertices[i], workingMinus.vertices[i], workingPlus.vertices[iNext]);
result.Add(tSide);
tSide = new Triangle(workingPlus.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]);
result.Add(tSide);
}
return result;
}
}
}

View File

@ -1,306 +1,306 @@
/*
* 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 OpenSim 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 OpenSim.Framework.Console;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Physics.Meshing;
public class Vertex : PhysicsVector, IComparable<Vertex>
{
public Vertex(float x, float y, float z)
: base(x, y, z)
{
}
public Vertex(PhysicsVector v)
: base(v.X, v.Y, v.Z)
{
}
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 virtual bool Equals(Vertex v, float tolerance)
{
PhysicsVector 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 List<Simplex> GetSimplices()
{
List<Simplex> result = new List<Simplex>();
Simplex s1 = new Simplex(v1, v2);
Simplex s2 = new Simplex(v2, v3);
Simplex s3 = new Simplex(v3, v1);
result.Add(s1);
result.Add(s2);
result.Add(s3);
return result;
}
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 PhysicsVector getNormal()
{
// Vertices
// Vectors for edges
PhysicsVector e1;
PhysicsVector e2;
e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
// Cross product for normal
PhysicsVector n = PhysicsVector.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;
}
/*
* 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 OpenSim 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 OpenSim.Framework.Console;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Physics.Meshing;
public class Vertex : PhysicsVector, IComparable<Vertex>
{
public Vertex(float x, float y, float z)
: base(x, y, z)
{
}
public Vertex(PhysicsVector v)
: base(v.X, v.Y, v.Z)
{
}
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 virtual bool Equals(Vertex v, float tolerance)
{
PhysicsVector 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 List<Simplex> GetSimplices()
{
List<Simplex> result = new List<Simplex>();
Simplex s1 = new Simplex(v1, v2);
Simplex s2 = new Simplex(v2, v3);
Simplex s3 = new Simplex(v3, v1);
result.Add(s1);
result.Add(s2);
result.Add(s3);
return result;
}
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 PhysicsVector getNormal()
{
// Vertices
// Vectors for edges
PhysicsVector e1;
PhysicsVector e2;
e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
// Cross product for normal
PhysicsVector n = PhysicsVector.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;
}
}

View File

@ -1,213 +1,213 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.Meshing
{
public class Mesh : IMesh
{
public List<Vertex> vertices;
public List<Triangle> triangles;
public float[] normals;
public Mesh()
{
vertices = new List<Vertex>();
triangles = new List<Triangle>();
}
public Mesh Clone()
{
Mesh result = new Mesh();
foreach (Vertex v in vertices)
{
if (v == null)
result.vertices.Add(null);
else
result.vertices.Add(v.Clone());
}
foreach (Triangle t in triangles)
{
int iV1, iV2, iV3;
iV1 = this.vertices.IndexOf(t.v1);
iV2 = this.vertices.IndexOf(t.v2);
iV3 = this.vertices.IndexOf(t.v3);
Triangle newT = new Triangle(result.vertices[iV1], result.vertices[iV2], result.vertices[iV3]);
result.Add(newT);
}
return result;
}
public void Add(Triangle triangle)
{
int i;
i = vertices.IndexOf(triangle.v1);
if (i < 0)
throw new ArgumentException("Vertex v1 not known to mesh");
i = vertices.IndexOf(triangle.v2);
if (i < 0)
throw new ArgumentException("Vertex v2 not known to mesh");
i = vertices.IndexOf(triangle.v3);
if (i < 0)
throw new ArgumentException("Vertex v3 not known to mesh");
triangles.Add(triangle);
}
public void Add(Vertex v)
{
vertices.Add(v);
}
public void Remove(Vertex v)
{
int i;
// First, remove all triangles that are build on v
for (i = 0; i < triangles.Count; i++)
{
Triangle t = triangles[i];
if (t.v1 == v || t.v2 == v || t.v3 == v)
{
triangles.RemoveAt(i);
i--;
}
}
// Second remove v itself
vertices.Remove(v);
}
public void RemoveTrianglesOutside(SimpleHull hull)
{
int i;
for (i = 0; i < triangles.Count; i++)
{
Triangle t = triangles[i];
Vertex v1 = t.v1;
Vertex v2 = t.v2;
Vertex v3 = t.v3;
PhysicsVector m = v1 + v2 + v3;
m /= 3.0f;
if (!hull.IsPointIn(new Vertex(m)))
{
triangles.RemoveAt(i);
i--;
}
}
}
public void Add(List<Vertex> lv)
{
foreach (Vertex v in lv)
{
vertices.Add(v);
}
}
public List<PhysicsVector> getVertexList()
{
List<PhysicsVector> result = new List<PhysicsVector>();
foreach (Vertex v in vertices)
{
result.Add(v);
}
return result;
}
public float[] getVertexListAsFloatLocked()
{
float[] result = new float[vertices.Count * 3];
for (int i = 0; i < vertices.Count; i++)
{
Vertex v = vertices[i];
if (v == null)
continue;
result[3 * i + 0] = v.X;
result[3 * i + 1] = v.Y;
result[3 * i + 2] = v.Z;
}
GCHandle.Alloc(result, GCHandleType.Pinned);
return result;
}
public int[] getIndexListAsInt()
{
int[] result = new int[triangles.Count * 3];
for (int i = 0; i < triangles.Count; i++)
{
Triangle t = triangles[i];
result[3 * i + 0] = vertices.IndexOf(t.v1);
result[3 * i + 1] = vertices.IndexOf(t.v2);
result[3 * i + 2] = vertices.IndexOf(t.v3);
}
return result;
}
public int[] getIndexListAsIntLocked()
{
int[] result = getIndexListAsInt();
GCHandle.Alloc(result, GCHandleType.Pinned);
return result;
}
public void Append(Mesh newMesh)
{
foreach (Vertex v in newMesh.vertices)
vertices.Add(v);
foreach (Triangle t in newMesh.triangles)
Add(t);
}
// Do a linear transformation of mesh.
public void TransformLinear(float[,] matrix, float[] offset)
{
foreach (Vertex v in vertices)
{
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 = Path.Combine(path, fileName);
StreamWriter sw = new StreamWriter(completePath);
foreach (Triangle t in triangles)
{
String s = t.ToStringRaw();
sw.WriteLine(s);
}
sw.Close();
}
}
}
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.Meshing
{
public class Mesh : IMesh
{
public List<Vertex> vertices;
public List<Triangle> triangles;
public float[] normals;
public Mesh()
{
vertices = new List<Vertex>();
triangles = new List<Triangle>();
}
public Mesh Clone()
{
Mesh result = new Mesh();
foreach (Vertex v in vertices)
{
if (v == null)
result.vertices.Add(null);
else
result.vertices.Add(v.Clone());
}
foreach (Triangle t in triangles)
{
int iV1, iV2, iV3;
iV1 = this.vertices.IndexOf(t.v1);
iV2 = this.vertices.IndexOf(t.v2);
iV3 = this.vertices.IndexOf(t.v3);
Triangle newT = new Triangle(result.vertices[iV1], result.vertices[iV2], result.vertices[iV3]);
result.Add(newT);
}
return result;
}
public void Add(Triangle triangle)
{
int i;
i = vertices.IndexOf(triangle.v1);
if (i < 0)
throw new ArgumentException("Vertex v1 not known to mesh");
i = vertices.IndexOf(triangle.v2);
if (i < 0)
throw new ArgumentException("Vertex v2 not known to mesh");
i = vertices.IndexOf(triangle.v3);
if (i < 0)
throw new ArgumentException("Vertex v3 not known to mesh");
triangles.Add(triangle);
}
public void Add(Vertex v)
{
vertices.Add(v);
}
public void Remove(Vertex v)
{
int i;
// First, remove all triangles that are build on v
for (i = 0; i < triangles.Count; i++)
{
Triangle t = triangles[i];
if (t.v1 == v || t.v2 == v || t.v3 == v)
{
triangles.RemoveAt(i);
i--;
}
}
// Second remove v itself
vertices.Remove(v);
}
public void RemoveTrianglesOutside(SimpleHull hull)
{
int i;
for (i = 0; i < triangles.Count; i++)
{
Triangle t = triangles[i];
Vertex v1 = t.v1;
Vertex v2 = t.v2;
Vertex v3 = t.v3;
PhysicsVector m = v1 + v2 + v3;
m /= 3.0f;
if (!hull.IsPointIn(new Vertex(m)))
{
triangles.RemoveAt(i);
i--;
}
}
}
public void Add(List<Vertex> lv)
{
foreach (Vertex v in lv)
{
vertices.Add(v);
}
}
public List<PhysicsVector> getVertexList()
{
List<PhysicsVector> result = new List<PhysicsVector>();
foreach (Vertex v in vertices)
{
result.Add(v);
}
return result;
}
public float[] getVertexListAsFloatLocked()
{
float[] result = new float[vertices.Count * 3];
for (int i = 0; i < vertices.Count; i++)
{
Vertex v = vertices[i];
if (v == null)
continue;
result[3 * i + 0] = v.X;
result[3 * i + 1] = v.Y;
result[3 * i + 2] = v.Z;
}
GCHandle.Alloc(result, GCHandleType.Pinned);
return result;
}
public int[] getIndexListAsInt()
{
int[] result = new int[triangles.Count * 3];
for (int i = 0; i < triangles.Count; i++)
{
Triangle t = triangles[i];
result[3 * i + 0] = vertices.IndexOf(t.v1);
result[3 * i + 1] = vertices.IndexOf(t.v2);
result[3 * i + 2] = vertices.IndexOf(t.v3);
}
return result;
}
public int[] getIndexListAsIntLocked()
{
int[] result = getIndexListAsInt();
GCHandle.Alloc(result, GCHandleType.Pinned);
return result;
}
public void Append(Mesh newMesh)
{
foreach (Vertex v in newMesh.vertices)
vertices.Add(v);
foreach (Triangle t in newMesh.triangles)
Add(t);
}
// Do a linear transformation of mesh.
public void TransformLinear(float[,] matrix, float[] offset)
{
foreach (Vertex v in vertices)
{
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 = Path.Combine(path, fileName);
StreamWriter sw = new StreamWriter(completePath);
foreach (Triangle t in triangles)
{
String s = t.ToStringRaw();
sw.WriteLine(s);
}
sw.Close();
}
}
}

View File

@ -1,393 +1,393 @@
/*
* 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 OpenSim 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.IO;
using System.Globalization;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.Meshing
{
public class MeshmerizerPlugin : IMeshingPlugin
{
public MeshmerizerPlugin()
{
}
public string GetName()
{
return "Meshmerizer";
}
public IMesher GetMesher()
{
return new Meshmerizer();
}
}
public class Meshmerizer : IMesher
{
// 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
// const string baseDir = "rawFiles";
const string baseDir = null;
static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
{
// p1, p2, points on the straight
// r1, r2, directional vectors of the straight. Not necessarily of length 1!
// note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
// thus allowing to decide whether an intersection is between two points
float r1x = r1.X;
float r1y = r1.Y;
float r2x = r2.X;
float r2y = r2.Y;
float denom = r1y*r2x - r1x*r2y;
if (denom == 0.0)
{
lambda = Single.NaN;
mu = Single.NaN;
return;
}
float p1x = p1.X;
float p1y = p1.Y;
float p2x = p2.X;
float p2y = p2.Y;
lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom;
mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom;
}
private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
{
List<Triangle> influenced = new List<Triangle>();
foreach (Triangle t in triangles)
{
if (t.isInCircle(v.X, v.Y))
{
influenced.Add(t);
}
}
return influenced;
}
private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
{
// This is a variant of the delaunay algorithm
// each time a new vertex is inserted, all triangles that are influenced by it are deleted
// and replaced by new ones including the new vertex
// It is not very time efficient but easy to implement.
int iCurrentVertex;
int iMaxVertex = vertices.Count;
for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
{
// Background: A triangle mesh fulfills the delaunay condition if (iff!)
// each circumlocutory circle (i.e. the circle that touches all three corners)
// of each triangle is empty of other vertices.
// Obviously a single (seeding) triangle fulfills this condition.
// If we now add one vertex, we need to reconstruct all triangles, that
// do not fulfill this condition with respect to the new triangle
// Find the triangles that are influenced by the new vertex
Vertex v=vertices[iCurrentVertex];
if (v == null)
continue; // Null is polygon stop marker. Ignore it
List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v);
List<Simplex> simplices = new List<Simplex>();
// Reconstruction phase. First step, dissolve each triangle into it's simplices,
// i.e. it's "border lines"
// Goal is to find "inner" borders and delete them, while the hull gets conserved.
// Inner borders are special in the way that they always come twice, which is how we detect them
foreach (Triangle t in influencedTriangles)
{
List<Simplex> newSimplices = t.GetSimplices();
simplices.AddRange(newSimplices);
triangles.Remove(t);
}
// Now sort the simplices. That will make identical ones reside side by side in the list
simplices.Sort();
// Look for duplicate simplices here.
// Remember, they are directly side by side in the list right now,
// So we only check directly neighbours
int iSimplex;
List<Simplex> innerSimplices = new List<Simplex>();
for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
{
if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0)
{
innerSimplices.Add(simplices[iSimplex - 1]);
innerSimplices.Add(simplices[iSimplex]);
}
}
foreach (Simplex s in innerSimplices)
{
simplices.Remove(s);
}
// each simplex still in the list belongs to the hull of the region in question
// The new vertex (yes, we still deal with verices here :-) ) forms a triangle
// with each of these simplices. Build the new triangles and add them to the list
foreach (Simplex s in simplices)
{
Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
if (!t.isDegraded())
{
triangles.Add(t);
}
}
}
}
static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the z (+ and -) surfaces of a box shaped prim
{
UInt16 hollowFactor = primShape.ProfileHollow;
UInt16 profileBegin = primShape.ProfileBegin;
UInt16 profileEnd = primShape.ProfileEnd;
// Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
// of a block are basically the same
// They may be warped differently but the shape is identical
// So we only create one surface as a model and derive both plus and minus surface of the block from it
// This is done in a model space where the block spans from -.5 to +.5 in X and Y
// The mapping to Scene space is done later during the "extrusion" phase
// Base
Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
Meshing.SimpleHull outerHull = new SimpleHull();
outerHull.AddVertex(MM);
outerHull.AddVertex(PM);
outerHull.AddVertex(PP);
outerHull.AddVertex(MP);
// Deal with cuts now
if ((profileBegin != 0) || (profileEnd != 0))
{
double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding
fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
fProfileEndAngle -= (90.0 + 45.0);
if (fProfileBeginAngle < fProfileEndAngle)
fProfileEndAngle -= 360.0;
// Note, that we don't want to cut out a triangle, even if this is a
// good approximation for small cuts. Indeed we want to cut out an arc
// and we approximate this arc by a polygon chain
// Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
// So it can easily be subtracted from the outer hull
int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree
double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps;
Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
// Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
SimpleHull cutHull = new SimpleHull();
cutHull.AddVertex(origin);
for (int i=0; i<iSteps; i++) {
double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!!
Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
cutHull.AddVertex(v);
}
Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors
cutHull.AddVertex(legEnd);
MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName);
SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
outerHull = cuttedHull;
}
// Deal with the hole here
if (hollowFactor > 0)
{
float hollowFactorF = (float) hollowFactor/(float) 50000;
Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
SimpleHull holeHull = new SimpleHull();
holeHull.AddVertex(IMM);
holeHull.AddVertex(IMP);
holeHull.AddVertex(IPP);
holeHull.AddVertex(IPM);
SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
outerHull = hollowedHull;
}
Mesh m = new Mesh();
Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
m.Add(Seed1);
m.Add(Seed2);
m.Add(Seed3);
m.Add(new Triangle(Seed1, Seed2, Seed3));
m.Add(outerHull.getVertices());
InsertVertices(m.vertices, 3, m.triangles);
m.DumpRaw(baseDir, primName, "Proto first Mesh");
m.Remove(Seed1);
m.Remove(Seed2);
m.Remove(Seed3);
m.DumpRaw(baseDir, primName, "Proto seeds removed");
m.RemoveTrianglesOutside(outerHull);
m.DumpRaw(baseDir, primName, "Proto outsides removed");
foreach (Triangle t in m.triangles)
{
PhysicsVector n = t.getNormal();
if (n.Z < 0.0)
t.invertNormal();
}
Extruder extr = new Extruder();
extr.size = size;
Mesh result = extr.Extrude(m);
result.DumpRaw(baseDir, primName, "Z extruded");
return result;
}
public static void CalcNormals(Mesh mesh)
{
int iTriangles = mesh.triangles.Count;
mesh.normals = new float[iTriangles*3];
int i = 0;
foreach (Triangle t in mesh.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);
// Normalized "normal"
nx /= l;
ny /= l;
nz /= l;
mesh.normals[i] = nx;
mesh.normals[i + 1] = ny;
mesh.normals[i + 2] = nz;
i += 3;
}
}
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
{
Mesh mesh = null;
switch (primShape.ProfileShape)
{
case ProfileShape.Square:
mesh=CreateBoxMesh(primName, primShape, size);
CalcNormals(mesh);
break;
default:
mesh = CreateBoxMesh(primName, primShape, size);
CalcNormals(mesh);
//Set default mesh to cube otherwise it'll return
// null and crash on the 'setMesh' method in the physics plugins.
//mesh = null;
break;
}
return mesh;
}
}
}
/*
* 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 OpenSim 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.IO;
using System.Globalization;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.Meshing
{
public class MeshmerizerPlugin : IMeshingPlugin
{
public MeshmerizerPlugin()
{
}
public string GetName()
{
return "Meshmerizer";
}
public IMesher GetMesher()
{
return new Meshmerizer();
}
}
public class Meshmerizer : IMesher
{
// 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
// const string baseDir = "rawFiles";
const string baseDir = null;
static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
{
// p1, p2, points on the straight
// r1, r2, directional vectors of the straight. Not necessarily of length 1!
// note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
// thus allowing to decide whether an intersection is between two points
float r1x = r1.X;
float r1y = r1.Y;
float r2x = r2.X;
float r2y = r2.Y;
float denom = r1y*r2x - r1x*r2y;
if (denom == 0.0)
{
lambda = Single.NaN;
mu = Single.NaN;
return;
}
float p1x = p1.X;
float p1y = p1.Y;
float p2x = p2.X;
float p2y = p2.Y;
lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom;
mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom;
}
private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
{
List<Triangle> influenced = new List<Triangle>();
foreach (Triangle t in triangles)
{
if (t.isInCircle(v.X, v.Y))
{
influenced.Add(t);
}
}
return influenced;
}
private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
{
// This is a variant of the delaunay algorithm
// each time a new vertex is inserted, all triangles that are influenced by it are deleted
// and replaced by new ones including the new vertex
// It is not very time efficient but easy to implement.
int iCurrentVertex;
int iMaxVertex = vertices.Count;
for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
{
// Background: A triangle mesh fulfills the delaunay condition if (iff!)
// each circumlocutory circle (i.e. the circle that touches all three corners)
// of each triangle is empty of other vertices.
// Obviously a single (seeding) triangle fulfills this condition.
// If we now add one vertex, we need to reconstruct all triangles, that
// do not fulfill this condition with respect to the new triangle
// Find the triangles that are influenced by the new vertex
Vertex v=vertices[iCurrentVertex];
if (v == null)
continue; // Null is polygon stop marker. Ignore it
List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v);
List<Simplex> simplices = new List<Simplex>();
// Reconstruction phase. First step, dissolve each triangle into it's simplices,
// i.e. it's "border lines"
// Goal is to find "inner" borders and delete them, while the hull gets conserved.
// Inner borders are special in the way that they always come twice, which is how we detect them
foreach (Triangle t in influencedTriangles)
{
List<Simplex> newSimplices = t.GetSimplices();
simplices.AddRange(newSimplices);
triangles.Remove(t);
}
// Now sort the simplices. That will make identical ones reside side by side in the list
simplices.Sort();
// Look for duplicate simplices here.
// Remember, they are directly side by side in the list right now,
// So we only check directly neighbours
int iSimplex;
List<Simplex> innerSimplices = new List<Simplex>();
for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
{
if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0)
{
innerSimplices.Add(simplices[iSimplex - 1]);
innerSimplices.Add(simplices[iSimplex]);
}
}
foreach (Simplex s in innerSimplices)
{
simplices.Remove(s);
}
// each simplex still in the list belongs to the hull of the region in question
// The new vertex (yes, we still deal with verices here :-) ) forms a triangle
// with each of these simplices. Build the new triangles and add them to the list
foreach (Simplex s in simplices)
{
Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
if (!t.isDegraded())
{
triangles.Add(t);
}
}
}
}
static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the z (+ and -) surfaces of a box shaped prim
{
UInt16 hollowFactor = primShape.ProfileHollow;
UInt16 profileBegin = primShape.ProfileBegin;
UInt16 profileEnd = primShape.ProfileEnd;
// Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
// of a block are basically the same
// They may be warped differently but the shape is identical
// So we only create one surface as a model and derive both plus and minus surface of the block from it
// This is done in a model space where the block spans from -.5 to +.5 in X and Y
// The mapping to Scene space is done later during the "extrusion" phase
// Base
Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
Meshing.SimpleHull outerHull = new SimpleHull();
outerHull.AddVertex(MM);
outerHull.AddVertex(PM);
outerHull.AddVertex(PP);
outerHull.AddVertex(MP);
// Deal with cuts now
if ((profileBegin != 0) || (profileEnd != 0))
{
double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding
fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
fProfileEndAngle -= (90.0 + 45.0);
if (fProfileBeginAngle < fProfileEndAngle)
fProfileEndAngle -= 360.0;
// Note, that we don't want to cut out a triangle, even if this is a
// good approximation for small cuts. Indeed we want to cut out an arc
// and we approximate this arc by a polygon chain
// Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
// So it can easily be subtracted from the outer hull
int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree
double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps;
Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
// Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
SimpleHull cutHull = new SimpleHull();
cutHull.AddVertex(origin);
for (int i=0; i<iSteps; i++) {
double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!!
Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
cutHull.AddVertex(v);
}
Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors
cutHull.AddVertex(legEnd);
MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName);
SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
outerHull = cuttedHull;
}
// Deal with the hole here
if (hollowFactor > 0)
{
float hollowFactorF = (float) hollowFactor/(float) 50000;
Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
SimpleHull holeHull = new SimpleHull();
holeHull.AddVertex(IMM);
holeHull.AddVertex(IMP);
holeHull.AddVertex(IPP);
holeHull.AddVertex(IPM);
SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
outerHull = hollowedHull;
}
Mesh m = new Mesh();
Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
m.Add(Seed1);
m.Add(Seed2);
m.Add(Seed3);
m.Add(new Triangle(Seed1, Seed2, Seed3));
m.Add(outerHull.getVertices());
InsertVertices(m.vertices, 3, m.triangles);
m.DumpRaw(baseDir, primName, "Proto first Mesh");
m.Remove(Seed1);
m.Remove(Seed2);
m.Remove(Seed3);
m.DumpRaw(baseDir, primName, "Proto seeds removed");
m.RemoveTrianglesOutside(outerHull);
m.DumpRaw(baseDir, primName, "Proto outsides removed");
foreach (Triangle t in m.triangles)
{
PhysicsVector n = t.getNormal();
if (n.Z < 0.0)
t.invertNormal();
}
Extruder extr = new Extruder();
extr.size = size;
Mesh result = extr.Extrude(m);
result.DumpRaw(baseDir, primName, "Z extruded");
return result;
}
public static void CalcNormals(Mesh mesh)
{
int iTriangles = mesh.triangles.Count;
mesh.normals = new float[iTriangles*3];
int i = 0;
foreach (Triangle t in mesh.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);
// Normalized "normal"
nx /= l;
ny /= l;
nz /= l;
mesh.normals[i] = nx;
mesh.normals[i + 1] = ny;
mesh.normals[i + 2] = nz;
i += 3;
}
}
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
{
Mesh mesh = null;
switch (primShape.ProfileShape)
{
case ProfileShape.Square:
mesh=CreateBoxMesh(primName, primShape, size);
CalcNormals(mesh);
break;
default:
mesh = CreateBoxMesh(primName, primShape, size);
CalcNormals(mesh);
//Set default mesh to cube otherwise it'll return
// null and crash on the 'setMesh' method in the physics plugins.
//mesh = null;
break;
}
return mesh;
}
}
}

View File

@ -1,363 +1,363 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenSim.Framework.Console;
namespace OpenSim.Region.Physics.Meshing
{
// A simple hull is a set of vertices building up to simplices that border a region
// The word simple referes to the fact, that this class assumes, that all simplices
// do not intersect
// Simple hulls can be added and subtracted.
// Vertices can be checked to lie inside a hull
// Also note, that the sequence of the vertices is important and defines if the region that
// is defined by the hull lies inside or outside the simplex chain
public class SimpleHull
{
List<Vertex> vertices = new List<Vertex>();
List<Vertex> holeVertices = new List<Vertex>(); // Only used, when the hull is hollow
// Adds a vertex to the end of the list
public void AddVertex(Vertex v) {
vertices.Add(v);
}
override public String ToString()
{
String result="";
foreach (Vertex v in vertices)
{
result += "b:" + v.ToString() + "\n";
}
return result;
}
public List<Vertex> getVertices() {
List<Vertex> newVertices = new List<Vertex>();
newVertices.AddRange(vertices);
newVertices.Add(null);
newVertices.AddRange(holeVertices);
return newVertices;
}
public SimpleHull Clone()
{
SimpleHull result = new SimpleHull();
foreach (Vertex v in vertices)
{
result.AddVertex(v.Clone());
}
foreach (Vertex v in this.holeVertices)
{
result.holeVertices.Add(v.Clone());
}
return result;
}
public bool IsPointIn(Vertex v1)
{
int iCounter=0;
List<Simplex> simplices=buildSimplexList();
foreach (Simplex s in simplices)
{
// Send a ray along the positive X-Direction
// Note, that this direction must correlate with the "below" interpretation
// of handling for the special cases below
Manager.PhysicsVector intersection = s.RayIntersect(v1, new Manager.PhysicsVector(1.0f, 0.0f, 0.0f), true);
if (intersection == null)
continue; // No intersection. Done. More tests to follow otherwise
// Did we hit the end of a simplex?
// Then this can be one of two special cases:
// 1. we go through a border exactly at a joint
// 2. we have just marginally touched a corner
// 3. we can slide along a border
// Solution: If the other vertex is "below" the ray, we don't count it
// Thus corners pointing down are counted twice, corners pointing up are not counted
// borders are counted once
if (intersection.IsIdentical(s.v1, 0.001f)) {
if (s.v2.Y < v1.Y)
continue;
}
// Do this for the other vertex two
if (intersection.IsIdentical(s.v2, 0.001f)) {
if (s.v1.Y<v1.Y)
continue;
}
iCounter++;
}
return iCounter % 2 == 1; // Point is inside if the number of intersections is odd
}
public bool containsPointsFrom(SimpleHull otherHull)
{
foreach (Vertex v in otherHull.vertices)
{
if (IsPointIn(v))
return true;
}
return false;
}
List<Simplex> buildSimplexList() {
List<Simplex> result = new List<Simplex>();
// Not asserted but assumed: at least three vertices
for (int i=0; i<vertices.Count-1; i++) {
Simplex s=new Simplex(vertices[i], vertices[i+1]);
result.Add(s);
}
Simplex s1=new Simplex(vertices[vertices.Count-1], vertices[0]);
result.Add(s1);
if (holeVertices.Count==0)
return result;
// Same here. At least three vertices in hole assumed
for (int i = 0; i < holeVertices.Count - 1; i++)
{
Simplex s = new Simplex(holeVertices[i], holeVertices[i + 1]);
result.Add(s);
}
s1 = new Simplex(holeVertices[holeVertices.Count - 1], holeVertices[0]);
result.Add(s1);
return result;
}
bool InsertVertex(Vertex v, int iAfter)
{
vertices.Insert(iAfter + 1, v);
return true;
}
Vertex getNextVertex(Vertex currentVertex)
{
int iCurrentIndex;
iCurrentIndex = vertices.IndexOf(currentVertex);
// Error handling for iCurrentIndex==-1 should go here (and probably never will)
iCurrentIndex++;
if (iCurrentIndex == vertices.Count)
iCurrentIndex = 0;
return vertices[iCurrentIndex];
}
public Vertex FindVertex(Vertex vBase, float tolerance) {
foreach (Vertex v in vertices) {
if (v.IsIdentical(vBase, tolerance))
return v;
}
return null;
}
public void FindIntersection(Simplex s, ref Vertex Intersection, ref Vertex nextVertex)
{
Vertex bestIntersection=null;
float distToV1=Single.PositiveInfinity;
Simplex bestIntersectingSimplex=null;
List<Simplex> simple = buildSimplexList();
foreach (Simplex sTest in simple)
{
Manager.PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f);
Vertex vTemp=null;
if (vvTemp != null)
vTemp = new Vertex(vvTemp);
if (vTemp!=null) {
Manager.PhysicsVector diff=(s.v1-vTemp);
float distTemp=diff.length();
if (bestIntersection==null || distTemp<distToV1) {
bestIntersection=vTemp;
distToV1=distTemp;
bestIntersectingSimplex = sTest;
}
} // end if vTemp
} // end foreach
Intersection = bestIntersection;
if (bestIntersectingSimplex != null)
nextVertex = bestIntersectingSimplex.v2;
else
nextVertex = null;
}
public static SimpleHull SubtractHull(SimpleHull baseHull, SimpleHull otherHull)
{
SimpleHull baseHullClone = baseHull.Clone();
SimpleHull otherHullClone = otherHull.Clone();
bool intersects = false;
MainLog.Instance.Debug("State before intersection detection");
MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString());
MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString());
{
int iBase, iOther;
// Insert into baseHull
for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
{
int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]);
for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++)
{
int iOtherNext = (iOther + 1) % otherHullClone.vertices.Count;
Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]);
Manager.PhysicsVector intersect = Simplex.Intersect(sBase, sOther, 0.001f, -.001f, 0.999f, 1.001f);
if (intersect != null)
{
Vertex vIntersect = new Vertex(intersect);
baseHullClone.vertices.Insert(iBase + 1, vIntersect);
sBase.v2 = vIntersect;
intersects = true;
}
}
}
}
MainLog.Instance.Debug("State after intersection detection for the base hull");
MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString());
{
int iOther, iBase;
// Insert into otherHull
for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++)
{
int iOtherNext = (iOther + 1) % otherHullClone.vertices.Count;
Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]);
for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
{
int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]);
Manager.PhysicsVector intersect = Simplex.Intersect(sBase, sOther, -.001f, 0.001f, 1.001f, 0.999f);
if (intersect != null)
{
Vertex vIntersect = new Vertex(intersect);
otherHullClone.vertices.Insert(iOther + 1, vIntersect);
sOther.v2 = vIntersect;
intersects = true;
}
}
}
}
MainLog.Instance.Debug("State after intersection detection for the base hull");
MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString());
bool otherIsInBase = baseHullClone.containsPointsFrom(otherHullClone);
if (!intersects && otherIsInBase)
{
// We have a hole here
baseHullClone.holeVertices = otherHullClone.vertices;
return baseHullClone;
}
SimpleHull result = new SimpleHull();
// Find a good starting Simplex from baseHull
// A good starting simplex is one that is outside otherHull
// Such a simplex must exist, otherwise the result will be empty
Vertex baseStartVertex = null;
{
int iBase;
for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
{
int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
Vertex center = new Vertex((baseHullClone.vertices[iBase] + baseHullClone.vertices[iBaseNext]) / 2.0f);
bool isOutside = !otherHullClone.IsPointIn(center);
if (isOutside)
{
baseStartVertex = baseHullClone.vertices[iBaseNext];
break;
}
}
}
if (baseStartVertex == null) // i.e. no simplex fulfilled the "outside" condition.
// In otherwords, subtractHull completely embraces baseHull
{
return result;
}
// The simplex that *starts* with baseStartVertex is outside the cutting hull,
// so we can start our walk with the next vertex without loosing a branch
Vertex V1 = baseStartVertex;
bool onBase = true;
// And here is how we do the magic :-)
// Start on the base hull.
// Walk the vertices in the positive direction
// For each vertex check, whether it is a vertex shared with the other hull
// if this is the case, switch over to walking the other vertex list.
// Note: The other hull *must* go backwards to our starting point (via several orther vertices)
// Thus it is important that the cutting hull has the inverse directional sense than the
// base hull!!!!!!!!! (means if base goes CW around it's center cutting hull must go CCW)
bool done = false;
while (!done)
{
result.AddVertex(V1);
Vertex nextVertex = null;
if (onBase)
{
nextVertex = otherHullClone.FindVertex(V1, 0.001f);
}
else
{
nextVertex = baseHullClone.FindVertex(V1, 0.001f);
}
if (nextVertex != null) // A node that represents an intersection
{
V1 = nextVertex; // Needed to find the next vertex on the other hull
onBase = !onBase;
}
if (onBase)
V1 = baseHullClone.getNextVertex(V1);
else
V1 = otherHullClone.getNextVertex(V1);
if (V1 == baseStartVertex)
done = true;
}
MainLog.Instance.Debug("The resulting Hull is:\n{1}", 0, result.ToString());
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using OpenSim.Framework.Console;
namespace OpenSim.Region.Physics.Meshing
{
// A simple hull is a set of vertices building up to simplices that border a region
// The word simple referes to the fact, that this class assumes, that all simplices
// do not intersect
// Simple hulls can be added and subtracted.
// Vertices can be checked to lie inside a hull
// Also note, that the sequence of the vertices is important and defines if the region that
// is defined by the hull lies inside or outside the simplex chain
public class SimpleHull
{
List<Vertex> vertices = new List<Vertex>();
List<Vertex> holeVertices = new List<Vertex>(); // Only used, when the hull is hollow
// Adds a vertex to the end of the list
public void AddVertex(Vertex v) {
vertices.Add(v);
}
override public String ToString()
{
String result="";
foreach (Vertex v in vertices)
{
result += "b:" + v.ToString() + "\n";
}
return result;
}
public List<Vertex> getVertices() {
List<Vertex> newVertices = new List<Vertex>();
newVertices.AddRange(vertices);
newVertices.Add(null);
newVertices.AddRange(holeVertices);
return newVertices;
}
public SimpleHull Clone()
{
SimpleHull result = new SimpleHull();
foreach (Vertex v in vertices)
{
result.AddVertex(v.Clone());
}
foreach (Vertex v in this.holeVertices)
{
result.holeVertices.Add(v.Clone());
}
return result;
}
public bool IsPointIn(Vertex v1)
{
int iCounter=0;
List<Simplex> simplices=buildSimplexList();
foreach (Simplex s in simplices)
{
// Send a ray along the positive X-Direction
// Note, that this direction must correlate with the "below" interpretation
// of handling for the special cases below
Manager.PhysicsVector intersection = s.RayIntersect(v1, new Manager.PhysicsVector(1.0f, 0.0f, 0.0f), true);
if (intersection == null)
continue; // No intersection. Done. More tests to follow otherwise
// Did we hit the end of a simplex?
// Then this can be one of two special cases:
// 1. we go through a border exactly at a joint
// 2. we have just marginally touched a corner
// 3. we can slide along a border
// Solution: If the other vertex is "below" the ray, we don't count it
// Thus corners pointing down are counted twice, corners pointing up are not counted
// borders are counted once
if (intersection.IsIdentical(s.v1, 0.001f)) {
if (s.v2.Y < v1.Y)
continue;
}
// Do this for the other vertex two
if (intersection.IsIdentical(s.v2, 0.001f)) {
if (s.v1.Y<v1.Y)
continue;
}
iCounter++;
}
return iCounter % 2 == 1; // Point is inside if the number of intersections is odd
}
public bool containsPointsFrom(SimpleHull otherHull)
{
foreach (Vertex v in otherHull.vertices)
{
if (IsPointIn(v))
return true;
}
return false;
}
List<Simplex> buildSimplexList() {
List<Simplex> result = new List<Simplex>();
// Not asserted but assumed: at least three vertices
for (int i=0; i<vertices.Count-1; i++) {
Simplex s=new Simplex(vertices[i], vertices[i+1]);
result.Add(s);
}
Simplex s1=new Simplex(vertices[vertices.Count-1], vertices[0]);
result.Add(s1);
if (holeVertices.Count==0)
return result;
// Same here. At least three vertices in hole assumed
for (int i = 0; i < holeVertices.Count - 1; i++)
{
Simplex s = new Simplex(holeVertices[i], holeVertices[i + 1]);
result.Add(s);
}
s1 = new Simplex(holeVertices[holeVertices.Count - 1], holeVertices[0]);
result.Add(s1);
return result;
}
bool InsertVertex(Vertex v, int iAfter)
{
vertices.Insert(iAfter + 1, v);
return true;
}
Vertex getNextVertex(Vertex currentVertex)
{
int iCurrentIndex;
iCurrentIndex = vertices.IndexOf(currentVertex);
// Error handling for iCurrentIndex==-1 should go here (and probably never will)
iCurrentIndex++;
if (iCurrentIndex == vertices.Count)
iCurrentIndex = 0;
return vertices[iCurrentIndex];
}
public Vertex FindVertex(Vertex vBase, float tolerance) {
foreach (Vertex v in vertices) {
if (v.IsIdentical(vBase, tolerance))
return v;
}
return null;
}
public void FindIntersection(Simplex s, ref Vertex Intersection, ref Vertex nextVertex)
{
Vertex bestIntersection=null;
float distToV1=Single.PositiveInfinity;
Simplex bestIntersectingSimplex=null;
List<Simplex> simple = buildSimplexList();
foreach (Simplex sTest in simple)
{
Manager.PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f);
Vertex vTemp=null;
if (vvTemp != null)
vTemp = new Vertex(vvTemp);
if (vTemp!=null) {
Manager.PhysicsVector diff=(s.v1-vTemp);
float distTemp=diff.length();
if (bestIntersection==null || distTemp<distToV1) {
bestIntersection=vTemp;
distToV1=distTemp;
bestIntersectingSimplex = sTest;
}
} // end if vTemp
} // end foreach
Intersection = bestIntersection;
if (bestIntersectingSimplex != null)
nextVertex = bestIntersectingSimplex.v2;
else
nextVertex = null;
}
public static SimpleHull SubtractHull(SimpleHull baseHull, SimpleHull otherHull)
{
SimpleHull baseHullClone = baseHull.Clone();
SimpleHull otherHullClone = otherHull.Clone();
bool intersects = false;
MainLog.Instance.Debug("State before intersection detection");
MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString());
MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString());
{
int iBase, iOther;
// Insert into baseHull
for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
{
int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]);
for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++)
{
int iOtherNext = (iOther + 1) % otherHullClone.vertices.Count;
Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]);
Manager.PhysicsVector intersect = Simplex.Intersect(sBase, sOther, 0.001f, -.001f, 0.999f, 1.001f);
if (intersect != null)
{
Vertex vIntersect = new Vertex(intersect);
baseHullClone.vertices.Insert(iBase + 1, vIntersect);
sBase.v2 = vIntersect;
intersects = true;
}
}
}
}
MainLog.Instance.Debug("State after intersection detection for the base hull");
MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString());
{
int iOther, iBase;
// Insert into otherHull
for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++)
{
int iOtherNext = (iOther + 1) % otherHullClone.vertices.Count;
Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]);
for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
{
int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]);
Manager.PhysicsVector intersect = Simplex.Intersect(sBase, sOther, -.001f, 0.001f, 1.001f, 0.999f);
if (intersect != null)
{
Vertex vIntersect = new Vertex(intersect);
otherHullClone.vertices.Insert(iOther + 1, vIntersect);
sOther.v2 = vIntersect;
intersects = true;
}
}
}
}
MainLog.Instance.Debug("State after intersection detection for the base hull");
MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString());
bool otherIsInBase = baseHullClone.containsPointsFrom(otherHullClone);
if (!intersects && otherIsInBase)
{
// We have a hole here
baseHullClone.holeVertices = otherHullClone.vertices;
return baseHullClone;
}
SimpleHull result = new SimpleHull();
// Find a good starting Simplex from baseHull
// A good starting simplex is one that is outside otherHull
// Such a simplex must exist, otherwise the result will be empty
Vertex baseStartVertex = null;
{
int iBase;
for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
{
int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
Vertex center = new Vertex((baseHullClone.vertices[iBase] + baseHullClone.vertices[iBaseNext]) / 2.0f);
bool isOutside = !otherHullClone.IsPointIn(center);
if (isOutside)
{
baseStartVertex = baseHullClone.vertices[iBaseNext];
break;
}
}
}
if (baseStartVertex == null) // i.e. no simplex fulfilled the "outside" condition.
// In otherwords, subtractHull completely embraces baseHull
{
return result;
}
// The simplex that *starts* with baseStartVertex is outside the cutting hull,
// so we can start our walk with the next vertex without loosing a branch
Vertex V1 = baseStartVertex;
bool onBase = true;
// And here is how we do the magic :-)
// Start on the base hull.
// Walk the vertices in the positive direction
// For each vertex check, whether it is a vertex shared with the other hull
// if this is the case, switch over to walking the other vertex list.
// Note: The other hull *must* go backwards to our starting point (via several orther vertices)
// Thus it is important that the cutting hull has the inverse directional sense than the
// base hull!!!!!!!!! (means if base goes CW around it's center cutting hull must go CCW)
bool done = false;
while (!done)
{
result.AddVertex(V1);
Vertex nextVertex = null;
if (onBase)
{
nextVertex = otherHullClone.FindVertex(V1, 0.001f);
}
else
{
nextVertex = baseHullClone.FindVertex(V1, 0.001f);
}
if (nextVertex != null) // A node that represents an intersection
{
V1 = nextVertex; // Needed to find the next vertex on the other hull
onBase = !onBase;
}
if (onBase)
V1 = baseHullClone.getNextVertex(V1);
else
V1 = otherHullClone.getNextVertex(V1);
if (V1 == baseStartVertex)
done = true;
}
MainLog.Instance.Debug("The resulting Hull is:\n{1}", 0, result.ToString());
return result;
}
}
}

View File

@ -1,198 +1,198 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.Meshing
{
// A simplex is a section of a straight line.
// It is defined by its endpoints, i.e. by two vertices
// Operation on vertices are
public class Simplex : IComparable<Simplex>
{
public Vertex v1;
public Vertex v2;
public Simplex(Vertex _v1, Vertex _v2)
{
v1 = _v1;
v2 = _v2;
}
public int CompareTo(Simplex other)
{
Vertex lv1, lv2, ov1, ov2, temp;
lv1 = v1;
lv2 = v2;
ov1 = other.v1;
ov2 = other.v2;
if (lv1 > lv2)
{
temp = lv1;
lv1 = lv2;
lv2 = temp;
}
if (ov1 > ov2)
{
temp = ov1;
ov1 = ov2;
ov2 = temp;
}
if (lv1 > ov1)
{
return 1;
}
if (lv1 < ov1)
{
return -1;
}
if (lv2 > ov2)
{
return 1;
}
if (lv2 < ov2)
{
return -1;
}
return 0;
}
private static void intersectParameter(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
{
// Intersects two straights
// p1, p2, points on the straight
// r1, r2, directional vectors of the straight. Not necessarily of length 1!
// note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
// thus allowing to decide whether an intersection is between two points
float r1x = r1.X;
float r1y = r1.Y;
float r2x = r2.X;
float r2y = r2.Y;
float denom = r1y*r2x - r1x*r2y;
float p1x = p1.X;
float p1y = p1.Y;
float p2x = p2.X;
float p2y = p2.Y;
float z1=-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x;
float z2=-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x;
if (denom == 0.0f) // Means the straights are parallel. Either no intersection or an infinite number of them
{
if (z1==0.0f) {// Means they are identical -> many, many intersections
lambda = Single.NaN;
mu = Single.NaN;
} else {
lambda = Single.PositiveInfinity;
mu = Single.PositiveInfinity;
}
return;
}
lambda = z1 / denom;
mu = z2 / denom;
}
// Intersects the simplex with another one.
// the borders are used to deal with float inaccuracies
// As a rule of thumb, the borders are
// lowerBorder1 : 0.0
// lowerBorder2 : 0.0
// upperBorder1 : 1.0
// upperBorder2 : 1.0
// Set these to values near the given parameters (e.g. 0.001 instead of 1 to exclude simplex starts safely, or to -0.001 to include them safely)
public static PhysicsVector Intersect(
Simplex s1,
Simplex s2,
float lowerBorder1,
float lowerBorder2,
float upperBorder1,
float upperBorder2)
{
PhysicsVector firstSimplexDirection = s1.v2 - s1.v1;
PhysicsVector secondSimplexDirection = s2.v2 - s2.v1;
float lambda = 0.0f;
float mu = 0.0f;
// Give us the parameters of an intersection. This subroutine does *not* take the constraints
// (intersection must be between v1 and v2 and it must be in the positive direction of the ray)
// into account. We do that afterwards.
intersectParameter(s1.v1, firstSimplexDirection, s2.v1, secondSimplexDirection, ref lambda, ref mu);
if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel.
return null;
if (Single.IsNaN(lambda)) // Special case. many, many intersections.
return null;
if (lambda > upperBorder1) // We're behind v2
return null;
if (lambda < lowerBorder1)
return null;
if (mu < lowerBorder2) // outside simplex 2
return null;
if (mu > upperBorder2) // outside simplex 2
return null;
return s1.v1 + lambda * firstSimplexDirection;
}
// Intersects the simplex with a ray. The ray is defined as all p=origin + lambda*direction
// where lambda >= 0
public PhysicsVector RayIntersect(Vertex origin, PhysicsVector direction, bool bEndsIncluded)
{
PhysicsVector simplexDirection = v2 - v1;
float lambda = 0.0f;
float mu = 0.0f;
// Give us the parameters of an intersection. This subroutine does *not* take the constraints
// (intersection must be between v1 and v2 and it must be in the positive direction of the ray)
// into account. We do that afterwards.
intersectParameter(v1, simplexDirection, origin, direction, ref lambda, ref mu);
if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel.
return null;
if (Single.IsNaN(lambda)) // Special case. many, many intersections.
return null;
if (mu < 0.0) // We're on the wrong side of the ray
return null;
if (lambda > 1.0) // We're behind v2
return null;
if (lambda == 1.0 && !bEndsIncluded)
return null; // The end of the simplices are not included
if (lambda < 0.0f) // we're before v1;
return null;
return this.v1 + lambda * simplexDirection;
}
}
using System;
using System.Collections.Generic;
using System.Text;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.Meshing
{
// A simplex is a section of a straight line.
// It is defined by its endpoints, i.e. by two vertices
// Operation on vertices are
public class Simplex : IComparable<Simplex>
{
public Vertex v1;
public Vertex v2;
public Simplex(Vertex _v1, Vertex _v2)
{
v1 = _v1;
v2 = _v2;
}
public int CompareTo(Simplex other)
{
Vertex lv1, lv2, ov1, ov2, temp;
lv1 = v1;
lv2 = v2;
ov1 = other.v1;
ov2 = other.v2;
if (lv1 > lv2)
{
temp = lv1;
lv1 = lv2;
lv2 = temp;
}
if (ov1 > ov2)
{
temp = ov1;
ov1 = ov2;
ov2 = temp;
}
if (lv1 > ov1)
{
return 1;
}
if (lv1 < ov1)
{
return -1;
}
if (lv2 > ov2)
{
return 1;
}
if (lv2 < ov2)
{
return -1;
}
return 0;
}
private static void intersectParameter(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
{
// Intersects two straights
// p1, p2, points on the straight
// r1, r2, directional vectors of the straight. Not necessarily of length 1!
// note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
// thus allowing to decide whether an intersection is between two points
float r1x = r1.X;
float r1y = r1.Y;
float r2x = r2.X;
float r2y = r2.Y;
float denom = r1y*r2x - r1x*r2y;
float p1x = p1.X;
float p1y = p1.Y;
float p2x = p2.X;
float p2y = p2.Y;
float z1=-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x;
float z2=-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x;
if (denom == 0.0f) // Means the straights are parallel. Either no intersection or an infinite number of them
{
if (z1==0.0f) {// Means they are identical -> many, many intersections
lambda = Single.NaN;
mu = Single.NaN;
} else {
lambda = Single.PositiveInfinity;
mu = Single.PositiveInfinity;
}
return;
}
lambda = z1 / denom;
mu = z2 / denom;
}
// Intersects the simplex with another one.
// the borders are used to deal with float inaccuracies
// As a rule of thumb, the borders are
// lowerBorder1 : 0.0
// lowerBorder2 : 0.0
// upperBorder1 : 1.0
// upperBorder2 : 1.0
// Set these to values near the given parameters (e.g. 0.001 instead of 1 to exclude simplex starts safely, or to -0.001 to include them safely)
public static PhysicsVector Intersect(
Simplex s1,
Simplex s2,
float lowerBorder1,
float lowerBorder2,
float upperBorder1,
float upperBorder2)
{
PhysicsVector firstSimplexDirection = s1.v2 - s1.v1;
PhysicsVector secondSimplexDirection = s2.v2 - s2.v1;
float lambda = 0.0f;
float mu = 0.0f;
// Give us the parameters of an intersection. This subroutine does *not* take the constraints
// (intersection must be between v1 and v2 and it must be in the positive direction of the ray)
// into account. We do that afterwards.
intersectParameter(s1.v1, firstSimplexDirection, s2.v1, secondSimplexDirection, ref lambda, ref mu);
if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel.
return null;
if (Single.IsNaN(lambda)) // Special case. many, many intersections.
return null;
if (lambda > upperBorder1) // We're behind v2
return null;
if (lambda < lowerBorder1)
return null;
if (mu < lowerBorder2) // outside simplex 2
return null;
if (mu > upperBorder2) // outside simplex 2
return null;
return s1.v1 + lambda * firstSimplexDirection;
}
// Intersects the simplex with a ray. The ray is defined as all p=origin + lambda*direction
// where lambda >= 0
public PhysicsVector RayIntersect(Vertex origin, PhysicsVector direction, bool bEndsIncluded)
{
PhysicsVector simplexDirection = v2 - v1;
float lambda = 0.0f;
float mu = 0.0f;
// Give us the parameters of an intersection. This subroutine does *not* take the constraints
// (intersection must be between v1 and v2 and it must be in the positive direction of the ray)
// into account. We do that afterwards.
intersectParameter(v1, simplexDirection, origin, direction, ref lambda, ref mu);
if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel.
return null;
if (Single.IsNaN(lambda)) // Special case. many, many intersections.
return null;
if (mu < 0.0) // We're on the wrong side of the ray
return null;
if (lambda > 1.0) // We're behind v2
return null;
if (lambda == 1.0 && !bEndsIncluded)
return null; // The end of the simplices are not included
if (lambda < 0.0f) // we're before v1;
return null;
return this.v1 + lambda * simplexDirection;
}
}
}

View File

@ -1,62 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<inventory>
<folder>
<name>My Inventory</name>
<folderID UUID="00000112-000f-0000-0000-000100bba000" />
<type>9</type>
<folders>
<folder>
<name>Animations</name>
<type>20</type>
</folder>
<folder>
<name>Body Parts</name>
<type>13</type>
</folder>
<folder>
<name>Clothing</name>
<type>5</type>
</folder>
<folder>
<name>Gestures</name>
<type>21</type>
</folder>
<folder>
<name>Landmarks</name>
<type>3</type>
</folder>
<folder>
<name>Lost And Found</name>
<type>16</type>
</folder>
<folder>
<name>Notecards</name>
<type>7</type>
</folder>
<folder>
<name>Objects</name>
<type>6</type>
</folder>
<folder>
<name>Photo Album</name>
<type>15</type>
</folder>
<folder>
<name>Scripts</name>
<type>10</type>
</folder>
<folder>
<name>Sounds</name>
<type>1</type>
</folder>
<folder>
<name>Textures</name>
<type>0</type>
</folder>
<folder>
<name>Trash</name>
<type>14</type>
</folder>
</folders>
</folder>
</inventory>
<?xml version="1.0" encoding="utf-8"?>
<inventory>
<folder>
<name>My Inventory</name>
<folderID UUID="00000112-000f-0000-0000-000100bba000" />
<type>9</type>
<folders>
<folder>
<name>Animations</name>
<type>20</type>
</folder>
<folder>
<name>Body Parts</name>
<type>13</type>
</folder>
<folder>
<name>Clothing</name>
<type>5</type>
</folder>
<folder>
<name>Gestures</name>
<type>21</type>
</folder>
<folder>
<name>Landmarks</name>
<type>3</type>
</folder>
<folder>
<name>Lost And Found</name>
<type>16</type>
</folder>
<folder>
<name>Notecards</name>
<type>7</type>
</folder>
<folder>
<name>Objects</name>
<type>6</type>
</folder>
<folder>
<name>Photo Album</name>
<type>15</type>
</folder>
<folder>
<name>Scripts</name>
<type>10</type>
</folder>
<folder>
<name>Sounds</name>
<type>1</type>
</folder>
<folder>
<name>Textures</name>
<type>0</type>
</folder>
<folder>
<name>Trash</name>
<type>14</type>
</folder>
</folders>
</folder>
</inventory>

View File

@ -1,144 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<inventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<folder>
<name>Library</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000000-0000-0000-0000-000000000000" />
<folderID UUID="00000112-000f-0000-0000-000100bba000" />
<type>9</type>
<version>0</version>
<folders>
<folder>
<name>Animations</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="d052e0a1-0bf7-4f2a-8982-472df8e4d226" />
<type>20</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Body Parts</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="52abdfa6-d50f-4743-b7db-b37f97857941" />
<type>13</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Clothing</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="5820e65c-eaa9-4404-a2bc-4c63fec47c83" />
<type>5</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Gestures</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="530e1f34-14fa-4129-a373-e4ee65249b78" />
<type>21</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Landmarks</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="a1419cef-d7d7-476e-a088-165c747532a2" />
<type>3</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Lost And Found</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="62c88a03-838c-4822-b912-10e4a9b831c5" />
<type>3</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Notecards</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="b61598ea-2312-49f9-9b1c-5214ba55facc" />
<type>7</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Objects</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="ff757447-ea4d-4769-8751-e3bb13cd570d" />
<type>6</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Photo Album</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="d6cadddd-68e1-4fc3-bd24-319cd593fdc0" />
<type>15</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Scripts</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="f0e2c3dc-3f44-4730-8b33-6a911994fea1" />
<type>10</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Sounds</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="b8815d3c-52b0-447c-adea-3a1a442dbb2b" />
<type>1</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Textures</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="23e487c5-43af-4fe6-b211-75cfc91845a6" />
<type>0</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Accessories</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="b4024e1c-9b1d-426e-a70e-55ae0078dc0b" />
<type>8</type>
<version>0</version>
<folders />
<items />
</folder>
</folders>
<items />
</folder>
<?xml version="1.0" encoding="utf-8"?>
<inventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<folder>
<name>Library</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000000-0000-0000-0000-000000000000" />
<folderID UUID="00000112-000f-0000-0000-000100bba000" />
<type>9</type>
<version>0</version>
<folders>
<folder>
<name>Animations</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="d052e0a1-0bf7-4f2a-8982-472df8e4d226" />
<type>20</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Body Parts</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="52abdfa6-d50f-4743-b7db-b37f97857941" />
<type>13</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Clothing</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="5820e65c-eaa9-4404-a2bc-4c63fec47c83" />
<type>5</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Gestures</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="530e1f34-14fa-4129-a373-e4ee65249b78" />
<type>21</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Landmarks</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="a1419cef-d7d7-476e-a088-165c747532a2" />
<type>3</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Lost And Found</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="62c88a03-838c-4822-b912-10e4a9b831c5" />
<type>3</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Notecards</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="b61598ea-2312-49f9-9b1c-5214ba55facc" />
<type>7</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Objects</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="ff757447-ea4d-4769-8751-e3bb13cd570d" />
<type>6</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Photo Album</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="d6cadddd-68e1-4fc3-bd24-319cd593fdc0" />
<type>15</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Scripts</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="f0e2c3dc-3f44-4730-8b33-6a911994fea1" />
<type>10</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Sounds</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="b8815d3c-52b0-447c-adea-3a1a442dbb2b" />
<type>1</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Textures</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="23e487c5-43af-4fe6-b211-75cfc91845a6" />
<type>0</type>
<version>0</version>
<folders />
<items />
</folder>
<folder>
<name>Accessories</name>
<agentID UUID="00000112-000f-0000-0000-000100bba000" />
<parentID UUID="00000112-000f-0000-0000-000100bba000" />
<folderID UUID="b4024e1c-9b1d-426e-a70e-55ae0078dc0b" />
<type>8</type>
<version>0</version>
<folders />
<items />
</folder>
</folders>
<items />
</folder>
</inventory>

View File

@ -1,64 +1,64 @@
[Startup]
gridmode = false
physics = basicphysics
; Prim Storage
; if you would like to use sqlite uncomment the following line (and
; comment the NullStorage line)
storage_plugin = "OpenSim.DataStore.MonoSqlite.dll"
;storage_plugin = "OpenSim.DataStore.NullStorage.dll"
startup_console_commands_file = "startup_commands.txt"
shutdown_console_commands_file = "shutdown_commands.txt"
serverside_object_permissions = false
; asset_database = "db4o"
; to try sqlite as the asset database , comment out the above line, and uncomment following one
asset_database = "sqlite"
verbose = true
physical_prim = true
[StandAlone]
accounts_authenticate = true
welcome_message = "Welcome to OpenSim"
inventory_plugin = "OpenSim.Framework.Data.SQLite.dll"
; userDatabase_plugin = "OpenSim.Framework.Data.DB4o.dll"
userDatabase_plugin = "OpenSim.Framework.Data.SQLite.dll"
default_location_x = 1000
default_location_y = 1000
dump_assets_to_file = false
[Network]
http_listener_port = 9000
remoting_listener_port = 8895
grid_server_url = "http://127.0.0.1:8001"
grid_send_key = "null"
grid_recv_key = "null"
user_server_url = "http://127.0.0.1:8002"
user_send_key = "null"
user_recv_key = "null"
asset_server_url = "http://127.0.0.1:8003"
[Chat]
whisper_distance = 10
say_distance = 30
shout_distance = 100
; Uncomment the following for IRC bridge
; experimental, so if it breaks... keep both parts... yada yada
; also, not good error detection when it fails
;[IRC]
;server = name.of.irc.server.on.the.net
;nick = OpenSimBotNameProbablyMakeThisShorter
;channel = #the_irc_channel_you_want_to_connect_to
; Uncomment the following to control the progression of daytime
; in the Sim. The defaults are what is shown below
;[Sun]
; number of wall clock hours for an opensim day. 24.0 would mean realtime
;day_length = 0.5
; send a Sun update ever frame_rate # of frames. A lower number will
; make for smoother sun transition at the cost of network
;frame_rate = 100
[Startup]
gridmode = false
physics = basicphysics
; Prim Storage
; if you would like to use sqlite uncomment the following line (and
; comment the NullStorage line)
storage_plugin = "OpenSim.DataStore.MonoSqlite.dll"
;storage_plugin = "OpenSim.DataStore.NullStorage.dll"
startup_console_commands_file = "startup_commands.txt"
shutdown_console_commands_file = "shutdown_commands.txt"
serverside_object_permissions = false
; asset_database = "db4o"
; to try sqlite as the asset database , comment out the above line, and uncomment following one
asset_database = "sqlite"
verbose = true
physical_prim = true
[StandAlone]
accounts_authenticate = true
welcome_message = "Welcome to OpenSim"
inventory_plugin = "OpenSim.Framework.Data.SQLite.dll"
; userDatabase_plugin = "OpenSim.Framework.Data.DB4o.dll"
userDatabase_plugin = "OpenSim.Framework.Data.SQLite.dll"
default_location_x = 1000
default_location_y = 1000
dump_assets_to_file = false
[Network]
http_listener_port = 9000
remoting_listener_port = 8895
grid_server_url = "http://127.0.0.1:8001"
grid_send_key = "null"
grid_recv_key = "null"
user_server_url = "http://127.0.0.1:8002"
user_send_key = "null"
user_recv_key = "null"
asset_server_url = "http://127.0.0.1:8003"
[Chat]
whisper_distance = 10
say_distance = 30
shout_distance = 100
; Uncomment the following for IRC bridge
; experimental, so if it breaks... keep both parts... yada yada
; also, not good error detection when it fails
;[IRC]
;server = name.of.irc.server.on.the.net
;nick = OpenSimBotNameProbablyMakeThisShorter
;channel = #the_irc_channel_you_want_to_connect_to
; Uncomment the following to control the progression of daytime
; in the Sim. The defaults are what is shown below
;[Sun]
; number of wall clock hours for an opensim day. 24.0 would mean realtime
;day_length = 0.5
; send a Sun update ever frame_rate # of frames. A lower number will
; make for smoother sun transition at the cost of network
;frame_rate = 100

View File

@ -1,479 +1,479 @@
<Nini>
<Section Name="Welcome notecard">
<Key Name="assetID" Value="00000000-0000-2222-3333-000000000001" />
<Key Name="name" Value="WelcomeNote" />
<Key Name="assetType" Value="7" />
<Key Name="inventoryType" Value="7" />
<Key Name="fileName" Value="welcomeNote.dat" />
</Section>
<Section Name="texture1">
<Key Name="assetID" Value="00000000-0000-2222-3333-000000000099" />
<Key Name="name" Value="femface" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="femaleface.jp2" />
</Section>
<Section Name="4-tile2 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001000" />
<Key Name="name" Value="4-tile2" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="4-tile2.jp2" />
</Section>
<Section Name="4-tile3 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001001" />
<Key Name="name" Value="4-tile3" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="4-tile3.jp2" />
</Section>
<Section Name="brick1_256 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001002" />
<Key Name="name" Value="brick1_256" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="brick1_256.jp2" />
</Section>
<Section Name="brick2_256 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001003" />
<Key Name="name" Value="brick2_256" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="brick2_256.jp2" />
</Section>
<Section Name="brick_mono Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001004" />
<Key Name="name" Value="brick_mono" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="brick_mono.jp2" />
</Section>
<Section Name="cedar Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001005" />
<Key Name="name" Value="cedar" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="cedar.jp2" />
</Section>
<Section Name="cement_block Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001006" />
<Key Name="name" Value="cement_block" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="cement_block.jp2" />
</Section>
<Section Name="clear Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001007" />
<Key Name="name" Value="clear" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="clear.jp2" />
</Section>
<Section Name="cobbles Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001008" />
<Key Name="name" Value="cobbles" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="cobbles.jp2" />
</Section>
<Section Name="creambrick Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001009" />
<Key Name="name" Value="creambrick" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="creambrick.jp2" />
</Section>
<Section Name="fgrass Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001010" />
<Key Name="name" Value="fgrass" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="fgrass.jp2" />
</Section>
<Section Name="glasstile2 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001011" />
<Key Name="name" Value="glasstile2" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="glasstile2.jp2" />
</Section>
<Section Name="graniteblock Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001012" />
<Key Name="name" Value="graniteblock" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="graniteblock.jp2" />
</Section>
<Section Name="grass Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001013" />
<Key Name="name" Value="grass" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="grass.jp2" />
</Section>
<Section Name="gravel Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001014" />
<Key Name="name" Value="gravel" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="gravel.jp2" />
</Section>
<Section Name="greybrick Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001015" />
<Key Name="name" Value="greybrick" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="greybrick.jp2" />
</Section>
<Section Name="ivy Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001016" />
<Key Name="name" Value="ivy" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="ivy.jp2" />
</Section>
<Section Name="mahogany Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001017" />
<Key Name="name" Value="mahogany" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="mahogany.jp2" />
</Section>
<Section Name="maple Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001018" />
<Key Name="name" Value="maple" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="maple.jp2" />
</Section>
<Section Name="mosaic02 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001019" />
<Key Name="name" Value="mosaic02" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="mosaic02.jp2" />
</Section>
<Section Name="palm1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001020" />
<Key Name="name" Value="palm1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="palm1.jp2" />
</Section>
<Section Name="papaya Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001021" />
<Key Name="name" Value="papaya" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="papaya.jp2" />
</Section>
<Section Name="papaya_bark Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001022" />
<Key Name="name" Value="papaya_bark" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="papaya_bark.jp2" />
</Section>
<Section Name="pastelbrick Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001023" />
<Key Name="name" Value="pastelbrick" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="pastelbrick.jp2" />
</Section>
<Section Name="pine1_10m Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001024" />
<Key Name="name" Value="pine1_10m" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="pine1_10m.jp2" />
</Section>
<Section Name="poplar Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001025" />
<Key Name="name" Value="poplar" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="poplar.jp2" />
</Section>
<Section Name="redtri_tile Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001026" />
<Key Name="name" Value="redtri_tile" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="redtri_tile.jp2" />
</Section>
<Section Name="rockbuilding Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001027" />
<Key Name="name" Value="rockbuilding" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rockbuilding.jp2" />
</Section>
<Section Name="rockwallbig Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001028" />
<Key Name="name" Value="rockwallbig" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rockwallbig.jp2" />
</Section>
<Section Name="roof01 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001029" />
<Key Name="name" Value="roof01" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="roof01.jp2" />
</Section>
<Section Name="rooftiles1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001030" />
<Key Name="name" Value="rooftiles1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rooftiles1.jp2" />
</Section>
<Section Name="rooftiles2_peach Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001031" />
<Key Name="name" Value="rooftiles2_peach" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rooftiles2_peach.jp2" />
</Section>
<Section Name="rooftiles2_roy Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001032" />
<Key Name="name" Value="rooftiles2_roy" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rooftiles2_roy.jp2" />
</Section>
<Section Name="saguaro_8m Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001033" />
<Key Name="name" Value="saguaro_8m" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="saguaro_8m.jp2" />
</Section>
<Section Name="seawater Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001034" />
<Key Name="name" Value="seawater" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="seawater.jp2" />
</Section>
<Section Name="snow1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001035" />
<Key Name="name" Value="snow1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="snow1.jp2" />
</Section>
<Section Name="steel Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001036" />
<Key Name="name" Value="steel" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="steel.jp2" />
</Section>
<Section Name="stone1wall Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001037" />
<Key Name="name" Value="stone1wall" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="stone1wall.jp2" />
</Section>
<Section Name="stonetile Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001038" />
<Key Name="name" Value="stonetile" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="stonetile.jp2" />
</Section>
<Section Name="street2 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001039" />
<Key Name="name" Value="street2" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="street2.jp2" />
</Section>
<Section Name="thatch Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001040" />
<Key Name="name" Value="thatch" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="thatch.jp2" />
</Section>
<Section Name="water1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001041" />
<Key Name="name" Value="water1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="water1.jp2" />
</Section>
<Section Name="water3 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001042" />
<Key Name="name" Value="water3" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="water3.jp2" />
</Section>
<Section Name="Sea">
<Key Name="assetID" Value="2bfd3884-7e27-69b9-ba3a-3e673f680004" />
<Key Name="name" Value="Sea" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="water3.jp2" />
</Section>
<Section Name="wood1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001043" />
<Key Name="name" Value="wood1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="wood1.jp2" />
</Section>
<Section Name="LOLCAT">
<Key Name="assetID" Value="13371337-1337-1337-1337-133713371337" />
<Key Name="name" Value="lolcat in ur assets" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="peaches.jp2" />
</Section>
<!-- Copied from hardcoded values -->
<Section Name="Bricks">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000001"/>
<Key Name="name" Value="Bricks"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="bricks.jp2"/>
</Section>
<Section Name="Plywood">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000002"/>
<Key Name="name" Value="Plywood"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="plywood.jp2"/>
</Section>
<Section Name="Rocks">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000003"/>
<Key Name="name" Value="Rocks"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rocks.jp2"/>
</Section>
<Section Name="Granite">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000004"/>
<Key Name="name" Value="Granite"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="granite.jp2"/>
</Section>
<Section Name="Hardwood">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000005"/>
<Key Name="name" Value="Hardwood"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="hardwood.jp2"/>
</Section>
<Section Name="Prim Base Texture">
<Key Name="assetID" Value="00000000-0000-1111-5005-000000000005"/>
<Key Name="name" Value="Prim Base Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="plywood.jp2"/>
</Section>
<Section Name="Map Base Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000006"/>
<Key Name="name" Value="Map Base Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="map_base.jp2"/>
</Section>
<Section Name="Map Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000007"/>
<Key Name="name" Value="Map Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="map1.jp2"/>
</Section>
<Section Name="Female Body Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000010"/>
<Key Name="name" Value="Female Body Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="femalebody.jp2"/>
</Section>
<Section Name="Female Bottom Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000011"/>
<Key Name="name" Value="Female Bottom Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="femalebottom.jp2"/>
</Section>
<Section Name="Female Face Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000012"/>
<Key Name="name" Value="Female Face Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="femaleface.jp2"/>
</Section>
<Section Name="Skin">
<Key Name="assetID" Value="77c41e39-38f9-f75a-024e-585989bbabbb"/>
<Key Name="name" Value="Skin"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="base_skin.dat"/>
</Section>
<Section Name="Skin">
<Key Name="assetID" Value="77c41e39-38f9-f75a-024e-585989bbabbc"/>
<Key Name="name" Value="Jim Skin"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="jim_skin.dat"/>
</Section>
<Section Name="Skin">
<Key Name="assetID" Value="77c41e39-38f9-f75a-024e-585989bbabbd"/>
<Key Name="name" Value="Goblin Skin"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="goblin_skin.dat"/>
</Section>
<Section Name="Shape">
<Key Name="assetID" Value="66c41e39-38f9-f75a-024e-585989bfab73"/>
<Key Name="name" Value="Shape"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="base_shape.dat"/>
</Section>
<Section Name="Shape">
<Key Name="assetID" Value="66c41e39-38f9-f75a-024e-585989bfab74"/>
<Key Name="name" Value="Jim Shape"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="jim_shape.dat"/>
</Section>
<Section Name="Shape">
<Key Name="assetID" Value="66c41e39-38f9-f75a-024e-585989bfab75"/>
<Key Name="name" Value="Little Goblin Shape"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="little_goblin_shape.dat"/>
</Section>
<Section Name="Shirt">
<Key Name="assetID" Value="00000000-38f9-1111-024e-222222111110"/>
<Key Name="name" Value="Shirt"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="newshirt.dat"/>
</Section>
<Section Name="Pants">
<Key Name="assetID" Value="00000000-38f9-1111-024e-222222111120"/>
<Key Name="name" Value="Pants"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="newpants.dat"/>
</Section>
<Section Name="Moon">
<Key Name="assetID" Value="fc4b9f0b-d008-45c6-96a4-01dd947ac621"/>
<Key Name="name" Value="Moon"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="moon.jp2"/>
</Section>
</Nini>
<Nini>
<Section Name="Welcome notecard">
<Key Name="assetID" Value="00000000-0000-2222-3333-000000000001" />
<Key Name="name" Value="WelcomeNote" />
<Key Name="assetType" Value="7" />
<Key Name="inventoryType" Value="7" />
<Key Name="fileName" Value="welcomeNote.dat" />
</Section>
<Section Name="texture1">
<Key Name="assetID" Value="00000000-0000-2222-3333-000000000099" />
<Key Name="name" Value="femface" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="femaleface.jp2" />
</Section>
<Section Name="4-tile2 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001000" />
<Key Name="name" Value="4-tile2" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="4-tile2.jp2" />
</Section>
<Section Name="4-tile3 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001001" />
<Key Name="name" Value="4-tile3" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="4-tile3.jp2" />
</Section>
<Section Name="brick1_256 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001002" />
<Key Name="name" Value="brick1_256" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="brick1_256.jp2" />
</Section>
<Section Name="brick2_256 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001003" />
<Key Name="name" Value="brick2_256" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="brick2_256.jp2" />
</Section>
<Section Name="brick_mono Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001004" />
<Key Name="name" Value="brick_mono" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="brick_mono.jp2" />
</Section>
<Section Name="cedar Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001005" />
<Key Name="name" Value="cedar" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="cedar.jp2" />
</Section>
<Section Name="cement_block Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001006" />
<Key Name="name" Value="cement_block" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="cement_block.jp2" />
</Section>
<Section Name="clear Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001007" />
<Key Name="name" Value="clear" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="clear.jp2" />
</Section>
<Section Name="cobbles Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001008" />
<Key Name="name" Value="cobbles" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="cobbles.jp2" />
</Section>
<Section Name="creambrick Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001009" />
<Key Name="name" Value="creambrick" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="creambrick.jp2" />
</Section>
<Section Name="fgrass Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001010" />
<Key Name="name" Value="fgrass" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="fgrass.jp2" />
</Section>
<Section Name="glasstile2 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001011" />
<Key Name="name" Value="glasstile2" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="glasstile2.jp2" />
</Section>
<Section Name="graniteblock Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001012" />
<Key Name="name" Value="graniteblock" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="graniteblock.jp2" />
</Section>
<Section Name="grass Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001013" />
<Key Name="name" Value="grass" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="grass.jp2" />
</Section>
<Section Name="gravel Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001014" />
<Key Name="name" Value="gravel" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="gravel.jp2" />
</Section>
<Section Name="greybrick Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001015" />
<Key Name="name" Value="greybrick" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="greybrick.jp2" />
</Section>
<Section Name="ivy Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001016" />
<Key Name="name" Value="ivy" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="ivy.jp2" />
</Section>
<Section Name="mahogany Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001017" />
<Key Name="name" Value="mahogany" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="mahogany.jp2" />
</Section>
<Section Name="maple Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001018" />
<Key Name="name" Value="maple" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="maple.jp2" />
</Section>
<Section Name="mosaic02 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001019" />
<Key Name="name" Value="mosaic02" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="mosaic02.jp2" />
</Section>
<Section Name="palm1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001020" />
<Key Name="name" Value="palm1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="palm1.jp2" />
</Section>
<Section Name="papaya Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001021" />
<Key Name="name" Value="papaya" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="papaya.jp2" />
</Section>
<Section Name="papaya_bark Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001022" />
<Key Name="name" Value="papaya_bark" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="papaya_bark.jp2" />
</Section>
<Section Name="pastelbrick Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001023" />
<Key Name="name" Value="pastelbrick" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="pastelbrick.jp2" />
</Section>
<Section Name="pine1_10m Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001024" />
<Key Name="name" Value="pine1_10m" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="pine1_10m.jp2" />
</Section>
<Section Name="poplar Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001025" />
<Key Name="name" Value="poplar" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="poplar.jp2" />
</Section>
<Section Name="redtri_tile Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001026" />
<Key Name="name" Value="redtri_tile" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="redtri_tile.jp2" />
</Section>
<Section Name="rockbuilding Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001027" />
<Key Name="name" Value="rockbuilding" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rockbuilding.jp2" />
</Section>
<Section Name="rockwallbig Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001028" />
<Key Name="name" Value="rockwallbig" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rockwallbig.jp2" />
</Section>
<Section Name="roof01 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001029" />
<Key Name="name" Value="roof01" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="roof01.jp2" />
</Section>
<Section Name="rooftiles1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001030" />
<Key Name="name" Value="rooftiles1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rooftiles1.jp2" />
</Section>
<Section Name="rooftiles2_peach Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001031" />
<Key Name="name" Value="rooftiles2_peach" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rooftiles2_peach.jp2" />
</Section>
<Section Name="rooftiles2_roy Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001032" />
<Key Name="name" Value="rooftiles2_roy" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rooftiles2_roy.jp2" />
</Section>
<Section Name="saguaro_8m Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001033" />
<Key Name="name" Value="saguaro_8m" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="saguaro_8m.jp2" />
</Section>
<Section Name="seawater Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001034" />
<Key Name="name" Value="seawater" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="seawater.jp2" />
</Section>
<Section Name="snow1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001035" />
<Key Name="name" Value="snow1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="snow1.jp2" />
</Section>
<Section Name="steel Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001036" />
<Key Name="name" Value="steel" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="steel.jp2" />
</Section>
<Section Name="stone1wall Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001037" />
<Key Name="name" Value="stone1wall" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="stone1wall.jp2" />
</Section>
<Section Name="stonetile Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001038" />
<Key Name="name" Value="stonetile" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="stonetile.jp2" />
</Section>
<Section Name="street2 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001039" />
<Key Name="name" Value="street2" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="street2.jp2" />
</Section>
<Section Name="thatch Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001040" />
<Key Name="name" Value="thatch" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="thatch.jp2" />
</Section>
<Section Name="water1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001041" />
<Key Name="name" Value="water1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="water1.jp2" />
</Section>
<Section Name="water3 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001042" />
<Key Name="name" Value="water3" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="water3.jp2" />
</Section>
<Section Name="Sea">
<Key Name="assetID" Value="2bfd3884-7e27-69b9-ba3a-3e673f680004" />
<Key Name="name" Value="Sea" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="water3.jp2" />
</Section>
<Section Name="wood1 Texture">
<Key Name="assetID" Value="00000000-0000-2222-3333-100000001043" />
<Key Name="name" Value="wood1" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="wood1.jp2" />
</Section>
<Section Name="LOLCAT">
<Key Name="assetID" Value="13371337-1337-1337-1337-133713371337" />
<Key Name="name" Value="lolcat in ur assets" />
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="peaches.jp2" />
</Section>
<!-- Copied from hardcoded values -->
<Section Name="Bricks">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000001"/>
<Key Name="name" Value="Bricks"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="bricks.jp2"/>
</Section>
<Section Name="Plywood">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000002"/>
<Key Name="name" Value="Plywood"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="plywood.jp2"/>
</Section>
<Section Name="Rocks">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000003"/>
<Key Name="name" Value="Rocks"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="rocks.jp2"/>
</Section>
<Section Name="Granite">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000004"/>
<Key Name="name" Value="Granite"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="granite.jp2"/>
</Section>
<Section Name="Hardwood">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000005"/>
<Key Name="name" Value="Hardwood"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="hardwood.jp2"/>
</Section>
<Section Name="Prim Base Texture">
<Key Name="assetID" Value="00000000-0000-1111-5005-000000000005"/>
<Key Name="name" Value="Prim Base Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="plywood.jp2"/>
</Section>
<Section Name="Map Base Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000006"/>
<Key Name="name" Value="Map Base Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="map_base.jp2"/>
</Section>
<Section Name="Map Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000007"/>
<Key Name="name" Value="Map Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="map1.jp2"/>
</Section>
<Section Name="Female Body Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000010"/>
<Key Name="name" Value="Female Body Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="femalebody.jp2"/>
</Section>
<Section Name="Female Bottom Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000011"/>
<Key Name="name" Value="Female Bottom Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="femalebottom.jp2"/>
</Section>
<Section Name="Female Face Texture">
<Key Name="assetID" Value="00000000-0000-1111-9999-000000000012"/>
<Key Name="name" Value="Female Face Texture"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="femaleface.jp2"/>
</Section>
<Section Name="Skin">
<Key Name="assetID" Value="77c41e39-38f9-f75a-024e-585989bbabbb"/>
<Key Name="name" Value="Skin"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="base_skin.dat"/>
</Section>
<Section Name="Skin">
<Key Name="assetID" Value="77c41e39-38f9-f75a-024e-585989bbabbc"/>
<Key Name="name" Value="Jim Skin"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="jim_skin.dat"/>
</Section>
<Section Name="Skin">
<Key Name="assetID" Value="77c41e39-38f9-f75a-024e-585989bbabbd"/>
<Key Name="name" Value="Goblin Skin"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="goblin_skin.dat"/>
</Section>
<Section Name="Shape">
<Key Name="assetID" Value="66c41e39-38f9-f75a-024e-585989bfab73"/>
<Key Name="name" Value="Shape"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="base_shape.dat"/>
</Section>
<Section Name="Shape">
<Key Name="assetID" Value="66c41e39-38f9-f75a-024e-585989bfab74"/>
<Key Name="name" Value="Jim Shape"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="jim_shape.dat"/>
</Section>
<Section Name="Shape">
<Key Name="assetID" Value="66c41e39-38f9-f75a-024e-585989bfab75"/>
<Key Name="name" Value="Little Goblin Shape"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="little_goblin_shape.dat"/>
</Section>
<Section Name="Shirt">
<Key Name="assetID" Value="00000000-38f9-1111-024e-222222111110"/>
<Key Name="name" Value="Shirt"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="newshirt.dat"/>
</Section>
<Section Name="Pants">
<Key Name="assetID" Value="00000000-38f9-1111-024e-222222111120"/>
<Key Name="name" Value="Pants"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="newpants.dat"/>
</Section>
<Section Name="Moon">
<Key Name="assetID" Value="fc4b9f0b-d008-45c6-96a4-01dd947ac621"/>
<Key Name="name" Value="Moon"/>
<Key Name="assetType" Value="0" />
<Key Name="inventoryType" Value="0" />
<Key Name="fileName" Value="moon.jp2"/>
</Section>
</Nini>

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
[mysqlconnection]
hostname=localhost
database=database
username=username
password=password
pooling=false
[mysqlconnection]
hostname=localhost
database=database
username=username
password=password
pooling=false
port=3306

View File

@ -1 +1 @@
backup
backup