3dObjectCSG.cpp
资源名称:gloop.zip [点击查看]
上传用户:shxiangxiu
上传日期:2007-01-03
资源大小:1101k
文件大小:10k
源码类别:
OpenGL
开发平台:
Visual C++
- /////////////////////////////////////////////////////////////////////////////
- // 3dObjectCSG.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.
- //
- // Constructive Solid Geometry algorithm based on information from the
- // Advanced OpenGL Rendering course at SIGGRAPH '96 by David Blythe and
- // Tom McReynolds.
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "glOOP.h"
- #include "3dObjectDialog.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- //////////////////////////////////////////////////////////////////
- // C3dObjectCSG
- IMPLEMENT_DYNAMIC(C3dObjectCSG, C3dObject)
- /////////////////////////////////////////////////////////////////////////////
- // C3dShape construction
- C3dObjectCSG::C3dObjectCSG()
- {
- // Set the attributes to default values..
- m_iType = SHAPE_OBJECT;
- m_szName.Format("CSG %u", nCSGObjects++);
- m_iCSGType = CSG_TYPE_OR;
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3DWorld Destructor
- C3dObjectCSG::~C3dObjectCSG()
- {
- // TODO: add destruction code here,
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectCSG Methods or virtual function implimentation
- void C3dObjectCSG::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
- {
- C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
- ASSERT(pSheet);
- // Add the page to the property sheet
- pSheet->AddPage(&pSheet->m_CSGPage);
- // Save the address of this object in the page
- pSheet->m_CSGPage.m_pObject = this;
- }
- void C3dObjectCSG::GetShapeBounds(C3dBoundingBox* pBox)
- {
- // Since a CSG object itself has no bounds (only its
- // children), return bogus numbers.
- // Note: The actual bounds will be found when the
- // calling function gets the CSG object's
- // child bounds.
- // Set the Max point to a very large negetive number
- pBox->m_fMax[X] = -(GLfloat)LARGE_NUMBER;
- pBox->m_fMax[Y] = -(GLfloat)LARGE_NUMBER;
- pBox->m_fMax[Z] = -(GLfloat)LARGE_NUMBER;
- // Set the Min point to a very large positive number
- pBox->m_fMin[X] = (GLfloat)LARGE_NUMBER;
- pBox->m_fMin[Y] = (GLfloat)LARGE_NUMBER;
- pBox->m_fMin[Z] = (GLfloat)LARGE_NUMBER;
- }
- int C3dObjectCSG::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( iObjectCSGBMImage > -1) {
- m_iBMImage = iObjectCSGBMImage;
- 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_CSG);
- m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- // Load the bitmap for the non-selected light
- bitmap.LoadBitmap(IDB_OBJECT_CSG_SELECTED);
- pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- iObjectCSGBMImage = m_iBMImage;
- return m_iBMImage;
- }
- void C3dObjectCSG::Serialize(CArchive& ar, int iVersion)
- {
- CString szBuffer;
- if (ar.IsStoring())
- {
- // Save the Object Class header...
- szBuffer.Format("n%sC3dObjectCSG {n", szIndent);
- ar.WriteString(szBuffer);
- // Save the this objects' specific data...
- szBuffer.Format("%stCSG Type < %d >n", szIndent, m_iCSGType);
- 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
- {
- if(iVersion < 102)
- // Read the base class object data...
- C3dObject::Serialize(ar, iVersion);
- // Read the derived class data..
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft(); // Remove leading white spaces
- sscanf(szBuffer, "CSG Type < %d >n", &m_iCSGType);
- if(iVersion < 102)
- // Read all child objects...
- LoadChildObjects(ar, iVersion);
- else
- // Read the base class object data...
- C3dObject::Serialize(ar, iVersion);
- }
- }
- void C3dObjectCSG::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);
- // if(m_bBuildLists) // Do we need to build the display lists?
- // {
- // 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 C3dObjectCSG::Build(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- C3dObject* a;
- C3dObject* b;
- POSITION objPos = m_ObjectList.GetHeadPosition();
- // Save the current gl state
- glPushAttrib(GL_ALL_ATTRIB_BITS); /* TODO - should just push depth */
- glEnable(GL_CULL_FACE);
- // Clear the stencil buffer
- glClear(GL_STENCIL_BUFFER_BIT);
- switch (m_iCSGType) {
- case CSG_TYPE_OR:
- Object_OR(pWorld, pCamera);
- break;
- case CSG_TYPE_SUB_AB:
- if(m_ObjectList.GetCount() < 2)
- break;
- a = m_ObjectList.GetAt(objPos);
- m_ObjectList.GetNext(objPos);
- b = m_ObjectList.GetAt(objPos);
- Object_SUB(pWorld, pCamera, a, b);
- break;
- case CSG_TYPE_SUB_BA:
- if(m_ObjectList.GetCount() < 2)
- break;
- a = m_ObjectList.GetAt(objPos);
- m_ObjectList.GetNext(objPos);
- b = m_ObjectList.GetAt(objPos);
- Object_SUB(pWorld, pCamera, b, a);
- break;
- case CSG_TYPE_AND:
- if(m_ObjectList.GetCount() < 2)
- break;
- a = m_ObjectList.GetAt(objPos);
- m_ObjectList.GetNext(objPos);
- b = m_ObjectList.GetAt(objPos);
- Object_AND(pWorld, pCamera, a, b);
- break;
- }
- // Restore the gl state
- glPopAttrib();
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectCSG function implimentation
- void C3dObjectCSG::Object_AND(C3dWorld* pWorld, C3dCamera* pCamera, C3dObject* a, C3dObject* b)
- {
- // boolean A and B (draw wherever A intersects B)
- // algorithm: Find where A is inside B, then find
- // where B is inside A
- Inside(pWorld, pCamera, a, b, GL_BACK, GL_NOTEQUAL);
- Fixup(pWorld, pCamera, b);
- Inside(pWorld, pCamera, b, a, GL_BACK, GL_NOTEQUAL);
- // reset stencil test
- glDisable(GL_STENCIL_TEST);
- }
- void C3dObjectCSG::Object_SUB(C3dWorld* pWorld, C3dCamera* pCamera, C3dObject* a, C3dObject* b)
- {
- // boolean A subtract B (draw wherever A is and B is NOT)
- // algorithm: Find where a is inside B, then find
- // where the BACK faces of B are NOT in A
- Inside(pWorld, pCamera, a, b, GL_FRONT, GL_NOTEQUAL);
- Fixup(pWorld, pCamera, b);
- Inside(pWorld, pCamera, b, a, GL_BACK, GL_EQUAL);
- // reset stencil test
- glDisable(GL_STENCIL_TEST);
- Fixup(pWorld, pCamera, a);
- }
- void C3dObjectCSG::Object_OR(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- // boolean A or B or C...
- // Algorithm: simple, just draw all depth test enabled
- // glPushAttrib(GL_ALL_ATTRIB_BITS); /* TODO - should just push depth */
- // glEnable(GL_DEPTH_TEST);
- // Display all child objects of this object
- DisplayChildObjects(pWorld, pCamera);
- // glPopAttrib();
- }
- void C3dObjectCSG::Inside(C3dWorld* pWorld, C3dCamera* pCamera, C3dObject* a, C3dObject* b, GLenum face, GLenum test)
- {
- // sets stencil buffer to show the part of A
- // (front or back face according to 'face')
- // that is inside of B.
- // draw A into depth buffer, but not into color buffer
- glEnable(GL_DEPTH_TEST);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glCullFace(face);
- a->DisplayObject(pWorld, pCamera);
- // use stencil buffer to find the parts of A that are
- // inside of B by first incrementing the stencil buffer
- // wherever B's front faces are...
- glDepthMask(GL_FALSE);
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 0, 0);
- glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
- glCullFace(GL_BACK);
- b->DisplayObject(pWorld, pCamera);
- // then decrement the stencil buffer wherever B's
- // back faces are
- glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
- glCullFace(GL_FRONT);
- b->DisplayObject(pWorld, pCamera);
- // now draw the part of A that is inside of B
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilFunc(test, 0, 1);
- glDisable(GL_DEPTH_TEST);
- glCullFace(face);
- a->DisplayObject(pWorld, pCamera);
- // reset stencil test
- glDisable(GL_STENCIL_TEST);
- }
- void C3dObjectCSG::Fixup(C3dWorld* pWorld, C3dCamera* pCamera, C3dObject* pObject)
- {
- // fixes up the depth buffer with pObject's depth
- // values
- // fix up the depth buffer
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glEnable(GL_DEPTH_TEST);
- glDisable(GL_STENCIL_TEST);
- glDepthFunc(GL_ALWAYS);
- pObject->DisplayObject(pWorld, pCamera);
- // reset depth func
- glDepthFunc(GL_LESS);
- }