Click here to Skip to main content
15,886,362 members
Articles / Desktop Programming / MFC

Drawing Spline Types, Tension and Control Point using OpenGL and MFC

Rate me:
Please Sign up or sign in to vote.
3.47/5 (17 votes)
1 Oct 2000 124.7K   4.4K   45  
This sample teaches you how to create an OpenGL based Spline Drawing application
// MFCSplineView.cpp : implementation of the CMFCSplineView class
//


/*##################################################################

  Author:	Masoud Samimi
  Website:	www.geocities.com/samimi73
  Email:	marcello43@hotmail.com

  Program:	MFC Spline Drawing Demo Application
  
  History:	Original code found from 
			http://www.planet-source-code.com as a GLUT based Spline Drawing Application
			as their copyright appears below.

			It was ported to MFC vesrsion by myself on 22.07.2000 (dd.mm.yy)
  
  Purpose: Please visit my website, it is expalined there.
  

Important Notice:

	This Idea and the Application is Copyright(c) Masoud Samimi 1999,2000.
	You can freely use it as long as you credit me for it.

	No guarantee/warantee is given on this app and I will not be responsible 
	for any damage to you, your property or any other person from using it.
	USE IT ON YOUR OWN RISK.

	Thankyou and have FUNNE =-)

	Masoud Samimi.

 
   Original source code:

    //**************************************
    // Name: OpenGL Spine drawing app
    // Description:It's a Spline Drawing Application that uses the OpenGL Libraries. I used the GLUT event handler interface to control Mouse functions.You will Need:
    // OpenGL
    // Glut
    // and a C++ compiler
    // Found at: http://modzer0.cs.uaf.edu/~hartsock/C_Cpp/OpenGL/Splines.html
    // By: Found on the World Wide Web
    //
    //
    // Inputs:None
    //
    // Returns:None
    //
    //Assumes:None
    //
    //Side Effects:None
    //
    //Warranty:
    //Code provided by Planet Source Code(tm) (http://www.Planet-Source-Code.com) 'as is', without warranties as to performance, fitness, merchantability,and any other warranty (whether expressed or implied).
    //**************************************
    
    /************************************************************************\
    |	
    |	Shawn R. Hartsock
    |	CS 381
    |	Prof: Hartman
    |	due: 11/4/1998
    |
    |	Splines.c
    |		Draws Splines!
    |		Menus: Spline Type, Tension, Reset, Quit
    |		Keys : z,x,i,j,k,l,1,2,3
    |Point: Drag to move spline points
    |Rainbows free of charge.
    | The color (rainbow) allows you to observe the "speed" at which
    | the points are moving along the line toward the end point.
    | Negative tension causes the control points to be weighted heavier...
    | Positive tension up to 1.0 causes the control points to be weighted
    | less, and a tension of 1.0 means that the control points are ignored.
    | A tension of MORE than 1.0 means that the control points "push" the
    | line rather than "pull" it, or vice versa (cardinal spline)... a
    | Positive value greater than 1.0 makes the control points weighted
    | NEGATIVELY.
    \************************************************************************/

//##################################################################

#include "stdafx.h"
#include "math.h"
#include "MFCSpline.h"

#include "MFCSplineDoc.h"
#include "MFCSplineView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif



///////////////////////////////////////////////////////////
// Color Indexes
struct colorIndexState 
{
    GLfloat amb[3];		/* ambient color / bottom of ramp */
    GLfloat diff[3];	/* diffuse color / middle of ramp */
    GLfloat spec[3];	/* specular color / top of ramp */
    GLfloat ratio;		/* ratio of diffuse to specular in ramp */
    GLint indexes[3];	/* where ramp was placed in palette */
};

#define NUM_COLORS (sizeof(colorv) / sizeof(colorv[0]))

struct colorIndexState colorv[] = 
{
    {
        { 0.0F, 0.0F, 0.0F },
        { 0.1F, 0.6F, 0.3F },
        { 1.0F, 1.0F, 1.0F },
        0.75F, { 0, 0, 0 },
    },
    {
        { 0.0F, 0.0F, 0.0F },
        { 0.0F, 0.2F, 0.5F },
        { 1.0F, 1.0F, 1.0F },
        0.75F, { 0, 0, 0 },
    },
    {
        { 0.0F, 0.05F, 0.05F },
        { 0.6F, 0.0F, 0.8F },
        { 1.0F, 1.0F, 1.0F },
        0.75F, { 0, 0, 0 },
    },
};


