Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #57 da revista programar. Faz já o download aqui!

CrzB

[C++/OpenGL] Rodar peça

Mensagens Recomendadas

CrzB    0
CrzB

Boas pessoal.

Estou a desenvolver um jogo em que a primeira parte consiste na criação de um cenário tipo tetris.

Já tenho esta parte bem adiantada. O que me falta é a rotação da peça em 90º graus.

Estive a pesquisar e encontrei umas "fórmulas" que consistem no seguinte:

novo x = -y

novo y= x(antigo)

O problema destas fórmulas, apesar de ela rodar, é que não se mantêm no sitio em que estão antes de proceder á rotação, isto é se a peça estiver na posição, por exemplo, (-3,5), ela roda, como eu quero, mas para uma posição longe de onde a peça se encontrava.

Gostava que me ajudassem a manter a peça no sitio onde ela se encontra mesmo quando a rodo.

Nota: O jogo está a ser feito em C++/OpenGL.

Cumprimentos.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Flinger    50
Flinger

void  glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);

em que o x, y e z são as coordenadas do eixo de rotação.

Exemplo:

glRotatef(angulo, 1.0f, 0.0f,0.0f)

roda no eixo dos x. Não me lembro é das unidades dos angulos... não era º, creio eu

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
CrzB    0
CrzB

Primeiro que tudo obrigado Flinger.

Cada peça que tenho é composta por 4 cubos(tetrónimo).

Usando o glRotatef como garanto que vão girar os quatros cubos de forma correcta? Quando crio os cubos?

Eu crio os cubos desta forma :

..

glBegin(GL_POLYGON);
    glVertex2f(x,y);
    glVertex2f(x,y);

    ...

Coloco o glRotate antes da criação dos 4 vértices de cada cubo ?

Obrigado :cheesygrin:

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1125
HappyHippyHippo

porque é exactamente por isso que a rotacao manda o objecto para outro lugar ... a rotacao nao esta a ser feita com o objecto no centro do eixo de rotacao

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
CrzB    0
CrzB

Sim mas eu não estou a usar o glRotatef.

A única coisa que estou a fazer é alterar os valor de x e y como disse:

novo x = -y(antigo)

novo y = x(antigo)

Cumprimentos.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1125
HappyHippyHippo

Gostava que me ajudassem a manter a peça no sitio onde ela se encontra mesmo quando a rodo.

A única coisa que estou a fazer é alterar os valor de x e y como disse:

novo x = -y(antigo)

novo y = x(antigo)

porque é exactamente por isso que a rotacao manda o objecto para outro lugar ... a rotacao nao esta a ser feita com o objecto no centro do eixo de rotacao

o que queres que te diga ... le novamente ?!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
CrzB    0
CrzB

Eu não estou a perceber onde queres chegar visto eu não estar a rodar nada exactamente.

Tal como leste só estou a mudar variáveis.

Mas para estares com esse tipo de respostas dispenso a tua ajuda.

Obrigado pela tua resposta. Cumprimentos.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
luis7    0
luis7

Nao te esqueças de colocar tudo numa Matrix

glPopMatrix();

glRotatef();

...

glPushMatrix();

O que te estavam a dizer é que, se tentares rodar a peça sem a moveres vai fazer uma rotação não da peça sobre si mesma, mas da peça sobre o eixo e como é óbvio ela vai mudar de posição.

Para rodares a peça sobre si mesma tens sempre de a mover para a origem.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1125
HappyHippyHippo

O problema destas fórmulas, apesar de ela rodar

Usando o glRotatef como garanto que vão girar os quatros cubos de forma correcta? Quando crio os cubos?

Eu não estou a perceber onde queres chegar visto eu não estar a rodar nada exactamente.

Tal como leste só estou a mudar variáveis.

Porque é que não segues alguns tutoriais na net tipo o do NeHe ??

o que andas a dizer não faz sentido.

primeiro dizes que rodas e depois dizes que nao rodas, so mudas posicões ...

garanto-te que alguma rotação estáa ser feita pelo simples facto de usares o glRotatef

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1125
HappyHippyHippo

Se nao estas a usar o glRotatef não estas a rodar, quanto muito esta a posicionar noutro lugar.

Logo não podes dizer que roda como disseste no primeiro post.

Para te explicar melhor somente com o código onde fazes a alteração e uma melhor explicação de que o que deveria acontecer e o que esta a acontecer.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
CrzB    0
CrzB

Ok esquecendo o que eu tenho porque não está a fazer o que eu quero.

O que eu quero é que uma determinada figura que tenho, neste caso é um tetronimo(conjunto de 4 cubos) quero fazer com que a figura rode tal como acontece no tetris quando carregamos numa determinada tecla.

O flinger disse-me que tenho que usar o glRotate.

Eu tenho uma função chamada desenhaFigura que o que faz é entrar num for e criar 4 cubos.

Código:

void desenhacubo(cubo c, GLfloat cor[]){

  glBegin(GL_POLYGON);
    glColor3f(cor[0], cor[1], cor[2]);
glVertex2f(c.cima.esq.x,c.cima.esq.y);
glVertex2f(c.cima.dir.x,c.cima.dir.y);
glVertex2f(c.baixo.dir.x,c.baixo.dir.y);
glVertex2f(c.baixo.esq.x,c.baixo.esq.y);
  glEnd();
}

void desenhaFigura(figura f){
for(int k=0;k<4;k++){	
	desenhacubo(f.cbs[k],f.cor);
}
}

Posto isto queria saber como fazer para a figura rodar como no tetris e ficar no sitio que está e ir buscar as novas coordenadas dos vertices dos cubos.

Agradeço a ajuda.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1125
HappyHippyHippo

Para resolver esse problema não usas a rotação do opengl pela simples razão que as posicões da figura deverão influenciar directamente o "mundo" do jogo.

No entanto, o problema não é tam directo como o que possa parecer pelas seguintes razões:

- uma rotação efectuada no canto do jogo pode provocar alguns dos cubos da figura sair do jogo

- uma rotação efectuada próxima de cubos já existentes podem se sobrepor

- uma rotação de uma figura (normalmente) não se enquadra dentro de um um cubo, como por exemplo a barra (4x1 >> 1X4)

A minha opinião é que tenhas uma representação lógica do jogo onde vais verificar se a rotação é possivel fazer sem complicações.

No que toca à rotação, experimenta pegar num caderno quadriculado de fazaer quadrados de 3x3 (ou 4x4 para a barra) e verificares como podes rodar as peças dentro desses quadrados.

Depois de veres como queres que as peças fiquem após a rotação (mais acima ou abaixo), podes mapear a transformação de cada cubo da figura, do género:

void mover_cubo(cubo c, float vertical, float horizontal) {
  c.cima.esq.x += horizontal;
  ...
}

void rodar_figura(figura f) {
  int x1,x2,x3,x4,y1,y2,y3,y4;

  switch (f.tipo) {
    case BARRA:
      // movimentos dos cubos
      x1 = ...;
      x2 = ...;

      // verificar problemas se a rotacao for feita e alterar os x1,x2 ... de acordo
      ....

      break;
    ....
  }

  mover_cubo(f.cbs[0], x1, y1);
  mover_cubo(f.cbs[1], x2, y2);
  mover_cubo(f.cbs[2], x3, y3);
  mover_cubo(f.cbs[3], x4, y4);
}

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
KTachyon    272
KTachyon

Fazer uma rotação mudando os valores dos vértices não é computação gráfica. É desenho :cheesygrin:

Em primeiro lugar, não vejo nenhum cubo a ser desenhado. Um cubo tem 6 faces e não 4, e as posições dos vértices dependes apenas de uma medida.

Se tu começares por fazer uma translação para a posição onde queres desenhar o cubo/quadrado, depois fizeres uma rotação (com um ângulo que é actualizado quando o utilizador carrega numa tecla) e finalmente desenhares o cubo/quadrado como se estivesses na origem (ou seja, não existem dependências do posicionamento do cubo nos valores dos vértices, são todos calculados da mesma forma), fazes exactamente o que pretendes.

Agora, aquilo que é crucial é que tu não cries os vértices em locais específicos no "mundo". O que tens que fazer é desenhar sempre os objectos numa origem que defines com uma função de translação (glTranslate). Se vais desenhar vários objectos que têm posições específicas relativas a uma origem, utilizas aquilo que o luis7 indicou para permitir que retornes a um determinado ponto.

A título de exemplo, imagina que queres desenhar um quadrado com tamanho 1 e centro em (2, 2, -4). Farias qualquer coisa como:

glPush(); // guarda a matriz de estado actual (estado X)
glTranslatef(2.0f, 2.0f, -4.0f); // faz uma translação para o centro do quadrado
desenhaQuadrado(1.0f);
glPop();  // recupera a matriz do estado X

Sendo que a tua função para desenhar o quadrado seria qualquer coisa como:

void desenhaQuadrado(GLFloat dim) {
    GLFloat half_dim = dim/2;
    glBegin(GL_POLYGON);
    {
        glVertex3f( half_dim, half_dim, 0.0f);
        glVertex3f(-half_dim, half_dim, 0.0f);
        glVertex3f(-half_dim,-half_dim, 0.0f);
        glVertex3f( half_dim,-half_dim, 0.0f);
    }
    glEnd();
}

Para desenhares um cubo completo tens que desenhar 6 faces. Para isso podes fazer tudo de uma vez baseado no centro do cubo (utilizando a 3ª coordenada com variações do half_dim, e tendo atenção à regra da mão direita), ou então utilizas vários rotates e translates para centrares em cada um dos cubos e desenhas um quadrado como está na função anterior para cada uma das faces.

Em pseudocódigo:

Para cada face do cubo:
    glPush()
    Aplica a rotação para ficar de frente para a face
    Aplica uma translação de (0, 0, half_dim)
    desenhaQuadrado(dim);
    glPop()

Para fazeres a rotação em torno do centro do quadrado ou do cubo, tens que a fazer depois de posicionares a origem, ou seja:

Translate para o centro do quadrado/cubo
Roda N em torno do eixo (x, y, z)
Desenha o quadrado/cubo

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Flinger    50
Flinger

Básicamente tens 2 opções. Ou fazes como o  KTachyon te disse, isto é, mudas o teu eixo de origem e desenhas a peça sempre da mesma maneira (pensa nisto como estares a rodar o mundo de forma a desenhares a tua peça, que é sempre desenhada daquela forma), ou então tens tu de recalcular as coordenadas todas da tua peça.

A primeira forma é a forma correcta de fazer animação. No teu caso, como os movimentos são bastante simples, recalcular as posições também não é muito complicado, mas se tivesses movimentos contínuos, ias ter uma trabalheira danada.

Se quiseres ainda assim desenhar recalculando as coordenadas, então esquece o rotate. O que tens de fazer é andar sempre com um ponto que represente o centro do polígono (Não dos quadrados, mas da figura). Os quadrados são desenhados de acordo com esse ponto e com  o ângulo de rotação. Ou seja, não andes com as coordenadas absolutas dos vértices atrás de ti, anda só com o centro do polígono e com o ângulo.

Faz como o Hyppo te disse, e desenha cada figura nas várias posições. escolhes o ponto central, e para cada posição vês quais são as coordenadas relativas dos vértices.

Se optares por esta solução, mais tarde vais descobrir que a primeira faz basicamente o mesmo e é mais simples :cheesygrin:

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1125
HappyHippyHippo

Se optares por esta solução, mais tarde vais descobrir que a primeira faz basicamente o mesmo e é mais simples :cheesygrin:

Sim é mais simples no que toca a apresentação da figura, mas tens de ver que a estutura de dados que ele tem não parece estar adequada a esse modelo.

Como disse no post anterior, existe as colisões entre figuras que teem de ser verificadas. Nota que o rodar a figura no estilo OpenGL não te da nenhuma informação de colisão sem ires usares uma tecnica que envolva a leitura do depth buffer ou o stencil buffer.

A solução que ele está a desenvolver é mais prática para este tipo de problemas em que as figuras/quadrados somente ocupam posições bem definidas.

No final é uma opção : rápido a apresentar e mais complicado a determinar a lógica do jogo ou vice-versa.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Flinger    50
Flinger

hmm... tens razão aí. Uma técnica usando hitboxes não se aplica,  e ele teria de recalcular as posições absolutas do polígono de qualquer forma. 

Os movimentos que vais fazer são fluídos ou escalados? Ou seja, a peça está sempre a cair, ou de x em x tempo desce um degrau?

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pikax    172
pikax

Quanto a OpenGL não posso ajudar muito.

Mas pelo o que sei, tens as matrizes(world, project,view, local,etc), cada objecto que vás desenhar irá ter uma matrix de local space:

float mat []={  
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
}

que é uma matrix que não altera as posições dos vertices.

quando tu queres mover um objecto fazes:

TranslateMatrix(&mat,2.0f, 2.0f, -4.0f); //irá mexer a mat para aquele ponto  2.0f->x, 2.0f->y, -4.0f->z;

quando qeres rodar o objecto fazes:

RotateMatrixX(&mat,1.0f);// irá rodar a matrix no eixo do X
RotateMatrixY(&mat,1.0f);// irá rodar a matrix no eixo do Y
RotateMatrixZ(&mat,1.0f);// irá rodar a matrix no eixo do Z

ATENÇÃO!!!: deverás fazer sempre primeiro a rotação e só depois a translação

Depois quando desenhares o objecto usas a matrix(mat) para fazer update às posições dos vertices.

No final multiplicas as matrizes world*mat*view*projection, o resultado desse calculo irá te dar a matriz do objecto referente ao world map, e irá desenhar direito o objecto.

MATRIX view=getCamera()->getViewMat();
MATRIX proj=getCamera()->getprojMat();

MATRIX final=world*mat*view*proj;

setGLSLmatrix(final);//definir a matrix do GLSL como final, já que tem as rotações e translações direitas
object.draw();//desenhar o objecto

Não posso ajudar muito mais porque uso o Direct3D e é um bocado diferente, mas penso que esta parte de matemática seja igual, se tiver a cometer algum engano desculpem.

NOTA: o código que coloquei aqui é pseudo-código, não sei muito como se trabalha com OpenGL, das poucas coisas que sei é que a matriz não é uma matriz(aka float mat[4][4]) mas sim um array(mat[16]).

EDIT: as multiplicações de matrizes não são comutativas, isto é (world*mat*view*proj) é diferente do que (proj*view*mat*world), não respeitando a ordem da multiplicação irás ter resultados inesperados.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
KTachyon    272
KTachyon

Pah, se é mesmo para calculares as rotações dos vértices à mão podes fazer isso manualmente com recurso a matrizes de rotação.

1. Primeiro calculas os valores dos vértices em relação ao ponto central por onde passa o eixo de rotação.

2. Depois multiplicas a matriz de rotação pela matriz de vértices (já mostrei isto em http://www.portugal-a-programar.pt/forums/topic/0-find-topic/?do=findComment&comment=427633)

3. Finalmente voltas a calcular os valores dos vértices em relação ao ponto inicial.

Isto é basicamente uma translação, uma rotação e uma translação inversa.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora


×

Aviso Sobre Cookies

Ao usar este site você aceita a nossa Política de Privacidade