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