axmol/cocos/2d/renderer/CCNewSprite.cpp

144 lines
3.7 KiB
C++

//
// CCNewSprite.cpp
// cocos2d_libs
//
// Created by NiTe Luo on 10/31/13.
//
//
#include "CCNewSprite.h"
#include "RenderCommand.h"
#include "Renderer.h"
#include "QuadCommand.h"
#include "CCMenuItem.h"
#include "Frustum.h"
#include "CCDirector.h"
NS_CC_BEGIN
#if CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
#define RENDER_IN_SUBPIXEL
#else
#define RENDER_IN_SUBPIXEL(__ARGS__) (ceil(__ARGS__))
#endif
NewSprite* NewSprite::create()
{
NewSprite* sprite = new NewSprite();
if(sprite && sprite->init())
{
sprite->autorelease();
return sprite;
}
CC_SAFE_DELETE(sprite);
return NULL;
}
NewSprite* NewSprite::create(const char *filename)
{
NewSprite* sprite = new NewSprite();
if(sprite && sprite->initWithFile(filename))
{
sprite->autorelease();
return sprite;
}
CC_SAFE_DELETE(sprite);
return NULL;
}
NewSprite::NewSprite()
:Sprite()
{
}
NewSprite::~NewSprite(void)
{
}
bool NewSprite::initWithTexture(Texture2D *texture, const Rect &rect, bool rotated)
{
bool result = Sprite::initWithTexture(texture, rect, rotated);
_recursiveDirty = true;
setDirty(true);
return result;
}
void NewSprite::updateQuadVertices()
{
#ifdef CC_USE_PHYSICS
updatePhysicsTransform();
setDirty(true);
#endif
//TODO optimize the performance cache affineTransformation
// recalculate matrix only if it is dirty
if(isDirty())
{
// if( ! _parent || _parent == (Node*)_batchNode )
// {
// _transformToBatch = getNodeToParentTransform();
// }
// else
// {
// CCASSERT( dynamic_cast<NewSprite*>(_parent), "Logic error in Sprite. Parent must be a Sprite");
// _transformToBatch = AffineTransformConcat( getNodeToParentTransform() , static_cast<NewSprite*>(_parent)->_transformToBatch );
// }
//TODO optimize this transformation, should use parent's transformation instead
_transformToBatch = getNodeToWorldTransform();
//
// calculate the Quad based on the Affine Matrix
//
Rect newRect = RectApplyAffineTransform(_rect, _transformToBatch);
_quad.bl.vertices = Vertex3F( RENDER_IN_SUBPIXEL(newRect.getMinX()), RENDER_IN_SUBPIXEL(newRect.getMinY()), _vertexZ );
_quad.br.vertices = Vertex3F( RENDER_IN_SUBPIXEL(newRect.getMaxX()), RENDER_IN_SUBPIXEL(newRect.getMinY()), _vertexZ );
_quad.tl.vertices = Vertex3F( RENDER_IN_SUBPIXEL(newRect.getMinX()), RENDER_IN_SUBPIXEL(newRect.getMaxY()), _vertexZ );
_quad.tr.vertices = Vertex3F( RENDER_IN_SUBPIXEL(newRect.getMaxX()), RENDER_IN_SUBPIXEL(newRect.getMaxY()), _vertexZ );
_recursiveDirty = false;
setDirty(false);
}
}
void NewSprite::draw(void)
{
updateQuadVertices();
if(!culling())
{
return;
}
//TODO implement z order
QuadCommand* renderCommand = QuadCommand::getCommandPool().generateCommand();
renderCommand->init(0, _vertexZ, _texture->getName(), _shaderProgram, _blendFunc, &_quad, 1);
Renderer::getInstance()->addCommand(renderCommand);
}
bool NewSprite::culling() const
{
Frustum* frustum = Director::getInstance()->getFrustum();
AffineTransform worldTM = getNodeToWorldTransform();
//generate aabb
kmVec3 point = {_quad.bl.vertices.x, _quad.bl.vertices.y, _vertexZ};
AABB aabb(point,point);
point = {_quad.br.vertices.x, _quad.br.vertices.y, _vertexZ};
aabb.expand(point);
point = {_quad.tl.vertices.x, _quad.tl.vertices.y, _vertexZ};
aabb.expand(point);
point = {_quad.tr.vertices.x, _quad.tr.vertices.y, _vertexZ};
aabb.expand(point);
return Frustum::IntersectResult::OUTSIDE !=frustum->intersectAABB(aabb);
}
NS_CC_END