texto numeros letras isometrico insertar extruir como opengl 3d geometry processing trigonometry

opengl - numeros - cómo extruir un camino en 3D?



numeros 3d autocad (1)

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.

Mi problema es rotar las ''articulaciones'' en los ángulos correctos. Creo que tengo una idea aproximada de cómo obtener los ángulos, no estoy seguro.

Empecé con una muestra de Simon Greenwold (Procesamiento> Archivo> Ejemplos> 3D> Formulario> Vértices). Aquí está mi intento:

ACTUALIZACIÓN> CÓDIGO REFACTADO / 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); } }

ACTUALIZAR

Así es como se ve mi boceto:

proceso de extrusión http://doc.gold.ac.uk/~ma802gp/extrude.gif

El problema es que las juntas no están en el ángulo correcto, por lo que la extrusión se ve mal. Este no es un 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.

Aquí hay algunas muestras:

pintura estrella http://doc.gold.ac.uk/~ma802gp/star_painting.jpg

escultura en papel estrella http://doc.gold.ac.uk/~ma802gp/star_paper_sculpture.jpg

triángulos http://doc.gold.ac.uk/~ma802gp/triangles_pencil.jpg

Perdon por la mala calidad.

Como puede ver en la imagen de triángulos, eso se lograría con extrusiones.

ACTUALIZAR

Aquí está mi intento de usar la ayuda de drhirsch en el método de sorteo:

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); }

Refactoreé el código así que ahora la clase que solía llamarse CShape se llama Extrusión, el código es menos y con suerte simple, y utilizo una matriz de objetos PVector en lugar de un Vector de objetos PVector que puede ser confuso.

Aquí está mi otro intento más con algunos resultados escher-esque:

drenaje desapasionado

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); } }

ACTUALIZAR

Aquí hay una ilustración simple de mi problema:

descripción http://doc.gold.ac.uk/~ma802gp/description.gif

La ruta azul es equivalente a la matriz de PVector de puntos [] en mi código, si pointsNum = 6. La ruta roja es lo que estoy luchando por resolver, la ruta verde es lo que quiero lograr.

ACTUALIZAR

Algunos problemas menores con el orden de los vértices, creo. 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

texto alternativo http://doc.gold.ac.uk/~ma802gp/points2.gif


Asumiendo que su forma tiene un vector normal S. En su ejemplo, S sería (0,0,1), porque su forma es plana en xy. Puede usar el producto cruzado entre el vector V de trayectoria actual (normalizado) y S para obtener el vector R de eje de rotación. Debe girar su forma alrededor de R. El ángulo de rotación puede obtenerse del producto de puntos entre S y V. Asi que:

R = S x V a = arc cos(S . V)

Ahora puede configurar una matriz de rotación con R y a y rotar la forma.

Puedes usar glRotate (...) para rotar la matriz actual en la pila, pero esto no se puede hacer entre glBegin () y glEnd (). Entonces usted tiene que hacer la multiplicación de la matriz usted mismo o con una biblioteca.

Editar: Después de una breve mirada a la biblioteca que está utilizando, debería poder configurar la matriz de rotación con

PVector s = new PVector(0,0,1); // is already normalized (meaning is has length 1) PVector cn; current.normalize(cn); PVector r = s.cross(cn); float a = acos(s.dot(cn)); PMatrix rot = new PMatrix(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);

y ahora multiplica cada elemento de tu forma con putrefacción y tradúcela por tu vector de ruta actual:

PVector rotVec; rot.mult((PVector)shape[i], rotVec); rotVec.add(current);