llSetPrimitiveParams Prim type params precision errors

remove-scene-viewer
Micheil Merlin 2011-09-04 12:21:29 -05:00 committed by Justin Clark-Casey (justincc)
parent bea2e0f32b
commit 28961dd1cf
2 changed files with 90 additions and 44 deletions

View File

@ -6570,6 +6570,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
{ {
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
@ -6651,8 +6652,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
twist.y = 1.0f; twist.y = 1.0f;
} }
shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x); // A fairly large precision error occurs for some calculations,
shapeBlock.PathTwist = (sbyte)(100 * twist.y); // if a float or double is directly cast to a byte or sbyte
// variable, in both .Net and Mono. In .Net, coding
// "(sbyte)(float)(some expression)" corrects the precision
// errors. But this does not work for Mono. This longer coding
// form of creating a tempoary float variable from the
// expression first, then casting that variable to a byte or
// sbyte, works for both .Net and Mono. These types of
// assignments occur in SetPrimtiveBlockShapeParams and
// SetPrimitiveShapeParams in support of llSetPrimitiveParams.
tempFloat = (float)(100.0d * twist.x);
shapeBlock.PathTwistBegin = (sbyte)tempFloat;
tempFloat = (float)(100.0d * twist.y);
shapeBlock.PathTwist = (sbyte)tempFloat;
shapeBlock.ObjectLocalID = part.LocalId; shapeBlock.ObjectLocalID = part.LocalId;
@ -6663,6 +6676,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Prim type box, cylinder and prism. // Prim type box, cylinder and prism.
protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve)
{ {
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock; ObjectShapePacket.ObjectDataBlock shapeBlock;
shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@ -6683,8 +6697,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
taper_b.y = 2f; taper_b.y = 2f;
} }
shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x)); tempFloat = (float)(100.0d * (2.0d - taper_b.x));
shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y)); shapeBlock.PathScaleX = (byte)tempFloat;
tempFloat = (float)(100.0d * (2.0d - taper_b.y));
shapeBlock.PathScaleY = (byte)tempFloat;
if (topshear.x < -0.5f) if (topshear.x < -0.5f)
{ {
topshear.x = -0.5f; topshear.x = -0.5f;
@ -6701,8 +6717,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
topshear.y = 0.5f; topshear.y = 0.5f;
} }
shapeBlock.PathShearX = (byte)(100 * topshear.x); tempFloat = (float)(100.0d * topshear.x);
shapeBlock.PathShearY = (byte)(100 * topshear.y); shapeBlock.PathShearX = (byte)tempFloat;
tempFloat = (float)(100.0d * topshear.y);
shapeBlock.PathShearY = (byte)tempFloat;
part.Shape.SculptEntry = false; part.Shape.SculptEntry = false;
part.UpdateShape(shapeBlock); part.UpdateShape(shapeBlock);
@ -6752,6 +6770,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Prim type torus, tube and ring. // Prim type torus, tube and ring.
protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve)
{ {
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock; ObjectShapePacket.ObjectDataBlock shapeBlock;
shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@ -6776,8 +6795,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
holesize.y = 0.5f; holesize.y = 0.5f;
} }
shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x)); tempFloat = (float)(100.0d * (2.0d - holesize.x));
shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y)); shapeBlock.PathScaleX = (byte)tempFloat;
tempFloat = (float)(100.0d * (2.0d - holesize.y));
shapeBlock.PathScaleY = (byte)tempFloat;
if (topshear.x < -0.5f) if (topshear.x < -0.5f)
{ {
topshear.x = -0.5f; topshear.x = -0.5f;
@ -6794,8 +6815,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
topshear.y = 0.5f; topshear.y = 0.5f;
} }
shapeBlock.PathShearX = (byte)(100 * topshear.x); tempFloat = (float)(100.0d * topshear.x);
shapeBlock.PathShearY = (byte)(100 * topshear.y); shapeBlock.PathShearX = (byte)tempFloat;
tempFloat = (float)(100.0d * topshear.y);
shapeBlock.PathShearY = (byte)tempFloat;
if (profilecut.x < 0f) if (profilecut.x < 0f)
{ {
profilecut.x = 0f; profilecut.x = 0f;
@ -6839,8 +6862,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
taper_a.y = 1f; taper_a.y = 1f;
} }
shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x); tempFloat = (float)(100.0d * taper_a.x);
shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y); shapeBlock.PathTaperX = (sbyte)tempFloat;
tempFloat = (float)(100.0d * taper_a.y);
shapeBlock.PathTaperY = (sbyte)tempFloat;
if (revolutions < 1f) if (revolutions < 1f)
{ {
revolutions = 1f; revolutions = 1f;
@ -6849,7 +6874,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
revolutions = 4f; revolutions = 4f;
} }
shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0)); tempFloat = 66.66667f * (revolutions - 1.0f);
shapeBlock.PathRevolutions = (byte)tempFloat;
// limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
if (radiusoffset < 0f) if (radiusoffset < 0f)
{ {
@ -6859,7 +6885,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
radiusoffset = 1f; radiusoffset = 1f;
} }
shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset); tempFloat = 100.0f * radiusoffset;
shapeBlock.PathRadiusOffset = (sbyte)tempFloat;
if (skew < -0.95f) if (skew < -0.95f)
{ {
skew = -0.95f; skew = -0.95f;
@ -6868,7 +6895,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
skew = 0.95f; skew = 0.95f;
} }
shapeBlock.PathSkew = (sbyte)(100 * skew); tempFloat = 100.0f * skew;
shapeBlock.PathSkew = (sbyte)tempFloat;
part.Shape.SculptEntry = false; part.Shape.SculptEntry = false;
part.UpdateShape(shapeBlock); part.UpdateShape(shapeBlock);
@ -7681,10 +7709,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
// float revolutions // float revolutions
res.Add(new LSL_Float((Shape.PathRevolutions * 0.015) + 1.0)); // Slightly inaccurate, because an unsigned res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
// byte is being used to represent the entire // Slightly inaccurate, because an unsigned byte is being used to represent
// range of floating-point values from 1.0 // the entire range of floating-point values from 1.0 through 4.0 (which is how
// through 4.0 (which is how SL does it). // SL does it).
//
// Using these formulas to store and retrieve PathRevolutions, it is not
// possible to use all values between 1.00 and 4.00. For instance, you can't
// represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
// use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
// with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
// behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
// In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
// such as 1.10. So, SL must store and retreive the actual user input rather
// than only storing the encoded value.
// float radiusoffset // float radiusoffset
res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));

View File

@ -49,7 +49,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6; private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
private const double FLOAT_ACCURACY = 0.00005d; private const float FLOAT_ACCURACY = 0.00005f;
private LSL_Api m_lslApi; private LSL_Api m_lslApi;
[SetUp] [SetUp]
@ -194,10 +194,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
0.80d, // Prim hollow 0.80f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
0.80d); // Prim hollow check 0.80f); // Prim hollow check
// Test a prism. // Test a prism.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -206,11 +206,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.90d, // Prim hollow 0.90f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.90d); // Prim hollow check 0.90f); // Prim hollow check
// Test a box. // Test a box.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -219,11 +219,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_BOX, // Prim type ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95d, // Prim hollow 0.95f, // Prim hollow
new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.95d); // Prim hollow check 0.95f); // Prim hollow check
// Test a tube. // Test a tube.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -232,16 +232,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.00d, // Prim hollow 0.00f, // Prim hollow
new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(1.0d, 0.5d, 0.0d), // Prim hole size new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear // Expression for y selected to test precision problems during byte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
new LSL_Types.Vector3(-1.0d, 1.0d, 0.0d), // Prim taper // Expression for y selected to test precision problems during sbyte
1.0d, // Prim revolutions // cast in SetPrimitiveShapeParams.
1.0d, // Prim radius new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
0.0d, // Prim skew 1.11f, // Prim revolutions
0.00d); // Prim hollow check 0.88f, // Prim radius
0.95f, // Prim skew
0.00f); // Prim hollow check
// Test a prism. // Test a prism.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -250,11 +254,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95d, // Prim hollow 0.95f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist // Expression for x selected to test precision problems during sbyte
new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper // cast in SetPrimitiveShapeBlockParams.
new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
// Expression for y selected to test precision problems during sbyte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.70d); // Prim hollow check 0.70f); // Prim hollow check
// Test a sculpted prim. // Test a sculpted prim.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -268,8 +276,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
// Set prim params for a box, cylinder or prism and check results. // Set prim params for a box, cylinder or prism and check results.
public void CheckllSetPrimitiveParams(string primTest, public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
double primHollowCheck) float primHollowCheck)
{ {
// Set the prim params. // Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@ -297,7 +305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
// Set prim params for a sphere and check results. // Set prim params for a sphere and check results.
public void CheckllSetPrimitiveParams(string primTest, public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, double primHollowCheck) float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
{ {
// Set the prim params. // Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@ -324,9 +332,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
// Set prim params for a torus, tube or ring and check results. // Set prim params for a torus, tube or ring and check results.
public void CheckllSetPrimitiveParams(string primTest, public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize, float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
double primRev, double primRadius, double primSkew, double primHollowCheck) float primRev, float primRadius, float primSkew, float primHollowCheck)
{ {
// Set the prim params. // Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@ -353,7 +361,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut"); CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut");
CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper"); CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY, Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim revolution fail"); "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY, Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim radius fail"); "TestllSetPrimitiveParams " + primTest + " prim radius fail");
Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY, Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY,