Merge pull request #9953 from darkdukey/renderFix

Render fix
This commit is contained in:
minggo 2015-01-14 11:06:33 +08:00
commit 0207c22cb6
28 changed files with 905 additions and 544 deletions

View File

@ -25,6 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "2d/CCCamera.h"
#include "CCAtlasNode.h"
#include "renderer/CCTextureAtlas.h"
#include "base/CCDirector.h"
@ -132,15 +133,32 @@ void AtlasNode::updateAtlasValues()
// AtlasNode - draw
void AtlasNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
_quadCommand.init(
_globalZOrder,
_textureAtlas->getTexture()->getName(),
getGLProgramState(),
_blendFunc,
_textureAtlas->getQuads(),
_quadsToDraw,
transform);
//Render as 3D object
if (flags & FLAGS_RENDER_AS_3D)
{
float depth = Camera::getVisitingCamera()->getDepthInView(transform);
_quadCommand.init(
depth,
_textureAtlas->getTexture()->getName(),
getGLProgramState(),
_blendFunc,
_textureAtlas->getQuads(),
_quadsToDraw,
transform);
_quadCommand.set3D(true);
}
else
{
_quadCommand.init(
_globalZOrder,
_textureAtlas->getTexture()->getName(),
getGLProgramState(),
_blendFunc,
_textureAtlas->getQuads(),
_quadsToDraw,
transform);
}
renderer->addCommand(&_quadCommand);
}

View File

@ -30,7 +30,19 @@ NS_CC_BEGIN
Camera* Camera::_visitingCamera = nullptr;
Camera* Camera::create()
Camera* Camera::getDefaultCamera()
{
auto scene = Director::getInstance()->getRunningScene();
if(scene)
{
return scene->getDefaultCamera();
}
return nullptr;
}
Camera* Camera::create()
{
Camera* camera = new (std::nothrow) Camera();
camera->initDefault();
@ -253,9 +265,9 @@ void Camera::unproject(const Size& viewport, Vec3* src, Vec3* dst) const
dst->set(screen.x, screen.y, screen.z);
}
void Camera::enableFrustumCulling(bool enalbe, bool clipZ)
void Camera::enableFrustumCulling(bool value, bool clipZ)
{
_enableFrustumCulling = enalbe;
_enableFrustumCulling = value;
_frustum.setClipZ(clipZ);
}
@ -273,6 +285,14 @@ bool Camera::isVisibleInFrustum(const AABB* aabb) const
return true;
}
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;
}
void Camera::onEnter()
{
if (_scene == nullptr)

View File

@ -35,8 +35,9 @@ class Scene;
* Note:
* Scene creates a default camera. And the default camera mask of Node is 1, therefore it can be seen by the default camera.
* During rendering the scene, it draws the objects seen by each camera in the added order except default camera. The default camera is the last one being drawn with.
* If 3D objects exist, you'd better create a seperate camera for them. And set the 3d camera flag to CameraFlag::USER1 or anything else except DEFAULT. The DEFAULT camera is for UI, because it is rendered at last.
* You can change the camera added order to get different result when depth test is not enabled.
* It's usually a good idea to render 3D objects in a separate camera.
* And set the 3d camera flag to CameraFlag::USER1 or anything else except DEFAULT. Dedicate The DEFAULT camera for UI, because it is rendered at last.
* You can change the camera order to get different result when depth test is not enabled.
* For each camera, transparent 3d sprite is rendered after opaque 3d sprite and other 2d objects.
*/
enum class CameraFlag
@ -76,7 +77,7 @@ public:
* @param nearPlane The near plane distance.
* @param farPlane The far plane distance.
*/
static Camera* createPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane);
static Camera* createPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane);
/**
* Creates an orthographic camera.
*
@ -86,7 +87,7 @@ public:
* @param nearPlane The near plane distance.
* @param farPlane The far plane distance.
*/
static Camera* createOrthographic(float zoomX, float zoomY, float nearPlane, float farPlane);
static Camera* createOrthographic(float zoomX, float zoomY, float nearPlane, float farPlane);
/** create default camera, the camera type depends on Director::getProjection */
static Camera* create();
@ -96,7 +97,7 @@ public:
*
* @return The camera type.
*/
Camera::Type getType() const { return _type; }
Camera::Type getType() const { return _type; }
/**get & set Camera flag*/
CameraFlag getCameraFlag() const { return (CameraFlag)_cameraFlag; }
@ -105,15 +106,14 @@ public:
* Sets the position (X, Y, and Z) in its parent's coordinate system
*/
virtual void setPosition3D(const Vec3& position) override;
/**
* Creates a view matrix based on the specified input parameters.
* Make Camera looks at target
*
* @param eyePosition The eye position.
* @param targetPosition The target's center position.
* @param up The up vector.
* @param dst A matrix to store the result in.
* @param target The target camera is point at
* @param up The up vector, usually it's Y axis
*/
virtual void lookAt(const Vec3& target, const Vec3& up);
virtual void lookAt(const Vec3& target, const Vec3& up = Vec3::UNIT_Y);
/**
* Gets the camera's projection matrix.
@ -139,18 +139,24 @@ public:
/**
* Enable frustum culling
*/
void enableFrustumCulling(bool enalbe, bool clipZ);
void enableFrustumCulling(bool value, bool clipZ);
/**
* Is this aabb visible in frustum
*/
bool isVisibleInFrustum(const AABB* aabb)const;
bool isVisibleInFrustum(const AABB* aabb) const;
/**
* Get object depth towards camera
*/
float getDepthInView(const Mat4& transform) const;
//override
virtual void onEnter() override;
virtual void onExit() override;
static const Camera* getVisitingCamera() { return _visitingCamera; }
static Camera* getDefaultCamera();
CC_CONSTRUCTOR_ACCESS:
Camera();

View File

@ -23,6 +23,7 @@
THE SOFTWARE.
****************************************************************************/
#include "2d/CCCamera.h"
#include "2d/CCLabel.h"
#include "2d/CCFontAtlasCache.h"
#include "2d/CCSprite.h"
@ -896,8 +897,18 @@ void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
_insideBounds = transformUpdated ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;
if(_insideBounds) {
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(Label::onDraw, this, transform, transformUpdated);
if (flags & FLAGS_RENDER_AS_3D)
{
float depth = Camera::getVisitingCamera()->getDepthInView(transform);
_customCommand.init(depth);
_customCommand.func = CC_CALLBACK_0(Label::onDraw, this, transform, transformUpdated);
}
else
{
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(Label::onDraw, this, transform, transformUpdated);
}
renderer->addCommand(&_customCommand);
}
}

View File

@ -108,6 +108,7 @@ public:
enum {
FLAGS_TRANSFORM_DIRTY = (1 << 0),
FLAGS_CONTENT_SIZE_DIRTY = (1 << 1),
FLAGS_RENDER_AS_3D = (1 << 3),
FLAGS_DIRTY_MASK = (FLAGS_TRANSFORM_DIRTY | FLAGS_CONTENT_SIZE_DIRTY),
};

View File

@ -29,7 +29,7 @@
*/
#include "2d/CCParticleBatchNode.h"
#include "2d/CCCamera.h"
#include "2d/CCGrid.h"
#include "2d/CCParticleSystem.h"
#include "renderer/CCTextureCache.h"
@ -403,12 +403,25 @@ void ParticleBatchNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t
return;
}
_batchCommand.init(
if (flags & FLAGS_RENDER_AS_3D)
{
float depth = Camera::getVisitingCamera()->getDepthInView(transform);
_batchCommand.init(
depth,
getGLProgram(),
_blendFunc,
_textureAtlas,
_modelViewTransform);
}
else
{
_batchCommand.init(
_globalZOrder,
getGLProgram(),
_blendFunc,
_textureAtlas,
_modelViewTransform);
}
renderer->addCommand(&_batchCommand);
CC_PROFILER_STOP("CCParticleBatchNode - draw");
}

View File

@ -31,6 +31,7 @@ THE SOFTWARE.
#include <algorithm>
#include "2d/CCCamera.h"
#include "2d/CCSpriteFrame.h"
#include "2d/CCParticleBatchNode.h"
#include "renderer/CCTextureAtlas.h"
@ -372,8 +373,17 @@ void ParticleSystemQuad::draw(Renderer *renderer, const Mat4 &transform, uint32_
//quad command
if(_particleIdx > 0)
{
_quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, _quads, _particleIdx, transform);
renderer->addCommand(&_quadCommand);
if (flags & FLAGS_RENDER_AS_3D)
{
float depth = Camera::getVisitingCamera()->getDepthInView(transform);
_quadCommand.init(depth, _texture->getName(), getGLProgramState(), _blendFunc, _quads, _particleIdx, transform);
renderer->addCommand(&_quadCommand);
}
else
{
_quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, _quads, _particleIdx, transform);
renderer->addCommand(&_quadCommand);
}
}
}

View File

@ -73,6 +73,8 @@ public:
/** get all cameras */
const std::vector<Camera*>& getCameras() const { return _cameras; }
Camera* getDefaultCamera() const { return _defaultCamera; }
const std::vector<BaseLight*>& getLights() const { return _lights; }
/** render the scene */

View File

@ -29,6 +29,7 @@ THE SOFTWARE.
#include <algorithm>
#include "2d/CCCamera.h"
#include "2d/CCSpriteBatchNode.h"
#include "2d/CCAnimationCache.h"
#include "2d/CCSpriteFrame.h"
@ -592,8 +593,19 @@ void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
if(_insideBounds)
{
_quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform);
//Render as 3D object
if (flags & FLAGS_RENDER_AS_3D)
{
float depth = Camera::getVisitingCamera()->getDepthInView(transform);
_quadCommand.init(depth, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform);
_quadCommand.set3D(true);
}
else
{
_quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform);
}
renderer->addCommand(&_quadCommand);
#if CC_SPRITE_DEBUG_DRAW
_debugDrawNode->clear();
Vec2 vertices[4] = {

View File

@ -26,6 +26,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "2d/CCCamera.h"
#include "2d/CCSpriteBatchNode.h"
#include "2d/CCSprite.h"
#include "base/CCDirector.h"
@ -378,12 +379,26 @@ void SpriteBatchNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t f
child->updateTransform();
}
_batchCommand.init(
//Render as 3D object
if (flags & FLAGS_RENDER_AS_3D)
{
float depth = Camera::getVisitingCamera()->getDepthInView(transform);
_batchCommand.init(
depth,
getGLProgram(),
_blendFunc,
_textureAtlas,
transform);
}
else
{
_batchCommand.init(
_globalZOrder,
getGLProgram(),
_blendFunc,
_textureAtlas,
transform);
}
renderer->addCommand(&_batchCommand);
}

View File

@ -32,8 +32,7 @@
NS_CC_BEGIN
BillBoard::BillBoard()
: _zDepthInView(0.0f)
, _mode(Mode::VIEW_POINT_ORIENTED)
: _mode(Mode::VIEW_POINT_ORIENTED)
, _modeDirty(false)
{
Node::setAnchorPoint(Vec2(0.5f,0.5f));
@ -96,42 +95,108 @@ BillBoard* BillBoard::create(Mode mode)
return nullptr;
}
void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
void BillBoard::visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags)
{
// quick return if not visible. children won't be drawn.
if (!_visible)
{
return;
}
uint32_t flags = processParentFlags(parentTransform, parentFlags);
//Add 3D flag so all the children will be rendered as 3D object
flags |= FLAGS_RENDER_AS_3D;
//Update Billboard transform
bool dirty = calculateBillbaordTransform();
if(dirty)
{
flags |= FLAGS_TRANSFORM_DIRTY;
}
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
bool visibleByCamera = isVisitableByVisitingCamera();
int i = 0;
if(!_children.empty())
{
sortAllChildren();
// draw children zOrder < 0
for( ; i < _children.size(); i++ )
{
auto node = _children.at(i);
if (node && node->getLocalZOrder() < 0)
node->visit(renderer, _modelViewTransform, flags);
else
break;
}
// self draw
if (visibleByCamera)
this->draw(renderer, _modelViewTransform, flags);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(renderer, _modelViewTransform, flags);
}
else if (visibleByCamera)
{
this->draw(renderer, _modelViewTransform, flags);
}
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
bool BillBoard::calculateBillbaordTransform()
{
//Get camera world position
auto camera = Camera::getVisitingCamera();
const Mat4& camWorldMat = camera->getNodeToWorldTransform();
if (memcmp(_camWorldMat.m, camWorldMat.m, sizeof(float) * 16) != 0 || memcmp(_mvTransform.m, transform.m, sizeof(float) * 16) != 0 || _modeDirty)
//TODO: use math lib to calculate math lib Make it easier to read and maintain
if (memcmp(_camWorldMat.m, camWorldMat.m, sizeof(float) * 16) != 0 || _transformDirty || _modeDirty)
{
//Rotate based on anchor point
Vec3 anchorPoint(_anchorPointInPoints.x , _anchorPointInPoints.y , 0.0f);
Mat4 localToWorld = transform;
Mat4 localToWorld = _modelViewTransform;
localToWorld.translate(anchorPoint);
//Decide billboard mode
Vec3 camDir;
switch (_mode)
{
case Mode::VIEW_POINT_ORIENTED:
camDir = Vec3(localToWorld.m[12] - camWorldMat.m[12], localToWorld.m[13] - camWorldMat.m[13], localToWorld.m[14] - camWorldMat.m[14]);
break;
case Mode::VIEW_PLANE_ORIENTED:
camWorldMat.transformVector(Vec3(0.0f, 0.0f, -1.0f), &camDir);
break;
default:
case Mode::VIEW_POINT_ORIENTED:
camDir = Vec3(localToWorld.m[12] - camWorldMat.m[12], localToWorld.m[13] - camWorldMat.m[13], localToWorld.m[14] - camWorldMat.m[14]);
break;
case Mode::VIEW_PLANE_ORIENTED:
camWorldMat.transformVector(Vec3(0.0f, 0.0f, -1.0f), &camDir);
break;
default:
CCASSERT(false, "invalid billboard mode");
break;
break;
}
_modeDirty = false;
if (camDir.length() < MATH_TOLERANCE)
{
camDir.set(camWorldMat.m[8], camWorldMat.m[9], camWorldMat.m[10]);
}
camDir.normalize();
Quaternion rotationQuaternion;
this->getNodeToWorldTransform().getRotation(&rotationQuaternion);
// fetch the rotation angle of z
float rotationZ = atan2(2*(rotationQuaternion.w*rotationQuaternion.z + rotationQuaternion.x*rotationQuaternion.y),
(1 - 2* (rotationQuaternion.y*rotationQuaternion.y + rotationQuaternion.z *rotationQuaternion.z)));
(1 - 2* (rotationQuaternion.y*rotationQuaternion.y + rotationQuaternion.z *rotationQuaternion.z)));
Mat4 rotationMatrix;
rotationMatrix.setIdentity();
rotationMatrix.rotateZ(rotationZ);
Vec3 upAxis = Vec3(rotationMatrix.m[4],rotationMatrix.m[5],rotationMatrix.m[6]);
Vec3 x, y;
camWorldMat.transformVector(upAxis, &y);
@ -139,30 +204,40 @@ void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
x.normalize();
Vec3::cross(x, camDir, &y);
y.normalize();
float xlen = sqrtf(localToWorld.m[0] * localToWorld.m[0] + localToWorld.m[1] * localToWorld.m[1] + localToWorld.m[2] * localToWorld.m[2]);
float ylen = sqrtf(localToWorld.m[4] * localToWorld.m[4] + localToWorld.m[5] * localToWorld.m[5] + localToWorld.m[6] * localToWorld.m[6]);
float zlen = sqrtf(localToWorld.m[8] * localToWorld.m[8] + localToWorld.m[9] * localToWorld.m[9] + localToWorld.m[10] * localToWorld.m[10]);
_billboardTransform.m[0] = x.x * xlen; _billboardTransform.m[1] = x.y * xlen; _billboardTransform.m[2] = x.z * xlen;
_billboardTransform.m[4] = y.x * ylen; _billboardTransform.m[5] = y.y * ylen; _billboardTransform.m[6] = y.z * ylen;
_billboardTransform.m[8] = -camDir.x * zlen; _billboardTransform.m[9] = -camDir.y * zlen; _billboardTransform.m[10] = -camDir.z * zlen;
_billboardTransform.m[12] = localToWorld.m[12]; _billboardTransform.m[13] = localToWorld.m[13]; _billboardTransform.m[14] = localToWorld.m[14];
_billboardTransform.translate(-anchorPoint);
const Mat4 &viewMat = camWorldMat.getInversed();
_zDepthInView = -(viewMat.m[2] * _billboardTransform.m[12] + viewMat.m[6] * _billboardTransform.m[13] + viewMat.m[10] * _billboardTransform.m[14] + viewMat.m[14]);
_mvTransform = transform;
Mat4 billboardTransform;
billboardTransform.m[0] = x.x * xlen; billboardTransform.m[1] = x.y * xlen; billboardTransform.m[2] = x.z * xlen;
billboardTransform.m[4] = y.x * ylen; billboardTransform.m[5] = y.y * ylen; billboardTransform.m[6] = y.z * ylen;
billboardTransform.m[8] = -camDir.x * zlen; billboardTransform.m[9] = -camDir.y * zlen; billboardTransform.m[10] = -camDir.z * zlen;
billboardTransform.m[12] = localToWorld.m[12]; billboardTransform.m[13] = localToWorld.m[13]; billboardTransform.m[14] = localToWorld.m[14];
billboardTransform.translate(-anchorPoint);
_modelViewTransform = billboardTransform;
_camWorldMat = camWorldMat;
return true;
}
return false;
}
void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
//Get depth
float depth = Camera::getVisitingCamera()->getDepthInView(transform);
//FIXME: frustum culling here
{
_quadCommand.init(_zDepthInView, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, _billboardTransform);
_quadCommand.setTransparent(true);
renderer->addCommand(&_quadCommand);
}
_quadCommand.init(depth, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, _modelViewTransform);
_quadCommand.setTransparent(true);
_quadCommand.setSkipBatching(true);
_quadCommand.set3D(true);
renderer->addCommand(&_quadCommand);
}
void BillBoard::setMode( Mode mode )

View File

@ -88,6 +88,10 @@ public:
Mode getMode() const;
//override
/** update billboard's transform and turn it towards camera */
virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags);
/** draw BillBoard object */
virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
@ -98,11 +102,9 @@ CC_CONSTRUCTOR_ACCESS:
protected:
Mat4 _camWorldMat;
Mat4 _mvTransform;
Mat4 _billboardTransform;
bool calculateBillbaordTransform();
float _zDepthInView;
Mat4 _camWorldMat;
Mode _mode;
bool _modeDirty;

View File

@ -48,10 +48,23 @@ NS_CC_BEGIN
std::string s_attributeNames[] = {GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::ATTRIBUTE_NAME_TEX_COORD1, GLProgram::ATTRIBUTE_NAME_TEX_COORD2,GLProgram::ATTRIBUTE_NAME_TEX_COORD3,GLProgram::ATTRIBUTE_NAME_NORMAL, GLProgram::ATTRIBUTE_NAME_BLEND_WEIGHT, GLProgram::ATTRIBUTE_NAME_BLEND_INDEX};
Sprite3D* Sprite3D::create()
{
//
auto sprite = new (std::nothrow) Sprite3D();
if (sprite && sprite->init())
{
sprite->autorelease();
return sprite;
}
CC_SAFE_DELETE(sprite);
return nullptr;
}
Sprite3D* Sprite3D::create(const std::string &modelPath)
{
if (modelPath.length() < 4)
CCASSERT(false, "improper name specified when creating Sprite3D");
CCASSERT(false, "invalid filename for Sprite3D");
auto sprite = new (std::nothrow) Sprite3D();
if (sprite && sprite->initWithFile(modelPath))
@ -241,6 +254,15 @@ Sprite3D::~Sprite3D()
removeAllAttachNode();
}
bool Sprite3D::init()
{
if(Node::init())
{
return true;
}
return false;
}
bool Sprite3D::initWithFile(const std::string &path)
{
_meshes.clear();
@ -599,6 +621,54 @@ static Texture2D * getDummyTexture()
}
#endif
void Sprite3D::visit(cocos2d::Renderer *renderer, const cocos2d::Mat4 &parentTransform, uint32_t parentFlags)
{
// quick return if not visible. children won't be drawn.
if (!_visible)
{
return;
}
uint32_t flags = processParentFlags(parentTransform, parentFlags);
flags &= FLAGS_RENDER_AS_3D;
//
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
bool visibleByCamera = isVisitableByVisitingCamera();
int i = 0;
if(!_children.empty())
{
sortAllChildren();
// draw children zOrder < 0
for( ; i < _children.size(); i++ )
{
auto node = _children.at(i);
if (node && node->getLocalZOrder() < 0)
node->visit(renderer, _modelViewTransform, flags);
else
break;
}
// self draw
if (visibleByCamera)
this->draw(renderer, _modelViewTransform, flags);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(renderer, _modelViewTransform, flags);
}
else if (visibleByCamera)
{
this->draw(renderer, _modelViewTransform, flags);
}
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
void Sprite3D::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
// camera clipping
@ -651,9 +721,11 @@ void Sprite3D::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
float globalZ = _globalZOrder;
bool isTransparent = (mesh->_isTransparent || color.a < 1.f);
if (isTransparent && Camera::getVisitingCamera())
{ // use the view matrix for Applying to recalculating transparent mesh's Z-Order
{
// use the view matrix for Applying to recalculating transparent mesh's Z-Order
const auto& viewMat = Camera::getVisitingCamera()->getViewMatrix();
globalZ = -(viewMat.m[2] * transform.m[12] + viewMat.m[6] * transform.m[13] + viewMat.m[10] * transform.m[14] + viewMat.m[14]);//fetch the Z from the result matrix
//fetch the Z from the result matrix
globalZ = -(viewMat.m[2] * transform.m[12] + viewMat.m[6] * transform.m[13] + viewMat.m[10] * transform.m[14] + viewMat.m[14]);
}
meshCommand.init(globalZ, textureID, programstate, _blend, mesh->getVertexBuffer(), mesh->getIndexBuffer(), mesh->getPrimitiveType(), mesh->getIndexFormat(), mesh->getIndexCount(), transform);

View File

@ -50,6 +50,13 @@ struct NodeData;
class CC_DLL Sprite3D : public Node, public BlendProtocol
{
public:
/**
* Creates an empty sprite3D without 3D model and texture.
*
* @return An autoreleased sprite3D object.
*/
static Sprite3D* create();
/** creates a Sprite3D*/
static Sprite3D* create(const std::string &modelPath);
@ -138,6 +145,9 @@ CC_CONSTRUCTOR_ACCESS:
Sprite3D();
virtual ~Sprite3D();
bool init();
bool initWithFile(const std::string &path);
bool initFrom(const NodeDatas& nodedatas, const MeshDatas& meshdatas, const MaterialDatas& materialdatas);
@ -148,6 +158,12 @@ CC_CONSTRUCTOR_ACCESS:
/** load file and set it to meshedatas, nodedatas and materialdatas, obj file .mtl file should be at the same directory if exist */
bool loadFromFile(const std::string& path, NodeDatas* nodedatas, MeshDatas* meshdatas, MaterialDatas* materialdatas);
/**
* Visits this Sprite3D's children and draw them recursively.
* Note: all its children will rendered as 3D objects
*/
virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags) override;
/**draw*/
virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;

View File

@ -169,12 +169,6 @@ bool Director::init(void)
_renderer = new (std::nothrow) Renderer;
_console = new (std::nothrow) Console;
// default clear color
_clearColor.r = 0;
_clearColor.g = 0;
_clearColor.b = 0;
_clearColor.a = 1.0;
return true;
}
@ -258,9 +252,6 @@ void Director::setGLDefaultValues()
// [self setDepthTest: view_.depthFormat];
setDepthTest(false);
setProjection(_projection);
// set other opengl default values
glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearColor.a);
}
// Draw the Scene
@ -281,7 +272,7 @@ void Director::drawScene()
_eventDispatcher->dispatchEvent(_eventAfterUpdate);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_renderer->clear();
/* to avoid flickr, nextScene MUST be here: after tick and before draw.
* FIXME: Which bug is this one. It seems that it can't be reproduced with v0.9
@ -726,8 +717,7 @@ void Director::setDepthTest(bool on)
void Director::setClearColor(const Color4F& clearColor)
{
_clearColor = clearColor;
glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
_renderer->setClearColor(clearColor);
}
static void GLToClipTransform(Mat4 *transformOut)

View File

@ -475,9 +475,6 @@ protected:
unsigned int _totalFrames;
float _secondsPerFrame;
/* clear color set outside be used in setGLDefaultValues() */
Color4F _clearColor;
/* The running scene */
Scene *_runningScene;

View File

@ -123,7 +123,7 @@ void MeshCommand::init(float globalOrder,
_indexFormat = indexFormat;
_indexCount = indexCount;
_mv.set(mv);
_is3D = true;
}
void MeshCommand::setCullFaceEnabled(bool enable)
@ -151,6 +151,14 @@ void MeshCommand::setDisplayColor(const Vec4& color)
_displayColor = color;
}
void MeshCommand::setTransparent(bool value)
{
_isTransparent = value;
//Skip batching for transparent mesh
_skipBatching = value;
setDepthWriteEnabled(!_isTransparent);
}
MeshCommand::~MeshCommand()
{
releaseVAO();

View File

@ -64,6 +64,8 @@ public:
void setLightMask(unsigned int lightmask) { _lightMask = lightmask; }
void setTransparent(bool value);
void execute();
//used for bath

View File

@ -30,7 +30,9 @@ NS_CC_BEGIN
RenderCommand::RenderCommand()
: _type(RenderCommand::Type::UNKNOWN_COMMAND)
, _globalOrder(0)
, _isTransparent(false)
, _isTransparent(true)
, _skipBatching(false)
, _is3D(false)
{
}

View File

@ -65,6 +65,14 @@ public:
/** set transparent flag */
inline void setTransparent(bool isTransparent) { _isTransparent = isTransparent; }
inline bool isSkipBatching() const { return _skipBatching; }
inline void setSkipBatching(bool value) { _skipBatching = value; }
inline bool is3D() const { return _is3D; }
inline void set3D(bool value) { _is3D = value; }
protected:
RenderCommand();
virtual ~RenderCommand();
@ -79,6 +87,12 @@ protected:
// transparent flag
bool _isTransparent;
// skip auto batching
bool _skipBatching;
// is the command been rendered on 3D pass
bool _is3D;
};
NS_CC_END

View File

