Skip to content

Commit

Permalink
NWN: Switch on lighting (WIP!)
Browse files Browse the repository at this point in the history
Horribly wrong and broken in several places.
Also, very very slow.
  • Loading branch information
DrMcCoy committed Feb 18, 2019
1 parent 1ce27a8 commit c36da06
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 10 deletions.
57 changes: 52 additions & 5 deletions src/engines/nwn/area.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "src/graphics/graphics.h"

#include "src/graphics/aurora/cursorman.h"
#include "src/graphics/aurora/modelnode.h"
#include "src/graphics/aurora/model.h"

#include "src/sound/sound.h"
Expand Down Expand Up @@ -238,8 +239,10 @@ void Area::show() {
GfxMan.lockFrame();

// Show tiles
for (std::vector<Tile>::iterator t = _tiles.begin(); t != _tiles.end(); ++t)
t->model->show();
for (std::vector<Tile>::iterator t = _tiles.begin(); t != _tiles.end(); ++t) {
if (t->model)
t->model->show();
}

// Show objects
for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
Expand All @@ -249,6 +252,8 @@ void Area::show() {
_pathfinding->showWalkmesh(!_walkmeshInvisible);
_localPathfinding->showWalkmesh(!_walkmeshInvisible);

LightMan.updateLighting();

GfxMan.unlockFrame();

// Play music and sound
Expand All @@ -274,7 +279,8 @@ void Area::hide() {

// Hide tiles
for (std::vector<Tile>::iterator t = _tiles.begin(); t != _tiles.end(); ++t)
t->model->hide();
if (t->model)
t->model->hide();

// Hide walkmesh
_pathfinding->showWalkmesh(false);
Expand Down Expand Up @@ -393,8 +399,8 @@ void Area::loadTile(const Aurora::GFF3Struct &t, Tile &tile) {
tile.mainLight[0] = t.getUint("Tile_MainLight1", 0);
tile.mainLight[1] = t.getUint("Tile_MainLight2", 0);

tile.srcLight[0] = t.getUint("Tile_SrcLight1", 0);
tile.srcLight[1] = t.getUint("Tile_SrcLight2", 0);
tile.srcLight[0] = t.getUint("Tile_SrcLight1", 0) * 2;
tile.srcLight[1] = t.getUint("Tile_SrcLight2", 0) * 2;

// Tile animations

Expand Down Expand Up @@ -460,9 +466,12 @@ void Area::unloadTileset() {
_tileset.reset();
}

static int H = 0;
void Area::loadTiles() {
for (uint32 y = 0; y < _height; y++) {
for (uint32 x = 0; x < _width; x++) {
if (x == 8 && y == 8)
continue;
uint32 n = y * _width + x;

Tile &t = _tiles[n];
Expand All @@ -481,6 +490,8 @@ void Area::loadTiles() {
// The actual height of a tile is dictated by the tileset.
const float tileZ = t.height * _tileset->getTilesHeight();

H = t.height;

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

Expand All @@ -489,13 +500,46 @@ void Area::loadTiles() {
float orientation[4] = {0.0f, 0.0f, 1.0f, ((int) t.orientation) * (float) M_PI * 0.5f};
_pathfinding->addTile(t.tile->model, orientation, position);
}

createLight(t.light[0], t.model, t.mainLight[0], t.tile->model + "ml1");
createLight(t.light[1], t.model, t.mainLight[1], t.tile->model + "ml2");
createLight(t.light[2], t.model, t.srcLight [0], t.tile->model + "sl1");
createLight(t.light[3], t.model, t.srcLight [1], t.tile->model + "sl2");
}
}

if (!_pathfinding->loaded())
_pathfinding->finalize();
}

void Area::createLight(Graphics::LightHandle &light, Graphics::Aurora::Model *model,
uint8 color, const Common::UString &nodeName) {

if ((color == 0) || (color > 31))
return;

Graphics::Aurora::ModelNode *node = model->getNode(nodeName);
if (!node)
return;

float x, y, z;
node->getWorldPosition(x, y, z);

light = LightMan.addLight();

const Aurora::TwoDAFile &lightColor = TwoDAReg.get2DA("lightcolor");

float r = lightColor.getRow(color).getFloat("TOOLSETRED");
float g = lightColor.getRow(color).getFloat("TOOLSETGREEN");
float b = lightColor.getRow(color).getFloat("TOOLSETBLUE");

LightMan.setAmbient (light, 0.0, 0.0, 0.0, 1.0);
LightMan.setDiffuse (light, r, g, b, 1.0);
LightMan.setSpecular(light, 0.0, 0.0, 0.0, 1.0);
LightMan.setPosition(light, x, y, z);
LightMan.switchOnOff(light, true);
}

void Area::unloadTiles() {
for (uint32 y = 0; y < _height; y++) {
for (uint32 x = 0; x < _width; x++) {
Expand All @@ -507,6 +551,9 @@ void Area::unloadTiles() {

delete t.model;
t.model = 0;

for (int i = 0; i < 4; i++)
t.light[i].clear();
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/engines/nwn/area.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@

#include "src/aurora/types.h"

#include "src/aurora/nwscript/object.h"

#include "src/graphics/lightman.h"

#include "src/graphics/aurora/types.h"

#include "src/sound/types.h"
Expand Down Expand Up @@ -151,6 +155,8 @@ class Area : public NWN::Object, public Events::Notifyable {
const Tileset::Tile *tile; ///< The actual tile within the tileset.

Graphics::Aurora::Model *model; ///< The tile's model.

Graphics::LightHandle light[4]; ///< The tile's lights.
};

typedef Common::PtrList<NWN::Object> ObjectList;
Expand Down Expand Up @@ -242,6 +248,9 @@ class Area : public NWN::Object, public Events::Notifyable {
void loadTiles();
void unloadTiles();

void createLight(Graphics::LightHandle &light, Graphics::Aurora::Model *model,
uint8 color, const Common::UString &nodeName);

// Highlight / active helpers

void checkActive(int x = -1, int y = -1);
Expand Down
4 changes: 4 additions & 0 deletions src/engines/nwn/nwn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

#include "src/events/events.h"

#include "src/graphics/lightman.h"

#include "src/graphics/aurora/textureman.h"
#include "src/graphics/aurora/cursorman.h"
#include "src/graphics/aurora/fontman.h"
Expand Down Expand Up @@ -127,6 +129,8 @@ void NWNEngine::run() {

CursorMan.showCursor();

LightMan.enableLighting(true);

_game.reset(new Game(*this, *_console, *_version));
_game->run();

Expand Down
77 changes: 77 additions & 0 deletions src/graphics/aurora/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ Model::Model(ModelType type)
_orientation[2] = 0.0f;
_orientation[3] = 0.0f;

_needEvalLights = true;

_center[0] = 0.0f; _center[1] = 0.0f; _center[2] = 0.0f;

// TODO: Is this the same as modelScale for non-UI?
Expand Down Expand Up @@ -110,11 +112,17 @@ Model::~Model() {

void Model::show() {
Renderable::show();

GfxMan.registerAnimatedModel(this);
_needEvalLights = true;
}

void Model::hide() {
for (StateList::iterator s = _stateList.begin(); s != _stateList.end(); ++s)
for (NodeList::iterator n = (*s)->nodeList.begin(); n != (*s)->nodeList.end(); ++n)
(*n)->clearLights();
GfxMan.unregisterAnimatedModel(this);

Renderable::hide();
}

Expand Down Expand Up @@ -242,6 +250,8 @@ void Model::setScale(float x, float y, float z) {
createAbsolutePosition();
calculateDistance();

_needEvalLights = true;

resort();

unlockFrameIfVisible();
Expand All @@ -258,6 +268,8 @@ void Model::setOrientation(float x, float y, float z, float angle) {
createAbsolutePosition();
calculateDistance();

_needEvalLights = true;

resort();

unlockFrameIfVisible();
Expand All @@ -273,6 +285,8 @@ void Model::setPosition(float x, float y, float z) {
createAbsolutePosition();
calculateDistance();

_needEvalLights = true;

resort();

unlockFrameIfVisible();
Expand Down Expand Up @@ -602,6 +616,67 @@ void Model::calculateDistance() {
_distance = x + y + z;
}

void Model::evaluateLights() {
if (!_needEvalLights)
return;

glm::mat4 position = _absolutePosition;

for (NodeList::iterator n = _currentState->rootNodes.begin();
n != _currentState->rootNodes.end(); ++n) {

(*n)->evaluateLights(position);
}

_needEvalLights = false;
}

/*
bool Model::buildList(RenderPass pass) {
evaluateLights();
if (_lists == 0)
_lists = glGenLists(kRenderPassAll);
glNewList(_lists + pass, GL_COMPILE);
// Apply our global model transformation
glScalef(_modelScale[0], _modelScale[1], _modelScale[2]);
if (_type == kModelTypeObject)
// Aurora world objects have a rotated axis
glRotatef(90.0, -1.0, 0.0, 0.0);
glTranslatef(_position[0], _position[1], _position[2]);
glRotatef( _rotation[0], 1.0, 0.0, 0.0);
glRotatef( _rotation[1], 0.0, 1.0, 0.0);
glRotatef(-_rotation[2], 0.0, 0.0, 1.0);
// Draw the bounding box, if requested
doDrawBound();
// Draw the nodes
for (NodeList::iterator n = _currentState->rootNodes.begin();
n != _currentState->rootNodes.end(); n++) {
glPushMatrix();
(*n)->render(pass);
glPopMatrix();
}
glEndList();
_needBuild[pass] = false;
return true;
}
*/

void Model::advanceTime(float dt) {
manageAnimations(dt);
flushNodeBuffers();
Expand Down Expand Up @@ -655,6 +730,8 @@ void Model::render(RenderPass pass) {
return;
}

evaluateLights();

// Apply our global model transformation
glTranslatef(_position[0], _position[1], _position[2]);
glRotatef(_orientation[3], _orientation[0], _orientation[1], _orientation[2]);
Expand Down
4 changes: 4 additions & 0 deletions src/graphics/aurora/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,16 @@ class Model : public GLContainer, public Renderable {
glm::mat4 _boundTransform;

private:
bool _needEvalLights;

bool _drawBound;
bool _drawSkeleton;
bool _drawSkeletonInvisible;

std::map<Common::UString, Model *> _attachedModels;

void evaluateLights();

/** Create the list of all state names. */
void createStateNamesList(std::list<Common::UString> *stateNames = 0);
/** Create the model's bounding box. */
Expand Down
47 changes: 46 additions & 1 deletion src/graphics/aurora/modelnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,47 @@ void ModelNode::orderChildren() {
(*c)->orderChildren();
}

void ModelNode::clearLights() {
_lighting.clear();
}

void ModelNode::evaluateLights(glm::mat4 position) {
clearLights();

_lighting.push_back(LightMan.createLighting());

position = glm::translate(position, glm::vec3(_position[0], _position[1], _position[2]));
position = glm::rotate(position, Common::deg2rad(_orientation[3]),
glm::vec3(_orientation[0], _orientation[1], _orientation[2]));

position = glm::rotate(position, Common::deg2rad(_rotation[0]), glm::vec3(1.0f, 0.0f, 0.0f));
position = glm::rotate(position, Common::deg2rad(_rotation[1]), glm::vec3(0.0f, 1.0f, 0.0f));
position = glm::rotate(position, Common::deg2rad(_rotation[2]), glm::vec3(0.0f, 0.0f, 1.0f));

position = glm::scale(position, glm::vec3(_scale[0], _scale[1], _scale[2]));

Common::BoundingBox bound;

bound.transform(position);
bound.add(_boundBox);
bound.absolutize();

float min[3], max[3], center[3];

bound.getMin(min[0], min[1], min[2]);
bound.getMax(max[0], max[1], max[2]);

center[0] = min[0] + ABS(max[0] - min[0]) / 2.0f;
center[1] = min[1] + ABS(max[1] - min[1]) / 2.0f;
center[2] = min[2] + ABS(max[2] - min[2]) / 2.0f;

LightMan.evaluateLighting(_lighting[0], center[0], center[1], center[2]);

// Recurse into the children
for (std::list<ModelNode *>::iterator c = _children.begin(); c != _children.end(); ++c)
(*c)->evaluateLights(position);
}

void ModelNode::renderGeometry(ModelNode::Mesh &mesh) {
TextureHandle *penvmap = 0;
EnvironmentMapMode envmapmode;
Expand Down Expand Up @@ -707,8 +748,12 @@ void ModelNode::render(RenderPass pass) {
((pass == kRenderPassTransparent) && !isTransparent))
shouldRender = false;

if (shouldRender)
if (shouldRender) {
if (!_lighting.empty())
LightMan.renderLights(_lighting[0]);

renderGeometry(*mesh);
}

if (_attachedModel) {
glPushMatrix();
Expand Down

0 comments on commit c36da06

Please sign in to comment.