Hollow prims (box only), thanks Gerard! Enjoy
parent
a0265300aa
commit
c1d3e93fbb
|
@ -0,0 +1,279 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
public class Vertex : IComparable<Vertex>
|
||||
{
|
||||
public String name;
|
||||
public PhysicsVector point;
|
||||
|
||||
public Vertex(String name, float x, float y, float z)
|
||||
{
|
||||
this.name = name;
|
||||
point = new PhysicsVector(x, y, z);
|
||||
}
|
||||
|
||||
public int CompareTo(Vertex other)
|
||||
{
|
||||
if (point.X < other.point.X)
|
||||
return -1;
|
||||
|
||||
if (point.X > other.point.X)
|
||||
return 1;
|
||||
|
||||
if (point.Y < other.point.Y)
|
||||
return -1;
|
||||
|
||||
if (point.Y > other.point.Y)
|
||||
return 1;
|
||||
|
||||
if (point.Z < other.point.Z)
|
||||
return -1;
|
||||
|
||||
if (point.Z > other.point.Z)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static bool operator >(Vertex me, Vertex other)
|
||||
{
|
||||
return me.CompareTo(other) > 0;
|
||||
}
|
||||
|
||||
public static bool operator <(Vertex me, Vertex other)
|
||||
{
|
||||
return me.CompareTo(other) < 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
public Vertex v2;
|
||||
public Vertex v3;
|
||||
|
||||
float radius_square;
|
||||
float cx;
|
||||
float cy;
|
||||
|
||||
public Triangle(Vertex _v1, Vertex _v2, Vertex _v3)
|
||||
{
|
||||
v1 = _v1;
|
||||
v2 = _v2;
|
||||
v3 = _v3;
|
||||
|
||||
CalcCircle();
|
||||
}
|
||||
|
||||
public bool isInCircle(float x, float y)
|
||||
{
|
||||
float dx, dy;
|
||||
float dd;
|
||||
|
||||
dx = x - this.cx;
|
||||
dy = y - this.cy;
|
||||
|
||||
dd = dx * dx + dy * dy;
|
||||
if (dd < this.radius_square)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CalcCircle()
|
||||
{
|
||||
// Calculate the center and the radius of a circle given by three points p1, p2, p3
|
||||
// It is assumed, that the triangles vertices are already set correctly
|
||||
double p1x, p2x, p1y, p2y, p3x, p3y;
|
||||
|
||||
// Deviation of this routine:
|
||||
// A circle has the general equation (M-p)^2=r^2, where M and p are vectors
|
||||
// this gives us three equations f(p)=r^2, each for one point p1, p2, p3
|
||||
// putting respectively two equations together gives two equations
|
||||
// f(p1)=f(p2) and f(p1)=f(p3)
|
||||
// bringing all constant terms to one side brings them to the form
|
||||
// M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors)
|
||||
// and c1, c2 are scalars (Naming conventions like the variables below)
|
||||
// Now using the equations that are formed by the components of the vectors
|
||||
// and isolate Mx lets you make one equation that only holds My
|
||||
// The rest is straight forward and eaasy :-)
|
||||
//
|
||||
|
||||
/* helping variables for temporary results */
|
||||
double c1, c2;
|
||||
double v1x, v1y, v2x, v2y;
|
||||
|
||||
double z, n;
|
||||
|
||||
double rx, ry;
|
||||
|
||||
// Readout the three points, the triangle consists of
|
||||
p1x = v1.point.X;
|
||||
p1y = v1.point.Y;
|
||||
|
||||
p2x = v2.point.X;
|
||||
p2y = v2.point.Y;
|
||||
|
||||
p3x = v3.point.X;
|
||||
p3y = v3.point.Y;
|
||||
|
||||
/* calc helping values first */
|
||||
c1 = (p1x * p1x + p1y * p1y - p2x * p2x - p2y * p2y) / 2;
|
||||
c2 = (p1x * p1x + p1y * p1y - p3x * p3x - p3y * p3y) / 2;
|
||||
|
||||
v1x = p1x - p2x;
|
||||
v1y = p1y - p2y;
|
||||
|
||||
v2x = p1x - p3x;
|
||||
v2y = p1y - p3y;
|
||||
|
||||
z = (c1 * v2x - c2 * v1x);
|
||||
n = (v1y * v2x - v2y * v1x);
|
||||
|
||||
if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location
|
||||
{
|
||||
radius_square = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
this.cy = (float)(z / n);
|
||||
|
||||
if (v2x != 0.0)
|
||||
{
|
||||
this.cx = (float)((c2 - v2y * this.cy) / v2x);
|
||||
}
|
||||
else if (v1x != 0.0)
|
||||
{
|
||||
this.cx = (float)((c1 - v1y * this.cy) / v1x);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */
|
||||
}
|
||||
|
||||
rx = (p1x - this.cx);
|
||||
ry = (p1y - this.cy);
|
||||
|
||||
this.radius_square = (float)(rx * rx + ry * ry);
|
||||
|
||||
}
|
||||
|
||||
public List<Simplex> GetSimplices()
|
||||
{
|
||||
List<Simplex> result = new List<Simplex>();
|
||||
Simplex s1 = new Simplex(v1, v2);
|
||||
Simplex s2 = new Simplex(v2, v3);
|
||||
Simplex s3 = new Simplex(v3, v1);
|
||||
|
||||
result.Add(s1);
|
||||
result.Add(s2);
|
||||
result.Add(s3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override String ToString()
|
||||
{
|
||||
|
||||
NumberFormatInfo nfi = new NumberFormatInfo();
|
||||
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) + ">";
|
||||
|
||||
return s1 + ";" + s2 + ";" + s3;
|
||||
|
||||
}
|
||||
|
||||
public PhysicsVector getNormal()
|
||||
{
|
||||
// Vertices
|
||||
|
||||
// Vectors for edges
|
||||
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);
|
||||
|
||||
// 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;
|
||||
|
||||
// Length
|
||||
float l = (float)Math.Sqrt(n.X * n.X + n.Y * n.Y + n.Z * n.Z);
|
||||
|
||||
// Normalized "normal"
|
||||
n.X /= l;
|
||||
n.Y /= l;
|
||||
n.Z /= l;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
public void invertNormal()
|
||||
{
|
||||
Vertex vt;
|
||||
vt = v1;
|
||||
v1 = v2;
|
||||
v2 = vt;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,560 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using OpenSim.Framework.Types;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
namespace OpenSim.Region.Physics.OdePlugin
|
||||
{
|
||||
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
|
||||
{
|
||||
|
||||
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))
|
||||
{
|
||||
influenced.Add(t);
|
||||
}
|
||||
}
|
||||
return influenced;
|
||||
}
|
||||
|
||||
|
||||
static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles, List<int> innerBorders)
|
||||
{
|
||||
// This is a variant of the delaunay algorithm
|
||||
// each time a new vertex is inserted, all triangles that are influenced by it are deleted
|
||||
// and replaced by new ones including the new vertex
|
||||
// It is not very time efficient but easy to implement.
|
||||
|
||||
int iCurrentVertex;
|
||||
int iMaxVertex=vertices.Count;
|
||||
for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
|
||||
{
|
||||
// Background: A triangle mesh fulfills the delaunay condition if (iff!)
|
||||
// each circumlocutory circle (i.e. the circle that touches all three corners)
|
||||
// of each triangle is empty of other vertices.
|
||||
// Obviously a single (seeding) triangle fulfills this condition.
|
||||
// If we now add one vertex, we need to reconstruct all triangles, that
|
||||
// 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);
|
||||
|
||||
List<Simplex> simplices = new List<Simplex>();
|
||||
|
||||
// Reconstruction phase. First step, dissolve each triangle into it's simplices,
|
||||
// i.e. it's "border lines"
|
||||
// Goal is to find "inner" borders and delete them, while the hull gets conserved.
|
||||
// Inner borders are special in the way that they always come twice, which is how we detect them
|
||||
foreach (Triangle t in influencedTriangles)
|
||||
{
|
||||
List<Simplex> newSimplices = t.GetSimplices();
|
||||
simplices.AddRange(newSimplices);
|
||||
triangles.Remove(t);
|
||||
}
|
||||
// Now sort the simplices. That will make identical ones 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
|
||||
int iSimplex;
|
||||
List<Simplex> innerSimplices=new List<Simplex>();
|
||||
for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
|
||||
{
|
||||
if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex])==0)
|
||||
{
|
||||
innerSimplices.Add(simplices[iSimplex - 1]);
|
||||
innerSimplices.Add(simplices[iSimplex]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Simplex s in innerSimplices)
|
||||
{
|
||||
simplices.Remove(s);
|
||||
}
|
||||
|
||||
// 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
|
||||
foreach (Simplex s in simplices)
|
||||
{
|
||||
Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Mesh CreateBoxMeshX(PrimitiveBaseShape primShape, PhysicsVector size)
|
||||
// Builds the x (+ and -) surfaces of a box shaped prim
|
||||
{
|
||||
UInt16 hollowFactor = primShape.ProfileHollow;
|
||||
Mesh meshMX = new Mesh();
|
||||
|
||||
|
||||
// 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));
|
||||
|
||||
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]));
|
||||
|
||||
|
||||
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));
|
||||
|
||||
|
||||
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]));
|
||||
|
||||
|
||||
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);
|
||||
|
||||
meshMX.Add(IPP);
|
||||
meshMX.Add(IPM);
|
||||
meshMX.Add(IMP);
|
||||
meshMX.Add(IMM);
|
||||
|
||||
meshMX.Add(new Triangle(IPP, IMP, IPM));
|
||||
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();
|
||||
result.Append(meshMX);
|
||||
result.Append(meshPX);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Mesh CreateBoxMeshY(PrimitiveBaseShape primShape, PhysicsVector size)
|
||||
// Builds the y (+ and -) surfaces of a box shaped prim
|
||||
{
|
||||
UInt16 hollowFactor = primShape.ProfileHollow;
|
||||
|
||||
// (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));
|
||||
|
||||
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]));
|
||||
|
||||
// (P)lus Y
|
||||
Mesh MeshPY = new Mesh();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
if (n.Z < 0.0)
|
||||
t.invertNormal();
|
||||
}
|
||||
|
||||
Mesh result = new Mesh();
|
||||
result.Append(MZ);
|
||||
result.Append(PZ);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static Mesh CreateBoxMesh(PrimitiveBaseShape primShape, PhysicsVector size)
|
||||
{
|
||||
Mesh result = new Mesh();
|
||||
|
||||
|
||||
|
||||
Mesh MeshX = Meshmerizer.CreateBoxMeshX(primShape, size);
|
||||
Mesh MeshY = Meshmerizer.CreateBoxMeshY(primShape, size);
|
||||
Mesh MeshZ = Meshmerizer.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;
|
||||
|
||||
mesh.normals = new float[iTriangles*3];
|
||||
|
||||
int i=0;
|
||||
foreach (Triangle t in mesh.triangles)
|
||||
{
|
||||
|
||||
float ux, uy, uz;
|
||||
float vx, vy, vz;
|
||||
float wx, wy, wz;
|
||||
|
||||
ux = t.v1.point.X;
|
||||
uy = t.v1.point.Y;
|
||||
uz = t.v1.point.Z;
|
||||
|
||||
vx = t.v2.point.X;
|
||||
vy = t.v2.point.Y;
|
||||
vz = t.v2.point.Z;
|
||||
|
||||
wx = t.v3.point.X;
|
||||
wy = t.v3.point.Y;
|
||||
wz = t.v3.point.Z;
|
||||
|
||||
// Vectors for edges
|
||||
float e1x, e1y, e1z;
|
||||
float e2x, e2y, e2z;
|
||||
|
||||
e1x = ux - vx;
|
||||
e1y = uy - vy;
|
||||
e1z = uz - vz;
|
||||
|
||||
e2x = ux - wx;
|
||||
e2y = uy - wy;
|
||||
e2z = uz - wz;
|
||||
|
||||
|
||||
// Cross product for normal
|
||||
float nx, ny, nz;
|
||||
nx = e1y * e2z - e1z * e2y;
|
||||
ny = e1z * e2x - e1x * e2z;
|
||||
nz = e1x * e2y - e1y * e2x;
|
||||
|
||||
// Length
|
||||
float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz);
|
||||
|
||||
// Normalized "normal"
|
||||
nx /= l;
|
||||
ny /= l;
|
||||
nz /= l;
|
||||
|
||||
mesh.normals[i] = nx;
|
||||
mesh.normals[i + 1] = ny;
|
||||
mesh.normals[i + 2] = nz;
|
||||
|
||||
i+=3;
|
||||
}
|
||||
}
|
||||
|
||||
public static Mesh CreateMesh(PrimitiveBaseShape primShape, PhysicsVector size)
|
||||
{
|
||||
Mesh mesh = null;
|
||||
|
||||
switch (primShape.ProfileShape)
|
||||
{
|
||||
case ProfileShape.Square:
|
||||
mesh=CreateBoxMesh(primShape, size);
|
||||
CalcNormals(mesh);
|
||||
break;
|
||||
default:
|
||||
mesh=null;
|
||||
break;
|
||||
}
|
||||
|
||||
return mesh;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue