323 lines
10 KiB
C++
323 lines
10 KiB
C++
///////////////////////////////////////////////////////////////////////
|
|
// 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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <vector>
|
|
//#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<float*>(pBuffer + 0);
|
|
float* pTexCoords1 = reinterpret_cast<float*>(pTexCoords0 + c_nGrassVertexTexture0Size * uiNumBlades * c_nNumCorners / sizeof(float));
|
|
unsigned char* pColors = (unsigned char*) pTexCoords1 + c_nGrassVertexTexture1Size * uiNumBlades * c_nNumCorners;
|
|
float* pPositions = reinterpret_cast<float*>(pColors + c_nGrassVertexColorSize * uiNumBlades * c_nNumCorners);
|
|
|
|
for (vector<SBlade>::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
|
|
|