PDA

View Full Version : [JAVA] Creare poligono con OpenGL


DrZoidberg
08-02-2011, 19:20
Salve a tutti,
sto disegnando con le OpenGL un parallelepipedo (per modellare un notebook). Ho modellato un parallelepipedo, ma ho bisogno di un aiuto per fare 2 cose:
1) Il mio parallelepipedo è troppo "spesso", devo farlo più fino: come si fa?
2) Devo crearne un altro che devo unire a questo già esistente, in modo che abbiano una base in comune.
Vi allego il codice del parallelepipedo creato fin ora (ogni lato ha un colore diverso per una migliore comprensione)

gl.glLoadIdentity();
gl.glTranslatef(1.5f, 0.0f, -6.0f);
gl.glRotatef(rquad, 1.0f, 1.0f, 1.0f);
gl.glBegin(GL2.GL_QUADS); // Draw A Quad
gl.glColor3f(0.0f, 1.0f, 0.0f); // Set The Color To Green
gl.glVertex3f(1.0f, 1.5f, -1.0f); // Top Right Of The Quad (Top)
gl.glVertex3f(-1.0f, 1.5f, -1.0f); // Top Left Of The Quad (Top)
gl.glVertex3f(-1.0f, 1.5f, 1.0f); // Bottom Left Of The Quad (Top)
gl.glVertex3f(1.0f, 1.5f, 1.0f); // Bottom Right Of The Quad (Top)

gl.glColor3f(1.0f, 0.5f, 0.0f); // Set The Color To Orange
gl.glVertex3f(1.0f, -1.5f, 1.0f); // Top Right Of The Quad (Bottom)
gl.glVertex3f(-1.0f, -1.5f, 1.0f); // Top Left Of The Quad (Bottom)
gl.glVertex3f(-1.0f, -1.5f, -1.0f); // Bottom Left Of The Quad (Bottom)
gl.glVertex3f(1.0f, -1.5f, -1.0f); // Bottom Right Of The Quad (Bottom)

gl.glColor3f(1.0f, 0.0f, 0.0f); // Set The Color To Red
gl.glVertex3f(1.0f, 1.5f, 1.0f); // Top Right Of The Quad (Front)
gl.glVertex3f(-1.0f, 1.5f, 1.0f); // Top Left Of The Quad (Front)
gl.glVertex3f(-1.0f, -1.5f, 1.0f); // Bottom Left Of The Quad (Front)
gl.glVertex3f(1.0f, -1.5f, 1.0f); // Bottom Right Of The Quad (Front)

gl.glColor3f(1.0f, 1.0f, 0.0f); // Set The Color To Yellow
gl.glVertex3f(1.0f, -1.5f, -0.2f); // Bottom Left Of The Quad (Back)
gl.glVertex3f(-1.0f, -1.5f, -0.2f); // Bottom Right Of The Quad (Back)
gl.glVertex3f(-1.0f, 1.5f, -0.2f); // Top Right Of The Quad (Back)
gl.glVertex3f(1.0f, 1.5f, -0.2f); // Top Left Of The Quad (Back)

gl.glColor3f(0.0f, 0.0f, 1.0f); // Set The Color To Blue
gl.glVertex3f(-1.0f, 1.5f, 1.0f); // Top Right Of The Quad (Left)
gl.glVertex3f(-1.0f, 1.5f, -1.0f); // Top Left Of The Quad (Left)
gl.glVertex3f(-1.0f, -1.5f, -1.0f); // Bottom Left Of The Quad (Left)
gl.glVertex3f(-1.0f, -1.5f, 1.0f); // Bottom Right Of The Quad (Left)

gl.glColor3f(1.0f, 0.0f, 1.0f); // Set The Color To Violet
gl.glVertex3f(1.0f, 1.5f, -1.0f); // Top Right Of The Quad (Right)
gl.glVertex3f(1.0f, 1.5f, 1.0f); // Top Left Of The Quad (Right)
gl.glVertex3f(1.0f, -1.5f, 1.0f); // Bottom Left Of The Quad (Right)
gl.glVertex3f(1.0f, -1.5f, -1.0f); // Bottom Right Of The Quad (Right)
gl.glEnd(); // Done Drawing The Quad
gl.glFlush();

Spero che qualcuno mi sappia aiutare.

Grazieeee

PGI-Bis
08-02-2011, 21:33
Come programmatore devi volerti un po' di bene altrimenti fai una fatica bestia.

La difficoltà che incontri deriva dal fatto che ti sei odiato - quasi a morte.

Per disegnare un parallelepipedo allineato con gli assi, centrato all'origine, ti bastano tre informazioni: quant'è largo, lungo e alto.

Basta uno schizzo su carta per capire che partendo dall'origine, note le tre dimensioni, puoi derivare gli otto vertici.

Una volta fatto il disegno devi portarlo dalla carta ad OpenGL. Come tutte le librerie di basso livello, basta poco per rendersi conto che OpenGL non è adatta all'uso umano quindi devi partire dalle decorazioni.

La prima astrazione che ti serve è un punto 3d:

package jogltest;

public class Tuple3f {

private final float x, y, z;

public Tuple3f(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}

public Tuple3f add(float x, float y, float z) {
return new Tuple3f(x + getX(), y + getY(), z + getZ());
}

public Tuple3f scale(float factor) {
return new Tuple3f(getX() * factor, getY() * factor, getZ() * factor);
}

public float getX() {
return x;
}

public float getY() {
return y;
}

public float getZ() {
return z;
}
}

Coi punti puoi disegnare il parallelepipedo:

package jogltest;

import javax.media.opengl.GL2;
import static javax.media.opengl.GL2.*;

public class Parallelepipedo {

private final Tuple3f size, a, b, c, d, e, f, g, h;

public Parallelepipedo(float larghezza, float altezza, float profondità) {
this(new Tuple3f(larghezza, altezza, profondità));
}

public Parallelepipedo(Tuple3f dim) {
this.size = dim;
d = dim.scale(0.5f).scale(-1f);
a = d.add(0, dim.getY(), 0);
b = a.add(dim.getX(), 0, 0);
c = b.add(0, -dim.getY(), 0);
e = a.add(0, 0, dim.getZ());
f = e.add(dim.getX(), 0, 0);
g = f.add(0, -dim.getY(), 0);
h = e.add(0, -dim.getY(), 0);
}

public void draw(GL2 gl) {
tempgl = gl;
quads();
quad(a, d, c, b);
quad(b, c, g, f);
quad(f, g, h, e);
quad(e, h, d, a);
quad(d, h, g, c);
quad(a, e, f, b);
end();
}

private GL2 tempgl;

private void quads() {
tempgl.glBegin(GL_QUADS);
}

private void quad(Tuple3f v0, Tuple3f v1, Tuple3f v2, Tuple3f v3) {
vert(v0);
vert(v1);
vert(v2);
vert(v3);
}

private void vert(Tuple3f v) {
tempgl.glVertex3f(v.getX(), v.getY(), g.getZ());
}

private void end() {
tempgl.glEnd();
tempgl.glFlush();
}
}

Non giurereri sulla correttezza dell'ordine dei vertici ma il punto è l'astrazione.

E qui hai finito: Parallelepipedo è il modello di un qualsiasi parallelepipedo allineato con gli assi, centrato all'origine. Lo crei da qualche parte e quando vuoi disegnarlo invochi:

istanzaParallelepipedo.draw(unQualcheGl2);

Meccanicamente Parallelepipedo disegna nello stesso modo del codice che hai incollato ma rende quelle istruzioni parametriche rispetto alle dimensioni impostate in costruzione.

DrZoidberg
09-02-2011, 12:56
Grazie mille...il codice funziona perfettamente. Giusto un piccolo errore di cui segnalo la correzione

private void vert(Tuple3f v) {
tempgl.glVertex3f(v.getX(), v.getY(), v.getZ());
}

Ora mi sorge un'altra domanda: disegnato ora un parallelepipedo, me ne serve disegnare un altro che abbia una faccia in comune con quello già disegnato.
Con il codice che hai scritto te la cosa la vedo un pò complicata...o sbaglio?
Qualche suggerimento?

Grazie mille ancora x la pazienza...

PGI-Bis
09-02-2011, 16:51
Potresti aggiungere un costruttore che accetta direttamente gli otto punti: a quel punto la condivisione di una faccia sarebbe la condivisione dei quattro punti che la definiscono. Il problema è che, potenzialmente, non è un più un parallelepipedo.

Se invece per condivisione intendi l'adiacenza di due facce, puoi aggiungere un metodo "translate" a Parallelepipedo:

public void translate(Tuple3f delta) {
a = a.add(delta);
b = b.add(delta);
c = c.add(delta);
...eccetera
}

Crei due scatole delle stesse dimensioni e poi ne sposti una di lato: a quel punto di trovi con due parallelepipedi uno di fianco all'altro.

Se poi vuoi avere un po' più di autonomia nella definizione delle tue geometrie ti conviene appoggiarti ad un modellatore 3d (tipo blender). Ad esempio se crei un cubo e lo esporti in formato wavefront/obj ti salta fuori un file di testo di questo genere:

# Blender3D v249 OBJ File:
# www.blender3d.org
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 0.999999 1.000000
v 0.999999 -1.000001 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
usemtl Material
s off
f 1 2 3 4
f 5 8 7 6
f 1 5 6 2
f 2 6 7 3
f 3 7 8 4
f 5 1 4 8

v sono i vertici, f sono le facce. Il parsing è elementare:

package jogltest;

import javax.media.opengl.GL2;

public class Triangle {

private final Tuple3f a, b, c;

public Triangle(Tuple3f a, Tuple3f b, Tuple3f c) {
this.a = a;
this.b = b;
this.c = c;
}

public void draw(GL2 gl) {
gl.glBegin(GL2.GL_TRIANGLES);
gl.glVertex3f(a.getX(), a.getY(), a.getZ());
gl.glVertex3f(b.getX(), b.getY(), b.getZ());
gl.glVertex3f(c.getX(), c.getY(), c.getZ());
gl.glEnd();
}
}

package jogltest;

import java.util.Collection;
import javax.media.opengl.GL2;

public class TriangleArray {

private final Triangle[] triangles;

public TriangleArray(Collection<? extends Triangle> triangles) {
this.triangles = triangles.toArray(new Triangle[triangles.size()]);
}

public void draw(GL2 gl) {
for (int i = 0; i < triangles.length; i++) {
Triangle triangle = triangles[i];
triangle.draw(gl);
}
}
}

package jogltest;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class ObjLoader {

public TriangleArray load(String fileName) throws IOException {
InputStream stream = null;
try {
stream = new File(fileName).toURI().toURL().openStream();
return load(stream);
} finally {
if(stream != null) stream.close();
}
}

public TriangleArray load(InputStream stream) throws IOException {
class Face {
int a, b, c, d;
Face(int a, int b, int c, int d) { this.a = a; this.b = b; this.c = c; this.d = d; }
void triangulate(List<Tuple3f> vertices, List<Triangle> buffer) {
buffer.add(new Triangle(vertices.get(a), vertices.get(b), vertices.get(c)));
if(d >= 0) buffer.add(new Triangle(vertices.get(c), vertices.get(d), vertices.get(a)));
}
}

ArrayList<Tuple3f> vertices = new ArrayList<Tuple3f>();
ArrayList<Face> faces = new ArrayList<Face>();
Scanner in = new Scanner(stream);
while(in.hasNextLine()) {
String line = in.nextLine();
if(line.startsWith("#")) continue;
if(line.startsWith("v")) {//vertex
String[] values = line.split(" ");
float x = Float.parseFloat(values[1]);
float y = Float.parseFloat(values[2]);
float z = Float.parseFloat(values[3]);
vertices.add(new Tuple3f(x, y, z));
} else if(line.startsWith("f")) {//face
String[] values = line.split(" ");
int a = Integer.parseInt(values[1]) - 1;
int b = Integer.parseInt(values[2]) - 1;
int c = Integer.parseInt(values[3]) - 1;
int d = values.length > 3 ? Integer.parseInt(values[4]) - 1 : -1;
faces.add(new Face(a, b, c, d));
}
}
ArrayList<Triangle> triangles = new ArrayList<Triangle>();
for (Face face : faces) {
face.triangulate(vertices, triangles);
}
return new TriangleArray(triangles);
}
}

