Conform to surface
by James Livingston · in Torque Game Engine · 02/11/2006 (10:15 am) · 13 replies
There is a thread in the examples section on this, but I'd like to link it here, hoping that someone in this forum can give some pointers.
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3148
This thread gives some excellent advice on making your player conform to surfaces.
The problem:
The engine still doesn't handle surface at angles of greater than 90deg...that is, upside down surfaces.
Also, because the bounding box of the player doesn't rotate with the player...the player::findContact function often finds the "wrong" surface you are walking on. From what I can tell, it looks at the feet properly...but used the bounding box to determine what you actually hit. Because the box doesn't rotate w/ the feet...well, you get the picture.
My thought was...ok, I'll just cast a ray down from the player, test the surface, and that will be the contact normal I use to orient my player with. EASY!
Here is what I have:
I'm not even 100% sure I am even doing the vector/matrix stuff right.
Unfortunately...this won't even run...the game just hangs. Is the castRay too time intensive to be in this function?
Thank in advance,
jc
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3148
This thread gives some excellent advice on making your player conform to surfaces.
The problem:
The engine still doesn't handle surface at angles of greater than 90deg...that is, upside down surfaces.
Also, because the bounding box of the player doesn't rotate with the player...the player::findContact function often finds the "wrong" surface you are walking on. From what I can tell, it looks at the feet properly...but used the bounding box to determine what you actually hit. Because the box doesn't rotate w/ the feet...well, you get the picture.
My thought was...ok, I'll just cast a ray down from the player, test the surface, and that will be the contact normal I use to orient my player with. EASY!
Here is what I have:
void Player::findContact(bool* run,bool* jump,VectorF* contactNormal)
{
Point3F pos;
getTransform().getColumn(3,&pos);
//trying to get a raycast down - JCL
//Position = feet? Seems lik eit.
Point3F playerPos, playerFeetPos;
MatrixF currMatrix = getTransform();
//For now, lets check down a bit further than the sTractionDistance amount.
currMatrix.mulV(VectorF(pos.x,pos.y,pos.z + mScaledBox.min.z - sTractionDistance - 1.0),&playerFeetPos);
//Let's try a raycast
RayInfo rInfo;
if (gClientContainer.castRay(playerPos, playerFeetPos, TerrainObjectType | InteriorObjectType | StaticObjectType, &rInfo))
{
F32 surfDist;
surfDist = rInfo.t; //get the surface distance
*contactNormal = rInfo.normal; //get the surface normal
}I'm not even 100% sure I am even doing the vector/matrix stuff right.
Unfortunately...this won't even run...the game just hangs. Is the castRay too time intensive to be in this function?
Thank in advance,
jc
About the author
#2
02/13/2006 (4:47 am)
Is your player rotating in other axis other than Z? If so, the calculation for playerFeetPos is pretty wrong, since it always cast a ray down in the world's Z axis. You'd need to cast a ray down in the player's Z axis if your player is rotating around.
#3
I thought I was initializing currMatrix with the player's current transformation.
I then took the player's position, moved straight down on the Z axis a little to look at the ground beneath, and multiplied that vector by currMatrix in order to get the correctly rotated position under the player.
Is that not correct?
02/13/2006 (5:01 am)
Thanks for the response, Manoel. Perhaps you could point me in the right direction?MatrixF currMatrix = getTransform(); //For now, lets check down a bit further than the sTractionDistance amount. currMatrix.mulV(VectorF(pos.x,pos.y,pos.z + mScaledBox.min.z - sTractionDistance - 1.0),&playerFeetPos);
I thought I was initializing currMatrix with the player's current transformation.
I then took the player's position, moved straight down on the Z axis a little to look at the ground beneath, and multiplied that vector by currMatrix in order to get the correctly rotated position under the player.
Is that not correct?
#4
In the meantime, I'm trying to understand how collision and such works in the engine. A nagging voice in the back of my head keeps me thinking, there's probably a very simple code change required to do this...I just don't know it yet.
I would grealy appreciate any help or direction from those in the know on this. It's a major part of what I'm trying to accomplish with Torque.
Thanks,
Craig
02/14/2006 (6:47 am)
I'm not asking for code or the work to be done on this, but I still am in need of some direction. Let me sum up what I'm trying to achieve...the ability for a player controlled object (or not player controlled) to be able to 'stick' and move on any surface I choose. Gravity would kick in if the object were in freefall. It would give a spiderman type of effect, I guess.In the meantime, I'm trying to understand how collision and such works in the engine. A nagging voice in the back of my head keeps me thinking, there's probably a very simple code change required to do this...I just don't know it yet.
I would grealy appreciate any help or direction from those in the know on this. It's a major part of what I'm trying to accomplish with Torque.
Thanks,
Craig
#5
But... tell that voice in your head to shut up, since doing what you want is far from a simple change. I'm not sure how far into it you got, but lots of collision problems arise when you rotate the player and it's bounding box in arbitrary axis. I've added support for a rotated collision box for our heavily modified player months ago, and it still has some collision bugs to this day.
The thing is that the player collision, and the whole findContact and step stuff is too specialized for a non-rotating axis-aligned box. It's hard to hack and modify it without introducing bugs. It's also hard to understand the whole logic behind of it.
Maybe you should try doing what I was told to try (but never really did, out of pure stubborness), and create a new class derived from the vehicle class, that features more general purpose collision features and in overall a more streamlined and less chaotic structure than the player, and port over features from the player class (like the whole actionThread thing) into it. I need to do that someday myself, maybe that'll address the headaches I have in every project regarding collision.
02/14/2006 (8:46 am)
Well, that mulV call should work, but you're feeding it the player's world position. If you feed it a vector point down the Z axis, it'll apply the player rotation and position to it. You can also find a transform's Z axis by doing this:transform.getColumn(2,&zAxis);
But... tell that voice in your head to shut up, since doing what you want is far from a simple change. I'm not sure how far into it you got, but lots of collision problems arise when you rotate the player and it's bounding box in arbitrary axis. I've added support for a rotated collision box for our heavily modified player months ago, and it still has some collision bugs to this day.
The thing is that the player collision, and the whole findContact and step stuff is too specialized for a non-rotating axis-aligned box. It's hard to hack and modify it without introducing bugs. It's also hard to understand the whole logic behind of it.
Maybe you should try doing what I was told to try (but never really did, out of pure stubborness), and create a new class derived from the vehicle class, that features more general purpose collision features and in overall a more streamlined and less chaotic structure than the player, and port over features from the player class (like the whole actionThread thing) into it. I need to do that someday myself, maybe that'll address the headaches I have in every project regarding collision.
#6
Something I was thinking about...
The collision box simply notifies the engine that it needs to check for collision against the player's polygons, right?
What I mean is...if I max the box big enough, outside the player, to cover the player no matter WHAT his orientation...the basic player collision should still work? All it would mean is, the engine might potentially have to do more work, because the player's bounding box covers a larger area than normal.
In findContact...it seems then that I could simply ditch all of the collision stuff, just find the surface beneath the player, and use that.
Or, am I wrong about how the bounding box works? Does it not only notify the engine that it needs to do more detailed checking in that area, but also that that really is the player's collision boundary?
Regardless, thanks Manoel. I am sure about one thing...I need to increase my understanding of how the engine works.
Thanks,
Craig
02/14/2006 (9:13 am)
Thanks for the excellent response, Manoel!Something I was thinking about...
The collision box simply notifies the engine that it needs to check for collision against the player's polygons, right?
What I mean is...if I max the box big enough, outside the player, to cover the player no matter WHAT his orientation...the basic player collision should still work? All it would mean is, the engine might potentially have to do more work, because the player's bounding box covers a larger area than normal.
In findContact...it seems then that I could simply ditch all of the collision stuff, just find the surface beneath the player, and use that.
Or, am I wrong about how the bounding box works? Does it not only notify the engine that it needs to do more detailed checking in that area, but also that that really is the player's collision boundary?
Regardless, thanks Manoel. I am sure about one thing...I need to increase my understanding of how the engine works.
Thanks,
Craig
#7
You need to implement a gravity vector, and a forward vector and the ability to rotate around an arbitrary angle.
Also, it would be best to change the collision object to an oriented bounding box. The bounding box it uses will cause issues.
02/14/2006 (9:24 am)
I completed exactly what you're trying to do. It took me a month and a half and had a couple bugs. It was very very difficult. You need to implement a gravity vector, and a forward vector and the ability to rotate around an arbitrary angle.
Also, it would be best to change the collision object to an oriented bounding box. The bounding box it uses will cause issues.
#8
Would you be able to offer any recommendation on which class I might derive from? I was planning on going with Manoel's suggestion that I use the vehicle class.
Thanks for all the feedback,
Craig
02/14/2006 (9:38 am)
Thanks for the information, Chris. Looks like I'm in for a challenge :)Would you be able to offer any recommendation on which class I might derive from? I was planning on going with Manoel's suggestion that I use the vehicle class.
Thanks for all the feedback,
Craig
#9
use the collision volume that the vehicle uses, an oriented bounding box (I think)
02/14/2006 (9:39 am)
Player Classuse the collision volume that the vehicle uses, an oriented bounding box (I think)
#10
Now it just appeared before my eyes... "v".
Lemme explain. I was using code inspired in the vehicle code to resolve intersections caused by rotations. I used findClosestState and getCollisionInfo, then using the collision results to push the object away. But it wasn't working in all cases. It failed when the objects had penetrated too much.
Then, out of the blue, I noticed the collisionState returned by findClosestState contained the interpenetration vector between both convexes: state->v. I tried just adding that to the current position, and iterating until no more states were found within the tolerance distance. Worked like a charm, and it makes it 100% impossible for the player to intersect anything. Even if you "teleport" the player into something, it'll be pushed out. I had to modify findClosestState a bit so I could pass an interest mask to it (otherwise the player would be pushed away from triggers and physical zones).
This might help someone writing out their own collision. The data contained in the collisionStateList of a convex contains everything you need to keep them from going through each other... and I never really noticed it!
02/14/2006 (11:45 am)
I just found the holy grail for collision... initially when I started dealing with the issue of resolving rotation collisions, I knew that somewhere in Torque there would be code that would tell me the interpenetration vector between two convexes. I had naver found that, and had to resort to very hackish ways to resolve the intersections generated by rotating the non unifor bounding box.Now it just appeared before my eyes... "v".
Lemme explain. I was using code inspired in the vehicle code to resolve intersections caused by rotations. I used findClosestState and getCollisionInfo, then using the collision results to push the object away. But it wasn't working in all cases. It failed when the objects had penetrated too much.
Then, out of the blue, I noticed the collisionState returned by findClosestState contained the interpenetration vector between both convexes: state->v. I tried just adding that to the current position, and iterating until no more states were found within the tolerance distance. Worked like a charm, and it makes it 100% impossible for the player to intersect anything. Even if you "teleport" the player into something, it'll be pushed out. I had to modify findClosestState a bit so I could pass an interest mask to it (otherwise the player would be pushed away from triggers and physical zones).
This might help someone writing out their own collision. The data contained in the collisionStateList of a convex contains everything you need to keep them from going through each other... and I never really noticed it!
#11
Also, if I understand what you are saying, this is a huge help to prevent the player from going "into" something. I take it you test for a collision, and if you find one...move the player "back" the way he came, until no more collisions are found?
I was looking at the collisionStateList earlier today. The code seems to be very neat, not cluttered at all. However, I do struggle at times with the lack of documentation. Several times, I found myself thinking it would be very useful to have a project to document the engine code :)
Either way, thanks for all of the information. I'm starving for understanding!
02/14/2006 (7:26 pm)
Rotation collisions...is this using a rotating bounding box, or simply collisions where one or more of the objects are rotating?Also, if I understand what you are saying, this is a huge help to prevent the player from going "into" something. I take it you test for a collision, and if you find one...move the player "back" the way he came, until no more collisions are found?
I was looking at the collisionStateList earlier today. The code seems to be very neat, not cluttered at all. However, I do struggle at times with the lack of documentation. Several times, I found myself thinking it would be very useful to have a project to document the engine code :)
Either way, thanks for all of the information. I'm starving for understanding!
#12
The one that get's instantitated inside the player class is hte only one you need to worry about for this. That one is only used for things like controlling player physics when it interacts with the ground.
02/15/2006 (3:35 am)
James there are 2 types of collision objects used by the Player class.The one that get's instantitated inside the player class is hte only one you need to worry about for this. That one is only used for things like controlling player physics when it interacts with the ground.
#13
02/15/2006 (7:23 am)
I was surprised at how usable the collisionStateList was. I have been cursing the convex class for months, pissed off at my unability to modify the player collision without making horrid hacks and introducing bugs. All of sudden, finding out that the convex class already features such clean way to deal with collisions make everything look clearer now.
Torque Owner James Livingston
Other than that, changing the code to be this instead:
RayInfo rInfo; if (gClientContainer.castRay(pos, playerFeetPos, TerrainObjectType | InteriorObjectType | StaticObjectType, &rInfo)) { F32 surfDist; surfDist = rInfo.t; //get the surface distance *contactNormal = rInfo.normal; //get the surface normal *run = *jump = true; } else { *run = *jump = false; } mContactInfo.clear(); mContactInfo.contactNormal = *contactNormal; mContactInfo.run = *run; mContactInfo.jump = *jump;Works...sort of. He has a tendency to walk on air, and still can't seem to walk underneath objects.
I think a lot of this goes back to the bounding box not rotating with the player. I'm not sure what to do at this point. I need rotating bounding boxes, I guess. Should I try to use vehicles instead? My understanding was that they are in the same boat...