wrong behaviour ogre::terrain with heightcollision

Lax

10-12-2010 10:12:04

Hi people,

I'm using OgreNewt2.0 and Newton2.26, everything works great except of one thing:

When I create an HeightField Collision of the Ogre::Terrain , then the collisionmap is correct. I can run with my Player on it and by pushing F3 I see the grid. But when I shoot an OgreNewt::BasicRaycast ray in the NEGATIVE_UNIT_Y direction (to test the height and the normal of the Player from the terrain), then I get NO HITS! When I jump on a box then I get with the ray this box as result. I've tried everything, but I don't get ray results of the TerrainBody.

here the code. This code worked with OgreNewt1.* perfectly and works with all objects besides of the terrain.


Ogre::Vector3 charPoint = Ogre::Vector3(this->getPosition().x, this->getPosition().y + 0.4f, this->getPosition().z);
OgreNewt::BasicRaycast ray(this->pOgreNewt, charPoint, charPoint + Ogre::Vector3::NEGATIVE_UNIT_Y * 500.0f, false);
OgreNewt::BasicRaycast::BasicRaycastInfo contact = ray.getFirstHit();

if (contact.getBody())
...
The body is allways NULL


and I debugged in OgreNewt and have seen that in the file: OgreNewt_RayCast.cpp in the function: BasicRaycast::BasicRaycastInfo BasicRaycast::getFirstHit() const
the raylist is empty!

Here the Body creation:


Ogre::Terrain* pTerrain = it.getNext()->instance;
OgreNewt::CollisionPtr col = OgreNewt::CollisionPtr(new OgreNewt::CollisionPrimitives::HeightField(this->pOgreNewt, pTerrain, 0));
OgreNewt::Body *pTerrainBody = new OgreNewt::Body(this->pOgreNewt, col);
pTerrainBody->attachNode(this->mAttachNode);


here some pics to show you what I mean:






Can someone please help, this is frustrating!

Thanks in advance!

Chookaa

11-12-2010 00:17:43

im pretty sure i know whats going on here, if you look in the raycast.h line 66 you'll see how a TreeCollision is handled and if you look at the TreeCollision class you'll see how the newtonRayCastCallback is implemented. well you will need to edit the HeightField class to have have that functionality and edit the RayCast class to handle it the same way it is for the TreeCollision.

hope this helps. if you get it working please post the changes for others :)

Lax

11-12-2010 15:30:21

ok I had the same thoughts. I tried serveral ways, but without success. I'm searching this error for 3 days, maybe I'm overseeing something. First I did as you told, but I hasn't worked, then I renamed the class raycast to TreeRayCast and added a new Class HeightFieldRayCast.
Here my code so far:

OgreNewt_CollisionPrimitives.h:

//! HeightField Collision
/*!
Builds a HeightField collision from raw data or directly from a OgreTerrain page

more info: http://newtondynamics.com/wiki/index.php5?title=NewtonCreateHeightFieldCollision
*/

class _OgreNewtExport HeightField : public Collision
{
public:
HeightField(const World* world): Collision(world){}
HeightField(const World* world, int width, int height, int gridsDiagonals, unsigned short *elevationMap, char *attributeMap, Ogre::Real horizontalScale, Ogre::Real verticleScale, int shapeID);
HeightField(const World* world, Ogre::Terrain *terrain, int shapeID);
~HeightField(){}

void setRayCastCallbackactive(bool active = true)
{
setRayCastCallbackactive( active, m_col );
}

//! used internally
static float _CDECL newtonRayCastCallback(float distance, float* normal, int faceId, void* userData);

private:
static void setRayCastCallbackactive( bool active , const NewtonCollision *col );
//!Used internally to create the newton Heightfield collision
//void createHeightFieldCollision(const World *world,int width,int height,int gridsDiagonals,unsigned short *elevationMap,char *attributeMap,Ogre::Real horizontalScale,Ogre::Real verticleScale,int shapeID);
};

OgreNewt_CollisionPrimitives.cpp:

HeightField::HeightField(const OgreNewt::World *world, Ogre::Terrain *terrain, int shapeID)
: Collision (world)
{
int width = terrain->getSize();
int height = width;
int gridsDiagonals = 0;

char *attributes;
unsigned short *elevations;

float *hData = terrain->getHeightData();
float verticleScale = 65535 / (terrain->getMaxHeight() - terrain->getMinHeight());
Ogre::Real horizontalScale = terrain->getWorldSize() / (terrain->getSize() - 1);

elevations = (unsigned short*) malloc (width * height * sizeof (unsigned short));
attributes = (char*) malloc (width * height * sizeof (char));
memset (attributes, 1, width * height * sizeof (char));

//HeightData reversed and mirror on X axis
int x = 0;

for (int i = width * height - 1; i >= 0; i--)
{
elevations[i-width+(x*2)+1] = unsigned short(*(hData)*verticleScale);
hData++;
x++;
if (x == width) x = 0;
}

//createHeightFieldCollision(world, width, height, gridsDiagonals, elevations, attributes, horizontalScale, float(1 / verticleScale), shapeID);
m_col = NewtonCreateHeightFieldCollision(world->getNewtonWorld(), width, height, gridsDiagonals, elevations, attributes, float(horizontalScale), float(1.0f / verticleScale), shapeID);

free (elevations);
free (attributes);
//NewtonReleaseCollision(world->getNewtonWorld(), m_col);
}

HeightField::HeightField(const OgreNewt::World *world, int width, int height, int gridsDiagonals, unsigned short *elevationMap, char *attributeMap, Ogre::Real horizontalScale, Ogre::Real verticleScale, int shapeID)
: Collision (world)
{
m_col = NewtonCreateHeightFieldCollision(world->getNewtonWorld(),width,height,gridsDiagonals,elevationMap,attributeMap,float(horizontalScale),float(verticleScale),shapeID);
}

float _CDECL HeightField::newtonRayCastCallback(float interception, float *normal, int faceId, void *userData)
{
Body* bod = ((HeightFieldRaycast*)userData)->m_heightfieldcollisioncallback_lastbody;

//! TODO: what do we need to return here?
if(!bod)
return 0;

((HeightFieldRaycast*)userData)->userCallback( bod, interception, Ogre::Vector3(normal[0], normal[1], normal[2]), faceId );

((HeightFieldRaycast*)userData)->m_heightfieldcollisioncallback_bodyalreadyadded = true;

return interception;
}

void HeightField::setRayCastCallbackactive(bool active, const NewtonCollision *col )
{
if(active)
NewtonTreeCollisionSetUserRayCastCallback( col, newtonRayCastCallback );
else
NewtonTreeCollisionSetUserRayCastCallback( col, NULL );
}

OgreNewt_RayCast.h:

/*
OgreNewt Library

Ogre implementation of Newton Game Dynamics SDK

OgreNewt basically has no license, you may use any or all of the library however you desire... I hope it can help you in any way.

by Walaber
some changes by melven

*/

#ifndef _INCLUDE_OGRENEWT_RAYCAST
#define _INCLUDE_OGRENEWT_RAYCAST


#include "OgreNewt_Prerequisites.h"
#include "OgreNewt_CollisionPrimitives.h"

// OgreNewt namespace. all functions and classes use this namespace.
namespace OgreNewt
{


//! general raycast
/*!
General class representing a raycast query in the Newton world. this class should be inherited to create specific raycast behavior.
*/
class _OgreNewtExport TreeRaycast
{
public:

//! constructor
TreeRaycast();

//! destuctor.
virtual ~TreeRaycast();

//! performs the raycast.
/*!
call after creating the object.
\param world pointer to the OgreNewt::World
\param startpt starting point of ray in global space
\param endpt ending point of ray in global space
*/
void go( const OgreNewt::World* world, const Ogre::Vector3& startpt, const Ogre::Vector3& endpt );


//! user callback pre-filter function.
/*!
This function is an optional pre-filter to completely ignore specific bodies during the raycast.
return false from this function to ignore this body, return true (default) to accept it.
*/
virtual bool userPreFilterCallback( OgreNewt::Body* body ) { return true; }

//! user callback filter function
/*! user callback function.
This function must be implemented by the user.
Newton calls this function for each body intersected by the ray. however it doesn't
necessarily go perfect cloest-to-farthest order.
return true and the callback will only be called for bodies closer to the start point than the current body.
return false and the callback will call for any other bodies, even those farther than the current one.
*/
virtual bool userCallback( OgreNewt::Body* body, Ogre::Real distance, const Ogre::Vector3& normal, int collisionID ) = 0;

friend float CollisionPrimitives::TreeCollision::newtonRayCastCallback(float distance, float *normal, int faceId, void *userData);
protected:
//! save the last OgreNewt::Body from the newtonRaycastPreFilter to use this for example the TreeCollisionRayCallback
OgreNewt::Body *m_treecollisioncallback_lastbody;

//! save if this body was already added by RayCastCallback from TreeCollision
bool m_treecollisioncallback_bodyalreadyadded;

private:

//! callback used for running the raycast itself... used internally
static float _CDECL newtonRaycastFilter(const NewtonBody* body, const float* hitNormal, int collisionID, void* userData, float intersetParam);

//! callback used for running the raycast prefilder... used internally
static unsigned _CDECL newtonRaycastPreFilter( const NewtonBody* body, const NewtonCollision* collision, void* userData );
};

//! general raycast
/*!
General class representing a raycast query in the Newton world. this class should be inherited to create specific raycast behavior.
*/
class _OgreNewtExport HeightFieldRaycast
{
public:

//! constructor
HeightFieldRaycast();

//! destuctor.
virtual ~HeightFieldRaycast();

//! performs the raycast.
/*!
call after creating the object.
\param world pointer to the OgreNewt::World
\param startpt starting point of ray in global space
\param endpt ending point of ray in global space
*/
void go( const OgreNewt::World* world, const Ogre::Vector3& startpt, const Ogre::Vector3& endpt );


//! user callback pre-filter function.
/*!
This function is an optional pre-filter to completely ignore specific bodies during the raycast.
return false from this function to ignore this body, return true (default) to accept it.
*/
virtual bool userPreFilterCallback( OgreNewt::Body* body ) { return true; }

//! user callback filter function
/*! user callback function.
This function must be implemented by the user.
Newton calls this function for each body intersected by the ray. however it doesn't
necessarily go perfect cloest-to-farthest order.
return true and the callback will only be called for bodies closer to the start point than the current body.
return false and the callback will call for any other bodies, even those farther than the current one.
*/
virtual bool userCallback( OgreNewt::Body* body, Ogre::Real distance, const Ogre::Vector3& normal, int collisionID ) = 0;

friend float CollisionPrimitives::HeightField::newtonRayCastCallback(float distance, float *normal, int faceId, void *userData);
protected:

//! save the last OgreNewt::Body from the newtonRaycastPreFilter to use this for example the HeightFieldRayCallback
OgreNewt::Body *m_heightfieldcollisioncallback_lastbody;

//! save if this body was already added by RayCastCallback from HeightFieldCollision
bool m_heightfieldcollisioncallback_bodyalreadyadded;

private:

//! callback used for running the raycast itself... used internally
static float _CDECL newtonRaycastFilter(const NewtonBody* body, const float* hitNormal, int collisionID, void* userData, float intersetParam);

//! callback used for running the raycast prefilder... used internally
static unsigned _CDECL newtonRaycastPreFilter( const NewtonBody* body, const NewtonCollision* collision, void* userData );
};

//! Basic implementation of the raycast
/*!
This class is provided for general raycast use. it returns information about all bodies hit by the ray.
*/
class _OgreNewtExport BasicRaycast : public TreeRaycast, HeightFieldRaycast
{
public:
//! simple class that represents a single raycast rigid body intersection.
class _OgreNewtExport BasicRaycastInfo
{
public:
BasicRaycastInfo();
~BasicRaycastInfo();

Ogre::Real getDistance() { return mDistance; };
OgreNewt::Body* getBody() { return mBody; };
int getCollisionId() { return mCollisionID; };
Ogre::Vector3 getNormal() { return mNormal; };
Ogre::Quaternion getNormalOrientation() { return OgreNewt::Converters::grammSchmidt(mNormal); };

Ogre::Real mDistance; //!< dist from point1 of the raycast, in range [0,1].
OgreNewt::Body* mBody; //!< pointer to body intersected with
int mCollisionID; //!< collision ID of the primitive hit by the ray (for compound collision bodies)
Ogre::Vector3 mNormal; //!< normal of intersection.

bool operator<(const BasicRaycastInfo& rhs) const
{
return mDistance < rhs.mDistance;
}
};


//! empty constructor
BasicRaycast();

//! constructor
/*!
performs a raycast, then the results can be queried from the object after creation.
\param world pointer to the OgreNewt::World
\param startpt starting point of the ray in global space
\param endpt ending point of the ray in global space
\param sorted sort the results by distance
*/
BasicRaycast( const OgreNewt::World* world, const Ogre::Vector3& startpt, const Ogre::Vector3& endpt, bool sorted);

//! perform a raycast
/*!
performs a raycast, then the results can be queried from the object after creation.
\param world pointer to the OgreNewt::World
\param startpt starting point of the ray in global space
\param endpt ending point of the ray in global space
\param sorted sort the results by distance
*/
void go( const OgreNewt::World* world, const Ogre::Vector3& startpt, const Ogre::Vector3& endpt, bool sorted);

//! destuctor.
~BasicRaycast();

//! the all-important custom callback function.
bool userCallback( Body* body, Ogre::Real distance, const Ogre::Vector3& normal, int collisionID );

// ------------------------------------------------------
// the following functions can be used to retrieve information about the bodies collided by the ray.

//! how many bodies did we hit?
int getHitCount() const;

//! retrieve the raycast info for a specific hit.
BasicRaycastInfo getInfoAt( unsigned int hitnum ) const;

//! get the closest body hit by the ray.
BasicRaycastInfo getFirstHit() const;

private:


// container for results.
typedef std::vector<BasicRaycastInfo> RaycastInfoList;

RaycastInfoList mRayList;
};


} // end NAMESPACE OgreNewt
#endif // _INCLUDE_OGRENEWT_RAYCAST