Così anzichè star lì a diventar matto coi punti crei la tua figura geometrica, la esporti in un file e poi nel codice scrivi:

TriangleArray geometria = new ObjLoader().load("figura.obj");

e la disegni quando ti serve con:

geometria.draw(istanzaGL2);

Naturalmente quando il numero di triangoli diventa rilevante occorre abbandonare il disegno a colpi di triangle3f, che è troppo comprensibile, e passare ai buffer, che sono un monumento all'astrusità ma questo abbiamo.

DrZoidberg
09-02-2011, 18:21
Si per condivisione intendo che due facce devono essere adiacenti. Nel metodo

public void translate(Tuple3f delta) {
a = a.add(delta);
b = b.add(delta);
c = c.add(delta);
...eccetera
}

delta cosa sarebbe?

PGI-Bis
09-02-2011, 18:46
delta è lo spostamento che vuoi applicare alla geometria.

Se crei il parallelepipedo con:

Parallelepipedo p = new Parallellepipedo(1, 0.5f, 1);

la figura è centrata rispetto all'origine. E' chiaro che se ne crei due:

Parallelepipedo p1 = new Parallellepipedo(1, 0.5f, 1);
Parallelepipedo p2 = new Parallellepipedo(1, 0.5f, 1);

Si sovrappongono. Per far sì che appaiano adiacenti, uno dei due va spostato lungo uno degli assi di un valore pari alla metà della somma delle dimensioni dei due parallelepipedi sullo stesso asse. Che pare arabo ma ha un suo senso. Nel caso di p1 e p2, col metodo translate, se dici:

p2.translate(1, 0, 0);

p2 appare a destra di p1 (sull'asse x entrambi misurano 1, (1 + 1) / 2 = 1).

Nota che translate altera la geometria della figura, si può ottenere lo stesso effetto usando gl.glTranslate, basta dotare il solido di un attributo "translation" e applicarlo nel metodo draw con glTranslatef prima di disegnare le facce.

In generale appena ti muovi un pelo più in alto di quelli che sono i metodi di opengl, creando le tue strutture per gestire il disegno, gli approcci possibili si moltiplicano a dismisura.

cdere
10-02-2011, 01:08
post di una inutilità scorcentante ma permettetemi.

PGI-Bis: :ave: :ave: :ave:

DrZoidberg
11-02-2011, 13:50
post di una inutilità scorcentante ma permettetemi.

PGI-Bis: :ave: :ave: :ave:

cdere...scusa se non siamo tutti cervelloni come te! Io di questi argomenti ne so poco, volevo qlc suggerimento e mi sembra che un forum serva anche a questo. Se trovi questo post di una inutilità sconcertante nessuno ti obbliga a seguirlo!
Meno male che c'è gente più gentile e disponibile come PGI-Bis...che approfitto per ringraziare infinitamente per la pazienza e la disponibilità!

PGI-Bis
11-02-2011, 13:57
Punto 100 cucuzze sul qui pro quo.

cdere faceva riferimento al suo intervento, non al topic.

"post di una inutilità scorcentante" = "intervengo dicendo una cosa non utile ai fini del topic"


Ho vinto?

cdere
11-02-2011, 14:35
Punto 100 cucuzze sul qui pro quo.

cdere faceva riferimento al suo intervento, non al topic.

"post di una inutilità scorcentante" = "intervengo dicendo una cosa non utile ai fini del topic"


Ho vinto?

hai vinto PGI-Bis ;)

DrZoidberg: hai soltanto capito male, io mi riferivo al mio intervento (post), tu invece hai capito ch'io mi stessi riferendo alla tua discussione (thread). Il mio voleva solo essere un plauso a PGI-Bis.
Comunque nessun problema, mi hai frainteso :)

banryu79
11-02-2011, 14:38
Ho vinto?

