mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-24 19:53:51 +00:00
Render pathgrid points and edges. Can move the points but the edges are not updated. Visibility mask does not work properly because pathgrid points are considered as objects by the physics engine.
This commit is contained in:
parent
0fd33e3198
commit
f2ff2f2988
9 changed files with 272 additions and 26 deletions
|
@ -83,6 +83,7 @@ opencs_units (view/render
|
|||
opencs_units_noqt (view/render
|
||||
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight
|
||||
lightingbright object cell terrainstorage textoverlay overlaymask overlaysystem mousestate
|
||||
pathgridpoint
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (view/render
|
||||
|
|
|
@ -308,6 +308,9 @@ std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
|
|||
// for font used in overlays
|
||||
Ogre::Root::getSingleton().addResourceLocation ((mResources / "mygui").string(),
|
||||
"FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
|
||||
// for pathgrid point nif
|
||||
Ogre::Root::getSingleton().addResourceLocation ((mResources / "materials").string(),
|
||||
"FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
|
||||
|
||||
if (!boost::filesystem::exists (mCfgMgr.getCachePath()))
|
||||
boost::filesystem::create_directories (mCfgMgr.getCachePath());
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreSceneNode.h>
|
||||
#include <OgreManualObject.h>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/esm/loadland.hpp>
|
||||
|
@ -10,10 +11,60 @@
|
|||
#include "../../model/world/idtable.hpp"
|
||||
#include "../../model/world/columns.hpp"
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/pathgrid.hpp"
|
||||
#include "../world/physicssystem.hpp"
|
||||
|
||||
#include "elements.hpp"
|
||||
#include "terrainstorage.hpp"
|
||||
#include "pathgridpoint.hpp"
|
||||
|
||||
// FIXME: redraw edges when pathgrid points are moved, added and deleted
|
||||
namespace CSVRender
|
||||
{
|
||||
// PLEASE NOTE: pathgrid edge code copied and adapted from mwrender/debugging
|
||||
static const std::string PG_LINE_MATERIAL = "pathgridLineMaterial";
|
||||
static const int POINT_MESH_BASE = 35;
|
||||
static const std::string DEBUGGING_GROUP = "debugging";
|
||||
}
|
||||
|
||||
void CSVRender::Cell::createGridMaterials()
|
||||
{
|
||||
if(Ogre::MaterialManager::getSingleton().getByName(PG_LINE_MATERIAL, DEBUGGING_GROUP).isNull())
|
||||
{
|
||||
Ogre::MaterialPtr lineMatPtr =
|
||||
Ogre::MaterialManager::getSingleton().create(PG_LINE_MATERIAL, DEBUGGING_GROUP);
|
||||
lineMatPtr->setReceiveShadows(false);
|
||||
lineMatPtr->getTechnique(0)->setLightingEnabled(true);
|
||||
lineMatPtr->getTechnique(0)->getPass(0)->setDiffuse(1,1,0,0);
|
||||
lineMatPtr->getTechnique(0)->getPass(0)->setAmbient(1,1,0);
|
||||
lineMatPtr->getTechnique(0)->getPass(0)->setSelfIllumination(1,1,0);
|
||||
}
|
||||
}
|
||||
|
||||
void CSVRender::Cell::destroyGridMaterials()
|
||||
{
|
||||
if(!Ogre::MaterialManager::getSingleton().getByName(PG_LINE_MATERIAL, DEBUGGING_GROUP).isNull())
|
||||
Ogre::MaterialManager::getSingleton().remove(PG_LINE_MATERIAL);
|
||||
}
|
||||
|
||||
Ogre::ManualObject *CSVRender::Cell::createPathgridEdge(const std::string &name,
|
||||
const Ogre::Vector3 &start, const Ogre::Vector3 &end)
|
||||
{
|
||||
Ogre::ManualObject *result = mSceneMgr->createManualObject(name);
|
||||
|
||||
result->begin(PG_LINE_MATERIAL, Ogre::RenderOperation::OT_LINE_LIST);
|
||||
|
||||
Ogre::Vector3 direction = (end - start);
|
||||
Ogre::Vector3 lineDisplacement = direction.crossProduct(Ogre::Vector3::UNIT_Z).normalisedCopy();
|
||||
// move lines up a little, so they will be less covered by meshes/landscape
|
||||
lineDisplacement = lineDisplacement * POINT_MESH_BASE + Ogre::Vector3(0, 0, 10);
|
||||
result->position(start + lineDisplacement);
|
||||
result->position(end + lineDisplacement);
|
||||
|
||||
result->end();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CSVRender::Cell::removeObject (const std::string& id)
|
||||
{
|
||||
|
@ -94,10 +145,28 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
|
|||
esmLand->mLandData->mHeights, mX, mY, 0, worldsize / (verts-1), verts);
|
||||
}
|
||||
}
|
||||
|
||||
addPathgrid();
|
||||
}
|
||||
|
||||
CSVRender::Cell::~Cell()
|
||||
{
|
||||
// destroy manual objects
|
||||
for(std::map<std::pair<int, int>, std::string>::iterator iter = mPgEdges.begin();
|
||||
iter != mPgEdges.end(); ++iter)
|
||||
{
|
||||
if(mSceneMgr->hasManualObject((*iter).second))
|
||||
mSceneMgr->destroyManualObject((*iter).second);
|
||||
}
|
||||
destroyGridMaterials();
|
||||
Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup(DEBUGGING_GROUP);
|
||||
|
||||
for(std::map<std::string, PathgridPoint *>::iterator iter (mPgPoints.begin());
|
||||
iter!=mPgPoints.end(); ++iter)
|
||||
{
|
||||
delete iter->second;
|
||||
}
|
||||
|
||||
mPhysics->removeHeightField(mSceneMgr, mX, mY);
|
||||
|
||||
for (std::map<std::string, Object *>::iterator iter (mObjects.begin());
|
||||
|
@ -236,3 +305,54 @@ float CSVRender::Cell::getTerrainHeightAt(const Ogre::Vector3 &pos) const
|
|||
else
|
||||
return -std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
void CSVRender::Cell::addPathgrid()
|
||||
{
|
||||
if(!Ogre::ResourceGroupManager::getSingleton().resourceGroupExists(DEBUGGING_GROUP))
|
||||
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(DEBUGGING_GROUP);
|
||||
createGridMaterials();
|
||||
|
||||
float worldsize = ESM::Land::REAL_SIZE;
|
||||
|
||||
CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgridCollection = mData.getPathgrids();
|
||||
int index = pathgridCollection.searchId(mId);
|
||||
if(index != -1)
|
||||
{
|
||||
const CSMWorld::Pathgrid pathgrid = pathgridCollection.getRecord(index).get();
|
||||
|
||||
std::vector<ESM::Pathgrid::Point>::const_iterator iter = pathgrid.mPoints.begin();
|
||||
for(index = 0; iter != pathgrid.mPoints.end(); ++iter, ++index)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Pathgrid_" << mId << "_" << index;
|
||||
std::string name = stream.str();
|
||||
|
||||
Ogre::Vector3 pos =
|
||||
Ogre::Vector3(worldsize*mX+(*iter).mX, worldsize*mY+(*iter).mY, (*iter).mZ);
|
||||
|
||||
mPgPoints.insert(std::make_pair(name, new PathgridPoint(name, mCellNode, pos, mPhysics)));
|
||||
}
|
||||
|
||||
for(ESM::Pathgrid::EdgeList::const_iterator it = pathgrid.mEdges.begin();
|
||||
it != pathgrid.mEdges.end();
|
||||
++it)
|
||||
{
|
||||
Ogre::SceneNode *node = mCellNode->createChildSceneNode();
|
||||
const ESM::Pathgrid::Edge &edge = *it;
|
||||
const ESM::Pathgrid::Point &p0 = pathgrid.mPoints[edge.mV0];
|
||||
const ESM::Pathgrid::Point &p1 = pathgrid.mPoints[edge.mV1];
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << mId << "_" << edge.mV0 << " " << edge.mV1;
|
||||
std::string name = stream.str();
|
||||
|
||||
Ogre::ManualObject *line = createPathgridEdge(name,
|
||||
Ogre::Vector3(worldsize*mX+p0.mX, worldsize*mY+p0.mY, p0.mZ),
|
||||
Ogre::Vector3(worldsize*mX+p1.mX, worldsize*mY+p1.mY, p1.mZ));
|
||||
line->setVisibilityFlags(Element_Pathgrid);
|
||||
node->attachObject(line);
|
||||
|
||||
mPgEdges.insert(std::make_pair(std::make_pair(edge.mV0, edge.mV1), name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace Ogre
|
|||
{
|
||||
class SceneManager;
|
||||
class SceneNode;
|
||||
class ManualObject;
|
||||
}
|
||||
|
||||
namespace CSMWorld
|
||||
|
@ -31,12 +32,16 @@ namespace CSVWorld
|
|||
|
||||
namespace CSVRender
|
||||
{
|
||||
class PathgridPoint;
|
||||
|
||||
class Cell
|
||||
{
|
||||
CSMWorld::Data& mData;
|
||||
std::string mId;
|
||||
Ogre::SceneNode *mCellNode;
|
||||
std::map<std::string, Object *> mObjects;
|
||||
std::map<std::string, PathgridPoint *> mPgPoints;
|
||||
std::map<std::pair<int, int>, std::string> mPgEdges;
|
||||
std::auto_ptr<Terrain::TerrainGrid> mTerrain;
|
||||
CSVWorld::PhysicsSystem *mPhysics;
|
||||
Ogre::SceneManager *mSceneMgr;
|
||||
|
@ -82,6 +87,15 @@ namespace CSVRender
|
|||
bool referenceAdded (const QModelIndex& parent, int start, int end);
|
||||
|
||||
float getTerrainHeightAt(const Ogre::Vector3 &pos) const;
|
||||
|
||||
private:
|
||||
|
||||
// for drawing pathgrid points & lines
|
||||
void createGridMaterials();
|
||||
void destroyGridMaterials();
|
||||
void addPathgrid();
|
||||
Ogre::ManualObject *createPathgridEdge(const std::string &name,
|
||||
const Ogre::Vector3 &start, const Ogre::Vector3 &end);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -206,6 +206,15 @@ namespace CSVRender
|
|||
mCurrentObj = result.first;
|
||||
|
||||
}
|
||||
// print some debug info
|
||||
std::string referenceId = mPhysics->sceneNodeToRefId(result.first);
|
||||
if(referenceId != "")
|
||||
std::cout << "result: " << referenceId << std::endl;
|
||||
else
|
||||
std::cout << "result: " << result.first << std::endl;
|
||||
std::cout << " hit pos "+ QString::number(result.second.x).toStdString()
|
||||
+ ", " + QString::number(result.second.y).toStdString()
|
||||
+ ", " + QString::number(result.second.z).toStdString() << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -213,15 +222,22 @@ namespace CSVRender
|
|||
{
|
||||
// final placement
|
||||
std::pair<bool, Ogre::Vector3> planeResult = mousePositionOnPlane(event->pos(), *mPlane);
|
||||
if(planeResult.first)
|
||||
if(planeResult.first && mGrabbedSceneNode != "")
|
||||
{
|
||||
if(mGrabbedSceneNode != "")
|
||||
{
|
||||
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
|
||||
Ogre::Vector3 pos = mOrigObjPos+planeRes.first*mOffset+planeResult.second-mOrigMousePos;
|
||||
// use the saved scene node name since the physics model has not moved yet
|
||||
std::string referenceId = mPhysics->sceneNodeToRefId(mGrabbedSceneNode);
|
||||
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
|
||||
Ogre::Vector3 pos = mOrigObjPos+planeRes.first*mOffset+planeResult.second-mOrigMousePos;
|
||||
// use the saved scene node name since the physics model has not moved yet
|
||||
std::string referenceId = mPhysics->sceneNodeToRefId(mGrabbedSceneNode);
|
||||
|
||||
if(QString(referenceId.c_str()).contains(QRegExp("^Pathgrid")))
|
||||
{
|
||||
// move pathgrid point, but don't save yet (need pathgrid
|
||||
// table feature & its data structure to be completed)
|
||||
// FIXME: need to signal PathgridPoint object of change
|
||||
placeObject(mGrabbedSceneNode, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
mParent->mDocument.getUndoStack().beginMacro (QObject::tr("Move Object"));
|
||||
mParent->mDocument.getUndoStack().push(new CSMWorld::ModifyCommand(*mIdTableModel,
|
||||
mIdTableModel->getModelIndex(referenceId, mColIndexPosX), pos.x));
|
||||
|
@ -230,22 +246,22 @@ namespace CSVRender
|
|||
mParent->mDocument.getUndoStack().push(new CSMWorld::ModifyCommand(*mIdTableModel,
|
||||
mIdTableModel->getModelIndex(referenceId, mColIndexPosZ), pos.z));
|
||||
mParent->mDocument.getUndoStack().endMacro();
|
||||
|
||||
// FIXME: highlight current object?
|
||||
//mCurrentObj = mGrabbedSceneNode; // FIXME: doesn't work?
|
||||
mCurrentObj = ""; // whether the object is selected
|
||||
|
||||
mMouseState = Mouse_Edit;
|
||||
|
||||
// reset states
|
||||
mCurrentMousePos = Ogre::Vector3(); // mouse pos to use in wheel event
|
||||
mOrigMousePos = Ogre::Vector3(); // starting pos of mouse in world space
|
||||
mOrigObjPos = Ogre::Vector3(); // starting pos of object in world space
|
||||
mGrabbedSceneNode = ""; // id of the object
|
||||
mOffset = 0.0f; // used for z-axis movement
|
||||
mOldPos = QPoint(0, 0); // to calculate relative movement of mouse
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: highlight current object?
|
||||
//mCurrentObj = mGrabbedSceneNode; // FIXME: doesn't work?
|
||||
mCurrentObj = ""; // whether the object is selected
|
||||
|
||||
mMouseState = Mouse_Edit;
|
||||
|
||||
// reset states
|
||||
mCurrentMousePos = Ogre::Vector3(); // mouse pos to use in wheel event
|
||||
mOrigMousePos = Ogre::Vector3(); // starting pos of mouse in world space
|
||||
mOrigObjPos = Ogre::Vector3(); // starting pos of object in world space
|
||||
mGrabbedSceneNode = ""; // id of the object
|
||||
mOffset = 0.0f; // used for z-axis movement
|
||||
mOldPos = QPoint(0, 0); // to calculate relative movement of mouse
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Mouse_Edit:
|
||||
|
@ -266,9 +282,9 @@ namespace CSVRender
|
|||
|
||||
void MouseState::mouseDoubleClickEvent (QMouseEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
//mPhysics->toggleDebugRendering(mSceneManager);
|
||||
//mParent->flagAsModified();
|
||||
//event->ignore();
|
||||
mPhysics->toggleDebugRendering(mSceneManager);
|
||||
mParent->flagAsModified();
|
||||
}
|
||||
|
||||
bool MouseState::wheelEvent (QWheelEvent *event)
|
||||
|
@ -401,6 +417,10 @@ namespace CSVRender
|
|||
std::pair<std::string, Ogre::Vector3> result = mPhysics->castRay(x, y, mSceneManager, getCamera());
|
||||
if(result.first != "")
|
||||
{
|
||||
std::cout << "result: " << result.first << std::endl;
|
||||
std::cout << " hit pos "+ QString::number(result.second.x).toStdString()
|
||||
+ ", " + QString::number(result.second.y).toStdString()
|
||||
+ ", " + QString::number(result.second.z).toStdString() << std::endl;
|
||||
// FIXME: is there a better way to distinguish terrain from objects?
|
||||
QString name = QString(result.first.c_str());
|
||||
if(name.contains(QRegExp("^HeightField")))
|
||||
|
@ -423,7 +443,7 @@ namespace CSVRender
|
|||
std::pair<std::string, Ogre::Vector3> result = mPhysics->castRay(x, y, mSceneManager, getCamera());
|
||||
if(result.first != "")
|
||||
{
|
||||
// NOTE: anything not terrain is assumed to be an object
|
||||
// NOTE: anything not terrain is assumed to be an object, e.g pathgrid points
|
||||
QString name = QString(result.first.c_str());
|
||||
if(!name.contains(QRegExp("^HeightField")))
|
||||
{
|
||||
|
@ -460,4 +480,17 @@ namespace CSVRender
|
|||
{
|
||||
return mParent->getCamera()->getViewport();
|
||||
}
|
||||
|
||||
void MouseState::placeObject(const std::string sceneNode, const Ogre::Vector3 &pos)
|
||||
{
|
||||
mSceneManager->getSceneNode(sceneNode)->setPosition(pos);
|
||||
|
||||
// update physics
|
||||
std::string refId = mPhysics->sceneNodeToRefId(sceneNode);
|
||||
|
||||
mPhysics->replaceObject(sceneNode, 1, pos, Ogre::Quaternion::IDENTITY);
|
||||
|
||||
// update all SceneWidgets and their SceneManagers
|
||||
updateSceneWidgets();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,8 @@ namespace CSVRender
|
|||
std::pair<Ogre::Vector3, Ogre::Vector3> planeAxis();
|
||||
void updateSceneWidgets();
|
||||
|
||||
void placeObject(const std::string sceneNode, const Ogre::Vector3 &pos); // FIXME
|
||||
|
||||
Ogre::Camera *getCamera(); // friend access
|
||||
Ogre::Viewport *getViewport(); // friend access
|
||||
};
|
||||
|
|
38
apps/opencs/view/render/pathgridpoint.cpp
Normal file
38
apps/opencs/view/render/pathgridpoint.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include "pathgridpoint.hpp"
|
||||
|
||||
#include <iostream> // FIXME
|
||||
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
//#include "../../model/world/pathgrid.hpp"
|
||||
#include "../world/physicssystem.hpp"
|
||||
|
||||
#include "elements.hpp"
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
PathgridPoint::PathgridPoint(const std::string &name,
|
||||
Ogre::SceneNode *cellNode, const Ogre::Vector3 &pos, CSVWorld::PhysicsSystem *physics)
|
||||
: mBase(cellNode), mPhysics(physics)
|
||||
{
|
||||
mBase = cellNode->createChildSceneNode();
|
||||
|
||||
mPgPoint = NifOgre::Loader::createObjects(mBase, "pathgrid_pt.nif");
|
||||
mPgPoint->setVisibilityFlags(Element_Pathgrid);
|
||||
mBase->setPosition(pos);
|
||||
|
||||
physics->addObject("pathgrid_pt.nif",
|
||||
mBase->getName(), name, 1, pos, Ogre::Quaternion::IDENTITY);
|
||||
}
|
||||
|
||||
PathgridPoint::~PathgridPoint()
|
||||
{
|
||||
mPgPoint.setNull();
|
||||
|
||||
mPhysics->removeObject(mBase->getName());
|
||||
|
||||
if (mBase)
|
||||
mBase->getCreator()->destroySceneNode(mBase);
|
||||
}
|
||||
}
|
35
apps/opencs/view/render/pathgridpoint.hpp
Normal file
35
apps/opencs/view/render/pathgridpoint.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef OPENCS_VIEW_PATHGRIDPOINT_H
|
||||
#define OPENCS_VIEW_PATHGRIDPOINT_H
|
||||
|
||||
#include <components/nifogre/ogrenifloader.hpp>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Vector3;
|
||||
class SceneNode;
|
||||
class SceneManager;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class PhysicsSystem;
|
||||
}
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
class PathgridPoint
|
||||
{
|
||||
CSVWorld::PhysicsSystem *mPhysics; // local copy
|
||||
NifOgre::ObjectScenePtr mPgPoint;
|
||||
Ogre::SceneNode *mBase;
|
||||
|
||||
public:
|
||||
|
||||
PathgridPoint(const std::string &name,
|
||||
Ogre::SceneNode *cellNode, const Ogre::Vector3 &pos, CSVWorld::PhysicsSystem *physics);
|
||||
|
||||
~PathgridPoint();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPENCS_VIEW_PATHGRIDPOINT_H
|
BIN
files/materials/pathgrid_pt.nif
Normal file
BIN
files/materials/pathgrid_pt.nif
Normal file
Binary file not shown.
Loading…
Reference in a new issue