#include #include #include #include #include #include #include #include #include #include "magnum_render.h" using namespace Magnum; using namespace Math::Literals; static const auto HUE_BG = 210.0_degf; static const auto COLOR_BG = Color4::fromHsv({HUE_BG, .3f, .9f}, 1.f); static const auto COLOR_GRID = Color4::fromHsv({HUE_BG, .3f, .7f}, 1.f); MagnumRenderer::MagnumRenderer() : m_init(false) {} MagnumRenderer::~MagnumRenderer() { delete m_subjectObject; delete m_subjectDrawable; delete m_gridObject; } void MagnumRenderer::t(const float t) { if (m_subjectDrawable) m_subjectDrawable->t(t); } void MagnumRenderer::hue(float hue) { if (m_subjectDrawable) m_subjectDrawable->hue(hue); } void MagnumRenderer::count(int count) { if (m_subjectDrawable) m_subjectDrawable->count(count); } Containers::Optional& MagnumRenderer::camera() { return m_camera; } float MagnumRenderer::lagging() { if (m_camera) return m_camera->lagging(); else return 0.f; } void MagnumRenderer::lagging(float lagging) { if (m_camera) m_camera->setLagging(lagging); } /** * @brief MagnumRenderer::lazyInitialize * */ void MagnumRenderer::lazyInitialize() { if (m_init) return; // The Cube { m_subject = MeshTools::compile(Primitives::cubeSolid()); m_subjectObject = new Object3D{&m_scene}; (*m_subjectObject).translate(Vector3{0.f, 1.f, 0.f}); m_subjectShader = Shaders::Phong{}; m_subjectShader .setShininess(20.f) .setLightColor(Color3{1.f}) .setLightPosition(Vector3{-100.f, 100.f, 50.f}); m_subjectDrawable = new SubjectDrawable{*m_subjectObject, m_subjectShader, m_subject, m_drawables, 1, 0, 0}; } // The Grid { m_grid = MeshTools::compile(Primitives::grid3DWireframe({15, 15})); m_gridObject = new Object3D{&m_scene}; (*m_gridObject).rotateX(90.0_degf).scale(Vector3{8.0f}); m_gridShader = Shaders::Flat3D{}; m_gridShader.setColor(COLOR_GRID); m_gridDrawable = new GridDrawable{*m_gridObject, m_gridShader, m_grid, m_drawables}; } // The Camera { const Vector3 eye{-10.0f, 8.f, -6.f}; const Vector3 center{0.f, 1.f, 0.f}; const Vector3 up = Vector3::yAxis(); m_camera.emplace(m_scene, eye, center, up, 45.0_degf, Vector2i{100, 100}, Vector2i{100, 100}); } m_init = true; } void MagnumRenderer::reset(Platform::GLContext *ctx, GL::Framebuffer fbo, Vector2i windowSize, Vector2i viewportSize) { lazyInitialize(); m_camera->reshape(windowSize, viewportSize); m_FBO = std::move(fbo); m_ctx = ctx; } /** * @brief MagnumRenderer::prepGLState * */ void MagnumRenderer::prepGLState() { GL::Renderer::setClearColor(COLOR_BG); GL::Renderer::enable(GL::Renderer::Feature::DepthTest); GL::Renderer::enable(GL::Renderer::Feature::FaceCulling); GL::Renderer::enable(GL::Renderer::Feature::Multisampling); GL::Renderer::setDepthFunction(GL::Renderer::DepthFunction::LessOrEqual); GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add); GL::Renderer::setBlendFunction( GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha); GL::Renderer::enable(GL::Renderer::Feature::Blending); } void MagnumRenderer::render() { m_ctx->resetState(GL::Context::State::ExitExternal); prepGLState(); m_FBO.bind(); m_FBO.clear(GL::FramebufferClear::Color | GL::FramebufferClear::Depth); m_camera->update(); m_camera->draw(m_drawables); /** Use instead this to limit rendering to camera changes * bool cameraChanged = m_camera->update(); * m_camera->draw(m_drawables); * if (cameraChanged) { * redraw(); // should call back to MagnumItem::update() * } */ // --- m_ctx->resetState(GL::Context::State::EnterExternal); } void GridDrawable::draw(const Matrix4 &transformation, SceneGraph::Camera3D &camera) { m_shader .setTransformationProjectionMatrix( camera.projectionMatrix()*transformation) .draw(m_mesh); } void SubjectDrawable::draw(const Matrix4 &transformation, SceneGraph::Camera3D &camera) { // We only need to do this once in this draw call m_shader .setNormalMatrix(transformation.normalMatrix()) .setProjectionMatrix(camera.projectionMatrix()); static const float width = 3.f; float x = -float(m_count)/2.f * width + width/2.f; for (int i = 0; i < m_count; i++) { // Change hue depending on position const auto color = Color3::fromHsv({Rad(m_hue+float(i)*.2f), 1.f, 1.f}); m_shader .setDiffuseColor(color) .setAmbientColor(Color3::fromHsv({color.hue(), 1.0f, 0.3f})); // Move in +x m_shader .setTransformationMatrix( transformation * Matrix4::translation({x, Math::sin(Rad(m_t*2.f+float(i))), 0.f})) .draw(m_mesh); x += width; } } void SubjectDrawable::count(int count) { m_count = count; } void SubjectDrawable::hue(float hue) { m_hue = hue; } void SubjectDrawable::t(float t) { m_t = t; }