Il seguente programma consente di modellare solidi utilizzando le OpenGL, e ruotarne la posizione nello spazio. Utilizzando la libreria GLEXT e GLU.
#include <windows.h> // File intestazione necessario
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glext.h>
HDC hDC=NULL; // GDI privato
HGLRC hRC=NULL; // Contesto di rendering
HWND hWnd=NULL; // Gestisce la finestra
HINSTANCE hInstance; // Gestisce istanza
bool tasti[256]; // Vettore per le routine tastiera
bool attivo=TRUE; // Flag per la finestra attiva
bool schermopieno=TRUE; // Flag per lo schermopieno
GLfloat rtri; // Angolo per i triangoli
GLfloat rquad; // Angolo per i quadrati
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Dichiarazione di WndProc
GLvoid RidimensioneScenaGL(GLsizei larghezza, GLsizei altezza) // Ridimensiona ed inizializza GL Window
{
if (altezza==0) // Previene divisione per 0
{
altezza=1;
}
glViewport(0,0,larghezza,altezza); // Reset dello schermo corrente
glMatrixMode(GL_PROJECTION); // Seleziona la matrice di proiezione
glLoadIdentity(); // Azzera la finestra Matrice
// Calcola l'aspetto della finstra e le sue dimensioni
gluPerspective(100.0f,(GLfloat)larghezza/(GLfloat)altezza,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Seleziona la matrice del Modelview
glLoadIdentity();
}
int InizGL(GLvoid) // Impostazioni per OpenGL
{
glShadeModel(GL_SMOOTH); // Abilita ombreggiatura
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Schermo a sfondo nero
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return TRUE; // Inizializzazione OK
}
int DisegnaScenaGL(GLvoid) // Qui vi sono le istruzioni di disegno
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);
glRotatef(rtri,0.0f,1.0f,0.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd(); // Disegno della Piramide
glLoadIdentity();
glTranslatef(1.5f,0.0f,-6.0f);
glRotatef(rquad,1.0f,1.0f,1.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f); // Disegno del cubo
glEnd();
glLoadIdentity();
glTranslatef(5.5f,0.0f,-8.0f);
glRotatef(rquad*2,1.0f,0.0f,0.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f );
glVertex3f(-1.0f,-1.0f, 1.0f );
glVertex3f( 1.0f,-1.0f, 1.0f );
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f );
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f); // Disegno della scatola
glEnd();
rtri+=0.2f; // Aumenta la rotazione per il triangolo
rquad-=0.15f; // Diminuisce la rotazione per il quadrato
return TRUE; // Continua...
}
In questo blog si parla di programmazione con il linguaggio C++, i post cercheranno di essere molto esplicativi sull'argomento trattato.
Visualizzazione post con etichetta costruttore. Mostra tutti i post
Visualizzazione post con etichetta costruttore. Mostra tutti i post
domenica 10 febbraio 2013
venerdì 28 dicembre 2012
Uso dell'operatore di Assegnazione sovraccaricato e costruttore Copia nelle classi derivate
E' già stato spiegato come scrivere un operatore di
assegnazione sovraccaricato e un costruttore copia per una classe.
Tuttavia, scriverli per una classe derivata richiede un leggero
lavoro ulteriore in quanto non sono ereditati dalla classe di base.
Quando si sovraccarica l'operatore di assegnazione nelle classi
derivate, di solito si richiama l'operatore di assegnazione delle
classi base, utilizzando una chiamata esplicita con il nome della
classe di base quale prefisso. Se Capo è derivato da Nemico,
la funzione dell'operatore di assegnazione definita in Capo di
solito recita:
Capo& operator=(const
Capo& b)
{ Nemico::operator=(b);
//gestisce i dati membro ereditati da Nemico
// di seguito bisogna
gestire i dati membro di Capo }
La chiamata esplicita dell'operatore di assegnazione
di Nemico gestisce i dati membro ereditati da esso. Ma il
resto della funzione deve occuparsi dei dati definiti in Capo.
Per il costruttore Copia, di solito si effettua una chiamata
al costruttore Copia della classe di base. Se Capo è
derivato da Nemico, il costruttore di copia definito in esso,
si scrive:
Capo (const Capo& b):
Nemico(b){
// si gestiscono i dati
membro definiti in Capo }
Dalla chiamata del costruttore Copia di Nemico
con Nemico(b), la copia dei
dati membro di Nemico viene messa nel nuovo oggetto Capo.
Nel resto della funzione di Capo
del costruttore copia si bada a tutti i dati membro dichiarati solo
in Capo del nuovo
oggetto.
lunedì 3 dicembre 2012
Definire un Costruttore Copia
A volte gli oggetti vengono ricopiati
automaticamente. Questo accade quando:
- Un oggetto passa un valore ad una funzione
- Un oggetto restituisce un valore da una funzione
- Inizializza un altro oggetto attraverso un inizializzatore
- Fornisce un singolo argomento al costruttore dell'oggetto
La copia viene effettuata attraverso una speciale
funzione membro chiamata costruttore copia. Come
i costruttori e i distruttori, una copia di default viene fornita se
non scritta appositamente per l'oggetto. La copia di default
semplicemente copia i valori di ogni dato membro a dati membro dello
stesso nome nel nuovo oggetto. Per le classi più semplice il
costruttore copia di default è più che sufficiente. Comunque quando
si ha una classe con dati membro che puntano ad un valore su heap,
solitamente viene scritto un proprio costruttore copia. La ragione è
che il costruttore di default si limiterebbe a copiare i puntatori
senza modificarne il contenuto, generando così una copia
vuota, per la quale i blocchi di
memoria non sono cambiati e puntano alle stesse locazioni
dell'oggetto originale. Per fare un esempio specifico. Se non fosse
stato scritto un proprio costruttore copia nel programma Dati membro
su Heap, il programma
avrebbe automaticamente creato una copia di ctopo
chiamata copia che esiste in testCopiaCostruttore().
testCopiaCostruttore(ctopo);
Il dato membro
m_pNome di copia
avrebbe puntato esattamente allo stesso oggetto string
su heap di ctopo
m_pNome. Perché si crea un
problema?
Al termine della
funzione testCopiaCostruttore(), il distruttore di copia viene
chiamato, liberando la memoria su heap alla
quale puntava il dato membro m_pNome
di copia. A causa di ciò ctopo
m_pNome avrebbe
puntato ad una memoria libera pertanto il dato membro si sarebbe
trasformato in un puntatore appeso. Ciò di cui si ha veramente
bisogno nel costruttore copia è di produrre un nuovo oggetto con il
proprio segmento di memoria su heap
alla quale puntare, una copia profonda.
Questo è quello che viene fatto con la seguente definizione del
costruttore copia, il quale sovraccarica il default fornito dal
compilatore.
Roditore(const Roditore&
c)
{ cout << “Copia
costruttore”;
m_pNome = new string;
*m_pNome = c.DaiNome();
}
Così come il
primo, anche in costruttore copia
deve avere lo stesso nome della classe, e non restituisce alcun
valore, ma accetta un riferimento ad un oggetto della classe,
l'oggetto che deve essere copiato. Il riferimento è quasi sempre una
costante che protegge l'oggetto originale dall'essere modificato
durante il processo di copia. Quando viene chiamato
testCopiaCostruttore() passando
ctopo come valore
della funzione, viene richiamato il costruttore copia.
Appare la scritta Costruttore Copia sullo schermo; quindi viene
creato un nuovo oggetto Roditore (la copia) che accetta i riferimenti
originali in c. Con la linea m_pNome = new string;
il costruttore alloca un nuovo blocco di memoria su heap
al quale punta m_pNome
dato membro per la copia. Nella riga successiva *m_pNome
=c.DaiNome(); il costruttore
copia acquisisce una copia dell'oggetto stringa che equivale a
“Topolino” dall'originale scrivendolo sul nuovo blocco di
memoria. Come risultato una copia profonda di ctopo
viene creata, quella usata in testCopiaCostruttore().
Quando testCopiaCostruttore()
termina, la copia del Roditore
usata dalla funzione viene distrutta, lasciando l'oggetto originale
al suo posto su heap.
Iscriviti a:
Post (Atom)