140 lines
4.7 KiB
C++
140 lines
4.7 KiB
C++
#include <DirectXMath.h>
|
|
#include <fstream>
|
|
|
|
class Camera {
|
|
public:
|
|
Camera() {
|
|
reset();
|
|
}
|
|
|
|
~Camera() {
|
|
|
|
}
|
|
|
|
void reset() {
|
|
m_cameraViewUp = DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f);
|
|
m_cameraViewDirection = DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f);
|
|
m_cameraViewPosition = DirectX::XMFLOAT3(0.0f, 0.0f, 3.0f);
|
|
}
|
|
|
|
void translate(float us, float vs, float ws) {
|
|
// RHS coordinate system U, V, W
|
|
DirectX::XMVECTOR w = DirectX::XMVectorScale(DirectX::XMLoadFloat3(&m_cameraViewDirection), -1.0f);
|
|
DirectX::XMVECTOR v = DirectX::XMLoadFloat3(&m_cameraViewUp);
|
|
DirectX::XMVECTOR u = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(v, w));
|
|
|
|
DirectX::XMVECTOR p = XMLoadFloat3(&m_cameraViewPosition);
|
|
|
|
DirectX::XMVECTOR wScaled = DirectX::XMVectorScale(u, us);
|
|
DirectX::XMVECTOR vScaled = DirectX::XMVectorScale(v, vs);
|
|
DirectX::XMVECTOR uScaled = DirectX::XMVectorScale(w, ws);
|
|
|
|
DirectX::XMStoreFloat3(&m_cameraViewPosition, DirectX::XMVectorAdd(p, DirectX::XMVectorAdd(uScaled, DirectX::XMVectorAdd(vScaled, wScaled))));
|
|
}
|
|
|
|
void rotateAroundU(float theta) {
|
|
// RHS coordinate system U, V, W
|
|
DirectX::XMVECTOR w = DirectX::XMVectorScale(DirectX::XMLoadFloat3(&m_cameraViewDirection), -1.0f);
|
|
DirectX::XMVECTOR v = DirectX::XMLoadFloat3(&m_cameraViewUp);
|
|
DirectX::XMVECTOR u = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(v, w));
|
|
|
|
float cosTheta = std::cos(theta);
|
|
float sinTheta = std::sin(theta);
|
|
|
|
// Rodriguez rotation of W around U
|
|
DirectX::XMVECTOR wNew = DirectX::XMVectorAdd(
|
|
DirectX::XMVectorScale(w, cosTheta),
|
|
DirectX::XMVectorScale(DirectX::XMVector3Normalize(DirectX::XMVector3Cross(u, w)), sinTheta));
|
|
|
|
// Rodriguez rotation of V around U
|
|
DirectX::XMVECTOR vNew = DirectX::XMVectorAdd(
|
|
DirectX::XMVectorScale(v, cosTheta),
|
|
DirectX::XMVectorScale(DirectX::XMVector3Normalize(DirectX::XMVector3Cross(u, v)), sinTheta));
|
|
|
|
// Compute and store new view direction (-W)
|
|
DirectX::XMStoreFloat3(&m_cameraViewDirection, DirectX::XMVectorScale(wNew, -1.0f));
|
|
|
|
// Store new up vector
|
|
DirectX::XMStoreFloat3(&m_cameraViewUp, vNew);
|
|
}
|
|
|
|
void rotateAroundV(float theta) {
|
|
// RHS coordinate system U, V, W
|
|
DirectX::XMVECTOR w = DirectX::XMVectorScale(DirectX::XMLoadFloat3(&m_cameraViewDirection), -1.0f);
|
|
DirectX::XMVECTOR v = DirectX::XMLoadFloat3(&m_cameraViewUp);
|
|
DirectX::XMVECTOR u = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(v, w));
|
|
|
|
float cosTheta = std::cos(theta);
|
|
float sinTheta = std::sin(theta);
|
|
|
|
// Rodriguez rotation of W around V
|
|
DirectX::XMVECTOR wNew = DirectX::XMVectorAdd(
|
|
DirectX::XMVectorScale(w, cosTheta),
|
|
DirectX::XMVectorScale(DirectX::XMVector3Normalize(DirectX::XMVector3Cross(v, w)), sinTheta));
|
|
|
|
// Compute and store new view direction (-W)
|
|
DirectX::XMStoreFloat3(&m_cameraViewDirection, DirectX::XMVectorScale(wNew, -1.0f));
|
|
}
|
|
|
|
void rotateAroundW(float theta) {
|
|
// RHS coordinate system U, V, W
|
|
DirectX::XMVECTOR w = DirectX::XMVectorScale(DirectX::XMLoadFloat3(&m_cameraViewDirection), -1.0f);
|
|
DirectX::XMVECTOR v = DirectX::XMLoadFloat3(&m_cameraViewUp);
|
|
DirectX::XMVECTOR u = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(v, w));
|
|
|
|
float cosTheta = std::cos(theta);
|
|
float sinTheta = std::sin(theta);
|
|
|
|
// Rodriguez rotation of V around W
|
|
DirectX::XMVECTOR vNew = DirectX::XMVectorAdd(
|
|
DirectX::XMVectorScale(v, cosTheta),
|
|
DirectX::XMVectorScale(DirectX::XMVector3Normalize(DirectX::XMVector3Cross(w, v)), sinTheta));
|
|
|
|
// Store new up vector
|
|
DirectX::XMStoreFloat3(&m_cameraViewUp, vNew);
|
|
}
|
|
|
|
|
|
const DirectX::XMFLOAT3& getViewUp() {
|
|
return m_cameraViewUp;
|
|
}
|
|
|
|
const DirectX::XMFLOAT3& getViewPosition() {
|
|
return m_cameraViewPosition;
|
|
}
|
|
|
|
const DirectX::XMFLOAT3& getViewDirection() {
|
|
return m_cameraViewDirection;
|
|
}
|
|
|
|
void storeCamera(std::string cameraFilename) {
|
|
std::ofstream outfile(cameraFilename.c_str(), std::ios::out | std::ios::binary);
|
|
|
|
outfile.write(reinterpret_cast<char*>(&m_cameraViewUp), sizeof(DirectX::XMFLOAT3));
|
|
outfile.write(reinterpret_cast<char*>(&m_cameraViewDirection), sizeof(DirectX::XMFLOAT3));
|
|
outfile.write(reinterpret_cast<char*>(&m_cameraViewPosition), sizeof(DirectX::XMFLOAT3));
|
|
|
|
outfile.close();
|
|
}
|
|
|
|
void loadCamera(std::string cameraFilename) {
|
|
std::ifstream infile(cameraFilename.c_str(), std::ios::out | std::ios::binary);
|
|
|
|
infile.read(reinterpret_cast<char*>(&m_cameraViewUp), sizeof(DirectX::XMFLOAT3));
|
|
infile.read(reinterpret_cast<char*>(&m_cameraViewDirection), sizeof(DirectX::XMFLOAT3));
|
|
infile.read(reinterpret_cast<char*>(&m_cameraViewPosition), sizeof(DirectX::XMFLOAT3));
|
|
|
|
|
|
infile.close();
|
|
}
|
|
|
|
|
|
protected:
|
|
DirectX::XMFLOAT3 m_cameraViewUp; // Y
|
|
DirectX::XMFLOAT3 m_cameraViewDirection; // -Z
|
|
DirectX::XMFLOAT3 m_cameraViewPosition; // P
|
|
|
|
float m_fovY;
|
|
|
|
|
|
}; |