a) the following is faster by 50%
b) it returns the angles in a more "correct" way : the angles are measured from (0,1,0) which coincides with the default upvector and also coincides with the default "north pole", which makes this point (0,1,0) a better candidate for the point from which we should count the angles. Coinciding with the default upvector means that you can just do a vec.rotateXZby(-angle.Y,center); vec.rotateYZby(-angle.X,center); in order to align "vec" with the (0,1,0) axis.
Code: Select all
vector3d<T> getPolarCoordinates()
{
vector3d<T> angle=vector3d<T>(0,0,0);
f32 length=getLength();
if (length) {
if (X!=0) {
if (X < 0) angle.Y = 90 + (T)atan(Z / X) * RADTODEG;
else angle.Y = 270 + (T)atan(Z / X) * RADTODEG;
}
else {
if (Z>=0) angle.Y=0;
else angle.Y=180;
}
angle.X = (T)acos(Y / length) * RADTODEG;
}
return angle;
}
Code: Select all
#include "stdafx.h"
#include "time.h"
#include <irrlicht.h>
using namespace std;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#pragma comment(lib, "Irrlicht.lib")
//#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
vector3df ppos;
f32 thi,phi,chi;
vector3df ReturnPolarCoordinates() {
vector3df angle=vector3df(0,0,0);
f32 length=ppos.getLength();
if (length) {
if (ppos.X!=0) {
if (ppos.X < 0) angle.Y = 90 + atan(ppos.Z / ppos.X) * RADTODEG;
else angle.Y = 270 + atan(ppos.Z / ppos.X) * RADTODEG;
}
else {
if (ppos.Z>=0) angle.Y=0;
else angle.Y=180;
}
angle.X = acos(ppos.Y / length) * RADTODEG;
}
return angle;
}
int main(int argc, char *argv[])
{
core::vector3df ang1, ang2, ang3, cen=vector3df(0,0,0);
int i;
IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D9, dimension2d<s32>(1024, 768), 32, true, true, false, 0);
ppos=core::vector3df(100,0,0);
u32 t1,t2,dt=0;
printf("initial: X=%f Y=%f Z=%f\n\n", ppos.X, ppos.Y, ppos.Z);
t1 = device->getTimer()->getRealTime();
for(i=1;i<=10000000;i++) {
ang1=ppos.getHorizontalAngle();
}
t2 = device->getTimer()->getRealTime();
dt=t2-t1;
printf("HA: Thi=%f Phi=%f dt=%d\n\n", ang1.X, ang1.Y, dt);
t1 = device->getTimer()->getRealTime();
for(i=1;i<=10000000;i++) {
ang2=ReturnPolarCoordinates();
}
t2 = device->getTimer()->getRealTime();
dt=t2-t1;
printf("PC: Thi=%f Phi=%f dt=%d\n\n", ang2.X, ang2.Y, dt);
t1 = device->getTimer()->getRealTime();
for(i=1;i<=10000000;i++) {
ang3=ppos.getPolarCoordinates();
}
t2 = device->getTimer()->getRealTime();
dt=t2-t1;
printf("gPC: Thi=%f Phi=%f dt=%d\n\n", ang3.X, ang3.Y, dt);
ppos.rotateXZBy(-ang3.Y,cen);
ppos.rotateYZBy(-ang3.X,cen);
printf("rotated: X=%f Y=%f Z=%f\n\n", ppos.X, ppos.Y, ppos.Z);
device->drop();
return 0;
}
Code: Select all
initial: X=100.000000 Y=0.000000 Z=0.000000
HA: Thi=0.000000 Phi=90.000000 dt=4555
PC: Thi=90.000000 Phi=270.000000 dt=2101
gPC: Thi=90.000000 Phi=270.000000 dt=2046
rotated: X=0.000001 Y=100.000000 Z=-0.000004