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);
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:
<material id="_1_-_Default-material" name="_1_-_Default">
It’s the id, not the name. You can also trace it from AS3 with:
, which is surprisingly simple. Replacing it works the same way as with a cube:
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.
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.
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.
Two snippets for people who want to handle PV3D primitives like cubes, planes or spheres. The solutions are quite basic, but badly documented and hard to find.
Change a cube’s materials:
Access (play, stop, gotoAndPlay, etc.) the MovieClip inside of a MovieAssetMaterial / MovieMaterial
Good to know.