From 584ccf65e4fc7962a844fc1f256bec8ea76ce56e Mon Sep 17 00:00:00 2001 From: Ricardo Quesada Date: Mon, 14 Apr 2014 16:46:19 -0700 Subject: [PATCH 1/2] Culling working again --- cocos/2d/CCSprite.cpp | 39 +-------------- cocos/2d/CCSprite.h | 5 -- cocos/2d/renderer/CCRenderer.cpp | 49 +++++++++++++++++-- cocos/2d/renderer/CCRenderer.h | 5 +- cocos/math/kazmath/kazmath/kazmath.h | 1 + cocos/math/kazmath/kazmath/vec4.c | 5 ++ .../NewRendererTest/NewRendererTest.cpp | 4 +- 7 files changed, 57 insertions(+), 51 deletions(-) diff --git a/cocos/2d/CCSprite.cpp b/cocos/2d/CCSprite.cpp index 7a0748890b..811895651f 100644 --- a/cocos/2d/CCSprite.cpp +++ b/cocos/2d/CCSprite.cpp @@ -276,7 +276,6 @@ Sprite::Sprite(void) : _shouldBeHidden(false) , _texture(nullptr) , _insideBounds(true) -, _cullingEnabled(false) { } @@ -590,7 +589,7 @@ void Sprite::updateTransform(void) void Sprite::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) { // Don't do calculate the culling if the transform was not updated - _insideBounds = transformUpdated ? isInsideBounds() : _insideBounds; + _insideBounds = transformUpdated ? renderer->checkVisibility(transform, _contentSize) : _insideBounds; if(_insideBounds) { @@ -622,42 +621,6 @@ void Sprite::drawDebugData() } #endif //CC_SPRITE_DEBUG_DRAW -void Sprite::setCullingEnabled(bool enabled) -{ - _cullingEnabled = enabled; -} - -// Culling function from cocos2d-iphone CCSprite.m file -bool Sprite::isInsideBounds() const -{ - if(!_cullingEnabled) return true; - - // half size of the screen - Size screen_half = Director::getInstance()->getWinSize(); - screen_half.width /= 2; - screen_half.height /= 2; - - float hcsx = _contentSize.width / 2; - float hcsy = _contentSize.height / 2; - - // convert to world coordinates - float x = hcsx * _modelViewTransform.mat[0] + hcsy * _modelViewTransform.mat[4] + _modelViewTransform.mat[12]; - float y = hcsx * _modelViewTransform.mat[1] + hcsy * _modelViewTransform.mat[5] + _modelViewTransform.mat[13]; - - // center of screen is (0,0) - x -= screen_half.width; - y -= screen_half.height; - - // convert content size to world coordinates - float wchw = hcsx * std::max(fabsf(_modelViewTransform.mat[0] + _modelViewTransform.mat[4]), fabsf(_modelViewTransform.mat[0] - _modelViewTransform.mat[4])); - float wchh = hcsy * std::max(fabsf(_modelViewTransform.mat[1] + _modelViewTransform.mat[5]), fabsf(_modelViewTransform.mat[1] - _modelViewTransform.mat[5])); - - // compare if it in the positive quadrant of the screen - float tmpx = (fabsf(x)-wchw); - float tmpy = (fabsf(y)-wchh); - return (tmpx < screen_half.width && tmpy < screen_half.height); -} - // Node overrides void Sprite::addChild(Node *child, int zOrder, int tag) { diff --git a/cocos/2d/CCSprite.h b/cocos/2d/CCSprite.h index 229903ef9c..27e011ccf3 100644 --- a/cocos/2d/CCSprite.h +++ b/cocos/2d/CCSprite.h @@ -426,8 +426,6 @@ public: virtual void setOpacityModifyRGB(bool modify) override; virtual bool isOpacityModifyRGB(void) const override; /// @} - //set culling enabled - void setCullingEnabled(bool enabled); CC_CONSTRUCTOR_ACCESS: @@ -529,8 +527,6 @@ protected: virtual void setReorderChildDirtyRecursively(void); virtual void setDirtyRecursively(bool bValue); - bool isInsideBounds() const; - // // Data used when the sprite is rendered using a SpriteSheet // @@ -576,7 +572,6 @@ protected: bool _flippedY; /// Whether the sprite is flipped vertically or not bool _insideBounds; /// whether or not the sprite was inside bounds the previous frame - bool _cullingEnabled; private: CC_DISALLOW_COPY_AND_ASSIGN(Sprite); }; diff --git a/cocos/2d/renderer/CCRenderer.cpp b/cocos/2d/renderer/CCRenderer.cpp index 21cd19f1d7..43e22b4b47 100644 --- a/cocos/2d/renderer/CCRenderer.cpp +++ b/cocos/2d/renderer/CCRenderer.cpp @@ -23,6 +23,9 @@ ****************************************************************************/ #include "renderer/CCRenderer.h" + +#include + #include "renderer/CCQuadCommand.h" #include "renderer/CCBatchCommand.h" #include "renderer/CCCustomCommand.h" @@ -34,15 +37,19 @@ #include "CCEventDispatcher.h" #include "CCEventListenerCustom.h" #include "CCEventType.h" -#include + +#include "kazmath/kazmath.h" NS_CC_BEGIN +// helper bool compareRenderCommand(RenderCommand* a, RenderCommand* b) { return a->getGlobalOrder() < b->getGlobalOrder(); } +// queue + void RenderQueue::push_back(RenderCommand* command) { float z = command->getGlobalOrder(); @@ -92,12 +99,14 @@ void RenderQueue::clear() _queuePosZ.clear(); } +// +// +// +static const int DEFAULT_RENDER_QUEUE = 0; // +// constructors, destructors, init // -// -#define DEFAULT_RENDER_QUEUE 0 - Renderer::Renderer() :_lastMaterialID(0) ,_numQuads(0) @@ -497,4 +506,36 @@ void Renderer::flush() _lastMaterialID = 0; } +// helpers + +bool Renderer::checkVisibility(const kmMat4 &transform, const Size &size) +{ + // half size of the screen + Size screen_half = Director::getInstance()->getWinSize(); + screen_half.width /= 2; + screen_half.height /= 2; + + float hSizeX = size.width/2; + float hSizeY = size.height/2; + + kmVec4 v4world; + kmVec4 v4local = (kmVec4) {hSizeX, hSizeY, 0, 1}; + kmVec4MultiplyMat4(&v4world, &v4local, &transform); + + // center of screen is (0,0) + v4world.x -= screen_half.width; + v4world.y -= screen_half.height; + + // convert content size to world coordinates + float wshw = std::max(fabsf(hSizeX * transform.mat[0] + hSizeY * transform.mat[4]), fabsf(hSizeX * transform.mat[0] - hSizeY * transform.mat[4])); + float wshh = std::max(fabsf(hSizeX * transform.mat[1] + hSizeY * transform.mat[5]), fabsf(hSizeX * transform.mat[1] - hSizeY * transform.mat[5])); + + // compare if it in the positive quadrant of the screen + float tmpx = (fabsf(v4world.x)-wshw); + float tmpy = (fabsf(v4world.y)-wshh); + bool ret = (tmpx < screen_half.width && tmpy < screen_half.height); + + return ret; +} + NS_CC_END diff --git a/cocos/2d/renderer/CCRenderer.h b/cocos/2d/renderer/CCRenderer.h index b204d9ef9c..472b8cbe87 100644 --- a/cocos/2d/renderer/CCRenderer.h +++ b/cocos/2d/renderer/CCRenderer.h @@ -113,7 +113,10 @@ public: void addDrawnVertices(ssize_t number) { _drawnVertices += number; }; inline GroupCommandManager* getGroupCommandManager() const { return _groupCommandManager; }; - + + /** returns whether or not a rectangle is visible or not */ + bool checkVisibility(const kmMat4& transform, const Size& size); + protected: void setupIndices(); diff --git a/cocos/math/kazmath/kazmath/kazmath.h b/cocos/math/kazmath/kazmath/kazmath.h index 3e1063d445..a25feaa0d7 100644 --- a/cocos/math/kazmath/kazmath/kazmath.h +++ b/cocos/math/kazmath/kazmath/kazmath.h @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vec2.h" #include "vec3.h" +#include "vec4.h" #include "mat3.h" #include "mat4.h" #include "utility.h" diff --git a/cocos/math/kazmath/kazmath/vec4.c b/cocos/math/kazmath/kazmath/vec4.c index 2efc88cb78..13a187466b 100644 --- a/cocos/math/kazmath/kazmath/vec4.c +++ b/cocos/math/kazmath/kazmath/vec4.c @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vec4.h" #include "mat4.h" +#include "neon_matrix_impl.h" kmVec4* kmVec4Fill(kmVec4* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w) { @@ -137,10 +138,14 @@ kmVec4* kmVec4Div( kmVec4* pOut,const kmVec4* pV1, const kmVec4* pV2 ) { /// Multiplies a 4D vector by a matrix, the result is stored in pOut, and pOut is returned. kmVec4* kmVec4MultiplyMat4(kmVec4* pOut, const kmVec4* pV, const struct kmMat4* pM) { +#if defined(__ARM_NEON__) && !defined(__arm64__) + NEON_Matrix4Vector4Mul(&pM->mat[0], (const float*)pV, (float*)pOut); +#else pOut->x = pV->x * pM->mat[0] + pV->y * pM->mat[4] + pV->z * pM->mat[8] + pV->w * pM->mat[12]; pOut->y = pV->x * pM->mat[1] + pV->y * pM->mat[5] + pV->z * pM->mat[9] + pV->w * pM->mat[13]; pOut->z = pV->x * pM->mat[2] + pV->y * pM->mat[6] + pV->z * pM->mat[10] + pV->w * pM->mat[14]; pOut->w = pV->x * pM->mat[3] + pV->y * pM->mat[7] + pV->z * pM->mat[11] + pV->w * pM->mat[15]; +#endif return pOut; } diff --git a/tests/cpp-tests/Classes/NewRendererTest/NewRendererTest.cpp b/tests/cpp-tests/Classes/NewRendererTest/NewRendererTest.cpp index 312100f39d..3e7f763135 100644 --- a/tests/cpp-tests/Classes/NewRendererTest/NewRendererTest.cpp +++ b/tests/cpp-tests/Classes/NewRendererTest/NewRendererTest.cpp @@ -474,9 +474,8 @@ NewCullingTest::NewCullingTest() { Size size = Director::getInstance()->getWinSize(); auto sprite = Sprite::create("Images/btn-about-normal-vertical.png"); - sprite->setRotation(-85); + sprite->setRotation(5); sprite->setPosition(Point(size.width/2,size.height/3)); - sprite->setCullingEnabled(true); sprite->setScale(2); addChild(sprite); @@ -484,7 +483,6 @@ NewCullingTest::NewCullingTest() sprite2->setRotation(-85); sprite2->setPosition(Point(size.width/2,size.height * 2/3)); sprite2->setScale(2); - sprite2->setCullingEnabled(false); addChild(sprite2); auto listener = EventListenerTouchOneByOne::create(); From 3978cee2ee067213ae0c794b896f34e5c05abc4d Mon Sep 17 00:00:00 2001 From: Ricardo Quesada Date: Mon, 14 Apr 2014 20:00:06 -0700 Subject: [PATCH 2/2] compiles on windows --- cocos/2d/renderer/CCRenderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos/2d/renderer/CCRenderer.cpp b/cocos/2d/renderer/CCRenderer.cpp index 43e22b4b47..0a54dcbd72 100644 --- a/cocos/2d/renderer/CCRenderer.cpp +++ b/cocos/2d/renderer/CCRenderer.cpp @@ -518,8 +518,8 @@ bool Renderer::checkVisibility(const kmMat4 &transform, const Size &size) float hSizeX = size.width/2; float hSizeY = size.height/2; - kmVec4 v4world; - kmVec4 v4local = (kmVec4) {hSizeX, hSizeY, 0, 1}; + kmVec4 v4world, v4local; + kmVec4Fill(&v4local, hSizeX, hSizeY, 0, 1); kmVec4MultiplyMat4(&v4world, &v4local, &transform); // center of screen is (0,0)