Replaced a lot of trig calls with lookup tables for common prim types in an attempt to improve meshing speed.

Added a new between points interpolation method to improve accuracy of profile cuts in triangle and square profile prims.
0.6.0-stable
Dahlia Trimble 2008-09-05 16:38:51 +00:00
parent 8e6062631c
commit 0fc618e7b2
1 changed files with 202 additions and 43 deletions

View File

@ -79,10 +79,137 @@ namespace OpenSim.Region.Physics.Meshing
} }
} }
//internal float angles3[][] = [
//[0.0f, 1.0f, 0.0f],
//[0.33333333333333331f, -0.49999999999999978f, 0.86602540378443871f],
//[0.66666666666666663f, -0.50000000000000044f, -0.86602540378443837f],
//[1.0f, 1.0f, -2.4492127076447545e-016f]];
/*
angles3 = [
[0.0, 1.0, 0.0],
[0.33333333333333331, -0.49999999999999978, 0.86602540378443871],
[0.66666666666666663, -0.50000000000000044, -0.86602540378443837],
[1.0, 1.0, -2.4492127076447545e-016]]
angles4 = [
[0.0, 1.0, 0.0],
[0.25, 0.0, 1.0],
[0.5, -1.0, 0.0],
[0.75, 0.0, -1.0],
[1.0, 1.0, 0.0]]
angles24 = [
[0.0, 0.5, 0.0],
[0.041666666666666664, 0.48296291314453416, 0.12940952255126037],
[0.083333333333333329, 0.43301270189221935, 0.25],
[0.125, 0.35355339059327379, 0.35355339059327373],
[0.16666666666666666, 0.25, 0.4330127018922193],
[0.20833333333333331, 0.12940952255126048, 0.4829629131445341],
[0.25, 0.0, 0.5],
[0.29166666666666663, -0.12940952255126031, 0.48296291314453416],
[0.33333333333333331, -0.25, 0.43301270189221935],
[0.375, -0.35355339059327373, 0.35355339059327379],
[0.41666666666666663, -0.43301270189221924, 0.25],
[0.45833333333333331, -0.4829629131445341, 0.12940952255126051],
[0.5, -0.5, 0.0],
[0.54166666666666663, -0.48296291314453421, -0.12940952255126018],
[0.58333333333333326, -0.43301270189221941, -0.25],
[0.62499999999999989, -0.35355339059327395, -0.35355339059327356],
[0.66666666666666663, -0.25, -0.43301270189221919],
[0.70833333333333326, -0.12940952255126076, -0.48296291314453405],
[0.75, 0.0, -0.5],
[0.79166666666666663, 0.12940952255126015, -0.48296291314453421],
[0.83333333333333326, 0.25, -0.43301270189221952],
[0.875, 0.35355339059327368, -0.35355339059327384],
[0.91666666666666663, 0.43301270189221919, -0.25],
[0.95833333333333326, 0.48296291314453405, -0.12940952255126079],
[1.0, 0.5, 0.0]]
angles24 = [
[0.0, 1.0, 0.0],
[0.041666666666666664, 0.96592582628906831, 0.25881904510252074],
[0.083333333333333329, 0.86602540378443871, 0.5],
[0.125, 0.70710678118654757, 0.70710678118654746],
[0.16666666666666667, 0.5, 0.8660254037844386],
[0.20833333333333331, 0.25881904510252096, 0.9659258262890682],
[0.25, 6.1230317691118863e-017, 1.0],
[0.29166666666666663, -0.25881904510252063, 0.96592582628906831],
[0.33333333333333333, -0.5, 0.86602540378443871],
[0.375, -0.70710678118654746, 0.70710678118654757],
[0.41666666666666663, -0.86602540378443849, 0.5],
[0.45833333333333331, -0.9659258262890682, 0.25881904510252102],
[0.5, -1.0, 1.2246063538223773e-016],
[0.54166666666666663, -0.96592582628906842, -0.25881904510252035],
[0.58333333333333326, -0.86602540378443882, -0.5],
[0.62499999999999989, -0.70710678118654791, -0.70710678118654713],
[0.66666666666666667, -0.5, -0.86602540378443837],
[0.70833333333333326, -0.25881904510252152, -0.96592582628906809],
[0.75, -1.8369095307335659e-016, -1.0],
[0.79166666666666663, 0.2588190451025203, -0.96592582628906842],
[0.83333333333333326, 0.5, -0.86602540378443904],
[0.875, 0.70710678118654735, -0.70710678118654768],
[0.91666666666666663, 0.86602540378443837, -0.5],
[0.95833333333333326, 0.96592582628906809, -0.25881904510252157],
[1.0, 1.0, -2.4492127076447545e-016]]
*/
internal class AngleList internal class AngleList
{ {
private float iX, iY; // intersection point private float iX, iY; // intersection point
private Angle[] angles3 =
{
new Angle(0.0f, 1.0f, 0.0f),
new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
new Angle(1.0f, 1.0f, 0.0f)
};
private Angle[] angles4 =
{
new Angle(0.0f, 1.0f, 0.0f),
new Angle(0.25f, 0.0f, 1.0f),
new Angle(0.5f, -1.0f, 0.0f),
new Angle(0.75f, 0.0f, -1.0f),
new Angle(1.0f, 1.0f, 0.0f)
};
private Angle[] angles24 =
{
new Angle(0.0f, 1.0f, 0.0f),
new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f),
new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f),
new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f),
new Angle(0.25f, 0.0f, 1.0f),
new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f),
new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f),
new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f),
new Angle(0.5f, -1.0f, 0.0f),
new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f),
new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f),
new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f),
new Angle(0.75f, 0.0f, -1.0f),
new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f),
new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f),
new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f),
new Angle(1.0f, 1.0f, 0.0f)
};
private Angle interpolatePoints(float newPoint, Angle p1, Angle p2)
{
float m = (newPoint - p1.angle) / (p2.angle - p1.angle);
return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y));
}
private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{ // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
@ -98,64 +225,96 @@ namespace OpenSim.Region.Physics.Meshing
internal List<Angle> angles; internal List<Angle> angles;
// this class should have a table of most commonly computed values
// instead of all the trig function calls
// most common would be for sides = 3, 4, or 24
internal void makeAngles( int sides, float startAngle, float stopAngle ) internal void makeAngles( int sides, float startAngle, float stopAngle )
{ {
angles = new List<Angle>(); angles = new List<Angle>();
double twoPi = System.Math.PI * 2.0; double twoPi = System.Math.PI * 2.0;
float twoPiInv = 1.0f / (float)twoPi;
if (sides < 1) if (sides < 1)
throw new Exception("number of sides not greater than zero"); throw new Exception("number of sides not greater than zero");
if (stopAngle <= startAngle) if (stopAngle <= startAngle)
throw new Exception("stopAngle not greater than startAngle"); throw new Exception("stopAngle not greater than startAngle");
double stepSize = twoPi / sides; if ((sides == 3 || sides == 4 || sides == 24))
int startStep = (int) (startAngle / stepSize);
double angle = stepSize * startStep;
int step = startStep;
double stopAngleTest = stopAngle;
if (stopAngle < twoPi)
{ {
stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1); startAngle *= twoPiInv;
if (stopAngleTest < stopAngle) stopAngle *= twoPiInv;
stopAngleTest += stepSize;
if (stopAngleTest > twoPi) Angle[] sourceAngles;
stopAngleTest = twoPi; if (sides == 3)
sourceAngles = angles3;
else if (sides == 4)
sourceAngles = angles4;
else sourceAngles = angles24;
int startAngleIndex = (int)(startAngle * sides);
int endAngleIndex = sourceAngles.Length - 1;
if (stopAngle < 1.0f)
endAngleIndex = (int)(stopAngle * sides) + 1;
if (endAngleIndex == startAngleIndex)
endAngleIndex++;
for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++)
angles.Add(sourceAngles[angleIndex]);
if (startAngle > 0.0f)
angles[0] = interpolatePoints(startAngle, angles[0], angles[1]);
if (stopAngle < 1.0f)
{
int lastAngleIndex = angles.Count - 1;
angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]);
}
} }
else
while (angle <= stopAngleTest)
{ {
Angle newAngle; double stepSize = twoPi / sides;
newAngle.angle = (float) angle;
newAngle.X = (float) System.Math.Cos(angle);
newAngle.Y = (float) System.Math.Sin(angle);
angles.Add(newAngle);
step += 1;
angle = stepSize * step;
}
if (startAngle > angles[0].angle) int startStep = (int)(startAngle / stepSize);
{ double angle = stepSize * startStep;
Angle newAngle; int step = startStep;
intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle)); double stopAngleTest = stopAngle;
newAngle.angle = startAngle; if (stopAngle < twoPi)
newAngle.X = iX; {
newAngle.Y = iY; stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1);
angles[0] = newAngle; if (stopAngleTest < stopAngle)
} stopAngleTest += stepSize;
if (stopAngleTest > twoPi)
stopAngleTest = twoPi;
}
int index = angles.Count - 1; while (angle <= stopAngleTest)
if (stopAngle < angles[index].angle) {
{ Angle newAngle;
Angle newAngle; newAngle.angle = (float)angle;
intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle)); newAngle.X = (float)System.Math.Cos(angle);
newAngle.angle = stopAngle; newAngle.Y = (float)System.Math.Sin(angle);
newAngle.X = iX; angles.Add(newAngle);
newAngle.Y = iY; step += 1;
angles[index] = newAngle; angle = stepSize * step;
}
if (startAngle > angles[0].angle)
{
Angle newAngle;
intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle));
newAngle.angle = startAngle;
newAngle.X = iX;
newAngle.Y = iY;
angles[0] = newAngle;
}
int index = angles.Count - 1;
if (stopAngle < angles[index].angle)
{
Angle newAngle;
intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle));
newAngle.angle = stopAngle;
newAngle.X = iX;
newAngle.Y = iY;
angles[index] = newAngle;
}
} }
} }
} }