Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
6
Question by Kinetic · Jun 17, 2012 at 08:12 AM · camerascalesizefovprojection-matrix

With a perspective camera: Distance independent size gameobject

Hi!, I need to make a GameObject approach the camera with a custom screen-space size (i need a object to have a "max size" and stop growing after a set distance). Ideally, i'd want a simple formula so i could scale the object depending its distance from the camera. After hours of trying and searching I found this simple formula:

 scale = focalLength / (focalLength + distance);

I tried applying this inversed so the object keeps its size, and this nearly works, but with not enough accuracy because i can't figure out what "focalLength" is exactly (at least this is my best guess, and certainly is not FOV).

Note that i'm struggling to wrap my head around this because i'm not comfortable around projection and transform matrices, so a noob-math friendly answer is mostly welcome.

Anyone can help me out with this or provide a better method?.

Thanks!

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Wolfram · Jun 17, 2012 at 08:23 PM 0
Share

In your case, "focalLength" is just your reference distance from the camera, and "distance" is the deviation from that, it is independent from the camera's FoV. Note that both values are local-z-distances from your camera, i.e. the distance vectors projectoed onto camera.transform.forward.

5 Replies

· Add your reply
  • Sort: 
avatar image
9

Answer by Ted-Bigham · Apr 30, 2015 at 06:35 AM

Instead of figuring out the math, just pick how big you want it on screen and use the camera functions to "measure" it in world units.

 public class LockToScreenSize : MonoBehaviour {
 
     public float sizeOnScreen;
 
     void Update () {
         Vector3 a = Camera.main.WorldToScreenPoint(transform.position);
         Vector3 b = new Vector3(a.x, a.y + sizeOnScreen, a.z);
 
         Vector3 aa = Camera.main.ScreenToWorldPoint(a);
         Vector3 bb = Camera.main.ScreenToWorldPoint(b);
 
         transform.localScale = Vector3.one * (aa - bb).magnitude;
     }
 }
Comment
Add comment · Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image SirChick · Apr 10, 2016 at 01:40 AM 0
Share

sizeOnScreen is what? In pixels? Because for me no matter what number i put it doesn't really change much.

avatar image Ted-Bigham SirChick · Apr 10, 2016 at 04:10 AM 0
Share

Size on screen is in vertical pixels. I just tried this in 800x480 resolution with a sphere. It maintained size on screen perfectly as I moved the camera closer and further. I noticed when the edges of the sphere touch the top and bottom of the viewport, sizeOneScreen is about 420. So it's not an exact number of pixels (or it would be 480), but the size does stay surprisingly consistent.

avatar image SirChick Ted-Bigham · Apr 10, 2016 at 04:13 AM 0
Share

Ah maybe its because $$anonymous$$e were sprites? When i change the pixels per unit it changed their size on screen but they do keep to a fixed size so it does work. Would of liked to have done via script rather than adjust the pixels per unit some how though.

Show more comments
Show more comments
avatar image SirChick · Apr 10, 2016 at 04:23 AM 0
Share

Ahhh i see my mistake now. Thanks it works properly now. Wish i understood exactly what the code does i suck at maths and understanding of 3D graphics :P But at least i have it working!

avatar image Ted-Bigham SirChick · Apr 10, 2016 at 04:42 AM 0
Share

All it's doing is creating a point (b) at a certain distance (sizeOnScreen) from the objects position on screen (a). Then it converts those screen points back to world points (aa) and (bb) and measures the distance (aa-bb). The distance is your new scale. I think that aa could be replaced with transform.position, but it's a little harder to read.

avatar image SirChick Ted-Bigham · Apr 10, 2016 at 04:47 AM 0
Share

Question, for distance with perspective wouldn't you apply "sizeOnScreen" to the Z value given Z is the distance from the camera, such (0,0,20), so if camera was at (0,0,0) with no rotations added to it then that would be 20 units away from the camera? Where as your code applies it to Y which is 20 units up from camera?

Thats kinda whats confusing me at the moment :P

Show more comments
avatar image
2

Answer by delstrega · Jun 17, 2012 at 09:02 AM

I don't exactly know what focal length is but googling revealed this relation between FOV and focal length: FOV = 2*arctan * (x / (2*focalLength)) (from http://kmp.bdimitrov.de/technology/fov.html)

The calculator on this page uses the following code to get the focal length f from a given FOV:

 function calcf(fov, crop)
 {
   if (fov == "") return "";
   if ((fov <= 0) || (fov >= 180)) return "error";
   f = (x / (2 * Math.tan(Math.PI * fov / 360)));
   return f / crop;
 }

Maybe this is a pointer in the right direction! Hope that helps :)

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
2

Answer by Wolfram · Jun 17, 2012 at 09:09 PM

If you don't care about actual pixel sizes, you can ignore the camera's FoV - the perceived scale change of an object is just the quotient objectAtDistanceA/objectAtDistanceB ("distance" being the local z distance to the camera, i.e. the distance vector from camera to object projected onto camera.transform.forward, as opposed to just the distance vector).

If you want to know how big your object is, or want to make an object exactly x pixels large, so you can keep it at a certain pixel height, you can use the formula @DelStrega pointed out to help you compute that size. So the height in pixels of an object at z-distance "distance" is just:

 objectPixelHeight=height/distance/(2*Mathf.Tan(Camera.main.fieldOfView/2*Mathf.Deg2Rad))*Camera.main.pixelHeight;

