Camera Collision Detection
Camera Collision Detection
I am creating a third person game and I'm not sure how to limit the camera so you cant see through walls, objects, etc. I already have the collision detection working fine for my character. How can I limit the camera movement? I am fairly new at the whole game creating process. Thanks
Well first get your third person camera working without this
Then, in your update or where ever, you can create a ray/line from the character's position to the *desired* camera position. Then collide this ray with the scenery, and the closest collision point to the character is the *actual* camera position.
Then, in your update or where ever, you can create a ray/line from the character's position to the *desired* camera position. Then collide this ray with the scenery, and the closest collision point to the character is the *actual* camera position.
Code: Select all
// Ray from player to camera
core::line3df camRay = core::line3df(playerPos, desiredCameraPos);
// not used
core::triangle3df triangle;
// Collide the ray with your triangleSelector. If a collision occurs
// then desiredCameraPos is set to the collision point
smgr->getSceneCollisionManager()->getCollisionPoint(camRay, triangleSelector, desiredCameraPos, triangle);
What do their names suggest?
playerPos is obviously the position of your player, define it yourself.
desiredCameraPos is the current position of the camera, where it really wants to be based on your third person camera setup, define it yourself.
Also, you should do the collision test in the opposite direction, not from camera to player but from player to camera because if there are two objects inbetween the camera and the player, casting the line from camera to player will only detect the collision with the first object and will mean the second object will block the view. If you do it backwards, from player to camera, it will find the farthest point from the player that the camera can be placed without being blocked by any objects.
Of course if the resulting position is 'too close' to the player, e.g. the player mesh is now blocking the view or you can't see the player mesh (and you want to be able to at all times) then you'd have to do some extra work like rotate the camera around a bit to find some free space.
playerPos is obviously the position of your player, define it yourself.
desiredCameraPos is the current position of the camera, where it really wants to be based on your third person camera setup, define it yourself.
Also, you should do the collision test in the opposite direction, not from camera to player but from player to camera because if there are two objects inbetween the camera and the player, casting the line from camera to player will only detect the collision with the first object and will mean the second object will block the view. If you do it backwards, from player to camera, it will find the farthest point from the player that the camera can be placed without being blocked by any objects.
Of course if the resulting position is 'too close' to the player, e.g. the player mesh is now blocking the view or you can't see the player mesh (and you want to be able to at all times) then you'd have to do some extra work like rotate the camera around a bit to find some free space.
First, I am a total Noob at all this so bear with me. Their names do represent the positions of the player and camera. So when I name them do I have to link the player and camera position to the names of the player and camera nodes?
Also, is the collision already not from player to camera?
Here is the code I have so far if this will help at all:
Also, is the collision already not from player to camera?
Here is the code I have so far if this will help at all:
Code: Select all
#include <irrlicht.h>
#include <math.h>
#include <iostream>
#define PI (3.14159265)
#define radtodeg (180.0/PI)
#define degtorad (PI/180.0)
using namespace irr;
IrrlichtDevice* device = 0;
scene::IAnimatedMeshSceneNode* hero = 0;
//Camera rotation
float camX=-90, camY=40, camDistance=150 /*this one is a distance */, test=0;
//Resolution declaration
int width=1024,height=768,depth=32;
//Key states
bool up = false;
bool down = false;
bool right = false;
bool left = false;
class charControl : public IEventReceiver
{
public:
virtual bool OnEvent(SEvent event)
{
//Get key states
if (event.EventType == EET_KEY_INPUT_EVENT)
{
if(event.KeyInput.Key==KEY_KEY_W)
if(event.KeyInput.PressedDown)
hero->setMD2Animation(scene::EMAT_RUN);
else
hero->setMD2Animation(scene::EMAT_STAND);
switch(event.KeyInput.Key)
{
case KEY_KEY_W: up = event.KeyInput.PressedDown; break;
case KEY_KEY_S: down = event.KeyInput.PressedDown; break;
case KEY_KEY_A: left = event.KeyInput.PressedDown; break;
case KEY_KEY_D: right = event.KeyInput.PressedDown; break;
}
//return true;
}
if (event.EventType == EET_MOUSE_INPUT_EVENT)
{
camX+=(event.MouseInput.X-width/2)*0.1;//0.5
camY+=(event.MouseInput.Y-height/2)*0.1;//0.5
if (event.MouseInput.Event == EMIE_MOUSE_WHEEL) camDistance- =event.MouseInput.Wheel*7;
//Limit the movement
if (camDistance<0) camDistance=0.1;
if (camY>60) camY=60; //85
if (camY<0) camY=0;
}
return false;
}
};
int main(int argc, char *argv[])
{
//check screen dimensions from arguments
if(argc==3)
if(strcmp(argv[1],"-screen")==0)
{
sscanf(argv[2],"%dx%dx%d",&width,&height,&depth);
}
// create device
charControl receiver;
// create device and exit if creation failed
IrrlichtDevice* device= createDevice(video::EDT_OPENGL, core::dimension2d<s32>(width,height),depth,true,true,true,&receiver);
//IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480),depth,false,false,false,&receiver);
if (device == 0) return 1; // could not create selected driver.
// set caption & hide cursor
device->setWindowCaption(L"Subversion");
device->getCursorControl()->setVisible(false);
device->getCursorControl()->setPosition(width/2,height/2); //center cursor
// create scenes
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
// load the scene
smgr->loadScene("scenes/level1.irr");
scene::ISceneNode* node = node=smgr->getSceneNodeFromId(0);
scene::IAnimatedMesh* mesh = smgr->getMeshCache()->getMeshByIndex(0);
scene::ITriangleSelector* selector = 0;
selector = smgr->createOctTreeTriangleSelector(mesh->getMesh(0), node, 128);
// add a user controlled camera
scene::ICameraSceneNode* camera =
camera = smgr->addCameraSceneNode(0);
camera->setPosition(core::vector3df(-20,20,-20));
// add animated hero.
video::SMaterial material;
material.Textures[0] = driver->getTexture("characters/sydney/texture.bmp");
material.Lighting = true;
//scene::IAnimatedMeshSceneNode* node = 0;
scene::IAnimatedMesh* heromesh = smgr->getMesh("characters/sydney/amesh.md2");
if (heromesh)
{
hero = smgr->addAnimatedMeshSceneNode(heromesh);
hero->setPosition(core::vector3df(20,-15,20));
hero->setMD2Animation(scene::EMAT_STAND);
hero->setScale(core::vector3df(1.5,1.5,1.5));
hero->getMaterial(0) = material;
}
if (selector)
{
scene::ISceneNodeAnimator* anim =
smgr->createCollisionResponseAnimator(
selector, hero,
core::vector3df(17,25,20),
core::vector3df(0,-3,0),
core::vector3df(0,8,0));
hero->addAnimator(anim);
anim->drop();
selector->drop();
}
// Ray from player to camera
core::line3df camRay = core::line3df(playerPos, desiredCameraPos);
// not used
core::triangle3df triangle;
// Collide the ray with your triangleSelector. If a collision occurs
// then desiredCameraPos is set to the collision point
smgr->getSceneCollisionManager()->getCollisionPoint(camRay, selector, desiredCameraPos, triangle);
// render loop
while(device->run())
if (device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(0,255,255,255));
device->getCursorControl()->setPosition(width/2,height/2); //center cursor
//Execute moving //float relDisplacement;
float speed=4;//6
float rotspeed=2.5;//4.5
//Get Position&Rotation
core::vector3df position = hero->getPosition();
core::vector3df camposition = position;
core::vector3df rotation = hero->getRotation();
//Change camera settings
camera->setTarget(position);
camposition.X+=sin(camX*degtorad)*camDistance;
camposition.Z+=cos(camX*degtorad)*camDistance;
camposition.Y+=sin(camY*degtorad)*camDistance;
camera->setPosition(camposition);
//Modify Position and Rotation //relDisplacement=0;
if (up||down)
{
float relDisplacement = down ? speed : -speed;
position.X+= -cos(rotation.Y * degtorad)*relDisplacement;
position.Z+= sin(rotation.Y * degtorad)*relDisplacement;
rotation.Y = camX + 90.0; /*yuuuuuk*/
}
//#define RIGHT_LEFT_ROTATES
#ifndef RIGHT_LEFT_ROTATES
if (left||right)
{
float relDisplacement = left ? speed : -speed;
position.X += sin(rotation.Y * degtorad) * relDisplacement;
position.Z += cos(rotation.Y * degtorad) * relDisplacement; //cos
rotation.Y = camX + 90.0; /*yuuuuuk*/
}
#else
if (left||right)
{
rotation.Y += right ? rotspeed : -rotspeed;
}
#endif
//Set Position&Rotation
hero->setPosition(position);
hero->setRotation(rotation);
smgr->drawAll();
driver->endScene();
}
device->drop();
//scanf("%c");
return 0;
}
You have to do that every frame, right? The character/camera is moving.
So right after you have found out the "camposition" (what I called desiredCameraPos), just before the line
camera->setPosition(camposition);
Of COURSE, you have to replace the arguments I named (e.g. playerPos, desiredCameraPos with what ever you are calling those. "position", "cameraposition")
It might help if you learnt to code before you attempted to write a game. (just some friendly advice y'know )
So right after you have found out the "camposition" (what I called desiredCameraPos), just before the line
camera->setPosition(camposition);
Of COURSE, you have to replace the arguments I named (e.g. playerPos, desiredCameraPos with what ever you are calling those. "position", "cameraposition")
It might help if you learnt to code before you attempted to write a game. (just some friendly advice y'know )
I am sort of learning as I go. I am in a group in school where we are trying to make a video game. We were all given a part and mine was to get the collision detection working for the character and the camera.
When I try to compile it now says that core::line3df camRay = core::line3df(hero, camera); and smgr->getSceneCollisionManager()->getCollisionPoint(camRay, selector, camera); have no matching functions. Any ideas?
When I try to compile it now says that core::line3df camRay = core::line3df(hero, camera); and smgr->getSceneCollisionManager()->getCollisionPoint(camRay, selector, camera); have no matching functions. Any ideas?
a short look into the API shows you all you need to know...
the api is realy a magic file... ,)
so pass the positions to it and not the nodes...line3d (const vector3d< T > &start, const vector3d< T > &end)
and here you see that you miss one parameter and your last parameter (your camera) and the missing one are pointers to store the results...virtual bool getCollisionPoint (const core::line3d< f32 > &ray, ITriangleSelector *selector, core::vector3df &outCollisionPoint, core::triangle3df &outTriangle)=0
the api is realy a magic file... ,)
while(!asleep) sheep++;
IrrExtensions:
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
IrrExtensions:
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java