Open Inventor In questa lezione impareremo a: Cambiare il colore di una Shape Muovere le shape presenti in scena Caricare i modelli 3D da file Creare un timer che chiami periodicamente una funzione Catturare gli eventi da tastiera per creare applicazioni interattive
I nodi Property I property nodes rappresentano l’apparenza e le caratteristiche qualitative della scena come il materiale degli oggetti, lo stile di disegno o le trasformazioni geometriche. Questo tipo di nodi possono essere divisi in tre sottocategorie: Nodi appearance che modificano l’apparenza degli oggetti quali SoMaterial, SoBaseColor, SoDrawStyle, SoLightModel, SoFont. Ad esempio: SoBaseColor *myColor = new SoBaseColor(); myColor->rgb.setValue(1.0, 0.0, 0.0); Nodi transform che realizzano trasformazioni geometriche quali SoTransform, SoRotation, SoScale, SoTranslation, SoRotationXYZ. Tutti questi nodi sono derivati da SoTransformation. Ad esempio: SoTransform *myXform = new SoTransform(); myXform->translation.setValue(1.0, 0.0, 0.0);
Il nodo SoBaseColor SoSeparator *root = new SoSeparator(); SoCone *cono = new SoCone(); SoBaseColor *myColor = new SoBaseColor(); myColor->rgb.setValue(1.0, 0.0, 0.0); root->addChild(myColor); root->addChild(cono);
Operazioni sui vettori Open Inventor mette a disposizioni due importanti classi per gestire i vettori: SbVec3f SbRotation Per gli SbVec3f sono disponibili molte operazioni di uso comune: somma, lunghezza, prodotto vettoriale e scalare, etc. Il modo più semplice per identificare una SbRotation è attraverso il vettore che rappresenta l’asse di rotazione e un float che rappresenta l’angolo di rotazione intorno all’asse. Sommare l’effetto di due rotazioni equivale a moltiplicarle (poiché OI le rappresenta come matrici): SbRotation rot3 = rot1 * rot2; Per applicare una rotazione ad un certo vettore è sufficiente fare: rot.multVec(vecchioVettore, nuovoVettore);
Il nodo SoTransform (traslazioni) SoSeparator *root = new SoSeparator(); SoCone *cono = new SoCone(); SoTransform *myXform = new SoTransform(); myXform->translation.setValue(0.0, 0.0, 0.0); root->addChild(myXform); root->addChild(cono); …. void muovi(SoTransform *transform) { SbVec3f posizione = transform->translation.getValue(); SbVec3f spostamento(1.0, 0.0, 0.0); transform->translation.setValue(posizione + spostamento); }
Il nodo SoTransform (rotazioni) SoSeparator *root = new SoSeparator(); SoCone *cono = new SoCone(); SoTransform *myXform = new SoTransform(); SbVec3f asseZ(0.0, 0.0, 1.0); myXform->rotation.setValue(asseZ, 0.0); root->addChild(myXform); root->addChild(cono); …. void gira(SoTransform *transform) { SbRotation rotazione = transform->rotation.getValue(); SbRotation deltaRot(asseZ, 0.05); transform->rotation.setValue(rotazione * deltaRot); }
Caricare i modelli 3D da file SoSeparator *readFile(const char *filename) { SoInput mySceneInput; if (!mySceneInput.openFile(filename)) { fprintf(stderr, "Cannot open file %s\n", filename); return NULL; } SoSeparator *myGraph = SoDB::readAll(&mySceneInput); if (myGraph == NULL) { fprintf(stderr, "Problem reading file\n"); return NULL; } mySceneInput.closeFile(); return myGraph; }
Il Timer Sensor void timerCallback (void *data, SoSensor *) { Veicolo *mioVeicolo = (Veicolo*) data; // conversione esplicita mioVeicolo->muovi(0.04); } …. Veicolo mioVeicolo; … SoTimerSensor *myTimerSensor = new SoTimerSensor(timerCallback, &mioVeicolo); timerSensor->setInterval(0.04f); // 1/25 sec = 0.04 timerSensor->schedule();
Catturare gli eventi da tastiera void myKeyPressCB(void *data, SoEventCallback *eventCB) { Veicolo *veicolo = (Veicolo*) data; const SoEvent *event = eventCB->getEvent(); if (SO_KEY_PRESS_EVENT(event, UP_ARROW )) { veicolo->accelera(); } eventCB->setHandled(); } … SoEventCallback *myEventCB = new SoEventCallback; myEventCB->addEventCallback( SoKeyboardEvent::getClassTypeId(), myKeyPressCB, veicolo); root->addChild(myEventCB); …