Note all this works correctly only for planar objects - as @Bunny83 pointed out, the perspective (and therefore the object's perceived size) changes if it has a depth.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Kinetic · Jun 18, 2012 at 12:32 AM 0
Share

Ok! I'm almost there!

First used this to get the "height" value:

 size = renderer.bounds.size.y

Next, I used this to get the z distance and pixelHeight as you pointed out:

 $$anonymous$$atrix4x4 m = Camera.main.worldToCamera$$anonymous$$atrix * $$anonymous$$atrix4x4.TRS( transform.position, transform.rotation, transform.localScale );

 Vector3 cameraRelativePos = ***matrix conversion here***

 float focalLength = 2 * $$anonymous$$athf.Tan( Camera.main.fov / 2 * $$anonymous$$athf.Deg2Rad );

 pixelHeight = size / -cameraRelativePos.z / focalLength * Camera.main.pixelHeight;

Now, to "fix" the scale to a deter$$anonymous$$ed pixel size when it passes a threshold:

 if ( pixelHeight > pixelLimit )
     transform.localScale = Vector3.one * -cameraRelativePos.z * (pixelLimit / 50); 

i'm a bit of lost here, this is working but is not FOV dependent, only works for 60 degrees. "50" is a value i discovered that fits to any pixelLimit for that fov, i can't find out where it is co$$anonymous$$g from. Curiously enough, FOV / FL = 50 for FOV 60, but doesn't scale well enough for other FOV values.

Any clues?

avatar image Wolfram · Jun 18, 2012 at 10:07 AM 2
Share

First, I would stay away from low-level $$anonymous$$atrix functions, they are usually not required in Unity, since there are many convenience functions around (for example, Camera.WorldToScreenPoint(), transform.TransformPoint(), and so on). In your example, I'd suggest Vector operations ins$$anonymous$$d, to find the z-distance:

 float zDistance=Vector3.Dot(transform.position-Camera.main.transform.position,Camera.main.transform.forward);

A "less mathematical" approach would ignore all that, and just use camera.WorldToScreenPoint() on renderer.bounds.max.y and renderer.bounds.$$anonymous$$.y to directly get the y-size in pixels. But I haven't tested this.

avatar image whydoidoit · Feb 05, 2013 at 07:22 PM 0
Share

@wolfram - can you help me out and rewrite this calculation:

 objectPixelHeight=(height/(distance/(2*$$anonymous$$athf.Tan(Camera.main.fieldOfView/2*$$anonymous$$athf.Deg2Rad))))*Camera.main.pixelHeight;

To calculate the distance at which objectPixelheight == Camera.main.pixelHeight?

avatar image whydoidoit · Feb 05, 2013 at 07:26 PM 0
Share

I think what I need is this:

   distance = 2*$$anonymous$$athf.Tan(Camera.main.fieldOfView/2 * $$anonymous$$athf.Deg2Rad)/height;

which presumable says for a given height what is the distance? Or I could be totally wrong :)

EDIT: yep, totally wrong

I'm trying to workout how to get a perspective rendered object to fill the camera vertically (to create a billboard).

avatar image Wolfram · Feb 06, 2013 at 10:43 AM 0
Share

Almost - it's the reciprocal of that:

 distance=WCheight/2/$$anonymous$$athf.Tan(Camera.main.fieldOfView/2 * $$anonymous$$athf.Deg2Rad)
avatar image
1

Answer by Bunny83 · Jun 17, 2012 at 10:49 AM

Of course you can calculate the size at a certain distance, but it won't help much. A perspective camera always shows closer parts bigger. If you calculate the size for the objects center, it will still be bigger. The closest bounding rectangle the object would fit in is much more complicated to calculate.

You might want to use a second camera and draw it orthographic? Keep in mind to setup the render order (camera's depth parameter) and the second camera should have clearflags none.

I'm not sure if the depth buffer will work in this case. Usually gizmos are displayed anyway. If you want to draw it no matter if it would be covered by something else or not, just set the Clear flags to depth-only

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Kinetic · Jun 17, 2012 at 08:01 PM 0
Share

Unfortunately i need the object to respect the z order so the 2nd camera solution is a no-no. I wrote i need a "gizmo-like" object because i thought this was the easier way to people to understand what i'm trying to do. I just want an object to "stop growing" when is near a specific threshold of distance from the camera (i'm maybe thinking something like the maxParticleSize property in Shuriken).

avatar image
0

Answer by Nimrod Harel · Jul 01, 2014 at 09:36 AM

In case someone comes across it, this solution worked in my case: Camera can zoom in / out and be moved on x/y axis, and some objects (game dialog) must be opened at fixed size regardless of camera zoom.

If using orthographic camera, just use the orthographic size (assuming you start at 100), and use it as scale for the fixed size object (if not, you can easily convert it to % from 100 if object scale isn't 100 by default).

say camera at size 120 (farther from plane, object must be larger, and will be scaled to 120% of it's original size).

public void updateScale() {

         float size = Camera.main.orthographicSize;
 
         Vector3 scale = new Vector3 (size, size, size);
         objectToScale.transform.localScale = scale;

}

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Wolfram · Jul 01, 2014 at 09:51 AM 0
Share

Note that the "orthographic size" of a Camera in Unity is the HALF size. So if you set Camera.main.orthographicSize=120, an object needs to be twice that large (=240) to exactly fit the vertical height of the camera view.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

11 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Formula for the scale value of an object based on ortographic camera size? 1 Answer

how to scale a cameras FOV in real time. 1 Answer

Possible to use an oblique frustum camera and still be able to change the fov? 1 Answer

How do I get an off-center camera view, without breaking FOV & aspect ratio? 1 Answer

auto scale camera error when upgrading unity4.3 into 4.5 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges