bullet3/examples/OpenGLWindow/SimpleCamera.cpp
erwincoumans ab8f16961e Code-style consistency improvement:
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files.
make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type.
This commit contains no other changes aside from adding and applying clang-format-all.sh
2018-09-23 14:17:31 -07:00

434 lines
9.8 KiB
C++

#include "SimpleCamera.h"
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3Quaternion.h"
#include "Bullet3Common/b3Matrix3x3.h"
#include "Bullet3Common/b3Transform.h"
B3_ATTRIBUTE_ALIGNED16(struct)
SimpleCameraInternalData
{
SimpleCameraInternalData()
: m_cameraTargetPosition(b3MakeVector3(0, 0, 0)),
m_cameraDistance(20),
m_cameraUp(b3MakeVector3(0, 1, 0)),
m_cameraForward(b3MakeVector3(1, 0, 0)),
m_cameraUpAxis(1),
m_yaw(20),
m_pitch(0),
m_aspect(1),
m_frustumZNear(0.01),
m_frustumZFar(1000),
m_enableVR(false)
{
b3Transform tr;
tr.setIdentity();
tr.getOpenGLMatrix(m_offsetTransformVR);
}
B3_DECLARE_ALIGNED_ALLOCATOR();
B3_ATTRIBUTE_ALIGNED16(float)
m_offsetTransformVR[16];
b3Vector3 m_cameraTargetPosition;
float m_cameraDistance;
b3Vector3 m_cameraUp;
b3Vector3 m_cameraForward;
int m_cameraUpAxis;
//the m_cameraPosition is a cached value, recomputed from other values
b3Vector3 m_cameraPosition;
float m_yaw;
float m_pitch;
float m_aspect;
float m_frustumZNear;
float m_frustumZFar;
bool m_enableVR;
float m_viewMatrixVR[16];
float m_projectionMatrixVR[16];
};
SimpleCamera::SimpleCamera()
{
m_data = new SimpleCameraInternalData;
}
SimpleCamera::~SimpleCamera()
{
delete m_data;
}
void SimpleCamera::setVRCamera(const float viewMat[16], const float projectionMatrix[16])
{
m_data->m_enableVR = true;
b3Matrix3x3 vm;
vm.setValue(viewMat[0], viewMat[4], viewMat[8],
viewMat[1], viewMat[5], viewMat[9],
viewMat[2], viewMat[6], viewMat[10]);
b3Vector3 vp = b3MakeVector3(viewMat[12], viewMat[13], viewMat[14]);
b3Transform tr;
tr.setBasis(vm);
tr.setOrigin(vp);
b3Transform cp = tr.inverse();
m_data->m_cameraPosition = cp.getOrigin();
for (int i = 0; i < 16; i++)
{
m_data->m_viewMatrixVR[i] = viewMat[i];
m_data->m_projectionMatrixVR[i] = projectionMatrix[i];
m_data->m_frustumZNear = m_data->m_projectionMatrixVR[14] / (m_data->m_projectionMatrixVR[10] - 1);
m_data->m_frustumZFar = m_data->m_projectionMatrixVR[14] / (m_data->m_projectionMatrixVR[10] + 1);
}
}
bool SimpleCamera::getVRCamera(float viewMat[16], float projectionMatrix[16])
{
if (m_data->m_enableVR)
{
for (int i = 0; i < 16; i++)
{
viewMat[i] = m_data->m_viewMatrixVR[i];
projectionMatrix[i] = m_data->m_projectionMatrixVR[i];
}
}
return false;
}
void SimpleCamera::disableVRCamera()
{
m_data->m_enableVR = false;
}
bool SimpleCamera::isVRCamera() const
{
return m_data->m_enableVR;
}
static void b3CreateFrustum(
float left,
float right,
float bottom,
float top,
float nearVal,
float farVal,
float frustum[16])
{
frustum[0 * 4 + 0] = (float(2) * nearVal) / (right - left);
frustum[0 * 4 + 1] = float(0);
frustum[0 * 4 + 2] = float(0);
frustum[0 * 4 + 3] = float(0);
frustum[1 * 4 + 0] = float(0);
frustum[1 * 4 + 1] = (float(2) * nearVal) / (top - bottom);
frustum[1 * 4 + 2] = float(0);
frustum[1 * 4 + 3] = float(0);
frustum[2 * 4 + 0] = (right + left) / (right - left);
frustum[2 * 4 + 1] = (top + bottom) / (top - bottom);
frustum[2 * 4 + 2] = -(farVal + nearVal) / (farVal - nearVal);
frustum[2 * 4 + 3] = float(-1);
frustum[3 * 4 + 0] = float(0);
frustum[3 * 4 + 1] = float(0);
frustum[3 * 4 + 2] = -(float(2) * farVal * nearVal) / (farVal - nearVal);
frustum[3 * 4 + 3] = float(0);
}
#if 0
static void b3CreateDiagonalMatrix(float value, float result[4][4])
{
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
{
if (i==j)
{
result[i][j] = value;
} else
{
result[i][j] = 0.f;
}
}
}
}
static void b3CreateOrtho(float left, float right, float bottom, float top, float zNear, float zFar, float result[4][4])
{
b3CreateDiagonalMatrix(1.f,result);
result[0][0] = 2.f / (right - left);
result[1][1] = 2.f / (top - bottom);
result[2][2] = - 2.f / (zFar - zNear);
result[3][0] = - (right + left) / (right - left);
result[3][1] = - (top + bottom) / (top - bottom);
result[3][2] = - (zFar + zNear) / (zFar - zNear);
}
#endif
static void b3CreateLookAt(const b3Vector3& eye, const b3Vector3& center, const b3Vector3& up, float result[16])
{
b3Vector3 f = (center - eye).normalized();
b3Vector3 u = up.normalized();
b3Vector3 s = (f.cross(u)).normalized();
u = s.cross(f);
result[0 * 4 + 0] = s.x;
result[1 * 4 + 0] = s.y;
result[2 * 4 + 0] = s.z;
result[0 * 4 + 1] = u.x;
result[1 * 4 + 1] = u.y;
result[2 * 4 + 1] = u.z;
result[0 * 4 + 2] = -f.x;
result[1 * 4 + 2] = -f.y;
result[2 * 4 + 2] = -f.z;
result[0 * 4 + 3] = 0.f;
result[1 * 4 + 3] = 0.f;
result[2 * 4 + 3] = 0.f;
result[3 * 4 + 0] = -s.dot(eye);
result[3 * 4 + 1] = -u.dot(eye);
result[3 * 4 + 2] = f.dot(eye);
result[3 * 4 + 3] = 1.f;
}
void SimpleCamera::setCameraUpAxis(int upAxis)
{
m_data->m_cameraUpAxis = upAxis;
update();
}
int SimpleCamera::getCameraUpAxis() const
{
return m_data->m_cameraUpAxis;
}
void SimpleCamera::update()
{
b3Scalar yawRad = m_data->m_yaw * b3Scalar(0.01745329251994329547); // rads per deg
b3Scalar pitchRad = m_data->m_pitch * b3Scalar(0.01745329251994329547); // rads per deg
b3Scalar rollRad = 0.0;
b3Quaternion eyeRot;
int forwardAxis(-1);
switch (m_data->m_cameraUpAxis)
{
case 1:
forwardAxis = 2;
m_data->m_cameraUp = b3MakeVector3(0, 1, 0);
//gLightPos = b3MakeVector3(-50.f,100,30);
eyeRot.setEulerZYX(rollRad, yawRad, -pitchRad);
break;
case 2:
forwardAxis = 1;
m_data->m_cameraUp = b3MakeVector3(0, 0, 1);
//gLightPos = b3MakeVector3(-50.f,30,100);
eyeRot.setEulerZYX(yawRad, rollRad, pitchRad);
break;
default:
{
//b3Assert(0);
return;
}
};
b3Vector3 eyePos = b3MakeVector3(0, 0, 0);
eyePos[forwardAxis] = -m_data->m_cameraDistance;
eyePos = b3Matrix3x3(eyeRot) * eyePos;
m_data->m_cameraPosition = eyePos;
m_data->m_cameraPosition += m_data->m_cameraTargetPosition;
m_data->m_cameraForward = m_data->m_cameraTargetPosition - m_data->m_cameraPosition;
if (m_data->m_cameraForward.length2() < B3_EPSILON)
{
m_data->m_cameraForward.setValue(1.f, 0.f, 0.f);
}
else
{
m_data->m_cameraForward.normalize();
}
}
void SimpleCamera::getCameraProjectionMatrix(float projectionMatrix[16]) const
{
if (m_data->m_enableVR)
{
for (int i = 0; i < 16; i++)
{
projectionMatrix[i] = m_data->m_projectionMatrixVR[i];
}
}
else
{
b3CreateFrustum(-m_data->m_aspect * m_data->m_frustumZNear, m_data->m_aspect * m_data->m_frustumZNear, -m_data->m_frustumZNear, m_data->m_frustumZNear, m_data->m_frustumZNear, m_data->m_frustumZFar, projectionMatrix);
}
}
void SimpleCamera::setVRCameraOffsetTransform(const float offset[16])
{
for (int i = 0; i < 16; i++)
{
m_data->m_offsetTransformVR[i] = offset[i];
}
}
void SimpleCamera::getCameraViewMatrix(float viewMatrix[16]) const
{
if (m_data->m_enableVR)
{
for (int i = 0; i < 16; i++)
{
b3Transform tr;
tr.setFromOpenGLMatrix(m_data->m_viewMatrixVR);
b3Transform shift = b3Transform::getIdentity();
shift.setFromOpenGLMatrix(m_data->m_offsetTransformVR);
tr = tr * shift;
tr.getOpenGLMatrix(viewMatrix);
//viewMatrix[i] = m_data->m_viewMatrixVR[i];
}
}
else
{
b3CreateLookAt(m_data->m_cameraPosition, m_data->m_cameraTargetPosition, m_data->m_cameraUp, viewMatrix);
}
}
void SimpleCamera::getCameraTargetPosition(double pos[3]) const
{
pos[0] = m_data->m_cameraTargetPosition[0];
pos[1] = m_data->m_cameraTargetPosition[1];
pos[2] = m_data->m_cameraTargetPosition[2];
}
void SimpleCamera::getCameraPosition(double pos[3]) const
{
pos[0] = m_data->m_cameraPosition[0];
pos[1] = m_data->m_cameraPosition[1];
pos[2] = m_data->m_cameraPosition[2];
}
void SimpleCamera::getCameraTargetPosition(float pos[3]) const
{
pos[0] = m_data->m_cameraTargetPosition[0];
pos[1] = m_data->m_cameraTargetPosition[1];
pos[2] = m_data->m_cameraTargetPosition[2];
}
void SimpleCamera::getCameraPosition(float pos[3]) const
{
pos[0] = m_data->m_cameraPosition[0];
pos[1] = m_data->m_cameraPosition[1];
pos[2] = m_data->m_cameraPosition[2];
}
void SimpleCamera::setCameraTargetPosition(float x, float y, float z)
{
m_data->m_cameraTargetPosition.setValue(x, y, z);
update();
}
float SimpleCamera::getCameraDistance() const
{
return m_data->m_cameraDistance;
}
void SimpleCamera::setCameraDistance(float dist)
{
m_data->m_cameraDistance = dist;
update();
}
void SimpleCamera::setCameraUpVector(float x, float y, float z)
{
m_data->m_cameraUp.setValue(x, y, z);
update();
}
void SimpleCamera::getCameraUpVector(float up[3]) const
{
if (m_data->m_enableVR)
{
float viewMatTotal[16];
getCameraViewMatrix(viewMatTotal);
up[0] = viewMatTotal[0];
up[1] = viewMatTotal[4];
up[2] = viewMatTotal[8];
}
else
{
up[0] = float(m_data->m_cameraUp[0]);
up[1] = float(m_data->m_cameraUp[1]);
up[2] = float(m_data->m_cameraUp[2]);
}
}
void SimpleCamera::getCameraForwardVector(float fwd[3]) const
{
if (m_data->m_enableVR)
{
float viewMatTotal[16];
getCameraViewMatrix(viewMatTotal);
fwd[0] = viewMatTotal[2];
fwd[1] = viewMatTotal[6];
fwd[2] = viewMatTotal[10];
}
else
{
fwd[0] = float(m_data->m_cameraForward[0]);
fwd[1] = float(m_data->m_cameraForward[1]);
fwd[2] = float(m_data->m_cameraForward[2]);
}
}
void SimpleCamera::setCameraYaw(float yaw)
{
m_data->m_yaw = yaw;
update();
}
float SimpleCamera::getCameraYaw() const
{
return m_data->m_yaw;
}
void SimpleCamera::setCameraPitch(float pitch)
{
m_data->m_pitch = pitch;
update();
}
void SimpleCamera::setAspectRatio(float ratio)
{
m_data->m_aspect = ratio;
update();
}
float SimpleCamera::getCameraPitch() const
{
return m_data->m_pitch;
}
float SimpleCamera::getAspectRatio() const
{
return m_data->m_aspect;
}
float SimpleCamera::getCameraFrustumFar() const
{
return m_data->m_frustumZFar;
}
float SimpleCamera::getCameraFrustumNear() const
{
return m_data->m_frustumZNear;
}
void SimpleCamera::setCameraFrustumFar(float far)
{
m_data->m_frustumZFar = far;
}
void SimpleCamera::setCameraFrustumNear(float near)
{
m_data->m_frustumZNear = near;
}