Need Help ive tried everything i know... Stupid prim doesnt render...

Started by
8 comments, last by Armadon 18 years, 6 months ago
:( Hi sorry for yet again turning up with a noob questioln but ive encountered another program problem im unable to solve... This time its part of my Terrain Class. It seems to load each value in from the .raw file nicely putting it into an array of CustomVertex and the indices into an array of ints. So i thought hey everything is loading correct why don't I render it? I was hoping some one could fish out the problem in my code.
[SOURCE]
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ)
typedef struct CVert
{
	float x,y,z;
}CVert;
class CTerrain  
{
public:
	void Render (LPDIRECT3DDEVICE9 device);
	D3DMATERIAL9 m_material;
	void SetMaterial (void);
	void FillBuffers (LPDIRECT3DDEVICE9 device);
	void LoadRaw (int size, char *fName);
	CTerrain();
	virtual ~CTerrain();
	int NumCells;
	int NumVertz;
	float step;
	D3DXVECTOR3 MinBounds;
	D3DXVECTOR3 MaxBounds;

	CVert *verts;
	int *inds;
	LPDIRECT3DVERTEXBUFFER9 VrtBuffer;
	LPDIRECT3DINDEXBUFFER9 IndBuffer;
};

[/SOURCE]
^^^^ was the Terrain Class header its got my Custom Vertex CVert and teh terrain define.
[SOURCE]
/////SECOND INIT FUNCTION FILLS BUFFERS WITH INDICES AND VERTICES
void CTerrain::FillBuffers(LPDIRECT3DDEVICE9 device)
{
	void *pVertices;
	int *pIndex;
	device->CreateVertexBuffer(sizeof(CVert)*NumVertz,
                                      D3DUSAGE_WRITEONLY,
                                      D3DFVF_CUSTOMVERTEX,
                                      D3DPOOL_MANAGED,
                                      &VrtBuffer,
                                      NULL);
	VrtBuffer->Lock( 0, sizeof(verts), (void**)&pVertices, 0 );
	
	memcpy( pVertices, verts, sizeof(verts) );

	VrtBuffer->Unlock();

	device->CreateIndexBuffer(sizeof(int)*(NumCells*NumCells*2)*3,
                                     D3DUSAGE_WRITEONLY,
                                     D3DFMT_INDEX16,
                                     D3DPOOL_MANAGED,
                                     &IndBuffer,
                                     NULL);
	IndBuffer->Lock(0,sizeof(inds),(void**)&pIndex,0);
	memcpy( pIndex, inds, sizeof(inds) );
	IndBuffer->Unlock();

}
////RENDER
void CTerrain::SetMaterial()
{
//this function is temporary just assigning the material some values


      ZeroMemory( &m_material, sizeof(D3DMATERIAL9) );
      m_material.Diffuse.r = m_material.Ambient.r = 255;
      m_material.Diffuse.g = m_material.Ambient.g = 255;
      m_material.Diffuse.b = m_material.Ambient.b = 255;
      m_material.Diffuse.a = m_material.Ambient.a = 1.0f;

}


	
void CTerrain::Render(LPDIRECT3DDEVICE9 device)
{
	// Set material
	SetMaterial ();
	device->SetMaterial( &m_material );

	D3DXMATRIXA16 matWorld;
	D3DXMatrixTranslation(&matWorld,0,0,0);
	device->SetTransform( D3DTS_WORLD, &matWorld );

	device->SetStreamSource( 0, VrtBuffer,0, sizeof(CVert) );

	
	device->SetIndices(IndBuffer);

	// draw a triangle list using our 24 vertices and 12 triangles
	device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0,24,0,12);
}
[/SOURCE]
^^Render function and fill buffers of CTerrain
[SOURCE]
//Projection Matrix Setting function fov is PI/4 aspect is 800/600 zn is 0 zf is 1000
void CProjection::Update(LPDIRECT3DDEVICE9 device)
{
	D3DXMATRIX matProj;
	D3DXMatrixPerspectiveFovLH( &matProj, fov, aspect,zn,zf );
	device->SetTransform( D3DTS_PROJECTION, &matProj );
}
//Camera function its set up a little looking at 0,0,0
void CCamera::Update(LPDIRECT3DDEVICE9 device)
{
		// Get D3DX to fill in the matrix values
	D3DXMATRIXA16 matView;
	D3DXMatrixLookAtLH( &matView, &this->vEyePt, &this->vLookatPt, &this->vUpVec );
	// Set our view matrix
	device->SetTransform( D3DTS_VIEW, &matView ); 
}

{/SOURCE]
Camera and Projection Matricies
[SOURCE]
void Render (void)
{
    if( NULL == Core.device )
        return;
    
    // Begin the scene
    if( SUCCEEDED( Core.device->BeginScene() ) )
    {
        // Rendering of scene objects can happen here
		Terra.SetMaterial ();
		Terra.Render (Core.device);
    // Destroy the vertex buffer
        // End the scene
        Core.device->EndScene();
    }

    // Present the backbuffer contents to the display
    Core.device->Present( NULL, NULL, NULL, NULL );
}

void GInit ( HWND hwnd)
{
	Core.Init (hwnd);
	Core.MainCam.Init (0,10,10,0,0,0);
	Core.Projection.Init (800/600,0,1000);
	Terra.LoadRaw (64,"Height.raw");
	Terra.FillBuffers (Core.device);
	Core.Projection.Update (Core.device);
	
	
	Core.device->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(50,50,50) );
}
[/SOURCE]
//And there is my classes being used Core is just a D3D initer and holds the device. but all this is giving me nothing... what am i doing wrong
-Scotto
Advertisement
Hi there Scotto1001,
How are you doing buddy?

The Problem
Terrain is not rendering.

The Solution
Buddy, I would check a few things if I were you. This is generally a good thought pattern and does help alot.

1) Check that the vertices are copied into the vertex buffer correctly
2) Check that the indices are copied into the index buffer correctly
3) You could disable the light and just add some color to the vertices and render that so that you can be sure that your materials, lights aren't a problem
4) Make sure that how you are importing the data from your raw file is correct. Here is a little snippit to get you going.
Terrain Creation Demo Code
void CTerrain::Create(char* heightmap, IDirect3DDevice9* pDevice) {    unsigned char* aHeightMap = new unsigned char[numTerrainVertices];    {        ifstream f(heightmap, ios::binary);        f.read(reinterpret_cast<char*>(aHeightMap), numTerrainVertices);    }    TERRAINVERTEX* pVertexData = 0;    pDevice->CreateVertexBuffer(sizeof(TERRAINVERTEX) * numTerrainVertices, D3DUSAGE_WRITEONLY, TERRAINVERTEX::fvf, D3DPOOL_MANAGED, &m_pTerrainVB, NULL);    m_pTerrainVB->Lock(0, 0, (void**)&pVertexData, 0);    DWORD pos = 0;    for (int y = 0; y < terrainHeight; y++) {        for (int x = 0; x < terrainWidth; x++) {            pVertexData[pos].x = (float)x * cellScale;            pVertexData[pos].y = getScaledHeight(aHeightMap[pos]);            pVertexData[pos].z = (float)y * cellScale;            pVertexData[pos].u1 = (float)((terrainWidth - 1) - y) / (terrainWidth - 1);            pVertexData[pos].v1 = (float)(x) / (terrainHeight - 1);            pVertexData[pos].u2 = (float)((terrainWidth - 1) - y) / (terrainWidth - 1);            pVertexData[pos].v2 = (float)(x) / (terrainHeight - 1);            pos++;        }    }    m_pTerrainVB->Unlock();    delete []aHeightMap;    unsigned short* pIndexData = 0;    pDevice->CreateIndexBuffer(sizeof(unsigned short) * numTerrainPrimitives * 3, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pTerrainIB, NULL);    m_pTerrainIB->Lock(0, 0, (void**)&pIndexData, 0);    for (int y = 0; y < (terrainHeight - 1); y++) {        for (int x = 0; x < (terrainWidth - 1); x++) {            *pIndexData++ = y * terrainWidth + x; //v1            *pIndexData++ = y * terrainWidth + x + 1; //v2            *pIndexData++ = (y + 1) * terrainWidth + x + 1; //v4            *pIndexData++ = y * terrainWidth + x; //v1            *pIndexData++ = (y + 1) * terrainWidth + x + 1; //v4            *pIndexData++ = (y + 1) * terrainWidth + x; //v3        }    }    m_pTerrainIB->Unlock();}

5) Also make sure that your camera is pointing to the right direction and is not out of range.
6) Make sure you catered for adequite clipping range. If your terrain is more than 1000units away and you set your clipping planes to 1.0 and 1000.0 it might cause some headaches.

I hope some of this information helps.
Take care buddy.
Vertice's are good
Indice's are good
Height value's good
My camera is looking straight at the ground where the terrain should be rendering
Projections should be correct with 1 and 1000 because im 500 away with my camera from 0,0,0

but one question how do i disable light?

-Scotto
Have you tried running Direct3D in Debug mode? If you're using Visual Studio (I'm not sure how other IDEs handle it) and you run you program with D3D in debug mode, it gives you a lot of information about what's going on in D3D's internals, and often can tell you why problems are happening.

To switch on D3D Debug mode (if you have the SDK installed), go to Control Panel->DirectX->Direct3D. Then select "Use Debug version of Direct3D", and then move the slider to the right of that box toward "More", although if you slide it all the way, you'll probably get more information than you need.

Remember to switch back to retail mode afterward though, as the Debug version is slower than Retail.
The light docs are here.
*sigh* Im practically useless anyhow i cant find Control Panel in Visual Studio 6.0, and in that light doc it would be great if i was creating a light but i cant find where to disable a light sry @_@ im like stupid today...then again im stupid everyday could u give me the function plz i think it would be SetLightState() buti cant find any parameters.
-Scotto
Hi Scotto1001,
How are you doing buddy?

The Problem
Terrain still not rendering

The Solution
Disabling light : pDevice->SetLight(0, NULL);

I think the problem may lie elsewhere but it's hard to tell without the code that actually reads the vertices or generates the indices. They might be wrong.

I would give you some demo coding to look over and you can just compare your terrain generation with the demo code

Demo Code
CTerrain.h
#ifndef _CTerrain_H_#define _CTerrain_H_#define sqrtf (float)sqrt#include <d3dx9.h>#include <d3d9.h>#include <fstream>class CTerrain {public:         CTerrain();        ~CTerrain();        void Create(char* heightmap, IDirect3DDevice9* pDevice);        void CreateTexture(char* texture_overlay, char* texture_details, IDirect3DDevice9* pDevice);        void SetTextureStages(IDirect3DDevice9* pDevice);        void Render(IDirect3DDevice9* pDevice);private:        LPDIRECT3DVERTEXBUFFER9 m_pTerrainVB;        LPDIRECT3DINDEXBUFFER9 m_pTerrainIB;        LPDIRECT3DTEXTURE9 textureDetails, textureOverlay;        DWORD numTerrainVertices;        DWORD numTerrainPrimitives;        int terrainWidth;        int terrainHeight;        float cellScale;        float scaleHeight;                struct TERRAINVERTEX {            float x, y, z;            float u1, v1;            float u2, v2;            const static DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX2;        };        float getScaledHeight(unsigned char heightmapValue) const;};#endif

CTerrain.cpp
#include "CTerrain.h"using namespace std;CTerrain::CTerrain() {    terrainWidth = 256;    terrainHeight = 256;    cellScale = 0.25f;    scaleHeight = 10.0f;    numTerrainVertices = terrainWidth * terrainHeight;    numTerrainPrimitives = (terrainWidth - 1) * (terrainHeight - 1) * 2;    m_pTerrainVB = NULL;    m_pTerrainIB = NULL;}CTerrain::~CTerrain() {    if (m_pTerrainVB) {        m_pTerrainVB->Release();        m_pTerrainVB = NULL;    }    if (m_pTerrainIB) {        m_pTerrainIB->Release();        m_pTerrainIB = NULL;    }}void CTerrain::Create(char* heightmap, IDirect3DDevice9* pDevice) {    unsigned char* aHeightMap = new unsigned char[numTerrainVertices];    {        ifstream f(heightmap, ios::binary);        f.read(reinterpret_cast<char*>(aHeightMap), numTerrainVertices);    }    TERRAINVERTEX* pVertexData = 0;    pDevice->CreateVertexBuffer(sizeof(TERRAINVERTEX) * numTerrainVertices, D3DUSAGE_WRITEONLY, TERRAINVERTEX::fvf, D3DPOOL_MANAGED, &m_pTerrainVB, NULL);    m_pTerrainVB->Lock(0, 0, (void**)&pVertexData, 0);    DWORD pos = 0;    for (int y = 0; y < terrainHeight; y++) {        for (int x = 0; x < terrainWidth; x++) {            pVertexData[pos].x = (float)x * cellScale;            pVertexData[pos].y = getScaledHeight(aHeightMap[pos]);            pVertexData[pos].z = (float)y * cellScale;            pVertexData[pos].u1 = (float)((terrainWidth - 1) - y) / (terrainWidth - 1);            pVertexData[pos].v1 = (float)(x) / (terrainHeight - 1);            pVertexData[pos].u2 = (float)((terrainWidth - 1) - y) / (terrainWidth - 1);            pVertexData[pos].v2 = (float)(x) / (terrainHeight - 1);            pos++;        }    }    m_pTerrainVB->Unlock();    delete []aHeightMap;    unsigned short* pIndexData = 0;    pDevice->CreateIndexBuffer(sizeof(unsigned short) * numTerrainPrimitives * 3, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pTerrainIB, NULL);    m_pTerrainIB->Lock(0, 0, (void**)&pIndexData, 0);    for (int y = 0; y < (terrainHeight - 1); y++) {        for (int x = 0; x < (terrainWidth - 1); x++) {            *pIndexData++ = y * terrainWidth + x; //v1            *pIndexData++ = y * terrainWidth + x + 1; //v2            *pIndexData++ = (y + 1) * terrainWidth + x + 1; //v4            *pIndexData++ = y * terrainWidth + x; //v1            *pIndexData++ = (y + 1) * terrainWidth + x + 1; //v4            *pIndexData++ = (y + 1) * terrainWidth + x; //v3        }    }    m_pTerrainIB->Unlock();}void CTerrain::Render(IDirect3DDevice9* pDevice){    pDevice->SetFVF(TERRAINVERTEX::fvf);    pDevice->SetTexture(0, textureOverlay);    pDevice->SetTexture(1, textureDetails);    pDevice->SetStreamSource(0, m_pTerrainVB, 0, sizeof(TERRAINVERTEX));    pDevice->SetIndices(m_pTerrainIB);    pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numTerrainVertices, 0, numTerrainPrimitives);    pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);}inline float CTerrain::getScaledHeight(unsigned char heightmapValue) const {    return heightmapValue / 255.0f * scaleHeight;}void CTerrain::CreateTexture(char* texture_overlay, char* texture_details, IDirect3DDevice9* pDevice){D3DXCreateTextureFromFile(pDevice, texture_details, &textureDetails);D3DXCreateTextureFromFile(pDevice, texture_overlay, &textureOverlay);}



I really hope this helps buddy,
Take care.

PS: if you really have any serious problems and you feel that you want to send me your code to look at. please do not hesitate to contact me. I am sure someone has your solution though, hang in there buddy.
thx again armadon looking at your code has brought something to my attention... From the get go when i wrote the D3DBase class that inited d3d.. I had d3d clear the screen to blue... but the screen is black and always has been so maybe its something in how i inited d3d...
-Scotto
after quite a bit of tinkering and time imbetween my homework and stuff i have managed to render a terrain =D. Thx Armadon for your help and you too gregs but i have one more quest any links to a normal calculation tutorial that really duals down the math so i can understand it i havent been through algebra II yet so im still learning but i would really like to put some lighting on my terrain. without it looking like a 2D mass of green...
-Scotto
Hi there Scotto1001,
How are you doing?

The Problem
Lighting for terrain
The Solution
You might consider looking at Lighting Maps. These are normally very helpful for large terrains. The basic overview goes in the sense that for a huge terrain you don't want to waste time calculating normals, although these normals might be static and precomputed.

Lightmaps are easy to implement and basically works in the sense that where the lightmap has a bright value let's say 255 you will change the value of the vertices where the lightmap is 255 to 255 for the alpha component and where the lightmap is dark( e.g. 0 ) you have the corresponding alpha value.

Wow, that's alot to take in right?

I hope this helps a bit.
Take care buddy.

This topic is closed to new replies.

Advertisement