domingo, 11 de abril de 2010

jMonkeyEngine Modelos 3D

Você está na série de posts sobre jMonkeyEngine. Acesse o post principal: jMonkeyEngine Tutorial

Nesse post vou mostrar como utilizar objetos 3D na sua aplicação, veja algumas imagens de exemplo:

jmonkeyengine

jmonkeyengine











jMonkeyEngine não suporta qualquer tipo de formato de arquivo 3D diretamente, é preciso fazer uma conversão para um formato propritário chamado "jME binary", mas felizmente, a api do jMonkey tem classes e métodos que ajudam muito nessas conversões.

Vamos ver alguns exemplos:

Arquivos .obj
http://www.localhost8080.com.br/jmonkeyengine/model/ModelLoadingObj.java

Arquivos .x3d
http://www.localhost8080.com.br/jmonkeyengine/model/ModelLoadingX3d.java

Arquivos .xml
http://www.localhost8080.com.br/jmonkeyengine/model/ModelLoadingXml.java

OBS: Para usar essas classes você precisará dos arquivos que estão dentro desse zip:
http://localhost8080.com.br/jmonkeyengine/model/jmonkeyengine-modelo3d-assets.zip
Descompacte e jogue a pasta assets na pata src do seu projeto.

Performance
Quando você estiver construindo uma grande aplicação poderá ter problemas de performance, pois as conversões estão sendo feitas em tempo de execução (o arquivo .obj, por exemplo, é tranformado em .jme apenas quando o programa está rodando).

Isso pode ser resolvido convertendo todos os modelos 3D apenas uma vez e gravando-os em arquivos .jme utilizando FileOutputStreams, quando sua aplicação começar, basta ler esse arquivo com FileInputStream e carregá-lo diretamente, sem conversões. Isso deixará a aplicação muito mais rápida!

Bounding
Você viu em todos os exemplos desse artigo algo como a seguinte linha:
// cerca a imagem com limites invisiveis
spatial.setModelBound(new BoundingBox());
spatial.updateModelBound();

BoundingSphere e BoundingBox são a chave da performance em jME.
Por quê? Imagine uma imagem 3D complexa, leva-se muita tempo para carregá-la, fazer cálculos com ela, desenhá-la, etc... então, quando você tem uma imagem 3D, você cerca ela com uma esfera ou um quadrado (invisíveis), assim se o jME precisa saber se a imagem 3D está na visão da camera, para então carregá-la e desenhá-la, ele faz cálculos com a esfera ou quadrado ao redor da imagem, o que é rápido e fácil, pois esses objetos são matematicamente simples.

Use sempre este artifício! Basta decidir se o objeto, baseado em seu formato, deve ser cercado por uma esfera (BoundingSphere) ou por um quadrado (BoundingBox), e então usar isso para melhorar a performance do seu programa.


Vaaleu!! Em breve postarei mais sobre jMonkeyEngine, até mais!

sexta-feira, 9 de abril de 2010

SQL hifen

colunas ou tabelas com hifen em um banco de dados podem dar muita dor de cabeça...
use sempre underlines (_) e não hífens (-)...

entretando.. se você estiver mexendo em um sistema que tenha essa situação, como aconteceu comigo hoje, terá que usar aspas duplas!

a seguinte query não funciona
select * from pub.empresa where ep-codigo = 1

Você obtém erros como:
Error: [DataDirect][OpenEdge JDBC Driver][OpenEdge] Column não encontrada ou especificada (7520)
Error: [DataDirect][OpenEdge JDBC Driver][OpenEdge] Column "EP" cannot be found or is not specified for query. (13865)
Caused by: java.sql.SQLException: [DataDirect][OpenEdge JDBC Driver][OpenEdge] Column "EMPRESA0_.EP" cannot be found or is not specified for query. (13865)

para resolver use aspas duplas:
select * from pub.empresa where "ep-codigo" = 1

e tudo funcionará perfeitamente..

se você usar hibernate, jpa.. e for mapear um campo com hífen, terá que colocar aspas também, mas terá que usar o caracter de escape \"

@Column(name = "\"ep-codigo\"")
private Long epCodigo;

é isso aí, valeu!

terça-feira, 6 de abril de 2010

redirecionar HTML

Olá, você pode acessar esse blog pelo domínio http://www.localhost8080.com.br, e então será redirecionado para http://localhost8080.blogspot.com, pois o index.html do localhost8080.com.br é assim:

<html>
<head>
<title>localhost8080</title>
</head>
<body>
<meta http-equiv="refresh" content="0; url=http://localhost8080.blogspot.com">
</body>
</html>

Esse código redireciona para a página que você colocar no atributo url... aquele 0 depois do content é o número de segundos antes do redirecionamento ser feito, se você colocar 10, depois de 10 segundos após abrir a página vai acontecer o redirecionamento...

Dá para fazer o mesmo sem mudar o link no browser, basta usar o seguinte código:

<html>
<head>
<title>localhost8080</title>
</head>
<body leftmargin="0" marginheight="0" marginwidth="0" scroll="no" topmargin="0">
<iframe frameborder="0" height="100%" src="http://localhost8080.blogspot.com" width="100%">
<script language="JavaScript">
location = "http://localhost8080.blogspot.com";
</script>
<noscript>
<p>
<a href="http://localhost8080.blogspot.com">Seu Browser nao suporta Frames, Clique Aqui...</a>
</p>
</noscript>
</iframe>
</body>
</html>

é isso aí! valeu!

segunda-feira, 5 de abril de 2010

Permissão negada:80

Ao inicializar o JBoss, aconteceu o seguinte erro:

11:13:53,412 INFO [Embedded] Catalina naming disabled
11:13:53,586 ERROR [Http11Protocol] Error initializing endpoint
java.net.BindException: Permissão negada:80
at org.apache.tomcat.util.net.PoolTcpEndpoint.initEndpoint(PoolTcpEndpoint.java:297)

[...]

at java.lang.Thread.run(Thread.java:619)
11:13:53,588 ERROR [Catalina] Catalina.start
LifecycleException: Protocol handler initialization failed: java.net.BindException: Permissão negada:80
at org.apache.catalina.connector.Connector.initialize(Connector.java:930)

[...]

at java.lang.Thread.run(Thread.java:619)
11:13:53,590 INFO [Catalina] Initialization processed in 150 ms
11:13:53,591 INFO [StandardService] Starting service jboss.web

Isso acontece aqui no ubuntu quando inicio o JBoss na porta 80, então para resolver simplesmente altero a porta do JBoss, fazer isso é simples, basta acessar o arquivo:

<PASTA DO JBOSS> /server/ <PASTA DO CONTEXTO> /deploy/jbossweb-tomcat55.sar/server.xml

e alterar o atributo port como abaixo:

De:
<Connector port="80" address="${jboss.bind.address}"
maxThreads="250" strategy="ms" maxHttpHeaderSize="8192"
emptySessionPath="true"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true">

Para:
<Connector port="8080" address="${jboss.bind.address}"
maxThreads="250" strategy="ms" maxHttpHeaderSize="8192"
emptySessionPath="true"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true">

e pronto o problema estará resolvido!

sexta-feira, 2 de abril de 2010

jMonkeyEngine HelloWorld II

Você está na série de posts sobre jMonkeyEngine. Acesse o post principal: jMonkeyEngine Tutorial

Caso seja seu primeiro contato com jMonkeyEngine, leia antes o post jMonkeyEngine HelloWorld para aprender a configurar o ambiente e executar sua aplicação.

Com esse exemplo quero passar um pouco mais sobre jMonkeyEngine... sobre outras formas geométricas, como posicioná-las na tela (grafo de cena) e como alterar seu tamanho.

Crie uma classe chamada HelloWorldII com o código abaixo e execute-a. (Dúvidas quanto a isso? Leia jMonkeyEngine HelloWorld)

import com.jme.app.SimpleGame;
import com.jme.math.Vector3f;
import com.jme.scene.shape.Arrow;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.shape.Teapot;

