Sign in to follow this  
HelderBorges

Rotating towers

Recommended Posts

HelderBorges    100
Hi guys. I´m studying computer engineering and i have to make a little game.

In the game, i need to have towers and a character.

I need the towers to face and focus the player, wen he enters their range zone.

i keep track of the position of the tower (i use post[3]) and the position of the player(i use posb[3]) with an array wish post[0] is the x coordinate the post[1] the y and the post[2] the z .
i use the function (sqrt(pow(a[0]-b[0],2)+pow(a[2]-b[2],2))) to calculate the distance between the 2 points, and if it is lower than the range, the tower needs to turn..... and that is my problem. I dont know how to face the tower to the player. I already tried some function, but i cant calculate that. :S

Can someone help plz????i will order you a pizza :D lol.

I´m using vs with c++. ty guys

Share this post


Link to post
Share on other sites
jyk    2094
There's a few different ways you can orient the tower. One would be to build an orthonormal basis from the normalized direction from the tower position to the player position. Another method (which might be a little more immediately intuitive) is to use atan2() to compute an angle of rotation for the tower that will align it as desired, e.g. (untested):

[code]y_angle = atan2(posb[2] - post[2], posb[0] - post[0]);[/code]
Depending on the conventions you're using, you may need to swap and/or negate the arguments to atan2(), or modify the angle that it returns.

Share this post


Link to post
Share on other sites
SuperVGA    1132
Slightly off topic: I have bad experience with pow in c++. Multiplying the number with itself &&/|| creating your own pow function seems faster.

Share this post


Link to post
Share on other sites
HelderBorges    100
[quote name='jyk' timestamp='1302692074' post='4797890']
There's a few different ways you can orient the tower. One would be to build an orthonormal basis from the normalized direction from the tower position to the player position. Another method (which might be a little more immediately intuitive) is to use atan2() to compute an angle of rotation for the tower that will align it as desired, e.g. (untested):

[code]y_angle = atan2(posb[2] - post[2], posb[0] - post[0]);[/code]
Depending on the conventions you're using, you may need to swap and/or negate the arguments to atan2(), or modify the angle that it returns.
[/quote]

Only 1 question. What is atan2()?
tried your tip(the coded one :P) but it dont work, i´m so pissed, cause i need to deliver the work in the next 2 days, and this is the only think not working xD

first i tried to use the product between 2 vectors doing rotatef(post[0]*posb[0]+post[1]*posb[1]+post[2]*posb[2],0,1,0);
then i tried to swap the angle argument for your atan2() function but it still dont work :\.I googled a lot already, but i think this forum is my last hope :\

Share this post


Link to post
Share on other sites
szecs    2990
"still don't work"

Could you be more specific? What are you using? OpenGL? Maybe the order of transformations are wrong
Could you show all the code?

Share this post


Link to post
Share on other sites
HelderBorges    100
[quote name='szecs' timestamp='1302693673' post='4797899']
"still don't work"

Could you be more specific? What are you using? OpenGL? Maybe the order of transformations are wrong
Could you show all the code?
[/quote]

Sory for the English :\.

I will try.


My tower is done with this:
[code]


void drawTorre(float m,float rtorre,float n){


glColor3f(1.0f, 2.0f, 0.0f);

glPushMatrix();


glTranslatef(0, coiso*distancia*escala,-10); //initial position of the tower
post[0]=0;
post[1]=coiso*distancia*escala;
post[2]=-10;
float d =calculardistancia(post,posb); //Calculate the distance between the tower and the object

if(d<=5) // compare if it is at the desired range
{

glRotatef(atan2(posb[0]-post[0],posb[2]-post[2]),0,1,0); //rotate the tower to the object

}

for(int i=0;i<ndonuts;i++){ ///draw the base of the tower
glPushMatrix();
glRotatef(90,1*escala,0,0);
glutWireTorus(raiointrior,raioexterior,numlados,aneis);
glPopMatrix();
glTranslatef(0, coiso*distancia*escala, 0);
}

//Bule de chá // draw the top of the tower
glTranslatef(0, coiso*distancia*escala-0.2, 0);
glRotatef(ang,m,rtorre,n);
glRotatef(-45,0,0,1*escala);//Incliar bool
glColor3f(0.0f, 1.0f, 0.0f);
glutSolidTeapot(tamanhobule); //Cria bule
glPopMatrix();



}

[/code]


and my test object till now is
[code]