post di una inutilità scorcentante ma permettimi: io dico di sì.
Ti piace vincere facile? :D
Bonsci-bonsci-bon-bon-bon...

DrZoidberg
11-02-2011, 14:50
hai vinto PGI-Bis ;)

DrZoidberg: hai soltanto capito male, io mi riferivo al mio intervento (post), tu invece hai capito ch'io mi stessi riferendo alla tua discussione (thread). Il mio voleva solo essere un plauso a PGI-Bis.
Comunque nessun problema, mi hai frainteso :)

Scusate...avevo frainteso tutto :(

DrZoidberg
15-02-2011, 18:15
Salve a tutti di nuovo. Riprendo questo post visto che mi è stato molto di aiuto...e magari lo sarà anche ora. Il problema è il seguente: ho disegnato 2 parallelepipedi che hanno 2 facce adiacenti. Devo ruotarne uno, e devo far si che la rotazione lungo l'asse x. Ora, in teoria prima di fare una rotazione su un punto, devo effettuare una traslazione che mi riporti la figura all'origine del sistema di riferimento, effettuare la rotazione e poi ri-effettuare una nuova traslazione per riportare la figura nella posizione originale. Vi posto il codice

final GL2 gl = gLDrawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.1f, -6.0f);
monitor = new Parallelepipedo(2,1,0.1f,0,0,0);
monitor.draw(gl);
gl.glTranslatef(0.0f, -0.1f, 0.0f);
gl.glRotatef(xmov, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.1f, 0.0f);
keyboard = new Parallelepipedo(2,1,0.1f,0,0,1);
keyboard.translate(new Tuple3f(0,1.02f,0));
keyboard.draw(gl);

Dove sbaglio?

PGI-Bis
16-02-2011, 17:39
Posto che non metterei la mano sul fuoco per neppure una delle sillabe che sto per scrivere...

Il metodo è giusto, direi che sia un problema di coordinate. Se vuoi far ruotare lo spazio di coordinate intorno al punto P, lungo l'asse Z di un angolo A scrivi:

translate(p.x, p.y, p.z)
rotate(a, 0, 0, 1)
translate(-p.x, -p.y. -p.z)
draw

Forse il risultato che ottieni è diverso da quello che ti aspetti perchè il punto intorno a cui ruoti non è quello che vorresti.

Se le coordinate del parallelepipedo sono disegnate intorno all'origine, è lungo (x) 10 e alto (y) 5 e vuoi farlo ruotare "intorno all'angolo in basso a sinistra", allora il punto della rotazione è (-5, -2.5, 0)

Se oltre a ruotarlo intorno ad un punto vuoi anche spostarlo allora devi prima spostarlo nella posizione che deve occupare, poi spostarlo nel punto in cui deve ruotare, ruotarlo e annullare lo spostamento.

Generalizzando, se O è l'oggetto, L è la posizione dell'oggetto, P è il "punto" di rotazione, A è l'asse e R l'angolo, scriverai:

glTranslatef(L.x, L.y, L.z);
glTranslatef(P.x, P.y, P.z);
glRotatef(R, A.x, A.y, A.z);
glTranslatef(-P.x, -P.y, -P.z);
O.draw(GL)

DrZoidberg
21-02-2011, 12:12
Ho fatto un pò di prove ma non ho ancora risolto il mio problema!
Il mio oggetto è posizionato in (-0.5,0,-6) e voglio fare una rotazione lungo l'asse x. Il problema è che l'oggetto si sposta e non rimane fermo nell'asse.
Questo è il codice:

gl.glTranslatef(0.5f, 0.0f, -6.0f);
gl.glTranslatef(-0.5f, 0.0f, 0.0f);
gl.glRotatef(xmov, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.5f, 0.0f, 0.0f);

PGI-Bis
21-02-2011, 12:59
Se la rotazione è intorno all'asse x allora il punto è zero. Cioè dovresti dire:

gl.glTranslatef(0.5f, 0.0f, -6.0f);
gl.glRotatef(xmov, 1.0f, 0.0f, 0.0f);
disegna

DrZoidberg
21-02-2011, 13:08
no nn è neanche questo l'effetto che voglio ottenere!
Forse allora mi devo rivedere tutto il sistema di riferimento in cui ho posizionato i miei oggetti !

DrZoidberg
21-02-2011, 19:37
Considerando questo codice

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glTranslatef(0.5f, 0.0f, -6.0f);

// KEYBOARD
gl.glPushMatrix();
keyboard = new Polygon(2,1,0.1f,"keyboard");
keyboard.drawFront(gl);
keyboard.drawBack(gl);
keyboard.drawSide(gl);
gl.glPopMatrix();

// MONITOR
gl.glPushMatrix();
gl.glTranslatef(-0.5f, 0.0f, 0.0f);
gl.glRotatef(xmov, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.5f, 0.0f, 0.0f);
monitor = new Polygon(2,1,0.1f,"monitor");
monitor.translate(new Point3D(0,1.02f,0));
monitor.drawFront(gl);
monitor.drawBack(gl);
monitor.drawSide(gl);
gl.glPopMatrix();

Cosa dovrei aspettarmi dalla rotazione dell'oggetto monitor? Dovrebbe ruotare intorno all'asse x o sbaglio?

PGI-Bis
21-02-2011, 19:45
dovrebbe ruotare intorno all'asse x = 0.5

DrZoidberg
21-02-2011, 19:47
e cosa dovrei fare x farlo ruotare intorno all'asse x=0 ?

PGI-Bis
21-02-2011, 19:58
lasciare x a zero. Parliamo dello spazio di coordinate dell'oggetto. Se l'asse x attorno a cui vuoi farlo ruotare è quello dello spazio di coordinate globale allora devi spostarti lungo l'asse di rotazione di un valore pari alla differenza tra i due sistemi di coordinate.

Hai pensato all'ipotesi di usare uno scenegraph opengl, tipo Java3D o Ardord3d o Xith3D? Secondo me ti semplificano la vita.

DrZoidberg
22-02-2011, 19:00
Scusa se ti disturbo ancora ma proprio non riesco a capire! C'è qualcosa che mi sfugge! Allora, la mia situazione è questa (la classe Polygon è la tua classe Parallelepipedo che mi hai suggerito in questo thread, con i relativi metodi):

gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, -5.0f);

// KEYBOARD
gl.glPushMatrix();
keyboard = new Polygon(2,1,0.1f,"keyboard");
keyboard.draw(gl);
gl.glPopMatrix();

// MONITOR
gl.glPushMatrix();
gl.glRotatef(monitor_mov, 1.0f, 0.0f, 0.0f);
monitor = new Polygon(2,1,0.1f,"monitor");
monitor.translate(new Point3D(0,1.02f,0));
monitor.draw(gl);
gl.glPopMatrix();

....
gl.glPopMatrix();

Quindi in teoria i miei oggetti sono posizionati nello spazio globale (0,0,-5) giusto? E se faccio una rotazione dell'oggetto monitor lungo l'asse x come definito in quel modo, cosa dovrei ottenere?
Quello che voglio ottenere è una simulazione della rotazione del monitor di un laptop x capirci...

PGI-Bis
22-02-2011, 23:27
Provo con la spiegazione B.

spostare e ruotare non è la stessa cosa di ruotare e spostare.

se ruoti e poi sposti lo spostamento si applica allo spazio di coordinate dopo che è stato ruotato.

cioè se dico:

ruota(45, asse z)
sposta(1, asse x)

l'oggetto si sposta in alto a destra, perchè la prima ruotazione "piega" l'asse x verso l'alto.

Se invece dico:

sposta(1, asse x)
ruota(45, asse z)

l'oggetto si sposta a destra e ruota intorno al suo asse (l'origine del sistema c.d. inerziale)

Se vuoi far ruotare un oggetto intorno ad un punto P, devi far coincidere l'origine del sistema inerziale dell'oggetto con il punto P, nello spazio di coordinate globali, ruotare l'oggetto e riportarlo il suo spazio inerziale dove stava prima della rotazione.

DrZoidberg
23-02-2011, 15:31
Risoltoo!!
Grazie mille ;)