Aye, please do!deadvirus wrote:If you think it would be useful, I could post it here.
You won't believe how many times people have been asking how to do that..
Aye, please do!deadvirus wrote:If you think it would be useful, I could post it here.
ARTIFEX TERRA 3D - Artist-friendly, free and easy WYSIWYG realtime outdoor scene Editor & Painter
New loader now with Ogre::Terrain support: Addons for Artifex on SourceForge
MOC - Minimal Ogre Collision & Mousepicking
Simple TerrainMaterialGenerator for the use of standard Ogre material with Ogre::Terrain
Support me on Patreon
Code: Select all
void CollisionTools::GetMeshInformation(const Ogre::MeshPtr mesh,
size_t &vertex_count,
Ogre::Vector3* &vertices,
size_t &index_count,
Ogre::uint32* &indices,
unsigned short* &indexToSubMesh,
const Ogre::Vector3 &position,
const Ogre::Quaternion &orient,
const Ogre::Vector3 &scale)
{
bool added_shared = false;
size_t current_offset = 0;
size_t shared_offset = 0;
size_t next_offset = 0;
size_t index_offset = 0;
size_t indexSMesh_offset = 0;
vertex_count = index_count = 0;
// Calculate how many vertices and indices we're going to need
for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = mesh->getSubMesh( i );
// We only need to add the shared vertices once
if(submesh->useSharedVertices)
{
if( !added_shared )
{
vertex_count += mesh->sharedVertexData->vertexCount;
added_shared = true;
}
}
else
{
vertex_count += submesh->vertexData->vertexCount;
}
// Add the indices
index_count += submesh->indexData->indexCount;
}
// Allocate space for the vertices and indices
vertices = new Ogre::Vector3[vertex_count];
indices = new Ogre::uint32[index_count];
indexToSubMesh = new unsigned short[index_count];
added_shared = false;
// Run through the submeshes again, adding the data into the arrays
for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = mesh->getSubMesh(i);
Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
//set this submesh number to its indices
for(size_t indexAddC = indexSMesh_offset;
indexAddC < indexSMesh_offset + submesh->indexData->indexCount; indexAddC++)
{
indexToSubMesh[indexAddC] = i;
}
indexSMesh_offset += submesh->indexData->indexCount;
if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
{
if(submesh->useSharedVertices)
{
added_shared = true;
shared_offset = current_offset;
}
const Ogre::VertexElement* posElem =
vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
Ogre::HardwareVertexBufferSharedPtr vbuf =
vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
unsigned char* vertex =
static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
// There is _no_ baseVertexPointerToElement() which takes an Ogre::Ogre::Real or a double
// as second argument. So make it float, to avoid trouble when Ogre::Ogre::Real will
// be comiled/typedefed as double:
// Ogre::Ogre::Real* pOgre::Real;
float* pReal;
for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
{
posElem->baseVertexPointerToElement(vertex, &pReal);
Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
vertices[current_offset + j] = (orient * (pt * scale)) + position;
}
vbuf->unlock();
next_offset += vertex_data->vertexCount;
}
Ogre::IndexData* index_data = submesh->indexData;
size_t numTris = index_data->indexCount / 3;
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
Ogre::uint32* pLong = static_cast<Ogre::uint32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
if ( use32bitindexes )
{
for ( size_t k = 0; k < numTris*3; ++k)
{
indices[index_offset++] = pLong[k] + static_cast<Ogre::uint32>(offset);
}
}
else
{
for ( size_t k = 0; k < numTris*3; ++k)
{
indices[index_offset++] = static_cast<Ogre::uint32>(pShort[k]) +
static_cast<Ogre::uint32>(offset);
}
}
ibuf->unlock();
current_offset = next_offset;
}
}
Code: Select all
bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result, Ogre::Entity* &target,float &closest_distance, unsigned short &submeshNumber, const Ogre::uint32 queryMask)
{
target = NULL;
// check we are initialised
if (mRaySceneQuery != NULL)
{
// create a query object
mRaySceneQuery->setRay(ray);
mRaySceneQuery->setSortByDistance(true);
mRaySceneQuery->setQueryMask(queryMask);
// execute the query, returns a vector of hits
if (mRaySceneQuery->execute().size() <= 0)
{
// raycast did not hit an objects bounding box
return (false);
}
}
else
{
//LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG;
return (false);
}
// at this point we have raycast to a series of different objects bounding boxes.
// we need to test these different objects to see which is the first polygon hit.
// there are some minor optimizations (distance based) that mean we wont have to
// check all of the objects most of the time, but the worst case scenario is that
// we need to test every triangle of every object.
//Ogre::Ogre::Real closest_distance = -1.0f;
closest_distance = -1.0f;
Ogre::Vector3 closest_result;
Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults();
for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++)
{
// stop checking if we have found a raycast hit that is closer
// than all remaining entities
if ((closest_distance >= 0.0f) &&
(closest_distance < query_result[qr_idx].distance))
{
break;
}
// only check this result if its a hit against an entity
if ((query_result[qr_idx].movable != NULL) &&
(query_result[qr_idx].movable->getMovableType().compare("Entity") == 0))
{
// get the entity to check
Ogre::Entity *pentity = static_cast<Ogre::Entity*>(query_result[qr_idx].movable);
// mesh data to retrieve
size_t vertex_count;
size_t index_count;
Ogre::Vector3 *vertices;
Ogre::uint32 *indices;
unsigned short *indexToSubmesh;
// get the mesh information
GetMeshInformation(((Ogre::Entity*)pentity)->getMesh(), vertex_count, vertices, index_count, indices, indexToSubmesh,
pentity->getParentNode()->_getDerivedPosition(),
pentity->getParentNode()->_getDerivedOrientation(),
pentity->getParentNode()->_getDerivedScale());
// test for hitting individual triangles on the mesh
bool new_closest_found = false;
size_t closest_i;
for (size_t i = 0; i < index_count; i += 3)
{
// check for a hit against this triangle
std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]],
vertices[indices[i+1]], vertices[indices[i+2]], true, false);
// if it was a hit check if its the closest
if (hit.first)
{
if ((closest_distance < 0.0f) ||
(hit.second < closest_distance))
{
// this is the closest so far, save it off
closest_distance = hit.second;
new_closest_found = true;
closest_i = i;
}
}
}
// free the verticies and indicies memory
delete[] vertices;
delete[] indices;
// if we found a new closest raycast for this object, update the
// closest_result before moving on to the next object.
if (new_closest_found)
{
target = pentity;
closest_result = ray.getPoint(closest_distance);
//get the index of the submesh
submeshNumber = indexToSubmesh[closest_i];
}
}
}
// return the result
if (closest_distance >= 0.0f)
{
// raycast success
result = closest_result;
return (true);
}
else
{
// raycast failed
return (false);
}
}
ARTIFEX TERRA 3D - Artist-friendly, free and easy WYSIWYG realtime outdoor scene Editor & Painter
New loader now with Ogre::Terrain support: Addons for Artifex on SourceForge
MOC - Minimal Ogre Collision & Mousepicking
Simple TerrainMaterialGenerator for the use of standard Ogre material with Ogre::Terrain
Support me on Patreon
ARTIFEX TERRA 3D - Artist-friendly, free and easy WYSIWYG realtime outdoor scene Editor & Painter
New loader now with Ogre::Terrain support: Addons for Artifex on SourceForge
MOC - Minimal Ogre Collision & Mousepicking
Simple TerrainMaterialGenerator for the use of standard Ogre material with Ogre::Terrain
Support me on Patreon
Code: Select all
bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result, Ogre::MovableObject* &target,float &closest_distance, Ogre::Vector3 &normal, const Ogre::uint32 queryMask)
{
target = NULL;
// check we are initialised
if (mRaySceneQuery != NULL)
{
// create a query object
mRaySceneQuery->setRay(ray);
mRaySceneQuery->setSortByDistance(true);
mRaySceneQuery->setQueryMask(queryMask);
// execute the query, returns a vector of hits
if (mRaySceneQuery->execute().size() <= 0)
{
// raycast did not hit an objects bounding box
return (false);
}
}
else
{
//LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG;
return (false);
}
// at this point we have raycast to a series of different objects bounding boxes.
// we need to test these different objects to see which is the first polygon hit.
// there are some minor optimizations (distance based) that mean we wont have to
// check all of the objects most of the time, but the worst case scenario is that
// we need to test every triangle of every object.
//Ogre::Ogre::Real closest_distance = -1.0f;
closest_distance = -1.0f;
Ogre::Vector3 closest_result;
Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults();
for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++)
{
// stop checking if we have found a raycast hit that is closer
// than all remaining entities
if ((closest_distance >= 0.0f) &&
(closest_distance < query_result[qr_idx].distance))
{
break;
}
// only check this result if its a hit against an entity
if ((query_result[qr_idx].movable != NULL) &&
(query_result[qr_idx].movable->getMovableType().compare("Entity") == 0))
{
// get the entity to check
Ogre::MovableObject *pentity = static_cast<Ogre::MovableObject*>(query_result[qr_idx].movable);
Ogre::Vector3 pnormal;
// mesh data to retrieve
size_t vertex_count;
size_t index_count;
Ogre::Vector3 *vertices;
Ogre::uint32 *indices;
// get the mesh information
GetMeshInformation(((Ogre::Entity*)pentity)->getMesh(), vertex_count, vertices, index_count, indices,
pentity->getParentNode()->_getDerivedPosition(),
pentity->getParentNode()->_getDerivedOrientation(),
pentity->getParentNode()->_getDerivedScale());
// test for hitting individual triangles on the mesh
bool new_closest_found = false;
for (size_t i = 0; i < index_count; i += 3)
{
// check for a hit against this triangle
std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]],
vertices[indices[i+1]], vertices[indices[i+2]], true, false);
// if it was a hit check if its the closest
if (hit.first)
{
if ((closest_distance < 0.0f) ||
(hit.second < closest_distance))
{
// this is the closest so far, save it off
closest_distance = hit.second;
new_closest_found = true;
//calculate normal
Ogre::Vector3 vec1OnPlane = vertices[indices[i]] - vertices[indices[i+1]];
Ogre::Vector3 vec2OnPlane = vertices[indices[i]] - vertices[indices[i+2]];
pnormal = vec1OnPlane.crossProduct(vec2OnPlane);
}
}
}
// free the verticies and indicies memory
delete[] vertices;
delete[] indices;
// if we found a new closest raycast for this object, update the
// closest_result before moving on to the next object.
if (new_closest_found)
{
target = pentity;
closest_result = ray.getPoint(closest_distance);
normal = pnormal.normalisedCopy();
}
}
}
// return the result
if (closest_distance >= 0.0f)
{
// raycast success
result = closest_result;
return (true);
}
else
{
// raycast failed
return (false);
}
}
ARTIFEX TERRA 3D - Artist-friendly, free and easy WYSIWYG realtime outdoor scene Editor & Painter
New loader now with Ogre::Terrain support: Addons for Artifex on SourceForge
MOC - Minimal Ogre Collision & Mousepicking
Simple TerrainMaterialGenerator for the use of standard Ogre material with Ogre::Terrain
Support me on Patreon
No problem! I am the one who has to say thanks for MOCNauk wrote:Good work deadvirus and thanks for sharing, I like it and will add it.
Code: Select all
#include "Gui.h"
Gui::Gui() :
root(),
sceneMgr(0),
window(0),
GuiSystem(0),
ois(0),
mouse(0),
exitgame(false)
{
//mLastTime = mTimer.getMilliseconds();
//
//mTimer1 = 0.0;
//mCollision = true;
}
Gui::~Gui()
{
delete root;
delete GuiSystem;
//delete mCollisionTools;
}
bool Gui::Start()
{
if (!InitOgre())
return false;
if (!InitOIS())
return false;
movement = 0;
yaw = 0;
while(!exitgame)
{
WindowEventUtilities::messagePump();
mouse->capture();
keyboard->capture();
root->renderOneFrame();
mShipNode->translate(Ogre::Vector3(0,0,movement),Ogre::SceneNode::TS_LOCAL);
mShipNode->yaw(Degree( yaw ) );
}
}
bool Gui::InitOgre()
{
root = new Root;
root->loadPlugin("RenderSystem_GL_d");
RenderSystemList *rs = root->getAvailableRenderers();
if(rs&&rs->size()&&rs->at(0)->getName().compare("RenderSystem_GL"))
{
RenderSystem * r=rs->at(0);
root->setRenderSystem(r);
r->setConfigOption("Full Screen","No");
r->setConfigOption("Video Mode","800 x 600 @ 16-bit colour");
}
else
{
return false;
}
ResourceGroupManager &resources=ResourceGroupManager::getSingleton();
resources.addResourceLocation("data","FileSystem");
//resources.addResourceLocation("resource","FileSystem");
resources.initialiseAllResourceGroups();
window = root->initialise(true, "Simple Ogre App");
sceneMgr = root->createSceneManager(ST_GENERIC);
//////added code//////////////////////////////////////////////////////
Ogre::WindowEventUtilities::addWindowEventListener(window, this);
// init the collision handler
mCollisionTools = new CollisionTools(sceneMgr);
/////////////////////////////added code///////////////////////////////
//Create our entity
sceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
mShip = sceneMgr->createEntity("ship", "tiger0.mesh");
mShip->setCastShadows(true);
mShipNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
mShipNode->attachObject(mShip);
mShipNode->setPosition(Ogre::Vector3(0,-100,0));
mFuel = sceneMgr->createEntity("fuel", "Box16.mesh");
mFuel->setCastShadows(true);
mFuel->setQueryFlags(ENTITY_MASK);
mFuelNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
mFuelNode->attachObject(mFuel);
mFuelNode->setPosition(Ogre::Vector3(0,-100,0));
mCube = sceneMgr->createEntity("cube", "pCube1.mesh");
mCubeNode = sceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(0,400,0));
mCubeNode->attachObject(mCube);
mCubeNode->scale( 100000,10000,100000 );
cam = sceneMgr->createCamera("SimpleCamera");
cam->setPosition(Ogre::Vector3(0.0f,50.0f,-400.0f));
cam->lookAt(Ogre::Vector3(0.0f,0.0f,0.0f));
cam->setNearClipDistance(5.0f);
cam->setFarClipDistance(5000.0f);
mShipNode->attachObject(cam);
Viewport* v = window->addViewport(cam);
v->setBackgroundColour(ColourValue(0,0,0));
cam->setAspectRatio(Real(v->getActualWidth())/v->getActualHeight());
sceneMgr->setAmbientLight( ColourValue( 0, 0, 0 ) );
light = sceneMgr->createLight("Light1");
light->setType(Light::LT_POINT);
light->setPosition(Ogre::Vector3(0, 100, 0));
light->setDiffuseColour(1.0, 1.0, 1.0);
light->setSpecularColour(1.0, 1.0, 1.0);
light = sceneMgr->createLight("Light3");
light->setType(Light::LT_DIRECTIONAL);
light->setDiffuseColour(ColourValue(1, 1, 1));
light->setSpecularColour(ColourValue(1, 1, 1));
light->setDirection(Ogre::Vector3( 0, -1, 1 ));
light = sceneMgr->createLight("Light2");
light->setType(Light::LT_SPOTLIGHT);
light->setDiffuseColour(1.0, 1.0, 1.0);
light->setSpecularColour(1.0, 1.0, 1.0);
light->setDirection(-1, -1, 0);
light->setPosition(Ogre::Vector3(300, 300, 0));
light->setSpotlightRange(Degree(35), Degree(50));
}
void Gui::Update()
{
float getHeightAt(float x, float z);
Root::getSingleton().renderOneFrame();
keyboard->capture();
mouse->capture();
Ogre::WindowEventUtilities::messagePump();
// take time since last loop to adapt movement to system speed
const float timeFactor = ((float)(mTimer.getMilliseconds()-mLastTime)/1000);
mTimer1 -= timeFactor;
// commit the camera movement (if moving and not colliding with any entity)
if (mDirection != Ogre::Vector3::ZERO)
{
// save last position
Ogre::Vector3 oldPos = mShipNode->getPosition();
// commit move
mShipNode->translate(cam->getOrientation() * mDirection * (mMoveSpeed * timeFactor));
// collision on?
if (mCollision) {
// calculate the new Y position: check vs. terrain & all objects flagged with ENTITY_MASK
// multiple masks possible like e.g. ENTITY_MASK|MY_MASK|ETC_MASK
// doGridCheck casts a 2nd ray, gridWidth=2.0f ogre units away from the exact camera position to
// avoid falling through small wholes or gaps in hangbridges for example.
mCollisionTools->calculateY(mShipNode,true,true,2.0f,ENTITY_MASK );
// check if we are colliding with anything with a collision radius of 2.5 ogre units and we
// set the ray origin -1.0 lower towards the ground to get smaller obstacles too
if (mCollisionTools->collidesWithEntity(oldPos, mShipNode->getPosition(), 2.5f, -100.0f,ENTITY_MASK ))
{
// undo move
mShipNode->setPosition(oldPos);
}
}
//else
//{
// // collision off -> get terrain height
// Ogre::Vector3 pos = mShipNode->getPosition();
// float y = mShip->getHeightAt(pos.x, pos.z);
// mShipNode->setPosition(pos.x,y+4.5f, pos.z);
//}
}
// commit the camera rotation (if rotating)
if (mRotation != 0.0f)
{
mShipNode->yaw( Degree(mRotation * mRotateSpeed* 50 *timeFactor) );
mShipNode->pitch( Degree(-mPitch * mRotateSpeed* 50 *timeFactor) );
// normalise the camera orientation to avoid distortion of the perspective
Quaternion q = mShipNode->getOrientation();
q.normalise();
mShipNode->setOrientation(q);
}
mLastTime = mTimer.getMilliseconds();
};
void Gui::pickEntity(const OIS::MouseEvent &arg, const Ogre::uint32 queryMask)
{
Entity *mFuel= NULL;
Ogre::Vector3 result = Ogre::Vector3::ZERO;
float distToColl;
if (mCollisionTools->raycastFromCamera(window, cam, arg, result, (ulong&)mShip, distToColl, queryMask))
{
SceneNode* mFuelNode = mFuel->getParentSceneNode();
if (mFuelNode->getShowBoundingBox())
{
mFuelNode->showBoundingBox(false);
}
else
{
mFuelNode->showBoundingBox(true);
}
}
}
bool Gui::onPushButtonClicked(const CEGUI::EventArgs &e)
{
exit(1);
}
bool Gui::InitOIS()
{
HWND hwnd = GetActiveWindow();
OIS::ParamList pl;
std::ostringstream oss;
oss << (long)hwnd;
pl.insert(std::make_pair(std::string("WINDOW"), oss.str()));
pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_EXCLUSIVE")));
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_BACKGROUND" )));
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
ois = OIS::InputManager::createInputSystem(pl);
mouse = static_cast<OIS::Mouse*>(ois->createInputObject( OIS::OISMouse, true ));
const OIS::MouseState &ms = mouse->getMouseState();
mouse->setEventCallback(this);
keyboard = static_cast<OIS::Keyboard*>(ois->createInputObject(OIS::OISKeyboard, true));
keyboard->setEventCallback(this);
ms.width = 800;
ms.height = 600;
return true;
}
bool Gui::keyPressed( const KeyEvent &arg )
{
switch(arg.key)
{
case OIS::KC_ESCAPE:
exit(1);
break;
case OIS::KC_DOWN:
movement = -50;
break;
case OIS::KC_UP:
movement = 50;
break;
case OIS::KC_LEFT:
yaw = 1;
break;
case OIS::KC_RIGHT:
yaw = -1;
break;
}
/*if(keyboard->isKeyDown(OIS::KC_ESCAPE))
{
exit(1);
}
if(keyboard->isKeyDown(OIS::KC_UP))
{
movement = 100;
}
if(keyboard->isKeyDown(OIS::KC_DOWN))
{
mShipNode->translate(Ogre::Vector3(0,0,-100));
}*/
return true;
}
bool Gui::keyReleased( const KeyEvent &arg )
{
switch(arg.key)
{
case OIS::KC_DOWN:
movement = 0;
break;
case OIS::KC_UP:
movement = 0;
break;
case OIS::KC_LEFT:
yaw = 0;
break;
case OIS::KC_RIGHT:
yaw = 0;
break;
}
return true;
}
bool Gui::mouseMoved( const OIS::MouseEvent &arg )
{
return true;
}
bool Gui::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
return true;
}
bool Gui::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
return true;
}
CEGUI::MouseButton Gui::MapMouseButton(OIS::MouseButtonID button)
{
switch (button)
{
case OIS::MB_Left:
return CEGUI::LeftButton;
case OIS::MB_Right:
return CEGUI::RightButton;
}
return CEGUI::LeftButton;
}
For the first error, try doing "Ogre::ulong" instead of just "ulong".crosswind wrote:Hi guys,
New to ogre and MOC but I am working on my ogre project but met with 2 errors while compiling my code. I incoporated the MOC source code i downloaded with my own ogre project. Anyone can help? Error and cpp file shown below......If you guys need more info, please PM or contact me...thanks
error C2872: 'ulong' : ambiguous symbol
error C2664: 'bool MOC::CollisionTools::raycastFromCamera(Ogre::RenderWindow *,Ogre::Camera *,const Ogre::Vector2 &,Ogre::Vector3 &,Ogre::MovableObject *&,float &,const Ogre::uint32)' : cannot convert parameter 3 from 'const OIS::MouseEvent' to 'const Ogre::Vector2 &'
Code: Select all
#include "Gui.h" Gui::Gui() : root(), sceneMgr(0), window(0), GuiSystem(0), ois(0), mouse(0), exitgame(false) { //mLastTime = mTimer.getMilliseconds(); // //mTimer1 = 0.0; //mCollision = true; } Gui::~Gui() { delete root; delete GuiSystem; //delete mCollisionTools; } bool Gui::Start() { if (!InitOgre()) return false; if (!InitOIS()) return false; movement = 0; yaw = 0; while(!exitgame) { WindowEventUtilities::messagePump(); mouse->capture(); keyboard->capture(); root->renderOneFrame(); mShipNode->translate(Ogre::Vector3(0,0,movement),Ogre::SceneNode::TS_LOCAL); mShipNode->yaw(Degree( yaw ) ); } } bool Gui::InitOgre() { root = new Root; root->loadPlugin("RenderSystem_GL_d"); RenderSystemList *rs = root->getAvailableRenderers(); if(rs&&rs->size()&&rs->at(0)->getName().compare("RenderSystem_GL")) { RenderSystem * r=rs->at(0); root->setRenderSystem(r); r->setConfigOption("Full Screen","No"); r->setConfigOption("Video Mode","800 x 600 @ 16-bit colour"); } else { return false; } ResourceGroupManager &resources=ResourceGroupManager::getSingleton(); resources.addResourceLocation("data","FileSystem"); //resources.addResourceLocation("resource","FileSystem"); resources.initialiseAllResourceGroups(); window = root->initialise(true, "Simple Ogre App"); sceneMgr = root->createSceneManager(ST_GENERIC); //////added code////////////////////////////////////////////////////// Ogre::WindowEventUtilities::addWindowEventListener(window, this); // init the collision handler mCollisionTools = new CollisionTools(sceneMgr); /////////////////////////////added code/////////////////////////////// //Create our entity sceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE); mShip = sceneMgr->createEntity("ship", "tiger0.mesh"); mShip->setCastShadows(true); mShipNode = sceneMgr->getRootSceneNode()->createChildSceneNode(); mShipNode->attachObject(mShip); mShipNode->setPosition(Ogre::Vector3(0,-100,0)); mFuel = sceneMgr->createEntity("fuel", "Box16.mesh"); mFuel->setCastShadows(true); mFuel->setQueryFlags(ENTITY_MASK); mFuelNode = sceneMgr->getRootSceneNode()->createChildSceneNode(); mFuelNode->attachObject(mFuel); mFuelNode->setPosition(Ogre::Vector3(0,-100,0)); mCube = sceneMgr->createEntity("cube", "pCube1.mesh"); mCubeNode = sceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(0,400,0)); mCubeNode->attachObject(mCube); mCubeNode->scale( 100000,10000,100000 ); cam = sceneMgr->createCamera("SimpleCamera"); cam->setPosition(Ogre::Vector3(0.0f,50.0f,-400.0f)); cam->lookAt(Ogre::Vector3(0.0f,0.0f,0.0f)); cam->setNearClipDistance(5.0f); cam->setFarClipDistance(5000.0f); mShipNode->attachObject(cam); Viewport* v = window->addViewport(cam); v->setBackgroundColour(ColourValue(0,0,0)); cam->setAspectRatio(Real(v->getActualWidth())/v->getActualHeight()); sceneMgr->setAmbientLight( ColourValue( 0, 0, 0 ) ); light = sceneMgr->createLight("Light1"); light->setType(Light::LT_POINT); light->setPosition(Ogre::Vector3(0, 100, 0)); light->setDiffuseColour(1.0, 1.0, 1.0); light->setSpecularColour(1.0, 1.0, 1.0); light = sceneMgr->createLight("Light3"); light->setType(Light::LT_DIRECTIONAL); light->setDiffuseColour(ColourValue(1, 1, 1)); light->setSpecularColour(ColourValue(1, 1, 1)); light->setDirection(Ogre::Vector3( 0, -1, 1 )); light = sceneMgr->createLight("Light2"); light->setType(Light::LT_SPOTLIGHT); light->setDiffuseColour(1.0, 1.0, 1.0); light->setSpecularColour(1.0, 1.0, 1.0); light->setDirection(-1, -1, 0); light->setPosition(Ogre::Vector3(300, 300, 0)); light->setSpotlightRange(Degree(35), Degree(50)); } void Gui::Update() { float getHeightAt(float x, float z); Root::getSingleton().renderOneFrame(); keyboard->capture(); mouse->capture(); Ogre::WindowEventUtilities::messagePump(); // take time since last loop to adapt movement to system speed const float timeFactor = ((float)(mTimer.getMilliseconds()-mLastTime)/1000); mTimer1 -= timeFactor; // commit the camera movement (if moving and not colliding with any entity) if (mDirection != Ogre::Vector3::ZERO) { // save last position Ogre::Vector3 oldPos = mShipNode->getPosition(); // commit move mShipNode->translate(cam->getOrientation() * mDirection * (mMoveSpeed * timeFactor)); // collision on? if (mCollision) { // calculate the new Y position: check vs. terrain & all objects flagged with ENTITY_MASK // multiple masks possible like e.g. ENTITY_MASK|MY_MASK|ETC_MASK // doGridCheck casts a 2nd ray, gridWidth=2.0f ogre units away from the exact camera position to // avoid falling through small wholes or gaps in hangbridges for example. mCollisionTools->calculateY(mShipNode,true,true,2.0f,ENTITY_MASK ); // check if we are colliding with anything with a collision radius of 2.5 ogre units and we // set the ray origin -1.0 lower towards the ground to get smaller obstacles too if (mCollisionTools->collidesWithEntity(oldPos, mShipNode->getPosition(), 2.5f, -100.0f,ENTITY_MASK )) { // undo move mShipNode->setPosition(oldPos); } } //else //{ // // collision off -> get terrain height // Ogre::Vector3 pos = mShipNode->getPosition(); // float y = mShip->getHeightAt(pos.x, pos.z); // mShipNode->setPosition(pos.x,y+4.5f, pos.z); //} } // commit the camera rotation (if rotating) if (mRotation != 0.0f) { mShipNode->yaw( Degree(mRotation * mRotateSpeed* 50 *timeFactor) ); mShipNode->pitch( Degree(-mPitch * mRotateSpeed* 50 *timeFactor) ); // normalise the camera orientation to avoid distortion of the perspective Quaternion q = mShipNode->getOrientation(); q.normalise(); mShipNode->setOrientation(q); } mLastTime = mTimer.getMilliseconds(); }; void Gui::pickEntity(const OIS::MouseEvent &arg, const Ogre::uint32 queryMask) { Entity *mFuel= NULL; Ogre::Vector3 result = Ogre::Vector3::ZERO; float distToColl; if (mCollisionTools->raycastFromCamera(window, cam, arg, result, (ulong&)mShip, distToColl, queryMask)) { SceneNode* mFuelNode = mFuel->getParentSceneNode(); if (mFuelNode->getShowBoundingBox()) { mFuelNode->showBoundingBox(false); } else { mFuelNode->showBoundingBox(true); } } } bool Gui::onPushButtonClicked(const CEGUI::EventArgs &e) { exit(1); } bool Gui::InitOIS() { HWND hwnd = GetActiveWindow(); OIS::ParamList pl; std::ostringstream oss; oss << (long)hwnd; pl.insert(std::make_pair(std::string("WINDOW"), oss.str())); pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" ))); pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_EXCLUSIVE"))); pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_BACKGROUND" ))); pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE"))); ois = OIS::InputManager::createInputSystem(pl); mouse = static_cast<OIS::Mouse*>(ois->createInputObject( OIS::OISMouse, true )); const OIS::MouseState &ms = mouse->getMouseState(); mouse->setEventCallback(this); keyboard = static_cast<OIS::Keyboard*>(ois->createInputObject(OIS::OISKeyboard, true)); keyboard->setEventCallback(this); ms.width = 800; ms.height = 600; return true; } bool Gui::keyPressed( const KeyEvent &arg ) { switch(arg.key) { case OIS::KC_ESCAPE: exit(1); break; case OIS::KC_DOWN: movement = -50; break; case OIS::KC_UP: movement = 50; break; case OIS::KC_LEFT: yaw = 1; break; case OIS::KC_RIGHT: yaw = -1; break; } /*if(keyboard->isKeyDown(OIS::KC_ESCAPE)) { exit(1); } if(keyboard->isKeyDown(OIS::KC_UP)) { movement = 100; } if(keyboard->isKeyDown(OIS::KC_DOWN)) { mShipNode->translate(Ogre::Vector3(0,0,-100)); }*/ return true; } bool Gui::keyReleased( const KeyEvent &arg ) { switch(arg.key) { case OIS::KC_DOWN: movement = 0; break; case OIS::KC_UP: movement = 0; break; case OIS::KC_LEFT: yaw = 0; break; case OIS::KC_RIGHT: yaw = 0; break; } return true; } bool Gui::mouseMoved( const OIS::MouseEvent &arg ) { return true; } bool Gui::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) { return true; } bool Gui::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) { return true; } CEGUI::MouseButton Gui::MapMouseButton(OIS::MouseButtonID button) { switch (button) { case OIS::MB_Left: return CEGUI::LeftButton; case OIS::MB_Right: return CEGUI::RightButton; } return CEGUI::LeftButton; }
Code: Select all
Ogre::Vector3 mousepos;
mousepos.x = arg.state.X.rel;
mousepos.y = arg.state.Y.rel;
if(mCollisionTools->raycastFromCamera(window, cam, mousepos, result, (Ogre::ulong&)mShip, distToColl, queryMask))
.....
Yes! Rightjacmoe wrote:Except that mousepos should be Ogre::Vector2.
Code: Select all
#include "Gui.h"
#include <OgreVector2.h>
using namespace Ogre;
Gui::Gui() :
root(),
sceneMgr(0),
window(0),
GuiSystem(0),
ois(0),
mouse(0),
exitgame(false)
{
mLMouseDown = mMMouseDown = mRMouseDown = false;
mLastTime = mTimer.getMilliseconds();
mTimer1 = 0.0;
mCollision = true;
}
Gui::~Gui()
{
delete root;
delete GuiSystem;
delete mCollisionTools;
}
bool Gui::Start()
{
if (!InitOgre())
return false;
if (!InitOIS())
return false;
movement = 0;
yaw = 0;
while(!exitgame)
{
WindowEventUtilities::messagePump();
mouse->capture();
keyboard->capture();
root->renderOneFrame();
mShipNode->translate(Ogre::Vector3(0,0,movement),Ogre::SceneNode::TS_LOCAL);
mShipNode->yaw(Degree( yaw ) );
gui->Update();
}
}
bool Gui::InitOgre()
{
root = new Root;
root->loadPlugin("RenderSystem_GL_d");
RenderSystemList *rs = root->getAvailableRenderers();
if(rs&&rs->size()&&rs->at(0)->getName().compare("RenderSystem_GL"))
{
RenderSystem * r=rs->at(0);
root->setRenderSystem(r);
r->setConfigOption("Full Screen","No");
r->setConfigOption("Video Mode","800 x 600 @ 16-bit colour");
}
else
{
return false;
}
ResourceGroupManager &resources=ResourceGroupManager::getSingleton();
resources.addResourceLocation("data","FileSystem");
resources.initialiseAllResourceGroups();
window = root->initialise(true, "Simple Ogre App");
sceneMgr = root->createSceneManager(ST_GENERIC);
//////added code//////////////////////////////////////////////////////
Ogre::WindowEventUtilities::addWindowEventListener(window, this);
// init the collision handler
mCollisionTools = new CollisionTools(sceneMgr);
/////////////////////////////added code///////////////////////////////
//Create our entity
sceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
mShip = sceneMgr->createEntity("ship", "tiger0.mesh");
mShip->setCastShadows(true);
mShipNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
mShipNode->attachObject(mShip);
mShipNode->setPosition(Ogre::Vector3(0,-100,0));
mFuel = sceneMgr->createEntity("fuel", "Box16.mesh");
mFuel->setCastShadows(true);
mFuel->setQueryFlags(ENTITY_MASK);
mFuelNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
mFuelNode->attachObject(mFuel);
mFuelNode->setPosition(Ogre::Vector3(0,-100,0));
mCube = sceneMgr->createEntity("cube", "pCube1.mesh");
mCubeNode = sceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(0,400,0));
mCubeNode->attachObject(mCube);
mCubeNode->scale( 5000,5000,5000 );
cam = sceneMgr->createCamera("SimpleCamera");
cam->setPosition(Ogre::Vector3(0.0f,50.0f,-400.0f));
cam->lookAt(Ogre::Vector3(0.0f,0.0f,0.0f));
cam->setNearClipDistance(5.0f);
cam->setFarClipDistance(5000.0f);
mShipNode->attachObject(cam);
Viewport* v = window->addViewport(cam);
v->setBackgroundColour(ColourValue(0,0,0));
cam->setAspectRatio(Real(v->getActualWidth())/v->getActualHeight());
sceneMgr->setAmbientLight( ColourValue( 0, 0, 0 ) );
light = sceneMgr->createLight("Light1");
light->setType(Light::LT_POINT);
light->setPosition(Ogre::Vector3(0, 100, 0));
light->setDiffuseColour(1.0, 1.0, 1.0);
light->setSpecularColour(1.0, 1.0, 1.0);
light = sceneMgr->createLight("Light3");
light->setType(Light::LT_DIRECTIONAL);
light->setDiffuseColour(ColourValue(1, 1, 1));
light->setSpecularColour(ColourValue(1, 1, 1));
light->setDirection(Ogre::Vector3( 0, -1, 1 ));
light = sceneMgr->createLight("Light2");
light->setType(Light::LT_SPOTLIGHT);
light->setDiffuseColour(1.0, 1.0, 1.0);
light->setSpecularColour(1.0, 1.0, 1.0);
light->setDirection(-1, -1, 0);
light->setPosition(Ogre::Vector3(300, 300, 0));
light->setSpotlightRange(Degree(35), Degree(50));
}
void Gui::Update()
{
float getHeightAt(float x, float z);
Root::getSingleton().renderOneFrame();
Ogre::WindowEventUtilities::messagePump();
// take time since last loop to adapt movement to system speed
const float timeFactor = ((float)(mTimer.getMilliseconds()-mLastTime)/1000);
mTimer1 -= timeFactor;
// commit the camera movement (if moving and not colliding with any entity)
if (mDirection != Ogre::Vector3::ZERO)
{
// save last position
Ogre::Vector3 oldPos = mShipNode->getPosition();
// commit move
mShipNode->translate(cam->getOrientation() * mDirection * (mMoveSpeed * timeFactor));
// collision on?
if (mCollision)
{
// calculate the new Y position: check vs. terrain & all objects flagged with ENTITY_MASK
// multiple masks possible like e.g. ENTITY_MASK|MY_MASK|ETC_MASK
// doGridCheck casts a 2nd ray, gridWidth=2.0f ogre units away from the exact camera position to
// avoid falling through small wholes or gaps in hangbridges for example.
mCollisionTools->calculateY(mShipNode,true,true,2.0f,ENTITY_MASK );
// check if we are colliding with anything with a collision radius of 2.5 ogre units and we
// set the ray origin -1.0 lower towards the ground to get smaller obstacles too
if (mCollisionTools->collidesWithEntity(oldPos, mShipNode->getPosition(), 2.5f, -100.0f,ENTITY_MASK ))
{
// undo move
mShipNode->setPosition(oldPos);
}
}
}
// commit the camera rotation (if rotating)
if (mRotation != 0.0f)
{
mShipNode->yaw( Degree(mRotation * mRotateSpeed* 50 *timeFactor) );
mShipNode->pitch( Degree(-mPitch * mRotateSpeed* 50 *timeFactor) );
// normalise the camera orientation to avoid distortion of the perspective
Quaternion q = mShipNode->getOrientation();
q.normalise();
mShipNode->setOrientation(q);
}
mLastTime = mTimer.getMilliseconds();
};
void Gui::pickEntity(const OIS::MouseEvent &arg, const Ogre::uint32 queryMask)
{
Entity *tmpE = NULL;
Ogre::Vector3 result = Ogre::Vector3::ZERO;
float distToColl;
mousepos.x = arg.state.X.rel;
mousepos.y = arg.state.Y.rel;
if (mCollisionTools->raycastFromCamera(window, cam, mousepos, result, mFuel, distToColl, queryMask))
{
SceneNode* mFuelNode= mFuel->getParentSceneNode();
if (mFuelNode->getShowBoundingBox())
{
mFuelNode->showBoundingBox(false);
}
else
{
mFuelNode->showBoundingBox(true);
}
}
}
bool Gui::onPushButtonClicked(const CEGUI::EventArgs &e)
{
exit(1);
}
bool Gui::InitOIS()
{
HWND hwnd = GetActiveWindow();
OIS::ParamList pl;
std::ostringstream oss;
oss << (long)hwnd;
pl.insert(std::make_pair(std::string("WINDOW"), oss.str()));
pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_EXCLUSIVE")));
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_BACKGROUND" )));
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
ois = OIS::InputManager::createInputSystem(pl);
mouse = static_cast<OIS::Mouse*>(ois->createInputObject( OIS::OISMouse, true ));
const OIS::MouseState &ms = mouse->getMouseState();
mouse->setEventCallback(this);
keyboard = static_cast<OIS::Keyboard*>(ois->createInputObject(OIS::OISKeyboard, true));
keyboard->setEventCallback(this);
ms.width = 800;
ms.height = 600;
return true;
}
bool Gui::keyPressed( const KeyEvent &arg )
{
switch(arg.key)
{
case OIS::KC_ESCAPE:
exit(1);
break;
case OIS::KC_DOWN:
movement = -50;
break;
case OIS::KC_UP:
movement = 50;
break;
case OIS::KC_LEFT:
yaw = 1;
break;
case OIS::KC_RIGHT:
yaw = -1;
break;
}
/*if(keyboard->isKeyDown(OIS::KC_ESCAPE))
{
exit(1);
}
if(keyboard->isKeyDown(OIS::KC_UP))
{
movement = 100;
}
if(keyboard->isKeyDown(OIS::KC_DOWN))
{
mShipNode->translate(Ogre::Vector3(0,0,-100));
}*/
return true;
}
bool Gui::keyReleased( const KeyEvent &arg )
{
switch(arg.key)
{
case OIS::KC_DOWN:
movement = 0;
break;
case OIS::KC_UP:
movement = 0;
break;
case OIS::KC_LEFT:
yaw = 0;
break;
case OIS::KC_RIGHT:
yaw = 0;
break;
}
return true;
}
bool Gui::mouseMoved( const OIS::MouseEvent &arg )
{
return true;
}
bool Gui::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
if ( id == OIS::MB_Left )
{
mLMouseDown = true;
pickEntity(arg, ENTITY_MASK);
}
else if ( id == OIS::MB_Middle )
{
mMMouseDown = true;
}
else if (id == OIS::MB_Right)
{
mRMouseDown = true;
}
return true;
}
bool Gui::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
if ( id == OIS::MB_Left )
{
mLMouseDown = false;
}
else if ( id == OIS::MB_Middle )
{
mMMouseDown = false;
}
else if (id == OIS::MB_Right)
{
mRMouseDown = false;
}
return true;
}
CEGUI::MouseButton Gui::MapMouseButton(OIS::MouseButtonID button)
{
switch (button)
{
case OIS::MB_Left:
return CEGUI::LeftButton;
case OIS::MB_Right:
return CEGUI::RightButton;
}
return CEGUI::LeftButton;
}
ARTIFEX TERRA 3D - Artist-friendly, free and easy WYSIWYG realtime outdoor scene Editor & Painter
New loader now with Ogre::Terrain support: Addons for Artifex on SourceForge
MOC - Minimal Ogre Collision & Mousepicking
Simple TerrainMaterialGenerator for the use of standard Ogre material with Ogre::Terrain
Support me on Patreon
please review the code before you integrate it. It basically caches the mesh information by allocating lots of memory that never gets freed.Nauk wrote:Nice work tdev going to include that in the next update.