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

CrzB

[C++/OpenGL] Rodar peça

Mensagens Recomendadas

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


Ligação para a mensagem
Partilhar noutros sites
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


Ligação para a mensagem
Partilhar noutros sites
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


Ligação para a mensagem
Partilhar noutros sites
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


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
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


Ligação para a mensagem
Partilhar noutros sites
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 ?!


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
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


Ligação para a mensagem
Partilhar noutros sites
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


Ligação para a mensagem
Partilhar noutros sites
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


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
CrzB

Eu não estou a usar glRotatef.

O Flinger é que me aconselhou a usar.

Tal como disse eu só estava a mudar posições o que não funciona.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
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.


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
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


Ligação para a mensagem
Partilhar noutros sites
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);
}


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
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


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
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


Ligação para a mensagem
Partilhar noutros sites
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.


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
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


Ligação para a mensagem
Partilhar noutros sites
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.


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
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.


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Partilhar esta mensagem


Ligação 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 os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.