English (UK)

Tratto da www.javastaff.com Autore originale Dmitry Leskov Tradotto da Luca Mattei

E' possibile creare un file exe a partire da un'applicazione java? Solitamente, alcuni problemi possono essere risolti senza creare un file EXE.

Il motivo principale della necessità di solito è semplificare la distribuzione di un'applicazione Java. Java compila le classi in bytecode proprietario (i file .class), che non è supportato direttamente dall'hardware dei PC. Quindi un programma Java ha bisogno della Java Runtime Environment (JRE) per essere eseguito, che so occupa di interpretare le istruzioni in bytecode e compilarle in codice nativo "on the fly". Questo obbliga l'autore del programma a richiedere che la corretta versione della JRE sia installata nei computer degli utenti finali. Generalmente, però, non si può assumere che gli utenti finali sappiano cosa è una JRE, o come verificare la versione di quella posseduta , o come installarne una versione diversa, senza creare problemi alle altre applicazioni java o alle applet visualizzate spesso. Se poi se anche si è sicuri che la versione corretta della JRE sia installata sulla macchina dell'utente finale, che su alcune classi di utenti è possibile, il comando da eseguire per richiamare l'applicazione è probilmente lungo:

java -Xmx200m -cp whatever.jar -Dsome.property MyApp

Sì, si può scrivere un file batch con il comando, del tipo: runme.bat, ma è molto più comodo distribuire la nostra applicazione, magari ad un collega o ad un insegnante o ad un amico, come un unico eseguibile da lanciare con un doppio click. O, magari, prevedere un processo di installazione (e di disinstallazione) nativo, che non crei conflitti con altre applicazioni. Per questo non è una sorpresa sapere che che il principale motivo del desiderio di convertire i programmi java in exe nasce dalla necessità di rendere più semplice e sicuro il deploy su utenti windows. La vera sorpresa, per i newbie, è che il JDK non offre una funzionalità del genere. Prima del J2SE 1.4 tutto quello che si poteva fare era:

JAR eseguibili: E' possibile rendere eseguibile una applicazione java attraverso un doppio click, racchiudendola in un jar eseguibile. per farlo bisogna specificare la classe principale della applicazione e ogni altro jar da includere nel file manifest contenuto:

Main-Class: MyAppMain Class-Path: mylib.jar

Quindi utilizziamo il tool "jar" contenuto del SDK, specificando l'opzione m e il nome del file manifest appena creato:

jar cvfm MyApp.jar MyApp.mf *.class *.gif

Ora per eseguire l'applicazione possiamo digitare:

java -jar MyApp.jar

e verrà letto nel file manifest il nome della classe della quale invocare il metodo main. Allo stesso modo, se la JRE è ben installata, basterà cliccare due volte sul jar per avviare la applicazione. Nota: Da J2SE 5.0, i file jar sono associati al launcher windows javaw, che non apre la finestra nera con la consolle. Quindi, se ne avete bisogno, dovrete far partire il jar da riga di comando o da un file batch. Se la vostra applicazione è composta da più jar, potete utilizzare il tool One-JAR per riunirli in un unico jar. Il maggior problema di questo metodo è la compatibilità con la JRE. La JRE di default potrebbe essere infatti troppo vecchia e non avere i necessari Java Optional Packages (conosciuti prima come Standard Extensions). Per esempio, se la vostra applicazione usa il package java.nio introdotto dalla versione 1.4.2, non funzionerà con la JRE versione 1.3.x. Allo stesso modo, se usa JavaMail 1.3, e la JRE installata ha JavaMail 1.2 o non la possiede affatto, il jar non verrà eseguito.

PRO:

  • Non si usano tool di terze parti.
  • Multipiattaforma

CONTRO:

  • Le applicazioni non partono se non si ha una JRE correttamente installata.
  • Le applicazioni non funzionano se le APIs utilizzate non sono presenti nella JRE di default.
  • Bisogna informare gli utenti che i file JAR sono cliccakabili.

RISORSE:

  • The Java Archive (JAR) File Format

TOOLS:

  • One-JAR

Java Web Start Fortunatamente, per risolvere questi problemi di compatibilità, dal SDK 1.4 è presente un tool che facilita la vita allo sviluppatore. Java Web Start (JWS) e il suo protocollo Java Network Launch Protocol (JNLP) permette la distribuzione delle applicazioni java direttamente da un webserver standard. L'utente finale può iniziare l'installazione semplicemente cliccando su un URL. Se Java Web Start non è presente nel sistema, verrà proposto il download e l'installazione del tool. Se necessario, JWS provvederà poi ad avviare download ed installazione della JRE corretta e di eventuali package aggiuntivi. L'applicazione viene quindi lanciata e rimane pronta e nascosta nel sistema dell'utente finche' l'utente non la richieda nuovamente dall'URL associato, senza reinstallarla a meno che la versione della applicazione non sia obsoleta. In tal caso verrà aggiornata. Un'altra caratteristica interessante di Java Web Start è la capacità di far girare le vostre applicazioni in una SandBox, un container "sicuro". Ma a differenza della SandBox delle Applet, l'applicazione può accedere alle risorse native, come filesystem, stampanti e alla memoria degli appunti attraverso le JNLP Api, dopo aver chiesto il permesso all'utente, ovviamente. Java WebStart è disponibile per piattaforme Windows, Linux, Solaris e Mac OsX a partire dalla versione 10.1. Ci sono anche implementazioni di terze parti del protocollo JNLP ed alcune includono tool per la preparazione di un package adatto a JWS. Ma passiamo ai difetti. Innanzitutto il WebServer che ospita le applicazioni deve supportare il tipo mime associato a Java Web Start:

application/x-java-jnlp-file

Alcuni providers potrebbero non permetterlo. Inoltre per utilizzare le funzionalità di versioning e il supporto agli updates, c'è bisogno di un webserver in grado di supportare servlets, cgi-bin scripts, etc. Lato client, non ci dovrebbero essere problemi nel riconoscere il MIME type, per lo meno nei browser più popolari. In alcuni browser più di nicchia invece potrebbe essere necessario configurarli manualmente. Abilitare JNLP in un'applicazione dovrebbe richiedere modifiche minime e la creazione di un set di files jar. Prima della J2SE 5.0, JWS aveva veramente poco da offrire, in termini di integrazione desktop, limitandosi a creare una icona sul desktop e/o un collegamento nel menu Start. In Windows, l'applicazione non apparirà nelle entry in "Installazione Applicazioni", quindi l'utente dovrà lanciare Java Web Start per disinstallare l'applicazione. Infine, si vede la necessità di una interfaccia utente più pulita per JWS. Allo stato attuale (J2SE 5.0) gli utenti si trovano a interagire con orribili finestre con messaggi incomprensibili. Lato client, non ci dovrebbero essere problemi nel riconoscere il MIME type, per lo meno nei browser più popolari. In alcuni browser più di nicchia invece potrebbe essere necessario configurarli manualmente. Abilitare JNLP in un'applicazione dovrebbe richiedere modifiche minime e la creazione di un set di files jar. Prima della J2SE 5.0, JWS aveva veramente poco da offrire, in termini di integrazione desktop, limitandosi a creare una icona sul desktop e/o un collegamento nel menu Start. In Windows, l'applicazione non apparirà nelle entry in "Installazione Applicazioni", quindi l'utente dovrà lanciare Java Web Start per disinstallare l'applicazione. Infine, si vede la necessità di una interfaccia utente più pulita per JWS. Allo stato attuale (J2SE 5.0) gli utenti si trovano a interagire con orribili finestre con messaggi incomprendibili. Riassumento, JWS può essere valida una opzione in ambienti controllati, come le intranet, ma non è pronto per il mercato consumer, per il quale sono preferibili le soluzioni seguenti.

Java Launcher e Wrappers custom Quando un programma Java è invocato utilizzando uno dei metodi discussi sopra (file batch, jar eseguibile, JWS/JNLP), il sistema operativo esegue un lancher java fornito dalla JRE. La versione windows della JRE ha launchers separati per le applicazioni command line e quelle grafiche, rispettivamente java.exe e javaw.exe. Come risultato, tutte le applicazioni java in esecuzione hanno lo stesso nome nel Task manager e la stessa icona nella taskbar o nel pannello "alt-tab". Se si hanno più di un applicazione java in esecuzione, non si ha modo di distinguere fra le diverse istanze di java nel task manager. Praticamente, questi launchers sono solamente piccoli programmi nativi che caricano la JVM da una dll (shared library) ed eseguono le tue applicazioni usando le Invocations API. Queste api fanno parte delle Java Native Interdace (JNI), quindi standard, e molto semplici. Questo rende relativamente semplice scrivere un nostro launcher con un nome e un'icona unici. Quello che bisogna fare è trovare una JRE disponibile sul sistema dell'utente (o includerne una nell'applicazione), caricare e inizializzare la JVM e far girare l'applicazione su di essa.

Tool Java per creare Setup Se si necessita solo di installare una copia privata della JRE insieme alla propria applicazione e creare un collegamento che la esegua su tale JRE, si può utilizzare qualsiasi generatore di setup. Comunque, utilizzare un tool basato su java potrebbe avere dei benefici:

  • Rilevare al momento dell'installazione eventuali JRE presenti ed eventuale download
  • Generazione di un launcher nativo
  • Parametri JVM editabili dall'utente
  • Redirezione degli stderr e stdout per salvare log ed eccezioni
  • Registrazione delle applicazioni Java come servizi Windows o demoni Unix

Questa categoria è la più diversificata in termini di prezzo e funzionalità. Le differenze sono spiegate qui sotto: I tool Windows centrici, come Advanced Installer for Java permettono di creare installativi MSI. I tool multipiattaforma possono generare installativi per più piattaforme: Windows, Linux, Mac OS. Install4j è uno di questi. Ci sono anche Tool che permettono di creare installativi unici che girino su più piattaforme. Tali installativi sono essenzialmente jar eseguibili con logiche specifiche per gli ambienti nativi, riconosciuti a runtime. InstallAnywhere è forse il più conosciuto della categoria, ma se il suo prezzo è oltre il vostro budget, considerate il più economico JExpress o IZPack, Open Source. Infine, c'è un tool che li racchiude tutti, InstallShield che può creare sia MSI per Windows che installativi closs-platform,anche per server o dispositivi mobili, per qualsiasi tipo di applicazione e per una moltitudine di sistemi operativi. E sì, supporta il riconoscimento della JRE, l'installazione in bundling, i launcher nativi e così via.. Comunque, per le installazioni semplici e dirette, InstallShield è un peso inutile. Ricordate anche che InstallShield e InstallAnywhere mirano agli sviluppatori enterprise ed i loro prezzi sono conseguentemente elevati. Tutte queste soluzioni non risolvono il problema fondamentale menzionato nella prima sezione di questo articolo. Sia creando un jar eseguibile o un sofisticato installativo, l'applicazione continua ad essere distribuita come bytecode platform-indipendent. Nei primi giorni di Java, l'unico modo di eseguire un programma java su di un comune PC, era di interpretare tale bytecode. Oggi, qualsiasi implementazione J2SE decente contiene un compilatore Just-in-Time (JIT) che compila i metodi eseguiti frequentemente in codice nativo. Così è abbastanza naturale passare un passo avanti e compilare tutta l'applicazione prima di distribuirla. Vediamo quali tool ci permettono di farlo.

Compilatori Ahead-Of-Time I compilatori AOT sono conosciuti anche come "compilatori statici" o "compilatori di codice nativo". Quest'ultima denominazione è la più usata e, come spesso succede, la meno corretta dal punto di vista tecnico, dato che anche i compilatori JIT producono codice nativo. Un compilatore Ahead-Of-Time (AOT) prende in input i vostri file jar o class e produce un eseguibile convenzionale in linguaggio nativo, come un EXE Windows o un binario ELF per Linux. Così come qualsiasi altra soluzione tecnica, anche questa ha i suoi vantaggi e svantaggi.

Vantaggi:

  • Performance. Un compilatore JIT funziona come una applicazione in background e condivide la cpu e le risorse di memoria con l'applicazione che compila e con qualsiasi altra applicazione in esecuzione. Un compilatore AOT gira sul sistema dello sviluppatore senza vincoli di tempo o di risorse. Per questo può, potenzialmente, utilizzare ottimizzazioni di risorse più potenti, rendendo il codice migliore.
  • Protezione della proprietà intellettuale. Il bytecode Java è molto facile da decompilare, basta cercare "download java decompiler" per ottenere il codice sorgente di qualsiasi applicazione java in 5 minuti. Sì, è possibile offuscare i nomi delle classi e dei metodi pubblici ai quali non si accede via reflection, ma l'offuscamento del controllo di flusso può rendere il bytecode non verificabile dalle future JVM e rendere impossibili le ottimizzazione implementate dai compilatori JIT. Infine, criptare il bytecode non lo protegge del tutto, qualsiasi algoritmo di criptaggio si usa. D'altra parte, il codice nativo prodotta da un compilatore AOT ottimizzante è troppo complesso da essere sottoposto a reverse engineering, quanto quello di applicazioni sviluppate in C++. Inutile da dire, non ci sono prestazioni perse. Se si è interessati a proteggere la propria proprietà intellettuale, si dia uno sguardo alla compilazione nativa.
  • Percezione dell'utente. Le applicazioni Java Client soffrono spesso della cossidetta sindrome del ciclo di riscaldamento. Avviare un programma java richiede l'interpretazione del bytecode, la sua profilazione e la compilazione JIT. Per questo i programmi Java tendono a partire più lentamente dei loro rivali nativi e l'iniziale tempo di risposta di una applicazione grafica Java è molto peggiore di quello effettivo dopo che è stata usata parecchie volte, che sono le due maggiori ragioni per cui Java è ancora percepita come lenta da molti utenti. Un eseguibile nativo gira direttamente sull'hardware, senza l'overehad interpretazione-profilazione-compilazione, così può avviarsi più velocemente ed ottenere migliori tempi di risposta.

Svantaggi:

  • Peso sul disco. Il bytecode del Java è stato progettato per la compattezza, a un livello molto più elevato del set di istruzioni macchina. Si pensi che un eseguibile prodotto da un compilatore AOT sia 2-4 volte più grande dell'originale file jar.
  • Applicazioni dinamiche. Le classi che l'applicazione carica dinamicamente a tempo di esecuzione possono essere non disponibili al sviluppatore. Queste librerie possono essere plugin di terzi, proxy dinamici ed altre classi generate a tempo di esecuzione e così via. Così il sistema deve includere un interprete di bytecode Java e/o un compilatore JIT. Inoltre, generalmente solo le classi che sono caricate dal sistema o dal classloader dell'applicazione possono essere precompilate in codice nativo. Così le applicazioni che usano i classloaders custom possono soltanto essere parzialmente precompilati.
  • Ottimizzazioni per Hardware specifico. Un compilatore JIT presenta un vantaggio potenziale rispetto ai compilatori AOT in quanto può selezionare pattern di generazione di codice secondo la reale configurazione hardware su cui sta girando l'applicazione. Per esempio, può utilizzare le estensioni Intel MMX/SSE/SSE2 per velocizzare i calcoli in virgola mobile. Un compilatore AOT deve o produrre codice per il minor comun denominatore oppure diverse versioni per i più metodi più CPU-intensivi, aumentando il volume di codice.

C'è anche un comune pregiudizio che la compilazione AOT uccida la portabilità Java. Questo non è il caso, dato che il codice sorgente non necessita di essere modificato e si può sempre distribuire il bytecode per le piattaforme per cui non esiste un compilatore AOT. (Si perderebbe ovviamente il vantaggio di protezione del codice). Per quanto riguarda i tools, nel 2000 ne erano presenti una mezza dozzina, ma solo un paio sono sopravvissuti, si tratta di Excelsior JET e di GCJ (Gnu Compiler for Java). (Se siete interessati al campo embedded, date un'occhiata a NewMonics PERC, che si indirizza a J2ME CDC ed ha anche un supporto limitato a J2SE 1.3.

Tratto da programmazione.it scritto da Dario Guadagno

In questa ultima parte si analizzerà come utilizzare le classi fornite per importare o esportare scene in VRML. Le due classi relative all’interfacciamento con file e creazioni in VRML sono: VRML97Saver e VRML97Loader.

La prima, come si può intuire dal nome, consente di salvare gli ambienti creati in Java3D come file VRML, mediante una conversione che, attraversando tutto lo scene graph, individua i nodi rilevanti e li trasforma in istruzioni VRML (a loro volta scritte sotto forma di nodi, che generano un albero che descrive una scena tridimensionale). La sintassi da utilizzare è la seguente:

import cv97.j3d.*;
...
BranchGroup j3dBranchGroup = ...
VRML97Saver saver = new VRML97Saver();
saver.setBranchGroup(j3dBranchGroup);
saver.save(“nomeScena.wrl”);

Il codice indicato consente di esportare in formato standard VRML la scena corrispondente al content branch radicato nel j3dBranchGroup. L’ambiente salvato sarà visibile con qualunque strumento in grado di aprire file VRML.

Funzionamento analogo, ma chiaramente inverso, è quello della classe VRML97Loader, che consente di aprire un file VRML, convertirne il contenuto in un insieme di nodi Java3D, e trasformarli in un content branch radicato in un unico BranchGroup, che quindi può essere utilizzato per le normali operazioni previste da Java3D relative agli ambienti tridimensionali. La sintassi per utilizzare la suddetta classe è la seguente:

import cv97.j3d.loader.*;
...
Canvas3D c3d = ...
VRML97Loader wrlLoader = new VRML97Loader(c3d);
Scene s = wrlLoader.load(“nomeScena.wrl”);
BranchGroup sgGroup = s.getSceneGroup();

Il loader viene inizializzato con la Canvas3D, che contiene l’universo in cui si sta lavorando per la creazione di un ambiente 3D. L’importazione di una scena descritta in VRML avviene in due fasi: dapprima, utilizzando il metodo load(), si carica il file .wrl che rappresenta la scena e si ottiene così una com.sun.j3d.loaders.Scene corrispondente al file caricato; poi, utilizzando il metodo getSceneGroup(), si ottiene il BranchGroup in cui è radicato il content branch, che descrive la scena sotto forma di istruzioni e nodi in Java3D.

L’oggetto sgGroup ottenuto potrà, quindi, essere utilizzato nel codice Java che segue la sua istanziazione come un qualsiasi BranchGroup, per cui potranno essere aggiunti ulteriori nodi come suoi figli, potrà essere associato ad un nodo gruppo (BranchGroup o TransformGroup) padre, o potrà essere inserito nell’universo su cui si sta lavorando, per consentire la visualizzazione della scena che sgGroup rappresenta.

Lo scorso settembre è stato annunciato che, finalmente dopo ben otto anni di silenzio assoluto, verrà rilasciata la versione aggiornata del linguaggio HTML. Si passerà quindi dalla release 4 del 1999 alla release 5. La nuova versione aggiungerà nuovi comandi al linguaggio, per venire incontro alle esigenze degli sviluppatori di integrare materiale multimediale e altro nelle pagine web. Ciò nonostante la vecchia versione sarà ancora valida al 100% e rimane alla fin fine la struttura portante di ogni pagina. Pubblichiamo qui una quick reference guide del linguaggio, per avere sempre a portata di mano comandi e parametri disponibili nella vecchia versione.

Solitamente, dopo aver scaricato ogni sorta di ben di dio da poter caricare nel proprio cellulare, sorge la fatidica domanda: e se ora facessi qualcosa io? Il proposito è lodevole, ma non privo di ostacoli. Per scrivere un gioco java per cellulari bisogna cimentarsi con la j2me, che volenti o nolenti, significa programmare. Ciò nonostante java è stato realizzato con due obiettivi principali: funzionare su qualsiasi dispositivo ed essere di facile apprendimento. Senza essere ipocriti, java è e rimane un linguaggio di programmazione a tutti gli effetti, ma con qualche buon esempio anche chi non è un buon programmatore ma è armato di pazienza e impegno è in grado di ottenere qualche soddisfazione.

Per poter apprendere in modo rapido i rudimenti di Java consiglio di leggere la guida che presenta HTML.it. Qui trovate invece una guida specifica per J2ME.

Il compilatore Java2, necessario per lo sviluppo dell'applicazione si scarica gratuitamente dal sito di Sun Microsystems. Similmente il pacchetto aggiuntivo J2ME. Scrivere dal Blocco Note di Windows è possibile, ma non è il massimo per chi si avvicina a Java per la prima volta. Ci si deve quindi appoggiare a degli IDE, dei programmi che ci assistono nella stesura del codice. Se vogliamo restare in casa Sun possiamo scaricare NetBeans, altrimenti anche Eclipse fa al caso nostro. Infine abbiamo bisogno di avere qualche esempio pronto da sviscerare per vedere come funziona il tutto. Qui trovate qualcosina che per iniziare è certamente d'aiuto.

Tratto da programmazione.it scritto da Dario Guadagno

In questo articolo, vedremo come esportare il lavoro fatto con Java3D in formati standard e quindi particolarmente portabili, come VRML e la sua evoluzione X3D. Il package CyberX3D è un sottoinsieme della libreria CyberGarage, realizzata dal programmatore giapponese Satoshi Konno, contenente un insieme di classi e metodi orientati alla realtà virtuale ed alla programmazione in grafica 3D.

Satoshi Konno, nato nel 1972 a Tokyo, lavora da anni nell’ambito della programmazione di sistemi in realtà virtuale, e dal 1996 ha iniziato a lavorare al CyberGarage, un insieme di prodotti ideati per semplificare o ottimizzare la programmazione di ambienti tridimensionali. La libreria CyberGarage, oltre a CyberX3D (scritto sia per programmatori Java che C++), contiene anche altri package interessanti, alcuni dei quali persino premiati da diversi riconoscimenti attestanti l’eccellente qualità.

Rilasciato nel 2003, CyberX3D è un package per programmatori Java che intendono interoperare con file e ambienti VRML o X3D. Utilizzando CyberX3D è possibile creare o utilizzare, in maniera piuttosto semplificata, classi e metodi per leggere/scrivere file VRML o X3D, reperire o modificare informazioni relative allo scene graph di un ambiente 3D, disegnare scene tridimensionali da esportare in uno dei suddetti formati.

L’utilizzo del package è subordinato alla presenza nel proprio sistema della piattaforma Java 2 Standard Edition e delle API Java3D. L’installazione di CyberX3D avviene, facilmente, copiando il package nella directory del Run Time Environment della JVM.

Tratto da programmazione.it, scritto da Dario Guadagno

In quest'ultima parte, tratteremo alcuni problemi che si potrebbero verificare durante la scrittura di programmi in grafica 3D in ambiente Java, e saranno spiegati alcuni dettagli relativi al motore 3D.

Come accennato nella prima parte dell'articolo, Java3D si appoggia su librerie native, per cui è da esse che deriva le proprie feature principali, mentre non è in grado di fornire supporto per alcune funzionalità, come la gestione delle ombre o delle texture animate, superfici trasparenti o specchi). Tuttavia, queste non sono limitazioni di Java3D, ma delle librerie native. Le operazioni citate sono infatti molto dispendiose in termini di risorse e non vengono utilizzate in grafica 3D in tempo reale. È lecito aspettarsi che quando l’evoluzione tecnologica porterà gli standard 3D a supportare questo tipo di caratteristiche, anche Java3D ne fornirà il supporto.

Java3D non è però solo un semplice wrapper su API esistenti: il suo motore si occupa anche di ottimizzazioni e operazioni aggiuntive che non sono previste nelle API native. Il runtime engine sceglie l’ordine di attraversamento dell’albero e non è limitato ad una direzione di tipo sinistra-destra o sopra-sotto, quindi può utilizzare strategie per l'ottimizzazione della visualizzazione. La rappresentazione di un'immagine tridimensionale avviene seguendo il seguente schema:

  • definizione del view volume, ovvero della porzione di spazio visibile all’utente;
  • rendering: conversione del view volume in un’immagine 2D;
  • rasterization: l’immagine viene convertita in una griglia di pixel;
  • shading: viene impostato il colore dei pixel.

Tutte le suddette operazioni sono eseguite direttamente, e in maniera trasparente a programmatore ed utente, dalla Java Virtual Machine, che immediatamente dopo, mostra l’effettiva scena attiva, pronta all’eventuale interazione. Ulteriori problematiche potrebbero essere connesse ad altre due segnalazioni: le classi di Java 3D non sono serializzabili e, come noto, richiedono un notevole impiego di risorse. Quest'ultimo punto, in particolare, merita una cura in più: se da un lato, chiaramente, esso determina un rallentamento nelle prestazioni, peraltro piuttosto lieve e sicuramente accettabile, dall'altro, in caso di scene particolarmente complesse e cariche di oggetti, può addirittura causare il crash dell'applicazione per problemi di insufficienza di memoria (Out of Memory Error).

Il problema si presenta perché, di default, la JVM ricorre ad un heap di dimensioni contenute, ideale per la maggior parte delle applicazioni eseguite, ma non sufficiente nel caso di sistemi più complessi. È possibile aggirare tale rischio ampliando l’heap a disposizione della JVM, specificando dei parametri aggiuntivi all’atto di mandare in esecuzione l'applicazione. Il progetto, in generale, presenta una certa semplicità d’uso anche se dà l’idea di essere stato sviluppato un po’ in disparte rispetto alle altre tecnologie Java. L’incompatibilità con Swing ne è un esempio (come la classe Locale che trova un duplicato in java.util) che potrebbe frenare progetti ambiziosi su Java3D.

Nonostante alcune limitazioni e complessità aggiuntive, comunque, è indubbio che Java3D sia un potentissimo strumento a disposizione dei programmatori Java. Le Api completano l’offerta della piattaforma, introducendo un elemento chiave quale la grafica 3D e fornendo un'ulteriore preziosa funzionalità all'intera tecnologia Java.

Tratto da programmazione.it, scritto da Dario Guadagno

Una soluzione alternativa per gestire gli eventi può essere ottenuta sfruttando il fatto che la Canvas3D, in quanto Component, è una possibile sorgente di eventi. Da ciò, catturando gli eventi generati dalla Canvas3D, e quindi le interazioni dell'utente con la scena, e sfruttando i metodi offerti dalla classe PickCanvas, che restituisce un riferimento all'oggetto (il nodo dell'albero) su cui l'utente ha cliccato, è possibile simulare una gestione di eventi basata sulle interazioni con gli oggetti 3D della scena.

Per lavorare in tal senso, d'altra parte, è bene ricordare che gli oggetti "interattivi" devono essere pick-reportable, cioè devono poter essere letti dal PickCanvas:

nodo3d.setCapability(TransformGroup.ENABLE_PICK_REPORTING);

Qualora si voglia gestire la possibilità di spostare/rimuovere oggetti dall'albero della scena in seguito a qualche interazione, essi devono anche essere detachable, cioè rimuovibili dallo Scene Graph, oppure devono consentire la lettura e scrittura delle loro proprietà all'interno dell'albero:

nodo3d.setCapability(BranchGroup.ALLOW_DETACH); //rende l'oggetto detachable

/* Lettura e modifica delle trasformazioni */
nodo3d.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
nodo3d.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);

/* Lettura e modifica dei figli nel sottoalbero radicato nel nodo oggetto3d */
nodo3d.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
nodo3d.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
nodo3d.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);

Una volta definita la scena e le eventuali interazioni, basterà rendere visibile il frame che contiene la Canvas3D per visualizzare la nostra prima scena tridimensionale. Con le prime tre parti di questo articolo sono stati mostrati gli aspetti fondamentali della programmazione in Java 3D.

Tratto da programmazione.it, scritto da Dario Guadagno

La scena, di default, indipendentemente dalle dimensioni del frame che la contiene, ha larghezza 2, il punto più a sinistra è posto alla coordinata -1 e l’estremo a destra è alla coordinata +1; al centro del frame è posta l’origine e l’asse della profondità è orientato secondo il verso “uscente” dallo schermo. L'asse dell'altezza ha dimensione calcolata in rapporto alla larghezza: ad esempio, se un frame ha altezza doppia rispetto alla larghezza, il punto più alto del frame avrà coordinata 2, e il più basso -2.

È possibile definire delle reazioni ai movimenti del mouse nella scena (specializzazioni della classe MouseBehavior), o alle specifiche interazioni su un oggetto 3D (specializzazioni della classe PickMouseBehavior), ma il meccanismo non è semplicissimo ed è certamente più macchinoso di quanto non accada con la normale gestione ad eventi. D'altra parte, alcune convenzioni adottate da Java 3D sono facilmente utilizzabili e permettono di gestire i movimenti "continui" degli oggetti tridimensionali, come la traslazione o la rotazione:

  • pressione del pulsante sinistro del mouse e trascinamento, per la rotazione di un oggetto, gestita dalla classe PickRotateBehavior.
  • Pressione del pulsante destro del mouse e trascinamento, per lo spostamento di un oggetto lungo l’asse orizzontale o verticale, gestita dalla classe PickTranslateBehavior.
  • Pressione del pulsante sinistro del mouse e, contemporaneamente, del tasto ALT della tastiera (tale combinazione equivale alla pressione del pulsante centrale nei mouse three button) e trascinamento, per avvicinare o allontanare un oggetto (spostamento lungo l’asse della profondità), gestita dalla classe PickZoomBehavior).

Le scelte relative ai componenti tridimensionali di una scena sono dovute anche al fatto che, chiaramente, i cambiamenti a runtime di un ambiente tridimensionali sono ben più “pesanti” di quelli all’interno di applicazioni 2D. Limitare e standardizzare i movimenti e rendere più "statici" gli oggetti alleggerisce il lavoro a runtime del motore 3D.

Tratto da programmazione.it, scritto da Dario Guadagno

Le API Java 3D sono una libreria di classi e metodi specifiche per la realizzazione di applicazioni dotate di interfaccia grafica tridimensionale. Java 3D consente la produzione in tempo reale di grafica 3D tramite un insieme di API omogenee e multipiattaforma. Queste non si occupano del rendering a basso livello delle immagini: questa operazione è delegata dal motore di rendering di Java 3D alle librerie native della piattaforma sottostante, come OpenGL e Direct3D.

L'installazione delle API può avvenire semplicemente eseguendo il comodo tool autoinstallante scaricabile dal sito di Sun Microsystems. In Java 3D, il concetto fondamentale è quello dello scene graph: un albero a cui si appendono tutti gli oggetti della scena 3D, intendendo con tale termine non solo gli elementi da visualizzare, ma anche le istruzioni per rappresentarli.

L’albero è radicato nell’Universo Virtuale (Virtual Universe) che, a sua volta, ha uno o più figli Locale (letteralmente, dei luoghi all’interno dell’universo), che rappresentano le scene tridimensionali. Lo scene graph viene percorso dal motore di Java 3D per trovare i dati per creare l'immagine, perciò qualsiasi cosa si desideri abbia un'influenza sulla scena va messa nello scene graph.

