Add ConvexDecompositionDotNet

dsg
Robert Adams 2011-05-19 13:36:01 -07:00
parent 973d0fcdaa
commit 95ce0caa76
23 changed files with 5667 additions and 0 deletions

View File

@ -0,0 +1,341 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class Wpoint
{
public float3 mPoint;
public float mWeight;
public Wpoint(float3 p, float w)
{
mPoint = p;
mWeight = w;
}
}
public class CTri
{
private const int WSCALE = 4;
public float3 mP1;
public float3 mP2;
public float3 mP3;
public float3 mNear1;
public float3 mNear2;
public float3 mNear3;
public float3 mNormal;
public float mPlaneD;
public float mConcavity;
public float mC1;
public float mC2;
public float mC3;
public int mI1;
public int mI2;
public int mI3;
public int mProcessed; // already been added...
public CTri(float3 p1, float3 p2, float3 p3, int i1, int i2, int i3)
{
mProcessed = 0;
mI1 = i1;
mI2 = i2;
mI3 = i3;
mP1 = new float3(p1);
mP2 = new float3(p2);
mP3 = new float3(p3);
mNear1 = new float3();
mNear2 = new float3();
mNear3 = new float3();
mNormal = new float3();
mPlaneD = mNormal.ComputePlane(mP1, mP2, mP3);
}
public float Facing(CTri t)
{
return float3.dot(mNormal, t.mNormal);
}
public bool clip(float3 start, ref float3 end)
{
float3 sect = new float3();
bool hit = lineIntersectsTriangle(start, end, mP1, mP2, mP3, ref sect);
if (hit)
end = sect;
return hit;
}
public bool Concave(float3 p, ref float distance, ref float3 n)
{
n.NearestPointInTriangle(p, mP1, mP2, mP3);
distance = p.Distance(n);
return true;
}
public void addTri(int[] indices, int i1, int i2, int i3, ref int tcount)
{
indices[tcount * 3 + 0] = i1;
indices[tcount * 3 + 1] = i2;
indices[tcount * 3 + 2] = i3;
tcount++;
}
public float getVolume()
{
int[] indices = new int[8 * 3];
int tcount = 0;
addTri(indices, 0, 1, 2, ref tcount);
addTri(indices, 3, 4, 5, ref tcount);
addTri(indices, 0, 3, 4, ref tcount);
addTri(indices, 0, 4, 1, ref tcount);
addTri(indices, 1, 4, 5, ref tcount);
addTri(indices, 1, 5, 2, ref tcount);
addTri(indices, 0, 3, 5, ref tcount);
addTri(indices, 0, 5, 2, ref tcount);
List<float3> vertices = new List<float3> { mP1, mP2, mP3, mNear1, mNear2, mNear3 };
List<int> indexList = new List<int>(indices);
float v = Concavity.computeMeshVolume(vertices, indexList);
return v;
}
public float raySect(float3 p, float3 dir, ref float3 sect)
{
float4 plane = new float4();
plane.x = mNormal.x;
plane.y = mNormal.y;
plane.z = mNormal.z;
plane.w = mPlaneD;
float3 dest = p + dir * 100000f;
intersect(p, dest, ref sect, plane);
return sect.Distance(p); // return the intersection distance
}
public float planeDistance(float3 p)
{
float4 plane = new float4();
plane.x = mNormal.x;
plane.y = mNormal.y;
plane.z = mNormal.z;
plane.w = mPlaneD;
return DistToPt(p, plane);
}
public bool samePlane(CTri t)
{
const float THRESH = 0.001f;
float dd = Math.Abs(t.mPlaneD - mPlaneD);
if (dd > THRESH)
return false;
dd = Math.Abs(t.mNormal.x - mNormal.x);
if (dd > THRESH)
return false;
dd = Math.Abs(t.mNormal.y - mNormal.y);
if (dd > THRESH)
return false;
dd = Math.Abs(t.mNormal.z - mNormal.z);
if (dd > THRESH)
return false;
return true;
}
public bool hasIndex(int i)
{
if (i == mI1 || i == mI2 || i == mI3)
return true;
return false;
}
public bool sharesEdge(CTri t)
{
bool ret = false;
uint count = 0;
if (t.hasIndex(mI1))
count++;
if (t.hasIndex(mI2))
count++;
if (t.hasIndex(mI3))
count++;
if (count >= 2)
ret = true;
return ret;
}
public float area()
{
float a = mConcavity * mP1.Area(mP2, mP3);
return a;
}
public void addWeighted(List<Wpoint> list)
{
Wpoint p1 = new Wpoint(mP1, mC1);
Wpoint p2 = new Wpoint(mP2, mC2);
Wpoint p3 = new Wpoint(mP3, mC3);
float3 d1 = mNear1 - mP1;
float3 d2 = mNear2 - mP2;
float3 d3 = mNear3 - mP3;
d1 *= WSCALE;
d2 *= WSCALE;
d3 *= WSCALE;
d1 = d1 + mP1;
d2 = d2 + mP2;
d3 = d3 + mP3;
Wpoint p4 = new Wpoint(d1, mC1);
Wpoint p5 = new Wpoint(d2, mC2);
Wpoint p6 = new Wpoint(d3, mC3);
list.Add(p1);
list.Add(p2);
list.Add(p3);
list.Add(p4);
list.Add(p5);
list.Add(p6);
}
private static float DistToPt(float3 p, float4 plane)
{
float x = p.x;
float y = p.y;
float z = p.z;
float d = x*plane.x + y*plane.y + z*plane.z + plane.w;
return d;
}
private static void intersect(float3 p1, float3 p2, ref float3 split, float4 plane)
{
float dp1 = DistToPt(p1, plane);
float3 dir = new float3();
dir.x = p2[0] - p1[0];
dir.y = p2[1] - p1[1];
dir.z = p2[2] - p1[2];
float dot1 = dir[0] * plane[0] + dir[1] * plane[1] + dir[2] * plane[2];
float dot2 = dp1 - plane[3];
float t = -(plane[3] + dot2) / dot1;
split.x = (dir[0] * t) + p1[0];
split.y = (dir[1] * t) + p1[1];
split.z = (dir[2] * t) + p1[2];
}
private static bool rayIntersectsTriangle(float3 p, float3 d, float3 v0, float3 v1, float3 v2, out float t)
{
t = 0f;
float3 e1, e2, h, s, q;
float a, f, u, v;
e1 = v1 - v0;
e2 = v2 - v0;
h = float3.cross(d, e2);
a = float3.dot(e1, h);
if (a > -0.00001f && a < 0.00001f)
return false;
f = 1f / a;
s = p - v0;
u = f * float3.dot(s, h);
if (u < 0.0f || u > 1.0f)
return false;
q = float3.cross(s, e1);
v = f * float3.dot(d, q);
if (v < 0.0f || u + v > 1.0f)
return false;
// at this stage we can compute t to find out where
// the intersection point is on the line
t = f * float3.dot(e2, q);
if (t > 0f) // ray intersection
return true;
else // this means that there is a line intersection but not a ray intersection
return false;
}
private static bool lineIntersectsTriangle(float3 rayStart, float3 rayEnd, float3 p1, float3 p2, float3 p3, ref float3 sect)
{
float3 dir = rayEnd - rayStart;
float d = (float)Math.Sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
float r = 1.0f / d;
dir *= r;
float t;
bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, out t);
if (ret)
{
if (t > d)
{
sect.x = rayStart.x + dir.x * t;
sect.y = rayStart.y + dir.y * t;
sect.z = rayStart.z + dir.z * t;
}
else
{
ret = false;
}
}
return ret;
}
}
}

View File

@ -0,0 +1,233 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public static class Concavity
{
// compute's how 'concave' this object is and returns the total volume of the
// convex hull as well as the volume of the 'concavity' which was found.
public static float computeConcavity(List<float3> vertices, List<int> indices, ref float4 plane, ref float volume)
{
float cret = 0f;
volume = 1f;
HullResult result = new HullResult();
HullDesc desc = new HullDesc();
desc.MaxFaces = 256;
desc.MaxVertices = 256;
desc.SetHullFlag(HullFlag.QF_TRIANGLES);
desc.Vertices = vertices;
HullError ret = HullUtils.CreateConvexHull(desc, ref result);
if (ret == HullError.QE_OK)
{
volume = computeMeshVolume2(result.OutputVertices, result.Indices);
// ok..now..for each triangle on the original mesh..
// we extrude the points to the nearest point on the hull.
List<CTri> tris = new List<CTri>();
for (int i = 0; i < result.Indices.Count / 3; i++)
{
int i1 = result.Indices[i * 3 + 0];
int i2 = result.Indices[i * 3 + 1];
int i3 = result.Indices[i * 3 + 2];
float3 p1 = result.OutputVertices[i1];
float3 p2 = result.OutputVertices[i2];
float3 p3 = result.OutputVertices[i3];
CTri t = new CTri(p1, p2, p3, i1, i2, i3);
tris.Add(t);
}
// we have not pre-computed the plane equation for each triangle in the convex hull..
float totalVolume = 0;
List<CTri> ftris = new List<CTri>(); // 'feature' triangles.
List<CTri> input_mesh = new List<CTri>();
for (int i = 0; i < indices.Count / 3; i++)
{
int i1 = indices[i * 3 + 0];
int i2 = indices[i * 3 + 1];
int i3 = indices[i * 3 + 2];
float3 p1 = vertices[i1];
float3 p2 = vertices[i2];
float3 p3 = vertices[i3];
CTri t = new CTri(p1, p2, p3, i1, i2, i3);
input_mesh.Add(t);
}
for (int i = 0; i < indices.Count / 3; i++)
{
int i1 = indices[i * 3 + 0];
int i2 = indices[i * 3 + 1];
int i3 = indices[i * 3 + 2];
float3 p1 = vertices[i1];
float3 p2 = vertices[i2];
float3 p3 = vertices[i3];
CTri t = new CTri(p1, p2, p3, i1, i2, i3);
featureMatch(t, tris, input_mesh);
if (t.mConcavity > 0.05f)
{
float v = t.getVolume();
totalVolume += v;
ftris.Add(t);
}
}
SplitPlane.computeSplitPlane(vertices, indices, ref plane);
cret = totalVolume;
}
return cret;
}
public static bool featureMatch(CTri m, List<CTri> tris, List<CTri> input_mesh)
{
bool ret = false;
float neardot = 0.707f;
m.mConcavity = 0;
for (int i = 0; i < tris.Count; i++)
{
CTri t = tris[i];
if (t.samePlane(m))
{
ret = false;
break;
}
float dot = float3.dot(t.mNormal, m.mNormal);
if (dot > neardot)
{
float d1 = t.planeDistance(m.mP1);
float d2 = t.planeDistance(m.mP2);
float d3 = t.planeDistance(m.mP3);
if (d1 > 0.001f || d2 > 0.001f || d3 > 0.001f) // can't be near coplaner!
{
neardot = dot;
t.raySect(m.mP1, m.mNormal, ref m.mNear1);
t.raySect(m.mP2, m.mNormal, ref m.mNear2);
t.raySect(m.mP3, m.mNormal, ref m.mNear3);
ret = true;
}
}
}
if (ret)
{
m.mC1 = m.mP1.Distance(m.mNear1);
m.mC2 = m.mP2.Distance(m.mNear2);
m.mC3 = m.mP3.Distance(m.mNear3);
m.mConcavity = m.mC1;
if (m.mC2 > m.mConcavity)
m.mConcavity = m.mC2;
if (m.mC3 > m.mConcavity)
m.mConcavity = m.mC3;
}
return ret;
}
private static float det(float3 p1, float3 p2, float3 p3)
{
return p1.x * p2.y * p3.z + p2.x * p3.y * p1.z + p3.x * p1.y * p2.z - p1.x * p3.y * p2.z - p2.x * p1.y * p3.z - p3.x * p2.y * p1.z;
}
public static float computeMeshVolume(List<float3> vertices, List<int> indices)
{
float volume = 0f;
for (int i = 0; i < indices.Count / 3; i++)
{
float3 p1 = vertices[indices[i * 3 + 0]];
float3 p2 = vertices[indices[i * 3 + 1]];
float3 p3 = vertices[indices[i * 3 + 2]];
volume += det(p1, p2, p3); // compute the volume of the tetrahedran relative to the origin.
}
volume *= (1.0f / 6.0f);
if (volume < 0f)
return -volume;
return volume;
}
public static float computeMeshVolume2(List<float3> vertices, List<int> indices)
{
float volume = 0f;
float3 p0 = vertices[0];
for (int i = 0; i < indices.Count / 3; i++)
{
float3 p1 = vertices[indices[i * 3 + 0]];
float3 p2 = vertices[indices[i * 3 + 1]];
float3 p3 = vertices[indices[i * 3 + 2]];
volume += tetVolume(p0, p1, p2, p3); // compute the volume of the tetrahedron relative to the root vertice
}
return volume * (1.0f / 6.0f);
}
private static float tetVolume(float3 p0, float3 p1, float3 p2, float3 p3)
{
float3 a = p1 - p0;
float3 b = p2 - p0;
float3 c = p3 - p0;
float3 cross = float3.cross(b, c);
float volume = float3.dot(a, cross);
if (volume < 0f)
return -volume;
return volume;
}
}
}

View File

@ -0,0 +1,411 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class DecompDesc
{
public List<float3> mVertices;
public List<int> mIndices;
// options
public uint mDepth; // depth to split, a maximum of 10, generally not over 7.
public float mCpercent; // the concavity threshold percentage. 0=20 is reasonable.
public float mPpercent; // the percentage volume conservation threshold to collapse hulls. 0-30 is reasonable.
// hull output limits.
public uint mMaxVertices; // maximum number of vertices in the output hull. Recommended 32 or less.
public float mSkinWidth; // a skin width to apply to the output hulls.
public ConvexDecompositionCallback mCallback; // the interface to receive back the results.
public DecompDesc()
{
mDepth = 5;
mCpercent = 5;
mPpercent = 5;
mMaxVertices = 32;
}
}
public class CHull
{
public float[] mMin = new float[3];
public float[] mMax = new float[3];
public float mVolume;
public float mDiagonal;
public ConvexResult mResult;
public CHull(ConvexResult result)
{
mResult = new ConvexResult(result);
mVolume = Concavity.computeMeshVolume(result.HullVertices, result.HullIndices);
mDiagonal = getBoundingRegion(result.HullVertices, mMin, mMax);
float dx = mMax[0] - mMin[0];
float dy = mMax[1] - mMin[1];
float dz = mMax[2] - mMin[2];
dx *= 0.1f; // inflate 1/10th on each edge
dy *= 0.1f; // inflate 1/10th on each edge
dz *= 0.1f; // inflate 1/10th on each edge
mMin[0] -= dx;
mMin[1] -= dy;
mMin[2] -= dz;
mMax[0] += dx;
mMax[1] += dy;
mMax[2] += dz;
}
public void Dispose()
{
mResult = null;
}
public bool overlap(CHull h)
{
return overlapAABB(mMin, mMax, h.mMin, h.mMax);
}
// returns the d1Giagonal distance
private static float getBoundingRegion(List<float3> points, float[] bmin, float[] bmax)
{
float3 first = points[0];
bmin[0] = first.x;
bmin[1] = first.y;
bmin[2] = first.z;
bmax[0] = first.x;
bmax[1] = first.y;
bmax[2] = first.z;
for (int i = 1; i < points.Count; i++)
{
float3 p = points[i];
if (p[0] < bmin[0]) bmin[0] = p[0];
if (p[1] < bmin[1]) bmin[1] = p[1];
if (p[2] < bmin[2]) bmin[2] = p[2];
if (p[0] > bmax[0]) bmax[0] = p[0];
if (p[1] > bmax[1]) bmax[1] = p[1];
if (p[2] > bmax[2]) bmax[2] = p[2];
}
float dx = bmax[0] - bmin[0];
float dy = bmax[1] - bmin[1];
float dz = bmax[2] - bmin[2];
return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
}
// return true if the two AABB's overlap.
private static bool overlapAABB(float[] bmin1, float[] bmax1, float[] bmin2, float[] bmax2)
{
if (bmax2[0] < bmin1[0]) return false; // if the maximum is less than our minimum on any axis
if (bmax2[1] < bmin1[1]) return false;
if (bmax2[2] < bmin1[2]) return false;
if (bmin2[0] > bmax1[0]) return false; // if the minimum is greater than our maximum on any axis
if (bmin2[1] > bmax1[1]) return false; // if the minimum is greater than our maximum on any axis
if (bmin2[2] > bmax1[2]) return false; // if the minimum is greater than our maximum on any axis
return true; // the extents overlap
}
}
public class ConvexBuilder
{
public List<CHull> mChulls = new List<CHull>();
private ConvexDecompositionCallback mCallback;
private int MAXDEPTH = 8;
private float CONCAVE_PERCENT = 1f;
private float MERGE_PERCENT = 2f;
public ConvexBuilder(ConvexDecompositionCallback callback)
{
mCallback = callback;
}
public void Dispose()
{
int i;
for (i = 0; i < mChulls.Count; i++)
{
CHull cr = mChulls[i];
cr.Dispose();
}
}
public bool isDuplicate(uint i1, uint i2, uint i3, uint ci1, uint ci2, uint ci3)
{
uint dcount = 0;
Debug.Assert(i1 != i2 && i1 != i3 && i2 != i3);
Debug.Assert(ci1 != ci2 && ci1 != ci3 && ci2 != ci3);
if (i1 == ci1 || i1 == ci2 || i1 == ci3)
dcount++;
if (i2 == ci1 || i2 == ci2 || i2 == ci3)
dcount++;
if (i3 == ci1 || i3 == ci2 || i3 == ci3)
dcount++;
return dcount == 3;
}
public void getMesh(ConvexResult cr, VertexPool vc, List<int> indices)
{
List<int> src = cr.HullIndices;
for (int i = 0; i < src.Count / 3; i++)
{
int i1 = src[i * 3 + 0];
int i2 = src[i * 3 + 1];
int i3 = src[i * 3 + 2];
float3 p1 = cr.HullVertices[i1];
float3 p2 = cr.HullVertices[i2];
float3 p3 = cr.HullVertices[i3];
i1 = vc.getIndex(p1);
i2 = vc.getIndex(p2);
i3 = vc.getIndex(p3);
}
}
public CHull canMerge(CHull a, CHull b)
{
if (!a.overlap(b)) // if their AABB's (with a little slop) don't overlap, then return.
return null;
CHull ret = null;
// ok..we are going to combine both meshes into a single mesh
// and then we are going to compute the concavity...
VertexPool vc = new VertexPool();
List<int> indices = new List<int>();
getMesh(a.mResult, vc, indices);
getMesh(b.mResult, vc, indices);
int vcount = vc.GetSize();
List<float3> vertices = vc.GetVertices();
int tcount = indices.Count / 3;
//don't do anything if hull is empty
if (tcount == 0)
{
vc.Clear();
return null;
}
HullResult hresult = new HullResult();
HullDesc desc = new HullDesc();
desc.SetHullFlag(HullFlag.QF_TRIANGLES);
desc.Vertices = vertices;
HullError hret = HullUtils.CreateConvexHull(desc, ref hresult);
if (hret == HullError.QE_OK)
{
float combineVolume = Concavity.computeMeshVolume(hresult.OutputVertices, hresult.Indices);
float sumVolume = a.mVolume + b.mVolume;
float percent = (sumVolume * 100) / combineVolume;
if (percent >= (100.0f - MERGE_PERCENT))
{
ConvexResult cr = new ConvexResult(hresult.OutputVertices, hresult.Indices);
ret = new CHull(cr);
}
}
vc.Clear();
return ret;
}
public bool combineHulls()
{
bool combine = false;
sortChulls(mChulls); // sort the convex hulls, largest volume to least...
List<CHull> output = new List<CHull>(); // the output hulls...
int i;
for (i = 0; i < mChulls.Count && !combine; ++i)
{
CHull cr = mChulls[i];
int j;
for (j = 0; j < mChulls.Count; j++)
{
CHull match = mChulls[j];
if (cr != match) // don't try to merge a hull with itself, that be stoopid
{
CHull merge = canMerge(cr, match); // if we can merge these two....
if (merge != null)
{
output.Add(merge);
++i;
while (i != mChulls.Count)
{
CHull cr2 = mChulls[i];
if (cr2 != match)
{
output.Add(cr2);
}
i++;
}
cr.Dispose();
match.Dispose();
combine = true;
break;
}
}
}
if (combine)
{
break;
}
else
{
output.Add(cr);
}
}
if (combine)
{
mChulls.Clear();
mChulls = output;
output.Clear();
}
return combine;
}
public int process(DecompDesc desc)
{
int ret = 0;
MAXDEPTH = (int)desc.mDepth;
CONCAVE_PERCENT = desc.mCpercent;
MERGE_PERCENT = desc.mPpercent;
ConvexDecomposition.calcConvexDecomposition(desc.mVertices, desc.mIndices, ConvexDecompResult, 0f, 0, MAXDEPTH, CONCAVE_PERCENT, MERGE_PERCENT);
while (combineHulls()) // keep combinging hulls until I can't combine any more...
;
int i;
for (i = 0; i < mChulls.Count; i++)
{
CHull cr = mChulls[i];
// before we hand it back to the application, we need to regenerate the hull based on the
// limits given by the user.
ConvexResult c = cr.mResult; // the high resolution hull...
HullResult result = new HullResult();
HullDesc hdesc = new HullDesc();
hdesc.SetHullFlag(HullFlag.QF_TRIANGLES);
hdesc.Vertices = c.HullVertices;
hdesc.MaxVertices = desc.mMaxVertices; // maximum number of vertices allowed in the output
if (desc.mSkinWidth != 0f)
{
hdesc.SkinWidth = desc.mSkinWidth;
hdesc.SetHullFlag(HullFlag.QF_SKIN_WIDTH); // do skin width computation.
}
HullError ret2 = HullUtils.CreateConvexHull(hdesc, ref result);
if (ret2 == HullError.QE_OK)
{
ConvexResult r = new ConvexResult(result.OutputVertices, result.Indices);
r.mHullVolume = Concavity.computeMeshVolume(result.OutputVertices, result.Indices); // the volume of the hull.
// compute the best fit OBB
//computeBestFitOBB(result.mNumOutputVertices, result.mOutputVertices, sizeof(float) * 3, r.mOBBSides, r.mOBBTransform);
//r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] * r.mOBBSides[2]; // compute the OBB volume.
//fm_getTranslation(r.mOBBTransform, r.mOBBCenter); // get the translation component of the 4x4 matrix.
//fm_matrixToQuat(r.mOBBTransform, r.mOBBOrientation); // extract the orientation as a quaternion.
//r.mSphereRadius = computeBoundingSphere(result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter);
//r.mSphereVolume = fm_sphereVolume(r.mSphereRadius);
mCallback(r);
}
result = null;
cr.Dispose();
}
ret = mChulls.Count;
mChulls.Clear();
return ret;
}
public void ConvexDecompResult(ConvexResult result)
{
CHull ch = new CHull(result);
mChulls.Add(ch);
}
public void sortChulls(List<CHull> hulls)
{
hulls.Sort(delegate(CHull a, CHull b) { return a.mVolume.CompareTo(b.mVolume); });
}
}
}

View File

@ -0,0 +1,200 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public delegate void ConvexDecompositionCallback(ConvexResult result);
public class FaceTri
{
public float3 P1;
public float3 P2;
public float3 P3;
public FaceTri() { }
public FaceTri(List<float3> vertices, int i1, int i2, int i3)
{
P1 = new float3(vertices[i1]);
P2 = new float3(vertices[i2]);
P3 = new float3(vertices[i3]);
}
}
public static class ConvexDecomposition
{
private static void addTri(VertexPool vl, List<int> list, float3 p1, float3 p2, float3 p3)
{
int i1 = vl.getIndex(p1);
int i2 = vl.getIndex(p2);
int i3 = vl.getIndex(p3);
// do *not* process degenerate triangles!
if ( i1 != i2 && i1 != i3 && i2 != i3 )
{
list.Add(i1);
list.Add(i2);
list.Add(i3);
}
}
public static void calcConvexDecomposition(List<float3> vertices, List<int> indices, ConvexDecompositionCallback callback, float masterVolume, int depth,
int maxDepth, float concavePercent, float mergePercent)
{
float4 plane = new float4();
bool split = false;
if (depth < maxDepth)
{
float volume = 0f;
float c = Concavity.computeConcavity(vertices, indices, ref plane, ref volume);
if (depth == 0)
{
masterVolume = volume;
}
float percent = (c * 100.0f) / masterVolume;
if (percent > concavePercent) // if great than 5% of the total volume is concave, go ahead and keep splitting.
{
split = true;
}
}
if (depth >= maxDepth || !split)
{
HullResult result = new HullResult();
HullDesc desc = new HullDesc();
desc.SetHullFlag(HullFlag.QF_TRIANGLES);
desc.Vertices = vertices;
HullError ret = HullUtils.CreateConvexHull(desc, ref result);
if (ret == HullError.QE_OK)
{
ConvexResult r = new ConvexResult(result.OutputVertices, result.Indices);
callback(r);
}
return;
}
List<int> ifront = new List<int>();
List<int> iback = new List<int>();
VertexPool vfront = new VertexPool();
VertexPool vback = new VertexPool();
// ok..now we are going to 'split' all of the input triangles against this plane!
for (int i = 0; i < indices.Count / 3; i++)
{
int i1 = indices[i * 3 + 0];
int i2 = indices[i * 3 + 1];
int i3 = indices[i * 3 + 2];
FaceTri t = new FaceTri(vertices, i1, i2, i3);
float3[] front = new float3[4];
float3[] back = new float3[4];
int fcount = 0;
int bcount = 0;
PlaneTriResult result = PlaneTri.planeTriIntersection(plane, t, 0.00001f, ref front, out fcount, ref back, out bcount);
if (fcount > 4 || bcount > 4)
{
result = PlaneTri.planeTriIntersection(plane, t, 0.00001f, ref front, out fcount, ref back, out bcount);
}
switch (result)
{
case PlaneTriResult.PTR_FRONT:
Debug.Assert(fcount == 3);
addTri(vfront, ifront, front[0], front[1], front[2]);
break;
case PlaneTriResult.PTR_BACK:
Debug.Assert(bcount == 3);
addTri(vback, iback, back[0], back[1], back[2]);
break;
case PlaneTriResult.PTR_SPLIT:
Debug.Assert(fcount >= 3 && fcount <= 4);
Debug.Assert(bcount >= 3 && bcount <= 4);
addTri(vfront, ifront, front[0], front[1], front[2]);
addTri(vback, iback, back[0], back[1], back[2]);
if (fcount == 4)
{
addTri(vfront, ifront, front[0], front[2], front[3]);
}
if (bcount == 4)
{
addTri(vback, iback, back[0], back[2], back[3]);
}
break;
}
}
// ok... here we recursively call
if (ifront.Count > 0)
{
int vcount = vfront.GetSize();
List<float3> vertices2 = vfront.GetVertices();
for (int i = 0; i < vertices2.Count; i++)
vertices2[i] = new float3(vertices2[i]);
int tcount = ifront.Count / 3;
calcConvexDecomposition(vertices2, ifront, callback, masterVolume, depth + 1, maxDepth, concavePercent, mergePercent);
}
ifront.Clear();
vfront.Clear();
if (iback.Count > 0)
{
int vcount = vback.GetSize();
List<float3> vertices2 = vback.GetVertices();
int tcount = iback.Count / 3;
calcConvexDecomposition(vertices2, iback, callback, masterVolume, depth + 1, maxDepth, concavePercent, mergePercent);
}
iback.Clear();
vback.Clear();
}
}
}

View File

@ -0,0 +1,74 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class ConvexResult
{
public List<float3> HullVertices;
public List<int> HullIndices;
public float mHullVolume; // the volume of the convex hull.
//public float[] OBBSides = new float[3]; // the width, height and breadth of the best fit OBB
//public float[] OBBCenter = new float[3]; // the center of the OBB
//public float[] OBBOrientation = new float[4]; // the quaternion rotation of the OBB.
//public float[] OBBTransform = new float[16]; // the 4x4 transform of the OBB.
//public float OBBVolume; // the volume of the OBB
//public float SphereRadius; // radius and center of best fit sphere
//public float[] SphereCenter = new float[3];
//public float SphereVolume; // volume of the best fit sphere
public ConvexResult()
{
HullVertices = new List<float3>();
HullIndices = new List<int>();
}
public ConvexResult(List<float3> hvertices, List<int> hindices)
{
HullVertices = hvertices;
HullIndices = hindices;
}
public ConvexResult(ConvexResult r)
{
HullVertices = new List<float3>(r.HullVertices);
HullIndices = new List<int>(r.HullIndices);
}
public void Dispose()
{
HullVertices = null;
HullIndices = null;
}
}
}

View File

@ -0,0 +1,171 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class HullResult
{
public bool Polygons = true; // true if indices represents polygons, false indices are triangles
public List<float3> OutputVertices = new List<float3>();
public List<int> Indices;
// If triangles, then indices are array indexes into the vertex list.
// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
}
public class PHullResult
{
public List<float3> Vertices = new List<float3>();
public List<int> Indices = new List<int>();
}
[Flags]
public enum HullFlag : int
{
QF_DEFAULT = 0,
QF_TRIANGLES = (1 << 0), // report results as triangles, not polygons.
QF_SKIN_WIDTH = (1 << 2) // extrude hull based on this skin width
}
public enum HullError : int
{
QE_OK, // success!
QE_FAIL // failed.
}
public class HullDesc
{
public HullFlag Flags; // flags to use when generating the convex hull.
public List<float3> Vertices;
public float NormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
public float SkinWidth;
public uint MaxVertices; // maximum number of vertices to be considered for the hull!
public uint MaxFaces;
public HullDesc()
{
Flags = HullFlag.QF_DEFAULT;
Vertices = new List<float3>();
NormalEpsilon = 0.001f;
MaxVertices = 4096;
MaxFaces = 4096;
SkinWidth = 0.01f;
}
public HullDesc(HullFlag flags, List<float3> vertices)
{
Flags = flags;
Vertices = new List<float3>(vertices);
NormalEpsilon = 0.001f;
MaxVertices = 4096;
MaxFaces = 4096;
SkinWidth = 0.01f;
}
public bool HasHullFlag(HullFlag flag)
{
return (Flags & flag) != 0;
}
public void SetHullFlag(HullFlag flag)
{
Flags |= flag;
}
public void ClearHullFlag(HullFlag flag)
{
Flags &= ~flag;
}
}
public class ConvexH
{
public struct HalfEdge
{
public short ea; // the other half of the edge (index into edges list)
public byte v; // the vertex at the start of this edge (index into vertices list)
public byte p; // the facet on which this edge lies (index into facets list)
public HalfEdge(short _ea, byte _v, byte _p)
{
ea = _ea;
v = _v;
p = _p;
}
public HalfEdge(HalfEdge e)
{
ea = e.ea;
v = e.v;
p = e.p;
}
}
public List<float3> vertices = new List<float3>();
public List<HalfEdge> edges = new List<HalfEdge>();
public List<Plane> facets = new List<Plane>();
public ConvexH(int vertices_size, int edges_size, int facets_size)
{
vertices = new List<float3>(vertices_size);
edges = new List<HalfEdge>(edges_size);
facets = new List<Plane>(facets_size);
}
}
public class VertFlag
{
public byte planetest;
public byte junk;
public byte undermap;
public byte overmap;
}
public class EdgeFlag
{
public byte planetest;
public byte fixes;
public short undermap;
public short overmap;
}
public class PlaneFlag
{
public byte undermap;
public byte overmap;
}
public class Coplanar
{
public ushort ea;
public byte v0;
public byte v1;
}
}

View File

@ -0,0 +1,99 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class HullTriangle : int3
{
public int3 n = new int3();
public int id;
public int vmax;
public float rise;
private List<HullTriangle> tris;
public HullTriangle(int a, int b, int c, List<HullTriangle> tris)
: base(a, b, c)
{
this.tris = tris;
n = new int3(-1, -1, -1);
id = tris.Count;
tris.Add(this);
vmax = -1;
rise = 0.0f;
}
public void Dispose()
{
Debug.Assert(tris[id] == this);
tris[id] = null;
}
public int neib(int a, int b)
{
int i;
for (i = 0; i < 3; i++)
{
int i1 = (i + 1) % 3;
int i2 = (i + 2) % 3;
if ((this)[i] == a && (this)[i1] == b)
return n[i2];
if ((this)[i] == b && (this)[i1] == a)
return n[i2];
}
Debug.Assert(false);
return -1;
}
public void setneib(int a, int b, int value)
{
int i;
for (i = 0; i < 3; i++)
{
int i1 = (i + 1) % 3;
int i2 = (i + 2) % 3;
if ((this)[i] == a && (this)[i1] == b)
{
n[i2] = value;
return;
}
if ((this)[i] == b && (this)[i1] == a)
{
n[i2] = value;
return;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
ConvexDecompositionDotNet
-------------------------
The MIT License
Copyright (c) 2010 Intel Corporation.
All rights reserved.
Based on the convexdecomposition library from
<http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,99 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class Plane
{
public float3 normal = new float3();
public float dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
public Plane(float3 n, float d)
{
normal = new float3(n);
dist = d;
}
public Plane(Plane p)
{
normal = new float3(p.normal);
dist = p.dist;
}
public Plane()
{
dist = 0;
}
public void Transform(float3 position, Quaternion orientation)
{
// Transforms the plane to the space defined by the
// given position/orientation
float3 newNormal = Quaternion.Inverse(orientation) * normal;
float3 origin = Quaternion.Inverse(orientation) * (-normal * dist - position);
normal = newNormal;
dist = -float3.dot(newNormal, origin);
}
public override int GetHashCode()
{
return normal.GetHashCode() ^ dist.GetHashCode();
}
public override bool Equals(object obj)
{
Plane p = obj as Plane;
if (p == null)
return false;
return this == p;
}
public static bool operator ==(Plane a, Plane b)
{
return (a.normal == b.normal && a.dist == b.dist);
}
public static bool operator !=(Plane a, Plane b)
{
return !(a == b);
}
public static Plane PlaneFlip(Plane plane)
{
return new Plane(-plane.normal, -plane.dist);
}
public static bool coplanar(Plane a, Plane b)
{
return (a == b || a == PlaneFlip(b));
}
}
}

View File

@ -0,0 +1,211 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public enum PlaneTriResult : int
{
PTR_FRONT,
PTR_BACK,
PTR_SPLIT
}
public static class PlaneTri
{
private static float DistToPt(float3 p, float4 plane)
{
return p.x * plane.x + p.y * plane.y + p.z * plane.z + plane.w;
}
private static PlaneTriResult getSidePlane(float3 p, float4 plane, float epsilon)
{
float d = DistToPt(p, plane);
if ((d + epsilon) > 0f)
return PlaneTriResult.PTR_FRONT; // it is 'in front' within the provided epsilon value.
return PlaneTriResult.PTR_BACK;
}
private static void add(float3 p, float3[] dest, ref int pcount)
{
dest[pcount++] = new float3(p);
Debug.Assert(pcount <= 4);
}
// assumes that the points are on opposite sides of the plane!
private static void intersect(float3 p1, float3 p2, float3 split, float4 plane)
{
float dp1 = DistToPt(p1, plane);
float[] dir = new float[3];
dir[0] = p2[0] - p1[0];
dir[1] = p2[1] - p1[1];
dir[2] = p2[2] - p1[2];
float dot1 = dir[0] * plane[0] + dir[1] * plane[1] + dir[2] * plane[2];
float dot2 = dp1 - plane[3];
float t = -(plane[3] + dot2) / dot1;
split.x = (dir[0] * t) + p1[0];
split.y = (dir[1] * t) + p1[1];
split.z = (dir[2] * t) + p1[2];
}
public static PlaneTriResult planeTriIntersection(float4 plane, FaceTri triangle, float epsilon, ref float3[] front, out int fcount, ref float3[] back, out int bcount)
{
fcount = 0;
bcount = 0;
// get the three vertices of the triangle.
float3 p1 = triangle.P1;
float3 p2 = triangle.P2;
float3 p3 = triangle.P3;
PlaneTriResult r1 = getSidePlane(p1, plane, epsilon); // compute the side of the plane each vertex is on
PlaneTriResult r2 = getSidePlane(p2, plane, epsilon);
PlaneTriResult r3 = getSidePlane(p3, plane, epsilon);
if (r1 == r2 && r1 == r3) // if all three vertices are on the same side of the plane.
{
if (r1 == PlaneTriResult.PTR_FRONT) // if all three are in front of the plane, then copy to the 'front' output triangle.
{
add(p1, front, ref fcount);
add(p2, front, ref fcount);
add(p3, front, ref fcount);
}
else
{
add(p1, back, ref bcount); // if all three are in 'back' then copy to the 'back' output triangle.
add(p2, back, ref bcount);
add(p3, back, ref bcount);
}
return r1; // if all three points are on the same side of the plane return result
}
// ok.. we need to split the triangle at the plane.
// First test ray segment P1 to P2
if (r1 == r2) // if these are both on the same side...
{
if (r1 == PlaneTriResult.PTR_FRONT)
{
add(p1, front, ref fcount);
add(p2, front, ref fcount);
}
else
{
add(p1, back, ref bcount);
add(p2, back, ref bcount);
}
}
else
{
float3 split = new float3();
intersect(p1, p2, split, plane);
if (r1 == PlaneTriResult.PTR_FRONT)
{
add(p1, front, ref fcount);
add(split, front, ref fcount);
add(split, back, ref bcount);
add(p2, back, ref bcount);
}
else
{
add(p1, back, ref bcount);
add(split, back, ref bcount);
add(split, front, ref fcount);
add(p2, front, ref fcount);
}
}
// Next test ray segment P2 to P3
if (r2 == r3) // if these are both on the same side...
{
if (r3 == PlaneTriResult.PTR_FRONT)
{
add(p3, front, ref fcount);
}
else
{
add(p3, back, ref bcount);
}
}
else
{
float3 split = new float3(); // split the point
intersect(p2, p3, split, plane);
if (r3 == PlaneTriResult.PTR_FRONT)
{
add(split, front, ref fcount);
add(split, back, ref bcount);
add(p3, front, ref fcount);
}
else
{
add(split, front, ref fcount);
add(split, back, ref bcount);
add(p3, back, ref bcount);
}
}
// Next test ray segment P3 to P1
if (r3 != r1) // if these are both on the same side...
{
float3 split = new float3(); // split the point
intersect(p3, p1, split, plane);
if (r1 == PlaneTriResult.PTR_FRONT)
{
add(split, front, ref fcount);
add(split, back, ref bcount);
}
else
{
add(split, front, ref fcount);
add(split, back, ref bcount);
}
}
return PlaneTriResult.PTR_SPLIT;
}
}
}

View File

@ -0,0 +1,209 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class Quaternion : float4
{
public Quaternion()
{
x = y = z = 0.0f;
w = 1.0f;
}
public Quaternion(float3 v, float t)
{
v = float3.normalize(v);
w = (float)Math.Cos(t / 2.0f);
v = v * (float)Math.Sin(t / 2.0f);
x = v.x;
y = v.y;
z = v.z;
}
public Quaternion(float _x, float _y, float _z, float _w)
{
x = _x;
y = _y;
z = _z;
w = _w;
}
public float angle()
{
return (float)Math.Acos(w) * 2.0f;
}
public float3 axis()
{
float3 a = new float3(x, y, z);
if (Math.Abs(angle()) < 0.0000001f)
return new float3(1f, 0f, 0f);
return a * (1 / (float)Math.Sin(angle() / 2.0f));
}
public float3 xdir()
{
return new float3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
}
public float3 ydir()
{
return new float3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
}
public float3 zdir()
{
return new float3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
}
public float3x3 getmatrix()
{
return new float3x3(xdir(), ydir(), zdir());
}
public static implicit operator float3x3(Quaternion q)
{
return q.getmatrix();
}
public static Quaternion operator *(Quaternion a, Quaternion b)
{
Quaternion c = new Quaternion();
c.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;
c.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y;
c.y = a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x;
c.z = a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w;
return c;
}
public static float3 operator *(Quaternion q, float3 v)
{
// The following is equivalent to:
//return (q.getmatrix() * v);
float qx2 = q.x * q.x;
float qy2 = q.y * q.y;
float qz2 = q.z * q.z;
float qxqy = q.x * q.y;
float qxqz = q.x * q.z;
float qxqw = q.x * q.w;
float qyqz = q.y * q.z;
float qyqw = q.y * q.w;
float qzqw = q.z * q.w;
return new float3((1 - 2 * (qy2 + qz2)) * v.x + (2 * (qxqy - qzqw)) * v.y + (2 * (qxqz + qyqw)) * v.z, (2 * (qxqy + qzqw)) * v.x + (1 - 2 * (qx2 + qz2)) * v.y + (2 * (qyqz - qxqw)) * v.z, (2 * (qxqz - qyqw)) * v.x + (2 * (qyqz + qxqw)) * v.y + (1 - 2 * (qx2 + qy2)) * v.z);
}
public static Quaternion operator +(Quaternion a, Quaternion b)
{
return new Quaternion(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
}
public static Quaternion operator *(Quaternion a, float b)
{
return new Quaternion(a.x *b, a.y *b, a.z *b, a.w *b);
}
public static Quaternion normalize(Quaternion a)
{
float m = (float)Math.Sqrt(a.w * a.w + a.x * a.x + a.y * a.y + a.z * a.z);
if (m < 0.000000001f)
{
a.w = 1;
a.x = a.y = a.z = 0;
return a;
}
return a * (1f / m);
}
public static float dot(Quaternion a, Quaternion b)
{
return (a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z);
}
public static Quaternion slerp(Quaternion a, Quaternion b, float interp)
{
if (dot(a, b) < 0.0)
{
a.w = -a.w;
a.x = -a.x;
a.y = -a.y;
a.z = -a.z;
}
float d = dot(a, b);
if (d >= 1.0)
{
return a;
}
float theta = (float)Math.Acos(d);
if (theta == 0.0f)
{
return (a);
}
return a * ((float)Math.Sin(theta - interp * theta) / (float)Math.Sin(theta)) + b * ((float)Math.Sin(interp * theta) / (float)Math.Sin(theta));
}
public static Quaternion Interpolate(Quaternion q0, Quaternion q1, float alpha)
{
return slerp(q0, q1, alpha);
}
public static Quaternion Inverse(Quaternion q)
{
return new Quaternion(-q.x, -q.y, -q.z, q.w);
}
public static Quaternion YawPitchRoll(float yaw, float pitch, float roll)
{
roll *= (3.14159264f / 180.0f);
yaw *= (3.14159264f / 180.0f);
pitch *= (3.14159264f / 180.0f);
return new Quaternion(new float3(0.0f, 0.0f, 1.0f), yaw) * new Quaternion(new float3(1.0f, 0.0f, 0.0f), pitch) * new Quaternion(new float3(0.0f, 1.0f, 0.0f), roll);
}
public static float Yaw(Quaternion q)
{
float3 v = q.ydir();
return (v.y == 0.0 && v.x == 0.0) ? 0.0f : (float)Math.Atan2(-v.x, v.y) * (180.0f / 3.14159264f);
}
public static float Pitch(Quaternion q)
{
float3 v = q.ydir();
return (float)Math.Atan2(v.z, Math.Sqrt(v.x * v.x + v.y * v.y)) * (180.0f / 3.14159264f);
}
public static float Roll(Quaternion q)
{
q = new Quaternion(new float3(0.0f, 0.0f, 1.0f), -Yaw(q) * (3.14159264f / 180.0f)) * q;
q = new Quaternion(new float3(1.0f, 0.0f, 0.0f), -Pitch(q) * (3.14159264f / 180.0f)) * q;
return (float)Math.Atan2(-q.xdir().z, q.xdir().x) * (180.0f / 3.14159264f);
}
}
}

View File

@ -0,0 +1,7 @@
ConvexDecompositionDotNet
=========================
A C# port of the ConvexDecomposition library by John W. Ratcliff and Stan Melax.
The original C++ version is available at <http://codesuppository.googlecode.com/>.
See the blog post at <http://codesuppository.blogspot.com/2006/08/approximate-convexdecomposition.html>
for a thorough explanation of generating convex hulls from concave meshes.

View File

@ -0,0 +1,265 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class Rect3d
{
public float[] mMin = new float[3];
public float[] mMax = new float[3];
public Rect3d()
{
}
public Rect3d(float[] bmin, float[] bmax)
{
mMin[0] = bmin[0];
mMin[1] = bmin[1];
mMin[2] = bmin[2];
mMax[0] = bmax[0];
mMax[1] = bmax[1];
mMax[2] = bmax[2];
}
public void SetMin(float[] bmin)
{
mMin[0] = bmin[0];
mMin[1] = bmin[1];
mMin[2] = bmin[2];
}
public void SetMax(float[] bmax)
{
mMax[0] = bmax[0];
mMax[1] = bmax[1];
mMax[2] = bmax[2];
}
public void SetMin(float x, float y, float z)
{
mMin[0] = x;
mMin[1] = y;
mMin[2] = z;
}
public void SetMax(float x, float y, float z)
{
mMax[0] = x;
mMax[1] = y;
mMax[2] = z;
}
}
public static class SplitPlane
{
public static bool computeSplitPlane(List<float3> vertices, List<int> indices, ref float4 plane)
{
float[] bmin = { Single.MaxValue, Single.MaxValue, Single.MaxValue };
float[] bmax = { Single.MinValue, Single.MinValue, Single.MinValue };
for (int i = 0; i < vertices.Count; i++)
{
float3 p = vertices[i];
if (p[0] < bmin[0])
bmin[0] = p[0];
if (p[1] < bmin[1])
bmin[1] = p[1];
if (p[2] < bmin[2])
bmin[2] = p[2];
if (p[0] > bmax[0])
bmax[0] = p[0];
if (p[1] > bmax[1])
bmax[1] = p[1];
if (p[2] > bmax[2])
bmax[2] = p[2];
}
float dx = bmax[0] - bmin[0];
float dy = bmax[1] - bmin[1];
float dz = bmax[2] - bmin[2];
float laxis = dx;
int axis = 0;
if (dy > dx)
{
axis = 1;
laxis = dy;
}
if (dz > dx && dz > dy)
{
axis = 2;
laxis = dz;
}
float[] p1 = new float[3];
float[] p2 = new float[3];
float[] p3 = new float[3];
p3[0] = p2[0] = p1[0] = bmin[0] + dx * 0.5f;
p3[1] = p2[1] = p1[1] = bmin[1] + dy * 0.5f;
p3[2] = p2[2] = p1[2] = bmin[2] + dz * 0.5f;
Rect3d b = new Rect3d(bmin, bmax);
Rect3d b1 = new Rect3d();
Rect3d b2 = new Rect3d();
splitRect(axis, b, b1, b2, p1);
switch (axis)
{
case 0:
p2[1] = bmin[1];
p2[2] = bmin[2];
if (dz > dy)
{
p3[1] = bmax[1];
p3[2] = bmin[2];
}
else
{
p3[1] = bmin[1];
p3[2] = bmax[2];
}
break;
case 1:
p2[0] = bmin[0];
p2[2] = bmin[2];
if (dx > dz)
{
p3[0] = bmax[0];
p3[2] = bmin[2];
}
else
{
p3[0] = bmin[0];
p3[2] = bmax[2];
}
break;
case 2:
p2[0] = bmin[0];
p2[1] = bmin[1];
if (dx > dy)
{
p3[0] = bmax[0];
p3[1] = bmin[1];
}
else
{
p3[0] = bmin[0];
p3[1] = bmax[1];
}
break;
}
computePlane(p1, p2, p3, plane);
return true;
}
internal static void computePlane(float[] A, float[] B, float[] C, float4 plane)
{
float vx = (B[0] - C[0]);
float vy = (B[1] - C[1]);
float vz = (B[2] - C[2]);
float wx = (A[0] - B[0]);
float wy = (A[1] - B[1]);
float wz = (A[2] - B[2]);
float vw_x = vy * wz - vz * wy;
float vw_y = vz * wx - vx * wz;
float vw_z = vx * wy - vy * wx;
float mag = (float)Math.Sqrt((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
if (mag < 0.000001f)
{
mag = 0;
}
else
{
mag = 1.0f / mag;
}
float x = vw_x * mag;
float y = vw_y * mag;
float z = vw_z * mag;
float D = 0.0f - ((x * A[0]) + (y * A[1]) + (z * A[2]));
plane.x = x;
plane.y = y;
plane.z = z;
plane.w = D;
}
public static void splitRect(int axis, Rect3d source, Rect3d b1, Rect3d b2, float[] midpoint)
{
switch (axis)
{
case 0:
b1.SetMin(source.mMin);
b1.SetMax(midpoint[0], source.mMax[1], source.mMax[2]);
b2.SetMin(midpoint[0], source.mMin[1], source.mMin[2]);
b2.SetMax(source.mMax);
break;
case 1:
b1.SetMin(source.mMin);
b1.SetMax(source.mMax[0], midpoint[1], source.mMax[2]);
b2.SetMin(source.mMin[0], midpoint[1], source.mMin[2]);
b2.SetMax(source.mMax);
break;
case 2:
b1.SetMin(source.mMin);
b1.SetMax(source.mMax[0], source.mMax[1], midpoint[2]);
b2.SetMin(source.mMin[0], source.mMin[1], midpoint[2]);
b2.SetMax(source.mMax);
break;
}
}
}
}

View File

@ -0,0 +1,70 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class VertexPool
{
private List<float3> mVertices = new List<float3>();
private Dictionary<float3, int> mIndices = new Dictionary<float3, int>();
public int getIndex(float3 vtx)
{
int idx;
if (mIndices.TryGetValue(vtx, out idx))
return idx;
idx = mVertices.Count;
mVertices.Add(vtx);
mIndices.Add(vtx, idx);
return idx;
}
public float3 Get(int idx)
{
return mVertices[idx];
}
public int GetSize()
{
return mVertices.Count;
}
public List<float3> GetVertices()
{
return mVertices;
}
public void Clear()
{
mVertices.Clear();
}
}
}

View File

@ -0,0 +1,70 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class float2
{
public float x;
public float y;
public float2()
{
}
public float2(float _x, float _y)
{
x = _x;
y = _y;
}
public float this[int i]
{
get
{
switch (i)
{
case 0: return x;
case 1: return y;
}
throw new ArgumentOutOfRangeException();
}
}
public static float2 operator -(float2 a, float2 b)
{
return new float2(a.x - b.x, a.y - b.y);
}
public static float2 operator +(float2 a, float2 b)
{
return new float2(a.x + b.x, a.y + b.y);
}
}
}

View File

@ -0,0 +1,444 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class float3 : IEquatable<float3>
{
public float x;
public float y;
public float z;
public float3()
{
x = 0;
y = 0;
z = 0;
}
public float3(float _x, float _y, float _z)
{
x = _x;
y = _y;
z = _z;
}
public float3(float3 f)
{
x = f.x;
y = f.y;
z = f.z;
}
public float this[int i]
{
get
{
switch (i)
{
case 0: return x;
case 1: return y;
case 2: return z;
}
throw new ArgumentOutOfRangeException();
}
}
public float Distance(float3 a)
{
float3 d = new float3(a.x - x, a.y - y, a.z - z);
return d.Length();
}
public float Distance2(float3 a)
{
float dx = a.x - x;
float dy = a.y - y;
float dz = a.z - z;
return dx * dx + dy * dy + dz * dz;
}
public float Length()
{
return (float)Math.Sqrt(x * x + y * y + z * z);
}
public float Area(float3 p1, float3 p2)
{
float A = Partial(p1);
A += p1.Partial(p2);
A += p2.Partial(this);
return A * 0.5f;
}
public float Partial(float3 p)
{
return (x * p.y) - (p.x * y);
}
// Given a point and a line (defined by two points), compute the closest point
// in the line. (The line is treated as infinitely long.)
public void NearestPointInLine(float3 point, float3 line0, float3 line1)
{
float3 nearestPoint = new float3();
float3 lineDelta = line1 - line0;
// Handle degenerate lines
if (lineDelta == float3.Zero)
{
nearestPoint = line0;
}
else
{
float delta = float3.dot(point - line0, lineDelta) / float3.dot(lineDelta, lineDelta);
nearestPoint = line0 + lineDelta * delta;
}
this.x = nearestPoint.x;
this.y = nearestPoint.y;
this.z = nearestPoint.z;
}
// Given a point and a line segment (defined by two points), compute the closest point
// in the line. Cap the point at the endpoints of the line segment.
public void NearestPointInLineSegment(float3 point, float3 line0, float3 line1)
{
float3 nearestPoint = new float3();
float3 lineDelta = line1 - line0;
// Handle degenerate lines
if (lineDelta == Zero)
{
nearestPoint = line0;
}
else
{
float delta = float3.dot(point - line0, lineDelta) / float3.dot(lineDelta, lineDelta);
// Clamp the point to conform to the segment's endpoints
if (delta < 0)
delta = 0;
else if (delta > 1)
delta = 1;
nearestPoint = line0 + lineDelta * delta;
}
this.x = nearestPoint.x;
this.y = nearestPoint.y;
this.z = nearestPoint.z;
}
// Given a point and a triangle (defined by three points), compute the closest point
// in the triangle. Clamp the point so it's confined to the area of the triangle.
public void NearestPointInTriangle(float3 point, float3 triangle0, float3 triangle1, float3 triangle2)
{
float3 nearestPoint = new float3();
float3 lineDelta0 = triangle1 - triangle0;
float3 lineDelta1 = triangle2 - triangle0;
// Handle degenerate triangles
if ((lineDelta0 == Zero) || (lineDelta1 == Zero))
{
nearestPoint.NearestPointInLineSegment(point, triangle1, triangle2);
}
else if (lineDelta0 == lineDelta1)
{
nearestPoint.NearestPointInLineSegment(point, triangle0, triangle1);
}
else
{
float3[] axis = new float3[3] { new float3(), new float3(), new float3() };
axis[0].NearestPointInLine(triangle0, triangle1, triangle2);
axis[1].NearestPointInLine(triangle1, triangle0, triangle2);
axis[2].NearestPointInLine(triangle2, triangle0, triangle1);
float3 axisDot = new float3();
axisDot.x = dot(triangle0 - axis[0], point - axis[0]);
axisDot.y = dot(triangle1 - axis[1], point - axis[1]);
axisDot.z = dot(triangle2 - axis[2], point - axis[2]);
bool bForce = true;
float bestMagnitude2 = 0;
float closeMagnitude2;
float3 closePoint = new float3();
if (axisDot.x < 0f)
{
closePoint.NearestPointInLineSegment(point, triangle1, triangle2);
closeMagnitude2 = point.Distance2(closePoint);
if (bForce || (bestMagnitude2 > closeMagnitude2))
{
bForce = false;
bestMagnitude2 = closeMagnitude2;
nearestPoint = closePoint;
}
}
if (axisDot.y < 0f)
{
closePoint.NearestPointInLineSegment(point, triangle0, triangle2);
closeMagnitude2 = point.Distance2(closePoint);
if (bForce || (bestMagnitude2 > closeMagnitude2))
{
bForce = false;
bestMagnitude2 = closeMagnitude2;
nearestPoint = closePoint;
}
}
if (axisDot.z < 0f)
{
closePoint.NearestPointInLineSegment(point, triangle0, triangle1);
closeMagnitude2 = point.Distance2(closePoint);
if (bForce || (bestMagnitude2 > closeMagnitude2))
{
bForce = false;
bestMagnitude2 = closeMagnitude2;
nearestPoint = closePoint;
}
}
// If bForce is true at this point, it means the nearest point lies
// inside the triangle; use the nearest-point-on-a-plane equation
if (bForce)
{
float3 normal;
// Get the normal of the polygon (doesn't have to be a unit vector)
normal = float3.cross(lineDelta0, lineDelta1);
float3 pointDelta = point - triangle0;
float delta = float3.dot(normal, pointDelta) / float3.dot(normal, normal);
nearestPoint = point - normal * delta;
}
}
this.x = nearestPoint.x;
this.y = nearestPoint.y;
this.z = nearestPoint.z;
}
public static float3 operator +(float3 a, float3 b)
{
return new float3(a.x + b.x, a.y + b.y, a.z + b.z);
}
public static float3 operator -(float3 a, float3 b)
{
return new float3(a.x - b.x, a.y - b.y, a.z - b.z);
}
public static float3 operator -(float3 a, float s)
{
return new float3(a.x - s, a.y - s, a.z - s);
}
public static float3 operator -(float3 v)
{
return new float3(-v.x, -v.y, -v.z);
}
public static float3 operator *(float3 v, float s)
{
return new float3(v.x * s, v.y * s, v.z * s);
}
public static float3 operator *(float s, float3 v)
{
return new float3(v.x * s, v.y * s, v.z * s);
}
public static float3 operator *(float3 v, float3x3 m)
{
return new float3((m.x.x * v.x + m.y.x * v.y + m.z.x * v.z), (m.x.y * v.x + m.y.y * v.y + m.z.y * v.z), (m.x.z * v.x + m.y.z * v.y + m.z.z * v.z));
}
public static float3 operator *(float3x3 m, float3 v)
{
return new float3(dot(m.x, v), dot(m.y, v), dot(m.z, v));
}
public static float3 operator /(float3 v, float s)
{
float sinv = 1.0f / s;
return new float3(v.x * sinv, v.y * sinv, v.z * sinv);
}
public bool Equals(float3 other)
{
return this == other;
}
public override bool Equals(object obj)
{
float3 f = obj as float3;
if (f == null)
return false;
return this == f;
}
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode();
}
public static bool operator ==(float3 a, float3 b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
return true;
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
return false;
return (a.x == b.x && a.y == b.y && a.z == b.z);
}
public static bool operator !=(float3 a, float3 b)
{
return (a.x != b.x || a.y != b.y || a.z != b.z);
}
public static float dot(float3 a, float3 b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
public static float3 cmul(float3 v1, float3 v2)
{
return new float3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
}
public static float3 cross(float3 a, float3 b)
{
return new float3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
}
public static float3 Interpolate(float3 v0, float3 v1, float alpha)
{
return v0 * (1 - alpha) + v1 * alpha;
}
public static float3 Round(float3 a, int digits)
{
return new float3((float)Math.Round(a.x, digits), (float)Math.Round(a.y, digits), (float)Math.Round(a.z, digits));
}
public static float3 VectorMax(float3 a, float3 b)
{
return new float3(Math.Max(a.x, b.x), Math.Max(a.y, b.y), Math.Max(a.z, b.z));
}
public static float3 VectorMin(float3 a, float3 b)
{
return new float3(Math.Min(a.x, b.x), Math.Min(a.y, b.y), Math.Min(a.z, b.z));
}
public static float3 vabs(float3 v)
{
return new float3(Math.Abs(v.x), Math.Abs(v.y), Math.Abs(v.z));
}
public static float magnitude(float3 v)
{
return (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
public static float3 normalize(float3 v)
{
float d = magnitude(v);
if (d == 0)
d = 0.1f;
d = 1 / d;
return new float3(v.x * d, v.y * d, v.z * d);
}
public static float3 safenormalize(float3 v)
{
if (magnitude(v) <= 0.0f)
return new float3(1, 0, 0);
else
return normalize(v);
}
public static float Yaw(float3 v)
{
return (v.y == 0.0 && v.x == 0.0) ? 0.0f : (float)Math.Atan2(-v.x, v.y) * (180.0f / 3.14159264f);
}
public static float Pitch(float3 v)
{
return (float)Math.Atan2(v.z, Math.Sqrt(v.x * v.x + v.y * v.y)) * (180.0f / 3.14159264f);
}
public float ComputePlane(float3 A, float3 B, float3 C)
{
float vx, vy, vz, wx, wy, wz, vw_x, vw_y, vw_z, mag;
vx = (B.x - C.x);
vy = (B.y - C.y);
vz = (B.z - C.z);
wx = (A.x - B.x);
wy = (A.y - B.y);
wz = (A.z - B.z);
vw_x = vy * wz - vz * wy;
vw_y = vz * wx - vx * wz;
vw_z = vx * wy - vy * wx;
mag = (float)Math.Sqrt((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
if (mag < 0.000001f)
{
mag = 0;
}
else
{
mag = 1.0f / mag;
}
x = vw_x * mag;
y = vw_y * mag;
z = vw_z * mag;
float D = 0.0f - ((x * A.x) + (y * A.y) + (z * A.z));
return D;
}
public override string ToString()
{
return String.Format("<{0}, {1}, {2}>", x, y, z);
}
public static readonly float3 Zero = new float3();
}
}

View File

@ -0,0 +1,195 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class float3x3
{
public float3 x = new float3();
public float3 y = new float3();
public float3 z = new float3();
public float3x3()
{
}
public float3x3(float xx, float xy, float xz, float yx, float yy, float yz, float zx, float zy, float zz)
{
x = new float3(xx, xy, xz);
y = new float3(yx, yy, yz);
z = new float3(zx, zy, zz);
}
public float3x3(float3 _x, float3 _y, float3 _z)
{
x = new float3(_x);
y = new float3(_y);
z = new float3(_z);
}
public float3 this[int i]
{
get
{
switch (i)
{
case 0: return x;
case 1: return y;
case 2: return z;
}
throw new ArgumentOutOfRangeException();
}
}
public float this[int i, int j]
{
get
{
switch (i)
{
case 0:
switch (j)
{
case 0: return x.x;
case 1: return x.y;
case 2: return x.z;
}
break;
case 1:
switch (j)
{
case 0: return y.x;
case 1: return y.y;
case 2: return y.z;
}
break;
case 2:
switch (j)
{
case 0: return z.x;
case 1: return z.y;
case 2: return z.z;
}
break;
}
throw new ArgumentOutOfRangeException();
}
set
{
switch (i)
{
case 0:
switch (j)
{
case 0: x.x = value; return;
case 1: x.y = value; return;
case 2: x.z = value; return;
}
break;
case 1:
switch (j)
{
case 0: y.x = value; return;
case 1: y.y = value; return;
case 2: y.z = value; return;
}
break;
case 2:
switch (j)
{
case 0: z.x = value; return;
case 1: z.y = value; return;
case 2: z.z = value; return;
}
break;
}
throw new ArgumentOutOfRangeException();
}
}
public static float3x3 Transpose(float3x3 m)
{
return new float3x3(new float3(m.x.x, m.y.x, m.z.x), new float3(m.x.y, m.y.y, m.z.y), new float3(m.x.z, m.y.z, m.z.z));
}
public static float3x3 operator *(float3x3 a, float3x3 b)
{
return new float3x3(a.x * b, a.y * b, a.z * b);
}
public static float3x3 operator *(float3x3 a, float s)
{
return new float3x3(a.x * s, a.y * s, a.z * s);
}
public static float3x3 operator /(float3x3 a, float s)
{
float t = 1f / s;
return new float3x3(a.x * t, a.y * t, a.z * t);
}
public static float3x3 operator +(float3x3 a, float3x3 b)
{
return new float3x3(a.x + b.x, a.y + b.y, a.z + b.z);
}
public static float3x3 operator -(float3x3 a, float3x3 b)
{
return new float3x3(a.x - b.x, a.y - b.y, a.z - b.z);
}
public static float Determinant(float3x3 m)
{
return m.x.x * m.y.y * m.z.z + m.y.x * m.z.y * m.x.z + m.z.x * m.x.y * m.y.z - m.x.x * m.z.y * m.y.z - m.y.x * m.x.y * m.z.z - m.z.x * m.y.y * m.x.z;
}
public static float3x3 Inverse(float3x3 a)
{
float3x3 b = new float3x3();
float d = Determinant(a);
Debug.Assert(d != 0);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
int i1 = (i + 1) % 3;
int i2 = (i + 2) % 3;
int j1 = (j + 1) % 3;
int j2 = (j + 2) % 3;
// reverse indexs i&j to take transpose
b[i, j] = (a[i1][j1] * a[i2][j2] - a[i1][j2] * a[i2][j1]) / d;
}
}
return b;
}
}
}

View File

@ -0,0 +1,170 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class float4
{
public float x;
public float y;
public float z;
public float w;
public float4()
{
x = 0;
y = 0;
z = 0;
w = 0;
}
public float4(float _x, float _y, float _z, float _w)
{
x = _x;
y = _y;
z = _z;
w = _w;
}
public float4(float3 v, float _w)
{
x = v.x;
y = v.y;
z = v.z;
w = _w;
}
public float4(float4 f)
{
x = f.x;
y = f.y;
z = f.z;
w = f.w;
}
public float this[int i]
{
get
{
switch (i)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
throw new ArgumentOutOfRangeException();
}
}
public float3 xyz()
{
return new float3(x, y, z);
}
public void setxyz(float3 xyz)
{
x = xyz.x;
y = xyz.y;
z = xyz.z;
}
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
public override bool Equals(object obj)
{
float4 f = obj as float4;
if (f == null)
return false;
return this == f;
}
public static float4 Homogenize(float3 v3)
{
return Homogenize(v3, 1.0f);
}
//C++ TO C# CONVERTER NOTE: C# does not allow default values for parameters. Overloaded methods are inserted above.
//ORIGINAL LINE: float4 Homogenize(const float3 &v3, const float &w =1.0f)
public static float4 Homogenize(float3 v3, float w)
{
return new float4(v3.x, v3.y, v3.z, w);
}
public static float4 cmul(float4 a, float4 b)
{
return new float4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
}
public static float4 operator +(float4 a, float4 b)
{
return new float4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
}
public static float4 operator -(float4 a, float4 b)
{
return new float4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
}
public static float4 operator *(float4 v, float4x4 m)
{
return v.x * m.x + v.y * m.y + v.z * m.z + v.w * m.w; // yes this actually works
}
public static bool operator ==(float4 a, float4 b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
return true;
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
return false;
return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
}
public static bool operator !=(float4 a, float4 b)
{
return !(a == b);
}
public static float4 operator *(float4 v, float s)
{
return new float4(v.x * s, v.y * s, v.z * s, v.w * s);
}
public static float4 operator *(float s, float4 v)
{
return new float4(v.x * s, v.y * s, v.z * s, v.w * s);
}
}
}

View File

@ -0,0 +1,284 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class float4x4
{
public float4 x = new float4();
public float4 y = new float4();
public float4 z = new float4();
public float4 w = new float4();
public float4x4()
{
}
public float4x4(float4 _x, float4 _y, float4 _z, float4 _w)
{
x = new float4(_x);
y = new float4(_y);
z = new float4(_z);
w = new float4(_w);
}
public float4x4(
float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
x = new float4(m00, m01, m02, m03);
y = new float4(m10, m11, m12, m13);
z = new float4(m20, m21, m22, m23);
w = new float4(m30, m31, m32, m33);
}
public float4x4(float4x4 m)
{
x = new float4(m.x);
y = new float4(m.y);
z = new float4(m.z);
w = new float4(m.w);
}
public float4 this[int i]
{
get
{
switch (i)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
throw new ArgumentOutOfRangeException();
}
set
{
switch (i)
{
case 0: x = value; return;
case 1: y = value; return;
case 2: z = value; return;
case 3: w = value; return;
}
throw new ArgumentOutOfRangeException();
}
}
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
public override bool Equals(object obj)
{
float4x4 m = obj as float4x4;
if (m == null)
return false;
return this == m;
}
public static float4x4 operator *(float4x4 a, float4x4 b)
{
return new float4x4(a.x * b, a.y * b, a.z * b, a.w * b);
}
public static bool operator ==(float4x4 a, float4x4 b)
{
return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
}
public static bool operator !=(float4x4 a, float4x4 b)
{
return !(a == b);
}
public static float4x4 Inverse(float4x4 m)
{
float4x4 d = new float4x4();
//float dst = d.x.x;
float[] tmp = new float[12]; // temp array for pairs
float[] src = new float[16]; // array of transpose source matrix
float det; // determinant
// transpose matrix
for (int i = 0; i < 4; i++)
{
src[i] = m[i].x;
src[i + 4] = m[i].y;
src[i + 8] = m[i].z;
src[i + 12] = m[i].w;
}
// calculate pairs for first 8 elements (cofactors)
tmp[0] = src[10] * src[15];
tmp[1] = src[11] * src[14];
tmp[2] = src[9] * src[15];
tmp[3] = src[11] * src[13];
tmp[4] = src[9] * src[14];
tmp[5] = src[10] * src[13];
tmp[6] = src[8] * src[15];
tmp[7] = src[11] * src[12];
tmp[8] = src[8] * src[14];
tmp[9] = src[10] * src[12];
tmp[10] = src[8] * src[13];
tmp[11] = src[9] * src[12];
// calculate first 8 elements (cofactors)
d.x.x = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
d.x.x -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
d.x.y = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
d.x.y -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
d.x.z = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
d.x.z -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
d.x.w = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
d.x.w -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
d.y.x = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
d.y.x -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
d.y.y = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
d.y.y -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
d.y.z = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
d.y.z -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
d.y.w = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
d.y.w -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
// calculate pairs for second 8 elements (cofactors)
tmp[0] = src[2]*src[7];
tmp[1] = src[3]*src[6];
tmp[2] = src[1]*src[7];
tmp[3] = src[3]*src[5];
tmp[4] = src[1]*src[6];
tmp[5] = src[2]*src[5];
tmp[6] = src[0]*src[7];
tmp[7] = src[3]*src[4];
tmp[8] = src[0]*src[6];
tmp[9] = src[2]*src[4];
tmp[10] = src[0]*src[5];
tmp[11] = src[1]*src[4];
// calculate second 8 elements (cofactors)
d.z.x = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
d.z.x -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
d.z.y = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
d.z.y -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
d.z.z = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
d.z.z -= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
d.z.w = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
d.z.w-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
d.w.x = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
d.w.x-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
d.w.y = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
d.w.y-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
d.w.z = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
d.w.z-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
d.w.w = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
d.w.w-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
// calculate determinant
det = src[0] * d.x.x + src[1] * d.x.y + src[2] * d.x.z + src[3] * d.x.w;
// calculate matrix inverse
det = 1/det;
for (int j = 0; j < 4; j++)
d[j] *= det;
return d;
}
public static float4x4 MatrixRigidInverse(float4x4 m)
{
float4x4 trans_inverse = MatrixTranslation(-m.w.xyz());
float4x4 rot = new float4x4(m);
rot.w = new float4(0f, 0f, 0f, 1f);
return trans_inverse * MatrixTranspose(rot);
}
public static float4x4 MatrixTranspose(float4x4 m)
{
return new float4x4(m.x.x, m.y.x, m.z.x, m.w.x, m.x.y, m.y.y, m.z.y, m.w.y, m.x.z, m.y.z, m.z.z, m.w.z, m.x.w, m.y.w, m.z.w, m.w.w);
}
public static float4x4 MatrixPerspectiveFov(float fovy, float aspect, float zn, float zf)
{
float h = 1.0f / (float)Math.Tan(fovy / 2.0f); // view space height
float w = h / aspect; // view space width
return new float4x4(w, 0, 0, 0, 0, h, 0, 0, 0, 0, zf / (zn - zf), -1, 0, 0, zn * zf / (zn - zf), 0);
}
public static float4x4 MatrixTranslation(float3 t)
{
return new float4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, t.x, t.y, t.z, 1);
}
public static float4x4 MatrixRotationZ(float angle_radians)
{
float s = (float)Math.Sin(angle_radians);
float c = (float)Math.Cos(angle_radians);
return new float4x4(c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
public static float4x4 MatrixLookAt(float3 eye, float3 at, float3 up)
{
float4x4 m = new float4x4();
m.w.w = 1.0f;
m.w.setxyz(eye);
m.z.setxyz(float3.normalize(eye - at));
m.x.setxyz(float3.normalize(float3.cross(up, m.z.xyz())));
m.y.setxyz(float3.cross(m.z.xyz(), m.x.xyz()));
return MatrixRigidInverse(m);
}
public static float4x4 MatrixFromQuatVec(Quaternion q, float3 v)
{
// builds a 4x4 transformation matrix based on orientation q and translation v
float qx2 = q.x * q.x;
float qy2 = q.y * q.y;
float qz2 = q.z * q.z;
float qxqy = q.x * q.y;
float qxqz = q.x * q.z;
float qxqw = q.x * q.w;
float qyqz = q.y * q.z;
float qyqw = q.y * q.w;
float qzqw = q.z * q.w;
return new float4x4(
1 - 2 * (qy2 + qz2),
2 * (qxqy + qzqw),
2 * (qxqz - qyqw),
0,
2 * (qxqy - qzqw),
1 - 2 * (qx2 + qz2),
2 * (qyqz + qxqw),
0,
2 * (qxqz + qyqw),
2 * (qyqz - qxqw),
1 - 2 * (qx2 + qy2),
0,
v.x,
v.y,
v.z,
1.0f);
}
}
}

View File

@ -0,0 +1,128 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class int3
{
public int x;
public int y;
public int z;
public int3()
{
}
public int3(int _x, int _y, int _z)
{
x = _x;
y = _y;
z = _z;
}
public int this[int i]
{
get
{
switch (i)
{
case 0: return x;
case 1: return y;
case 2: return z;
}
throw new ArgumentOutOfRangeException();
}
set
{
switch (i)
{
case 0: x = value; return;
case 1: y = value; return;
case 2: z = value; return;
}
throw new ArgumentOutOfRangeException();
}
}
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode();
}
public override bool Equals(object obj)
{
int3 i = obj as int3;
if (i == null)
return false;
return this == i;
}
public static bool operator ==(int3 a, int3 b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
return true;
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
return false;
for (int i = 0; i < 3; i++)
{
if (a[i] != b[i])
return false;
}
return true;
}
public static bool operator !=(int3 a, int3 b)
{
return !(a == b);
}
public static int3 roll3(int3 a)
{
int tmp = a[0];
a[0] = a[1];
a[1] = a[2];
a[2] = tmp;
return a;
}
public static bool isa(int3 a, int3 b)
{
return (a == b || roll3(a) == b || a == roll3(b));
}
public static bool b2b(int3 a, int3 b)
{
return isa(a, new int3(b[2], b[1], b[0]));
}
}
}

View File

@ -0,0 +1,66 @@
/* The MIT License
*
* Copyright (c) 2010 Intel Corporation.
* All rights reserved.
*
* Based on the convexdecomposition library from
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
{
public class int4
{
public int x;
public int y;
public int z;
public int w;
public int4()
{
}
public int4(int _x, int _y, int _z, int _w)
{
x = _x;
y = _y;
z = _z;
w = _w;
}
public int this[int i]
{
get
{
switch (i)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
throw new ArgumentOutOfRangeException();
}
}
}
}

View File

@ -0,0 +1,24 @@
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.ConvexDecompositionDotNet" path="addon-modules/ConvexDecompositionDotNet" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../bin/Physics/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../bin/Physics/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Core"/>
<Reference name="System.Data"/>
<Reference name="System.Xml"/>
<Files>
<Match pattern="*.cs" recurse="true">
<Exclude name="Tests" pattern="Tests"/>
</Match>
</Files>
</Project>