* Added stretchable ellipsoid support with configurable LOD. It's actually a split facet icosahedral geodesic sphere that's scaled.

* In other words, you can stretch spheres into oblong shapes now and watch them roll around like a football would.
* Still can't cut, twist or profile cut spheres yet.
0.6.0-stable
Teravus Ovares 2008-04-08 05:03:43 +00:00
parent 04fe45c55c
commit 95e31c9f02
2 changed files with 166 additions and 58 deletions

View File

@ -39,6 +39,83 @@ public class Vertex : PhysicsVector, IComparable<Vertex>
{ {
} }
public float length()
{
return (float)Math.Sqrt(X * X + Y * Y + Z * Z);
}
public Vertex normalize()
{
float tlength = length();
if (tlength != 0)
{
return new Vertex(X / tlength, Y / tlength, Z / tlength);
}
else
{
return new Vertex(0, 0, 0);
}
}
public Vertex cross(Vertex v)
{
return new Vertex(Y * v.Z - Z * v.Y, Z * v.X - X * v.Z, X * v.Y - Y * v.X);
}
public static Vertex operator +(Vertex v1, Vertex v2)
{
return new Vertex(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
public static Vertex operator -(Vertex v1, Vertex v2)
{
return new Vertex(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
}
public static Vertex operator *(Vertex v1, Vertex v2)
{
return new Vertex(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z);
}
public static Vertex operator +(Vertex v1, float am)
{
v1.X += am;
v1.Y += am;
v1.Z += am;
return v1;
}
public static Vertex operator -(Vertex v1, float am)
{
v1.X -= am;
v1.Y -= am;
v1.Z -= am;
return v1;
}
public static Vertex operator *(Vertex v1, float am)
{
v1.X *= am;
v1.Y *= am;
v1.Z *= am;
return v1;
}
public static Vertex operator /(Vertex v1, float am)
{
if (am == 0f)
{
return new Vertex(0f,0f,0f);
}
v1.X /= am;
v1.Y /= am;
v1.Z /= am;
return v1;
}
public float dot(Vertex v)
{
return X * v.X + Y * v.Y + Z * v.Z;
}
public Vertex(PhysicsVector v) public Vertex(PhysicsVector v)
: base(v.X, v.Y, v.Z) : base(v.X, v.Y, v.Z)
{ {

View File

@ -989,8 +989,17 @@ namespace OpenSim.Region.Physics.Meshing
return result; return result;
} }
private static Mesh CreateSphereMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) private static Mesh CreateSphereMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the z (+ and -) surfaces of a box shaped prim
{ {
// Builds an icosahedral geodesic sphere
// based on an article by Paul Bourke
// http://local.wasp.uwa.edu.au/~pbourke/
// articles:
// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonmesh/
// and
// http://local.wasp.uwa.edu.au/~pbourke/geometry/polyhedra/index.html
// Still have more to do here.
UInt16 hollowFactor = primShape.ProfileHollow; UInt16 hollowFactor = primShape.ProfileHollow;
UInt16 profileBegin = primShape.ProfileBegin; UInt16 profileBegin = primShape.ProfileBegin;
UInt16 profileEnd = primShape.ProfileEnd; UInt16 profileEnd = primShape.ProfileEnd;
@ -999,13 +1008,17 @@ namespace OpenSim.Region.Physics.Meshing
UInt16 pathShearX = primShape.PathShearX; UInt16 pathShearX = primShape.PathShearX;
UInt16 pathShearY = primShape.PathShearY; UInt16 pathShearY = primShape.PathShearY;
Mesh m = new Mesh(); Mesh m = new Mesh();
float radius = 0.6f;
float LOD = 0.2f;
float diameter = 0.5f;// Our object will result in -0.5 to 0.5
float sq5 = (float) Math.Sqrt(5.0); float sq5 = (float) Math.Sqrt(5.0);
float phi = (1 + sq5) * 0.5f; float phi = (1 + sq5) * 0.5f;
float rat = (float) Math.Sqrt(10f + (2f * sq5)) / (4f * phi); float rat = (float) Math.Sqrt(10f + (2f * sq5)) / (4f * phi);
float a = (radius / rat) * 0.5f; float a = (diameter / rat) * 0.5f;
float b = (radius / rat) / (2.0f * phi); float b = (diameter / rat) / (2.0f * phi);
// 12 Icosahedron vertexes
Vertex v1 = new Vertex(0f, b, -a); Vertex v1 = new Vertex(0f, b, -a);
Vertex v2 = new Vertex(b, a, 0f); Vertex v2 = new Vertex(b, a, 0f);
Vertex v3 = new Vertex(-b, a, 0f); Vertex v3 = new Vertex(-b, a, 0f);
@ -1018,72 +1031,47 @@ namespace OpenSim.Region.Physics.Meshing
Vertex v10 = new Vertex(-a, 0f, -b); Vertex v10 = new Vertex(-a, 0f, -b);
Vertex v11 = new Vertex(b, -a, 0); Vertex v11 = new Vertex(b, -a, 0);
Vertex v12 = new Vertex(-b, -a, 0); Vertex v12 = new Vertex(-b, -a, 0);
m.Add(v1);
m.Add(v2);
m.Add(v3);
m.Add(v4);
m.Add(v5);
m.Add(v6);
m.Add(v7);
m.Add(v8);
m.Add(v9);
m.Add(v10);
m.Add(v11);
m.Add(v12);
Triangle t1 = new Triangle(v1, v2, v3);
Triangle t2 = new Triangle(v4, v3, v2);
Triangle t3 = new Triangle(v4, v5, v6);
Triangle t4 = new Triangle(v4, v9, v5);
Triangle t5 = new Triangle(v1, v7, v8);
Triangle t6 = new Triangle(v1, v10, v7);
Triangle t7 = new Triangle(v5, v11, v12);
Triangle t8 = new Triangle(v7, v12, v11);
Triangle t9 = new Triangle(v3, v6, v10);
Triangle t10 = new Triangle(v12, v10, v6);
Triangle t11 = new Triangle(v2, v8, v9);
Triangle t12 = new Triangle(v11, v9, v8);
Triangle t13 = new Triangle(v4, v6, v3);
Triangle t14 = new Triangle(v4, v2, v9);
Triangle t15 = new Triangle(v1, v3, v10);
Triangle t16 = new Triangle(v1, v8, v2);
Triangle t17 = new Triangle(v7, v10, v12);
Triangle t18 = new Triangle(v7, v11, v8);
Triangle t19 = new Triangle(v5, v12, v6);
Triangle t20 = new Triangle(v5, v9, v11);
m.Add(t1);
m.Add(t2);
m.Add(t3);
m.Add(t4);
m.Add(t5);
m.Add(t6);
m.Add(t7);
m.Add(t8);
m.Add(t9);
m.Add(t10);
m.Add(t11);
m.Add(t12);
m.Add(t13);
m.Add(t14);
m.Add(t15);
m.Add(t16);
m.Add(t17);
m.Add(t18);
m.Add(t19);
m.Add(t20);
// strechy!
// Base Faces of the Icosahedron (20)
SphereLODTriangle(v1, v2, v3, diameter, LOD, m);
SphereLODTriangle(v4, v3, v2, diameter, LOD, m);
SphereLODTriangle(v4, v5, v6, diameter, LOD, m);
SphereLODTriangle(v4, v9, v5, diameter, LOD, m);
SphereLODTriangle(v1, v7, v8, diameter, LOD, m);
SphereLODTriangle(v1, v10, v7, diameter, LOD, m);
SphereLODTriangle(v5, v11, v12, diameter, LOD, m);
SphereLODTriangle(v7, v12, v11, diameter, LOD, m);
SphereLODTriangle(v3, v6, v10, diameter, LOD, m);
SphereLODTriangle(v12, v10, v6, diameter, LOD, m);
SphereLODTriangle(v2, v8, v9, diameter, LOD, m);
SphereLODTriangle(v11, v9, v8, diameter, LOD, m);
SphereLODTriangle(v4, v6, v3, diameter, LOD, m);
SphereLODTriangle(v4, v2, v9, diameter, LOD, m);
SphereLODTriangle(v1, v3, v10, diameter, LOD, m);
SphereLODTriangle(v1, v8, v2, diameter, LOD, m);
SphereLODTriangle(v7, v10, v12, diameter, LOD, m);
SphereLODTriangle(v7, v11, v8, diameter, LOD, m);
SphereLODTriangle(v5, v12, v6, diameter, LOD, m);
SphereLODTriangle(v5, v9, v11, diameter, LOD, m);
// Scale the mesh based on our prim scale
foreach (Vertex v in m.vertices) foreach (Vertex v in m.vertices)
{ {
v.X *= size.X; v.X *= size.X;
v.Y *= size.Y; v.Y *= size.Y;
v.Z *= size.Z; v.Z *= size.Z;
} }
// This was built with the normals pointing inside..
// therefore we have to invert the normals
foreach (Triangle t in m.triangles) foreach (Triangle t in m.triangles)
{ {
t.invertNormal(); t.invertNormal();
} }
m.DumpRaw(baseDir, primName, "Z extruded"); // Dump the faces for visualization in blender.
m.DumpRaw(baseDir, primName, "Icosahedron");
return m; return m;
} }
@ -1149,6 +1137,49 @@ namespace OpenSim.Region.Physics.Meshing
} }
} }
public static Vertex midUnitRadialPoint(Vertex a, Vertex b, float radius)
{
Vertex midpoint = new Vertex(a + b) * 0.5f;
return (midpoint.normalize() * radius);
}
public static void SphereLODTriangle(Vertex a, Vertex b, Vertex c, float diameter, float LOD, Mesh m)
{
Vertex aa = a - b;
Vertex ba = b - c;
Vertex da = c - a;
if (((aa.length() < LOD) && (ba.length() < LOD) && (da.length() < LOD)))
{
// We don't want duplicate verticies. Duplicates cause the scale algorithm to produce a spikeball
// spikes are novel, but we want ellipsoids.
if (!m.vertices.Contains(a))
m.Add(a);
if (!m.vertices.Contains(b))
m.Add(b);
if (!m.vertices.Contains(c))
m.Add(c);
// Add the triangle to the mesh
Triangle t = new Triangle(a, b, c);
m.Add(t);
}
else
{
Vertex ab = midUnitRadialPoint(a, b, diameter);
Vertex bc = midUnitRadialPoint(b, c, diameter);
Vertex ca = midUnitRadialPoint(c, a, diameter);
// Recursive! Splits the triangle up into 4 smaller triangles
SphereLODTriangle(a, ab, ca, diameter, LOD, m);
SphereLODTriangle(ab, b, bc, diameter, LOD, m);
SphereLODTriangle(ca, bc, c, diameter, LOD, m);
SphereLODTriangle(ab, bc, ca, diameter, LOD, m);
}
}
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
{ {
Mesh mesh = null; Mesh mesh = null;