Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera fails to show sprites outside visible size #10487

Closed
Tiger-Coding opened this issue Feb 12, 2015 · 6 comments · Fixed by #13105
Closed

Camera fails to show sprites outside visible size #10487

Tiger-Coding opened this issue Feb 12, 2015 · 6 comments · Fixed by #13105
Assignees
Milestone

Comments

@Tiger-Coding
Copy link

From the forum:
http://discuss.cocos2d-x.org/t/camera-bug-when-moving/19904/2

Using 3.4 final, I create a bunch of sprites, then position them one by one to the right. I move the camera to the right, and everything off the screen is hidden. However, if I move the layer to the left, I can see the sprites.

Code from forum post:

The init of HelloWorld:

auto spritebatch = SpriteBatchNode::create("MySprites.png");
addChild(spritebatch);
auto spriteCache = SpriteFrameCache::getInstance();
spriteCache->addSpriteFramesWithFile("MySprites.plist");

Then I create the sprites and add them to the layer, each one positioned to the right of the previous sprite.

for (int i = 0; i < 100; i++) {
    auto sprite = Sprite::createWithSpriteFrameName("MySprite.png");
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x + (visibleSize.width * i), visibleSize.height/2 + origin.y));
    this->addChild(sprite);
}

In the onEnter:

void HelloWorld::onEnter()
{
Layer::onEnter();
Size visibleSize = Director::getInstance()->getVisibleSize();
Camera *camera = Director::getInstance()->getRunningScene()->getCameras().front();
auto move = MoveBy::create(35.0, Vec3(10 * visibleSize.width, 0, 0));
camera->runAction(move);
}

Related?
#10275

@marianopixowl
Copy link

I've experienced this issue too in cocos2d-x 3.4. It seems as if culling is not taking into account the camera movement, but only the original screen bounds. (Looking at Renderer::checkVisibility() seems to confirm this. I can't see the camera being used in the visibility calculations).

For the time being, I'm setting #define CC_USE_CULLING 0 as a workaround. (Which by the way, creates a compilation error in Label::draw() since the code references a local variable only defined within the #if CC_USE_CULLING ... #endif block).

@zeyangl
Copy link

zeyangl commented Jun 4, 2015

confirm issue exists in 3.6...

@fusijie
Copy link
Contributor

fusijie commented Jun 29, 2015

I have added a test case to reproduce this bug.

Renderer->Auto-culling is affected by transform and view matrix. Now the implementation ignore the view matrix dirty so lead to this bug.

The checkVisibility method is fixed here by @yangws ?

But draw method still not check view matrix dirty. Let's discuss this issue here. @yangws @dabingnn @super626

@Cybertwip
Copy link

This happens also when drawing a FastTMXTiledMap and its TMXLayer objects.

This seems to partially solve the camera cull for TMX Layers:

void TMXLayer::draw(Renderer *renderer, const Mat4& transform, uint32_t flags)
{
    _quadsDirty = true;

    updateTotalQuads();

//    if( flags != 0 || _dirty || _quadsDirty )
//    {
//        Size s = Director::getInstance()->getWinSize();
//        auto rect = Rect(0, 0, s.width, s.height);

        auto director = Director::getInstance();

        Rect visibleRect(Camera::getVisitingCamera()->getPositionX() - director->getVisibleSize().width * 0.5, 
                         Camera::getVisitingCamera()->getPositionY() - director->getVisibleSize().height * 0.5,
                         director->getVisibleSize().width, 
                         director->getVisibleSize().height);

        Mat4 inv = transform;
        inv.inverse();
        visibleRect = RectApplyTransform(visibleRect, inv);

        updateTiles(visibleRect);
        updateIndexBuffer();
        updatePrimitives();
        _dirty = false;
//    }

    if(_renderCommands.size() < static_cast<size_t>(_primitives.size()))
    {
        _renderCommands.resize(_primitives.size());
    }

    int index = 0;
    for(const auto& iter : _primitives)
    {
        if(iter.second->getCount() > 0)
        {
            auto& cmd = _renderCommands[index++];
            cmd.init(iter.first, _texture->getName(), getGLProgramState(), BlendFunc::ALPHA_NON_PREMULTIPLIED, iter.second, _modelViewTransform, flags);
            renderer->addCommand(&cmd);
        }
    }
}

@fusijie
Copy link
Contributor

fusijie commented Jul 29, 2015

Here is auto-culling's performance test.
peformancetest1

Result:

  • All inside of screen
    • Enable or disable auto-culling have almost the same performance.
    • But if not check dirty, will cause perfermance loss in Android (-20%).
  • All outside of screen
    • Enable auto-culling is much better than disable it.(iOS 105%, Android 15%)
  • Half inside of screen and half outside of screen
    • Enable auto-culling is much better than disable it.(iOS 26%, Android 18%)

Conclusion:

  • Keep enable auto-culling.
  • As far as possible, enable check transform dirty.
  • For fix this issue:
    • Enable check dirty for default camera to ensure 2d performance.
    • Disable check dirty for other cameras.

Remaining issue:

  • Performance test.
  • To keep trace with all cameras' viewMatrix changing.

@fusijie
Copy link
Contributor

fusijie commented Jul 30, 2015

According to the performance test, fixed in #13105.
New2 Code -> #13105.
peformancetest2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants