Eralp 142 Report post Posted May 11, 2008 Hi, what kind of algorithm do you use when zooming your camera class, i am using the following code but when you do it 20 times back and forth it becomes "wrong". I think it is because the small data losses.but anyway what should I do ? void Camera::zoomin(float units)//units doesnt mean anything for now { // pos = position vector; // look = lookat vector; if(zoom <= -5) return; pos.x = (pos.x-look.x)-((pos.x-look.x)/5)+look.x; pos.y = (pos.y-look.y)-((pos.y-look.y)/5)+look.y; pos.z = (pos.z-look.z)-((pos.z-look.z)/5)+look.z; zoom--; } void Camera::zoomout(float units)//units doesnt mean anything for now { if(zoom >= 5) return; pos.x = (pos.x-look.x)+((pos.x-look.x)/5)+look.x; pos.y = (pos.y-look.y)+((pos.y-look.y)/5)+look.y; pos.z = (pos.z-look.z)+((pos.z-look.z)/5)+look.z; zoom++; } 0 Share this post Link to post Share on other sites
fastcall22 10853 Report post Posted May 12, 2008 You're translating the camera, which is bad in this case. What you want to do is modify the camera's fov. A smaller fov will "zoom in" and a larger fov will "zoom out". 0 Share this post Link to post Share on other sites
erissian 727 Report post Posted May 12, 2008 As a note:pos.x = (pos.x-look.x)-((pos.x-look.x)/5)+look.x;is equivalent topos.x = 0.8*pos.x + 0.2*look.xAnyways, you have three options if you want to make something look bigger:#1 Get closer to it by repositioning the camera. This is what you're doing now.#2 Apply a scaling transformation to the camera#3 Adjust the field-of-view (as _fastcall said)I think any of these are alright, but it doesn't seem that your zoom-in and zoom-out functions are inverted. Consider this:Px1 = 0.8*Px0 + 0.2*Lx // zooming out, reducedPx2 = 1.2*Px1 - 0.2*Lx // zooming in, reducedPx2 = 1.2*(0.8*Px0 + 0.2*Lx) + 0.2*LxPx2 = 0.96*Px0 + 0.24*Lx + 0.2*LxPx2 = 0.96*Px0 + 0.44*LxPx2 != Px0So you can see, zooming out and zooming back in does not result in the same values. This is where you're losing information. 0 Share this post Link to post Share on other sites
Tenac 124 Report post Posted May 12, 2008 From what I see, what if your walking up against a wall or object and you zoom in? It looks like your camera will go inside the wall/object rather than enlarging the view from where your standing. I'm not 100% sure how to solve this though =\ 0 Share this post Link to post Share on other sites
DaveMS 187 Report post Posted May 13, 2008 I've just implemented the same sort of thing. Heres how I done it.pos is a vector representing the camera's position.target is the object the camera is looking at.z is the number of units to zoom. passing -z as a param to the function will zoom out.I don't know if you are using a 3d vector class, but I think it makes thing easier, so i've included the source for my vector class below if you want to use it, although it's probably not perfect.void Camera::zoom(float z){ // get the vector between the camera and target Vector3D lineVector = pos - target->getPosition(); // if the camera is zoomed in the max amount, exit function if(lineVector.magnitude() < MIN_CAM_DIST && z < 0) return; // if the camera is zoomed out the maximum amount, exit function if(lineVector.magnitude() > MAX_CAM_DIST && z > 0) return;// get the directional vector of lineVector, and multiply by the number of units// to zoom (z), then add to the camera's positional vector(pos) pos += z * lineVector.direction();}Vector3D.h#ifndef VECTOR3D_H#define VECTOR3D_H#include <math.h>class Vector3D{private: float x_val; float y_val; float z_val;public: Vector3D(); Vector3D(float x, float y, float z); ~Vector3D(); float x(); void x(float x); float y(); void y(float y); float z(); void z(float z); Vector3D direction(); float magnitude(); Vector3D normalize(); float dotProduct(const Vector3D &vec); Vector3D operator=(const Vector3D &u); Vector3D operator+=(const Vector3D &u); Vector3D operator-=(const Vector3D &u); Vector3D operator*=(float f); Vector3D operator/=(float f); friend Vector3D operator*(const Vector3D &u, float f); friend Vector3D operator*(float f, const Vector3D &u); friend Vector3D operator+(const Vector3D &u, const Vector3D &v); friend Vector3D operator-(const Vector3D &u, const Vector3D &v); friend Vector3D operator/(const Vector3D &u, float f);};Vector3D.cpp#include "Vector3D.h"Vector3D::Vector3D(){ x_val = 0.0f; y_val = 0.0f; z_val = 0.0f;}Vector3D::Vector3D(float x, float y, float z){ x_val = x; y_val = y; z_val = z;}Vector3D::~Vector3D(){}float Vector3D::x(){ return x_val;}float Vector3D::y(){ return y_val;}float Vector3D::z(){ return z_val;}void Vector3D::x(float x){ x_val = x;}void Vector3D::y(float y){ y_val = y;}void Vector3D::z(float z){ z_val = z;}float Vector3D::magnitude(){ return sqrt(x_val*x_val + y_val * y_val + z_val * z_val);}Vector3D Vector3D::direction(){ float m = magnitude(); Vector3D dir = *this; if (m < 0.0001) { dir.x_val = 1.0; dir.y_val = 0; dir.z_val = 0; } else { dir.x_val /= m; dir.y_val /= m; dir.z_val /= m; } return dir;}Vector3D Vector3D::normalize(){ //Make the Vector a unit Vector, and return self float m = magnitude(); if(m < 0.000001) { x_val = 1.0; y_val = 0; z_val = 0; m = 0.0; }else{ x_val /= m; y_val /= m; z_val /= m; } return *this;}float Vector3D::dotProduct(const Vector3D &vec){ //a.b = ax*bx + ay*by Vector3D dotProd = *this; return (dotProd.x_val * vec.x_val) + (dotProd.y_val * vec.y_val) + (dotProd.z_val * vec.z_val);}Vector3D Vector3D::operator =(const Vector3D &u){ x_val = u.x_val; y_val = u.y_val; z_val = u.z_val; return *this;}Vector3D Vector3D::operator +=(const Vector3D &u){ x_val += u.x_val; y_val += u.y_val; z_val += u.z_val; return *this;}Vector3D Vector3D::operator -=(const Vector3D &u){ x_val -= u.x_val; y_val -= u.y_val; z_val -= u.z_val; return *this;}Vector3D Vector3D::operator *=(float f){ x_val *= f; y_val *= f; z_val *= f; return *this;}Vector3D Vector3D::operator /=(float f){ x_val /= f; y_val /= f; z_val /= f; return *this;}Vector3D operator*(const Vector3D &u, float f) { return Vector3D (u.x_val * f, u.y_val * f, u.z_val * f);}Vector3D operator*(float f, const Vector3D &u) { return Vector3D(u.x_val * f, u.y_val * f, u.z_val * f);}Vector3D operator/(const Vector3D &u, float f) { return Vector3D(u.x_val / f, u.y_val / f, u.z_val / f);}Vector3D operator+(const Vector3D &u, const Vector3D &v){ return Vector3D (u.x_val + v.x_val, u.y_val + v.y_val, u.z_val + v.z_val);} Vector3D operator-(const Vector3D &u, const Vector3D &v){ return Vector3D(u.x_val - v.x_val, u.y_val - v.y_val, u.z_val - v.z_val);} [Edited by - DaveMS on May 13, 2008 3:52:36 AM] 0 Share this post Link to post Share on other sites
haegarr 7374 Report post Posted May 13, 2008 Quote:Original post by TenacFrom what I see, what if your walking up against a wall or object and you zoom in? It looks like your camera will go inside the wall/object rather than enlarging the view from where your standing.Right you are. AFAIK this kind of camera manipulation is named "dolly in". Due to translating the near (and far) clipping plane with the camera, unwanted side effects may occur.IMHO, the best solution w.r.t. a "perfect" zoom would be erissian's #2: incorporating it into the view matrix by doing a scale. On the other hand, changing the FoV is possible, too, but may make big differences in the distortion by perspective projection. 0 Share this post Link to post Share on other sites
Zahlman 1682 Report post Posted May 13, 2008 Go stand 100m away from a tree. Now move closer to it by 1/5 of your current distance from it. 1/5 of 100 is 20, so now you are 80 m away. Now move further away from it by 1/5 of your current distance from it. You are 80m away right now, and 1/5 of 80 is 16, so you move to 96m away. That's not where you started. And that's the problem. :)Consider storing some separate value for "distance", which you increase or decrease by a fixed amount for the zoom in/out calls. Then translate that into an actual camera position. (You'll need a reference vector for the "direction" of the camera to the look point.) You don't even need a linear mapping. It could look like, for example:void Camera::zoomin() { ++dist; _recalcPos();}void Camera::zoomout() { --dist; _recalcPos();}void Camera::_recalcPos() { // a private helper function dist = std::min(std::max(-5, dist), 5); // set limits pos.x = look.x + ref.x * std::pow(1.2, dist); // just for an example // similarly for y and z - but you should really use or make a vector class for this :)} 0 Share this post Link to post Share on other sites
Eralp 142 Report post Posted May 13, 2008 Quote:Original post by ZahlmanGo stand 100m away from a tree. Now move closer to it by 1/5 of your current distance from it. 1/5 of 100 is 20, so now you are 80 m away. Now move further away from it by 1/5 of your current distance from it. You are 80m away right now, and 1/5 of 80 is 16, so you move to 96m away. That's not where you started. And that's the problem. :)Geez, why couldn't I think of it !? :D thanks codewise it is not that hard but I always thought that this "loss" occurs because of variable-type changes.Anyway it helped. 0 Share this post Link to post Share on other sites