📄 camera.cpp
字号:
#include "camera.h"
void Camera::Normalise(XYZ *p)
{
float length;
length = (float) sqrt(p->x * p->x + p->y * p->y + p->z * p->z);
if (length != 0) {
p->x /= length;
p->y /= length;
p->z /= length;
} else {
p->x = 0;
p->y = 0;
p->z = 0;
}
}
void Camera::Normalise(float *x, float *y, float *z)
{
float length;
length = (float) sqrt( (*x)*(*x) + (*y)*(*y) + (*z)*(*z));
if (length != 0)
{
*x /= length; // *x = hodnota z adresy x, x - smernik, adresa
*y /= length;
*z /= length;
}
else
{
*x = 0;
*y = 0;
*z = 0;
}
}
void Camera::DerivateMatrix(void)
{
glLoadIdentity();
gluLookAt(vp.x, vp.y, vp.z, vd.x+vp.x, vd.y+vp.y, vd.z+vp.z, vu.x, vu.y, vu.z);
}
void Camera::d(void)
{
glLoadIdentity();
gluLookAt(vp.x, vp.y, vp.z, vd.x+vp.x, vd.y+vp.y, vd.z+vp.z, vu.x, vu.y, vu.z);
}
Camera::Camera(void)
{
Reset();
stack_pointer = NULL;
SetCursorPos(screen_x/2,screen_y/2); // nastavy mys do stredu obrazovky , je mozne to vypnut
}
Camera::~Camera(void)
{
if(stack_pointer==NULL)return;
{
position *pom; // pomocny smernik
int i=0,j;
pom = stack_pointer;
while(pom->next!=NULL) {pom = pom->next; i++;} // po skonceni v i bude pocet alokovanych struktur - 1
while(i>0) // v kazdom cykle uvolnime poslednu cast spojkoveho zoznamu
{
i--;
pom = stack_pointer;
for(j=i;j!=0;j--)pom = pom->next;
delete pom->next;
}
delete stack_pointer;
}
}
void Camera::Reset(void)
{
vp.x=0.0f;vp.y=0.0f;vp.z=1.5f;
vd.x=0;vd.y=0;vd.z=-1;
vu.x=0;vu.y=1;vu.z=0;
vr.x=1;vr.y=0;vr.z=0;
}
void Camera::RelativeTranslate(float x,float y,float z)
{
vp.x += x;
vp.y += y;
vp.z += z;
}
void Camera::RelativeRotate(float uhol,float x,float y,float z)
{
// rotuje suradnicovu sustavu podla vlastnych osi
/* v - normalizovany vektor v = (x, y, z) vT - transponovany vektor v
( 0 -z y) (1 0 0) (x) (xx xy xz)
S = ( z 0 -x) I = (0 1 0) vT =(y) v*vT = (yx yy yz)
(-y x 0) (0 0 1) (z) (zx zy zz)
A = v*vT + cos(uhol)*(I-v*vT) + sin(uhol)*S */
// Najprv vypocitame rotacnu maticu
float a[9];
float c,s;
Normalise(&x, &y, &z);
c = (float) cos(uhol*PI180);
s = (float) sin(uhol*PI180);
a[0] = x*x + c*(1-x*x); // ( a0 3 a6 )
a[1] = x*y + c*(0-x*y) + s*z; // A = ( a1 a4 a7 )
a[2] = x*z + c*(0-x*z) - s*y; // ( a2 a5 a8 )
a[3] = y*x + c*(0-y*x) - s*z;
a[4] = y*y + c*(1-y*y);
a[5] = y*z + c*(0-y*z) + s*x;
a[6] = z*x + c*(0-z*x) + s*y;
a[7] = z*y + c*(0-z*y) - s*x;
a[8] = z*z + c*(1-z*z);
// Rotovanie jednotlivych vektorov pomocou rotacnej matice A
// Kedze pohybujem kamerov musime nou hybat opacne ako sa bude tocit scena
// preto nebudem nasobit (x,y,z)T * A, ale naopak A * (x,y,z)T
vp.x = a[0]*vp.x + a[1]*vp.y + a[2]*vp.z;
vp.y = a[3]*vp.x + a[4]*vp.y + a[5]*vp.z;
vp.z = a[6]*vp.x + a[7]*vp.y + a[8]*vp.z;
vd.x = a[0]*vd.x + a[1]*vd.y + a[2]*vd.z;
vd.y = a[3]*vd.x + a[4]*vd.y + a[5]*vd.z;
vd.z = a[6]*vd.x + a[7]*vd.y + a[8]*vd.z;
Normalise(&vd);
vu.x = a[0]*vu.x + a[1]*vu.y + a[2]*vu.z;
vu.y = a[3]*vu.x + a[4]*vu.y + a[5]*vu.z;
vu.z = a[6]*vu.x + a[7]*vu.y + a[8]*vu.z;
Normalise(&vu);
CROSSPROD(vd,vu,vr);
Normalise(&vr);
}
void Camera::RelativeRotatePoint(float uhol,float x,float y,float z, float px, float py, float pz)
{
vp.x -= px; // aby sme rotovali okolo bodu (px,py,pz)
vp.y -= py; // najprv polohu posunieme do opacneho bodu
vp.z -= pz;
RelativeRotate(uhol, x, y, z);
vp.x += px; // po rotacii polohu vratime naspat
vp.y += py;
vp.z += pz;
}
void Camera::AbsoluteRotate(float x, float y, float z)
{
float dd;
// velkost vp
dd = (float) sqrt(vp.x*vp.x + vp.y*vp.y + vp.z*vp.z);
vp.x += dd * x * vu.x + dd * y * vr.x;
vp.y += dd * x * vu.y + dd * y * vr.y;
vp.z += dd * x * vu.z + dd * y * vr.z;
Normalise(&vp);
vp.x *= dd;
vp.y *= dd;
vp.z *= dd;
vr.x = vp.x + vr.x; // vypocet noveho praveho vektora
vr.y = vp.y + vr.y;
vr.z = vp.z + vr.z;
Normalise(&vr);
vd.x = - vp.x; // pozerame na bod 0,0,0
vd.y = - vp.y;
vd.z = - vp.z;
Normalise(&vd);
CROSSPROD(vr,vd,vu); // vypocet noveho up vektora
Normalise(&vu);
CROSSPROD(vd,vu,vr);
Normalise(&vr);
// otocenie kamery okolo osi
if (z != 0) {
vu.x += z * vr.x;
vu.y += z * vr.y;
vu.z += z * vr.z;
Normalise(&vu);
CROSSPROD(vd,vu,vr);
Normalise(&vr);
}
}
void Camera::AbsoluteRotatePoint(float x, float y, float z, float px, float py, float pz)
{
XYZ pr,d;
float dd;
pr.x = px;
pr.y = py;
pr.z = pz;
// vypocet vzdialenosti k bodu okolo ktoreho sa bude rotovat
d.x = vp.x - pr.x;
d.y = vp.y - pr.y;
d.z = vp.z - pr.z;
dd = (float) sqrt(d.x*d.x + d.y*d.y + d.z*d.z);
// vypocet noveho bodu z ktoreho sa pozerame
vp.x += dd * x * vu.x + dd * y * vr.x - pr.x;
vp.y += dd * x * vu.y + dd * y * vr.y - pr.y;
vp.z += dd * x * vu.z + dd * y * vr.z - pr.z;
Normalise(&vp);
vp.x = pr.x + dd * vp.x;
vp.y = pr.y + dd * vp.y;
vp.z = pr.z + dd * vp.z;
// vypocet smeroveho vektora
vd.x = pr.x - vp.x; // pozerame sa na bod okolo ktoreha sa rotuje
vd.y = pr.y - vp.y;
vd.z = pr.z - vp.z;
Normalise(&vd);
// vypocet noveho praveho vektora
vr.x = vp.x - pr.x + vr.x;
vr.y = vp.y - pr.y + vr.y;
vr.z = vp.z - pr.z + vr.z;
Normalise(&vr);
vr.x = pr.x + dd * vr.x - vp.x;
vr.y = pr.y + dd * vr.y - vp.y;
vr.z = pr.z + dd * vr.z - vp.z;
// vypocet up vektora
CROSSPROD(vr,vd,vu); // vektorovy sucin
Normalise(&vu);
CROSSPROD(vd,vu,vr);
Normalise(&vr);
// otocenie kamery okolo osi
if (z != 0) {
vu.x += z * vr.x;
vu.y += z * vr.y;
vu.z += z * vr.z;
Normalise(&vu);
CROSSPROD(vd,vu,vr);
Normalise(&vr);
}
}
void Camera::AbsoluteRotateDistance(float x, float y, float z, float distance)
{
AbsoluteRotatePoint(x, y, z, distance*vd.x + vp.x, distance*vd.y + vp.y, distance*vd.z + vp.z);
}
void Camera::FlyRotate(float x, float y, float z)
{
// FlyRotate - rotacia, ktora zabezpecuje volny pohyb (Fly - lietanie), surad. sustava (myslim tym osi x,y,z vykreslene po tejto transformacii)
// sa rotuje tak, ze sa otaca vzdy oko osi horizontalne (x) a vertikalnej (y)
// v pripade ze mame vp = {0,0,5}, vd = {0,0,-1} a vp = {0,1,0} tak pre
// x > 0 sa suradnicova sustava posunie dolava t.j. kamera sa otoci doprava
// x < 0 doprava dolava
// y > 0 sa suradnicova sustava posunie dole t.j. kamera sa otoci hore
// y < 0 hore dole
// z > 0 sa suradnicova sustava otoci proti smeru hodinovych ruciciek
// z < 0 v smere
/* zmenime poluhu smeroveho (direction) vektora tak,
ze k nemu pripocitame cast vektora kolmeho na nho v danom smere */
vd.x += x*vr.x + y*vu.x; // vr - vektor smerujuci vpravo - v smere osi x
vd.y += x*vr.y + y*vu.y; // vu - (up) hore smerujuci vektor - v smere osi y
vd.z += x*vr.z + y*vu.z; //
Normalise(&vd); // normalizacia vektora, aby (velkost) ||vd||=1
CROSSPROD(vr,vd,vu); // vypocitame novy vu vektor a to pomocu vekoroveho sucinu
Normalise(&vu); // vektora smerom vpravo a dopredu
CROSSPROD(vd,vu,vr);
Normalise(&vr);
if(z!=0) // v pripade ze chceme kameru rotovat v smere osi
{
vu.x += z*vr.x; // k vektoru smerujucemu hore pripocitame cast vektora
vu.y += z*vr.y; // smerujuceho vpravo, tym sa vektor vu otoci vpravo a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -