问题
More a maths question then a programming one, but I need to code camera rotation and I have no idea how. The maths are a bit to abstract for me to do out of the blue. The camera's rotation is done with quaternions, all I really want is a sample to study or just an article about the subject but I can't find anything.
回答1:
here is something i wrote in opengl. the basic algorithm should be the same in any language. the things you need are:
the up vector of unit length (where up is defined if you are looking at the center): (upx, upy, upz)
origin (the place you are looking at): (ox,oy,oz)
camera position (where your camera is): (cx, cy, cz)
assume "del" is the amount you want to move, and that
norma() = (ox-cx, oy-cy, oz-cz)/sqrt( (ox-cx) * (ox-cx) + (oy-cy) * (oy-cy) + (oz-cz) * (oz-cz) )
after that, you can calculate the "forward" vector. that is, the vector which is unit length and points from you to the center via:
(fox, foy, foz) = (ox-cx, oy-cy, oz-cz)/norma();
you can then calculate the unit "left" vector, that is, the vector pointing to the left of unit length if you are looking at the center:
lx = foz*upy-foy*upz;
ly = fox*upz-foz*upx;
lz = foy*upx-fox*upy;
you can then write the following routines (each original '//' justified left signifies a new routine)
// move camera forward
cx = cx + del*fox;
cy = cy + del*foy;
cz = cz + del*foz;
// move camera backward
cx = cx - del*fox;
cy = cy - del*foy;
cz = cz - del*foz;
// rotate figure right
cx0 = cx; // initial position
cy0 = cy;
cz0 = cz;
R1 = norma(); // initial distance
cx = cx + del*lx;
cy = cy + del*ly;
cz = cz + del*lz;
R2 = norma(); // new distance after moving in up direction
cx = cx + (R2-R1)*fox;
cy = cy + (R2-R1)*foy;
cz = cz + (R2-R1)*foz; // move towards center so the original distance is the same
// new "left" vector should be (cx-cx0, cy-cy0, cz-cz0) but normalized
lx = (cx-cx0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
ly = (cy-cy0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
lz = (cz-cz0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
// rotate left
cx0 = cx; // initial position
cy0 = cy;
cz0 = cz;
R1 = norma(); // initial distance
cx = cx - del*lx;
cy = cy - del*ly;
cz = cz - del*lz;
R2 = norma(); // new distance after moving in up direction
cx = cx + (R2-R1)*fox;
cy = cy + (R2-R1)*foy;
cz = cz + (R2-R1)*foz; // move towards center so the original distance is the same
// new "left" vector should be (cx-cx0, cy-cy0, cz-cz0) but normalized
lx = (cx-cx0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
ly = (cy-cy0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
lz = (cz-cz0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
// rotate figure up
cx0 = cx; // initial position
cy0 = cy;
cz0 = cz;
R1 = norma(); // initial distance
cx = cx + del*upx;
cy = cy + del*upy;
cz = cz + del*upz;
R2 = norma(); // new distance after moving in up direction
cx = cx + (R2-R1)*fox;
cy = cy + (R2-R1)*foy;
cz = cz + (R2-R1)*foz; // move towards center so the original distance is the same
// new "up" vector should be (cx-cx0, cy-cy0, cz-cz0) but normalized
upx = (cx-cx0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
upy = (cy-cy0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
upz = (cz-cz0)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
// rotate figure down
cx0 = cx; // initial position
cy0 = cy;
cz0 = cz;
R1 = norma(); // initial distance
cx = cx - del*upx;
cy = cy - del*upy;
cz = cz - del*upz;
R2 = norma(); // new distance after moving in up direction
cx = cx + (R2-R1)*fox;
cy = cy + (R2-R1)*foy;
cz = cz + (R2-R1)*foz; // move towards center so the original distance is the same
// new "up" vector should be (cx-cx0, cy-cy0, cz-cz0) but normalized
upx = (cx0-cx)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
upy = (cy0-cy)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
upz = (cz0-cz)/sqrt( (cx-cx0)*(cx-cx0) + (cy-cy0)*(cy-cy0) + (cz-cz0)*(cz-cz0) );
// move fig down
cx = cx + del*upx;
cy = cy + del*upy;
cz = cz + del*upz;
ox = ox + del*upx;
oy = oy + del*upy;
oz = oz + del*upz;
// move fig up
cx = cx - del*upx;
cy = cy - del*upy;
cz = cz - del*upz;
ox = ox - del*upx;
oy = oy - del*upy;
oz = oz - del*upz;
// move fig left
cx = cx + del*rx;
cy = cy + del*ry;
cz = cz + del*rz;
ox = ox + del*rx;
oy = oy + del*ry;
oz = oz + del*rz;
// move fig right
cx = cx - del*rx;
cy = cy - del*ry;
cz = cz - del*rz;
ox = ox - del*rx;
oy = oy - del*ry;
oz = oz - del*rz;
来源:https://stackoverflow.com/questions/7703262/camera-rotation-algorithm