Week 8 Tutorial Solutions

Question 1: Bezier Curves

  1. Use de Casteljau's algorithm to generate the point a t = 0.25 on the degree 3 Bezier curve with control points (0,0), (4,16), (20,8), (20,0).

    The point is (4.8125, 7.875) as illutrated by the construction below.
  2. Prove that de Casteljau's algorithm describes the same curve as given by the degree 3 Berstein polynomials.

    Prove that de Casteljau's algorithm describes the same curve as given by the degree 3 Berstein polynomials.

  3. Find the tangent vector for the point on the Bezier curve from part a.

    The equation for the tangent is

    P1 - P0 = (4,16) - (0,0) = (4,16)
    P2 - P1 = (20,8) - (4,16) = (16,-8)
    P3 - P2 = (20,0) - (20,8) = (0,-8)
    
    tangent = 3 * [(1-0.25)^2 (4,16) + 2*0.25*(1-0.25) (16,-8) + 0.25^2 (0,-8)]
            =  3 * [ (2.25,9) + (6,-3) + (0,-0.5)]
            = 3 * (8.25,5.5)
            = (24.75,16.5)
    

Question 2: 3d Modeling

  1. Write code/pseudocode to generate a cylinder. The front face of the cylinder should be a circle of radius 1 at (0,0,-1), lying on the z=-1 plane with a back face at z=-3. The two faces should be connected by quads or a quadstrip. Make sure you do not forget to specify normals.
    
        double zFront = -1;
        double zBack = -3;
        double angleIncrement = (Math.PI * 2.0) / SLICES;
        
        //Draw Front Face   
        gl.glNormal3f(0,0,1);
        gl.glBegin(GL2.GL_POLYGON);{      
            for(int i=0; i< SLICES; i++){
                double angle = i*angleIncrement;
    	    double xPos = Math.cos(angle);
    	    double yPos = Math.sin(angle);
    	    gl.glVertex3d(xPos,yPos,zFront);       		
            }
        }gl.glEnd();
           
        //Draw Back face       
        gl.glNormal3f(0,0,-1);
        gl.glBegin(GL2.GL_POLYGON);{ 
            for(int i=0; i< SLICES; i++){
    	    double angle = -i*angleIncrement;
    	    double xPos = Math.cos(angle);
    	    double yPos = Math.sin(angle);
    	    gl.glVertex3d(xPos,yPos,zBack);
    	}
        }gl.glEnd();
          
        //Lateral Surface
        gl.glBegin(GL2.GL_QUADS);{
            for(int i=0; i< SLICES; i++){
    	    double angle0 = i*angleIncrement;
    	    double angle1 = (i+1)*angleIncrement;
    	    double xPos0 = Math.cos(angle0);
    	    double yPos0 = Math.sin(angle0);
    
    	    double xPos1 = Math.cos(angle1);
    	    double yPos1 = Math.sin(angle1);
    
    	    gl.glNormal3d(xPos0, yPos0, 0);
    	    gl.glVertex3d(xPos0,yPos0,zFront);
    	    gl.glVertex3d(xPos0,yPos0,zBack);
    	        	
    	    gl.glNormal3d(xPos1, yPos1, 0);
    	    gl.glVertex3d(xPos1,yPos1,zBack);
    	    gl.glVertex3d(xPos1,yPos1,zFront);
    	        	
    	        	
    	}
        }gl.glEnd();
            
    
    
  2. Suppose we have a profile of a curve that is a quarter of a circle as defined by the following function

    C(u) = (radius*cos(u),radius*sin(u)) For u [0..90]
    
    What would the surface of revolution around the y-axis be defined as in terms of t and the angle v for v[0..360]
    P(u,v) = ?
    
    Assuming we use the function C(t) to generate values for X and Y so that
    X(u) = radius*cos(u)
    Y(u) = radius*sin(u)
    P(u,v) = ( X(u)cos(v),Y(u), X(u)*sin(v))
    

    Write a piece of code to generate a list of vertices and normals for the object.

    
    private void createVertices(){
        //Angle used in semi-circle profile. Semi-circle so PI/2
        double angleSize = Math.PI/2.0/(NUM_STACKS);
        int i;
        int j = 0;
        int k=0;
        vertices = new double[NUM_STACKS][NUM_SLICES+1][3];
        normals = new double[NUM_STACKS][NUM_SLICES+1][3];
        for(i = 0; i < NUM_STACKS ; i++){
        	double currentAngle = angleSize*i;
        	double x = radius * Math.sin(currentAngle);
        	double y = radius * Math.cos(currentAngle);
        	for(j = 0; j <= NUM_SLICES ;j++){
        	    vertices[i][j][0] = x * Math.cos(Math.PI * 2.0 * j/(NUM_SLICES-1) ); 
        	    vertices[i][j][1] = y; 
                vertices[i][j][2] = x * Math.sin(Math.PI * 2.0 * j/(NUM_SLICES-1) );  
    
                //In this situation the normals are just the x,y,z co-ordinates.
             
                normals[i][j][0] = vertices[i][j][0];
        	    normals[i][j][1] = vertices[i][j][1]
                normals[i][j][2] = vertices[i][j][2]				    		 
            }
        }
    }
    

    Write a piece of code to draw the the object given the list of vertices.

    
        for (i=0;i<NUM_STACKS;i++) { 
            gl.glBegin(GL2.GL_TRIANGLE_STRIP); 
                for(j=0; j<= NUM_SLICES; j++){  
                               
                 x1= vertices[i][j][0];
                 x2= vertices[i+1][j][0];
                 nx1= normals[i][j][0];
                 nx2= normals[i+1][j][0];
    
    
                 y1= vertices[i][j][1];
                 y2= vertices[i+1][j][1];
                 ny1= normals[i][j][1];
                 ny2= normals[i+1][j][1];
                
                
                 z1= vertices[i][j][2];
                 z2= vertices[i+1][j][2];
                 nz1= normals[i][j][2];
                 nz2= normals[i+1][j][2];
             
                 gl.glNormal3d(nx1,ny1,nz1);
                 gl.glVertex3d(x1,y1,z1); 
                 
                 gl.glNormal3d(nx2,ny2,nz2);
                 gl.glVertex3d(x2,y2,z2); 
             
               }; 
            gl.glEnd();  
        }
            
    
  3. Calculate the frenet frame for the helix spine at t = PI for b = 1
    C(t) = (cos(t), sin(t), bt)
    
    First find the origin
    C(PI) = (-1,0,PI)
    
    Then find the tangent. Either by
    C'(t) = (-sin(t), cos(t), b) = (0,-1,1)
    Normalised = (0,-1/sqrt(2),1/sqrt(2));
    
    Or you could evaluate C(t) with t = PI-Epsilon and t = PI+Epsilon etc and subtract
    
    For example
    tanget = C(PI+0.1) - C(PI-0.1) and you should get the same result.
    
    Once we have k = (0,-1/sqrt(2),1/sqrt(2))
    
    We find the perpendicular vector corresponding to (-y,x,0);
    This would give us (1/sqrt(2),0,0) which we would need to normalise
    
    i = (1,0,0)
    
    j = kxi 
      = (0,        -1/sqrt(2),1/sqrt(2)) x (1,0 0);       
    
      = (0,1/sqrt(2),-1/sqrt(2))
    
                     i   j          k           o 
    Frenet frame = [ 1   0          0           -1  ]
                   [ 0   1/sqrt(2) -1/sqrt(2)   0   ]
                   [ 0  -1/sqrt(2)  1/sqrt(2)   PI  ]
                   [ 0   0          0            1  ]
    

    Suppose you had the triangle with points P0, P1 and P2 and you wanted to extrude it along the given helical spine. How would you generate the points at the cross section where t = PI on the spine? You would simply multiply each point by the Frenet Frame

Question 3:

Consider an L-System with the rules

X -> F[+X]F[-X]+X
F -> FF

Starting with the symbol X compute the first three iterations of this system.

Suppose the symbols translate to the following commands:

X : null
F : forwards 10
+ : rotate 30
- : rotate -30
[ : push the current pen position
] : pop the pen position

Draw the shapes for the strings generated above.

0 X
1 F[+X]F[-X]+X
2 FF[+F[+X]F[-X]+X]FF[-F[+X]F[-X]+X]+F[+X]F[-X]+X
3 FFFF[+FF[+F[+X]F[-X]+X]FF[-F[+X]F[-X]+X]+F[+X]F[-X]+X]FFFF[-FF[+F[+X]F[-X]+X]FF[-F[+X]F[-X]+X]+F[+X]F[-X]+X]+FF[+F[+X]F[-X]+X]FF[-F[+X]F[-X]+X]+F[+X]F[-X]+X

Using the Madflame L-system app, the 1st generation looks like this:

Using the Madflame L-system app, the 2nd generation looks like this:

Using the Madflame L-system app, the 3rd generation looks like this:

Assignment 2

If there is any time left discuss assignment 2.