@ -51,12 +51,28 @@ static bool compareRenderCommand(RenderCommand* a, RenderCommand* b)
return a->getGlobalOrder() < b->getGlobalOrder();
}
static bool compare3DCommand(RenderCommand* a, RenderCommand* b)
{
return a->getGlobalOrder() > b->getGlobalOrder();
}
// queue
void RenderQueue::push_back(RenderCommand* command)
{
float z = command->getGlobalOrder();
if(z < 0)
if(command->is3D())
{
if(command->isTransparent())
{
_queue3DTransparent.push_back(command);
}
else
{
_queue3DOpaque.push_back(command);
}
}
else if(z < 0)
_queueNegZ.push_back(command);
else if(z > 0)
_queuePosZ.push_back(command);
@ -66,18 +82,29 @@ void RenderQueue::push_back(RenderCommand* command)
ssize_t RenderQueue::size() const
{
return _queueNegZ.size() + _queue0.size() + _queuePosZ.size();
return _queue3DOpaque.size() + _queue3DTransparent.size() + _queueNegZ.size() + _queue0.size() + _queuePosZ.size();
}
void RenderQueue::sort()
{
// Don't sort _queue0, it already comes sorted
std::sort(std::begin(_queue3DTransparent), std::end(_queue3DTransparent), compare3DCommand);
std::sort(std::begin(_queueNegZ), std::end(_queueNegZ), compareRenderCommand);
std::sort(std::begin(_queuePosZ), std::end(_queuePosZ), compareRenderCommand);
}
RenderCommand* RenderQueue::operator[](ssize_t index) const
{
if(index < static_cast<ssize_t>(_queue3DOpaque.size()))
return _queue3DOpaque[index];
index -= _queue3DOpaque.size();
if(index < static_cast<ssize_t>(_queue3DTransparent.size()))
return _queue3DTransparent[index];
index -= _queue3DTransparent.size();
if(index < static_cast<ssize_t>(_queueNegZ.size()))
return _queueNegZ[index];
@ -97,37 +124,13 @@ RenderCommand* RenderQueue::operator[](ssize_t index) const
void RenderQueue::clear()
{
_queue3DOpaque.clear();
_queue3DTransparent.clear();
_queueNegZ.clear();
_queue0.clear();
_queuePosZ.clear();
}
// helper
static bool compareTransparentRenderCommand(RenderCommand* a, RenderCommand* b)
{
return a->getGlobalOrder() > b->getGlobalOrder();
}
void TransparentRenderQueue::push_back(RenderCommand* command)
{
_queueCmd.push_back(command);
}
void TransparentRenderQueue::sort()
{
std::sort(std::begin(_queueCmd), std::end(_queueCmd), compareTransparentRenderCommand);
}
RenderCommand* TransparentRenderQueue::operator[](ssize_t index) const
{
return _queueCmd[index];
}
void TransparentRenderQueue::clear()
{
_queueCmd.clear();
}
//
//
//
@ -155,6 +158,9 @@ Renderer::Renderer()
RenderQueue defaultRenderQueue;
_renderGroups.push_back(defaultRenderQueue);
_batchedCommands.reserve(BATCH_QUADCOMMAND_RESEVER_SIZE);
// default clear color
_clearColor = Color4F::BLACK;
}
Renderer::~Renderer()
@ -344,164 +350,156 @@ int Renderer::createRenderQueue()
return (int)_renderGroups.size() - 1;
}
void Renderer::visitRenderQueue(const RenderQueue& queue)
void Renderer::processRenderCommand(RenderCommand* command)
{
ssize_t size = queue.size();
for (ssize_t index = 0; index < size; ++index)
auto commandType = command->getType();
if( RenderCommand::Type::TRIANGLES_COMMAND == commandType)
{
auto command = queue[index];
auto commandType = command->getType();
if( RenderCommand::Type::TRIANGLES_COMMAND == commandType)
//Draw if we have batched other commands which are not triangle command
flush3D();
flushQuads();
//Process triangle command
auto cmd = static_cast<TrianglesCommand*>(command);
//Draw batched Triangles if necessary
if(cmd->isSkipBatching() || _filledVertex + cmd->getVertexCount() > VBO_SIZE || _filledIndex + cmd->getIndexCount() > INDEX_VBO_SIZE)
{
CCASSERT(cmd->getVertexCount()>= 0 && cmd->getVertexCount() < VBO_SIZE, "VBO for vertex is not big enough, please break the data down or use customized render command");
CCASSERT(cmd->getIndexCount()>= 0 && cmd->getIndexCount() < INDEX_VBO_SIZE, "VBO for index is not big enough, please break the data down or use customized render command");
//Draw batched Triangles if VBO is full
drawBatchedTriangles();
}
//Batch Triangles
_batchedCommands.push_back(cmd);
fillVerticesAndIndices(cmd);
if(cmd->isSkipBatching())
{
drawBatchedTriangles();
}
}
else if ( RenderCommand::Type::QUAD_COMMAND == commandType )
{
//Draw if we have batched other commands which are not quad command
flush3D();
flushTriangles();
//Process quad command
auto cmd = static_cast<QuadCommand*>(command);
//Draw batched quads if necessary
if(cmd->isSkipBatching()|| (_numberQuads + cmd->getQuadCount()) * 4 > VBO_SIZE )
{
CCASSERT(cmd->getQuadCount()>= 0 && cmd->getQuadCount() * 4 < VBO_SIZE, "VBO for vertex is not big enough, please break the data down or use customized render command");
//Draw batched quads if VBO is full
drawBatchedQuads();
}
//Batch Quads
_batchQuadCommands.push_back(cmd);
fillQuads(cmd);
if(cmd->isSkipBatching())
{
drawBatchedQuads();
}
}
else if (RenderCommand::Type::MESH_COMMAND == commandType)
{
flush2D();
auto cmd = static_cast<MeshCommand*>(command);
if (cmd->isSkipBatching() || _lastBatchedMeshCommand == nullptr || _lastBatchedMeshCommand->getMaterialID() != cmd->getMaterialID())
{
flush3D();
if(_numberQuads > 0)
if(cmd->isSkipBatching())
{
drawBatchedQuads();
_lastMaterialID = 0;
cmd->execute();
}
auto cmd = static_cast<TrianglesCommand*>(command);
//Batch Triangles
if( _filledVertex + cmd->getVertexCount() > VBO_SIZE || _filledIndex + cmd->getIndexCount() > INDEX_VBO_SIZE)
else
{
CCASSERT(cmd->getVertexCount()>= 0 && cmd->getVertexCount() < VBO_SIZE, "VBO for vertex is not big enough, please break the data down or use customized render command");
CCASSERT(cmd->getIndexCount()>= 0 && cmd->getIndexCount() < INDEX_VBO_SIZE, "VBO for index is not big enough, please break the data down or use customized render command");
//Draw batched Triangles if VBO is full
drawBatchedTriangles();
}
_batchedCommands.push_back(cmd);
fillVerticesAndIndices(cmd);
}
else if ( RenderCommand::Type::QUAD_COMMAND == commandType )
{
flush3D();
if(_filledIndex > 0)
{
drawBatchedTriangles();
_lastMaterialID = 0;
}
auto cmd = static_cast<QuadCommand*>(command);
//Batch quads
if( (_numberQuads + cmd->getQuadCount()) * 4 > VBO_SIZE )
{
CCASSERT(cmd->getQuadCount()>= 0 && cmd->getQuadCount() * 4 < VBO_SIZE, "VBO for vertex is not big enough, please break the data down or use customized render command");
//Draw batched quads if VBO is full
drawBatchedQuads();
}
_batchQuadCommands.push_back(cmd);
fillQuads(cmd);
}
else if(RenderCommand::Type::GROUP_COMMAND == commandType)
{
flush();
int renderQueueID = ((GroupCommand*) command)->getRenderQueueID();
visitRenderQueue(_renderGroups[renderQueueID]);
}
else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)
{
flush();
auto cmd = static_cast<CustomCommand*>(command);
cmd->execute();
}
else if(RenderCommand::Type::BATCH_COMMAND == commandType)
{
flush();
auto cmd = static_cast<BatchCommand*>(command);
cmd->execute();
}
else if(RenderCommand::Type::PRIMITIVE_COMMAND == commandType)
{
flush();
auto cmd = static_cast<PrimitiveCommand*>(command);
cmd->execute();
}
else if (RenderCommand::Type::MESH_COMMAND == commandType)
{
flush2D();
auto cmd = static_cast<MeshCommand*>(command);
if (_lastBatchedMeshCommand == nullptr || _lastBatchedMeshCommand->getMaterialID() != cmd->getMaterialID())
{
flush3D();
cmd->preBatchDraw();
cmd->batchDraw();
_lastBatchedMeshCommand = cmd;
}
else
{
cmd->batchDraw();
}
}
else
{
CCLOGERROR("Unknown commands in renderQueue");
cmd->batchDraw();
}
}
else if(RenderCommand::Type::GROUP_COMMAND == commandType)
{
flush();
int renderQueueID = ((GroupCommand*) command)->getRenderQueueID();
visitRenderQueue(_renderGroups[renderQueueID]);
}
else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)
{
flush();
auto cmd = static_cast<CustomCommand*>(command);
cmd->execute();
}
else if(RenderCommand::Type::BATCH_COMMAND == commandType)
{
flush();
auto cmd = static_cast<BatchCommand*>(command);
cmd->execute();
}
else if(RenderCommand::Type::PRIMITIVE_COMMAND == commandType)
{
flush();
auto cmd = static_cast<PrimitiveCommand*>(command);
cmd->execute();
}
else
{
CCLOGERROR("Unknown commands in renderQueue");
}
}
void Renderer::visitTransparentRenderQueue(const TransparentRenderQueue& queue)
void Renderer::visitRenderQueue(const RenderQueue& queue)
{
// do not batch for transparent objects
ssize_t size = queue.size();
_batchedCommands.clear();
_filledVertex = 0;
_filledIndex = 0;
for (ssize_t index = 0; index < size; ++index)
//Process Opaque Object
const std::vector<RenderCommand*>& opaqueQueue = queue.getOpaqueCommands();
if (opaqueQueue.size() > 0)
{
auto command = queue[index];
auto commandType = command->getType();
if( RenderCommand::Type::TRIANGLES_COMMAND == commandType)
{
auto cmd = static_cast<TrianglesCommand*>(command);
_batchedCommands.push_back(cmd);
fillVerticesAndIndices(cmd);
drawBatchedTriangles();
}
else if(RenderCommand::Type::QUAD_COMMAND == commandType)
{
auto cmd = static_cast<QuadCommand*>(command);
_batchQuadCommands.push_back(cmd);
fillQuads(cmd);
drawBatchedQuads();
}
else if(RenderCommand::Type::GROUP_COMMAND == commandType)
{
int renderQueueID = (static_cast<GroupCommand*>(command))->getRenderQueueID();
visitRenderQueue(_renderGroups[renderQueueID]);
}
else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)
{
auto cmd = static_cast<CustomCommand*>(command);
cmd->execute();
}
else if(RenderCommand::Type::BATCH_COMMAND == commandType)
{
auto cmd = static_cast<BatchCommand*>(command);
cmd->execute();
}
else if(RenderCommand::Type::PRIMITIVE_COMMAND == commandType)
{
auto cmd = static_cast<PrimitiveCommand*>(command);
cmd->execute();
}
else if (RenderCommand::Type::MESH_COMMAND == commandType)
{
auto cmd = static_cast<MeshCommand*>(command);
cmd->execute();
}
else
{
CCLOGERROR("Unknown commands in renderQueue");
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
for (auto it = opaqueQueue.cbegin(); it != opaqueQueue.cend(); ++it) {
processRenderCommand(*it);
}
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
}
flush();
//Setup Transparent rendering
if (opaqueQueue.size() > 0)
{
glEnable(GL_DEPTH_TEST);
}
else
{
glDisable(GL_DEPTH_TEST);
}
//Process Transparent Object
for (ssize_t index = queue.getOpaqueQueueSize(); index < size; ++index)
{
processRenderCommand(queue[index]);
}
flush();
}
void Renderer::render()
@ -521,17 +519,6 @@ void Renderer::render()
renderqueue.sort();
}
visitRenderQueue(_renderGroups[0]);
flush();
//Process render commands
//draw transparent objects here, do not batch for transparent objects
if (0 < _transparentRenderGroups.size())
{
_transparentRenderGroups.sort();
glEnable(GL_DEPTH_TEST);
visitTransparentRenderQueue(_transparentRenderGroups);
glDisable(GL_DEPTH_TEST);
}
}
clean();
_isRendering = false;
@ -558,8 +545,14 @@ void Renderer::clean()
_numberQuads = 0;
_lastMaterialID = 0;
_lastBatchedMeshCommand = nullptr;
_transparentRenderGroups.clear();
}
void Renderer::clear()
{
//Enable Depth mask to make sure glClear clear the depth buffer correctly
glDepthMask(true);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(false);
}
void Renderer::fillVerticesAndIndices(const TrianglesCommand* cmd)
@ -819,23 +812,8 @@ void Renderer::flush()
void Renderer::flush2D()
{
//Check depth write
GLboolean depthWirte;
glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWirte);
//Turn depth write off if necessary
if(depthWirte)
{
glDepthMask(false);
}
drawBatchedQuads();
_lastMaterialID = 0;
drawBatchedTriangles();
_lastMaterialID = 0;
//Turn depth write on if necessary
if(depthWirte)
{
glDepthMask(true);
}
flushQuads();
flushTriangles();
}
void Renderer::flush3D()
@ -847,8 +825,25 @@ void Renderer::flush3D()
}
}
// helpers
void Renderer::flushQuads()
{
if(_numberQuads > 0)
{
drawBatchedQuads();
_lastMaterialID = 0;
}
}
void Renderer::flushTriangles()
{
if(_filledIndex > 0)
{
drawBatchedTriangles();
_lastMaterialID = 0;
}
}
// helpers
bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
{
auto scene = Director::getInstance()->getRunningScene();
@ -884,4 +879,11 @@ bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
return ret;
}
void Renderer::setClearColor(const Color4F &clearColor)
{
_clearColor = clearColor;
glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
}
NS_CC_END

