mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-03 16:39:41 +00:00
Merge branch 'master' of http://github.com/zinnschlag/openmw
This commit is contained in:
commit
91e8590288
36 changed files with 786 additions and 112 deletions
|
@ -13,12 +13,15 @@ set(GAMEREND
|
||||||
mwrender/mwscene.cpp
|
mwrender/mwscene.cpp
|
||||||
mwrender/cellimp.cpp
|
mwrender/cellimp.cpp
|
||||||
mwrender/interior.cpp
|
mwrender/interior.cpp
|
||||||
|
mwrender/exterior.cpp
|
||||||
|
mwrender/playerpos.cpp
|
||||||
mwrender/sky.cpp)
|
mwrender/sky.cpp)
|
||||||
set(GAMEREND_HEADER
|
set(GAMEREND_HEADER
|
||||||
mwrender/cell.hpp
|
mwrender/cell.hpp
|
||||||
mwrender/cellimp.hpp
|
mwrender/cellimp.hpp
|
||||||
mwrender/mwscene.hpp
|
mwrender/mwscene.hpp
|
||||||
mwrender/interior.hpp
|
mwrender/interior.hpp
|
||||||
|
mwrender/exterior.hpp
|
||||||
mwrender/playerpos.hpp
|
mwrender/playerpos.hpp
|
||||||
mwrender/sky.hpp)
|
mwrender/sky.hpp)
|
||||||
source_group(apps\\openmw\\mwrender FILES ${GAMEREND} ${GAMEREND_HEADER})
|
source_group(apps\\openmw\\mwrender FILES ${GAMEREND} ${GAMEREND_HEADER})
|
||||||
|
|
|
@ -21,9 +21,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
|
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace MWClass
|
||||||
const float radius = float (ref->base->data.radius);
|
const float radius = float (ref->base->data.radius);
|
||||||
cellRender.insertLight (r, g, b, radius);
|
cellRender.insertLight (r, g, b, radius);
|
||||||
|
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ namespace MWClass
|
||||||
std::string headModel = "meshes\\" +
|
std::string headModel = "meshes\\" +
|
||||||
environment.mWorld->getStore().bodyParts.find(headID)->model;
|
environment.mWorld->getStore().bodyParts.find(headID)->model;
|
||||||
|
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
|
|
||||||
cellRender.insertMesh (headModel);
|
cellRender.insertMesh (headModel);
|
||||||
|
|
||||||
//TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the
|
//TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the
|
||||||
|
@ -51,7 +52,7 @@ namespace MWClass
|
||||||
if (bodyPart)
|
if (bodyPart)
|
||||||
cellRender.insertMesh("meshes\\" + bodyPart->model);
|
cellRender.insertMesh("meshes\\" + bodyPart->model);
|
||||||
|
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
|
void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace MWClass
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
cellRender.insertBegin (ref->ref);
|
MWRender::Rendering rendering (cellRender, ref->ref);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled()));
|
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "cellimp.hpp"
|
#include "cellimp.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
@ -23,8 +25,16 @@ void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environ
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr (&*it, &cell);
|
MWWorld::Ptr ptr (&*it, &cell);
|
||||||
|
|
||||||
class_.insertObj (ptr, cellRender, environment);
|
try
|
||||||
class_.enable (ptr, environment);
|
{
|
||||||
|
class_.insertObj (ptr, cellRender, environment);
|
||||||
|
class_.enable (ptr, environment);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::string error ("error during rendering: ");
|
||||||
|
std::cerr << error + e.what() << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,38 @@ namespace MWRender
|
||||||
void insertCell(ESMS::CellStore<MWWorld::RefData> &cell, MWWorld::Environment& environment);
|
void insertCell(ESMS::CellStore<MWWorld::RefData> &cell, MWWorld::Environment& environment);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Exception-safe rendering
|
||||||
|
class Rendering
|
||||||
|
{
|
||||||
|
CellRenderImp& mCellRender;
|
||||||
|
bool mEnd;
|
||||||
|
|
||||||
|
// not implemented
|
||||||
|
Rendering (const Rendering&);
|
||||||
|
Rendering& operator= (const Rendering&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Rendering (CellRenderImp& cellRender, ESM::CellRef &ref)
|
||||||
|
: mCellRender (cellRender), mEnd (false)
|
||||||
|
{
|
||||||
|
mCellRender.insertBegin (ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Rendering()
|
||||||
|
{
|
||||||
|
if (!mEnd)
|
||||||
|
mCellRender.insertEnd (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string end (bool enable)
|
||||||
|
{
|
||||||
|
assert (!mEnd);
|
||||||
|
mEnd = true;
|
||||||
|
return mCellRender.insertEnd (enable);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
241
apps/openmw/mwrender/exterior.cpp
Normal file
241
apps/openmw/mwrender/exterior.cpp
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
#include "exterior.hpp"
|
||||||
|
|
||||||
|
#include <OgreEntity.h>
|
||||||
|
#include <OgreLight.h>
|
||||||
|
#include <OgreSceneNode.h>
|
||||||
|
#include <OgreCamera.h>
|
||||||
|
#include <OgreSceneManager.h>
|
||||||
|
|
||||||
|
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||||
|
#include "mwscene.hpp"
|
||||||
|
|
||||||
|
using namespace MWRender;
|
||||||
|
using namespace Ogre;
|
||||||
|
using namespace ESMS;
|
||||||
|
|
||||||
|
bool ExteriorCellRender::lightConst = false;
|
||||||
|
float ExteriorCellRender::lightConstValue = 0.0f;
|
||||||
|
|
||||||
|
bool ExteriorCellRender::lightLinear = true;
|
||||||
|
int ExteriorCellRender::lightLinearMethod = 1;
|
||||||
|
float ExteriorCellRender::lightLinearValue = 3;
|
||||||
|
float ExteriorCellRender::lightLinearRadiusMult = 1;
|
||||||
|
|
||||||
|
bool ExteriorCellRender::lightQuadratic = false;
|
||||||
|
int ExteriorCellRender::lightQuadraticMethod = 2;
|
||||||
|
float ExteriorCellRender::lightQuadraticValue = 16;
|
||||||
|
float ExteriorCellRender::lightQuadraticRadiusMult = 1;
|
||||||
|
|
||||||
|
bool ExteriorCellRender::lightOutQuadInLin = false;
|
||||||
|
|
||||||
|
// start inserting a new reference.
|
||||||
|
|
||||||
|
void ExteriorCellRender::insertBegin (ESM::CellRef &ref)
|
||||||
|
{
|
||||||
|
assert (!insert);
|
||||||
|
|
||||||
|
// Create and place scene node for this object
|
||||||
|
insert = base->createChildSceneNode();
|
||||||
|
|
||||||
|
const float *f = ref.pos.pos;
|
||||||
|
insert->setPosition(f[0], f[1], f[2]);
|
||||||
|
insert->setScale(ref.scale, ref.scale, ref.scale);
|
||||||
|
|
||||||
|
// Convert MW rotation to a quaternion:
|
||||||
|
f = ref.pos.rot;
|
||||||
|
|
||||||
|
// Rotate around X axis
|
||||||
|
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
||||||
|
|
||||||
|
// Rotate around Y axis
|
||||||
|
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
||||||
|
|
||||||
|
// Rotate around Z axis
|
||||||
|
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
||||||
|
|
||||||
|
// Rotates first around z, then y, then x
|
||||||
|
insert->setOrientation(xr*yr*zr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert a mesh related to the most recent insertBegin call.
|
||||||
|
|
||||||
|
void ExteriorCellRender::insertMesh(const std::string &mesh)
|
||||||
|
{
|
||||||
|
assert (insert);
|
||||||
|
|
||||||
|
NIFLoader::load(mesh);
|
||||||
|
MovableObject *ent = scene.getMgr()->createEntity(mesh);
|
||||||
|
insert->attachObject(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert a light related to the most recent insertBegin call.
|
||||||
|
void ExteriorCellRender::insertLight(float r, float g, float b, float radius)
|
||||||
|
{
|
||||||
|
assert (insert);
|
||||||
|
|
||||||
|
Ogre::Light *light = scene.getMgr()->createLight();
|
||||||
|
light->setDiffuseColour (r, g, b);
|
||||||
|
|
||||||
|
float cval=0.0f, lval=0.0f, qval=0.0f;
|
||||||
|
|
||||||
|
if(lightConst)
|
||||||
|
cval = lightConstValue;
|
||||||
|
if(!lightOutQuadInLin)
|
||||||
|
{
|
||||||
|
if(lightLinear)
|
||||||
|
radius *= lightLinearRadiusMult;
|
||||||
|
if(lightQuadratic)
|
||||||
|
radius *= lightQuadraticRadiusMult;
|
||||||
|
|
||||||
|
if(lightLinear)
|
||||||
|
lval = lightLinearValue / pow(radius, lightLinearMethod);
|
||||||
|
if(lightQuadratic)
|
||||||
|
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME:
|
||||||
|
// Do quadratic or linear, depending if we're in an exterior or interior
|
||||||
|
// cell, respectively. Ignore lightLinear and lightQuadratic.
|
||||||
|
}
|
||||||
|
|
||||||
|
light->setAttenuation(10*radius, cval, lval, qval);
|
||||||
|
|
||||||
|
insert->attachObject(light);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish inserting a new reference and return a handle to it.
|
||||||
|
|
||||||
|
std::string ExteriorCellRender::insertEnd (bool enable)
|
||||||
|
{
|
||||||
|
assert (insert);
|
||||||
|
|
||||||
|
std::string handle = insert->getName();
|
||||||
|
|
||||||
|
if (!enable)
|
||||||
|
insert->setVisible (false);
|
||||||
|
|
||||||
|
insert = 0;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure lighting according to cell
|
||||||
|
|
||||||
|
void ExteriorCellRender::configureAmbient()
|
||||||
|
{
|
||||||
|
ambientColor.setAsABGR (cell.cell->ambi.ambient);
|
||||||
|
setAmbientMode();
|
||||||
|
|
||||||
|
// Create a "sun" that shines light downwards. It doesn't look
|
||||||
|
// completely right, but leave it for now.
|
||||||
|
Ogre::Light *light = scene.getMgr()->createLight();
|
||||||
|
Ogre::ColourValue colour;
|
||||||
|
colour.setAsABGR (cell.cell->ambi.sunlight);
|
||||||
|
light->setDiffuseColour (colour);
|
||||||
|
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||||
|
light->setDirection(0,-1,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure fog according to cell
|
||||||
|
void ExteriorCellRender::configureFog()
|
||||||
|
{
|
||||||
|
Ogre::ColourValue color;
|
||||||
|
color.setAsABGR (cell.cell->ambi.fog);
|
||||||
|
|
||||||
|
float high = 4500 + 9000 * (1-cell.cell->ambi.fogDensity);
|
||||||
|
float low = 200;
|
||||||
|
|
||||||
|
scene.getMgr()->setFog (FOG_LINEAR, color, 0, low, high);
|
||||||
|
scene.getCamera()->setFarClipDistance (high + 10);
|
||||||
|
scene.getViewport()->setBackgroundColour (color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExteriorCellRender::setAmbientMode()
|
||||||
|
{
|
||||||
|
switch (ambientMode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
scene.getMgr()->setAmbientLight(ambientColor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
|
||||||
|
scene.getMgr()->setAmbientLight(0.7f*ambientColor + 0.3f*ColourValue(1,1,1));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
|
||||||
|
scene.getMgr()->setAmbientLight(ColourValue(1,1,1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExteriorCellRender::show()
|
||||||
|
{
|
||||||
|
base = scene.getRoot()->createChildSceneNode();
|
||||||
|
|
||||||
|
configureAmbient();
|
||||||
|
configureFog();
|
||||||
|
|
||||||
|
insertCell(cell, mEnvironment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExteriorCellRender::hide()
|
||||||
|
{
|
||||||
|
if(base)
|
||||||
|
base->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExteriorCellRender::destroy()
|
||||||
|
{
|
||||||
|
if(base)
|
||||||
|
{
|
||||||
|
base->removeAndDestroyAllChildren();
|
||||||
|
scene.getMgr()->destroySceneNode(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
base = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch through lighting modes.
|
||||||
|
|
||||||
|
void ExteriorCellRender::toggleLight()
|
||||||
|
{
|
||||||
|
if (ambientMode==2)
|
||||||
|
ambientMode = 0;
|
||||||
|
else
|
||||||
|
++ambientMode;
|
||||||
|
|
||||||
|
switch (ambientMode)
|
||||||
|
{
|
||||||
|
case 0: std::cout << "Setting lights to normal\n"; break;
|
||||||
|
case 1: std::cout << "Turning the lights up\n"; break;
|
||||||
|
case 2: std::cout << "Turning the lights to full\n"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAmbientMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExteriorCellRender::enable (const std::string& handle)
|
||||||
|
{
|
||||||
|
if (!handle.empty())
|
||||||
|
scene.getMgr()->getSceneNode (handle)->setVisible (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExteriorCellRender::disable (const std::string& handle)
|
||||||
|
{
|
||||||
|
if (!handle.empty())
|
||||||
|
scene.getMgr()->getSceneNode (handle)->setVisible (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExteriorCellRender::deleteObject (const std::string& handle)
|
||||||
|
{
|
||||||
|
if (!handle.empty())
|
||||||
|
{
|
||||||
|
Ogre::SceneNode *node = scene.getMgr()->getSceneNode (handle);
|
||||||
|
node->removeAndDestroyAllChildren();
|
||||||
|
scene.getMgr()->destroySceneNode (node);
|
||||||
|
}
|
||||||
|
}
|
114
apps/openmw/mwrender/exterior.hpp
Normal file
114
apps/openmw/mwrender/exterior.hpp
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef _GAME_RENDER_EXTERIOR_H
|
||||||
|
#define _GAME_RENDER_EXTERIOR_H
|
||||||
|
|
||||||
|
#include "cell.hpp"
|
||||||
|
#include "cellimp.hpp"
|
||||||
|
|
||||||
|
#include "OgreColourValue.h"
|
||||||
|
|
||||||
|
namespace Ogre
|
||||||
|
{
|
||||||
|
class SceneNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
class MWScene;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This class is responsible for inserting meshes and other
|
||||||
|
rendering objects from the given cell into the given rendering
|
||||||
|
scene.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ExteriorCellRender : public CellRender, private CellRenderImp
|
||||||
|
{
|
||||||
|
|
||||||
|
static bool lightConst;
|
||||||
|
static float lightConstValue;
|
||||||
|
|
||||||
|
static bool lightLinear;
|
||||||
|
static int lightLinearMethod;
|
||||||
|
static float lightLinearValue;
|
||||||
|
static float lightLinearRadiusMult;
|
||||||
|
|
||||||
|
static bool lightQuadratic;
|
||||||
|
static int lightQuadraticMethod;
|
||||||
|
static float lightQuadraticValue;
|
||||||
|
static float lightQuadraticRadiusMult;
|
||||||
|
|
||||||
|
static bool lightOutQuadInLin;
|
||||||
|
|
||||||
|
ESMS::CellStore<MWWorld::RefData> &cell;
|
||||||
|
MWWorld::Environment &mEnvironment;
|
||||||
|
MWScene &scene;
|
||||||
|
|
||||||
|
/// The scene node that contains all objects belonging to this
|
||||||
|
/// cell.
|
||||||
|
Ogre::SceneNode *base;
|
||||||
|
|
||||||
|
Ogre::SceneNode *insert;
|
||||||
|
|
||||||
|
// 0 normal, 1 more bright, 2 max
|
||||||
|
int ambientMode;
|
||||||
|
|
||||||
|
Ogre::ColourValue ambientColor;
|
||||||
|
|
||||||
|
/// start inserting a new reference.
|
||||||
|
virtual void insertBegin (ESM::CellRef &ref);
|
||||||
|
|
||||||
|
/// insert a mesh related to the most recent insertBegin call.
|
||||||
|
virtual void insertMesh(const std::string &mesh);
|
||||||
|
|
||||||
|
/// insert a light related to the most recent insertBegin call.
|
||||||
|
virtual void insertLight(float r, float g, float b, float radius);
|
||||||
|
|
||||||
|
/// finish inserting a new reference and return a handle to it.
|
||||||
|
virtual std::string insertEnd (bool Enable);
|
||||||
|
|
||||||
|
/// configure lighting according to cell
|
||||||
|
void configureAmbient();
|
||||||
|
|
||||||
|
/// configure fog according to cell
|
||||||
|
void configureFog();
|
||||||
|
|
||||||
|
void setAmbientMode();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ExteriorCellRender(ESMS::CellStore<MWWorld::RefData> &_cell, MWWorld::Environment& environment,
|
||||||
|
MWScene &_scene)
|
||||||
|
: cell(_cell), mEnvironment (environment), scene(_scene), base(NULL), insert(NULL), ambientMode (0) {}
|
||||||
|
|
||||||
|
virtual ~ExteriorCellRender() { destroy(); }
|
||||||
|
|
||||||
|
/// Make the cell visible. Load the cell if necessary.
|
||||||
|
virtual void show();
|
||||||
|
|
||||||
|
/// Remove the cell from rendering, but don't remove it from
|
||||||
|
/// memory.
|
||||||
|
virtual void hide();
|
||||||
|
|
||||||
|
/// Destroy all rendering objects connected with this cell.
|
||||||
|
virtual void destroy(); // comment by Zini: shouldn't this go into the destructor?
|
||||||
|
|
||||||
|
/// Switch through lighting modes.
|
||||||
|
void toggleLight();
|
||||||
|
|
||||||
|
/// Make the reference with the given handle visible.
|
||||||
|
virtual void enable (const std::string& handle);
|
||||||
|
|
||||||
|
/// Make the reference with the given handle invisible.
|
||||||
|
virtual void disable (const std::string& handle);
|
||||||
|
|
||||||
|
/// Remove the reference with the given handle permanently from the scene.
|
||||||
|
virtual void deleteObject (const std::string& handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -24,8 +24,6 @@ namespace MWRender
|
||||||
This class is responsible for inserting meshes and other
|
This class is responsible for inserting meshes and other
|
||||||
rendering objects from the given cell into the given rendering
|
rendering objects from the given cell into the given rendering
|
||||||
scene.
|
scene.
|
||||||
|
|
||||||
TODO FIXME: Doesn't do full cleanup yet.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class InteriorCellRender : public CellRender, private CellRenderImp
|
class InteriorCellRender : public CellRender, private CellRenderImp
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
#include "OgreCamera.h"
|
#include "OgreCamera.h"
|
||||||
#include "OgreTextureManager.h"
|
#include "OgreTextureManager.h"
|
||||||
|
|
||||||
|
#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include <components/esm/loadstat.hpp>
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
|
||||||
|
@ -36,7 +40,7 @@ MWScene::MWScene(OEngine::Render::OgreRenderer &_rend)
|
||||||
mRaySceneQuery = rend.getScene()->createRayQuery(Ray());
|
mRaySceneQuery = rend.getScene()->createRayQuery(Ray());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::string, float> MWScene::getFacedHandle()
|
std::pair<std::string, float> MWScene::getFacedHandle (MWWorld::World& world)
|
||||||
{
|
{
|
||||||
std::string handle = "";
|
std::string handle = "";
|
||||||
float distance = -1;
|
float distance = -1;
|
||||||
|
@ -57,10 +61,14 @@ std::pair<std::string, float> MWScene::getFacedHandle()
|
||||||
{
|
{
|
||||||
// there seem to be omnipresent objects like the caelum sky dom,
|
// there seem to be omnipresent objects like the caelum sky dom,
|
||||||
// the distance of these objects is always 0 so this if excludes these
|
// the distance of these objects is always 0 so this if excludes these
|
||||||
// TODO: Check if the object can be focused (ignore walls etc..
|
|
||||||
// in this state of openmw not possible)
|
|
||||||
if ( itr->movable && itr->distance >= 0.1)
|
if ( itr->movable && itr->distance >= 0.1)
|
||||||
{
|
{
|
||||||
|
// horrible hack to exclude statics. this must be removed as soon as a replacement for the
|
||||||
|
// AABB raycasting is implemented (we should not ignore statics)
|
||||||
|
MWWorld::Ptr ptr = world.getPtrViaHandle (itr->movable->getParentSceneNode()->getName());
|
||||||
|
if (ptr.getType()==typeid (ESM::Static))
|
||||||
|
break;
|
||||||
|
|
||||||
if ( nearest == result.end() ) //if no object is set
|
if ( nearest == result.end() ) //if no object is set
|
||||||
{
|
{
|
||||||
nearest = itr;
|
nearest = itr;
|
||||||
|
@ -80,4 +88,3 @@ std::pair<std::string, float> MWScene::getFacedHandle()
|
||||||
|
|
||||||
return std::pair<std::string, float>(handle, distance);
|
return std::pair<std::string, float>(handle, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,11 @@ namespace Ogre
|
||||||
class RaySceneQuery;
|
class RaySceneQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class World;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
/** Class responsible for Morrowind-specific interfaces to OGRE.
|
/** Class responsible for Morrowind-specific interfaces to OGRE.
|
||||||
|
@ -43,7 +48,7 @@ namespace MWRender
|
||||||
//pair<name, distance>
|
//pair<name, distance>
|
||||||
//name is empty and distance = -1 if there is no object which
|
//name is empty and distance = -1 if there is no object which
|
||||||
//can be faced
|
//can be faced
|
||||||
std::pair<std::string, float> getFacedHandle();
|
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
apps/openmw/mwrender/playerpos.cpp
Normal file
18
apps/openmw/mwrender/playerpos.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
#include "playerpos.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
void PlayerPos::setPos(float x, float y, float z, bool updateCamera)
|
||||||
|
{
|
||||||
|
mWorld.moveObject (getPlayer(), x, y, z);
|
||||||
|
|
||||||
|
if (updateCamera)
|
||||||
|
camera->setPosition (Ogre::Vector3 (
|
||||||
|
mPlayer.ref.pos.pos[0],
|
||||||
|
mPlayer.ref.pos.pos[2],
|
||||||
|
-mPlayer.ref.pos.pos[1]));
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,11 @@
|
||||||
#include "../mwworld/refdata.hpp"
|
#include "../mwworld/refdata.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class World;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
// This class keeps track of the player position. It takes care of
|
// This class keeps track of the player position. It takes care of
|
||||||
|
@ -18,31 +23,19 @@ namespace MWRender
|
||||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> mPlayer;
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> mPlayer;
|
||||||
MWWorld::Ptr::CellStore *mCellStore;
|
MWWorld::Ptr::CellStore *mCellStore;
|
||||||
Ogre::Camera *camera;
|
Ogre::Camera *camera;
|
||||||
|
MWWorld::World& mWorld;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlayerPos(Ogre::Camera *cam, const ESM::NPC *player) :
|
PlayerPos(Ogre::Camera *cam, const ESM::NPC *player, MWWorld::World& world) :
|
||||||
mCellStore (0), camera(cam)
|
mCellStore (0), camera(cam), mWorld (world)
|
||||||
{
|
{
|
||||||
mPlayer.base = player;
|
mPlayer.base = player;
|
||||||
mPlayer.ref.pos.pos[0] = mPlayer.ref.pos.pos[1] = mPlayer.ref.pos.pos[2] = 0;
|
mPlayer.ref.pos.pos[0] = mPlayer.ref.pos.pos[1] = mPlayer.ref.pos.pos[2] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the player position. Uses Morrowind coordinates.
|
// Set the player position. Uses Morrowind coordinates.
|
||||||
void setPos(float _x, float _y, float _z, bool updateCamera = false)
|
void setPos(float _x, float _y, float _z, bool updateCamera = false);
|
||||||
{
|
|
||||||
mPlayer.ref.pos.pos[0] = _x;
|
|
||||||
mPlayer.ref.pos.pos[1] = _y;
|
|
||||||
mPlayer.ref.pos.pos[2] = _z;
|
|
||||||
|
|
||||||
if (updateCamera)
|
|
||||||
camera->setPosition (Ogre::Vector3 (
|
|
||||||
mPlayer.ref.pos.pos[0],
|
|
||||||
mPlayer.ref.pos.pos[2],
|
|
||||||
mPlayer.ref.pos.pos[1]));
|
|
||||||
|
|
||||||
// TODO: Update sound listener
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCell (MWWorld::Ptr::CellStore *cellStore)
|
void setCell (MWWorld::Ptr::CellStore *cellStore)
|
||||||
{
|
{
|
||||||
mCellStore = cellStore;
|
mCellStore = cellStore;
|
||||||
|
@ -54,7 +47,6 @@ namespace MWRender
|
||||||
// orientation. After the call, the new position is returned.
|
// orientation. After the call, the new position is returned.
|
||||||
void moveRel(float &relX, float &relY, float &relZ)
|
void moveRel(float &relX, float &relY, float &relZ)
|
||||||
{
|
{
|
||||||
// TODO: Update mPlayer state
|
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
|
||||||
// Move camera relative to its own direction
|
// Move camera relative to its own direction
|
||||||
|
@ -75,7 +67,7 @@ namespace MWRender
|
||||||
// Set the position
|
// Set the position
|
||||||
setPos(relX, relY, relZ);
|
setPos(relX, relY, relZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr getPlayer()
|
MWWorld::Ptr getPlayer()
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr (&mPlayer, mCellStore);
|
MWWorld::Ptr ptr (&mPlayer, mCellStore);
|
||||||
|
|
|
@ -18,50 +18,79 @@ namespace MWScript
|
||||||
class OpCellChanged : public Interpreter::Opcode0
|
class OpCellChanged : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
InterpreterContext& context
|
InterpreterContext& context
|
||||||
= static_cast<InterpreterContext&> (runtime.getContext());
|
= static_cast<InterpreterContext&> (runtime.getContext());
|
||||||
|
|
||||||
runtime.push (context.getWorld().hasCellChanged() ? 1 : 0);
|
runtime.push (context.getWorld().hasCellChanged() ? 1 : 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class OpCOC : public Interpreter::Opcode0
|
class OpCOC : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
InterpreterContext& context
|
InterpreterContext& context
|
||||||
= static_cast<InterpreterContext&> (runtime.getContext());
|
= static_cast<InterpreterContext&> (runtime.getContext());
|
||||||
|
|
||||||
std::string cell = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string cell = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
ESM::Position pos;
|
ESM::Position pos;
|
||||||
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
|
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
|
||||||
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
||||||
context.getWorld().changeCell (cell, pos);
|
context.getWorld().changeCell (cell, pos);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OpCOE : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
InterpreterContext& context
|
||||||
|
= static_cast<InterpreterContext&> (runtime.getContext());
|
||||||
|
|
||||||
|
Interpreter::Type_Integer x = runtime[0].mInteger;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
Interpreter::Type_Integer y = runtime[0].mInteger;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
ESM::Position pos;
|
||||||
|
|
||||||
|
context.getWorld().indexToPosition (x, y, pos.pos[0], pos.pos[1]);
|
||||||
|
pos.pos[2] = 0;
|
||||||
|
|
||||||
|
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
||||||
|
|
||||||
|
context.getWorld().changeToExteriorCell (pos);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const int opcodeCellChanged = 0x2000000;
|
const int opcodeCellChanged = 0x2000000;
|
||||||
const int opcodeCOC = 0x2000026;
|
const int opcodeCOC = 0x2000026;
|
||||||
|
const int opcodeCOE = 0x200007c;
|
||||||
|
|
||||||
void registerExtensions (Compiler::Extensions& extensions)
|
void registerExtensions (Compiler::Extensions& extensions)
|
||||||
{
|
{
|
||||||
extensions.registerFunction ("cellchanged", 'l', "", opcodeCellChanged);
|
extensions.registerFunction ("cellchanged", 'l', "", opcodeCellChanged);
|
||||||
extensions.registerInstruction ("coc", "S", opcodeCOC);
|
extensions.registerInstruction ("coc", "S", opcodeCOC);
|
||||||
extensions.registerInstruction ("centeroncell", "S", opcodeCOC);
|
extensions.registerInstruction ("centeroncell", "S", opcodeCOC);
|
||||||
|
extensions.registerInstruction ("coe", "ll", opcodeCOE);
|
||||||
|
extensions.registerInstruction ("centeronexterior", "ll", opcodeCOE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
interpreter.installSegment5 (opcodeCellChanged, new OpCellChanged);
|
interpreter.installSegment5 (opcodeCellChanged, new OpCellChanged);
|
||||||
interpreter.installSegment5 (opcodeCOC, new OpCOC);
|
interpreter.installSegment5 (opcodeCOC, new OpCOC);
|
||||||
|
interpreter.installSegment5 (opcodeCOE, new OpCOE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,10 @@ op 0x2000078: GetItemCount
|
||||||
op 0x2000079: GetItemCount, explicit reference
|
op 0x2000079: GetItemCount, explicit reference
|
||||||
op 0x200007a: RemoveItem
|
op 0x200007a: RemoveItem
|
||||||
op 0x200007b: RemoveItem, explicit reference
|
op 0x200007b: RemoveItem, explicit reference
|
||||||
|
<<<<<<< HEAD:apps/openmw/mwscript/docs/vmformat.txt
|
||||||
|
op 0x200007c: COC
|
||||||
|
opcodes 0x200007d-0x3ffffff unused
|
||||||
|
=======
|
||||||
op 0x200007c: GetAiPackageDone
|
op 0x200007c: GetAiPackageDone
|
||||||
op 0x200007d: GetAiPackageDone, explicit reference
|
op 0x200007d: GetAiPackageDone, explicit reference
|
||||||
op 0x200007e-0x2000084: Enable Controls
|
op 0x200007e-0x2000084: Enable Controls
|
||||||
|
@ -95,3 +99,4 @@ op 0x2000085-0x200008b: Disable Controls
|
||||||
op 0x200008c: Unlock
|
op 0x200008c: Unlock
|
||||||
op 0x200008d: Unlock, explicit reference
|
op 0x200008d: Unlock, explicit reference
|
||||||
opcodes 0x200008e-0x3ffffff unused
|
opcodes 0x200008e-0x3ffffff unused
|
||||||
|
>>>>>>> master:apps/openmw/mwscript/docs/vmformat.txt
|
||||||
|
|
|
@ -13,6 +13,9 @@ namespace MWWorld
|
||||||
|
|
||||||
void ActionTeleportPlayer::execute (Environment& environment)
|
void ActionTeleportPlayer::execute (Environment& environment)
|
||||||
{
|
{
|
||||||
environment.mWorld->changeCell (mCellName, mPosition);
|
if (mCellName.empty())
|
||||||
|
environment.mWorld->changeToExteriorCell (mPosition);
|
||||||
|
else
|
||||||
|
environment.mWorld->changeCell (mCellName, mPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace MWWorld
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ActionTeleportPlayer (const std::string& cellName, const ESM::Position& position);
|
ActionTeleportPlayer (const std::string& cellName, const ESM::Position& position);
|
||||||
|
///< If cellName is empty, an exterior cell is asumed.
|
||||||
|
|
||||||
virtual void execute (Environment& environment);
|
virtual void execute (Environment& environment);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "../mwrender/sky.hpp"
|
#include "../mwrender/sky.hpp"
|
||||||
#include "../mwrender/interior.hpp"
|
#include "../mwrender/interior.hpp"
|
||||||
|
#include "../mwrender/exterior.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||||
|
|
||||||
|
@ -249,6 +250,66 @@ namespace MWWorld
|
||||||
throw std::runtime_error ("month out of range");
|
throw std::runtime_error ("month out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::removeScripts (Ptr::CellStore *cell)
|
||||||
|
{
|
||||||
|
ScriptList::iterator iter = mLocalScripts.begin();
|
||||||
|
|
||||||
|
while (iter!=mLocalScripts.end())
|
||||||
|
{
|
||||||
|
if (iter->second.getCell()==cell)
|
||||||
|
mLocalScripts.erase (iter++);
|
||||||
|
else
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::unloadCell (CellRenderCollection::iterator iter)
|
||||||
|
{
|
||||||
|
removeScripts (iter->first);
|
||||||
|
mEnvironment.mMechanicsManager->dropActors (iter->first);
|
||||||
|
iter->second->destroy();
|
||||||
|
mEnvironment.mSoundManager->stopSound (iter->first);
|
||||||
|
delete iter->second;
|
||||||
|
mActiveCells.erase (iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::loadCell (Ptr::CellStore *cell, MWRender::CellRender *render)
|
||||||
|
{
|
||||||
|
// register local scripts
|
||||||
|
insertInteriorScripts (*cell);
|
||||||
|
|
||||||
|
// This connects the cell data with the rendering scene.
|
||||||
|
std::pair<CellRenderCollection::iterator, bool> result =
|
||||||
|
mActiveCells.insert (std::make_pair (cell, render));
|
||||||
|
|
||||||
|
if (result.second)
|
||||||
|
{
|
||||||
|
// Load the cell and insert it into the renderer
|
||||||
|
result.first->second->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position)
|
||||||
|
{
|
||||||
|
mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2], true);
|
||||||
|
mPlayerPos->setCell (cell);
|
||||||
|
// TODO orientation
|
||||||
|
|
||||||
|
mEnvironment.mMechanicsManager->addActor (mPlayerPos->getPlayer());
|
||||||
|
mEnvironment.mMechanicsManager->watchActor (mPlayerPos->getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void World::adjustSky()
|
||||||
|
{
|
||||||
|
if (mSky)
|
||||||
|
{
|
||||||
|
toggleSky();
|
||||||
|
// TODO set weather
|
||||||
|
toggleSky();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
World::World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,
|
World::World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,
|
||||||
const std::string& master, bool newGame, Environment& environment)
|
const std::string& master, bool newGame, Environment& environment)
|
||||||
: mSkyManager (0), mScene (renderer), mPlayerPos (0), mCurrentCell (0), mGlobalVariables (0),
|
: mSkyManager (0), mScene (renderer), mPlayerPos (0), mCurrentCell (0), mGlobalVariables (0),
|
||||||
|
@ -263,7 +324,7 @@ namespace MWWorld
|
||||||
mEsm.open (masterPath.file_string());
|
mEsm.open (masterPath.file_string());
|
||||||
mStore.load (mEsm);
|
mStore.load (mEsm);
|
||||||
|
|
||||||
mPlayerPos = new MWRender::PlayerPos (mScene.getCamera(), mStore.npcs.find ("player"));
|
mPlayerPos = new MWRender::PlayerPos (mScene.getCamera(), mStore.npcs.find ("player"), *this);
|
||||||
|
|
||||||
// global variables
|
// global variables
|
||||||
mGlobalVariables = new Globals (mStore);
|
mGlobalVariables = new Globals (mStore);
|
||||||
|
@ -522,57 +583,114 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::changeCell (const std::string& cellName, const ESM::Position& position)
|
void World::changeCell (const std::string& cellName, const ESM::Position& position)
|
||||||
{
|
{
|
||||||
|
// remove active
|
||||||
|
CellRenderCollection::iterator active = mActiveCells.begin();
|
||||||
|
|
||||||
|
while (active!=mActiveCells.end())
|
||||||
|
{
|
||||||
|
unloadCell (active++);
|
||||||
|
}
|
||||||
|
|
||||||
// Load cell.
|
// Load cell.
|
||||||
mInteriors[cellName].loadInt (cellName, mStore, mEsm);
|
mInteriors[cellName].loadInt (cellName, mStore, mEsm);
|
||||||
Ptr::CellStore *cell = &mInteriors[cellName];
|
Ptr::CellStore *cell = &mInteriors[cellName];
|
||||||
|
|
||||||
|
loadCell (cell, new MWRender::InteriorCellRender (*cell, mEnvironment, mScene));
|
||||||
|
|
||||||
|
// adjust player
|
||||||
|
mCurrentCell = cell;
|
||||||
|
playerCellChange (cell, position);
|
||||||
|
|
||||||
|
// Sky system
|
||||||
|
adjustSky();
|
||||||
|
|
||||||
|
mCellChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::changeCell (int X, int Y, const ESM::Position& position)
|
||||||
|
{
|
||||||
// remove active
|
// remove active
|
||||||
CellRenderCollection::iterator active = mActiveCells.begin();
|
CellRenderCollection::iterator active = mActiveCells.begin();
|
||||||
|
|
||||||
if (active!=mActiveCells.end())
|
while (active!=mActiveCells.end())
|
||||||
{
|
{
|
||||||
mEnvironment.mMechanicsManager->dropActors (active->first);
|
if (!(active->first->cell->data.flags & ESM::Cell::Interior))
|
||||||
active->second->destroy();
|
{
|
||||||
mEnvironment.mSoundManager->stopSound (active->first);
|
if (std::abs (X-active->first->cell->data.gridX)<=1 &&
|
||||||
delete active->second;
|
std::abs (Y-active->first->cell->data.gridY)<=1)
|
||||||
mActiveCells.erase (active);
|
{
|
||||||
|
// keep cells within the new 3x3 grid
|
||||||
|
++active;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unloadCell (active++);
|
||||||
}
|
}
|
||||||
|
|
||||||
// register local scripts
|
// Load cells
|
||||||
mLocalScripts.clear(); // FIXME won't work with exteriors
|
for (int x=X-1; x<=X+1; ++x)
|
||||||
insertInteriorScripts (*cell);
|
for (int y=Y-1; y<=Y+1; ++y)
|
||||||
|
{
|
||||||
|
CellRenderCollection::iterator iter = mActiveCells.begin();
|
||||||
|
|
||||||
|
while (iter!=mActiveCells.end())
|
||||||
|
{
|
||||||
|
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
|
||||||
|
|
||||||
|
if (x==iter->first->cell->data.gridX &&
|
||||||
|
y==iter->first->cell->data.gridY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter==mActiveCells.end())
|
||||||
|
{
|
||||||
|
mExteriors[std::make_pair (x, y)].loadExt (x, y, mStore, mEsm);
|
||||||
|
Ptr::CellStore *cell = &mExteriors[std::make_pair (x, y)];
|
||||||
|
|
||||||
|
loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find current cell
|
||||||
|
CellRenderCollection::iterator iter = mActiveCells.begin();
|
||||||
|
|
||||||
|
while (iter!=mActiveCells.end())
|
||||||
|
{
|
||||||
|
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
|
||||||
|
|
||||||
|
if (X==iter->first->cell->data.gridX &&
|
||||||
|
Y==iter->first->cell->data.gridY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (iter!=mActiveCells.end());
|
||||||
|
|
||||||
|
mCurrentCell = iter->first;
|
||||||
|
|
||||||
// adjust player
|
// adjust player
|
||||||
mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2], true);
|
playerCellChange (&mExteriors[std::make_pair (X, Y)], position);
|
||||||
mPlayerPos->setCell (cell);
|
|
||||||
// TODO orientation
|
|
||||||
|
|
||||||
// This connects the cell data with the rendering scene.
|
|
||||||
std::pair<CellRenderCollection::iterator, bool> result =
|
|
||||||
mActiveCells.insert (std::make_pair (cell,
|
|
||||||
new MWRender::InteriorCellRender (*cell, mEnvironment, mScene)));
|
|
||||||
|
|
||||||
if (result.second)
|
|
||||||
{
|
|
||||||
// Load the cell and insert it into the renderer
|
|
||||||
result.first->second->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actors
|
|
||||||
mEnvironment.mMechanicsManager->addActor (mPlayerPos->getPlayer());
|
|
||||||
mEnvironment.mMechanicsManager->watchActor (mPlayerPos->getPlayer());
|
|
||||||
|
|
||||||
// Sky system
|
// Sky system
|
||||||
if (mSky)
|
adjustSky();
|
||||||
{
|
|
||||||
toggleSky();
|
|
||||||
// TODO set weather
|
|
||||||
toggleSky();
|
|
||||||
}
|
|
||||||
|
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::changeToExteriorCell (const ESM::Position& position)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
positionToIndex (position.pos[0], position.pos[1], x, y);
|
||||||
|
|
||||||
|
changeCell (x, y, position);
|
||||||
|
}
|
||||||
|
|
||||||
void World::markCellAsUnchanged()
|
void World::markCellAsUnchanged()
|
||||||
{
|
{
|
||||||
mCellChanged = false;
|
mCellChanged = false;
|
||||||
|
@ -580,7 +698,7 @@ namespace MWWorld
|
||||||
|
|
||||||
std::string World::getFacedHandle()
|
std::string World::getFacedHandle()
|
||||||
{
|
{
|
||||||
std::pair<std::string, float> result = mScene.getFacedHandle();
|
std::pair<std::string, float> result = mScene.getFacedHandle (*this);
|
||||||
|
|
||||||
if (result.first.empty() ||
|
if (result.first.empty() ||
|
||||||
result.second>getStore().gameSettings.find ("iMaxActivateDist")->i)
|
result.second>getStore().gameSettings.find ("iMaxActivateDist")->i)
|
||||||
|
@ -608,4 +726,56 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::moveObject (Ptr ptr, float x, float y, float z)
|
||||||
|
{
|
||||||
|
ptr.getCellRef().pos.pos[0] = x;
|
||||||
|
ptr.getCellRef().pos.pos[1] = y;
|
||||||
|
ptr.getCellRef().pos.pos[2] = z;
|
||||||
|
|
||||||
|
if (ptr==mPlayerPos->getPlayer())
|
||||||
|
{
|
||||||
|
if (mCurrentCell)
|
||||||
|
{
|
||||||
|
if (!(mCurrentCell->cell->data.flags & ESM::Cell::Interior))
|
||||||
|
{
|
||||||
|
// exterior -> adjust loaded cells
|
||||||
|
int cellX = 0;
|
||||||
|
int cellY = 0;
|
||||||
|
|
||||||
|
positionToIndex (x, y, cellX, cellY);
|
||||||
|
|
||||||
|
if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY)
|
||||||
|
{
|
||||||
|
changeCell (cellX, cellY, mPlayerPos->getPlayer().getCellRef().pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO cell change for non-player ref
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::indexToPosition (int cellX, int cellY, float &x, float &y) const
|
||||||
|
{
|
||||||
|
const int cellSize = 8192;
|
||||||
|
|
||||||
|
x = cellSize * cellX;
|
||||||
|
y = cellSize * cellY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::positionToIndex (float x, float y, int &cellX, int &cellY) const
|
||||||
|
{
|
||||||
|
const int cellSize = 8192;
|
||||||
|
|
||||||
|
cellX = static_cast<int> (x/cellSize);
|
||||||
|
|
||||||
|
if (x<0)
|
||||||
|
--cellX;
|
||||||
|
|
||||||
|
cellY = static_cast<int> (y/cellSize);
|
||||||
|
|
||||||
|
if (y<0)
|
||||||
|
--cellY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::vector<std::pair<std::string, Ptr> > ScriptList;
|
typedef std::list<std::pair<std::string, Ptr> > ScriptList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ namespace MWWorld
|
||||||
ESM::ESMReader mEsm;
|
ESM::ESMReader mEsm;
|
||||||
ESMS::ESMStore mStore;
|
ESMS::ESMStore mStore;
|
||||||
std::map<std::string, Ptr::CellStore> mInteriors;
|
std::map<std::string, Ptr::CellStore> mInteriors;
|
||||||
|
std::map<std::pair<int, int>, Ptr::CellStore> mExteriors;
|
||||||
ScriptList mLocalScripts;
|
ScriptList mLocalScripts;
|
||||||
MWWorld::Globals *mGlobalVariables;
|
MWWorld::Globals *mGlobalVariables;
|
||||||
bool mSky;
|
bool mSky;
|
||||||
|
@ -76,6 +77,16 @@ namespace MWWorld
|
||||||
|
|
||||||
int getDaysPerMonth (int month) const;
|
int getDaysPerMonth (int month) const;
|
||||||
|
|
||||||
|
void removeScripts (Ptr::CellStore *cell);
|
||||||
|
|
||||||
|
void unloadCell (CellRenderCollection::iterator iter);
|
||||||
|
|
||||||
|
void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render);
|
||||||
|
|
||||||
|
void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position);
|
||||||
|
|
||||||
|
void adjustSky();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& master,
|
World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& master,
|
||||||
|
@ -130,12 +141,24 @@ namespace MWWorld
|
||||||
void changeCell (const std::string& cellName, const ESM::Position& position);
|
void changeCell (const std::string& cellName, const ESM::Position& position);
|
||||||
///< works only for interior cells currently.
|
///< works only for interior cells currently.
|
||||||
|
|
||||||
|
void changeCell (int X, int Y, const ESM::Position& position);
|
||||||
|
|
||||||
|
void changeToExteriorCell (const ESM::Position& position);
|
||||||
|
|
||||||
void markCellAsUnchanged();
|
void markCellAsUnchanged();
|
||||||
|
|
||||||
std::string getFacedHandle();
|
std::string getFacedHandle();
|
||||||
///< Return handle of the object the player is looking at
|
///< Return handle of the object the player is looking at
|
||||||
|
|
||||||
void deleteObject (Ptr ptr);
|
void deleteObject (Ptr ptr);
|
||||||
|
|
||||||
|
void moveObject (Ptr ptr, float x, float y, float z);
|
||||||
|
|
||||||
|
void indexToPosition (int cellX, int cellY, float &x, float &y) const;
|
||||||
|
///< Convert cell numbers to position.
|
||||||
|
|
||||||
|
void positionToIndex (float x, float y, int &cellX, int &cellY) const;
|
||||||
|
///< Convert position to cell numbers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,14 @@ namespace ESMS
|
||||||
/** Ditto for exterior cell. */
|
/** Ditto for exterior cell. */
|
||||||
void loadExt(int X, int Y, const ESMStore &store, ESMReader &esm)
|
void loadExt(int X, int Y, const ESMStore &store, ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
std::cout << "loading exterior cell '" << X << ", " << Y << "'\n";
|
||||||
|
|
||||||
|
cell = store.cells.searchExt (X, Y);
|
||||||
|
|
||||||
|
if(cell == NULL)
|
||||||
|
throw std::runtime_error("Exterior cell not found");
|
||||||
|
|
||||||
|
loadRefs(store, esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -194,6 +194,21 @@ namespace ESMS
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Cell *searchExt (int x, int y) const
|
||||||
|
{
|
||||||
|
ExtCells::const_iterator it = extCells.find (x);
|
||||||
|
|
||||||
|
if (it==extCells.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ExtCellsCol::const_iterator it2 = it->second.find (y);
|
||||||
|
|
||||||
|
if (it2 == it->second.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return it2->second;
|
||||||
|
}
|
||||||
|
|
||||||
void load(ESMReader &esm, const std::string &id)
|
void load(ESMReader &esm, const std::string &id)
|
||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
Loading…
Reference in a new issue