Jump to content
  • Advertisement
Sign in to follow this  
Honas

Passing an object to another class

This topic is 2479 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey gamedev,
I am extremely rusty with my C++ skills. I want to pass my camera object to the terrain class, so I can cull some subgrids from my view frustrum.
So, my initial idea was to pass the camera in the terrain constructor.
I have my camera declared like this:
Camera g_Camera;
and after I initialize the camera I call the constructor for my terrain.
I am really unsure how I should accomplish this, but I would save a "Camera &" in my terrain class and just pass over the reference in the constructor. But I get these errors:

1>c:\***\thegame\terrain.cpp(13): error C2758: 'Terrain::mCamera' : must be initialized in constructor base/member initializer list
1> c:\***\thegame\terrain.h(72) : see declaration of 'Terrain::mCamera'
1>c:\***\thegame\terrain.cpp(128): error C2327: 'Terrain::mCamera' : is not a type name, static, or enumerator
1>c:\***\thegame\terrain.cpp(128): error C2065: 'mCamera' : undeclared identifier
1>c:\***\thegame\terrain.cpp(128): error C2228: left of '.getPos' must have class/struct/union
1> type is ''unknown-type''


Can anyone outline the correct way to do this? [Full code below]

Share this post


Link to post
Share on other sites
Advertisement
References must be initialized when defined, however this doesn't work for non-static members, thus you must initialize the reference in the class initializer list.

Share this post


Link to post
Share on other sites

References must be initialized when defined, however this doesn't work for non-static members, thus you must initialize the reference in the class initializer list.


Let's say I have :
Terrain::Terrain(****, Camera & cam) //terrain.cpp
and I call it this way:
g_Terrain = new Terrain(****, &g_Camera); //main.cpp

Changing it to:
Terrain::Terrain(****, Camera & cam):m_Camera(cam) // terrain.cpp
does not help, where m_Camera is declared like this
Camera & m_Camera; // terrain.h

Share this post


Link to post
Share on other sites
Well, seeing as how you havent really posted much code, I can't tell you what's wrong. Although the error messages do suggest that it doesn't know what a "Camera" is, perhaps you're missing a header include.

Share this post


Link to post
Share on other sites
// main.cpp
#include "Camera.h"
#include "Terrain.h"
//declarations
Camera g_Camera;
Terrain* g_Terrain;
// before the game loop in the main function...
g_Camera = Camera(tbVector3(0.0f,30.0f,0.0f));
g_Terrain = new Terrain(/*uninteresting stuff*/ g_Camera);


// camera.h
// contains uninteresting stuff..


// terrain.h
#ifndef TERRAIN_H
#define TERRAIN_H
#include "Heightmap.h"
#include "d3dUtil.h"
#include "Vertex.h"
class Camera;
class Terrain
{
public:
Terrain(/*uninteresting*/ Camera & cam);
~Terrain();
private:
Camera & g_Camera;
};
#endif // TERRAIN_H


//terrain.cpp
#include "Terrain.h"
#include "d3dUtil.h"
#include <list>
Terrain::Terrain(*/uninteresting*/ Camera & cam)
{
g_Camera = cam;
}

Share this post


Link to post
Share on other sites
You didn't include camera in your terain.cpp. The definition of the incomplete type of Camera is required by then.

Share this post


Link to post
Share on other sites

You didn't include camera in your terain.cpp. The definition of the incomplete type of Camera is required by then.

I don't need to include the camera because of the forward declaration: terrain is not a parent of camera and it does not contain a camera object, but a reference.
Nevertheless, I switched to '#include "Camera.h"' and I get the exact same error.

Share this post


Link to post
Share on other sites
You need the definition of the camera class at the time of construction because incomplete types (which is what a forward decleration is) cannot be constructed.

Regardless of that, this line:

g_Camera = cam;


Is incorrect.

Share this post


Link to post
Share on other sites

1>c:\***\thegame\terrain.cpp(13): error C2758: 'Terrain::mCamera' : must be initialized in constructor base/member initializer list
1> c:\***\thegame\terrain.h(72) : see declaration of 'Terrain::mCamera'

This tells you that you need to initialize the reference in the initializer list of the constructor.

1>c:\***\thegame\terrain.cpp(128): error C2327: 'Terrain::mCamera' : is not a type name, static, or enumerator
1>c:\***\thegame\terrain.cpp(128): error C2065: 'mCamera' : undeclared identifier
1>c:\***\thegame\terrain.cpp(128): error C2228: left of '.getPos' must have class/struct/union
1> type is ''unknown-type''

Without seeing the code here, I can't tell you exactly what's going on here, however it basically is just telling you that it has no idea what mCamera is, its not encountered it within the current name scope. The code you pasted is, pretty much, useless.

Share this post


Link to post
Share on other sites
Well I took out everything that is not part of the problem. Here's the complete source code of terrain:

#ifndef TERRAIN_H
#define TERRAIN_H
#include "Heightmap.h"
#include "d3dUtil.h"
#include "Vertex.h"
#include "Camera.h"
class Terrain
{
public:
Terrain(UINT vertRows, UINT vertCols, float dx, float dz,
char * heightmap, char * tex0, char *tex1,
char * tex2, char * blendMap, float heightScale,
float yOffset, Camera & cam);
~Terrain();
DWORD getNumTriangles();
DWORD getNumVertices();
float getWidth();
float getDepth();
void onLostDevice();
void onResetDevice();
// (x, z) relative to terrain's local space.
float getHeight(float x, float z);

void setDirToSunW(const D3DXVECTOR3& d);
void draw(D3DXMATRIX& view, D3DXMATRIX& proj);
private:
void buildGeometry();
void buildSubGridMesh(RECT& R, VertexPNT* gridVerts);
void buildEffect();

Camera & mCamera;
struct SubGrid
{
ID3DXMesh* mesh;
AABB box;
// For sorting.
bool operator<(const SubGrid& rhs)const;
const static int NUM_ROWS = 33;
const static int NUM_COLS = 33;
const static int NUM_TRIS = (NUM_ROWS-1)*(NUM_COLS-1)*2;
const static int NUM_VERTS = NUM_ROWS*NUM_COLS;
};
private:
Heightmap mHeightmap;
std::vector<SubGrid> mSubGrids;
DWORD mVertRows;
DWORD mVertCols;
float mWidth;
float mDepth;
float mDX;
float mDZ;
IDirect3DTexture9* mTex0;
IDirect3DTexture9* mTex1;
IDirect3DTexture9* mTex2;
IDirect3DTexture9* mBlendMap;
ID3DXEffect* mFX;
D3DXHANDLE mhTech;
D3DXHANDLE mhViewProj;
D3DXHANDLE mhDirToSunW;
D3DXHANDLE mhTex0;
D3DXHANDLE mhTex1;
D3DXHANDLE mhTex2;
D3DXHANDLE mhBlendMap;
};
#endif // TERRAIN_H


I marked the errors down below.