OgreNewt_RayCast.cpp:

#include "OgreNewt_stdafx.h"
#include "OgreNewt_Body.h"
#include "OgreNewt_World.h"
#include "OgreNewt_RayCast.h"
#include "OgreNewt_Tools.h"
#include "OgreNewt_Debugger.h"
#include "OgreNewt_Collision.h"


namespace OgreNewt
{
TreeRaycast::TreeRaycast() {}
TreeRaycast::~TreeRaycast() {}


void TreeRaycast::go(const OgreNewt::World* world, const Ogre::Vector3& startpt, const Ogre::Vector3& endpt )
{
if( world->getDebugger().isRaycastRecording() )
{
world->getDebugger().addRay(startpt, endpt);
}

m_treecollisioncallback_lastbody = NULL;


// perform the raycast!
NewtonWorldRayCast( world->getNewtonWorld(), (float*)&startpt, (float*)&endpt, OgreNewt::TreeRaycast::newtonRaycastFilter, this, OgreNewt::TreeRaycast::newtonRaycastPreFilter );

m_treecollisioncallback_lastbody = NULL;

}

float _CDECL TreeRaycast::newtonRaycastFilter(const NewtonBody* body, const float* hitNormal, int collisionID, void* userData, float intersectParam)
{
// get our object!
TreeRaycast* me = (TreeRaycast*)userData;

Body* bod = (Body*)NewtonBodyGetUserData( body );
const World* world = bod->getWorld();
Ogre::Vector3 normal = Ogre::Vector3( hitNormal[0], hitNormal[1], hitNormal[2] );


if( me->m_treecollisioncallback_bodyalreadyadded)
return intersectParam;




if( world->getDebugger().isRaycastRecording() && world->getDebugger().isRaycastRecordingHitBodies() )
{
world->getDebugger().addHitBody(bod);
}


if (me->userCallback( bod, intersectParam, normal, collisionID ))
return intersectParam;
else
return 1.1f;

}

unsigned _CDECL TreeRaycast::newtonRaycastPreFilter(const NewtonBody *body, const NewtonCollision *collision, void* userData)
{
// get our object!
TreeRaycast* me = (TreeRaycast*)userData;

Body* bod = (Body*)NewtonBodyGetUserData( body );
const World* world = bod->getWorld();


me->m_treecollisioncallback_bodyalreadyadded = false;
me->m_treecollisioncallback_lastbody = bod;


if (me->userPreFilterCallback( bod ))
return 1;
else
{

if( world->getDebugger().isRaycastRecording() && world->getDebugger().isRaycastRecordingHitBodies() )
{
world->getDebugger().addDiscardedBody(bod);
}

return 0;
}
}

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

HeightFieldRaycast::HeightFieldRaycast() {}
HeightFieldRaycast::~HeightFieldRaycast() {}


void HeightFieldRaycast::go(const OgreNewt::World* world, const Ogre::Vector3& startpt, const Ogre::Vector3& endpt )
{
if( world->getDebugger().isRaycastRecording() )
{
world->getDebugger().addRay(startpt, endpt);
}


m_heightfieldcollisioncallback_lastbody = NULL;

// perform the raycast!
NewtonWorldRayCast( world->getNewtonWorld(), (float*)&startpt, (float*)&endpt, OgreNewt::HeightFieldRaycast::newtonRaycastFilter, this, OgreNewt::HeightFieldRaycast::newtonRaycastPreFilter );


m_heightfieldcollisioncallback_lastbody = NULL;
}

float _CDECL HeightFieldRaycast::newtonRaycastFilter(const NewtonBody* body, const float* hitNormal, int collisionID, void* userData, float intersectParam)
{
// get our object!
HeightFieldRaycast* me = (HeightFieldRaycast*)userData;

Body* bod = (Body*)NewtonBodyGetUserData( body );
const World* world = bod->getWorld();
Ogre::Vector3 normal = Ogre::Vector3( hitNormal[0], hitNormal[1], hitNormal[2] );


if(me->m_heightfieldcollisioncallback_bodyalreadyadded)
return intersectParam;




if( world->getDebugger().isRaycastRecording() && world->getDebugger().isRaycastRecordingHitBodies() )
{
world->getDebugger().addHitBody(bod);
}


if (me->userCallback( bod, intersectParam, normal, collisionID ))
return intersectParam;
else
return 1.1f;

}

unsigned _CDECL HeightFieldRaycast::newtonRaycastPreFilter(const NewtonBody *body, const NewtonCollision *collision, void* userData)
{
// get our object!
HeightFieldRaycast* me = (HeightFieldRaycast*)userData;

Body* bod = (Body*)NewtonBodyGetUserData( body );
const World* world = bod->getWorld();



me->m_heightfieldcollisioncallback_bodyalreadyadded = false;
me->m_heightfieldcollisioncallback_lastbody = bod;

if (me->userPreFilterCallback( bod ))
return 1;
else
{

if( world->getDebugger().isRaycastRecording() && world->getDebugger().isRaycastRecordingHitBodies() )
{
world->getDebugger().addDiscardedBody(bod);
}

return 0;
}
}



//--------------------------------
BasicRaycast::BasicRaycastInfo::BasicRaycastInfo()
{
mBody = NULL;
mDistance = -1.0;
mNormal = Ogre::Vector3::ZERO;
}

BasicRaycast::BasicRaycastInfo::~BasicRaycastInfo() {}


BasicRaycast::BasicRaycast() {}


BasicRaycast::BasicRaycast(const OgreNewt::World* world, const Ogre::Vector3& startpt, const Ogre::Vector3& endpt, bool sorted)
: TreeRaycast(), HeightFieldRaycast()
{
go( world, startpt, endpt, sorted );
}


void BasicRaycast::go(const OgreNewt::World* world, const Ogre::Vector3& startpt, const Ogre::Vector3& endpt, bool sorted)
{
// clean the list each time this function is called this way it can be re used for multiple casting.
mRayList.clear();
TreeRaycast::go( world, startpt, endpt );
HeightFieldRaycast::go( world, startpt, endpt );
if( sorted )
{
std::sort(mRayList.begin(), mRayList.end());
}
}


BasicRaycast::~BasicRaycast() {}


int BasicRaycast::getHitCount() const { return (int)mRayList.size(); }


BasicRaycast::BasicRaycastInfo BasicRaycast::getFirstHit() const
{
//return the closest hit...
BasicRaycast::BasicRaycastInfo ret;

Ogre::Real dist = Ogre::Math::POS_INFINITY;

RaycastInfoList::const_iterator it;
for (it = mRayList.begin(); it != mRayList.end(); it++)
{
if (it->mDistance < dist)
{
dist = it->mDistance;
ret = (*it);
}
}


return ret;
}


BasicRaycast::BasicRaycastInfo BasicRaycast::getInfoAt( unsigned int hitnum ) const
{
if (hitnum < mRayList.size())
{
return mRayList.at(hitnum);
}
else
{
BasicRaycast::BasicRaycastInfo emptyInfo;

return emptyInfo;
}
}

bool BasicRaycast::userCallback( OgreNewt::Body* body, Ogre::Real distance, const Ogre::Vector3& normal, int collisionID )
{
// create a new infor object.
BasicRaycast::BasicRaycastInfo newinfo;

newinfo.mBody = body;
newinfo.mDistance = distance;
newinfo.mNormal = normal;
newinfo.mCollisionID = collisionID;

mRayList.push_back( newinfo );

return false;
}

} // end NAMESPACE OgreNewt

Chookaa

11-12-2010 22:51:48

yep your on the right track, but your not going to be able to fix it till the newton lib is updated to include NewtonHeightFieldCollisionCallback and NewtonHeightFieldCollisionSetUserRayCastCallback. i've already put in a request for these http://newtondynamics.com/forum/viewtop ... =10&t=6323

while we're at it is there anything else that needs addressing with the OgreNewt Heightfield class? cross platform support comes to mind. might as well fix it now if there is

Lax

12-12-2010 10:08:15

ok thanks for making the request!
As far as I'm concerned that's everything that needs to be done at the moment . Looks like we have to wait for the new version :D

Chookaa

19-12-2010 01:31:10

newton 2.27 is now available which features the update. let me know how you go with it.

Lax

19-12-2010 14:30:28

Excellent! I will test It this week and post the results.

Lax

23-12-2010 11:12:44

Ok, I'm completely stucked with the new newton2.27 version. They changed something and now the function setRayCastCallbackactive in the treecollision class doesn't work anymore:


void TreeCollision::setRayCastCallbackactive(bool active, const NewtonCollision *col )
{
if(active)
NewtonTreeCollisionSetUserRayCastCallback( col, newtonRayCastCallback /*now newton wants "NewtonCollisionTreeRayCastCallback" type I tried to convert etc. but nothing worked so far*/);
else
NewtonTreeCollisionSetUserRayCastCallback( col, NULL );
}


Have you any idea, of how do get this worked?

Chookaa

24-12-2010 06:03:37

yep i knew this would come up :) i actually don't use OgreNewt i have my own incarnation of it, but before i fixed mine to work i made sure OgreNewt compiled for me. julio added the body and collision to the treecollision callback. if you have a look at the prototypes in newton.h you'll see it. so for treecollision in OgreNewt line 336 of OgreNewt_CollisionPrimitives.h should read

static float _CDECL newtonRayCastCallback (const NewtonBody* const body, const NewtonCollision* const treeCollision, dFloat interception, dFloat* normal, int faceId, void* userData);

don't forget to update the .cpp to suit and the same for OgreNewt_Raycast.h line 66.

i was just waiting to see how you went with it before posting a patch for OgreNewt.

also i havent yet checked if NewtonWorldGetVersion show's the correct version as the changes he made are interface breaking and will need a version check implemented in OgreNewt for proper backward compatibility.

another thing i had to do was rerun a build on dMath and dJointLibrary, i loaded the projects up separatley and i built dMath first then i had to update the linker for dJointLibrary to find dMath.

Lax

24-12-2010 23:32:04

Hey, I've got it compiled without error, but I still get no contact with the terrain. For the treecollision the contact works.
see code in: OgreNewt_CollisionPrimitives.cpp

float _CDECL HeightField::newtonRayCastCallback(const NewtonBody* const body, const NewtonCollision* const heightFieldCollision, dFloat interception, int row, int col, dFloat* normal, int faceId, void* usedData)
{
Body* bod = ((HeightFieldRaycast*)usedData)->m_heightfieldcollisioncallback_lastbody;

//! TODO: what do we need to return here?
if(!bod)
return 0;

((HeightFieldRaycast*)usedData)->userCallback( bod, interception, Ogre::Vector3(normal[0], normal[1], normal[2]), faceId );

((HeightFieldRaycast*)usedData)->m_heightfieldcollisioncallback_bodyalreadyadded = true;

return interception;
}

void HeightField::setRayCastCallbackactive(bool active, const NewtonCollision *col )
{
if(active)
NewtonHeightFieldSetUserRayCastCallback(col, newtonRayCastCallback);
else
NewtonHeightFieldSetUserRayCastCallback(col, NULL);
}


and in OgreNewt_RayCast.h:

