Lezione 4 - Sviluppo di applicazioni grafiche in C++ con Qt,OpenGl e OpenInventor

Tweet
In questa lezione vedremo come si realizzano in C++ quelle applicazioni grafiche che abbiamo gia' visto realizzate in Java. Limitandoci come al solito al solo software disponibile gratuitamente, con Linux abbiamo 3 possibilita' di creare applicazioni grafiche:
  1. Usare direttamente la libreria X11 del sistema X Window che e' alla base della grafica Unix. Questa libreria e' ormai antiquata e quindi poco adatta per programmi ad oggetti.
  2. Usare GTK+ : questa e' una libreria grafica avanzata che e' servita per realizzare Gnome e gimp. Purtroppo non e' in C++ ma in C.
  3. La soluzione che adotteremo e' di usare Qt una libreria grafica avanzata in C++ . Essa e' alla base di KDE , e' object oriented e molto simile a Java(in effetti essendo stata scritta dopo che Java era nato, ne risente l'influsso).
Chiariamo brevemente che al momento attuale Linux viene distribuito con due interfacce grafiche alternative e praticamente identiche:Gnome e KDE. Gnome ha alla base GTK+ e KDE invece Qt. Ambedue le interfacce sono servite a costruire programmi molto avanzati che ne mostrano le possibilita' come: Gimp(una specie di Photoshop per Linux) per GTK+ e Konqueror (un browser) per il KDE. Possiamo dire che i due approcci sono equivalenti ed e' questione di gusti se scegliere l'uno o l'altro. L'esperimento CMS al Cern ha scelto per esempio Qt per i suoi programmi grafici.
Prima di cominciare, facciamo notare che in Qt possiamo realizzare solo l'equivalente delle applicazioni Java ma non applet! Il C++, a differenza di Java, di solito non puo' girare all'interno di un browser.


Programma 1: Scrivete un'applicazione grafica che realizza la famosa scritta "Ciao a tutti!" .S

    file ciao.cc


#include <qapplication.h>
#include <qlabel.h>

 int main (int argc, char* argv[])
 {
    QApplication ciao(argc,argv);
    QLabel* scritta = new QLabel("Ciao a tutti!",0);
    scritta->resize(120,30);
    ciao.setMainWidget(scritta);
    scritta->show();
    return ciao.exec();
 }

Per eseguire questo programma dovreste dare dei comandi di questo tipo:
g++ -o ciao ciao.cc -I$QTDIR/include -L/$QTDIR/lib  -lqt
ciao

Programma 2: Riscrivete in Qt l'Applicazione 1 della lezione 4 su Java .S

    file MyWidget.cpp

#include <qapplication.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qvbox.h>

class MyWidget : public QVBox 
{
 public:
 MyWidget (QWidget *parent=0, const char *name=0);
};

 MyWidget::MyWidget(QWidget *parent, const char *name)
        : QVBox(parent,name)
 {
   QPushButton *b1 = new QPushButton("This is button 1",this);
   QPushButton *b2 = new QPushButton("This is button 2",this);
   QLineEdit *t = new QLineEdit("This is a LineEdit",this);
 }

int main (int argc, char* argv[])
 {
    QApplication a(argc,argv);
    MyWidget w;
    a.setMainWidget(&w);
    w.show();
    return a.exec(); 
 }




Programma 3: Disponete in una tabella i 3 oggetti del programma 2 .S

    file MyWidget1.cpp


Programma 4: Modificate il programma precedente in modo che scriva qualcosa quando si premono i due tasti .S

    file MyButton.h

#include <qapplication.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlayout.h>
# include  <iostream>
# include  <string>



class MyWidget : public QWidget 
{
   Q_OBJECT
 public:
   MyWidget (QWidget *parent=0, const char *name=0);
 signals:
 public slots: 
   void scrivi1();
   void scrivi2();
};

    file MyButton.cpp


#include "MyButton.h"

 MyWidget::MyWidget(QWidget *parent, const char *name)
        : QWidget(parent,name)
 {
   QPushButton *b1 = new QPushButton("This is button 1",this);
   QPushButton *b2 = new QPushButton("This is button 2",this);
   QLineEdit *t = new QLineEdit("This is a LineEdit",this);
   QGridLayout *grid = new QGridLayout( this, 2, 2, 10 );
   grid->addWidget( b1, 0, 0 );
   grid->addWidget( b2, 1, 0 );
   grid->addWidget( t, 1, 1 );
   QObject::connect(b1, SIGNAL(clicked()),this,SLOT(scrivi1()));
   QObject::connect(b2, SIGNAL(clicked()),this,SLOT(scrivi2()));

 }
  void MyWidget::scrivi1(){cout << "Bottone 1 cliccato!" << endl;} 
  void MyWidget::scrivi2(){cout << "Bottone 2 cliccato!" << endl;} 

int main (int argc, char* argv[])
 {
    QApplication a(argc,argv);
    MyWidget w;
    w.setGeometry(100,100,200,100);
    a.setMainWidget(&w);
    w.show();
    return a.exec(); 
 }




Per eseguire questo programma dovreste dare i seguenti comandi:
$QTDIR/bin/moc -o MyButton_moc.cc MyButton.h 
g++ -o MyButton MyButton.cpp MyButton_moc.cc -I$QTDIR/include -L$QTDIR/lib -lqt 
./MyButton       
In definitiva il trattamento degli eventi in Qt e' fatto in questo modo: ogni oggetto grafico ha un certo numero di segnali e slot predefiniti che all'atto dell'esecuzione sono "collegati" tra di loro.Il programmatore puo' scrivere i metodi che vuole per funzionare come "slot", ma l'informazione che puo' essere passata a queste slot e' solo quella fornita dai segnali che di solito non sono scritti dal programmatore.
Programma 5: Scrivete un programma dove un cursore permette di modificare le dimensioni di un rettangolo .S

    file MyButton.h


#include <qapplication.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qslider.h>
# include  <iostream>
# include  <string>
#include "MyCanvas.h"


class MyWidget : public QWidget 
{
   Q_OBJECT
 public:
   MyWidget (QWidget *parent=0, const char *name=0);
 signals:
 public slots: 
 private:
  QSlider *slider;
  MyCanvas *canvas;
};





    file MyButton.cpp


#include "MyButton.h"

 MyWidget::MyWidget(QWidget *parent, const char *name)
        : QWidget(parent,name)
 {
   slider = new QSlider(Horizontal,this,"slider");
   slider->setRange(0,99);
   slider->setValue(0);
   canvas = new MyCanvas(this,"MyCanvas");
   QGridLayout *grid = new QGridLayout( this, 2, 1, 10 );
   grid->addWidget( slider, 0, 0 );
   grid->addWidget( canvas, 1, 0 );
   QObject::connect(slider, SIGNAL(valueChanged(int)),canvas,SLOT(draw(int)));

 }

int main (int argc, char* argv[])
 {
    QApplication a(argc,argv);
    MyWidget w;
    w.setGeometry(100,100,200,100);
    a.setMainWidget(&w);
    w.show();
    return a.exec(); 
 }




    file MyCanvas.h


#ifndef MYCANVAS_H
#define MYCANVAS_H 
#include <qwidget.h>

class MyCanvas : public QWidget 
{
   Q_OBJECT
 public:
   MyCanvas (QWidget *parent=0, const char *name=0);
 signals:
 public slots: 
  void draw(int size);
 protected:
  void paintEvent(QPaintEvent *);
 private:
   int size;
};
#endif





    file MyCanvas.cpp


#include "MyCanvas.h"
#include <qpainter.h>

 

 MyCanvas::MyCanvas(QWidget *parent, const char *name)
        : QWidget(parent,name)
 {
  size=1; 
  setPalette( QPalette( QColor( 250, 250, 200) ) );

 }
 void MyCanvas::draw(int s){
  size = s;
   repaint();
  }
 void MyCanvas::paintEvent( QPaintEvent * )
{
    QPainter p( this );
    p.drawRect( 100, 100, size,size );
}


Programma 6: Modificate il programma precedente in modo da passare all'oggetto MyCanvas anche una stringa da scrivere nella finestra grafica. S

    file MyButton.h


#include <qapplication.h>
#include <qpushbutton.h>
#include <qmainwindow.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qslider.h>
# include  <iostream>
# include  <string>
#include "MyCanvas.h"


class MyWidget : public QWidget 
{
   Q_OBJECT
 public:
   MyWidget (QWidget *parent=0, const char *name=0);
 signals:
  void mysignal(int,string);
 public slots: 
  void myslot(int);
 private:
  QSlider *slider;
  MyCanvas *canvas;
   string s; 
   int size;
};

class MainWindow : public QMainWindow 
{
 public:
   MainWindow (QWidget *parent=0, const char *name=0);
 private:
   MyWidget *mw;
};




    file MyButton.cpp

#include "MyButton.h"

 MainWindow::MainWindow(QWidget *parent, const char *name)
        : QMainWindow(parent,name)
 {
    mw = new MyWidget(this,"MyWidget");
    setCentralWidget(mw);
 }
 MyWidget::MyWidget(QWidget *parent, const char *name)
        : QWidget(parent,name)
 {
   slider = new QSlider(Horizontal,this,"slider");
   slider->setRange(0,99);
   slider->setValue(0);
   canvas = new MyCanvas(this,"MyCanvas");
   QGridLayout *grid = new QGridLayout( this, 2, 1, 10 );
   grid->addWidget( slider, 0, 0 );
   grid->addWidget( canvas, 1, 0 );
   s = "Pinco Pallino";
   QObject::connect(slider, SIGNAL(valueChanged(int)),this,SLOT(myslot(int)));
   QObject::connect(this, SIGNAL(mysignal(int,string)),canvas,SLOT(draw(int,string)));

 }
void MyWidget::myslot(int x){
  size = x;
   emit mysignal(size,s);
  }



int main (int argc, char* argv[])
 {
    QApplication a(argc,argv);
    MainWindow *w = new MainWindow();;
    w->setCaption("Quadrato di dimensioni variabili");
    w->setGeometry(100,100,200,100);
    w->show(); 
    return a.exec(); 
 }




    file MyCanvas.h


#ifndef MYCANVAS_H
#define MYCANVAS_H 
#include <qwidget.h>
#include <string>

class MyCanvas : public QWidget 
{
   Q_OBJECT
 public:
   MyCanvas (QWidget *parent=0, const char *name=0);
 signals:
 public slots: 
  void draw(int size,string s);
 protected:
  void paintEvent(QPaintEvent *);
 private:
   int size;
   string nome;
};
#endif





    file MyCanvas.cpp


#include "MyCanvas.h"
#include <qpainter.h>
#include <qstring.h>

 

 MyCanvas::MyCanvas(QWidget *parent, const char *name)
        : QWidget(parent,name)
 {
  size=1; 
  setPalette( QPalette( QColor( 250, 250, 200) ) );

 }
 void MyCanvas::draw(int s,string str){
  size = s;
  nome=str;
   repaint();
  }
 void MyCanvas::paintEvent( QPaintEvent * )
{
    const char *c = nome.c_str();
    QString qnome(c) ;
    QPainter p( this );
    p.drawRect( 100, 100, size,size );
    p.drawText(10,10,qnome); 
}


Da 2D a 3D : OpenGL difficile ma veloce

OpenGl e' innanzitutto uno standard multipiattaforma per la grafica 3D che e' implementato anche a livello hardware dalle schede video.
OpenGL non definisce cose tipiche della grafica 2D come finestre od eventi e per questo per poterlo usare dobbiamo prima decidere a quale pacchetto 2D abbinarlo. Nel nostro caso useremo ovviamente Qt ma avremmo anche potuto usare GTK+ o X11,GLUT,SDL,etc... Su Linux e' di solito disponibile la libreria applicativa fornita da sourceforge:MEsa 3D Graphics Library.
Una semplice applicazione OpenGL opengl application Il dado con un'immagine presa da un file sulle varie faccie, ruota in continuazione.
file Makefile
# Makefile for Simple X11 OpenGL program.
GLDIR = /lhcxx/specific/redhat61/Mesa/3.2
CPP = g++
LIBDIR = -L$(GLDIR)/lib -L/usr/lib -L/usr/X11R6/lib
INCDIR = -I$(GLDIR)/include -I/usr/include -I/usr/X11R6/include
CFLAGS = $(INCDIR) $(LIBDIR)
XLIBS = -lX11 -lXext -lXmu -lXt -lXi -lSM -lICE
GL_LIBS = -lglut -lGLU -lGL -lm
PROGS = simple_x11
 
##### RULES #####
.cpp:   *.cpp
        $(CPP) $(CFLAGS) $< $(GL_LIBS) -o $@
 
##### TARGETS ######
 
default: $(PROGS) 

OpenInventor : facile ma lento

Negli esempi che seguono abbiamo usato la versione di OpenInventor fornita da TGS:questa non e' gratis ma esiste anche un'implementazione free source di OpenInventor chiamata Coin.
Qui il manuale.
Siccome si basa su OpenGL, possiamo pensare ad esso come un pacchetto applicativo 3D ad alto livello che ,come OpenGL, e' indipendente dalla piattaforma. L'aggiunta piu' importante ad OpenGL e' la definizione di un formato di file standard per la descrizione di scene 3D. Questo significa che se voi avete a disposizione un visualizzatore OpenInventor come iview potete,con OpenInventor, creare e visualizzare una scena 3D scrivendo un file ASCII che descrive la scena senza bisogno di scrivere programmi!
Semplice esempio e makefile necessario per farlo girare al Cern su macchine Linux.
Il modello su cui si basa lo sviluppo di applicazioni 3D in OpenInventor e' quello di creare delle scene mettendo insieme una serie di nodi. Un nodo puo' rappresentare una forma,un attributo,una telecamera,una luce,una trasformazione e altro.Una volta che i nodi sono stati raggruppati in una struttura gerarchica a formare una o piu' scene, e' possibile applicare azioni come rendering,picking(selezione),etc sia al singolo nodo che a intere scene.
A differenza di OpenGL che non ha il supporto di finestre, OpenInventor ha un supporto di tipo finestre incluso nel pacchetto e basato su Motif(per macchine Unix). Questo permette di scrivere dei programmi completi di grafica senza dover far ricorso a pacchetti esterni.
Un programma "CiaoATutti" OpenInventor potrebbe consistere di una finestra SoXtRenderArea nella quale inseriamo una semplice scena con una forma 3D SoCone,di un materiale SoMaterial illuminata da una SoDirectionalLight e vista da una telecamera SoPerspectiveCamera. I 4 nodi vengono tutti collegati a un oggetto SoSeparator che serve a creare la struttura.
#include <math.h>
#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/SoXtRenderArea.h>
#include <Inventor/nodes/SoCone.h>
#include <Inventor/nodes/SoDirectionalLight.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoPerspectiveCamera.h>
#include <Inventor/nodes/SoSeparator.h>
 
void
main(int , char **argv)
{
   // Initialize Inventor. This returns a main window to use.
   // If unsuccessful, exit.
   Widget myWindow = SoXt::init(argv[0]); // pass the app name
   if (myWindow == NULL) exit(1);  
   SoSeparator *root = new SoSeparator;
   SoPerspectiveCamera *myCamera = new SoPerspectiveCamera;
   SoMaterial *myMaterial = new SoMaterial;
   root->ref();
   root->addChild(myCamera);
   root->addChild(new SoDirectionalLight);
   myMaterial->diffuseColor.setValue(0.0, 1.0, 0.0);   //Green 
   root->addChild(myMaterial);
   root->addChild(new SoCone);
 
   // Create a renderArea in which to see our scene graph.
   // The render area will appear within the main window.
   SoXtRenderArea *myRenderArea = new SoXtRenderArea(myWindow);
 
   // Make myCamera see everything.
   myCamera->viewAll(root, myRenderArea->getViewportRegion());
 
   // Put our scene in myRenderArea, change the title
   myRenderArea->setSceneGraph(root);      
   myRenderArea->setTitle("Hello Cone");
   myRenderArea->show();
 
   SoXt::show(myWindow);  // Display main window
   SoXt::mainLoop();      // Main Inventor event loop
}                  
Se invece di usare la SoXtRenderArea usiamo una SoXtExaminerViewer abbiamo tutta una serie di gadget che ci permettono di manipolare la scena a nostro piacimento.


Programma 7: Create la scena col cono all'interno di SoXtExaminer .S

    file Prog2.cxx


#include <Inventor/SoDB.h>
#include <Inventor/SoInput.h>
#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/viewers/SoXtExaminerViewer.h>
#include <Inventor/nodes/SoSeparator.h>
#include <math.h>
#include <Inventor/nodes/SoCone.h>
#include <Inventor/nodes/SoDirectionalLight.h>
#include <Inventor/nodes/SoMaterial.h>
 



void
main(int argc, char **argv)
{
   // Initialize Inventor and Xt
   Widget myWindow = SoXt::init(argv[0]);

   if (myWindow == NULL) exit(1);  
   SoSeparator *root = new SoSeparator;
   SoMaterial *myMaterial = new SoMaterial;
   root->ref();
   root->addChild(new SoDirectionalLight);
   myMaterial->diffuseColor.setValue(0.0, 1.0, 0.0);   //Green 
   root->addChild(myMaterial);
   root->addChild(new SoCone);
 
 

   // Create a viewer
   SoXtExaminerViewer *myViewer = 
            new SoXtExaminerViewer(myWindow);

   // attach and show viewer
   myViewer->setSceneGraph(root);
   myViewer->setTitle("File Reader");
   myViewer->show();
    
   // Loop forever
   SoXt::show(myWindow);
   SoXt::mainLoop();
}
Il toolkit di OpenInventor contiene moltissimi oggetti grafici (tutti col nome che comincia con So) e questi possono essere estesi.
La stessa scena puo' essere poi definita con questo file Ascii:
#Inventor V2.0 ascii
                             Separator {
                             SpotLight {
                                 color 0.6 0.3 0.3
                                 location 5 10 0
                                 direction -1 -1 0
                             }
                                 Material {
                                     diffuseColor 0.8 0.0 0.8
                                     specularColor 0.3 0.0 0.3
                                     ambientColor 0.2 0.0 0.2
                                 }
                                 Transform {
                                     translation -1.0 1.5 1.0
                                 }
                                 Cone {}
 
                         }    
cono openinventor Ed ecco come appare la scena in un visualizzatore che l'ha letta dal file Ascii.


Programma 8: Definite una "casa" come una serie di facce e di linee nello spazio. Createne una seconda copia spostata e ruotata .S

    file casa.iv


#Inventor V2.1 ascii


		  DEF RPC_ Separator {

			 Material {
			  ambientColor 0 0 0
			  diffuseColor 0 0 0
			  specularColor 0.622 0.622 0.622
			  emissiveColor 0 1 1
			  shininess 0.121
			  transparency 0
			 }
                         ShapeHints {
			  shapeType SOLID
			 }
			 Coordinate3 {
			  point [ 0. 0. 13.5 ,
				   4. 0. 13.5 ,
				   4. 3. 13.5,
				   2. 4. 13.5,
				   0. 3. 13.5,
				   0. 0. 7.5,
				   4. 0. 7.5,
				   4. 3. 7.5,
				   2. 4. 7.5,
				   0. 3. 7.5,
				   1. 0. 13.5,
				   2. 0. 13.5,
				   2. 2. 13.5,
				   1. 2. 13.5]
			 }
			 IndexedFaceSet {
			  coordIndex [ 0 , 1 , 2, 3, 4, -1 ,5,6,7,8,9, 
				    -1 , 1,6,7,2 , -1 , 5,0,4,9,
				    -1 , 4,3,8,9 ,
				   -1 , 3,2,7,8, -1 ]
			 }
			 DrawStyle {
			  linePattern 0xffff
			 }
			 IndexedLineSet {
			  coordIndex [ 0 , 1 , 2, 3, 4, -1 ,5,6,7,8,9, 
				    -1 , 1,6,7,2 , -1 , 5,0,4,9,
				    -1 , 4,3,8,9 ,
				   -1 , 3,2,7,8, -1,10,11,12,13,-1 ]
			 }
			 		  		 }

    file casa2.iv


#Inventor V2.1 ascii


		   Separator {
                        SpotLight {
                                 color 0.6 0.3 0.3
                                 location 5 10 0
                                 direction -1 -1 0
                             }

			 Material {
			  ambientColor 0.2 0 0.2
			  diffuseColor 0.8 0 0.8
			  specularColor 0.3 0.0 0.3
			  emissiveColor 0 1 1
			  shininess 0.121
			  transparency 0
			 }
                         ShapeHints {
			  shapeType SOLID
			 }
			 Coordinate3 {
			  point [ 0. 0. 13.5 ,
				   4. 0. 13.5 ,
				   4. 3. 13.5,
				   2. 4. 13.5,
				   0. 3. 13.5,
				   0. 0. 7.5,
				   4. 0. 7.5,
				   4. 3. 7.5,
				   2. 4. 7.5,
				   0. 3. 7.5,
				   1. 0. 13.5,
				   2. 0. 13.5,
				   2. 2. 13.5,
				   1. 2. 13.5]
			 }
			 IndexedFaceSet {
			  coordIndex [ 0 , 1 , 2, 3, 4, -1 ,5,6,7,8,9, 
				    -1 , 1,6,7,2 , -1 , 5,0,4,9,
				    -1 , 4,3,8,9 ,
				   -1 , 3,2,7,8, -1 ]
			 }
			 DrawStyle {
			  linePattern 0xffff
			 }
			 IndexedLineSet {
			  coordIndex [ 0 , 1 , 2, 3, 4, -1 ,5,6,7,8,9, 
				    -1 , 1,6,7,2 , -1 , 5,0,4,9,
				    -1 , 4,3,8,9 ,
				   -1 , 3,2,7,8, -1,10,11,12,13,-1 ]
			 }
                         ResetTransform {
                         }
                         Transform {
                          translation 1.307 -7.049 -5.3295
                          rotation -1.09278e-08 -1.09278e-08 1  3.14159
                          scaleFactor 1 1 1
                          scaleOrientation -0.434027 0.17978 -0.88278  0.877436
                         }          
			 Coordinate3 {
			  point [ 0. 0. 13.5 ,
				   4. 0. 13.5 ,
				   4. 3. 13.5,
				   2. 4. 13.5,
				   0. 3. 13.5,
				   0. 0. 7.5,
				   4. 0. 7.5,
				   4. 3. 7.5,
				   2. 4. 7.5,
				   0. 3. 7.5,
				   1. 0. 13.5,
				   2. 0. 13.5,
				   2. 2. 13.5,
				   1. 2. 13.5]
			 }
			 IndexedFaceSet {
			  coordIndex [ 0 , 1 , 2, 3, 4, -1 ,5,6,7,8,9, 
				    -1 , 1,6,7,2 , -1 , 5,0,4,9,
				    -1 , 4,3,8,9 ,
				   -1 , 3,2,7,8, -1 ]
			 }
			 DrawStyle {
			  linePattern 0xffff
			 }
			 IndexedLineSet {
			  coordIndex [ 0 , 1 , 2, 3, 4, -1 ,5,6,7,8,9, 
				    -1 , 1,6,7,2 , -1 , 5,0,4,9,
				    -1 , 4,3,8,9 ,
				   -1 , 3,2,7,8, -1,10,11,12,13,-1 ]
			 }
			 		  		 }



Programma 9: Definite la stessa casa del programma 2 in OpenGL facendola ruotare in continuazione .S

    file Prog1.cpp


	
#include <iostream.h>
	
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>


GLfloat casa[14][3]={
	{0.,0.,13.5}, 
	{4.,0.,13.5},
	{4., 3., 13.5},
	{2.,4.,13.5},
	{0.,3.,13.5}, 
	{0.,0.,7.5},
	{4.,0.,7.5},
	{4.,3.,7.5},
	{2.,4.,7.5},
        {0.,3.,7.5}, 
         {1.,0.,13.5},
          {2.,0.,13.5},
          {2.,2.,13.5},
          {1.,2.,13.5} };


int faceRefs[6][5]= {
	{0, 1, 2, 3,4},
	{5, 9, 8, 7, 6},
	{1, 6, 7, 2,-1},
	{5, 0, 4, 9,-1},
	{4, 3, 8, 9,-1},
	{3, 2, 7, 8,-1} };


void buildCasaList(void)
{
	GLfloat x, y, z;
	

	glNewList(1, GL_COMPILE);

			for (int i=0; i<6; i++) {
		               glBegin(GL_POLYGON);
				x=casa[faceRefs[i][0]][0];
				y=casa[faceRefs[i][0]][1];
				z=casa[faceRefs[i][0]][2];
				glVertex3f(x, y, z);
				x=casa[faceRefs[i][1]][0];
				y=casa[faceRefs[i][1]][1];
				z=casa[faceRefs[i][1]][2];
				glVertex3f(x, y, z);
				x=casa[faceRefs[i][2]][0];
				y=casa[faceRefs[i][2]][1];
				z=casa[faceRefs[i][2]][2];
				glVertex3f(x, y, z);
				x=casa[faceRefs[i][3]][0];
				y=casa[faceRefs[i][3]][1];
				z=casa[faceRefs[i][3]][2];
				glVertex3f(x, y, z);
                                if(faceRefs[i][4] != -1){
				x=casa[faceRefs[i][4]][0];
				y=casa[faceRefs[i][4]][1];
				z=casa[faceRefs[i][4]][2];
				glVertex3f(x, y, z);
                                }
		               glEnd();	
			}
	glColor3f(1.0f,0.0f,0.0f);
            glBegin(GL_QUADS);
		x=casa[10][0];
		y=casa[10][1];
		z=casa[10][2];
                glVertex3f(x,y,z);
		x=casa[11][0];
		y=casa[11][1];
		z=casa[11][2];
                glVertex3f(x,y,z);
		x=casa[12][0];
		y=casa[12][1];
		z=casa[12][2];
                glVertex3f(x,y,z);
		x=casa[13][0];
		y=casa[13][1];
		z=casa[13][2];
                glVertex3f(x,y,z);
               glEnd();


	glEndList();	
}

void renderScene(void)
{
	glClearColor(0.0, 0.0, 0.0, 1.0);

	glClear(GL_COLOR_BUFFER_BIT);

	glColor3f(0.0, 0.0, 1.0);

	glCallList(1);

	glFlush();

	glutSwapBuffers();
}

void reshapeFunction(int width, int height)
{

	glViewport(0, 0, (GLint)width, (GLint)height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
    
	glOrtho(-20.5, 20.5, -2.5, 15.5, 50.0, -50.0);
    
	glMatrixMode(GL_MODELVIEW);
}

void idleFunction(void)
{

	glRotatef(0.1f, 0.0, 1.0, 1.0);

	renderScene();
}


int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(200, 200); 
	glutInitWindowPosition (100, 100);
	
	glutCreateWindow("Casa");
	glutReshapeFunc(reshapeFunction);
	
	
	buildCasaList();
	glutDisplayFunc(renderScene);
	glutIdleFunc(idleFunction);
	 
	glutMainLoop();
	
	return 0;  
}



Programma 10: Usate un cursore Qt per ingrandire un cubo OpenInventor. S

    file MyCube.h


#include <qapplication.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qslider.h>
# include  <iostream>
# include  <string>
# include "My3DCanvas.h" 


class MyWidget : public QWidget 
{
   Q_OBJECT
 public:
   MyWidget (QWidget *parent=0, const char *name=0);
 signals:
 public slots: 
 private:
  QSlider *slider;
  My3DCanvas *canvas;
};





    file MyCube.cpp

 
#include "MyCube.h"

 MyWidget::MyWidget(QWidget *parent, const char *name)
        : QWidget(parent,name)
 {
   slider = new QSlider(Horizontal,this,"slider");
   slider->setRange(0,99);
   slider->setValue(0);
   QGridLayout *grid = new QGridLayout( this, 2, 1, 10 );
   My3DCanvas *canvas = new My3DCanvas(this,"cube");
   grid->addWidget( slider, 0, 0 );
   grid->addWidget( canvas, 1, 0 );
   QObject::connect(slider, SIGNAL(valueChanged(int)),canvas,SLOT(draw(int)));

 }

int main (int argc, char* argv[])
 {
    QApplication a(argc,argv);
    MyWidget w;
    w.setGeometry(100,100,400,400);
    a.setMainWidget(&w);
    w.show();
    return a.exec(); 
 }




    file My3DCanvas.h


#ifndef MY3DCANVAS_H
#define MY3DCANVAS_H 
#include <qwidget.h>
#include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
#include <Inventor/nodes/SoSeparator.h>  
#include <Inventor/nodes/SoCube.h>  

class My3DCanvas : public QWidget 
{
   Q_OBJECT
 public:
   My3DCanvas (QWidget *parent=0, const char *name=0);
 signals:
 public slots: 
  void draw(int size);
 private:
   int size;
    SoQtExaminerViewer *eviewer;
    SoSeparator *root;
    SoCube *cube1;
};
#endif





    file My3DCanvas.cpp


#include "My3DCanvas.h"
#include <Inventor/Qt/SoQt.h>
#include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
#include <Inventor/nodes/SoCube.h>  
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoDirectionalLight.h>
#include <Inventor/nodes/SoMaterial.h>

 My3DCanvas::My3DCanvas(QWidget *parent, const char *name)
        : QWidget(parent,name)
 {
  size=1; 
  SoQt::init(this);
  eviewer = new SoQtExaminerViewer(this);
  root = new SoSeparator;
  SoCube *mycube = new SoCube;
   SoMaterial *myMaterial1 = new SoMaterial;
   mycube->width = 400;
   mycube->height =400;
   mycube->depth =400 ;
   myMaterial1->diffuseColor.setValue(1.0, 0.0, 0.0);
   myMaterial1->transparency = 1.0;
   root->addChild(myMaterial1);
   root->addChild(mycube);      
   SoMaterial *myMaterial = new SoMaterial;
   root->ref();
   root->addChild(new SoDirectionalLight);
   myMaterial->diffuseColor.setValue(0.0, 1.0, 0.0);   //Green 
   root->addChild(myMaterial);
  cube1 = new SoCube;
   cube1->width = size;
   cube1->height =size;
   cube1->depth =size ;
   root->addChild(cube1);
  eviewer->setSceneGraph(root);
  eviewer->show();  

 }
 void My3DCanvas::draw(int s){
  size = s;
   root->enableNotify(FALSE);
   cube1->width = size;
   cube1->height =size;
   cube1->depth =size ;
   root->enableNotify(TRUE);
   root->touch();
  }








INDIETRO a Imparate C++ in una settimana
INDIETRO a Da Java al C++
Maintained by Giuseppe Zito: info@zitogiuseppe.com
Ultimo aggiornamento: