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

Problems with scene graph and debug renderer #79

Closed
wivlaro opened this Issue Dec 22, 2014 · 5 comments

Comments

@wivlaro
Contributor

wivlaro commented Dec 22, 2014

I've been trying to figure out a problem with the scene graph I've been having whereby I get complaints about the rotation 3x3 part of child objects' transformation matrix not being evenly scaled. I have tried to make a simple program that uses parenting, but I'm having trouble displaying anything at all.

Now I have tried to use the debug renderers as documented here http://mosra.cz/blog/magnum-doc/debug-tools.html#debug-tools-renderers but there are some problems with the resource manager not being correctly initialized.

For this example, I have the dreaded blank screen anyway, the simpledraw functions are just trying to make SOMETHING appear.

If anyone can shed any light on either the resource manager problem, or why the scene graph doesn't seem to be combining matrices properly, it would be appreciated.

Complete code (stack trace below):

#include <vector>
#include <iostream>
#include <memory>

#include <Magnum/DefaultFramebuffer.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/SceneGraph/Scene.h>
#include <Magnum/SceneGraph/MatrixTransformation3D.h>
#include <Magnum/SceneGraph/AbstractCamera.h>
#include <Magnum/SceneGraph/Camera3D.h>
#include <Magnum/SceneGraph/Drawable.h>
#include <Magnum/Buffer.h>
#include <Magnum/Math/Matrix4.h>
#include <Magnum/Shaders/VertexColor.h>
#include <Magnum/Mesh.h>
#include <Magnum/DebugTools/ResourceManager.h>
#include <Magnum/DebugTools/ObjectRenderer.h>
#include <Magnum/Renderer.h>
#include <Corrade/PluginManager/AbstractManager.h>

using namespace Magnum;

typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D;
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D;

class MyObject3D;

class MyApplication: public Platform::Application {
    public:
        explicit MyApplication(const Arguments& arguments);

    private:
        void drawEvent() override;
        void mouseMoveEvent(MouseMoveEvent& event) override;

        Scene3D scene;
        Object3D* cameraObject;
        SceneGraph::Camera3D* camera;
        SceneGraph::DrawableGroup3D drawables;

        MyObject3D* obj;
        MyObject3D* obj2;

        // Global instance of debug resource manager, drawable group for the renderers
        DebugTools::ResourceManager manager;
        SceneGraph::DrawableGroup3D debugDrawables;
};

class MyObject3D : public Object3D, SceneGraph::Drawable3D {
public:
    MyObject3D(const std::vector<Vector3>& data, Object3D* parent, SceneGraph::DrawableGroup3D* drawables)
    :   Object3D(parent)
    ,   SceneGraph::Drawable3D(*this, drawables)
    {
        _buffer.setData(data, BufferUsage::StaticDraw);
        _mesh.setPrimitive(MeshPrimitive::Triangles)
            .setCount(data.size() / 2)
            .addVertexBuffer(_buffer, 0, Shaders::VertexColor3D::Position{}, Shaders::VertexColor3D::Color{});
    }
    void simpledraw() {
        _mesh.draw(_shader);
    }

private:
    void draw(const Matrix4& transformationMatrix, SceneGraph::AbstractCamera3D& camera) override {
        _shader.setTransformationProjectionMatrix(transformationMatrix);
        _mesh.draw(_shader);
    }
    Buffer _buffer;
    Mesh _mesh;
    Shaders::VertexColor3D _shader;
};


MyApplication::MyApplication(const Arguments& arguments): Platform::Application(arguments) {
    CORRADE_RESOURCE_INITIALIZE(MagnumShaders_RCS);
    /* Configure camera */
    cameraObject = new Object3D(&scene);
    cameraObject->translate(Vector3::zAxis(5.0f));
    camera = new SceneGraph::Camera3D(*cameraObject);
    camera->setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend)
        .setPerspective(35.0_degf, 4.0f/3.0f, 0.001f, 1000.0f)
        .setViewport(defaultFramebuffer.viewport().size());

    std::vector<Vector3> data {
        {-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, /* Left vertex, red color */
        { 0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, /* Right vertex, green color */
        { 0.0f,  0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}  /* Top vertex, blue color */
    };
    std::vector<Vector3> data2 = {
        {-0.5f, -0.5f, 0.0f}, {1.0f, 1.0f, 0.0f}, /* Left vertex, red color */
        { 0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 1.0f}, /* Right vertex, green color */
        { 0.0f,  0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}  /* Top vertex, blue color */
    };


    auto debugRendererOptions = new DebugTools::ObjectRendererOptions();
    debugRendererOptions->setSize(0.3f);

    obj = new MyObject3D(data, &scene, &drawables);
    obj->setTransformation(Matrix4::translation({0.1f,0.2f,0.3f}) * Matrix4::rotation(0.2_degf, Vector3{1.0,0.0,0.0}));
    obj2 = new MyObject3D(data2, obj, &drawables);
    obj2->setTransformation(Matrix4::translation({0.1f,0.2f,0.3f}) * Matrix4::rotation(-0.1_degf, Vector3{-0.41f, 0.0f, 0.41f}.normalized()));

    DebugTools::ResourceManager::instance().set("my", DebugTools::ObjectRendererOptions().setSize(0.3f));
    new DebugTools::ObjectRenderer3D(*obj, "my", &debugDrawables);
    new DebugTools::ObjectRenderer3D(*obj2, "my", &debugDrawables);
}

void MyApplication::mouseMoveEvent(MouseMoveEvent& event) {
//     if(!(event.buttons() & MouseMoveEvent::Button::Left)) return;

    auto xrot = Rad(event.position().x() / 100.0f);
    auto yrot = Rad(event.position().y() / 100.0f);
    std::cout << "xrot " << Float(Deg(xrot)) << " yrot " << Float(Deg(yrot)) << std::endl;
    Matrix4 cameraTransformation = 
        Matrix4::rotationY(xrot)
        *
        Matrix4::translation({0,0,50})
//      *
//      Matrix4::rotationZ(yrot)
    ;



    cameraObject->setTransformation(
        cameraTransformation
    );

    event.setAccepted();
    redraw();
}

void MyApplication::drawEvent() {
    defaultFramebuffer.clear(FramebufferClear::Color|FramebufferClear::Depth);

    Renderer::disable(Renderer::Feature::DepthTest);
    Renderer::enable(Renderer::Feature::DebugOutput);
    camera->draw(drawables);
    camera->draw(debugDrawables);

    obj->simpledraw();
    obj2->simpledraw();


    swapBuffers();
}

MAGNUM_APPLICATION_MAIN(MyApplication)

Here is the stack trace, it looks like the std::map is not properly initialized. I've been using resource manager before in other places and haven't had problems.

#0 std::_Hashtable<Magnum::ResourceKey, std::pair<Magnum::ResourceKey const, Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::Data>, std::allocator<std::pair<Magnum::ResourceKey const, Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::Data> >, std::__detail::_Select1st, std::equal_to<Magnum::ResourceKey>, std::hash<Magnum::ResourceKey>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_find_before_node() at /usr/include/c++/4.9/bits/hashtable.h:1442
#1 std::_Hashtable<Magnum::ResourceKey, std::pair<Magnum::ResourceKey const, Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::Data>, std::allocator<std::pair<Magnum::ResourceKey const, Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::Data> >, std::__detail::_Select1st, std::equal_to<Magnum::ResourceKey>, std::hash<Magnum::ResourceKey>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_find_node() at /usr/include/c++/4.9/bits/hashtable.h:625
#2 std::_Hashtable<Magnum::ResourceKey, std::pair<Magnum::ResourceKey const, Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::Data>, std::allocator<std::pair<Magnum::ResourceKey const, Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::Data> >, std::__detail::_Select1st, std::equal_to<Magnum::ResourceKey>, std::hash<Magnum::ResourceKey>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::find() at /usr/include/c++/4.9/bits/hashtable.h:1304
#3 std::unordered_map<Magnum::ResourceKey, Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::Data, std::hash<Magnum::ResourceKey>, std::equal_to<Magnum::ResourceKey>, std::allocator<std::pair<Magnum::ResourceKey const, Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::Data> > >::find() at /usr/include/c++/4.9/bits/unordered_map.h:574
#4 Magnum::Implementation::ResourceManagerData<Magnum::DebugTools::ObjectRendererOptions>::set() at /usr/local/include/Magnum/ResourceManager.h:507
#5 Magnum::ResourceManager<Magnum::AbstractShaderProgram, Magnum::Buffer, Magnum::Mesh, Magnum::MeshView, Magnum::DebugTools::ForceRendererOptions, Magnum::DebugTools::ObjectRendererOptions, Magnum::DebugTools::ShapeRendererOptions>::set<Magnum::DebugTools::ObjectRendererOptions>() at /usr/local/include/Magnum/ResourceManager.h:313
#6 Magnum::ResourceManager<Magnum::AbstractShaderProgram, Magnum::Buffer, Magnum::Mesh, Magnum::MeshView, Magnum::DebugTools::ForceRendererOptions, Magnum::DebugTools::ObjectRendererOptions, Magnum::DebugTools::ShapeRendererOptions>::set<Magnum::DebugTools::ObjectRendererOptions>() at /usr/local/include/Magnum/ResourceManager.h:330
#7 Magnum::ResourceManager<Magnum::AbstractShaderProgram, Magnum::Buffer, Magnum::Mesh, Magnum::MeshView, Magnum::DebugTools::ForceRendererOptions, Magnum::DebugTools::ObjectRendererOptions, Magnum::DebugTools::ShapeRendererOptions>::set<Magnum::DebugTools::ObjectRendererOptions&>() at /usr/local/include/Magnum/ResourceManager.h:335
#8 MyApplication::MyApplication() at /home/bill/programming/magnum-scenegraph3D/src/MyApplication.cpp:105
#9 main() at /home/bill/programming/magnum-scenegraph3D/src/MyApplication.cpp:149

Also, I have all the libraries and plugins set to statically link, if that makes any difference.

@mosra

This comment has been minimized.

Show comment
Hide comment
@mosra

mosra Dec 25, 2014

Owner

Hi, apologies for the late reply.

The ResourceManager crash looks like serious issue with static build, as the dynamic build runs fine and properly displays object positions. For now try using dynamic build, if possible.

Other than that, the "black screen" problem is related to this piece of code:

void draw(const Matrix4& transformationMatrix, SceneGraph::AbstractCamera3D& camera) override {
    _shader.setTransformationProjectionMatrix(transformationMatrix);
    _mesh.draw(_shader);
}

The transformation matrix contains just transformation relative to camera. Because the camera's Z position is 5, camera-relative Z position of the objects is around -5. That doesn't fit in the OpenGL unit cube and thus everything gets clipped. To fix this, you need to include camera's projection matrix as well:

void draw(const Matrix4& transformationMatrix, SceneGraph::AbstractCamera3D& camera) override {
    _shader.setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix);
    _mesh.draw(_shader);
}

This way the camera's projective transformation is correctly applied and the two triangles are now rendered. The other problem is why the simpledraw() function wasn't also rendering anything: you didn't set any new transformation/projection matrix to the shader and thus it just used the last set value, which was, unfortunately, the one with Z set to -5.

Just looking at that, the documentation on scene graph is seriously lacking and there is not one simple example, sorry about that. I need to improve it.

I've been trying to figure out a problem with the scene graph I've been having whereby I get complaints about the rotation 3x3 part of child objects' transformation matrix not being evenly scaled.

If there is anything else that seems to be wrong, please elaborate. There didn't seem to be any other problem with the code or the things it displayed.

std::cout << "xrot " << Float(Deg(xrot)) << " yrot " << Float(Deg(yrot)) << std::endl;

Just a tip: you can print almost everything (even containers, vectors and matrices) using the builtin Debug functionality. It behaves similarly to qDebug() from Qt:

Debug() << "xrot" << xrot << "yrot" << yrot;

Hope this helps. I'll now look deeper into the problem with static build.

Owner

mosra commented Dec 25, 2014

Hi, apologies for the late reply.

The ResourceManager crash looks like serious issue with static build, as the dynamic build runs fine and properly displays object positions. For now try using dynamic build, if possible.

Other than that, the "black screen" problem is related to this piece of code:

void draw(const Matrix4& transformationMatrix, SceneGraph::AbstractCamera3D& camera) override {
    _shader.setTransformationProjectionMatrix(transformationMatrix);
    _mesh.draw(_shader);
}

The transformation matrix contains just transformation relative to camera. Because the camera's Z position is 5, camera-relative Z position of the objects is around -5. That doesn't fit in the OpenGL unit cube and thus everything gets clipped. To fix this, you need to include camera's projection matrix as well:

void draw(const Matrix4& transformationMatrix, SceneGraph::AbstractCamera3D& camera) override {
    _shader.setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix);
    _mesh.draw(_shader);
}

This way the camera's projective transformation is correctly applied and the two triangles are now rendered. The other problem is why the simpledraw() function wasn't also rendering anything: you didn't set any new transformation/projection matrix to the shader and thus it just used the last set value, which was, unfortunately, the one with Z set to -5.

Just looking at that, the documentation on scene graph is seriously lacking and there is not one simple example, sorry about that. I need to improve it.

I've been trying to figure out a problem with the scene graph I've been having whereby I get complaints about the rotation 3x3 part of child objects' transformation matrix not being evenly scaled.

If there is anything else that seems to be wrong, please elaborate. There didn't seem to be any other problem with the code or the things it displayed.

std::cout << "xrot " << Float(Deg(xrot)) << " yrot " << Float(Deg(yrot)) << std::endl;

Just a tip: you can print almost everything (even containers, vectors and matrices) using the builtin Debug functionality. It behaves similarly to qDebug() from Qt:

Debug() << "xrot" << xrot << "yrot" << yrot;

Hope this helps. I'll now look deeper into the problem with static build.

@mosra mosra self-assigned this Dec 25, 2014

@wivlaro

This comment has been minimized.

Show comment
Hide comment
@wivlaro

wivlaro Jan 4, 2015

Contributor

Thanks very much for your help with the example. I figured out my rotation matrix problem in the end. I was reading it in from an external source and it needed transposing.

Contributor

wivlaro commented Jan 4, 2015

Thanks very much for your help with the example. I figured out my rotation matrix problem in the end. I was reading it in from an external source and it needed transposing.

@wivlaro wivlaro closed this Jan 4, 2015

@mosra mosra reopened this Jan 4, 2015

@mosra

This comment has been minimized.

Show comment
Hide comment
@mosra

mosra Jan 4, 2015

Owner

Let's keep it open, I still need to resolve the issue with static build and make the documentation suck less :)

Owner

mosra commented Jan 4, 2015

Let's keep it open, I still need to resolve the issue with static build and make the documentation suck less :)

@mosra

This comment has been minimized.

Show comment
Hide comment
@mosra

mosra Jan 11, 2015

Owner

Documentation should be hopefully improved with 4caeb30 and 9fd25a1 (also already uploaded to web), now focusing on the static build ...

Owner

mosra commented Jan 11, 2015

Documentation should be hopefully improved with 4caeb30 and 9fd25a1 (also already uploaded to web), now focusing on the static build ...

@mosra mosra modified the milestone: Last pre-Vulkan release Mar 10, 2015

mosra added a commit that referenced this issue Apr 5, 2015

Better fix to ensure a single static ResourceManager instance.
I'm not exactly sure where was the actual problem, but it seems to
be related to definition of templated function with static member
variables in header file in combination with dynamic libraries, causing
multiple definitions of a symbol which did or did not lead to compile
error and/or things breaking in horribly unpredictable way.

Previously it was done via (undocumented) macros, depending on include
order, which is great until it breaks horribly after random unrelated
changes. Currently it is done via black template magic and I'm
still afraid of including it in the public documentation.

There should be no visible change to the end user except for possibly
one less randomly weird bug (#79? couldn't reproduce).

... well, looking at the diff, the solution is still an ugly **********,
but at least it seems to work.
@mosra

This comment has been minimized.

Show comment
Hide comment
@mosra

mosra Apr 5, 2015

Owner

Finally got time to look into the static build, but couldn't reproduce (static build of Corrade + Magnum) with the code you posted above. Fixed possibly related issue in 7e8d90a and added additional test to verify that this kind of problems won't appear again.

If you come across this crash again, please reopen.

Owner

mosra commented Apr 5, 2015

Finally got time to look into the static build, but couldn't reproduce (static build of Corrade + Magnum) with the code you posted above. Fixed possibly related issue in 7e8d90a and added additional test to verify that this kind of problems won't appear again.

If you come across this crash again, please reopen.

@mosra mosra closed this Apr 5, 2015

@mosra mosra added this to the 2015.05 milestone Feb 15, 2018

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