Initial commit of KazEngine3
[kazengine.git] / src / scene / camera.cpp
blob27b46bb07822516e9833c5e09de1c07fa20302ee
2 #include <kazmath/utility.h>
3 #include <kazmathxx/mat4.h>
4 #include <kazmathxx/vec3.h>
5 #include <GL/gl.h>
7 #include "scene/camera.h"
9 namespace engine {
11 namespace scene {
13 Camera::Camera(const string& name):
14 yawFixed(false),
15 m_FrustumNeedsUpdating(true) {
16 m_Name = name;
17 kmQuaternionIdentity(&m_Orientation);
20 Camera::Camera(const string& name, const Vec3& vec):
21 yawFixed(false),
22 m_FrustumNeedsUpdating(true) {
23 m_Name = name;
24 m_Position = vec;
25 kmQuaternionIdentity(&m_Orientation);
28 Camera::Camera(const string& name, float x, float y, float z):
29 yawFixed(false),
30 m_FrustumNeedsUpdating(true) {
31 m_Name = name;
32 m_Position = Vec3(x, y, z);
33 kmQuaternionIdentity(&m_Orientation);
36 void Camera::setPosition(const Vec3& vec) {
37 m_Position = vec;
40 void Camera::lookAt(const Vec3& vec) {
41 Vec3 newForward;
42 newForward = vec - m_Position;
43 setDirection(newForward);
44 m_FrustumNeedsUpdating = true;
47 void Camera::setNearClipDistance(float dist) {
51 void Camera::setFarClipDistance(float dist) {
55 void Camera::yaw(float angle) {
56 Vec3 yAxis;
58 if (yawFixed) {
59 // Rotate around fixed yaw axis
60 yAxis = yawFixedAxis;
61 } else {
62 Vec3 UNIT_Y(0, 1, 0);
63 kmQuaternionMultiplyVec3(&yAxis, &m_Orientation, &UNIT_Y);
66 rotate(yAxis, angle);
67 m_FrustumNeedsUpdating = true;
70 void Camera::pitch(float angle) {
71 Vec3 xAxis;
73 Vec3 UNIT_X(1, 0, 0);
74 kmQuaternionMultiplyVec3(&xAxis, &m_Orientation, &UNIT_X);
76 rotate(xAxis, angle);
78 m_FrustumNeedsUpdating = true;
81 void Camera::roll(float val) {
85 void Camera::rotate(const Vec3& axis, float angle) {
86 kmQuaternion q;
87 kmQuaternionRotationAxis(&q, &axis, kmDegreesToRadians(angle));
89 rotate(q);
92 void Camera::rotate(const kmQuaternion& q) {
93 kmQuaternion q2;
95 kmQuaternionNormalize(&q2, &q);
96 kmQuaternionMultiply(&m_Orientation, &q, &m_Orientation);
97 kmQuaternionNormalize(&m_Orientation, &m_Orientation);
98 m_FrustumNeedsUpdating = true;
101 /* Vec3 Camera::getUp() const {
102 return Vec3();
105 Vec3 Camera::getRight() const {
106 return Vec3();
109 Vec3 Camera::getForward() const {
110 return Vec3();
113 string Camera::getName() {
114 return m_Name;
117 void Camera::setFixedYawAxis(bool fixYaw, const Vec3& axis) {
118 yawFixed = fixYaw;
119 yawFixedAxis = axis;
122 void Camera::setOrientation(const kmQuaternion& q) {
123 m_Orientation = q;
126 void Camera::setDirection(const Vec3& vec) {
127 //Do nothing if the vector passed has no length
128 if (vec==Vec3()) {
129 return;
132 //Get the normalized vector, negated to take into accoun the Z axis
134 Vec3 normDir(-vec);
135 kmVec3Normalize(&normDir, &normDir);
137 //If the yaw axis is fixed (i.e. first person camera)
138 if (yawFixed) {
139 Vec3 right;
140 kmVec3Cross(&right, &yawFixedAxis, &normDir);
142 Vec3 up;
143 kmVec3Cross(&up, &normDir, &right);
145 //Set the orientation
146 kmMat4 rotation;
147 kmMat4Identity(&rotation);
149 rotation.m_Mat[0] = right.x;
150 rotation.m_Mat[1] = right.y;
151 rotation.m_Mat[2] = right.z;
153 rotation.m_Mat[4] = up.x;
154 rotation.m_Mat[5] = up.y;
155 rotation.m_Mat[6] = up.z;
157 rotation.m_Mat[8] = normDir.x;
158 rotation.m_Mat[9] = normDir.y;
159 rotation.m_Mat[10] = normDir.z;
161 kmQuaternionRotationMatrix(&m_Orientation, &rotation);
162 } else {
163 Vec3 axes[3];
164 Mat4 rotation;
166 kmMat4RotationQuaternion(&rotation, &m_Orientation);
167 axes[0].x = rotation.m_Mat[0];
168 axes[0].y = rotation.m_Mat[1];
169 axes[0].z = rotation.m_Mat[2];
171 axes[1].x = rotation.m_Mat[4];
172 axes[1].y = rotation.m_Mat[5];
173 axes[1].z = rotation.m_Mat[6];
175 axes[2].x = rotation.m_Mat[8];
176 axes[2].y = rotation.m_Mat[9];
177 axes[2].z = rotation.m_Mat[10];
180 kmQuaternion rotQuat;
181 Vec3 temp = axes[2] + normDir;
182 if (kmVec3LengthSq(&temp) < 0.00005f) {
183 kmQuaternionRotationAxis(&rotQuat, &axes[1], kmPI);
184 } else {
185 Vec3 fallback;
186 kmQuaternionRotationBetweenVec3(&rotQuat, &axes[2], &normDir, &fallback);
189 kmQuaternionMultiply(&m_Orientation, &rotQuat, &m_Orientation);
190 kmQuaternionNormalize(&m_Orientation, &m_Orientation);
193 m_FrustumNeedsUpdating = true;
196 void Camera::use() {
197 kmMat4 transform;
199 kmMat4RotationQuaternion(&transform, &m_Orientation);
200 glMultMatrixf(transform.m_Mat);
202 transform.m_Mat[12] = m_Position.x;
203 transform.m_Mat[13] = m_Position.y;
204 transform.m_Mat[14] = m_Position.z;
206 glTranslatef(m_Position.x, m_Position.y, m_Position.z);
208 if (m_FrustumNeedsUpdating) {
209 float model[16] = {0}; // Array to store the modelview matrix.
210 float proj[16] = {0}; // Array to store the projection matrix.
212 glGetFloatv(GL_PROJECTION_MATRIX, proj);
213 glGetFloatv(GL_MODELVIEW_MATRIX, model);
214 m_Frustum.update_frustum(model, proj);
218 void Camera::moveRelative(const Vec3& vec) {
219 // Transform the axes of the relative vector by camera's local axes
220 Vec3 trans;
222 kmQuaternionMultiplyVec3(&trans, &m_Orientation, &vec);
223 m_Position = m_Position + trans;
224 m_FrustumNeedsUpdating = true;