[SOLVED]ogreopcode and ofusion scene

bens1404

17-01-2008 00:25:58

hi anybody
i am using ogreopcode collision detection library on my scens loaded with ofusion ,i wanna make a first person camera style ,so

here is my code
main.cpp

#include "ExampleApplication.h"
#include "collision.h"
// oScene loader library header file
#include "OgreOSMScene.h"

// Callback handler to post-process created objects
class oSceneCallback : public OSMSceneCallbacks {
public:

// We override the OnCreate method for cameras (See IXMLSceneCallbacks class)
void OnCameraCreate(Ogre::Camera* pCamera, TiXmlElement* pCameraDesc) {

// If a camera of name "FirstCamera" is loaded, it will be set as the default current
if(pCamera->getName() == "FirstCamera")
Ogre::Root::getSingleton().getAutoCreatedWindow()->getViewport(0)->setCamera(pCamera);


}
void OnEntityCreate(Ogre::Entity* pEntity, TiXmlElement* pEntityDesc) {

pEntity->getParentSceneNode()->showBoundingBox(true);
}
};


// Event handler to animate
class oSceneLibDemoFrameListener : public ExampleFrameListener, Collision::CollisionListener
{
protected:
bool mFlagGravity;
Real mTimeSinceLastFrame;
String mLatestCollision;
SceneManager* mSceneMgr;

public:
oSceneLibDemoFrameListener(SceneManager* sceneMgr, RenderWindow* win, Camera* cam,SceneNode* camNode)
: mSceneMgr(sceneMgr), ExampleFrameListener(win, cam,camNode),mFlagGravity(false),
Collision::CollisionListener()
{
}


bool frameStarted(const FrameEvent& evt)
{


if( ExampleFrameListener::frameStarted(evt) == false )
return false;


mTimeSinceLastFrame = evt.timeSinceLastFrame;
return true;



}

//--------------

void moveCamera()
{
Quaternion q = mCamNode->getWorldOrientation();
Vector3 vel = q * mTranslateVector;

Vector3 gravity(0, 0, 0);
if (mFlagGravity) {
// adjust gravity based on fps
gravity = Vector3(0, -100 * mTimeSinceLastFrame, 0);
}

// small enough so we can fly out of open windows
Real radius = 0.3;

if (vel != Vector3::ZERO || mFlagGravity) {
// do the collision
Vector3 pos = Collision::collideAndSlide(mCamNode->getPosition(), vel,
radius, gravity, this);
mCamNode->setPosition(pos);
}

mCamNode->yaw(mRotX, Node::TS_WORLD);
mCamNode->pitch(mRotY);
}

//-------------------------------
void collisionOccurred(String obj)
{
mLatestCollision = "/ Latest collision: " + obj;
}
//------------------------
bool processUnbufferedKeyInput(const FrameEvent& evt)
{

static Real currentTime = 0;

bool ret = ExampleFrameListener::processUnbufferedKeyInput(evt);
if (!ret) return false;



if(mKeyboard->isKeyDown(OIS::KC_G) && mTimeUntilNextToggle <= 0) {
mFlagGravity = !mFlagGravity;
mTimeUntilNextToggle = 1;

}


return true;
}
};

class oSceneLibApplication : public ExampleApplication {
public:

oSceneLibApplication() {}

protected:

OgreOpcode::CollisionContext *mCollisionContext;

void setupCollisions()
{
using namespace OgreOpcode;
new CollisionManager(mSceneMgr);
CollisionManager* colMgr = CollisionManager::getSingletonPtr();
mCollisionContext = colMgr->getDefaultContext();
Details::OgreOpcodeDebugger *debuger = new Details::OgreOpcodeDebugger("entity_alias", mSceneMgr);
// notice that camera sliding does not use collision classes at all
// (it uses COLLTYPE_ALWAYS_EXACT)
//colMgr->addCollClass("gameobject");
//colMgr->addCollType("gameobject", "gameobject", COLLTYPE_IGNORE);
SceneManager::MovableObjectIterator mov_it = mSceneMgr->getMovableObjectIterator("Entity");
while (mov_it.hasMoreElements()) {
MovableObject* movable = mov_it.getNext();
Entity* ent = static_cast<Entity*>(movable);
String entName = ent->getName();
CollisionObject* collObj = mCollisionContext->createObject(entName + "_CollObj");
EntityCollisionShape* collShape = colMgr->createEntityCollisionShape(entName + "_CollShape");
collShape->load(ent);
collObj->setShape(collShape);
mCollisionContext->addObject(collObj);
// this line is needed for some reason (otherwise CollisionObject minv/maxv
// gets strange values and no collisions occur)
// looks like some bounding box is not calculated if objects are not moving
collShape->visualize(debuger);
collObj->update(0);


}
}
// Just override the mandatory create scene method
void createScene(void)
{
// Here is the code that will load the scene file
// A fixed filename "scene.osm" is implemented for this demo

// Create the scene loader
OSMScene oScene;

// Create an oE_Loader Callback object to post-process created objects
oSceneCallback oe_Callback;

// Initialises with the scene to be loaded and the callback if requiered
oScene.initialise("myworld.osm");

// create and setup the scene in the root node
oScene.createScene();

mSceneMgr = oScene.getSceneManager();


mCamera = mSceneMgr->createCamera("PlayerCam");
mCamera->setNearClipDistance(5);
mCamNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
mCamNode->lookAt(Vector3(0, 0, -300), Node::TS_WORLD);
mCamNode->attachObject(mCamera);
mCamNode->setPosition(0, 15,300);
Ogre::Root::getSingleton().getAutoCreatedWindow()->getViewport(0)->setCamera(mCamera);
setupCollisions();

}

// The scene manager will be created by the Scene Loader lib
void chooseSceneManager(void) {}
void createCamera(void)
{

}
void createViewports(void) {}

// Create new frame listener
void createFrameListener(void)
{
mFrameListener= new oSceneLibDemoFrameListener(mSceneMgr, mWindow, mCamera,mCamNode);
mRoot->addFrameListener(mFrameListener);
}

};


i got the collision work but the entity and the collision shape they
dont have the some size and my camera go a bit through wall
beleive me the entity from ofusion got scaled by ofusion node

hope if anybody can help me to fix that,how do i scale the collision
shape to fit the entity node loaded fom ofusion

Lioric

17-01-2008 02:42:35

In any collision detection lib that uses trimehses as the object geometry, your entities must be of "unit scale", this means that the object scale must be converted to be the unit scale (and remove any non unit scale in any vector)

To do this, you need to "Reset Xform" of the objects in max (or at least "Reset Scale" from the hierarchy tab)

Its been a long time from the last time i used that collision detection library (in a different platfrom), but it didnt have a scale method for trimeshes (and for performance reasons it must not), that is why you need to set the current object scale to be the unit scale

About the camera, it might be using the near clip plane when creating the geom, test by increasing the near clip plane

bens1404

17-01-2008 10:56:27

thanks for your reply
i did all that ,reset all my objects xform in max before exporting my scene with ofusion but didnt fixe my problem
the algorithm work fine with .scene file format

i set my applicatin scale in
in collision.cpp


// Set this to match application scale..
const float unitsPerMeter = 100.0f;

// All hard-coded distances in this function is
// scaled to fit the setting above..
const float unitScale = unitsPerMeter / 100.0f;
const float veryCloseDistance = 0.005f * unitScale; // 0.5cm if unitsPerMeter is 100



and the system unit scale in 3ds max is 1 meter

i tried to play with my app scale but nothing got changed

Lioric

17-01-2008 15:10:44

If your scene scale is 1 meter, then in you might want to set "unitsPerMeter = 1"

What is the difference between the objects boundingbox and the debug visual display?

bens1404

17-01-2008 15:58:50

i did this but nothing happen
the entity boundig box and the visual debug display dont have some size
the bounding box is bigger,and the visual debug display match exactly the entity shape
also i update my mesh with ogre meshupgrade tools but the some problem persist

seem the problem in ofusion scene node transformation

Lioric

17-01-2008 21:55:12

The boundiung box is bigger because it is padded by the Ogre engine (for visivility test purposes), but only a single unit in all directions, and because the boundingbox takes all of the node positions from the hierarchy (if your entitiy is part of a node hierachy and you ar are selecting the parent node)

But if the visual debug display of the geom is of the correct size for the entity and it is in the correct location, then the issue is with the library you are using, either in the setup or in the world steps (at each frame)

bens1404

18-01-2008 00:25:53

thanks you lioric for your help

i fixed my problem and all be right now
the error was in the function call in colliton.cpp indeed in the world steps as you said , thanks again
doOgreOpcodeCollision(colData, veryCloseDistance *5, listener);

i am stupid, why multiplay by 5 :oops:

the function must be called like that
doOgreOpcodeCollision(colData, veryCloseDistance, listener);

elieajaltouni

05-06-2009 19:45:10

Hi everyone I am trying to add collision detection to a scene exported using ofusion.
I am trying to get the ogreopcode source code from the current svn and as I see it does not have the collision.h file
used by bens1404...
bens1404 can you please send me a link for your ogreopcode source code.


Any suggestions other than using ogreopcode? Am I on the right track?

Lioric

05-06-2009 22:26:28

There are several other libs that are easier to use and might fit your needs and include sample code, search the forums or the Ogre wiki

bens1404

08-06-2009 19:20:52

Hi everyone I am trying to add collision detection to a scene exported using ofusion.
I am trying to get the ogreopcode source code from the current svn and as I see it does not have the collision.h file
used by bens1404...
bens1404 can you please send me a link for your ogreopcode source code.


Any suggestions other than using ogreopcode? Am I on the right track?


hi

excuse me to be late ,since long ago didnt browse the ofusion forum
here is the link to ogreopcode svn reposity

https://ogreconglo.svn.sourceforge.net/ ... ogreopcode

download the revision 384 and let see

hope this help

bens1404

19-06-2009 14:11:14

hi and finaly here is the collision.h and collision.cpp files

colllision.h


/**
* Copyright (c) 2007 Mikko Vننnنnen
* This code is in the public domain.
*/
#ifndef __COLLISION_H__
#define __COLLISION_H__

#include "OgreVector3.h"

namespace Collision {

using namespace Ogre;

class CollisionListener
{
public:
CollisionListener() {}

/** Tells the name of collided object.
*/
virtual void collisionOccurred(String obj) {}
};

/** Collides a sphere with world.
@param pos
The colliding sphere position.
@param vel
The colliding sphere velocity.
@param radius
The colliding sphere radius.
@param gravity
The amount of gravity in the world.
@param listener
(optional) The collision listener.
@param slopeSlideThresold
(optional) The steepness thresold for sliding.
@return
New position for collided sphere.
*/
Vector3 collideAndSlide(const Vector3& pos, const Vector3& vel, Real radius,
const Vector3& gravity, CollisionListener* listener = 0,
const Degree& slopeSlideThresold = Degree(45));
}

#endif



collision.cpp



/**
* This code is based on "Improved Collision detection and Response",
* Kasper Fauerby, 2003.
*
* Copyright (c) 2007 Mikko Vننnنnen
* This code is in the public domain.
*/
#include "collision.h"
#include "OgreOpcode.h"


namespace Collision {


class CollisionPacket {
public:
Vector3 eRadius; // ellipsoid radius
// Information about the move being requested: (in R3)
Vector3 R3Velocity;
Vector3 R3Position;
// Information about the move being requested: (in eSpace)
Vector3 velocity;
Vector3 normalizedVelocity;
Vector3 basePoint;
// Hit information
bool foundCollision;
double nearestDistance;
Vector3 intersectionPoint;
};


void doOgreOpcodeCollision(CollisionPacket& colData, float sweepOffset,
CollisionListener* listener)
{
Vector3 pos_R3 = colData.basePoint * colData.eRadius;
Vector3 vel_R3 = colData.velocity * colData.eRadius;

OgreOpcode::CollisionPair** reports;

// TODO: sweptSphereCheck does not support ellipsoids,
// so we must use only one dimension!!!
Real radius = colData.eRadius.x;

// Add a little offset to velocity so that we don't get too close.
Vector3 offset = vel_R3;
offset.normalise();
offset *= sweepOffset;

OgreOpcode::Details::CollisionClass collClass = OgreOpcode::COLLTYPE_ALWAYS_EXACT;

int count = OgreOpcode::CollisionManager::getSingletonPtr()->getDefaultContext()->
sweptSphereCheck(pos_R3, vel_R3 + offset, radius, collClass, reports);

if (count) {
// search for closest distance collision
int closest = 0;
Real d = reports[0]->distance;
for (int i = 1; i < count; i++) {
if (reports[i]->distance < d) {
d = reports[i]->distance;
closest = i;
}
}

colData.foundCollision = true;
colData.nearestDistance = reports[closest]->distance;
colData.intersectionPoint = reports[closest]->contact / colData.eRadius;

if (listener) {
String otherName = reports[closest]->other_object->getName();
listener->collisionOccurred(otherName);
}
}
}



// Set this to match application scale..
const float unitsPerMeter = 100.0f;

// All hard-coded distances in this function is
// scaled to fit the setting above..
const float unitScale = unitsPerMeter / 100.0f;
const float veryCloseDistance = 0.005f * unitScale; // 0.5cm if unitsPerMeter is 100

Vector3 collideWithWorld(int recursionDepth, const Vector3& pos,
const Vector3& vel, CollisionPacket& colData,
CollisionListener* listener, bool gravityStep,
const Degree& slopeSlideThresold)
{
// do we need to worry?
if (recursionDepth > 5)
return pos;

// Ok, we need to worry:
colData.velocity = vel;
colData.normalizedVelocity = vel;
colData.normalizedVelocity.normalise();
colData.basePoint = pos;
colData.foundCollision = false;

// ----------------------------
// OgreOpcode part begin
doOgreOpcodeCollision(colData, veryCloseDistance * 5, listener);
// OgreOpcode part end
// ----------------------------

// If no collision we just move along the velocity
if (colData.foundCollision == false) {
return pos + vel;
}

// *** Collision occured ***
// The original destination point
Vector3 destinationPoint = pos + vel;
Vector3 newBasePoint = pos;

// only update if we are not already very close
// and if so we only move very close to intersection..not
// to the exact spot.
if (colData.nearestDistance >= veryCloseDistance) {
Vector3 V = vel;
V.normalise();
V = V * (colData.nearestDistance - veryCloseDistance);
newBasePoint = colData.basePoint + V;
// Adjust polygon intersection point (so sliding
// plane will be unaffected by the fact that we
// move slightly less than collision tells us)
V.normalise();
colData.intersectionPoint -= veryCloseDistance * V;
}

// Determine the sliding plane
Vector3 slidePlaneOrigin = colData.intersectionPoint;
Vector3 slidePlaneNormal = newBasePoint - colData.intersectionPoint;
slidePlaneNormal.normalise();
Plane slidingPlane(slidePlaneNormal, slidePlaneOrigin);

Vector3 newDestinationPoint = destinationPoint -
slidingPlane.getDistance(destinationPoint) *
slidePlaneNormal;

// Generate the slide vector, which will become our new
// velocity vector for the next iteration
Vector3 newVelocityVector = newDestinationPoint - colData.intersectionPoint;

// Recurse:
// dont recurse if the new velocity is very small
if (newVelocityVector.length() < veryCloseDistance) {
return newBasePoint;
}

// simulate "friction"
if (gravityStep) {
// apply gravity only if slope is steep enough
const Radian tolerance = Radian(slopeSlideThresold);
Vector3 gravity = vel;
gravity.normalise();
if (slidePlaneNormal.directionEquals(-gravity, tolerance)) {
return newBasePoint;
}
}

return collideWithWorld(recursionDepth++, newBasePoint, newVelocityVector,
colData, listener, gravityStep, slopeSlideThresold);
}


Vector3 collideAndSlide(const Vector3& pos, const Vector3& vel, Real radius,
const Vector3& gravity, CollisionListener* listener,
const Degree& slopeSlideThresold)
{
CollisionPacket colData;

// Information about the move being requested: (in R3)
colData.R3Position = pos;
colData.R3Velocity = vel;

// convert simple sphere radius into ellipsoid radius
// (algorithm works with ellipsoids but for now ogreopcode works only with spheres)
colData.eRadius = Vector3(radius, radius, radius);

// calculate position and velocity in eSpace
Vector3 eSpacePosition = colData.R3Position / colData.eRadius;
Vector3 eSpaceVelocity = colData.R3Velocity / colData.eRadius;

// Iterate until we have our final position.
Vector3 finalPosition = collideWithWorld(0, eSpacePosition, eSpaceVelocity,
colData, listener, false, Degree(0));

// Add gravity pull:
if (gravity != Vector3::ZERO) {
// Set the new R3 position (convert back from eSpace to R3)
colData.R3Position = finalPosition * colData.eRadius;
colData.R3Velocity = gravity;
eSpacePosition = colData.R3Position / colData.eRadius;
eSpaceVelocity = gravity / colData.eRadius;
finalPosition = collideWithWorld(0, eSpacePosition, eSpaceVelocity,
colData, listener, true, slopeSlideThresold);
}

// Convert final result back to R3:
return finalPosition * colData.eRadius;
}

} // namespace



now you can do a sample collision detection in ofusion scene

just include those file in your project with help of the file posted earlier

you must have ogreopcode installed too

this sample its from house collision demo in ogreopcode forum and i adapted it to work with ofusion scene

hope this help people wanna do a simple collision detection with camera sliding ,without use a physics engine