MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
Post Reply
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by jacmoe »

deadvirus wrote:If you think it would be useful, I could post it here.
Aye, please do! :)
You won't believe how many times people have been asking how to do that..
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
Nauk
Gnoll
Posts: 653
Joined: Thu May 11, 2006 9:12 pm
Location: Bavaria
x 36
Contact:

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by Nauk »

Sure post it :) - talking about indices I am thinking of adding a caching functionality to MOC, especially for non-animated meshes or entities that share the same mesh. It should be somewhat faster not to build the index and vertex arrays everytime you make a check new for each and every mesh.
User avatar
deadvirus
Gnoblar
Posts: 13
Joined: Fri Mar 13, 2009 5:57 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by deadvirus »

Here it is! I'm not sure if it's the right way to do it, or if it has any kind of problems, so if you see anything that could be better, please tell me :)

I will post the entire functions, but the changes to the ones included in MOC, are not much.

This one gets the mesh information:

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;
    }
}
The raycast function:

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);
    }
}
The others just need to deal with the new param.
I think the best way is to override the other functions, so you can (should) use the "normal" functions when you don't need to know the submesh (it's faster).
The absence of light,
DeadVirus.
adanar
Gnoblar
Posts: 23
Joined: Sun Feb 19, 2006 9:06 pm
Location: Greece, Crete

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by adanar »

Hello again.

I noticed some strange behavior in raycast method. whenever it hits an entity, the intersects method returns a very small distance from the ray's origin, much smaller than the correct one.
I did several tests:
I printed the vertices positions which are correct (in world space)
the ray is aslo in worldspace
in the getMeshInformation call I used _getDerived* functions

I also printed the hit.second value for each hit, along with the ray.getOrigin().distance(vertices[indices]) (the first vertex in the triangle hit).
The value for hit.second (the value returned by the raycast method) was always approximately 400 times small than the distance of the ray's origin with the 1st vertex.

Do u have any idea why this could be happening?
User avatar
Nauk
Gnoll
Posts: 653
Joined: Thu May 11, 2006 9:12 pm
Location: Bavaria
x 36
Contact:

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by Nauk »

No actually I haven't - so if I understand you right, you do get the correct entity as result, but the distance is wrong?
adanar
Gnoblar
Posts: 23
Joined: Sun Feb 19, 2006 9:06 pm
Location: Greece, Crete

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by adanar »

Yes. that's right.

I would think it is my mistake but as I told you, the strange thing is that on the raycast function I also calculate the distance of the ray origin to the first vertex of the 3 vertices used in the intersects method just before and THAT distance is correct (and approx. always 400 times large)
User avatar
deadvirus
Gnoblar
Posts: 13
Joined: Fri Mar 13, 2009 5:57 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by deadvirus »

I needed a way to find out the normal of the intersected plane, so I implemented it.
Here it is (just some minor changes on the raycast method). I sugest to keep the other raycast method, so that It doesn't need to waste time finding the normal, when you will not use it.

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);
    }
}
Hope it helps someone!
The absence of light,
DeadVirus.
User avatar
deadvirus
Gnoblar
Posts: 13
Joined: Fri Mar 13, 2009 5:57 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by deadvirus »

Nauk wrote:Good work deadvirus and thanks for sharing, I like it and will add it. :)
No problem! I am the one who has to say thanks for MOC :D
The absence of light,
DeadVirus.
crosswind
Gnoblar
Posts: 15
Joined: Mon Apr 06, 2009 1:29 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by crosswind »

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


User avatar
deadvirus
Gnoblar
Posts: 13
Joined: Fri Mar 13, 2009 5:57 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by deadvirus »

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


For the first error, try doing "Ogre::ulong" instead of just "ulong".
For the second error, you should get mouse position to a Ogre::Vector3, and then pass that Vector3 instead of passing the OIS::MouseEvent.
The absence of light,
DeadVirus.
crosswind
Gnoblar
Posts: 15
Joined: Mon Apr 06, 2009 1:29 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by crosswind »

thanks deadvirus....that was fast....let me go try now.
crosswind
Gnoblar
Posts: 15
Joined: Mon Apr 06, 2009 1:29 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by crosswind »

For the 2nd pt....dnt quite get you....care to elaborate? and my bad...i am using the keyboard atm instead of the mouse
Last edited by crosswind on Sun May 17, 2009 6:54 pm, edited 1 time in total.
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by jacmoe »

What's in an OIS::arg? You need a Ogre::Vector2..
I think you'll find the answer in the MOC demo.
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
crosswind
Gnoblar
Posts: 15
Joined: Mon Apr 06, 2009 1:29 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by crosswind »

Hi Jacmoe,

i took the collisiontools.h and .cpp and then put into my Ogre project and edited it....yap i d/l the source code bt been staring at it for hours
User avatar
deadvirus
Gnoblar
Posts: 13
Joined: Fri Mar 13, 2009 5:57 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by deadvirus »

Something like:

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))
.....
I think that'll work...
The absence of light,
DeadVirus.
crosswind
Gnoblar
Posts: 15
Joined: Mon Apr 06, 2009 1:29 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by crosswind »

thanks guys or the help....will try it out immediately now....=)
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by jacmoe »

Except that mousepos should be Ogre::Vector2. :wink:
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
deadvirus
Gnoblar
Posts: 13
Joined: Fri Mar 13, 2009 5:57 pm

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by deadvirus »

Oh, by the way, if you're using the last MOC version, you don't need to cast mShip to ulong (you can't).
jacmoe wrote:Except that mousepos should be Ogre::Vector2. :wink:
Yes! Right :)
The absence of light,
DeadVirus.
crosswind
Gnoblar
Posts: 15
Joined: Mon Apr 06, 2009 1:29 pm

HELP

Post by crosswind »

Having tis break in my code when it compiles....Trying to implement the collision code bt breaks at the update area:
const float timeFactor = ((float)(mTimer.getMilliseconds()-mLastTime)/1000);

Call stack at the bottom

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

Image
User avatar
tdev
Silver Sponsor
Silver Sponsor
Posts: 244
Joined: Thu Apr 12, 2007 9:21 pm
Location: Germany
x 14

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by tdev »

i found some way to get StaticGeometry working, but its horribly slow (see attached sources)

EDIT: found the reason why its slow, *improving*
EDIT2: attached col2.zip is slightly faster, but still too slow to be usable :/

the collision with static geometry seems to work well, but the FPS drops from 120 normal to 20 when moving for me :(
any ideas how to speed this up? maybe store the mesh information once retrieved?

EDIT3: performance problems solved :D
the attached col3.zip caches the retrieved mesh information of static geometry, thus the FPS drop is only 1-5 FPS at ~120 :D
Attachments
col3.zip
(7.66 KiB) Downloaded 216 times
col2.zip
(7.47 KiB) Downloaded 167 times
col.zip
(7.5 KiB) Downloaded 187 times
compvis
Gremlin
Posts: 165
Joined: Wed Sep 10, 2008 6:14 am

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by compvis »

Hi,

How can i track a collision event ? My goal is:
I have a missile and a bullet. After shooting the bullet to the missile, if the bullet hits the missile then how can i handle that event. I will use this event to call a function that plays a particle effect (explosion).

if i can do ?
User avatar
tdev
Silver Sponsor
Silver Sponsor
Posts: 244
Joined: Thu Apr 12, 2007 9:21 pm
Location: Germany
x 14

Re: MOC - Minimal Ogre Collision 1.0 - [Update 03.May.2009]

Post by tdev »

Nauk wrote:Nice work tdev :) going to include that in the next update.
please review the code before you integrate it. It basically caches the mesh information by allocating lots of memory that never gets freed.
So for a production quality software there should be an algorithm that determines which cached variables to free at what time.

The caching i did for static geometry could also be used for other static / non moving objects and thus speed up things a lot. (i think its clear in the code how its done)
Post Reply