set svn:eol-style
parent
33ac0653a3
commit
db174dfa20
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
|
@ -1 +1 @@
|
|||
backup
|
||||
backup
|
||||
|
|
Loading…
Reference in New Issue