Fix not being able to look straight up or down with camera

This commit is contained in:
UnknownShadow200 2018-08-02 20:00:26 +10:00
parent 51820d1c4c
commit cdb45aff12
10 changed files with 56 additions and 149 deletions

View File

@ -138,20 +138,15 @@ namespace OpenTK {
a, b, c, -1,
0, 0, d, 0);
}
public static void LookAt(Vector3 eye, Vector3 target, Vector3 up, out Matrix4 result) {
Vector3 z = Vector3.Normalize(eye - target);
Vector3 x = Vector3.Normalize(Vector3.Cross(up, z));
Vector3 y = Vector3.Normalize(Vector3.Cross(z, x));
Matrix4 rot = new Matrix4(new Vector4(x.X, y.X, z.X, 0.0f),
new Vector4(x.Y, y.Y, z.Y, 0.0f),
new Vector4(x.Z, y.Z, z.Z, 0.0f),
Vector4.UnitW);
public static void LookRot(Vector3 pos, ClassicalSharp.Vector2 rot, out Matrix4 result) {
Matrix4 rotX, rotY, trans;
RotateX(out rotX, rot.Y);
RotateY(out rotY, rot.X);
Translate(out trans, -pos.X, -pos.Y, -pos.Z);
Matrix4 trans;
Translate(out trans, -eye.X, -eye.Y, -eye.Z);
Mult(out result, ref trans, ref rot);
Mult(out result, ref rotY, ref rotX);
Mult(out result, ref trans, ref result);
}
public static void Mult(out Matrix4 result, ref Matrix4 left, ref Matrix4 right) {

View File

@ -50,25 +50,21 @@ namespace ClassicalSharp {
}
}
static Vector3 adjust = new Vector3(0.1f);
static bool CameraClip(Game game, PickedPos pos) {
if (BlockInfo.Draw[t.Block] == DrawType.Gas || BlockInfo.Collide[t.Block] != CollideType.Solid)
return false;
float t0, t1;
const float adjust = 0.1f;
if (!Intersection.RayIntersectsBox(t.Origin, t.Dir, t.Min, t.Max, out t0, out t1))
return false;
// Need to collide with slightly outside block, to avoid camera clipping issues
t.Min -= adjust; t.Max += adjust;
Intersection.RayIntersectsBox(t.Origin, t.Dir, t.Min, t.Max, out t0, out t1);
Vector3 I = t.Origin + t.Dir * t0;
pos.SetAsValid(t.X, t.Y, t.Z, t.Min, t.Max, t.Block, I);
switch (pos.Face) {
case BlockFace.XMin: pos.Intersect.X -= adjust; break;
case BlockFace.XMax: pos.Intersect.X += adjust; break;
case BlockFace.YMin: pos.Intersect.Y -= adjust; break;
case BlockFace.YMax: pos.Intersect.Y += adjust; break;
case BlockFace.ZMin: pos.Intersect.Z -= adjust; break;
case BlockFace.ZMax: pos.Intersect.Z += adjust; break;
}
return true;
}

View File

@ -61,26 +61,6 @@ namespace OpenTK {
result.Y = blend * (b.Y - a.Y) + a.Y;
result.Z = blend * (b.Z - a.Z) + a.Z;
}
public static float Dot(Vector3 left, Vector3 right) {
return left.X * right.X + left.Y * right.Y + left.Z * right.Z;
}
public static void Dot(ref Vector3 left, ref Vector3 right, out float result) {
result = left.X * right.X + left.Y * right.Y + left.Z * right.Z;
}
public static Vector3 Cross(Vector3 left, Vector3 right) {
return new Vector3(left.Y * right.Z - left.Z * right.Y,
left.Z * right.X - left.X * right.Z,
left.X * right.Y - left.Y * right.X);
}
public static void Cross(ref Vector3 left, ref Vector3 right, out Vector3 result) {
result = new Vector3(left.Y * right.Z - left.Z * right.Y,
left.Z * right.X - left.X * right.Z,
left.X * right.Y - left.Y * right.X);
}
public static Vector3 Normalize(Vector3 vec) {
float scale = 1f / (float)Math.Sqrt(vec.LengthSquared);

View File

@ -90,10 +90,10 @@ namespace ClassicalSharp.Renderers {
static Vector3 sOffset = new Vector3(0.46f, -0.52f, -0.72f);
void SetMatrix() {
Player p = game.LocalPlayer;
Vector3 eyePos = Vector3.Zero; eyePos.Y = p.EyeHeight;
Vector3 eye = Vector3.Zero; eye.Y = p.EyeHeight;
Matrix4 m, lookAt;
Matrix4.LookAt(eyePos, eyePos - Vector3.UnitZ, Vector3.UnitY, out lookAt);
Matrix4 lookAt, m;
Matrix4.Translate(out lookAt, -eye.X, -eye.Y, -eye.Z);
Matrix4.Mult(out m, ref lookAt, ref Camera.tiltM);
game.Graphics.View = m;
}

View File

@ -31,7 +31,6 @@ namespace ClassicalSharp {
public abstract class PerspectiveCamera : Camera {
protected static Vector2 rotOffset;
protected static Vector3 targetOffset;
protected LocalPlayer player;
public PerspectiveCamera(Game game) {
@ -40,18 +39,6 @@ namespace ClassicalSharp {
tiltM = Matrix4.Identity;
}
protected Vector3 GetDirVector() {
Vector2 rot = GetOrientation();
Vector3 dir = Utils.GetDirVector(rot.X, rot.Y);
// Adjusts pitch of the player to avoid looking straight up or down,
// as pitch parallel to camera up vector causes rendering issues
if (dir.Y > +0.999998f) dir.Y = +0.999998f;
if (dir.Y < -0.999998f) dir.Y = -0.999998f;
return dir;
}
public override void GetProjection(out Matrix4 m) {
float fov = game.Fov * Utils.Deg2Rad;
float aspectRatio = (float)game.Width / game.Height;
@ -61,15 +48,13 @@ namespace ClassicalSharp {
public override void GetView(out Matrix4 m) {
Vector3 pos = game.CurrentCameraPos;
Vector3 target = pos + targetOffset;
Matrix4.LookAt(pos, target, Vector3.UnitY, out m);
Vector2 rot = GetOrientation();
Matrix4.LookRot(pos, rot, out m);
Matrix4.Mult(out m, ref m, ref tiltM);
}
public override void GetPickedBlock(PickedPos pos) {
Vector3 eyePos = player.EyePosition;
//Vector3 dir = GetDirVector();
Vector3 dir = Utils.GetDirVector(player.HeadYRadians, player.HeadXRadians);
float reach = game.LocalPlayer.ReachDistance;
@ -134,7 +119,7 @@ namespace ClassicalSharp {
// Need to make sure we don't cross the vertical axes, because that gets weird.
if (update.HeadX >= 90 && update.HeadX <= 270) {
update.HeadX = player.interp.next.HeadX < 180 ? 89.9f : 270.1f;
update.HeadX = player.interp.next.HeadX < 180 ? 90.0f : 270.0f;
}
game.LocalPlayer.SetLocation(update, false);
}
@ -193,12 +178,13 @@ namespace ClassicalSharp {
Vector3 target = player.EyePosition;
target.Y += bobbingVer;
Vector3 dir = -GetDirVector();
Picking.ClipCameraPos(game, target, dir, dist, game.CameraClipPos);
Vector3 camPos = game.CameraClipPos.Intersect;
// cast ray from player position to camera position
// this way we can stop if we hit a block in the way
Vector2 rot = GetOrientation();
Vector3 dir = -Utils.GetDirVector(rot.X, rot.Y);
targetOffset = target - camPos;
return camPos;
Picking.ClipCameraPos(game, target, dir, dist, game.CameraClipPos);
return game.CameraClipPos.Intersect;
}
}
@ -218,8 +204,6 @@ namespace ClassicalSharp {
double headY = player.HeadYRadians;
camPos.X += bobbingHor * (float)Math.Cos(headY);
camPos.Z += bobbingHor * (float)Math.Sin(headY);
targetOffset = GetDirVector();
return camPos;
}
}

View File

@ -9,23 +9,10 @@
#include "Input.h"
Vector2 cam_rotOffset;
Vector3 cam_targetOffset;
struct Camera Camera_Cameras[3];
Int32 Camera_ActiveIndex;
#define Cam_IsForward_Third() (Camera_ActiveIndex == 2)
static Vector3 PerspectiveCamera_GetDirVector(void) {
Vector2 rot = Camera_Active->GetOrientation();
Vector3 dir = Vector3_GetDirVector(rot.X, rot.Y);
/* Adjusts pitch of the player to avoid looking straight up or down, */
/* as pitch parallel to camera up vector causes rendering issues */
if (dir.Y > +0.999998f) dir.Y = +0.999998f;
if (dir.Y < -0.999998f) dir.Y = -0.999998f;
return dir;
}
static void PerspectiveCamera_GetProjection(struct Matrix* proj) {
Real32 fovy = Game_Fov * MATH_DEG2RAD;
Real32 aspectRatio = (Real32)Game_Width / (Real32)Game_Height;
@ -33,16 +20,14 @@ static void PerspectiveCamera_GetProjection(struct Matrix* proj) {
}
static void PerspectiveCamera_GetView(struct Matrix* mat) {
Vector3 pos = Game_CurrentCameraPos, target, up = Vector3_UnitY;
Vector3_Add(&target, &pos, &cam_targetOffset);
Matrix_LookAt(mat, pos, target, up);
Vector3 pos = Game_CurrentCameraPos;
Vector2 rot = Camera_Active->GetOrientation();
Matrix_LookRot(mat, pos, rot);
Matrix_MulBy(mat, &Camera_TiltM);
}
static void PerspectiveCamera_GetPickedBlock(struct PickedPos* pos) {
struct Entity* p = &LocalPlayer_Instance.Base;
/* Vector3 dir = PerspectiveCamera_GetDirVector(); */
Vector3 dir = Vector3_GetDirVector(p->HeadY * MATH_DEG2RAD, p->HeadX * MATH_DEG2RAD);
Vector3 eyePos = Entity_GetEyePosition(p);
Real32 reach = LocalPlayer_Instance.ReachDistance;
@ -104,7 +89,7 @@ static void PerspectiveCamera_UpdateMouseRotation(void) {
/* Need to make sure we don't cross the vertical axes, because that gets weird. */
if (update.HeadX >= 90.0f && update.HeadX <= 270.0f) {
update.HeadX = player->Interp.Next.HeadX < 180.0f ? 89.9f : 270.1f;
update.HeadX = player->Interp.Next.HeadX < 180.0f ? 90.0f : 270.0f;
}
struct Entity* e = &player->Base;
@ -165,8 +150,6 @@ static Vector3 FirstPersonCamera_GetPosition(Real32 t) {
Real32 headY = (p->HeadY * MATH_DEG2RAD);
camPos.X += Camera_BobbingHor * Math_CosF(headY);
camPos.Z += Camera_BobbingHor * Math_SinF(headY);
cam_targetOffset = PerspectiveCamera_GetDirVector();
return camPos;
}
@ -200,19 +183,19 @@ static Vector3 ThirdPersonCamera_GetPosition(Real32 t) {
Vector3 target = Entity_GetEyePosition(p);
target.Y += Camera_BobbingVer;
Vector3 dir = PerspectiveCamera_GetDirVector(); Vector3_Negate(&dir, &dir);
Picking_ClipCameraPos(target, dir, dist, &Game_CameraClipPos);
Vector3 camPos = Game_CameraClipPos.Intersect;
Vector2 rot = Camera_Active->GetOrientation();
Vector3 dir = Vector3_GetDirVector(rot.X, rot.Y);
Vector3_Negate(&dir, &dir);
Vector3_Sub(&cam_targetOffset, &target, &camPos);
return camPos;
Picking_ClipCameraPos(target, dir, dist, &Game_CameraClipPos);
return Game_CameraClipPos.Intersect;
}
static bool ThirdPersonCamera_Zoom(Real32 amount) {
Real32* dist = Cam_IsForward_Third() ? &dist_forward : &dist_third;
Real32 newDist = *dist - amount;
newDist = min(newDist, 2.0f); *dist = newDist;
*dist = max(newDist, 2.0f);
return true;
}

View File

@ -51,12 +51,10 @@ static void HeldBlockRenderer_RenderModel(void) {
static void HeldBlockRenderer_SetMatrix(void) {
struct Entity* player = &LocalPlayer_Instance.Base;
Vector3 eyePos = VECTOR3_CONST(0.0f, Entity_GetEyeHeight(player), 0.0f);
Vector3 up = Vector3_UnitY;
Vector3 target = eyePos; target.Z -= 1.0f; /* Look straight down*/
Vector3 eye = VECTOR3_CONST(0.0f, Entity_GetEyeHeight(player), 0.0f);
struct Matrix m, lookAt;
Matrix_LookAt(&lookAt, eyePos, target, up);
Matrix_Translate(&lookAt, -eye.X, -eye.Y, -eye.Z);
Matrix_Mul(&m, &lookAt, &Camera_TiltM);
Gfx_View = m;
}

View File

@ -199,30 +199,21 @@ static bool Picking_ClipBlock(struct PickedPos* pos) {
return true;
}
static Vector3 picking_adjust = VECTOR3_CONST1(0.1f);
static bool Picking_ClipCamera(struct PickedPos* pos) {
if (Block_Draw[tracer.Block] == DRAW_GAS || Block_Collide[tracer.Block] != COLLIDE_SOLID) {
return false;
}
if (Block_Draw[tracer.Block] == DRAW_GAS || Block_Collide[tracer.Block] != COLLIDE_SOLID) return false;
Real32 t0, t1;
if (!Intersection_RayIntersectsBox(tracer.Origin, tracer.Dir, tracer.Min, tracer.Max, &t0, &t1)) {
return false;
}
if (!Intersection_RayIntersectsBox(tracer.Origin, tracer.Dir, tracer.Min, tracer.Max, &t0, &t1)) return false;
/* Need to collide with slightly outside block, to avoid camera clipping issues */
Vector3_Sub(&tracer.Min, &tracer.Min, &picking_adjust);
Vector3_Add(&tracer.Max, &tracer.Max, &picking_adjust);
Intersection_RayIntersectsBox(tracer.Origin, tracer.Dir, tracer.Min, tracer.Max, &t0, &t1);
Vector3 intersect;
Vector3_Mul1(&intersect, &tracer.Dir, t0); /* intersect = dir * t0 */
Vector3_Mul1(&intersect, &tracer.Dir, t0); /* intersect = dir * t0 */
Vector3_Add(&intersect, &tracer.Origin, &intersect); /* intersect = origin + dir * t0 */
PickedPos_SetAsValid(pos, &tracer, intersect);
#define PICKING_ADJUST 0.1f
switch (pos->ClosestFace) {
case FACE_XMIN: pos->Intersect.X -= PICKING_ADJUST; break;
case FACE_XMAX: pos->Intersect.X += PICKING_ADJUST; break;
case FACE_YMIN: pos->Intersect.Y -= PICKING_ADJUST; break;
case FACE_YMAX: pos->Intersect.Y += PICKING_ADJUST; break;
case FACE_ZMIN: pos->Intersect.Z -= PICKING_ADJUST; break;
case FACE_ZMAX: pos->Intersect.Z += PICKING_ADJUST; break;
}
return true;
}
@ -236,7 +227,7 @@ void Picking_ClipCameraPos(Vector3 origin, Vector3 dir, Real32 reach, struct Pic
bool noClip = !Game_CameraClipping || LocalPlayer_Instance.Hacks.Noclip;
if (noClip || !Picking_RayTrace(origin, dir, reach, pos, Picking_ClipCamera)) {
PickedPos_SetAsInvalid(pos);
Vector3_Mul1(&pos->Intersect, &dir, reach); /* intersect = dir * reach */
Vector3_Mul1(&pos->Intersect, &dir, reach); /* intersect = dir * reach */
Vector3_Add(&pos->Intersect, &origin, &pos->Intersect); /* intersect = origin + dir * reach */
}
}

View File

@ -52,18 +52,6 @@ void Vector3_Lerp(Vector3* result, Vector3* a, Vector3* b, Real32 blend) {
result->Z = blend * (b->Z - a->Z) + a->Z;
}
Real32 Vector3_Dot(Vector3* a, Vector3* b) {
return a->X * b->X + a->Y * b->Y + a->Z * b->Z;
}
void Vector3_Cross(Vector3* result, Vector3* a, Vector3* b) {
/* a or b could be pointing to result - can't directly assign X/Y/Z therefore */
Real32 x = a->Y * b->Z - a->Z * b->Y;
Real32 y = a->Z * b->X - a->X * b->Z;
Real32 z = a->X * b->Y - a->Y * b->X;
result->X = x; result->Y = y; result->Z = z;
}
void Vector3_Normalize(Vector3* result, Vector3* a) {
Real32 lenSquared = a->X * a->X + a->Y * a->Y + a->Z * a->Z;
Real32 scale = 1.0f / Math_SqrtF(lenSquared);
@ -257,21 +245,14 @@ void Matrix_PerspectiveOffCenter(struct Matrix* result, Real32 left, Real32 rig
result->Row2.W = -1.0f;
}
void Matrix_LookAt(struct Matrix* result, Vector3 eye, Vector3 target, Vector3 up) {
/* Transposed, source https://msdn.microsoft.com/en-us/library/windows/desktop/bb281711(v=vs.85).aspx */
Vector3 x, y, z;
Vector3_Sub(&z, &eye, &target); Vector3_Normalize(&z, &z);
Vector3_Cross(&x, &up, &z); Vector3_Normalize(&x, &x);
Vector3_Cross(&y, &z, &x); Vector3_Normalize(&y, &y);
void Matrix_LookRot(struct Matrix* result, Vector3 pos, Vector2 rot) {
struct Matrix rotX, rotY, trans;
Matrix_RotateX(&rotX, rot.Y);
Matrix_RotateY(&rotY, rot.X);
Matrix_Translate(&trans, -pos.X, -pos.Y, -pos.Z);
result->Row0.X = x.X; result->Row0.Y = y.X; result->Row0.Z = z.X; result->Row0.W = 0.0f;
result->Row1.X = x.Y; result->Row1.Y = y.Y; result->Row1.Z = z.Y; result->Row1.W = 0.0f;
result->Row2.X = x.Z; result->Row2.Y = y.Z; result->Row2.Z = z.Z; result->Row2.W = 0.0f;
result->Row3.X = -Vector3_Dot(&x, &eye);
result->Row3.Y = -Vector3_Dot(&y, &eye);
result->Row3.Z = -Vector3_Dot(&z, &eye);
result->Row3.W = 1.0f;
Matrix_Mul(result, &rotY, &rotX);
Matrix_Mul(result, &trans, result);
}
Real32

View File

@ -41,7 +41,6 @@ void Vector3_Negate(Vector3* result, Vector3* a);
void Vector3_Lerp(Vector3* result, Vector3* a, Vector3* b, Real32 blend);
Real32 Vector3_Dot(Vector3* left, Vector3* right);
void Vector3_Cross(Vector3* result, Vector3* a, Vector3* b);
void Vector3_Normalize(Vector3* result, Vector3* a);
void Vector3_Transform(Vector3* result, Vector3* a, struct Matrix* mat);
@ -81,7 +80,7 @@ void Matrix_Orthographic(struct Matrix* result, Real32 width, Real32 height, Rea
void Matrix_OrthographicOffCenter(struct Matrix* result, Real32 left, Real32 right, Real32 bottom, Real32 top, Real32 zNear, Real32 zFar);
void Matrix_PerspectiveFieldOfView(struct Matrix* result, Real32 fovy, Real32 aspect, Real32 zNear, Real32 zFar);
void Matrix_PerspectiveOffCenter(struct Matrix* result, Real32 left, Real32 right, Real32 bottom, Real32 top, Real32 zNear, Real32 zFar);
void Matrix_LookAt(struct Matrix* result, Vector3 eye, Vector3 target, Vector3 up);
void Matrix_LookRot(struct Matrix* result, Vector3 pos, Vector2 rot);
bool FrustumCulling_SphereInFrustum(Real32 x, Real32 y, Real32 z, Real32 radius);
void FrustumCulling_CalcFrustumEquations(struct Matrix* projection, struct Matrix* modelView);