成员函数模板

Code Snippet

using namespace Magnum;
using namespace Magnum::Math::Literals;

class CameraObject;
class ModelViewerApp;

class CameraObject: public Interconnect::Receiver, public Object3D {
public:
    CameraObject(ModelViewerApp& app);
    void mousePressEvent(Platform::Application::MouseEvent& event) {}
    void mouseReleaseEvent(Platform::Application::MouseEvent& event) {}
    void mouseMoveEvent(Platform::Application::MouseMoveEvent& event) {
        ... 
        event.setAccepted(true);
    }

private:
    Vector2i _prevPos{-1, -1};
};

class ModelViewerApp: public Platform::Application, public Interconnect::Emitter{
private:
    Scene3D _scene;
    Object3D _sceneRoot;
    CameraObject _cameraObject;

    Shaders::Phong _coloredShader{{}, 2};
    std::shared_ptr<SceneGraph::Camera3D> _camera;
    SceneGraph::DrawableGroup3D _drawables;
    Containers::Array<Containers::Optional<GL::Mesh>> _meshes;

public:
    explicit ModelViewerApp(const Arguments& arguments);

    struct SignalKey{enum Event{
        mousePressEvent,
        mouseReleaseEvent,
        mouseMoveEvent
    };};

    template <SignalKey::Event _SignalKey, class ...Args>
    Signal triggered(typename Interconnect::Implementation::Identity<Args>::Type... args) {
        return emit(&ModelViewerApp::triggered<_SignalKey, Args...>, args ...);
    }

private:
    void drawEvent() override;
    void mousePressEvent(MouseEvent& event) override;
    void mouseReleaseEvent(MouseEvent& event) override;
    void mouseMoveEvent(MouseMoveEvent& event) override;
};

CameraObject::CameraObject(ModelViewerApp& app) {
    using App = ModelViewerApp;
    Interconnect::connect(app, &App::triggered<App::SignalKey::mousePressEvent, App::MouseEvent&>,
            *this, &CameraObject::mousePressEvent);
    Interconnect::connect(app, &App::triggered<App::SignalKey::mouseReleaseEvent, App::MouseEvent&>,
            *this, &CameraObject::mouseReleaseEvent);
    Interconnect::connect(app, &App::triggered<App::SignalKey::mouseMoveEvent, App::MouseMoveEvent&>,
            *this, &CameraObject::mouseMoveEvent);
}

ModelViewerApp::ModelViewerApp(const Arguments& arguments):
        Platform::Application{arguments, Configuration{}.setTitle("Magnum Primitives Example")},
        _cameraObject(*this)
{
    Utility::Arguments args;
    args.addArgument("file").setHelp("file", "file to load")
        .parse(arguments.argc, arguments.argv);

    GL::Renderer::enable(GL::Renderer::Feature::DepthTest);
    GL::Renderer::enable(GL::Renderer::Feature::FaceCulling);

    const Trade::MeshData3D cube = Primitives::cubeSolid();

    ...

    _sceneRoot.setParent(&_scene);
    _cameraObject
            .setParent(&_scene)
            .translate(Vector3(0.0f, 10.f, 60.0f));
    _camera.reset( new SceneGraph::Camera3D{_cameraObject});
    (*_camera)
            .setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend)
            .setProjectionMatrix(Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.01f, 1000.0f))
            .setViewport(GL::defaultFramebuffer.viewport().size());
    ...

    new ColoredDrawable{_sceneRoot, _coloredShader, *_meshes[0], 0x377777_rgbf, _drawables};
}

void ModelViewerApp::drawEvent() {
    GL::defaultFramebuffer.clear(GL::FramebufferClear::Color|GL::FramebufferClear::Depth);
    _camera->draw(_drawables);
    swapBuffers();
}

void ModelViewerApp::mousePressEvent(MouseEvent& event) {
    triggered<SignalKey::mousePressEvent, MouseEvent&>(event);
}

void ModelViewerApp::mouseReleaseEvent(MouseEvent& event) {
    triggered<SignalKey::mouseReleaseEvent, MouseEvent&>(event);
}

void ModelViewerApp::mouseMoveEvent(MouseMoveEvent& event) {
    triggered<SignalKey::mouseMoveEvent, MouseMoveEvent&>(event);
    if(event.isAccepted()) redraw();
}

MAGNUM_APPLICATION_MAIN(ModelViewerApp)
For The Complete Version Code
#include <Magnum/GL/Buffer.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/GL/Renderer.h>

