prim cuts in ODE

Much thanks to Gerhard!
Merged with Darok's recent changes re: physical prims
afrisby
dan miller 2007-11-05 12:25:53 +00:00
parent 6bb1e91d41
commit fdb57b28b1
8 changed files with 507 additions and 516 deletions

View File

@ -221,6 +221,14 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
set { }
}
public override PrimitiveBaseShape Shape
{
set
{
return;
}
}
public override PhysicsVector Velocity
{
get { return _velocity; }

View File

@ -686,6 +686,15 @@ namespace OpenSim.Region.Physics.BulletXPlugin
get { return _size; }
set { lock (BulletXScene.BulletXLock) { _size = value; } }
}
public override PrimitiveBaseShape Shape
{
set
{
return;
}
}
public override PhysicsVector Acceleration
{
get { return _acceleration; }

View File

@ -26,6 +26,7 @@
*
*/
using Axiom.Math;
using OpenSim.Framework;
namespace OpenSim.Region.Physics.Manager
{
@ -50,6 +51,11 @@ namespace OpenSim.Region.Physics.Manager
public abstract PhysicsVector Size { get; set; }
public abstract PrimitiveBaseShape Shape
{
set;
}
public abstract PhysicsVector Position { get; set; }
public abstract PhysicsVector Velocity { get; set; }
@ -85,6 +91,14 @@ namespace OpenSim.Region.Physics.Manager
set { return; }
}
public override PrimitiveBaseShape Shape
{
set
{
return;
}
}
public override PhysicsVector Velocity
{
get { return PhysicsVector.Zero; }

View File

@ -25,6 +25,10 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System;
namespace OpenSim.Region.Physics.Manager
{
public class PhysicsVector
@ -50,5 +54,51 @@ namespace OpenSim.Region.Physics.Manager
{
return "<" + X + "," + Y + "," + Z + ">";
}
// Operations
public static PhysicsVector operator +(PhysicsVector a, PhysicsVector b)
{
return new PhysicsVector(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
public static PhysicsVector operator -(PhysicsVector a, PhysicsVector b)
{
return new PhysicsVector(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
}
public static PhysicsVector cross(PhysicsVector a, PhysicsVector b)
{
return new PhysicsVector(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 float length()
{
return (float)Math.Sqrt(X*X + Y*Y + Z*Z);
}
public static PhysicsVector operator / (PhysicsVector v, float f)
{
return new PhysicsVector(v.X / f, v.Y / f, v.Z / f);
}
public static PhysicsVector operator *(PhysicsVector v, float f)
{
return new PhysicsVector(v.X * f, v.Y * f, v.Z * f);
}
public static PhysicsVector operator *(float f, PhysicsVector v)
{
return v * f;
}
public virtual bool IsIdentical(PhysicsVector v, float tolerance)
{
PhysicsVector diff = this - v;
float d = diff.length();
if (d < tolerance)
return true;
return false;
}
}
}

View File

@ -30,37 +30,63 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using OpenSim.Framework.Console;
using OpenSim.Region.Physics.Manager;
public class Vertex : IComparable<Vertex>
{
public String name;
public PhysicsVector point;
using OpenSim.Region.Physics.OdePlugin.Meshing;
public Vertex(String name, float x, float y, float z)
public class Vertex : PhysicsVector, IComparable<Vertex>
{
public Vertex(float x, float y, float z)
: base(x, y, z)
{
this.name = name;
point = new PhysicsVector(x, y, z);
}
public Vertex(PhysicsVector v)
: base(v.X, v.Y, v.Z)
{
}
public Vertex Clone()
{
return new Vertex(X, Y, Z);
}
public static Vertex FromAngle(double angle)
{
return new Vertex((float)Math.Cos(angle), (float)Math.Sin(angle), 0.0f);
}
public virtual bool Equals(Vertex v, float tolerance)
{
PhysicsVector diff = this - v;
float d = diff.length();
if (d < tolerance)
return true;
return false;
}
public int CompareTo(Vertex other)
{
if (point.X < other.point.X)
if (X < other.X)
return -1;
if (point.X > other.point.X)
if (X > other.X)
return 1;
if (point.Y < other.point.Y)
if (Y < other.Y)
return -1;
if (point.Y > other.point.Y)
if (Y > other.Y)
return 1;
if (point.Z < other.point.Z)
if (Z < other.Z)
return -1;
if (point.Z > other.point.Z)
if (Z > other.Z)
return 1;
return 0;
@ -75,52 +101,25 @@ public class Vertex : IComparable<Vertex>
{
return me.CompareTo(other) < 0;
}
public String ToRaw()
{
// Why this stuff with the number formatter?
// Well, the raw format uses the english/US notation of numbers
// where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1.
// The german notation uses these characters exactly vice versa!
// The Float.ToString() routine is a localized one, giving different results depending on the country
// settings your machine works with. Unusable for a machine readable file format :-(
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ".";
nfi.NumberDecimalDigits = 3;
String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi);
return s1;
}
}
public class Simplex : IComparable<Simplex>
{
public Vertex v1;
public Vertex v2;
public Simplex(Vertex _v1, Vertex _v2)
{
// Presort indices to make sorting (comparing) easier
if (_v1 > _v2)
{
v1 = _v1;
v2 = _v2;
}
else
{
v1 = _v2;
v2 = _v1;
}
}
public int CompareTo(Simplex other)
{
if (v1 > other.v1)
{
return 1;
}
if (v1 < other.v1)
{
return -1;
}
if (v2 > other.v2)
{
return 1;
}
if (v2 < other.v2)
{
return -1;
}
return 0;
}
} ;
public class Triangle
{
public Vertex v1;
@ -155,6 +154,12 @@ public class Triangle
return false;
}
public bool isDegraded()
{
// This means, the vertices of this triangle are somewhat strange.
// They either line up or at least two of them are identical
return (radius_square == 0.0);
}
private void CalcCircle()
{
@ -184,14 +189,14 @@ public class Triangle
double rx, ry;
// Readout the three points, the triangle consists of
p1x = v1.point.X;
p1y = v1.point.Y;
p1x = v1.X;
p1y = v1.Y;
p2x = v2.point.X;
p2y = v2.point.Y;
p2x = v2.X;
p2y = v2.Y;
p3x = v3.point.X;
p3y = v3.point.Y;
p3x = v3.X;
p3y = v3.Y;
/* calc helping values first */
c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2;
@ -253,12 +258,9 @@ public class Triangle
nfi.CurrencyDecimalDigits = 2;
nfi.CurrencyDecimalSeparator = ".";
String s1 = "<" + v1.point.X.ToString(nfi) + "," + v1.point.Y.ToString(nfi) + "," + v1.point.Z.ToString(nfi) +
">";
String s2 = "<" + v2.point.X.ToString(nfi) + "," + v2.point.Y.ToString(nfi) + "," + v2.point.Z.ToString(nfi) +
">";
String s3 = "<" + v3.point.X.ToString(nfi) + "," + v3.point.Y.ToString(nfi) + "," + v3.point.Z.ToString(nfi) +
">";
String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">";
String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">";
String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">";
return s1 + ";" + s2 + ";" + s3;
}
@ -271,23 +273,17 @@ public class Triangle
PhysicsVector e1;
PhysicsVector e2;
e1 = new PhysicsVector(v1.point.X - v2.point.X, v1.point.Y - v2.point.Y, v1.point.Z - v2.point.Z);
e2 = new PhysicsVector(v1.point.X - v3.point.X, v1.point.Y - v3.point.Y, v1.point.Z - v3.point.Z);
e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
// Cross product for normal
PhysicsVector n = new PhysicsVector();
float nx, ny, nz;
n.X = e1.Y*e2.Z - e1.Z*e2.Y;
n.Y = e1.Z*e2.X - e1.X*e2.Z;
n.Z = e1.X*e2.Y - e1.Y*e2.X;
PhysicsVector n = PhysicsVector.cross(e1, e2);
// Length
float l = (float) Math.Sqrt(n.X*n.X + n.Y*n.Y + n.Z*n.Z);
float l = n.length();
// Normalized "normal"
n.X /= l;
n.Y /= l;
n.Z /= l;
n = n / l;
return n;
}
@ -299,4 +295,12 @@ public class Triangle
v1 = v2;
v2 = vt;
}
// Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and
// debugging purposes
public String ToStringRaw()
{
String output = v1.ToRaw() + " " + v2.ToRaw() + " " +v3.ToRaw();
return output;
}
}

View File

@ -27,99 +27,61 @@
*/
using System;
using System.IO;
using System.Globalization;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.OdePlugin
namespace OpenSim.Region.Physics.OdePlugin.Meshing
{
public class Mesh
{
public List<Vertex> vertices;
public List<Triangle> triangles;
public float[] normals;
public Mesh()
{
vertices = new List<Vertex>();
triangles = new List<Triangle>();
}
public void Add(Triangle triangle)
{
int i;
i = vertices.IndexOf(triangle.v1);
if (i < 0)
throw new ArgumentException("Vertex v1 not known to mesh");
i = vertices.IndexOf(triangle.v2);
if (i < 0)
throw new ArgumentException("Vertex v2 not known to mesh");
i = vertices.IndexOf(triangle.v3);
if (i < 0)
throw new ArgumentException("Vertex v3 not known to mesh");
triangles.Add(triangle);
}
public void Add(Vertex v)
{
vertices.Add(v);
}
public float[] getVertexListAsFloat()
{
float[] result = new float[vertices.Count*3];
for (int i = 0; i < vertices.Count; i++)
{
Vertex v = vertices[i];
PhysicsVector point = v.point;
result[3*i + 0] = point.X;
result[3*i + 1] = point.Y;
result[3*i + 2] = point.Z;
}
GCHandle.Alloc(result, GCHandleType.Pinned);
return result;
}
public int[] getIndexListAsInt()
{
int[] result = new int[triangles.Count*3];
for (int i = 0; i < triangles.Count; i++)
{
Triangle t = triangles[i];
result[3*i + 0] = vertices.IndexOf(t.v1);
result[3*i + 1] = vertices.IndexOf(t.v2);
result[3*i + 2] = vertices.IndexOf(t.v3);
}
GCHandle.Alloc(result, GCHandleType.Pinned);
return result;
}
public void Append(Mesh newMesh)
{
foreach (Vertex v in newMesh.vertices)
vertices.Add(v);
foreach (Triangle t in newMesh.triangles)
Add(t);
}
}
public class Meshmerizer
{
// Setting baseDir to a path will enable the dumping of raw files
// raw files can be imported by blender so a visual inspection of the results can be done
// const string baseDir = "rawFiles";
const string baseDir = null;
static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
{
// p1, p2, points on the straight
// r1, r2, directional vectors of the straight. Not necessarily of length 1!
// note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
// thus allowing to decide whether an intersection is between two points
float r1x = r1.X;
float r1y = r1.Y;
float r2x = r2.X;
float r2y = r2.Y;
float denom = r1y*r2x - r1x*r2y;
if (denom == 0.0)
{
lambda = Single.NaN;
mu = Single.NaN;
return;
}
float p1x = p1.X;
float p1y = p1.Y;
float p2x = p2.X;
float p2y = p2.Y;
lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom;
mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom;
}
private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
{
List<Triangle> influenced = new List<Triangle>();
foreach (Triangle t in triangles)
{
float dx, dy;
if (t.isInCircle(v.point.X, v.point.Y))
if (t.isInCircle(v.X, v.Y))
{
influenced.Add(t);
}
@ -128,8 +90,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles,
List<int> innerBorders)
private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
{
// This is a variant of the delaunay algorithm
// each time a new vertex is inserted, all triangles that are influenced by it are deleted
@ -148,8 +109,10 @@ namespace OpenSim.Region.Physics.OdePlugin
// do not fulfill this condition with respect to the new triangle
// Find the triangles that are influenced by the new vertex
Vertex v = vertices[iCurrentVertex];
List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v);
Vertex v=vertices[iCurrentVertex];
if (v == null)
continue; // Null is polygon stop marker. Ignore it
List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v);
List<Simplex> simplices = new List<Simplex>();
@ -163,11 +126,12 @@ namespace OpenSim.Region.Physics.OdePlugin
simplices.AddRange(newSimplices);
triangles.Remove(t);
}
// Now sort the simplices. That will make identical ones side by side in the list
// Now sort the simplices. That will make identical ones reside side by side in the list
simplices.Sort();
// Look for duplicate simplices here.
// Remember, they are directly side by side in the list right now
// Remember, they are directly side by side in the list right now,
// So we only check directly neighbours
int iSimplex;
List<Simplex> innerSimplices = new List<Simplex>();
for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
@ -186,310 +150,145 @@ namespace OpenSim.Region.Physics.OdePlugin
// each simplex still in the list belongs to the hull of the region in question
// The new vertex (yes, we still deal with verices here :-) ) forms a triangle
// With each of these simplices. Build the new triangles and add them to the list
// with each of these simplices. Build the new triangles and add them to the list
foreach (Simplex s in simplices)
{
Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
triangles.Add(t);
if (!t.isDegraded())
{
triangles.Add(t);
}
}
}
// At this point all vertices should be inserted into the mesh
// But the areas, that should be kept free still are filled with triangles
// We have to remove them. For this we have a list of indices to vertices.
// Each triangle that solemnly constists of vertices from the inner border
// are deleted
List<Triangle> innerTriangles = new List<Triangle>();
foreach (Triangle t in triangles)
{
if (
innerBorders.Contains(vertices.IndexOf(t.v1))
&& innerBorders.Contains(vertices.IndexOf(t.v2))
&& innerBorders.Contains(vertices.IndexOf(t.v3))
)
innerTriangles.Add(t);
}
foreach (Triangle t in innerTriangles)
{
triangles.Remove(t);
}
}
private static Mesh CreateBoxMeshX(PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the x (+ and -) surfaces of a box shaped prim
static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the z (+ and -) surfaces of a box shaped prim
{
UInt16 hollowFactor = primShape.ProfileHollow;
Mesh meshMX = new Mesh();
UInt16 profileBegin = primShape.ProfileBegin;
UInt16 profileEnd = primShape.ProfileEnd;
// Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
// of a block are basically the same
// They may be warped differently but the shape is identical
// So we only create one surface as a model and derive both plus and minus surface of the block from it
// This is done in a model space where the block spans from -.5 to +.5 in X and Y
// The mapping to Scene space is done later during the "extrusion" phase
// Surface 0, -X
meshMX.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
meshMX.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
meshMX.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
meshMX.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
// Base
Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
meshMX.Add(new Triangle(meshMX.vertices[0], meshMX.vertices[2], meshMX.vertices[1]));
meshMX.Add(new Triangle(meshMX.vertices[1], meshMX.vertices[2], meshMX.vertices[3]));
Meshing.SimpleHull outerHull = new SimpleHull();
outerHull.AddVertex(MM);
outerHull.AddVertex(PM);
outerHull.AddVertex(PP);
outerHull.AddVertex(MP);
// Deal with cuts now
if ((profileBegin != 0) || (profileEnd != 0))
{
double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding
fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
fProfileEndAngle -= (90.0 + 45.0);
if (fProfileBeginAngle < fProfileEndAngle)
fProfileEndAngle -= 360.0;
Mesh meshPX = new Mesh();
// Surface 1, +X
meshPX.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
meshPX.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
meshPX.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
meshPX.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
// Note, that we don't want to cut out a triangle, even if this is a
// good approximation for small cuts. Indeed we want to cut out an arc
// and we approximate this arc by a polygon chain
// Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
// So it can easily be subtracted from the outer hull
int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree
double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps;
Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
meshPX.Add(new Triangle(meshPX.vertices[0], meshPX.vertices[1], meshPX.vertices[2]));
meshPX.Add(new Triangle(meshPX.vertices[2], meshPX.vertices[1], meshPX.vertices[3]));
// Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
SimpleHull cutHull = new SimpleHull();
cutHull.AddVertex(origin);
for (int i=0; i<iSteps; i++) {
double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!!
Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
cutHull.AddVertex(v);
}
Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors
cutHull.AddVertex(legEnd);
MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName);
SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
outerHull = cuttedHull;
}
// Deal with the hole here
if (hollowFactor > 0)
{
float hollowFactorF = (float) hollowFactor/(float) 50000;
Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
Vertex IPP;
Vertex IPM;
Vertex IMP;
Vertex IMM;
SimpleHull holeHull = new SimpleHull();
IPP = new Vertex("Inner-X+Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
IPM = new Vertex("Inner-X+Y-Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
IMP = new Vertex("Inner-X-Y+Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
IMM = new Vertex("Inner-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
holeHull.AddVertex(IMM);
holeHull.AddVertex(IMP);
holeHull.AddVertex(IPP);
holeHull.AddVertex(IPM);
meshMX.Add(IPP);
meshMX.Add(IPM);
meshMX.Add(IMP);
meshMX.Add(IMM);
SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
meshMX.Add(new Triangle(IPP, IMP, IPM));
meshMX.Add(new Triangle(IPM, IMP, IMM));
outerHull = hollowedHull;
foreach (Triangle t in meshMX.triangles)
{
PhysicsVector n = t.getNormal();
}
IPP = new Vertex("Inner+X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
IPM = new Vertex("Inner+X+Y-Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
IMP = new Vertex("Inner+X-Y+Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
IMM = new Vertex("Inner+X-Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
meshPX.Add(IPP);
meshPX.Add(IPM);
meshPX.Add(IMP);
meshPX.Add(IMM);
meshPX.Add(new Triangle(IPP, IPM, IMP));
meshPX.Add(new Triangle(IMP, IPM, IMM));
foreach (Triangle t in meshPX.triangles)
{
PhysicsVector n = t.getNormal();
}
}
Mesh result = new Mesh();
result.Append(meshMX);
result.Append(meshPX);
Mesh m = new Mesh();
return result;
}
Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
m.Add(Seed1);
m.Add(Seed2);
m.Add(Seed3);
private static Mesh CreateBoxMeshY(PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the y (+ and -) surfaces of a box shaped prim
{
UInt16 hollowFactor = primShape.ProfileHollow;
m.Add(new Triangle(Seed1, Seed2, Seed3));
m.Add(outerHull.getVertices());
// (M)inus Y
Mesh MeshMY = new Mesh();
MeshMY.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
MeshMY.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
MeshMY.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
MeshMY.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
InsertVertices(m.vertices, 3, m.triangles);
m.DumpRaw(baseDir, primName, "Proto first Mesh");
MeshMY.Add(new Triangle(MeshMY.vertices[0], MeshMY.vertices[1], MeshMY.vertices[2]));
MeshMY.Add(new Triangle(MeshMY.vertices[2], MeshMY.vertices[1], MeshMY.vertices[3]));
m.Remove(Seed1);
m.Remove(Seed2);
m.Remove(Seed3);
m.DumpRaw(baseDir, primName, "Proto seeds removed");
// (P)lus Y
Mesh MeshPY = new Mesh();
m.RemoveTrianglesOutside(outerHull);
m.DumpRaw(baseDir, primName, "Proto outsides removed");
MeshPY.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
MeshPY.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
MeshPY.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
MeshPY.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
MeshPY.Add(new Triangle(MeshPY.vertices[1], MeshPY.vertices[0], MeshPY.vertices[2]));
MeshPY.Add(new Triangle(MeshPY.vertices[1], MeshPY.vertices[2], MeshPY.vertices[3]));
if (hollowFactor > 0)
{
float hollowFactorF = (float) hollowFactor/(float) 50000;
Vertex IPP;
Vertex IPM;
Vertex IMP;
Vertex IMM;
IPP = new Vertex("Inner+X-Y+Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
IPM = new Vertex("Inner+X-Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
IMP = new Vertex("Inner-X-Y+Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
IMM = new Vertex("Inner-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
MeshMY.Add(IPP);
MeshMY.Add(IPM);
MeshMY.Add(IMP);
MeshMY.Add(IMM);
MeshMY.Add(new Triangle(IPP, IPM, IMP));
MeshMY.Add(new Triangle(IMP, IPM, IMM));
foreach (Triangle t in MeshMY.triangles)
{
PhysicsVector n = t.getNormal();
}
IPP = new Vertex("Inner+X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
IPM = new Vertex("Inner+X+Y-Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
IMP = new Vertex("Inner-X+Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
IMM = new Vertex("Inner-X+Y-Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
MeshPY.Add(IPP);
MeshPY.Add(IPM);
MeshPY.Add(IMP);
MeshPY.Add(IMM);
MeshPY.Add(new Triangle(IPM, IPP, IMP));
MeshPY.Add(new Triangle(IMP, IMM, IPM));
foreach (Triangle t in MeshPY.triangles)
{
PhysicsVector n = t.getNormal();
}
}
Mesh result = new Mesh();
result.Append(MeshMY);
result.Append(MeshPY);
return result;
}
private static Mesh CreateBoxMeshZ(PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the z (+ and -) surfaces of a box shaped prim
{
UInt16 hollowFactor = primShape.ProfileHollow;
// Base, i.e. outer shape
// (M)inus Z
Mesh MZ = new Mesh();
MZ.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
MZ.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
MZ.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
MZ.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
MZ.Add(new Triangle(MZ.vertices[1], MZ.vertices[0], MZ.vertices[2]));
MZ.Add(new Triangle(MZ.vertices[1], MZ.vertices[2], MZ.vertices[3]));
// (P)lus Z
Mesh PZ = new Mesh();
PZ.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, 0.0f));
PZ.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, 0.0f));
PZ.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, 0.0f));
PZ.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, 0.0f));
// Surface 5, +Z
PZ.Add(new Triangle(PZ.vertices[0], PZ.vertices[1], PZ.vertices[2]));
PZ.Add(new Triangle(PZ.vertices[2], PZ.vertices[1], PZ.vertices[3]));
if (hollowFactor > 0)
{
float hollowFactorF = (float) hollowFactor/(float) 50000;
MZ.Add(new Vertex("-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
MZ.Add(new Vertex("-X+Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
MZ.Add(new Vertex("-X-Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
MZ.Add(new Vertex("-X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
List<int> innerBorders = new List<int>();
innerBorders.Add(4);
innerBorders.Add(5);
innerBorders.Add(6);
innerBorders.Add(7);
InsertVertices(MZ.vertices, 4, MZ.triangles, innerBorders);
PZ.Add(new Vertex("-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
PZ.Add(new Vertex("-X+Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
PZ.Add(new Vertex("-X-Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
PZ.Add(new Vertex("-X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
innerBorders = new List<int>();
innerBorders.Add(4);
innerBorders.Add(5);
innerBorders.Add(6);
innerBorders.Add(7);
InsertVertices(PZ.vertices, 4, PZ.triangles, innerBorders);
}
foreach (Vertex v in PZ.vertices)
{
v.point.Z = size.Z/2.0f;
}
foreach (Vertex v in MZ.vertices)
{
v.point.Z = -size.Z/2.0f;
}
foreach (Triangle t in MZ.triangles)
{
PhysicsVector n = t.getNormal();
if (n.Z > 0.0)
t.invertNormal();
}
foreach (Triangle t in PZ.triangles)
foreach (Triangle t in m.triangles)
{
PhysicsVector n = t.getNormal();
if (n.Z < 0.0)
t.invertNormal();
}
Mesh result = new Mesh();
result.Append(MZ);
result.Append(PZ);
Extruder extr = new Extruder();
extr.size = size;
Mesh result = extr.Extrude(m);
result.DumpRaw(baseDir, primName, "Z extruded");
return result;
}
private static Mesh CreateBoxMesh(PrimitiveBaseShape primShape, PhysicsVector size)
{
Mesh result = new Mesh();
Mesh MeshX = CreateBoxMeshX(primShape, size);
Mesh MeshY = CreateBoxMeshY(primShape, size);
Mesh MeshZ = CreateBoxMeshZ(primShape, size);
result.Append(MeshX);
result.Append(MeshY);
result.Append(MeshZ);
return result;
}
public static void CalcNormals(Mesh mesh)
{
int iTriangles = mesh.triangles.Count;
@ -503,17 +302,18 @@ namespace OpenSim.Region.Physics.OdePlugin
float vx, vy, vz;
float wx, wy, wz;
ux = t.v1.point.X;
uy = t.v1.point.Y;
uz = t.v1.point.Z;
ux = t.v1.X;
uy = t.v1.Y;
uz = t.v1.Z;
vx = t.v2.point.X;
vy = t.v2.point.Y;
vz = t.v2.point.Z;
vx = t.v2.X;
vy = t.v2.Y;
vz = t.v2.Z;
wx = t.v3.X;
wy = t.v3.Y;
wz = t.v3.Z;
wx = t.v3.point.X;
wy = t.v3.point.Y;
wz = t.v3.point.Z;
// Vectors for edges
float e1x, e1y, e1z;
@ -550,14 +350,14 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
public static Mesh CreateMesh(PrimitiveBaseShape primShape, PhysicsVector size)
public static Mesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
{
Mesh mesh = null;
switch (primShape.ProfileShape)
{
case ProfileShape.Square:
mesh = CreateBoxMesh(primShape, size);
mesh=CreateBoxMesh(primName, primShape, size);
CalcNormals(mesh);
break;
default:

View File

@ -32,6 +32,8 @@ using Axiom.Math;
using Ode.NET;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Physics.OdePlugin.Meshing;
namespace OpenSim.Region.Physics.OdePlugin
{
@ -274,6 +276,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
{
/*
String name1 = null;
String name2 = null;
@ -294,45 +297,52 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
// MainLog.Instance.Debug("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z);
*/
return 1;
}
public bool needsMeshing(PrimitiveBaseShape pbs)
{
if (pbs.ProfileHollow != 0)
return true;
if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
return true;
return false;
}
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
PhysicsVector size, Quaternion rotation) //To be removed
{
return this.AddPrimShape(primName, pbs, position, size, rotation, false);
}
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
PhysicsVector size, Quaternion rotation, bool isPhysical)
{
PhysicsActor result;
Mesh mesh = null;
switch (pbs.ProfileShape)
{
case ProfileShape.Square:
/// support simple box & hollow box now; later, more shapes
if (pbs.ProfileHollow == 0)
if (needsMeshing(pbs))
{
result = AddPrim(primName, position, size, rotation, null, null);
mesh = Meshmerizer.CreateMesh(primName, pbs, size);
}
else
{
Mesh mesh = Meshmerizer.CreateMesh(pbs, size);
result = AddPrim(primName, position, size, rotation, mesh, pbs);
}
break;
default:
result = AddPrim(primName, position, size, rotation, null, null);
break;
}
result = AddPrim(primName, position, size, rotation, mesh, pbs);
return result;
}
public override void Simulate(float timeStep)
{
step_time += timeStep;
@ -551,6 +561,13 @@ namespace OpenSim.Region.Physics.OdePlugin
set { }
}
public override PrimitiveBaseShape Shape
{
set
{
return;
}
}
public override PhysicsVector Velocity
{
@ -753,6 +770,12 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
public override bool IsPhysical
{
get { return false; }
set { return; }
}
public void setMesh(OdeScene parent_scene, Mesh mesh)
{
float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory
@ -769,12 +792,6 @@ namespace OpenSim.Region.Physics.OdePlugin
prim_geom = d.CreateTriMesh(parent_scene.space, _triMeshData, parent_scene.triCallback, null, null);
}
public override bool IsPhysical
{
get { return false; }
set { return; }
}
public override bool Flying
{
get { return false; //no flying prims for you
@ -810,18 +827,70 @@ namespace OpenSim.Region.Physics.OdePlugin
_size = value;
lock (OdeScene.OdeLock)
{
if (_mesh != null) // We deal with a mesh here
string oldname = _parent_scene.geom_name_map[prim_geom];
// Cleanup of old prim geometry
d.GeomDestroy(prim_geom);
if (_mesh != null)
{
string oldname = _parent_scene.geom_name_map[prim_geom];
d.GeomDestroy(prim_geom);
Mesh mesh = Meshmerizer.CreateMesh(_pbs, _size);
// Cleanup meshing here
}
// Construction of new prim
if (this._parent_scene.needsMeshing(_pbs))
{
Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size);
setMesh(_parent_scene, mesh);
_parent_scene.geom_name_map[prim_geom] = oldname;
} else {
prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z);
}
else
_parent_scene.geom_name_map[prim_geom] = oldname;
d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
d.Quaternion myrot = new d.Quaternion();
myrot.W = _orientation.w;
myrot.X = _orientation.x;
myrot.Y = _orientation.y;
myrot.Z = _orientation.z;
d.GeomSetQuaternion(prim_geom, ref myrot);
}
}
}
public override PrimitiveBaseShape Shape
{
set
{
_pbs = value;
lock (OdeScene.OdeLock)
{
string oldname = _parent_scene.geom_name_map[prim_geom];
// Cleanup of old prim geometry
d.GeomDestroy(prim_geom);
if (_mesh != null)
{
d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
// Cleanup meshing here
}
// Construction of new prim
if (this._parent_scene.needsMeshing(_pbs))
{
Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size);
setMesh(_parent_scene, mesh);
} else {
prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z);
}
_parent_scene.geom_name_map[prim_geom] = oldname;
d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
d.Quaternion myrot = new d.Quaternion();
myrot.W = _orientation.w;
myrot.X = _orientation.x;
myrot.Y = _orientation.y;
myrot.Z = _orientation.z;
d.GeomSetQuaternion(prim_geom, ref myrot);
}
}
}

View File

@ -291,15 +291,23 @@ namespace OpenSim.Region.Physics.PhysXPlugin
gravityAccel = 0;
}
}
public void UpdatePosition()
public override PrimitiveBaseShape Shape
{
Vec3 vec = _character.Position;
_position.X = vec.X;
_position.Y = vec.Y;
_position.Z = vec.Z;
set
{
return;
}
}
}
public void UpdatePosition()
{
Vec3 vec = this._character.Position;
this._position.X = vec.X;
this._position.Y = vec.Y;
this._position.Z = vec.Z;
}
}
public class PhysXPrim : PhysicsActor
{
@ -358,55 +366,84 @@ namespace OpenSim.Region.Physics.PhysXPlugin
}
}
public override PrimitiveBaseShape Shape
{
set
{
return;
}
}
public override PhysicsVector Velocity
{
get
{
return _velocity;
}
set
{
_velocity = value;
}
}
public override bool Kinematic
{
get
{
return this._prim.Kinematic;
}
set
{
this._prim.Kinematic = value;
}
}
public override Quaternion Orientation
{
get
{
Quaternion res = new Quaternion();
PhysXWrapper.Quaternion quat = this._prim.GetOrientation();
res.w = quat.W;
res.x = quat.X;
res.y = quat.Y;
res.z = quat.Z;
return res;
}
set
{
}
}
public override PhysicsVector Acceleration
{
get
{
return _acceleration;
}
}
public void SetAcceleration (PhysicsVector accel)
{
this._acceleration = accel;
}
public override void AddForce(PhysicsVector force)
{
}
public override void SetMomentum(PhysicsVector momentum)
{
}
public override PhysicsVector Size
{
get { return new PhysicsVector(0, 0, 0); }
set { }
}
public override PhysicsVector Velocity
{
get { return _velocity; }
set { _velocity = value; }
}
public override bool Kinematic
{
get { return _prim.Kinematic; }
set { _prim.Kinematic = value; }
}
public override Quaternion Orientation
{
get
{
Quaternion res = new Quaternion();
PhysXWrapper.Quaternion quat = _prim.GetOrientation();
res.w = quat.W;
res.x = quat.X;
res.y = quat.Y;
res.z = quat.Z;
return res;
}
set { }
}
public override PhysicsVector Acceleration
{
get { return _acceleration; }
}
public void SetAcceleration(PhysicsVector accel)
{
_acceleration = accel;
}
public override void AddForce(PhysicsVector force)
{
}
public override void SetMomentum(PhysicsVector momentum)
{
}
}
}