// Lighting components

GLfloat  ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat  diffuseLight[] = { 0.6f, 0.6f, 0.6f, 1.0f };
GLfloat  specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};

GLfloat m_lightPosX = -100.0f; // Light Position X axis
GLfloat m_lightPosY = -50.0f;	// Light Position Y axis
GLfloat m_lightPosZ = 150.0f;	// Light Position Z axis
GLfloat m_lightPosW = 1.0f;	// Light Position W axis

GLfloat	 lightPos[4] = { m_lightPosX,m_lightPosY,m_lightPosZ,m_lightPosW };


//########################################################
// Spline Data

#ifndef M_PI
#define M_PI 3.14159265359
#endif

# define NUMSTEPS 0.01 /* <-- for win32 compatability */

#define DIST(a,b) sqrt( (a[0] - b[0] ) * ( a[0] - b[0] ) + (a[1] - b[1]) * (a[1] - b[1]) )

double P[4][2] = {
		{0,0}, {50,250}, {300,300}, {350,350}
	}; 

//
//########################################################


/////////////////////////////////////////////////////////////////////////////
// CMFCSplineView

IMPLEMENT_DYNCREATE(CMFCSplineView, CView)

BEGIN_MESSAGE_MAP(CMFCSplineView, CView)
	//{{AFX_MSG_MAP(CMFCSplineView)
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_WM_SIZE()
	ON_WM_DESTROY()
	ON_WM_CREATE()
	ON_WM_QUERYNEWPALETTE()
	ON_WM_PALETTECHANGED()
	ON_COMMAND(ID_SPLINE_TENSION_1, OnSplineTension1)
	ON_COMMAND(ID_SPLINE_TENSION_2, OnSplineTension2)
	ON_COMMAND(ID_SPLINE_TENSION_3, OnSplineTension3)
	ON_COMMAND(ID_SPLINE_TENSION_4, OnSplineTension4)
	ON_COMMAND(ID_SPLINE_TENSION_5, OnSplineTension5)
	ON_COMMAND(ID_SPLINE_TENSION_6, OnSplineTension6)
	ON_COMMAND(ID_SPLINE_TENSION_7, OnSplineTension7)
	ON_COMMAND(ID_SPLINE_TENSION_8, OnSplineTension8)
	ON_COMMAND(ID_SPLINE_TENSION_9, OnSplineTension9)
	ON_COMMAND(ID_SPLINE_TENSION_10, OnSplineTension10)
	ON_COMMAND(ID_SPLINE_TENSION_11, OnSplineTension11)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_1, OnUpdateSplineTension1)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_2, OnUpdateSplineTension2)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_3, OnUpdateSplineTension3)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_4, OnUpdateSplineTension4)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_5, OnUpdateSplineTension5)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_6, OnUpdateSplineTension6)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_7, OnUpdateSplineTension7)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_8, OnUpdateSplineTension8)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_9, OnUpdateSplineTension9)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_10, OnUpdateSplineTension10)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_TENSION_11, OnUpdateSplineTension11)
	ON_COMMAND(ID_SPLINE_RESET, OnSplineReset)
	ON_COMMAND(ID_SLPINE_CARDINAL, OnSlpineCardinal)
	ON_COMMAND(ID_SPLINE_BEZIER, OnSplineBezier)
	ON_COMMAND(ID_SPLINE_HERMITE, OnSplineHermite)
	ON_UPDATE_COMMAND_UI(ID_SLPINE_CARDINAL, OnUpdateSlpineCardinal)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_BEZIER, OnUpdateSplineBezier)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_HERMITE, OnUpdateSplineHermite)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_COMMAND(ID_SPLINE_SELECT_ANCHORPOINT1, OnSplineSelectAnchorpoint1)
	ON_COMMAND(ID_SPLINE_SELECT_ANCHORPOINT2, OnSplineSelectAnchorpoint2)
	ON_COMMAND(ID_SPLINE_SELECT_TANGENTPOINT1, OnSplineSelectTangentpoint1)
	ON_COMMAND(ID_SPLINE_SELECT_TANGENTPOINT2, OnSplineSelectTangentpoint2)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_SELECT_ANCHORPOINT1, OnUpdateSplineSelectAnchorpoint1)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_SELECT_ANCHORPOINT2, OnUpdateSplineSelectAnchorpoint2)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_SELECT_TANGENTPOINT1, OnUpdateSplineSelectTangentpoint1)
	ON_UPDATE_COMMAND_UI(ID_SPLINE_SELECT_TANGENTPOINT2, OnUpdateSplineSelectTangentpoint2)
	ON_WM_CONTEXTMENU()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMFCSplineView construction/destruction

CMFCSplineView::CMFCSplineView()
{
	// TODO: add construction code here
	
	m_ptLMouse = 0;
	m_bLMouseDown = FALSE;
	
	m_nSelectedPoint = 0;
	m_dTension = 0.0;

    m_dScale = 0.02;
    T_Y = 5.0;
	T_X = 5.0;


}

CMFCSplineView::~CMFCSplineView()
{
}

BOOL CMFCSplineView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_OWNDC);

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMFCSplineView drawing

void CMFCSplineView::OnDraw(CDC* pDC)
{
	CMFCSplineDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

		// Make the rendering context current
	wglMakeCurrent(m_hDC,m_hRC);

	// Call to the rendering function
	MainRenderScene();
	
	// Swap our scene to the front
	SwapBuffers(m_hDC);

	// Allow other rendering contexts to co-exist
	wglMakeCurrent(m_hDC,NULL);

	// TODO: add draw code for native data here
}

/////////////////////////////////////////////////////////////////////////////
// CMFCSplineView printing

BOOL CMFCSplineView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMFCSplineView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMFCSplineView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CMFCSplineView diagnostics

#ifdef _DEBUG
void CMFCSplineView::AssertValid() const
{
	CView::AssertValid();
}

void CMFCSplineView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMFCSplineDoc* CMFCSplineView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCSplineDoc)));
	return (CMFCSplineDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMFCSplineView message handlers

BOOL CMFCSplineView::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	return TRUE;
	
}

void CMFCSplineView::OnMouseMove(UINT nFlags, CPoint point) 
{
	    
	CPoint x = m_ptLMouse.x;
	CPoint y = m_ptLMouse.y;


	switch(nFlags){ //1

    case MK_LBUTTON:

		if (m_bLMouseDown){ //2
			for(int ii=0; ii<4; ii++) 
			{ //3
    			if ( (( ( ((m_ptLMouse.x - point.x) / m_dScale) + T_Y)) > (P[ii][0]+10) )&&
    	      	   
				   (( ( ((m_ptLMouse.x - point.x) / m_dScale) + T_Y)) < (P[ii][0]-10) )&&

    			   (( ( ((m_ptLMouse.y - point.y) / m_dScale) + T_X)) > (P[ii][1]+10) )&&
    			   
				   (( ( ((m_ptLMouse.y - point.y) / m_dScale) + T_X)) < (P[ii][1]-10) ))
				{ //4
    			
						m_nMovePoint = ii;	
						Invalidate();
						break;

				} //4

				else m_nMovePoint = 2;//1;//2;//3;//4;
				Invalidate();
				
			} //3
					
		
		if(m_nMovePoint != 4)
		{ //5
    		P[m_nMovePoint][0] = ((m_ptLMouse.x-point.x) / m_dScale) + T_X;
    		P[m_nMovePoint][1] = ((m_ptLMouse.y-point.y) / m_dScale) + T_Y;
    		
			break;
		} //5
		
		} //2	
	
	}//1

	
	CView::OnMouseMove(nFlags, point);
}


void CMFCSplineView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
	wglMakeCurrent(m_hDC,m_hRC);
			
	GLsizei width, height;
	GLdouble aspect;
	width = cx;
	height = cy;
	if (cy==0)
		aspect = (GLdouble)width;
	else
		aspect = (GLdouble)width/(GLdouble)height;
	m_WHRatio = aspect;    //save it for further use.
	glViewport(0, 0, width, height);

	// Reset coordinate system
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

    // Setup perspective for viewing
    gluPerspective(35.0, m_WHRatio, 1, 1000);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

    // Viewing transformation, backup 100 units
    glTranslatef(0.0f, 0.0f, -300.0f);
	glScalef(15.0f, 15.0f, 15.0f); 

	wglMakeCurrent(NULL,NULL);

}

void CMFCSplineView::OnDestroy() 
{
	CView::OnDestroy();
	
	// TODO: Add your message handler code here
		// Clean up rendering context stuff
	wglDeleteContext(m_hRC);
	::ReleaseDC(m_hWnd,m_hDC);

}

int CMFCSplineView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	
		
	int nPixelFormat;					// Pixel format index
	m_hDC = ::GetDC(m_hWnd);			// Get the Device context

	static PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR),	// Size of this structure
		1,								// Version of this structure	
		PFD_DRAW_TO_WINDOW |			// Draw to Window (not to bitmap)
		PFD_SUPPORT_OPENGL |			// Support OpenGL calls in window
		PFD_DOUBLEBUFFER,				// Double buffered mode
		PFD_TYPE_RGBA,					// RGBA Color mode
		24,								// Want 24bit color 
		0,0,0,0,0,0,					// Not used to select mode
		0,0,							// Not used to select mode
		0,0,0,0,0,						// Not used to select mode
		32,								// Size of depth buffer
		0,								// Not used to select mode
		0,								// Not used to select mode
		PFD_MAIN_PLANE,					// Draw in main plane
		0,								// Not used to select mode
		0,0,0 };						// Not used to select mode

	// Choose a pixel format that best matches that described in pfd
	nPixelFormat = ChoosePixelFormat(m_hDC, &pfd);

	// Set the pixel format for the device context
	VERIFY(SetPixelFormat(m_hDC, nPixelFormat, &pfd));

	// Create the rendering context
	m_hRC = wglCreateContext(m_hDC);

	// Make the rendering context current, perform initialization, then
	// deselect it
	VERIFY(wglMakeCurrent(m_hDC,m_hRC));
	
	wglMakeCurrent(NULL,NULL);

	// Create the palette if needed
	InitializePalette();
		
	return 0;
}


// Initializes the CPalette object
void CMFCSplineView::InitializePalette(void)
{

	PIXELFORMATDESCRIPTOR pfd;
    LOGPALETTE* pPal;
    int pixelFormat = GetPixelFormat(m_hDC);
    int paletteSize;

    DescribePixelFormat(m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

    /*
    ** Determine if a palette is needed and if so what size.
    */
    if (pfd.dwFlags & PFD_NEED_PALETTE) 
	{
		paletteSize = 1 << pfd.cColorBits;
    }else 
	if (pfd.iPixelType == PFD_TYPE_COLORINDEX) 
	{
		paletteSize = 4096;
    }else 
	{
		return;
    }

    pPal = (LOGPALETTE*)
	malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
    pPal->palVersion = 0x300;
    pPal->palNumEntries = paletteSize;

    if (pfd.iPixelType == PFD_TYPE_RGBA) 
	{
		/*
		** Fill the logical paletee with RGB color ramps
		*/
		int redMask = (1 << pfd.cRedBits) - 1;
		int greenMask = (1 << pfd.cGreenBits) - 1;
		int blueMask = (1 << pfd.cBlueBits) - 1;
		int i;

		for (i=0; i<paletteSize; ++i) 
		{
			pPal->palPalEntry[i].peRed =
				(((i >> pfd.cRedShift) & redMask) * 255) / redMask;
			pPal->palPalEntry[i].peGreen =
				(((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
			pPal->palPalEntry[i].peBlue =
				(((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
			pPal->palPalEntry[i].peFlags = 0;
		}
    }else 
	{
		int numRamps = NUM_COLORS;
		int rampSize = (paletteSize - 20) / numRamps;
		int extra = (paletteSize - 20) - (numRamps * rampSize);
		int i, r;

		GetSystemPaletteEntries(m_hDC, 0, paletteSize, &pPal->palPalEntry[0]);

		for (r=0; r<numRamps; ++r) 
		{
			int rampBase = r * rampSize + 10;
			PALETTEENTRY *pe = &pPal->palPalEntry[rampBase];
			int diffSize = (int) (rampSize * colorv[r].ratio);
			int specSize = rampSize - diffSize;

			for (i=0; i<rampSize; ++i) 
			{
				GLfloat *c0, *c1;
				GLint a;
	
				if (i < diffSize) 
				{
					c0 = colorv[r].amb;
					c1 = colorv[r].diff;
					a = (i * 255) / (diffSize - 1);
				}else 
				{
					c0 = colorv[r].diff;
					c1 = colorv[r].spec;
					a = ((i - diffSize) * 255) / (specSize - 1);
				}

				pe[i].peRed = (BYTE) (a * (c1[0] - c0[0]) + 255 * c0[0]);
				pe[i].peGreen = (BYTE) (a * (c1[1] - c0[1]) + 255 * c0[1]);
				pe[i].peBlue = (BYTE) (a * (c1[2] - c0[2]) + 255 * c0[2]);
				pe[i].peFlags = PC_NOCOLLAPSE;
			}

			colorv[r].indexes[0] = rampBase;
			colorv[r].indexes[1] = rampBase + (diffSize-1);
			colorv[r].indexes[2] = rampBase + (rampSize-1);
		}

		for (i=0; i<extra; ++i) 
		{
			int index = numRamps*rampSize+10+i;
			PALETTEENTRY *pe = &pPal->palPalEntry[index];

			pe->peRed = (BYTE) 0;
			pe->peGreen = (BYTE) 0;
			pe->peBlue = (BYTE) 0;
		    pe->peFlags = PC_NOCOLLAPSE;
		}
    }

   m_hPalette2 = CreatePalette(pPal);
   free(pPal);

    if(m_hPalette2) 
	{
		SelectPalette(m_hDC, m_hPalette2, FALSE);
		RealizePalette(m_hDC);
    }		
	
}

BOOL CMFCSplineView::EnableRC(HDC m_hDC, HGLRC m_hRC, BOOL bEnable)
{
	if(bEnable)
	{
		if(!wglMakeCurrent(m_hDC, m_hRC))
		{
			if(m_bDisplayErrorMessages)
			{
				LPVOID lpMsgBuf;

				FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
					NULL, GetLastError(),
					MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
					(LPTSTR) &lpMsgBuf, 0, NULL);

				MessageBox( /*NULL,*/ (LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );

				LocalFree( lpMsgBuf );
			}

			TRACE("3DeeZView::EnableRC - wglMakeCurrent failed\n");
			return FALSE;
		}
	}
	else
	{
		wglMakeCurrent(NULL, NULL);\
	}

	return TRUE;
}



BOOL CMFCSplineView::OnQueryNewPalette() 
{
	// If the palette was created.
	if((HPALETTE)m_GLPalette)
		{
		int nRet;

		// Selects the palette into the current device context
		SelectPalette(m_hDC, (HPALETTE)m_GLPalette, FALSE);

		// Map entries from the currently selected palette to
		// the system palette.  The return value is the number 
		// of palette entries modified.
		nRet = RealizePalette(m_hDC);

		// Repaint, forces remap of palette in current window
		InvalidateRect(NULL,FALSE);

		return nRet;
		}

	return CView::OnQueryNewPalette();
}

void CMFCSplineView::OnPaletteChanged(CWnd* pFocusWnd) 
{
	if(((HPALETTE)m_GLPalette != NULL) && (pFocusWnd != this))
		{
		// Select the palette into the device context
		SelectPalette(m_hDC,(HPALETTE)m_GLPalette,FALSE);

		// Map entries to system palette
		RealizePalette(m_hDC);
				
		// Remap the current colors to the newly realized palette
		UpdateColors(m_hDC);
		return;
		}

	CView::OnPaletteChanged(pFocusWnd);
}

void CMFCSplineView::MainRenderScene()
{

	// Main Scene Color of the last selected parameters
	glClearColor(0.0f,0.0f,0.0f,1.0f);
	// Clear the window with current clearing color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	// Hidden surface removal
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_COLOR_MATERIAL);
	
	glShadeModel(GL_SMOOTH);
    glEnable(GL_NORMALIZE);

	glFrontFace(GL_CW);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	// Light to setup propeties
	glEnable(GL_LIGHTING);
	glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0);
	glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
	glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
	glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
	glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
	glEnable(GL_LIGHT0);

	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
	glMaterialfv(GL_FRONT, GL_SPECULAR,specular);
	glMateriali(GL_FRONT,GL_SHININESS,100);
	
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	glEnable(GL_LINE_SMOOTH);
	glEnable(GL_POINT_SMOOTH);

/*	
	// Test for gl drawing only.
	glPushMatrix();
	glPointSize(5.0);
	glBegin(GL_POLYGON);
	glVertex2d(0.0,0.0);
	glVertex2d(0.0,-5.0);
	glVertex2d(-5.0,-5.0);
	glVertex2d(-5.0,0.0);
	glEnd();
	glPopMatrix();

*/
//########################################################
// Spline drawing code
	
	   	glPushMatrix();
    	
		glTranslated((-T_X),(-T_Y),0); /* move */
		glScaled(m_dScale, m_dScale, 1);/* Zoom */
    	
    	
	/* Draw Here */
    	
    if(m_nSelectedPoint == 0){ 
		DrawArrows(P[0],P[1]); DrawArrows(P[2],P[3]);
		}
    	
		DrawSpline();
    	DrawPoints();
    	
		glPopMatrix();

    	
	glFlush();



}

void CMFCSplineView::DrawPoints()
{

	glPushMatrix();

	glPointSize(6);
	glBegin(GL_POINTS);
	glColor3d(0.9, 0.1, 0.1);

		for(int i=0; i<4; i++)
			glVertex2i( (int) P[i][0], (int) P[i][1] );
	glColor3d(1.0, 1.0, 1.0);
	glEnd();
	glPointSize(1.0);
	
	glPopMatrix();

}

void CMFCSplineView::DrawArrows(double w1[2], double w2[2])
{
	
	glPushMatrix();
    	glTranslated(w1[0],w1[1],0); 
    	glRotated(atan2(w2[1]-w1[1],w2[0]-w1[0])*180/M_PI,0,0,1);
    	
		glScaled( DIST(w1,w2), DIST(w1,w2) ,1);

    	/* The portion of the code up to here may be useful in subsequent
    	programs. We have transformed coordinate space so that w1 has been
    	mapped to (0,0) and w2 has been mapped to (1,0). */
    	
		glBegin(GL_LINES);
    	glColor3d(0.9,0.9,0.2);
    	glVertex2d(0.0,0.0); glVertex2d(1.0,0.0);
    	glVertex2d(0.9,0.02); glVertex2d(1.0,0.0);
    	glVertex2d(0.9,-0.02); glVertex2d(1.0,0.0);
    	glColor3d(1.0,1.0,1.0);
    	glEnd();
    	glPopMatrix();
	
}

double CMFCSplineView::StartPoint(int i)
{
	if(m_nSelectedPoint == 2) return P[1][i]; /*P2*/
    	else return P[0][i]; /*P1*/
}

double CMFCSplineView::EndPoint(int i)
{
	if(m_nSelectedPoint == 1)	return P[3][i]; /*P4*/
    	else		return P[2][i]; /*P3*/
}

double CMFCSplineView::StartTangent(int i)
{

	if(m_nSelectedPoint == 0){	
		return((1 - m_dTension)*(P[1][i] - P[0][i]) ); }
    
	if(m_nSelectedPoint == 1){
		return( 3 * (1 - m_dTension)*(P[1][i] - P[0][i]) ); }

    if(m_nSelectedPoint == 2){
		return((1 - m_dTension)*(P[2][i] - P[0][i]) /2 ); }
    
		else return 0.0;

}

double CMFCSplineView::EndTangent(int i)
{

	if(m_nSelectedPoint == 0){	
		return((1 - m_dTension)*(P[3][i] - P[2][i]) ); }
    
	if(m_nSelectedPoint == 1){	
		return( 3 * (1-m_dTension)*(P[3][i] - P[2][i]) ); }
    
	if(m_nSelectedPoint == 2){	
		return((1 - m_dTension)*(P[3][i] - P[1][i])/2 ); }
    	
		else return 0.0;

}

void CMFCSplineView::MakeSpline()
{

	   	double R,G,B,t, vv[2];
    	double inc;
    	inc = NUMSTEPS;
    	R = 1.0; G = 0.7; B = 0.0;
    	for(t=0; t<=1; t+=inc){
    		for(int i=0; i<2; i++){
    			
				vv[i] = ((2*t*t*t)-(3*t*t)+1)*StartPoint(i)
    				+ ((-2*t*t*t)+(3*t*t))*EndPoint(i)
    				+ ((t*t*t)-(2*t*t)+t)*StartTangent(i)
    				+ ((t*t*t)-(t*t))*EndTangent(i);
    		}
    		R -= t * 0.08;
    		B += t * 0.08;
    		glColor3d(R,G,B);
    	 glVertex2dv(vv);
    	}

}

void CMFCSplineView::DrawSpline()
{

		glBegin(GL_LINE_STRIP);
    	MakeSpline();
    	glEnd();

}


void CMFCSplineView::OnSplineTension1() 
{
	// TODO: Add your command handler code here
	m_dTension = -2.0;
	Invalidate();

}

void CMFCSplineView::OnSplineTension2() 
{
	// TODO: Add your command handler code here
	m_dTension = -1.0;
	Invalidate();
}

void CMFCSplineView::OnSplineTension3() 
{
	// TODO: Add your command handler code here
	m_dTension = -0.5;
	Invalidate();
}

void CMFCSplineView::OnSplineTension4() 
{
	// TODO: Add your command handler code here
	m_dTension = 0.0;
	Invalidate();
}

void CMFCSplineView::OnSplineTension5() 
{
	// TODO: Add your command handler code here
	m_dTension = 0.2;
	Invalidate();
}

void CMFCSplineView::OnSplineTension6() 
{
	// TODO: Add your command handler code here
	m_dTension = 0.4;
	Invalidate();
}

void CMFCSplineView::OnSplineTension7() 
{
	// TODO: Add your command handler code here
	m_dTension = 0.6;
	Invalidate();
}

void CMFCSplineView::OnSplineTension8() 
{
	// TODO: Add your command handler code here
	m_dTension = 0.8;
	Invalidate();
}

void CMFCSplineView::OnSplineTension9() 
{
	// TODO: Add your command handler code here
	m_dTension = 1.0;
	Invalidate();
}

void CMFCSplineView::OnSplineTension10() 
{
	// TODO: Add your command handler code here
	m_dTension = 2.0;
	Invalidate();
}

void CMFCSplineView::OnSplineTension11() 
{
	// TODO: Add your command handler code here
	m_dTension = 4.0;
	Invalidate();
}

void CMFCSplineView::OnUpdateSplineTension1(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==-2.0); 
}

void CMFCSplineView::OnUpdateSplineTension2(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==-1.0);
}

void CMFCSplineView::OnUpdateSplineTension3(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==-0.5);
}

void CMFCSplineView::OnUpdateSplineTension4(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==0.0);
}

void CMFCSplineView::OnUpdateSplineTension5(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==0.2);
}

