Frustum Culling – First Clash in OpenGL

Lately I have started preparing tools for voxel engine, after yesterdays fails with bloom/hdr today I won the battle with Frustum Culling – well it was only battle and there is still lot to improve.
Above we can see snowman’s – my tech model – used in OpenGL API learning process.

Anyway – for some weird reason I have decided that drown “testing models” will be in red. and the colling ones green – don’t ask. Fairly quickly I figured out that culling is updating only when camera is in the move. when rotates frustum is not being updated.. Need to investigate that.
Not tonight..

Zombeesh back in 2D

After lately chat with my tutor I have to move back to 2D based game. – time pressure and general overloading forced me to make this decision.
GDD must be finished by tomorrow – but shall not fear! I have some resources. I will borrow units tile set from star craft – come on zombies looks almost like infected marine

as well as terrain tiles – provided by Maniak – thanks man!

I am improving level manager so I will be able to deal with offsets and a stuff.. as far as now I have prototype and hopefully it will be ready in next couple hours.

LevelManager.h
[cc lang=”cpp”]

#pragma once

#ifndef LEVELMANAGER_H
#define LEVELMANAGER_H

#include

#include
#include “Level.h”

class LevelManager
{
private:
//list of maps
static std::map levels;
static int currentLevelId;

public:

static LevelManager* instance;
static void init();
static void loadLevel(Level* level); // load level
static void unloadLevel(Level* level);
static void registerLevel(Level* level); //add level to levels pool
static Level* getLevel(int id) ;
static D3DXVECTOR3 getOffset(); //gets offset off current map;

LevelManager();
~LevelManager();
};

#endif

[/cc]

LevelManager.cpp
[cc lang=”cpp”]
#include “LevelManager.h”

int LevelManager::currentLevelId=-1; //no level
LevelManager* LevelManager::instance =0;
std::map LevelManager::levels = std::map();

LevelManager::LevelManager()
{
}

void LevelManager::init()
{
LevelManager::instance = new LevelManager();
}

LevelManager::~LevelManager()
{
if(!levels.empty())
{
std::map::iterator iter = levels.begin();
for(; iter != levels.end(); ++iter)
{
delete iter->second;
iter->second = 0;
}
levels.clear();
}
}

void LevelManager::loadLevel(Level* level)
{
registerLevel(level);
LevelManager::currentLevelId = levels.size();
}

void LevelManager::unloadLevel(Level* level)
{
std::map::iterator iter = levels.find(level->getId());
if(iter != levels.end())
levels.erase(iter);
}

void LevelManager::registerLevel(Level* level)
{
//get size of current levels list and increment by one
int size = levels.size() + 1;
levels[size]= level;
level->setId(size);
}

//ok do I need to register all entitys into level? – I guess I do. need to double check that with Kevin
Level* LevelManager::getLevel(int id)
{
std::map::iterator iter = levels.find(id);
if(iter != levels.end())
{
return iter->second;
}
return 0;
}
D3DXVECTOR3 LevelManager::getOffset(){

std::map::iterator iter = levels.find(currentLevelId);
if(iter != levels.end())
return iter->second->getOffset();
return D3DXVECTOR3(0,0,0);

}

[/cc]

I see meshes everywhere!

Huzza!! I did it!

I have learned how to create a mesh from .x file format! – now I only need to apply picking and I am good to go!

Mesh.h
[cc lang=”cpp”]

#pragma once
#ifndef MESH_H
#define MESH_H

#include
#include

class Mesh
{
friend class MeshInstance;
public:
Mesh();
~Mesh();
Mesh(LPCSTR fName, IDirect3DDevice9* dev);
HRESULT Load(LPCSTR fName, IDirect3DDevice9* Dev);
void Render();
void Release();

private:
IDirect3DDevice9* m_pDevice;
ID3DXMesh* m_pMesh;
std::vector m_textures;
std::vector m_materials;
D3DMATERIAL9 m_white;

};

class MeshInstance{
public:
MeshInstance();
MeshInstance(Mesh* meshPtr);
void Render();

void SetMesh(Mesh* m) { m_pMesh = m;}
void SetPosition(D3DXVECTOR3 p) { m_pos = p; }
void SetRotation(D3DXVECTOR3 r) { m_rot = r; }
void SetScale(D3DXVECTOR3 s) { m_sca = s; }

private:
Mesh* m_pMesh;
D3DXVECTOR3 m_pos, m_rot, m_sca;

};

#endif
[/cc]

Mesh.cpp
[cc lang=”cpp”]
#include “Mesh.h”

Mesh::Mesh()
{
m_pDevice = NULL;
m_pMesh = NULL;
}

Mesh::Mesh(LPCSTR fName, IDirect3DDevice9* dev)
{
m_pDevice = dev;
m_pMesh = NULL;
Load(fName, m_pDevice);
}

Mesh::~Mesh()
{
Release();
}

HRESULT Mesh::Load(LPCSTR fName, IDirect3DDevice9* dev)
{
m_pDevice = dev;

//Set m_white material
m_white.Ambient = m_white.Specular = m_white.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
m_white.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
m_white.Power = 1.0f;

Release();

//Load new m_pMesh
ID3DXBuffer * adjacencyBfr = NULL;
ID3DXBuffer * materialBfr = NULL;
DWORD noMaterials = NULL;

if(FAILED(D3DXLoadMeshFromX(fName, D3DXMESH_MANAGED, m_pDevice,
&adjacencyBfr, &materialBfr, NULL,
&noMaterials, &m_pMesh)))
return E_FAIL;

D3DXMATERIAL *mtrls = (D3DXMATERIAL*)materialBfr->GetBufferPointer();

for(int i=0;i< (int)noMaterials;i++) { //mtrls[i].MatD3D.Ambient = mt[i].MatD3D.Diffuse; m_materials.push_back(mtrls[i].MatD3D); if(mtrls[i].pTextureFilename != NULL) { char textureFileName[90]; strcpy(textureFileName, "meshes/"); strcat(textureFileName, mtrls[i].pTextureFilename); IDirect3DTexture9 * newTexture = NULL; D3DXCreateTextureFromFile(m_pDevice, textureFileName, &newTexture); m_textures.push_back(newTexture); } else m_textures.push_back(NULL); } m_pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,
(DWORD*)adjacencyBfr->GetBufferPointer(), NULL, NULL, NULL);

adjacencyBfr->Release();
materialBfr->Release();

return S_OK;
}

void Mesh::Render()
{
for(int i=0;i< (int)m_materials.size();i++) { if(m_textures[i] != NULL)m_pDevice->SetMaterial(&m_white);
else m_pDevice->SetMaterial(&m_materials[i]);
m_pDevice->SetTexture(0,m_textures[i]);
m_pMesh->DrawSubset(i);
}
}

void Mesh::Release()
{
//Clear old mesh…
if(m_pMesh != NULL)
{
m_pMesh->Release();
m_pMesh = NULL;
}

//Clear textures and materials
for(int i=0;i< (int)m_textures.size();i++) if(m_textures[i] != NULL) m_textures[i]->Release();

m_textures.clear();
}

MeshInstance::MeshInstance()
{
m_pMesh = NULL;
m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
}

MeshInstance::MeshInstance(Mesh* meshPtr)
{
m_pMesh = meshPtr;
m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
}

void MeshInstance::Render()
{
if(m_pMesh != NULL)
{
D3DXMATRIX p, r, s;
D3DXMatrixTranslation(&p, m_pos.x, m_pos.y, m_pos.z);
D3DXMatrixRotationYawPitchRoll(&r, m_rot.y, m_rot.x, m_rot.z);
D3DXMatrixScaling(&s, m_sca.x, m_sca.y, m_sca.z);

D3DXMATRIX world = s * r * p;
m_pMesh->m_pDevice->SetTransform(D3DTS_WORLD, &world);

m_pMesh->Render();
}
}
[/cc]

ObjectClass.h
[cc lang=”cpp”]
#ifndef OBJECTCLASS_H
#define OBJECTCLASS_H

#include
#include “debug.h”
#include “mesh.h”

HRESULT LoadObjectResources(IDirect3DDevice9* Device);
void UnloadObjectResources();

#define OBJ_TREE 0
#define OBJ_STONE 1

class ObjectClass{
public:
ObjectClass();
ObjectClass(int t, D3DXVECTOR3 pos, D3DXVECTOR3 rot, D3DXVECTOR3 sca);
void Render();

private:
MeshInstance m_meshInstance;
int m_type;
};

#endif
[/cc]

ObjectClass.cpp
[cc lang=”cpp”]
#include “ObjectClass.h”

std::vector objectMeshes;

HRESULT LoadObjectResources(IDirect3DDevice9* device)
{
Mesh* one = new Mesh(“meshes/one.x”, device);
objectMeshes.push_back(one);

Mesh* two= new Mesh(“meshes/two.x”, device);
objectMeshes.push_back(two);

return S_OK;
}

void UnloadObjectResources()
{
for(int i=0; i< (int)objectMeshes.size(); i++) objectMeshes[i]->Release();

objectMeshes.clear();
}

ObjectClass::ObjectClass()
{
m_type =0;
}

ObjectClass::ObjectClass(int t, D3DXVECTOR3 pos, D3DXVECTOR3 rot, D3DXVECTOR3 sca)
{
m_type = t;
m_meshInstance.SetPosition(pos);
m_meshInstance.SetRotation(rot);
m_meshInstance.SetScale(sca);
m_meshInstance.SetMesh(objectMeshes[m_type]);
}

void ObjectClass::Render()
{
m_meshInstance.Render();
}
[/cc]

usage is really simple:

in our main program class game/application/app you name it.

we need to add include
[cc lang=”cpp”]
#include “ObjectClass.h”
[/cc]

then in Init method for your program place

[cc lang=”cpp”]
LoadObjectResources(m_pDevice);
[/cc]

it is loading resources do our device.

to add object call
[cc lang=”cpp”]
AddObject(0, INTPOINT(x, y)); //objec one
else if(m_pHeightMap->GetHeight(x, y) >= 1.0f && hm3.GetHeight(x, y) > 0.9f && rand()%20 == 0)
AddObject(1, INTPOINT(x, y)); //object two
[/cc]

I am calling it in terrain class.

at the moment placed randomly

[cc lang=”cpp”]
void Terrain::AddObject(int type, INTPOINT mappos)
{
D3DXVECTOR3 pos = D3DXVECTOR3((float)mappos.x, m_pHeightMap->GetHeight(mappos), (float)-mappos.y);
D3DXVECTOR3 rot = D3DXVECTOR3((rand()%1000 / 1000.0f) * 0.13f, (rand()%1000 / 1000.0f) * 3.0f, (rand()%1000 / 1000.0f) * 0.13f);

float sca_xz = (rand()%1000 / 1000.0f) * 0.5f + 0.5f;
float sca_y = (rand()%1000 / 1000.0f) * 1.0f + 0.5f;
D3DXVECTOR3 sca = D3DXVECTOR3(sca_xz, sca_y, sca_xz);

m_objects.push_back(ObjectClass(type, pos, rot, sca));
}
[/cc]

Tomorrows plans.. picking!!
and come on! 374 FPS ain’t bad!

PlayerManager – prototype class

Just a quick note. I have managed to write Player Manager class which is kind a prototype.. the two issues that I am having are how to get an offset of a map.. if I am trying to set up offset to static DXDVECTOR3 variable inside Level class linker is complaining, passing as attribute well it is a option but then I need to modify other classes.

Second problem is click in a frame. actually I have just figured this out :).. wow sometimes one sec break and step back can do the trick.

Anyway deep beta presents PlayerManager prototype class – probably it will be totally modified but as far as now I have something like that:

PlayerManager.h
[cc lang=”cpp”]

#pragma once
#ifndef PLAYERMANAGER_H
#define PLAYERMANAGER_H

#include “Entity.h”
#include

#include “Level.h”
#include

class PlayerManager
{

private:
//players entities
static std::map playersEntities;
static std::map
playersSelectedEntities;

public:
static PlayerManager* instance;
static void init();
static void registerPlayersEntity(Entity* playersEntity); // called in players unity type constructor
static void removePlayersEntity(Entity* playersEntity);
static Entity* getPlayersEntity(int id);
static void clearSelected();
static void addEntityToSelected(POINT mousePosition);

PlayerManager();
~PlayerManager();
};

#endif
[/cc]
PlayerManager.cpp
[cc lang=”cpp”]
#include “PlayerManager.h”
#include “Collision.h”

PlayerManager* PlayerManager::instance =0;
std::map PlayerManager::playersEntities = std::map();
std::map
PlayerManager::playersSelectedEntities = std::map();

PlayerManager::PlayerManager()
{
}

void PlayerManager::init()
{
PlayerManager::instance = new PlayerManager();
}

PlayerManager::~PlayerManager()
{
{
//clear selected units list
std::map::iterator iter = playersSelectedEntities.begin();
for(; iter != playersSelectedEntities.end(); ++iter)
{
delete iter->second;
iter->second = 0;
}
playersSelectedEntities.clear();
}
{
playersEntities.clear();
}
}

//register entity in players list
void PlayerManager::registerPlayersEntity(Entity* entity)
{
//register entity called only once and after registration in entity manager
// we have entity ID and I am pretty sure it will not dublicate.
playersEntities[entity->getID()] = entity;
}

void PlayerManager::removePlayersEntity(Entity* entity)
{
//removes selecred entity from players entities lise
std::map::iterator iter = playersEntities.find(entity->getID());
if(iter != playersEntities.end())
playersEntities.erase(iter);
}

Entity* PlayerManager::getPlayersEntity(int id)
{
//returns pointer to entity defined by id
std::map::iterator iter = playersEntities.find(id);
if(iter != playersEntities.end())
return iter->second;
return 0;
}

void PlayerManager::addEntityToSelected(POINT mousePosition){

D3DXVECTOR3 position(0.0f,0.0f,0.0f);
float radius = 1.0f;

D3DXVECTOR3 mPosition(mousePosition.x, mousePosition.y, 0.0f);

Circle mouseCircle = {mPosition, radius };
Circle unitCircle = {position, radius };
//CollisionResults collisionResult;

mouseCircle.position.x = mousePosition.x; // need to figure out how to apply offset
mouseCircle.position.y = mousePosition.y;
mouseCircle.position.z = 0.0f;
mouseCircle.radius = 2.0f;

std::map::iterator iter = playersEntities.begin();
for(; iter != playersEntities.end(); ++iter)
{
unitCircle.position = iter->second->getPosition();
unitCircle.radius = 20.0f; // need to set this global instead of calculated based on number images etc like TILEBASEWIDTH or something
CollisionResults collisionResult = TestCollisionCircle(mouseCircle, unitCircle);
//iter->second->update(frameTime);
if(collisionResult == OVERLAPPING)
{
std::cout < < "AWESOME"; }else { PlayerManager::clearSelected(); std::cout << "NOT"; } } } void PlayerManager::clearSelected() { std::map::iterator iter = playersSelectedEntities.begin();
for(; iter != playersSelectedEntities.end(); ++iter)
{
if(iter->second)
{
delete iter->second;
iter->second = 0;
}
}
playersSelectedEntities.clear();

}
[/cc]

Zombeesh overview 1 – Collision detection circle based

After less than one week – weekend not counted in (I have had over 24hrs of sleep during weekend, I really hate to be sick) I have cought up with university material. Material covered:

  • Tile system for map loaded from a file
  • offset for moving map
  • entity manager for all objects on the map – plus improvement
  • messaging system – communication between instances of objects
  • collision detection – and my own improvement
  • moving around the map – mouse based
  • font manager

Plans for next week

  • Selecting objects by mouse click – hoping to select more than one element
  • collision detection applied for object on a map
  • placing building on the map
  • shooting to zombies and other stuff.

Meanwhile I will post some code – I haven’t done that for a while.

Collision detection class with improvements

Collision.h
[cc lang=”cpp”]
#pragma once
#ifndef COLLISION_H
#define COLLISION_H

#include

const float TOUCH_DISTANCE = 0.000000000001;

static enum CollisionResults {
NO_COLLISION, TOUCHING, OVERLAPPING
};

struct Circle
{
D3DXVECTOR3& position;
float radius;
};

struct BoundingBox
{
D3DXVECTOR3& position;
D3DXVECTOR3& size;
};

bool TestCollision(const BoundingBox& a, const BoundingBox& b);

CollisionResults TestCollisionCircle(const Circle& a, const Circle& b);

#endif
[/cc]

Pretty easy stuff here – two structs for BoundingBox and Circle enum for collision between circles – I have added it because I want to base selecting objects and – well all collision on two circles.

Collision.cpp
[cc lang=”cpp”]
#include “Collision.h”

bool TestCollision(const BoundingBox& a, const BoundingBox& b)
{
float t;
if((t = a.position.x – b.position.x) > b.size.x || -t > a.size.x)
return false;
if((t = a.position.y – b.position.y) > b.size.y || -t > a.size.y)
return false;
if((t = a.position.z – b.position.z) > b.size.z || -t > a.size.z)
return false;
return true;
}

CollisionResults TestCollisionCircle(const Circle& a, const Circle& b)
{
//for math
CollisionResults colliding;
float distance_squared;
float radii_squared;

//a*a + b*b = c*c
distance_squared =
((a.position.x – b.position.x)*
(a.position.x – b.position.x))+
((a.position.y – b.position.y)*
(a.position.y – b.position.y));

//Multiplication is faster than taking a square root
radii_squared =
(a.radius + b.radius) *
(a.radius + b.radius);

if( -TOUCH_DISTANCE < radii_squared – distance_squared &&
radii_squared – distance_squared < TOUCH_DISTANCE) colliding = TOUCHING; else if(radii_squared > distance_squared)
colliding = OVERLAPPING;
else
colliding = NO_COLLISION;

return colliding;
}

[/cc]

pretty simple stuff here as well – Pythagorean theorem based. if distance between two points is bigger than sum of radius of circles then there is no collision if it is equal there is a collision but if it is smaller they overlap – so we have covered all 3 states first two for collision detection on the map and third one for selecting. simple

I wanted to write bit more tonight but my lovely women wants me.. so sorry.. priority is clear.
nn.
L

Global Game Jam..

Over 30h without sleep.. and loads things to do..

tired.. no exhausted.. but excited.. we almost reached 2nd stage for a game development.. all relationships, behaviours are set up and ready to go.. now.. level modelling tweaking and balancing game play..
it is kind a hard to manage and catch up with 8people team.. really. but we are doing pretty well!

pictures and demo tomorrow!

Day 10: Height Map

I am satisfied with that height map – no multi textures, blending, water or even trees.. I need to concentrate on logic now, polishing details will be last thing.

plan for today/tomorrow.

picking + adding objects on the map..

good luck Luke..

thanks Luke.

edit:
ok 2 more thing left before I ll be ready to go with picking and objects,

1. need to set up camera in 45 degree
2. I need to think of optimisation.. some sort of quad tree or so..