void drawTriangolo(){


glTranslatef(x,y,z); // move o objecto // move the object with the keys
posb[0]=x; //store position of x
posb[1]=y;//store position of y
posb[2]=z;//store position of z
// ângulo em graus
glRotatef(ang2,f,g,h); //ignore
glRotatef(ang3,t,u,v); //ignore
glPushMatrix();
glBegin(GL_TRIANGLES);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
glPopMatrix();
}

[/code]


ad this is the function that calc the distance

[code]


float calculardistancia(float *a,float*b){



return (sqrt(pow(a[0]-b[0],2)+pow(a[2]-b[2],2)));


}

[/code]


i want the tower to always be turned to the object (the triangle for now) since he get in the range, and until he get out of the range.:\


I´m using Opengl on visual studio 2010 and with c++

Share this post


Link to post
Share on other sites
HelderBorges    100
[quote name='SuperVGA' timestamp='1302693743' post='4797900']
Are you #including <cmath> ? And using atn2 from the std -namespace?
[/quote]

Nope, i never used atn2, so i didnt know that i needed other library beside cmath :\ and i´m using opengl

Share this post


Link to post
Share on other sites
SuperVGA    1132
[quote name='Helder19' timestamp='1302694520' post='4797905']
[quote name='SuperVGA' timestamp='1302693743' post='4797900']
Are you #including <cmath> ? And using atn2 from the std -namespace?
[/quote]

Nope, i never used atn2, so i didnt know that i needed other library beside cmath :\ and i´m using opengl
[/quote]

Well, if you do use cmath, you would have [code]#include <cmath>[/code] in the top of your code that uses atn2,
and either a [code]using namespace std[/code] below that, or [code]std::tan2[/code] where you make your tan2 - invocation.

Hope this will solve your problem! :)

Share this post


Link to post
Share on other sites
HelderBorges    100
Ty all, but still not working :\
my complete code is


[code]


#include <glut.h>
#include <cmath>
#include <math.h>




float x=0,y=0,z=0;
float m=0,rtorre=0,n=0;
float f=0,g=0,h=0;
float t=0,u=0,v=0;

float q=1;

float ang=0;
float ang2=0;
float ang3=0;

GLenum modo=GL_FILL;

float post[3];//posicao da torre
float posb[3]={0,0,0};//posicao do boneco
float rtb[3]; // raio para rodar
float dist=100; //distancia da torre ao boneco
float coiso =1;
float distancia=0.6;
float escala=0.6;
float tamanhobule=1*escala;
float raiointrior=0.4*escala;
float raioexterior=0.6*escala;
int numlados=200*escala;
int aneis=100*escala;
int ndonuts=3;//número de dónuts

void changeSize(int w, int h) {

// Prevent a divide by zero, when window is too short
// (you cant make a window with zero width).
if(h == 0)
h = 1;

// compute window's aspect ratio
float ratio = w * 1.0 / h;

// Set the projection matrix as current
glMatrixMode(GL_PROJECTION);
// Load Identity Matrix
glLoadIdentity();

// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Set perspective
gluPerspective(45.0f ,ratio, 0.1f ,1000.0f);

// return to the model view matrix mode
glMatrixMode(GL_MODELVIEW);
}

float calculardistancia(float *a,float*b){



return (sqrt(pow(a[0]-b[0],2)+pow(a[2]-b[2],2)));


}




void drawTriangolo(){


glTranslatef(x,y,z); // move o objecto
posb[0]=x;
posb[1]=y;
posb[2]=z;
// ângulo em graus
glRotatef(ang2,f,g,h);
glRotatef(ang3,t,u,v);
glPushMatrix();
glBegin(GL_TRIANGLES);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
glPopMatrix();
}


void drawTorre(float m,float rtorre,float n){

using namespace std;
glColor3f(1.0f, 2.0f, 0.0f);

glPushMatrix();


glTranslatef(0, coiso*distancia*escala,-10);
post[0]=0;
post[1]=coiso*distancia*escala;
post[2]=-10;
float d =calculardistancia(post,posb);

if(d<=5)
{

glRotatef(atan2(posb[2]-post[2],posb[0]-post[0]),0,1,0);

}

for(int i=0;i<ndonuts;i++){
glPushMatrix();
glRotatef(90,1*escala,0,0);
glutWireTorus(raiointrior,raioexterior,numlados,aneis);
glPopMatrix();
glTranslatef(0, coiso*distancia*escala, 0);
}

//Bule de chá
glTranslatef(0, coiso*distancia*escala-0.2, 0);
glRotatef(ang,m,rtorre,n);
glRotatef(-45,0,0,1*escala);//Incliar bool
glColor3f(0.0f, 1.0f, 0.0f);
glutSolidTeapot(tamanhobule); //Cria bule
glPopMatrix();



}


void drawScene() {

drawTorre(m,rtorre,n);
drawTriangolo();

}




void renderScene(void) {



// clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// set the camera
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,
0.0,0.0,-1.0,
0.0f,1.0f,0.0f);

drawScene();



// End of frame
glutSwapBuffers();
}



// escrever função de processamento do teclado

void teclado(unsigned char tecla, int a, int b){
switch (tecla){
case 'w': z+=0.1;
break;
case 's': z-=0.1;
break;
case 'a': x-=0.1;
break;
case 'd': x+=0.1;
break;

case 'i': ang+=5;rtorre=1;m=0;
break;
case 'k': ang-=5;rtorre=1;m=0;
break;
case 'j': ang2+=5;f=0;g=1;
break;
case 'l': ang2-=5;f=0;g=1;
break;

case 'o': ang3+=5;t=0;u=0;v=1;
break;
case 'p': ang3-=5;t=0;u=0;v=1;
break;

case 'r': q+=0.1;
break;
case 't': q-=0.1;
break;

}
glutPostRedisplay();
}



// escrever função de processamento do menu

void menu(int id_op){

switch(id_op){
case 1 : modo=GL_FILL;
break;
case 2 : modo=GL_LINE;
break;
case 3: modo=GL_POINT;
break;
}
glutPostRedisplay();

}




void main(int argc, char **argv) {

// pôr inicialização aqui

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("CG@DI");


// pôr registo de funções aqui

glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);

// pôr aqui registo da funções do teclado e rato
glutKeyboardFunc(teclado);

// pôr aqui a criação do menu

glutCreateMenu(menu);
glutAddMenuEntry("Vermelho",1);
glutAddMenuEntry("Vermelho1",2);
glutAddMenuEntry("Vermelho2",3);
glutAttachMenu(GLUT_RIGHT_BUTTON);


// alguns settings para OpenGL
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);

// entrar no ciclo do GLUT aqui
glutMainLoop();
}



[/code]



The only think that i want to be working is the damn tower facing for the object.
:| i´m beginning to panic xD

Share this post


Link to post
Share on other sites
szecs    2990
The problem is that you seem to miss some very-very basic knowledge about openGL. I'd simply rewrite the whole code for you (it would be too hard to explain at this time IMHO), if I wasn't working :/

Share this post


Link to post
Share on other sites
alvaro    21263
[quote name='SuperVGA' timestamp='1302692291' post='4797894']
Slightly off topic: I have bad experience with pow in c++. Multiplying the number with itself &&/|| creating your own pow function seems faster.
[/quote]

That depends on your compiler. g++'s implementation of pow is very impressive.

Share this post


Link to post
Share on other sites
SuperVGA    1132
[quote name='alvaro' timestamp='1302700176' post='4797929']
[quote name='SuperVGA' timestamp='1302692291' post='4797894']
Slightly off topic: I have bad experience with pow in c++. Multiplying the number with itself &&/|| creating your own pow function seems faster.
[/quote]

That depends on your compiler. g++'s implementation of pow is very impressive.
[/quote]

That's strange. It wasn't impressive the way I remember it....

@Helder19; i agree with szecs you need to study the basics a bit more. Also; where's that std::atn2 call in your code? :P

Share this post


Link to post
Share on other sites
HelderBorges    100
[quote name='szecs' timestamp='1302699515' post='4797927']
The problem is that you seem to miss some very-very basic knowledge about openGL. I'd simply rewrite the whole code for you (it would be too hard to explain at this time IMHO), if I wasn't working :/
[/quote]

You just broke my heart :\. I know i miss some basic knowledg. its my first year and first time using opengl and graphic programing:\. I rely feel noob right now xD
But if you cold just give me some tips.... i will swap that pizza for 2 cookies :D

Share this post


Link to post
Share on other sites
ksmpal    136
I think there is something wrong with your calculardistancia() function: This code (sqrt(pow(a[0]-b[0],2)+pow(a[2]-b[2],2))) when re-written in simple algebra expression means sqrt((a_0 - b_0)^2 + (a_2 - b_2)^2). Where is the difference for between a[1] and b[1] in the equation for calculating distance between two 3D points?

I assume float* a and float* b are float arrays of size 3. Maybe you would want to correct this error first before searching else where?

I personally wouldn't write such cryptic looking expressions for implementing mathematical equations because you can make really hard to spot errors. Break it up into several small but simple logical steps. I myself would write calculardistancia() function like this:

[code]
float calculardistancia(float *a, float *b)
{
float c[3], dist;
c[0] = a[0] - b[0];
c[1] = a[1] - b[1];
c[2] = a[2] - b[2];
dist = sqrt( c[0]*c[0] + c[1]*c[1] + c[2]*c[2] );
return dist;
}
[/code]

Share this post


Link to post
Share on other sites
HelderBorges    100
[quote name='SuperVGA' timestamp='1302701242' post='4797932']


That's strange. It wasn't impressive the way I remember it....

@Helder19; i agree with szecs you need to study the basics a bit more. Also; where's that std::atn2 call in your code? :P
[/quote]

i placed it at the if :P. but it was before i passed the code to forum :P. Sory. why i feel like you are laughing at me ? xD

I thought that i had a pretty nice code. hahha i rely need to learn more :)

Share this post


Link to post
Share on other sites
HelderBorges    100
[quote name='fisyher' timestamp='1302701597' post='4797935']
I think there is something wrong with your calculardistancia() function: This code (sqrt(pow(a[0]-b[0],2)+pow(a[2]-b[2],2))) when re-written in simple algebra expression means sqrt((a_0 - b_0)^2 + (a_2 - b_2)^2). Where is the difference for between a[1] and b[1] in the equation for calculating distance between two 3D points. I assume float* a and float* b are float arrays of size 3. Maybe you would want to correct this error first before searching else where? I personally wouldn't write such cryptic looking expressions for implementing mathematical equations because you can make really hard to spot errors. Break it up into several small but simple logical steps. I myself would write calculardistancia() function like this: [code] float calculardistancia(float *a, float *b){ float c[3], dist; c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; c[2] = a[2] - b[2]; dist = sqrt( c[0]*c[0] + c[1]*c[1] + c[2]*c[2] ); return dist; } [/code]
[/quote]

Thanks for the tip. I only ignored the y axis information because both the objects are in the same plane, so it is almost a 2d problem, since they will move only in 2 axis.

Share this post


Link to post
Share on other sites
alvaro    21263
[quote name='SuperVGA' timestamp='1302701242' post='4797932']
[quote name='alvaro' timestamp='1302700176' post='4797929']
g++'s implementation of pow is very impressive.
[/quote]

That's strange. It wasn't impressive the way I remember it....
[/quote]

Well, if you write `pow(x,17)' and look at the assembly output, you'll see that it's doing something like this:
[code]x2 = x*x;
x4 = x2*x2;
x8 = x4*x4;
x16 = x8*x8;
x17 = x16*x;[/code]

Share this post


Link to post
Share on other sites
szecs    2990
No, it1s not the atan stuff. The transformations are mixed up I think, useless pushing popping etc. I can't even follow the code, that's why it would be easier to rewrite the whole stuff.

Or read our openGL books again, especially the transformations part

Share this post


Link to post
Share on other sites
ksmpal    136
[quote name='Helder19' timestamp='1302701851' post='4797937']
[quote name='fisyher' timestamp='1302701597' post='4797935']
I think there is something wrong with your calculardistancia() function: This code (sqrt(pow(a[0]-b[0],2)+pow(a[2]-b[2],2))) when re-written in simple algebra expression means sqrt((a_0 - b_0)^2 + (a_2 - b_2)^2). Where is the difference for between a[1] and b[1] in the equation for calculating distance between two 3D points. I assume float* a and float* b are float arrays of size 3. Maybe you would want to correct this error first before searching else where? I personally wouldn't write such cryptic looking expressions for implementing mathematical equations because you can make really hard to spot errors. Break it up into several small but simple logical steps. I myself would write calculardistancia() function like this: [code] float calculardistancia(float *a, float *b){ float c[3], dist; c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; c[2] = a[2] - b[2]; dist = sqrt( c[0]*c[0] + c[1]*c[1] + c[2]*c[2] ); return dist; } [/code]
[/quote]

Thanks for the tip. I only ignored the y axis information because both the objects are in the same plane, so it is almost a 2d problem, since they will move only in 2 axis.
[/quote]

In your code:

posb[0]=x;
posb[1]=y;
posb[2]=z;
where y is always 0 since you only initialize it but never change it.

...

post[0]=0;
post[1]=coiso*distancia*escala;
post[2]=-10;
float d = calculardistancia(post,posb);

where you initialize coiso, distancia and escala as
float coiso =1;
float distancia=0.6;
float escala=0.6;
and never change it afterwards.

However you tried to calculate distance between post and posb with your calculardistancia function when the difference between their y-values are clearly not zero.

How can your assumption for your distance equation be correct when you already broke it in this case?
Please stick to mathematically sound equation. Don't make assumptions when you are going to break it like this.

Share this post


Link to post
Share on other sites
HelderBorges    100
[quote name='fisyher' timestamp='1302703100' post='4797947']

However you tried to calculate distance between post and posb with your calculardistancia function when the difference between their y-values are clearly not zero.

How can your assumption for your distance equation be correct when you already broke it in this case?
Please stick to mathematically sound equation. Don't make assumptions when you are going to break it like this.

[/quote]

Ok... you got the point. i have to change that. But i think i already found the solution. i will post it wen i´m done :P

But thanks all guys

Share this post


Link to post
Share on other sites
HelderBorges    100
[quote name='szecs' timestamp='1302702651' post='4797945']
No, it1s not the atan stuff. The transformations are mixed up I think, useless pushing popping etc. I can't even follow the code, that's why it would be easier to rewrite the whole stuff.

Or read our openGL books again, especially the transformations part
[/quote]

Thanks szecs. Can you send me the link? i´m using the push pop so many time, because my teacher like it that way xD and i was messing up with the y value. :S i will reset the y value xD

Share this post


Link to post
Share on other sites
SuperVGA    1132
[quote name='alvaro' timestamp='1302702320' post='4797940']
[quote name='SuperVGA' timestamp='1302701242' post='4797932']
[quote name='alvaro' timestamp='1302700176' post='4797929']
g++'s implementation of pow is very impressive.
[/quote]

That's strange. It wasn't impressive the way I remember it....
[/quote]

Well, if you write `pow(x,17)' and look at the assembly output, you'll see that it's doing something like this:
[code]x2 = x*x;
x4 = x2*x2;
x8 = x4*x4;
x16 = x8*x8;
x17 = x16*x;[/code]
[/quote]

Aha! Ok, I see now how it would be faster in some cases. However, that would be slower when it comes to squaring and as such, computing distances.
But I get your point, nonetheless. Nice implementation.

Share this post


Link to post
Share on other sites
alvaro    21263
[quote name='SuperVGA' timestamp='1302706767' post='4797977']
Aha! Ok, I see now how it would be faster in some cases. However, that would be slower when it comes to squaring and as such, computing distances.[/quote]
Please, check your compiler's output carefully. Last time I did, I found that pow(x,2) resulted in the exact same assembly code as x*x.

Share this post


Link to post
Share on other sites
HelderBorges    100
Ok, i´m not done :\ mi friend told me to try this:

[code]

float dotProduct(float x[3],float y[3]){
return x[0]*y[0]+x[1]*y[1]*x[2]+y[2];}

float length(float x[3]){
return sqrtf(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]);
}

float clamp(float v, float i, float s){
if (v<i)
return i;
else if(v>s)
return s;
else return v;
}

float anglbetween(float x[3], float y[3])
{

float xu[3]; //aux array so i can create an unitary vector
float yu[3]; //aux array so i can create an unitary vector

xu[0]=x[0]/(abs(x[0]));
xu[1]=x[1]/(abs(x[1]));
xu[2]=x[2]/(abs(x[2]));

yu[0]=y[0]/(abs(y[0]));
yu[1]=y[1]/(abs(y[1]));
yu[2]=y[2]/(abs(y[2]));

float lp = length(xu) * length(yu);
if(lp<1e-6f)
lp=1e-6f;

float f= dotProduct(xu,yu)/lp;

f=clamp(f,-1,1);
return acosf(f);
}

[/code]



but it does not work. I used some "printf" for fast debug, and i found a strange thing, first i use calculadistancia() and both parameters have their values right, but wen i passe the same parameters to anglbetween() they have strange values like: 1.#IND000


And i was so close :\ i think xD

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this