mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-11-04 01:26:41 +00:00 
			
		
		
		
	very early implementation of exterior rendering
This commit is contained in:
		
							parent
							
								
									6583b66e82
								
							
						
					
					
						commit
						0111631ee9
					
				
					 8 changed files with 469 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -13,12 +13,14 @@ set(GAMEREND
 | 
			
		|||
    mwrender/mwscene.cpp
 | 
			
		||||
    mwrender/cellimp.cpp
 | 
			
		||||
    mwrender/interior.cpp
 | 
			
		||||
    mwrender/exterior.cpp
 | 
			
		||||
    mwrender/sky.cpp)
 | 
			
		||||
set(GAMEREND_HEADER
 | 
			
		||||
    mwrender/cell.hpp
 | 
			
		||||
    mwrender/cellimp.hpp
 | 
			
		||||
    mwrender/mwscene.hpp
 | 
			
		||||
    mwrender/interior.hpp
 | 
			
		||||
    mwrender/exterior.hpp
 | 
			
		||||
    mwrender/playerpos.hpp
 | 
			
		||||
    mwrender/sky.hpp)
 | 
			
		||||
source_group(apps\\openmw\\mwrender FILES ${GAMEREND} ${GAMEREND_HEADER})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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
 | 
			
		||||
     rendering objects from the given cell into the given rendering
 | 
			
		||||
     scene.
 | 
			
		||||
 | 
			
		||||
     TODO FIXME: Doesn't do full cleanup yet.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  class InteriorCellRender : public CellRender, private CellRenderImp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,50 +18,79 @@ namespace MWScript
 | 
			
		|||
        class OpCellChanged : public Interpreter::Opcode0
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime& runtime)
 | 
			
		||||
                {
 | 
			
		||||
                    InterpreterContext& context
 | 
			
		||||
                        = static_cast<InterpreterContext&> (runtime.getContext());
 | 
			
		||||
                        
 | 
			
		||||
 | 
			
		||||
                    runtime.push (context.getWorld().hasCellChanged() ? 1 : 0);
 | 
			
		||||
                } 
 | 
			
		||||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class OpCOC : public Interpreter::Opcode0
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime& runtime)
 | 
			
		||||
                {
 | 
			
		||||
                    InterpreterContext& context
 | 
			
		||||
                        = static_cast<InterpreterContext&> (runtime.getContext());
 | 
			
		||||
                        
 | 
			
		||||
 | 
			
		||||
                    std::string cell = runtime.getStringLiteral (runtime[0].mInteger);
 | 
			
		||||
                    runtime.pop();                        
 | 
			
		||||
                        
 | 
			
		||||
                    runtime.pop();
 | 
			
		||||
 | 
			
		||||
                    ESM::Position pos;
 | 
			
		||||
                    pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
 | 
			
		||||
                    pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
 | 
			
		||||
                    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();
 | 
			
		||||
 | 
			
		||||
                    const int cellSize = 8192;
 | 
			
		||||
 | 
			
		||||
                    ESM::Position pos;
 | 
			
		||||
                    pos.pos[0] = cellSize * x;
 | 
			
		||||
                    pos.pos[1] = cellSize * y;
 | 
			
		||||
                    pos.pos[2] = 0;
 | 
			
		||||
                    pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
 | 
			
		||||
                    context.getWorld().changeToExteriorCell (pos);
 | 
			
		||||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const int opcodeCellChanged = 0x2000000;
 | 
			
		||||
        const int opcodeCOC = 0x2000026;
 | 
			
		||||
    
 | 
			
		||||
        const int opcodeCOE = 0x200007c;
 | 
			
		||||
 | 
			
		||||
        void registerExtensions (Compiler::Extensions& extensions)
 | 
			
		||||
        {
 | 
			
		||||
            extensions.registerFunction ("cellchanged", 'l', "", opcodeCellChanged);
 | 
			
		||||
            extensions.registerInstruction ("coc", "S", opcodeCOC);
 | 
			
		||||
            extensions.registerInstruction ("centeroncell", "S", opcodeCOC);
 | 
			
		||||
            extensions.registerInstruction ("coe", "ll", opcodeCOE);
 | 
			
		||||
            extensions.registerInstruction ("centeronexterior", "ll", opcodeCOE);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        void installOpcodes (Interpreter::Interpreter& interpreter)
 | 
			
		||||
        {
 | 
			
		||||
            interpreter.installSegment5 (opcodeCellChanged, new OpCellChanged);
 | 
			
		||||
            interpreter.installSegment5 (opcodeCOC, new OpCOC);
 | 
			
		||||
            interpreter.installSegment5 (opcodeCOE, new OpCOE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,4 +83,5 @@ op 0x2000078: GetItemCount
 | 
			
		|||
op 0x2000079: GetItemCount, explicit reference
 | 
			
		||||
op 0x200007a: RemoveItem
 | 
			
		||||
op 0x200007b: RemoveItem, explicit reference
 | 
			
		||||
opcodes 0x200007c-0x3ffffff unused
 | 
			
		||||
op 0x200007c: COC
 | 
			
		||||
opcodes 0x200007d-0x3ffffff unused
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
 | 
			
		||||
#include "../mwrender/sky.hpp"
 | 
			
		||||
#include "../mwrender/interior.hpp"
 | 
			
		||||
#include "../mwrender/exterior.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwmechanics/mechanicsmanager.hpp"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -573,6 +574,69 @@ namespace MWWorld
 | 
			
		|||
        mCellChanged = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void World::changeCell (int X, int Y, const ESM::Position& position)
 | 
			
		||||
    {
 | 
			
		||||
        // Load cell.
 | 
			
		||||
        mExteriors[std::make_pair (X, Y)].loadExt (X, Y, mStore, mEsm);
 | 
			
		||||
        Ptr::CellStore *cell = &mExteriors[std::make_pair (X, Y)];
 | 
			
		||||
 | 
			
		||||
        // remove active
 | 
			
		||||
        CellRenderCollection::iterator active = mActiveCells.begin();
 | 
			
		||||
 | 
			
		||||
        if (active!=mActiveCells.end())
 | 
			
		||||
        {
 | 
			
		||||
            mEnvironment.mMechanicsManager->dropActors (active->first);
 | 
			
		||||
            active->second->destroy();
 | 
			
		||||
            mEnvironment.mSoundManager->stopSound (active->first);
 | 
			
		||||
            delete active->second;
 | 
			
		||||
            mActiveCells.erase (active);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // register local scripts
 | 
			
		||||
        mLocalScripts.clear(); // FIXME won't work with exteriors
 | 
			
		||||
        insertInteriorScripts (*cell);
 | 
			
		||||
 | 
			
		||||
        // adjust player
 | 
			
		||||
        mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2], true);
 | 
			
		||||
        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::ExteriorCellRender (*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
 | 
			
		||||
        if (mSky)
 | 
			
		||||
        {
 | 
			
		||||
            toggleSky();
 | 
			
		||||
            // TODO set weather
 | 
			
		||||
            toggleSky();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mCellChanged = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void World::changeToExteriorCell (const ESM::Position& position)
 | 
			
		||||
    {
 | 
			
		||||
        const int cellSize = 8192;
 | 
			
		||||
 | 
			
		||||
        int x = static_cast<int> (position.pos[0] / cellSize);
 | 
			
		||||
        int y = static_cast<int> (position.pos[1] / cellSize);
 | 
			
		||||
 | 
			
		||||
        changeCell (x, y, position);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void World::markCellAsUnchanged()
 | 
			
		||||
    {
 | 
			
		||||
        mCellChanged = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,7 @@ namespace MWWorld
 | 
			
		|||
            ESM::ESMReader mEsm;
 | 
			
		||||
            ESMS::ESMStore mStore;
 | 
			
		||||
            std::map<std::string, Ptr::CellStore> mInteriors;
 | 
			
		||||
            std::map<std::pair<int, int>, Ptr::CellStore> mExteriors;
 | 
			
		||||
            ScriptList mLocalScripts;
 | 
			
		||||
            MWWorld::Globals *mGlobalVariables;
 | 
			
		||||
            bool mSky;
 | 
			
		||||
| 
						 | 
				
			
			@ -130,6 +131,10 @@ namespace MWWorld
 | 
			
		|||
            void changeCell (const std::string& cellName, const ESM::Position& position);
 | 
			
		||||
            ///< works only for interior cells currently.
 | 
			
		||||
 | 
			
		||||
            void changeCell (int X, int Y, const ESM::Position& position);
 | 
			
		||||
 | 
			
		||||
            void changeToExteriorCell (const ESM::Position& position);
 | 
			
		||||
 | 
			
		||||
            void markCellAsUnchanged();
 | 
			
		||||
 | 
			
		||||
            std::string getFacedHandle();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue