View Full Version : Texture in Java 3D
Salve a tutti, avrei bisogno di un aiutino...
Come faccio ad applicare una texture su un'altra? mi spiego meglio: ho un parallelepipedo dove ho applicato una texture di mattoni e adesso vorrei applicare in un punto specifico una texture per le finestre. Come si fa?
Grazie e ciao.
Se usi almeno la versione 1.3 (siamo alla 1.4 è in dirittura d'arrivo la 1.5) puoi passare per:
setSubImage(java.awt.image.RenderedImage image, int width, int height, int srcX, int srcY, int dstX, int dstY)
di ImageComponent2D.
setSubimage è l'omologo dell'openg-elliano glTexSubimage2D
Non sono molto pratico, potresti spiegarti meglio?
Questo è quello che io ho scritto:
Appearance appB = new Appearance();
TextureLoader tl = new TextureLoader("muro.jpg",null); //Applico una textura in maniera ripetuta
TextureAttributes myTex = new TextureAttributes();
Transform3D myT = new Transform3D();
myT.set(4.0);
myTex.setTextureTransform(myT);
Texture tex = tl.getTexture();
appB.setTextureAttributes(myTex);
appB.setTexture(tex);
//Crea l'aspetto del piano
Appearance appear=new Appearance();
//Carica la texture
TextureLoader loader=new TextureLoader("finestra.jpg",null);
ImageComponent2D image=loader.getImage();
//Crea la texture
Texture2D texture=new Texture2D(Texture.BASE_LEVEL,Texture.RGBA,image.getWidth(),image.getHeight());
texture.setImage(0,image);
//Crea un piano
QuadArray plane=new QuadArray(4,GeometryArray.COORDINATES|GeometryArray.TEXTURE_COORDINATE_2);
Point3f p=new Point3f(-1.0f,1.0f,0.0f);
plane.setCoordinate(0,p);
p.set(-1.0f,-1.0f,0.0f);
plane.setCoordinate(1,p);
p.set(1.0f,-1.0f,0.0f);
plane.setCoordinate(2,p);
p.set(1.0f,1.0f,0.0f);
plane.setCoordinate(3,p);
TexCoord2f q=new TexCoord2f(0.0f,1.0f);
q.set(0,1);
plane.setTextureCoordinate(0,0,q);
q.set(0,0);
plane.setTextureCoordinate(0,1,q);
q.set(1,0);
plane.setTextureCoordinate(0,2,q);
q.set(1,1);
plane.setTextureCoordinate(0,3,q);
//Imposta la texture nell'aspetto
appB.setTexture(texture);
Come faccio a "mettere" la finestra?
Grazie e ciao
Ho fatto zic anzichè zac col registro di windows e al momento sono un po' precario. Ti "indirizzo".
Allora, tex è la texture del muro e image è lo ImageComponent2D della finestra.
Quello che dovresti fare è copiare "image" nell'ImageComponent2D di "tex".
ImageComponent2D texImage = (ImageComponent2D)tex.getImage(0);
RenderedImage windowImage = image.getRenderedImage();
textImage.setSubImage(
windowImage,
altezzaFinestra,
larghezzaFinestra,
0, 0, //"origine" della porzione di finestra da copiare
posizioneXFinestraSullImmagineDelMuro,
posizioneYFinestraSullImmagineDelMuro);
Teoricamente non fa una piega ma al momento non posso fare una prova preliminare.
PUMA81, ti rispondo "al pubblico ludibrio".
Supponendo di avere due immagini, wall.png e window.png, appiccico window su wall.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import javax.imageio.*;
import com.sun.j3d.utils.universe.*;
public class Main extends WindowAdapter implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Main());
}
private Frame frame = new Frame("3D");
private Canvas3D canvas;
public void run() {
int vertexFormat =
GeometryArray.COORDINATES |
GeometryArray.NORMALS |
GeometryArray.TEXTURE_COORDINATE_2;
float[] coords = {
0, 0, 0,
1, 0, 0,
1, 1, 0,
0, 1, 0,
};
//Dritto negli occhi (z+)
float[] normals = {
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1,
};
//U = X + Z
//V = Y
float[] uv = {
0, 0,
1, 0,
1, 1,
0, 1,
};
QuadArray tile = new QuadArray(4, vertexFormat);
tile.setCoordinates(0, coords);
tile.setNormals(0, normals);
tile.setTextureCoordinates(0, 0, uv);
/* Il muro */
BufferedImage wallImage = getImage("/wall.png"); //64*64
/* La finestra */
BufferedImage windowImage = getImage("/window.png"); //16*32
/* ImageComponent2D del muro... */
ImageComponent2D wallImageComponent =
new ImageComponent2D(ImageComponent.FORMAT_RGB, wallImage);
/* Spiaccica la finestra sul muro... */
wallImageComponent.setSubImage(
windowImage,
windowImage.getWidth(),
windowImage.getHeight(),
0,
0,
24,
4);
/* Crea la texture del muro (che ha la finestra appiccicata) */
Texture2D wallTexture = new Texture2D(
Texture2D.BASE_LEVEL,
Texture2D.RGB,
wallImage.getWidth(),
wallImage.getHeight());
/* Imposta la texture del muro al livello mip map 0 */
wallTexture.setImages(new ImageComponent[] { wallImageComponent });
/* Multitexturing... con una texture sola =) */
TextureUnitState wallTextureUnit = new TextureUnitState();
wallTextureUnit.setTexture(wallTexture);
TextureUnitState[] stateArray = { wallTextureUnit };
Appearance tileApp = new Appearance();
tileApp.setTextureUnitState(stateArray);
Shape3D tileShape = new Shape3D(tile, tileApp);
Transform3D tileLocation = new Transform3D();
tileLocation.setTranslation(new Vector3d(-0.5f, -0.5f, -5));
TransformGroup tileGroup = new TransformGroup(tileLocation);
tileGroup.addChild(tileShape);
Background bg = new Background(new Color3f(0.5f, 0.5f, 0.5f));
BoundingSphere bounds = new BoundingSphere(new Point3d(0, 0, 0), 1000);
bg.setApplicationBounds(bounds);
BranchGroup root = new BranchGroup();
root.addChild(bg);
root.addChild(tileGroup);
root.compile();
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
canvas = new Canvas3D(config);
SimpleUniverse universe = new SimpleUniverse(canvas);
universe.addBranchGraph(root);
//universe.getViewingPlatform().setNominalViewingTransform();
frame.addWindowListener(this);
frame.setLayout(new GridLayout(1, 1));
frame.add(canvas);
frame.setSize(400, 400);
frame.setVisible(true);
}
private BufferedImage getImage(String path) {
try {
return ImageIO.read(getClass().getResource(path));
} catch(Exception ex) {
throw new RuntimeException(ex);
}
}
public void windowClosing(WindowEvent e) {
System.exit(-1);
}
}
Praticamente a te interessa solo la parte colorata, il resto è fuffa sperimentale.
Grazie PGI-Bis, sei un grande!!! :D :D :D
E' quello che serviva a me :p
Ancora grazie e ciao.
Ciao, volevo chiederti ancora una cosa, però non riguarda direttamente le texture...
Allora:
BoundingSphere bounds=new BoundingSphere(new Point3d(),1500.0);
ImageComponent2D image = new TextureLoader("cielo.jpg",this).getScaledImage(larg,altez);
//Aggiunge uno sfondo
Background background=new Background(image);
background.setApplicationBounds(bounds);
//aggiungiamo l'istanza dello sfondo alla scena 3D
objRoot.addChild(background);
Avrei creato un BoundingSphere e messo una immagine di sfondo.
Adesso nella mia applicazione ho il terreno e subito attaccato il cielo.
Io vorrei fare una cosa un pochino più bellina e cioè mettere tra la terra e il cielo, ad esempio, delle montagne.
Ho provato a replicare ciò che ho scritto sopra passando diverse coordinate rispetto a quelle che passo nel getScaledImage() ma non va, cioè visualizzo solo la prima immagine caricata.
Volevo chiederti: è possibile fare quello che ti ho appena descritto??
Grazie e ciao.
Non puoi usare come sfondo un'immagine in cui ci siano già sia le montagne che il cielo?
Non puoi usare come sfondo un'immagine in cui ci siano già sia le montagne che il cielo?
Dici che mi conviene??
ma se volessi fare come ti ho scritto è molto complicato??
Il fatto è che la nostra applicazione è sospesa nella sfera e al di sotto di essa si vede tutto cielo...
magari volevo provare a mettere un'immagine che si adattava bene all'applicazione...
cmq se dici che non ne vale la pena... :p
So che esiste la possibilità di fare "sfondi carini" usando delle geometrie come sfondi ma non conosco la teoria che ci sta dietro per cui direi al 101% una cialtroneria :D.
So che esiste la possibilità di fare "sfondi carini" usando delle geometrie come sfondi ma non conosco la teoria che ci sta dietro per cui direi al 101% una cialtroneria :D.
ma senti un po' ma di che ti occupi? ne sai di ogni linguaggio e di tutte le librerie possibili e immaginabili :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.