Re: Basic. Camera Controls
New code.
I create new function to calculate Yaw, Pitch, Distance between two positions 3D.
Calculate Yaw and Pitch is necessary for using Cam.setAngle();
For using Cam.setSpherical no is necessary because you can modify Cam.at variable to move the camera, and in this mode the camera has fixed focus.
Cam.setFromAt function focus your camera on a point (similar to Cam.setSpherical, but you can change the position of the camera directly).
I have applied Cam.setPosDir function to put the camera over object 3d (Ball), when you move the Ball, then the camera follow it.
Code:
/******************************************************************************/
#include "stdafx.h"
/******************************************************************************/
Vec PosEsfera; // 3D position (x,y,z)
Int iVar1=0,iVar2(0); // Integer variables
Flt tiempo,fVar; // Float variables
/******************************************************************************/
Flt Yaw(Vec &pos1,Vec &pos2) // Function to calculate yaw value
{
Flt xc=pos1.x,zc=pos1.z,xp=pos2.x,zp=pos2.z; // Local variables
if (xp==xc && zp>=zc) {return 0;}
if (xp==xc && zp<zc) {return 3;}
if (zp==zc && xp>xc) {return -1.5;}
if (zp==zc && xp<xc) {return 1.5;}
if (zp>zc) {return Atan((xc-xp)/(zp-zc));}
if (xp>xc) {return ((Atan((zc-zp)/(xc-xp)))-1.5);}
else {return ((Atan((zc-zp)/(xc-xp)))+1.5);}
}
Flt Pitch(Vec &pos1,Vec &pos2) // Function to calculate pitch value
{
Flt xc=pos1.x,yc=pos1.y,zc=pos1.z,xp=pos2.x,yp=pos2.y,zp=pos2.z; //Local variables
if (yp==yc) {return 0;}
return Atan((yp-yc)/(Sqrt(Sqr(xp-xc)+Sqr(zp-zc))));
}
Flt Distance(Vec &pos1,Vec &pos2) // Function to calculate distance
{
Flt xc=pos1.x,yc=pos1.y,zc=pos1.z,xp=pos2.x,yp=pos2.y,zp=pos2.z; //Local variables
return Sqrt(Sqr(xc-xp)+Sqr(yc-yp)+Sqr(zc-zp));
}
/******************************************************************************/
void InitPre()
{
// Initial configuration
App.name="TallerCamara";
App.flag=APP_FULL_TOGGLE;
IOPath="../data/";
PakAdd("engine.pak");
// Screen 800x600
D.mode(800,600);
}
/******************************************************************************/
Bool Init()
{
/*
Default Camera:
Cam.matrix.pos=(0,0,1)
Cam.at=(0,0,0)
Cam.dist=1
Cam.pitch=0
Cam.roll =0 */
tiempo=Tm.time(); //Save current time
PosEsfera=Vec(0,0,5); // Initial Ball Position
return true;
}
/******************************************************************************/
void Shut()
{
}
/******************************************************************************/
Bool Main()
{
if (Kb.bp(KB_ESC)){return false;}
if (Kb.bp(KB_TAB)) {iVar1++; return true;}
if (Kb.bp(KB_SPACE)) {iVar2++; return true;}
if (Kb.bp(KB_ENTER)) if (iVar2==0) {Cam.yaw=Yaw(Cam.matrix.pos,PosEsfera); Cam.pitch=Pitch(Cam.matrix.pos,PosEsfera);
Cam.setAngle(Cam.matrix.pos,Cam.yaw,Cam.pitch,Cam.roll).updateVelocities().set(); return true;}
else if (iVar2==1) {Cam.at=PosEsfera; Cam.setSpherical(Cam.at,Cam.yaw,Cam.pitch,Cam.roll,Cam.dist).updateVelocities().set(); return true;}
else if (iVar2==2) {Cam.at=PosEsfera; Cam.setFromAt(Cam.matrix.pos,Cam.at,Cam.roll).updateVelocities().set(); return true;}
if ((Kb.b(KB_LEFT)) || (Kb.b(KB_DOWN))) {fVar=-Tm.d*1.05;} else if ((Kb.b(KB_RIGHT)) || (Kb.b(KB_UP))) {fVar=Tm.d*1.05;} else {return true;}
switch (iVar1) {
case 0 : if ((Kb.b(KB_LEFT )) || (Kb.b(KB_RIGHT))) {Cam.matrix.pos+=Cam.matrix.x*fVar;} else if (Kb.b(KB_LCTRL)) {Cam.matrix.pos+=Cam.matrix.z*fVar;} else {Cam.matrix.pos+=Cam.matrix.y*fVar;} break;
case 1 : if ((Kb.b(KB_UP )) || (Kb.b(KB_DOWN ))) {Cam.dist-=fVar;} break;
case 2 : if ((Kb.b(KB_LEFT )) || (Kb.b(KB_RIGHT))) {Cam.yaw-=fVar;} break;
case 3 : if ((Kb.b(KB_UP )) || (Kb.b(KB_DOWN ))) {Cam.pitch+=fVar;} break;
case 4 : if ((Kb.b(KB_LEFT )) || (Kb.b(KB_RIGHT))) {Cam.roll+=fVar;} break;
case 6 : if ((Kb.b(KB_LEFT )) || (Kb.b(KB_RIGHT))) {Cam.at.x+=fVar;} else if (Kb.b(KB_LCTRL)) {Cam.at.z+=fVar;} else {Cam.at.y+=fVar;} break;
default : if ((Kb.b(KB_LEFT )) || (Kb.b(KB_RIGHT))) {PosEsfera.x+=fVar;} else if (Kb.b(KB_LCTRL)) {PosEsfera.z+=fVar;} else {PosEsfera.y+=fVar;}
}
switch (iVar2) {
case 0 : Cam.setAngle(Cam.matrix.pos,Cam.yaw,Cam.pitch,Cam.roll); break;
case 1 : Cam.setSpherical(Cam.at,Cam.yaw,Cam.pitch,Cam.roll,Cam.dist); break;
case 2 : Cam.setFromAt(Cam.matrix.pos,Cam.at,Cam.roll); break;
default : Cam.setPosDir(Vec(PosEsfera.x,(PosEsfera.y)+1,(PosEsfera.z)-1));
}
Cam.updateVelocities().set(); // Update and set camera changes
return true;
}
/******************************************************************************/
void Draw()
{
if (iVar1==7) iVar1=0;
if (iVar2==4) iVar2=0;
D.clear(WHITE); //Clear Screen in White.
Ball(1,PosEsfera).draw(ColorHue(Tm.time()/3)); // Draw Ball with time color
TextDS estilo; // declare text format
estilo.color=GREY;
estilo.scale/=1.2;
estilo.align.set(-1,0);
estilo.shadow=1;
D.text(estilo,1.3,0.92,"Press SPACE BAR to change selection");
estilo.align.set(1,0);
D.text(estilo,-1.3,0.92,"Press TAB to change selection");
estilo.color=BLACK;
estilo.scale/=1.4;
estilo.shadow=0;
D.text(estilo,-1.2,0.85,S+"Camera Position (x,y,z): "+Cam.matrix.pos);
D.text(estilo,-1.2,0.8,S+"Distance: "+Cam.dist);
D.text(estilo,-1.2,0.75,S+"Orientation (Yaw): "+Cam.yaw);
D.text(estilo,-1.2,0.7,S+"Inclination (Pitch): "+Cam.pitch);
D.text(estilo,-1.2,0.65,S+"Rotation (Roll): "+Cam.roll);
D.text(estilo,-1.2,0.6,S+"Move Ball. Position: "+PosEsfera);
D.text(estilo,-1.2,0.55,S+"Focus to position: "+Cam.at);
D.text(estilo,-1.3,0.45,S+"Distance between camera and object 3D: "+Distance(Cam.matrix.pos,PosEsfera));
estilo.align.set(-1,0);
D.text(estilo,1.2,0.85,"Cam.setAngle");
D.text(estilo,1.2,0.8,"Cam.setSpherical");
D.text(estilo,1.2,0.75,"Cam.setFromAt");
D.text(estilo,1.2,0.7,"Cam.setPosDir");
estilo.color=RED;
if ((Tm.time()-tiempo)>0.4f) {
D.text(estilo,1.3,(0.85-(0.05*iVar2)),"<<<");
estilo.align.set(1,0);
D.text(estilo,-1.3,(0.85-(0.05*iVar1)),">>>");
}
estilo.scale*=1.2;
estilo.align.set(0,0);
switch (iVar1) {
case 0 : case 5 : case 6 : D.text(estilo,0,-0.8,"Use arrow keys left/right(x), up/down(y), hold left Ctrl button(z)"); break;
case 1 : case 3 : D.text(estilo,0,-0.8,"Use arrow keys up/down"); break;
default : D.text(estilo,0,-0.8,"Use arrow keys left/right");
}
estilo.scale*=1.4;
estilo.shadow=1;
if ((Tm.time()-tiempo)>1.8f) {tiempo=Tm.time();} else if ((Tm.time()-tiempo)>1.1f) {estilo.color=WHITE;}
D.text(estilo,0,-0.9,"Press ENTER to focus the Mesh");
}
/******************************************************************************/
I have obtained the formulas about this other formula: tan(A) = opp / adj
|