Skip to content

Commit

Permalink
NWN: Show walkmesh and pathfinding capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
Supermanu committed Jul 4, 2018
1 parent c2f39dc commit 72895e2
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 1 deletion.
103 changes: 102 additions & 1 deletion src/engines/nwn/area.cpp
Expand Up @@ -23,9 +23,11 @@
*/

#include <cassert>
#include <ctime>

#include "src/common/util.h"
#include "src/common/error.h"
#include "src/common/maths.h"

#include "src/aurora/gff3file.h"
#include "src/aurora/2dafile.h"
Expand All @@ -41,11 +43,13 @@
#include "src/engines/aurora/util.h"
#include "src/engines/aurora/model.h"

#include "src/engines/nwn/localpathfinding.h"
#include "src/engines/nwn/area.h"
#include "src/engines/nwn/module.h"
#include "src/engines/nwn/waypoint.h"
#include "src/engines/nwn/placeable.h"
#include "src/engines/nwn/door.h"
#include "src/engines/nwn/pathfinding.h"
#include "src/engines/nwn/creature.h"

namespace Engines {
Expand All @@ -54,7 +58,7 @@ namespace NWN {

Area::Area(Module &module, const Common::UString &resRef) : Object(kObjectTypeArea),
_module(&module), _resRef(resRef), _visible(false),
_activeObject(0), _highlightAll(false) {
_activeObject(0), _highlightAll(false), _localPathfinding(0) {

try {
load();
Expand All @@ -74,10 +78,18 @@ Area::~Area() {

removeFocus();

delete _pathfinding;
delete _localPathfinding;

clear();
}

void Area::load() {
std::vector<bool> walkableProp;
loadWalkableSurface(walkableProp);
_pathfinding = new Pathfinding(walkableProp);
_localPathfinding = new /*Engines::*/LocalPathfinding(_pathfinding);

Aurora::GFF3File are(_resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' '), true);
loadARE(are.getTopLevel());

Expand Down Expand Up @@ -236,6 +248,9 @@ void Area::show() {

GfxMan.unlockFrame();

_pathfinding->showPath(true);
_pathfinding->showWalkmesh(true);

// Play music and sound
playAmbientSound();
playAmbientMusic();
Expand Down Expand Up @@ -265,6 +280,11 @@ void Area::hide() {

unloadModels();

_pathfinding->showPath(false);
_pathfinding->showWalkmesh(false);
_localPathfinding->showPath(false);
_localPathfinding->showWalkmesh(false);

_visible = false;
}

Expand Down Expand Up @@ -464,8 +484,25 @@ void Area::loadTiles() {

t.model->setPosition(tileX, tileY, tileZ);
t.model->setOrientation(0.0f, 0.0f, 1.0f, ((int) t.orientation) * 90.0f);

float position[3] = { tileX, tileY, tileZ };
float orientation[4] = {0.0f, 0.0f, 1.0f, ((int) t.orientation) * (float) M_PI * 0.5f};
_pathfinding->addData(t.tile->model, orientation, position);
}
}


_pathfinding->finalize();
}

void Area::loadWalkableSurface(std::vector<bool> &walkability) {
walkability.clear();

const Aurora::TwoDAFile &surfacematTwoDA = TwoDAReg.get2DA("surfacemat");
for (uint32 s = 0; s < surfacematTwoDA.getRowCount(); ++s) {
const Aurora::TwoDARow &row = surfacematTwoDA.getRow(s);
walkability.push_back(static_cast<bool>(row.getInt("Walk")));
}
}

void Area::unloadTiles() {
Expand Down Expand Up @@ -503,6 +540,11 @@ void Area::loadPlaceables(const Aurora::GFF3List &list) {
Placeable *placeable = new Placeable(**p);

loadObject(*placeable);
float position[3];
float orientation[4];
placeable->getPosition(position[0], position[1], position[2]);
placeable->getOrientation(orientation[3], orientation[0], orientation[1], orientation[2]);
_localPathfinding->addPlaceables(placeable->getModelName(), position, orientation);
}
}

Expand Down Expand Up @@ -537,6 +579,65 @@ void Area::processEventQueue() {
if (e->button.button == SDL_BUTTON_LMASK) {
checkActive(e->button.x, e->button.y);
click(e->button.x, e->button.y);

if (_activeObject)
continue;

float width = 0.4;
float x1, y1, z1, x2, y2, z2;
int x, y;
CursorMan.getPosition(x, y);
GfxMan.unproject((float) x, (float) y, x1, y1, z1, x2, y2, z2);
glm::vec3 intersect;

if (_pathfinding->findIntersection(x1, y1, z1, x2, y2, z2, intersect, true)) {
warning("intersection (%f, %f, %f)", intersect[0], intersect[1], intersect[2]);
if (_startEndPoints.size() < 2) {
_startEndPoints.push_back(intersect);
} else {
_startEndPoints[0] = _startEndPoints[1];
_startEndPoints[1] = intersect;
}

if (_startEndPoints.size() == 2) {
std::vector<uint32> path;
clock_t startFindPath = std::clock();
bool out = _pathfinding->findPath(_startEndPoints[0][0], _startEndPoints[0][1],
_startEndPoints[1][0], _startEndPoints[1][1], path, width);
clock_t endFindPath = std::clock();
warning("Out is %i", out);
clock_t startSmooth = std::clock();
std::vector<glm::vec3> smoothPath;
if (out) {
_pathfinding->smoothPath(_startEndPoints[0][0], _startEndPoints[0][1],
_startEndPoints[1][0], _startEndPoints[1][1], path, smoothPath);
_startEndPoints.clear();
}
clock_t endSmooth = std::clock();
double findPath = double(endFindPath - startFindPath);
double smoothing = double(endSmooth - startSmooth);
warning("Time spent find path: %f ms", findPath / CLOCKS_PER_SEC * 1000);
warning("Time spent smoothing: %f ms", smoothing / CLOCKS_PER_SEC * 1000);
warning("Total time: %f ms", (findPath + smoothing) / CLOCKS_PER_SEC * 1000);
if (out) {
_localPathfinding->showWalkmesh(false);
_localPathfinding->showPath(false);
clock_t startLocal = std::clock();
_localPathfinding->buildWalkmeshAround(smoothPath, width / 2);
clock_t endLocal = std::clock();
double local = double(endLocal - startLocal);
warning("Time spent building local: %f ms", local / CLOCKS_PER_SEC * 1000);
startLocal = std::clock();
_localPathfinding->findPathTo(smoothPath);
endLocal = std::clock();
local = double(endLocal - startLocal);
warning("Time spent finding local: %f ms", local / CLOCKS_PER_SEC * 1000);
_localPathfinding->showWalkmesh(true);
_localPathfinding->showPath(true);

}
}
}
}
} else if (e->type == Events::kEventKeyDown) { // Holding down TAB
if (e->key.keysym.sym == SDLK_TAB)
Expand Down
12 changes: 12 additions & 0 deletions src/engines/nwn/area.h
Expand Up @@ -29,6 +29,8 @@
#include <list>
#include <map>

#include "glm/vec3.hpp"

#include "src/common/types.h"
#include "src/common/ptrlist.h"
#include "src/common/ustring.h"
Expand All @@ -46,10 +48,15 @@
#include "src/engines/nwn/tileset.h"
#include "src/engines/nwn/object.h"


namespace Engines {

//class LocalPathfinding;

namespace NWN {

class Pathfinding;
class LocalPathfinding;
class Module;

/** An area in Neverwinter Nights, holding all objects and room tiles within, as
Expand Down Expand Up @@ -199,6 +206,9 @@ class Area : public NWN::Object, public Events::Notifyable {

Common::Mutex _mutex; ///< Mutex securing access to the area.

Pathfinding *_pathfinding;
/*Engines::*/LocalPathfinding *_localPathfinding;
std::vector<glm::vec3> _startEndPoints;

// Loading helpers

Expand All @@ -219,6 +229,8 @@ class Area : public NWN::Object, public Events::Notifyable {
void loadDoors (const Aurora::GFF3List &list);
void loadCreatures (const Aurora::GFF3List &list);

void loadWalkableSurface(std::vector<bool> &walkability);

// Model loading/unloading helpers

void loadModels();
Expand Down

0 comments on commit 72895e2

Please sign in to comment.