Skip to content

Commit

Permalink
[Engine] Camera ignores object hierarchy #491 (#492)
Browse files Browse the repository at this point in the history
[Engine] Camera ignores object hierarchy #491
  • Loading branch information
eprikazchikov authored Dec 8, 2022
1 parent 5351936 commit a9d22bb
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 117 deletions.
21 changes: 16 additions & 5 deletions engine/includes/components/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@

#include "renderable.h"

class PipelineContext;
class CameraPrivate;

class ENGINE_EXPORT Camera : public Component {
A_REGISTER(Camera, Component, Components)

Expand Down Expand Up @@ -56,7 +53,7 @@ class ENGINE_EXPORT Camera : public Component {
float fov() const;
void setFov(const float angle);

Vector4 &color() const;
Vector4 color() const;
void setColor(const Vector4 color);

float orthoSize() const;
Expand All @@ -81,7 +78,21 @@ class ENGINE_EXPORT Camera : public Component {
#endif

private:
CameraPrivate *p_ptr;
bool m_ortho;

float m_fov;

float m_near;

float m_far;

float m_ratio;

float m_focal;

float m_orthoSize;

Vector4 m_color;

};

Expand Down
162 changes: 50 additions & 112 deletions engine/src/components/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,75 +7,7 @@

#include "pipelinecontext.h"

class CameraPrivate {
public:
CameraPrivate() :
m_ortho(false),
m_fov(45.0), // 2*arctan(height/(2*distance))
m_near(0.1f),
m_far(1000.0f),
m_ratio(1.0f),
m_focal(1.0f),
m_orthoSize(1.0f),
m_color(Vector4()),
m_pipeline(nullptr) {

}

static inline bool intersect(Plane pl[6], Vector3 points[8]) {
for(int i = 0; i < 6; i++) {
if(pl[i].sqrDistance(points[0]) > 0) {
continue;
}
if(pl[i].sqrDistance(points[1]) > 0) {
continue;
}
if(pl[i].sqrDistance(points[2]) > 0) {
continue;
}
if(pl[i].sqrDistance(points[3]) > 0) {
continue;
}
if(pl[i].sqrDistance(points[4]) > 0) {
continue;
}
if(pl[i].sqrDistance(points[5]) > 0) {
continue;
}
if(pl[i].sqrDistance(points[6]) > 0) {
continue;
}
if(pl[i].sqrDistance(points[7]) > 0) {
continue;
}
return false;
}
return true;
}

bool m_ortho;

float m_fov;

float m_near;

float m_far;

float m_ratio;

float m_focal;

float m_orthoSize;

Vector4 m_color;

static Camera *s_current;

PipelineContext *m_pipeline;

};

Camera *CameraPrivate::s_current = nullptr;
Camera *s_currentCamera = nullptr;

/*!
\class Camera
Expand All @@ -85,32 +17,38 @@ Camera *CameraPrivate::s_current = nullptr;
*/

Camera::Camera() :
p_ptr(new CameraPrivate) {
m_ortho(false),
m_fov(45.0), // 2*arctan(height/(2*distance))
m_near(0.1f),
m_far(1000.0f),
m_ratio(1.0f),
m_focal(1.0f),
m_orthoSize(1.0f),
m_color(Vector4()) {

}

Camera::~Camera() {
delete p_ptr;
p_ptr = nullptr;

}
/*!
Returns view matrix for the camera.
*/
Matrix4 Camera::viewMatrix() const {
Transform *t = actor()->transform();
Matrix4 m;
m.translate(-t->position());
return Matrix4(t->quaternion().toMatrix()).inverse() * m;
m.translate(-t->worldPosition());
return Matrix4(t->worldQuaternion().toMatrix()).inverse() * m;
}
/*!
Returns projection matrix for the camera.
*/
Matrix4 Camera::projectionMatrix() const {
if(p_ptr->m_ortho) {
float width = p_ptr->m_orthoSize * p_ptr->m_ratio;
return Matrix4::ortho(-width / 2, width / 2, -p_ptr->m_orthoSize / 2, p_ptr->m_orthoSize / 2, p_ptr->m_near, p_ptr->m_far);
if(m_ortho) {
float width = m_orthoSize * m_ratio;
return Matrix4::ortho(-width / 2, width / 2, -m_orthoSize / 2, m_orthoSize / 2, m_near, m_far);
}
return Matrix4::perspective(p_ptr->m_fov, p_ptr->m_ratio, p_ptr->m_near, p_ptr->m_far);
return Matrix4::perspective(m_fov, m_ratio, m_near, m_far);
}
/*!
Transforms position from \a worldSpace into screen space using \a modelView and \a projection matrices.
Expand Down Expand Up @@ -162,19 +100,19 @@ Vector3 Camera::unproject(const Vector3 &screenSpace, const Matrix4 &modelView,
*/
Ray Camera::castRay(float x, float y) {
Transform *t = actor()->transform();
Vector3 p = t->position();
Vector3 dir = t->quaternion() * Vector3(0.0, 0.0,-1.0);
Vector3 p = t->worldPosition();
Vector3 dir = t->worldQuaternion() * Vector3(0.0, 0.0,-1.0);
dir.normalize();

Vector3 view;
if(p_ptr->m_ortho) {
p += t->quaternion() * Vector3((x - 0.5f) * p_ptr->m_orthoSize * p_ptr->m_ratio,
(y - 0.5f) * p_ptr->m_orthoSize, 0.0f);
if(m_ortho) {
p += t->worldQuaternion() * Vector3((x - 0.5f) * m_orthoSize * m_ratio,
(y - 0.5f) * m_orthoSize, 0.0f);
} else {
float tang = tan(p_ptr->m_fov * DEG2RAD);
float tang = tan(m_fov * DEG2RAD);
Vector3 right = dir.cross(Vector3(0.0f, 1.0f, 0.0f));
Vector3 up = right.cross(dir);
view = Vector3((x - 0.5f) * tang * p_ptr->m_ratio) * right +
view = Vector3((x - 0.5f) * tang * m_ratio) * right +
Vector3((y - 0.5f) * tang) * up + p + dir;

dir = (view - p);
Expand All @@ -186,123 +124,123 @@ Ray Camera::castRay(float x, float y) {
Returns field of view angle for the camera in degrees.
*/
float Camera::fov() const {
return p_ptr->m_fov;
return m_fov;
}
/*!
Sets field of view \a angle for the camera in degrees.
\note Applicable only for the perspective mode.
*/
void Camera::setFov(const float angle) {
p_ptr->m_fov = angle;
m_fov = angle;
}
/*!
Returns a distance to near cut plane.
*/
float Camera::nearPlane() const {
return p_ptr->m_near;
return m_near;
}
/*!
Sets a \a distance to near cut plane.
*/
void Camera::setNear(const float distance) {
p_ptr->m_near = distance;
m_near = distance;
}
/*!
Returns a distance to far cut plane.
*/
float Camera::farPlane() const {
return p_ptr->m_far;
return m_far;
}
/*!
Sets a \a distance to far cut plane.
*/
void Camera::setFar(const float distance) {
p_ptr->m_far = distance;
m_far = distance;
}
/*!
Returns the aspect ratio (width divided by height).
*/
float Camera::ratio() const {
return p_ptr->m_ratio;
return m_ratio;
}
/*!
Sets the aspect \a ratio (width divided by height).
*/
void Camera::setRatio(float ratio) {
p_ptr->m_ratio = ratio;
m_ratio = ratio;
}
/*!
Returns a focal distance for the camera.
*/
float Camera::focal() const {
return p_ptr->m_focal;
return m_focal;
}
/*!
Sets a \a focal distance for the camera.
*/
void Camera::setFocal(const float focal) {
p_ptr->m_focal = focal;
m_focal = focal;
}
/*!
Returns the color with which the screen will be cleared.
*/
Vector4 &Camera::color() const {
return p_ptr->m_color;
Vector4 Camera::color() const {
return m_color;
}
/*!
Sets the \a color with which the screen will be cleared.
*/
void Camera::setColor(const Vector4 color) {
p_ptr->m_color = color;
m_color = color;
}
/*!
Returns camera size for orthographic mode.
*/
float Camera::orthoSize() const {
return p_ptr->m_orthoSize;
return m_orthoSize;
}
/*!
Sets camera \a size for orthographic mode.
*/
void Camera::setOrthoSize(const float size) {
p_ptr->m_orthoSize = size;
m_orthoSize = size;
}
/*!
Returns true for the orthographic mode; for the perspective mode, returns false.
*/
bool Camera::orthographic() const {
return p_ptr->m_ortho;
return m_ortho;
}
/*!
Sets orthographic \a mode.
*/
void Camera::setOrthographic(const bool mode) {
p_ptr->m_ortho = mode;
m_ortho = mode;
}
/*!
Returns current active camera.
*/
Camera *Camera::current() {
return CameraPrivate::s_current;
return s_currentCamera;
}
/*!
Sets \a current active camera.
*/
void Camera::setCurrent(Camera *current) {
CameraPrivate::s_current = current;
s_currentCamera = current;
}
/*!
Returns frustum corners for the \a camera.
*/
array<Vector3, 8> Camera::frustumCorners(const Camera &camera) {
Transform *t = camera.actor()->transform();

return Camera::frustumCorners(camera.p_ptr->m_ortho, (camera.p_ptr->m_ortho) ?
camera.p_ptr->m_orthoSize :
camera.p_ptr->m_fov,
camera.p_ptr->m_ratio,
return Camera::frustumCorners(camera.m_ortho, (camera.m_ortho) ?
camera.m_orthoSize :
camera.m_fov,
camera.m_ratio,
t->worldPosition(), t->worldRotation(),
camera.p_ptr->m_near, camera.p_ptr->m_far);
camera.m_near, camera.m_far);
}
/*!
Returns frustum corners with provided parameters.
Expand Down Expand Up @@ -379,8 +317,8 @@ RenderList Camera::frustumCulling(RenderList &list, const array<Vector3, 8> &fru
bool Camera::drawHandles(ObjectList &selected) {
Transform *t = actor()->transform();
if(isSelected(selected)) {
array<Vector3, 8> a = frustumCorners(p_ptr->m_ortho, (p_ptr->m_ortho) ? p_ptr->m_orthoSize : p_ptr->m_fov,
p_ptr->m_ratio, t->worldPosition(), t->worldRotation(), nearPlane(), farPlane());
array<Vector3, 8> a = frustumCorners(m_ortho, (m_ortho) ? m_orthoSize : m_fov,
m_ratio, t->worldPosition(), t->worldRotation(), nearPlane(), farPlane());

Handles::s_Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f);
Vector3Vector points(a.begin(), a.end());
Expand All @@ -391,6 +329,6 @@ bool Camera::drawHandles(ObjectList &selected) {
Handles::drawLines(Matrix4(), points, indices);
}
Handles::s_Color = Handles::s_Normal;
return Handles::drawBillboard(t->position(), Vector2(0.5f), Engine::loadResource<Texture>(".embedded/camera.png"));
return Handles::drawBillboard(t->worldPosition(), Vector2(0.5f), Engine::loadResource<Texture>(".embedded/camera.png"));
}
#endif

0 comments on commit a9d22bb

Please sign in to comment.