View File

@ -54,29 +54,17 @@ public:
void sort();
RenderCommand* operator[](ssize_t index) const;
void clear();
ssize_t getOpaqueQueueSize() const { return _queue3DOpaque.size(); }
const std::vector<RenderCommand*>& getOpaqueCommands() const { return _queue3DOpaque; }
protected:
std::vector<RenderCommand*> _queue3DOpaque;
std::vector<RenderCommand*> _queue3DTransparent;
std::vector<RenderCommand*> _queueNegZ;
std::vector<RenderCommand*> _queue0;
std::vector<RenderCommand*> _queuePosZ;
};
//render queue for transparency object, NOTE that the _globalOrder of RenderCommand is the distance to the camera when added to the transparent queue
class TransparentRenderQueue {
public:
void push_back(RenderCommand* command);
ssize_t size() const
{
return _queueCmd.size();
}
void sort();
RenderCommand* operator[](ssize_t index) const;
void clear();
protected:
std::vector<RenderCommand*> _queueCmd;
};
struct RenderStackElement
{
int renderQueueID;
@ -125,6 +113,11 @@ public:
/** Cleans all `RenderCommand`s in the queue */
void clean();
/** Clear GL buffer and screen */
void clear();
/** set color for clear screen */
void setClearColor(const Color4F& clearColor);
/* returns the number of drawn batches in the last frame */
ssize_t getDrawnBatches() const { return _drawnBatches; }
/* RenderCommands (except) QuadCommand should update this value */
@ -157,26 +150,29 @@ protected:
void flush2D();
void flush3D();
void flushQuads();
void flushTriangles();
void processRenderCommand(RenderCommand* command);
void visitRenderQueue(const RenderQueue& queue);
void visitTransparentRenderQueue(const TransparentRenderQueue& queue);
void fillVerticesAndIndices(const TrianglesCommand* cmd);
void fillQuads(const QuadCommand* cmd);
/* clear color set outside be used in setGLDefaultValues() */
Color4F _clearColor;
std::stack<int> _commandGroupStack;
std::vector<RenderQueue> _renderGroups;
TransparentRenderQueue _transparentRenderGroups; //transparency objects
uint32_t _lastMaterialID;
MeshCommand* _lastBatchedMeshCommand;
std::vector<TrianglesCommand*> _batchedCommands;
std::vector<QuadCommand*> _batchQuadCommands;
//for TrianglesCommand
V3F_C4B_T2F _verts[VBO_SIZE];
GLushort _indices[INDEX_VBO_SIZE];

View File

@ -606,15 +606,6 @@ void TextureAtlas::drawNumberOfQuads(ssize_t numberOfQuads, ssize_t start)
if(!numberOfQuads)
return;
//Check depth write
GLboolean depthWirte;
glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWirte);
//Turn depth write off if necessary
if(depthWirte)
{
glDepthMask(false);
}
GL::bindTexture2D(_texture->getName());
if (Configuration::getInstance()->supportsShareableVAO())
@ -694,12 +685,6 @@ void TextureAtlas::drawNumberOfQuads(ssize_t numberOfQuads, ssize_t start)
}
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,numberOfQuads*6);
//Turn depth write on if necessary
if(depthWirte)
{
glDepthMask(true);
}
CHECK_GL_ERROR_DEBUG();
}

View File

@ -75,9 +75,11 @@ static Layer* restartSpriteTestAction()
BillBoardTest::BillBoardTest()
: _camera(nullptr)
{
//Create touch listener
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesMoved = CC_CALLBACK_2(BillBoardTest::onTouchesMoved, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
auto layer3D=Layer::create();
addChild(layer3D,0);
_layerBillBorad=layer3D;
@ -89,6 +91,7 @@ BillBoardTest::BillBoardTest()
_layerBillBorad->addChild(_camera);
}
//Create rotating billboards
std::string imgs[3] = {"Images/Icon.png", "Images/r2.png"};
for (unsigned int i = 0; i < 4; ++i)
{
@ -96,12 +99,11 @@ BillBoardTest::BillBoardTest()
auto billboard = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1() * 1 + 0.5)]);
billboard->setScale(0.5f);
billboard->setPosition3D(Vec3(0.0f, 0.0f, CCRANDOM_MINUS1_1() * 150.0f));
billboard->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);
billboard->setOpacity(CCRANDOM_0_1() * 128 + 128);
_billboards.push_back(billboard);
layer->addChild(billboard);
_layerBillBorad->addChild(layer);
layer->runAction( RepeatForever::create( RotateBy::create( CCRANDOM_0_1(), Vec3(0.0f, 45.0f, 0.0f) ) ) );
layer->runAction( RepeatForever::create( RotateBy::create( CCRANDOM_0_1() * 10, Vec3(0.0f, 45.0f, 0.0f) ) ) );
}
{
@ -127,11 +129,13 @@ BillBoardTest::BillBoardTest()
addNewBillBoradWithCoords(Vec3(100,5,0));
addNewBillBoradWithCoords(Vec3(140,5,0));
addNewBillBoradWithCoords(Vec3(180,5,0));
addNewAniBillBoradWithCoords(Vec3(-20,0,0));
addNewAniBillBoradWithCoords(Vec3(-60,0,0));
addNewAniBillBoradWithCoords(Vec3(-100,0,0));
addNewAniBillBoradWithCoords(Vec3(-140,0,0));
addNewAniBillBoradWithCoords(Vec3(-180,0,0));
_camera->setPosition3D(Vec3(0, 100, 230));
_camera->lookAt(Vec3(0,0,0), Vec3(0,1,0));
@ -158,6 +162,8 @@ BillBoardTest::BillBoardTest()
menu->setPosition(Vec2(0,0));
this->addChild(menu, 10);
menuCallback_orientedPoint(nullptr);
schedule(schedule_selector(BillBoardTest::update));
}
void BillBoardTest::menuCallback_orientedPoint(Ref* sender)
@ -183,7 +189,7 @@ BillBoardTest::~BillBoardTest()
}
std::string BillBoardTest::title() const
{
return "Testing BillBoard";
return "BillBoard Test";
}
std::string BillBoardTest::subtitle() const
{
@ -197,8 +203,8 @@ void BillBoardTest::addNewBillBoradWithCoords(Vec3 p)
auto billborad = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1() * 1 + 0.5)]);
billborad->setScale(0.5f);
billborad->setPosition3D(Vec3(p.x, p.y, -150.0f + 30 * i));
billborad->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);
billborad->setOpacity(CCRANDOM_0_1() * 128 + 128);
_layerBillBorad->addChild(billborad);
_billboards.push_back(billborad);
}
@ -207,10 +213,10 @@ void BillBoardTest::addNewAniBillBoradWithCoords(Vec3 p)
{
for (unsigned int i = 0; i < 10; ++i)
{
auto billboradAni = BillBoard::create("Images/grossini.png");
billboradAni->setScale(0.5f);
billboradAni->setPosition3D(Vec3(p.x, p.y, -150.0f + 30 * i));
_layerBillBorad->addChild(billboradAni);
auto billboardAni = BillBoard::create("Images/grossini.png");
billboardAni->setScale(0.5f);
billboardAni->setPosition3D(Vec3(p.x, p.y, -150.0f + 30 * i));
_layerBillBorad->addChild(billboardAni);
auto animation = Animation::create();
for( int i=1;i<15;i++)
@ -224,15 +230,13 @@ void BillBoardTest::addNewAniBillBoradWithCoords(Vec3 p)
animation->setRestoreOriginalFrame(true);
auto action = Animate::create(animation);
billboradAni->runAction(RepeatForever::create(action));
billboradAni->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);
billboradAni->setOpacity(CCRANDOM_0_1() * 128 + 128);
_billboards.push_back(billboradAni);
billboardAni->runAction(RepeatForever::create(action));
billboardAni->setOpacity(CCRANDOM_0_1() * 128 + 128);
_billboards.push_back(billboardAni);
}
}
void BillBoardTest::update(float dt)
{
}
void BillBoardTest::onTouchesMoved(const std::vector<Touch*>& touches, Event* event)
{

View File

@ -24,8 +24,6 @@ THE SOFTWARE.
****************************************************************************/
#include "Camera3DTest.h"
#include <algorithm>
#include "../testResource.h"
enum
{
@ -38,18 +36,18 @@ static int sceneIdx = -1;
static std::function<Layer*()> createFunctions[] =
{
CL(CameraRotationTest),
CL(Camera3DTestDemo),
CL(CameraClippingDemo),
CL(CameraCullingDemo),
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
// 3DEffect use custom shader which is not supported on WP8/WinRT yet.
CL(FogTestDemo),
#endif
CL(CameraArcBallDemo)
};
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
static Layer* nextSpriteTestAction()
static Layer*nextTest()
{
sceneIdx++;
sceneIdx = sceneIdx % MAX_LAYER;
@ -57,7 +55,7 @@ static Layer* nextSpriteTestAction()
return layer;
}
static Layer* backSpriteTestAction()
static Layer*backTest()
{
sceneIdx--;
int total = MAX_LAYER;
@ -68,21 +66,163 @@ static Layer* backSpriteTestAction()
return layer;
}
static Layer* restartSpriteTestAction()
static Layer* restartTest()
{
auto layer = (createFunctions[sceneIdx])();
return layer;
}
void Camera3DTestScene::runThisTest()
{
auto layer = nextTest();
addChild(layer);
Director::getInstance()->replaceScene(this);
}
//------------------------------------------------------------------
//
// SpriteTestDemo
// CameraBaseTest
//
//------------------------------------------------------------------
void CameraBaseTest::restartCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild(restartTest());
Director::getInstance()->replaceScene(s);
s->release();
}
void CameraBaseTest::nextCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild(nextTest());
Director::getInstance()->replaceScene(s);
s->release();
}
void CameraBaseTest::backCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild(backTest());
Director::getInstance()->replaceScene(s);
s->release();
}
//------------------------------------------------------------------
//
// Camera Rotation Test
//
//------------------------------------------------------------------
CameraRotationTest::CameraRotationTest()
{
auto s = Director::getInstance()->getWinSize();
_camControlNode = Node::create();
_camControlNode->setNormalizedPosition(Vec2(.5,.5));
addChild(_camControlNode);
_camNode = Node::create();
_camNode->setPositionZ(Camera::getDefaultCamera()->getPosition3D().z);
_camControlNode->addChild(_camNode);
//Billboards
//Yellow is at the back
bill1 = BillBoard::create("Images/Icon.png");
bill1->setPosition3D(Vec3(s.width/2 + 50, s.height/2 + 10, -10));
bill1->setColor(Color3B::YELLOW);
bill1->setScale(0.6);
addChild(bill1);
l1 = Label::create();
l1->setPosition(Vec2(0,-10));
l1->setString("Billboard1");
l1->setColor(Color3B::WHITE);
l1->setScale(3);
bill1->addChild(l1);
bill2 = BillBoard::create("Images/Icon.png");
bill2->setPosition3D(Vec3(s.width/2 - 50, s.height/2 - 10, 10));
bill2->setScale(0.6);
addChild(bill2);
l2 = Label::create();
l2->setString("Billboard2");
l2->setPosition(Vec2(0,-10));
l2->setColor(Color3B::WHITE);
l2->setScale(3);
bill2->addChild(l2);
//3D models
auto model = Sprite3D::create("Sprite3DTest/boss1.obj");
model->setScale(4);
model->setTexture("Sprite3DTest/boss.png");
model->setPosition3D(Vec3(s.width/2, s.height/2, 0));
addChild(model);
//Listener
_lis = EventListenerTouchOneByOne::create();
_lis->onTouchBegan = [this](Touch* t, Event* e) {
return true;
};
_lis->onTouchMoved = [this](Touch* t, Event* e) {
float dx = t->getDelta().x;
Vec3 rot = _camControlNode->getRotation3D();
rot.y += dx;
_camControlNode->setRotation3D(rot);
Vec3 worldPos;
_camNode->getNodeToWorldTransform().getTranslation(&worldPos);
Camera::getDefaultCamera()->setPosition3D(worldPos);
Camera::getDefaultCamera()->lookAt(_camControlNode->getPosition3D());
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(_lis, this);
schedule(schedule_selector(CameraRotationTest::update));
}
CameraRotationTest::~CameraRotationTest()
{
Director::getInstance()->getEventDispatcher()->removeEventListener(_lis);
}
std::string CameraRotationTest::title() const
{
return "Camera Rotation Test";
}
std::string CameraRotationTest::subtitle() const
{
return "Slide to rotate";
}
void CameraRotationTest::onEnter()
{
BaseTest::onEnter();
}
void CameraRotationTest::onExit()
{
BaseTest::onExit();
}
void CameraRotationTest::update(float dt)
{
}
//------------------------------------------------------------------
//
// Camera3DTestDemo
//
//------------------------------------------------------------------
Camera3DTestDemo::Camera3DTestDemo(void)
: BaseTest()
, _incRot(nullptr)
: _incRot(nullptr)
, _camera(nullptr)
, _decRot(nullptr)
, _bZoomOut(false)
@ -102,13 +242,9 @@ std::string Camera3DTestDemo::title() const
return "Testing Camera";
}
std::string Camera3DTestDemo::subtitle() const
{
return "";
}
void Camera3DTestDemo::scaleCameraCallback(Ref* sender,float value)
{
if(_camera&& _cameraType!=CameraType::FirstCamera)
if(_camera&& _cameraType!=CameraType::FirstPerson)
{
Vec3 cameraPos= _camera->getPosition3D();
cameraPos+= cameraPos.getNormalized()*value;
@ -117,7 +253,7 @@ void Camera3DTestDemo::scaleCameraCallback(Ref* sender,float value)
}
void Camera3DTestDemo::rotateCameraCallback(Ref* sender,float value)
{
if(_cameraType==CameraType::FreeCamera || _cameraType==CameraType::FirstCamera)
if(_cameraType==CameraType::Free || _cameraType==CameraType::FirstPerson)
{
Vec3 rotation3D= _camera->getRotation3D();
rotation3D.y+= value;
@ -131,33 +267,33 @@ void Camera3DTestDemo::SwitchViewCallback(Ref* sender, CameraType cameraType)
return ;
}
_cameraType = cameraType;
if(_cameraType==CameraType::FreeCamera)
if(_cameraType==CameraType::Free)
{
_camera->setPosition3D(Vec3(0, 130, 130) + _sprite3D->getPosition3D());
_camera->lookAt(_sprite3D->getPosition3D(), Vec3(0,1,0));
_camera->lookAt(_sprite3D->getPosition3D());
_RotateRightlabel->setColor(Color3B::WHITE);
_RotateLeftlabel->setColor(Color3B::WHITE);
_ZoomInlabel->setColor(Color3B::WHITE);
_ZoomOutlabel->setColor(Color3B::WHITE);
}
else if(_cameraType==CameraType::FirstCamera)
else if(_cameraType==CameraType::FirstPerson)
{
Vec3 newFaceDir;
_sprite3D->getWorldToNodeTransform().getForwardVector(&newFaceDir);
newFaceDir.normalize();
_camera->setPosition3D(Vec3(0,35,0) + _sprite3D->getPosition3D());
_camera->lookAt(_sprite3D->getPosition3D() + newFaceDir*50, Vec3(0, 1, 0));
_camera->lookAt(_sprite3D->getPosition3D() + newFaceDir*50);
_RotateRightlabel->setColor(Color3B::WHITE);
_RotateLeftlabel->setColor(Color3B::WHITE);
_ZoomInlabel->setColor(Color3B::GRAY);
_ZoomOutlabel->setColor(Color3B::GRAY);
}
else if(_cameraType==CameraType::ThirdCamera)
else if(_cameraType==CameraType::ThirdPerson)
{
_camera->setPosition3D(Vec3(0, 130, 130) + _sprite3D->getPosition3D());
_camera->lookAt(_sprite3D->getPosition3D(), Vec3(0,1,0));
_camera->lookAt(_sprite3D->getPosition3D());
_RotateRightlabel->setColor(Color3B::GRAY);
_RotateLeftlabel->setColor(Color3B::GRAY);
@ -239,11 +375,11 @@ void Camera3DTestDemo::onEnter()
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener4, _RotateRightlabel);
auto label1 = Label::createWithTTF(ttfConfig,"free ");
auto menuItem1 = MenuItemLabel::create(label1, CC_CALLBACK_1(Camera3DTestDemo::SwitchViewCallback,this,CameraType::FreeCamera));
auto menuItem1 = MenuItemLabel::create(label1, CC_CALLBACK_1(Camera3DTestDemo::SwitchViewCallback,this,CameraType::Free));
auto label2 = Label::createWithTTF(ttfConfig,"third person");
auto menuItem2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Camera3DTestDemo::SwitchViewCallback,this,CameraType::ThirdCamera));
auto menuItem2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Camera3DTestDemo::SwitchViewCallback,this,CameraType::ThirdPerson));
auto label3 = Label::createWithTTF(ttfConfig,"first person");
auto menuItem3 = MenuItemLabel::create(label3, CC_CALLBACK_1(Camera3DTestDemo::SwitchViewCallback,this,CameraType::FirstCamera));
auto menuItem3 = MenuItemLabel::create(label3, CC_CALLBACK_1(Camera3DTestDemo::SwitchViewCallback,this,CameraType::FirstPerson));
auto menu = Menu::create(menuItem1, menuItem2, menuItem3, nullptr);
menu->setPosition(Vec2::ZERO);
@ -259,7 +395,7 @@ void Camera3DTestDemo::onEnter()
_camera->setCameraFlag(CameraFlag::USER1);
_layer3D->addChild(_camera);
}
SwitchViewCallback(this,CameraType::ThirdCamera);
SwitchViewCallback(this,CameraType::ThirdPerson);
DrawNode3D* line =DrawNode3D::create();
//draw x
for( int j =-20; j<=20 ;j++)
@ -287,30 +423,6 @@ void Camera3DTestDemo::onExit()
}
}
void Camera3DTestDemo::restartCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild(restartSpriteTestAction());
Director::getInstance()->replaceScene(s);
s->release();
}
void Camera3DTestDemo::nextCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild( nextSpriteTestAction() );
Director::getInstance()->replaceScene(s);
s->release();
}
void Camera3DTestDemo::backCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild( backSpriteTestAction() );
Director::getInstance()->replaceScene(s);
s->release();
}
void Camera3DTestDemo::addNewSpriteWithCoords(Vec3 p,std::string fileName,bool playAnimation,float scale,bool bindCamera)
{
auto sprite = Sprite3D::create(fileName);
@ -348,7 +460,7 @@ void Camera3DTestDemo::onTouchesMoved(const std::vector<Touch*>& touches, cocos2
auto touch = touches[0];
auto location = touch->getLocation();
Point newPos = touch->getPreviousLocation()-location;
if(_cameraType==CameraType::FreeCamera || _cameraType==CameraType::FirstCamera)
if(_cameraType==CameraType::Free || _cameraType==CameraType::FirstPerson)
{
Vec3 cameraDir;
Vec3 cameraRightDir;
@ -362,7 +474,7 @@ void Camera3DTestDemo::onTouchesMoved(const std::vector<Touch*>& touches, cocos2
cameraPos+=cameraDir*newPos.y*0.1f;
cameraPos+=cameraRightDir*newPos.x*0.1f;
_camera->setPosition3D(cameraPos);
if(_sprite3D && _cameraType==CameraType::FirstCamera)
if(_sprite3D && _cameraType==CameraType::FirstPerson)
{
_sprite3D->setPosition3D(Vec3(_camera->getPositionX(),0,_camera->getPositionZ()));
_targetPos=_sprite3D->getPosition3D();
@ -383,7 +495,7 @@ void Camera3DTestDemo::move3D(float elapsedTime)
_sprite3D->setPosition3D(curPos);
offset.x=offset.x;
offset.z=offset.z;
if(_cameraType==CameraType::ThirdCamera)
if(_cameraType==CameraType::ThirdPerson)
{
Vec3 cameraPos= _camera->getPosition3D();
cameraPos.x+=offset.x;
@ -430,7 +542,7 @@ void Camera3DTestDemo::onTouchesEnded(const std::vector<Touch*>& touches, cocos2
auto location = touch->getLocationInView();
if(_camera)
{
if(_sprite3D && _cameraType==CameraType::ThirdCamera && _bZoomOut == false && _bZoomIn == false && _bRotateLeft == false && _bRotateRight == false)
if(_sprite3D && _cameraType==CameraType::ThirdPerson && _bZoomOut == false && _bZoomIn == false && _bRotateLeft == false && _bRotateRight == false)
{
Vec3 nearP(location.x, location.y, -1.0f), farP(location.x, location.y, 1.0f);
@ -467,7 +579,7 @@ void Camera3DTestDemo::updateCamera(float fDelta)
{
if(_sprite3D)
{
if( _cameraType==CameraType::ThirdCamera)
if( _cameraType==CameraType::ThirdPerson)
{
updateState(fDelta);
if(isState(_curState,State_Move))
@ -515,7 +627,7 @@ void Camera3DTestDemo::updateCamera(float fDelta)
{
if(_camera)
{
if(_cameraType == CameraType::ThirdCamera)
if(_cameraType == CameraType::ThirdPerson)
{
Vec3 lookDir = _camera->getPosition3D() - _sprite3D->getPosition3D();
Vec3 cameraPos = _camera->getPosition3D();
@ -525,7 +637,7 @@ void Camera3DTestDemo::updateCamera(float fDelta)
_camera->setPosition3D(cameraPos);
}
}
else if(_cameraType == CameraType::FreeCamera)
else if(_cameraType == CameraType::Free)
{
Vec3 cameraPos = _camera->getPosition3D();
if(cameraPos.length() <= 300)
@ -540,7 +652,7 @@ void Camera3DTestDemo::updateCamera(float fDelta)
{
if(_camera)
{
if(_cameraType == CameraType::ThirdCamera)
if(_cameraType == CameraType::ThirdPerson)
{
Vec3 lookDir = _camera->getPosition3D() - _sprite3D->getPosition3D();
Vec3 cameraPos = _camera->getPosition3D();
@ -550,7 +662,7 @@ void Camera3DTestDemo::updateCamera(float fDelta)
_camera->setPosition3D(cameraPos);
}
}
else if(_cameraType == CameraType::FreeCamera)
else if(_cameraType == CameraType::Free)
{
Vec3 cameraPos = _camera->getPosition3D();
if(cameraPos.length() >= 50)
@ -563,7 +675,7 @@ void Camera3DTestDemo::updateCamera(float fDelta)
}
if(_bRotateLeft == true)
{
if(_cameraType==CameraType::FreeCamera || _cameraType==CameraType::FirstCamera)
if(_cameraType==CameraType::Free || _cameraType==CameraType::FirstPerson)
{
Vec3 rotation3D= _camera->getRotation3D();
rotation3D.y+= 1;
@ -572,7 +684,7 @@ void Camera3DTestDemo::updateCamera(float fDelta)
}
if(_bRotateRight == true)
{
if(_cameraType==CameraType::FreeCamera || _cameraType==CameraType::FirstCamera)
if(_cameraType==CameraType::Free || _cameraType==CameraType::FirstPerson)
{
Vec3 rotation3D= _camera->getRotation3D();
rotation3D.y-= 1;
@ -663,11 +775,10 @@ void Camera3DTestDemo::onTouchesRotateRightEnd(Touch* touch, Event* event)
}
////////////////////////////////////////////////////////////
// CameraClippingDemo
CameraClippingDemo::CameraClippingDemo(void)
: BaseTest()
, _layer3D(nullptr)
, _cameraType(CameraType::FirstCamera)
// CameraCullingDemo
CameraCullingDemo::CameraCullingDemo(void)
: _layer3D(nullptr)
, _cameraType(CameraType::FirstPerson)
, _cameraFirst(nullptr)
, _cameraThird(nullptr)
, _moveAction(nullptr)
@ -676,49 +787,26 @@ CameraClippingDemo::CameraClippingDemo(void)
, _row(3)
{
}
CameraClippingDemo::~CameraClippingDemo(void)
CameraCullingDemo::~CameraCullingDemo(void)
{
}
std::string CameraClippingDemo::title() const
std::string CameraCullingDemo::title() const
{
return "Camera Frustum Clipping";
}
void CameraClippingDemo::restartCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild(restartSpriteTestAction());
Director::getInstance()->replaceScene(s);
s->release();
}
void CameraClippingDemo::nextCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild( nextSpriteTestAction() );
Director::getInstance()->replaceScene(s);
s->release();
}
void CameraClippingDemo::backCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild( backSpriteTestAction() );
Director::getInstance()->replaceScene(s);
s->release();
}
void CameraClippingDemo::onEnter()
void CameraCullingDemo::onEnter()
{
BaseTest::onEnter();
schedule(schedule_selector(CameraClippingDemo::update), 0.0f);
schedule(schedule_selector(CameraCullingDemo::update), 0.0f);
auto s = Director::getInstance()->getWinSize();
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesBegan = CC_CALLBACK_2(CameraClippingDemo::onTouchesBegan, this);
listener->onTouchesMoved = CC_CALLBACK_2(CameraClippingDemo::onTouchesMoved, this);
listener->onTouchesEnded = CC_CALLBACK_2(CameraClippingDemo::onTouchesEnded, this);
listener->onTouchesBegan = CC_CALLBACK_2(CameraCullingDemo::onTouchesBegan, this);
listener->onTouchesMoved = CC_CALLBACK_2(CameraCullingDemo::onTouchesMoved, this);
listener->onTouchesEnded = CC_CALLBACK_2(CameraCullingDemo::onTouchesEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
auto layer3D=Layer::create();
addChild(layer3D,0);
@ -728,7 +816,7 @@ void CameraClippingDemo::onEnter()
MenuItemFont::setFontName("fonts/arial.ttf");
MenuItemFont::setFontSize(20);
auto menuItem1 = MenuItemFont::create("Switch Camera", CC_CALLBACK_1(CameraClippingDemo::switchViewCallback,this));
auto menuItem1 = MenuItemFont::create("Switch Camera", CC_CALLBACK_1(CameraCullingDemo::switchViewCallback,this));
menuItem1->setColor(Color3B(0,200,20));
auto menu = Menu::create(menuItem1,NULL);
menu->setPosition(Vec2::ZERO);
@ -737,9 +825,9 @@ void CameraClippingDemo::onEnter()
// + -
MenuItemFont::setFontSize(40);
auto decrease = MenuItemFont::create(" - ", CC_CALLBACK_1(CameraClippingDemo::delSpriteCallback, this));
auto decrease = MenuItemFont::create(" - ", CC_CALLBACK_1(CameraCullingDemo::delSpriteCallback, this));
decrease->setColor(Color3B(0,200,20));
auto increase = MenuItemFont::create(" + ", CC_CALLBACK_1(CameraClippingDemo::addSpriteCallback, this));
auto increase = MenuItemFont::create(" + ", CC_CALLBACK_1(CameraCullingDemo::addSpriteCallback, this));
increase->setColor(Color3B(0,200,20));
menu = Menu::create(decrease, increase, nullptr);
@ -770,7 +858,7 @@ void CameraClippingDemo::onEnter()
addSpriteCallback(nullptr);
}
void CameraClippingDemo::onExit()
void CameraCullingDemo::onExit()
{
BaseTest::onExit();
if (_cameraFirst)
@ -783,11 +871,11 @@ void CameraClippingDemo::onExit()
}
}
void CameraClippingDemo::update(float dt)
void CameraCullingDemo::update(float dt)
{
_drawAABB->clear();
if(_cameraType == CameraType::ThirdCamera)
if(_cameraType == CameraType::ThirdPerson)
drawCameraFrustum();
Vector<Node*>& children = _layer3D->getChildren();
@ -804,7 +892,7 @@ void CameraClippingDemo::update(float dt)
}
}
void CameraClippingDemo::reachEndCallBack()
void CameraCullingDemo::reachEndCallBack()
{
_cameraFirst->stopActionByTag(100);
auto inverse = (MoveTo*)_moveAction->reverse();
@ -812,12 +900,12 @@ void CameraClippingDemo::reachEndCallBack()
_moveAction->release();
_moveAction = inverse;
auto rot = RotateBy::create(1.f, Vec3(0.f, 180.f, 0.f));
auto seq = Sequence::create(rot, _moveAction, CallFunc::create(CC_CALLBACK_0(CameraClippingDemo::reachEndCallBack, this)), nullptr);
auto seq = Sequence::create(rot, _moveAction, CallFunc::create(CC_CALLBACK_0(CameraCullingDemo::reachEndCallBack, this)), nullptr);
seq->setTag(100);
_cameraFirst->runAction(seq);
}
void CameraClippingDemo::switchViewCallback(Ref* sender)
void CameraCullingDemo::switchViewCallback(Ref* sender)
{
auto s = Director::getInstance()->getWinSize();
@ -826,10 +914,10 @@ void CameraClippingDemo::switchViewCallback(Ref* sender)
_cameraFirst = Camera::createPerspective(30, (GLfloat)s.width/s.height, 10, 200);
_cameraFirst->setCameraFlag(CameraFlag::USER8);
_cameraFirst->setPosition3D(Vec3(-100,0,0));
_cameraFirst->lookAt(Vec3(1000,0,0), Vec3(0, 1, 0));
_cameraFirst->lookAt(Vec3(1000,0,0));
_moveAction = MoveTo::create(4.f, Vec2(100, 0));
_moveAction->retain();
auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(CameraClippingDemo::reachEndCallBack, this)), nullptr);
auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(CameraCullingDemo::reachEndCallBack, this)), nullptr);
seq->setTag(100);
_cameraFirst->runAction(seq);
addChild(_cameraFirst);
@ -840,20 +928,20 @@ void CameraClippingDemo::switchViewCallback(Ref* sender)
_cameraThird = Camera::createPerspective(60, (GLfloat)s.width/s.height, 1, 1000);
_cameraThird->setCameraFlag(CameraFlag::USER8);
_cameraThird->setPosition3D(Vec3(0, 130, 130));
_cameraThird->lookAt(Vec3(0,0,0), Vec3(0, 1, 0));
_cameraThird->lookAt(Vec3(0,0,0));
addChild(_cameraThird);
}
if(_cameraType == CameraType::FirstCamera)
if(_cameraType == CameraType::FirstPerson)
{
_cameraType = CameraType::ThirdCamera;
_cameraType = CameraType::ThirdPerson;
_cameraThird->setCameraFlag(CameraFlag::USER1);
_cameraThird->enableFrustumCulling(false, false);
_cameraFirst->setCameraFlag(CameraFlag::USER8);
}
else if(_cameraType == CameraType::ThirdCamera)
else if(_cameraType == CameraType::ThirdPerson)
{
_cameraType = CameraType::FirstCamera;
_cameraType = CameraType::FirstPerson;
_cameraFirst->setCameraFlag(CameraFlag::USER1);
_cameraFirst->enableFrustumCulling(true, true);
_cameraThird->setCameraFlag(CameraFlag::USER8);
@ -861,7 +949,7 @@ void CameraClippingDemo::switchViewCallback(Ref* sender)
}
}
void CameraClippingDemo::addSpriteCallback(Ref* sender)
void CameraCullingDemo::addSpriteCallback(Ref* sender)
{
_layer3D->removeAllChildren();
_objects.clear();
@ -889,7 +977,7 @@ void CameraClippingDemo::addSpriteCallback(Ref* sender)
_labelSprite3DCount->setString(szText);
}
void CameraClippingDemo::delSpriteCallback(Ref* sender)
void CameraCullingDemo::delSpriteCallback(Ref* sender)
{
if (_row == 0) return;
@ -917,7 +1005,7 @@ void CameraClippingDemo::delSpriteCallback(Ref* sender)
_labelSprite3DCount->setString(szText);
}
void CameraClippingDemo::drawCameraFrustum()
void CameraCullingDemo::drawCameraFrustum()
{
_drawFrustum->clear();
auto size = Director::getInstance()->getWinSize();
@ -971,9 +1059,9 @@ void CameraClippingDemo::drawCameraFrustum()
////////////////////////////////////////////////////////////
// CameraArcBallDemo
CameraArcBallDemo::CameraArcBallDemo(void)
: BaseTest()
: CameraBaseTest()
, _layer3D(nullptr)
, _cameraType(CameraType::FreeCamera)
, _cameraType(CameraType::Free)
, _camera(nullptr)
,_drawGrid(nullptr)
,_sprite3D1(nullptr)
@ -994,31 +1082,6 @@ std::string CameraArcBallDemo::title() const
return "Camera ArcBall Moving";
}
void CameraArcBallDemo::restartCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild(restartSpriteTestAction());
Director::getInstance()->replaceScene(s);
s->release();
}
void CameraArcBallDemo::nextCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild( nextSpriteTestAction() );
Director::getInstance()->replaceScene(s);
s->release();
}
void CameraArcBallDemo::backCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild( backSpriteTestAction() );
Director::getInstance()->replaceScene(s);
s->release();
}
void CameraArcBallDemo::onEnter()
{
BaseTest::onEnter();
@ -1219,9 +1282,9 @@ void CameraArcBallDemo::update(float dt)
////////////////////////////////////////////////////////////
// FogTestDemo
FogTestDemo::FogTestDemo(void)
: BaseTest()
: CameraBaseTest()
, _layer3D(nullptr)
, _cameraType(CameraType::FreeCamera)
, _cameraType(CameraType::Free)
, _camera(nullptr)
, _shader(nullptr)
, _state(nullptr)
@ -1236,31 +1299,6 @@ std::string FogTestDemo::title() const
return "Fog Test Demo";
}
void FogTestDemo::restartCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild(restartSpriteTestAction());
Director::getInstance()->replaceScene(s);
s->release();
}
void FogTestDemo::nextCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild( nextSpriteTestAction() );
Director::getInstance()->replaceScene(s);
s->release();
}
void FogTestDemo::backCallback(Ref* sender)
{
auto s = new (std::nothrow) Camera3DTestScene();
s->addChild( backSpriteTestAction() );
Director::getInstance()->replaceScene(s);
s->release();
}
void FogTestDemo::onEnter()
{
BaseTest::onEnter();
@ -1436,7 +1474,7 @@ void FogTestDemo::onTouchesMoved(const std::vector<Touch*>& touches, cocos2d::Ev
Vec2 prelocation = touches[0]->getPreviousLocationInView();
Vec2 location = touches[0]->getLocationInView();
Vec2 newPos = prelocation - location;
if(_cameraType==CameraType::FreeCamera)
if(_cameraType==CameraType::Free)
{
Vec3 cameraDir;
Vec3 cameraRightDir;
@ -1453,10 +1491,3 @@ void FogTestDemo::onTouchesMoved(const std::vector<Touch*>& touches, cocos2d::Ev
}
}
}
void Camera3DTestScene::runThisTest()
{
auto layer = nextSpriteTestAction();
addChild(layer);
Director::getInstance()->replaceScene(this);
}

View File

@ -48,9 +48,9 @@ enum State
};
enum class CameraType
{
FreeCamera=0,
FirstCamera=1,
ThirdCamera=2,
Free = 0,
FirstPerson = 1,
ThirdPerson = 2,
};
enum class OperateCamType
@ -59,21 +59,60 @@ enum class OperateCamType
RotateCamera=1,
};
class Camera3DTestDemo : public BaseTest
class Camera3DTestScene : public TestScene
{
public:
virtual void runThisTest();
};
class CameraBaseTest : public BaseTest
{
public:
void restartCallback(Ref* sender);
void nextCallback(Ref* sender);
void backCallback(Ref* sender);
protected:
BillBoard* bill1;
BillBoard* bill2;
Label* l1;
Label* l2;
};
class CameraRotationTest : public CameraBaseTest {
public:
CREATE_FUNC(CameraRotationTest);
CameraRotationTest(void);
virtual ~CameraRotationTest(void);
virtual void onEnter() override;
virtual void onExit() override;
virtual void update(float dt) override;
// overrides
virtual std::string title() const override;
virtual std::string subtitle() const override;
protected:
Node* _camControlNode;
Node* _camNode;
EventListenerTouchOneByOne* _lis;
};
class Camera3DTestDemo : public CameraBaseTest
{
public:
CREATE_FUNC(Camera3DTestDemo);
Camera3DTestDemo(void);
virtual ~Camera3DTestDemo(void);
void restartCallback(Ref* sender);
void nextCallback(Ref* sender);
void backCallback(Ref* sender);
virtual void onEnter() override;
virtual void onExit() override;
// overrides
virtual std::string title() const override;
virtual std::string subtitle() const override;
void addNewSpriteWithCoords(Vec3 p,std::string fileName,bool playAnimation=false,float scale=1.0f,bool bindCamera=false);
void onTouchesBegan(const std::vector<Touch*>& touches, cocos2d::Event *event);
void onTouchesMoved(const std::vector<Touch*>& touches, cocos2d::Event *event);
@ -117,16 +156,12 @@ protected:
Label* _ZoomOutlabel;
};
class CameraClippingDemo : public BaseTest
class CameraCullingDemo : public CameraBaseTest
{
public:
CREATE_FUNC(CameraClippingDemo);
CameraClippingDemo(void);
virtual ~CameraClippingDemo(void);
void restartCallback(Ref* sender);
void nextCallback(Ref* sender);
void backCallback(Ref* sender);
CREATE_FUNC(CameraCullingDemo);
CameraCullingDemo(void);
virtual ~CameraCullingDemo(void);
virtual void onEnter() override;
virtual void onExit() override;
@ -155,17 +190,13 @@ protected:
int _row;
};
class CameraArcBallDemo : public BaseTest
class CameraArcBallDemo : public CameraBaseTest
{
public:
CREATE_FUNC(CameraArcBallDemo);
CameraArcBallDemo(void);
virtual ~CameraArcBallDemo(void);
void restartCallback(Ref* sender);
void nextCallback(Ref* sender);
void backCallback(Ref* sender);
virtual void onEnter() override;
virtual void onExit() override;
@ -196,17 +227,13 @@ protected:
Sprite3D* _sprite3D2;
};
class FogTestDemo : public BaseTest
class FogTestDemo : public CameraBaseTest
{
public:
CREATE_FUNC(FogTestDemo);
FogTestDemo(void);
virtual ~FogTestDemo(void);
void restartCallback(Ref* sender);
void nextCallback(Ref* sender);
void backCallback(Ref* sender);
virtual void onEnter() override;
virtual void onExit() override;
@ -233,9 +260,5 @@ protected:
#endif
};
class Camera3DTestScene : public TestScene
{
public:
virtual void runThisTest();
};
#endif

View File

@ -68,7 +68,8 @@ static std::function<Layer*()> createFunctions[] =
CL(Sprite3DReskinTest),
CL(Sprite3DWithOBBPerfromanceTest),
CL(Sprite3DMirrorTest),
CL(QuaternionTest)
CL(QuaternionTest),
CL(Sprite3DEmptyTest)
};
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
@ -154,6 +155,30 @@ void Sprite3DTestDemo::backCallback(Ref* sender)
s->release();
}
//------------------------------------------------------------------
//
// Sprite3DEmptyTest
//
//------------------------------------------------------------------
Sprite3DEmptyTest::Sprite3DEmptyTest()
{
auto s = Sprite3D::create();
s->setNormalizedPosition(Vec2(.5,.5));
auto l = Label::create();
l->setString("Test");
s->addChild(l);
addChild(s);
}
std::string Sprite3DEmptyTest::title() const
{
return "Testing Sprite3D Container";
}
std::string Sprite3DEmptyTest::subtitle() const
{
return "Sprite3D can act as containers for 2D objects";
}
//------------------------------------------------------------------
//

View File

@ -54,6 +54,15 @@ public:
virtual void onEnter() override;
};
class Sprite3DEmptyTest : public Sprite3DTestDemo
{
public:
CREATE_FUNC(Sprite3DEmptyTest);
Sprite3DEmptyTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class Sprite3DBasicTest : public Sprite3DTestDemo
{
public: