Ângulo entre 2 pontos em 3d
Boa tarde galera, estou fazendo um jogo básico em delphi para aprender opengl e estou tendo problemas para calcular o angulo entre dois pontos 3d.
Estou utilizando os valores em Graus 0-360 . Para os testes eu crei um objeto que possui uma variavel AngleX e AngleY que seria para onde o objeto está apontando/olhando. X seria para os lados e Y seria para cima e para baixo. E talvez eu precise do angulo Z mas ainda não sei.
Consegui montar uma função utilizando os meus códigos 2D.
[i:4d81e227de]
function getAngleX(Pa, Pb : XVector) : Single;
begin
Result := (180 * ((ArcTan2(Pa.x-Pb.x, Pa.z-Pb.z) / -PI)))+180;
end;
[/i:4d81e227de]
Ela retorna um angulo de 0 a 360 . Para rodar o objeto eu utilizo a funcao glRotate antes de de desenhar o objeto. Para o angulo X está funcionando perfeitamente. Nos testes eu coloco o objeto para apontar sempre para a posicao da camera.
No caso, eu calculo o angulo entre a posicao do objeto e a posicao da camera. O resultado eu utilizo da seguinte maneira:
[i:4d81e227de]
glPushMatrix;
glTranslatef(x, y, z); //posicao do objecto
glRotatef(-AngleX, 0, 1, 0);
//Render objeto
glPopMatrix;
[/i:4d81e227de]
Esta parte funciona legal. Nenhum erro idependente de onde eu estiver com a camera.
Ou seja o objeto está sempre olhando para a camera no eixo X. (olha para os lados) ;
Preciso que o objeto possa olhar para cima e para baixo também . Mas não estou conseguindo chegar em uma solução.
Pelo que entendi deveria ser praticamente a mesma função, só que levando em conta o componente Y dos dois pontos informados. mas não está rolando..
A lógica que eu estou seguindo seria essa, porém não está funcionando.
[i:4d81e227de]
glPushMatrix;
glTranslatef(x, y, z); //posicao do objecto
glRotatef(-AngleX, 0, 1, 0);
[b:4d81e227de]glRotatef(-AngleY, 1, 0, 0);[/b:4d81e227de]
//Render objeto
glPopMatrix;
[/i:4d81e227de]
Para o angleY eu uso outra funcao getAngleY, que utiliza o componentes Y e Z ao invez do X e Z como na funcao getAngleX;
Se alguém tiver alguma idéia, qq ajuda... valeu !!!
Estou utilizando os valores em Graus 0-360 . Para os testes eu crei um objeto que possui uma variavel AngleX e AngleY que seria para onde o objeto está apontando/olhando. X seria para os lados e Y seria para cima e para baixo. E talvez eu precise do angulo Z mas ainda não sei.
Consegui montar uma função utilizando os meus códigos 2D.
[i:4d81e227de]
function getAngleX(Pa, Pb : XVector) : Single;
begin
Result := (180 * ((ArcTan2(Pa.x-Pb.x, Pa.z-Pb.z) / -PI)))+180;
end;
[/i:4d81e227de]
Ela retorna um angulo de 0 a 360 . Para rodar o objeto eu utilizo a funcao glRotate antes de de desenhar o objeto. Para o angulo X está funcionando perfeitamente. Nos testes eu coloco o objeto para apontar sempre para a posicao da camera.
No caso, eu calculo o angulo entre a posicao do objeto e a posicao da camera. O resultado eu utilizo da seguinte maneira:
[i:4d81e227de]
glPushMatrix;
glTranslatef(x, y, z); //posicao do objecto
glRotatef(-AngleX, 0, 1, 0);
//Render objeto
glPopMatrix;
[/i:4d81e227de]
Esta parte funciona legal. Nenhum erro idependente de onde eu estiver com a camera.
Ou seja o objeto está sempre olhando para a camera no eixo X. (olha para os lados) ;
Preciso que o objeto possa olhar para cima e para baixo também . Mas não estou conseguindo chegar em uma solução.
Pelo que entendi deveria ser praticamente a mesma função, só que levando em conta o componente Y dos dois pontos informados. mas não está rolando..
A lógica que eu estou seguindo seria essa, porém não está funcionando.
[i:4d81e227de]
glPushMatrix;
glTranslatef(x, y, z); //posicao do objecto
glRotatef(-AngleX, 0, 1, 0);
[b:4d81e227de]glRotatef(-AngleY, 1, 0, 0);[/b:4d81e227de]
//Render objeto
glPopMatrix;
[/i:4d81e227de]
Para o angleY eu uso outra funcao getAngleY, que utiliza o componentes Y e Z ao invez do X e Z como na funcao getAngleX;
Se alguém tiver alguma idéia, qq ajuda... valeu !!!
Rickyale2
Curtidas 0
Respostas
Rickyale2
06/02/2008
aee consegui finalmente!! mas não usei métodos convencionais hahaha..
vou postar aqui caso alguem queira utilizar:
Function DistanceXZ(pa, pb : XVector): Single;
Var dx,dy, dz : Single;
Begin
dx := (pb.x-pa.x);
dz := (pb.z-pa.z);
Result := Sqrt((dx*dx)+(dz*dz));
End;
function getAngleX(Pa, Pb : XVector) : Integer;
begin
Result := Round((180 * ((ArcTan2(Pa.x-Pb.x, Pa.z-Pb.z) / -PI)))+180);
end;
function getAngleY(Pa, Pb : XVector) : Integer;
begin
Result := Round((180 * ((ArcTan2(Pa.y-Pb.y, -DistanceXZ(pa, pb)) / PI))))+180;
end;
Objetivo: fazer com que um objeto olhe diretamente para um determinado ponto X,Y,Z baseado em angulos:
X de 0-360 olha para os ´lados´ esquerda direita
Y de 0-360 olha para cima e para baixo
Como utilizar: exemplo
type XObject = class
posicao : XVector;
AngleX, AngleY : Single; para onde está olhando.
end;
var ObjA, ObjB : XObject;
//faz objeto A olhar para objeto B
ObjA.AngleX := getAngleX(ObjA.position, ObjB.position);
ObjA.AngleY := getAngleY(ObjA.position, ObjB.position);
na funcao draw:
glPushMatrix;
glTranslatef(A.position.x, A.position.y, A.position.z);
if rAngleX > 0 then glRotatef(-rAngleX, 0, 1, 0);
if rAngleY > 0 then glRotatef(-rAngleY, 1, 0, 0);
Objeto.
glPopMatrix;
Funciona perfeito, mas to com a impressão que não era pra ser assim. mas ta valendo. Quando eu aprender eu melhoro o codigo.
e tb dá pra melhorar um pouco ai, pra não ter q fazer tantas conversões. essa foi a versão beta.
espero q ajude alguém até+
vou postar aqui caso alguem queira utilizar:
Function DistanceXZ(pa, pb : XVector): Single;
Var dx,dy, dz : Single;
Begin
dx := (pb.x-pa.x);
dz := (pb.z-pa.z);
Result := Sqrt((dx*dx)+(dz*dz));
End;
function getAngleX(Pa, Pb : XVector) : Integer;
begin
Result := Round((180 * ((ArcTan2(Pa.x-Pb.x, Pa.z-Pb.z) / -PI)))+180);
end;
function getAngleY(Pa, Pb : XVector) : Integer;
begin
Result := Round((180 * ((ArcTan2(Pa.y-Pb.y, -DistanceXZ(pa, pb)) / PI))))+180;
end;
Objetivo: fazer com que um objeto olhe diretamente para um determinado ponto X,Y,Z baseado em angulos:
X de 0-360 olha para os ´lados´ esquerda direita
Y de 0-360 olha para cima e para baixo
Como utilizar: exemplo
type XObject = class
posicao : XVector;
AngleX, AngleY : Single; para onde está olhando.
end;
var ObjA, ObjB : XObject;
//faz objeto A olhar para objeto B
ObjA.AngleX := getAngleX(ObjA.position, ObjB.position);
ObjA.AngleY := getAngleY(ObjA.position, ObjB.position);
na funcao draw:
glPushMatrix;
glTranslatef(A.position.x, A.position.y, A.position.z);
if rAngleX > 0 then glRotatef(-rAngleX, 0, 1, 0);
if rAngleY > 0 then glRotatef(-rAngleY, 1, 0, 0);
Objeto.
glPopMatrix;
Funciona perfeito, mas to com a impressão que não era pra ser assim. mas ta valendo. Quando eu aprender eu melhoro o codigo.
e tb dá pra melhorar um pouco ai, pra não ter q fazer tantas conversões. essa foi a versão beta.
espero q ajude alguém até+
GOSTEI 0