prim cuts in ODE
Much thanks to Gerhard! Merged with Darok's recent changes re: physical primsafrisby
parent
6bb1e91d41
commit
fdb57b28b1
|
@ -221,6 +221,14 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override PrimitiveBaseShape Shape
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override PhysicsVector Velocity
|
public override PhysicsVector Velocity
|
||||||
{
|
{
|
||||||
get { return _velocity; }
|
get { return _velocity; }
|
||||||
|
|
|
@ -686,6 +686,15 @@ namespace OpenSim.Region.Physics.BulletXPlugin
|
||||||
get { return _size; }
|
get { return _size; }
|
||||||
set { lock (BulletXScene.BulletXLock) { _size = value; } }
|
set { lock (BulletXScene.BulletXLock) { _size = value; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override PrimitiveBaseShape Shape
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override PhysicsVector Acceleration
|
public override PhysicsVector Acceleration
|
||||||
{
|
{
|
||||||
get { return _acceleration; }
|
get { return _acceleration; }
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
using Axiom.Math;
|
using Axiom.Math;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.Manager
|
namespace OpenSim.Region.Physics.Manager
|
||||||
{
|
{
|
||||||
|
@ -50,6 +51,11 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
|
|
||||||
public abstract PhysicsVector Size { get; set; }
|
public abstract PhysicsVector Size { get; set; }
|
||||||
|
|
||||||
|
public abstract PrimitiveBaseShape Shape
|
||||||
|
{
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract PhysicsVector Position { get; set; }
|
public abstract PhysicsVector Position { get; set; }
|
||||||
|
|
||||||
public abstract PhysicsVector Velocity { get; set; }
|
public abstract PhysicsVector Velocity { get; set; }
|
||||||
|
@ -85,6 +91,14 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
set { return; }
|
set { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override PrimitiveBaseShape Shape
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override PhysicsVector Velocity
|
public override PhysicsVector Velocity
|
||||||
{
|
{
|
||||||
get { return PhysicsVector.Zero; }
|
get { return PhysicsVector.Zero; }
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.Manager
|
namespace OpenSim.Region.Physics.Manager
|
||||||
{
|
{
|
||||||
public class PhysicsVector
|
public class PhysicsVector
|
||||||
|
@ -50,5 +54,51 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
{
|
{
|
||||||
return "<" + X + "," + Y + "," + Z + ">";
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,37 +30,63 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
public class Vertex : IComparable<Vertex>
|
using OpenSim.Region.Physics.OdePlugin.Meshing;
|
||||||
{
|
|
||||||
public String name;
|
|
||||||
public PhysicsVector point;
|
|
||||||
|
|
||||||
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)
|
public int CompareTo(Vertex other)
|
||||||
{
|
{
|
||||||
if (point.X < other.point.X)
|
if (X < other.X)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (point.X > other.point.X)
|
if (X > other.X)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (point.Y < other.point.Y)
|
if (Y < other.Y)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (point.Y > other.point.Y)
|
if (Y > other.Y)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (point.Z < other.point.Z)
|
if (Z < other.Z)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (point.Z > other.point.Z)
|
if (Z > other.Z)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -75,52 +101,25 @@ public class Vertex : IComparable<Vertex>
|
||||||
{
|
{
|
||||||
return me.CompareTo(other) < 0;
|
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 class Triangle
|
||||||
{
|
{
|
||||||
public Vertex v1;
|
public Vertex v1;
|
||||||
|
@ -155,6 +154,12 @@ public class Triangle
|
||||||
return false;
|
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()
|
private void CalcCircle()
|
||||||
{
|
{
|
||||||
|
@ -184,14 +189,14 @@ public class Triangle
|
||||||
double rx, ry;
|
double rx, ry;
|
||||||
|
|
||||||
// Readout the three points, the triangle consists of
|
// Readout the three points, the triangle consists of
|
||||||
p1x = v1.point.X;
|
p1x = v1.X;
|
||||||
p1y = v1.point.Y;
|
p1y = v1.Y;
|
||||||
|
|
||||||
p2x = v2.point.X;
|
p2x = v2.X;
|
||||||
p2y = v2.point.Y;
|
p2y = v2.Y;
|
||||||
|
|
||||||
p3x = v3.point.X;
|
p3x = v3.X;
|
||||||
p3y = v3.point.Y;
|
p3y = v3.Y;
|
||||||
|
|
||||||
/* calc helping values first */
|
/* calc helping values first */
|
||||||
c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2;
|
c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2;
|
||||||
|
@ -253,12 +258,9 @@ public class Triangle
|
||||||
nfi.CurrencyDecimalDigits = 2;
|
nfi.CurrencyDecimalDigits = 2;
|
||||||
nfi.CurrencyDecimalSeparator = ".";
|
nfi.CurrencyDecimalSeparator = ".";
|
||||||
|
|
||||||
String s1 = "<" + v1.point.X.ToString(nfi) + "," + v1.point.Y.ToString(nfi) + "," + v1.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 s2 = "<" + v2.point.X.ToString(nfi) + "," + v2.point.Y.ToString(nfi) + "," + v2.point.Z.ToString(nfi) +
|
String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">";
|
||||||
">";
|
|
||||||
String s3 = "<" + v3.point.X.ToString(nfi) + "," + v3.point.Y.ToString(nfi) + "," + v3.point.Z.ToString(nfi) +
|
|
||||||
">";
|
|
||||||
|
|
||||||
return s1 + ";" + s2 + ";" + s3;
|
return s1 + ";" + s2 + ";" + s3;
|
||||||
}
|
}
|
||||||
|
@ -271,23 +273,17 @@ public class Triangle
|
||||||
PhysicsVector e1;
|
PhysicsVector e1;
|
||||||
PhysicsVector e2;
|
PhysicsVector e2;
|
||||||
|
|
||||||
e1 = new PhysicsVector(v1.point.X - v2.point.X, v1.point.Y - v2.point.Y, v1.point.Z - v2.point.Z);
|
e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
|
||||||
e2 = new PhysicsVector(v1.point.X - v3.point.X, v1.point.Y - v3.point.Y, v1.point.Z - v3.point.Z);
|
e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
|
||||||
|
|
||||||
// Cross product for normal
|
// Cross product for normal
|
||||||
PhysicsVector n = new PhysicsVector();
|
PhysicsVector n = PhysicsVector.cross(e1, e2);
|
||||||
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;
|
|
||||||
|
|
||||||
// Length
|
// Length
|
||||||
float l = (float) Math.Sqrt(n.X*n.X + n.Y*n.Y + n.Z*n.Z);
|
float l = n.length();
|
||||||
|
|
||||||
// Normalized "normal"
|
// Normalized "normal"
|
||||||
n.X /= l;
|
n = n / l;
|
||||||
n.Y /= l;
|
|
||||||
n.Z /= l;
|
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
@ -299,4 +295,12 @@ public class Triangle
|
||||||
v1 = v2;
|
v1 = v2;
|
||||||
v2 = vt;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -27,99 +27,61 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.Physics.Manager;
|
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
|
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)
|
private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
|
||||||
{
|
{
|
||||||
List<Triangle> influenced = new List<Triangle>();
|
List<Triangle> influenced = new List<Triangle>();
|
||||||
foreach (Triangle t in triangles)
|
foreach (Triangle t in triangles)
|
||||||
{
|
{
|
||||||
float dx, dy;
|
if (t.isInCircle(v.X, v.Y))
|
||||||
|
|
||||||
if (t.isInCircle(v.point.X, v.point.Y))
|
|
||||||
{
|
{
|
||||||
influenced.Add(t);
|
influenced.Add(t);
|
||||||
}
|
}
|
||||||
|
@ -128,8 +90,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles,
|
private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
|
||||||
List<int> innerBorders)
|
|
||||||
{
|
{
|
||||||
// This is a variant of the delaunay algorithm
|
// This is a variant of the delaunay algorithm
|
||||||
// each time a new vertex is inserted, all triangles that are influenced by it are deleted
|
// 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
|
// do not fulfill this condition with respect to the new triangle
|
||||||
|
|
||||||
// Find the triangles that are influenced by the new vertex
|
// Find the triangles that are influenced by the new vertex
|
||||||
Vertex v = vertices[iCurrentVertex];
|
Vertex v=vertices[iCurrentVertex];
|
||||||
List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v);
|
if (v == null)
|
||||||
|
continue; // Null is polygon stop marker. Ignore it
|
||||||
|
List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v);
|
||||||
|
|
||||||
List<Simplex> simplices = new List<Simplex>();
|
List<Simplex> simplices = new List<Simplex>();
|
||||||
|
|
||||||
|
@ -163,11 +126,12 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
simplices.AddRange(newSimplices);
|
simplices.AddRange(newSimplices);
|
||||||
triangles.Remove(t);
|
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();
|
simplices.Sort();
|
||||||
|
|
||||||
// Look for duplicate simplices here.
|
// 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;
|
int iSimplex;
|
||||||
List<Simplex> innerSimplices = new List<Simplex>();
|
List<Simplex> innerSimplices = new List<Simplex>();
|
||||||
for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
|
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
|
// 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
|
// 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)
|
foreach (Simplex s in simplices)
|
||||||
{
|
{
|
||||||
Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
|
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)
|
static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
|
||||||
// Builds the x (+ and -) surfaces of a box shaped prim
|
// Builds the z (+ and -) surfaces of a box shaped prim
|
||||||
{
|
{
|
||||||
UInt16 hollowFactor = primShape.ProfileHollow;
|
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
|
// Base
|
||||||
meshMX.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
|
Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
|
||||||
meshMX.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
|
Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
|
||||||
meshMX.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
|
Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
|
||||||
meshMX.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
|
Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
|
||||||
|
|
||||||
meshMX.Add(new Triangle(meshMX.vertices[0], meshMX.vertices[2], meshMX.vertices[1]));
|
Meshing.SimpleHull outerHull = new SimpleHull();
|
||||||
meshMX.Add(new Triangle(meshMX.vertices[1], meshMX.vertices[2], meshMX.vertices[3]));
|
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();
|
// Note, that we don't want to cut out a triangle, even if this is a
|
||||||
// Surface 1, +X
|
// good approximation for small cuts. Indeed we want to cut out an arc
|
||||||
meshPX.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
|
// and we approximate this arc by a polygon chain
|
||||||
meshPX.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
|
// Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
|
||||||
meshPX.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
|
// So it can easily be subtracted from the outer hull
|
||||||
meshPX.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
|
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]));
|
// Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
|
||||||
meshPX.Add(new Triangle(meshPX.vertices[2], meshPX.vertices[1], meshPX.vertices[3]));
|
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)
|
if (hollowFactor > 0)
|
||||||
{
|
{
|
||||||
float hollowFactorF = (float) hollowFactor/(float) 50000;
|
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;
|
SimpleHull holeHull = new SimpleHull();
|
||||||
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);
|
holeHull.AddVertex(IMM);
|
||||||
IPM = new Vertex("Inner-X+Y-Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
|
holeHull.AddVertex(IMP);
|
||||||
IMP = new Vertex("Inner-X-Y+Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
|
holeHull.AddVertex(IPP);
|
||||||
IMM = new Vertex("Inner-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
|
holeHull.AddVertex(IPM);
|
||||||
|
|
||||||
meshMX.Add(IPP);
|
SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
|
||||||
meshMX.Add(IPM);
|
|
||||||
meshMX.Add(IMP);
|
|
||||||
meshMX.Add(IMM);
|
|
||||||
|
|
||||||
meshMX.Add(new Triangle(IPP, IMP, IPM));
|
outerHull = hollowedHull;
|
||||||
meshMX.Add(new Triangle(IPM, IMP, IMM));
|
|
||||||
|
|
||||||
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();
|
Mesh m = new Mesh();
|
||||||
result.Append(meshMX);
|
|
||||||
result.Append(meshPX);
|
|
||||||
|
|
||||||
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)
|
m.Add(new Triangle(Seed1, Seed2, Seed3));
|
||||||
// Builds the y (+ and -) surfaces of a box shaped prim
|
m.Add(outerHull.getVertices());
|
||||||
{
|
|
||||||
UInt16 hollowFactor = primShape.ProfileHollow;
|
|
||||||
|
|
||||||
// (M)inus Y
|
InsertVertices(m.vertices, 3, m.triangles);
|
||||||
Mesh MeshMY = new Mesh();
|
m.DumpRaw(baseDir, primName, "Proto first 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));
|
|
||||||
|
|
||||||
MeshMY.Add(new Triangle(MeshMY.vertices[0], MeshMY.vertices[1], MeshMY.vertices[2]));
|
m.Remove(Seed1);
|
||||||
MeshMY.Add(new Triangle(MeshMY.vertices[2], MeshMY.vertices[1], MeshMY.vertices[3]));
|
m.Remove(Seed2);
|
||||||
|
m.Remove(Seed3);
|
||||||
|
m.DumpRaw(baseDir, primName, "Proto seeds removed");
|
||||||
|
|
||||||
// (P)lus Y
|
m.RemoveTrianglesOutside(outerHull);
|
||||||
Mesh MeshPY = new Mesh();
|
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));
|
foreach (Triangle t in m.triangles)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
PhysicsVector n = t.getNormal();
|
PhysicsVector n = t.getNormal();
|
||||||
if (n.Z < 0.0)
|
if (n.Z < 0.0)
|
||||||
t.invertNormal();
|
t.invertNormal();
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh result = new Mesh();
|
Extruder extr = new Extruder();
|
||||||
result.Append(MZ);
|
|
||||||
result.Append(PZ);
|
|
||||||
|
|
||||||
|
extr.size = size;
|
||||||
|
|
||||||
|
Mesh result = extr.Extrude(m);
|
||||||
|
result.DumpRaw(baseDir, primName, "Z extruded");
|
||||||
return result;
|
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)
|
public static void CalcNormals(Mesh mesh)
|
||||||
{
|
{
|
||||||
int iTriangles = mesh.triangles.Count;
|
int iTriangles = mesh.triangles.Count;
|
||||||
|
@ -503,17 +302,18 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
float vx, vy, vz;
|
float vx, vy, vz;
|
||||||
float wx, wy, wz;
|
float wx, wy, wz;
|
||||||
|
|
||||||
ux = t.v1.point.X;
|
ux = t.v1.X;
|
||||||
uy = t.v1.point.Y;
|
uy = t.v1.Y;
|
||||||
uz = t.v1.point.Z;
|
uz = t.v1.Z;
|
||||||
|
|
||||||
vx = t.v2.point.X;
|
vx = t.v2.X;
|
||||||
vy = t.v2.point.Y;
|
vy = t.v2.Y;
|
||||||
vz = t.v2.point.Z;
|
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
|
// Vectors for edges
|
||||||
float e1x, e1y, e1z;
|
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;
|
Mesh mesh = null;
|
||||||
|
|
||||||
switch (primShape.ProfileShape)
|
switch (primShape.ProfileShape)
|
||||||
{
|
{
|
||||||
case ProfileShape.Square:
|
case ProfileShape.Square:
|
||||||
mesh = CreateBoxMesh(primShape, size);
|
mesh=CreateBoxMesh(primName, primShape, size);
|
||||||
CalcNormals(mesh);
|
CalcNormals(mesh);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -32,6 +32,8 @@ using Axiom.Math;
|
||||||
using Ode.NET;
|
using Ode.NET;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Region.Physics.OdePlugin.Meshing;
|
||||||
|
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.OdePlugin
|
namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
|
@ -274,6 +276,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
|
public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
String name1 = null;
|
String name1 = null;
|
||||||
String name2 = null;
|
String name2 = null;
|
||||||
|
|
||||||
|
@ -294,45 +297,52 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
|
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);
|
// 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;
|
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,
|
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
|
||||||
PhysicsVector size, Quaternion rotation) //To be removed
|
PhysicsVector size, Quaternion rotation) //To be removed
|
||||||
{
|
{
|
||||||
return this.AddPrimShape(primName, pbs, position, size, rotation, false);
|
return this.AddPrimShape(primName, pbs, position, size, rotation, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
|
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
|
||||||
PhysicsVector size, Quaternion rotation, bool isPhysical)
|
PhysicsVector size, Quaternion rotation, bool isPhysical)
|
||||||
{
|
{
|
||||||
PhysicsActor result;
|
PhysicsActor result;
|
||||||
|
Mesh mesh = null;
|
||||||
|
|
||||||
switch (pbs.ProfileShape)
|
switch (pbs.ProfileShape)
|
||||||
{
|
{
|
||||||
case ProfileShape.Square:
|
case ProfileShape.Square:
|
||||||
/// support simple box & hollow box now; later, more shapes
|
/// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = AddPrim(primName, position, size, rotation, mesh, pbs);
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void Simulate(float timeStep)
|
public override void Simulate(float timeStep)
|
||||||
{
|
{
|
||||||
step_time += timeStep;
|
step_time += timeStep;
|
||||||
|
@ -551,6 +561,13 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override PrimitiveBaseShape Shape
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override PhysicsVector Velocity
|
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)
|
public void setMesh(OdeScene parent_scene, Mesh mesh)
|
||||||
{
|
{
|
||||||
float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory
|
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);
|
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
|
public override bool Flying
|
||||||
{
|
{
|
||||||
get { return false; //no flying prims for you
|
get { return false; //no flying prims for you
|
||||||
|
@ -810,18 +827,70 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
_size = value;
|
_size = value;
|
||||||
lock (OdeScene.OdeLock)
|
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];
|
// Cleanup meshing here
|
||||||
d.GeomDestroy(prim_geom);
|
}
|
||||||
Mesh mesh = Meshmerizer.CreateMesh(_pbs, _size);
|
|
||||||
|
// Construction of new prim
|
||||||
|
if (this._parent_scene.needsMeshing(_pbs))
|
||||||
|
{
|
||||||
|
Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size);
|
||||||
setMesh(_parent_scene, mesh);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,15 +291,23 @@ namespace OpenSim.Region.Physics.PhysXPlugin
|
||||||
gravityAccel = 0;
|
gravityAccel = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override PrimitiveBaseShape Shape
|
||||||
public void UpdatePosition()
|
|
||||||
{
|
{
|
||||||
Vec3 vec = _character.Position;
|
set
|
||||||
_position.X = vec.X;
|
{
|
||||||
_position.Y = vec.Y;
|
return;
|
||||||
_position.Z = vec.Z;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
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
|
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
|
public override PhysicsVector Size
|
||||||
{
|
{
|
||||||
get { return new PhysicsVector(0, 0, 0); }
|
get { return new PhysicsVector(0, 0, 0); }
|
||||||
set { }
|
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue