1
0
Fork 1
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:
cc9cii 2014-11-08 15:51:45 +11:00
parent 0fd33e3198
commit f2ff2f2988
9 changed files with 272 additions and 26 deletions

View file

@ -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

View file

@ -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());

View file

@ -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));
}
}
}

View file

@ -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);
};
}

View file

@ -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();
}
}

View file

@ -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
};

View 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);
}
}

View 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

Binary file not shown.