Estoy tratando de extruir un camino en 3d. No es nada lujoso aún, solo sigue algunos puntos y usa un polígono regular para 'tubos'. Estoy usando Processing por ahora para hacer un prototipo rápido, pero luego convertiré el código en OpenGL.cómo extruir un camino en 3D?
Mi problema es girar las "articulaciones" en los ángulos correctos. Creo que tengo una idea aproximada de cómo obtener los ángulos, no estoy seguro.
He empezado a partir de una muestra de Simon Greenwold (producción> Archivo> Ejemplos> 3D> Formulario> Vértices) .Aquí de mi intento hasta el momento:
ACTUALIZACIÓN> refactorizado/código simplificado
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;
}
Y aquí está la clase 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);
}
}
ACTUALIZACIÓN
Aquí es cómo mi bosquejo parece:
processing extrude http://doc.gold.ac.uk/~ma802gp/extrude.gif
El problema es que las articulaciones no están en el ángulo derecho, por lo que la extrusión se ve mal. Este no es un muy buen ejemplo, ya que esto podría lograrse con un torno. Si puedo obtener un torno para trabajar con un conjunto arbitrario de puntos y un eje que será genial. Estoy utilizando la extrusión porque estoy tratando de crear cuerpos geométricos basados en el arte de Liviu Stoicoviciu.
He aquí algunos ejemplos:
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
Lo siento por la mala calidad.
Como puede ver en la imagen de triángulos, eso se lograría con extrusiones.
ACTUALIZACIÓN
Aquí está mi intento de utilizar la ayuda de drhirsch en el método 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);
}
He refactorizado el código por lo que ahora la clase que solía ser llamado CShape se llama Extrusión, el código es menos y, con suerte, simple, y utilizo una matriz de objetos de PVector en lugar de un Vector de objetos de PVector que puede ser confuso.
Aquí está mi otro intento con algunos resultados de Escher-esque:
upated dibujar
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
Editar por drhirsch Esto debería funcionar:
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);
}
}
ACTUALIZACIÓN
Aquí es una simple ilustración de mi problema:
description http://doc.gold.ac.uk/~ma802gp/description.gif
El camino azul es equivalente a los puntos [] array PVector en mi código, si pointsNum = 6. El camino rojo es lo que estoy luchando por resolver, el camino verde es lo que quiero lograr.
ACTUALIZACIÓN
Algunos problemas menores con el fin de vértices que pienso. Aquí hay algunas pantallas de impresión que usan 6 puntos y ninguna condición de estrella (si/else% 2).
points1 http://doc.gold.ac.uk/~ma802gp/points1.gif
alt text http://doc.gold.ac.uk/~ma802gp/points2.gif
La única razón para calcular los ángulos sería generar normales. ¿Por qué no haces la extrusión por una traducción a lo largo del eje z? Y podrías usar un QUAD_STRIP a los lados. – hirschhornsalz
¿O desea hacer una extrusión a lo largo de un camino con una rotación automática para que coincida con la inclinación en la tangente de esta ruta? – hirschhornsalz
@drhirsch Gracias por el consejo sobre QUAD_STRIP, lo usaré. Quiero una extrusión a lo largo de un camino con una rotación automática para que coincida con la inclinación en la tangente de la ruta. Creo que lo resolví en 2d, teniendo problemas al pasar a 3d.para obtener la inclinación para un segundo punto, uso el atan2 de la diferencia entre el 3er punto y el 1er punto y agrego 90 grados (una perpendicular). No estoy seguro de cómo aplicar eso en 3d. –