123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- #include "Camera3D.h"
- #include "../engine/Wrapper.h"
- #include <cmath>
- #include "../engine/Utils.h"
- Camera3D::Camera3D()
- {
- }
- Camera3D::~Camera3D()
- {
- }
- const Vector3D& Camera3D::getFlatFront() const
- {
- return flatFront;
- }
- const Vector3D& Camera3D::getFlatBack() const
- {
- return flatBack;
- }
- const Vector3D& Camera3D::getFlatRight() const
- {
- return flatRight;
- }
- const Vector3D& Camera3D::getFlatLeft() const
- {
- return flatLeft;
- }
- const Vector3D& Camera3D::getFlatUp() const
- {
- return flatUp;
- }
- const Vector3D& Camera3D::getFlatDown() const
- {
- return flatDown;
- }
- void Camera3D::addToOldLengthAngle(float f)
- {
- oldLengthAngle += f;
- }
- void Camera3D::storePosition()
- {
- oldCamera.set(camera);
- oldLengthAngle = lengthAngle;
- oldWidthAngle = widthAngle;
- }
- void Camera3D::setPosition(float x, float y, float z, float length, float width)
- {
- camera.set(x, y, z);
- lengthAngle = length;
- widthAngle = width;
- }
- float old = 0;
- float current = 0;
- void Camera3D::update(float lag)
- {
- // -------------------------------------------------------------------------
- // calculate vectors for the view matrix
- // -------------------------------------------------------------------------
-
- // front
- front.setAngles(interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
-
- // back
- back.setInverse(front);
- // right
- right.set(front);
- right.cross(0.0f, 1.0f, 0.0f);
- right.normalize();
-
- // left
- left.setInverse(right);
-
- // up
- up.set(front);
- up.cross(left);
- up.normalize();
-
- // down
- down.setInverse(up);
-
- Vector3D interCamera = oldCamera;
- interCamera.addMul(camera, lag);
- interCamera.addMul(oldCamera, -lag);
-
- view.set(0, 0, right.getX());
- view.set(0, 1, right.getY());
- view.set(0, 2, right.getZ());
- view.set(0, 3, right.dotInverse(interCamera));
-
- view.set(1, 0, up.getX());
- view.set(1, 1, up.getY());
- view.set(1, 2, up.getZ());
- view.set(1, 3, up.dotInverse(interCamera));
-
- view.set(2, 0, back.getX());
- view.set(2, 1, back.getY());
- view.set(2, 2, back.getZ());
- view.set(2, 3, back.dotInverse(interCamera));
-
- view.set(3, 0, 0.0f);
- view.set(3, 1, 0.0f);
- view.set(3, 0, 0.0f);
- view.set(3, 3, 1.0f);
-
- // -------------------------------------------------------------------------
- // calculate flat vectors for movement
- // -------------------------------------------------------------------------
-
- // front
- flatFront.set(front);
- flatFront.setY(0.0f);
- flatFront.normalize();
-
- // back
- flatBack.setInverse(flatFront);
- // right
- flatRight.set(flatFront);
- flatRight.cross(0.0f, 1.0f, 0.0f);
- flatRight.normalize();
-
- // left
- flatLeft.setInverse(flatRight);
- // up
- flatUp.set(0.0f, 1.0f, 0.0f);
-
- // down
- flatDown.setInverse(flatUp);
-
- // -------------------------------------------------------------------------
- // update frustum planes
- // -------------------------------------------------------------------------
-
- // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
- float tan = tanf((0.5f * Engine::getFieldOfView()) * M_PI / 180.0f);
- float aspect = (float) Engine::getWidth() / Engine::getHeight();
-
- float nearHigh = tan * Engine::getNearClip();
- float nearWidth = nearHigh * aspect;
- float farHigh = tan * Engine::getFarClip();
- float farWidth = farHigh * aspect;
- Vector3D fc = interCamera;
- fc.addMul(front, Engine::getFarClip());
- Vector3D ftl = fc;
- ftl.addMul(left, farWidth);
- ftl.addMul(up, farHigh);
- Vector3D fbl = fc;
- fbl.addMul(left, farWidth);
- fbl.addMul(down, farHigh);
- Vector3D fbr = fc;
- fbr.addMul(right, farWidth);
- fbr.addMul(down, farHigh);
- Vector3D nc = interCamera;
- nc.addMul(front, Engine::getNearClip());
- Vector3D ntl = nc;
- ntl.addMul(left, nearWidth);
- ntl.addMul(down, nearHigh);
- Vector3D ntr = nc;
- ntr.addMul(right, nearWidth);
- ntr.addMul(up, nearHigh);
- Vector3D nbr = nc;
- nbr.addMul(right, nearWidth);
- nbr.addMul(down, nearHigh);
- // generating planes with counter clockwise vector order
- frustumPlanes[0].set(fbl, ftl, fbr); // far
- frustumPlanes[1].set(ntl, ftl, fbl); // left
- frustumPlanes[2].set(fbr, ntr, nbr); // right
- frustumPlanes[3].set(fbl, fbr, nbr); // bottom
- frustumPlanes[4].set(ntr, ftl, ntl); // top
- frustumPlanes[5].set(nbr, ntr, ntl); // near
- }
- const float* Camera3D::getViewMatrix()
- {
- return view.getValues();
- }
- bool Camera3D::isInFrustum(float x, float y, float z, float x2, float y2, float z2) const
- {
- // some tolerance
- x -= 1;
- y -= 1;
- z -= 1;
- x2 += 1;
- y2 += 1;
- z2 += 1;
- //return true;
- // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
- // for each plane do ...
- for(int fp = 0; fp < 6; fp++)
- {
- // reset counters for corners in and out
- int out = 0;
- int in = 0;
- // for each corner of the box do ...
- // get out of the cycle as soon as a box as corners
- // both inside and out of the frustum
- for(int i = 0; i < 8 && (in == 0 || out == 0); i++)
- {
- // is the corner outside or inside
- if(frustumPlanes[fp].getSignedDistance(((i >> 2) & 1) ? x : x2, ((i >> 1) & 1) ? y : y2, (i & 1) ? z : z2) > 0)
- {
- out++;
- }
- else
- {
- in++;
- }
- }
- //if all corners are out
- if(in == 0)
- {
- return false;
- }
- }
- return true;
- }
|