2014-08-07 15:23:31 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2014 Chukong Technologies Inc.
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
2015-06-03 07:56:59 +08:00
|
|
|
|
|
|
|
Code based GamePlay3D's Camera: http://gameplay3d.org
|
|
|
|
|
2014-08-07 15:23:31 +08:00
|
|
|
****************************************************************************/
|
2014-10-20 16:25:24 +08:00
|
|
|
#include "2d/CCCamera.h"
|
2014-08-07 15:23:31 +08:00
|
|
|
#include "base/CCDirector.h"
|
|
|
|
#include "platform/CCGLView.h"
|
|
|
|
#include "2d/CCScene.h"
|
2015-05-07 15:09:06 +08:00
|
|
|
#include "renderer/CCRenderer.h"
|
|
|
|
#include "renderer/CCQuadCommand.h"
|
|
|
|
#include "renderer/CCGLProgramCache.h"
|
2015-05-07 18:32:32 +08:00
|
|
|
#include "renderer/ccGLStateCache.h"
|
2015-06-09 15:32:12 +08:00
|
|
|
#include "renderer/CCFrameBuffer.h"
|
2015-06-13 06:03:48 +08:00
|
|
|
#include "renderer/CCRenderState.h"
|
2014-08-07 15:23:31 +08:00
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2014-08-08 11:49:59 +08:00
|
|
|
Camera* Camera::_visitingCamera = nullptr;
|
2015-06-09 16:21:50 +08:00
|
|
|
experimental::Viewport Camera::_defaultViewport;
|
2015-01-09 08:30:00 +08:00
|
|
|
|
|
|
|
Camera* Camera::getDefaultCamera()
|
|
|
|
{
|
|
|
|
auto scene = Director::getInstance()->getRunningScene();
|
|
|
|
if(scene)
|
|
|
|
{
|
|
|
|
return scene->getDefaultCamera();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-06-09 16:21:50 +08:00
|
|
|
Camera* Camera::create()
|
2014-08-07 15:23:31 +08:00
|
|
|
{
|
2014-08-28 07:31:57 +08:00
|
|
|
Camera* camera = new (std::nothrow) Camera();
|
2014-08-13 15:57:22 +08:00
|
|
|
camera->initDefault();
|
|
|
|
camera->autorelease();
|
2015-02-11 18:14:22 +08:00
|
|
|
camera->setDepth(0.f);
|
2014-08-13 15:57:22 +08:00
|
|
|
|
2014-08-07 15:23:31 +08:00
|
|
|
return camera;
|
|
|
|
}
|
|
|
|
|
|
|
|
Camera* Camera::createPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane)
|
|
|
|
{
|
2014-08-28 07:31:57 +08:00
|
|
|
auto ret = new (std::nothrow) Camera();
|
2014-08-07 15:23:31 +08:00
|
|
|
if (ret)
|
|
|
|
{
|
2014-08-12 14:42:08 +08:00
|
|
|
ret->initPerspective(fieldOfView, aspectRatio, nearPlane, farPlane);
|
2014-08-07 15:23:31 +08:00
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
CC_SAFE_DELETE(ret);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Camera* Camera::createOrthographic(float zoomX, float zoomY, float nearPlane, float farPlane)
|
|
|
|
{
|
2014-08-28 07:31:57 +08:00
|
|
|
auto ret = new (std::nothrow) Camera();
|
2014-08-07 15:23:31 +08:00
|
|
|
if (ret)
|
|
|
|
{
|
2014-08-12 14:42:08 +08:00
|
|
|
ret->initOrthographic(zoomX, zoomY, nearPlane, farPlane);
|
2014-08-07 15:23:31 +08:00
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
CC_SAFE_DELETE(ret);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Camera::Camera()
|
2014-10-30 22:25:46 +08:00
|
|
|
: _scene(nullptr)
|
2014-08-07 15:23:31 +08:00
|
|
|
, _viewProjectionDirty(true)
|
2014-10-30 22:25:46 +08:00
|
|
|
, _cameraFlag(1)
|
2014-12-16 16:34:35 +08:00
|
|
|
, _frustumDirty(true)
|
2015-02-11 18:14:22 +08:00
|
|
|
, _depth(-1)
|
2015-05-12 16:43:17 +08:00
|
|
|
, _fbo(nullptr)
|
2014-08-07 15:23:31 +08:00
|
|
|
{
|
2015-01-14 14:41:10 +08:00
|
|
|
_frustum.setClipZ(true);
|
2014-08-07 15:23:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Camera::~Camera()
|
|
|
|
{
|
2015-05-12 16:43:17 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_fbo);
|
2014-08-07 15:23:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const Mat4& Camera::getProjectionMatrix() const
|
|
|
|
{
|
|
|
|
return _projection;
|
|
|
|
}
|
2014-08-07 15:57:15 +08:00
|
|
|
const Mat4& Camera::getViewMatrix() const
|
2014-08-07 15:23:31 +08:00
|
|
|
{
|
|
|
|
Mat4 viewInv(getNodeToWorldTransform());
|
|
|
|
static int count = sizeof(float) * 16;
|
|
|
|
if (memcmp(viewInv.m, _viewInv.m, count) != 0)
|
|
|
|
{
|
|
|
|
_viewProjectionDirty = true;
|
2014-12-18 17:18:22 +08:00
|
|
|
_frustumDirty = true;
|
2014-08-07 15:23:31 +08:00
|
|
|
_viewInv = viewInv;
|
|
|
|
_view = viewInv.getInversed();
|
|
|
|
}
|
|
|
|
return _view;
|
|
|
|
}
|
|
|
|
void Camera::lookAt(const Vec3& lookAtPos, const Vec3& up)
|
|
|
|
{
|
|
|
|
Vec3 upv = up;
|
|
|
|
upv.normalize();
|
|
|
|
Vec3 zaxis;
|
|
|
|
Vec3::subtract(this->getPosition3D(), lookAtPos, &zaxis);
|
|
|
|
zaxis.normalize();
|
|
|
|
|
|
|
|
Vec3 xaxis;
|
|
|
|
Vec3::cross(upv, zaxis, &xaxis);
|
|
|
|
xaxis.normalize();
|
|
|
|
|
|
|
|
Vec3 yaxis;
|
|
|
|
Vec3::cross(zaxis, xaxis, &yaxis);
|
|
|
|
yaxis.normalize();
|
|
|
|
Mat4 rotation;
|
|
|
|
rotation.m[0] = xaxis.x;
|
|
|
|
rotation.m[1] = xaxis.y;
|
|
|
|
rotation.m[2] = xaxis.z;
|
|
|
|
rotation.m[3] = 0;
|
|
|
|
|
|
|
|
rotation.m[4] = yaxis.x;
|
|
|
|
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;
|
|
|
|
rotation.m[11] = 0;
|
2014-10-31 11:32:10 +08:00
|
|
|
|
2014-08-07 15:23:31 +08:00
|
|
|
Quaternion quaternion;
|
|
|
|
Quaternion::createFromRotationMatrix(rotation,&quaternion);
|
2015-06-19 18:46:14 +08:00
|
|
|
quaternion.normalize();
|
|
|
|
setRotationQuat(quaternion);
|
2014-08-07 15:23:31 +08:00
|
|
|
}
|
|
|
|
|
2014-08-07 15:57:15 +08:00
|
|
|
const Mat4& Camera::getViewProjectionMatrix() const
|
2014-08-07 15:23:31 +08:00
|
|
|
{
|
|
|
|
getViewMatrix();
|
|
|
|
if (_viewProjectionDirty)
|
|
|
|
{
|
|
|
|
_viewProjectionDirty = false;
|
|
|
|
Mat4::multiply(_projection, _view, &_viewProjection);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _viewProjection;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Camera::setAdditionalProjection(const Mat4& mat)
|
|
|
|
{
|
|
|
|
_projection = mat * _projection;
|
|
|
|
getViewProjectionMatrix();
|
|
|
|
}
|
|
|
|
|
2014-08-12 14:42:08 +08:00
|
|
|
bool Camera::initDefault()
|
|
|
|
{
|
|
|
|
auto size = Director::getInstance()->getWinSize();
|
|
|
|
//create default camera
|
|
|
|
auto projection = Director::getInstance()->getProjection();
|
|
|
|
switch (projection)
|
|
|
|
{
|
|
|
|
case Director::Projection::_2D:
|
|
|
|
{
|
|
|
|
initOrthographic(size.width, size.height, -1024, 1024);
|
2014-08-13 15:57:22 +08:00
|
|
|
setPosition3D(Vec3(0.0f, 0.0f, 0.0f));
|
2014-08-14 09:06:06 +08:00
|
|
|
setRotation3D(Vec3(0.f, 0.f, 0.f));
|
2014-08-12 14:42:08 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Director::Projection::_3D:
|
|
|
|
{
|
|
|
|
float zeye = Director::getInstance()->getZEye();
|
|
|
|
initPerspective(60, (GLfloat)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);
|
|
|
|
setPosition3D(eye);
|
|
|
|
lookAt(center, up);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
CCLOG("unrecognized projection");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Camera::initPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane)
|
|
|
|
{
|
|
|
|
_fieldOfView = fieldOfView;
|
|
|
|
_aspectRatio = aspectRatio;
|
|
|
|
_nearPlane = nearPlane;
|
|
|
|
_farPlane = farPlane;
|
|
|
|
Mat4::createPerspective(_fieldOfView, _aspectRatio, _nearPlane, _farPlane, &_projection);
|
|
|
|
_viewProjectionDirty = true;
|
2014-12-18 17:18:22 +08:00
|
|
|
_frustumDirty = true;
|
2014-08-12 14:42:08 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Camera::initOrthographic(float zoomX, float zoomY, float nearPlane, float farPlane)
|
|
|
|
{
|
|
|
|
_zoom[0] = zoomX;
|
|
|
|
_zoom[1] = zoomY;
|
|
|
|
_nearPlane = nearPlane;
|
|
|
|
_farPlane = farPlane;
|
2014-08-13 15:57:22 +08:00
|
|
|
Mat4::createOrthographicOffCenter(0, _zoom[0], 0, _zoom[1], _nearPlane, _farPlane, &_projection);
|
2014-08-12 14:42:08 +08:00
|
|
|
_viewProjectionDirty = true;
|
2014-12-18 17:18:22 +08:00
|
|
|
_frustumDirty = true;
|
2014-08-12 14:42:08 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-02-27 10:01:57 +08:00
|
|
|
Vec2 Camera::project(const Vec3& src) const
|
2014-08-07 15:23:31 +08:00
|
|
|
{
|
2015-02-26 15:20:20 +08:00
|
|
|
Vec2 screenPos;
|
|
|
|
|
|
|
|
auto viewport = Director::getInstance()->getWinSize();
|
|
|
|
Vec4 clipPos;
|
2015-02-27 10:01:57 +08:00
|
|
|
getViewProjectionMatrix().transformVector(Vec4(src.x, src.y, src.z, 1.0f), &clipPos);
|
2015-02-26 15:20:20 +08:00
|
|
|
|
2015-07-14 15:28:36 +08:00
|
|
|
CCASSERT(clipPos.w != 0.0f, "clipPos.w can't be 0.0f!");
|
2015-02-26 15:20:20 +08:00
|
|
|
float ndcX = clipPos.x / clipPos.w;
|
|
|
|
float ndcY = clipPos.y / clipPos.w;
|
|
|
|
|
|
|
|
screenPos.x = (ndcX + 1.0f) * 0.5f * viewport.width;
|
|
|
|
screenPos.y = (1.0f - (ndcY + 1.0f) * 0.5f) * viewport.height;
|
|
|
|
return screenPos;
|
|
|
|
}
|
|
|
|
|
2015-05-29 10:41:19 +08:00
|
|
|
Vec2 Camera::projectGL(const Vec3& src) const
|
2015-02-26 15:20:20 +08:00
|
|
|
{
|
2015-05-29 10:41:19 +08:00
|
|
|
Vec2 screenPos;
|
|
|
|
|
2015-02-26 15:20:20 +08:00
|
|
|
auto viewport = Director::getInstance()->getWinSize();
|
2015-05-29 10:41:19 +08:00
|
|
|
Vec4 clipPos;
|
|
|
|
getViewProjectionMatrix().transformVector(Vec4(src.x, src.y, src.z, 1.0f), &clipPos);
|
|
|
|
|
2015-07-14 15:28:36 +08:00
|
|
|
CCASSERT(clipPos.w != 0.0f, "clipPos.w can't be 0.0f!");
|
2015-05-29 10:41:19 +08:00
|
|
|
float ndcX = clipPos.x / clipPos.w;
|
|
|
|
float ndcY = clipPos.y / clipPos.w;
|
|
|
|
|
|
|
|
screenPos.x = (ndcX + 1.0f) * 0.5f * viewport.width;
|
|
|
|
screenPos.y = (ndcY + 1.0f) * 0.5f * viewport.height;
|
|
|
|
return screenPos;
|
|
|
|
}
|
2015-02-26 15:33:18 +08:00
|
|
|
|
2015-05-29 10:41:19 +08:00
|
|
|
Vec3 Camera::unproject(const Vec3& src) const
|
|
|
|
{
|
|
|
|
Vec3 dst;
|
|
|
|
unproject(Director::getInstance()->getWinSize(), &src, &dst);
|
|
|
|
return dst;
|
|
|
|
}
|
2015-02-26 15:33:18 +08:00
|
|
|
|
2015-05-29 10:41:19 +08:00
|
|
|
Vec3 Camera::unprojectGL(const Vec3& src) const
|
|
|
|
{
|
|
|
|
Vec3 dst;
|
|
|
|
unprojectGL(Director::getInstance()->getWinSize(), &src, &dst);
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Camera::unproject(const Size& viewport, const Vec3* src, Vec3* dst) const
|
|
|
|
{
|
|
|
|
CCASSERT(src && dst, "vec3 can not be null");
|
|
|
|
|
|
|
|
Vec4 screen(src->x / viewport.width, ((viewport.height - src->y)) / viewport.height, src->z, 1.0f);
|
2014-08-07 15:23:31 +08:00
|
|
|
screen.x = screen.x * 2.0f - 1.0f;
|
|
|
|
screen.y = screen.y * 2.0f - 1.0f;
|
|
|
|
screen.z = screen.z * 2.0f - 1.0f;
|
|
|
|
|
|
|
|
getViewProjectionMatrix().getInversed().transformVector(screen, &screen);
|
|
|
|
if (screen.w != 0.0f)
|
|
|
|
{
|
|
|
|
screen.x /= screen.w;
|
|
|
|
screen.y /= screen.w;
|
|
|
|
screen.z /= screen.w;
|
|
|
|
}
|
|
|
|
|
2015-05-29 10:41:19 +08:00
|
|
|
dst->set(screen.x, screen.y, screen.z);
|
2015-02-26 15:20:20 +08:00
|
|
|
}
|
|
|
|
|
2015-05-29 10:41:19 +08:00
|
|
|
void Camera::unprojectGL(const Size& viewport, const Vec3* src, Vec3* dst) const
|
2015-02-26 15:20:20 +08:00
|
|
|
{
|
2015-02-27 10:01:57 +08:00
|
|
|
CCASSERT(src && dst, "vec3 can not be null");
|
2015-03-06 11:29:40 +08:00
|
|
|
|
2015-05-29 10:41:19 +08:00
|
|
|
Vec4 screen(src->x / viewport.width, src->y / viewport.height, src->z, 1.0f);
|
2015-03-06 11:29:40 +08:00
|
|
|
screen.x = screen.x * 2.0f - 1.0f;
|
|
|
|
screen.y = screen.y * 2.0f - 1.0f;
|
|
|
|
screen.z = screen.z * 2.0f - 1.0f;
|
|
|
|
|
|
|
|
getViewProjectionMatrix().getInversed().transformVector(screen, &screen);
|
|
|
|
if (screen.w != 0.0f)
|
|
|
|
{
|
|
|
|
screen.x /= screen.w;
|
|
|
|
screen.y /= screen.w;
|
|
|
|
screen.z /= screen.w;
|
|
|
|
}
|
|
|
|
|
|
|
|
dst->set(screen.x, screen.y, screen.z);
|
2014-08-07 15:23:31 +08:00
|
|
|
}
|
|
|
|
|
2014-12-25 14:04:41 +08:00
|
|
|
bool Camera::isVisibleInFrustum(const AABB* aabb) const
|
2014-12-16 16:34:35 +08:00
|
|
|
{
|
2015-01-14 14:41:10 +08:00
|
|
|
if (_frustumDirty)
|
2014-12-16 16:34:35 +08:00
|
|
|
{
|
2015-01-14 14:41:10 +08:00
|
|
|
_frustum.initFrustum(this);
|
|
|
|
_frustumDirty = false;
|
2014-12-16 16:34:35 +08:00
|
|
|
}
|
2015-01-14 14:41:10 +08:00
|
|
|
return !_frustum.isOutOfFrustum(*aabb);
|
2014-12-16 16:34:35 +08:00
|
|
|
}
|
|
|
|
|
2015-01-13 12:06:50 +08:00
|
|
|
float Camera::getDepthInView(const Mat4& transform) const
|
|
|
|
{
|
|
|
|
Mat4 camWorldMat = getNodeToWorldTransform();
|
|
|
|
const Mat4 &viewMat = camWorldMat.getInversed();
|
|
|
|
float depth = -(viewMat.m[2] * transform.m[12] + viewMat.m[6] * transform.m[13] + viewMat.m[10] * transform.m[14] + viewMat.m[14]);
|
|
|
|
return depth;
|
|
|
|
}
|
|
|
|
|
2015-05-12 16:43:17 +08:00
|
|
|
void Camera::setDepth(int8_t depth)
|
2015-02-11 18:14:22 +08:00
|
|
|
{
|
|
|
|
if (_depth != depth)
|
|
|
|
{
|
|
|
|
_depth = depth;
|
|
|
|
if (_scene)
|
|
|
|
{
|
|
|
|
//notify scene that the camera order is dirty
|
|
|
|
_scene->setCameraOrderDirty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-07 15:23:31 +08:00
|
|
|
void Camera::onEnter()
|
|
|
|
{
|
|
|
|
if (_scene == nullptr)
|
|
|
|
{
|
2014-08-08 11:49:59 +08:00
|
|
|
auto scene = getScene();
|
|
|
|
if (scene)
|
2015-02-11 18:14:22 +08:00
|
|
|
{
|
2014-08-08 11:49:59 +08:00
|
|
|
setScene(scene);
|
2015-02-11 18:14:22 +08:00
|
|
|
}
|
2014-08-07 15:23:31 +08:00
|
|
|
}
|
|
|
|
Node::onEnter();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Camera::onExit()
|
|
|
|
{
|
|
|
|
// remove this camera from scene
|
|
|
|
setScene(nullptr);
|
|
|
|
Node::onExit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Camera::setScene(Scene* scene)
|
|
|
|
{
|
|
|
|
if (_scene != scene)
|
|
|
|
{
|
|
|
|
//remove old scene
|
|
|
|
if (_scene)
|
|
|
|
{
|
|
|
|
auto& cameras = _scene->_cameras;
|
|
|
|
auto it = std::find(cameras.begin(), cameras.end(), this);
|
|
|
|
if (it != cameras.end())
|
|
|
|
cameras.erase(it);
|
|
|
|
_scene = nullptr;
|
|
|
|
}
|
|
|
|
//set new scene
|
|
|
|
if (scene)
|
|
|
|
{
|
|
|
|
_scene = scene;
|
|
|
|
auto& cameras = _scene->_cameras;
|
|
|
|
auto it = std::find(cameras.begin(), cameras.end(), this);
|
|
|
|
if (it == cameras.end())
|
2015-02-11 18:14:22 +08:00
|
|
|
{
|
2014-08-07 15:23:31 +08:00
|
|
|
_scene->_cameras.push_back(this);
|
2015-02-11 18:14:22 +08:00
|
|
|
//notify scene that the camera order is dirty
|
|
|
|
_scene->setCameraOrderDirty();
|
|
|
|
}
|
2014-08-07 15:23:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 18:32:32 +08:00
|
|
|
void Camera::clearBackground(float depth)
|
2015-05-07 15:09:06 +08:00
|
|
|
{
|
2015-05-07 18:32:32 +08:00
|
|
|
GLboolean oldDepthTest;
|
|
|
|
GLint oldDepthFunc;
|
|
|
|
GLboolean oldDepthMask;
|
2015-05-07 15:09:06 +08:00
|
|
|
{
|
2015-05-07 18:32:32 +08:00
|
|
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
|
|
glStencilMask(0);
|
2015-06-13 06:03:48 +08:00
|
|
|
|
2015-05-07 18:32:32 +08:00
|
|
|
oldDepthTest = glIsEnabled(GL_DEPTH_TEST);
|
|
|
|
glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);
|
|
|
|
glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthMask);
|
2015-06-13 06:03:48 +08:00
|
|
|
|
2015-05-07 18:32:32 +08:00
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthFunc(GL_ALWAYS);
|
2015-05-07 15:09:06 +08:00
|
|
|
}
|
2015-06-13 06:03:48 +08:00
|
|
|
|
2015-05-07 15:09:06 +08:00
|
|
|
//draw
|
|
|
|
static V3F_C4B_T2F_Quad quad;
|
|
|
|
quad.bl.vertices = Vec3(-1,-1,0);
|
|
|
|
quad.br.vertices = Vec3(1,-1,0);
|
|
|
|
quad.tl.vertices = Vec3(-1,1,0);
|
|
|
|
quad.tr.vertices = Vec3(1,1,0);
|
|
|
|
|
|
|
|
quad.bl.colors = quad.br.colors = quad.tl.colors = quad.tr.colors = Color4B(0,0,0,1);
|
|
|
|
|
|
|
|
quad.bl.texCoords = Tex2F(0,0);
|
|
|
|
quad.br.texCoords = Tex2F(1,0);
|
|
|
|
quad.tl.texCoords = Tex2F(0,1);
|
|
|
|
quad.tr.texCoords = Tex2F(1,1);
|
|
|
|
|
|
|
|
auto shader = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_CAMERA_CLEAR);
|
2015-05-18 10:31:17 +08:00
|
|
|
auto programState = GLProgramState::getOrCreateWithGLProgram(shader);
|
2015-05-07 15:09:06 +08:00
|
|
|
programState->setUniformFloat("depth", 1.0);
|
2015-05-07 18:32:32 +08:00
|
|
|
programState->apply(Mat4());
|
|
|
|
GLshort indices[6] = {0, 1, 2, 3, 2, 1};
|
2015-05-07 15:09:06 +08:00
|
|
|
|
2015-05-07 18:32:32 +08:00
|
|
|
{
|
|
|
|
GL::bindVAO(0);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
|
|
|
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
|
|
|
|
|
|
|
|
// vertices
|
2015-05-08 14:21:23 +08:00
|
|
|
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &quad.tl.vertices);
|
2015-05-07 18:32:32 +08:00
|
|
|
|
|
|
|
// colors
|
2015-05-08 14:21:23 +08:00
|
|
|
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), &quad.tl.colors);
|
2015-05-07 18:32:32 +08:00
|
|
|
|
|
|
|
// tex coords
|
2015-05-08 14:21:23 +08:00
|
|
|
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &quad.tl.texCoords);
|
2015-05-07 18:32:32 +08:00
|
|
|
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
|
|
|
}
|
|
|
|
|
2015-05-07 15:09:06 +08:00
|
|
|
|
2015-05-07 18:32:32 +08:00
|
|
|
{
|
|
|
|
if(GL_FALSE == oldDepthTest)
|
|
|
|
{
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
}
|
|
|
|
glDepthFunc(oldDepthFunc);
|
2015-06-16 01:40:47 +08:00
|
|
|
|
2015-05-07 18:32:32 +08:00
|
|
|
if(GL_FALSE == oldDepthMask)
|
|
|
|
{
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
}
|
2015-06-16 01:40:47 +08:00
|
|
|
|
|
|
|
/* IMPORTANT: We only need to update the states that are not restored.
|
|
|
|
Since we don't know what was the previous value of the mask, we update the RenderState
|
|
|
|
after setting it.
|
|
|
|
The other values don't need to be updated since they were restored to their original values
|
|
|
|
*/
|
2015-05-07 18:32:32 +08:00
|
|
|
glStencilMask(0xFFFFF);
|
2015-07-01 14:06:37 +08:00
|
|
|
// RenderState::StateBlock::_defaultState->setStencilWrite(0xFFFFF);
|
2015-06-13 06:03:48 +08:00
|
|
|
|
2015-06-16 01:40:47 +08:00
|
|
|
/* BUG: RenderState does not support glColorMask yet. */
|
2015-05-07 18:32:32 +08:00
|
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
|
}
|
2015-05-07 15:09:06 +08:00
|
|
|
}
|
|
|
|
|
2015-06-09 10:59:43 +08:00
|
|
|
void Camera::setFrameBufferObject(experimental::FrameBuffer *fbo)
|
2015-05-12 16:43:17 +08:00
|
|
|
{
|
|
|
|
CC_SAFE_RETAIN(fbo);
|
|
|
|
CC_SAFE_RELEASE_NULL(_fbo);
|
|
|
|
_fbo = fbo;
|
|
|
|
if(_scene)
|
|
|
|
{
|
|
|
|
_scene->setCameraOrderDirty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Camera::applyFrameBufferObject()
|
|
|
|
{
|
|
|
|
if(nullptr == _fbo)
|
|
|
|
{
|
2015-06-09 10:59:43 +08:00
|
|
|
experimental::FrameBuffer::applyDefaultFBO();
|
2015-05-12 16:43:17 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-05-28 17:08:36 +08:00
|
|
|
_fbo->applyFBO();
|
2015-05-12 16:43:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-29 14:08:20 +08:00
|
|
|
void Camera::apply()
|
|
|
|
{
|
|
|
|
applyFrameBufferObject();
|
2015-05-29 15:52:06 +08:00
|
|
|
applyViewport();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Camera::applyViewport()
|
|
|
|
{
|
2015-06-01 14:26:08 +08:00
|
|
|
if(nullptr == _fbo)
|
|
|
|
{
|
|
|
|
glViewport(getDefaultViewport()._left, getDefaultViewport()._bottom, getDefaultViewport()._width, getDefaultViewport()._height);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glViewport(_viewport._left * _fbo->getWidth(), _viewport._bottom * _fbo->getHeight(),
|
|
|
|
_viewport._width * _fbo->getWidth(), _viewport._height * _fbo->getHeight());
|
|
|
|
}
|
|
|
|
|
2015-05-29 14:08:20 +08:00
|
|
|
}
|
|
|
|
|
2015-05-12 16:43:17 +08:00
|
|
|
int Camera::getRenderOrder() const
|
|
|
|
{
|
|
|
|
int result(0);
|
|
|
|
if(_fbo)
|
|
|
|
{
|
|
|
|
result = _fbo->getFID()<<8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = 127 <<8;
|
|
|
|
}
|
|
|
|
result += _depth;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-07-30 11:53:23 +08:00
|
|
|
void Camera::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags)
|
|
|
|
{
|
|
|
|
_viewProjectionUpdated = _transformUpdated;
|
|
|
|
return Node::visit(renderer, parentTransform, parentFlags);
|
|
|
|
}
|
|
|
|
|
2014-08-07 15:23:31 +08:00
|
|
|
NS_CC_END
|