Container::castRay question
by Dumbledore · in Torque Game Engine · 05/20/2008 (8:52 am) · 15 replies
Hello. I'm new, but maybe someone can help me.
Here's my code:
Now, every time I click on a Projectile, it ri.object.getType() == TerrainObjectType.
Why is this?
My guess is it has to do with castRay only returning the first intersection it detects with an object that matches the typeMask parameter. So if this is the case than how can I specify for it to look top to bottom rather than bottom to top or whatever it is doing now?
Here is the rest of the code:
Here's my code:
bool hit = gClientContainer.castRay(startPnt, endPnt, TerrainObjectType | PlayerObjectType | StaticShapeObjectType | ProjectileObjectType, &ri);
Now, every time I click on a Projectile, it ri.object.getType() == TerrainObjectType.
Why is this?
My guess is it has to do with castRay only returning the first intersection it detects with an object that matches the typeMask parameter. So if this is the case than how can I specify for it to look top to bottom rather than bottom to top or whatever it is doing now?
Here is the rest of the code:
bool GuiRTSTSCtrl::collide(const Gui3DMouseEvent & event, CollisionInfo & info)
{
// turn off the collision with the control object
SceneObject * controlObj = NULL; //getControlObject(); // Get this somehow
if(controlObj)// this line is useless...
controlObj->disableCollision();
//
Point3F startPnt = event.pos;
// It seems like this next line attempts to cast a ray in the direction of the mouse click position 500 meters long.
Point3F endPnt = event.pos + event.vec * 500.f; // bjgtodo - figure out better value for this
//
RayInfo ri;
bool hit;
// Select Missiles Patch: Change start here.
hit = gClientContainer.castRay(startPnt, endPnt, TerrainObjectType | PlayerObjectType | StaticShapeObjectType
| ProjectileObjectType, &ri); // added ProjectileObjectType
// Select Missiles Patch: End change here.
if(controlObj) // this line is useless...
controlObj->enableCollision();
//
if(hit)
{
RTSConnection* conn = RTSConnection::getServerConnection();
// Select Missiles Patch: Change start here.
RTSUnit* unit = dynamic_cast<RTSUnit*>(ri.object);
// End Missiles Patch: Change start here.
if ( !unit || conn->isUnitVisible(unit) ) // if the unit is not a RTSUnit or if the unit is visible.
{
info.pos = ri.point;
info.obj = ri.object;
info.normal = ri.normal;
//info.start = event.pos;
AssertFatal(info.obj, "GuiSquadTSCtrl::collide - client container returned non SceneObject");
AssertFatal(info.obj->isClientObject(), "Non server object!");
}
//-----------------------Begin Bug Fix: http://www.garagegames.com/mg/forums/result.thread.php?qt=23267
else if( unit && !conn->isUnitVisible(unit) ) // Or else if it IS an RTSUnit, but its not visible...
{
hit = gClientContainer.castRay(startPnt, endPnt, TerrainObjectType | StaticShapeObjectType, &ri);
if(hit)
{
info.pos = ri.point;
info.obj = ri.object;
info.normal = ri.normal;
//info.start = event.pos;
AssertFatal(info.obj, "GuiSquadTSCtrl::collide - client container returned non SceneObject");
AssertFatal(info.obj->isClientObject(), "Non server object!");
}
}
//-----------------------End Bug Fix
else
{
hit = false;
}
}
return(hit);
}
#2
Secondly, it's possible that the Projectile does not exist on the client scenegraph, but I assumed it does because it renders. Also does setting its netmask to scopeAlways not make the projectile get ghosted to the client (and thus get added to the gClientContainer)?
This is of course from the RTSSK which doesn't support Projectiles. The creators of the RTSSK assumed that for most cases RTSUnit derivatives would suffice and I've noticed that most of the RTS code is specific to RTSUnit, but I'm doing my best to make the RTSSK congenial to all SceneObjects. I have no idea how deep the dependence on RTSUnit stretches, I can only hope that I don't have to completely rewrite the RTSSK.
05/20/2008 (10:02 am)
Thanks James for your input, but I have a question. You say the event.pos should be the camera position. I thought the event.pos would be the position that the mouse click occured at. Secondly, it's possible that the Projectile does not exist on the client scenegraph, but I assumed it does because it renders. Also does setting its netmask to scopeAlways not make the projectile get ghosted to the client (and thus get added to the gClientContainer)?
This is of course from the RTSSK which doesn't support Projectiles. The creators of the RTSSK assumed that for most cases RTSUnit derivatives would suffice and I've noticed that most of the RTS code is specific to RTSUnit, but I'm doing my best to make the RTSSK congenial to all SceneObjects. I have no idea how deep the dependence on RTSUnit stretches, I can only hope that I don't have to completely rewrite the RTSSK.
#3
You could try some debug-rendering to show the startpoint-endpoint line when you click. You might try using gDebugDraw for this--its very handy. If the rendered line goes where you expect and right through the object you clicked but without the raycast hitting it, that will give you at least some information.
You may need to remove some comments in debugDraw.h so that ENABLE_DEBUGDRAW is defined. And include debugDraw.h in your cpp file. Then you might add something like this...
If it is rendering then it should exist in the client sceneGraph. Setting it to scopeAlways should do this.
gClientContainer is not defined in the Torque codebase I am working on ( although it probably is for you if you are using it ), anyway, just for testing purposes you could try changing it to:
or even (if running singleplayer):
I do not own a RTSSK license ( although I always wanted to ). So I can't say much on that subject.
05/20/2008 (10:24 am)
I was looking at EditTSCtrl::make3DMouseEvent, and I believe the pos is the camera position and the event.vec represents the direction that you have clicked. You could try some debug-rendering to show the startpoint-endpoint line when you click. You might try using gDebugDraw for this--its very handy. If the rendered line goes where you expect and right through the object you clicked but without the raycast hitting it, that will give you at least some information.
You may need to remove some comments in debugDraw.h so that ENABLE_DEBUGDRAW is defined. And include debugDraw.h in your cpp file. Then you might add something like this...
if ( gDebugDraw )
{
gDebugDraw->drawLine( startPoint, endPoint, ColorF(0,1,0,1) );
gDebugDraw->setLastTTL( 7000 );
}If it is rendering then it should exist in the client sceneGraph. Setting it to scopeAlways should do this.
gClientContainer is not defined in the Torque codebase I am working on ( although it probably is for you if you are using it ), anyway, just for testing purposes you could try changing it to:
gClientSceneGraph->getContainer()
or even (if running singleplayer):
if ( gServerSceneGraph ) gServerSceneGraph->getContainer()
I do not own a RTSSK license ( although I always wanted to ). So I can't say much on that subject.
#4
05/20/2008 (10:26 am)
I managed to answer my own question about the event.pos equalling the camera's position. void EditTSCtrl::make3DMouseEvent(Gui3DMouseEvent & gui3DMouseEvent, const GuiEvent & event)
{
(GuiEvent&)(gui3DMouseEvent) = event;
// get the eye pos and the mouse vec from that...
Point3F sp(event.mousePoint.x, event.mousePoint.y, 1);
Point3F wp;
unproject(sp, &wp);
gui3DMouseEvent.pos = smCamPos;
gui3DMouseEvent.vec = wp - smCamPos;
gui3DMouseEvent.vec.normalize();
}
#5
Now that I think of it, I bet you are missing the "setCollisionMask" line, as it would cause exactly your problem...
05/20/2008 (10:34 am)
Make sure your projectile onAdd is doing the following ( as a minimum ):if ( !Parent::onAdd() ) // If this is not called the object's worldbox will not be initialized return false; // ( among other things ) setCollisionMask(getTypeMask()); // Required for collisions to occur. addToScene(); // same thing...
Now that I think of it, I bet you are missing the "setCollisionMask" line, as it would cause exactly your problem...
#6
05/20/2008 (10:55 am)
By the way, you just posted the same thing three times '-)
#7
But thank you James.
setCollisionMask(getTypeMask()); // Required for collisions to occur.
This is indeed not present in my Projectile::onAdd().
However addToScene() is there, and the projectile collides and explodes with other objects in the scene. I'm still searching for the cause. I will try gDebugDraw.
When I try to add setCollisionMask i get compiler error "setCollisionMask: identifier not found." Maybe the RTSSK doesn't use this?
EDIT: setCollisionMask is not used in TGE 1.52 either, in the Projectile::onAdd() method.
05/20/2008 (11:21 am)
I have no idea why it posted 3 times. But thank you James.
setCollisionMask(getTypeMask()); // Required for collisions to occur.
This is indeed not present in my Projectile::onAdd().
However addToScene() is there, and the projectile collides and explodes with other objects in the scene. I'm still searching for the cause. I will try gDebugDraw.
When I try to add setCollisionMask i get compiler error "setCollisionMask: identifier not found." Maybe the RTSSK doesn't use this?
EDIT: setCollisionMask is not used in TGE 1.52 either, in the Projectile::onAdd() method.
#8
05/20/2008 (11:33 am)
SetCollisionMask is a virtual method of ISceneObject in the codebase I am working on. You can delete your duplicate posts by clicking on the trash-can icon.
#9
I see this code:
if (bool(mDataBlock->projectileShape) == true)
mObjBox = mDataBlock->projectileShape->bounds;
Which insinuates a .dts file can define its own bounds (Box3F)?
If so, can I use TorqueShowTool to check out the bounding box in the model?
05/20/2008 (11:34 am)
This may be a collision mesh issue. I noticed that my projectile only collides with other objects when its center touches them. Perhaps I can't click my projectile because I can never hit it dead center. I see this code:
if (bool(mDataBlock->projectileShape) == true)
mObjBox = mDataBlock->projectileShape->bounds;
Which insinuates a .dts file can define its own bounds (Box3F)?
If so, can I use TorqueShowTool to check out the bounding box in the model?
#10
click "display properties" on the left-side menu
click the "render" tab
check "render collision meshes"
05/20/2008 (11:41 am)
Yes you can. I don't actually have any models with a collision mesh to test this, but it looks like you would do...click "display properties" on the left-side menu
click the "render" tab
check "render collision meshes"
#11
05/20/2008 (12:23 pm)
I'm pretty sure projectiles have their collision meshes disabled by default, because they collide with the world using a simple raycast. If you want rays to collide with projectiles you'll have to modify the projectile code to submit a Convex.
#12
EDIT: actually never mind, that was enough info... i figured it out lol.
05/20/2008 (12:41 pm)
Okay Dan, that sounds right, but I don't know what you mean by "submit a convex". I just need a little more help than that ;)EDIT: actually never mind, that was enough info... i figured it out lol.
#13
Does there have to be a bounding box defined in the .dts shape and then do I also have to write code to use it in the projectile? Is that how this works?
05/20/2008 (4:29 pm)
Alright this Convex collision stuff is extremely confusing to a newbie like me. Does there have to be a bounding box defined in the .dts shape and then do I also have to write code to use it in the projectile? Is that how this works?
#14
Note: I thought the projectile class was of your own creation, if I knew it was the stock projectile class I might have though of that ( doh ), thanks Dan.
05/21/2008 (9:55 am)
It looks like you might have this working now, reading your other thread. Is that correct, or you have any other questions?Note: I thought the projectile class was of your own creation, if I knew it was the stock projectile class I might have though of that ( doh ), thanks Dan.
#15
Also this projectile is of my own design, but it does derive from Projectile ;)
Thanks again.
05/24/2008 (11:25 am)
Yes I figured it out, but Dan threw me a real curve ball. There was no need to even consider "submitting a convex" you simply override the castRay() method within your class that derives from SceneObject to implement the ray "collision detection". AAlso this projectile is of my own design, but it does derive from Projectile ;)
Thanks again.
Associate James Ford
Sickhead Games
Does your projectile exist on the client scenegraph? Is your projectile collision working properly with other objects? Are you getting any strange values for event.pos?
I have noticed that raycasts done in this way do not always hit object that you appeared to click on, especially if you are some distance from the object or it is relatively small on your screen. If you try zooming the camera in very close and clicking at multiple points within your projectile object -- can you ever get it to hit?