public class HelloWorldII extends SimpleGame {

private Teapot teapot1;
private Teapot teapot2;

private Arrow arrow;
private Box box;
private Sphere sphere;

public static void main(String[] args) {
HelloWorldII app = new HelloWorldII();
app.setConfigShowMode(ConfigShowMode.AlwaysShow);
app.start();
}

protected void simpleInitGame() {
//cria uma chaleira 3D
teapot1 = new Teapot("teapot1");
//move a chaleira (diminui 7 no eixo x, aumenta 2 no eixo y e 1 no eixo z)
teapot1.setLocalTranslation(new Vector3f(-7, 2, 1));
//aumenta o tamanho do objeto em duas vezes
teapot1.setLocalScale(2);
//Adiciona a chaleira na tela
rootNode.attachChild(teapot1);

//cria uma chaleira 3D
teapot2 = new Teapot("teapot2");
//move a chaleira (aumenta 3 no eixo x, diminui 2 no eixo y e não mexe no eixo z)
teapot2.setLocalTranslation(3, -2, 0);
//diminui o tamanho do objeto pela metade
teapot2.setLocalScale(0.5F);
//Adiciona a chaleira na tela
rootNode.attachChild(teapot2);

//vamos criar outros objetos 3D agora!

//cria uma seta de 3 de comprimento e 1 de largura
arrow = new Arrow("arrow", 3, 1);
//posiciona a seta no canto inferior esquerdo da tela
arrow.setLocalTranslation(-10, -5, 0);
//adiciona a seta na tela
rootNode.attachChild(arrow);

//cria uma caixa do ponto (x=0, y=0, z=0) até o ponto (x=2, y=2, z=2)
box = new Box("box", new Vector3f(0, 0, 0), new Vector3f(2, 2, 2));
//posiciona a caixa no canto inferior esquerdo da tela
box.setLocalTranslation(-8, -6, 0);
//adiciona a caixa na tela
rootNode.attachChild(box);

//cria uma esfera de raio 2
sphere = new Sphere("sphere", 30, 30, 2);
//posiciona a esfera no canto superior direito da tela
sphere.setLocalTranslation(4, 5, 0);
//adiciona a esfera na tela
rootNode.attachChild(sphere);
}
}

Você obterá algo semelhante a essas imagens:

jmonkeyengine hwii 1jmonkeyengine hwii 2


Explicando o código

Formas geométricas
Nesse exemplo foram utilizadas as seguintes formas: Teapot (Chaleira), Arrow (Seta), Box (Caixa, cubo), Sphere (Esfera, bola).

Teapot
Teapot é uma chaleira, para usar basta criar uma instância passando um nome qualquer:
Teapot teapot = new Teapot("teapot");
e depois adicionar na tela:
rootNode.attachChild(teapot);

Arrow
Uma seta, seu construtor recebe, um nome, o comprimento e a largura
Arrow arrow = new Arrow("arrow", 3, 1);
para visualizá-la é necessário adicionar o objeto na tela
rootNode.attachChild(arrow);

Box
Box representa uma caixa, um cubo, o seu construtor recebe um nome e dois vetores, o primeiro vetor representa onde a caixa começa, o segungo, onde ela termina
//cria uma caixa do ponto (x=0, y=0, z=0) até o ponto (x=2, y=2, z=2)
Box box = new Box("box", new Vector3f(0, 0, 0), new Vector3f(2, 2, 2));

Depois, basta adicionar à tela:
rootNode.attachChild(box);

Sphere
Utilizada para desenhar esferas, globos. Para criar é necessário passar ao construtor um nome, dois atributos que representam a circunferência da esfera e o raio:
Sphere sphere = new Sphere("sphere", 30, 30, 2);
jME não pode desenhar curvas, então desenha triângulos, utilizando muitos triângulos é possível desenhar uma esfera. Os dois primeiros números representam a proximidade dos triangulos, se você alterar de 30, 30 para 7, 7 você vai ver uma esfera como a abaixo:

7 x 730 x 30
jmonkeyengine esfera 7 7jmonkeyengine esfera 30 30

Quanto maior os números passados, mais esférico ficará o componente. Porém, números muito altos criam muitos triângulos, podendo deixar a aplicação pesada e lenta... é preciso encontrar um equilíbrio entre perfomance e aparência.

como sempre, é necessário adicionar na tela:
rootNode.attachChild(sphere);

Posicionamento
Mover objetos no cenário é simples, é só chamar o método setLocalTranslation.

Sphere sphere = new Sphere("sphere", 30, 30, 2);
sphere.setLocalTranslation(new Vector3f(0,2,0));


Um Vector3f, na jME API, tem o formato (x, y, z), então o código acima com Vector3f(0,2,0) movimenta o objeto duas unidades para cima (eixo y). Se eu tivesse usado Vector3f(0,-2,0) então a esfera teria sido movida duas unidades para baixo.

Mover objetos é realmente fácil. Você apenas tem que lembrar que x é direita/esquerda, y é cima/baixo, e z é trás/frente.

Alterar tamanho
Para alterar o tamanho de algum objeto o método setLocalScale é chamado.

Sphere sphere = new Sphere("sphere", 30, 30, 2);
sphere.setLocalScale(2);


Nele é passado quantas vezes maior ou menor você quer que o objeto fique, passando 2, o objeto fica duas vezes maior, passando 5, o objeto fica 5 vezes maior, passando 0.5, o objeto fica com metade do seu tamanho.


E é isso! Leia o post jMonkeyEngine Modelos 3D