|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
[JAVA] Creare poligono con OpenGL
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 |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
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: Codice:
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;
}
}
Codice:
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();
}
}
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. |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
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... |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
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: Codice:
public void translate(Tuple3f delta) {
a = a.add(delta);
b = b.add(delta);
c = c.add(delta);
...eccetera
}
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: Codice:
# 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 Codice:
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();
}
}
Codice:
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);
}
}
}
Codice:
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);
}
}
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. |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
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? |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
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. |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Feb 2001
Città: Foggia
Messaggi: 2519
|
post di una inutilità scorcentante ma permettetemi.
PGI-Bis:
__________________
mi sembra di essere tornato adolescente ai bei tempi.. che figata essere di nuovo su questo forum |
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
Quote:
Meno male che c'è gente più gentile e disponibile come PGI-Bis...che approfitto per ringraziare infinitamente per la pazienza e la disponibilità! |
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
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? |
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Feb 2001
Città: Foggia
Messaggi: 2519
|
Quote:
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
__________________
mi sembra di essere tornato adolescente ai bei tempi.. che figata essere di nuovo su questo forum |
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
post di una inutilità scorcentante ma permettimi: io dico di sì.
Ti piace vincere facile? Bonsci-bonsci-bon-bon-bon...
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
Quote:
|
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
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? |
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
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) |
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
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); |
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
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
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
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 ! |
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
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? |
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 326
|
e cosa dovrei fare x farlo ruotare intorno all'asse x=0 ?
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 19:06.




















