Skip to content

Commit

Permalink
feat: add camera XZ translation and Y-axis rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
tomezpl committed Oct 13, 2023
1 parent 62ff9da commit 07e95d0
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 62 deletions.
27 changes: 6 additions & 21 deletions src/L3D/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ namespace lepus

lepus::math::Matrix4x4 BuildViewMatrix()
{
lepus::math::Matrix4x4 rot = lepus::math::Matrix4x4::Identity();
lepus::math::Matrix4x4 pos = lepus::math::Matrix4x4::Identity();

/*
rot[0] = vec4(c+axis.x*axis.x*(1.0 - c), axis.y*axis.x*(1.0 - c)+axis.z*s, axis.z*axis.x*(1.0 - c)-axis.y*s, 0.0);
Expand All @@ -69,27 +67,14 @@ namespace lepus
*/

lepus::types::Vector4& axisAngle = m_Transform.Rotation();
lepus::types::Vector3 axis = lepus::types::Vector3((float*)axisAngle.GetData());
axis = axis * (1.f / axis.Magnitude());

float c = cosf(axisAngle.w());
float s = sinf(axisAngle.w());

rot.set<0, 0>(c + axis.x() * axis.x() * (1.f - c));
rot.set<1, 0>(axis.y() * axis.x() * (1.f - c) + axis.z() * s);
rot.set<2, 0>(axis.z() * axis.x() * (1.f - c) - axis.y() * s);

rot.set<0, 1>(axis.y() * axis.x() * (1.f - c) - axis.z() * s);
rot.set<1, 1>(c + axis.y() * axis.y() * (1.f - c));
rot.set<2, 1>(axis.z() * axis.y() * (1.f - c) + axis.x() * s);

rot.set<0, 2>(axis.z() * axis.x() * (1.f - c) + axis.y() * s);
rot.set<1, 2>(axis.z() * axis.y() * (1.f - c) - axis.x() * s);
rot.set<2, 2>(c + axis.z() * axis.z() * (1.f - c));
// TODO: shouldn't need the non-const float* cast
lepus::math::Matrix4x4 rot = lepus::math::Transform::AxisAngle(lepus::types::Vector3((float*)axisAngle.GetData()), axisAngle.w());
lepus::math::Matrix4x4 pos = lepus::math::Matrix4x4::Identity();

pos.set<0, 3>(m_Transform.Origin().x());
pos.set<1, 3>(m_Transform.Origin().y());
pos.set<2, 3>(m_Transform.Origin().z());
pos.set<0, 3>(-m_Transform.Origin().x());
pos.set<1, 3>(-m_Transform.Origin().y());
pos.set<2, 3>(-m_Transform.Origin().z());

return rot.Multiply(pos);
}
Expand Down
91 changes: 57 additions & 34 deletions src/LDemo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,49 +28,39 @@ using namespace LepusEngine;

float fov = 0.f;
float angle = 0.f;
float x = 0.f, y = 0.f, z = 0.f;
const float camSpeed = 0.1f;
const float camSpeed = 0.005f;
double xposLast = -1.0;
double yposLast = -1.0;
float deltaTime = 0.f;
lepus::gfx::Camera camera;

void scrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
fov = fmax(1.f, fmin(179.f, fov + (float)yoffset));
LepusEngine::ConsoleLogger::Global().LogInfo("", "scrollCallback", "yoffset", (char*)std::to_string(xoffset).append(", ").append(std::to_string(yoffset)).append("FOV: ").append(std::to_string(fov)).c_str());
}

void keyInputCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
void mouseCallback(GLFWwindow* window, double xpos, double ypos)
{
LepusEngine::ConsoleLogger::Global().LogInfo("", "keyInputCallback", (char*)std::to_string(key).c_str());

switch (key)
if (xposLast < 0.0)
{
case 87:
// W
z -= camSpeed;
break;
case 65:
// A
x -= camSpeed;
break;
case 83:
// S
z += camSpeed;
break;
case 68:
x += camSpeed;
break;
xposLast = xpos;
}
}

void mouseCallback(GLFWwindow* window, double xpos, double ypos)
{
if (xposLast < 0.0)
if (yposLast < 0.0)
{
xposLast = xpos;
yposLast = ypos;
}

angle += (xpos - xposLast) / 100.0;
float deltaX = (xpos - xposLast) / 100.0;
float deltaY = (ypos - yposLast) / 100.0;
angle += deltaX * 0.3f;
camera.Transform().Rotate(lepus::types::Vector3(0.0f, 1.f, 0.f), deltaX * 0.3f);

LepusEngine::ConsoleLogger::Global().LogInfo("", "mouseCallback", (char*)std::to_string(angle).c_str());
xposLast = xpos;
yposLast = ypos;
}

int main()
Expand Down Expand Up @@ -107,7 +97,7 @@ int main()
// Set up engine for drawing.
engine.Setup();

lepus::gfx::Camera camera = lepus::gfx::Camera();
camera = lepus::gfx::Camera();
lepus::math::Matrix4x4 projMatrix = camera.BuildPerspectiveMatrix();
((lepus::gfx::GLMatrixUniformBinding*)api.GetUniform<lepus::gfx::GLMatrixUniformBinding>("PROJ"))->Value((float*)projMatrix.data());

Expand All @@ -117,24 +107,54 @@ int main()
fov = camera.FOV();

glfwSetScrollCallback(reinterpret_cast<GLFWwindow*>(windowing->GetWindowPtr()), scrollCallback);
glfwSetKeyCallback(reinterpret_cast<GLFWwindow*>(windowing->GetWindowPtr()), keyInputCallback);
//glfwSetKeyCallback(reinterpret_cast<GLFWwindow*>(windowing->GetWindowPtr()), keyInputCallback);
glfwSetCursorPosCallback(reinterpret_cast<GLFWwindow*>(windowing->GetWindowPtr()), mouseCallback);

float runningTime = glfwGetTime();

camera.Transform().Rotation().y(1.f);
//camera.Transform().Rotation().z(1.f);
camera.Transform().Origin().y(-2.f);
camera.Transform().Origin().z(-4.f);

GLFWwindow* window = reinterpret_cast<GLFWwindow*>(windowing->GetWindowPtr());

glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, 1);

while (isRunning)
{
camera.FOV(fov);
projMatrix = camera.BuildPerspectiveMatrix();

camera.Transform().Origin().x(x);
camera.Transform().Origin().y(y);
camera.Transform().Origin().z(z);
int left = glfwGetKey(window, GLFW_KEY_A);
int right = glfwGetKey(window, GLFW_KEY_D);
int forward = glfwGetKey(window, GLFW_KEY_W);
int back = glfwGetKey(window, GLFW_KEY_S);
lepus::types::Vector3 forwardDelta, rightDelta;
if (back == GLFW_PRESS)
{
forwardDelta = forwardDelta - (camera.Transform().Forward() * deltaTime * camSpeed);
}
if (forward == GLFW_PRESS)
{
forwardDelta = forwardDelta + (camera.Transform().Forward() * deltaTime * camSpeed);
}
if (right == GLFW_PRESS)
{
rightDelta = rightDelta + (camera.Transform().Right() * deltaTime * camSpeed);
}
if (left == GLFW_PRESS)
{
rightDelta = rightDelta - (camera.Transform().Right() * deltaTime * camSpeed);
}

camera.Transform().Origin(camera.Transform().Origin() + forwardDelta + rightDelta);


/*
camera.Transform().Origin().x(x);
camera.Transform().Origin().y(y);
camera.Transform().Origin().z(z);
*/
camera.Transform().Rotation().w(angle);
viewMatrix = camera.BuildViewMatrix();

Expand All @@ -145,7 +165,10 @@ int main()
windowing->Update(); // Update window before drawing
engine.Render<unsigned char, Lepus3D::GraphicsEngine::PixelFormat::RGBA32>(100, 149, 237);

runningTime = glfwGetTime();
float newRunningTime = glfwGetTime();
deltaTime = newRunningTime - runningTime;

ConsoleLogger::Global().LogInfo("", "main", (char*)camera.Transform().Forward().ToString().c_str());

isRunning = windowing->Update();
}
Expand Down
1 change: 1 addition & 0 deletions src/LUtility/Math.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "Types/Vector.h"
#include "Types/Matrix4x4.h"
#include "Types/Quaternion.h"
#include "Types/Transform.h"

#define DEG2RAD PI/180.0
Expand Down
10 changes: 10 additions & 0 deletions src/LUtility/Types/Matrix4x4.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ namespace lepus
return ret;
}

lepus::types::Vector4 Multiply(const lepus::types::Vector4& v) const
{
return lepus::types::Vector4(
get(0, 0) * v.x() + get(0, 1) * v.y() + get(0, 2) * v.z() + get(0, 3) * v.w(),
get(1, 0) * v.x() + get(1, 1) * v.y() + get(1, 2) * v.z() + get(1, 3) * v.w(),
get(2, 0) * v.x() + get(2, 1) * v.y() + get(2, 2) * v.z() + get(2, 3) * v.w(),
get(3, 0) * v.x() + get(3, 1) * v.y() + get(3, 2) * v.z() + get(3, 3) * v.w()
);
}

inline const float* data() const
{
return m_Elements;
Expand Down
42 changes: 42 additions & 0 deletions src/LUtility/Types/Quaternion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef LEPUS_UTILITY_TYPES_QUATERNION
#define LEPUS_UTILITY_TYPES_QUATERNION

#include "Vector.h"

namespace lepus
{
namespace types
{
class Quaternion : public Vector4
{
public:
Quaternion()
{
const float const identity[] = { 0.f, 0.f, 0.f, 1.f };
init((float*)identity);
}

Quaternion(const Quaternion& quat)
{
init(quat);
}

Quaternion(float* quatData)
{
init(quatData);
}

inline Quaternion operator*(const Quaternion& b)
{
// TODO: use scalar/vector notation for multiplying quaternions
Quaternion result = Quaternion();
result.x(x() * b.x());
result.y(y() * b.y());
result.z(z() * b.z());
result.w(w() * b.w());
}
};
}
}

#endif
73 changes: 67 additions & 6 deletions src/LUtility/Types/Transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,86 @@ namespace lepus
private:
lepus::types::Vector3 m_Origin, m_Forward, m_Right, m_Up;
// axis-angle
lepus::types::Vector4 m_Rotation;
lepus::types::Quaternion m_Rotation;

public:
Transform()
{
m_Origin = lepus::types::Vector3();

m_Forward = lepus::types::Vector3(0.f, 0.f, 1.f);
m_Forward = lepus::types::Vector3(0.f, 0.f, -1.f);
m_Right = lepus::types::Vector3(1.f, 0.f, 0.f);
m_Up = lepus::types::Vector3(0.f, 1.f, 0.f);

m_Rotation = lepus::types::Vector4(0.f, 0.f, 0.f, 1.f);
m_Rotation = lepus::types::Quaternion();
}

inline lepus::types::Vector3& Origin() { return m_Origin; }
inline lepus::types::Vector3 const& Forward() { return m_Forward; }
inline lepus::types::Vector3 const& Right() { return m_Right; }
inline lepus::types::Vector3 const& Up() { return m_Up; }
inline void Origin(lepus::types::Vector3& vec)
{
m_Origin.x(vec.x());
m_Origin.y(vec.y());
m_Origin.z(vec.z());
}
inline lepus::types::Vector3 Forward() { return lepus::types::Vector3(m_Forward); }
inline lepus::types::Vector3 Right() { return lepus::types::Vector3(m_Right); }
inline lepus::types::Vector3 Up() { return lepus::types::Vector3(m_Up); }
inline lepus::types::Vector4& Rotation() { return m_Rotation; }
inline void Rotation(lepus::types::Vector4& newRotation)
{
m_Rotation.x(newRotation.x());
m_Rotation.y(newRotation.y());
m_Rotation.z(newRotation.z());
m_Rotation.w(newRotation.w());
}

inline void Rotation(float x, float y, float z, float w)
{
m_Rotation.x(x);
m_Rotation.y(y);
m_Rotation.z(z);
m_Rotation.w(w);
}

inline void Rotate(lepus::types::Vector3& axis, float angle)
{
lepus::math::Matrix4x4 rotationMatrix = AxisAngle(axis, -angle);

auto newForward = rotationMatrix.Multiply(lepus::types::Vector4(m_Forward));
auto newRight = rotationMatrix.Multiply(lepus::types::Vector4(m_Right));
auto newUp = rotationMatrix.Multiply(lepus::types::Vector4(m_Up));

m_Forward.x(newForward.x());m_Forward.y(newForward.y());m_Forward.z(newForward.z());
m_Right.x(newRight.x());m_Right.y(newRight.y());m_Right.z(newRight.z());
m_Up.x(newUp.x());m_Up.y(newUp.y());m_Up.z(newUp.z());

lepus::types::Vector4& currentRot = Rotation();
// TODO: Set the rotation to a multiplication of currentRot by the delta quaternion
}

static inline lepus::math::Matrix4x4 AxisAngle(lepus::types::Vector3& axis, float angle)
{
lepus::math::Matrix4x4 ret = lepus::math::Matrix4x4::Identity();

lepus::types::Vector3 unitAxis = axis * (1.f / axis.Magnitude());

float c = cosf(angle);
float s = sinf(angle);

ret.set<0, 0>(c + (unitAxis.x() * unitAxis.x() * (1.f - c)));
ret.set<1, 0>((unitAxis.y() * unitAxis.x() * (1.f - c)) + (unitAxis.z() * s));
ret.set<2, 0>((unitAxis.z() * unitAxis.x() * (1.f - c)) - (unitAxis.y() * s));

ret.set<0, 1>((unitAxis.y() * unitAxis.x() * (1.f - c)) - (unitAxis.z() * s));
ret.set<1, 1>(c + (unitAxis.y() * unitAxis.y() * (1.f - c)));
ret.set<2, 1>((unitAxis.z() * unitAxis.y() * (1.f - c)) + (unitAxis.x() * s));

ret.set<0, 2>((unitAxis.z() * unitAxis.x() * (1.f - c)) + (unitAxis.y() * s));
ret.set<1, 2>((unitAxis.z() * unitAxis.y() * (1.f - c)) - (unitAxis.x() * s));
ret.set<2, 2>(c + (unitAxis.z() * unitAxis.z() * (1.f - c)));

return ret;
}
};
}
}
Expand Down
Loading

0 comments on commit 07e95d0

Please sign in to comment.