Camera, 3rd POV and clipping
by FruitBatInShades · in Torque Game Engine · 12/20/2004 (1:11 am) · 14 replies
I have been having trouble with some interiors. When in 3rd POV, the camera seems to get confused momentarily under specific conditions. When these conditions occur it seems as though it gets lost in the BSP tree and does not draw anything so you see the exterior outside the interior.
It seems to not detect a plane and passes through it, but only for 2-3 frames, then it seems to settle back on the plane again. I orginally thought that it was an error in the interior but it settles back on the right plane. This mainly happens when you have a right angle that the camera is flush against (ceiling/wall junction) and you rotate the mouse.
Has anyone else seen this?
It seems to not detect a plane and passes through it, but only for 2-3 frames, then it seems to settle back on the plane again. I orginally thought that it was an error in the interior but it settles back on the right plane. This mainly happens when you have a right angle that the camera is flush against (ceiling/wall junction) and you rotate the mouse.
Has anyone else seen this?
#2
It's a relatively complex issue to be honest, because there are so many possible scenarios (like the one you noted--even without direct control over the camera, you were able to get your player in the right position, with the right rotation, to have the camera inside the plane).
12/20/2004 (3:27 am)
@Fruit: I know that this is/was an issue in the advanced Camera resource as well, mostly due to the raycast looking for collision of the camera. I'm not sure how far Thomas progressed, but he was working on making sure the camera couldn't find itself "inside" an object, and/or on a plane barrier like you are talking about.It's a relatively complex issue to be honest, because there are so many possible scenarios (like the one you noted--even without direct control over the camera, you were able to get your player in the right position, with the right rotation, to have the camera inside the plane).
#3
Pseudocode :) The idea being that the plane the camera is locked too is used to set the cameras XYZ and then the planes normal is used for the offset direction. This could be done on each plane the camera is in contact with so you would only incur multiple passes when the camera is actually in contact with more than one plane.
Using the normal would mean that the camera is nudged in the correct direction, when the camera is not near a plane, no extra overhead would be incurred.
You could also save a pass by not recalculating if the locked planes have not changed since the last pass.
12/20/2004 (3:38 am)
Surely this would solve most of those issues:-CameraXYZ = MoveCamera(); For each LockedPlane CameraXYZ.XYZ = LockedPlane.normalXYZ + offset Next LockedPLane
Pseudocode :) The idea being that the plane the camera is locked too is used to set the cameras XYZ and then the planes normal is used for the offset direction. This could be done on each plane the camera is in contact with so you would only incur multiple passes when the camera is actually in contact with more than one plane.
Using the normal would mean that the camera is nudged in the correct direction, when the camera is not near a plane, no extra overhead would be incurred.
You could also save a pass by not recalculating if the locked planes have not changed since the last pass.
#4
Of course, it doesn't do that for terrain, etc., and it's designed specifically for things like backing yourself up against a wall in 3rd person mode.
The main problem you run into with your version (I think, not sure) is that at this point in the scene management, you don't have "knowledge" per se of your planes as planes, but simply as things you can collide with. I could be wrong of course, just kind of brainstorming here with you!
12/20/2004 (3:44 am)
I think the current technique that is being used throws a raycast during the camera positioning in the direction the camera is facing, and if it intersects anything, move the camera closer so it no longer intersects.Of course, it doesn't do that for terrain, etc., and it's designed specifically for things like backing yourself up against a wall in 3rd person mode.
The main problem you run into with your version (I think, not sure) is that at this point in the scene management, you don't have "knowledge" per se of your planes as planes, but simply as things you can collide with. I could be wrong of course, just kind of brainstorming here with you!
#5
The offset would be added before the camera is re-rendered so all the info should be there by then I'd hope :) The thing is, it generally happens at the point of the first contact with the surface/plane so there is some calculation that is awry. If you move the mouse character when the images above are in action, it renders ok again.
12/20/2004 (3:57 am)
Surely the collision information must include a normal? This isn't a new technique, its just one that would run after the camera has been positioned to just add the offset in the direction away from the collision mesh/plane. All we'd be after is the direction the collision face is facing so we can subtract/add to the right XYZ co-ord. The offset would be added before the camera is re-rendered so all the info should be there by then I'd hope :) The thing is, it generally happens at the point of the first contact with the surface/plane so there is some calculation that is awry. If you move the mouse character when the images above are in action, it renders ok again.
#6
I haven't messed with camera stuff since around June sometime, and my orbit cam mode was my very first major self-mod to the engine, so I'm reasonably confident I didn't know what I was really doing!
I just don't want to lead you in the wrong direction...
12/20/2004 (4:05 am)
I'm gonna have to defer continuing this convo until (hopefully) Thomas, or someone else more focused on the camera stuff can jump in--getting quickly out of my recent experience level!I haven't messed with camera stuff since around June sometime, and my orbit cam mode was my very first major self-mod to the engine, so I'm reasonably confident I didn't know what I was really doing!
I just don't want to lead you in the wrong direction...
#7
12/20/2004 (4:13 am)
Thats Ok, I have absolutely no idea, just thinking aloud as is my habit :o) Thanks for your time Stephen.
#8
What the adv camera does is what Stephen says.
Before placing itself in a certain position it casts a ray from where it should place itself and the "look at" position. If it collides with terrain, interiors or objects (except the player) then it moves itself to the collision point + a small offset.
Trying to do ascii art, with
C = camera
P = player
- = raycast
T = terrain (or an interior etc.)
The offset should ensure that in most situations you dont get the camera placed right in the plane, and thus get a view that is partly "inside the terrain".
This works for 99% of the situations, but I've encountered problems in some special cases. I havent opened up the adv camera code for a while, so I cannot remember the exact details.
Speculating: One source of problem could be if there is more than 1 collision between the camera and the player. I cannot remember if I cast the ray from the player or from the camera - if its the camera it could return more than 1 collision and place itself in the wrong spot. It should cast a ray from the player, and then pick the first/nearest collision - minus the offset.
The adv camera has a separate method for the "check for collision" - should be easy to spot and maybe correct.
(Footnote: reason for not coding more on the adv camera is that I'm contemplating redoing it totally, putting in some nice editors, camera control beyond basics with its own script language etc and then release it as a code pack. But its still in the idea phase and has been for quite a while with not enough time to actually do it at the moment)
Edit:
Oh - I've noticed the problem is especially noticable when colliding against interiors. I've got a test map where I have a hut with windows, and with the camera in 3rd person its going absolutely bananas when the camera goes in/out of the windows adjusting itself.
12/21/2004 (12:02 am)
/me jumps inWhat the adv camera does is what Stephen says.
Before placing itself in a certain position it casts a ray from where it should place itself and the "look at" position. If it collides with terrain, interiors or objects (except the player) then it moves itself to the collision point + a small offset.
Trying to do ascii art, with
C = camera
P = player
- = raycast
T = terrain (or an interior etc.)
Before doing raycast the situation is that the player is backed up against terrain, and camera is in 3rd person. So the camera position is inside the terrain like: C---T----P After the raycast the camera is moved to the collision point + an offset straight into the line of the ray ----TC---P
The offset should ensure that in most situations you dont get the camera placed right in the plane, and thus get a view that is partly "inside the terrain".
This works for 99% of the situations, but I've encountered problems in some special cases. I havent opened up the adv camera code for a while, so I cannot remember the exact details.
Speculating: One source of problem could be if there is more than 1 collision between the camera and the player. I cannot remember if I cast the ray from the player or from the camera - if its the camera it could return more than 1 collision and place itself in the wrong spot. It should cast a ray from the player, and then pick the first/nearest collision - minus the offset.
The adv camera has a separate method for the "check for collision" - should be easy to spot and maybe correct.
(Footnote: reason for not coding more on the adv camera is that I'm contemplating redoing it totally, putting in some nice editors, camera control beyond basics with its own script language etc and then release it as a code pack. But its still in the idea phase and has been for quite a while with not enough time to actually do it at the moment)
Edit:
Oh - I've noticed the problem is especially noticable when colliding against interiors. I've got a test map where I have a hut with windows, and with the camera in 3rd person its going absolutely bananas when the camera goes in/out of the windows adjusting itself.
#9
In theory it should be a case of just passing the camera position to the routine above that offsets it slightly, then returning the edited position to the renderer. Thing is my math is crap, I'm going to go back to college and do maths again because the more I look into the code, the more I have no idea, what it does! Lol
12/21/2004 (1:49 am)
@Thomas: All my idea is; is to basically use an offset so the camera can never actually touch a plane, this should prevent these glitches as it can never get near enough a plane to pass through it. So the camera position is calculated on the plane as it is now, but the position the camera is rendered to is offset by a couple of units in the direction of the normal.In theory it should be a case of just passing the camera position to the routine above that offsets it slightly, then returning the edited position to the renderer. Thing is my math is crap, I'm going to go back to college and do maths again because the more I look into the code, the more I have no idea, what it does! Lol
#10
And honestly, the raycasting is pretty much exactly what you are talking about, with the exception of not really being able to detect that it is "on" a particular plane. I would imagine that a better designed and defined "anti-inside-anything" (check for collision) would be able to handle this.
Side Note: To point out that this isn't really trivial, I've seen not a few AAA games (Everquest, Shadowbane as well) where you can do pretty much exactly what you describe. In EQ, it was a little known but very useful "check spawn" cheat--certain zones you could position yourself so your camera was thrown "inside" the walls, and therfore could see the entire zone (walls as you know are commonly transparent from the "can't be seen" side, and therefore would let you see just about everything!).
12/21/2004 (3:09 am)
The only problem with doing it "just in the editor" is that if it happens there, it's almost certainly going to happen when the models are "in game" as well. And as I mentioned, as far as I am aware, the camera itself really doesn't have much contextual "knowledge" of the geography of the scene, other that what can be "discovered" via raycast, etc.And honestly, the raycasting is pretty much exactly what you are talking about, with the exception of not really being able to detect that it is "on" a particular plane. I would imagine that a better designed and defined "anti-inside-anything" (check for collision) would be able to handle this.
Side Note: To point out that this isn't really trivial, I've seen not a few AAA games (Everquest, Shadowbane as well) where you can do pretty much exactly what you describe. In EQ, it was a little known but very useful "check spawn" cheat--certain zones you could position yourself so your camera was thrown "inside" the walls, and therfore could see the entire zone (walls as you know are commonly transparent from the "can't be seen" side, and therefore would let you see just about everything!).
#11
12/21/2004 (5:21 pm)
I will add only to this that there is a vast gulf between theory and implementation.
#12
12/22/2004 (1:35 am)
I know that Ben, I am a coder, just not a torque coder ;)
#13
05/18/2005 (3:54 pm)
Just wondering if anyone has worked on this issue at all or made any headway into reducing or completely clearing it up.
#14
I implemented the advanced camera resource yesterday and went about fixing the problem where the camera would draw the exterior outside of an interior.
There are basically 3 cases for the camera, when it is inside a brush, when it is on a brush plane, and when it is outside a brush.
The problem was partially solved with a ray being cast from the player (plus the offset) to the camera and then determining if it was inside the brush. It is then offset from the collision point to put it back in a safe position.
The problem is that castRay appears to return false if you are on the brush plane and not technically inside of it. Since sitting on the brush plane is just as bad as being in a brush this is what needed to be addressed.
My fix seems to handle all cases because of the following:
The case where the camera is inside a brush is already taken care of with cast ray.
As far as I know we cant test for being on the brush plane or that would be the ideal condition to test for.
The player is always in a safe position (or should be) so moving the camera toward the player will always move the camera nearer to a safe position.
This makes the worst case scenario that the camera is sitting on a brush plane.
If we ALWAYS offset the camera towards the player when it has been determined that it is not inside a brush we can guarantee that it will be off the plane into a safe position.
The drawback of this is that the CurrentLookAtOffset that you define is never exactly what you set it to be. It will always that offset and the value set by DISTANCE_FROM_COLLISION that determines the final camera position, regardless if you are on a brush plane or not. In my opinion this is a small price to pay for the huge gain of not ending up looking at the exteriors.
Anyways onto the code. In the function AdvancedCamera::runCameraCollisionCheck in advancedCamera.cc change this:
to this:
I have tested this fairly extensively with the 3rd person camera and some fairly detailed interiors with lots of rooms. I have not tested the other camera modes though.
05/23/2005 (3:22 pm)
@FruitBatInShadesI implemented the advanced camera resource yesterday and went about fixing the problem where the camera would draw the exterior outside of an interior.
There are basically 3 cases for the camera, when it is inside a brush, when it is on a brush plane, and when it is outside a brush.
The problem was partially solved with a ray being cast from the player (plus the offset) to the camera and then determining if it was inside the brush. It is then offset from the collision point to put it back in a safe position.
The problem is that castRay appears to return false if you are on the brush plane and not technically inside of it. Since sitting on the brush plane is just as bad as being in a brush this is what needed to be addressed.
My fix seems to handle all cases because of the following:
The case where the camera is inside a brush is already taken care of with cast ray.
As far as I know we cant test for being on the brush plane or that would be the ideal condition to test for.
The player is always in a safe position (or should be) so moving the camera toward the player will always move the camera nearer to a safe position.
This makes the worst case scenario that the camera is sitting on a brush plane.
If we ALWAYS offset the camera towards the player when it has been determined that it is not inside a brush we can guarantee that it will be off the plane into a safe position.
The drawback of this is that the CurrentLookAtOffset that you define is never exactly what you set it to be. It will always that offset and the value set by DISTANCE_FROM_COLLISION that determines the final camera position, regardless if you are on a brush plane or not. In my opinion this is a small price to pay for the huge gain of not ending up looking at the exteriors.
Anyways onto the code. In the function AdvancedCamera::runCameraCollisionCheck in advancedCamera.cc change this:
// Cast ray and check for collision with terrain and interiors
if (!gClientContainer.castRay(startpos + mCurrentLookAtOffset, endpos, mask, &collisionInfo)) {
// No collision, so return endpos
return endpos;
}to this:
// Cast ray and check for collision with terrain and interiors
if (!gClientContainer.castRay(startpos + mCurrentLookAtOffset, endpos, mask, &collisionInfo))
{
// No collision, but we offset anyway because we could be on the brush plane
Point3F LookDir = startpos + mCurrentLookAtOffset - endpos;
LookDir.normalize();
Point3F AntiClippingOffset = LookDir * DISTANCE_FROM_COLLISION;
return endpos + AntiClippingOffset;
}I have tested this fairly extensively with the 3rd person camera and some fairly detailed interiors with lots of rooms. I have not tested the other camera modes though.
Torque Owner FruitBatInShades
This occurs when the camera is exactly on the plane, if you slowly move the camera to the ceiling, just as it touches before it starts to move forwards along the plane.
I wonder if the cameras central point is being used for the calculations? Would it be possible to offest the calculations so that the camera never actually touches a plane? Set up an offset and doing the cameras FOV from that offset, the camera calulations would be the same but the offset would just be adjusted by X units away from the normal of the plane?