mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 02:56:09 -04:00
Fix not being able to look straight up or down with camera
This commit is contained in:
parent
51820d1c4c
commit
cdb45aff12
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user