Ir ao conteúdo
  • Cadastre-se

Recommended Posts

Pseudo 3D


 


Olá a todos. Falarei a respeito de algo interessante na programação, o pseudo 3D. O Pseudo 3D é um método utilizado para renderização de um ambiente com uma sensação de profundidade (eixo Z) porém o efeito é apenas ilusão.


Este método de renderização era utilizado em muitos jogos antigos como por exemplo, os jogos de corrida onde a pista da corrida parecia ter uma profundidade.


curves1.png


 


 


Existem tipos parecidos de renderização como o "Mode 7" onde a renderização já possui mais recursos como por exemplo, a Rotação.


Mode_7_Test-0000.png


 


Gostaria de falar a respeito com o pessoal do forum, para pedir se alguém possui algum material explicativo ou algum tutorial onde ensine o básico sobre esta renderização.


Bem bacana ter conhecimento para ver como na realidade funciona o openGL por baixo dos panos. 


 


Sei que deve existir uma lógica bem básica para isto e quero aprender, para assim, programar algo em JAVA. 


 


Gostaria também de saber se existe um nome específico para este tipo de renderização.


 


Código:


Podemos utilizar uma simples JFrame em java, criar um Thread, más a lógica para que possamos gerar este eixo Z, e movimentar as faixas geradas para dar impressão 3D é o que preciso.


O assunto é um pouco complicado para ser encontrado na internet, más o que achei foi o conteúdo deste site, porém ainda sim é um tanto complexo a explicação.


http://www.extentofthejam.com/pseudo/


 


Se puderem disponibilizar algo básico em java com esta lógica utilizada ajudará muito.


 


 


Evolução:


Tentei reproduzir um efeito simples em Pseudo3D da mesma forma utilizar para estes jogos antigos. Obtive o seguinte resultado:


GxTAY5b.gif



package pseudo3d;

/**
*
* @author Vinicius
*/
public class Pseudo3D {

public static void main(String[] args) {

new Tela();

}
}


package pseudo3d;

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;

/**
*
* @author Vinicius
*/
public class Tela extends JFrame implements Runnable, KeyListener{

//Constantes - Tamanho
public static final int LARGURA = 800;
public static final int ALTURA = 600;
public static final int CENTRO_LARGURA = LARGURA / 2;
public static final int CENTRO_ALTURA = ALTURA / 2;

//Constantes - Evento
public static final int PARADO = 0;
public static final int CIMA = 1;
public static final int BAIXO = 2;
public static final int ESQUERDA = 3;
public static final int DIREITA = 4;

//Atributos - Imagem
private BufferedImage imagem;
private Graphics grafico;
private Render3D render3D;

//Atributos - Evento
private int evento = PARADO;
private int deslocamentoX = 0, deslocamentoZ = 0;

/*
* Construtor
*/
public Tela()
{
this.setTitle("Pseudo-3D v1.0");
this.setSize(LARGURA, ALTURA);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.addKeyListener(this);
this.setVisible(true);

this.imagem = new BufferedImage(LARGURA, ALTURA, BufferedImage.TYPE_INT_RGB);
this.grafico = this.imagem.getGraphics();

new Thread(this).start();
}

/**
* Calcular fps do sistema.
* <p>
* <code>long tempo = System.currentTimeMillis(); </code>
* <p>
* <code>while(System.currentTimeMillis() - tempo < 30);</code>
*/
public void fps()
{
long tempo = System.currentTimeMillis();

while(System.currentTimeMillis() - tempo < 30);

//System.out.println("fps: " + (System.currentTimeMillis() - tempo));
}

/**
* Verificar evento de movimentação.
* Irá realizar validação de limite.
*/
private void evento()
{
switch(this.evento)
{
case CIMA: this.deslocamentoZ++; break;
case ESQUERDA: this.deslocamentoX-= 40; break;
case DIREITA: this.deslocamentoX+= 40; break;
}

if(deslocamentoZ > 5)
{
deslocamentoZ = 0;
}
}

@[member=override]
public void run()
{
this.render3D = new Render3D(this);

while(true)
{
this.fps();

this.render3D.renderTeto(deslocamentoZ);
this.render3D.renderPiso(deslocamentoZ);
this.render3D.renderProfundidadeTeto(deslocamentoX);
this.render3D.renderProfundidadePiso(deslocamentoX);

this.repaint();

this.evento();
}
}

@[member=override]
public void keyTyped(KeyEvent e)
{
}

@[member=override]
public void keyPressed(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_UP: this.evento = CIMA; break;
case KeyEvent.VK_DOWN: this.evento = BAIXO; break;
case KeyEvent.VK_LEFT: this.evento = ESQUERDA; break;
case KeyEvent.VK_RIGHT: this.evento = DIREITA; break;
}
}

@[member=override]
public void keyReleased(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_UP:
case KeyEvent.VK_DOWN:
case KeyEvent.VK_LEFT:
case KeyEvent.VK_RIGHT:
this.evento = PARADO; break;
}
}

@[member=override]
public void paint(Graphics g)
{
g.drawImage(this.imagem, 0, 0, this);
}

/*
* Get e Set
*/
public BufferedImage getImagem() {
return imagem;
}

public void setImagem(BufferedImage imagem) {
this.imagem = imagem;
}

public Graphics getGrafico() {
return grafico;
}

public void setGrafico(Graphics grafico) {
this.grafico = grafico;
}
}



package pseudo3d;

import java.awt.Color;

/**
*
* @author Vinicius
*/
public class Render3D {

//Atributos - Imagem
private Tela tela;

/**
* Construtor da classe. Passar uma tela para que seja renderizado
* as linhas bidimensionais.
* @param tela
*/
public Render3D(Tela tela)
{
this.tela = tela;
}

/**
* Renderizar Teto na tela em perpectiva. Passar como parâmetro o deslocamento.
* Passar 0 como valor do parâmetro para não fornecer deslocamento.
* <p>
* Utilizará variável "Z" para calcular a profundidade
* @param deslocamento
*/
public void renderTeto(int deslocamento)
{
int z = 2 + deslocamento;

for(int i = this.tela.CENTRO_ALTURA; i >= 0; i--)
{
if(i == (this.tela.CENTRO_ALTURA - z))
{
this.tela.getGrafico().setColor(Color.BLACK);
z *= 2;
}
else
{
this.tela.getGrafico().setColor(Color.GRAY);
}

this.tela.getGrafico().drawLine(0, i, this.tela.LARGURA, i);
}
}

/**
* Renderizar Piso na tela em perpectiva. Passar como parâmetro o deslocamento.
* Passar 0 como valor do parâmetro para não fornecer deslocamento.
* <p>
* Utilizará variável "Z" para calcular a profundidade
* @param deslocamento
*/
public void renderPiso(int deslocamento)
{
int z = 2 + deslocamento;

for(int i = this.tela.CENTRO_ALTURA; i < this.tela.ALTURA; i++)
{
if(i == (this.tela.CENTRO_ALTURA + z))
{
this.tela.getGrafico().setColor(Color.BLACK);
z *= 2;
}
else
{
this.tela.getGrafico().setColor(Color.DARK_GRAY);
}

this.tela.getGrafico().drawLine(0, i, this.tela.LARGURA, i);
}
}

/**
* Renderizar profundidade do Teto na tela em perpectiva. Passar como parâmetro o deslocamento.
* Passar 0 como valor do parâmetro para não fornecer deslocamento.
* <p>
* Utilizará variável "Z" para calcular a profundidade
* @param deslocamento
*/
public void renderProfundidadeTeto(int deslocamento)
{
this.tela.getGrafico().setColor(Color.BLACK);

for(int i = (this.tela.ALTURA * this.tela.LARGURA) * -1; i < (this.tela.LARGURA * this.tela.ALTURA); i++)
{
if((i + deslocamento) % 600 == 0)
{
this.tela.getGrafico().drawLine(i, 0, this.tela.CENTRO_LARGURA, this.tela.CENTRO_ALTURA);
}
}
}

/**
* Renderizar profundidade do Piso na tela em perpectiva. Passar como parâmetro o deslocamento.
* Passar 0 como valor do parâmetro para não fornecer deslocamento.
* <p>
* Utilizará variável "Z" para calcular a profundidade
* @param deslocamento
*/
public void renderProfundidadePiso(int deslocamento)
{
this.tela.getGrafico().setColor(Color.BLACK);

for(int i = (this.tela.ALTURA * this.tela.LARGURA) * -1; i < (this.tela.LARGURA * this.tela.ALTURA); i++)
{
if((i + deslocamento) % 600 == 0)
{
this.tela.getGrafico().drawLine(i, this.tela.ALTURA, this.tela.CENTRO_LARGURA, this.tela.CENTRO_ALTURA);
}
}
}
}


Obs:


Já fiz uma postagem no fórum referente a técnicas de renderização em 3D utilizando Ray Casting, e o que encontrei na internet foi um tutorial super complexo. Procurei até demais para encontrar uma simples classe java que me ajudasse a aprender, com um código básico, simples e muito melhor que o código complexo.


Estou aqui para solicitar algo básico e se puderem ajudar :rolleyes:  estarei grato. 


 


 


Demonstração:


Este app foi desenvolvido por um gringo. Feito em javascript, e por possuir muitos recursos, não ficou bom para ter uma noção e sim, bom para se perder no código.


http://codeincomplete.com/projects/racer/v1.straight.html


Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×