Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SER431 Lecture 19

SER431 Lecture 19

Advanced Graphics
NURBS
(201810)

Javier Gonzalez-Sanchez
PRO

October 31, 2018
Tweet

More Decks by Javier Gonzalez-Sanchez

Other Decks in Programming

Transcript

  1. jgs
    SER 431
    Advanced Graphics
    Lecture 19: Non-Uniform Rational Basis Splines
    Javier Gonzalez-Sanchez
    [email protected]
    PERALTA 230U
    Office Hours: By appointment

    View Slide

  2. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 1
    jgs
    NURBS
    § Non-Uniform Rational Basis Splines
    § They are generalizations of B-Splines - are defined by some control points
    and a knot vector,
    § Rational – ratio of two polynomials (spline functions)
    § Non-Uniform – Use knot multiplicity to produce variations in curve
    § Control points are specified in homogeneous coordinates.
    § NURBS rendering is part of the OpenGL Utilities library of functions
    (prefixed with “glu”).

    View Slide

  3. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 2
    jgs
    Definition
    § They reduce the memory consumption when storing shapes (compared to
    simpler methods). They can be evaluated reasonably quickly by
    numerically stable and accurate algorithms.

    View Slide

  4. jgs
    Surfaces From Scratch

    View Slide

  5. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 4
    jgs
    Screenshot
    https://github.com/javiergs/SER431/blob/master/Lecture19/surface_bezier.cpp

    View Slide

  6. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 5
    jgs
    Screenshot
    4 Bezier Curves
    with 4 Control
    Points Each
    https://github.com/javiergs/SER431/blob/master/Lecture19/surface_bezier.cpp

    View Slide

  7. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 6
    jgs
    Code
    // a structure to hold a control point of the surface
    struct Point {
    float x;
    float y;
    float z;
    };
    // 4x4 grid of points that will define the surface
    Point points[4][4] = {
    { { 20, 0, 10 }, { 0, 0, 10 }, { -5, 0, 10 }, { -10, 0, 10 } },
    { { 20, 0, 5 }, { 0, 15, 5 }, { -5, 15, 5 }, { -10, 0, 5 } },
    { { 20, 0, -5 }, { 0, 10, -5 }, { -5, 10, -5 }, { -10, 0, -5 } },
    { { 20, 0, -10 }, { 0, 0, -10 }, { -5, 0, -10 }, { -10, 0, -10 } }
    };

    View Slide

  8. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 7
    jgs
    // display
    void display() {
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(30, 20, -30, 0, 0, 0, 0, 1, 0);
    glColor3f(0, 1, 0);
    glPointSize(3);
    // curves
    glBegin(GL_POINTS);
    for (int i = 0; i != N; ++i) {
    float u = (float)i / (N - 1);
    for (int j = 0; j != N; ++j) {
    float v = (float)j / (N - 1);
    Point p = calculate(u, v);
    glVertex3f(p.x, p.y, p.z);
    }
    }
    glEnd();
    // more...
    }

    View Slide

  9. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 8
    jgs
    Point calculate(float u, float v) {
    Point temp[4];
    // calculate each point on our final v curve
    temp[0] = CalculateU(u, 0);
    temp[1] = CalculateU(u, 1);
    temp[2] = CalculateU(u, 2);
    temp[3] = CalculateU(u, 3);
    // integrate curves as a surface (in columns)
    return CalculateV(v, temp);
    }

    View Slide

  10. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 9
    jgs
    // calculate each point on our final v curve
    Point CalculateU(float t, int row) {
    Point p;
    float it = 1.0f - t;
    // blending functions
    float b0 = t * t*t;
    float b1 = 3 * t*t*it;
    float b2 = 3 * t*it*it;
    float b3 = it * it*it;
    // curve
    p.x = b0 * points[row][0].x + b1 * points[row][1].x + b2 * points[row][2].x + b3 * points[row][3].x;
    p.y = b0 * points[row][0].y + b1 * points[row][1].y + b2 * points[row][2].y + b3 * points[row][3].y;
    p.z = b0 * points[row][0].z + b1 * points[row][1].z + b2 * points[row][2].z + b3 * points[row][3].z;
    return p;
    }

    View Slide

  11. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 10
    jgs
    // integrate curves as a surface (in columns)
    Point CalculateV(float t, Point* pnts) {
    Point p;
    float it = 1.0f - t;
    // calculate blending functions
    float b0 = t * t*t;
    float b1 = 3 * t*t*it;
    float b2 = 3 * t*it*it;
    float b3 = it * it*it;
    // blending functions
    p.x = b0 * pnts[0].x + b1 * pnts[1].x + b2 * pnts[2].x + b3 * pnts[3].x;
    p.y = b0 * pnts[0].y + b1 * pnts[1].y + b2 * pnts[2].y + b3 * pnts[3].y;
    p.z = b0 * pnts[0].z + b1 * pnts[1].z + b2 * pnts[2].z + b3 * pnts[3].z;
    return p;
    }

    View Slide

  12. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 11
    jgs
    Screenshot
    4 Bezier Curves
    with 4 Control
    Points Each
    https://github.com/javiergs/SER431/blob/master/Lecture19/surface_bezier.cpp

    View Slide

  13. jgs
    Surfaces using OpenGL Support
    First, Let us review Curves

    View Slide

  14. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 13
    jgs
    Screenshot
    https://github.com/javiergs/SER431/blob/master/Lecture16/bspline_connected.cpp
    https://github.com/javiergs/SER431/blob/master/Lecture19/nurbs_curve.cpp

    View Slide

  15. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 14
    jgs
    display()
    GLUnurbs* nurb = gluNewNurbsRenderer();
    GLfloat ctlpoints[7][3] = { { 10, 10, 0 }, { 5, 10, 0 }, { 0, 0, 0 },
    { -5, -5, 0 }, { -10, 0, 0 }, { -5, 10, 0 },
    { 0, 5, 0 } };
    GLfloat knots[11] = {0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0 };
    gluBeginCurve(nurb);
    gluNurbsCurve(nurb,
    11, // how many knots
    knots,
    3, //offset between consecutive control points in ctlpoints
    &ctlpoints[0][0],
    4, // order is the degree + 1
    GL_MAP1_VERTEX_3); // type
    gluEndCurve(nurb);
    // display method continues here…

    View Slide

  16. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 15
    jgs
    void gluBeginCurve(GLUnurbsObj * nobj)
    Start NURBS curve rendering.
    void gluEndCurve(GLUnurbsObj * nobj)
    Stop NURBS curve rendering.
    void gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot,
    GLint stride, GLfloat * ctlpoints, GLint order, GLenum type)
    nobj: Pointer to NURBS object
    nknots: Number of knot values
    knot: Array of knot values
    stride: Offset between consecutive control point data in ctlpoints
    ctlpoints: Array of control point coordinates
    order: Blending function degree plus one.
    type: Any valid one-dimensional evaluator types. Such as GL_MAP1_VERTEX_3,
    GL_MAP1_COLOR_4, etc.
    gluBeginCurve, gluNurbsCurve, gluEndCurve

    View Slide

  17. jgs
    Surfaces using OpenGL Support

    View Slide

  18. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 17
    jgs
    Screenshot
    https://github.com/javiergs/SER431/blob/master/Lecture19/surface_bezier.cpp
    https://github.com/javiergs/SER431/blob/master/Lecture19/nurbs_surface_grid.cpp

    View Slide

  19. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 18
    jgs
    Code
    // control points
    GLfloat ctlpoints[4][4][3] = {
    { { 20, 0, 10 },{ 0, 0, 10 },{ -5, 0, 10 },{ -10, 0, 10 } },
    { { 20, 0, 5 },{ 0, 15, 5 },{ -5, 15, 5 },{ -10, 0, 5 } },
    { { 20, 0, -5 },{ 0, 10, -5 },{ -5, 10, -5 },{ -10, 0, -5 } },
    { { 20, 0, -10 },{ 0, 0, -10 },{ -5, 0, -10 },{ -10, 0, -10 } }
    };
    GLfloat knots[8] = { 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 3.0 };
    GLUnurbsObj *theNurb;
    // init
    void init(void) {
    theNurb = gluNewNurbsRenderer();
    gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);
    gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
    }

    View Slide

  20. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 19
    jgs
    // display
    void display(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    gluLookAt(2, 2, -6.5, 0, 0, 0, 0, 1, 0);
    glPushMatrix();
    glScalef(0.125, 0.125, 0.125);
    // NURBS
    glColor3f(0, 1, 0);
    gluBeginSurface(theNurb);
    gluNurbsSurface(theNurb,
    8, knots, 8, knots, // knots u and v
    4 * 3, 3, // offset u and v
    &ctlpoints[0][0][0],
    4, 4, // function degree u and v
    GL_MAP2_VERTEX_3);
    gluEndSurface(theNurb);
    // more ...
    }

    View Slide

  21. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 20
    jgs
    void gluNurbsProperty( GLUnurbsObj *nobj, GLenum property, TYPE value)
    property = GLU_DISPLAY_MODE
    Specify how NURBS surface is rendered.
    value Meaning
    GLU_FILL The surface is rendered as filled polygons. (Default value)
    GLU_OUTLINE_POLYGON Only render outlines of the polygons.
    GLU_OUTLINE_PATCH Only render outlines of patches and trimming curves.
    gluNurbsProperty
    property = GLU_SAMPLING_METHOD
    Specify how NURBS surface is tessellated.
    Value Meaning
    GLU_PATH_LENGTH Specify the maximum length, in pixels, of the edges of the
    tessellated polygons. (Default value)
    GLU_PARAMETRIC_ERROR Specify the maximum distance, in pixels, between the
    tessellated polygons and the true NURBS surface.
    GLU_DOMAIN_DISTANCE Specify, in parametric coordinates, how many sample points
    per unit length in u and v directions.

    View Slide

  22. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 21
    jgs
    property = GLU_SAMPLING_TOLERANCE
    Specify the maximum length, in pixels, to be used when the sampling
    method is set to GLU_PATH_LENGTH. Default value is 50.0.
    property = GLU_PARAMETRIC_TOLERANCE
    Specify the maximum length, in pixels, to be used when the sampling
    method is set to GLU_PARAMETRIC_ERROR. Default value is 0.5.
    property = GLU_U_STEP
    Specify the number of sample points per unit length in u direction when
    sampling method is set to GLU_DOMAIN_DISTANCE. Default value is 100.
    property = GLU_V_STEP
    Specify the number of sample points per unit length in v direction when
    sampling method is set to GLU_DOMAIN_DISTANCE. Default value is 100.

    View Slide

  23. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 22
    jgs
    void gluBeginSurface(GLUnurbsObj * nobj)
    Start NURBS surface rendering.
    void gluEndSurface(GLUnurbsObj * nobj)
    Stop NURBS surface rendering.
    gluBeginCurve, gluNurbsCurve, gluEndCurve
    nobj: Pointer to NURBS object
    uknot_count: Number of knot values in u direction
    uknot: Array of knot values in u direction
    vknot_count: Number of knot values in v direction
    vknot: Array of knot values in v direction
    ustride: Offset between consecutive control point data in ctlpoints in u
    direction
    vstride: Offset between consecutive control point data in ctlpoints in v
    direction
    ctlpoints: 2D Array of control point coordinates
    uorder: Blending function degree plus one for u direction.
    vorder: Blending function degree plus one for v direction.
    type: Any valid two-dimensional evaluator types.
    void gluNurbsSurface(GLUnurbsObj * nobj, GLint uknot_count, GLfloat * uknot,
    GLint vknot_count, GLfloat * vknot,
    GLint ustride, GLint vstride, GLfloat * ctlpoints,
    GLint uorder, GLint vorder, GLenum type)

    View Slide

  24. jgs
    Surfaces using OpenGL Support
    Solid Shape with Materials and Light

    View Slide

  25. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 24
    jgs
    Screenshot
    https://github.com/javiergs/SER431/blob/master/Lecture19/nurbs_surface_grid.cpp
    https://github.com/javiergs/SER431/blob/master/Lecture19/nurbs_surface_solid.cpp

    View Slide

  26. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 25
    jgs
    Code
    // same control points and knots that before
    GLUnurbsObj *theNurb;
    // init
    void init(void) {
    // Materials and Light
    GLfloat mat_diffuse[] = { 1.0f, 0.5f, 0.31f, 1. };
    GLfloat mat_specular[] = { 0.5f, 0.5f, 0.5f, 1. };
    GLfloat mat_ambient[] = { 1.0f, 0.5f, 0.31f, 1. };
    GLfloat mat_shininess[] = { 100.0 };
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
    glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST);
    // We need normals
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);
    theNurb = gluNewNurbsRenderer();
    gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);
    gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
    }

    View Slide

  27. Javier Gonzalez-Sanchez | SER431 | Fall 2018 | 26
    jgs
    Homework
    § Review the source codes posted on GitHub

    View Slide

  28. jgs
    SER431 Advanced Graphics
    Javier Gonzalez-Sanchez
    [email protected]
    Fall 2018
    Disclaimer. These slides can only be used as study material for the class SER431 at ASU. They cannot be
    distributed or used for another purpose.

    View Slide