27 return static_cast<FStops>(i);
86 const mat4<F32> modelViewT( a_modelView.getTranspose() );
111 s_lastFrameTimeSec = Time::MicrosecondsToSeconds<F32>( deltaTimeUS );
116 cameEntry._camera->update();
124 return _utilityCameras[
to_base( type )];
142 _utilityCameras.fill(
nullptr );
144 s_cameraPool.clear();
149 const U64 targetHash =
_ID( cameraName.c_str() );
152 if ( camera !=
nullptr )
162 if ( camera !=
nullptr )
169 s_cameraPool.emplace_back(
nullptr, 1u);
170 s_cameraPool.back()._camera.reset(
new Camera( cameraName, mode ));
172 return s_cameraPool.back()._camera.get();
177 if ( camera ==
nullptr )
182 const U64 targetHash =
_ID( camera->resourceName().c_str() );
187 return erase_if( s_cameraPool,
190 if (
_ID( camEntry.
_camera->resourceName().c_str() ) == targetHash)
192 camEntry._useCount.fetch_sub( 1u );
193 return camEntry._useCount == 0u;
210 auto it = eastl::find_if( begin( s_cameraPool ),
214 return _ID( camEntry.
_camera->resourceName().c_str() ) == nameHash;
216 if ( it != std::end( s_cameraPool ) )
227 if (
entry !=
nullptr )
229 return entry->_camera.get();
239 const auto it = s_changeCameraListeners.find(
id );
240 if ( it != std::cend( s_changeCameraListeners ) )
242 s_changeCameraListeners.erase( it );
253 insert( s_changeCameraListeners, ++s_changeCameraId, f );
254 return s_changeCameraId;
277 _reflectionActive = camera._reflectionActive;
279 _maxRadius = camera._maxRadius;
280 _minRadius = camera._minRadius;
281 _curRadius = camera._curRadius;
288 _speedFactor = camera._speedFactor;
289 _orthoRect.set( camera._orthoRect );
291 rotationLocked( camera._rotationLocked );
292 movementLocked( camera._movementLocked );
293 frustumLocked( camera._frustumLocked );
327 newTargetOrientation.
yaw =
M_PI_f - newTargetOrientation.
yaw;
335 _minRadius = std::max( _minRadius, 0.01f );
336 if ( _minRadius > _maxRadius )
338 std::swap( _minRadius, _maxRadius );
340 CLAMP<F32>( _curRadius, _minRadius, _maxRadius );
350 _targetTransform = tComp;
402 return cameraUpdated;
407 if ( _rotationLocked )
423 setRotation( yawRot * pitchRot );
429 if ( _rotationLocked )
474 _reflectionPlane = reflectionPlane;
475 _reflectionActive =
true;
476 _viewMatrixDirty =
true;
481 _reflectionActive =
false;
558 _data._projectionMatrix.set( projection );
559 _data._projectionMatrix.getInverse( _data._invProjectionMatrix );
560 _data._zPlanes = zPlanes;
561 _projectionDirty =
false;
562 _frustumDirty =
true;
563 _data._isOrthoCamera = isOrtho;
565 return _data._projectionMatrix;
570 _data._aspectRatio = ratio;
571 _projectionDirty =
true;
576 _data._fov = verticalFoV;
577 _projectionDirty =
true;
583 _projectionDirty =
true;
599 if ( _rotationLocked )
606 const F32 turnSpeed = speedFactor().turn * s_lastFrameTimeSec;
607 yaw = -yaw * turnSpeed;
608 pitch = -pitch * turnSpeed;
609 roll = -roll * turnSpeed;
612 if ( mode() == Mode::FIRST_PERSON )
614 _accumPitchDegrees += pitch;
616 if ( _accumPitchDegrees > 90.0f )
618 pitch = 90.0f - (_accumPitchDegrees - pitch);
619 _accumPitchDegrees = 90.0f;
622 if ( _accumPitchDegrees < -90.0f )
624 pitch = -90.0f - (_accumPitchDegrees - pitch);
625 _accumPitchDegrees = -90.0f;
633 _data._orientation = tempOrientation * _data._orientation;
641 _data._orientation = _data._orientation * tempOrientation;
646 tempOrientation.
fromEuler( pitch, yaw, roll );
647 _data._orientation *= tempOrientation;
650 _viewMatrixDirty =
true;
670 if ( _movementLocked )
677 const F32 moveSpeed = speedFactor().move * s_lastFrameTimeSec;
685 _data._eye += rightDir * dx;
688 if ( mode() == Mode::FIRST_PERSON )
694 _data._eye += forward * dz;
701 _viewMatrixDirty =
true;
708 bool updated =
false;
741 move( relMovement.
y, relMovement.
z, relMovement.
x );
770 if ( mode() ==
Mode::ORBIT || (targetYaw > -rotationLimitRollLower && targetYaw < rotationLimitRollUpper) )
782 if ( mode() ==
Mode::ORBIT || (targetPitch > -rotationLimitPitch && targetPitch < rotationLimitPitch) )
810 curRadius( _curRadius += zoomFactor * speedFactor().zoom * s_lastFrameTimeSec * -0.01f );
844 if ( _reflectionActive )
858 if ( _frustumLocked )
869 _frustumLocked =
true;
871 _frustumLocked =
false;
883 const F32 offsetWinCoordsX = winCoordsX - viewport.x;
884 const F32 offsetWinCoordsY = winCoordsY - viewport.y;
885 const I32 winWidth = viewport.z;
886 const I32 winHeight = viewport.w;
890 offsetWinCoordsX / (winWidth * 0.5f) - 1.0f,
891 offsetWinCoordsY / (winHeight * 0.5f) - 1.0f
903 const vec2<F32> tempEyeSpace = (invProjMatrix * clipSpace).xy;
912 const vec3<F32> worldSpace = (worldMatrix() * eyeSpace).xyz;
927 const vec4<F32> clipSpace = projectionMatrix() * viewSpace;
931 const vec2<F32> ndcSpace = clipSpace.
xy / clampedClipW;
933 const vec2<F32> winSpace = (ndcSpace + 1.0f) * 0.5f * winSize;
935 return winOffset + winSpace;
946 ret.
m[0][0] = xAxis.
x;
947 ret.
m[1][0] = xAxis.
y;
948 ret.
m[2][0] = xAxis.
z;
949 ret.
m[3][0] = -xAxis.
dot( eye );
951 ret.
m[0][1] = yAxis.
x;
952 ret.
m[1][1] = yAxis.
y;
953 ret.
m[2][1] = yAxis.
z;
954 ret.
m[3][1] = -yAxis.
dot( eye );
956 ret.
m[0][2] = zAxis.
x;
957 ret.
m[1][2] = zAxis.
y;
958 ret.
m[2][2] = zAxis.
z;
959 ret.
m[3][2] = -zAxis.
dot( eye );
973 std::string savePath = (prefix.empty() ?
"camera." : (prefix +
".camera."));
980 pt.put( savePath +
".reflectionPlane.active", _reflectionActive );
982 pt.put( savePath +
".frustumLocked", _frustumLocked );
983 pt.put( savePath +
".euler.<xmlattr>.x", _euler.x );
984 pt.put( savePath +
".euler.<xmlattr>.y", _euler.y );
985 pt.put( savePath +
".euler.<xmlattr>.z", _euler.z );
986 pt.put( savePath +
".eye.<xmlattr>.x",
_data.
_eye.
x );
987 pt.put( savePath +
".eye.<xmlattr>.y",
_data.
_eye.
y );
988 pt.put( savePath +
".eye.<xmlattr>.z",
_data.
_eye.
z );
989 pt.put( savePath +
".orientation.<xmlattr>.x", orientation.
x );
990 pt.put( savePath +
".orientation.<xmlattr>.y", orientation.
y );
991 pt.put( savePath +
".orientation.<xmlattr>.z", orientation.
z );
992 pt.put( savePath +
".orientation.<xmlattr>.w", orientation.
w );
997 pt.put( savePath +
".speedFactor.<xmlattr>.turn", _speedFactor.turn );
998 pt.put( savePath +
".speedFactor.<xmlattr>.move", _speedFactor.move );
999 pt.put( savePath +
".speedFactor.<xmlattr>.zoom", _speedFactor.zoom );
1000 pt.put( savePath +
".fixedYawAxis.<xmlattr>.x",
_fixedYawAxis.
x );
1001 pt.put( savePath +
".fixedYawAxis.<xmlattr>.y",
_fixedYawAxis.
y );
1002 pt.put( savePath +
".fixedYawAxis.<xmlattr>.z",
_fixedYawAxis.
z );
1003 pt.put( savePath +
".yawFixed",
_yawFixed );
1004 pt.put( savePath +
".rotationLocked", _rotationLocked );
1005 pt.put( savePath +
".movementLocked", _movementLocked );
1006 pt.put( savePath +
".maxRadius", maxRadius() );
1007 pt.put( savePath +
".minRadius", minRadius() );
1008 pt.put( savePath +
".curRadius", curRadius() );
1012 pt.put( savePath +
".offsetDir.<xmlattr>.x",
_offsetDir.
x );
1013 pt.put( savePath +
".offsetDir.<xmlattr>.y",
_offsetDir.
y );
1014 pt.put( savePath +
".offsetDir.<xmlattr>.z",
_offsetDir.
z );
1021 std::string savePath = (prefix.empty() ?
"camera." : (prefix +
".camera."));
1030 _reflectionActive = pt.get( savePath +
".reflectionPlane.active", _reflectionActive );
1033 _frustumLocked = pt.get( savePath +
".frustumLocked", _frustumLocked );
1035 pt.get( savePath +
".euler.<xmlattr>.x", _euler.x ),
1036 pt.get( savePath +
".euler.<xmlattr>.y", _euler.y ),
1037 pt.get( savePath +
".euler.<xmlattr>.z", _euler.z )
1040 pt.get( savePath +
".eye.<xmlattr>.x",
_data.
_eye.
x ),
1041 pt.get( savePath +
".eye.<xmlattr>.y",
_data.
_eye.
y ),
1042 pt.get( savePath +
".eye.<xmlattr>.z",
_data.
_eye.
z )
1045 pt.get( savePath +
".orientation.<xmlattr>.x", orientation.
x ),
1046 pt.get( savePath +
".orientation.<xmlattr>.y", orientation.
y ),
1047 pt.get( savePath +
".orientation.<xmlattr>.z", orientation.
z ),
1048 pt.get( savePath +
".orientation.<xmlattr>.w", orientation.
w )
1058 _speedFactor.turn = pt.get( savePath +
".speedFactor.<xmlattr>.turn", _speedFactor.turn );
1059 _speedFactor.move = pt.get( savePath +
".speedFactor.<xmlattr>.move", _speedFactor.move );
1060 _speedFactor.zoom = pt.get( savePath +
".speedFactor.<xmlattr>.zoom", _speedFactor.zoom );
1062 pt.get( savePath +
".fixedYawAxis.<xmlattr>.x",
_fixedYawAxis.
x ),
1063 pt.get( savePath +
".fixedYawAxis.<xmlattr>.y",
_fixedYawAxis.
y ),
1064 pt.get( savePath +
".fixedYawAxis.<xmlattr>.z",
_fixedYawAxis.
z )
1067 _rotationLocked = pt.get( savePath +
".rotationLocked", _rotationLocked );
1068 _movementLocked = pt.get( savePath +
".movementLocked", _movementLocked );
1069 maxRadius( pt.get( savePath +
".maxRadius", maxRadius() ) );
1070 minRadius( pt.get( savePath +
".minRadius", minRadius() ) );
1071 curRadius( pt.get( savePath +
".curRadius", curRadius() ) );
1078 pt.get( savePath +
".offsetDir.<xmlattr>.x",
_offsetDir.
x ),
1079 pt.get( savePath +
".offsetDir.<xmlattr>.y",
_offsetDir.
y ),
1080 pt.get( savePath +
".offsetDir.<xmlattr>.z",
_offsetDir.
z )
#define PROFILE_SCOPE_AUTO(CATEGORY)
const mat4< F32 > & projectionMatrix() const noexcept
Returns the most recent/up-to-date projection matrix.
static void DestroyPool()
const mat4< F32 > & setProjection(vec2< F32 > zPlanes)
vec3< F32 > _fixedYawAxis
bool updateViewMatrix() noexcept
void rotatePitch(Angle::DEGREES< F32 > angle)
Change camera's pitch.
bool rotateRelative(const vec3< F32 > &relRotation)
static CameraEntry * FindCameraEntryLocked(const U64 nameHash)
mat4< F32 > _viewProjectionMatrix
const mat4< F32 > & viewMatrix() const noexcept
Returns the most recent/up-to-date view matrix.
static Camera * GetUtilityCamera(const UtilityCamera type)
const mat4< F32 > & lookAt(const mat4< F32 > &viewMatrix)
Sets the camera's view matrix to specify the specified value by extracting the eye position,...
bool updateFrustum()
Extract the frustum associated with our current PoV.
Angle::DEGREES< F32 > getHorizontalFoV() const noexcept
Returns the horizontal field of view, calculated from the vertical FoV and aspect ratio.
void rotateYaw(Angle::DEGREES< F32 > angle)
static Camera * CreateCamera(const Str< 256 > &cameraName, Mode cameraMode)
const CameraSnapshot & snapshot() const noexcept
Returns the internal camera snapshot data (eye, orientation, etc)
static mat4< F32 > LookAt(const vec3< F32 > &eye, const vec3< F32 > &target, const vec3< F32 > &up) noexcept
void setAspectRatio(F32 ratio) noexcept
Plane< F32 > _reflectionPlane
bool updateLookAt()
Return true if the cached camera state wasn't up-to-date.
void fromSnapshot(const CameraSnapshot &snapshot)
Sets the internal snapshot data (eye, orientation, etc) to match the specified value.
void rotateRoll(Angle::DEGREES< F32 > angle)
Change camera's roll.
CameraListenerMap _updateCameraListeners
static Camera * FindCamera(const U64 nameHash)
void setFixedYawAxis(const bool useFixed, const vec3< F32 > &fixedAxis=WORLD_Y_AXIS) noexcept
Exactly as in Ogre3D: locks the yaw movement to the specified axis.
void rotate(const Quaternion< F32 > &q)
Rotates the camera (changes its orientation) by the specified quaternion (_orientation *= q)
void setGlobalRotation(F32 yaw, F32 pitch, F32 roll=0.0f) noexcept
Global rotations are applied relative to the world axis, not the camera's.
void setHorizontalFoV(Angle::DEGREES< F32 > horizontalFoV) noexcept
vec3< Angle::RADIANS< F32 > > _cameraRotation
bool removeUpdateListener(U32 id)
Angle::DEGREES< F32 > _accumPitchDegrees
void setTarget(TransformComponent *tComp, const vec3< F32 > &offsetDirection=VECTOR3_ZERO) noexcept
Offset direction is a (eventually normalized) vector that is scaled by curRadius and applied to the c...
bool moveFromPlayerState(const SceneStatePerPlayer &playerState)
vec3< F32 > unProject(F32 winCoordsX, F32 winCoordsY, const Rect< I32 > &viewport) const noexcept
void setVerticalFoV(Angle::DEGREES< F32 > verticalFoV) noexcept
void setEye(const F32 x, const F32 y, const F32 z) noexcept
Sets the camera's eye position.
static mat4< F32 > Perspective(Angle::DEGREES< F32 > fovyRad, F32 aspect, F32 zNear, F32 zFar) noexcept
static CameraEntry * FindCameraEntry(const U64 nameHash)
TransformComponent * _targetTransform
static mat4< F32 > Ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar) noexcept
void saveToXML(boost::property_tree::ptree &pt, std::string prefix="") const
void fromCamera(const Camera &camera)
Copies all of the internal data from the specified camera to the current one.
bool zoom(F32 zoomFactor) noexcept
Camera(const std::string_view name, Mode mode, const vec3< F32 > &eye=VECTOR3_ZERO)
void setReflection(const Plane< F32 > &reflectionPlane) noexcept
Specify a reflection plane that alters the final view matrix to be a mirror of the internal lookAt ma...
bool updateProjection() noexcept
static U32 AddChangeListener(const CameraListener &f)
static bool RemoveChangeListener(U32 id)
static bool DestroyCamera(Camera *&camera)
bool moveRelative(const vec3< F32 > &relMovement)
vec2< F32 > project(const vec3< F32 > &worldCoords, const Rect< I32 > &viewport) const noexcept
void loadFromXML(const boost::property_tree::ptree &pt, std::string prefix="")
void setRotation(const Quaternion< F32 > &q) noexcept
Sets the camera's orientation.
void clearReflection() noexcept
Clears the reflection plane specified (if any)
static void Update(U64 deltaTimeUS)
U32 addUpdateListener(const CameraListener &f)
void move(F32 dx, F32 dy, F32 dz) noexcept
Moves the camera by the specified offsets in each direction.
const std::array< Plane< F32 >, to_base(FrustumPlane::COUNT)> & computePlanes(const mat4< F32 > &viewProjMatrix)
void set(const vec4< T > &equation) noexcept
void fromMatrix(const mat3< T > &rotationMatrix) noexcept
vec3< T > xAxis() const noexcept
void fromAxisAngle(const vec3< T > &v, Angle::DEGREES< T > angle) noexcept
Convert from Axis Angle.
void set(const vec4< T > &values) noexcept
const vec4< T > & asVec4() const noexcept
void normalize() noexcept
normalizing a quaternion works similar to a vector. This method will not
vec3< T > yAxis() const noexcept
vec3< T > zAxis() const noexcept
vec3< Angle::RADIANS< T > > getEuler() const noexcept
void fromEuler(const vec3< Angle::DEGREES< T > > &v) noexcept
vec3< T > getForwardDirection() const noexcept
Returns normalized(getForwardVec())
const mat4 & reflect(U x, U y, U z, U w) noexcept
void setRow(I32 index, U value) noexcept
mat4 getInverse() const noexcept
static mat4< T > Multiply(const mat4< T > &matrixA, const mat4< T > &matrixB) noexcept
ret = A * B
vec3< T > getRightDirection() const noexcept
Returns normalized(getRightVec())
const vec4< T > & getRow(I32 index) const noexcept
void set(std::initializer_list< T > matrix) noexcept
void set(const T *v) noexcept
set the 2 components of the vector manually using a source pointer to a (large enough) array
T dot(const vec3 &v) const noexcept
calculate the dot product between this vector and the specified one
T lengthSquared() const noexcept
return the squared distance of the vector
void set(const T *v) noexcept
set the 3 components of the vector manually using a source pointer to a (large enough) array
constexpr T DegreesToRadians(T angleDegrees) noexcept
Return the radian equivalent of the given degree value.
constexpr DEGREES< T > to_DEGREES(RADIANS< T > angle) noexcept
constexpr RADIANS< T > to_RADIANS(DEGREES< T > angle) noexcept
constexpr DEGREES< T > to_VerticalFoV(DEGREES< T > horizontalFoV, D64 aspectRatio) noexcept
static const char * fStops[]
static const char * cameraMode[]
constexpr Optick::Category::Type GameLogic
const char * CameraModeToString(const Camera::Mode mode) noexcept
Camera::Mode StringToCameraMode(const string &name)
FStops StringToFStops(const string &name)
const char * FStopsToString(const FStops stop) noexcept
void Normalize(vec3< F32 > &inputRotation, bool degrees=false, bool normYaw=true, bool normPitch=true, bool normRoll=true) noexcept
Normalise the selected rotations to be within the +/-180 degree range.
string MakeXMLSafe(std::string_view subject)
std::array< Camera *, to_base(Camera::UtilityCamera::COUNT)> _utilityCameras
CameraListenerMap s_changeCameraListeners
eastl::list< CameraEntry > CameraPool
SharedMutex s_cameraPoolLock
vec3< F32 > ExtractCameraPos2(const mat4< F32 > &a_modelView) noexcept
Handle console commands that start with a forward slash.
vec2< T > Normalized(vec2< T > vector) noexcept
std::lock_guard< mutex > LockGuard
bool IS_ZERO(const T X) noexcept
void insert(eastl::vector< T, A1 > &target, const eastl::vector< T, A2 > &source)
static const vec3< F32 > WORLD_X_AXIS
hashMap< U32, CameraListener > CameraListenerMap
static const vec3< F32 > WORLD_Z_AXIS
constexpr D64 to_D64(const T value)
std::shared_mutex SharedMutex
void GetInverse(const mat4< T > &inM, mat4< T > &r) noexcept
T Dot(vec2< T > a, vec2< T > b) noexcept
general vec2 dot product
constexpr F32 EPSILON_F32
std::shared_lock< mutex > SharedLock
constexpr U64 _ID(const char *const str, const U64 value=val_64_const) noexcept
constexpr U8 to_U8(const T value)
vec2< T > Cross(vec2< T > v1, vec2< T > v2) noexcept
general vec2 cross function
DELEGATE< void, const Camera & > CameraListener
mat3< T > GetMatrix(const Quaternion< T > &q) noexcept
Project const SceneEntry & entry
static const vec3< F32 > WORLD_Y_AXIS
constexpr auto to_base(const Type value) -> Type
float asinf(const float in)
std::atomic_size_t _useCount
Quaternion< F32 > _orientation
mat4< F32 > _invViewMatrix
mat4< F32 > _projectionMatrix
std::array< Plane< F32 >, 6 > _frustumPlanes
mat4< F32 > _invProjectionMatrix
Angle::DEGREES< F32 > _fov
static NO_INLINE void printfn(const char *format, T &&... args)
F32 topValue() const noexcept