#include "Terrain.h"
#include <list>
Terrain::Terrain(UINT vertRows, UINT vertCols, float dx, float dz,
char * heightmap, char *tex0, char *tex1,
char * tex2, char *blendMap, float heightScale,
float yOffset, Camera & cam):mCamera(cam) // <--- Like this?
{
mVertRows = vertRows;
mVertCols = vertCols;
mDX = dx;
mDZ = dz;
mWidth = (mVertCols-1)*mDX;
mDepth = (mVertRows-1)*mDZ;
mHeightmap.loadRAW(vertRows, vertCols, heightmap, heightScale, yOffset);
tbTextureManager& tm = tbTextureManager::Instance();
mBlendMap = tm.GetTexture(blendMap);
mTex0 = tm.GetTexture(tex0);
mTex1 = tm.GetTexture(tex1);
mTex2 = tm.GetTexture(tex2);
buildGeometry();
buildEffect();
}
Terrain::~Terrain()
{
for(UINT i = 0; i < mSubGrids.size(); ++i)
ReleaseCOM(mSubGrids.mesh);
ReleaseCOM(mFX);
ReleaseCOM(mTex0);
ReleaseCOM(mTex1);
ReleaseCOM(mTex2);
ReleaseCOM(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()
{
HR(mFX->OnLostDevice());
}
void Terrain::onResetDevice()
{
HR(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;
// Get the row and column we are in.
int row = (int)floorf(d);
int col = (int)floorf(c);
// Grab the heights of the cell we are in.
// A*--*B
// | /|
// |/ |
// C*--*D
float A = mHeightmap(row, col);
float B = mHeightmap(row, col+1);
float C = mHeightmap(row+1, col);
float D = mHeightmap(row+1, col+1);
// Where we are relative to the cell.
float s = c - (float)col;
float t = d - (float)row;
// If upper triangle ABC.
if(t < 1.0f - s)
{
float uy = B - A;
float vy = C - A;
return A + s*uy + t*vy;
}
else // lower triangle DCB.
{
float uy = C - D;
float vy = B - D;
return D + (1.0f-s)*uy + (1.0f-t)*vy;
}
}
void Terrain::setDirToSunW(const D3DXVECTOR3& d)
{
HR(mFX->SetValue(mhDirToSunW, &d, sizeof(D3DXVECTOR3)));
}

bool Terrain::SubGrid::operator<(const SubGrid& rhs) const
{
D3DXVECTOR3 d1 = box.center() - mCamera->getPos().vD3DVector; // ERROR
D3DXVECTOR3 d2 = rhs.box.center() - mCamera->getPos().vD3DVector; // ERROR
return D3DXVec3LengthSq(&d1) < D3DXVec3LengthSq(&d2);
}
void Terrain::draw(D3DXMATRIX& view, D3DXMATRIX& proj)
{
// Frustum cull sub-grids.
std::list<SubGrid> visibleSubGrids;
for(UINT i = 0; i < mSubGrids.size(); ++i)
{
if( mCamera->isVisible(mSubGrids.box) ) // ERROR
visibleSubGrids.push_back(mSubGrids);
}
// Sort front-to-back from camera.
visibleSubGrids.sort();
HR(mFX->SetMatrix(mhViewProj, &(view*proj)));
HR(mFX->SetTechnique(mhTech));
UINT numPasses = 0;
HR(mFX->Begin(&numPasses, 0));
HR(mFX->BeginPass(0));
for(std::list<SubGrid>::iterator iter = visibleSubGrids.begin(); iter != visibleSubGrids.end(); ++iter)
HR(iter->mesh->DrawSubset(0));
HR(mFX->EndPass());
HR(mFX->End());
}
void Terrain::buildGeometry()
{
//===============================================================
// Create one large mesh for the grid in system memory.
DWORD numTris = (mVertRows-1)*(mVertCols-1)*2;
DWORD numVerts = mVertRows*mVertCols;
ID3DXMesh* mesh = 0;
D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
UINT numElems = 0;
HR(VertexPNT::Decl->GetDeclaration(elems, &numElems));
// Use Scratch pool since we are using this mesh purely for some CPU work,
// which will be used to create the sub-grids that the graphics card
// will actually draw.
HR(D3DXCreateMesh(numTris, numVerts,
D3DPOOL_SCRATCH|D3DXMESH_32BIT, elems, tbDirect3D::Instance().GetDevice(), &mesh));

//===============================================================
// Write the grid vertices and triangles to the mesh.
VertexPNT* v = 0;
HR(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)
{
// We store the grid vertices in a linear array, but we can
// convert the linear array index to an (r, c) matrix index.
int r = i / mVertCols;
int c = i % mVertCols;
v.pos = verts;
v.pos.y = mHeightmap(r, c);
v.tex0.x = (v.pos.x + (0.5f*w)) / w;
v.tex0.y = (v.pos.z - (0.5f*d)) / -d;
}
// Write triangle data so we can compute normals.
DWORD* indexBuffPtr = 0;
HR(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];
}
HR(mesh->UnlockIndexBuffer());
// Compute Vertex Normals.
HR(D3DXComputeNormals(mesh, 0));

//===============================================================
// Now break the grid up into subgrid meshes.
// Find out the number of subgrids we'll have. For example, if
// m = 513, n = 257, SUBGRID_VERT_ROWS = SUBGRID_VERT_COLS = 33,
// then subGridRows = 512/32 = 16 and sibGridCols = 256/32 = 8.
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);
}
}
HR(mesh->UnlockVertexBuffer());
ReleaseCOM(mesh); // Done with global mesh.
}
void Terrain::buildSubGridMesh(RECT& R, VertexPNT* gridVerts)
{
//===============================================================
// Get indices for subgrid (we don't use the verts here--the verts
// are given by the parameter 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;
HR(VertexPNT::Decl->GetDeclaration(elems, &numElems));
HR(D3DXCreateMesh(SubGrid::NUM_TRIS, SubGrid::NUM_VERTS,
D3DXMESH_MANAGED, elems, tbDirect3D::Instance().GetDevice(), &subMesh));

//===============================================================
// Build Vertex Buffer. Copy rectangle of vertices from the
// grid into the subgrid structure.
VertexPNT* v = 0;
HR(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];
}
}
//===============================================================
// Compute the bounding box before unlocking the vertex buffer.
AABB bndBox;
HR(D3DXComputeBoundingBox((D3DXVECTOR3*)v, subMesh->GetNumVertices(),
sizeof(VertexPNT), &bndBox.minPt, &bndBox.maxPt));
HR(subMesh->UnlockVertexBuffer());

//===============================================================
// Build Index and Attribute Buffer.
WORD* indices = 0;
DWORD* attBuff = 0;
HR(subMesh->LockIndexBuffer(0, (void**)&indices));
HR(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 = 0; // All in subset 0.
}
HR(subMesh->UnlockIndexBuffer());
HR(subMesh->UnlockAttributeBuffer());

//===============================================================
// Optimize for the vertex cache and build attribute table.
DWORD* adj = new DWORD[subMesh->GetNumFaces()*3];
HR(subMesh->GenerateAdjacency(EPSILON, adj));
HR(subMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE|D3DXMESHOPT_ATTRSORT,
adj, 0, 0, 0));
delete[] adj;

//===============================================================
// Save the mesh and bounding box.
SubGrid g;
g.mesh = subMesh;
g.box = bndBox;
mSubGrids.push_back(g);
}
void Terrain::buildEffect()
{
ID3DXBuffer* errors = 0;
HR(D3DXCreateEffectFromFile(tbDirect3D::Instance().GetDevice(), "Terrain.fx",
0, 0, D3DXSHADER_DEBUG, 0, &mFX, &errors));
if( errors )
MessageBox(0, (char*)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");
HR(mFX->SetTexture(mhTex0, mTex0));
HR(mFX->SetTexture(mhTex1, mTex1));
HR(mFX->SetTexture(mhTex2, mTex2));
HR(mFX->SetTexture(mhBlendMap, mBlendMap));
}


Main (beware of German commentary! InitTerrain plays a key role here.)

// ===================
// Hier werden die Direct3D-Klassen der TriBase-Engine angewandt.
#include <TriBase.h>
#include "Resource.h"
#include "Config.h"
#include "Vertex.h"
#include "Camera.h"
#include "GameObject.h"
#include "Terrain.h"
// ******************************************************************
// Globale Variablen
tbConfig g_Config; // Konfigurationsstruktur
PDIRECT3DCUBETEXTURE9 g_pEnvMap = NULL; // Umgebungstextur
tbEffect* g_pSkyBoxEffect = NULL; // Sky-Box-Effekt
tbVertexBuffer* g_pSkyBoxVB = NULL; // Sky-Box-Vertex-Buffer
tbIndexBuffer* g_pSkyBoxIB = NULL; // Sky-Box-Index-Buffer
tbFont* g_pFont1 = NULL; // Erste Schriftart
float g_fTime = 0.0f; // Globaler Zeitzähler
Camera g_Camera; /// Kamera
GameObject* g_Cube; /// Würfel
Terrain* g_Terrain; /// Landschaft
tbModel* g_pDuckModel; /// Platzhaltermodell
// ******************************************************************
// Die Move-Funktion
tbResult MoveProc(float fNumSecsPassed)
{
tbVector3 vCameraDir;
// Den Zeitzähler aktualisieren
g_fTime += fNumSecsPassed;
// Input
//---------------------------------------------------------------
g_Cube->UpdateInput(fNumSecsPassed);
g_Camera.moveCamera(g_Cube->Position, fNumSecsPassed);
// Physics
// --------------------------------------------------------------
//g_Terrain->setDirToSunW(D3DXVECTOR3(cos(fNumSecsPassed), sin(fNumSecsPassed) , 0.0f)); // looks nice
g_Cube->UpdatePhysics(g_Terrain, fNumSecsPassed);

return TB_OK;
}
// ******************************************************************
// Die Render-Funktion
tbResult RenderProc(float fNumSecsPassed)
{
tbMatrix mWorld;
int iNumPasses;

tbDirect3D& D3D = tbDirect3D::Instance();

//Z-Buffer clearen, Skybox überschreibt das Bild
D3D->Clear(0,NULL, D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0, 0,0), 1.0f, 0);
// Die Szene beginnen
D3D->BeginScene();
// ------------------------------------------------------------------
g_Camera.setUpCamera();
// ------------------------------------------------------------------

// Z-Buffer deaktivieren, Dithering aktivieren
D3D.SetRS(D3DRS_ZENABLE, FALSE);
D3D.SetRS(D3DRS_DITHERENABLE, TRUE);
// Die Umgebungstextur setzen
D3D.SetTexture(0, g_pEnvMap);
D3D.SetTSS(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
// Weltmatrix erstellen, die die Sky-Box zur Kamera hin schiebt
mWorld = tbMatrixTranslation(g_Camera.getPos());
D3D.SetTransform(D3DTS_WORLD, mWorld);
// Vertex- und Index-Buffer aktivieren und das Vertexformat setzen
D3D->SetStreamSource(0, g_pSkyBoxVB->GetVB(), 0, sizeof(SSkyBoxVertex));
D3D->SetIndices(g_pSkyBoxIB->GetIB());
D3D.SetFVF(SSkyBoxVertex::dwFVF);
// Zeichnen!
iNumPasses = g_pSkyBoxEffect->Begin();
for(int iPass = 0; iPass < iNumPasses; iPass++)
{
g_pSkyBoxEffect->Pass(iPass);
D3D->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
}
g_pSkyBoxEffect->End();
//-------------------------------------------------------------------
D3D.SetRS(D3DRS_ZENABLE, TRUE);
g_Terrain->draw((D3DXMATRIX&) g_Camera.getViewMatrix(), (D3DXMATRIX&) g_Camera.getProjMatrix() );
//-------------------------------------------------------------------
g_Cube->UpdateGraphics(g_fTime);
//-------------------------------------------------------------------
///ENTE
D3DLIGHT9 Light;
// Ein Richtungslicht erstellen mit der Richtung der Kamera
ZeroMemory(&Light, sizeof(D3DLIGHT9));
Light.Type = D3DLIGHT_DIRECTIONAL;
Light.Diffuse = tbColor(0.5f, 0.5f, 0.5f);
Light.Ambient = tbColor(0.5f, 0.5f, 0.5f);
Light.Specular = tbColor(0.5f, 0.5f, 0.5f);
Light.Direction = g_Camera.getTarget();
D3D->SetLight(0, &Light);
D3D->LightEnable(0, TRUE);
// Weltmatrix zurücksetzen
D3D.SetTransform(D3DTS_WORLD, tbMatrixIdentity());
D3D.SetRS(D3DRS_LIGHTING, TRUE);
g_pDuckModel->Render(-1, -1, TRUE, FALSE);
//-------------------------------------------------------------------
// Debug-Hilfen
char acText[256]; // Speichert die Nachricht
tbVector3 camPos = g_Camera.getPos();
g_pFont1->Begin();
sprintf(acText, "Camera: %.2f | %.2f | %.2f", camPos.x, camPos.y, camPos.z);
g_pFont1->DrawTextA(tbVector2(10.0f,10.0f), acText);
sprintf(acText, "Player: %.2f | %.2f | %.2f", g_Cube->Position.x, g_Cube->Position.y, g_Cube->Position.z);
g_pFont1->DrawTextA(tbVector2(10.0f,30.0f), acText);

switch(g_Camera.getMode())
{
case FREE_FLYING: {sprintf(acText, "Camera mode: Free flying"); break;}
case BIRDS_EYE_PLAYER: {sprintf(acText, "Camera mode: Bird's eye on player"); break;}
case FOLLOW_PLAYER: {sprintf(acText, "Camera mode: Follow player"); break;}
case FOLLOW_PLAYER_LEFT: {sprintf(acText, "Camera mode: Follow left of player"); break;}
case FOLLOW_PLAYER_RIGHT: {sprintf(acText, "Camera mode: Follow Right of player"); break;}
}
g_pFont1->DrawTextA(tbVector2(10.0f,50.0f), acText);
g_pFont1->End();
// ------------------------------------------------------------------
// Szene beenden
D3D->EndScene();
return TB_OK;
}
// ******************************************************************
// Initialisierung der Sky-Box
tbResult InitSkyBox()
{
SSkyBoxVertex aVertex[8];
// Vertex- und Index-Buffer erstellen. 8 Vertizes, 36 Indizes.
g_pSkyBoxVB = new tbVertexBuffer;
if(g_pSkyBoxVB->Init(8 * sizeof(SSkyBoxVertex), sizeof(SSkyBoxVertex), SSkyBoxVertex::dwFVF,
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DPOOL_DEFAULT))
{
// Fehler!
return TB_ERROR;
}
// Nun der Index-Buffer (16 Bits pro Index)
g_pSkyBoxIB = new tbIndexBuffer;
if(g_pSkyBoxIB->Init(36 * sizeof(WORD), sizeof(WORD), D3DFMT_INDEX16))
{
// Fehler!
return TB_ERROR;
}
// ------------------------------------------------------------------
// Die Vertizes erstellen
aVertex[0].vPosition = tbVector3(-1.0f, 1.0f, 1.0f);
aVertex[1].vPosition = tbVector3( 1.0f, 1.0f, 1.0f);
aVertex[2].vPosition = tbVector3( 1.0f, 1.0f, -1.0f);
aVertex[3].vPosition = tbVector3(-1.0f, 1.0f, -1.0f);
aVertex[4].vPosition = tbVector3(-1.0f, -1.0f, 1.0f);
aVertex[5].vPosition = tbVector3( 1.0f, -1.0f, 1.0f);
aVertex[6].vPosition = tbVector3( 1.0f, -1.0f, -1.0f);
aVertex[7].vPosition = tbVector3(-1.0f, -1.0f, -1.0f);
// Die Texturkoordinaten entsprechen den Vertexpositionen
for(int iVertex = 0; iVertex < 8; iVertex++)
{
// Texturkoordinate eintragen
aVertex[iVertex].vTexture = aVertex[iVertex].vPosition;
}
// Alle Vertizes eintragen und den Vertex-Buffer aktualisieren
g_pSkyBoxVB->AddVertices(8, aVertex);
if(g_pSkyBoxVB->Update()) return TB_ERROR;
// ------------------------------------------------------------------
// Den Index-Buffer ausfüllen
WORD awIndex[36] = {7, 3, 0, 4, 7, 0, // Vorderseite
5, 1, 2, 6, 5, 2, // Hinterseite
4, 0, 1, 5, 4, 1, // Linke Seite
6, 2, 3, 7, 6, 3, // Rechte Seite
2, 1, 0, 3, 2, 0, // Oberseite
4, 5, 6, 7, 4, 6}; // Unterseite
g_pSkyBoxIB->AddIndices(36, awIndex);
if(g_pSkyBoxIB->Update()) return TB_ERROR;
// ------------------------------------------------------------------
// Die Textur der Sky-Box laden
g_pEnvMap = tbTextureManager::Instance().GetCubeTexture("_GRAPHICS/EnvMap.dds");
if(g_pEnvMap == NULL) return TB_ERROR;
// Effekt laden
g_pSkyBoxEffect = new tbEffect;
if(g_pSkyBoxEffect == NULL) return TB_ERROR;
if(g_pSkyBoxEffect->Init("_GRAPHICS/SkyBox.fx")) return TB_ERROR;
return TB_OK;
}
// ******************************************************************
// Initialisierung der Schriftarten
tbResult InitFonts()
{
// Erste Schriftart...
g_pFont1 = new tbFont;
if(g_pFont1->Init("_GRAPHICS/Futura_8_22.tga", "_GRAPHICS/Futura_8_22.tbf"))
{
// Fehler...
return TB_ERROR;
}
return TB_OK;
}
// ******************************************************************
// Initialisierung des Terrains
tbResult InitTerrain()
{
InitVertexDeclaration();
g_Terrain = new Terrain(257, 257, 0.5f, 0.5f,
"heightmap17_257.raw",
"_GRAPHICS/grass.dds",
"_GRAPHICS/dirt.dds",
"_GRAPHICS/stone.dds",
"_GRAPHICS/blend_hm17.dds",
0.2f, 0.0f, g_Camera);
g_Terrain->setDirToSunW(D3DXVECTOR3(0.0f, 1.0f, 0.0f));

if (g_Terrain == NULL)
return TB_ERROR;
else
return TB_OK;
}
// ******************************************************************
// Aufräumen
tbResult CleanUp()
{
///
tbDirect3D& D3D = tbDirect3D::Instance();

// Textur deaktivieren und löschen
D3D->SetTexture(0, NULL);
// Vertex- und Index-Buffer deaktivieren und löschen
D3D->SetStreamSource(0, NULL, 0, 0);
D3D->SetIndices(NULL);

// Terrain benutzt Declaration anstatt FVF
DestroyVertexDeclaration();
g_Terrain->~Terrain();
// Alles löschen
tbDirect3D::Instance().Exit();
tbTextureManager::Instance().Exit();
tbDirectInput::Instance().Exit();
TB_SAFE_DELETE(g_pDuckModel);
TB_SAFE_DELETE(g_pSkyBoxEffect);
TB_SAFE_DELETE(g_pSkyBoxVB);
TB_SAFE_DELETE(g_pSkyBoxIB);
TB_SAFE_DELETE(g_pFont1);
delete g_Cube;
// Die TriBase-Engine herunterfahren
tbExit();
return TB_OK;
}
// ******************************************************************
// Windows-Hauptfunktion
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
char* pcCommandLine,
int iShowCommand)
{
// TriBase-Engine initialisieren
tbInit();
tbResult r;
// Konfiguration abfragen
if (tbFileExists("Config.txt"))
{
if (r = loadConfig(&g_Config, "Config.txt"))
{
// Fehler!
MessageBox(NULL, "Fehler beim Laden der Konfiguration!", "Fehler",
MB_OK | MB_ICONEXCLAMATION);
return 1;
}
}
else
{
if(r = tbDoConfigDialog(&g_Config)) // Hier wird der Dialog gestartet.
{
if(r == TB_CANCELED) return 0;
else
{
// Fehler!
MessageBox(NULL, "Fehler im Konfigurationsdialog!", "Fehler",
MB_OK | MB_ICONEXCLAMATION);
return 1;
}
}
if (r = saveConfig(&g_Config, "Config.txt")) // ausgewählte Config wird automatisch gespeichert.
{
// Fehler!
MessageBox(NULL, "Fehler beim Speichern der Konfiguration!", "Fehler",
MB_OK | MB_ICONEXCLAMATION);
return 1;
}
}

// Direct3D initialisieren
if(tbDirect3D::Instance().Init(&g_Config, // Hier wird die Konfiguration weitergegeben.
"Game. Work in progress.",
NULL,
LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1))))
{
// Fehler!
MessageBox(NULL, "Fehler bei der Direct3D-Initialisierung!", "Fehler",
MB_OK | MB_ICONEXCLAMATION);
CleanUp();
return 1;
}
// Den Texturmanager initialisieren
if(tbDirectInput::Instance().Init())
{
MessageBox(tbDirect3D::Instance().GetWindow(), "Fehler beim Initialisieren von tbDirectInput!",
"Fehler", MB_OK | MB_ICONEXCLAMATION);
CleanUp();
return 1;
}
// Den Texturmanager initialisieren
if(tbTextureManager::Instance().Init())
{
MessageBox(tbDirect3D::Instance().GetWindow(), "Fehler beim Initialisieren des Texturmanagers!",
"Fehler", MB_OK | MB_ICONEXCLAMATION);
CleanUp();
return 1;
}
// Die Sky-Box initialisieren
if(InitSkyBox())
{
MessageBox(tbDirect3D::Instance().GetWindow(), "Fehler beim Initialisieren der Sky-Box!",
"Fehler", MB_OK | MB_ICONEXCLAMATION);
CleanUp();
return 1;
}

// Die Schriftarten initialisieren
if (InitFonts())
{
MessageBox(tbDirect3D::Instance().GetWindow(), "Fehler beim Initialisieren der Schriftarten!",
"Fehler", MB_OK | MB_ICONEXCLAMATION);
CleanUp();
return 1;
}

g_Camera = Camera(tbVector3(0.0f,30.0f,0.0f));
// Das Terrain initialisieren
if (InitTerrain())
{
MessageBox(tbDirect3D::Instance().GetWindow(), "Fehler beim Initialisieren des Terrains!",
"Fehler", MB_OK | MB_ICONEXCLAMATION);
CleanUp();
return 1;
}

// Das Stadtmodell laden
g_pDuckModel = new tbModel;
if(g_pDuckModel->Init("_GRAPHICS/Ente.tbm"))
{
MessageBox(tbDirect3D::Instance().GetWindow(), "Fehler beim Laden der Entenmodelldatei!",
"Fehler", MB_OK | MB_ICONEXCLAMATION);
CleanUp();
return 1;
}

/// GameObjects initialisieren
g_Cube = createCube(tbVector3(10.0f, 24.0f,0.0f));
if(tbDoMessageLoop(MoveProc, RenderProc))
{
MessageBox(tbDirect3D::Instance().GetWindow(), "Fehler beim Zeichnen!",
"Fehler", MB_OK | MB_ICONEXCLAMATION);
CleanUp();
return 1;
}
// Aufräumen
CleanUp();
return 0;
}


#ifndef CAMERA_H
#define CAMERA_H
#include "TriBase.h"
#include "d3dUtil.h"
enum CameraMode {FREE_FLYING, FOLLOW_PLAYER, FOLLOW_PLAYER_LEFT, FOLLOW_PLAYER_RIGHT, BIRDS_EYE_PLAYER};
class Camera
{
private:
tbVector3 m_vCameraPos; // Kameraposition
float m_fCameraRot; // Rotation der Kamera
float m_fCameraUpDown; // Schaut die Kamera hoch oder runter?
tbVector3 m_vCameraDir; // Wohin schaut die Kamera?
int m_iCameraMode; // Modus der Kamera

tbMatrix mProjection; // Für die Projektions-Matrix
tbMatrix mView; // Für die View-Matrix

// Frustum Planes
D3DXPLANE mFrustumPlanes[6]; // [0] = near
// [1] = far
// [2] = left
// [3] = right
// [4] = top
// [5] = bottom
public:
Camera()
{
m_vCameraPos = (0.0f, 30.0f, 0.0f);
m_iCameraMode = FOLLOW_PLAYER;
m_fCameraUpDown = 0.0f;
m_fCameraRot = 0.0f;
m_vCameraDir = tbVector3(sinf(m_fCameraRot) * cosf(m_fCameraUpDown),
sinf(m_fCameraUpDown),
cosf(m_fCameraRot) * cosf(m_fCameraUpDown));
}
Camera(tbVector3 pos)
{
m_vCameraPos = pos;
m_iCameraMode = FOLLOW_PLAYER;
m_fCameraUpDown = 0.0f;
m_fCameraRot = 0.0f;
m_vCameraDir = tbVector3(sinf(m_fCameraRot) * cosf(m_fCameraUpDown),
sinf(m_fCameraUpDown),
cosf(m_fCameraRot) * cosf(m_fCameraUpDown));
}
tbVector3 getPos(){ return m_vCameraPos; }
tbVector3 getTarget() { return m_vCameraDir; }
int getMode(){ return m_iCameraMode; }
tbMatrix getProjMatrix() { return mProjection; }
tbMatrix getViewMatrix() { return mView; }
void moveCamera(tbVector3 vTarget, float fTime);
void setUpCamera();
void buildWorldFrustumPlanes();
// Box coordinates should be relative to world space.
bool isVisible(const AABB& box) const;
};
#endif CAMERA_H


#include "Camera.h"
void Camera::moveCamera(tbVector3 vTarget, float fTime)
{
switch (m_iCameraMode)
{
case FREE_FLYING:
{
// Tastatursteuerung...
m_vCameraDir = tbVector3(sinf(m_fCameraRot) * cosf(m_fCameraUpDown),
sinf(m_fCameraUpDown),
cosf(m_fCameraRot) * cosf(m_fCameraUpDown));

if(GetAsyncKeyState(VK_A)) m_fCameraRot -= 1.0f * fTime;
if(GetAsyncKeyState(VK_D)) m_fCameraRot += 1.0f * fTime;
if(GetAsyncKeyState(VK_UP)) m_fCameraUpDown -= 1.0f * fTime;
if(GetAsyncKeyState(VK_DOWN)) m_fCameraUpDown += 1.0f * fTime;
if(GetAsyncKeyState(VK_W)) m_vCameraPos += m_vCameraDir * 25.0f * fTime;
if(GetAsyncKeyState(VK_S)) m_vCameraPos -= m_vCameraDir * 25.0f * fTime;
break;
}
case BIRDS_EYE_PLAYER:
{
m_vCameraPos = vTarget + tbVector3(0.0f, 40.0f, 0.0f);
m_fCameraRot = 0.0f;
m_fCameraUpDown = -1.55f; // ~90° da PI / 2
break;
}
case FOLLOW_PLAYER:
{
m_vCameraPos = vTarget + tbVector3(0.0f, 20.0f, -20.0f);
m_fCameraRot = 0.0f;
m_fCameraUpDown = -0.78f; // ~45° da PI / 4
break;
}
case FOLLOW_PLAYER_LEFT:
{
m_vCameraPos = vTarget + tbVector3(20.0f, 20.0f, 0.0f);
m_fCameraRot = -1.55f;
m_fCameraUpDown = -0.78f; // ~45° da PI / 4
break;
}
case FOLLOW_PLAYER_RIGHT:
{
m_vCameraPos = vTarget + tbVector3(-20.0f, 20.0f, 0.0f);
m_fCameraRot = 1.55f;
m_fCameraUpDown = -0.78f; // ~45° da PI / 4
break;
}
}

// Kamera-Modus via NumPad
if(GetAsyncKeyState(VK_NUMPAD2)) m_iCameraMode = FOLLOW_PLAYER;
if(GetAsyncKeyState(VK_NUMPAD4)) m_iCameraMode = FOLLOW_PLAYER_LEFT;
if(GetAsyncKeyState(VK_NUMPAD6)) m_iCameraMode = FOLLOW_PLAYER_RIGHT;
if(GetAsyncKeyState(VK_NUMPAD5)) m_iCameraMode = FREE_FLYING;
if(GetAsyncKeyState(VK_NUMPAD8)) m_iCameraMode = BIRDS_EYE_PLAYER;
}
void Camera::setUpCamera()
{
tbDirect3D& D3D = tbDirect3D::Instance();

// Projektionsmatrix erstellen und einsetzen
mProjection = tbMatrixProjection(TB_DEG_TO_RAD(90.0f), D3D.GetAspect(), 0.1f, 100.0f);
D3D.SetTransform(D3DTS_PROJECTION, mProjection);

//switch (m_iCameraMode)
//{
// case FREE_FLYING:
// {
// Kameramatrix erstellen und einsetzen
m_vCameraDir = tbVector3(sinf(m_fCameraRot) * cosf(m_fCameraUpDown),
sinf(m_fCameraUpDown),
cosf(m_fCameraRot) * cosf(m_fCameraUpDown));
// break;
// }
//}
mView = tbMatrixCamera(m_vCameraPos, m_vCameraPos + m_vCameraDir);
buildWorldFrustumPlanes();
D3D.SetTransform(D3DTS_VIEW, mView);
}
void Camera::buildWorldFrustumPlanes()
{
// Note: Extract the frustum planes in world space.
tbMatrix VP = mView * mProjection;
D3DXVECTOR4 col0(VP(0,0), VP(1,0), VP(2,0), VP(3,0));
D3DXVECTOR4 col1(VP(0,1), VP(1,1), VP(2,1), VP(3,1));
D3DXVECTOR4 col2(VP(0,2), VP(1,2), VP(2,2), VP(3,2));
D3DXVECTOR4 col3(VP(0,3), VP(1,3), VP(2,3), VP(3,3));
// Planes face inward.
mFrustumPlanes[0] = (D3DXPLANE)(col2); // near
mFrustumPlanes[1] = (D3DXPLANE)(col3 - col2); // far
mFrustumPlanes[2] = (D3DXPLANE)(col3 + col0); // left
mFrustumPlanes[3] = (D3DXPLANE)(col3 - col0); // right
mFrustumPlanes[4] = (D3DXPLANE)(col3 - col1); // top
mFrustumPlanes[5] = (D3DXPLANE)(col3 + col1); // bottom
for(int i = 0; i < 6; i++)
D3DXPlaneNormalize(&mFrustumPlanes, &mFrustumPlanes);
}
bool Camera::isVisible(const AABB& box)const
{
// Test assumes frustum planes face inward.
D3DXVECTOR3 P;
D3DXVECTOR3 Q;
// N *Q *P
// | / /
// |/ /
// -----/----- Plane -----/----- Plane
// / / |
// / / |
// *P *Q N
//
// PQ forms diagonal most closely aligned with plane normal.
// For each frustum plane, find the box diagonal (there are four main
// diagonals that intersect the box center point) that points in the
// same direction as the normal along each axis (i.e., the diagonal
// that is most aligned with the plane normal). Then test if the box
// is in front of the plane or not.
for(int i = 0; i < 6; ++i)
{
// For each coordinate axis x, y, z...
for(int j = 0; j < 3; ++j)
{
// Make PQ point in the same direction as the plane normal on this axis.
if( mFrustumPlanes[j] >= 0.0f )
{
P[j] = box.minPt[j];
Q[j] = box.maxPt[j];
}
else
{
P[j] = box.maxPt[j];
Q[j] = box.minPt[j];
}
}
// If box is in negative half space, it is behind the plane, and thus, completely
// outside the frustum. Note that because PQ points roughly in the direction of the
// plane normal, we can deduce that if Q is outside then P is also outside--thus we
// only need to test Q.
if( D3DXPlaneDotCoord(&mFrustumPlanes, &Q) < 0.0f ) // outside
return false;
}
return true;
}


Code is originally (partly) from Frank D. Luna and David Scherfing.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!