friend float CollisionPrimitives::HeightField::newtonRayCastCallback(const NewtonBody* const body, const NewtonCollision* const heightFieldCollision, dFloat interception, int row, int col, dFloat* normal, int faceId, void* usedData);


I changed everything important in the other *.h files too.

Chookaa

25-12-2010 02:58:27

i pretty much left Raycast as it was except for declaring the friend function like you did and in my HeightField class i have


float _CDECL HeightField::newtonRayCastCallback(const NewtonBody* const body, const NewtonCollision* const heightField, dFloat interception, int row, int col, dFloat* normal, int faceId, void* userData)
{
NewtonBody* bod = NewtonBodyGetUserData(body);

((Raycast*)userData)->userCallback( bod, interception, Ogre::Vector3(normal[0], normal[1], normal[2]), faceId );

((Raycast*)userData)->m_treecollisioncallback_bodyalreadyadded = true;

return interception;
}


sorry im not that much help atm, my vs2010 crashed and killed every one of my project files that were loaded. it didn't loose any source files just the project files became corrupt and wont load. i'll be a couple of days sorting things back to vs2008 as vs2010 is proving to be more hassle than its worth atm. it's nicer to look at but intellisense is slow and the constant crashes and BSOD's are driving me nuts.

Lax

25-12-2010 10:44:05

Does the heightfield raycast contact working to you?
Concerning your crash. I could send you my vs2010 project with ogrenewt2_0.
Because I don't know what to do yet. I don't see whats wrong. I did with the heightfieldcollision raycast, like with treecollision raycast, but only the treecollision raycast works like earlier.

Lax

25-12-2010 16:20:51

Ok, It works! It worked before but I only get results if I move above the terrain, because of that I didn't realize It.
Thanks for your help Chookaa

Chookaa

25-12-2010 23:57:19

yep it works for me.

i didnt create a HeightField raycast i just added

friend float CollisionPrimitives::HeightField::newtonRayCastCallback(const NewtonBody* const body, const NewtonCollision* const heightFieldCollision, dFloat interception, int row, int col, dFloat* normal, int faceId, void* usedData);



re: crash, i got most of my stuff working again, but now with vs2008, i'll give vs2010 a miss till a service pack comes out for it.

Chookaa

26-12-2010 00:00:10

Ok, It works! It worked before but I only get results if I move above the terrain, because of that I didn't realize It.
Thanks for your help Chookaa


sound like you just need to make the start point of your ray a little bit higher?

Lax

28-12-2010 10:30:45

ok now It works perfectly!

Lax

06-01-2011 19:47:16

Hi Chookaa,

could you send me your solution in OgreNewt please?
After a long time of testing I'm now beginning to get scared. After a while when I'm testing my simulation and compile, test, compile... I get no Rayhits like before!!
This afternoon everything works perfect and I hat nothing manipulated with the terrain for a while. And now nothing works.
I have no clue what the reason is for this.

Lax

08-01-2011 12:22:55

Ok this makes me crazy. After long testing it is for me obvious, that the heighfieldraycast is faulty!! When I add my Debuglabels to show the player height from the terrain, then It works, when I remove them, It doesnt work. When I rename the function that calulates the ray and remove the debuglabels --> It works. When I'm directed in the Ogre::Vector3::NEGATIVE_UNIT_Z direction (north) then it doesn't work. When vsync is enabled It doesn't work. Then I renamed t

This is sooo frustrating. I first thought, that I made an error somehow. But now I see that It is purely arbitrary!

But raycast on all other objects works!

millahjovich

04-07-2016 12:06:49

im pretty sure i know whats going on here, if you look in the raycast.h line 66 you'll see how a TreeCollision is handled and if you look at the TreeCollision class you'll see how the newtonRayCastCallback is implemented. well you will need to edit the HeightField class to have have that functionality and edit the RayCast class to handle it the same way it is for the TreeCollision.

Lax

02-09-2016 10:56:24

Hi millahjovich,

please could you share your fix for that issue?

Regards
Lax

Root13

02-11-2016 13:06:58

And what about vs2013, has anyone tried with it?

Lax

09-11-2016 20:27:05

You mean the usage of Visual Studio 2013 (v120) plattform toolset, not really, because I had a lot of dependencies which are only compatible with v110. I'm waiting for the new Ogre 2.1 version and maybe I will compile everything including OgreNewt with newer plattform toolsets.