Da ogni nodo Locale partono due rami (branches) principali: il content branch e il view branch: il primo contiene gli oggetti da visualizzare, il loro colore, dove sono messi nello spazio e tutte le altre informazioni rilevanti; il secondo contiene tutto quello che riguarda “il vedere” la scena, ad esempio i dispositivi di input/output, punto di vista ecc.

La creazione dell’Universo Virtuale, del contesto locale e di tutti gli aspetti relativi al view branch può essere effettuata automaticamente utilizzando la classe SimpleUniverse fornita di default dal package, in com.sun.j3d.utils.universe.*

Il disegno tridimensionale viene creato all'interno di un oggetto Canvas3D, che è un'estensione della classe Component, per cui può semplicemente essere aggiunto ad un frame; tuttavia, non è un container, quindi non può contenere altri componenti. La Canvas3D viene creata a partire dal view branch, e riempita, quindi, con gli elementi del content branch. Gli oggetti tridimensionali immessi nella scena, in effetti, non sono altro che dei rendering delle immagini descritte dai nodi, per cui, non è possibile associare degli eventi da catturare e gestire, secondo la normale programmazione a eventi di Java, ma è possibile definire dei behavior, cioè delle reazioni degli oggetti tridimensionali all'interazione dell'utente con la scena.

Come detto, quindi, ogni elemento della scena, sia esso un oggetto 3D, una luce o una qualsiasi entità che definisca le modalità di visualizzazione dell'ambiente, non è altro che un nodo del grafo della scena. Due nodi, tuttavia, hanno una funzione particolare: i BranchGroup, radici di sottoalberi di oggetti con proprietà comuni, e i TransformGroup, che definiscono delle trasformazioni (rotazioni, spostamenti lungo uno degli assi ecc.) associate a tutti gli elementi del loro sottoalbero.

Le foglie dello Scene Graph sono, tipicamente, gli oggetti fisici che popolano la scena.