rewrote hanging llParseStringKeepNulls()

avinationmerge
Mike Rieker 2010-07-06 02:22:47 +00:00
parent 6c6c7b0927
commit 90c5555d6d
1 changed files with 139 additions and 164 deletions

View File

@ -562,23 +562,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
double sqx = q1.x*q1.x; double sqx = q1.x*q1.x;
double sqy = q1.z*q1.z; double sqy = q1.z*q1.z;
double sqz = q1.y*q1.y; double sqz = q1.y*q1.y;
double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
double test = q1.x*q1.z + q1.y*q1.s; double test = q1.x*q1.z + q1.y*q1.s;
if (test > 0.4999*unit) { // singularity at north pole if (test > 0.4999*unit) { // singularity at north pole
eul.z = 2 * Math.Atan2(q1.x,q1.s); eul.z = 2 * Math.Atan2(q1.x,q1.s);
eul.y = Math.PI/2; eul.y = Math.PI/2;
eul.x = 0; eul.x = 0;
return eul; return eul;
} }
if (test < -0.4999*unit) { // singularity at south pole if (test < -0.4999*unit) { // singularity at south pole
eul.z = -2 * Math.Atan2(q1.x,q1.s); eul.z = -2 * Math.Atan2(q1.x,q1.s);
eul.y = -Math.PI/2; eul.y = -Math.PI/2;
eul.x = 0; eul.x = 0;
return eul; return eul;
} }
eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw); eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
eul.y = Math.Asin(2*test/unit); eul.y = Math.Asin(2*test/unit);
eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw); eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
return eul; return eul;
} }
@ -804,51 +804,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// This method mimics the 180 errors found in SL // This method mimics the 180 errors found in SL
// See www.euclideanspace.com... angleBetween // See www.euclideanspace.com... angleBetween
LSL_Vector vec_a = a; LSL_Vector vec_a = a;
LSL_Vector vec_b = b; LSL_Vector vec_b = b;
// Eliminate zero length // Eliminate zero length
LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a); LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b); LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
if (vec_a_mag < 0.00001 || if (vec_a_mag < 0.00001 ||
vec_b_mag < 0.00001) vec_b_mag < 0.00001)
{ {
return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
} }
// Normalize // Normalize
vec_a = llVecNorm(vec_a); vec_a = llVecNorm(vec_a);
vec_b = llVecNorm(vec_b); vec_b = llVecNorm(vec_b);
// Calculate axis and rotation angle // Calculate axis and rotation angle
LSL_Vector axis = vec_a % vec_b; LSL_Vector axis = vec_a % vec_b;
LSL_Float cos_theta = vec_a * vec_b; LSL_Float cos_theta = vec_a * vec_b;
// Check if parallel // Check if parallel
if (cos_theta > 0.99999) if (cos_theta > 0.99999)
{ {
return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
} }
// Check if anti-parallel // Check if anti-parallel
else if (cos_theta < -0.99999) else if (cos_theta < -0.99999)
{ {
LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a); LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0); if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0); return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
} }
else // other rotation else // other rotation
{ {
LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f; LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
axis = llVecNorm(axis); axis = llVecNorm(axis);
double x, y, z, s, t; double x, y, z, s, t;
s = Math.Cos(theta); s = Math.Cos(theta);
t = Math.Sin(theta); t = Math.Sin(theta);
x = axis.x * t; x = axis.x * t;
y = axis.y * t; y = axis.y * t;
z = axis.z * t; z = axis.z * t;
return new LSL_Rotation(x,y,z,s); return new LSL_Rotation(x,y,z,s);
} }
} }
public void llWhisper(int channelID, string text) public void llWhisper(int channelID, string text)
@ -8627,130 +8627,105 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
{ {
int beginning = 0; int srclen = src.Length;
int srclen = src.Length; int seplen = separators.Length;
int seplen = separators.Length; object[] separray = separators.Data;
object[] separray = separators.Data; int spclen = spacers.Length;
int spclen = spacers.Length; object[] spcarray = spacers.Data;
object[] spcarray = spacers.Data;
int mlen = seplen+spclen;
int[] offset = new int[mlen+1]; int outlen = 0;
bool[] active = new bool[mlen]; LSL_String[] outarray = new LSL_String[srclen*2+1];
int best; int i, j, lastUsed;
int j;
// Initial capacity reduces resize cost
LSL_List tokens = new LSL_List();
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// All entries are initially valid /*
* Point to beginning of current non-delimeter string.
*/
lastUsed = 0;
for (int i = 0; i < mlen; i++) /*
active[i] = true; * Scan through source string from beginning to end.
*/
for (i = 0; i < srclen;) {
offset[mlen] = srclen; /*
* See if rest of string (starting at i) matches any separator.
*/
string rest = src.Substring(i);
for (j = 0; j < seplen; j ++) {
string sep = separray[j].ToString();
if ((sep.Length > 0) && rest.StartsWith(sep)) {
while (beginning < srclen) /*
{ * Separator matched, output string from end of last delimeter to beginning of this one.
*/
outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed));
best = mlen; // as bad as it gets /*
* Remove separator from input string.
*/
i += sep.Length;
// Scan for separators /*
* Next non-delimeter starts where this separator left off.
for (j = 0; j < seplen; j++) */
{ lastUsed = i;
if (active[j]) goto nextsrc;
{
// scan all of the markers
if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1)
{
// not present at all
active[j] = false;
}
else
{
// present and correct
if (offset[j] < offset[best])
{
// closest so far
best = j;
if (offset[best] == beginning)
break;
}
}
} }
} }
// Scan for spacers /*
* See if rest of string (starting at i) matches any spacer.
*/
for (j = 0; j < spclen; j ++) {
string spc = spcarray[j].ToString();
if ((spc.Length > 0) && rest.StartsWith(spc)) {
if (offset[best] != beginning) /*
{ * Spacer matched, output string from end of last delimeter to beginning of this one.
for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) * Then output the spacer itself.
{ */
if (active[j]) outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed));
{ outarray[outlen++] = new LSL_String(spc);
// scan all of the markers
if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1) /*
{ * Remove spacer from input string.
// not present at all */
active[j] = false; i += spc.Length;
}
else /*
{ * Next non-delimeter starts where this spacer left off.
// present and correct */
if (offset[j] < offset[best]) lastUsed = i;
{ goto nextsrc;
// closest so far
best = j;
}
}
}
} }
} }
// This is the normal exit from the scanning loop /*
* Didn't match any separator or spacer, skip over it and it
if (best == mlen) * becomes part of the non-delimeter string starting with
{ * lastUsed.
// no markers were found on this pass */
// so we're pretty much done i ++;
tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning))); nextsrc:;
break;
}
// Otherwise we just add the newly delimited token
// and recalculate where the search should continue.
tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning)));
if (best < seplen)
{
beginning = offset[best] + (separray[best].ToString()).Length;
}
else
{
beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
tokens.Add(new LSL_String(spcarray[best - seplen].ToString()));
}
} }
// This an awkward an not very intuitive boundary case. If the /*
// last substring is a tokenizer, then there is an implied trailing * Output last non-delimeter (including a possible null string if
// null list entry. Hopefully the single comparison will not be too * delimeter ran to end of source string).
// arduous. Alternatively the 'break' could be replced with a return */
// but that's shabby programming. outarray[outlen++] = new LSL_String(src.Substring(lastUsed));
if (beginning == srclen) /*
{ * Make up an exact-sized output array suitable for an LSL_List object.
if (srclen != 0) */
tokens.Add(new LSL_String("")); object[] outlist = new object[outlen];
for (i = 0; i < outlen; i ++) {
outlist[i] = outarray[i];
} }
return new LSL_List(outlist);
return tokens;
} }
public LSL_Integer llGetObjectPermMask(int mask) public LSL_Integer llGetObjectPermMask(int mask)