Sei sulla pagina 1di 7

Scene Graph

E' un albero contenente oggetti che hanno bisogno di essere interpretati. Alla base di quest'albero c' un oggetto chiamato render. Niente pu essere interpretato se l'oggetto render non viene inserito nello Scene Graph. Con il metodo reparentTo() si sistema il genitore del modello che si vuole caricare, piazzandolo nello Scene Graph. Per, invece, aggiustare la scala e la posizione del modello si utilizzano due procedure setScale() e setPos() che, rispettivamente, definiscono la scala e la posizione del modello ambientale. Panda 3D usa le coordinate "geografiche" del sistema(X,Y,Z) che sarebbero le coordinate del piano (X,Y) e l'altezza Z. Codice: from direct.showbase.ShowBase import ShowBase class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) # Carica il modello ambientale. self.environ = self.loader.loadModel("models/environment") # Reparent the model to render. self.environ.reparentTo(self.render) # Applica i parametri di scala e posizione al modello. self.environ.setScale(0.25, 0.25, 0.25) self.environ.setPos(-8, 42, 0) app = MyApp() app.run() La procedura in ShowBase loader.loadModel() carica il file specificato, in questo caso environment.egg, dalla cartella models.

Sistemi di controllo default per la telecamera


Di default Panda3D avvia un'operazione che ti permette usare la telecamera con il mouse. Pulsante sinistro del mouse ---> Sposta a destra e sinistra; Pulsante destro del mouse ---> Muove avanti e indietro; Pulsante centrale del mouse(rotellina) ---> Ruota attorno all'origine dell'applicazione; Pulsante destro e centrale---> Ruota il punto di vista attorno gli assi dello spazio; Codice: def spinCameraTask(self, task):

angleDegrees = task.time * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3) self.camera.setHpr(angleDegrees, 0, 0) return Task.cont La procedura taskMgr.add() dice al task manager di Panda3D di chiamare la funzione spinCameraTask() per ogni struttura. Questa una funzione utilizzata per il controllo della telecamera. Fino a quando la funzione spinCameraTask() da come risultato Task.cont, il task manager continuer a chiamarla per ciascuna struttura(Frame). Nel codice sopra descritto la funzione spinCameraTask() calcola la posizione desiderata della telecamera basandosi su quanto tempo passato. La telecamera ruota di 6 gradi ogni secondo. Le prime 2 linee calcolano l'orientazione desiderata della telecamera; prima in gradi, poi in radianti. La chiamata setPos() imposta la posizione della telecamera.(Ricorda che Y orizzontale e Z verticale, quindi la posizione cambiata animando X e Y mentre Z fissata a 3 unit sopra il livello del terreno.) La chiamata a setHpr() imposta l'orientamento.

Actors
La classe Actor per i modelli animati. Nota che noi utilizziamo loadModel() per i modelli statici e Actor solo quando sono animati. I due argomenti costruttori per la classe Actor sono i nomi dei file che contengono il modello e un dizionario Python contentente i nomi dei file che posseggono le animazioni per il modello. Codice aggiornato: from math import pi, sin, cos from direct.showbase.ShowBase import ShowBase from direct.task import Task from direct.actor.Actor import Actor class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) # Load the environment model. self.environ = self.loader.loadModel("models/environment") # Reparent the model to render. self.environ.reparentTo(self.render) # Apply scale and position transforms on the model. self.environ.setScale(0.25, 0.25, 0.25) self.environ.setPos(-8, 42, 0) # Add the spinCameraTask procedure to the task manager. self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")

# Load and transform the panda actor. self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.005, 0.005, 0.005) self.pandaActor.reparentTo(self.render) # Loop its animation. self.pandaActor.loop("walk") # Define a procedure to move the camera. def spinCameraTask(self, task): angleDegrees = task.time * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3) self.camera.setHpr(angleDegrees, 0, 0) return Task.cont app = MyApp() app.run() Il comando loop("walk") la causa dell'animazione walk infinita (il panda cammina all'infinito).

Intervalli e Sequenze
Intervalli
Gli intervalli sono operazioni che cambiano una propriet da una valore ad un altro dopo un intervallo di tempo specificato. Facendo partire un intervallo, effettivamente, parte un processo in background che modifica le priopriet in un intervallo di tempo predefinito.

Sequenze
Le sequenze sono operazioni che eseguono un intervallo dopo l'altro. Codice Aggiornato: from math import pi, sin, cos from direct.showbase.ShowBase import ShowBase from direct.task import Task from direct.actor.Actor import Actor from direct.interval.IntervalGlobal import Sequence from panda3d.core import Point3 class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self)

# Disable the camera trackball controls. self.disableMouse() # Load the environment model. self.environ = self.loader.loadModel("models/environment") # Reparent the model to render. self.environ.reparentTo(self.render) # Apply scale and position transforms on the model. self.environ.setScale(0.25, 0.25, 0.25) self.environ.setPos(-8, 42, 0) # Add the spinCameraTask procedure to the task manager. self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") # Load and transform the panda actor. self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.005, 0.005, 0.005) self.pandaActor.reparentTo(self.render) # Loop its animation. self.pandaActor.loop("walk") # Create the four lerp intervals needed for the panda to # walk back and forth. pandaPosInterval1 = self.pandaActor.posInterval(13, Point3(0, -10, 0), startPos=Point3(0, 10, 0)) pandaPosInterval2 = self.pandaActor.posInterval(13, Point3(0, 10, 0), startPos=Point3(0, -10, 0)) pandaHprInterval1 = self.pandaActor.hprInterval(3, Point3(180, 0, 0), startHpr=Point3(0, 0, 0)) pandaHprInterval2 = self.pandaActor.hprInterval(3, Point3(0, 0, 0), startHpr=Point3(180, 0, 0)) # Create and play the sequence that coordinates the intervals. self.pandaPace = Sequence(pandaPosInterval1, pandaHprInterval1, pandaPosInterval2, pandaHprInterval2, name="pandaPace") self.pandaPace.loop() # Define a procedure to move the camera. def spinCameraTask(self, task): angleDegrees = task.time * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3) self.camera.setHpr(angleDegrees, 0, 0) return Task.cont

app = MyApp() app.run() Quando l'intervallo pandaPosInterval1 viene eseguito, gradualmente esso allineer al posizione del panda da (0,10,0) a (0,-10,0) dopo un periodo di 13 secondi. Lo stesso avviene, quando l'intervallo pandaHprInterval1 viene eseguito, la testa del panda ruota di 180 gradi ogni 3 secondi. La sequenza pandaPace causa il movimento del panda lungo una linea retta, una rotazione, un movimento dalla parte opposta rispetto all'inizio e, alla fine, una nuova rotazione. Il codice pandaPace.loop() fa partire la Sequenza in modalit loop(ciclo infinito).

Variabili globali con __builtin__ in ShowBase


__builtin__.base = self __builtin__.render2d = self.render2d __builtin__.aspect2d = self.aspect2d __builtin__.pixel2d = self.pixel2d __builtin__.render = self.render __builtin__.hidden = self.hidden __builtin__.camera = self.camera __builtin__.loader = self.loader __builtin__.taskMgr = self.taskMgr __builtin__.jobMgr = self.jobMgr __builtin__.eventMgr = self.eventMgr __builtin__.messenger = self.messenger __builtin__.bboard = self.bboard __builtin__.run = self.run __builtin__.ostream = Notify.out() __builtin__.directNotify = directNotify __builtin__.giveNotify = giveNotify __builtin__.globalClock = globalClock __builtin__.vfs = vfs __builtin__.cpMgr = ConfigPageManager.getGlobalPtr() __builtin__.cvMgr = ConfigVariableManager.getGlobalPtr() __builtin__.pandaSystem = PandaSystem.getGlobalPtr() __builtin__.wantUberdog = base.config.GetBool('want-uberdog', 1) I pi usati comunemente sono base, render, render2d, camera, messenger, and taskMgr.

La Scena Grafica: un albero di nodi


Molti motori grafici 3D mantengono una lista di modelli 3D per interpretare ogni riquadro(Frame). In questi semplici motori questi modelli devono essere caricati dal disco ed essere inseriti nella lista dei modelli da interpretare perch essi non sono visibili finch non sono inseriti in quest'ultima. Panda 3D leggermente pi sofisticato. Invece di mantenere una lista di oggetti da interpretare, mantiene un albero di oggetti. Un oggetto non visibile se non inserito in questo albero.

