3dObjectNURB.cpp
资源名称:gloop.zip [点击查看]
上传用户:shxiangxiu
上传日期:2007-01-03
资源大小:1101k
文件大小:14k
源码类别:
OpenGL
开发平台:
Visual C++
- /////////////////////////////////////////////////////////////////////////////
- // 3dObjectNURB.cpp : implementation file
- //
- // glOOP (OpenGL Object Oriented Programming library)
- // Copyright (c) Craig Fahrnbach 1997, 1998
- //
- // OpenGL is a registered trademark of Silicon Graphics
- //
- //
- // This program is provided for educational and personal use only and
- // is provided without guarantee or warrantee expressed or implied.
- //
- // Commercial use is strickly prohibited without written permission
- // from ImageWare Development.
- //
- // This program is -not- in the public domain.
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "glOOP.h"
- #include "3dObjectDialog.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- //////////////////////////////////////////////////////////////////
- // C3dObjectNURB Static functions
- // NURBS callback error handler
- void CALLBACK NurbsErrorHandler()
- {
- char cMessage[64];
- GLenum nErrorCode;
- // Get the error code
- nErrorCode = glGetError();
- // Extract the text message of the error
- strcpy(cMessage, "NURBS error occured: ");
- strcat(cMessage, (const char*)gluErrorString(nErrorCode));
- // Display the message to the user
- MessageBox(NULL, cMessage, NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
- //////////////////////////////////////////////////////////////////
- // C3dObjectNURB
- IMPLEMENT_DYNAMIC(C3dObjectNURB, C3dObject)
- /////////////////////////////////////////////////////////////////////////////
- // C3dShape construction
- C3dObjectNURB::C3dObjectNURB()
- {
- // Set the attributes to default values..
- m_iType = SHAPE_OBJECT;
- m_szName.Format("NURB %u", nNURBObjects++);
- m_fDepth = 3.0f;
- m_fWidth = 3.0f;
- m_iUSegments = 10;
- m_iVSegments = 10;
- m_iNumUCtrlPoints = 4;
- m_iNumVCtrlPoints = 4;
- m_hUKnots = NULL;
- m_hVKnots = NULL;
- m_pUKnots = NULL;
- m_pVKnots = NULL;
- // Create a NURBS rendering object
- m_pNURBObj = gluNewNurbsRenderer();
- ASSERT(m_pNURBObj);
- // Install error handler to notify the user of NURBS errors
- gluNurbsCallback(m_pNURBObj, GLU_ERROR, NurbsErrorHandler);
- // Create our C3dPointArray object
- m_pPointArray = new C3dPointArray;
- ASSERT(m_pPointArray);
- // Create an array of points for our vertices
- m_pPointArray->Create(m_iNumUCtrlPoints*m_iNumVCtrlPoints);
- // Initialize our cubes vertices (points)
- InitVertices();
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3DWorld Destructor
- C3dObjectNURB::~C3dObjectNURB()
- {
- // Free our points array memory
- if(m_hUKnots)
- {
- GlobalUnlock(m_hUKnots);
- GlobalFree(m_hUKnots);
- m_hUKnots = NULL;
- m_pUKnots = NULL;
- }
- // Free our points array memory
- if(m_hVKnots)
- {
- GlobalUnlock(m_hVKnots);
- GlobalFree(m_hVKnots);
- m_hVKnots = NULL;
- m_pVKnots = NULL;
- }
- // Delete our point array
- if(m_pPointArray)
- delete m_pPointArray;
- if(m_pNURBObj)
- gluDeleteNurbsRenderer(m_pNURBObj);
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectNURB Methods or virtual function implimentation
- void C3dObjectNURB::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
- {
- C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
- ASSERT(pSheet);
- // Add the page to the property sheet
- pSheet->AddPage(&pSheet->m_NURBPage);
- // Save the address of this object in the page
- pSheet->m_NURBPage.m_pObject = this;
- }
- int C3dObjectNURB::LoadBitMapImage(CImageList* pList)
- {
- CBitmap bitmap;
- // If the image index has been stored in this object,
- // return the index.
- if(m_iBMImage > -1)
- return m_iBMImage;
- // If the image index for this object type has been
- // created, store the index for this object and
- // return the index.
- if( iObjectNURBBMImage > -1) {
- m_iBMImage = iObjectNURBBMImage;
- return m_iBMImage;
- }
- // The image index for this object type has not been
- // loaded and the object image index has not been
- // stored.
- //
- // Load the bitmap for the non-selected light
- bitmap.LoadBitmap(IDB_OBJECT_NURB);
- m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- // Load the bitmap for the non-selected light
- bitmap.LoadBitmap(IDB_OBJECT_NURB_SELECTED);
- pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- iObjectNURBBMImage = m_iBMImage;
- return m_iBMImage;
- }
- void C3dObjectNURB::Serialize(CArchive& ar, int iVersion)
- {
- CString szBuffer;
- if (ar.IsStoring())
- {
- // Save the Object Class header...
- szBuffer.Format("n%sC3dObjectNURB {n", szIndent);
- ar.WriteString(szBuffer);
- // Save the this objects' specific data...
- szBuffer.Format("%stDepth < %f >n", szIndent, m_fDepth);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stWidth < %f >n", szIndent, m_fWidth);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stNumUSegments < %d >n", szIndent, m_iUSegments);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stNumVSegments < %d >n", szIndent, m_iVSegments);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stNumUCtrlPnts < %d >n", szIndent, m_iNumUCtrlPoints);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stNumVCtrlPnts < %d >n", szIndent, m_iNumVCtrlPoints);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stNum Points < %d >n", szIndent, m_pPointArray->m_iNumPoints);
- ar.WriteString(szBuffer);
- for(int i=0; i<m_pPointArray->m_iNumPoints; i++)
- {
- szBuffer.Format("%stt < %f, %f, %f >n", szIndent, m_pPointArray->m_pPoints[i].m_fOrigin[0],
- m_pPointArray->m_pPoints[i].m_fOrigin[1],
- m_pPointArray->m_pPoints[i].m_fOrigin[2]);
- ar.WriteString(szBuffer);
- }
- // Save the base class object data...
- C3dObject::Serialize(ar, iVersion);
- szBuffer.Format("%s}n", szIndent); // end of object def
- ar.WriteString(szBuffer);
- }
- else
- {
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft(); // Remove leading white spaces
- sscanf(szBuffer, "Depth < %f >n", &m_fDepth);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Width < %f >n", &m_fWidth);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "NumUSegments < %d >n", &m_iUSegments);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "NumVSegments < %d >n", &m_iVSegments);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "NumUCtrlPnts < %d >n", &m_iNumUCtrlPoints);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "NumVCtrlPnts < %d >n", &m_iNumVCtrlPoints);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Num Points < %d >n", &m_pPointArray->m_iNumPoints);
- // Resize our control point array
- if(m_pPointArray->SetArraySize(m_iNumUCtrlPoints*m_iNumVCtrlPoints))
- return;
- // Read the shape vertice, or point data
- for(int i=0; i<m_pPointArray->m_iNumPoints; i++)
- {
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "< %f, %f, %f >n", &m_pPointArray->m_pPoints[i].m_fOrigin[X],
- &m_pPointArray->m_pPoints[i].m_fOrigin[Y],
- &m_pPointArray->m_pPoints[i].m_fOrigin[Z]);
- }
- // Initialize our knots
- InitKnots();
- // Read the base class object data...
- C3dObject::Serialize(ar, iVersion);
- }
- }
- void C3dObjectNURB::DisplayObject(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- // Save the current transformation matrix..
- glPushMatrix();
- // Transform our object
- TransformObject(pWorld);
- if(this == pWorld->m_pSelectedObj)
- {
- DisplaySelected(pWorld, FALSE);
- if(pWorld->m_bDisplayPoints)
- // Display all points in our object
- DisplayPoints(pWorld, pCamera);
- }
- // Save the name on the stack. This will be used to determine
- // hits from the selection buffer
- glLoadName(m_iName);
- // Setup this objects polygon color material
- // or texture attributes
- SetAttributes(pWorld, m_pQuad);
- // Special case for NURBS objects. Set the fill/outline mode.
- if(pWorld->m_iRenderMode == RENDER_WIREFRAME)
- gluNurbsProperty(m_pNURBObj, GLU_DISPLAY_MODE, (GLfloat)GLU_OUTLINE_POLYGON);
- else
- gluNurbsProperty(m_pNURBObj, GLU_DISPLAY_MODE, (GLfloat)GLU_FILL);
- // Do we need to build the display lists?
- if(m_bBuildLists)
- {
- if(!m_iDisplayLists)
- m_iDisplayLists = glGenLists(1);// Create the DisplayList(s)
- Build(pWorld, pCamera); // Build the shape
- m_bBuildLists = FALSE; // Set the flag
- }
- else
- glCallList(m_iDisplayLists); // Display the list
- // Display all child objects of this object
- DisplayChildObjects(pWorld, pCamera);
- // Restore the current transformation matrix..
- glPopMatrix();
- }
- void C3dObjectNURB::Build(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- GLint u_knot_count, v_knot_count;
- GLint u_offset, v_offset;
- GLint u_order, v_order;
- // Initialize our variables
- u_knot_count = m_iNumUCtrlPoints*2;
- v_knot_count = m_iNumVCtrlPoints*2;
- v_offset = sizeof(C3dPoint)/sizeof(GLfloat);
- u_offset = v_offset*m_iNumVCtrlPoints;
- u_order = m_iNumUCtrlPoints;
- v_order = m_iNumVCtrlPoints;
- // Compile and build the list
- glNewList(m_iDisplayLists, GL_COMPILE_AND_EXECUTE);
- // We use GLU_DOMAIN_DISTANCE to specify, in parametric coordinates,
- // how many sample points per unit length to take in the u and v dimensions.
- gluNurbsProperty(m_pNURBObj, GLU_SAMPLING_METHOD, (GLfloat)GLU_DOMAIN_DISTANCE);
- gluNurbsProperty(m_pNURBObj, GLU_U_STEP, (GLfloat)m_iUSegments);
- gluNurbsProperty(m_pNURBObj, GLU_V_STEP, (GLfloat)m_iVSegments);
- gluBeginSurface(m_pNURBObj);
- gluNurbsSurface(m_pNURBObj,
- u_knot_count, m_pUKnots,
- v_knot_count, m_pVKnots,
- u_offset,
- v_offset,
- (GLfloat*)m_pPointArray->m_pPoints->m_fOrigin,
- u_order, v_order,
- GL_MAP2_VERTEX_3);
- gluNurbsSurface(m_pNURBObj,
- u_knot_count, m_pUKnots,
- v_knot_count, m_pVKnots,
- u_offset,
- v_offset,
- (GLfloat*)m_pPointArray->m_pPoints->m_fOrigin,
- u_order, v_order,
- GL_MAP2_NORMAL);
- /*
- gluNurbsSurface(m_pNURBObj,
- u_knot_count, m_pUKnots,
- v_knot_count, m_pVKnots,
- u_offset,
- v_offset,
- (GLfloat*)m_pPointArray->m_pPoints->m_fOrigin,
- u_order, v_order,
- GL_MAP2_COLOR_4);
- */
- gluNurbsSurface(m_pNURBObj,
- u_knot_count, m_pUKnots,
- v_knot_count, m_pVKnots,
- u_offset,
- v_offset,
- (GLfloat*)m_pPointArray->m_pPoints->m_fOrigin,
- u_order, v_order,
- GL_MAP2_TEXTURE_COORD_2);
- gluEndSurface(m_pNURBObj);
- glEndList();
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectNURB Methods or Implementation
- void C3dObjectNURB::InitVertices()
- {
- // Our NURBS plane is created by positioning the control points along the
- // u & v vector. The vector points, for a typical 4 x 4 grid, are
- // initialized as follows:
- /*
- V
- / ---------------------
- / p3* / / *p7 / *p11 / *p15
- / / / / /
- / p2* / / *p6 / *p10 / *p14
- / / / / /
- / p1* / / *p5 / *p9 / *p13
- / / / / /
- / p0* /-----/------/-------/ *p12
- / * p4 * p8
- /
- -------------------------------------> U
- */
- int u, v;
- // Resize our control point array
- if(m_pPointArray->SetArraySize(m_iNumUCtrlPoints*m_iNumVCtrlPoints))
- return; // function failed
- // Initialize our control points
- for(u=0; u<m_iNumUCtrlPoints; u++)
- {
- for(v=0; v<m_iNumVCtrlPoints; v++)
- {
- m_pPointArray->m_pPoints[(u*m_iNumVCtrlPoints)+v].m_fOrigin[X] = ((u*m_fWidth)/(m_iNumUCtrlPoints-1))-(m_fWidth/2);
- m_pPointArray->m_pPoints[(u*m_iNumVCtrlPoints)+v].m_fOrigin[Y] = ((v*m_fDepth)/(m_iNumVCtrlPoints-1))-(m_fDepth/2);
- m_pPointArray->m_pPoints[(u*m_iNumVCtrlPoints)+v].m_fOrigin[Z] = 0.0f;
- }
- }
- // Initialize our Knot arrays
- InitKnots();
- }
- int C3dObjectNURB::InitKnots()
- {
- int u, v;
- // Create an array of nondecreasing knot values in the parametric u direction.
- if(m_hUKnots) // Does the array already exist?
- {
- // Unlock the memory handle
- GlobalUnlock(m_hUKnots);
- // Reallocate the memory block
- m_hUKnots = GlobalReAlloc(m_hUKnots, m_iNumUCtrlPoints*2*sizeof(GLfloat),
- GMEM_MOVEABLE | GMEM_ZEROINIT);
- }
- else
- m_hUKnots = GlobalAlloc(GPTR, m_iNumUCtrlPoints*2*sizeof(GLfloat));
- if(m_hUKnots == NULL)
- {
- AfxMessageBox("Not enought memory to create U Knot Array!", MB_OK, NULL);
- return(-1);
- }
- m_pUKnots = (GLfloat*)GlobalLock(m_hUKnots);
- if(m_pUKnots == NULL) {
- AfxMessageBox("Not enought memory to create U Knot Array!", MB_OK, NULL);
- GlobalFree(m_hUKnots);
- m_hUKnots = NULL;
- return(-1);
- }
- // Create an array of nondecreasing knot values in the parametric v direction.
- if(m_hVKnots) // Does the array already exist?
- {
- // Unlock the memory handle
- GlobalUnlock(m_hVKnots);
- // Reallocate the memory block
- m_hVKnots = GlobalReAlloc(m_hVKnots, m_iNumVCtrlPoints*2*sizeof(GLfloat),
- GMEM_MOVEABLE | GMEM_ZEROINIT);
- }
- else
- m_hVKnots = GlobalAlloc(GPTR, m_iNumVCtrlPoints*2*sizeof(GLfloat));
- if(m_hVKnots == NULL)
- {
- AfxMessageBox("Not enought memory to create V Knot Array!", MB_OK, NULL);
- return(-1);
- }
- m_pVKnots = (GLfloat*)GlobalLock(m_hVKnots);
- if(m_pVKnots == NULL) {
- AfxMessageBox("Not enought memory to create V Knot Array!", MB_OK, NULL);
- GlobalFree(m_hVKnots);
- m_hVKnots = NULL;
- return(-1);
- }
- // Now that our Knot array memory has been allocated, initialize in nondecreasing
- // order
- for(u=0; u<m_iNumUCtrlPoints; u++)
- {
- m_pUKnots[u] = 0.0f;
- m_pUKnots[u+m_iNumUCtrlPoints] = 1.0f;
- }
- for(v=0; v<m_iNumVCtrlPoints; v++)
- {
- m_pVKnots[v] = 0.0f;
- m_pVKnots[v+m_iNumVCtrlPoints] = 1.0f;
- }
- return 0;
- }