//================================================== ==========================
// Prim Face Creation Code
//
// For Use with Jeffrey Gomez's OBJ Model Importer For Second Life
//
// For Usage Instructions, Rights, and Other Relevant Info, See Other Script.
//
// Major Variables:
//
float thickness = 0.01; //Thickness of each face.
string sim = ""; //Desired sim for script; Initialization only!
//================================================== ==========================
warpPos( vector destpos)
{ //R&D by Keknehv Psaltery, 05/25/2006
//with a little pokeing by Strife, and a bit more
//some more munging by Talarus Luan
//Final cleanup by Keknehv Psaltery
// Compute the number of jumps necessary
integer jumps = (integer)(llVecDist(destpos, llGetPos()) / 10.0) + 1;
// Try and avoid stack/heap collisions
if (jumps > 100 )
jumps = 100; // 1km should be plenty
list rules = [ PRIM_POSITION, destpos ]; //The start for the rules list
integer count = 1;
while ( ( count = count << 1 ) < jumps)
rules = (rules=[]) + rules + rules; //should tighten memory use.
llSetPrimitiveParams( rules + llList2List( rules, (count - jumps) << 1, count) );
if ( llVecDist( llGetPos(), destpos ) > .001 ) //Failsafe
while ( --jumps )
llSetPos( destpos );
}
vector Proj(vector u, vector v) {
// Return the projection of u onto v.
// Special Thanks to Xylor Baysklef for jogging my memory on this
return ( (u * v) / (v * v) ) * v;
}
vector crossProduct(vector one, vector two)
{
//================================================== ======================
// This returns a Cross Product of two vectors. If you have no idea what
// that means, look it up.
//
// Note no actual call to this function exists. This is because it exists
// in LSL's modulus (%) command. It's simply from old code.
//================================================== ======================
return <

one.y * two.z) - (one.z * two.y),(one.z * two.x) - (one.x * two.z),(one.x * two.y) - (one.y * two.x)>;
}
integer g_listener = FALSE; //Just a measly listener. Ho hum. Don't hurt me.
default
{
on_rez(integer param)
{
if(param)
{
integer param = llGetStartParameter();
g_listener = llListen(param,"","",""

;
llSay(param, "on_rez"

;
sim = llGetRegionName();
}
}
//================================================== ======================
// Most of the hard stuff happens here. I'll explain it each time we run
// across something, so if you don't understand it, that's my fault.
// This data is called by a listener event, the listener of which is
// promptly removed to save server load and keep faces from listening to
// every command. Trust me, I had that happen. It wasn't pretty.
//================================================== ======================
listen(integer chan, string name, key id, string msg)
{
llListenRemove(g_listener);
//================================================== ==================
//
// Phase One: Get Our Vectors
//
// Nothing unduly interesting here. We just take our string and get
// the vector values we want from them.
//
//================================================== ==================
vector vector1 = (vector)llGetSubString(msg,0,llSubStringIndex(msg, ">"

);
msg = llDeleteSubString(msg,0,llSubStringIndex(msg,">"

);
vector vector2 = (vector)llGetSubString(msg,0,llSubStringIndex(msg, ">"

);
msg = llDeleteSubString(msg,0,llSubStringIndex(msg,">"

);
vector vector3 = (vector)llGetSubString(msg,0,llSubStringIndex(msg, ">"

);
//================================================== ==================
//
// Phase Two: Edge Detection Calls
//
// Now comes the fun stuff. Since we've been passed our largest edge,
// vector one and two, which prevents our script from causing problems
// later, we now need to find which edge is closer to the odd vector
// out (vector3). We do this because the smallest edge, or closest
// vector, to it will make for a handy little edge on a 3D parallelo-
// gram that we have to construct to find out points in this script
//
// If you're not lost yet, don't worry. There are plenty of places
// along the way to fall off the bus. =]
//
//================================================== ==================
float edge1 = llVecMag(vector1 - vector3);
float edge2 = llVecMag(vector2 - vector3);
vector vect = (vector1 + vector2 + vector3) / 3;
//Failsafe initialization
//This constructs the last edge of our parallelogram.
if(edge1 < edge2)
{
vect = vector3 - vector1;
vect += vector2;
}
else
{
vect = vector3 - vector2;
vect += vector1;
}
//================================================== ==================
//
// Phase Three: Lots of Stuff Happens
//
// No better way to put it. Now, the reason we created that 3D
// parallelogram (remember? That shape in math class that everyone
// just called a crooked box) is because it's a pretty handy shape,
// since the corners all have the same angle and, more importantly,
// we can use one to find out the center of mass of the face!
//
// And now, for those of you that flunked math class. Center of Mass
// is just a really long way of saying "Average Them, Stupid."
//
// Unfortunately, even with that center, we're not done. Once we have
// it, we have to find the Primitive Center that Second Life uses.
// That's a little harder. To do that, we borrow something from
// Linear Algebra: Projections. Basically, we take a point in 3D and
// project it onto a line, find where it is on the line, and go from
// there.
//
// Said number will give us the value we can use to find Second Life's
// center, or a fair approximation (see below). We then go from the
// center of vectors one and two to the distance we just found.
//
// And that, ladies and gentlemen, is our center! *applause*
//
//================================================== ==================
vector duoCenter = (vector1 + vector2) / 2;
vector Center = (vector1 + vector2 + vector3 + vect) / 4;
vector dot = vector1 + Proj(Center - vector1,vector2 - vector1);
vector Center2 = duoCenter + (Center - dot);
//================================================== ==================
//
// Phase Four: The Reason You Flunked Physics Class
//
// This is rather hard to explain. Simply put, though, a Cross Product
// does something very, very very very very ... helpful for us here:
//
// It gives us a place to go.
//
// Okay. What it does for us here isn't quite that simple. Actually,
// what it does for us is take our values, and extends an axis
// perpendicular to them. That might not sound like much here, but
// that does something really important, because the Linden sponsored
// command, llAxes2Rot, turns axes into a rotation! Thanks, Lindens!
//
// </shameless plug>
//
// Anyway, after we do that, we finally go to where we want to go
// and rotate to the proper rotation.
//
//================================================== ==================
vector fwd = ((vector2 - duoCenter) / llVecMag(vector2 - duoCenter)) % ((Center - dot) / llVecMag(Center - dot));
rotation rot = llAxes2Rot(fwd,((Center - dot) / llVecMag(Center - dot)) % fwd,(Center - dot) / llVecMag(Center - dot));
//vector pos = llGetPos();
//integer i = 0;
//while(pos + Center2 != llGetPos())
//{
//i += 1;
//if(llGetRegionName() != sim) llDie();
//llSetPos(pos + Center2);
//if(i >= 100) llDie();
//}
//llSetPos(pos + Center2);
warpPos(llGetPos() + Center2);
llSetRot(rot);
//================================================== ==================
//
// Phase Final: "Tri" Means "Three"
//
// This took me a little while to figure out. What we do now is take
// all of our data from above, and put a new dot on that imaginary
// parallelogram, right on the edge between vector3 and the last
// corner that we made earlier. We do this to toy with the Top Shear
// value of a prim to emulate the final vertex. To do that, we just
// see how far vector3 is from that new dot, and convert it to
// something Second Life understands.
//
// Once that's done, we get to resize and reshape our prim, and we're
// done!
//
// ... but wait, now all I have is a triangle!
//
// Ah, but that's the beauty of it. See, all those little triangles
// will now take the shape of whatever your original object was!
//
//================================================== ==================
vector transpose = Center2 + (Center - dot);
float shear = llVecMag(transpose - vector3) / llVecMag(vector2 - vector1);
if(llVecMag(vector1 - dot) > llVecMag(vector2 - dot)) shear *= -1;
vector size = <thickness,2 * llVecMag(vector2 - duoCenter),2 * llVecMag(dot - Center)>;
llSetPrimitiveParams([PRIM_SIZE,size]);
llSetPrimitiveParams([PRIM_TYPE,PRIM_TYPE_BOX,00,<0.000000, 1.000000, 0.000000>,0.000000,<0.000000, 0.000000, 0.000000>,<1.000000, 0.000000, 0.000000>,<0.000000, shear, 0.000000>]);
integer j;
integer tot = llGetInventoryNumber(INVENTORY_SCRIPT);
for(j = 0; j < tot; j++)
{
if(llGetInventoryName(INVENTORY_SCRIPT,j) != llGetScriptName())
llRemoveInventory(llGetInventoryName(INVENTORY_SCRIPT,j));
}
llRemoveInventory(llGetScriptName());
}
}