Fafnir, I have
a script that does exactly this. Unfortunately, several people decided to take up arms against me about it, so I took it down.
This may be a good prompt to share the revised code I've made, which evades the problem that they complained at me for. I'll be adding that to the posted link presently.
Let's discuss the core of how this is done.
First, you will want to mirror the actual position of the object. This requires a little vector math:
vector pos = ((reference point here) - llGetPos()) / llGetRot();
rotation rot = (reference rotation here) / llGetRot();
This will give you an unbiased position and rotation versus your reference point.
If you're lost, the reference point is essentially the point, in space, that you will be mirroring through. Think of it as a tall glass mirror, with the inverted image on the other side.
Now, here are the actual transformations:
For a cube, prism, or cylinder:
vector rot2 = llRot2Euler(rot);
cut = <1 - cut.y, 1 - cut.x, 0>;
topshear = <topshear.y,topshear.x,0>;
topsize = <topsize.y,topsize.x,0>;
twist *= -1;
size = <size.y,size.x,size.z>;
// "X","Y", and "Z" denote the axes the object is mirrored over
if(mirror == "X")
{
pos.x *= -1;
rot2.y *= -1;
rot2.z *= -1;
rot = <0.00000, 0.00000, 0.70711, 0.70711> * llEuler2Rot(rot2);
}
else if(mirror == "Y")
{
pos.y *= -1;
rot2.x *= -1;
rot2.z *= -1;
rot = <0.00000, 0.00000, -0.70711, 0.70711> * llEuler2Rot(rot2);
}
else if(mirror == "Z")
{
pos.z *= -1;
rot2.x *= -1;
rot2.y *= -1;
rot = <-0.70711, -0.70711, -0.00000, 0.00000> * llEuler2Rot(rot2);
}
For a cylinder and a prism, this needs to be added. This is a little inefficient, since it basically is undoing some stuff we did already. Regardless:
if(type == 2 || type == 1)
{
topshear = <topshear.y,-1 * topshear.x,0>;
topsize = <topsize.y,topsize.x,0>;
rot2 = llRot2Euler(rot);
rot2.z += PI_BY_TWO;
rot = llEuler2Rot(rot2);
size = <size.y,size.x,size.z>;
}
And then you basically end up doing this for a cube, prism, or cylinder:
pos = llGetPos() + (pos * llGetRot());
rot = rot * llGetRot();
params = [pos,rot,size,type,holeshape,cut,hollow,twist,topsize,topshear];
If we have a sphere, we need to do this:
vector rot2 = llRot2Euler(rot);
cut = <1 - cut.y, 1 - cut.x, 0>;
twist = <twist.y,twist.x,0>;
if(mirror == "X")
{
pos.x *= -1;
rot2.z *= -1;
rot2.y *= -1;
rot = <-0.00000, -1.00000, -0.00000, 0.00000> * llEuler2Rot(rot2);
}
else if(mirror == "Y")
{
pos.y *= -1;
rot2.x *= -1;
rot2.z *= -1;
rot = <1.00000, -0.00000, -0.00000, 0.00000> * llEuler2Rot(rot2);
}
else if(mirror == "Z")
{
pos.z *= -1;
rot2.x *= -1;
rot2.y *= -1;
rot = llEuler2Rot(rot2);
}
pos = llGetPos() + (pos * llGetRot());
rot = rot * llGetRot();
params = [pos,rot,size,type,holeshape,cut,hollow,twist,dimple];
And for everything else (ring, torus, etc), we do this:
cut = <1 - cut.y, 1 - cut.x, 0>;
twist = <twist.y,twist.x,0>;
topshear = <topshear.x * -1,topshear.y * -1,0>;
taper *= -1;
radiusoffset *= -1;
skew *= -1;
if(mirror == "X")
{
vector rot2 = llRot2Euler(rot);
rot2.y *= -1;
rot2.y += PI;
rot = llEuler2Rot(rot2);
pos.x *= -1;
}
else if(mirror == "Y")
{
pos.y *= -1;
vector rot2 = llRot2Euler(rot);
rot2.x *= -1;
rot2.x += PI;
rot2.y *= -1;
rot = llEuler2Rot(rot2);
}
else if(mirror == "Z")
{
pos.z *= -1;
vector rot2 = llRot2Euler(rot);
rot2.x *= -1;
rot2 += <PI,PI,PI>;
rot = llEuler2Rot(rot2);
}
pos = llGetPos() + (pos * llGetRot());
rot = rot * llGetRot();
params = [pos,rot,size,type,holeshape,cut,hollow,twist,holesize,topshear];
params2 = [advancedcut,taper,revolutions,radiusoffset,skew];
// Basically, combine params and params2
I'm guessing that's a bit hard to digest, so I'll post the "fixed" code up now and give you a copy to fiddle with in-world.