Add zoom and camera features.

This commit is contained in:
DelinWorks 2022-06-13 21:04:24 +03:00
parent d6bfe25f76
commit 6d5c1a446a
2 changed files with 206 additions and 13 deletions

View File

@ -94,6 +94,12 @@ const Camera* Camera::getVisitingCamera()
// end static methods
Camera::Camera()
: _eyeZdistance(1)
, _zoomFactor(1)
, _nearPlane(-1024)
, _farPlane(1024)
, _zoomFactorFarPlane(1024)
, _positionCenter({0, 0})
{
// minggo comment
// _frustum.setClipZ(true);
@ -137,6 +143,7 @@ void Camera::lookAt(const Vec3& lookAtPos, const Vec3& up)
Vec3::cross(zaxis, xaxis, &yaxis);
yaxis.normalize();
Mat4 rotation;
rotation.m[0] = xaxis.x;
rotation.m[1] = xaxis.y;
rotation.m[2] = xaxis.z;
@ -146,6 +153,7 @@ void Camera::lookAt(const Vec3& lookAtPos, const Vec3& up)
rotation.m[5] = yaxis.y;
rotation.m[6] = yaxis.z;
rotation.m[7] = 0;
rotation.m[8] = zaxis.x;
rotation.m[9] = zaxis.y;
rotation.m[10] = zaxis.z;
@ -177,6 +185,8 @@ void Camera::setAdditionalProjection(const Mat4& mat)
bool Camera::initDefault()
{
_projectionType = Director::getInstance()->getProjection();
auto size = _director->getWinSize();
// create default camera
auto projection = _director->getProjection();
@ -185,7 +195,7 @@ bool Camera::initDefault()
case Director::Projection::_2D:
{
initOrthographic(size.width, size.height, -1024, 1024);
setPosition3D(Vec3(0.0f, 0.0f, 0.0f));
setPosition3D(Vec3(0.f, 0.f, 0.f));
setRotation3D(Vec3(0.f, 0.f, 0.f));
break;
}
@ -195,6 +205,7 @@ bool Camera::initDefault()
initPerspective(60, (float)size.width / size.height, 10, zeye + size.height / 2.0f);
Vec3 eye(size.width / 2, size.height / 2.0f, zeye), center(size.width / 2, size.height / 2, 0.0f),
up(0.0f, 1.0f, 0.0f);
_eyeZdistance = eye.z;
setPosition3D(eye);
lookAt(center, up);
break;
@ -203,15 +214,19 @@ bool Camera::initDefault()
CCLOG("unrecognized projection");
break;
}
if (_zoomFactor != 1.0F)
applyZoom();
return true;
}
bool Camera::initPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane)
{
_fieldOfView = fieldOfView;
_aspectRatio = aspectRatio;
_nearPlane = nearPlane;
_farPlane = farPlane;
_fieldOfView = fieldOfView;
_aspectRatio = aspectRatio;
_nearPlane = nearPlane;
_farPlane = farPlane;
if (_zoomFactorFarPlane == 1024)
_zoomFactorFarPlane = farPlane;
Mat4::createPerspective(_fieldOfView, _aspectRatio, _nearPlane, _farPlane, &_projection);
_viewProjectionDirty = true;
_frustumDirty = true;
@ -354,6 +369,82 @@ void Camera::setDepth(int8_t depth)
}
}
void Camera::setZoom(float factor)
{
// Stretch the far plane further the more we zoom out.
if (_projectionType == Director::Projection::_3D && _zoomFactorFarPlane * factor > _farPlane)
{
_farPlane = _zoomFactorFarPlane * factor;
applyCustomProperties();
}
_zoomFactor = factor;
applyZoom();
if (_projectionType == Director::Projection::_2D)
setPositionCenter(_positionCenter);
}
void Camera::setPositionCenter(const Vec2& position)
{
setPositionCenter(position.x, position.y);
}
void Camera::setPositionCenter(float x, float y)
{
Vec2 pos = {x, y};
_positionCenter = pos;
auto v = Director::getInstance()->getVisibleSize();
setPosition(pos.x + v.width / 2 * (1.0F - _zoomFactor), pos.y + v.height / 2 * (1.0F - _zoomFactor));
}
void Camera::applyZoom()
{
switch (_projectionType)
{
case cocos2d::Director::Projection::_2D:
{
this->setScale(_zoomFactor);
break;
}
case cocos2d::Director::Projection::_3D:
{
this->setPositionZ(_eyeZdistance * _zoomFactor);
break;
}
}
}
void Camera::applyCustomProperties()
{
_projectionType = Director::getInstance()->getProjection();
auto& size = _director->getWinSize();
// create default camera
switch (_projectionType)
{
case Director::Projection::_2D:
{
initOrthographic(size.width, size.height, _nearPlane, _farPlane);
setPosition3D(Vec3(0.f, 0.f, 0.f));
setRotation3D(Vec3(0.f, 0.f, 0.f));
break;
}
case Director::Projection::_3D:
{
float zeye = _director->getZEye();
initPerspective(_fieldOfView, _aspectRatio, _nearPlane, _farPlane);
Vec3 eye(size.width / 2, size.height / 2.0f, zeye), center(size.width / 2, size.height / 2, 0.0f),
up(0.0f, 1.0f, 0.0f);
_eyeZdistance = eye.z;
setPosition3D(eye);
lookAt(center, up);
break;
}
}
if (_zoomFactor != 1.0F)
applyZoom();
}
void Camera::onEnter()
{
if (_scene == nullptr)
@ -431,6 +522,30 @@ int Camera::getRenderOrder() const
return result;
}
void Camera::setAspectRatio(float ratio)
{
_aspectRatio = ratio;
applyCustomProperties();
}
void Camera::setFOV(float fieldOfView)
{
_fieldOfView = fieldOfView;
applyCustomProperties();
}
void Camera::setFarPlane(float farPlane)
{
_farPlane = farPlane;
applyCustomProperties();
}
void Camera::setNearPlane(float nearPlane)
{
_nearPlane = nearPlane;
applyCustomProperties();
}
void Camera::visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags)
{
_viewProjectionUpdated = _transformUpdated;

View File

@ -234,22 +234,94 @@ public:
int getRenderOrder() const;
/**
* Get the frustum's far plane.
* Gets the aspect ratio of the camera if the projection mode is 3D.
*/
float getAspectRatio() const { return _fieldOfView; }
/**
* Sets the aspect ratio of the camera if the projection mode is 3D.
*/
void setAspectRatio(float ratio);
/**
* Gets the field of view of the camera if the projection mode is 3D.
*/
float getFOV() const { return _fieldOfView; }
/**
* Sets the field of view of the camera if the projection mode is 3D.
*/
void setFOV(float fov);
/**
* Gets the frustum's far plane.
*/
float getFarPlane() const { return _farPlane; }
/**
* Get the frustum's near plane.
* Sets the frustum's far plane.
*/
void setFarPlane(float farPlane);
/**
* Gets the frustum's near plane.
*/
float getNearPlane() const { return _nearPlane; }
/**
* Gets the frustum's near plane.
*/
void setNearPlane(float nearPlane);
/**
* Gets the zoom multiplier of the camera.
*/
float getZoom() const { return _zoomFactor; }
/**
* Sets the zoom multiplier of the camera.
* This is designed to be used with 2D views only.
*
* For 2D projection mode the zoom will be at the bottom left of the viewport, If you don't want this behaviour and
* want it to be around the center then you need to use the functions 'setPositionCenter()' and 'getPositionCenter()'
*
* @param factor The zoom factor of the camera.
*/
void setZoom(float factor);
/**
* Gets the position of the camera before any zoom transformations.
* Should only be used If you're zooming in and out while 2D projection mode is set in the director.
*/
const Vec2& getPositionCenter() { return _positionCenter; }
/**
* Sets the position of the camera with respect to the zoom factor.
* Should only be used If you're zooming in and out while 2D projection mode is set in the director.
*/
void setPositionCenter(const Vec2& position);
/**
* Sets the position of the camera with respect to the zoom factor.
* Should only be used If you're zooming in and out while 2D projection mode is set in the director.
*/
void setPositionCenter(float x, float y);
/**
Apply the zoom factor.
*/
void applyZoom();
void applyCustomProperties();
// override
virtual void onEnter() override;
virtual void onExit() override;
/**
Before rendering scene with this camera, the background need to be cleared. It clears the depth buffer with max
depth by default. Use setBackgroundBrush to modify the default behavior
Before rendering the scene with this camera, the background needs to be cleared.
It will clear the depth buffer with max depth by default.
Use setBackgroundBrush to modify this default behavior.
*/
void clearBackground();
/**
@ -258,8 +330,8 @@ public:
void apply();
/**
* Whether or not the viewprojection matrix was updated since the last frame.
* @return True if the viewprojection matrix was updated since the last frame.
* Whether or not the viewprojection matrix was updated last frame.
* @return True if the viewprojection matrix was updated last frame.
*/
bool isViewProjectionUpdated() const { return _viewProjectionUpdated; }
@ -282,7 +354,7 @@ public:
~Camera();
/**
* Set the scene,this method shall not be invoke manually
* Set the owner scene of the camera, this method shall not be invoked manually
*/
void setScene(Scene* scene);
@ -300,7 +372,7 @@ protected:
static Camera* _visitingCamera;
static Viewport _defaultViewport;
Scene* _scene = nullptr; // Scene camera belongs to
Scene* _scene = nullptr; // Scene that owns this camera.
Mat4 _projection;
mutable Mat4 _view;
mutable Mat4 _viewInv;
@ -320,6 +392,12 @@ protected:
mutable bool _frustumDirty = true;
int8_t _depth = -1; // camera depth, the depth of camera with CameraFlag::DEFAULT flag is 0 by default, a camera
// with larger depth is drawn on top of camera with smaller depth
Director::Projection _projectionType;
float _eyeZdistance; // Z eye projection distance for 2D in 3D projection.
float _zoomFactor; // The zoom factor of the camera. 3D = (cameraZDistance * _zoomFactor), 2D = (cameraScale * _zoomFactor)
float _zoomFactorFarPlane;
Vec2 _positionCenter;
CameraBackgroundBrush* _clearBrush = nullptr; // brush used to clear the back ground
};