From 407edc770c0005a9f179717fa9532d063b8ecbd8 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 11 Nov 2014 07:47:35 +1100 Subject: [PATCH] Added a simplistic snap to closest object or terrain. --- apps/opencs/view/render/mousestate.cpp | 25 +++++---- apps/opencs/view/world/physicssystem.cpp | 70 +++++++++++++++++++++++- apps/opencs/view/world/physicssystem.hpp | 6 +- 3 files changed, 89 insertions(+), 12 deletions(-) diff --git a/apps/opencs/view/render/mousestate.cpp b/apps/opencs/view/render/mousestate.cpp index ba668901f..8f254f08d 100644 --- a/apps/opencs/view/render/mousestate.cpp +++ b/apps/opencs/view/render/mousestate.cpp @@ -242,18 +242,23 @@ namespace CSVRender if(result.first != "" && // don't allow pathgrid points under the cursor !QString(refId.c_str()).contains(QRegExp("^Pathgrid"))) { - // drop (does not work if placed below the object/terrain) - // maybe look for closest object/terrain in both directions? - std::pair res = mPhysics->distToGround(pos, getCamera()); + // snap (defaults to 300 or less) + // FIXME: sticks to the underside of the object if snapping up + std::pair res = + mPhysics->distToClosest(pos, getCamera(), 500); if(res.first != "") + { pos.z -= res.second; - // FIXME: rather than just updating at the end, should - // consider providing visual feedback of terrain height - // while dragging the pathgrid point (maybe check whether - // the object is a pathgrid point at the begging and set - // a flag?) - placeObject(mGrabbedSceneNode, pos); // result.second - mParent->pathgridMoved(referenceId, pos); // result.second + // FIXME: rather than just updating at the end, should + // consider providing visual feedback of terrain height + // while dragging the pathgrid point (maybe check whether + // the object is a pathgrid point at the begging and set + // a flag?) + placeObject(mGrabbedSceneNode, pos); // result.second + mParent->pathgridMoved(referenceId, pos); // result.second + } + else + cancelDrag(); } else cancelDrag(); // FIXME: does not allow editing if terrain not visible diff --git a/apps/opencs/view/world/physicssystem.cpp b/apps/opencs/view/world/physicssystem.cpp index 55da2e221..358bb90ca 100644 --- a/apps/opencs/view/world/physicssystem.cpp +++ b/apps/opencs/view/world/physicssystem.cpp @@ -281,7 +281,7 @@ namespace CSVWorld } } - std::pair PhysicsSystem::distToGround(Ogre::Vector3 &position, + std::pair PhysicsSystem::distToGround(const Ogre::Vector3 &position, Ogre::Camera *camera) { btVector3 _from, _to; @@ -318,6 +318,74 @@ namespace CSVWorld return std::make_pair(result.first, 300000*result.second); } + // FIXME: remove code duplication + std::pair PhysicsSystem::distToClosest(const Ogre::Vector3 &position, + Ogre::Camera *camera, const float limit) + { + uint32_t visibilityMask = camera->getViewport()->getVisibilityMask(); + bool ignoreHeightMap = !(visibilityMask & (uint32_t)CSVRender::Element_Terrain); + bool ignoreObjects = !(visibilityMask & (uint32_t)CSVRender::Element_Reference); + bool ignorePathgrid = !(visibilityMask & (uint32_t)CSVRender::Element_Pathgrid); + + short mask = OEngine::Physic::CollisionType_Raycasting; + + btVector3 _from, _to; + _from = btVector3(position.x, position.y, position.z); + _to = btVector3(position.x, position.y, position.z-limit); + + std::pair resDown = std::make_pair("", -1); + std::vector > objectsDown = mEngine->rayTest2(_from, _to, mask); + + for (std::vector >::iterator it = objectsDown.begin(); + it != objectsDown.end(); ++it) + { + if(ignorePathgrid && QString((*it).second.c_str()).contains(QRegExp("^Pathgrid"))) + continue; + else if(ignoreObjects && QString((*it).second.c_str()).contains(QRegExp("^ref#"))) + continue; + else if(ignoreHeightMap && QString((*it).second.c_str()).contains(QRegExp("^Height"))) + continue; + + resDown = std::make_pair((*it).second, (*it).first); + break; + } + + _to = btVector3(position.x, position.y, position.z+limit); + std::pair resUp = std::make_pair("", -1); + std::vector > objectsUp = mEngine->rayTest2(_from, _to, mask); + + for (std::vector >::iterator it = objectsDown.begin(); + it != objectsDown.end(); ++it) + { + if(ignorePathgrid && QString((*it).second.c_str()).contains(QRegExp("^Pathgrid"))) + continue; + else if(ignoreObjects && QString((*it).second.c_str()).contains(QRegExp("^ref#"))) + continue; + else if(ignoreHeightMap && QString((*it).second.c_str()).contains(QRegExp("^Height"))) + continue; + + resUp = std::make_pair((*it).second, (*it).first); + break; + } + + if(resDown.first != "") + { + if(resUp.first != "") + { + if(fabs(resUp.second) < fabs(resDown.second)) + return std::make_pair(resUp.first, -limit*resUp.second); + else + return std::make_pair(resDown.first, limit*resDown.second); + } + else + return std::make_pair(resDown.first, limit*resDown.second); + } + else if(resUp.first != "") + return std::make_pair(resUp.first, -limit*resUp.second); + else + return std::make_pair("", -1); + } + std::string PhysicsSystem::refIdToSceneNode(std::string referenceId, Ogre::SceneManager *sceneMgr) { return mRefIdToSceneNode[referenceId][sceneMgr]; diff --git a/apps/opencs/view/world/physicssystem.hpp b/apps/opencs/view/world/physicssystem.hpp index f28272532..6436b8743 100644 --- a/apps/opencs/view/world/physicssystem.hpp +++ b/apps/opencs/view/world/physicssystem.hpp @@ -73,7 +73,11 @@ namespace CSVWorld std::pair castRay(float mouseX, float mouseY, Ogre::SceneManager *sceneMgr, Ogre::Camera *camera); - std::pair distToGround(Ogre::Vector3 &position, Ogre::Camera *camera); + std::pair distToGround(const Ogre::Vector3 &position, + Ogre::Camera *camera); + + std::pair distToClosest(const Ogre::Vector3 &position, + Ogre::Camera *camera, const float limit = 300.0f); std::string sceneNodeToRefId(std::string sceneNodeName);