3dObjectCylinder.cpp
资源名称:gloop.zip [点击查看]
上传用户:shxiangxiu
上传日期:2007-01-03
资源大小:1101k
文件大小:17k
源码类别:
OpenGL
开发平台:
Visual C++
- /////////////////////////////////////////////////////////////////////////////
- // 3dObjectCylinder.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
- //////////////////////////////////////////////////////////////////
- // C3dObjectCylinder
- IMPLEMENT_DYNAMIC(C3dObjectCylinder, C3dObject)
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectCylinder construction
- C3dObjectCylinder::C3dObjectCylinder()
- {
- // Set the attributes to default values..
- m_iType = SHAPE_OBJECT;
- m_szName.Format("Cylinder %u", nCylinderObjects++);
- m_bSolid = TRUE;
- m_bSmooth = TRUE;
- m_fHeight = 2.0f;
- m_fTopRadius = 1.0f;
- m_fBaseRadius = 1.0f;
- m_iSegments = 40;
- // Create our C3dPointArray object
- m_pPointArray = new C3dPointArray;
- ASSERT(m_pPointArray);
- // Create an array of points for our vertices
- m_pPointArray->Create((m_iSegments*2)+2);
- // Initialize our cubes vertices (points)
- InitVertices();
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectCylinder Destructor
- C3dObjectCylinder::~C3dObjectCylinder()
- {
- // Delete our point array
- if(m_pPointArray)
- delete m_pPointArray;
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectCylinder Methods or virtual function implimentation
- void C3dObjectCylinder::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
- {
- C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
- ASSERT(pSheet);
- // Add the page to the property sheet
- pSheet->AddPage(&pSheet->m_CylinderPage);
- // Save the address of this object in the page
- pSheet->m_CylinderPage.m_pObject = this;
- }
- int C3dObjectCylinder::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( iObjectCylinderBMImage > -1) {
- m_iBMImage = iObjectCylinderBMImage;
- 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_CYLINDER);
- m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- // Load the bitmap for the non-selected light
- bitmap.LoadBitmap(IDB_OBJECT_CYLINDER_SELECTED);
- pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- iObjectCylinderBMImage = m_iBMImage;
- return m_iBMImage;
- }
- void C3dObjectCylinder::Serialize(CArchive& ar, int iVersion)
- {
- CString szBuffer;
- if (ar.IsStoring())
- {
- // Save the Object Class header...
- szBuffer.Format("n%sC3dObjectCylinder {n", szIndent);
- ar.WriteString(szBuffer);
- // Save the this objects' specific data...
- szBuffer.Format("%stSolid < %d >n", szIndent, m_bSolid);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stHeight < %f >n", szIndent, m_fHeight);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stTopRadius < %f >n", szIndent, m_fTopRadius);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stBaseRadius < %f >n", szIndent, m_fBaseRadius);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stSmooth < %d >n", szIndent, m_bSmooth);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stSegments < %d >n", szIndent, m_iSegments);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stSolid Color < %d >n", szIndent, m_bSolidColor);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stNum Points < %d >n", szIndent, m_pPointArray->m_iNumPoints);
- ar.WriteString(szBuffer);
- m_pPointArray->Serialize(ar, iVersion, !m_bSolidColor);
- // 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, "Solid < %d >n", &m_bSolid);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Height < %f >n", &m_fHeight);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "TopRadius < %f >n", &m_fTopRadius);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "BaseRadius < %f >n", &m_fBaseRadius);
- if(iVersion < 110)
- {
- // Version 1.1 changed the definition of our member m_iNumMajor to
- // m_iSegments and added point manipulation
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "MajorSlices < %d >n", &m_iSegments);
- // Eliminated member m_iNumMinor (minor slices), so
- // just read the string
- ar.ReadString(szBuffer);
- // Set the cones point array size
- if(m_pPointArray->SetArraySize((m_iSegments*2)+2))
- return;
- // Initialize our point array vertices
- InitVertices();
- }
- else
- {
- // Version 1.1 added smooth normals
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Smooth < %d >n", &m_bSmooth);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Segments < %d >n", &m_iSegments);
- if(iVersion > 130)
- {
- // Version 1.4 added point color capability
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Solid Color < %d >n", &m_bSolidColor);
- }
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Num Points < %d >n", &m_pPointArray->m_iNumPoints);
- // Set the cones point array size
- if(m_pPointArray->SetArraySize((m_iSegments*2)+2))
- return;
- // Read the shape vertice, or point data
- m_pPointArray->Serialize(ar, iVersion, !m_bSolidColor);
- }
- if(iVersion < 102)
- // Read all child objects...
- LoadChildObjects(ar, iVersion);
- else
- // Read the base class object data...
- C3dObject::Serialize(ar, iVersion);
- }
- }
- void C3dObjectCylinder::Build(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- C3dPointArray Normals;
- VECTORF Normal;
- GLfloat x0, y0, x1, y1;
- double a0, a1;
- int i;
- // Create an array to hold the segment normals
- Normals.Create((m_iSegments*2)+4);
- // Calculate our smooth face normals
- CalNormals(Normals.m_pPoints, m_bSmooth);
- C3dPoint* pBaseCenter; // Center point of our cones base
- C3dPoint* pTopCenter; // Center point of our cones top
- C3dPoint* pRadialPoint; // Pointer to the first radial base point
- C3dPoint* pNextBasePoint; // Pointer to the next radial base point
- C3dPoint* pNextTopPoint; // Pointer to the next radial top point
- C3dPoint* pNormal; // Pointer to the radial point normals
- C3dPoint* pNextBaseNormal; // Pointer to the next radial base normal
- C3dPoint* pNextTopNormal; // Pointer to the next radial top normal
- pBaseCenter = &m_pPointArray->m_pPoints[0]; // first point in array
- pTopCenter = &m_pPointArray->m_pPoints[1]; // second point in array
- pRadialPoint = &m_pPointArray->m_pPoints[2]; // third point in array
- pNormal = &Normals.m_pPoints[2]; // third normal in array
- // Compile and build the list
- glNewList(m_iDisplayLists, GL_COMPILE_AND_EXECUTE);
- // Initialize our disks vertice points
- for(i=0; i<m_iSegments; i++)
- {
- a0 = i * (360/(double)m_iSegments);
- x0 = Cosf((GLfloat)a0);
- y0 = Sinf((GLfloat)a0);
- a1 = (i+1) * (360/(double)m_iSegments);
- x1 = Cosf((GLfloat)a1);
- y1 = Sinf((GLfloat)a1);
- if(i==m_iSegments-1)
- {
- // First radial point
- pNextBasePoint = &m_pPointArray->m_pPoints[2];
- pNextTopPoint = &m_pPointArray->m_pPoints[3];
- // First radial point normal
- pNextBaseNormal = &Normals.m_pPoints[2];
- pNextTopNormal = &Normals.m_pPoints[3];
- }
- else
- {
- // First radial point
- pNextBasePoint = &pRadialPoint[(i*2)+2];
- pNextTopPoint = &pRadialPoint[(i*2)+3];
- // First radial point normal
- pNextBaseNormal = &pNormal[(i*2)+2];
- pNextTopNormal = &pNormal[(i*2)+3];
- }
- if(m_bSmooth)
- {
- glBegin(GL_TRIANGLE_STRIP);
- // ** Side of the Cylinder **
- glNormal3fv(pNormal[(i*2)].m_fOrigin);
- glTexCoord2d(i*(1/(double)m_iSegments), 0);
- if(!m_bSolidColor)
- glColor4fv(pRadialPoint[(i*2)].m_Color.m_fColor);
- glVertex3fv(pRadialPoint[(i*2)].m_fOrigin);
- glNormal3fv(pNextBaseNormal->m_fOrigin);
- glTexCoord2d((i+1)*(1/(double)m_iSegments), 0);
- if(!m_bSolidColor)
- glColor4fv(pNextBasePoint->m_Color.m_fColor);
- glVertex3fv(pNextBasePoint->m_fOrigin);
- glNormal3fv(pNormal[(i*2)+1].m_fOrigin);
- glTexCoord2d(i*(1/(double)m_iSegments), 1);
- if(!m_bSolidColor)
- glColor4fv(pRadialPoint[(i*2)+1].m_Color.m_fColor);
- glVertex3fv(pRadialPoint[(i*2)+1].m_fOrigin);
- glNormal3fv(pNextTopNormal->m_fOrigin);
- glTexCoord2d((i+1)*(1/(double)m_iSegments), 1);
- if(!m_bSolidColor)
- glColor4fv(pNextTopPoint->m_Color.m_fColor);
- glVertex3fv(pNextTopPoint->m_fOrigin);
- glEnd();
- }
- else
- {
- glBegin(GL_TRIANGLE_STRIP);
- // ** Side of the Cylinder **
- glNormal3fv(pNormal[(i*2)].m_fOrigin);
- glTexCoord2d(i*(1/(double)m_iSegments), 0);
- if(!m_bSolidColor)
- glColor4fv(pRadialPoint[(i*2)].m_Color.m_fColor);
- glVertex3fv(pRadialPoint[(i*2)].m_fOrigin);
- glTexCoord2d((i+1)*(1/(double)m_iSegments), 0);
- if(!m_bSolidColor)
- glColor4fv(pNextBasePoint->m_Color.m_fColor);
- glVertex3fv(pNextBasePoint->m_fOrigin);
- glTexCoord2d(i*(1/(double)m_iSegments), 1);
- if(!m_bSolidColor)
- glColor4fv(pRadialPoint[(i*2)+1].m_Color.m_fColor);
- glVertex3fv(pRadialPoint[(i*2)+1].m_fOrigin);
- glTexCoord2d((i+1)*(1/(double)m_iSegments), 1);
- if(!m_bSolidColor)
- glColor4fv(pNextTopPoint->m_Color.m_fColor);
- glVertex3fv(pNextTopPoint->m_fOrigin);
- glEnd();
- }
- if(m_bSolid)
- {
- glBegin(GL_TRIANGLES);
- // ** Bottom of the Cylinder **
- // Calculate the normal for the triangle
- CalNormalf(pBaseCenter->m_fOrigin,
- pRadialPoint[(i*2)].m_fOrigin,
- pNextBasePoint->m_fOrigin,
- Normal);
- glNormal3fv(Normal);
- glTexCoord2d(0.5, 0.5);
- if(!m_bSolidColor)
- glColor4fv(pBaseCenter->m_Color.m_fColor);
- glVertex3fv(pBaseCenter->m_fOrigin);
- glTexCoord2d((x1*0.5)+0.5, 1-((y1*0.5)+0.5));
- if(!m_bSolidColor)
- glColor4fv(pNextBasePoint->m_Color.m_fColor);
- glVertex3fv(pNextBasePoint->m_fOrigin);
- glTexCoord2d((x0*0.5)+0.5, 1-((y0*0.5)+0.5));
- if(!m_bSolidColor)
- glColor4fv(pRadialPoint[(i*2)].m_Color.m_fColor);
- glVertex3fv(pRadialPoint[(i*2)].m_fOrigin);
- // ** Top of the Cylinder **
- // Calculate the normal for the triangle
- CalNormalf(pTopCenter->m_fOrigin,
- pNextTopPoint->m_fOrigin,
- pRadialPoint[(i*2)+1].m_fOrigin,
- Normal);
- glNormal3fv(Normal);
- glTexCoord2d(0.5, 0.5);
- if(!m_bSolidColor)
- glColor4fv(pTopCenter->m_Color.m_fColor);
- glVertex3fv(pTopCenter->m_fOrigin);
- glTexCoord2d((x0*0.5)+0.5, 1-((y0*0.5)+0.5));
- if(!m_bSolidColor)
- glColor4fv(pRadialPoint[(i*2)+1].m_Color.m_fColor);
- glVertex3fv(pRadialPoint[(i*2)+1].m_fOrigin);
- glTexCoord2d((x1*0.5)+0.5, 1-((y1*0.5)+0.5));
- if(!m_bSolidColor)
- glColor4fv(pNextTopPoint->m_Color.m_fColor);
- glVertex3fv(pNextTopPoint->m_fOrigin);
- glEnd();
- }
- }
- glEndList();
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectCylinder Methods or Implementation
- void C3dObjectCylinder::InitVertices()
- {
- /* We define our cone as follows:
- p7 ------ p5
- /
- /
- p9 | *p0 | p3
- | |
- /
- /
- P11 ------ pN+1
- p6 ------ p4
- /
- /
- p8 | *p0 | p2
- | |
- BASE /
- /
- P10 ------ pN
- */
- C3dPoint* pPoint;
- int i;
- // Resize our array to ensure we have the memory for our points
- if(m_pPointArray->SetArraySize((m_iSegments*2)+2))
- return; // function failed
- // Set the point to the address of the first point
- // in the array
- pPoint= m_pPointArray->m_pPoints;
- // Initialize our disks vertice points
- Vec3f(0.0f, 0.0f, -m_fHeight/2, pPoint[0].m_fOrigin); // Set the base center
- Vec3f(0.0f, 0.0f, m_fHeight/2, pPoint[1].m_fOrigin); // Apex
- // Now the points about the base radius
- for(i=0; i<m_iSegments; i++)
- {
- double a0 = i * (360/(double)m_iSegments);
- double x0 = Cosd(a0);
- double y0 = Sind(a0);
- pPoint[(i*2)+2].m_fOrigin[X] = (GLfloat)(m_fBaseRadius*x0);
- pPoint[(i*2)+2].m_fOrigin[Y] = (GLfloat)(m_fBaseRadius*y0);
- pPoint[(i*2)+2].m_fOrigin[Z] = (GLfloat)(-m_fHeight/2);
- pPoint[(i*2)+3].m_fOrigin[X] = (GLfloat)(m_fTopRadius*x0);
- pPoint[(i*2)+3].m_fOrigin[Y] = (GLfloat)(m_fTopRadius*y0);
- pPoint[(i*2)+3].m_fOrigin[Z] = (GLfloat)(m_fHeight/2);
- }
- }
- void C3dObjectCylinder::CalNormals(C3dPoint* pNormals, BOOL bSmooth)
- {
- // Calculate the normals for each point about the sides of
- // the cylinder.
- C3dPointArray FaceNormals;
- int i;
- // Create a temporary array to store our face normals
- FaceNormals.Create((m_iSegments*2)+2);
- C3dPoint* pRadialPoint = &m_pPointArray->m_pPoints[2]; // third point in array
- C3dPoint* pNextBasePoint; // Pointer to the next radial base point
- C3dPoint* pNextTopPoint; // Pointer to the next radial top point
- C3dPoint* pFaceNormal = &FaceNormals.m_pPoints[2];
- // First calculate the normals for each face (triangle) of the cylinder
- // and store them in the FaceNormal array.
- for(i=0; i<m_iSegments; i++)
- {
- if(i==m_iSegments-1)
- {
- // First radial points
- pNextBasePoint = &m_pPointArray->m_pPoints[2];
- pNextTopPoint = &m_pPointArray->m_pPoints[3];
- }
- else
- {
- // Next radial points
- pNextBasePoint = &pRadialPoint[(i*2)+2];
- pNextTopPoint = &pRadialPoint[(i*2)+3];
- }
- // Calculate the normal for the triangle
- CalNormalf(pRadialPoint[(i*2)].m_fOrigin,
- pRadialPoint[(i*2)+1].m_fOrigin,
- pNextBasePoint->m_fOrigin,
- pFaceNormal[(i*2)].m_fOrigin);
- CalNormalf(pRadialPoint[(i*2)+1].m_fOrigin,
- pNextTopPoint->m_fOrigin,
- pRadialPoint[(i*2)].m_fOrigin,
- pFaceNormal[(i*2)+1].m_fOrigin);
- }
- if(bSmooth)
- {
- // Now that we have the face normals, calculate the point normals for each
- // vertice by averaging the adjacent face normals of each vertice.
- C3dPoint* PreviousBaseNormal;
- C3dPoint* PreviousTopNormal;
- for(i=0; i<m_iSegments; i++)
- {
- if(i==0)
- {
- // Last face normal
- PreviousBaseNormal = &pFaceNormal[(m_iSegments*2)-2];
- PreviousTopNormal = &pFaceNormal[(m_iSegments*2)-1];
- }
- else
- {
- // Previous face normal
- PreviousBaseNormal = &pFaceNormal[(i*2)-2];
- PreviousTopNormal = &pFaceNormal[(i*2)-1];
- }
- VecAddf(PreviousBaseNormal->m_fOrigin,
- pFaceNormal[(i*2)].m_fOrigin,
- pNormals[(i*2)+2].m_fOrigin); // Bottom radial point normal
- pNormals[(i*2)+2].m_fOrigin[X] = pNormals[(i*2)+2].m_fOrigin[X]/2;
- pNormals[(i*2)+2].m_fOrigin[Y] = pNormals[(i*2)+2].m_fOrigin[Y]/2;
- pNormals[(i*2)+2].m_fOrigin[Z] = pNormals[(i*2)+2].m_fOrigin[Z]/2;
- VecAddf(PreviousTopNormal->m_fOrigin,
- pFaceNormal[(i*2)+1].m_fOrigin,
- pNormals[(i*2)+3].m_fOrigin); // Top radial point normal
- pNormals[(i*2)+3].m_fOrigin[X] = pNormals[(i*2)+3].m_fOrigin[X]/2;
- pNormals[(i*2)+3].m_fOrigin[Y] = pNormals[(i*2)+3].m_fOrigin[Y]/2;
- pNormals[(i*2)+3].m_fOrigin[Z] = pNormals[(i*2)+3].m_fOrigin[Z]/2;
- }
- }
- else
- {
- // Just copy the normals
- for(i=0; i<=(m_iSegments*2); i++)
- VecCopy3f(pFaceNormal[i].m_fOrigin,
- pNormals[i+2].m_fOrigin);
- }
- }