A piece from today’s report writing.
You probably can’t see the full width of the images within the post, but if you click an image you should be able to see it fully.
To position the camera, a target and an origin are decided. The target is the position of centre of the player character. The origin is the camera’s current position. The origin is then scaled so that its distance from the target is 1.5m.
In order to prevent other objects from getting between the target and origin, obstructing the view, a linear cast (or “shape cast”) is performed. This is a feature of Havok Physics and to explain how it works, first I will explain how I attempted to solve this problem using a simple raycast.
Figure 2a shows an origin→target vector without any obstruction. By casting a ray from the target to the origin, obstructions can be found and the vector clipped to a point where the obstruction is no longer in the way. In figure 2b an obstruction has been found by a raycast, and the origin will be moved to the point marked with a red X.
Figure 2: Detecting collisions with camera vectors.
This works well, except in the case where there is a very small angle between a polygon close to the origin. This often happens if the player character moves along a wall, for example. In this case, it is possible for the wall’s presence to have been detected by the raycast, but some of the wall’s surface falls between the origin and the near clip plane. This is illustrated in figure 3. In this case, the origin has moved away from the wall (and the raycast therefore reports there is no obstruction). However, part of the polygon (i.e., the surface of the wall) is behind the near clip plane. More of the same polygon is beyond the near clip plane, inside the viewing frustrum’s volume. Therefore there will be a visual artefact in the form of being able to see through the part of the polygon behind the near clip plane. In figure 3, this area which will not be rendered is shaded in red. The origin is marked as an orange point, and the totally unobstructed raycast, coming from the target and ending at the origin is green.
Figure 3: A demonstration of how a simple raycast-based camera vector clipping can cause artefacts.
A raycast can be thought of as a shape cast where the shape is a single point. Linear casting allows you use any shape at all though, instead of just a point. For example, a cube can be “swept” through 3D space, and any collisions with objects will be reported. (Please note that though collisions are detected, they are not resolved and the simulation is not affected by the cast.)
If one makes a sphere, with a radius equal to the distance between the camera origin and the near clip plane, this proves to go a long way to resolving the artefact mentioned above. In figure 4, this sphere is linear casted in place of the raycast. The sphere will collide with the wall, and the new position of the origin can be calculated from the returned contact point like so:
contactPoint.position + ( contactPoint.normal * sphere.radius )
Figure 4: Using a shapecast to clip the camera’s vector.
Figure 4 shows the normal as a purple arrow. As a normal is a vector normalised to a length of 1, this means that the near clip distance must be about 3 or 4 metres. However, the normal’s length was shortened for simplicity of illustration: please note that the near clip distance is set to 0.01m in YakumoDemo, which means that the resulting sphere is 20cm in diameter.
