* added basic terrain rendering code [STILL INCORRECT!]

* added url to show at startup
* added error message if out of memory
This commit is contained in:
False.Genesis 2007-11-25 02:23:38 +00:00
parent abff02ac19
commit bdbc8cc721
20 changed files with 2582 additions and 31 deletions

BIN
bin/data/misc/dirt_test.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

392
src/Client/GUI/MCamera.h Normal file
View File

@ -0,0 +1,392 @@
/*-----------------------------------------------------------------------------*
| headerfile MCamera.h |
| |
| version 1.20 |
| date: (29.04.2007) |
| |
| author: Michal Švantner |
| |
| for Irrlicht engine |
| firsth person and orbiting cameras |
*-----------------------------------------------------------------------------*/
#ifndef MCAMERA_H
#define MCAMERA_H
#include "irrlicht/irrlicht.h"
using namespace irr;
class MCameraFPS
{
scene::ICameraSceneNode* camera;
f32 rotationX;
f32 rotationY;
core::vector3df direction;
public:
MCameraFPS(scene::ISceneManager* smgr)
{
camera = smgr->addCameraSceneNode();
rotationX = 0.0f;
rotationY = 0.0f;
direction = core::vector3df(0,0,1);
}
~MCameraFPS(){}
void turnRight(f32 i)
{
rotationY += i;
if(rotationY>=360)rotationY-=360;
if(rotationY<0)rotationY+=360;
direction = core::vector3df(0,0,1);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (rotationX,rotationY,0));
matrix.rotateVect(direction);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void turnLeft(f32 i)
{
rotationY -= i;
if(rotationY>=360)rotationY-=360;
if(rotationY<0)rotationY+=360;
direction = core::vector3df(0,0,1);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (rotationX,rotationY,0));
matrix.rotateVect(direction);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void turnUp(f32 i)
{
rotationX += i;
if(rotationX>=360)rotationX-=360;
if(rotationX<0)rotationX+=360;
direction = core::vector3df(0,0,1);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (rotationX,rotationY,0));
matrix.rotateVect(direction);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void turnDown(f32 i)
{
rotationX -= i;
if(rotationX>=360)rotationX-=360;
if(rotationX<0)rotationX+=360;
direction = core::vector3df(0,0,1);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (rotationX,rotationY,0));
matrix.rotateVect(direction);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void moveForward(f32 i)
{
core::vector3df step = core::vector3df(0,0,i);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (0,rotationY,0));
matrix.rotateVect(step);
camera->setPosition(camera->getPosition() + step);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void moveBack(f32 i)
{
core::vector3df step = core::vector3df(0,0,-i);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (0,rotationY,0));
matrix.rotateVect(step);
camera->setPosition(camera->getPosition() + step);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void moveRight(f32 i)
{
core::vector3df step = core::vector3df(i,0,0);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (0,rotationY,0));
matrix.rotateVect(step);
camera->setPosition(camera->getPosition() + step);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void moveLeft(f32 i)
{
core::vector3df step = core::vector3df(-i,0,0);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (0,rotationY,0));
matrix.rotateVect(step);
camera->setPosition(camera->getPosition() + step);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void setHeight(f32 i)
{
camera->setPosition(core::vector3df(camera->getPosition().X, i, camera->getPosition().Z));
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void setPosition(core::vector3df pos)
{
camera->setPosition(pos);
camera->updateAbsolutePosition();
}
core::vector3df getPosition()
{
return camera->getPosition();
}
core::vector3df getDirection()
{
return direction;
}
core::vector3df getTarget()
{
return camera->getTarget();
}
f32 getHeading()
{
return rotationY;
}
f32 getPitch()
{
return rotationX;
}
f32 getFarValue()
{
return camera->getFarValue();
}
void setFarValue(f32 f)
{
camera->setFarValue(f);
}
f32 getNearValue()
{
return camera->getNearValue();
}
void setNearValue(f32 n)
{
camera->setNearValue(n);
}
f32 getFOV()
{
return camera->getFOV();
}
void setFOV(f32 v)
{
camera->setFOV(v);
}
f32 getAspectRatio()
{
return camera->getAspectRatio();
}
void setAspectRatio(f32 a)
{
camera->setAspectRatio(a);
}
scene::ISceneNode* getNode()
{
return camera;
}
};
class MCameraOrbit
{
scene::ICameraSceneNode* camera;
f32 rotationX;
f32 rotationY;
f32 distance;
void update()
{
core::vector3df direction = core::vector3df(0,0,distance);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (rotationX,rotationY,0));
matrix.rotateVect(direction);
camera->setPosition(camera->getTarget() + direction);
camera->updateAbsolutePosition();
}
public:
MCameraOrbit(scene::ISceneManager* smgr)
{
camera = smgr->addCameraSceneNode();
rotationX = 0.0f;
rotationY = 0.0f;
distance = 1.0f;
camera->setTarget(core::vector3df(0,0,0));
update();
}
~MCameraOrbit(){}
void turnRight(f32 i)
{
rotationY += i;
if(rotationY>=360)rotationY-=360;
if(rotationY<0)rotationY+=360;
update();
}
void turnLeft(f32 i)
{
rotationY -= i;
if(rotationY>=360)rotationY-=360;
if(rotationY<0)rotationY+=360;
update();
}
void turnUp(f32 i)
{
rotationX += i;
if(rotationX>=360)rotationX-=360;
if(rotationX<0)rotationX+=360;
update();
}
void turnDown(f32 i)
{
rotationX -= i;
if(rotationX>=360)rotationX-=360;
if(rotationX<0)rotationX+=360;
update();
}
core::vector3df getTarget()
{
return camera->getTarget();
}
void setTarget(core::vector3df target)
{
camera->setTarget(target);
update();
}
core::vector3df getPosition()
{
return camera->getPosition();
}
f32 getDistance()
{
return distance;
}
void setDistance(f32 i)
{
distance = i;
update();
}
void adjustDistance(f32 i)
{
distance += i;
update();
}
f32 getHeading()
{
return rotationY;
}
f32 getPitch()
{
return rotationX;
}
f32 getFarValue()
{
return camera->getFarValue();
}
void setFarValue(f32 f)
{
camera->setFarValue(f);
}
f32 getNearValue()
{
return camera->getNearValue();
}
void setNearValue(f32 n)
{
camera->setNearValue(n);
}
f32 getFOV()
{
return camera->getFOV();
}
void setFOV(f32 v)
{
camera->setFOV(v);
}
f32 getAspectRatio()
{
return camera->getAspectRatio();
}
void setAspectRatio(f32 a)
{
camera->setAspectRatio(a);
}
scene::ISceneNode* getNode()
{
return camera;
}
};
#endif

160
src/Client/GUI/MInput.h Normal file
View File

@ -0,0 +1,160 @@
/*-----------------------------------------------------------------------------*
| headerfile MInput.h |
| |
| version 1.10 |
| date: (29.04.2007) |
| |
| author: Michal Švantner |
| |
| for Irrlicht engine |
| store keyboard and mouse input in structures "key" and "mouse" |
*-----------------------------------------------------------------------------*/
#ifndef MINPUT_H
#define MINPUT_H
#include "irrlicht/irrlicht.h"
using namespace irr;
struct IKeys
{
bool pressed(EKEY_CODE keycode)
{
return code[keycode];
}
bool pressed_once(EKEY_CODE keycode)
{
if(code[keycode])
{
code[keycode] = false;
return true;
}
return false;
}
void reset()
{
for(s32 i=0; i<KEY_KEY_CODES_COUNT; i++) code[i] = false;
}
bool code[KEY_KEY_CODES_COUNT];
};
struct IMouse
{
bool left_pressed()
{
return left;
}
bool middle_pressed()
{
return middle;
}
bool right_pressed()
{
return right;
}
bool left_pressed_once()
{
if(left)
{
left = false;
return true;
}
return false;
}
bool middle_pressed_once()
{
if(middle)
{
middle = false;
return true;
}
return false;
}
bool right_pressed_once()
{
if(right)
{
right = false;
return true;
}
return false;
}
void reset()
{
X = 0;
Y = 0;
wheel = 0.0f;
left = false;
middle = false;
right = false;
}
s32 X;
s32 Y;
f32 wheel;
bool left;
bool middle;
bool right;
};
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver()
{
for(s32 i=0; i<KEY_KEY_CODES_COUNT; i++)
key.code[i] = false;
mouse.X = 0;
mouse.Y = 0;
mouse.wheel = 0.0f;
mouse.left = false;
mouse.middle = false;
mouse.right = false;
}
virtual bool OnEvent(SEvent event)
{
bool value = false;
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
{
key.code[event.KeyInput.Key] = event.KeyInput.PressedDown;
value = true;
}
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
{
switch(event.MouseInput.Event)
{
case EMIE_LMOUSE_PRESSED_DOWN: mouse.left = true; break;
case EMIE_RMOUSE_PRESSED_DOWN: mouse.right = true; break;
case EMIE_MMOUSE_PRESSED_DOWN: mouse.middle = true; break;
case EMIE_LMOUSE_LEFT_UP: mouse.left = false; break;
case EMIE_RMOUSE_LEFT_UP: mouse.right = false; break;
case EMIE_MMOUSE_LEFT_UP: mouse.middle = false; break;
case EMIE_MOUSE_MOVED: mouse.X = event.MouseInput.X; mouse.Y = event.MouseInput.Y; break;
case EMIE_MOUSE_WHEEL: mouse.wheel = mouse.wheel + event.MouseInput.Wheel; break;
}
value = true;
}
return value;
}
IMouse mouse;
IKeys key;
};
#endif

View File

@ -42,6 +42,7 @@ PseuGUI::PseuGUI()
_device = NULL; _device = NULL;
_guienv = NULL; _guienv = NULL;
_scene = NULL; _scene = NULL;
_passtime = _lastpasstime = _passtimediff = 0;
} }
PseuGUI::~PseuGUI() PseuGUI::~PseuGUI()
@ -113,6 +114,7 @@ void PseuGUI::_Init(void)
_driver = _device->getVideoDriver(); _driver = _device->getVideoDriver();
_smgr = _device->getSceneManager(); _smgr = _device->getSceneManager();
_guienv = _device->getGUIEnvironment(); _guienv = _device->getGUIEnvironment();
_timer = _device->getTimer();
//... //...
_initialized = true; _initialized = true;
} }
@ -123,6 +125,7 @@ void PseuGUI::Cancel(void)
if(_scene) if(_scene)
{ {
_scene->OnDelete();
delete _scene; delete _scene;
_scene = NULL; _scene = NULL;
} }
@ -158,6 +161,9 @@ void PseuGUI::Run(void)
while(_device && _device->run() && !_mustdie) while(_device && _device->run() && !_mustdie)
{ {
_lastpasstime = _passtime;
_passtime = _timer->getTime() / 1000.0f;
_passtimediff = _passtime - _lastpasstime;
// _HandleWindowResize(); // not yet used; doesnt work // _HandleWindowResize(); // not yet used; doesnt work
if (!_device->isWindowActive()) if (!_device->isWindowActive())
@ -167,9 +173,13 @@ void PseuGUI::Run(void)
try try
{ {
_UpdateSceneState();
if(_scene && _initialized)
_scene->OnUpdate(_passtimediff);
_driver->beginScene(true, true, 0); _driver->beginScene(true, true, 0);
_UpdateSceneState();
DrawCurrentScene(); DrawCurrentScene();
_smgr->drawAll(); _smgr->drawAll();
@ -229,9 +239,13 @@ void PseuGUI::_UpdateSceneState(void)
{ {
if(_scenestate != _scenestate_new && _smgr) if(_scenestate != _scenestate_new && _smgr)
{ {
_smgr->clear();
if(_scene) if(_scene)
{
_scene->OnDelete();
delete _scene; delete _scene;
}
_smgr->clear();
_guienv->clear();
_scenestate = _scenestate_new; _scenestate = _scenestate_new;
@ -250,10 +264,8 @@ void PseuGUI::_UpdateSceneState(void)
void PseuGUI::DrawCurrentScene(void) void PseuGUI::DrawCurrentScene(void)
{ {
if(!_initialized) if(_scene && _initialized)
return; _scene->OnDraw();
if(_scene)
_scene->Draw();
} }
void PseuGUI::_HandleWindowResize(void) void PseuGUI::_HandleWindowResize(void)

View File

@ -54,6 +54,7 @@ public:
~PseuGUI(); ~PseuGUI();
void SetInstance(PseuInstance*); void SetInstance(PseuInstance*);
inline PseuInstance *GetInstance(void) { return _instance; }
void Run(void); void Run(void);
void SetDriver(uint8); void SetDriver(uint8);
void SetResolution(uint16 x, uint16 y, uint16 depth=32); void SetResolution(uint16 x, uint16 y, uint16 depth=32);
@ -90,6 +91,8 @@ private:
PseuInstance *_instance; PseuInstance *_instance;
SceneState _scenestate, _scenestate_new; SceneState _scenestate, _scenestate_new;
Scene *_scene; Scene *_scene;
irr::ITimer *_timer;
float _passtime, _lastpasstime, _passtimediff;
irr::core::dimension2d<irr::s32> _screendimension; irr::core::dimension2d<irr::s32> _screendimension;
}; };

View File

@ -12,7 +12,20 @@ Scene::Scene(PseuGUI *g)
guienv = gui->_guienv; guienv = gui->_guienv;
} }
void Scene::Draw(void) void Scene::OnDraw(void)
{ {
device->yield(); device->yield();
} }
void Scene::OnDelete(void)
{
}
void Scene::OnUpdate(f32)
{
}
Scene::~Scene()
{
DEBUG(logdebug("Scene::~Scene()"));
}

View File

@ -18,8 +18,12 @@ class Scene
friend class PseuGUI; friend class PseuGUI;
public: public:
Scene(PseuGUI *g); Scene(PseuGUI *g);
virtual void Draw(void); ~Scene();
virtual void OnUpdate(f32);
virtual void OnDraw(void);
virtual void OnDelete(void);
protected: protected:
PseuGUI *gui; PseuGUI *gui;
irr::IrrlichtDevice *device; irr::IrrlichtDevice *device;
irr::video::IVideoDriver* driver; irr::video::IVideoDriver* driver;
@ -31,18 +35,28 @@ class SceneGuiStart : public Scene
{ {
public: public:
SceneGuiStart(PseuGUI *gui); SceneGuiStart(PseuGUI *gui);
~SceneGuiStart(); void OnDelete(void);
private: private:
IGUIImage *irrlogo, *driverlogo; IGUIImage *irrlogo, *driverlogo;
}; };
class ShTlTerrainSceneNode;
class MCameraFPS;
class MyEventReceiver;
class SceneWorld : public Scene class SceneWorld : public Scene
{ {
public: public:
SceneWorld(PseuGUI *gui); SceneWorld(PseuGUI *gui);
~SceneWorld(); void OnDraw(void);
void Draw(void); void OnDelete(void);
void OnUpdate(f32);
private:
ShTlTerrainSceneNode *terrain;
MCameraFPS *camera;
MyEventReceiver *eventrecv;
}; };

View File

@ -27,8 +27,7 @@ SceneGuiStart::SceneGuiStart(PseuGUI *gui) : Scene(gui)
} }
SceneGuiStart::~SceneGuiStart() void SceneGuiStart::OnDelete(void)
{ {
irrlogo->drop(); // not necessary to delete the images, because they are deleted by guienv->clear()
driverlogo->drop();
} }

View File

@ -2,22 +2,134 @@
#include "PseuGUI.h" #include "PseuGUI.h"
#include "PseuWoW.h" #include "PseuWoW.h"
#include "Scene.h" #include "Scene.h"
#include "MapTile.h"
#include "MapMgr.h"
#include "ShTlTerrainSceneNode.h"
#include "MCamera.h"
#include "MInput.h"
#include "WorldSession.h"
#include "World.h"
#include <sstream>
SceneWorld::SceneWorld(PseuGUI *g) : Scene(g) SceneWorld::SceneWorld(PseuGUI *g) : Scene(g)
{ {
DEBUG(logdebug("SceneWorld: Initializing..."));
s32 mapsize = 9 * 16; // 9 height floats in 16 chunks per tile per axis
s32 tilesize = UNITSIZE;
s32 meshsize = CHUNKSIZE;
vector3df terrainPos(0.0f, 0.0f, 0.0f); // TODO: use PseuWoW's world coords here?
eventrecv = new MyEventReceiver();
device->setEventReceiver(eventrecv);
camera = new MCameraFPS(smgr);
camera->setNearValue(0.1f);
camera->setFarValue(tilesize*meshsize/2);
camera->setPosition(core::vector3df(mapsize*tilesize/2, 0, mapsize*tilesize/2) + terrainPos);
terrain = new ShTlTerrainSceneNode(smgr,mapsize,mapsize,tilesize,meshsize);
terrain->drop();
terrain->follow(camera->getNode());
terrain->setMaterialTexture(0, driver->getTexture("data/misc/dirt_test.jpg"));
terrain->setDebugDataVisible(scene::EDS_FULL);
terrain->setMaterialFlag(video::EMF_LIGHTING, true);
terrain->setMaterialFlag(video::EMF_FOG_ENABLE, false);
terrain->setPosition(terrainPos);
// randomize base color
for(s32 j=0; j<terrain->getSize().Height+1; j++)
for(s32 i=0; i<terrain->getSize().Width+1; i++)
{
u32 g = (rand() % 150) + 80;
u32 r = (rand() % 50);
u32 b = (rand() % 50);
terrain->setColor(i,j, video::SColor(255,r,g,b));
}
MapMgr *mapmgr = g->GetInstance()->GetWSession()->GetWorld()->GetMapMgr();
// TODO: better to do this with some ZThread Condition or FastMutex, but dont know how to. help plz! [FG]
if(!mapmgr->Loaded())
{
logdebug("SceneWorld: Waiting until maps are loaded...");
while(!mapmgr->Loaded())
device->sleep(50);
}
// something is not good here. we have terrain, but the chunks are read incorrectly.
// need to find out where which formula is wrong
// the current terrain renderer code is just a test to see if ADT files are read correctly. apparantly not :D
MapTile *maptile = mapmgr->GetCurrentTile();
if(maptile)
{
// apply map height data
for(uint32 chx = 0; chx < 16; chx++)
for(uint32 chy = 0; chy < 16; chy++)
{
MapChunk *chunk = maptile->GetChunk(chx, chy);
std::stringstream ss;
DEBUG(logdebug("Apply MapChunk (%u, %u)",chx,chy));
for(uint32 hy = 0; hy < 9; hy++)
{
for(uint32 hx = 0; hx < 9; hx++)
{
f32 h = chunk->hmap_rough[hy * 9 + hx];
ss.precision(3);
ss << h << '\t';
terrain->setHeight(9 * chx + hx, 9 * chy + hy, h);
}
ss << "\n";
}
DEBUG(logdebug("\n%s\n",ss.str().c_str()));
}
}
else
{
logerror("SceneWorld: MapTile not loaded, can't apply heightmap!");
}
terrain->smoothNormals();
ILightSceneNode* light = smgr->addLightSceneNode(0, core::vector3df(0,0,0),
SColorf(255, 255, 255, 255), 1000.0f);
SLight ldata = light->getLightData();
ldata.AmbientColor = video::SColorf(0.2f,0.2f,0.2f);
ldata.DiffuseColor = video::SColorf(1.0f,1.0f,1.0f);
ldata.Type = video::ELT_DIRECTIONAL;
ldata.Position = core::vector3df(-10,5,-5);
light->setLightData(ldata);
driver->setFog(video::SColor(255,100,101,140), true, tilesize*meshsize/4, tilesize*(meshsize-4)/2, 0.05f);
DEBUG(logdebug("SceneWorld: Init done!"));
} }
void SceneWorld::Draw(void) void SceneWorld::OnUpdate(f32 timediff)
{ {
// draw maps here if(eventrecv->key.pressed(KEY_KEY_W)) camera->moveForward(50 * timediff);
if(eventrecv->key.pressed(KEY_KEY_S)) camera->moveBack(50 * timediff);
if(eventrecv->key.pressed(KEY_KEY_D)) camera->moveRight(50 * timediff);
if(eventrecv->key.pressed(KEY_KEY_A)) camera->moveLeft(50 * timediff);
// mouse directional control
camera->turnRight(5 * (device->getCursorControl()->getRelativePosition().X - 0.5f));
camera->turnUp(5 * (device->getCursorControl()->getRelativePosition().Y - 0.5f));
//device->getCursorControl()->setPosition(0.5f, 0.5f);
// camera height control
if (eventrecv->mouse.wheel < 10) eventrecv->mouse.wheel = 10;
camera->setHeight( eventrecv->mouse.wheel + terrain->getHeight(camera->getPosition()) );
}
void SceneWorld::OnDraw(void)
{
// draw all objects // draw all objects
gui->domgr.Update(); // iterate over DrawObjects, draw them and clean up gui->domgr.Update(); // iterate over DrawObjects, draw them and clean up
// draw interface here
} }
SceneWorld::~SceneWorld() void SceneWorld::OnDelete(void)
{ {
DEBUG(logdebug("~SceneWorld()"));
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,317 @@
/*-----------------------------------------------------------------------------*
| headerfile ShTlTerrainSceneNode.h |
| |
| version 2.00 |
| date: (29.04.2007) |
| |
| author: Michal Švantner |
| |
| Shifting Tiled Terrain Scene Node |
| |
| This node can render quit large terrain consisting of tiles by storing data |
| of individual tiles in array and rendering only part of terrain around |
| defined position and in defined size. This can be position of another scene |
| node defined by user and terrain node can be set to render around it |
| automaticaly. |
| It is done by creating mesh of given size which then glide over invisible |
| data skelet like a peace of soft cloth, updating its atributes from data |
| arrays each time it shifts to a new position. |
| |
| Diferent atributes of individual tiles can be adjusted, most of them on run |
| time. Namely texture coordinates, position of tile vertices, normals and |
| color. |
| |
| Scene node use 2 texture layers. |
| Firsth texture is standard texture which gives detail to terrain close by |
| and can by assigned to individual tiles by setting their UV coordinates. |
| User have complete freedom as howe to apply this texture to tiles. Texture |
| can for example consist of seweral subtextures and each can be set to |
| diferent tiles using UV coordinates. |
| |
| Second texture is created by terrain node internaly and is used to render |
| color of individual tiles. This adds some variability to terrain at distance.|
| Both textures are blended together using EMT_DETAIL_MAP material type. |
| |
| Normaly textures should be set in oposite order but there are some bugs with |
| updating texture under OpenGL so until it gets solved I have to stick with |
| detailmap applyed as firsth texture layer. Not perfect but working. |
| |
| This scene node also provide user with functions to get height at given |
| coordinates and test 3d line for collision useful for line of sight or bullet|
| collision testing. |
| |
| Rendered mesh is split in to seweral sectors which are culled individualy. |
| This exclude around 60% of polygoons from rendering. |
| |
| Writen for Irrlicht engine version 1.3 |
*-----------------------------------------------------------------------------*/
#ifndef SHTLTERRAINSCENENODE_H
#define SHTLTERRAINSCENENODE_H
#include "irrlicht/irrlicht.h"
using namespace irr;
#include "TlTMesh.h"
// Shifting Tiled Terrain Scene Node class
class ShTlTerrainSceneNode : public scene::ISceneNode
{
// dimensions of whole terrain
core::dimension2d<s32> Size;
// bounding box of terrain mesh
core::aabbox3d<f32> BoundingBox;
// terrain vertex data
array2d<TlTData> Data;
// terrain tile UV data for 1th texture layer
array2d<TlTCoords> UVdata;
// terrain mesh sectors
array2d<TlTSector> Sector;
// array of pointers to vertices of tiles
array2d<TlTTile> Tile;
// size of vissible terrain mesh
core::dimension2d<s32> MeshSize;
// position of vissible terrain mesh relative to whole terrain in tiles
core::vector2d<s32> MeshPosition;
// material
core::array<video::SMaterial> Material;
// size of terrain tiles
f32 TileSize;
// node terrain mesh should be rendered around
scene::ISceneNode* Fnode;
// color texture set as 2nd texture layer
video::ITexture* CTexture;
// number of sectors rendered last frame
u32 SectorsRendered;
// howe many tiles should be skiped before terrain mesh gets updated
s32 ShStep;
// return true if sector is on screen
virtual bool isSectorOnScreen(TlTSector* sctr);
// update vertices of sector
virtual void updateVertices(TlTSector &sector);
// update 2nd texture layer
virtual void updateTexture(u32* p, TlTSector &sector);
// return true if 3d line colide with tile
virtual bool getIntersectionWithTile(s32 w, s32 h, core::line3d<f32> line,
core::vector3df &outIntersection);
public:
// constructor
// \param smgr -pointer to scene manager
// \param width - width of terrain in tiles
// \param height - heighth of terrain in tiles
// \param tilesize -size of tile
// \param rendersize -size of rendered terrain mesh in tiles
// \param parent -parent scene node
// \param id -ID number
ShTlTerrainSceneNode(scene::ISceneManager* pSceneManager, s32 width, s32 height,
f32 tilesize, s32 rendersize, scene::ISceneNode* parent = 0, s32 id = -1);
// destructor
~ShTlTerrainSceneNode();
// frame
virtual void OnRegisterSceneNode();
// renders terrain
virtual void render();
// returns the axis aligned bounding box of terrain
virtual const core::aabbox3d<f32>& getBoundingBox() const;
// recalculate terrain bounding box
virtual void recalculateBoundingBox();
// returns amount of materials used by terrain
// this terrain uses only one material
virtual u32 getMaterialCount();
// returns the material of terrain based on the zero based index
// \param i -index of material to return
virtual video::SMaterial& getMaterial(u32 i);
// return number of tiles to skip before terrain mesh gets updated
virtual s32 getStep();
// set number of tiles to skip before terrain mesh gets updated, default is 1
// updating slows down rendering and seting step higher will cause terrain to update less ofthen
// \param newstep -amount of tiles to skip before updating
virtual void setStep(u32 newstep);
// return dimensions of whole terrain in tiles
virtual core::dimension2d<s32> getSize();
// return dimension of terrain tile
virtual f32 getTileSize();
// set new dimensions of terrain tile
// \param newsize -new size of tile
virtual void setTileSize(f32 newsize);
// returns dimension of rendered mesh in tiles
virtual core::dimension2d<s32> getRenderedSize();
// return number of sectors into which terrain mesh is divided
virtual u32 getSectorCount();
// returns sectors rendered last frame
virtual u32 getSectorsRendered();
// return relative height of terrain spot at terrain coordinates
// \param w -width coordinate of spot in tiles
// \param h -height coordinate of spot in tiles
virtual f32 getHeight(u32 w, u32 h);
// return height of terrain at any position
// \param pos -3d coordinates at which to get height of terrain
virtual f32 getHeight(core::vector3df pos);
// set relative height of terrain spot at terrain coordinates
// \param w -width coordinate of spot in tiles
// \param h -height coordinate of spot in tiles
// \param newheight -new height of spot
virtual void setHeight(u32 w, u32 h, f32 newheight);
// return normal of terrain at terrain coordinates
// \param w -width coordinate of spot in tiles
// \param h -height coordinate of spot in tiles
virtual core::vector3df getNormal(u32 w, u32 h);
// set normal of terrain at terrain coordinates
// \param w -width coordinate of spot in tiles
// \param h -height coordinate of spot in tiles
// \param newnormal -new normal vector terrain spot
virtual void setNormal(s32 w, s32 h, core::vector3df newnormal);
// recalculate normal at terrain coordinates
// \param w -width coordinate of spot in tiles
// \param h -height coordinate of spot in tiles
virtual void recalculateNormal(s32 w, s32 h);
// recalculare normals of whole terrain making it look smooth under light
virtual void smoothNormals();
// get texture coordinates of tile corner
// \param w -width coordinate of tile
// \param h -height coordinate of tile
// \param corner -tile corner, can be LOWER_LEFT, UPPER_LEFT, UPPER_RIGHT, LOWER_RIGHT
virtual core::vector2d<f32> getTileUV(u32 w, u32 h, TILE_VERTEX corner);
// set texture coordinates of tile
// \param w -width coordinate of tile
// \param h -height coordinate of tile
// \param UVLowerLeft -UV coordinates of lower left corner
// \param UVUpperLeft -UV coordinates of upper left corner
// \param UVUpperRight -UV coordinates of upper right corner
// \param UVLowerRight -UV coordinates of lower right corner
virtual void setTileUV(u32 w, u32 h, core::vector2d<f32> UVLowerLeft,
core::vector2d<f32> UVUpperLeft, core::vector2d<f32> UVUpperRight,
core::vector2d<f32> UVLowerRight);
// stretch texture over whole terrain
// \param scale -scale of the texture stretched, 2,2 would stretch it twice
virtual void stretchTexture(core::vector2d<f32> scale = core::vector2d<f32>(1,1));
// stretch texture over every tile individualy
// \param scale -scale of the texture stretched, 0.5,0.5 would display half of texture over each tile
virtual void stretchTextureOverTile(core::vector2d<f32> scale = core::vector2d<f32>(1,1));
// rotate texture of tile 90 degrees
// \param w -width coordinate of tile
// \param h -height coordinate of tile
virtual void rotateTileTexture90(u32 w, u32 h);
// rotate texture of tile 180 degrees
// \param w -width coordinate of tile
// \param h -height coordinate of tile
virtual void rotateTileTexture180(u32 w, u32 h);
// rotate texture of tile 270 degrees
// \param w -width coordinate of tile
// \param h -height coordinate of tile
virtual void rotateTileTexture270(u32 w, u32 h);
// flip (mirror) texture of tile horizontaly
// \param w -width coordinate of tile
// \param h -height coordinate of tile
virtual void flipTileTextureHorizontal(u32 w, u32 h);
// flip (mirror) texture of tile verticaly
// \param w -width coordinate of tile
// \param h -height coordinate of tile
virtual void flipTileTextureVertical(u32 w, u32 h);
// get color of tile at terrain coordinates
// \param w -width coordinate of tile
// \param h -height coordinate of tile
virtual video::SColor getColor(u32 w, u32 h);
// set color of tile at terrain coordinates
// \param w -width coordinate of tile
// \param h -height coordinate of tile
// \param newcolor -new color of tile
virtual void setColor(u32 w, u32 h, video::SColor newcolor);
// set rendered mesh position relative to terrain
// note that origin of mesh is in its lower left corner
// \param pos -new position of mesh relative to terrain in tiles
virtual void setMeshPosition(core::vector2d<s32> pos);
// center rendered mesh at 3d coordinates
// \param pos -new position mesh should be rendered around
virtual void centerAt(core::vector3d<f32> pos);
// update rendered mesh
virtual void update();
// set scene node terrain mesh should be automaticly rendered arround
// can be camera or player node for example
// \param node -scene node to automaticaly follow
virtual void follow(scene::ISceneNode* node);
// cancel pervious function
// stop following scene node if any
virtual void stop();
// test if 3d line colide with terrain
// returns true if yes, false if not and store intersection in "outIntersection" vector
// \param line -3d line
// \param outIntersection -vector to store intersection point if any
virtual bool getIntersectionWithLine( core::line3d<f32> line, core::vector3df &outIntersection);
// load height data from texture
// parameters allow to specify place where to load data, which makes possible
// to load terrain from seweral smaller textures
// \param filename -filename of texture
// \param scale -scale to apply at height data, if you want white color to be height of 10.5 set scale to 10.5
// \param w -width coordinate of tile were to start loading
// \param h -height coordinate of tile were to start loading
virtual void loadHeightMap(const c8 *filename, f32 scale, u32 w = 0, u32 h = 0);
// load color data from texture
// parameters allow to specify place where to load data, which makes possible
// to load terrain from seweral smaller textures
// \param filename -filename of texture
// \param w -width coordinate of tile were to start loading
// \param h -height coordinate of tile were to start loading
virtual void loadColorMap(const c8 *filename, u32 w = 0, u32 h = 0);
};
#endif

148
src/Client/GUI/TlTMesh.h Normal file
View File

@ -0,0 +1,148 @@
/*-----------------------------------------------------------------------------*
| headerfile TLTMesh.h |
| |
| version 1.00 |
| date: (17.04.2007) |
| |
| author: Michal Švantner |
| |
| Some structures used for Tiled Terrain |
| Writen for Irrlicht engine version 1.3 |
*-----------------------------------------------------------------------------*/
#ifndef TLTMESH_H
#define TLTMESH_H
#include <irrlicht/irrlicht.h>
using namespace irr;
// dynamic 2d array
template <class T> class array2d
{
T** data;
s32 w, h;
public:
array2d() : w(0), h(0) {}
array2d(int width, int height) : w(width), h(height)
{
data = new T*[w];
for(int i=0; i<w; i++) data[i] = new T[h];
}
virtual void reset(int width, int height)
{
if(w && h)
{
for(int i=0; i<w; i++) delete data[i];
delete [] data;
}
if(width && height)
{
w = width;
h = height;
data = new T*[w];
for(int i=0; i<w; i++) data[i] = new T[h];
}
else
{
w = 0;
h = 0;
}
}
~array2d()
{
if(w && h)
{
for(int i=0; i<w; i++) delete [] data[i];
delete [] data;
}
}
virtual T& operator ()(u32 index1, u32 index2)
{
return data[index1][index2];
}
virtual s32 width() {return w;}
virtual s32 height() {return h;}
};
// enumeration of tile vertices
enum TILE_VERTEX
{
LOWER_LEFT = 0,
UPPER_LEFT,
UPPER_RIGHT,
LOWER_RIGHT,
};
// structure holding pointers to 4 vertices of tile
// makes possible to acces vertex data based on tile structure
struct TlTTile
{
video::S3DVertex2TCoords* Vertex[4];
};
// structure holding texture coordinates of tile
struct TlTCoords
{
core::vector2d<f32> Vertex[4];
};
// structure which holds some data about spot on tiled terrain
struct TlTData
{
f32 Height;
core::vector3df Normal;
video::SColor Color;
};
// structure which is used as meshbuffer for Tiled Terrain
class TlTSector
{
public:
TlTSector() {};
~TlTSector() {};
// position relative to whole mesh of which sector is part in tiles
core::vector2d<s32> Offset;
// dimension of sector in tiles
core::dimension2d<u32> Size;
// array of vertices
core::array<video::S3DVertex2TCoords> Vertex;
// array of indices
core::array<u16> Index;
// axis aligned bounding box
core::aabbox3d<f32> BoundingBox;
// update texture flag
bool UpdateTexture;
// update vertices flag
bool UpdateVertices;
// vissibility flag
bool isVissible;
};
#endif

View File

@ -7,6 +7,7 @@ MapMgr::MapMgr()
{ {
_tiles = new MapTileStorage(); _tiles = new MapTileStorage();
_gridx = _gridy = _mapid = (-1); _gridx = _gridy = _mapid = (-1);
_mapsLoaded = false;
} }
MapMgr::~MapMgr() MapMgr::~MapMgr()
@ -33,8 +34,8 @@ void MapMgr::Update(float x, float y, uint32 m)
_gridx = _gridy = (-1); // must load tiles now _gridx = _gridy = (-1); // must load tiles now
} }
uint32 xg,yg; // MapTile IDs. Range 0..64 uint32 xg,yg; // MapTile IDs. Range 0..64
xg = (uint32)( (ZEROPOINT - x) / TILESIZE); xg = GetGridCoord(x);
yg = (uint32)( (ZEROPOINT - y) / TILESIZE); yg = GetGridCoord(y);
if(xg != _gridx || yg != _gridy) if(xg != _gridx || yg != _gridy)
{ {
_LoadNearTiles(xg,yg,m); _LoadNearTiles(xg,yg,m);
@ -47,6 +48,7 @@ void MapMgr::Update(float x, float y, uint32 m)
void MapMgr::Flush(void) void MapMgr::Flush(void)
{ {
_mapsLoaded = false;
for(uint32 i = 0; i < 4096; i++) for(uint32 i = 0; i < 4096; i++)
_tiles->UnloadMapTile(i); _tiles->UnloadMapTile(i);
logdebug("MAPMGR: Flushed all maps"); logdebug("MAPMGR: Flushed all maps");
@ -62,6 +64,7 @@ void MapMgr::_LoadNearTiles(uint32 gx, uint32 gy, uint32 m)
_LoadTile(h,v,m); _LoadTile(h,v,m);
} }
} }
_mapsLoaded = true;
} }
void MapMgr::_LoadTile(uint32 gx, uint32 gy, uint32 m) void MapMgr::_LoadTile(uint32 gx, uint32 gy, uint32 m)
@ -115,11 +118,33 @@ void MapMgr::_UnloadOldTiles(void)
} }
} }
// Using forceLoad is VERY ineffective here, because the tile is removed again after the next Update() call!
MapTile *MapMgr::GetTile(uint32 xg, uint32 yg, bool forceLoad)
{
MapTile *tile = _tiles->GetTile(xg,yg);
if(!tile)
{
_LoadTile(xg,yg,_mapid);
tile = _tiles->GetTile(xg,yg);
}
return tile;
}
MapTile *MapMgr::GetCurrentTile(void)
{
return GetTile(_gridx,_gridy);
}
uint32 MapMgr::GetGridCoord(float f)
{
return (ZEROPOINT - f) / TILESIZE;
}
float MapMgr::GetZ(float x, float y) float MapMgr::GetZ(float x, float y)
{ {
uint32 xg,yg; // MapTile IDs. Range 0..64 uint32 xg,yg; // MapTile IDs. Range 0..64
xg = (uint32)( (ZEROPOINT - x) / TILESIZE); xg = GetGridCoord(x);
yg = (uint32)( (ZEROPOINT - y) / TILESIZE); yg = GetGridCoord(y);
MapTile *tile = _tiles->GetTile(xg,yg); MapTile *tile = _tiles->GetTile(xg,yg);
if(tile) if(tile)
{ {
@ -134,6 +159,3 @@ float MapMgr::GetZ(float x, float y)
return 0; return 0;
} }

View File

@ -2,6 +2,7 @@
#define MAPMGR_H #define MAPMGR_H
class MapTileStorage; class MapTileStorage;
class MapTile;
class MapMgr class MapMgr
{ {
@ -11,6 +12,10 @@ public:
void Update(float,float,uint32); void Update(float,float,uint32);
void Flush(void); void Flush(void);
float GetZ(float,float); float GetZ(float,float);
uint32 GetGridCoord(float f);
MapTile *GetTile(uint32 xg, uint32 yg, bool forceLoad = false);
MapTile *GetCurrentTile(void);
inline bool Loaded(void) { return _mapsLoaded; }
private: private:
MapTileStorage *_tiles; MapTileStorage *_tiles;
@ -19,6 +24,7 @@ private:
void _UnloadOldTiles(void); void _UnloadOldTiles(void);
uint32 _mapid; uint32 _mapid;
uint32 _gridx,_gridy; uint32 _gridx,_gridy;
bool _mapsLoaded;
}; };
#endif #endif

View File

@ -17,6 +17,7 @@ public:
void UpdatePos(float,float,uint32); void UpdatePos(float,float,uint32);
void UpdatePos(float,float); void UpdatePos(float,float);
inline float GetPosZ(float x, float y); inline float GetPosZ(float x, float y);
inline MapMgr *GetMapMgr(void) { return _mapmgr; }
private: private:
WorldSession *_session; WorldSession *_session;

View File

@ -313,12 +313,12 @@ void WorldSession::_HandleAuthChallengeOpcode(WorldPacket& recvPacket)
// recvPacket << ziped_UI_Plugins_Info // recvPacket << ziped_UI_Plugins_Info
// TODO: add addon data, simulate no addons. // TODO: add addon data, simulate no addons.
auth<<(uint32)0; // no addons? no idea, but seems to work. MaNGOS doesnt accept without this. auth<<(uint32)0; // no addons? no idea, but seems to work. MaNGOS doesnt accept without this.
auth.SetOpcode(CMSG_AUTH_SESSION); auth.SetOpcode(CMSG_AUTH_SESSION);
SendWorldPacket(auth); SendWorldPacket(auth);
// note that if the sessionkey/auth is wrong or failed, the server sends the following packet UNENCRYPTED! // note that if the sessionkey/auth is wrong or failed, the server sends the following packet UNENCRYPTED!
// so its not 100% correct to init the crypt here, but it should do the job if authing was correct // so its not 100% correct to init the crypt here, but it should do the job if authing was correct
_socket->InitCrypt(GetInstance()->GetSessionKey().AsByteArray(), 40); _socket->InitCrypt(GetInstance()->GetSessionKey().AsByteArray(), 40);
} }
@ -939,6 +939,13 @@ void WorldSession::_HandleLoginVerifyWorldOpcode(WorldPacket& recvPacket)
delete _world; delete _world;
_world = new World(this); _world = new World(this);
_world->UpdatePos(x,y,m); _world->UpdatePos(x,y,m);
// temp. solution to test terrain rendering
PseuGUI *gui = GetInstance()->GetGUI();
if(gui)
{
gui->SetSceneState(SCENESTATE_WORLD);
}
} }
ByteBuffer& operator>>(ByteBuffer& bb, WhoListEntry& e) ByteBuffer& operator>>(ByteBuffer& bb, WhoListEntry& e)

View File

@ -1,7 +1,10 @@
#include <new.h>
#include "common.h" #include "common.h"
#include "main.h" #include "main.h"
#include "PseuWoW.h" #include "PseuWoW.h"
std::list<PseuInstanceRunnable*> instanceList; // TODO: move this to a "Master" class later std::list<PseuInstanceRunnable*> instanceList; // TODO: move this to a "Master" class later
@ -68,12 +71,20 @@ void abortproc(void)
} }
} }
void _new_handler(void)
{
logcritical("ERROR: Out of memory!");
throw;
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
try try
{ {
set_new_handler(_new_handler);
_log_setcolor(true,LGREEN); _log_setcolor(true,LGREEN);
printf("+----------------------------------+\n" printf("+----------------------------------+\n"
"| (C) 2006,2007 Snowstorm Software |\n" "| (C) 2006,2007 Snowstorm Software |\n"
"| http://www.mangosclient.org |\n"
"+----------------------------------+\n"); "+----------------------------------+\n");
_log_resetcolor(true); _log_resetcolor(true);

View File

@ -6,6 +6,7 @@ void _UnhookSignals(void);
void _OnSignal(int); void _OnSignal(int);
void quitproc(void); void quitproc(void);
void abortproc(void); void abortproc(void);
void _new_handler(void);
int main(int,char**); int main(int,char**);
#endif #endif

View File

@ -414,6 +414,12 @@
<File <File
RelativePath=".\Client\Gui\DrawObjMgr.h"> RelativePath=".\Client\Gui\DrawObjMgr.h">
</File> </File>
<File
RelativePath=".\Client\Gui\MCamera.h">
</File>
<File
RelativePath=".\Client\Gui\MInput.h">
</File>
<File <File
RelativePath=".\Client\Gui\PseuGUI.cpp"> RelativePath=".\Client\Gui\PseuGUI.cpp">
</File> </File>
@ -432,6 +438,15 @@
<File <File
RelativePath=".\Client\Gui\SceneWorld.cpp"> RelativePath=".\Client\Gui\SceneWorld.cpp">
</File> </File>
<File
RelativePath=".\Client\Gui\ShTlTerrainSceneNode.cpp">
</File>
<File
RelativePath=".\Client\Gui\ShTlTerrainSceneNode.h">
</File>
<File
RelativePath=".\Client\Gui\TlTMesh.h">
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter

View File

@ -31,6 +31,7 @@ public:
void ImportFromADT(ADTFile*); void ImportFromADT(ADTFile*);
float GetZ(float,float); float GetZ(float,float);
void DebugDumpToFile(void); void DebugDumpToFile(void);
inline MapChunk *GetChunk(uint32 x, uint32 y) { return &_chunks[x * 16 + y]; }
private: private:
MapChunk _chunks[256]; // 16x16 MapChunk _chunks[256]; // 16x16