Ogni qual volta un nota azienda sforna un prodotto che fa della non-libertà il suo cavallo di battaglia e una valanga di persone accorre ad acquistare e ad osannare il sommo leader, mi chiedo che fine faranno le libertà digitali. Non voglio parlare del prodotto in se; non l’ho usato e non voglio scadere nel solito post criticone e di parte. Voglio affrontare un problema più vasto.

Per prima cosa dobbiamo dare a Cesare quel che è di Cesare. Che tali prodotti siano affascinanti e funzionanti è senza ombra di dubbio soprattutto se paragonati a quel trattore a pedali che è Windows. Oltretutto basta cercare fra i temi più scaricati in Gnome-Look per rendersi conto a quale sistema si ispirano i temi nelle prime posizioni. Anche le ultime scelte di sviluppo e restyling grafico di Ubuntu proposte dal “vendicatore solitario” Mark Shuttleworth puntano sempre più vistosamente in quella direzione.

C’è quindi un forte desiderio di imitazione, desiderio che a volte mi fa pensare se non sia che molte persone usino GNU/Linux solamente perché non possono permettersi gli attrezzi ultra-costosi della mela.

In questo spazio dove trovano spazio le libertà digitali? Perché ci deve essere qualcuno al di sopra degli utenti che deve decidere che cosa posso o non posso fare con un oggetto che ho comprato? Ci vengono a dire che lo fanno per questioni di sicurezza. Una giustificazione terribilmente insensata: sarebbe come un frigorifero che si rifiutasse di tenere al fresco alimenti poco salutari o come vietare la vendita di fertilizzanti per evitare che qualche malintenzionato li usi per fabbricare degli esplosivi. Tale “censura” inoltre viene applicata in triplice via: tramite incomprensibili limitazioni hardware (vedi la mancanza di una porta USB nell’ultima tavolozza), tramite SDK inutilmente mutilate e, dulcis in fundo, tramite dissennate e severe censure nello store.

La prima è piuttosto evidente. Conosciamo tutti le carenze che vengono riscontrate ad ogni rilascio di qualche attrezzo del genere. Carenza sempre sminuite dal “non c’è… tanto non la uso”. Frase pronunciata in continuazione prima di rimangiarsi tutto quando nella versione successiva tale funzione viene magicamente integrata. A quel punto serve, è utile e bella.

La seconda invece è molto subdola e costringe gli sviluppatori a fare i salti mortali per simulare una funzione che, per qualche strano motivo, è vietata dalle SDK. Tanto per dirne una: il tethering esplicitamente vietato del primo telefono “melenso” (non so se sia ancora così).

La terza invece è del tutto aberrante. Il solo pensiero che sia un gruppo di persone non meglio identificato a decidere quale software è possibile installare e quale no è qualcosa che non concepisco. Prendiamo ad esempio il caso dell’applicazione podcaster, piccola applicazione per gestire i podcast, di cui è stata vietata la vendita perché iTunes svolge le medesime funzioni. Oltre il madornale conflitto di interessi appare chiaro che è una palese violazione di una libertà digitale. Perché non posso usare quel programma se a me iTunes fa schifo? Non si sa. Vuolsi così colà dove si puote / ciò che si vuole, e più non dimandare. Punto.

Censure tanto abominevoli quanto le risposte estremamente demagogiche del tipo:

Siamo stati sommersi dalle lamentele soprattutto di clienti donne che trovavano il contenuto di molte applicazioni degradante e discutibile, ma anche di genitori preoccupati di quello che potevano vedere i loro figli.

Apple tiene in piena considerazione gli sviluppatori, ma prima di loro vengono le famiglie e i bambini.

Come se non fossero sufficienti i meccanismi di parental control (e senza contare che se ad un bambino in età prepuberale regali un telefono da 500€ meriti la galera).

Per capire meglio l’infondatezza di alcune motivazioni tenete presente che anche i repository delle più famose distribuzioni GNU/Linux compiono severissime selezioni prima di inserire un software all’interno del proprio sistema di distribuzione. Chiunque abbia mai provato ad inserire una propria applicazione all’interno dei repo ufficiali di Debian sa quanta severità e quanta inutile burocrazia bisogna seguire. Ma tutto questo iter è necessario per garantire la presenza di software affidabili: non viene in alcun modo impedito l’accesso di un programma per ragioni “etiche” o per motivazioni concorrenziali.

Mi chiedo quindi come sia possibile non rendersi conto che il prezzo da pagare va ben oltre il già caro prezzo da pagare al negoziante di fiducia? Il potere più forte che abbiamo non è il voto: è il boicottaggio ed io, nel mio piccolo, lo faccio a 360 gradi.

Quando ho deciso di passare a GNU/Linux l’ho fatto anche per questo. Per riacquistare la mia libertà, per liberarmi di DRM e altre volgarità digitali, abbracciare l’idea che l’uomo debba lavorare per l’uomo e, soprattutto, per non dare più un centesimo ad aziende che, giustamente, curano solamente i loro interessi. Perché è ovvio che delle aziende del genere non fanno dei prodotti per “il bene dell’umanità”.

A questo punto torniamo alla domanda principale: che fine fanno le libertà digitali? Secondo me vivono e continueranno a vivere finché ci sarà qualcuno a crederci. Vivranno finché ci saranno persone che non si arrenderanno a quella che sembra “l’evidenza dei fatti”. Nonostante il circo dei media si occupi sempre del nuovo giocattolo luminescente di turno.

“Fa più rumore un albero che cade che una foresta che cresce” diceva qualcuno. Io, nel mio piccolo, penso proprio di far parte della foresta.

 

Avendo per le mani due piccole idee e dedicandomi a programmarle sono 6 giorni che ho poco tempo per scrivere articoli di un certo spessore tecnico. Nonostante ciò posso ancora deliziarvi con inutili baggianate della serie “posso benissimo vivere anche senza”. Tuttavia questo offre la casa e questo vi tenete. :D

Volevo infatti mostrarmi una piccola immagine molto comoda se siete soliti usare simboli particolari. Rappresenta infatti, in breve, tutti i caratteri tipografici che potete scrivere utilizzando semplicemente alcune piccole combinazioni di tasti utilizzando la vostra classica tastiera su linux.

L’immagine è molto comoda e, se ne avete bisogno, vi consiglio di stamparla e appendervela al muro.

Non è una novità per chi usa linux da tempo ma visto che molti nuovi utenti spesso non lo sanno ho pensato che magari era idea gradita.

 

In e C/C++ si ha la convenzione di suddividere il codice all’interno di due file: i file .h per le dichiarazioni e .cpp o .c. Le motivazioni di questa scelta, in realtà, vanno oltre il semplice vezzo stilistico. Tale suddivisione permette infatti una profonda modularità del software e una rudimentale forma di information-hiding. I vari moduli (cpp) quando richiamano un altro modulo (tramite include) vengono a conoscenza solamente delle dichiarazioni delle funzioni e mai della loro implementazione. Implementazione che, inoltre, non gli servirebbe a nulla.

Capita così che il novello programmatore C++ (nostro ormai noto compagno di avventure), conscio di questa convenzione, inizia a scrivere le sue classi con disinvoltura. Suddivide tutte le sue classi con cura ma pecca di solerzia: divide anche le classi template.

Le classi template sono delle classi che hanno uno (o più) tipi parametrizzati. Supponiamo infatti di voler scrivere una struttura dati (ad esempio un array)per organizzare Pere. Poi decidiamo di scrivere una struttura dati analoga solo per gestire Autoradio. Ci rendiamo conto che la struttura fondamentale delle due classi è la stessa. Senza template dovremmo scrivere due classi differenti mentre con le classi template ci basta farne una parametrizzata. Vediamo un esempio:

template
class MyArray
{
         std::vector data;
      public:
         void Add(T  *d);
         void Remove();
         void Print();
};

Come potete notare all’interno di questo scheletro di classe il tipo gestito non è esplicito ma indicato da un segnaposto T. Quando inizializziamo una nuova coda non ci resta che inizializzarla specificando il tipo parametrizzato, ad esempio in questo modo:

MyArray<Pere> lista_pere = new MyArray<Pere>

Ma come funziona questo artificio stregonesco? Molto semplice: in pratica è il compilatore che si incarica di scrivere le classi differenti basandosi sullo scheletro che voi avete dato.

Ed è proprio qui che cade la magagna! A causa di ciò, infatti, le classi template non possono essere divise in file .h e .cpp. se lo fate noterete che il vostro linker inizierà a lamentarsi vistosamente dicendovi che non esiste nessun MyArray<Pere>.

Il motivo di questo comportamento è logico se ci pensate. Supponiamo di avere diviso il nostro template in due file: MyArray.h e MyArray.cpp. Supponiamo poi di utilizzare il nostro template nel file Fruttivendolo.cpp. A questo punto compiliamo:

  1. Compiliamo tranquillamente il nostro template generando il file compilato MyArray.o.
  2. A questo punto andiamo a compilare Fruttivendolo.cpp.
  3. Come abbiamo detto prima il compilatore nota la riga
    MyArray<Pere>

    e quindi “costruisce” la classe corrispodente.

  4. Ma il file Fruttivendolo.cpp può vedere solo MyArray.h perché è il solo file incluso!

A questo punto il compilatore si porge giustamente la domanda: come faccio a compilare la classe MyArray<Pere> se non conosco come sono implementati i metodi del template MyArray.h?

Infatti non lo fa. Ignora il tutto lasciando il compito al linker e sperando che esso trovi da qualche parte un aggancio ad una classe MyArray<pere> che, come è giusto che sia, non trova.

Come risolvere il problema? La soluzione più semplice è di scrivere tutto (dichiarazione più implementazione) tutto nel file header. Tuttavia noi vogliamo mantenere una certa omogeneità nel codice e vogliamo quindi mantenere la divisione!

Per questo ci sono tre soluzioni accettabili. Ovviamente ognuna hai suoi vantaggi e svantaggi e sta a voi scegliere quale sia la migliore per la vostra esigenza:

  1. Nel file .h aggiungere alla fine la riga #include MyArray.cpp. In questo modo viene simulata la scrittura “tutto in uno” pur mantenendo la suddivisione del file. Ovviamente in questo caso nel file .cpp NON VA INCLUSO IL FILE .h per evitare un inclusione ciclica. Questa soluzione ha lo svantaggio di “gonfiare” il codice compilato nel caso lo stesso template venga utilizzato in parecchi file.
  2. Una soluzione alternativa è di definire tutte le funzioni come inline. Anche qui abbiamo gli stessi svantaggi del caso precedente (forse sono anche peggio).
  3. La terza soluzione è l’ideale se sapete da subito quali sono i tipi di dato con cui utilizzerete il template. In questo caso vi basta aggiungere in fonfo al file .cpp la riga
    template class MyArray<Pere>;

    per forzare la compilazione del template per quei tipi particolari. A questo punto il linker troverà sicuramente una versione già compilate della classe che è stata appena chiamata.

Spero che questa piccola note, spesso trascurata quando si parla di template, vi faccia risparmiare tutto il tempo che ha fatto perdere a me a suo tempo.

Buon coding! :D

 

Stavo attrezzando un piccolo progettino scemo sulle OpenGL (più didattico che altro) e così ho pensato di condividere quelle regole non scritte che servono ad organizzare e gestire un progetto software. Sono piccole “tips”, struttura delle cartelle e file che non devono mai mancare. Presenterò anche altri strumenti, come ho fatto per Python, ma questa volta saranno strumenti “generici”, ovvero utilizzabili con qualunque linguaggio.

Questo perché tenere in piedi un progetto male organizzato è come costruire un castello di carta. Ci vuole una base forte per rendere il più accogliente possibile il progetto per le persone interessate a collaborare, sia per i membri del vostro team (se ne avete uno).

STRUTTURA CARTELLE

Le cartelle vanno organizzate in modo piuttosto coerente. È importante non mischiare tutto in poche cartelle confuse specialmente per progetti destinati a crescere rapidamente. Una struttura minimale è la seguente:

  • src – La cartella src contiene il codice sorgente. Il codice al suo interno può essere organizzato come si desidera in accordo con le convenzioni del linguaggio. L’importante è che contenga solamente il codice del programma/libreria.
  • test – La cartella test contiene il codice sorgente dedicato ai test. Il codice di test serve a provare il corretto funzionamento delle classi sviluppate o di alcuni moduli software oppure possono essere semplicemente test prestazionali.
  • build – La cartella build contiene tutti i file ottenuti come residuo di una compilazione. Possono essere moduli parziali C/C++ (.o), classi Java (.class), file python compilati (.pyc) e così via. La cartella va a sua volta divisa nelle varie configurazioni di compilazione (ad esempio ci potrebbe essere una configurazione Debug con compilati ottimizzati per il debug e una configurazione Release con compilati ottimizzati per le prestazioni).
  • dist – La cartella dist contiene il prodotto finito. Può essere il programma eseguibile, un file .jar, una libreria .so e così via. Tutto quello che sta in dist deve essere pronto per essere eseguito e distribuito.
  • doc – La cartella doc contiene la documentazione dettagliata. Tale documentazione è per lo più la specifica dettagliata delle API la quale è solitamente auto-generata.

FILE MUST

Nella cartella radice sono necessari alcuni file. Necessari è una parola grossa in quanto solitamente il programma funziona benissimo anche senza, ma sono un tocco di classe e di umanità verso chi vuole accedere ai sorgenti della vostra applicazione.

  • Tool di compilazione - Sia Makefile, o Cmake o qualunque altro tool utilizzate… DEVE esserci uno strumento per la configurazione e la compilazione. Molti IDE possono anche auto-generare roba simile.
  • README – Il readme deve dire vita morte e miracoli sull’applicazione. Deve spiegare come può essere compilata  l’applicazione, quali sono le dipendenze, i bug noti, etc..
  • README.src – Per applicazioni il cui README è eccessivamente complesso è bene separare le informazioni per sviluppatori in un file a parte. Il file README.src deve spiegare come è organizzato il codice, quale IDE si è usato (se si è usato), quale librerie di sviluppo servono, quale strumenti si sono usati per generare la documentazione, per i test e per altro. Insomma… tutto ciò che può essere utile per chi è interessato alla modifica del codice.
  • COPYRIGTH - Il file che contiene le informazioni sulla licenza del progetto.
  • CHANGELOG – Il file che contiene la lista dei cambiamenti apportati al programma nel corso della sua storia. Questo file può essere auto-generato da alcuni sistemi di CVS.

DOCUMENTAZIONE

Scrivere a mano la documentazione è sempre l’ultimo dei problemi. Nonostante ci siano molte cose che debbano necessariamente essere scritte a mano, per le API è possibile usare dei tools automatici. Abbiamo visto Epydoc per python. Bene, per tutto il resto c’è Doxygen. Doxygen è un programma di auto-generazione della documentazione utilizzabile per una miriade di linguaggi.

CVS

Il programma per CVS è essenziale se programmate in gruppo ma è molto utile anche se programmate da soli. Vi permette di manipolare il codice con molta disinvoltura navigando fra branch diversi in modo del tutto trasparente.

Potete usare quello che vi pare come CVS anche se io consiglio sempre GIT. Lo trovo molto più veloce ed elastico dei concorrenti. Se volete convincervi potete sempre andare su http://it.whygitisbetterthanx.com/ :D

MESSAGGISTICA

Ebbene si. Se avete un gruppo di persone con cui lavorate insieme non potete prescindere da un sistema rapido e veloce per lo scambio di informazioni, siano esse “OMG! Non funziona una cippa!” o messaggi più tecnici.

A questo punto avete le basi. Non vi resta che seguire questi consigli e lanciarvi nel tempestoso mondo del software libero sperando che il vostro progetto non sia un castello di carte spazzato via dal vento.

 

So che lo state pensando. “Oh no! Un altra GUI per Git! Che dio ci scampi!”. Effettivamente di gui per git ce ne sono a valanghe. Ognuna con i suoi vantaggi e svantaggi. Però Gitg ha qualcosa che te la fa preferire. Innanzitutto è ben integrato con GNOME, secondo ha una velocità impressionante nel caricare repository di enormi dimensioni (dall’immagine potete vedere che carica più di 17.000 commit in meno di un secondo).

E poi è graficamente gradevole con i suoi colori e amenità varie. E questo non guasta mai. :D

Il programma è disponibile nei repo ufficiali di Lucid ma vi consiglio di usare la versione 0.0.6 che invece trovate nei repo di Maverik. Potete prenderla direttamente da la, non ci sono problemi.

Unica pecca il supporto ai repository remoti non ancora completo.

Se vi capita provatelo. Buon sabato.

 

Supponiamo di aver studiato a fondo un linguaggio di programmazione, anche due, anche tre o come me che, per forza o per diletto, conosco ad alto livello la grammatica di almeno 4-5 linguaggi (C/C++, Java, Python e Scheme). Supponiamo che abbiamo consumato la nostra ragione e la nostra tastiera in esempi e piccoli progetti personali.

Adesso siamo pronti. Pronti per affacciarci nel meraviglioso mondo dell’Open Source! Dove chiunque può collaborare al progetto che più lo aggrada oppure può inserire il loro piccolo progetto all’interno del mare di progetti liberi e aperti alla collaborazione globale!

O no?

Beh non proprio. O meglio… funziona così almeno in teoria. La pratica, d’altro canto, è una specie di incubo.

PROGETTO PERSONALE O COLLABORAZIONE?

Non c’è nulla di più stimolante ed istruttivo che programmare in gruppo. Il gruppo diminuisce il carico di lavoro, velocizza l’apprendimento di librerie e triplica le idee. Sfortunatamente formare un gruppo solido necessita di parecchia fatica.

Il primo dubbio per il novello collaboratore è: porto avanti un mio innovativo progetto o collaboro ad un progetto già esistente? Il problema dei progetti personali è che raramente sono innovativi e non sempre si ha un idea carina in testa. Quindi perché aggiungere, ad esempio, un player audio nel campo già saturo dei player audio?

Partecipiamo ad un progetto allora! Scegliamone uno nel marasma dei progetti esistenti, leggiamo alcune piccole faq e ci scarichiamo anche i sorgenti. Poi il nulla.

Si perché conoscere un linguaggio, anche nelle sue formule più arcane, non ci da nessuna mano per affrontare un progetto vero e proprio, allo stesso modo di come saper usare somma, sottrazione, moltiplicazione e divisione non ci rende automaticamente matematici esperti. Ogni progetto, infatti, usa le sue librerie, a volte tali librerie sono “personalizzate”, sono strutturate in modi particolare, etc.. etc… con il risultato che il novello collaboratore rimarrà per minuti a fissare il codice sorgente con la faccia a punto interrogativo perenne. Finché desiste.

I punti critici qui sono due: scarsa conoscenza delle librerie specifiche e scarsa documentazione del codice. Il primo è inevitabile, nessuno può conoscere tutte le librerie esistenti (siano esse le OpenGL, o l’interfacciamento a gstreamer o a Xine o qualunque altra cosa vi venga in mente) e spesso un progetto di media complessità ne utilizza anche due-tre insieme. Il secondo invece è dovuto da una scarsa apertura degli sviluppatori del progetto.

Progetti piccoli sono solitamente scarsamente documentati mentre progetti grandi sono (per le loro natura di “grandi”) estremamente documentati (ma anche poco alla portata del novello collaboratore). Tenete presente poi che per documentazione non intendo la semplice lista delle API ma qualcosa di più alto: come sono organizzati i moduli, quale modulo fa cosa, quale sono le convenzioni utilizzate nella stesura del codice (e poi magari anche qualche bozza di diagramma delle classi non sarebbe male).

Questo fa parte della difficoltà di accesso a progetti esterni. Manca, purtroppo, un meccanismo che accompagni e guidi i collaboratori all’interno del codice.

RESTO SOLO IO!

A questo punto, a meno che non si è stati estremamente fortunati, si deve ripartire da soli. Ma cosa fare da soli? In teoria qualunque cosa, in pratica solo roba semplice. Questo perché non si può scendere in campo a cercare collaboratori e per avere speranze di recuperarne qualcuno che non faccia solo presenza, bisogna avere almeno un qualcosa di funzionante e se il progetto è troppo complesso quel “qualcosa di funzionante” potrebbe non arrivare mai.

D’altro canto un progetto troppo semplice spesso è banale e non attira l’interesse della comunità. Esiste una soglia di “massa critica” per i progetti open source dopo la quale il progetto cresce esponenzialmente e sotto la quale il progetto si spegne. Raggiungere tale soglia è quasi sempre un impresa titanica.

CONCLUSIONI

Esiste quindi una specie di selezione naturale? Solo i migliori vanno avanti? Si, in un certo senso si ma la mia visione è completamente differente. Io credo che ci sia un enorme mare di potenziale non sfruttato della comunità, di persone che hanno difficoltà a partire ma che con i meccanismi giusti potrebbero dare molto. Eppure rimangono la, parcheggiati per anni, inattivi. Un mare di “forza” che è inutilizzato a causa di spigoli che bisognerebbe smussare.

Non do soluzioni perché al momento non ne ho. Però vorrei far riflettere su questo e magari sensibilizzare di più chi un suo progetto attivo ce l’ha già.

 

Mi sono ritrovato nella cartella Download del PC questo Pdf. Non mi ricordo dove l’ho preso, in ogni caso voglio rendervi partecipi.

In questo PDF sono elencate in modo sintetico tutte (o quasi) le funzioni di OpenGL e la relativa sintassi. Uno strumento utilissimo per chi programma in OpenGL e, ovviamente, non ricorda la particolare sintassi di una particolare funzione!

Ecco qui di seguito il pratico download! :D

OpenGL4 Quick Reference Card

 

Abbiamo visto come si può disegnare qualsivoglia figura inserendo i vari vertici della figura manualmente. Abbiamo visto anche che prima di inserire un vertice dobbiamo prepararlo impostando, ad esempio, il colore, il vettore normale (vedremo a cosa serve quando parleremo della luce), le texture e via dicendo. Questo può sembrarvi estremamente macchinoso… e lo è: dobbiamo usare circa 3-4 istruzioni per inserire ogni vertice! Un metodo decisamente inadatto per inserire oggetti formati da centinaia di vertici!

Anche volendo disegnare un semplice cubo (quindi con la miseria di 8 vertici) ci rendiamo conto che ogni vertice andrebbe specificato ben 3 volte (uno per ogni faccia a cui appartiene) con inutile spreco di prestazioni!

Ovviamente esiste la soluzione: usare gli array. Tramite gli array possiamo inserire con una manciata di comandi intere liste di vertici. Ma andiamo per passi.

1 – ABILITARE GLI ARRAY

Come gran parte degli stati di OpenGL gli array sono disabilitati di default. Esistono 8 diversi array da abilitare:

  • GL_VERTEX_ARRAY
  • GL_COLOR_ARRAY
  • GL_SECOND_COLOR_ARRAY
  • GL_INDEX_ARRAY
  • GL_NORMAL_ARRAY
  • GL_FOG_COORDINATE_ARRAY
  • GL_TEXTURE_COORDINATE_ARRAY
  • GL_EDGE_FLAG_ARRAY

Ovviamente non ci serviranno tutte adesso e possiamo limitarci, ad esempio, solamente a vertici e colori. Possiamo quindi abilitare gli array che ci interessano con glEnableClientState() come abbiamo visto in precedenza.

2 – INSERIRE DATI NEGLI ARRAY

Una volta che gli array sono abilitati bisogna inserire dei dati al loro interno. Esiste una funzione per ogni tipo di array. Noi però per il momento vedremo solamente le funzioni che ci interessano:

  • glVertexPointer(size, type, stride, pointer) è la funzione che permette di inserire un vettore all’interno dell’array dei vertici. size è semplicemente il numero di coordinate per vertice (può valere solo 2,3 o 4). type indica il tipo con cui sono specificati i vertici (GL_INT_, GL_FLOAT e così via). stride è un valore che indica l’offeset fra vertici consecutivi all’interno del vettore. Questo parametro è solitamente 0 per array che contengono solamente vertici. pointer è invece il puntatore al vettore che contiene i vertici da inserire nell’array.
  • glColorPointer(size, type, stride, pointer) è analoga a sopra ma serve per impostare il vettore dei colori.

3 – UTILIZZARE GLI ARRAY

Esistono diverse funzioni per utilizzare i dati presenti negli array. La prima funzione base è glArrayElement(k). Questa funzione non fa altro che inserire il k-esimo elemento dell’array. Facciamo un esempio. Supponiamo di avere due array vertex e color correttamente inizializzati e inseriti negli array di OpenGL.

A questo punto i due codici sono equivalenti:

glBegin(GL_TRIANGLES)
glArrayElement(2)
glArrayElement(3)
glArrayElement(5)
glEnd()
glBegin(GL_TRIANGLES)
glColor3f(color[2*3], color[2*3 + 1], color[2*3+2])
glVertex2f(color[2*2], color[2*2 + 1])
glColor3f(color[3*3], color[3*3 + 1], color[3*3+2])
glVertex2f(color[3*2], color[3*2 + 1])
glColor3f(color[5*3], color[5*3 + 1], color[5*3+2])
glVertex2f(color[5*2], color[5*2 + 1])
glEnd()

Come potete vedere c’è un bel risparmio. Notate anche che il vertice k-esimo viene colorato con il colore k-esimo.

La seconda funzione che vediamo ci permette di semplificare il tutto ancora di più. Tale funzione è glDrawElements(mode, count, type, indices). Questa funzione è del tutto equivalente a questo codice:

glBegin(mode)
for i in range(count) :
    glArrayElement(indices[i])
glEnd()

Il parametro indices, come avrete notato, è un array di indici. Se indices contiene [0, 4, 6] verranno inseriti in sequenza il vertice 0, 4 e 6 contenuto nell’array di OpenGL. Notate anche che è un errore inserire glDrawElements() all’interno di un blocco glBegin/glEnd.

Una terza funzione è glDrawArray(mode, first, count). Questa funzione è equivalente a:

glBegin(mode)
for i in range(count) :
    glArrayElement(first + i)
glEnd()

La differenza principale con glDrawElements riguarda la scelta degli indici: mentre glDrawElements permette di campionare gli indici in ordine sparso all’interno dell’array di OpenGL, glDrawArray permette solamente di disegnare un gruppo di vertici contiguo.

Per il momento basta così. Vi lascio con un piccolissimo esempio pratico:

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

def init():
    glClearColor(0, 0, 0, 0)
    glShadeModel(GL_SMOOTH)

def test():
    glutInit()

def display():
    glClear(GL_COLOR_BUFFER_BIT)

    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_COLOR_ARRAY)

    vertici = [25, 25,
        100, 325,
        175, 25,
        175, 325,
        250, 25,
        325, 325]

    colori = [1, 0.2, 0.2,
        0.2, 0.2, 1,
        0.8, 1, 0.2,
        0.75, 0.75, 0.75,
        0.35, 0.35, 0.35,
        0.5, 0.5, 0.5]

    glColorPointer(3, GL_FLOAT, 0, colori)
    glVertexPointer(2, GL_INT, 0, vertici)

    indici = [0, 1, 2, 3, 4, 5]

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indici)

    glDisableClientState(GL_COLOR_ARRAY)
    glDisableClientState(GL_VERTEX_ARRAY)
    glFlush()

def reshape(w, h):
    glViewport(0, 0, w, h)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluOrtho2D(0, w, 0, h)

if __name__ == '__main__':
    glutInit()
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
    glutInitWindowSize(350, 350)
    glutInitWindowPosition(100, 100)
    glutCreateWindow("Array: Due Triangoli")
    init()
    glutDisplayFunc(display)
    glutReshapeFunc(reshape)
    glutMainLoop()

L’esempio è piuttosto semplice alla luce della spiegazione.

Con questo si conclude la prima parte del corso dedicata ai vertici. Nella prossima vedremo come manipolare la “telecamera” e gli oggetti. Analizzeremo quindi i 3 aspetti fondamentali della visualizzazione: composizione, inquadratura e proiezione.

Vi ricordo che per ulteriori chiarimenti sono sempre disponibile nei commenti, su LQH e se ci sono potete abusare di me all’indirizzo Jabber: thek3nger@jabber.linux.it

 

Passato il week-end posso rimettermi al lavoro per scrivere l’ultima parte del primo capitolo del nostro corso introduttivo alle OpenGL. Nel frattempo però voglio suggerirvi un libro interessante e conciso per capire le meccaniche alla base di ogni sistema grafico tridimensionale.

Il libro non si basa su nessuna libreria ma spiega in modo molto semplice tutti i passi con cui un sistema digitale costruisce, gestisce e disegna su schermo un modello tridimensionale analizzando le varie fasi: modellazione, clipping, proiezione, colore, luce ecc. Un libro molto utile per poter avere una visione di insieme del mondo della grafica 3D mentre si studia una libreria specifica.

Il libro è scritto a quattro mani da Riccardo Scateni, Paolo Cignoni, Claudio Montani e Roberto Scopigno e ha un prezzo di circa 25€.

Se vi interessa il mondo della computer grafica è un libro assolutamente da non perdere.

 

Dopo aver fatto un post quasi melenso verso tutte le cose buone che ho ritrovato su Ubuntu dopo due anni di assenza è giunto il momento di riassumere tutte quelle mie idee che gradirei vedere implementate nelle prossime versioni. Molte di esse sono di “concept” finalizzati ad aumentare la confidenza e l’usabilità dell’ambiente desktop. Altre invece sono solo pareri personali su alcune applicazioni di default e quindi prendeteli per tali.

I concept in particolare sono idee che ho ma che non so realizzare data la mia scarsa confidenza con le Gtk.

1. PROGRESS BAR

Mokup di KDE del 2007. Rende l'idea di cosa vorrei si facesse anche su Gnome

Questa idea è presa in prestito da KDE. In KDE tutte le progress bar delle azioni di sistema (copia, ricerca, eliminazione, masterizzazione e simili) sono ammucchiate in un comodo contatore posto sulla barra principale. In Gnome (e quindi in Ubuntu) le barre sono visualizzate tramite finestre separate che svolazzano di qua e di là e sono difficilmente reperibili. Ho visto alcuni mokup di qualcosa di simile ma non mi sono piaciuti. Uno integrava tutte le barre in un altra finestra e la mia idea è proprio di eliminare le finestre per questo genere di cose. L’altra metteva gli indicatori direttamente sui file di Nautilus. Questo però limiterebbe l’uso di tale tecnologia solamente alle operazioni su file.

L’idea va anche incontro alla tendenza di Ubuntu di integrare tutto l’integrabile nell’area di notifica della barra superiore. In pratica sarebbe un estenzione del sistema di notifiche già esistente.

2. STANDARD OUTPUT GRAFICO

Allora sappiamo tutti che il modo migliore per capirci qualcosa quando un applicazione fa le bizze è quella di avviarla da terminale e leggersi quello che il programma sputa su stdout e stderr. Ma perché bisogna costringere le persone ad aprire un programma da terminale? Anche perché spesso gli errori e i crash sono sporadici e un utente non può ogni volta aprire un applicazione da terminale in attesa (quasi la speranza direi) che l’applicazione muoia per individuare l’errore. La legge di Murphy infatti ci dice che l’applicazione crasha sempre quando non viene aperta da terminale.

La mia idea è quindi di stampare lo standard output e lo standard error dietro la finestra. Come dietro? Esattamente dietro. Si potrebbe quindi, all’occorrenza far ribaltare la finestra (magari sfruttando anche qualche comando posto sul Winindicators che piazzeranno a destra oppure “trascinando un angolo”), farla flippare per mostrare il retro. Ed il retro non sarà altro che una specie di finestra di terminale con il log del programma (ma volendo si può fare anche qualcosa di più complesso.

Ovviamente si dovrebbe anche evitare che in caso di crash la finestra si chiuda di colpo. Magari sostituendo il davanti con un immagine a lutto (come quando crashano i plugin di Chrome) per permettere all’utente di girare la finestra e leggere le ultime parole agonizzanti del defunto.

Questo si potrebbe fare anche tramite un plugin di Compiz credo.

3. UN DEMONE DI VERIFICA MAIL E CALENDARIO

Trovo abbastanza idiota il fatto che per poter visualizzare le mie email nell’indicatore di sistema debba avere Evolution o chi per lui aperto. Quell’indicatore dovrebbe proprio servirmi ad evitare di andare ad aprire il programma di email se non ho email. Quindi o si cambia approccio o si crea una specie di evolution-light che ha soltanto lo scopo di verificare email e calendario. Altrimenti così è un po’ scomodo.

4. BANSHEE

Ok… è scritto in C# e questo fa incazzare parecchie persone. Non condivido questa Monofobia (o almeno non pienamente) ma capisco che a qualcuno possa dar fastidio. Nonostante tutto credo che sia nettamente superiore a Rhythmbox. Già lo stile meno iTunes-like è un punto positivo. Inoltre ha un bel supporto per Wikipedia, Last.fm e Youtube. E come se non bastasse esistono già plugin che permettono una perfetta integrazione con Ubuntu.

Ci sarebbe anche Exaile (che dalla sua ha la mancanza di problemi etici) ma ancora non mi sembra così completo.

5. F-SPOT

Come si ridimensiona!? E soprattutto... come diamine si annulla una modifica senza ripartire da capo?

Lo trovo un programma piuttosto inutile e povero. Io lo chiamo F-Sput… Da quello che ho sentito lo hanno escluso dalle prossime release. Ma purtroppo lo hanno sostituito con Shotwell, un programma che sembra, a primo avviso, ancora più traballante.

Sarà che su KDE c’è Digikam, il non plus ultra dei gestori fotografici e, avendo una ragazza fotografa, so abbastanza cosa serve e cosa no, ma F-Spot e il nuovo arrivato mancano di tutte le funzionalità chiave.

Certo, Digikam è un programma molto professionale e non tutti hanno bisogno di funzionalità professionali, ma raddrizzare una foto con tre click (contati, ne servono esattamente 3) e avere pieno controllo sui RAW non mi sembrano funzionalità così “professionali” ed interessano qualunque amatore della fotografia.

Non so se esista qualcosa di simile in Gtk ma, sicuramente, F-SPOT e compagnia danzante mi danno l’impressione di povertà. Lo sostituirei addirittura con Picasa+Wine se necessario!

Shotwell per il momento non mi sembra molto superiore in quanto a features.

PS: Sarò imbranato io ma con F-Spot non sono riuscito nemmeno a ridimensionare una foto. Ho dovuto installare Gimp :\

6. OPEN OFFICE

Ottimo programma, non ho dubbi su questo. Ma cambiate la grafica da anteguerra. Solo questo.

7. NOTIFICHE PERSONALIZZABILI

Esiste già una patch a tal fine ma è, ovviamente, non ufficiale. Possibile che non si possa modificare posizione, colore e forma delle notifiche senza doversi ricompilare il santissimo?

8. GNOME DO

Altra bestia nera in Mono. Tuttavia è molto più carino e funzionale della finestrella che esce con Alt+F2. Io proporrei di sostituirlo ad essa di default. Uscirebbe qualcosa di più carino e funzionale come già esiste per KDE. Magari integrandolo con un sistema di indicizzazione decente per avere accesso ultrarapido a file, musica, contatti etc.

9. MENU

Si parla tanto di spostare i menù in un unica barra in stile Mac. Ennesimo scopiazzamento del Mac che un po mi fastidia. Io invece pensavo che invece di spostare i menù a destra e a manca chiediamoci se servono davvero.

Come? Direte voi. I menù esistono da sempre.

Appunto. Molte cose sono cambiate dagli albori dei sistemi a finestre e quindi è normale che qualcosa possa cambiare anche radicalmente. Chrome, ad esempio, ci insegna che i menù non sono necessari o, almeno, che non è necessario utilizzare un intera riga per elencare comandi che per il 50% sono accessibili da altrove (tasto destro ad esempio).

Esiste un plugin per firefox che fa la stessa cosa condensando in un unico pulsante l’intera barra dei menù.

Potremmo quindi escogitare nuovi modi di organizzare i dati che non siano menù invece di spararli in alto per emulare dio-mac. Basterebbe qualche pulsante ben congegnato in più e il menù contestuale farebbe il resto.

Non ho ben chiaro questo punto ma ci sto pensando da quando mi sono accorto che utilizzo un menù solamente l’1% del tempo in cui utilizzo l’applicazione.

Con questo concludo il mio poste semi-osceno e forse a tratti banale su Ubuntu. Volevo aggiungere una 10° cosa ma mi sembra di aver letto che mi hanno preceduto :D In pratica suggerivo di rendere i 4 desktop di sistema completamente indipendenti e, a quanto pare, questa è un ipotesi già al vaglio dagli sviluppatori.

Sperando di non aver detto troppe fesserie vi saluto! Alla prossima!

© 2008-2012 SlashCode Suffusion theme by Sayontan Sinha