client/SpeedTreeLib/SpeedGrassWrapper.cpp

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