Enviado por junemberg

41Realidadeaumentada

Propaganda
Jairo Barros Junior
([email protected]) é bacharel em Sistemas
de Informação pela Faculdade de Alagoas e possui
experiência em desenvolvimento de software. Está
cursando pós-graduação em gerência de projetos.
Possui certificação SCJP 6 e é instrutor da tecnologia.
Atua como líder técnico no Tribunal de Justiça do
Estado de Alagoas e é co-fundador da empresa Sook –
Desenvolvendo Inovações, na qual atua como líder de
projetos utilizando as tecnologias Java e Ruby.
Realidade
Aumentada
Transforme o Real no Virtual
Construa um simples jogo de quebracabeça utilizando jMonkey Engine e
NyARToolkit.
Descubra como é possível interagir o real com o
virtual, por meio de objetos simples e conheça
os conceitos por trás desta tecnologia. Aprenda
a construir jogos interativos, trazendo de volta o
interesse pelos jogos tradicionais. Saiba quais são
as principais ferramentas utilizadas para tornar
possível a realização da realidade aumentada e
quais os projetos que estão sendo desenvolvidos
com essa poderosa tecnologia.
65
"SUJHPt5SBOTGPSNFP3FBMOP7JSUVBMo3FBMJEBEF"VNFOUBEB
Figura 1. Demonstração de como funciona um ambiente de realidade aumentada.
realidade aumentada, do inglês augmented reality, ou
simplesmente AR, é a sobreposição de objetos virtuais
tridimensionais, gerados por computador, em um ambiente real, por meio de um dispositivo tecnológico. Embora
pareça mágica, não é, funciona da seguinte forma: por meio de um
aplicativo, a câmera fica capturando imagens e as compara utilizando
técnicas de visão computacional. Se existir alguma semelhança com o
cenário preestabelecido, o aplicativo exibe em tempo real uma imagem
em três dimensões, sobreposta no marcador. O marcador pode ser um
quadrado preto-e-branco utilizado como forma de monitoramento.
A AR não é uma tecnologia nova, porém só agora está despertando
interesse dos pesquisadores e da indústria. A figura 1 ilustra como se dá
este processo. Estão sendo criados livros bem mais interativos, imagine
uma criança lendo a história do Sítio do Picapau Amarelo, de Monteiro Lobato, e após posicionar a imagem presente no livro em frente à
câmera, o aplicativo reproduz sons e exibe em três dimensões os personagens. Mas a tecnologia não está apenas limitada à utilização do
papel, na medicina existe o projeto VeinViewer, onde o aparelho emite
raios infravermelhos sob a pele, identificando através do calor as veias.
Após a sua identificação é projetada uma imagem em tempo real sobre
a pele do paciente. Este projeto está sendo utilizado no tratamento de
varizes. São diversas as áreas em que é possível a aplicação da realidade
aumentada, ultimamente vem se investindo bastante na área de publicidade e propaganda, por atrair a atenção de clientes. Outro projeto
impressionante é o Wikitude, desenvolvido para dispositivos móveis
que utilizam o sistema Android e, em breve, no iPhone, o qual segue
a mesma filosofia do Wikipédia, teoricamente a sua funcionalidade é
simples, após posicionar a câmera para um horizonte o aplicativo exibe
informações sobre o local na tela do aparelho, baseado na localização
geográfica.
A
É possível afirmar que com a utilização da AR o poder de interatividade
do usuário com os jogos virtuais do computador é bem maior, não
estamos limitados apenas ao teclado e ao mouse: agora é possível sua
manipulação direta com as mãos ou através de elementos mais simples, como placas, cubos de papel ou madeira, familiares à maioria das
pessoas. Existem alguns projetos que estão sendo desenvolvidos com o
66 www.mundoj.com.br
objetivo de trazer de volta o desejo de jogar os jogos tradicionais, como
quebra-cabeças, jogo de palavras, torre de Hanói, cubo mágico e dominó. São diversas as vantagens que esses tipos de jogos proporcionam,
pois permitem uma maior facilidade de interação entre pessoas que
utilizam comunicação verbal, gestos, expressões faciais e movimentos
naturais para manipulação de objetos.
O principal projeto que torna possível a utilização da AR é o ARToolKit
(http://www.hitl.washington.edu/artoolkit/), desenvolvido em C e
C++, pelo laboratório HIT (Human Interface Technology) da universidade de Washington. A última versão está compatível com os principais
sistemas operacionais. Além do ARToolkit há versões para algumas
linguagens de programação, como Java, ActionScript3 e C#. A AR está
compatível com as tecnologias Android, iPhone e WindowsMobile. Este
artigo apresenta a utilização da realidade aumentada aplicada no desenvolvimento de um jogo de quebra-cabeça utilizando o framework
NyARToolkit, que é uma versão da biblioteca ARToolkit para Java, juntamente com a API de jogos jMonkey Engine – jME, open-source.
Configurando o ambiente
O ambiente utilizado foi WindowsXP e Eclipse com JDK 6, porém todos os
aplicativos e frameworks utilizados neste artigo podem ser implementados em qualquer plataforma. Antes de tudo, é necessário que se tenha
uma webcam. Para este exemplo fui utilizada a LG-Webpro.
Luminosidade adequada, boa resolução da câmera e um bom processamento podem contribuir para uma melhor qualidade do aplicativo.
Utilizaremos basicamente dois frameworks e suas dependências para a
implementação do jogo de quebra-cabeça, são eles:
NyARToolKit
NyARToolkit é um framework que proporciona a interação da webcam
com os marcadores, escrito 100% em Java e está sob licença GPL.
Para se ter uma noção da evolução deste framework, após a con-
"SUJHPt5SBOTGPSNFP3FBMOP7JSUVBMo3FBMJEBEF"VNFOUBEB
Figura 2. Representação do diretório onde se encontram as dlls.
clusão do exemplo deste artigo, foi lançada uma nova versão. Faça
o download da última versão "NyARToolkit for Java – NyARToolkit
Core-2.4.0", disponível em: http://nyatla.jp/nyartoolkit/wiki/index.
php?NyARToolkit%20for%20Java.en, e importe para a sua Workspace. Para importar, abra o Eclipse File->Import->General – Existing Projects into Workspace, selecione a pasta NyARToolkit-2.4.0 e importe os
projetos: NyARToolkit, NyARToolkit.utils.jmf e NyARToolkit.utils.jogl.
O projeto NyARToolkit.utils.jmf e o NyARToolkit.utils.jogl necessitam
da biblioteca JMF 2.1, baixe o instalador, para o Windows, disponível em: http://java.sun.com/javase/technologies/desktop/media/
jmf/2.1.1/download.html. Antes de instalar o JMF, certifique-se que
a webcam já esteja conectada ao computador, pois durante a instalação é realizada uma busca dos dispositivos, essa mesma ação pode
ser realizada nas preferências do aplicativo. Além dessa biblioteca o
projeto NyARToolkit.utils.jogl requer a gluegen-rt.jar e jogl.jar, que
podem ser encontradas na pasta “lib” do projeto jMonkey Engine.
Finalmente, para que o NyARToolkit consiga utilizar todas essas bibliotecas é necessário, para o Windows, algumas dlls. Para não fugir do
foco deste artigo e torná-lo mais didático, você pode baixar todas elas
a partir do site da revista, lembrando que assim como elas estão disponíveis para o Windows, existem para os outros sistemas operacionais.
jMonkey Engine
jMonkey Engine – jME é o motor gráfico, atualmente muito utilizado no
desenvolvimento de jogos, escrito totalmente em Java. Ele irá apresentar
nossos objetos em 3D e tornará possível a interação com teclado e mouse, caso necessário. Faça o download da última versão jME 2.0, disponível
em: http://www.jmonkeyengine.com/
Criando o projeto do jogo
Com o Eclipse aberto, crie um novo projeto Java, denominado de Puzzle.
Configure o Build Path, associando os projetos importados anteriormente,
Project->Properties->Java Build Path, na aba Projects adicione os três
projetos do NyARToolkit. Descompacte a pasta com as dlls dentro deste
projeto e novamente configure o Build Path, editando o caminho do Native
Library Location, da sua JRE, para a pasta das dlls, como mostra a figura 2.
Após ter configurado as bibliotecas do NyARToolkit, é hora de adicionar
as bibliotecas do jME ao projeto. Para isso, localize e adicione os seguintes Jars, como mostra na figura 3.
No final, seu projeto deve ficar com a mesma estrutura apresentada na
figura 3. Para o desenvolvimento deste jogo, é necessário criar quatro
marcadores e seus arquivos-padrão, que irão representar cada peça individualmente. É necessário ainda criar quatro peças em 3D e associá-las a
uma imagem, que será o objetivo final do jogo.
Criando os marcadores
Após ter configurado o ambiente, é necessário criar os marcadores. Um
marcador é a referência que a câmera possui para que o aplicativo possa
acionar a execução de alguma funcionalidade. Um marcador pode ser
representado de diversas formas. Neste artigo, será representado por
imagens em 2D. Para cada marcador terá uma peça do jogo associada.
Crie quatro imagens simples, diferentes, preto-e-branco, com alto contraste e com bordas grossas. Na parte central da imagem, desenhe um
símbolo que será interpretado pela webcam. Lembrando que quanto
maior a espessura do símbolo mais fácil sua identificação. Para este artigo
foram utilizadas as imagens dos marcadores apresentadas na figura 4.
67
"SUJHPt5SBOTGPSNFP3FBMOP7JSUVBMo3FBMJEBEF"VNFOUBEB
Figura 3. Estrutura geral do projeto e suas dependências.
Figura 4. Marcadores.
68 www.mundoj.com.br
"SUJHPt5SBOTGPSNFP3FBMOP7JSUVBMo3FBMJEBEF"VNFOUBEB
Figura 5. Imagem que será o objetivo do quebra-cabeça.
Para facilitar o manuseio dos marcadores, é importante que eles sejam colados em uma superfície rígida, você pode colá-los em pedaços de papelão
ou madeira.
A classe na Listagem 2 representa o modelo das peças. Esta classe é responsável por carregar o arquivo em 3D, aplicar a sua textura e configurar
o diretório onde se encontra o arquivo .pat.
Para que o jogo possa interagir com os marcadores, é necessário gerar um
arquivo-padrão, que possui a extensão .pat. Nele está a representação do
marcador. O arquivo .pat pode ser gerado no aplicativo MakerGenerator para
Adobe Air, disponível em: http://saqoosha.net/lab/FLARToolKit/MarkerGenerator/MakerGenerator.air, ou até mesmo on-line, no site: http://flash.
tarotaro.org/ar/MarkerGeneratorOnline.html. Com este aplicativo, é possível
gerar o arquivo .pat de duas formas: posicionando a imagem do marcador já
impressa em frente à webcam ou enviando o arquivo da imagem (.jpg, .gif ou
.png). Salve os arquivos gerados dentro da pasta "Data", com a extensão .pat
e com os seguintes nomes: 1, 2, 3 e 4. No final, teremos quatro marcadores
iguais aos da figura 4, com seus respectivos arquivos .pat. Os marcadores e os
arquivos .pat podem ser baixados a partir do site da revista.
Agora, iremos implementar os métodos individualmente da classe
Puzzle. Para não dificultar a visualização dos próximos códigos, todos os imports necessários estão na Listagem 1. Na Listagem 3 estão
sendo configurados os parâmetros que serão utilizados pelo jMonkey.
Juntando as peças
Após ter criado os marcadores, deve-se modelar os objetos em 3D que serão
representados pelas peças. Crie quatro peças em 3D de forma que uma se
encaixe nas outras. Para a construção das peças foi utilizado o Blender na
versão 2.49b, que pode ser baixado em: http://www.blender.org/
Salve cada peça individualmente dentro da pasta "Data", com a extensão .3ds
e com os seguintes nomes: 1, 2, 3 e 4. Escolha uma imagem que será sobreposta nas peças, na qual formará o desenho do quebra-cabeça montado, e
recorte a imagem de acordo com os objetos criados em 3D. Para este artigo,
iremos utilizar a figura 5.
Finalmente, agora é hora de criar a classe que irá interagir com todos esses
objetos. A Listagem 1 apresenta um simples exemplo de uma classe base para
qualquer implementação que deseje fazer com a utilização destes frameworks.
A Listagem 4 contém as configurações necessárias para a inicialização do
dispositivo da webcam. Nela são adicionados os códigos dos marcadores que
serão capturados pela webcam e interpretados pelo método da Listagem 7.
A Listagem 5 é uma classe que faz parte do projeto NyARToolkit Java3D
utilities, porém não vem incluso na API que foi baixada. Ela encontra-se
sob licença do MIT.
De volta à implementação da classe Puzzle, a Listagem 6 é uma das
mais importantes: é nela onde ocorre o processo de captura e armazenamento do buffer gerado pela webcam que será utilizado pelo
método da Listagem 7. IMPORTANTE: por questão de performance,
as imagens capturadas pela webcam não terão todas as cores, porém as imagens dos modelos em 3D que serão carregados estarão
normais.
Na Listagem 7 é onde ocorre todo o processamento principal,
o método simpleUpdate é responsável por ficar comparando as
imagens capturadas pela câmera, a fim de verificar a existência de
marcadores. Após a identificação dos marcadores, as peças em 3D
serão “projetadas” na superfície do papel. Este método é executado
quadro a quadro, deve-se ter cuidado com sua implementação, pois
se ele demorar a ser executado, o aplicativo terá um baixo desempenho na visualização, tornando lenta sua exibição.
69
"SUJHPt5SBOTGPSNFP3FBMOP7JSUVBMo3FBMJEBEF"VNFOUBEB
Listagem 1. Modelo da classe base do jogo.
Listagem 2. Classe modelo que representa as peças.
package game;
package game;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingSphere;
import com.jme.image.Texture;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.MaxToJme;
import com.jmex.model.converters.ObjToJme;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import javax.media.Buffer;
import jp.nyatla.nyartoolkit.NyARException;
import jp.nyatla.nyartoolkit.core.NyARCode;
import jp.nyatla.nyartoolkit.core.param.NyARPerspectiveProjectionMatrix;
import jp.nyatla.nyartoolkit.core.transmat.NyARTransMatResult;
import jp.nyatla.nyartoolkit.detector.NyARDetectMarker;
import jp.nyatla.nyartoolkit.jmf.utils.JmfCaptureDevice;
import jp.nyatla.nyartoolkit.jmf.utils.JmfCaptureDeviceList;
import jp.nyatla.nyartoolkit.jmf.utils.JmfCaptureListener;
import jp.nyatla.nyartoolkit.jogl.utils.GLNyARRaster_RGB;
import com.jme.app.SimpleGame;
import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.image.Image.Format;
import com.jme.light.DirectionalLight;
import com.jme.light.PointLight;
import com.jme.math.Matrix3f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
public class Puzzle extends SimpleGame implements JmfCaptureListener {
private static final String PARAM_FILE = Puzzle.class.getResource(“/”).
getPath() + “/Data/camera_para.dat”;
private static final int WIDTH = 640;
private static final int HEIGHT = 480;
@Override
protected void simpleInitGame() {
//Terá todos os parâmetros para inicialização do jogo
}
@Override
protected void simpleUpdate() {
//Será chamado por cada frame, é ele que irá desenhar as peças nos marcadores
}
@Override
public void onUpdateBuffer(Buffer i_buffer) {
//Captura o buffer gerado pela webcam para incluí-lo no ambiente do jMonkey.
}
}
class Piece extends Node {
private DisplaySystem display;
public Piece(String name, DisplaySystem display) {
super(name);
this.display = display;
this.loadModel3ds();
this.loadTexture();
this.removeFromBoard();
}
public String getPatCodeFile() {
return Piece.class.getClassLoader().getResource(“Data/” + getName()
+ “.pat”).getFile();
}
//Aplica a textura correspondente a peça
private void loadTexture() {
TextureState ts = this.display.getRenderer().createTextureState();
ts.setEnabled(true);
Texture loadTexture = TextureManager.loadTexture(
Piece.class.getClassLoader().getResource(“Data/” + getName() + “.png”),
Texture.MinificationFilter.BilinearNoMipMaps,
Texture.MagnificationFilter.Bilinear);
loadTexture.setApply(Texture.ApplyMode.Decal);
ts.setTexture(loadTexture);
this.setRenderState(ts);
this.updateRenderState();
}
//Carrega o modelo em 3D correspondente a peça
private void loadModel3ds() {
MaxToJme maxToJme = new MaxToJme();
ByteArrayOutputStream output = new ByteArrayOutputStream();
URL url = Piece.class.getClassLoader().getResource(“Data/” +
getName() + “.3ds”);
BinaryImporter binaryImporter = BinaryImporter.getInstance();
try {
maxToJme.convert(url.openStream(), output);
Node model3d = (Node) binaryImporter.load(
new ByteArrayInputStream(output.toByteArray()));
this.attachChild(model3d);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
//Altera a posição da peça, para os casos onde o marcador não foi encontrado
public void removeFromBoard() {
this.setLocalTranslation(0,0,-100000f);
}
}
www.mundoj.com.br
ndoj.com.
j.com.
j.c
om.br
om.
70 www.mundoj.c
"SUJHPt5SBOTGPSNFP3FBMOP7JSUVBMo3FBMJEBEF"VNFOUBEB
Listagem 3. Configuração dos parâmetros de inicialização.
private Quad background;
private TextureState textureState;
private Piece piece1;
private Piece piece2;
private Piece piece3;
private Piece piece4;
private JmfCaptureDevice capture;
@Override
protected void simpleInitGame() {
this.display.setTitle(“Puzzle”);
this.display.setVSyncEnabled(true);
//Desabilita a interação com teclado e mouse
this.input.setEnabled(false);
//Altera a posição da câmera para ficar próximo a tela
this.cam.setLocation(new Vector3f(0, 0, 0));
this.cam.update();
Listagem 4. Inicializa as configurações da câmera, junto com as
do NyARToolkit.
private GLNyARRaster_RGB raster;
private NyARDetectMarker nyArDetectMarker;
private Texture textureBackground;
private Image image;
private void initCapture() {
try {
//Instância o dispositivo da webcam
JmfCaptureDeviceList devlist = new JmfCaptureDeviceList();
this.capture = devlist.getDevice(0);
this.capture.setCaptureFormat(Puzzle.WIDTH, Puzzle.HEIGHT, 15f);
this.capture.setOnCapture(this);
//Criar o quadrado que irá exibir a imagem capturada pela webcam
this.background = new Quad(“Background”);
this.background.updateGeometry(Puzzle.WIDTH*4, Puzzle.HEIGHT*4);
this.background.setCastsShadows(false);
//Configura os parâmetros do NyARToolkit
this.arParam = new JmeNyARParam();
this.arParam.loadARParamFromFile(Puzzle.PARAM_FILE);
this.arParam.changeScreenSize(Puzzle.WIDTH, Puzzle.HEIGHT);
//Gira em 180 graus o quadrado que irá exibir a imagem capturada pela webcam
Matrix3f m = new Matrix3f();
m.fromAngleAxis((float) Math.toRadians(180), new Vector3f(0, 0, 0));
this.background.setLocalRotation(m);
this.raster = new GLNyARRaster_RGB(this.arParam, this.capture.
getCaptureFormat());
//Habilita o quadrado de fundo para processar as imagens que serão
//atribuídas ao textureState
this.textureState = this.display.getRenderer().createTextureState();
this.textureState.setEnabled(true);
this.background.setRenderState(this.textureState);
//Adiciona o código com a lista dos marcadores a serem capturados
double[] width = new double[] { 80.0, 80.0, 80.0, 80.0 };
NyARCode[] arCodes = new NyARCode[4];
arCodes[0] = new NyARCode(16, 16);
arCodes[0].loadARPattFromFile(this.piece1.getPatCodeFile());
arCodes[1] = new NyARCode(16, 16);
arCodes[1].loadARPattFromFile(this.piece2.getPatCodeFile());
arCodes[2] = new NyARCode(16, 16);
arCodes[2].loadARPattFromFile(this.piece3.getPatCodeFile());
arCodes[3] = new NyARCode(16, 16);
arCodes[3].loadARPattFromFile(this.piece4.getPatCodeFile());
this.nyArDetectMarker = new NyARDetectMarker(this.arParam,
arCodes, width, arCodes.length, this.raster.getBufferReader().getBufferType());
this.nyArDetectMarker.setContinueMode(false);
//Cria as peças com seus respectivos nomes
this.piece1 = new Piece(“1”,display);
this.piece2 = new Piece(“2”,display);
this.piece3 = new Piece(“3”,display);
this.piece4 = new Piece(“4”,display);
//Configura o ponto de luz
this.buildLighting();
//Inicializa as configuração da câmera, junto com o NyARToolkit
this.initCapture();
//Adiciona as peças no cenário
this.rootNode.attachChild(this.piece1);
this.rootNode.attachChild(this.piece2);
this.rootNode.attachChild(this.piece3);
this.rootNode.attachChild(this.piece4);
this.rootNode.attachChild(this.background);
//Define os posicionamentos da câmera
NyARPerspectiveProjectionMatrix m =
arParam.getPerspectiveProjectionMatrix();
background.setLocalTranslation(new Vector3f(0, 0,(float) -m.m00 * 4));
float[] ad = arParam.getCameraFrustum();
cam.setFrustum(ad[0], ad[1], ad[2], ad[3], ad[4], ad[5]);
try {
//Inicializa o dispositivo de captura
this.capture.start();
} catch (Exception e) { e.printStackTrace(); }
}
private void buildLighting() {
PointLight pl = new PointLight();
pl.setAmbient(new ColorRGBA(0.75f, 0.75f, 0.75f, 1));
pl.setDiffuse(new ColorRGBA(1, 1, 1, 1));
pl.setLocation(new Vector3f(50, 0, 0));
pl.setEnabled(true);
DirectionalLight dl = new DirectionalLight();
dl.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));
dl.setDiffuse(new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));
dl.setDirection(new Vector3f(0, -1, 1));
dl.setEnabled(true);
this.lightState.attach(pl);
this.lightState.attach(dl);
}
//Cria a textura que receberá os dados da imagem processada
BufferedImage bufferImage = new BufferedImage(Puzzle.WIDTH,
Puzzle.HEIGHT, BufferedImage.TYPE_INT_RGB);
this.textureBackground = TextureManager.loadTexture(bufferImage,
Texture.MinificationFilter.BilinearNoMipMaps,
Texture.MagnificationFilter.Bilinear, true);
} catch (Exception e) {
e.printStackTrace();
}
}
71
"SUJHPt5SBOTGPSNFP3FBMOP7JSUVBMo3FBMJEBEF"VNFOUBEB
Listagem 5. Classe de parâmetros adaptada para a utilização do
jMonkey.
package game;
import jp.nyatla.nyartoolkit.core.param.NyARParam;
import jp.nyatla.nyartoolkit.jogl.utils.NyARGLUtil;
/**
* NyARParam for jMonkeyEngine
*/
public class JmeNyARParam extends NyARParam {
private float distMin = 1.0f;
private float distMax = 10000.0f;
private float[] projection = null;
Listagem 7. Exibe os objetos em 3D.
private ArrayList<Piece> piecesToRemove = new ArrayList<Piece>();
private final NyARTransMatResult displayTransMatResult = new NyARTransMatResult();
@Override
protected void simpleUpdate() {
if (this.image == null) {
return;
}
try {
//Adiciona as peças na lista auxiliar para poder excluir do cenário as
// peças sem referência de marcador
this.piecesToRemove.add(this.piece1);
this.piecesToRemove.add(this.piece2);
this.piecesToRemove.add(this.piece3);
this.piecesToRemove.add(this.piece4);
public void setViewDistanceMin(float val) {
projection = null;
distMin = val;
}
//Adiciona na textura as imagens capturadas pela webcam
synchronized (this.raster) {
TextureManager.deleteTextureFromCard(this.textureBackground);
this.textureBackground.setImage(this.image);
this.textureState.setTexture(this.textureBackground);
}
public void setViewDistanceMax(float val) {
projection = null;
distMax = val;
}
public float[] getCameraFrustum() {
if (projection != null) {
return projection;
}
NyARGLUtil glu = new NyARGLUtil(null);
double[] ad = new double[16];
glu.toCameraFrustumRH(this, ad);
//Obtém a quantidade de marcadores identificados.
int foundMarkerLite = this.nyArDetectMarker.detectMarkerLite(
this.raster, 110);
//Compara o índice do código do marcador para que possa alterar o
// posicionamento da peça, exibindo na tela.
for (int i = 0; i < foundMarkerLite; i++) {
if (i > 3) {
continue;
}
if (this.nyArDetectMarker.getARCodeIndex(i) == 0) {
setLocalPosition(this.piece1, i);
}
if (this.nyArDetectMarker.getARCodeIndex(i) == 1) {
setLocalPosition(this.piece2, i);
}
if (this.nyArDetectMarker.getARCodeIndex(i) == 2) {
setLocalPosition(this.piece3, i);
}
if (this.nyArDetectMarker.getARCodeIndex(i) == 3) {
setLocalPosition(this.piece4, i);
}
}
float near = distMin;
float far = distMax;
float left = (float) (near * (ad[8] + 1) / ad[0]);
float right = (float) (near * (ad[8] - 1) / ad[0]);
float top = (float) (near * (ad[9] + 1) / ad[5]);
float bottom = (float) (near * (ad[9] - 1) / ad[5]);
projection = new float[] { near, far, left, right, top, bottom };
return projection;
}
}
Listagem 6. Captura e armazena o buffer gerado pela webcam.
@Override
public void onUpdateBuffer(Buffer iBuffer) {
try {
synchronized (this.raster) {
this.raster.setBuffer(iBuffer);
ByteBuffer byteBuffer = ByteBuffer.wrap(this.raster.getGLRgbArray());
this.image = new Image(Format.RGB8, Puzzle.WIDTH,
Puzzle.HEIGHT, byteBuffer);
}
} catch (Exception e) {
e.printStackTrace();
}
}
72 www.mundoj.com.br
//Remove da tela as peças que estão sem referência de marcador
for (Piece piece : this.piecesToRemove) {
piece.removeFromBoard();
}
this.piecesToRemove.clear();
Thread.sleep(2);
} catch (Exception e) {
e.printStackTrace();
}
}
"SUJHPt5SBOTGPSNFP3FBMOP7JSUVBMo3FBMJEBEF"VNFOUBEB
C ont. Listagem 7. Exibe os objetos em 3D.
//Altera o posicionamento das coordenadas(X,Y e Z) da peça de acordo com
//o marcador
private void setLocalPosition(Piece piece, int index) throws NyARException {
this.piecesToRemove.remove(piece);
this.nyArDetectMarker.getTransmationMatrix(index, displayTransMatResult);
setLocalRotation(piece);
piece.setLocalTranslation((float) -displayTransMatResult.m03,
(float) (-displayTransMatResult.m13),
(float) -displayTransMatResult.m23);
}
//Altera o posicionamento da rotação da peça de acordo com o marcador
private void setLocalRotation(Piece piece) {
piece.setLocalRotation(new Matrix3f((float) -displayTransMatResult.m00,
(float) -displayTransMatResult.m01, (float) displayTransMatResult.m02,
(float) -displayTransMatResult.m10, (float) -displayTransMatResult.m11,
(float) displayTransMatResult.m12, (float) -displayTransMatResult.m20,
(float) -displayTransMatResult.m21, (float) displayTransMatResult.m22));
}
Listagem 8. Executa o jogo.
public static void main(String[] args) {
Puzzle game = new Puzzle();
game.setConfigShowMode(ConfigShowMode.AlwaysShow);
game.start();
}
Pronto, aguarde uns instantes até que o aplicativo seja carregado e
divirta-se.
Para que o objeto virtual possa aparecer, as bordas quadradas pretas do
marcador devem estar à vista pela câmera.
Como pode ser observado na figura 6 a forma de jogar é muito semelhante ao modelo de quebra-cabeça clássico. Só que com esse modelo de
quebra-cabeça, podemos deixar ainda mais motivador do que o modelo
clássico. Pois se pode agregar novas funcionalidade, como sons e estilos
visuais de vitória. Pode-se ainda criar um ambiente mais complexo, adicionando a participação de vários jogadores, contabilizar as chances que
cada jogador perdeu ao posicionar uma peça errada e salvar o tempo que
o jogador levou para alcançar o objetivo. É importante lembrar que com
a facilidade que se tem em alterar a imagem do objetivo do jogo, esse
novo modelo de quebra-cabeça torna-se ainda mais dinâmico e atraente.
Apesar deste artigo não apresentar nenhuma característica do aplicativo
para Web, é possível adaptar este mesmo projeto para ser executado na
Internet, através de Applets.
Figura 6. Exibição final.
Considerações finais
A interação proporcionada por esta tecnologia pode contribuir de forma
significativa tanto para o entretenimento quanto no processo de ensino
de aprendizagem, pois fornecem ambientes agradáveis, motivadores e
são ricos com ilustrações.
Neste artigo, foram apresentados os principais projetos desenvolvidos
e quais as ferramentas necessárias para a construção de um jogo ou
aplicativo utilizando a realidade aumentada. Além do tipo de sistema
de realidade aumentada utilizado neste artigo, que é o sistema de visão
por vídeo baseado em monitor, o sistema de visão ótica direta, com a
utilização de óculos, vem se inserindo rapidamente, tornando ainda mais
fascinante.
Agradecimentos
Wallisson Narciso foi responsável pelo desenvolvimento da figura 1, que
ilustra como se dá o processo de integração com a realidade aumentada.
Ele também mantém seus trabalhos no blog http://nanquimaoquadrado.
com/blog. Edvaldo Gomes Cruz foi responsável por criar as peças do
quebra-cabeça em 3D. Agradeço também a todos que sanaram minhas
dúvidas no fórum do site jMonkey.
Referências
t
t
t
t
t
t
t
t
t
"35PPM,JUoIUUQXXXIJUMXBTIJOHUPOFEVBSUPPMLJUEPDVNFOUBUJPO
K.POLFZ8JLJoIUUQXXXKNPOLFZFOHJOFDPNXJLJEPLVQIQ
3FBMJEBEF7JSUVBMF"VNFOUBEBoIUUQXXXSFBMJEBEFWJSUVBMDPNCS
)BOEIFME"VHNFOUFE3FBMJUZoIUUQTUVEJFSTUVCFJDHUVHSB[BDBUIBOEIFME@BSBSUPPMLJUQMVT
php
;03;"- &3$"3%040 "MFYBOESF,*3/&3 $MBVEJP-".06/*&3+Á/*03 &EHBSE3FBMJEBEF
Aumentada Aplicada em Jogos Educacionais. http://www.realidadeaumentada.com.br/
BSUJHPTQEG
;03;"- &3#6$$*0-* "SUIVS"VHVTUP#BTUPT,*3/&3 $MBVEJP%FTFOWPMWJNFOUPEF+PHPTFN
"NCJFOUF EF 3FBMJEBEF "VNFOUBEB IUUQXXXSFBMJEBEFBVNFOUBEBDPNCSBSUJHPT
pdf
;03;"- & 3 ,*3/&3 $MBVEJP $"3%040 "MFYBOESF -".06/*&3 +Á/*03 &EHBSE
7JBCJMJ[BOEP P %FTFOWPMWJNFOUP EF +PHPT &TQBDJBJT DPN 3FBMJEBEF "VNFOUBEB IUUQXXX
SFBMJEBEFBVNFOUBEBDPNCSBSUJHPTQEG
.&*(6*/4 #JBODIJ4FSJRVFFUBM.VMUJEJNFOTJPOBM*OGPSNBUJPO7JTVBMJ[BUJPO6TJOH"VHNFOUFE
3FBMJUZIUUQXXXTCDPSHCSCJCMJPUFDBEJHJUBMEPXOMPBEQIQ QBQFS
4"/5*/ 3BGBFM,*3/&3 $MBVEJP5ÏDOJDBTQBSB'JYBS0CKFUPT7JSUVBJTFN"NCJFOUFTEF"VUPSJB
DPN3FBMJEBEF"VNFOUBEB
73
Download