#include <Magnum/Trade/MeshData3D.h>
#include <Magnum/Trade/AbstractImporter.h>

#include <Magnum/MeshTools/Interleave.h>
#include <Magnum/MeshTools/CompressIndices.h>
#include <Magnum/MeshTools/Compile.h>

#include <Magnum/Primitives/Cube.h>
#include <Magnum/Shaders/Phong.h>

#include <Magnum/SceneGraph/Scene.h>
#include <Magnum/SceneGraph/Camera.h>
#include <Magnum/SceneGraph/Drawable.h>
#include <Magnum/SceneGraph/DualQuaternionTransformation.h>

#include <Magnum/Platform/GlfwApplication.h>

#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Interconnect/Emitter.h>
#include <Corrade/Interconnect/Receiver.h>
#include <Corrade/Utility/Arguments.h>



using namespace Magnum;
typedef SceneGraph::Object<SceneGraph::DualQuaternionTransformation> Object3D;
typedef SceneGraph::Scene<SceneGraph::DualQuaternionTransformation> Scene3D;


class ColoredDrawable: public SceneGraph::Drawable3D {
public:
    explicit ColoredDrawable(Object3D& object, Shaders::Phong& shader, GL::Mesh& mesh, const Color4& color, SceneGraph::DrawableGroup3D& group):
                SceneGraph::Drawable3D{object, &group}, _shader(shader), _mesh(mesh), _color{color} {}

private:
    void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) override {
        _shader
                .setSpecularColor({0, 0, 0})
                .setDiffuseColor(_color)
                .setAmbientColor({0.2, 0.2, 0.2})
                .setLightPositions({camera.cameraMatrix().transformPoint({0.0f, 0.0f, -50.0f}),
                                    camera.cameraMatrix().transformPoint({0.0f, 0.0f, 50.0f})})
                .setTransformationMatrix(transformationMatrix)
                .setNormalMatrix(transformationMatrix.rotationScaling())
                .setProjectionMatrix(camera.projectionMatrix());

        _mesh.draw(_shader);
    }

    Shaders::Phong& _shader;
    GL::Mesh& _mesh;
    Color4 _color;
};

class TexturedDrawable: public SceneGraph::Drawable3D {
public:
    explicit TexturedDrawable(Object3D& object, Shaders::Phong& shader, GL::Mesh& mesh, GL::Texture2D& texture, SceneGraph::DrawableGroup3D& group):
                SceneGraph::Drawable3D{object, &group}, _shader(shader), _mesh(mesh), _texture(texture) {}

private:
    void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) override {
        _shader
                .setLightPosition(camera.cameraMatrix().transformPoint({-3.0f, 10.0f, 10.0f}))
                .setTransformationMatrix(transformationMatrix)
                .setNormalMatrix(transformationMatrix.rotationScaling())
                .setProjectionMatrix(camera.projectionMatrix())
                .bindDiffuseTexture(_texture);

        _mesh.draw(_shader);
    }

    Shaders::Phong& _shader;
    GL::Mesh& _mesh;
    GL::Texture2D& _texture;
};


using namespace Magnum;
using namespace Magnum::Math::Literals;

class CameraObject;
class ModelViewerApp;

class CameraObject: public Interconnect::Receiver, public Object3D {
public:
    CameraObject(ModelViewerApp& app);
    void mousePressEvent(Platform::Application::MouseEvent& event) {}
    void mouseReleaseEvent(Platform::Application::MouseEvent& event) {}
    void mouseMoveEvent(Platform::Application::MouseMoveEvent& event) {
        if(_prevPos[0] < 0 )
            _prevPos = event.position();
        else {
            this->rotateZ(Rad((event.position()[0]-_prevPos[0])/360.0*3.1415926));
//	        this->rotateX(Rad((event.position()[1]-_prevPos[1])/360.0*3.1415926));
	        _prevPos = event.position();
        }
        event.setAccepted(true);
    }

private:
    Vector2i _prevPos{-1, -1};
};

class ModelViewerApp: public Platform::Application, public Interconnect::Emitter{
private:
    Scene3D _scene;
    Object3D _sceneRoot;
    CameraObject _cameraObject;

    Shaders::Phong _coloredShader{{}, 2};
    std::shared_ptr<SceneGraph::Camera3D> _camera;
    SceneGraph::DrawableGroup3D _drawables;
    Containers::Array<Containers::Optional<GL::Mesh>> _meshes;

public:
    explicit ModelViewerApp(const Arguments& arguments);

    struct SignalKey{enum Event{
        mousePressEvent,
        mouseReleaseEvent,
        mouseMoveEvent
    };};

    template <SignalKey::Event _SignalKey, class ...Args>
    Signal triggered(typename Interconnect::Implementation::Identity<Args>::Type... args) {
        return emit(&ModelViewerApp::triggered<_SignalKey, Args...>, args ...);
    }

private:
    void drawEvent() override;
    void mousePressEvent(MouseEvent& event) override;
    void mouseReleaseEvent(MouseEvent& event) override;
    void mouseMoveEvent(MouseMoveEvent& event) override;
};

CameraObject::CameraObject(ModelViewerApp& app) {
    using App = ModelViewerApp;
    Interconnect::connect(app, &App::triggered<App::SignalKey::mousePressEvent, App::MouseEvent&>,
            *this, &CameraObject::mousePressEvent);
    Interconnect::connect(app, &App::triggered<App::SignalKey::mouseReleaseEvent, App::MouseEvent&>,
            *this, &CameraObject::mouseReleaseEvent);
    Interconnect::connect(app, &App::triggered<App::SignalKey::mouseMoveEvent, App::MouseMoveEvent&>,
            *this, &CameraObject::mouseMoveEvent);
}

ModelViewerApp::ModelViewerApp(const Arguments& arguments):
        Platform::Application{arguments, Configuration{}.setTitle("Magnum Primitives Example")},
        _cameraObject(*this)
{
    Utility::Arguments args;
    args.addArgument("file").setHelp("file", "file to load")
        .parse(arguments.argc, arguments.argv);

    GL::Renderer::enable(GL::Renderer::Feature::DepthTest);
    GL::Renderer::enable(GL::Renderer::Feature::FaceCulling);

    const Trade::MeshData3D cube = Primitives::cubeSolid();

    /* Load a scene importer plugin */
    PluginManager::Manager<Trade::AbstractImporter> manager;
    Containers::Pointer<Trade::AbstractImporter> importer = manager.loadAndInstantiate("ObjImporter");
    if(!importer) std::exit(1);
    if(!importer->openFile(args.value("file")))
        std::exit(1);

    _sceneRoot.setParent(&_scene);
    _cameraObject
            .setParent(&_scene)
            .translate(Vector3(0.0f, 10.f, 60.0f));
    _camera.reset( new SceneGraph::Camera3D{_cameraObject});
    (*_camera)
            .setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend)
            .setProjectionMatrix(Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.01f, 1000.0f))
            .setViewport(GL::defaultFramebuffer.viewport().size());
    _meshes = Containers::Array<Containers::Optional<GL::Mesh>>{importer->mesh3DCount()};

    for(UnsignedInt i = 0; i != importer->mesh3DCount(); ++i) {
        Containers::Optional<Trade::MeshData3D> meshData = importer->mesh3D(i);
        if(!meshData || meshData->primitive() != MeshPrimitive::Triangles) {
            Warning{} << "Cannot load the mesh, skipping";
            continue;
        }

        /* Compile the mesh */
        _meshes[i] = MeshTools::compile(*meshData, MeshTools::CompileFlag::GenerateSmoothNormals);
    }

    new ColoredDrawable{_sceneRoot, _coloredShader, *_meshes[0], 0x377777_rgbf, _drawables};
}

void ModelViewerApp::drawEvent() {

    GL::defaultFramebuffer.clear(GL::FramebufferClear::Color|GL::FramebufferClear::Depth);

    _camera->draw(_drawables);

    swapBuffers();
}

void ModelViewerApp::mousePressEvent(MouseEvent& event) {
    triggered<SignalKey::mousePressEvent, MouseEvent&>(event);
}

void ModelViewerApp::mouseReleaseEvent(MouseEvent& event) {
    triggered<SignalKey::mouseReleaseEvent, MouseEvent&>(event);
}

void ModelViewerApp::mouseMoveEvent(MouseMoveEvent& event) {
    triggered<SignalKey::mouseMoveEvent, MouseMoveEvent&>(event);
    if(event.isAccepted()) redraw();
}

MAGNUM_APPLICATION_MAIN(ModelViewerApp)
posted @ 2019-10-16 22:13  xiconxi  阅读(414)  评论(0编辑  收藏  举报