2. 2
Sumário
1.º Exemplo: criando um programa básico....................................................................................................3
2.º Exemplo: Iluminação................................................................................................................................4
3.º Exemplo: Posicionando Objetos...............................................................................................................5
4.º Exemplo: Aparência .................................................................................................................................8
5.º Exemplo: Java 3D e a Interface do usuário............................................................................................12
6.º Exemplo: Animação e Interação ............................................................................................................14
3. 3
1.º Exemplo: criando um programa básico
O programa codificado na Listagem 1 apresenta os passos básicos necessários para a construção
de objetos 3D na tela. Os passos são os seguintes:
1. Criar um universo virtual que contenha uma cena;
2. Criar uma estrutura que contenha um grupo de objetos;
3. Adicionar um objeto em um grupo;
4. Posicionar o visualizador de modo que ele esteja olhando para o objeto
5. Adicionar o grupo de objetos ao Universo.
Observe o construtor Hello3D() e repare nas cinco primeiras linhas que implementam cada um
desses passos. O programa apresenta um cubo incandescente, o visualizador está olhando diretamente
para a face vermelha do cubo, então o que se vê de fato é um quadrado vermelho em um fundo preto. A
importação feita no início do programa usa várias partes do JAVA3D, então compilar e executar este
programa é um bom teste para verificar se a instalação foi feita corretamente.
Listagem 1: Exemplo1
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.geometry.Sphere;
import javax.media.j3d.BranchGroup;
public class Hello3d {
public Hello3d()
{
SimpleUniverse universe = new SimpleUniverse();
BranchGroup group = new BranchGroup();
group.addChild(new ColorCube(0.3));
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(group);
}
public static void main( String[] args ) {
new Hello3d();
}
} // end of class Hello3d
4. 4
2.º Exemplo: Iluminação
O exemplo da seção anterior foi muito bom para começar, mas e o 3D? Se não se consegue
enxergar o quadrado como um objeto tridimensional, então efeitos de iluminação devem ser adicionados
no Universo. A forma como a luz incide sobre um objeto fornece o sombreamento que ajuda a ver as
formas em três dimensões. O próximo exemplo apresentado na listagem 2 ilustra como exibir uma esfera
iluminada por uma luz vermelha.
A esfera que criada é branca por padrão, ela aparece vermelha por causa da luz colorida. Uma vez
que é uma luz direcional (DirectionalLight), também é necessário especificar o quanto a luz brilha e em
que direção. Neste exemplo, a Luz brilha 100 metros a partir da origem e a direção está para a direita,
abaixo e dentro da tela. Isto é definido pelo vetor: 4.0 à direita, -7.0 abaixo, e – 12.0 na tela.
Uma AmbientLight também pode ser criada, o que irá produzir uma luz sem direção, ou um
holofote (LightSpot), caso seja necessário se concentrar em uma parte específica da cena. Uma
combinação de uma forte luz direcional e uma luz ambiente mais fraca dá uma aparência natural para a
cena. As luzes no Java 3D não produzem sombras.
Listagem 2: Exemplo2
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Ball {
public Ball() {
// Create the universe
SimpleUniverse universe = new SimpleUniverse();
// Create a structure to contain objects
BranchGroup group = new BranchGroup();
// Create a ball and add it to the group of objects
Sphere sphere = new Sphere(0.5f);
group.addChild(sphere);
// Create a red light that shines for 100m from the origin
Color3f light1Color = new Color3f(1.8f, 0.1f, 0.1f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); Vector3f
light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
// look towards the ball
universe.getViewingPlatform().setNominalViewingTransform();
// add the group of objects to the Universe
universe.addBranchGraph(group);
}
public static void main(String[] args) { new Ball(); }
}
5. 5
3.º Exemplo: Posicionando Objetos
Até agora, os exemplos criaram objetos no mesmo lugar, o centro do universo. Em Java 3D, os
locais são descritos usando coordenadas x, y, z. As coordenadas crescem ao longo do eixo-x para a
direita, ao longo do eixo-y para cima, e ao longo do eixo Z para fora da tela. Na figura, x, y e z são
representadas por esferas, cones e cilindros.
Figura 1: Coordenadas
Isso é chamado de sistema de coordenadas destro porque o polegar e os dois primeiros dedos da
mão direita podem ser usados para representar as três direções. Todas as distâncias são medidas em
metros. Para colocar os objetos na cena, o ponto (0,0,0) é o começo, e, em seguida, os objetos podem ser
movidos para qualquer lugar. O ato de mover os objetos é chamado de "transformação" (transformações
geométricas), por isso as classes usadas são: TransformGroup e Transform3D. O correto é adicionar o
objeto e o Transform3D a um TransformGroup antes de adicionar o TransformGroup para o resto da
cena.
Tabela 1: Passos e Implementação em Código
Passo Exemplo
Criando a transformação, e um grupo de
transformação de um objeto
Transform = new Transform3D();
transformGroup tg = new TransformGroup();
Cone cone = new Cone(0.5f, 0.5f);
Especificando uma localização para o
objeto
Vector3f vector = new Vector3f(-.2f,.1f , -.4f);
Setando a translação do objeto
(movimento o objeto de local)
Transform.setTranslation(vector);
Adicionado a transformação do grupo de
transformação
tg.setTransform(transform);
Adicionando o objeto ao grupo de
transformação
tg.addChild(cone);
Isto pode parecer complicado, mas os grupos de transformação permitem recolher objetos e movê-
los juntos como uma unidade. Por exemplo, uma tabela poderia ser constituída por cilindros para as
6. 6
pernas e uma caixa para o topo. Se adicionar todas as partes da tabela a um único grupo de transformação,
a tabela inteira pode ser movida com uma translação. A classe Transform3D pode fazer muito mais do
que especificar as coordenadas do objeto. As funções incluem setScale para alterar o tamanho de um
objeto e rotX, rotY e rotZ para girar um objeto em torno de cada eixo (sentido anti-horário). O exemplo
ilustrado na Listagem 3 mostra os diferentes objetos em cada eixo.
Listagem 3: Exemplo3
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Position {
public Position() {
SimpleUniverse universe = new SimpleUniverse();
BranchGroup group = new BranchGroup();
// X axis made of spheres (esferas)
for (float x = -1.0f; x <= 1.0f; x = x + 0.1f)
{
Sphere sphere = new Sphere(0.05f);
TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();
Vector3f vector = new Vector3f( x, .0f, .0f);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(sphere);
group.addChild(tg);
}
// Y axis made of cones (cones)
for (float y = -1.0f; y <= 1.0f; y = y + 0.1f)
{
TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();
Cone cone = new Cone(0.05f, 0.1f);
Vector3f vector = new Vector3f(.0f, y, .0f);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(cone);
group.addChild(tg);
}
// Z axis made of cylinders (cilindros)
for (float z = -1.0f; z <= 1.0f; z = z+ 0.1f)
{
TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();
Cylinder cylinder = new Cylinder(0.05f, 0.1f);
Vector3f vector = new Vector3f(.0f, .0f, z);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(cylinder);
group.addChild(tg);
}
Color3f light1Color = new Color3f(.1f, 1.4f, .1f); // luz verde
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
universe.getViewingPlatform().setNominalViewingTransform();
7. 7
//adiciona o grupo de objetos no Universo
universe.addBranchGraph(group);
}
public static void main(String[] args) {
new Position();
}
}
8. 8
4.º Exemplo: Aparência
Há muitas maneiras de mudar a forma com que se vê a cena. Pode-se mudar a cor, a quantidade de
luz que eles refletem, pintá-las com imagens bidimensionais, ou adicionar texturas ásperas para as
superfícies. A classe Appearence contém as funções para fazer essas alterações. A maneira mais simples
de definir a aparência é especificando apenas a cor e o método de sombreamento. Isso funciona para a
criação de um objeto com uma cor simples, mas para fazer um objeto parecer mais realista, é necessário
especificar como um objeto aparece sob as luzes. Isso é feito através da criação de um material.
Passos Exemplos
Criar um objeto Sphere sphere = new Sphere();
Criar uma aparência Appearance ap = new Appearance();
Criar uma cor Color3f col = new Color3f(0.0f, 0.0f, 1.0f);
Criar os atributos de cor
ColoringAttributes ca = new
ColoringAttributes
(col, ColoringAttributes.NICEST);
Adicionar os atributos à aparência ap.setColoringAttributes(ca);
Configurar a aparência para o objeto sphere.setAppearance(ap);
Materiais
Os materiais têm cinco propriedades que permitem especificar como o objeto aparece. Há quatro
cores: ambiente, emissiva, difusa e especular. A quinta propriedade é o brilho, que é especificado com um
número. Cada cor especifica como a luz é emitida em uma determinada situação.
Ambient color: reflete a luz que foi muito espalhada pelo ambiente, fazendo com que a direção
seja impossível de se determinar. Esta cor é criada por um AmbientLight em Java 3D.
Emissive color: fará com que o objeto pareça brilhar, mas não iluminará os objetos envolta dele.
Indica que ele não só reflete luz, como também brilha. Esta cor poderia ser usada para um néon, por
exemplo, ou para fazer brilhar um objeto no escuro.
Diffuse color: representa a luz que parece ter vindo de uma origem, mas que reflete com
intensidade proporcional ao ângulo que o raio de luz atinge a superfície do objeto.
Specular light: um componente especular forte faz com que haja um brilho num único ponto da
figura, tal como ocorre com os metais. Já um componente fraco, torna a figura fosca, como no caso da
borracha escolar, usada para apagar texto. A luz especular tem um componente fortemente direcional,
portanto, reflete-se praticamente numa única direção.
Alterar o fator brilho afeta não somente como o brilho do objeto é, mas também como o brilho
será em uma pequena ou grande área. Para a maioria dos objetos, pode-se usar uma cor para ambos os
componentes ambientais e difusos, e pretos para emissivo (as maiorias das coisas não brilham no escuro).
Se for um objeto brilhante, deve-se usar uma cor mais clara para reflexões especulares.
9. 9
Para uma bola de borracha, uma luz especular, preta ou vermelha em vez de branco poderia ser
utilizada, o que tornaria a bola menos brilhante. Reduzir o fator de brilho, não funcionaria do jeito que
talvez esteja se esperando. Isso espalharia o reflexo branco através de todo o objeto em vez de ser
concentrado em um ponto.
Listagem 4: Exemplo 4
//billiard ball
//ambient emissive diffuse specular shininess
//Material mat = new Material(red, black, red, white, 70f);
Textura
Materiais mudam a aparência de uma forma geral, mas às vezes, até mesmo os objetos mais
brilhantes podem parecer maçantes. Ao adicionar textura pode-se produzir efeitos mais interessantes
como um marmoreio ou então utilizar uma imagem bidimensional em torno de seu objeto.
A classe TextureLoader permite que carregar uma imagem para usar como uma textura. As
dimensões da imagem devem ser potências de dois, por exemplo, 128 pixels por 256. Quando carregar a
textura também é possível especificar como deseja usar a imagem. Por exemplo, RGB para utilizar a cor
da imagem ou LUMINÂNCIA para ver a imagem em preto e branco.
Após a textura ser carregada, é possível alterar as TextureAttributes. Também pode ser aplicada
como um decalque ou misturar a imagem com uma cor qualaquer. Se estiver usando um objeto simples,
como uma esfera, então também terá de permitir a texturização, definindo as "primitives flags". Estes
podem ser definidos para Primitive.GENERATE_NORMALS +
Primitive.GENERATE_TEXTURE_COORDS quando se cria o objeto.
A listagem 5 apresenta um exemplo de uso de materiais com textura. A imagem utilizada no
exemplo a seguir pode ser baixada em http://www.java3d.org/Arizona.jpg ou você pode substituir uma
imagem de seu gosto. Você também pode configurar texturas tridimensionais, usando formas em vez de
uma imagem plana. Infelizmente, estes atualmente não funcionam muito bem em diferentes plataformas.
Listagem 5: Exemplo 5
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.image.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.awt.Container;
public class PictureBall {
public PictureBall() {
// Create the universe
SimpleUniverse universe = new SimpleUniverse();
10. 10
// Create a structure to contain objects
BranchGroup group = new BranchGroup();
// Set up colors
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
Color3f red = new Color3f(0.7f, .15f, .15f);
// Set up the texture map
TextureLoader loader = new TextureLoader("K:3dArizona.jpg",
"LUMINANCE", new Container());
Texture texture = loader.getTexture();
texture.setBoundaryModeS(Texture.WRAP);
texture.setBoundaryModeT(Texture.WRAP);
texture.setBoundaryColor( new Color4f( 0.0f, 1.0f, 0.0f, 0.0f ) );
// Set up the texture attributes
//could be REPLACE, BLEND or DECAL instead of MODULATE
TextureAttributes texAttr = new TextureAttributes();
texAttr.setTextureMode(TextureAttributes.MODULATE);
Appearance ap = new Appearance();
ap.setTexture(texture);
ap.setTextureAttributes(texAttr);
//set up the material
ap.setMaterial(new Material(red, black, red, black, 1.0f));
// Create a ball to demonstrate textures
int primflags = Primitive.GENERATE_NORMALS +
Primitive.GENERATE_TEXTURE_COORDS;
Sphere sphere = new Sphere(0.5f, primflags, ap);
group.addChild(sphere);
// Create lights
Color3f light1Color = new Color3f(1f, 1f, 1f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
AmbientLight ambientLight =
new AmbientLight(new Color3f(.5f,.5f,.5f));
ambientLight.setInfluencingBounds(bounds);
group.addChild(ambientLight);
// look towards the ball
universe.getViewingPlatform().setNominalViewingTransform();
// add the group of objects to the Universe
universe.addBranchGraph(group);
}
public static void main(String[] args) {
new PictureBall();
}
}
Efeitos especiais
11. 11
Veja o exemplo AppearanceTest que vem com Java 3D para mais efeitos que podem ser usados.
Por exemplo, exibir objetos como fio-frames, exibir somente os cantos de um objeto e assim por diante.
Até objetos transparentes podem ser feitos, com as seguintes configurações da listagem 6.
Listagem 6: Exemplo 6
TransparencyAttributes t_attr =
new TransparencyAttributes(TransparencyAttributes.BLENDED,0.5,
TransparencyAttributes.BLEND_SRC_ALPHA,
TransparencyAttributes.BLEND_ONE);
ap.setTransparencyAttributes( t_attr );
12. 12
5.º Exemplo: Java 3D e a Interface do usuário
A maioria das aplicações reais utilizam uma mistura de três elementos tridimensionais e
bidimensionais. Esta seção descreve como combinar o seu Java 3D com o resto do seu programa.
Canvas3D
Cada área onde os gráficos tridimensionais podem ser pintados é chamado de Canvas3D. Este é
um retângulo que contém uma exibição dos objetos em seu universo. A tela é colocada dentro de um
quadro, em seguida, um universo a ser exibido na tela é criado. O exemplo da listagem 7 apresenta como
criar uma tela em um quadro com as etiquetas na parte superior e inferior. O programa pode ser executado
como um applet ou uma aplicação.
Listagem 7: Exemplo 7
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.geometry.ColorCube;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import java.awt.GraphicsConfiguration;
import java.awt.BorderLayout;
import java.awt.Label;
import java.applet.Applet;
import com.sun.j3d.utils.applet.MainFrame;
public class CanvasDemo extends Applet {
public CanvasDemo() {
setLayout(new BorderLayout());
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(config);
add("North",new Label("This is the top"));
add("Center", canvas);
add("South",new Label("This is the bottom"));
BranchGroup contents = new BranchGroup();
contents.addChild(new ColorCube(0.3));
SimpleUniverse universe = new SimpleUniverse(canvas);
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(contents);
}
public static void main( String[] args ) {
CanvasDemo demo = new CanvasDemo();
new MainFrame(demo,400,400);
}
}
Java 3D e Swing
O Canvas3D tira proveito da placa gráfica do seu computador para aumentar o desempenho.
Infelizmente, isso significa que ele não se mistura muito bem com componentes de interface do usuário
13. 13
Swing da Sun. Esses componentes são chamados de componentes leves que podem ser escondidos por
um Canvas3D. Existem várias soluções para este problema:
- Misturar componentes leves e pesados, na mesma tela se mantê-los em recipientes separados.
- Usar menus pop-up, uma função estática em JPopupMenu corrige o problema:
setDefaultLightWeightPopupEnabled (false);
- Utilizar os componentes do AWT que são mais velhos que o Swing.
14. 14
6.º Exemplo: Animação e Interação
Para criar animação é necessário mover os objetos entre cada quadro de animação. Usar um timer
e mover os objetos 3D por uma pequena quantidade de cada vez é uma forma de fazer isto. Além disso,
os objetos podem ser modificados de outras formas. A listagem 8 apresenta uma bola quicando. Para a
interação com o usuário, as teclas digitadas ou cliques em botões ou outros componentes podem ser
processados. Uma coisa a notar é que deve ser dito ao Java3D que algo está se movendo, definindo um
recurso. Caso contrário, nada será capaz de mover qualquer coisa uma vez que já foi desenhado.
objTrans = new TransformGroup ();
objTrans.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
O exemplo da listagem 8 combina estas técnicas. Deve ser iniciado clicando no botão, em seguida,
a bola salta para cima e para baixo, e A ou S deve ser pressionado para passar a bola da a esquerda ou
direita.
Listagem 8: Exemplo 8
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.WindowAdapter;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.Sphere;
import javax.swing.Timer;
public class BouncingBall extends Applet implements ActionListener, KeyListener {
private Button go = new Button("Go");
private TransformGroup objTrans;
private Transform3D trans = new Transform3D();
private float height=0.0f;
private float sign = 1.0f; // going up or down
private Timer timer;
private float xloc=0.0f;
public BranchGroup createSceneGraph() {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objRoot.addChild(objTrans);
// Create a simple shape leaf node, add it to the scene graph.
Sphere sphere = new Sphere(0.25f);
objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Transform3D pos1 = new Transform3D();
pos1.setTranslation(new Vector3f(0.0f,0.0f,0.0f));
objTrans.setTransform(pos1);
objTrans.addChild(sphere);
objRoot.addChild(objTrans);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
15. 15
Color3f light1Color = new Color3f(1.0f, 0.0f, 0.2f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
// Set up the ambient light
Color3f ambientColor = new Color3f(1.0f, 1.0f, 1.0f);
AmbientLight ambientLightNode = new AmbientLight(ambientColor);
ambientLightNode.setInfluencingBounds(bounds);
objRoot.addChild(ambientLightNode);
return objRoot;
}
public BouncingBall() {
setLayout(new BorderLayout());
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
Canvas3D c = new Canvas3D(config);
add("Center", c);
c.addKeyListener(this);
timer = new Timer(100,this);
//timer.start();
Panel p =new Panel();
p.add(go);
add("North",p);
go.addActionListener(this);
go.addKeyListener(this);
// Create a simple scene and attach it to the virtual universe
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public void keyPressed(KeyEvent e) {
//Invoked when a key has been pressed.
if (e.getKeyChar()=='s') {xloc = xloc + .1f;}
if (e.getKeyChar()=='a') {xloc = xloc - .1f;}
}
public void keyReleased(KeyEvent e){
// Invoked when a key has been released.
}
public void keyTyped(KeyEvent e){
//Invoked when a key has been typed.
}
public void actionPerformed(ActionEvent e ) {
// start timer when button is pressed
if (e.getSource()==go){
if (!timer.isRunning()) {
timer.start();
}
}
else {
height += .1 * sign;
if (Math.abs(height *2) >= 1 ) sign = -1.0f * sign;
if (height<-0.4f) {
trans.setScale(new Vector3d(1.0, .8, 1.0));
}
else {
trans.setScale(new Vector3d(1.0, 1.0, 1.0));
}
trans.setTranslation(new Vector3f(xloc,height,0.0f));
objTrans.setTransform(trans);
}
}
16. 16
public static void main(String[] args) {
System.out.println("Program Started");
BouncingBall bb = new BouncingBall();
bb.addKeyListener(bb);
MainFrame mf = new MainFrame(bb, 256, 256);
}
}
17. 17
Este texto foi escrito com base nos seguintes textos:
http://pontov.com.br/site/opengl/183-cores-luzes-e-materiais
http://www.java3d.org/introduction.html
https://docs.oracle.com/cd/E17802_01/j2se/javase/technologies/desktop/java3d/forDevelopers/J3D_1_3_
API/j3dapi/