Sto provando a estrudere un percorso in 3d. Niente di eccezionale, basta seguire alcuni punti e usare un poligono regolare per "tubing". Sto usando Processing per ora per creare rapidamente un prototipo, ma in seguito trasformerò il codice in OpenGL.come estrudere un percorso in 3d?
Il mio problema è la rotazione dei "giunti" ad angolo retto. Penso di avere una vaga idea di come ottenere gli angoli, non sono sicuro.
ho iniziato da un campione di Simon Greenwold (produzione> File> Esempi> 3D> Modulo> vertici) di .Qui il mio tentativo finora:
UPDATE> refactoring/SEMPLIFICATO CODICE
Here is the main sketch code:
int pointsNum = 10;
Extrusion star;
int zoom = 0;
void setup() {
size(500, 500, P3D);
PVector[] points = new PVector[pointsNum+1];
for(int i = 0 ; i <= pointsNum ; i++){
float angle = TWO_PI/pointsNum * i;
if(i % 2 == 0)
points[i] = new PVector(cos(angle) * 100,sin(angle) * 100,0);
else
points[i] = new PVector(cos(angle) * 50,sin(angle) * 50,0);
}
star = new Extrusion(10,10,points,3);
}
void draw() {
background(0);
lights();
translate(width/2, height/2,zoom);
rotateY(map(mouseX, 0, width, 0, PI));
rotateX(map(mouseY, 0, height, 0, PI));
rotateZ(-HALF_PI);
noStroke();
fill(255, 255, 255);
translate(0, -40, 0);
star.draw();
}
void keyPressed(){
if(key == 'a') zoom += 5;
if(key == 's') zoom -= 5;
}
Ed ecco la classe Extrusion:
import processing.core.PMatrix3D;
class Extrusion{
float topRadius,bottomRadius,tall,sides;
int pointsNum;
PVector[] points;
Extrusion(){}
Extrusion(float topRadius, float bottomRadius, PVector[] points, int sides) {
this.topRadius = topRadius;
this.bottomRadius = bottomRadius;
this.points = points;
this.pointsNum = points.length;
this.sides = sides;
}
void draw() {
if(pointsNum >= 2){
float angle = 0;
float angleIncrement = TWO_PI/sides;
//begin draw segments between caps
angle = 0;
for(int i = 1; i < pointsNum ; ++i){
beginShape(QUAD_STRIP);
for(int j = 0; j < sides + 1; j++){
vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius);
vertex(points[i].x + cos(angle) * bottomRadius, points[i].y, points[i].z + sin(angle) * bottomRadius);
angle += angleIncrement;
}
endShape();
}
//begin draw segments between caps
}else println("Not enough points: " + pointsNum);
}
}
UPDATE
Ecco come il mio schizzo assomiglia:
processing extrude http://doc.gold.ac.uk/~ma802gp/extrude.gif
Il problema è che le articolazioni non sono ad angolo retto, per cui l'estrusione sembra sbagliato. Questo non è un ottimo esempio, poiché questo potrebbe essere ottenuto con un tornio. Se riesco a far funzionare un tornio con un insieme arbitrario di punti e un asse che sarà fantastico. Sto usando estrusione perché sto cercando di creare corpi geometrici basati sull'arte di Liviu Stoicoviciu.
Ecco alcuni esempi:
star painting http://doc.gold.ac.uk/~ma802gp/star_painting.jpg
star paper sculpture http://doc.gold.ac.uk/~ma802gp/star_paper_sculpture.jpg
triangles http://doc.gold.ac.uk/~ma802gp/triangles_pencil.jpg
Ci scusiamo per la scarsa qualità.
Come potete vedere nell'immagine dei triangoli, ciò si otterrebbe con le estrusioni.
UPDATE
Ecco il mio tentativo di utilizzare l'aiuto di drhirsch nel metodo draw:
void draw() {
if(pointsNum >= 2){
float angle = 0;
float angleIncrement = TWO_PI/sides;
//begin draw segments between caps
angle = 0;
for(int i = 1; i < pointsNum ; ++i){
beginShape(QUAD_STRIP);
for(int j = 0; j < sides + 1; j++){
PVector s = new PVector(0,0,1);
PVector cn = new PVector();
points[i].normalize(cn);
PVector r = s.cross(cn);
float a = acos(s.dot(cn));
PMatrix3D rot = new PMatrix3D(1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1);
rot.rotate(a,r.x,r.y,r.z);
PVector rotVec = new PVector();
rot.mult(points[i],rotVec);
rotVec.add(new PVector(cos(angle) * topRadius,0,sin(angle) * topRadius));
vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius);
vertex(rotVec.x,rotVec.y,rotVec.y);
//vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius);
//vertex(points[i].x + cos(angle) * bottomRadius, points[i].y, points[i].z + sin(angle) * bottomRadius);
angle += angleIncrement;
}
endShape();
}
//begin draw segments between caps
}else println("Not enough points: " + pointsNum);
}
ho refactoring del codice in modo ormai la classe che si chiamava CShape è chiamato Estrusione, il codice è di meno e si spera che sia semplice, e io uso una serie di oggetti PVector invece di un vettore di oggetti PVector che potrebbero confondere.
Ecco il mio ennesimo tentativo con alcune Escher-esque risultati:
upated disegnare
void draw() {
if(pointsNum >= 2){
float angle = 0;
float angleIncrement = TWO_PI/sides;
//begin draw segments between caps
angle = 0;
for(int i = 1; i < pointsNum ; ++i){
beginShape(QUAD_STRIP);
float angleBetweenNextAndPrevious = 0.0;
if(i < pointsNum - 1) angleBetweenNextAndPrevious = PVector.angleBetween(points[i],points[i+1]);
for(int j = 0; j < sides + 1; j++){
PVector s = new PVector(0,0,1);
PVector s2 = new PVector(0,0,1);
PVector cn = new PVector();
PVector cn2 = new PVector();
points[i-1].normalize(cn);
points[i].normalize(cn);
PVector r = s.cross(cn);
PVector r2 = s.cross(cn2);
PMatrix3D rot = new PMatrix3D(1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1);
PMatrix3D rot2 = new PMatrix3D(1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1);
rot.rotate(angleBetweenNextAndPrevious,r.x,r.y,r.z);
rot2.rotate(angleBetweenNextAndPrevious,r2.x,r2.y,r2.z);
PVector rotVec = new PVector();
rot.mult(points[i-1],rotVec);
rotVec.add(new PVector(cos(angle) * topRadius,0,sin(angle) * topRadius));
PVector rotVec2 = new PVector();
rot2.mult(points[i],rotVec2);
rotVec2.add(new PVector(cos(angle) * topRadius,0,sin(angle) * topRadius));
vertex(rotVec.x,rotVec.y,rotVec.z);
vertex(rotVec2.x,rotVec2.y,rotVec2.z);
//vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius);
//vertex(points[i].x + cos(angle) * bottomRadius, points[i].y, points[i].z + sin(angle) * bottomRadius);
angle += angleIncrement;
}
endShape();
}
//begin draw segments between caps
}else println("Not enough points: " + pointsNum);
}
}
fix_test http://doc.gold.ac.uk/~ma802gp/extrude2.gif
Edit by drhirsch Questo dovrebbe funzionare:
void draw() {
if(pointsNum >= 2){
float angle = 0;
float angleIncrement = TWO_PI/sides;
//begin draw segments between caps
angle = 0;
for(int i = 1; i < pointsNum ; ++i){
beginShape(QUAD_STRIP);
float angleBetweenNextAndPrevious = 0.0;
if(i < pointsNum - 1) angleBetweenNextAndPrevious = PVector.angleBetween(points[i],points[i+1]);
PVector s = new PVector(0,0,1);
PVector s2 = new PVector(0,0,1);
PVector cn = new PVector();
PVector cn2 = new PVector();
points[i-1].normalize(cn);
points[i].normalize(cn2);
PVector r = s.cross(cn);
PVector r2 = s.cross(cn2);
PMatrix3D rot = new PMatrix3D(1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1);
PMatrix3D rot2 = new PMatrix3D(1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1);
rot.rotate(angleBetweenNextAndPrevious,r.x,r.y,r.z);
rot2.rotate(angleBetweenNextAndPrevious,r2.x,r2.y,r2.z);
PVector rotVec = new PVector();
PVector rotVec2 = new PVector();
for(int j = 0; j < sides + 1; j++){
// I am still not sure about this. Should the shape be in the xy plane
// if the extrusion is mainly along the z axis? If the shape is now in
// the xz plane, you need to use (0,1,0) as normal vector of the shape
// (this would be s and s2 above, don't use the short names I have
// used, sorry)
PVector shape = new PVector(cos(angle) * topRadius,0,sin(angle) * topRadius);
rot.mult(shape, rotVec);
rot2.mult(shape,rotVec2);
rotVec.add(points[i-1]);
rotVec2.add(points[i]);
vertex(rotVec.x,rotVec.y,rotVec.z);
vertex(rotVec2.x,rotVec2.y,rotVec2.z);
//vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius);
//vertex(points[i].x + cos(angle) * bottomRadius, points[i].y, points[i].z + sin(angle) * bottomRadius);
angle += angleIncrement;
}
endShape();
}
//begin draw segments between caps
}else println("Not enough points: " + pointsNum);
}
}
UPDATE
Ecco una semplice illustrazione del mio problema:
description http://doc.gold.ac.uk/~ma802gp/description.gif
Il percorso blu è equivalente ai punti [] array PVector nel mio codice, se pointsNum = 6. Il percorso rosso è quello che sto cercando di risolvere, il percorso verde è ciò che voglio raggiungere.
UPDATE
Alcuni problemi minori con l'ordine dei vertici credo. Ecco alcune schermate di stampa che usano 6 punti e nessuna (se/meno% 2) condizione stella.
points1 http://doc.gold.ac.uk/~ma802gp/points1.gif
alt text http://doc.gold.ac.uk/~ma802gp/points2.gif
L'unico motivo per calcolare gli angoli sarebbe generare le normali. Perché non fai l'estrusione con una traduzione lungo l'asse z? E potresti usare un QUAD_STRIP ai lati. – hirschhornsalz
O vuoi eseguire un'estrusione lungo un percorso con una rotazione automatica per abbinare l'inclinazione alla tangente di questo percorso? – hirschhornsalz
@drhirsch Grazie per il suggerimento su QUAD_STRIP, lo userò. Voglio un'estrusione lungo un percorso con una rotazione automatica per abbinare l'inclinazione alla tangente del percorso. Penso di averlo risolto in 2D, avendo problemi quando mi sono trasferito in 3d.per ottenere l'inclinazione per un secondo punto, utilizzo l'atan2 della differenza tra il terzo punto e il primo punto e aggiungo 90 gradi (una perpendicolare). Non so come applicarlo in 3d. –