• fullscreen
  • drawings.pde
  • hilbert_3D_v1.pde
  • hilbert_3D_v3.pde
  • //////////////////////////////////////////////////////////////////////////////
    // DRAWING
    //////////////////////////////////////////////////////////////////////////////
    
    
    void drawCurve(){  
      colorMode(HSB, verts.length-1, 100, 100);
      float col = 0;
      strokeWeight(1f);
      stroke(0);
      noFill();
      beginShape(POLYGON);
        for( float[] v : verts) {
          stroke(col++, 100, 95);
          vertex(v[0], v[1], v[2]);
        }
      endShape();
      colorMode(RGB, 255, 255, 255);
    }
    
    
    
    void drawCurveExtruded(){
      lights();
      noStroke();
      
      colorMode(HSB, verts.length-1, 100, 100);
      float col = 0;
      int A_col = color(col++, 100, 100);
      
      float size = (float) (SIZE/Math.pow(2,DEPTH));
      float s_extr = size* .20f;
      float s_cube = size* .45f;
      
      for(int i = 0; i < verts.length-1; i++, col++){
        loft(verts[i], verts[i+1], s_extr, A_col, A_col=color(col, 100, 100));
      }
      
      col = 0;
      for( float[] v : verts){
        fill(col++, 100, 50);
        cube(v, s_cube);
      }
      colorMode(RGB, 255, 255, 255);
    }
    
    // only in world-axis directions!
    void loft(final float[] A, final float[] B, float size, int A_col, int B_col){
      final double EPSILON = 0.0001;
      final float ax = A[0], ay = A[1], az = A[2];
      final float bx = B[0], by = B[1], bz = B[2];
      final float s = size*0.5f, so;
      
      float dir;
      if( Math.abs(dir=(A[2]-B[2])) > EPSILON ){ // extrusion at Z-AXIS
        so = dir>0 ? +s : -s;  
        beginShape(QUAD_STRIP);
        fill(A_col); vertex(ax-s, ay-s, az-so);  fill(B_col); vertex(bx-s, by-s, bz+so); 
        fill(A_col); vertex(ax+s, ay-s, az-so);  fill(B_col); vertex(bx+s, by-s, bz+so); 
        fill(A_col); vertex(ax+s, ay+s, az-so);  fill(B_col); vertex(bx+s, by+s, bz+so); 
        fill(A_col); vertex(ax-s, ay+s, az-so);  fill(B_col); vertex(bx-s, by+s, bz+so); 
        fill(A_col); vertex(ax-s, ay-s, az-so);  fill(B_col); vertex(bx-s, by-s, bz+so); 
        endShape();
      } else if ( Math.abs(dir=(A[1]-B[1])) > EPSILON ){ // extrusion at Y-AXIS
        so = dir>0 ? +s : -s;  
        beginShape(QUAD_STRIP);
        fill(A_col); vertex(ax-s, ay-so, az-s);  fill(B_col); vertex(bx-s, by+so, bz-s); 
        fill(A_col); vertex(ax+s, ay-so, az-s);  fill(B_col); vertex(bx+s, by+so, bz-s); 
        fill(A_col); vertex(ax+s, ay-so, az+s);  fill(B_col); vertex(bx+s, by+so, bz+s); 
        fill(A_col); vertex(ax-s, ay-so, az+s);  fill(B_col); vertex(bx-s, by+so, bz+s); 
        fill(A_col); vertex(ax-s, ay-so, az-s);  fill(B_col); vertex(bx-s, by+so, bz-s); 
        endShape();
      } else if ( Math.abs(dir=(A[0]-B[0])) > EPSILON ){ // extrusion at X-AXIS
        so = dir>0 ? +s : -s;  
        beginShape(QUAD_STRIP);
        fill(A_col); vertex(ax-so, ay-s, az-s);  fill(B_col); vertex(bx+so, by-s, bz-s); 
        fill(A_col); vertex(ax-so, ay+s, az-s);  fill(B_col); vertex(bx+so, by+s, bz-s); 
        fill(A_col); vertex(ax-so, ay+s, az+s);  fill(B_col); vertex(bx+so, by+s, bz+s); 
        fill(A_col); vertex(ax-so, ay-s, az+s);  fill(B_col); vertex(bx+so, by-s, bz+s); 
        fill(A_col); vertex(ax-so, ay-s, az-s);  fill(B_col); vertex(bx+so, by-s, bz-s); 
        endShape();
      }
      
    }
    
    
    
    
    void drawCubes(){
      colorMode(HSB, verts.length-1, 100, 100);
      noStroke();
      float s = (float) (SIZE/Math.pow(2,DEPTH)) * 2;
      float col = 0;
      for( float[] v : verts){
        fill(col++, 100, 85);
        cube(v, s);
      }
      colorMode(RGB, 255, 255, 255);
    }
    
    
    void cube(final float[] v, float s){
      s*=0.5f;
      final float[][]CUBE_CORNERS = 
        {
          {  v[0]-s, v[1]-s, v[2]+s  }, // 0   
          {  v[0]+s, v[1]-s, v[2]+s  }, // 1  
          {  v[0]-s, v[1]+s, v[2]+s  }, // 2   
          {  v[0]+s, v[1]+s, v[2]+s  }, // 3
          {  v[0]-s, v[1]-s, v[2]-s  }, // 4   
          {  v[0]+s, v[1]-s, v[2]-s  }, // 5  
          {  v[0]-s, v[1]+s, v[2]-s  }, // 6   
          {  v[0]+s, v[1]+s, v[2]-s  }  // 7
        };
    
      beginShape(TRIANGLE_STRIP);
      {
        vertex3f( CUBE_CORNERS[0] );  // 0
        vertex3f( CUBE_CORNERS[1] );  // 1
        vertex3f( CUBE_CORNERS[2] );  // 2
        vertex3f( CUBE_CORNERS[3] );  // 3
        vertex3f( CUBE_CORNERS[7] );  // 7
        vertex3f( CUBE_CORNERS[1] );  // 1
        vertex3f( CUBE_CORNERS[5] );  // 5
        vertex3f( CUBE_CORNERS[4] );  // 4
        vertex3f( CUBE_CORNERS[7] );  // 7
        vertex3f( CUBE_CORNERS[6] );  // 6
        vertex3f( CUBE_CORNERS[2] );  // 2
        vertex3f( CUBE_CORNERS[4] );  // 4
        vertex3f( CUBE_CORNERS[0] );  // 0
        vertex3f( CUBE_CORNERS[1] );  // 1 
      }
      endShape();
    }
    
    
    void vertex3f(final float[] v){
      vertex(v[0], v[1], v[2]);
    }
    
    
    /*
      // thomas diewald
      // 
      // hilbert curve - quick and short example
      //
      // 16.11.2010
      // last updated: 16.11.2010 (thomas)
    */
    //import processing.opengl.*;
    import peasy.*; 
    PeasyCam cam;  
    
    int levels = 1; // recursion depth
    
    
    void setup(){
      size( 600, 600, P3D);
      cam = new PeasyCam(this, 0,0, 0, 100);
      cam.setMinimumDistance(10);
      cam.setMaximumDistance(500);
      cam.setDistance(300);
    }
    
    
    
    void draw(){
      background(255);
    
      Vector c3d[] = hilbert3D(  new Vector( 0,0,0) , 100.0,    levels,      0, 1, 2, 3, 4, 5, 6, 7); // hilbert(center, side-length, recursion depth, start-indices)
    
      strokeWeight(3); stroke(0);
      for(int i = 0; i < c3d.length-1; i++)
        line(c3d[i].x, c3d[i].y, c3d[i].z, c3d[i+1].x, c3d[i+1].y, c3d[i+1].z);
      
      int tmp_level = levels > 0 ? levels-1:0;
    
      Vector c3d_1[] = hilbert3D(  new Vector( 0,0,0) , 100.0,    tmp_level,      0, 1, 2, 3, 4, 5, 6, 7 ); // hilbert(center, side-length, recursion depth, start-indices)
    
      strokeWeight(2); stroke(255,0,0);
      for(int i = 0; i < c3d_1.length-1; i++)
        line(c3d_1[i].x, c3d_1[i].y, c3d_1[i].z, c3d_1[i+1].x, c3d_1[i+1].y, c3d_1[i+1].z);
    }
    
    
    
    Vector[] hilbert3D( Vector center,  float side,  int iterations, int v0, int v1, int v2, int v3, int v4, int v5, int v6, int v7  ){
      Vector vec_s[] = {
        new Vector(  center.x - side/2,   center.y + side/2, center.z - side/2  ),
        new Vector(  center.x - side/2,   center.y + side/2, center.z + side/2  ),
        new Vector(  center.x - side/2,   center.y - side/2, center.z + side/2  ),
        new Vector(  center.x - side/2,   center.y - side/2, center.z - side/2  ),
        new Vector(  center.x + side/2,   center.y - side/2, center.z - side/2  ),
        new Vector(  center.x + side/2,   center.y - side/2, center.z + side/2  ),
        new Vector(  center.x + side/2,   center.y + side/2, center.z + side/2  ),
        new Vector(  center.x + side/2,   center.y + side/2, center.z - side/2  )
      };
      
      Vector vec[] = { vec_s[ v0 ], vec_s[ v1 ], vec_s[ v2 ], vec_s[ v3 ], vec_s[ v4 ], vec_s[ v5 ], vec_s[ v6 ], vec_s[ v7 ]};
    
      if( --iterations >= 0) {
        Vector tmp[] = new Vector[0];
        tmp = (Vector[]) concat( tmp,   hilbert3D ( vec[ 0 ],  side/2,   iterations,   v0, v3, v4, v7, v6, v5, v2, v1  ));
        tmp = (Vector[]) concat( tmp,   hilbert3D ( vec[ 1 ],  side/2,   iterations,   v0, v7, v6, v1, v2, v5, v4, v3  ));
        tmp = (Vector[]) concat( tmp,   hilbert3D ( vec[ 2 ],  side/2,   iterations,   v0, v7, v6, v1, v2, v5, v4, v3  )); 
        tmp = (Vector[]) concat( tmp,   hilbert3D ( vec[ 3 ],  side/2,   iterations,   v2, v3, v0, v1, v6, v7, v4, v5  ));
        tmp = (Vector[]) concat( tmp,   hilbert3D ( vec[ 4 ],  side/2,   iterations,   v2, v3, v0, v1, v6, v7, v4, v5  )); 
        tmp = (Vector[]) concat( tmp,   hilbert3D ( vec[ 5 ],  side/2,   iterations,   v4, v3, v2, v5, v6, v1, v0, v7  ));
        tmp = (Vector[]) concat( tmp,   hilbert3D ( vec[ 6 ],  side/2,   iterations,   v4, v3, v2, v5, v6, v1, v0, v7  ));
        tmp = (Vector[]) concat( tmp,   hilbert3D ( vec[ 7 ],  side/2,   iterations,   v6, v5, v2, v1, v0, v3, v4, v7  ));
        return tmp;
      }
      return vec;
    }
    
    
    
    
    
    class Vector{
      float x, y, z;
      Vector( float x, float y, float  z){
        this.x = x; 
        this.y = y; 
        this.z = z; 
      }
    }
    
    
    
    
    void keyReleased(){
      if( key == CODED){
        if( keyCode == RIGHT) levels++;
        if( keyCode == LEFT)  levels--;
        if( levels > 4) levels = 4;
        if( levels < 0) levels = 0;
      }
    }
    
    //----------------------------------------------------------------------------
    //
    // author: (c) thomas diewald
    // date: 13.01.2012
    //
    // Processing:1.5.1
    // Renderer: P3D
    //
    // Hilbert Curve 3D, fast algorithm
    //
    //----------------------------------------------------------------------------
    
    import java.util.Locale;
    import peasy.*;
    
     
    PeasyCam cam;
    
    int DEPTH=2, SIZE=100;                  // hilbert curve params
    int IDX;                                // coord index
    float[][] verts;                        // curve-coords  
    float[][] SXD, SYD, SZD;                // cube corners (precomputed for each depth)
    float[] SX = {-1,-1,-1,-1,+1,+1,+1,+1}; // corner directions for x
    float[] SY = {+1,+1,-1,-1,-1,-1,+1,+1}; // corner directions for y
    float[] SZ = {-1,+1,+1,-1,-1,+1,+1,-1}; // corner directions for z
    
    int VISUAL = 2; // 1,2,3
    
    
    @Override
    public void setup(){
      size(700, 700, P3D);
      background(255);
      cam = new PeasyCam(this, 0, 0, 0, 400);
      cam.setRotations( -1.3968815, 0.71367186, -0.12572986);
    }
    
    
    
    @Override
    public void draw() {
      background(255);
      
      hilbert3D();
      noLights();
    
      switch(VISUAL){
        case 1: 
          drawCubes(); 
          break;
        case 2: 
          drawCurveExtruded(); 
          break;
        case 3:
          drawCurve();
          break;
      }
      updateWindowTitle();
    }
    
    
    
    
    //////////////////////////////////////////////////////////////////////////////
    // HILBERT CURVE
    //////////////////////////////////////////////////////////////////////////////
    
    void hilbert3D(){
      
      // create coords array
      int num_verts = (int)Math.pow(8,DEPTH);
      if( verts == null || num_verts != verts.length){
        verts = new float[num_verts][3];
      }
    
      // precompute cube corners for each depth
      SXD = new float[DEPTH][8];
      SYD = new float[DEPTH][8];
      SZD = new float[DEPTH][8];
      float s = SIZE/2;
      for(int i = DEPTH-1; i >= 0; i--, s/=2){
        for(int j = 0; j < 8; j++){
          SXD[i][j] = SX[j]*s; 
          SYD[i][j] = SY[j]*s;
          SZD[i][j] = SZ[j]*s;
        }
      }
      
      // create curve
      IDX = 0;
      hilbert3D(0,0,0, DEPTH, 0,1,2,3,4,5,6,7);
    }
    
    
    
    /**
     * Hilbert Curve: generates 3D-Coordinates in a very fast way.
     * 
     * @param x  x-coord       
     * @param y  y-coord       
     * @param z  z-coord
     * @param d  depth         
     * @param A  corner index A
     * @param B  corner index B
     * @param C  corner index C
     * @param D  corner index D
     * @param E  corner index E
     * @param F  corner index F
     * @param G  corner index G
     * @param H  corner index H
     */
    final void hilbert3D(float x, float y, float z, int d, int A, int B, int C, int D, int E, int F, int G, int H) {
      if (d-- == 0)  {
        verts[IDX][0] = x;
        verts[IDX][1] = y;
        verts[IDX][2] = z;  
        IDX++;
      } else {
        final float[] sxd = SXD[d], syd = SYD[d], szd = SZD[d];        
        hilbert3D(x + sxd[A], y + syd[A], z + szd[A], d, A, D, E, H, G, F, C, B ); 
        hilbert3D(x + sxd[B], y + syd[B], z + szd[B], d, A, H, G, B, C, F, E, D ); 
        hilbert3D(x + sxd[C], y + syd[C], z + szd[C], d, A, H, G, B, C, F, E, D ); 
        hilbert3D(x + sxd[D], y + syd[D], z + szd[D], d, C, D, A, B, G, H, E, F ); 
        hilbert3D(x + sxd[E], y + syd[E], z + szd[E], d, C, D, A, B, G, H, E, F ); 
        hilbert3D(x + sxd[F], y + syd[F], z + szd[F], d, E, D, C, F, G, B, A, H ); 
        hilbert3D(x + sxd[G], y + syd[G], z + szd[G], d, E, D, C, F, G, B, A, H ); 
        hilbert3D(x + sxd[H], y + syd[H], z + szd[H], d, G, F, C, B, A, D, E, H ); 
      }
    }
    
    
    
    
    
    void updateWindowTitle(){
      if( online ) 
        return;
      String txt_title     = "Hilbert Curve 3D";
      String txt_framerate = String.format(Locale.ENGLISH, "fps %6.2f", frameRate);
      String txt_depth     = String.format(Locale.ENGLISH, "depth %2d", DEPTH);
      String txt_num_verts = String.format(Locale.ENGLISH, "verts %3d", verts.length);
      txt_title += " | " + txt_depth;
      txt_title += " | " + txt_num_verts;
      txt_title += " | " + txt_framerate;
      frame.setTitle(txt_title);
    }
    
    
    @Override
    public void keyPressed(){
      if( key == ESC && online) key = 0;
    }
    @Override
    public void keyReleased(){
      if (key == 's' && !online ){
        String filename = "screenshot/diewald_hilbertcurve3D_"+VISUAL+".png";
        save(filename);
        System.out.println("saved image: "+filename);
      }
      
      if( key=='q' || key=='w' ){
        if( key=='w' ) DEPTH++;
        if( key=='q' ) DEPTH--;
          
        if( DEPTH<=0) DEPTH = 0;
        if( DEPTH>=6) DEPTH = 6;
      }
      
      if( key == '1') VISUAL = 1;
      if( key == '2') VISUAL = 2;
      if( key == '3') VISUAL = 3;
    }
    
    
    
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement

    Report Sketch

    Report for inappropriate content

    Please provide details if possible:

    Your have successfully reported the sketch. Thank you very much for helping to keep OpenProcessing clean and tidy :)

    Make a Copyright Infringement claim

    Thomas Diewald

    Hilbert Curve 3D

    Add to Faves Me Likey@! 7
    You must login/register to add this sketch to your favorites.

    This applet draws the hilbert-curve (3D).

    posted here:
    http://thomasdiewald.com/blog/?p=561

    UPDATE:
    13.01.2013 - improved algorithm

    controls:

    1/2/3 - display-mode
    q/w - change recursion-depth
    s - save screenshot (only offline)

    bob desnos
    13 Dec 2010
    hi
    Thomas


    i ask you one thing

    is possibile add animation

    without mouse moviment ?

    thank
    You need to login/register to comment.