Click here to Skip to main content
15,892,927 members
Articles / Desktop Programming / MFC

Basic Curves And Surfaces Modeler

Rate me:
Please Sign up or sign in to vote.
4.17/5 (40 votes)
18 Apr 2012CPOL3 min read 248K   16.4K   117  
A basic demo of modeling curves and surfaces in OpenGL.
// GLSurface.cpp: implementation of the CGLSurface class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "GLSurface.h"
#include "MMath.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CGLSurface::CGLSurface(const CSurface* s)
{
    pSurf = s->Copy();
    glObjType = GLSURFACE;
    glObjID = (int)glObjType + CGLObject::GetCount();
    SMOOTH = 100;
    CSMOOTH = 100;

    itsShadeRed = 150;
    itsShadeGreen = 150;
    itsShadeBlue = 150;

    itsRed = 200;
    itsGreen = 225;
    itsBlue = 50;

    isoRed = 205;
    isoGreen = 205;
    isoBlue = 255;

    factor = 1;
    pattern = 0x5555;

    SetMaterial(BRONZE);

    pointList = new CListOfCPoint3D;
    pointWFUList = new CListOfCPoint3D;
    pointWFVList = new CListOfCPoint3D;
    normalList = new CListOfCPoint3D;
    bpointList = new CListOfCPoint3D;

    myListWFUIter.SetList(pointWFUList);
    myListWFVIter.SetList(pointWFVList);

    ComputePoints();
    ComputeWFPoints();
    ComputeBoundLimits();
    InitDisplayList();
}

CGLSurface::~CGLSurface()
{
    if(pointList)
    {
	pointList->Clear();
	delete pointList;
    }
    if(pointWFUList)
    {
	pointWFUList->Clear();
	delete pointWFUList;
    }
    if(pointWFVList)
    {
	pointWFVList->Clear();
	delete pointWFVList;
    }
    if(normalList)
    {
	normalList->Clear();
	delete normalList;
    }
    if(bpointList)
    {
	bpointList->Clear();
	delete bpointList;
    }
    glDeleteLists(wireList, 1);
    glDeleteLists(edgeList, 1);
    glDeleteLists(shadList, 1);
    delete pSurf;
}

CGLObject* CGLSurface::Copy() const
{
    CGLSurface* S = new CGLSurface(pSurf);
    S->SetColor(itsRed, itsGreen, itsBlue);
    S->SetMaterial(GetMaterial());
    S->glObjID = glObjID;
    return S;
}

void CGLSurface::DefineDisplay()
{
    GLfloat bgcol[4];
    glGetFloatv(GL_COLOR_CLEAR_VALUE, bgcol);
    GLfloat  specref[] =  { 1.0f, 1.0f, 1.0f, 1.0f };
    // Enable Depth Testing
    glEnable(GL_DEPTH_TEST);


    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

    // Enable lighting
    glEnable(GL_LIGHTING);


    // Enable color tracking
    glEnable(GL_COLOR_MATERIAL);

    // Set Material properties to follow glColor values
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specref);
    glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,128);

    glShadeModel(GL_SMOOTH);

    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);

    if(displayMode == GLSHADED)
    {	
	glPushAttrib(GL_LIGHTING_BIT);
	ApplyMaterial();
	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(8, 8);
	DrawShaded();	
	glDisable(GL_LIGHTING);
	glDisable(GL_COLOR_MATERIAL);
	glColor3ub(25, 25, 25);
	DrawEdges();
	glDisable(GL_POLYGON_OFFSET_FILL);
	glPopAttrib();
    }	
    else if(displayMode == GLWIREFRAME)
    {
	glPushAttrib(GL_LIGHTING_BIT);
	glDisable(GL_LIGHTING);
	glDisable(GL_COLOR_MATERIAL);
	glDisable(GL_DEPTH_TEST);
	glColor3ub(itsRed, itsGreen, itsBlue);
	DrawWired();
	glPopAttrib();
    }
    else if(displayMode == GLHLREMOVED)
    {	
	glPushAttrib(GL_LIGHTING_BIT);
	glDisable(GL_LIGHTING);
	glDisable(GL_COLOR_MATERIAL);
	glEnable(GL_DEPTH_TEST);

	glColor3f(bgcol[0], bgcol[1], bgcol[2]);
	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(5, 5);
	DrawShaded();
	DrawWired();

	glDisable(GL_POLYGON_OFFSET_FILL);
	glPopAttrib();
    }
}

void CGLSurface::Display(const GLDisplayMode& dMode)
{
    displayMode = dMode;
    DefineDisplay();
}

void CGLSurface::Hilight(const GLDisplayMode&)
{
    glPushAttrib(GL_LIGHTING_BIT);
    glDisable(GL_LIGHTING);
    glDisable(GL_COLOR_MATERIAL);
    glDisable(GL_DEPTH_TEST);
    itsRed = 0; itsGreen = 255; itsBlue = 255;
    isoRed = 0; isoGreen = 255; isoBlue = 255;
    glColor3ub(itsRed, itsGreen, itsBlue);
    DrawWired();
    glPopAttrib();
}

void CGLSurface::SetColor(const GLubyte& red, const GLubyte& green, const GLubyte& blue)
{
    if(displayMode == GLWIREFRAME)
    {
	itsRed = red;
	itsGreen = green;
	itsBlue = blue;
    }
    else
    {
	itsShadeRed = red;
	itsShadeGreen = green;
	itsShadeBlue = blue;
    }
    DefineDisplay();
}

void CGLSurface::GetColor(GLubyte* colVect) const
{
    colVect = new GLubyte[3];
    if(displayMode == GLWIREFRAME)
    {
	colVect[0] = itsRed;
	colVect[1] = itsGreen;
	colVect[2] = itsBlue;
    }
    else
    {

	colVect[0] = itsShadeRed;
	colVect[1] = itsShadeGreen;
	colVect[2] = itsShadeBlue;
    }
}

void CGLSurface::SetSurface(const CSurface* s)
{
    pSurf = s->Copy();
    ComputePoints();
    ComputeBoundLimits();
}

CGeometry* CGLSurface::Geometry() const
{
    CSurface* surf = pSurf->Copy();
    return surf;
}

void CGLSurface::ComputeBoundLimits()
{
    /*
       if(pSurf->IsOfType(SPHERE))
       {
       CSphere* pSph = static_cast<CSphere*> (pSurf);
       double rad = pSph->GetRadius();
       CPoint3D P = pSph->GetLocation().GetPosition();
       itsBox.SetLimits(-rad+P.GetX(), rad+P.GetX(), -rad+P.GetY(), rad+P.GetY(), -rad+P.GetZ(), rad+P.GetZ());
       return;
       }
       double lx=0,ly=0,lz=0,sx=0,sy=0,sz=0;
       CPoint3D P;
       QList<double> pxArray, pyArray, pzArray;
       pxArray.setAutoDelete(TRUE);
       pyArray.setAutoDelete(TRUE);
       pzArray.setAutoDelete(TRUE);

       CListIteratorOfListOfCPoint3D myListIter(bpointList);
       for(myListIter.Init(); myListIter.More(); myListIter.Next())
       {
       P = myListIter.Current();	
       double *x = new double, *y = new double, *z = new double;
     *x = P.GetX(); *y = P.GetY(); *z = P.GetZ();
     pxArray.append(x);
     pyArray.append(y);
     pzArray.append(z);
     }
     pxArray.sort();
     pyArray.sort();
     pzArray.sort();
     sx = *pxArray.first();  lx = *pxArray.last();
     sy = *pyArray.first();  ly = *pyArray.last();
     sz = *pzArray.first();  lz = *pzArray.last();

     itsBox.SetLimits(sx,lx,sy,ly,sz,lz);
     */
}

void CGLSurface::ComputePoints()
{
    SMOOTH *= 6;

    CPoint3D curP1;
    double uparts, vparts, istep, jstep;
    double fUPar, lUPar, fVPar, lVPar;

    double i, j;

    fUPar = pSurf->FirstUParameter();
    lUPar = pSurf->LastUParameter();

    fVPar = pSurf->FirstVParameter();
    lVPar = pSurf->LastVParameter();

    uparts = vparts = SMOOTH/15;

    istep = fabs(lUPar-fUPar)/uparts;
    jstep = fabs(lVPar-fVPar)/vparts;

    if(pointList && (!pointList->IsEmpty()))
	pointList->Clear();
    if(normalList && (!normalList->IsEmpty()))
	normalList->Clear();
    if(bpointList && (!bpointList->IsEmpty()))
	bpointList->Clear();


    for(j = fVPar; j <= lVPar; j += jstep)
    {
	for(i = fUPar; i <= lUPar; i += istep)
	{
	    curP1 = pSurf->PointAtPara(i, j);
	    bpointList->Append(curP1);
	}
    }

    CPoint3D curP; CVector3D N;

    for(j = fVPar; j < lVPar; j += jstep)
    {
	for(i = fUPar; i < lUPar; i += istep)
	{
	    curP = pSurf->PointAtPara(i, j);
	    N = pSurf->NormalAt(i,j);

	    N.Normalize();
	    normalList->Append(N.Point());
	    pointList->Append(curP);

	    curP = pSurf->PointAtPara(i, j+jstep);
	    N = pSurf->NormalAt(i,j+jstep);
	    N.Normalize();
	    normalList->Append(N.Point());
	    pointList->Append(curP);
	}
	curP = pSurf->PointAtPara(lUPar, j);
	N = pSurf->NormalAt(lUPar,j);
	N.Normalize();
	normalList->Append(N.Point());
	pointList->Append(curP);

	curP = pSurf->PointAtPara(lUPar, j+jstep);
	N = pSurf->NormalAt(lUPar,j+jstep);
	N.Normalize();

	normalList->Append(N.Point());
	pointList->Append(curP);
    }
}

void CGLSurface::ComputeWFPoints()
{
    double fUPar = pSurf->FirstUParameter();
    double lUPar = pSurf->LastUParameter();
    double fVPar = pSurf->FirstVParameter();
    double lVPar = pSurf->LastVParameter();
    double parts;
    if(pSurf->IsOfType(EXTRUDED) || pSurf->IsOfType(RULED))
	parts = 2;
    else
	parts = 3;
    double ustep = fabs(lUPar-fUPar)/parts;
    double vstep = fabs(lVPar-fVPar)/parts;
    double i;

    //Compute U ISO Lines
    ComputeUIso(fVPar);	//Edge
    for(i = fVPar+vstep; i < lVPar; i += vstep)
	ComputeUIso(i);
    ComputeUIso(lVPar);	//Edge

    //Compute V ISO Lines
    ComputeVIso(fUPar);	//Edge
    for(i = fUPar+ustep; i <= lUPar; i += ustep)
	ComputeVIso(i);
    ComputeVIso(lUPar);	//Edge
}

void CGLSurface::ComputeUIso(const double vPar)
{
    double fPar = pSurf->FirstUParameter();
    double lPar = pSurf->LastUParameter();
    double parts = CSMOOTH;
    double step = fabs(lPar-fPar)/parts;
    double i;
    CPoint3D curP;

    for(i = fPar; i <= lPar; i += step)
    {
	curP = pSurf->PointAtPara(i, vPar);
	pointWFUList->Append(curP);
    }
    curP = pSurf->PointAtPara(lPar, vPar);
    pointWFUList->Append(curP);
}

void CGLSurface::ComputeVIso(const double uPar)
{
    double fPar = pSurf->FirstVParameter();
    double lPar = pSurf->LastVParameter();
    double parts = CSMOOTH;
    double step = fabs(lPar-fPar)/parts;
    double i;
    CPoint3D curP;

    for(i = fPar; i <= lPar; i += step)
    {
	curP = pSurf->PointAtPara(uPar, i);
	pointWFVList->Append(curP);
    }
    curP = pSurf->PointAtPara(uPar, lPar);
    pointWFVList->Append(curP);
}

void CGLSurface::DrawUIso()
{
    double fPar = pSurf->FirstUParameter();
    double lPar = pSurf->LastUParameter();
    double parts = CSMOOTH;
    double step = fabs(lPar-fPar)/parts;
    double i;
    CPoint3D curP;

    glColor3ub(isoRed, isoGreen, isoBlue);
    glBegin(GL_LINE_STRIP);
    for(i = fPar; i <= lPar; i += step)
    {
	curP = myListWFUIter.Current();
	glVertex3d(curP.GetX(), curP.GetY(), curP.GetZ());
	myListWFUIter.Next();
    }
    curP = myListWFUIter.Current();
    glVertex3d(curP.GetX(), curP.GetY(), curP.GetZ());
    myListWFUIter.Next();
    glEnd();
}

void CGLSurface::DrawVIso()
{
    double fPar = pSurf->FirstVParameter();
    double lPar = pSurf->LastVParameter();
    double parts = CSMOOTH;
    double step = fabs(lPar-fPar)/parts;
    double i;
    CPoint3D curP;

    glColor3ub(isoRed, isoGreen, isoBlue);
    glBegin(GL_LINE_STRIP);
    for(i = fPar; i <= lPar; i += step)
    {
	curP = myListWFVIter.Current();
	glVertex3d(curP.GetX(), curP.GetY(), curP.GetZ());
	myListWFVIter.Next();
    }
    curP = myListWFVIter.Current();
    glVertex3d(curP.GetX(), curP.GetY(), curP.GetZ());
    myListWFVIter.Next();
    glEnd();
}

void CGLSurface::DrawWired()
{
    myListWFUIter.Init();
    myListWFVIter.Init();
    double fUPar = pSurf->FirstUParameter();
    double lUPar = pSurf->LastUParameter();
    double fVPar = pSurf->FirstVParameter();
    double lVPar = pSurf->LastVParameter();
    double parts;
    if(pSurf->IsOfType(EXTRUDED) || pSurf->IsOfType(RULED))
	parts = 2;
    else
	parts = 3;
    double ustep = fabs(lUPar-fUPar)/parts;
    double vstep = fabs(lVPar-fVPar)/parts;
    double i;

    glLineStipple(factor,pattern);

    //Draw U ISO Lines
    isoRed = itsRed;
    isoGreen = itsGreen;
    isoBlue = itsBlue;
    glDisable(GL_LINE_STIPPLE);
    DrawUIso();	//Edge
    for(i = fVPar+vstep; i < lVPar; i += vstep)
    {
	isoRed = 205;
	isoGreen = 205;
	isoBlue = 255;
	glEnable(GL_LINE_STIPPLE);
	DrawUIso();
    }
    isoRed = itsRed;
    isoGreen = itsGreen;
    isoBlue = itsBlue;
    glDisable(GL_LINE_STIPPLE);
    DrawUIso();	//Edge

    //Draw V ISO Lines
    DrawVIso();	//Edge
    for(i = fUPar+ustep; i <= lUPar; i += ustep)
    {	
	isoRed = 205;
	isoGreen = 205;
	isoBlue = 255;
	glEnable(GL_LINE_STIPPLE);
	DrawVIso();
    }
    isoRed = itsRed;
    isoGreen = itsGreen;
    isoBlue = itsBlue;
    glDisable(GL_LINE_STIPPLE);
    DrawVIso();	//Edge

    glDisable(GL_LINE_STIPPLE);
}

void CGLSurface::DrawShaded()
{
    CPoint3D curP; CPoint3D N;
    double uparts, vparts, istep, jstep;
    double fUPar, lUPar, fVPar, lVPar;

    double i, j;

    fUPar = pSurf->FirstUParameter();
    lUPar = pSurf->LastUParameter();

    fVPar = pSurf->FirstVParameter();
    lVPar = pSurf->LastVParameter();

    uparts = vparts = SMOOTH/15;

    istep = fabs(lUPar-fUPar)/uparts;
    jstep = fabs(lVPar-fVPar)/vparts;

    CListIteratorOfListOfCPoint3D myListIterP(pointList);
    CListIteratorOfListOfCPoint3D myListIterN(normalList);
    myListIterP.Init();
    myListIterN.Init();


    if(displayMode == GLSHADED) 
	glColor3ub(itsShadeRed, itsShadeGreen, itsShadeBlue);
    //else HLR

    glFrontFace(GL_CW);
    for(j = fVPar; j < lVPar; j += jstep)
    {
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glBegin(GL_TRIANGLE_STRIP);
	for(i = fUPar; i < lUPar; i += istep)
	{
	    curP = myListIterP.Current();
	    N = myListIterN.Current();
	    glNormal3d(N.GetX(), N.GetY(), N.GetZ());
	    glVertex3d(curP.GetX(), curP.GetY(), curP.GetZ());
	    myListIterP.Next();
	    myListIterN.Next();

	    curP = myListIterP.Current();
	    N = myListIterN.Current();
	    glNormal3d(N.GetX(), N.GetY(), N.GetZ());
	    glVertex3d(curP.GetX(), curP.GetY(), curP.GetZ());
	    myListIterP.Next();
	    myListIterN.Next();
	}
	curP = myListIterP.Current();
	N = myListIterN.Current();
	glNormal3d(N.GetX(), N.GetY(), N.GetZ());
	glVertex3d(curP.GetX(), curP.GetY(), curP.GetZ());
	myListIterP.Next();
	myListIterN.Next();

	curP = myListIterP.Current();
	N = myListIterN.Current();
	glNormal3d(N.GetX(), N.GetY(), N.GetZ());
	glVertex3d(curP.GetX(), curP.GetY(), curP.GetZ());
	myListIterP.Next();
	myListIterN.Next();

	glEnd();
    }
    glFrontFace(GL_CCW);
}

void CGLSurface::DrawEdges()
{
    myListWFUIter.Init();
    myListWFVIter.Init();
    double fUPar = pSurf->FirstUParameter();
    double lUPar = pSurf->LastUParameter();
    double fVPar = pSurf->FirstVParameter();
    double lVPar = pSurf->LastVParameter();
    double parts;
    if(pSurf->IsOfType(EXTRUDED) || pSurf->IsOfType(RULED))
	parts = 2;
    else
	parts = 3;
    double ustep = fabs(lUPar-fUPar)/parts;
    double vstep = fabs(lVPar-fVPar)/parts;
    double i;

    isoRed = 25;
    isoGreen = 25;
    isoBlue = 25;
    glDisable(GL_LINE_STIPPLE);
    glLineWidth(2.5);
    //Draw U ISO Lines    	
    DrawUIso();	//Edge
    for(i = fVPar+vstep; i < lVPar; i += vstep)
    {			
	DrawUIso();
    }    
    DrawUIso();	//Edge

    //Draw V ISO Lines
    DrawVIso();	//Edge
    for(i = fUPar+ustep; i <= lUPar; i += ustep)
    {		
	DrawVIso();
    }    	
    DrawVIso();	//Edge

    glLineWidth(1.0);
}

void CGLSurface::InitDisplayList()
{
    //wire list
    wireList = glGenLists(1);
    glNewList(wireList, GL_COMPILE);
    DrawWired();
    glEndList();

    //edges list
    edgeList = glGenLists(1);
    glNewList(edgeList, GL_COMPILE);
    DrawEdges();
    glEndList();

    //shaded list
    shadList = glGenLists(1);
    glNewList(shadList, GL_COMPILE);
    DrawShaded();
    glEndList();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Product Manager Mahindra & Mahindra
India India
Sharjith is a Mechanical Engineer with strong passion for Automobiles, Aircrafts and Software development.

Comments and Discussions