Graphics – MGP – Create a surface

19 05 2010

Now that we have the points needed for the curve we can code the function that will give as any point and then that which defines the surface of revolution.

The first step towards this is to understand the Bezier Curve functions and how to code them.

Calculating points on a Bezier Curve

The equation for a point on a bezier curve of arbitrary order (i.e. an arbitrary number of control points in the curve) is:

where P(i) is the ith point. B(i,n) is the Bernstein polynomial and is given by

and

Equation images taken from Wikipedia’s article here: Bezier Curve

We have Bezier curves of order-4 (they have 4 control points) and we could be all clever, just calculate our coefficients and hard-code them but that isn’t as fun! Performance also isn’t an issue for us as this will only be used at the start of the program for generating assets and then used no more…

In fact the code for the general case is fairly easy to implement provided you don’t try to do it all at once and so we get some helper functions for the second two functions.

int factorial(int n)
{
    for(int i = n-1; i > 1; i--)
        n *= i;
    return n;
}
int coefficient(int i, int n)
{
    if( i==0 || i == n )
        return 1;
    return factorial(n) / (double)(factorial(i)*factorial(n-i));
}
double Basis(int n,int i,float t)
{
    return coefficient(i, n) * pow(t,i) * pow(1.0 - t, n-i);
}

And when it comes to actually using these to compute a point on the curve we get something like this:

-(NSPoint) pointOnCurve:(double) t
{
    NSPoint ret = NSMakePoint(0,0);
    double bern;
    for( int i=0; i < [mControlPoints count]; i++ )
    {
        bern = Basis([mControlPoints count]-1, i, t);
        ret.x += [[mControlPoints objectAtIndex: i] pointValue].x * bern;
        ret.y += [[mControlPoints objectAtIndex: i] pointValue].y * bern;
    }
    return ret;
}

I should have mention that I’m doing all this in Objective-C / Cocoa where possible. Of course for small helper functions I just fall back on my friend: C.

Creating a Surface

Given the methods above (and a few other very simple ones to aggregate multiple curves into one) we can now create our surface of revolution.

This is also pretty easy and will give us a new function that takes 2 parameters (therefore a parametric surface) and spits out a point in 3D.

-(NSPoint3) pointOnSurfaceT:(double) t S:(double) s
{
    NSPoint3 ret;
    NSPoint onPath = [mPath pointOnCurve: t];
    ret.x = onPath.y * cos( 2 * pi * s );
    ret.y = onPath.y * sin( 2 * pi * s );
    ret.z = onPath.x;
    return ret;
}

Fairly easy to follow but broken down into steps:

  1. Calculate a point on our bezier curve
  2. Use the ‘x’ component of the 2D point as our ‘z’ value
  3. Rotate the ‘y’ component around the ‘z’ axis

I tend to use the ‘z up’ coordinate system but it doesn’t really matter.

This function can then be used to create as many vertices as we need at whatever resolution.

For the purposes of this installment we will just treat these vertices as points and next time we’ll deal with normals and tessellation to create a solid surface. In the mean time this is what our code has given us so far:

Surface of Points

Advertisements

Actions

Information

One response

7 06 2010
Graphics – MGP – Normals « NSH + Graphics

[…] Which is easier than it looks and mostly uses the code from the previous post on creating a surface. […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: