#include "dxut.h"
#include "Terrain.h"
#include "d3dUtil.h"
#include "Camera.h"
#include <algorithm>
#include <list>
#include "SDKmisc.h"
Terrain::Terrain(LPDIRECT3DDEVICE9 pDevice, UINT vertRows, UINT vertCols, float dx, float dz, 
LPCWSTR heightmap, LPCWSTR tex0, LPCWSTR tex1, 
LPCWSTR tex2, LPCWSTR blendMap, float heightScale, 
float yOffset)
{
WCHAR filename[MAX_PATH]; m_pDevice = pDevice;
mVertRows = vertRows;
mVertCols = vertCols; mDX = dx;
mDZ = dz; mWidth = (mVertCols-1)*mDX;
mDepth = (mVertRows-1)*mDZ; DXUTFindDXSDKMediaFileCch( filename, MAX_PATH, heightmap ); mHeightmap.loadRAW(vertRows, vertCols, (LPCWSTR)filename, heightScale, yOffset); DXUTFindDXSDKMediaFileCch( filename, MAX_PATH, tex0 );
D3DXCreateTextureFromFile(m_pDevice, filename, &mTex0); DXUTFindDXSDKMediaFileCch( filename, MAX_PATH, tex1 );
D3DXCreateTextureFromFile(m_pDevice, filename, &mTex1); DXUTFindDXSDKMediaFileCch( filename, MAX_PATH, tex2 );
D3DXCreateTextureFromFile(m_pDevice, filename, &mTex2); DXUTFindDXSDKMediaFileCch( filename, MAX_PATH, blendMap );
D3DXCreateTextureFromFile(m_pDevice, filename, &mBlendMap); buildGeometry();
buildEffect(); gCamera = new Camera;    gCamera->pos() = D3DXVECTOR3(0, -0, 0);
    gCamera->setSpeed(100.0f);
}Terrain::~Terrain()
{
for(UINT i = 0; i < mSubGrids.size(); ++i)
SafeRelease(mSubGrids[i].mesh);

delete gCamera;
SafeRelease(mFX);
SafeRelease(mTex0);
SafeRelease(mTex1);
SafeRelease(mTex2);
SafeRelease(mBlendMap);
}DWORD Terrain::getNumTriangles()
{
return (DWORD)mSubGrids.size()*mSubGrids[0].mesh->GetNumFaces();
}DWORD Terrain::getNumVertices()
{
return (DWORD)mSubGrids.size()*mSubGrids[0].mesh->GetNumVertices();
}float Terrain::getWidth()
{
return mWidth;
}float Terrain::getDepth()
{
return mDepth;
}void Terrain::onLostDevice()
{
HRESULT hr;
V(mFX->OnLostDevice());
}void Terrain::onResetDevice()
{
HRESULT hr;
V(mFX->OnResetDevice());
}float Terrain::getHeight(float x, float z)
{
// Transform from terrain local space to "cell" space.
float c = (x + 0.5f*mWidth) /  mDX;
float d = (z - 0.5f*mDepth) / -mDZ; int row = (int)floorf(d);
int col = (int)floorf(c); float A = mHeightmap(row, col);
float B = mHeightmap(row, col+1);
float C = mHeightmap(row+1, col);
float D = mHeightmap(row+1, col+1); float s = c - (float)col;
float t = d - (float)row; if(t < 1.0f - s)
{
float uy = B - A;
float vy = C - A;
return A + s*uy + t*vy;
}
else  {
float uy = C - D;
float vy = B - D;
return D + (1.0f-s)*uy + (1.0f-t)*vy;
}
}void Terrain::setDirToSunW(const D3DXVECTOR3& d)
{
HRESULT hr;
V(mFX->SetValue(mhDirToSunW, &d, sizeof(D3DXVECTOR3)));
}bool Terrain::SubGrid::operator<(const SubGrid& rhs) const
{
D3DXVECTOR3 d1 = box.center() - gCamera->pos();
D3DXVECTOR3 d2 = rhs.box.center() - gCamera->pos();
return D3DXVec3LengthSq(&d1) < D3DXVec3LengthSq(&d2);
}void Terrain::draw()
{
std::list<SubGrid> visibleSubGrids;
for(UINT i = 0; i < mSubGrids.size(); ++i)
{
if( gCamera->isVisible(mSubGrids[i].box) )
visibleSubGrids.push_back(mSubGrids[i]);
} visibleSubGrids.sort(); THR(mFX->SetMatrix(mhViewProj, &gCamera->viewProj()));
THR(mFX->SetTechnique(mhTech));
UINT numPasses = 0;
THR(mFX->Begin(&numPasses, 0));
THR(mFX->BeginPass(0)); for(std::list<SubGrid>::iterator iter = visibleSubGrids.begin(); iter != visibleSubGrids.end(); ++iter)
THR(iter->mesh->DrawSubset(0)); THR(mFX->EndPass());
THR(mFX->End());
}void Terrain::buildGeometry()
{
DWORD numTris  = (mVertRows-1)*(mVertCols-1)*2;
DWORD numVerts = mVertRows*mVertCols; ID3DXMesh* mesh = 0;
D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
UINT numElems = 0;
THR(VertexPNT::Decl->GetDeclaration(elems, &numElems));
THR(D3DXCreateMesh(numTris, numVerts, 
D3DPOOL_SCRATCH|D3DXMESH_32BIT, elems, m_pDevice, &mesh));
VertexPNT* v = 0;
THR(mesh->LockVertexBuffer(0, (void**)&v));

std::vector<D3DXVECTOR3> verts;
std::vector<DWORD> indices;
GenTriGrid(mVertRows, mVertCols, mDX, mDZ, D3DXVECTOR3(0.0f, 0.0f, 0.0f), verts, indices); float w = mWidth;
float d = mDepth;
for(UINT i = 0; i < mesh->GetNumVertices(); ++i)
{
int r = i / mVertCols;
int c = i % mVertCols; v[i].pos   = verts[i];
v[i].pos.y = mHeightmap(r, c); v[i].tex0.x = (v[i].pos.x + (0.5f*w)) / w;
v[i].tex0.y = (v[i].pos.z - (0.5f*d)) / -d;
} DWORD* indexBuffPtr = 0;
THR(mesh->LockIndexBuffer(0, (void**)&indexBuffPtr));
for(UINT i = 0; i < mesh->GetNumFaces(); ++i)
{
indexBuffPtr[i*3+0] = indices[i*3+0];
indexBuffPtr[i*3+1] = indices[i*3+1];
indexBuffPtr[i*3+2] = indices[i*3+2];
}
THR(mesh->UnlockIndexBuffer()); THR(D3DXComputeNormals(mesh, 0));
int subGridRows = (mVertRows-1) / (SubGrid::NUM_ROWS-1);
int subGridCols = (mVertCols-1) / (SubGrid::NUM_COLS-1); for(int r = 0; r < subGridRows; ++r)
{
for(int c = 0; c < subGridCols; ++c)
{
// Rectangle that indicates (via matrix indices ij) the
// portion of grid vertices to use for this subgrid.
RECT R = 
{
c * (SubGrid::NUM_COLS-1),
r * (SubGrid::NUM_ROWS-1),
(c+1) * (SubGrid::NUM_COLS-1),
(r+1) * (SubGrid::NUM_ROWS-1)
}; buildSubGridMesh(R, v); 
}
} THR(mesh->UnlockVertexBuffer()); SafeRelease(mesh); // Done with global mesh.
}void Terrain::buildSubGridMesh(RECT& R, VertexPNT* gridVerts)
{
std::vector<D3DXVECTOR3> tempVerts;
std::vector<DWORD> tempIndices;
GenTriGrid(SubGrid::NUM_ROWS, SubGrid::NUM_COLS, mDX, mDZ, 
D3DXVECTOR3(0.0f, 0.0f, 0.0f), tempVerts, tempIndices); ID3DXMesh* subMesh = 0;
D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
UINT numElems = 0;
THR(VertexPNT::Decl->GetDeclaration(elems, &numElems));
THR(D3DXCreateMesh(SubGrid::NUM_TRIS, SubGrid::NUM_VERTS, 
D3DXMESH_MANAGED, elems, m_pDevice, &subMesh));
VertexPNT* v = 0;
THR(subMesh->LockVertexBuffer(0, (void**)&v));
int k = 0;
for(int i = R.top; i <= R.bottom; ++i)
{
for(int j = R.left; j <= R.right; ++j)
{
v[k++] = gridVerts[i*mVertCols+j];
}
} AABB bndBox;
THR(D3DXComputeBoundingBox((D3DXVECTOR3*)v, subMesh->GetNumVertices(), 
sizeof(VertexPNT), &bndBox.minPt, &bndBox.maxPt)); THR(subMesh->UnlockVertexBuffer());
WORD* indices  = 0;
DWORD* attBuff = 0;
THR(subMesh->LockIndexBuffer(0, (void**)&indices));
THR(subMesh->LockAttributeBuffer(0, &attBuff));
for(int i = 0; i < SubGrid::NUM_TRIS; ++i)
{
indices[i*3+0] = (WORD)tempIndices[i*3+0];
indices[i*3+1] = (WORD)tempIndices[i*3+1];
indices[i*3+2] = (WORD)tempIndices[i*3+2]; attBuff[i] = 0; // All in subset 0.
}
THR(subMesh->UnlockIndexBuffer());
THR(subMesh->UnlockAttributeBuffer());
DWORD* adj = new DWORD[subMesh->GetNumFaces()*3];
THR(subMesh->GenerateAdjacency(0.001f, adj));
THR(subMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE|D3DXMESHOPT_ATTRSORT,
adj, 0, 0, 0));
delete[] adj;
SubGrid g;
g.mesh = subMesh;
g.box  = bndBox;
mSubGrids.push_back(g);
}void Terrain::buildEffect()
{
ID3DXBuffer* errors = 0;
WCHAR str[MAX_PATH];
DWORD dwShaderFlags = 0; THR( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"Terrain.fx" ) );
THR(D3DXCreateEffectFromFile(m_pDevice, str,
0, 0, dwShaderFlags, 0, &mFX, &errors));
if( errors )
MessageBox(0, (LPCWSTR)errors->GetBufferPointer(), 0, 0); mhTech      = mFX->GetTechniqueByName("TerrainTech");
mhViewProj  = mFX->GetParameterByName(0, "gViewProj");
mhDirToSunW = mFX->GetParameterByName(0, "gDirToSunW");
mhTex0      = mFX->GetParameterByName(0, "gTex0");
mhTex1      = mFX->GetParameterByName(0, "gTex1");
mhTex2      = mFX->GetParameterByName(0, "gTex2");
mhBlendMap  = mFX->GetParameterByName(0, "gBlendMap"); THR(mFX->SetTexture(mhTex0, mTex0));
THR(mFX->SetTexture(mhTex1, mTex1));
THR(mFX->SetTexture(mhTex2, mTex2));
THR(mFX->SetTexture(mhBlendMap, mBlendMap));
}
这个是关于地形Terrain的程序代码?那位高手可以看出来他是用什么方法做的吗?

解决方案 »

  1.   

    这是用什么方法做的地形啊?
    PS:
    今天星期六,大家都玩儿去了吧?.......谁有做好的动态云可不可以发我一份,作个参考?[email protected]
      

  2.   

    // CPoint3DCloudView.cpp : implementation of the CCPoint3DCloudView class
    //#include "stdafx.h"
    #include "CPoint3DCloud.h"#include "CPoint3DCloudDoc.h"
    #include "CPoint3DCloudView.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CCPoint3DCloudViewIMPLEMENT_DYNCREATE(CCPoint3DCloudView, CView)BEGIN_MESSAGE_MAP(CCPoint3DCloudView, CView)
    //{{AFX_MSG_MAP(CCPoint3DCloudView)
    ON_WM_DESTROY()
    ON_WM_CREATE()
    ON_WM_ERASEBKGND()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_MOUSEMOVE()
    ON_WM_MOUSEWHEEL()
    ON_WM_RBUTTONDOWN()
    ON_WM_RBUTTONUP()
    ON_WM_SIZE()
    ON_WM_MBUTTONDOWN()
    ON_WM_MBUTTONUP()
    //}}AFX_MSG_MAP
    // Standard printing commands
    ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CCPoint3DCloudView construction/destructionCCPoint3DCloudView::CCPoint3DCloudView()
    {
    // TODO: add construction code here
    m_nViewOpenGL.SetProjectionMode(1);
    m_nViewOpenGL.SetTwoView(false);
    }CCPoint3DCloudView::~CCPoint3DCloudView()
    {
    }BOOL CCPoint3DCloudView::PreCreateWindow(CREATESTRUCT& cs)
    {
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs return CView::PreCreateWindow(cs);
    }/////////////////////////////////////////////////////////////////////////////
    // CCPoint3DCloudView drawingvoid CCPoint3DCloudView::OnDraw(CDC* pDC)
    {
    CCPoint3DCloudDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here
    m_nViewOpenGL.OnInitRenderOpenGL();
          pDoc->OnDraw();
    m_nViewOpenGL.SwapBufferOpenGL();
    }/////////////////////////////////////////////////////////////////////////////
    // CCPoint3DCloudView printingBOOL CCPoint3DCloudView::OnPreparePrinting(CPrintInfo* pInfo)
    {
    // default preparation
    return DoPreparePrinting(pInfo);
    }void CCPoint3DCloudView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
    {
    // TODO: add extra initialization before printing
    }void CCPoint3DCloudView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
    {
    // TODO: add cleanup after printing
    }/////////////////////////////////////////////////////////////////////////////
    // CCPoint3DCloudView diagnostics#ifdef _DEBUG
    void CCPoint3DCloudView::AssertValid() const
    {
    CView::AssertValid();
    }void CCPoint3DCloudView::Dump(CDumpContext& dc) const
    {
    CView::Dump(dc);
    }CCPoint3DCloudDoc* CCPoint3DCloudView::GetDocument() // non-debug version is inline
    {
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCPoint3DCloudDoc)));
    return (CCPoint3DCloudDoc*)m_pDocument;
    }
    #endif //_DEBUG/////////////////////////////////////////////////////////////////////////////
    // CCPoint3DCloudView message handlersvoid CCPoint3DCloudView::OnDestroy() 
    {
    CView::OnDestroy();

    // TODO: Add your message handler code here
    m_nViewOpenGL.OnDestroyOpenGL();
    }int CCPoint3DCloudView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
    if (CView::OnCreate(lpCreateStruct) == -1)
    return -1;

    // TODO: Add your specialized creation code here
    m_nViewOpenGL.OnInitOpenGL(GetSafeHwnd());
    return 0;
    }BOOL CCPoint3DCloudView::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
    return TRUE;
    // return CView::OnEraseBkgnd(pDC);
    }void CCPoint3DCloudView::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nViewOpenGL.OnLButtonDown(nFlags,point);
    CView::OnLButtonDown(nFlags, point);
    }void CCPoint3DCloudView::OnLButtonUp(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nViewOpenGL.OnLButtonUp(nFlags,point);
    InvalidateRect(NULL,FALSE); 
    CView::OnLButtonUp(nFlags, point);
    }void CCPoint3DCloudView::OnMouseMove(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nViewOpenGL.OnMouseMove(nFlags,point);
    InvalidateRect(NULL,FALSE); 
    CView::OnMouseMove(nFlags, point);
    }BOOL CCPoint3DCloudView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nViewOpenGL.OnMouseWheel(nFlags, zDelta, pt);
    InvalidateRect(NULL,FALSE);
    return CView::OnMouseWheel(nFlags, zDelta, pt);
    }void CCPoint3DCloudView::OnRButtonDown(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nViewOpenGL.OnRButtonDown(nFlags, point);
    CView::OnRButtonDown(nFlags, point);
    }void CCPoint3DCloudView::OnRButtonUp(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nViewOpenGL.OnRButtonUp(nFlags,point);
    InvalidateRect(NULL,FALSE); 
    CView::OnRButtonUp(nFlags, point);
    }void CCPoint3DCloudView::OnSize(UINT nType, int cx, int cy) 
    {
    CView::OnSize(nType, cx, cy);

    // TODO: Add your message handler code here
        m_nViewOpenGL.OnSizeOpenGL(nType, cx, cy);
    }void CCPoint3DCloudView::OnMButtonDown(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nViewOpenGL.OnMButtonDown(nFlags,point);
    CView::OnMButtonDown(nFlags, point);
    }void CCPoint3DCloudView::OnMButtonUp(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nViewOpenGL.OnMButtonUp(nFlags,point);
    InvalidateRect(NULL,FALSE); 
    CView::OnMButtonUp(nFlags, point);
    }