Camera interacting with terrain
by Steve Self · in Torque Game Engine · 12/20/2005 (5:13 pm) · 9 replies
I've noticed this in a lot of torque games, when the camera is in 3rd person mode it sometimes "goes under" the terrain and reveals whatever is underneath. It's a small thing, but I'm fussy about that sort of stuff and I was wondering if there is any way to stop the camera from doing that.
#2
12/20/2005 (8:25 pm)
Cast a ray or otherwise make the camera collide against the terrain. For best results treat the camera as a sphere instead of a point.
#3
I guess my question is: Is it easy to change the minimum distance that the camera can be above the terrain? I'd like to make it higher. If anyone can help me figure out what to change or even what parts of it mean, I would appreciate it greatly. (Maybe this topic should be in the Engine forum now...)
12/21/2005 (12:50 pm)
I think I have discovered where the camera collision code is in the engine. I have been trying to decipher it so that I can understand what it means but that's a bit hard since I don't know C++! Anyways, the code we found is in camera.cc, starting on line 186 and going to line 210 (or 225?). Here it is:if(mode == OrbitObjectMode || mode == OrbitPointMode)
{
if(mode == OrbitObjectMode && bool(mOrbitObject))
{
// If this is a shapebase, use its render eye transform
// to avoid jittering.
GameBase *castObj = mOrbitObject;
ShapeBase* shape = dynamic_cast<ShapeBase*>(castObj);
if( shape != NULL )
{
MatrixF ret;
shape->getRenderEyeTransform( &ret );
mPosition = ret.getPosition();
}
else
{
// Hopefully this is a static object that doesn't move,
// because the worldbox doesn't get updated between ticks.
mOrbitObject->getWorldBox().getCenter(&mPosition);
}
}
setPosition(mPosition, mRot);
validateEyePoint(1.0f, &mObjToWorld);
pos = mPosition;
}
else
{
// Update pos
bool faster = move->trigger[0] || move->trigger[1];
F32 scale = mMovementSpeed * (faster + 1);
mObjToWorld.getColumn(3,&pos);
mObjToWorld.getColumn(0,&vec);
pos += vec * move->x * TickSec * scale;
mObjToWorld.getColumn(1,&vec);
pos += vec * move->y * TickSec * scale;
mObjToWorld.getColumn(2,&vec);
pos += vec * move->z * TickSec * scale;
setPosition(pos,mRot);
}I guess my question is: Is it easy to change the minimum distance that the camera can be above the terrain? I'd like to make it higher. If anyone can help me figure out what to change or even what parts of it mean, I would appreciate it greatly. (Maybe this topic should be in the Engine forum now...)
#4
Would strongly recommend getting a C++ in 21 days book or something like that, studying up a bit. :)
12/21/2005 (1:11 pm)
I think you care about validateEyePoint().Would strongly recommend getting a C++ in 21 days book or something like that, studying up a bit. :)
#5
12/21/2005 (8:42 pm)
void Camera::validateEyePoint(F32 pos, MatrixF *mat)
{
if (pos != 0)
{
// Use the eye transform to orient the camera
Point3F dir;
mat->getColumn(1, &dir);
pos *= mMaxOrbitDist - mMinOrbitDist;
// Use the camera node's pos.
Point3F startPos = getRenderPosition();
Point3F endPos;
// Make sure we don't extend the camera into anything solid
if(mOrbitObject)
mOrbitObject->disableCollision();
disableCollision();
RayInfo collision;
U32 mask = TerrainObjectType |
InteriorObjectType |
WaterObjectType |
StaticShapeObjectType |
PlayerObjectType |
ItemObjectType |
VehicleObjectType;
Container* pContainer = isServerObject() ? &gServerContainer : &gClientContainer;
if (!pContainer->castRay(startPos, startPos - dir * 2.5 * pos, mask, &collision))
endPos = startPos - dir * pos;
else
{
float dot = mDot(dir, collision.normal);
if(dot > 0.01)
{
float colDist = mDot(startPos - collision.point, dir) - (1 / dot) * CameraRadius;
if(colDist > pos)
colDist = pos;
if(colDist < 0)
colDist = 0;
endPos = startPos - dir * colDist;
}
else
endPos = startPos - dir * pos;
}
mat->setColumn(3,endPos);
enableCollision();
if(mOrbitObject)
mOrbitObject->enableCollision();
}
}Here is the code for the validateEyePoint function... I'm not sure what many variables represent though, like endPos, startPos, dir, colDist, dot, and pos, which makes it VERY hard to know what to change.
#6
You're going to have to learn to understand how to read C++ code if you want to make changes to it. I don't really have time to give an in-depth walkthrough, though perhaps someone else in the community would be willing to. If you take it a statement at a time, take notes on a seperate piece of paper, and think it through, I'm sure you'll be able to figure it out.
12/21/2005 (9:26 pm)
Thanks, I think we all know what's in that function. :)You're going to have to learn to understand how to read C++ code if you want to make changes to it. I don't really have time to give an in-depth walkthrough, though perhaps someone else in the community would be willing to. If you take it a statement at a time, take notes on a seperate piece of paper, and think it through, I'm sure you'll be able to figure it out.
#7
I have expierience with coding (or at least enough to understand the structure of C++), and I can reasonably follow the flow of the code, but I don't know what many of the variables stand for. Is there a place where I can find a "glossary" of what all variables actually mean? Thanks for all your help.
12/21/2005 (9:41 pm)
Thanks, I'll do that.I have expierience with coding (or at least enough to understand the structure of C++), and I can reasonably follow the flow of the code, but I don't know what many of the variables stand for. Is there a place where I can find a "glossary" of what all variables actually mean? Thanks for all your help.
#8
pContainer, after this line, is set to either the server or client container, depending on whether the object is a server or client object. It's never reset, so that's what it remains for the whole function.
12/22/2005 (10:12 am)
Ah... no. Basically all the variables in this function are just used for temporary storage during the course of processing. If you note what is assigned to them at each step, it's fairly easy to see what's going on, for instance:Container* pContainer = isServerObject() ? &gServerContainer : &gClientContainer;
pContainer, after this line, is set to either the server or client container, depending on whether the object is a server or client object. It's never reset, so that's what it remains for the whole function.
#9
12/22/2005 (6:42 pm)
Thanks for all your help, Ben Garney. @ anyone, it was said before that the way to solve the bug was to cast a ray or make the camera collide with the terrain/interior/collision mesh. Isn't that already done? How, in a general sense, does the script determine if the camera is colliding? Anyways, thanks for all your help with this.
Torque Owner Chris Byars
Ion Productions