Game Development Community

Player Walking on Surfaces

by Demolishun · in Torque Game Engine · 12/17/2005 (2:48 pm) · 33 replies

I am working on creating a player that will walk on surfaces and match those surfaces even if they are upside down. This will be the default behavior of the game I am developing. I am looking through the player.cc class and trying to decide what keeps the orc verticle, what additional information will need to be sent accross the network, all the functions that affect the player being locked into a verticle Z rotation only, etc. If someone has already worked on this please let me know what I should be looking at and what to watch out for. I realize for matching the surfaces I need to add ray casts to determine if -z of the player is near an object. I have already implemented similar ray casts for vehicles.

Thanks

About the author

I love programming, I love programming things that go click, whirr, boom. For organized T3D Links visit: http://demolishun.com/?page_id=67

Page «Previous 1 2
#1
12/17/2005 (3:38 pm)
I'm going to post a resource for gravity shifts after the holidays that should help
#2
12/17/2005 (3:44 pm)
Okay, first status on this.
I changed a whole ton of locations that deal with rotation of the player. I added the necessary code to transfer mRot.x,y,z over the network and changed all the location where rotation is updated to allow for the x and y rotation. One problem I have found and cannot figure out just yet is unless I add this code in updateMove:
else
      {
         mRot.z += y;
         // Rotate the head back to the front, center horizontal
         // as well if we're controlling another object.
         mHead.z *= 0.5;
         if (mControlObject)
            mHead.x *= 0.5;
      }
      
// code I added
      mRot.x = 0; // fudge for now to get to be straight
      mRot.y = 0;
// end code I added
      // constrain the range of mRot.z
      while (mRot.z < 0)
         mRot.z += M_2PI;
      while (mRot.z > M_2PI)
         mRot.z -= M_2PI;

The player will stand at a slant. Even with this code I cannot change the x and y rotation in the editor from this value:
"0 1 0 57.2958"

Is there some hard fixed code somewhere in the player.cc file? Everywhere I found things like:
zRot.set(EulerF(0, 0, mRot.z));
I changed to:
zRot.set(EulerF(mRot.x, mRot.y, mRot.z));

Thanks
#3
12/17/2005 (3:45 pm)
Treb,
That sounds very cool. I would appreciate anything I can get.

Thanks
#4
12/17/2005 (4:00 pm)
I found it:
setTransform was fixed to always be upward.

Changed it to call parent version.

Still stuck absolutely verticle.

update:
this is a good thing, i can now add changes to x and y and get rotational changes.

I have added my ray casts and soone should be adding the code to change angle based upon the balance of the casts. Next step after that is attraction to the walls.
#5
12/18/2005 (1:42 pm)
Proper way to convert input rotations to mRot.x mRot.y mRot.z in player object.
I created the proper code to ray cast, but I cannot figure out for the life of me why I cannot get the rotations correct:
// z rot
         currTransform.getColumn(0, &sn);
         currTransform.getColumn(1, &sn2);
         mCross(sn, sn2, &r);
         r.normalize();
         mRot += y * r;

// y rot
         currTransform.getColumn(0, &sn);
         currTransform.getColumn(2, &sn2);
         mCross(sn, sn2, &r);
         r.normalize();
         mRot += 0 * r;
// x rot
         currTransform.getColumn(1, &sn);
         currTransform.getColumn(2, &sn2);
         mCross(sn, sn2, &r);
         r.normalize();
         mRot += 0.05 * r;


This code I got from the vehicle class, but it does not work at all. It gets all wierd when you change the z. Is this a case of mixing apples and oranges.
#6
12/18/2005 (4:39 pm)
Okay, getting closer I am using:
QuatF qRot;
qRot.set(EulerF(rot));
qRot.setMatrix(&mat);
Inside of setPosition and setRenderPosition
#7
12/19/2005 (2:07 pm)
You're working pretty hard on this so I'll throw my gravity code out there.

sceneobject.cc

ConsoleMethod( SceneObject, setGravityVec, void, 3, 3, "(Point3F scale)")
{
VectorF scale(0.f,0.f,0.f);
dSscanf(argv[2], "%g %g %g", &scale.x, &scale.y, &scale.z);
object->setGravityVec(scale);
}
ConsoleMethod( SceneObject, getGravityVec, const char*, 2, 2, "Get scaling as a Point3F.")
{
char *returnBuffer = Con::getReturnBuffer(256);
const VectorF & scale = object->getGravityVec();
dSprintf(returnBuffer, 256, "%g %g %g",
scale.x, scale.y, scale.z);
return(returnBuffer);
}
void SceneObject::setGravityVec(const Point3F & Vec)
{
mgravityvec = Vec;
}

Point3F SceneObject::getGravityVec()
{
return mgravityvec;
}

under

mObjScale.set(1,1,1);

add

mgravityvec.set(0,0,1);

sceneObject.h
under
virtual void setScale(const VectorF & scale);
add
virtual void setGravityVec(const VectorF & Vec);

Point3F getGravityVec();

under

Point3F mObjScale; ///< Object scale

add

Point3F mgravityvec; ///< gravity vec

Player.cc

replace

// Acceleration due to gravity
VectorF acc(0,0,mGravity * mGravityMod * TickSec);

with

// Acceleration due to gravity
Point3F GravityVector = getGravityVec();
VectorF acc(mGravity * mGravityMod * TickSec*GravityVector.x,mGravity * mGravityMod * TickSec*GravityVector.y,mGravity * mGravityMod * TickSec*GravityVector.z);

now in your script go

%player.setGravityVec("0.5 0.5 0.5");

this would make it pull with half power on x, y, and z.

oh yeah and %player.getGravityVec(); should return it but I'm not sure if that works.
#8
12/19/2005 (8:23 pm)
It looks like I am going to have to make some radical changes to the player code. I am in the process to change the internal rotational representation to quaternions. The euler angles are just not cutting it. I am running into gimble lock. Should have approached it that way before, but for some reason I figured dumping it to a matrix was enough. Here are some quaternion related questions:
Given this:
Point3F rot1, rot2, rot3;
rot1 = rot2 + rot3;
What is the quaternion equivalent?
QuatF rot1, rot2, rot3;
rot1 = rot2 + rot3;
(?!)
or ...
rot1 = rot2 * rot3;

I seem to think it was the latter, but cannot remember.
#9
12/19/2005 (9:40 pm)
I've been down this road before. If you want a player that can move around freely... switch to the vehicle class, that's what it's for. ;)
#10
12/20/2005 (3:12 pm)
I am concerned about the number of calculations required for a vehicle based player. Can I exclude integration from the vehicle code? I am going to need 25 to 50 characters on the screen at one time. I have seen just a couple of vehicles slow down the engine on older machines. I understand there are a ton of calculations done on standard vehicles, but I am leery of the integration function.
#11
12/20/2005 (8:30 pm)
Sure, just cut it out. The parts you care about are smoothing and networking, if I'm not mistaken.

It'll definitely be a bit of work to get it to do exactly what you want but it'll end up being a solid solution.
#12
12/21/2005 (11:09 am)
I have the player version nearly working. Currently I can walk around, but actually performing rotations causes the player to vibrate instead of rotate, but it is stable now. I think mostly it is understanding how to properly interpolate. I am going to go through the vehicle code and compare each area to modify my implementation to work correctly. Thanks for pointing me to the vehicle code. I have already played with that code a lot so it will be pretty easy to pull out what I need. If that does not work out the way I want I will start fresh from the vehicle code.
#13
12/21/2005 (11:26 am)
Frank, you will either need to change the type of collision convex the player uses (The best way) or change the way the current collision convex works. It returns faceDot, the dotProduct of the ground poly you're standing on and gravity (assumed to be z is always up) ... You'll need to add gravDot sending in the gravity vector to get a new dot product. Also, due to the z is up assumption, the Player class has no way to know what way it's facing after you start rotating. You will need to store a y-axis vector.

I completed this change to the Player class... it took me a month and a lot of heart ache. There is a ton of things that need changing.
#14
12/21/2005 (4:30 pm)
Yeah, I found a bunch of that stuff. I did not know/understand the collision convex issue (I still don't). Every time I think I am moving forward I find out some more fun stuff. This code certainly is complex.

Thanks

Edit:
I think I am going to retreat and wait for your code to come out. In the meantime I will attack the vehicle angle. I do like the idea of a collision mesh shaped like my player. I will need to readd sound triggers and the like back in, but maybe it is for the best.
#15
12/21/2005 (4:44 pm)
Yes it is.

I will talk to the guy I did the work for. he may be willing to let me slide the code changes to you... I'll see what he says
#16
12/21/2005 (8:24 pm)
Ben,
I took the hover craft code and ripped out the default update forces code and I turned on the mRigid.atRest function so it cannot integrate or run the collision checks. I think I want to turn the collision checks back on, but I am not sure what I will have to do to interface with it. More hacking will be needed for that. First I will put in the code to match terrain/objects.

Do you have any pointers for how to proceed? I will eventually figure this out, but if you have some time savers or can point to a resource or two.

Thanks
#17
12/21/2005 (9:32 pm)
To reimplement the collision for your purposes? Or to make a little thing you can fly around in 3space with minimal physics constraints? Not sure I understand what you're asking. :)
#18
12/21/2005 (10:45 pm)
I want basic collision like the player has. I am not wanting to fly, I just want to be able to climb on walls and things. The default behavior of my "player" will be to climb on any surface and be upside down even. The collision just needs to take into account the geometry, maybe using the vehicle stuff that is already there. I am messing with just adding back enough stuff in to allow the collisions to stop forward motion. I am trying to keep just enough of the physics from the vehicle code to do the basic collision.

I pulled this out of the integrator and put it in my vehicle:
// Update collision information based on our current pos.
   bool collided = false;
   mRigid.atRest = true;
   //if (!mRigid.atRest) {
   if (1){//!mRigid.atRest) {
      collided = updateCollision(dt);

      // Now that all the forces have been processed, lets       
      // see if we're at rest.  Basically, if the kinetic energy of
      // the vehicles is less than some percentage of the energy added
      // by gravity for a short period, we're considered at rest.
      // This should really be part of the rigid class...
      if (mCollisionList.count) {
         F32 k = mRigid.getKineticEnergy();
         F32 G = sVehicleGravity * dt;
         F32 Kg = 0.5 * mRigid.mass * G * G;
         if (k < sRestTol * Kg && ++restCount > sRestCount)
            mRigid.setAtRest();
      }
      else
         restCount = 0;
   }
   
   // do just the collision response stuff
   if(1)//!mRigid.atRest)
   {
      // Update angular momentum
      mRigid.angMomentum = mRigid.angMomentum + mRigid.torque * dt;
   
      // Update linear position, momentum
      mRigid.linPosition = mRigid.linPosition + mRigid.linVelocity * dt;//mRigid.delta;
      mRigid.linMomentum = mRigid.linMomentum + mRigid.force * dt;//mRigid.delta;
      mRigid.linVelocity = mRigid.linMomentum * mRigid.oneOverMass;
      
      mRigid.linVelocity.x = mRigid.linMomentum.x * mRigid.oneOverMass;
      mRigid.linVelocity.y = mRigid.linMomentum.y * mRigid.oneOverMass;
      mRigid.linVelocity.z = mRigid.linMomentum.z * mRigid.oneOverMass;
      mRigid.invWorldInertia.mulV(mRigid.angMomentum,&mRigid.angVelocity);
   }
   
   // Integrate forward
   //if (!mRigid.atRest)
   if (0)
      mRigid.integrate(dt);

This is in the function: updatePos
updateforces is empty now, but I plan on using that as my control input area by manipulating the mRigid variables to get the effects I want.
#19
12/22/2005 (10:14 am)
As a horrible hack, but something quick, what you might do is just apply forces as normal, but simply setVelocity(0,0,0) when something shows up in the collision list. It'll be the crudest possible bounding box/bounding box collision, but it's a pretty decent start, and it'll be a stable place to start developing more complex collision response with.
#20
12/22/2005 (10:48 am)
So your thinking like:
if collided == true then
setVelocity(0,0,0)

I will play with that.
Page «Previous 1 2