/////////////////////////////////////////////////////////////////////// // CSpeedGrassWrapper Class // // (c) 2003 IDV, Inc. // // *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION *** // // This software is supplied under the terms of a license agreement or // nondisclosure agreement with Interactive Data Visualization and may // not be copied or disclosed except in accordance with the terms of // that agreement. // // Copyright (c) 2001-2003 IDV, Inc. // All Rights Reserved. // // IDV, Inc. // 1233 Washington St. Suite 610 // Columbia, SC 29201 // Voice: (803) 799-1699 // Fax: (803) 931-0320 // Web: http://www.idvinc.com #include "StdAfx.h" #include #include #include //#include "../Common Source/extgl.h" //#include "SpeedGrassWrapper.h" //#include "Scene.h" //#include "../Common Source/nv_dds.h" //#include "../Common Source/Random.h" //#include "TextureLayers.h" using namespace std; #ifdef USE_SPEEDGRASS /////////////////////////////////////////////////////////////////////// // CSpeedGrassWrapper::CSpeedGrassWrapper CSpeedGrassWrapper::CSpeedGrassWrapper() : m_pMapOutdoor(NULL), m_lpD3DTexure8(NULL)//m_uiTexture(0) { } /////////////////////////////////////////////////////////////////////// // CSpeedGrassWrapper::~CSpeedGrassWrapper CSpeedGrassWrapper::~CSpeedGrassWrapper( ) { } /////////////////////////////////////////////////////////////////////// // CSpeedGrassWrapper::Draw int CSpeedGrassWrapper::Draw(float fDensity) { int nTriangleCount = 0; // // determine which regions are visible // Cull( ); // // // setup opengl state // glPushAttrib(GL_ENABLE_BIT); // glDisable(GL_CULL_FACE); // glDisable(GL_BLEND); // // glEnable(GL_TEXTURE_2D); // glBindTexture(GL_TEXTURE_2D, m_uiTexture); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // // glEnable(GL_ALPHA_TEST); // glAlphaFunc(GL_GREATER, 0.4f); // glDisable(GL_LIGHTING); // // unsigned int uiCount = 0; // unsigned int uiNumRegions = 0; // const SRegion* pRegions = GetRegions(uiNumRegions); // // // setup for vertex buffer rendering (enable client buffers) // CIdvVertexBuffer::Enable(true); // if (uiNumRegions > 0) // pRegions[0].m_pVertexBuffer->EnableClientStates( ); // // // run through the regions and render those that aren't culled // for (unsigned int i = 0; i < uiNumRegions; ++i) // { // if (!pRegions[i].m_bCulled) // { // pRegions[i].m_pVertexBuffer->Bind( ); // unsigned int uiNumBlades = int(fDensity * pRegions[i].m_vBlades.size( )); // glDrawArrays(GL_QUADS, 0, uiNumBlades * 4); // nTriangleCount += uiNumBlades * 2; // } // } // // // disable client buffers // if (uiNumRegions > 0) // pRegions[0].m_pVertexBuffer->DisableClientStates( ); // CIdvVertexBuffer::Disable(true); // // // restore opengl state // glPopAttrib( ); return nTriangleCount; } /////////////////////////////////////////////////////////////////////// // CSpeedGrassWrapper::InitFromBsfFile bool CSpeedGrassWrapper::InitFromBsfFile(const char* pFilename, unsigned int nNumBlades, unsigned int uiRows, unsigned int uiCols, float fCollisionDistance) { bool bSuccess = false; if (pFilename) { // use SpeedGrass's built-in parse function if (ParseBsfFile(pFilename, nNumBlades, uiRows, uiCols, fCollisionDistance)) bSuccess = true; } InitGraphics( ); return bSuccess; } /////////////////////////////////////////////////////////////////////// // CSpeedGrassWrapper::Color float CSpeedGrassWrapper::Color(float fX, float fY, const float* pNormal, float* pTopColor, float* pBottomColor) const { const float c_fColorAdjust = 0.3f; // controls how much the color of the top vertices of each grass blade can vary const float c_fColorThrow = 1.0f; // controls how much the r, g, and b components can vary const float c_fColorRandomness = 0.01f; // controls how much the r, g, and b components can vary const float c_TopLight = 0.75f; float afLowColor[4] = { 0.0f }, afHighColor[4] = { 0.0f }; if (m_pMapOutdoor->GetBrushColor(fX, fY, afLowColor, afHighColor)) { pBottomColor[0] = afLowColor[2]; pBottomColor[1] = afLowColor[1]; pBottomColor[2] = afLowColor[0]; float fColorThrow = GetRandom(0.0f, c_fColorThrow); pTopColor[0] = VecInterpolate(pBottomColor[0], afHighColor[2], fColorThrow) + GetRandom(-c_fColorRandomness, c_fColorRandomness); pTopColor[1] = VecInterpolate(pBottomColor[1], afHighColor[1], fColorThrow) + GetRandom(-c_fColorRandomness, c_fColorRandomness); pTopColor[2] = VecInterpolate(pBottomColor[2], afHighColor[0], fColorThrow) + GetRandom(-c_fColorRandomness, c_fColorRandomness); float fLargest = pTopColor[0]; if (pTopColor[1] > fLargest) fLargest = pTopColor[1]; if (pTopColor[2] > fLargest) fLargest = pTopColor[2]; if (fLargest > 1.0f) { pTopColor[0] /= fLargest; pTopColor[1] /= fLargest; pTopColor[2] /= fLargest; } pTopColor[0] = max(0.0f, pTopColor[0]); pTopColor[1] = max(0.0f, pTopColor[1]); pTopColor[2] = max(0.0f, pTopColor[2]); } return afLowColor[3]; } /////////////////////////////////////////////////////////////////////// // CSpeedGrassWrapper::Height float CSpeedGrassWrapper::Height(float fX, float fY, float* pNormal) const { float fHeight = 0.0f; float afPos[3] = { fX, fY, 0.0f }; fHeight = m_pMapOutdoor->GetHeight(afPos); pNormal[0] = 0.0f; pNormal[1] = 0.0f; pNormal[2] = 1.0f; return fHeight; } /////////////////////////////////////////////////////////////////////// // CSpeedGrassWrapper::InitGraphics void CSpeedGrassWrapper::InitGraphics(void) { // load texture // m_uiTexture = LoadDDS((c_strDataPath + string("brush_2.dds")).c_str( )); CGraphicImage * pImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer("D:/ymir work/special/brush_2.dds"); m_GrassImageInstance.SetImagePointer(pImage); m_lpD3DTexure8 = m_GrassImageInstance.GetTexturePointer()->GetD3DTexture(); // prepare static vertex buffers for (int i = 0; i < m_nNumRegions; ++i) { SRegion* pRegion = m_pRegions + i; // pRegion->m_pVertexBuffer = new CIdvVertexBuffer; // setup up temporary buffer to copy later const int c_nNumCorners = 4; unsigned int uiNumBlades = pRegion->m_vBlades.size( ); unsigned int uiBufferSize = uiNumBlades * c_nNumCorners * c_nGrassVertexTotalSize; unsigned char* pBuffer = new unsigned char[uiBufferSize]; // setup initial pointers for individual attribute copying float* pTexCoords0 = reinterpret_cast(pBuffer + 0); float* pTexCoords1 = reinterpret_cast(pTexCoords0 + c_nGrassVertexTexture0Size * uiNumBlades * c_nNumCorners / sizeof(float)); unsigned char* pColors = (unsigned char*) pTexCoords1 + c_nGrassVertexTexture1Size * uiNumBlades * c_nNumCorners; float* pPositions = reinterpret_cast(pColors + c_nGrassVertexColorSize * uiNumBlades * c_nNumCorners); for (vector::const_iterator iBlade = pRegion->m_vBlades.begin( ); iBlade != pRegion->m_vBlades.end( ); ++iBlade) { float fS1 = float(iBlade->m_ucWhichTexture) / c_nNumBladeMaps; float fS2 = float(iBlade->m_ucWhichTexture + 1) / c_nNumBladeMaps; for (int nCorner = 0; nCorner < c_nNumCorners; ++nCorner) { // texcoord 0 switch (nCorner) { case 0: pTexCoords0[0] = fS2; pTexCoords0[1] = 1.0f; break; case 1: pTexCoords0[0] = fS1; pTexCoords0[1] = 1.0f; break; case 2: pTexCoords0[0] = fS1; pTexCoords0[1] = 0.0f; break; case 3: pTexCoords0[0] = fS2; pTexCoords0[1] = 0.0f; break; default: assert(false); } pTexCoords0 += c_nGrassVertexTexture0Size / sizeof(float); // texcoord 1 switch (nCorner) { case 0: pTexCoords1[0] = c_nShaderGrassBillboard; pTexCoords1[2] = iBlade->m_fThrow; break; case 1: pTexCoords1[0] = c_nShaderGrassBillboard + 1; pTexCoords1[2] = iBlade->m_fThrow; break; case 2: pTexCoords1[0] = c_nShaderGrassBillboard + 2; pTexCoords1[2] = 0.0f; break; case 3: pTexCoords1[0] = c_nShaderGrassBillboard + 3; pTexCoords1[2] = 0.0f; break; default: assert(false); } // same for all corners pTexCoords1[1] = iBlade->m_fSize; pTexCoords1[3] = iBlade->m_fNoise; pTexCoords1 += c_nGrassVertexTexture1Size / sizeof(float); // color unsigned long ulColor = 0; if (nCorner == 0 || nCorner == 1) ulColor = (int(iBlade->m_afTopColor[0] * 255.0f) << 0) + (int(iBlade->m_afTopColor[1] * 255.0f) << 8) + (int(iBlade->m_afTopColor[2] * 255.0f) << 16) + 0xff000000; else ulColor = (int(iBlade->m_afBottomColor[0] * 255.0f) << 0) + (int(iBlade->m_afBottomColor[1] * 255.0f) << 8) + (int(iBlade->m_afBottomColor[2] * 255.0f) << 16) + 0xff000000; memcpy(pColors, &ulColor, c_nGrassVertexColorSize); pColors += c_nGrassVertexColorSize; // position memcpy(pPositions, iBlade->m_afPos, c_nGrassVertexPositionSize); pPositions += c_nGrassVertexPositionSize / sizeof(float); } } // assert((unsigned char*) pTexCoords0 - pBuffer == c_nGrassVertexTexture0Size * uiNumBlades * c_nNumCorners); // assert(pTexCoords1 - pTexCoords0 == (c_nGrassVertexTexture1Size * uiNumBlades * c_nNumCorners) / sizeof(float)); // assert(pColors - (unsigned char*) pTexCoords1 == c_nGrassVertexColorSize * uiNumBlades * c_nNumCorners); // assert((unsigned char*) pPositions - pColors == c_nGrassVertexPositionSize * uiNumBlades * c_nNumCorners); // pRegion->m_pVertexBuffer->SetBuffer(pBuffer, uiBufferSize, true); // pRegion->m_pVertexBuffer->SetStride(CIdvVertexBuffer::VERTEX_TEXCOORD0, 2, GL_FLOAT, 0, 0); // pRegion->m_pVertexBuffer->SetStride(CIdvVertexBuffer::VERTEX_TEXCOORD1, 4, GL_FLOAT, 0, (unsigned char*) pTexCoords0 - pBuffer); // pRegion->m_pVertexBuffer->SetStride(CIdvVertexBuffer::VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, 0, (unsigned char*) pTexCoords1 - pBuffer); // pRegion->m_pVertexBuffer->SetStride(CIdvVertexBuffer::VERTEX_POSITION, 3, GL_FLOAT, 0, pColors - pBuffer); DWORD dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1; // pRegion->m_VertexBuffer.Create(); delete[] pBuffer; } } #endif // USE_SPEEDGRASS