PV3D: Finding 2D screen coordinates of a 3D object

I’ve written about how to get the 3D coordinates of a 2D point on your screen, this time I needed to do it the other way round. Here’s a nice post about both of it, but it doesn’t exactly work with the current version of Papervision3D. This one, using the DisplayObject3D.screen property, is much better, though there’s some minor things to notice:

1. dobj3d.autoCalcScreenCoords has to be set to true – some pages in the web tend to ignore that and people’ll always get (0,0,0).

2. You can only get the 2D coordinates after the object rendred, because the calcultion of the 2D point seems to use the previous render. I tried instantiating a new DisplayObject3D for testing and trace the screen coordinates right after that, and it didn’t work. Bummer. The correct way to get it should be:

myObject.autoCalcScreenCoords = true;
trace(dae.screen.x + viewport.viewportWidth / 2 + viewport.x);
trace(dae.screen.y + viewport.viewportHeight / 2 + viewport.y);

PV3D: Access, Swap & Replace Collada / Dae-Material

Wow. In Papervision3D, the function to replace materials on a cube I’ve mentioned earlier also works on Collada models, which I wouldn’t have expected. Considering how well implemented Collada is (in all engines I’ve tried), I was seriously expecting that this isn’t possible. But it is. Just be sure to get the right material name and it works like a blast. Collada files are XML-based, so the name can be traced rather quickly:

<library_materials>
   <material id="_1_-_Default-material" name="_1_-_Default">
     <instance_effect url="#_1_-_Default"/>
   </material>
 </library_materials>

It’s the id, not the name. You can also trace it from AS3 with:

trace(dae.materials);

, which is surprisingly simple. Replacing it works the same way as with a cube:

dae.replaceMaterialByName(material, "_1_-_Default-material");

I suppose this was especially easy because I used a UV-Mapped model with only one material, but it should work the same for models with multiple materials.

PV3D: get 2D mouse-click coordinates in a 3D world

This is something important for game development (or whatever else you may want to do with 3D worlds). The problem: You have a 3D world (e.g. a 3D-map) and click with your 2D-Mouse Cursor somewhere on your screen (e.g. to place a flag at that point) – to do that, you need to project the position of your 3D-mouse into the 3D world. This is how to do it in Papervision 3D:

var ray:Number3D = camera.unproject(viewport.containerSprite.mouseX,viewport.containerSprite.mouseY);
var cameraPosition:Number3D = new Number3D(camera.x,camera.y,camera.z);
ray = Number3D.add(ray,cameraPosition);
var p:Plane3D = new Plane3D();
p.setNormalAndPoint(new Number3D(0, 1, 0), new Number3D(0, 0, 0));
var intersect:Number3D = p.getIntersectionLineNumbers(cameraPosition,ray);

Basically you shoot a ray from your camera to the position where the mouse-cursor is and check where it intersects with an imaginary plane p. That’s where you’ve clicked.

Nice and all, but I personally can’t use it on tcm, because navigation by clicking is far slower and less intuitive than moving with arrow- or wasd-keys. D’oh. This is basic stuff though, so it might come in handy one day or the other.

Tweener vs. TweenLite / TweenMax

This should be basic, but I still want to express my love for it: Nowadays, unless it’s small or especially detailed stuff, most of the animation I show is scripted and I suppose non of the more advanced websites around could do without. Flash’s internal Tween-Class has been around for a few years, but it’s rather cumbersome to use and not exactly fast.

Two alternative tweening-engines are widely popular: TweenLite and Tweener, with Tweener being the by far most mentioned one. Both are extremely similar, though. To e.g. set a movieclips alpha to 0 in 2 seconds, you’d write:

TweenLite.to(myMovieClip, 2, {alpha:0}); // or:
Tweener.addTween(myMovieClip, {time:2, alpha:0});

The differences are so small, that, even in larger projects, it should be possible to switch between both within minutes. If it were only a matter of preference, I’d choose Tweener because of it’s slightly nicer syntax – but TweenLite’s speed is superior by far. Their speed test shows it quite clearly, but even in rather simple environments where I thought performance was no issue, when using Tweener, I’ve continuously gotten to dead ends I just couldn’t understand and which were solved instantly, when trying the same with TweenLite.

And one of the greatest functions in recent history (at least for me) is TweenLite’s delayedCall. As the name suggests it delays the calling of a function; which is absolutely essential, when scripting animation – and a lot less messy than using the usual onComplete parameter. I really couldn’t imagine working without it anymore. So show TweenLite some love! :)

Away3D: Pixel Precision / Pixel Perfect display?

I’ve taken a look at Away3D again, because I had a problem in PV3D, which was so stupid I couldn’t believe that it could actually be a problem. However, as expected, Away3D isn’t exactly free of problems either: If you place 3D objects on a website it might be necessary to display them precisely 1:1, without distortion. That’s especially important if I want to place text or small bitmaps on the objects, as e.g seen on the temporary TCM splash page. In Papervision3D the setting is:

Object.z = Math.round((camera.zoom * camera.focus) -Math.abs(camera.z))
           + Object.depth/2; // take or add 0.5 if it's still blurred

In Away3D the major solution is to place the surface 900 pixels away from the camera, when using default camera. Why 900? I have no clue, but who cares, it won’t persist through changes of the camera anyway. Even worse, it’s not even giving proper results… I’ve spent quite a while testing it and there’s always artifacts and distortions:

I know the image isn’t friendly to the eyes, but it shows the problem quite clearly. The top right one is the original that I used as a material. Weirdly, the bottom left pixel corner is cut and one pixel line in the middle of the plane is duplicated horizontally and vertically as soon as you place it on an object (a cube, in this case). Adding segments or turning on precision doesn’t change anything. Adding / subtracting 0.5 from the coordinates shows parts of the cut corners, but the opposite sides get blurry. Adding smoothing to the material, as some suggested, isn’t a solution either. I suppose this isn’t a mere problem of not having tried enough, because there were others who had this problem before, with no solution. Maybe it only works for planes and not cubes? Well, at least up there’s the setting to get it almost correct.

I’ve quickly checked Hidden Heroes, which was made with Away3D, to see if those ingenious guys fromGGH have found a solution… but it seems that they’re also just switching between blurred and distorted 3D-Planes and normal 2D MovieClips.

Meh. I’ll keep looking.