Iterating through raycast reports

Night Elf

31-08-2007 23:01:52

Based on this forum post I'm trying to iterate through raycast reports like this:

for (NxOgre::RayCastHit* hit = rayCaster.mReport.begin(); hit = rayCaster.mReport.next(); )
{ /* do something */ }

But the compiler complains that begin() and next() do not return pointers:

Error 1 error C2440: 'initializing' : cannot convert from 'NxOgre::RayCastHit' to 'NxOgre::RayCastHit *' e:\Dev\Behaviours.cpp 157
Error 2 error C2440: '=' : cannot convert from 'NxOgre::RayCastHit' to 'NxOgre::RayCastHit *' e:\Dev\Behaviours.cpp 157

If I change to this:

for (NxOgre::RayCastHit* hit = &rayCaster.mReport.begin(); hit = &rayCaster.mReport.next(); )
{ /* do something */ }

now I get an error inside NxOgre:

Error 1 error C2664: 'NxOgre::RayCastHit::RayCastHit(const NxOgre::RayCastHit &)' : cannot convert parameter 1 from 'int' to 'const NxOgre::RayCastHit &' c:\libs\nxogre\nxogre\include\NxOgreContainer.h 102

So, how should I iterate through a RayCastReport?

betajaen

31-08-2007 23:25:31

for (NxOgre::RayCastHit hit = rayCaster.mReport.begin(); hit = rayCaster.mReport.next(); )
{ /* do something */ }

Night Elf

31-08-2007 23:42:00

Are you sure? next() returns NULL when it gets to the end of the container... (Can't test it right now as my machine is busy compiling)

EDIT: I tried it and it doesn't compile. I get the following error:

Error 1 error C2451: conditional expression of type 'NxOgre::RayCastHit' is illegal e:\Dev\Behaviours.cpp 157

Which is understandable as the second part of the for must evaluate to a bool or an int to be able to serve as a condition...

betajaen

01-09-2007 00:02:32

Hmm. That's really odd. It's is "RayCastHit" and not "RayCastHit*"

typedef Container<NxString, RayCastHit> RayCastReport;

I'll have a fiddle tomorrow, and see how it works. But you may have to use the std::map iterator inside the container directly.

Night Elf

01-09-2007 00:58:13

Looking a how next() is implemented

TT next() {
if (mIterator == items.end())
return NULL;
return (mIterator++)->second.t;
}


I'd say NxOgre::Container should only be used store pointers as it returns NULL when the iterator reaches the end.

betajaen

01-09-2007 09:27:16

It's used to store both, but the iterator only works with pointer containers.

TWO

24-01-2008 19:20:54

This is still not fixed in bleeding, is it?

betajaen

24-01-2008 20:01:42

Most likely I'll be replacing that with SharedList in BetajaenCC. Much better system.

lonwolf

08-02-2008 13:45:23

it has been a while since i used std::map, can any1 post a code on how to iterate with std::map or maybe you betajaen?

im trying somthing like

std::map<NxOgre::NxString,NxOgre::RayCastHit>::iterator i = rc->mReport.begin();
while(i)
{
//do something
i=rc->mReport.next();
}


but i can't compile the first line due to the fact that i forgot how to properly init a std::map container.. used it rarely anyways.. so a method to iterate through mReport can you post? i need to move all my kinematic bodies that are hit by a raycast but i can't itterate through the report atm.

any solution (even for dummies) will be grately appreciated.. it's a school project and i need to finish it asap so i can concentrate on my other exams..


hope to hearing from you soon :)
Lonwolf

edit:

full code void Pad::move_bricks(Ogre::Vector3 p)
{
NxOgre::RayCaster* rc = new NxOgre::RayCaster(p,Vector3(0,1,0),30,NxOgre::RayCaster::RCT_ALL,mCurrentScene);
std::map<NxOgre::NxString,NxOgre::RayCastHit,std::less<Ogre::_StringBase>>::iterator i = rc->mReport.begin();
while(i)
{
//do smth
i = rc->mReport.next();
}
delete rc;
}


error list

Compiling...
1>Pad.cpp
1>.\src\Pad.cpp(96) : error C2440: 'initializing' : cannot convert from 'NxOgre::RayCastHit' to 'std::_Tree<_Traits>::iterator'
1> with
1> [
1> _Traits=std::_Tmap_traits<NxOgre::NxString,NxOgre::RayCastHit,std::less<Ogre::_StringBase>,std::allocator<std::pair<const NxOgre::NxString,NxOgre::RayCastHit>>,false>
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
1>.\src\Pad.cpp(97) : error C2451: conditional expression of type 'std::_Tree<_Traits>::iterator' is illegal
1> with
1> [
1> _Traits=std::_Tmap_traits<NxOgre::NxString,NxOgre::RayCastHit,std::less<Ogre::_StringBase>,std::allocator<std::pair<const NxOgre::NxString,NxOgre::RayCastHit>>,false>
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>.\src\Pad.cpp(100) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'NxOgre::RayCastHit' (or there is no acceptable conversion)
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xtree(484): could be 'std::_Tree<_Traits>::iterator &std::_Tree<_Traits>::iterator::operator =(const std::_Tree<_Traits>::iterator &)'
1> with
1> [
1> _Traits=std::_Tmap_traits<NxOgre::NxString,NxOgre::RayCastHit,std::less<Ogre::_StringBase>,std::allocator<std::pair<const NxOgre::NxString,NxOgre::RayCastHit>>,false>
1> ]
1> while trying to match the argument list '(std::_Tree<_Traits>::iterator, NxOgre::RayCastHit)'
1> with
1> [
1> _Traits=std::_Tmap_traits<NxOgre::NxString,NxOgre::RayCastHit,std::less<Ogre::_StringBase>,std::allocator<std::pair<const NxOgre::NxString,NxOgre::RayCastHit>>,false>
1> ]


sorry for the long post :(

lonwolf

08-02-2008 14:10:03

ok i found an alternative, i hope this works (it compiles..)

NxOgre::RayCastReport::Iterator i;
for(i = rc->mReport.items.begin(); i!=rc->mReport.items.end();++i)
{
//etc
}

betajaen

08-02-2008 16:06:20

This is more "NxOgrey", because map will not be used in the future for containers:-

// With: Object*

Container<NxString, Object*> Objects;
Objects myObjects;
// ...
for (Object* object = myObjects.begin();object = myObjects.next();) {
// ...
}

// With: Object

Container<NxString, Object> Objects
Objects myObjects;
// ...
if (myObjects.count()) {
for (Object object = myObjects._begin();!myObjects._atEnd();object = myObjects._next()) {
// ...
}
}

lonwolf

08-02-2008 16:16:47

thnks for the info.. i hope i wont use map in the future cuz it gives me terrible headaches.. i've had a look at getClosestActor() and rewrote that so i can iterate through the report with my own function.. hope it helps some1, took me a while untill i've cleaned it up ..

btw any chance when the nxogre.org will go up again? it's pretty difficult to work with NxOgre this way.. im looking at the training programs, but i say a wiki would be easier.. though i haven't found the reason you closed the wiki.. anyway i'll struggle on finding these things on my own or with the forum :roll:


void Pad::move_bricks(Ogre::Vector3 p, NxString &x)
{
Vector3 dir=Vector3::ZERO;
dir.y=50;
NxOgre::RayCaster* rc = new NxOgre::RayCaster(p,dir.normalisedCopy(),30,NxOgre::RayCaster::RCT_ALL,mCurrentScene);
rc->castShape(NxOgre::RayCaster::AF_NONE);
if(rc->mReport.count()!=0)
{
NxOgre::RayCastReport::Iterator i;
for(i = rc->mReport.items.begin();i!=rc->mReport.items.end();++i)
{
Actor* a = (*i).second.t.mActor;
if(a!=0)
{
x=a->getName();
if(x[1]=='r')
{
Vector3 pos = a->getGlobalPosition();
pos.y-=3.01;
a->moveGlobalPosition(pos);
}
}
}
}
delete rc;
}


it returns the name of the last actor itterated and moves my bricks (note the b[1]=='r' <> "brick001").. it's a wierd solution, if i used dynamic bricks then they will all move crazy and the dps drops; if i changed the material, the ball would have lost cinematic energy <> velocity. Can't be static cuz i want them to drop when the first brick is destroyed.. AND the funny part is that KINEMATIC actors don't interact with gravity.. so i had to clamp the boxes 3.01 down the Y axis when the first one is destroyed..

a kinematic actor that could be affected by gravity would really simplify all this code :lol:

anyway it works, so here's a nice iteration without that std::map thingy