Well, I didn't like that functionality. It hurt my brain. ;)
So I've written some of my own methods for it, borrowing a little from
what was in the Mirror class...
Here are my additions if anyone else wants them:
Addition to Object3D.as:
public static const MIRROR_X:int = 1;
public static const MIRROR_Y:int = 2;
public static const MIRROR_Z:int = 4;
/**
* Mirrors the object about an origin
*
* @param _flags
Any combination of MIRROR_X, MIRROR_Y, and
MIRROR_Z which states which axis to mirror along
* @param _origin [optional] The
origin to mirror about. Defaults
to 0,0,0
* @param _duplicate [optional] When
true any container objects are
not manipulated. Instead underlying objects such as 'Mesh' physically
duplicate their geometry in the mirrored position. Defaults to true.
*
*/
public function mirror(_flags:int, _origin:Number3D = null,
_duplicate:Boolean = true):void
{
if (!_duplicate)
{
if (_origin == null)
{
_origin = new Number3D();
}
if ((_flags & MIRROR_X) != 0)
{
_transform.tx = -_transform.tx +
((_origin.x - _transform.tx));
}
if ((_flags & MIRROR_Y) != 0)
{
_transform.ty = -_transform.ty +
((_origin.y - _transform.ty));
}
if ((_flags & MIRROR_Z) != 0)
{
_transform.tz = -_transform.tz +
((_origin.z - _transform.tz));
}
}
}
Addition to ObjectContainer3D.as:
public override function mirror(_flags:int, _origin:Number3D =
null,
_duplicate:Boolean = true):void
{
for each (var child:Object3D in _children)
{
child.mirror(_flags, _origin, _duplicate);
}
super.mirror(_flags, _origin, _duplicate);
}
Addition to Mesh.as:
public override function mirror(_flags:int, _origin:Number3D =
null,
_duplicate:Boolean = true):void
{
var aFaces:Array = faces;
var facecount:int = aFaces.length;
var face:Face;
var va:Vertex;
var vb:Vertex;
var vc:Vertex;
var v0:Vertex;
var v1:Vertex;
var v2:Vertex;
var uvTemp:UV;
var offset:Number3D;
var vax:Number = 0;
var vbx:Number = 0;
var vcx:Number = 0;
var vay:Number = 0;
var vby:Number = 0;
var vcy:Number = 0;
var vaz:Number = 0;
var vbz:Number = 0;
var vcz:Number = 0;
var flipNormals:Boolean = false;
if (_duplicate)
{
if (_origin == null)
{
_origin = new Number3D();
}
var pos:Number3D = scenePosition;
offset = new Number3D((_origin.x - pos.x) * 2,
(_origin.y - pos.y)
* 2, (_origin.z - pos.z) * 2);
}
for (var i:int = 0; i < facecount; i++)
{
flipNormals = false;
face = aFaces[i];
va = face._v0;
vb = face._v1;
vc = face._v2;
if (_duplicate)
{
if ((_flags & MIRROR_X) != 0)
{
vax = -va.x + offset.x;
vbx = -vb.x + offset.x;
vcx = -vc.x + offset.x;
flipNormals = !flipNormals;
}
else
{
vax = va.x;
vbx = vb.x;
vcx = vc.x;
}
if ((_flags & MIRROR_Y) != 0)
{
vay = -va.y + offset.y;
vby = -vb.y + offset.y;
vcy = -vc.y + offset.y;
flipNormals = !flipNormals;
}
else
{
vay = va.y;
vby = vb.y;
vcy = vc.y;
}
if ((_flags & MIRROR_Z) != 0)
{
vaz = -va.z + offset.z;
vbz = -vb.z + offset.z;
vcz = -vc.z + offset.z;
flipNormals = !flipNormals;
}
else
{
vaz = va.z;
vbz = vb.z;
vcz = vc.z;
}
v0 = new Vertex( vax, vay, vaz);
v1 = new Vertex( vbx, vby, vbz);
v2 = new Vertex( vcx, vcy, vcz);
if (flipNormals)
{
addFace(new Face(v1, v0, v2,
face.material, face.uv1, face.uv0,
face.uv2 ) );
}
else
{
addFace(new Face(v0, v1, v2,
face.material, face.uv0, face.uv1,
face.uv2 ) );
}
}
else
{
if ((_flags & MIRROR_X) != 0)
{
vax = -va.x;
vbx = -vb.x;
vcx = -vc.x;
flipNormals = !flipNormals;
}
else
{
vax = va.x;
vbx = vb.x;
vcx = vc.x;
}
if ((_flags & MIRROR_Y) != 0)
{
vay = -va.y;
vby = -vb.y;
vcy = -vc.y;
flipNormals = !flipNormals;
}
else
{
vay = va.y;
vby = vb.y;
vcy = vc.y;
}
if ((_flags & MIRROR_Z) != 0)
{
vaz = -va.z;
vbz = -vb.z;
vcz = -vc.z;
flipNormals = !flipNormals;
}
else
{
vaz = va.z;
vbz = vb.z;
vcz = vc.z;
}
v0 = new Vertex( vax, vay, vaz);
v1 = new Vertex( vbx, vby, vbz);
v2 = new Vertex( vcx, vcy, vcz);
// perhaps have a mirror method in face
as well
if (flipNormals)
{
face.v0 = v1;
face.v1 = v0;
face.v2 = v2;
uvTemp = face.uv0;
face.uv0 = face.uv1;
face.uv1 = uvTemp;
}
else
{
face.v0 = v0;
face.v1 = v1;
face.v2 = v2;
}
}
}
super.mirror(_flags, _origin, _duplicate);
}
The usage is pretty simple:
// X Mirror about the origin
myObject.mirror(Object3D.MIRROR_X);
// Y Mirror about 0,30,0
myObject.mirror(Object3D.MIRROR_Y, new Number3D(0, 30, 0));
// X and Z Mirror about 10,0,10
myObject.mirror(Object3D.MIRROR_X | Object3D.MIRROR_Z, new
Number3D(10, 0, 10));
// X Mirror about 20,0,0 with no duplication
myObject.mirror(Object3D.MIRROR_X, new Number3D(20, 0, 0),
false);
It's recursive and seems to work on any containers, loaded meshes, and
primitives. Having it work on a specified origin also allows for
greater flexibility. I don't mean to state that the Mirror class is
wrong; it just didn't exhibit the behaviour I expected.
Hope this helps someone else out too.
-Wex
On Mar 4, 3:54 pm, Fabrice3D <[email protected]> wrote:
> these example is exact in terms of functionality
> x+ will test the outmost maxX fopund as offset for the mirror, same nut
> reversed for x-
>
> using mirror x is also correct, but that doesn't mean your model is.
> let me explain: if you plan for instance to mirror on x, at 0,0,0
> then because model will be exactly mirrored at that point, it means that your
> model should be excenter in your modeler so that x 0 is at side of your model.
> plus , if you do not set the mirror mesh duplicate to false, you will get an
> additive result. the mirrored part become part of the original model.
>
> your "i" comfirms the above, by looking at the shared space at the base 0,0,0
> of the geometry.
>
> play around with the settings in Prefab, it's not having the unique mesh
> option there yet, but you should be able to test
>
> Fabrice
>
> On Mar 4, 2010, at 4:29 PM, Wex wrote:
>
> > Okay, some Mirror testing; this is the scene creation code:
>
> > private function buildMirrorTest():void
> > {
> > var mat:ShadingColorMaterial = new
> > ShadingColorMaterial(0xFFFF00);
> > var sphere:Sphere = new Sphere( { radius:4, material:mat
> > } );
> > m_view.scene.addChild(sphere);
>
> > mesh = Max3DS.load("axis.3DS");
> > mesh.addOnSuccess(flip);
> > m_view.scene.addChild(mesh);
> > }
>
> > private function flip(_event:Loader3DEvent):void
> > {
> > var cube:LoaderCube = _event.target as LoaderCube;
>
> > cube.handle.x = 0;
> > cube.handle.y = 0;
> > cube.handle.z = 0;
> > }
>
> > This just loads a basic multiple-mesh model as seen here:
> >http://www.creativenorth.co.uk/post-content/away003.png
>
> > There are 4 meshes in this model, one for the main three bars and one
> > each for the three end-cubes. All have the same material applied.
>
> > If I then apply a Mirror be making the following change:
>
> > private function flip(_event:Loader3DEvent):void
> > {
> > var cube:LoaderCube = _event.target as LoaderCube;
>
> > cube.handle.x = 0;
> > cube.handle.y = 0;
> > cube.handle.z = 0;
>
> > Mirror.apply(cube.handle, "x", true, true);
> > }
>
> > I get the correct, expected, result:
> >http://www.creativenorth.co.uk/post-content/away004.png
>
> > However using either x+ or x- gives the following respectivly:
> >http://www.creativenorth.co.uk/post-content/away005.png
> >http://www.creativenorth.co.uk/post-content/away006.png
>
> > In addition; if I do:
> > cube.handle.x = -40;
> > Mirror.apply(cube.handle, "x", true, true);
>
> > It should mirror about the world origin, but I get (yellow sphere is
> > at 0,0,0):
> >http://www.creativenorth.co.uk/post-content/away007.png
>
> > It's worth noting that the same results are seen if the Mirror's
> > recenter parameter is set to be false.
>
> > -Wex
>
> > On Mar 4, 1:16 pm, Fabrice3D <[email protected]> wrote:
> >> Mirror with prop "x", if the model is at 0,0,0 AND recentered AND
> >> duplicate mesh is false, will perfectly mirror.
> >> The class doesn't recenter the mesh for you, simply because you might no
> >> want it to do it.
>
> >> Fabrice
>
> >> On Mar 4, 2010, at 1:44 PM, Wex wrote:
>
> >>> Indeed, after further debugging I determined that it was Mirroring the
> >>> LoaderCube and not the final mesh.
>
> >>> I've added an event handler via addOnSuccess() and now I manage to
> >>> flip the right mesh. Not 100% about how it's flipping right now as it
> >>> doesn't seem to flip about the world origin and the +/- options don't
> >>> seem to do the right thing as I would expect. However, I'll do some
> >>> more looking into the issue before making a formal query about it.
>
> >>> Thanks for the help.
>
> >>> -Wex
>
> >>> On Mar 4, 12:18 pm, Fabrice3D <[email protected]> wrote:
> >>>> then you do not target the right mesh...
> >>>> Drop your model in Prefab, select your mesh and open mirror panel..
> >>>> just to see whats happening...
>
> >>>> Fabrice
>
> >>>> On Mar 4, 2010, at 1:03 PM, Wex wrote:
>
> >>>>> Cheers for replying. I've tried all the flips. Just done x+ and x-
> >>>>> again to be sure; still nothing.
>
> >>>>> Also, the object isn't at 0,0,0. I move it as shown in the posted
> >>>>> code.
>
> >>>>> -Wex
>
> >>>>> On Mar 4, 11:23 am, Fabrice3D <[email protected]> wrote:
> >>>>>> it might do it, but no being obvious... especially if your model is at
> >>>>>> 0,0,0 and symetrical
> >>>>>> try x+ or x- just to see.
>
> >>>>>> Fabrice
>
> >>>>>> On Mar 4, 2010, at 12:08 PM, Wex wrote:
>
> >>>>>>> Been banging my head against this for a few hours now... for some
> >>>>>>> reason when I mirror a mesh loaded from a 3DS file, it doesn't do
> >>>>>>> anything. Here's the code I'm testing with:
>
> >>>>>>> var mat:ShadingColorMaterial = new ShadingColorMaterial(0x00FF00);
> >>>>>>> var sphere:Sphere = new Sphere( { material:mat, segmentsH:6,
> >>>>>>> segmentsW:6, radius:10 } );
> >>>>>>> sphere.x = -20;
> >>>>>>> sphere.z = -200;
> >>>>>>> m_view.scene.addChild(sphere);
> >>>>>>> Mirror.apply(sphere, "x");
>
> >>>>>>> var mesh:Loader3D = Max3DS.load("wall.3DS");
> >>>>>>> mesh.x = -20;
> >>>>>>> mesh.z = -200;
> >>>>>>> m_view.scene.addChild(mesh);
> >>>>>>> Mirror.apply(mesh, "x");
>
> >>>>>>> The sphere mirrors wonderfully, but the 3DS just shows up as normal.
> >>>>>>> I've dumped a load of trace-ouputs in Mirror.as to see if it's doing
> >>>>>>> anything, and it does reach the obj.addFace call; all the verts seem
> >>>>>>> to be mirrored as expected... so I'm at a loss at to what's going on.
>
> >>>>>>> I'm running v3.4.0 of Away.
>
> >>>>>>> Any ideas?