RESOLVED: Camera / Projection functionality

Software: Away3D 3.x

TomByrne, Newbie
Posted: 20 September 2011 07:50 AM   Total Posts: 11

I am trying to get Away3D to work alongside another 3D framework but there appear to be differences in the way the two systems project points into 3D.

The behaviour I would expect from Away3D (and that the other framework exhibits) is that a face sitting at the same position as the camera (and facing the camera) should appear at 100% on the screen (as a result of the old x*focalLength/(focalLength + z) projection method). This doesn’t happen though.

When gradually changing the fov with a slider the scene doe not gradually change but seems to be affected in a slightly jerky manner (I think this is the result of using the camera.zoom property to calculate a new camera.zoom value in several of the lenses).

I’m struggling to understand what the focus and zoom properties represent in a pure 3D sense. I understand their affects on the visual output, but not how to set them in a manner that they have no affect.

Also, the app doesn’t use the entire screen area, and I’m therefore using the camera.fixedZoom = false option. Are there any other places that must be notified of this? (i.e. frustrum culling etc.)

Any help would be much appreciated.

   

Avatar
Alejandro Santander, Administrator
Posted: 21 September 2011 12:14 AM   Total Posts: 414   [ # 1 ]

What you are mentioning not only is arbitrary between frameworks but also between Away3D versions. Away3D 3.x uses custom perspective projections, Away3DLite uses Flash’s native perspective projections and Away3D 4.x uses a more OpenGL like perspective projection considering frustum near and far clipping among other things in shaders.

There are some discussions about this in the 3.x arena in the old google group:
http://groups.google.com/group/away3d-dev/browse_thread/thread/e74119b70135c48a/fc8d6c13cbd3bbb0?lnk=gst&q=camera+zoom#fc8d6c13cbd3bbb0
http://groups.google.com/group/away3d-dev/browse_thread/thread/a5a1c7ed0b207594/00dfbeb816f4d6fb?lnk=gst&q=camera+fov#00dfbeb816f4d6fb

If you wish to understand the projection used in 4.x, I recommend having a look at “Mathematics for 3D Game Programming and Computer Graphics” where a detailed explanation of perspective projections and its application in OpenGL type rendering pipelines is done.

 

   

TomByrne, Newbie
Posted: 21 September 2011 12:24 AM   Total Posts: 11   [ # 2 ]

Thanks very much for you succinct reply.

I am assuming that the OpenGL-like perspective projection used in Away3d 4.x is the built in Flash Player 11 projection?

Would there be any available information on the difference between the 4.x projection and OpenGLs version?

Also, if I were to write my own version of PerspectiveLens, would this be sufficient in changing the 3.6 behaviour, or would there be more to it (I’ve noticed that the ‘zoom’ variable gets referenced all around the place)?

 

   

Avatar
Alejandro Santander, Administrator
Posted: 21 September 2011 12:41 AM   Total Posts: 414   [ # 3 ]

There is no built in Flash Player 11 projection. Vertex data is fed to shaders and developers write the shaders, so its up to them in the end.

If you want to test the differences in projections between 3.x and 4.x you would have to run some tests.

I can’t say much about your last point since I haven’t used 3.x for a while now.

I’m sorry if this is not helpful, lets see what others have to say about your query.

 

   

Avatar
Rob Bateman, Administrator
Posted: 21 September 2011 11:18 AM   Total Posts: 120   [ # 4 ]

Hey Tom

For the perspective behaviour you describe, i would recommend using the ZoomFocusLens class for the camera. In this use - focus represents focalLength, and zoom represents an overall zooming value on the resulting projection. To achieve x*focalLength/(focalLength + z), zoom must be set to 1 (the default value here is 10)

generally, focalLength is not use in the way you decribe above - this approach is a Legacy approach used by engines such as Papervision. The current wisdom (and the approach used with the native projection classes in Flash) is to apply x*focalLength/z. This can easily be modified to achieve the old approach by simply adding your focalLength to all projected z values, but it is not the way most engines and 3D packages generally handle projection

hth!


Rob

 

 

   

Avatar
Alejandro Santander, Administrator
Posted: 21 September 2011 02:50 PM   Total Posts: 414   [ # 5 ]

Thanks Rob! I think this is the answer we were looking for =)

 

   

TomByrne, Newbie
Posted: 22 September 2011 02:07 AM   Total Posts: 11   [ # 6 ]

Thanks, that works perfectly.

 

   

TomByrne, Newbie
Posted: 23 September 2011 02:53 AM   Total Posts: 11   [ # 7 ]

Is there any way to get the same projection in 4.0 from the PerspectiveLens (i.e. ZoomFocusLens with zoom=1)?

 

   

andreas_dila, Newbie
Posted: 25 October 2011 09:49 AM   Total Posts: 9   [ # 8 ]

Hey Guys,

Just started getting my hands dirty with the newest build of away3d.  I too was using the ZoomFocusLens to achieve the desired projection effect. It seems that class no longer exists in the framework.  Has it been renamed ?  omitted ?  Is it still possible to achive this effect ?  any feedback would be greatly appreciated.  Thanks for all the hard work !!

 

   

andreas_dila, Newbie
Posted: 15 November 2011 12:31 PM   Total Posts: 9   [ # 9 ]

For anyone who may be experiencing similar issues this is the progress I have made (though not sure it’s in the right direction).

I have found one formula that translates field of view to focallength:

FOV = 2*arctan (x / (2*focalLength)) // where x is the diagonal of the film (or in this case view.width ? )

solving for focallength in as3:

var focalLength:Number = view.width / ( Math.tan(PerspectiveLens(camera.lens).fieldOfView/2)*2)

I was hoping that knowing the focallength I could apply the following formula to get a scale ratio:

var scaleRatio:Number = (focalLength+object.z)/focalLength

The above approach doesn’t seem to work though. Further more another online post points out that internally away3d has the following code:

_focalLengthInv = Math.tan(_fieldOfView*Math.PI/360)

not quite sure how this is used.

Anyways hope this helps anyone else.  I’ll post any further development.  Would love it if someone with more experience could chime in…

 

 

   

iplat, Newbie
Posted: 19 November 2011 10:52 AM   Total Posts: 1   [ # 10 ]

Hi,

I ‘ve just started experimenting with Away3d 4.0 and I thought it would be useful for my projects to figure out the 1:1 projection formula. All equations from the previous versions of Away3d didn’t seem to work, so did the ones from other frameworks using the fieldOfView concept. So I did a research about projection and perspective lenses and I came up with the attached diagram. After that, the formula was easy to calculate.

tan(f/2) = (h/2) / d

f is the fov angle, h the view height, and d the distance between the camera and the 3d object.

Solving for f:

f = 2 * arctan(h/2d) (radians)

Converting radians to degrees: degrees = (180/pi) * radians

f = (180/pi) * [2 * arctan(h/2d)]

and finally,

f = (360/pi) * arctan(h/2d) (degrees),

assuming that the dimensions of the object match the dimensions of the view. The actionscript implementation is pretty straight forward (assume that the object is a cube):

var d:Number = Math.abs(_camera3D.z) - _cube.depth / 2;
var fieldOfView:Number = (360 / Math.PI) * Math.atan(_view3D.height / (2 * d));
_lens.fieldOfView = fieldOfView;

That’s it! The objects are now projected in their original dimensions. I hope the above information will help users with the same problem.

My problem now, is that when I apply bitmap materials on the cube, they are a little blurred. Is this a result of the smooth = true property? Is there a way to avoid that?

Thanks.

 

   

andreas_dila, Newbie
Posted: 21 November 2011 04:37 PM   Total Posts: 9   [ # 11 ]

Thanks iplat !

That was really helpful.  I always forget to change radians to degrees !  your post (and diagram) where just what I needed.


So to recap for anyone else who may stumble on to this post:

For objects to appear at fullsize when placed at 0 on z axis (ie a 500 width plane to render at 500 pxls)  you need to create a relationship between the distance of the camera from the origin and its lenses’ field of view.

if setting camera distance based on lens.fieldOfView it’s:

var distance = view.height /(2*Math.tan( PerspectiveLens(camera.lens).fieldOfView*(Math.PI/360)) );

if setting lens.fieldOfView it’s based on distance it’s:

PerspectiveLens(camera.lens).fieldOfView = Math.atan( view.height / (distance*2) )*(360/Math.PI);

 

   

R Villani, Newbie
Posted: 02 February 2012 10:41 PM   Total Posts: 13   [ # 12 ]

Using andreas_dila and iplat formulas, I came with a new one that I had to make in order to resize my object to fit the screen without having to move it closer/away from the camera nor changing the camera fov.

Browsing on Kirupa I found this:
http://www.kirupa.com/developer/mx/perspective.htm
And this formula to define the scale of the object from the focal length:
scale=fl/(fl+z);
fl = focal length;
z = the distance from the object to the camera, not the object’s z position.

So, to fit the object to the view on it’s original size, whatever is your FOV or the object position, just use this:

public function scaleByFOV(FOV:Numberdistance:NumberviewHeight:Number):Number
{
 
// focal length is the position where objects are seen at their 
 // natural size on the screen
 // fLength = viewHeight / 2 arctan(radianFOV)
 
var fl:Number viewHeight / (Math.tan(FOV * (180 Math.PI)));
 
// scale = fLength / (fLength + distanceFromViewer);
 
return / (fl / (fl distance));

Notice that on the return statement I divide 1 by the result. That’s because this formula shrinks the object if it’s far away. That’s the correct. But I wanted to make it bigger as it goes away.
1/result does the trick as 1 divided by n<1 gives n>1 proportionally.

 

   

Hector, Sr. Member
Posted: 10 February 2012 09:20 PM   Total Posts: 137   [ # 13 ]

Thanks everybody for this post. The explanations make it very easy to follow.

I need my Sprite3Ds in Away3D 4 to keep the scale while camera fov changes (like the old ‘distanceScaling’ from v3.6).

I guess I need to set an initial sprite size. Do you think using a percent of the view height is the best option?

Will ‘scaleByFOV()’ work if I use the sprite height instead of the view height?

Eg:

spriteSize view.height 0.2// Use 20% of the view height for the sprite size.
spriteScale scaleByFOV(cameraFOVcameraDistancespriteSize); 

Then I would use an event listener to update spriteScale every time the fov changes.

Does this sounds ok?

Thanks in advance.

 

   

R Villani, Newbie
Posted: 11 February 2012 10:30 AM   Total Posts: 13   [ # 14 ]

No. It has to be the view size for the focalLength formula to work. It’s an approximation from the formula used in real cameras that uses the film diagonal size.

That formula automatically makes your sprite maintain the scale as it moves or the FOV changes, if you recalculate it as it changes. Like you said, I would go for an eventListener too.

To choose the size your sprite will have on the screen, you will have to use first the focal length only. (here comes long nerdy explanation XD)

The focal length is the distance from the camera where your objects will show with their natural size on screen. Not bigger neither smaller. So, e.g, if your plane is 150 pixels tall and your view 300 pixels heigth, when it’s positioned at the focal length distance from the cam, it’ll be occupying half the screen.
So, to know the size your object will be on screen after applying scaleByFOV to it’s scale, first put it at the focal lenght distance from the cam. Then, set the scale as you desire.
Since the formula I showed you changes the scaleX and scaleY of the sprite directly, it would mess with your personalized scaling. You can maintain a required scale (that’s not 1, in this case) by putting it inside a container of scale 1 and applying the formula to this container instead of the srpite itself. So the sprite maintains your personalized size.
Or you could use always your scale * scaleByFOV().

Eg:

// position your sprite at this distance from the camera
// to know it's natural size
var fl:Number viewHeight / (Math.tan(FOV * (180 Math.PI)));

// now that you figured out the perfect scaling for your sprite
// is x: 0.8 and y: 0.5, apply the formula with this scaling
fovScale scaleByFOV(cameraFOVcameraDistanceviewHeight);
mySprite.scaleX 0.8  fovScale;
mySprite.scaleY 0.5  fovScale

 

   

Hector, Sr. Member
Posted: 12 February 2012 02:19 PM   Total Posts: 137   [ # 15 ]

R Villani Thanks Very Much for your reply!

I must be doing something wrong (see attached file).

For this test I added the sprite inside a ‘spriteContainer’ and then set ‘spriteContainer.z = focalLength;’ at the very beginning. Then, the ‘onEnterFrame’ function changes the spriteContainer scale using your function.

The buttons for zoom in and out changes the camera FOV value by 0.5 every time they are clicked.

You can see there is a big difference in the fovScale values every time the zoom buttons are pressed. Also after a few clicks the fovScale values become negative values, then positive again.

I have reviewed the code several times to make sure I’m following all the steps correctly.

 

File Attachments
SpriteScale.zip  (File Size: 152KB - Downloads: 320)
   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X