Resizing papervision3d viewport in Flex
I’ve been spending some time getting PV3D to play nicely in Flex. As others have noted, there aren’t as many tutorials out there for Flex-specific users (although that’s changing by the day).
The bad: you can’t get quick answers. The good: you’re forced to use your brain to figure the little things out, which increases your facility with the library and postpones inevitable decline.
In my case, setting the width and height of the viewport was messing me up. Should be simple right? The application I’m building for my client has a certain screen that allows the user to drag elements from a datagrid into a “comparison window” and get a visual representation.
When the user drops the item, a new component containing my papervision stuff (viewport, camera, etc) is added to the container. The component should a small 3D rendering of the building.
First mistake: relying on the autoScaleToStage property of the viewport.
I first started by creating a custom mxml component to hold the PV3D building rendering and some labels and such to show important data. The PV3D viewport is created in a function launched soon after the creationComplete event. The autoScaleToStage is the third parameter (Boolean).
viewport = new Viewport3D(this.width, this.height, true, false)
You can see in this shot that my building models aren’t showing up in the custom components (little blue panels) when they are dragged to the comparison area. It turns out the viewport is doing what it was instructed to do, which is size to the stage. The stage size isn’t what we want, we want to size of the UIComponent I’ve placed it in. So the models are there, they’re just behind the gray area.
Second mistake: resizing the actual height and width of viewport
Ok. ok. If I can’t rely on the autoScaleToStage, I’ll just resize the viewport myself when Flex sends resize events to the component. So, I set the third parameter on the viewport creation to false and added an event handler to my mxml component to catch the resize events. The top of my mxml file looked like this…
and my onResize() function looked like this
private function onResize():void
{
if (viewport !=null)
{
viewport.width = this.width
viewport.height = this.height
}
}
(Note: the way my component is set up, the viewport won’t be created when the first onResize is launched. So I check to make sure it exists before resizing)
Unfortunately, this does exactly what I’m telling it to do, which like so many other times isn’t what I want. (”Just do it! Do it!”) The viewport is a flash MovieClip class, and by directly setting it’s width and height, I’m essentially squeezing and distorting the MovieClip’s children. So each time I add a custom component to the UI component that holds them (the black area at the top of the screen), it squeezes the ones already there.
You can see the result here, where the first custom component added (on the left) has gotten progressively squeezed each time I added another…
First bright idea of the day: look at the PV3D code
Ok, so let’s just check how the PV3D viewport manages scaling. Searching for the resize function in the Viewport class, we find:
/**
* Resizes the viewport when the stage is resized (if autoScaleToStage == true)
*/
protected function onStageResize(event:Event = null):void
{
if(_autoScaleToStage)
{
viewportWidth = stage.stageWidth;
viewportHeight = stage.stageHeight;
}
}
Ah, so there we are. There are special properties called viewportWidth and viewportHeight that control the correct size of the viewport. So I can just set them from my resize function and all should be fine. My onResize() function now looks like this:
private function onResize():void
{
if (viewport !=null)
{
viewport.viewportWidth = this.width
viewport.viewportHeight = this.height
}
}
and it does what I want.




