152 lines
3.7 KiB
C++
152 lines
3.7 KiB
C++
#include "directxmath/DirectXMath.h"
|
|
|
|
#include "camera.h"
|
|
|
|
struct CameraState {
|
|
XMFLOAT3 eye;
|
|
XMFLOAT3 look;
|
|
XMFLOAT3 up;
|
|
float yaw;
|
|
float pitch;
|
|
float fov;
|
|
|
|
XMFLOAT3 light_position;
|
|
};
|
|
|
|
struct ViewState {
|
|
XMFLOAT4X4 viewProj;
|
|
XMFLOAT4X4 lightViewProj;
|
|
XMFLOAT4 lightPosition;
|
|
XMFLOAT4 eyePosition;
|
|
};
|
|
|
|
static inline XMMATRIX camera_view(CameraState const * state)
|
|
{
|
|
XMMATRIX view = XMMatrixLookToRH(XMLoadFloat3(&state->eye),
|
|
XMLoadFloat3(&state->look),
|
|
XMLoadFloat3(&state->up));
|
|
return view;
|
|
}
|
|
|
|
static inline XMMATRIX camera_projection(CameraState const * state, float aspect)
|
|
{
|
|
float near_z = 0.01;
|
|
float far_z = 1000.0;
|
|
|
|
XMMATRIX projection = XMMatrixPerspectiveFovRH(state->fov,
|
|
aspect,
|
|
near_z,
|
|
far_z);
|
|
return projection;
|
|
};
|
|
|
|
extern "C" void log(float x);
|
|
|
|
static inline float min(float a, float b)
|
|
{
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
static inline float max(float a, float b)
|
|
{
|
|
return a > b ? a : b;
|
|
}
|
|
|
|
static inline float fract(float a)
|
|
{
|
|
return a - __builtin_floorf(a);
|
|
}
|
|
|
|
void camera_move(CameraState * state,
|
|
int lu, int ll, int ld, int lr,
|
|
int lal, int lar,
|
|
int ru, int rl, int rd, int rr)
|
|
{
|
|
const float linearSpeed = 0.3;
|
|
const float rotationalSpeed = 0.025;
|
|
XMFLOAT3 move = {0, 0, 0};
|
|
|
|
if (ll)
|
|
move.x -= 1.0;
|
|
if (lr)
|
|
move.x += 1.0;
|
|
if (lu)
|
|
move.z -= 1.0;
|
|
if (ld)
|
|
move.z += 1.0;
|
|
if (lal)
|
|
move.y += 1.0;
|
|
if (lar)
|
|
move.y -= 1.0;
|
|
//XMStoreFloat3(&move, XMVector3Normalize(XMLoadFloat3(&move)));
|
|
|
|
if (rl)
|
|
state->yaw += rotationalSpeed;
|
|
if (rr)
|
|
state->yaw -= rotationalSpeed;
|
|
if (ru)
|
|
state->pitch += rotationalSpeed;
|
|
if (rd)
|
|
state->pitch -= rotationalSpeed;
|
|
|
|
state->pitch = min(state->pitch, XM_PIDIV2 * 0.9);
|
|
state->pitch = max(state->pitch, -XM_PIDIV2 * 0.9);
|
|
|
|
state->yaw = fract(state->yaw * (1.0f / XM_2PI)) * XM_2PI;
|
|
|
|
float sinyaw;
|
|
float cosyaw;
|
|
XMScalarSinCos(&sinyaw, &cosyaw, state->yaw);
|
|
|
|
// eye
|
|
float x = move.x * -cosyaw - move.z * sinyaw;
|
|
float y = move.y;
|
|
float z = move.x * sinyaw - move.z * cosyaw;
|
|
state->eye.x += x * linearSpeed;
|
|
state->eye.y += y * linearSpeed;
|
|
state->eye.z += z * linearSpeed;
|
|
|
|
// look
|
|
float sinpitch;
|
|
float cospitch;
|
|
XMScalarSinCos(&sinpitch, &cospitch, state->pitch);
|
|
state->look.x = cospitch * sinyaw;
|
|
state->look.y = sinpitch;
|
|
state->look.z = cospitch * cosyaw;
|
|
}
|
|
|
|
void camera_init(CameraState * camera_state)
|
|
{
|
|
camera_state->fov = XMConvertToRadians(45 * 1.5);
|
|
|
|
camera_state->yaw = XM_PI;
|
|
camera_state->pitch = 0.0f;
|
|
|
|
camera_state->up = {0, 1, 0};
|
|
camera_state->look = {0, 0, -1};
|
|
camera_state->eye = {0, 0, 5};
|
|
|
|
camera_state->light_position = {10, 10, 10};
|
|
}
|
|
|
|
void camera_view_projection(CameraState * camera_state,
|
|
ViewState * view_state,
|
|
float aspect)
|
|
{
|
|
XMVECTOR light_position = XMLoadFloat3(&camera_state->light_position);
|
|
light_position = XMVector3Transform(light_position, XMMatrixRotationY(0.025));
|
|
XMStoreFloat3(&camera_state->light_position, light_position);
|
|
|
|
XMMATRIX view = camera_view(camera_state);
|
|
XMMATRIX projection = camera_projection(camera_state, aspect);
|
|
|
|
XMMATRIX view_projection = view * projection;
|
|
|
|
XMMATRIX light_world = XMMatrixTranslationFromVector(light_position);
|
|
|
|
XMStoreFloat4x4(&view_state->viewProj, view_projection);
|
|
XMStoreFloat4x4(&view_state->lightViewProj, light_world * view_projection);
|
|
XMStoreFloat4(&view_state->lightPosition, light_position);
|
|
XMStoreFloat4(&view_state->eyePosition, XMLoadFloat3(&camera_state->eye));
|
|
}
|