L'albero formato da oggetti della classe PandaNode. Questa attualmente una sovraclasse per 3 classi: ModelNode, GeomNode, LightNode. Uscendo da questo manuale comune riferirsi a questi oggetti con il nome di nodi (nodes). La radice di quest' albero chiamata render (Nota: potrebbero esserci radici addizionali per propositi speciali, come render2d per oggetti 2D). "L'albero di cose da interpretare" di Panda3D chiamato Scene Graph (scena grafica). Cosa bisogna conoscere sulle gerarchie della scena grafica Qui sono elencate le cose pi importanti che bisogna conoscere sulle organizzazioni gerarchiche: 1. Tu controlli dove gli oggetti vanno nell'albero. Si pu specificare, quando viene inserito un nuovo oggetto nell'albero, dove si vuole inserire l'oggetto. 2. Le posizioni degli oggetti sono specificate in relazione ai genitori presenti nell'albero. Per esempio, se hai un modello 3D di un cappello, potresti voler specificare che esso si trova sempre 5 unit sopra un modello 3D di una testa di persona. Si inserisce il cappello come figlio della testa e si imposta la posizione del cappello (0,0,5) Z=altezza=5. 3. Quando i modelli sono organizzati in un albero, qualunque attributo di rendering che si assegna a un nodo sar propagato ai suoi figli . Per esempio, se specifichi che un dato nodo dovrebbe essere interpretato con nebbia spessa, poi i suoi figli saranno interpretati con una spessa nebbia, senza esplicitare il livello del figlio. 4. Panda 3D genera scatole unite per ogni nodo all'albero. Se la scatola legata ad un intero ramo fuori il fusto, non c' bisogno di esaminare i figli. I principianti solitamente scelgono di fare il proprio albero completamente piatto; ogni cosa inserita immediatamente al di sotto della radice. NodePaths Esiste una classe aiutante chiamata NodePath la quale contiene solamente un puntatore per un nodo, pi qualche informazione amministrativa. Per ora, si possono ignorare le informazioni amministrative (fine manuale). E' l'intento dei progettatori di panda quello di poter pensare a un NodePath(puntatore al nodo) come una maniglia per un nodo. Qualunque funzione che crea un nodo ritorna a NodePath che indirizza per un nodo appena creato. Un NodePath non esattamente un puntatore al nodo; esso una maniglia per il nodo. Concettualmente, questa almeno una distinzione senza una differenza. Comunque, ci sono delle funzioni API che aspettano te per passare in un NodePath, e ci sono altre API che aspettano una tua indicazione per passare in un puntatore del nodo. Si pu convertire un NodePath in un puntatore regolare sempre chiamando nodePath.node() . Non c' nessuna via disambigua per riconvertirlo. Qualche volta si ha bisogno di un NodePath altre volte, invece, si potrebbe aver bisogno di un puntatore al nodo, per questo raccomandato riservare NodePaths e non puntatori di nodo. La chiamata pu comunque sempre convertire il NodePath in un puntatore se si ha bisogno. NodePath-Methods e Node-Methods

Ci sono molti metodi che si possono invocare sui nodepath, e sono appropriati sia per i nodi che per i tipi. Tipi specializzati di nodi, come LODNodes e Cameras (per le istanze), fornisce metodi addizionali avviabili sono per nodi di quel tipo, che bisogna chiamare sui nodi stessi. Esempi:
# NODEPATH METHODS: myNodePath.setPos(x, y, z) myNodePath.setColor(banana) # LODNODE METHODS: myNodePath.node().addSwitch(1000, 100) myNodePath.node().setCenter(Point3(0, 5, 0)) # CAMERA NODE METHODS: myNodePath.node().setLens(PerspectiveLens()) myNodePath.node().getCameraMask()

Ricorda sempre: quando chiami un metodo di NodePath, stai gestendo un'operazione dal nodo ai suoi punti. Nell'esempio qui sopra noi chiamiamo i metodi del nodo dopo aver prima convertito i nodepath in nodi, e poi immediatamente chiamato il metodo del nodo. Questo lo stile raccomandato.

Le Scene Grafiche predefinite


Di default, ci sono 2 differenti Scene Grafiche create automaticamente durante lo start up di Panda3D. Queste scene sono rirerite ai nodi pi in alto: render e render2d. Render viene utilizzato spesso perch il metodo pi alto dell'ordinaria scena 3D. Per mettere un oggetto nel paesaggio, bisogna collegarlo a render (o a qualche oggetto nodo che collegato a render). Invece, si utilizza render2d per gli elementi di GUI render 2D, come testi o pulsanti, che vuoi far apparire sullo schermo. Niente collegato a render2d verr interpretato al di sopra di scene 3D.