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<:camera3d> _camera;
SceneGraph::DrawableGroup3D _drawables;
Containers::Array<:optional>> _meshes;
public:
explicit ModelViewerApp(const Arguments& arguments);
struct SignalKey{enum Event{
mousePressEvent,
mouseReleaseEvent,
mouseMoveEvent
};};
template <:event _signalkey class ...args>
Signal triggered(typename Interconnect::Implementation::Identity::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<:signalkey::mousepressevent app::mouseevent>,
*this, &CameraObject::mousePressEvent);
Interconnect::connect(app, &App::triggered<:signalkey::mousereleaseevent app::mouseevent>,
*this, &CameraObject::mouseReleaseEvent);
Interconnect::connect(app, &App::triggered<: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<:mousepressevent mouseevent>(event);
}
void ModelViewerApp::mouseReleaseEvent(MouseEvent& event) {
triggered<:mousereleaseevent mouseevent>(event);
}
void ModelViewerApp::mouseMoveEvent(MouseMoveEvent& event) {
triggered<:mousemoveevent mousemoveevent>(event);
if(event.isAccepted()) redraw();
}
MAGNUM_APPLICATION_MAIN(ModelViewerApp)
For The Complete Version Code
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace Magnum;
typedef SceneGraph::Object<:dualquaterniontransformation> Object3D;
typedef SceneGraph::Scene<: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<:camera3d> _camera;
SceneGraph::DrawableGroup3D _drawables;
Containers::Array<:optional>> _meshes;
public:
explicit ModelViewerApp(const Arguments& arguments);
struct SignalKey{enum Event{
mousePressEvent,
mouseReleaseEvent,
mouseMoveEvent
};};
template <:event _signalkey class ...args>
Signal triggered(typename Interconnect::Implementation::Identity::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<:signalkey::mousepressevent app::mouseevent>,
*this, &CameraObject::mousePressEvent);
Interconnect::connect(app, &App::triggered<:signalkey::mousereleaseevent app::mouseevent>,
*this, &CameraObject::mouseReleaseEvent);
Interconnect::connect(app, &App::triggered<: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<:abstractimporter> manager;
Containers::Pointer<: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<:optional>>{importer->mesh3DCount()};
for(UnsignedInt i = 0; i != importer->mesh3DCount(); ++i) {
Containers::Optional<: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<:mousepressevent mouseevent>(event);
}
void ModelViewerApp::mouseReleaseEvent(MouseEvent& event) {
triggered<:mousereleaseevent mouseevent>(event);
}
void ModelViewerApp::mouseMoveEvent(MouseMoveEvent& event) {
triggered<:mousemoveevent mousemoveevent>(event);
if(event.isAccepted()) redraw();
}
MAGNUM_APPLICATION_MAIN(ModelViewerApp)