- Home /
Framing an Object, Bounds & Encapsulating
Hi All,
I have a selection system that is working fine, But I need to have the ability to zoom into the object I have clicked on, Similar to pressing 'F' Unity/Any other 3D package.
I have been looking into the bounds and can even get my camera to go to the objects bounds correctly, But I am not sure how to get it to frame it on screen, as it goes right into the middle of the objects bounds or to one of the edges depending on which mode I use.
Say I wanted to have it in the middle of the screen with a 10% screen gap around, I know I could do an offset but it wouldnt always be correct as some objects are significantly bigger than others.
I also have groups, And if I selected a group of objects I would want that to be framed with the same 10% margin around, Which I think I would use Encapsulating for.
If anyone can think of anything to point me in the right direction I would be incredibly grateful, Out of ideas at this point...
Cheers, Russell
Bump as its my first post it didn't show up for ages and is now buried far far below....(I think, apologies if mistaken!)
Basically what this guy is describing here for the editor but at runtime.... http://answers.unity3d.com/questions/813814/fra$$anonymous$$g-objects-via-script-in-the-unity-editor.html
They use -
Selection.activeGameObject = yourObject; SceneView.FrameLastActiveSceneView();
Cheers, Russell
Answer by carrollh · Feb 03, 2015 at 12:36 AM
EDIT: Here are some simple scripts that will move the camera a set distance away from an object and look at it. Imagine an object rests at (0,0,0) and the camera is looking at from (3,3,3). These scripts will move the camera to be the same distance away on the x and z-axis while staying at height 3. This rough, doesn't care about the height of the GO, and sets itself to a specific distance away. You can adjust this script for varying sized objects simply by testing out what you think looks good and storing that value in the offset variable on the object.
On your GameObject:
float offset = 4.24264f
void OnMouseOver()
{
if (Input.GetMouseButtonDown(0))
{
Camera.main.GetComponent<FocusScript>().Focus(transform, offset);
}
}
On your main camera:
public void Focus(Transform target, float offset)
{
Vector3 direction = transform.position - target.position;
direction = offset * direction.normalized;
Vector3 moveTo = target.position + direction;
transform.position = new Vector3(moveTo.x, 3f, moveTo.z);
transform.LookAt(target);
}
I hope this works for you. If you need something a little more dynamic, you could use the height as a factor multiplied against a static offset. Like if the GO is 2 units tall you could move it 2 * offset away. And just look up the collider height to feed that value.
END EDIT
Well, first take a look at Transform.LookAt.
Then it gets hairy unless there is an API call for this that I can't find (like your example from the unity editor). If you have a collider on the thing you're trying to frame, you could look at it's dimensions, then adjust the current viewport to the larger one respective to your current aspect ratio (plus your padding).
Maybe Camera.WorldToViewportPoint and Camera.ViewportToScreenPoint will come in handy.
Whatever math you use to figure out the new rectangle you're looking at based on the collider you wanted to frame, do that again except figure it out based on the width of the group of objects you have selected. Find the leftmost and rightmost objects in the group after you've turned the camera to look at them, and use that as your bounds (plus your pladding). You can probably use Bounds.Encapsulate to accomplish this actually, then it's a repeat of the simple version.
I realize there's a lot of code you're going to need for this, so hopefully someone else knows a more API based "FrameInView" method or something.
Thanks for your reply, really helpful!
I have all the rest of my camera stuff set up - Look at/Rotations/panning ect & this is the last bit of functionality I need and have been putting off for months before release ha!
I will look into those 2 things tonight! Cheers, Russell
regarding how far from the object you want to focus on, to place the camera: This can be simplified if you followed the standard of having your models exist (in model space) at size of ONE unit width or height (which ever is greater). If you have done this, you can simply set the distance to a HARD 1.5 (deter$$anonymous$$e that 1.5f experimentally- it will be based on the camera's field of view angle). Use that distance and your orientation[Lookat(0,0,0) in model space] to deter$$anonymous$$e a position in $$anonymous$$O$$anonymous$$SPAC$$anonymous$$ THEN you can use worldCameraPos=focusobject.transform.TransformPoint(localCameraPos) To convert from the objects local(model) to world coordinates, for a final world-space camera location.
Of course, if your models, in $$anonymous$$O$$anonymous$$SPACE are different sizes, this wont work. (but there also other reason to make your models this way.. like say.. fitting a model inside a sphere or box.)
I think I am slightly misunderstanding you sorry, All my $$anonymous$$odels are at a scale of 1,1,1. Imported from $$anonymous$$aya. But are of many different sizes, the smallest being about a 10th of the size of the largest.
He was just saying that if all the things you want to focus on are the same size (not scale) you can hard code the function to stop at a certain range away with a static focal length. But since all of your objects are different sizes you are probably going to want to figure it out dynamically when the focus method gets called. One solution to the dynamic approach would be to use something already on the objects (like a collider) that you can query for dimensions.
Answer by RussellT · Feb 04, 2015 at 04:46 PM
Thanks for the reply, Much appreciated. I do have a collider on each of the objects, Which I my RayCast hits when each object is selected - So I can get all the bounds information from that and go up the hierarchy to encapsulate multiple objects. I'm just not sure how to then turn that information into something I can tell the camera to do...
I.E - Keep moving forwards until this object reaches some predefined boundary on the camera...
Currently having a look at this in the manual: http://docs.unity3d.com/Manual/FrustumSizeAtDistance.html
Cheers, Russell
Your answer
Follow this Question
Related Questions
Make camera Zoom in or Zoom Out to focus all target objects 0 Answers
Keep Player + Party and/or Targeted Enemies in Camera Focus 1 Answer
Losing Focus When Zooming In And Out 1 Answer
Implementing Camera bounds proportionally to its ortographic size 0 Answers
Camera movement and zoom bounds 0 Answers