3dObjectCloud.cpp
资源名称:gloop.zip [点击查看]
上传用户:shxiangxiu
上传日期:2007-01-03
资源大小:1101k
文件大小:29k
源码类别:
OpenGL
开发平台:
Visual C++
- /////////////////////////////////////////////////////////////////////////////
- // 3dObjectCloud.cpp : implementation file
- //
- // glOOP (OpenGL Object Oriented Programming library)
- // Copyright (c) Craig m_pFahrnbach 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.
- //
- // Adapted from source code, with permission, by: Paul E. Martz
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "glOOP.h"
- #include "3dObjectDialog.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- //////////////////////////////////////////////////////////////////
- // C3dObjectCloud
- IMPLEMENT_DYNAMIC(C3dObjectCloud, C3dObject)
- /////////////////////////////////////////////////////////////////////////////
- // C3dShape construction
- C3dObjectCloud::C3dObjectCloud()
- {
- // Set the attributes to dem_pFault values..
- m_iType = SHAPE_OBJECT;
- m_szName.Format("Cloud %u", nCloudObjects++);
- m_iSize = 8; // 2^8, or 256 x 256 texture map
- m_iTile = 1; // Only one tile
- m_iTextureWrap = 3; // Wrap texture three times
- m_iHeightSeed = 0;
- m_iCloudTextureMap = 0;
- m_iCloudImageMap = 0;
- m_fWidth = 50.0f;
- m_fDepth = 50.0f;
- m_fBumpHeight = 0.7f;
- m_fOpacity = 1.0f;
- m_fDensity = 0.2f;
- m_pFa = NULL;
- m_Color.SetColor4f(0.0f, 0.0f, 0.0f, 1.0f);
- m_ColorHighlight.SetColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- // Create our C3dPointArray object
- m_pPointArray = new C3dPointArray;
- ASSERT(m_pPointArray);
- m_pPointArray->Create(5); // Create an array of points for our vertices
- // Initialize our cubes vertices (points)
- InitVertices();
- }
- void C3dObjectCloud::CopyParameters(C3dObjectCloud* pSrc, C3dObjectCloud* pDest)
- {
- // Since this function is used by the preview window, we want
- // the image to fit 'mostly' within the window, so we will
- // use our default settings. We also want to conserve memory
- // so we will use the default array size setting.
- // pDest->m_iSize = pSrc->m_iSize;
- // pDest->m_iTile = pSrc->m_iTile;
- // pDest->m_fDepth = pSrc->m_fDepth;
- // pDest->m_fWidth = pSrc->m_fWidth;
- pDest->m_iHeightSeed = pSrc->m_iHeightSeed;
- pDest->m_iTextureWrap = pSrc->m_iTextureWrap;
- pDest->m_fBumpHeight = pSrc->m_fBumpHeight;
- pDest->m_fDensity = pSrc->m_fDensity;
- pDest->m_fOpacity = pSrc->m_fOpacity;
- pDest->m_Color.SetColor4fv(&pSrc->m_Color);
- pDest->m_ColorHighlight.SetColor4fv(&pSrc->m_ColorHighlight);
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3DWorld Destructor
- C3dObjectCloud::~C3dObjectCloud()
- {
- // Delete our point array
- if(m_pPointArray)
- delete m_pPointArray;
- // Delete the Terrain image
- if(m_iCloudTextureMap)
- {
- glDeleteLists(m_iCloudImageMap, 1);
- m_iCloudImageMap = 0;
- }
- // Delete the Terrain Texturemap
- if(m_iCloudTextureMap)
- {
- glDeleteLists(m_iCloudTextureMap, 1);
- m_iCloudTextureMap = 0;
- }
- // Delete the fractural array
- if(m_pFa)
- FreeFractArray();
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectCloud Methods or virtual function implimentation
- void C3dObjectCloud::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
- {
- C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
- ASSERT(pSheet);
- // Add the page to the property sheet
- pSheet->AddPage(&pSheet->m_CloudPage);
- // Save the address of this object in the page
- pSheet->m_CloudPage.m_pObject = this;
- // Add the page to the property sheet
- pSheet->AddPage(&pSheet->m_CloudColorPage);
- // Save the address of this object in the page
- pSheet->m_CloudColorPage.m_pObject = this;
- pSheet->m_CloudColorPage.m_pWorld = pWorld;
- }
- int C3dObjectCloud::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( iObjectCloudBMImage > -1) {
- m_iBMImage = iObjectCloudBMImage;
- 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_CLOUD);
- m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- // Load the bitmap for the non-selected light
- bitmap.LoadBitmap(IDB_OBJECT_CLOUD_SELECTED);
- pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- iObjectCloudBMImage = m_iBMImage;
- return m_iBMImage;
- }
- void C3dObjectCloud::GetShapeBounds(C3dBoundingBox* pBox)
- {
- if(m_pPointArray)
- m_pPointArray->GetMinMax(pBox);
- // We need to calculate the overall size of the object based
- // on the number of times we have tiled the basic shape
- pBox->m_fMax[X] *= m_iTile;
- pBox->m_fMax[Y] *= m_iTile;
- pBox->m_fMin[X] *= m_iTile;
- pBox->m_fMin[Y] *= m_iTile;
- }
- void C3dObjectCloud::Serialize(CArchive& ar, int iVersion)
- {
- CString szBuffer;
- if (ar.IsStoring())
- {
- // Save the Object Class header...
- szBuffer.Format("n%sC3dObjectCloud {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("%stBumpHeight < %f >n", szIndent, m_fBumpHeight);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stDensity < %f >n", szIndent, m_fDensity);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stOpacity < %f >n", szIndent, m_fOpacity);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stHeightSeed < %d >n", szIndent, m_iHeightSeed);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stSize < %d >n", szIndent, m_iSize);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stTextureWrap < %d >n", szIndent, m_iTextureWrap);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stTile < %d >n", szIndent, m_iTile);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stHighlightColor < %f %f %f %f > // RGBAn", szIndent, m_ColorHighlight.m_fColor[0], m_ColorHighlight.m_fColor[1], m_ColorHighlight.m_fColor[2], m_ColorHighlight.m_fColor[3]);
- 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
- {
- // Read the derived class data..
- 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, "BumpHeight < %f >n", &m_fBumpHeight);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Density < %f >n", &m_fDensity);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Opacity < %f >n", &m_fOpacity);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "HeightSeed < %d >n", &m_iHeightSeed);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Size < %d >n", &m_iSize);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "TextureWrap < %d >n", &m_iTextureWrap);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Tile < %d >n", &m_iTile);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "HighlightColor < %f %f %f %f >n", &m_ColorHighlight.m_fColor[0], &m_ColorHighlight.m_fColor[1], &m_ColorHighlight.m_fColor[2], &m_ColorHighlight.m_fColor[3]);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Num Points < %d >n", &m_pPointArray->m_iNumPoints);
- // 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]);
- }
- // Read the base class object data...
- C3dObject::Serialize(ar, iVersion);
- }
- }
- void C3dObjectCloud::DisplayPoints(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- static BOOL bDisplayMsg = TRUE;
- if(m_iTile>1 && bDisplayMsg)
- {
- AfxMessageBox("To edit the Cloud object points, the 'Tile' membern"
- "variable must be set to one.", MB_OK);
- // Display the message only once per session
- bDisplayMsg = FALSE;
- return;
- }
- if(m_iTile==1)
- {
- // Display all points in our object
- if(m_pPointArray)
- {
- if(m_pPointArray->m_pPoints)
- m_pPointArray->Display(pWorld, pCamera, this, 2.0f, FALSE);
- }
- }
- }
- void C3dObjectCloud::Build(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- float x, y;
- int i, j;
- // This may take a while, so display an hour glass cursor
- CWaitCursor hourglass;
- // Render the cloudmap to create our texture image
- RenderCloudTextureMap(pWorld, pCamera);
- // Render the cloud image to create our display list image
- RenderCloudImageMap(pWorld, pCamera);
- // Compile and build the list
- glNewList(m_iDisplayLists, GL_COMPILE_AND_EXECUTE);
- // Center our tiled image about the objects' origin
- glPushMatrix();
- glTranslatef( (m_fWidth * (float)(m_iTile-1))/2.0f,
- (m_fDepth * (float)(m_iTile-1))/2.0f,
- 0.0f);
- y = -m_fDepth * (float) (m_iTile-1);
- for (i=0; i<m_iTile; i++)
- {
- x = -m_fWidth * (float) (m_iTile-1);
- for (j=0; j<m_iTile; j++)
- {
- glPushMatrix();
- glTranslatef(x, y, 0.f);
- if(m_iCloudImageMap)
- glCallList(m_iCloudImageMap);
- glPopMatrix ();
- x += m_fWidth;
- }
- y += m_fDepth;
- }
- glPopMatrix();
- glEndList();
- // Restore the cursor to its' default
- hourglass.Restore();
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectCloud Methods or Implementation
- void C3dObjectCloud::InitVertices()
- {
- /*
- Our cloud is mapped to four trainagles arranged to form a plane as
- defined by the five (5) vertices, or points below.
- p3 * ____________ * p0
- / /
- / p4 * /
- / /
- p2 * /------------/ * p1
- */
- C3dPoint* pPoint = m_pPointArray->m_pPoints;
- // Initialize our clouds plane vertice points p0-p3
- pPoint->m_fOrigin[X] = m_fWidth/2;
- pPoint->m_fOrigin[Y] = m_fDepth/2;
- pPoint->m_fOrigin[Z] = 0.0f;
- pPoint++;
- pPoint->m_fOrigin[X] = m_fWidth/2;
- pPoint->m_fOrigin[Y] = -m_fDepth/2;
- pPoint->m_fOrigin[Z] = 0.0f;
- pPoint++;
- pPoint->m_fOrigin[X] = -m_fWidth/2;
- pPoint->m_fOrigin[Y] = -m_fDepth/2;
- pPoint->m_fOrigin[Z] = 0.0f;
- pPoint++;
- pPoint->m_fOrigin[X] = -m_fWidth/2;
- pPoint->m_fOrigin[Y] = m_fDepth/2;
- pPoint->m_fOrigin[Z] = 0.0f;
- pPoint++;
- pPoint->m_fOrigin[X] = 0.0f;
- pPoint->m_fOrigin[Y] = 0.0f;
- pPoint->m_fOrigin[Z] = 0.0f;
- }
- void C3dObjectCloud::RenderCloudImageMap(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- /*
- Our cloud is mapped to four trainagles arranged to form a plane as
- defined by the five (5) vertices, or points below.
- p3 * ____________ * p0
- / /
- / p4 * /
- / /
- p2 * /------------/ * p1
- */
- float fTextureWrap = (GLfloat)m_iTextureWrap;
- float fTextureWrapCenter = fTextureWrap*.707f;
- static BOOL textureLinear = TRUE;
- if(!m_iCloudImageMap)
- // Create our cloud image map display list
- m_iCloudImageMap = glGenLists(1);// Create the DisplayList(s)
- // Compile and build the list
- glNewList(m_iCloudImageMap, GL_COMPILE);
- float pureWhite[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
- VECTORF Normal;
- // Enable blending and alpha test
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- glAlphaFunc(GL_GREATER, 0.0f);
- glEnable(GL_ALPHA_TEST);
- // Set the current color to white
- glColor4fv(pureWhite);
- // Goes a little m_pFaster but looks like crud:
- //glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, (GLfloat)GL_MODULATE);
- glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, pureWhite);
- glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- textureLinear ? (GLfloat) GL_LINEAR
- : (GLfloat) GL_NEAREST);
- glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- textureLinear ? (GLfloat) GL_LINEAR
- : (GLfloat) GL_NEAREST);
- glEnable (GL_TEXTURE_2D);
- // recall our cloud texture map
- glCallList (m_iCloudTextureMap);
- // Now that the environment is set, begin drawing the cloud
- // texture map onto our plane
- glBegin(GL_TRIANGLE_FAN);
- // Point p4: The center of our triangle fan
- CalNormalf(m_pPointArray->m_pPoints[4].m_fOrigin,
- m_pPointArray->m_pPoints[1].m_fOrigin,
- m_pPointArray->m_pPoints[2].m_fOrigin,
- Normal);
- glNormal3fv(Normal);
- glTexCoord2f(fTextureWrapCenter, fTextureWrapCenter);
- glVertex3fv(m_pPointArray->m_pPoints[4].m_fOrigin);
- // Point p0
- CalNormalf(m_pPointArray->m_pPoints[0].m_fOrigin,
- m_pPointArray->m_pPoints[1].m_fOrigin,
- m_pPointArray->m_pPoints[3].m_fOrigin,
- Normal);
- glNormal3fv(Normal);
- glTexCoord2f(fTextureWrap, fTextureWrap);
- glVertex3fv(m_pPointArray->m_pPoints[0].m_fOrigin);
- // Point p1
- CalNormalf(m_pPointArray->m_pPoints[1].m_fOrigin,
- m_pPointArray->m_pPoints[2].m_fOrigin,
- m_pPointArray->m_pPoints[0].m_fOrigin,
- Normal);
- glNormal3fv(Normal);
- glTexCoord2f(fTextureWrap, 0.f);
- glVertex3fv(m_pPointArray->m_pPoints[1].m_fOrigin);
- // Point p2
- CalNormalf(m_pPointArray->m_pPoints[2].m_fOrigin,
- m_pPointArray->m_pPoints[3].m_fOrigin,
- m_pPointArray->m_pPoints[1].m_fOrigin,
- Normal);
- glNormal3fv(Normal);
- glTexCoord2f(0.f, 0.f);
- glVertex3fv(m_pPointArray->m_pPoints[2].m_fOrigin);
- // Point p3
- CalNormalf(m_pPointArray->m_pPoints[3].m_fOrigin,
- m_pPointArray->m_pPoints[0].m_fOrigin,
- m_pPointArray->m_pPoints[2].m_fOrigin,
- Normal);
- glNormal3fv(Normal);
- glTexCoord2f(0.f, fTextureWrap);
- glVertex3fv(m_pPointArray->m_pPoints[3].m_fOrigin);
- // Point p0
- CalNormalf(m_pPointArray->m_pPoints[0].m_fOrigin,
- m_pPointArray->m_pPoints[1].m_fOrigin,
- m_pPointArray->m_pPoints[3].m_fOrigin,
- Normal);
- glNormal3fv(Normal);
- glTexCoord2f(fTextureWrap, fTextureWrap);
- glVertex3fv(m_pPointArray->m_pPoints[0].m_fOrigin);
- glEnd ();
- // Disable blending and alpha depth testing
- glDisable(GL_BLEND);
- glDisable(GL_ALPHA_TEST);
- glEndList();
- }
- BOOL C3dObjectCloud::RenderCloudTextureMap(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- // Render the cloud texture map. If the cloud fract array
- // doesn't already exist, allocate it, tesselate it, and
- // create the texture map using SetSkyPixelColor(). Then create a
- // display list with this texture map in the list.
- GLubyte *tmap;
- int size = 1 << m_iSize;
- // Set the size our our cloud fractual array
- if(m_pFa)
- FreeFractArray();
- m_pFa = Alloc2DFractArray(size);
- if(!m_pFa)
- return (FALSE);
- FillFractualArray(size, 1.0f);
- tmap = (GLubyte *) malloc (size*size*4);
- if (tmap==NULL) return (FALSE);
- SetSkyPixelColor(size, tmap);
- if(!m_iCloudTextureMap)
- // Create our texture map display list
- m_iCloudTextureMap = glGenLists(1);// Create the DisplayList(s)
- glNewList (m_iCloudTextureMap, GL_COMPILE);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, // lod
- 4, // num components
- size, size, // width, height
- 0, // border
- GL_RGBA, // format
- GL_UNSIGNED_BYTE, // type
- tmap); // pointer to our bits
- glEndList ();
- // Done with the texture map bits, so free them.
- free (tmap);
- return(TRUE); // ** Comment out this return and the remaining
- // functions in Build() to see the 'raw' texture map.
- // Once we have the texture map, we simply draw a quad as
- // big as will fit in the window, with the cloud texture map
- // applied to it.
- glCallList (m_iCloudTextureMap);
- glMatrixMode (GL_PROJECTION);
- glLoadIdentity ();
- if (pCamera->m_iScreenWidth > pCamera->m_iScreenHeight)
- glOrtho (-1.f, pCamera->m_fAspect*2.f-1.f,
- -1.f, 1.f, 1., -1.);
- else
- glOrtho (-1.f, 1.f,
- -1.f, 2.f/pCamera->m_fAspect-1.f, 1., -1.);
- glMatrixMode (GL_MODELVIEW);
- glLoadIdentity ();
- glDisable (GL_DEPTH_TEST);
- glDisable (GL_FOG);
- glDisable (GL_LIGHTING);
- glDisable (GL_BLEND);
- glEnable (GL_TEXTURE_2D);
- glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
- (GLfloat) GL_REPLACE);
- glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- (GLfloat) GL_NEAREST);
- glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- (GLfloat) GL_NEAREST);
- glClear (GL_COLOR_BUFFER_BIT);
- glBegin (GL_QUADS); {
- glTexCoord2f (0.f, 0.f); glVertex2f (-1.f, -1.f);
- glTexCoord2f (1.f, 0.f); glVertex2f (1.f, -1.f);
- glTexCoord2f (1.f, 1.f); glVertex2f (1.f, 1.f);
- glTexCoord2f (0.f, 1.f); glVertex2f (-1.f, 1.f);
- } glEnd ();
- glFlush ();
- glPopAttrib ();
- return (TRUE);
- }
- void C3dObjectCloud::SetSkyPixelColor (int size, GLubyte *skyTex)
- {
- // Converts a 2D fract array into a nice blue and white
- // cloudy sky texture map. First, it finds the average height
- // value in the map. Then it clamps values to +/- SKY_LIMIT
- // around the average value. Values in the array are then
- // mapped from a medium blue to white. The resulting RGB
- // values are stored in skyTex.
- //
- // Note that while the fract array is assumed to have dimension
- // (size+1)X(size+1), skyTex must have dimension sizeXsize.
- // This m_pFacilitates its being used as an OpenGL texture map.
- #define SKY_LIMIT 0.2f
- int i, j;
- const int subSize = size;
- unsigned char *skyptr;
- float shadeFactor;
- float skyAv=0.f;
- float scaleR, scaleG, scaleB;
- // Calculate the scale of the RGB color components
- scaleR = (m_ColorHighlight.m_fColor[0]-m_Color.m_fColor[0])/.5f;
- scaleG = (m_ColorHighlight.m_fColor[1]-m_Color.m_fColor[1])/.5f;
- scaleB = (m_ColorHighlight.m_fColor[2]-m_Color.m_fColor[2])/.5f;
- size++;
- for (i=0; i<size*size; i++)
- skyAv += m_pFa[i];
- skyAv /= (float)(size*size);
- skyptr = skyTex;
- for (i=0; i<subSize; i++)
- {
- for (j=0; j<subSize; j++)
- {
- if (m_pFa[i*size+j] < (skyAv - SKY_LIMIT))
- shadeFactor = -SKY_LIMIT;
- else if (m_pFa[i*size+j] > (skyAv + SKY_LIMIT))
- shadeFactor = SKY_LIMIT;
- else
- shadeFactor = m_pFa[i*size+j] - skyAv;
- /* shadeFactor is now in range -SKY_LIMIT - SKY_LIMIT.
- scale shadeFactor to range 0.0 - 0.5 */
- shadeFactor = ((shadeFactor + SKY_LIMIT) *
- (.5f / (2.f * SKY_LIMIT)));
- // Set the pixels' color. (ranged from m_ColorHighlight color to m_Color)
- skyptr[0] = (GLubyte)((m_Color.m_fColor[0]+scaleR*shadeFactor)*255); /* red */
- skyptr[1] = (GLubyte)((m_Color.m_fColor[1]+scaleG*shadeFactor)*255); /* green */
- skyptr[2] = (GLubyte)((m_Color.m_fColor[2]+scaleB*shadeFactor)*255); /* blue */
- // Set the pixels' transparancy value
- if(shadeFactor < m_fDensity)
- skyptr[3] = 0x00;
- else if(shadeFactor < m_fDensity+.025f)
- skyptr[3] = (unsigned char)(0x55*m_fOpacity);
- else if(shadeFactor < m_fDensity+.075f)
- skyptr[3] = (unsigned char)(0xaa*m_fOpacity);
- else
- skyptr[3] = (unsigned char)(0xff*m_fOpacity);
- skyptr += 4;
- }
- }
- }
- // randNum - Return a random floating point number such that
- // (min <= return-value <= max)
- // 32,767 values are possible for any given range.
- //
- float C3dObjectCloud::RandNum (float min, float max)
- {
- int r;
- float x;
- r = rand ();
- x = (float)(r & 0x7fff) /
- (float)0x7fff;
- return (x * (max - min) + min);
- }
- // fractRand is a useful interm_pFace to randnum.
- //
- #define FractRand(v) RandNum (-v, v)
- // powerOf2 - Returns 1 if size is a power of 2. Returns 0 if size is
- // not a power of 2, or is zero.
- //
- int C3dObjectCloud::PowerOf2 (int size)
- {
- int i, bitcount = 0;
- // Note this code assumes that (sizeof(int)*8) will yield the
- // number of bits in an int. Should be portable to most
- // platforms.
- for (i=0; i<sizeof(int)*8; i++)
- if (size & (1<<i))
- bitcount++;
- if (bitcount == 1)
- // One bit. Must be a power of 2.
- return (1);
- else
- // either size==0, or size not a power of 2. Sorry, Charlie.
- return (0);
- }
- // AvgDiamondVals - Given the i,j location as the center of a diamond,
- // average the data values at the four corners of the diamond and
- // return it. "Stride" represents the distance from the diamond center
- // to a diamond corner.
- //
- float C3dObjectCloud::AvgDiamondVals (int i, int j, int stride,
- int size, int subSize)
- {
- /* In this diagram, our input stride is 1, the i,j location is
- indicated by "X", and the four value we want to average are
- "*"s:
- . * .
- * X *
- . * .
- */
- // In order to support tiled surm_pFaces which meet seamless at the
- // edges (that is, they "wrap"), We need to be careful how we
- // calculate averages when the i,j diamond center lies on an edge
- // of the array. The first four 'if' clauses handle these
- // cases. The final 'else' clause handles the general case (in
- // which i,j is not on an edge).
- if (i == 0)
- return ((float) (m_pFa[(i*size) + j-stride] +
- m_pFa[(i*size) + j+stride] +
- m_pFa[((subSize-stride)*size) + j] +
- m_pFa[((i+stride)*size) + j]) * .25f);
- else if (i == size-1)
- return ((float) (m_pFa[(i*size) + j-stride] +
- m_pFa[(i*size) + j+stride] +
- m_pFa[((i-stride)*size) + j] +
- m_pFa[((0+stride)*size) + j]) * .25f);
- else if (j == 0)
- return ((float) (m_pFa[((i-stride)*size) + j] +
- m_pFa[((i+stride)*size) + j] +
- m_pFa[(i*size) + j+stride] +
- m_pFa[(i*size) + subSize-stride]) * .25f);
- else if (j == size-1)
- return ((float) (m_pFa[((i-stride)*size) + j] +
- m_pFa[((i+stride)*size) + j] +
- m_pFa[(i*size) + j-stride] +
- m_pFa[(i*size) + 0+stride]) * .25f);
- else
- return ((float) (m_pFa[((i-stride)*size) + j] +
- m_pFa[((i+stride)*size) + j] +
- m_pFa[(i*size) + j-stride] +
- m_pFa[(i*size) + j+stride]) * .25f);
- }
- // AvgSquareVals - Given the i,j location as the center of a square,
- // average the data values at the four corners of the square and return
- // it. "Stride" represents half the length of one side of the square.
- float C3dObjectCloud::AvgSquareVals (int i, int j, int stride, int size)
- {
- /* In this diagram, our input stride is 1, the i,j location is
- indicated by "*", and the four value we want to average are
- "X"s:
- X . X
- . * .
- X . X
- */
- return ((float) (m_pFa[((i-stride)*size) + j-stride] +
- m_pFa[((i-stride)*size) + j+stride] +
- m_pFa[((i+stride)*size) + j-stride] +
- m_pFa[((i+stride)*size) + j+stride]) * .25f);
- }
- // FillFractualArray - Use the diamond-square algorithm to tessalate a
- // grid of float values into a fractal height map.
- //
- void C3dObjectCloud::FillFractualArray (int size, float heightScale)
- {
- int i, j;
- int stride;
- int oddline;
- int subSize;
- int seedValue;
- float ratio, scale;
- if (!PowerOf2(size) || (size==1))
- {
- // We can't tesselate the array if it is not a power of 2.
- #ifdef DEBUG
- printf ("Error: FillFractualArray: size %d is not a power of 2.n");
- #endif /* DEBUG */
- return;
- }
- // subSize is the dimension of the array in terms of connected line
- // segments, while size is the dimension in terms of number of
- // vertices.
- subSize = size;
- size++;
- // Initialize random number generator
- if(m_iHeightSeed < 0)
- {
- // Seed the random-number generator with current time so that
- // the numbers will be different every time we run.
- seedValue = (unsigned)time( NULL );
- srand( seedValue );
- m_iHeightSeed = seedValue;
- }
- else
- srand (m_iHeightSeed);
- // Set up our roughness constants.
- // Random numbers are always generated in the range 0.0 to 1.0.
- // 'scale' is multiplied by the randum number.
- // 'ratio' is multiplied by 'scale' after each iteration
- // to effectively reduce the random number range.
- ratio = (float) pow ((double)2.0,(double)-m_fBumpHeight);
- scale = heightScale * ratio;
- /* Seed the first four values. For example, in a 4x4 array, we
- would initialize the data points indicated by '*':
- * . . . *
- . . . . .
- . . . . .
- . . . . .
- * . . . *
- In terms of the "diamond-square" algorithm, this gives us
- "squares".
- We want the four corners of the array to have the same
- point. This will allow us to tile the arrays next to each other
- such that they join seemlessly.
- */
- stride = subSize / 2;
- m_pFa[(0*size)+0] = m_pFa[(subSize*size)+0] =
- m_pFa[(subSize*size)+subSize] =
- m_pFa[(0*size)+subSize] = 0.f;
- // Now we add ever-increasing detail based on the "diamond" seeded
- // values. We loop over stride, which gets cut in half at the
- // bottom of the loop. Since it's an int, eventually division by 2
- // will produce a zero result, terminating the loop.
- while (stride)
- {
- /* Take the existing "square" data and produce "diamond"
- data. On the first pass through with a 4x4 matrix, the
- existing data is shown as "X"s, and we need to generate the
- "*" now:
- X . . . X
- . . . . .
- . . * . .
- . . . . .
- X . . . X
- It doesn't look like diamonds. What it actually is, for the
- first pass, is the corners of four diamonds meeting at the
- center of the array. */
- for (i=stride; i<subSize; i+=stride)
- {
- for (j=stride; j<subSize; j+=stride)
- {
- m_pFa[(i * size) + j] = scale * FractRand (.5f) +
- AvgSquareVals (i, j, stride, size);
- j += stride;
- }
- i += stride;
- }
- /* Take the existing "diamond" data and make it into
- "squares". Back to our 4X4 example: The first time we
- encounter this code, the existing values are represented by
- "X"s, and the values we want to generate here are "*"s:
- X . * . X
- . . . . .
- * . X . *
- . . . . .
- X . * . X
- i and j represent our (x,y) position in the array. The
- first value we want to generate is at (i=2,j=0), and we use
- "oddline" and "stride" to increment j to the desired value.
- */
- oddline = 0;
- for (i=0; i<subSize; i+=stride)
- {
- oddline = (oddline == 0);
- for (j=0; j<subSize; j+=stride)
- {
- if ((oddline) && !j)
- j+=stride;
- // i and j are setup. Call avgDiamondVals with the
- // current position. It will return the average of the
- // surrounding diamond data points.
- m_pFa[(i * size) + j] = scale * FractRand (.5f) +
- AvgDiamondVals (i, j, stride, size, subSize);
- // To wrap edges seamlessly, copy edge values around
- // to other side of array.
- if (i==0)
- m_pFa[(subSize*size) + j] =
- m_pFa[(i * size) + j];
- if (j==0)
- m_pFa[(i*size) + subSize] =
- m_pFa[(i * size) + j];
- j+=stride;
- }
- }
- // reduce random number range.
- scale *= ratio;
- stride >>= 1;
- }
- }
- float* C3dObjectCloud::Alloc2DFractArray(int size)
- {
- float* fp;
- /* For a sizeXsize array, we need (size+1)X(size+1) space. For
- example, a 2x2 mesh needs 3x3=9 data points:
- * * *
- * * *
- * * *
- To account for this, increment 'size'. */
- size++;
- fp = (float*) malloc (sizeof(float) * size * size);
- if(!fp)
- {
- AfxMessageBox("Could not allocate cloud array points.", MB_OK);
- return NULL;
- }
- return fp;
- }
- void C3dObjectCloud::FreeFractArray()
- {
- free(m_pFa);
- m_pFa = NULL;
- }