Add ConvexDecompositionDotNet
parent
973d0fcdaa
commit
95ce0caa76
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
@ -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.
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
Loading…
Reference in New Issue