void CMFCSplineView::OnUpdateSplineTension6(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==0.4);
}

void CMFCSplineView::OnUpdateSplineTension7(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==0.6);
}

void CMFCSplineView::OnUpdateSplineTension8(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==0.8);
}

void CMFCSplineView::OnUpdateSplineTension9(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==1.0);
}

void CMFCSplineView::OnUpdateSplineTension10(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==2.0);
}

void CMFCSplineView::OnUpdateSplineTension11(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetRadio(m_dTension==4.0);
}


void CMFCSplineView::OnSplineReset() 
{
	// TODO: Add your command handler code here
	

		 P[0][0] = 0;
		 P[0][1] = 0;
		 
		 P[1][0] = 1;
		 P[1][1] = 20;

    	 P[2][0] = 15;
		 P[2][1] = 15;
		 
		 P[3][0] = 5;
		 P[3][1] = 20;
	

    	 T_Y = 5.0000;
		 T_X = 5.0000;
    		 
		 m_dScale = 0.5;
    	 m_dTension = 0.0;
    	 m_nSelectedPoint = 0;

		 
		 Invalidate();

    		 
}

void CMFCSplineView::OnSlpineCardinal() 
{
	// TODO: Add your command handler code here
	m_nSelectedPoint = 0;
	Invalidate();

}

void CMFCSplineView::OnSplineBezier() 
{
	// TODO: Add your command handler code here
	m_nSelectedPoint = 1;
	Invalidate();

}

void CMFCSplineView::OnSplineHermite() 
{
	// TODO: Add your command handler code here
	m_nSelectedPoint = 2;
	Invalidate();

}

void CMFCSplineView::OnUpdateSlpineCardinal(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(m_nSelectedPoint == 0);
}

void CMFCSplineView::OnUpdateSplineBezier(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(m_nSelectedPoint == 1);
}

void CMFCSplineView::OnUpdateSplineHermite(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(m_nSelectedPoint == 2);
}

void CMFCSplineView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	m_ptLMouse = point;
	m_bLMouseDown = TRUE;
	SetCapture();

	Invalidate();

	HCURSOR hCursor = NULL;
    CWinApp *cWinApp = AfxGetApp ();
	hCursor = cWinApp->LoadCursor(IDC_CURSOR_CROSS);
	SetCursor(hCursor);
   
	CView::OnLButtonDown(nFlags, point);
}

void CMFCSplineView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	m_ptLMouse = 0;
	m_bLMouseDown = FALSE;
	ReleaseCapture();

	Invalidate();

	HCURSOR hCursor = NULL;
    CWinApp *cWinApp = AfxGetApp ();
	hCursor = LoadCursor (NULL, IDC_ARROW);
	SetCursor(hCursor);
	
	CView::OnLButtonUp(nFlags, point);
}

void CMFCSplineView::OnSplineSelectAnchorpoint1() 
{
	// TODO: Add your command handler code here
	m_nSelectedPoint = 1;
	Invalidate();

}

void CMFCSplineView::OnSplineSelectAnchorpoint2() 
{
	// TODO: Add your command handler code here
	m_nSelectedPoint = 2;
	Invalidate();
}

void CMFCSplineView::OnSplineSelectTangentpoint1() 
{
	// TODO: Add your command handler code here
	m_nSelectedPoint = 3;
	Invalidate();
}

void CMFCSplineView::OnSplineSelectTangentpoint2() 
{
	// TODO: Add your command handler code here
	m_nSelectedPoint = 4;
	Invalidate();
}

void CMFCSplineView::OnUpdateSplineSelectAnchorpoint1(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(m_nSelectedPoint == 1);
}

void CMFCSplineView::OnUpdateSplineSelectAnchorpoint2(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(m_nSelectedPoint == 2);
}

void CMFCSplineView::OnUpdateSplineSelectTangentpoint1(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(m_nSelectedPoint == 3);
}

void CMFCSplineView::OnUpdateSplineSelectTangentpoint2(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(m_nSelectedPoint == 4);
}

void CMFCSplineView::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	// TODO: Add your message handler code here
		// make sure window is active
	GetParentFrame()->ActivateFrame();

	CPoint local = point;
	ScreenToClient(&local);

		CMenu menu;
		if (menu.LoadMenu(ID_POPUP_MENU))
		{
			CMenu* pPopup = menu.GetSubMenu(0);
			ASSERT(pPopup != NULL);

			pPopup->TrackPopupMenu(TPM_RIGHTBUTTON | TPM_LEFTALIGN,
								   point.x, point.y,
								   AfxGetMainWnd()); // route commands through main window
		}

}

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Technical Lead Samimi Information Technology
United Arab Emirates United Arab Emirates
My company provides services in the fields of:

LAN/WAN Networking
Data Management and Security
Data Recovery
ERP/CRM Solutions
IT Infrastructure Solutions
Software/Hardware Sales/Service

Comments and Discussions