Skip to content
Snippets Groups Projects
Commit f211345a authored by Philip Trettner's avatar Philip Trettner
Browse files

working on visualization lib

parent 15fadc3e
Branches
Tags
No related merge requests found
Showing
with 628 additions and 1 deletion
......@@ -10,6 +10,10 @@ endif()
# all glow-extras
add_library(glow-extras ${GLOW_LINK_TYPE} glow-extras.cc)
# Colors
add_subdirectory(colors)
target_link_libraries(glow-extras PUBLIC glow-extras-colors)
# Camera
add_subdirectory(camera)
target_link_libraries(glow-extras PUBLIC glow-extras-camera)
......@@ -64,3 +68,12 @@ if (TARGET aion)
else()
message(STATUS "target 'aion' not found, disabling glow-extras-glfw")
endif()
# Viewer
# requires 'polymesh'
if (TARGET polymesh)
add_subdirectory(viewer)
target_link_libraries(glow-extras PUBLIC glow-extras-viewer)
else()
message(STATUS "target 'polymesh' not found, disabling glow-extras-viewer")
endif()
......@@ -271,7 +271,7 @@ protected:
public:
/// Initializes GLFW and GLOW, and runs until window is closed
int run(int argc, char* argv[]);
int run(int argc = 0, char* argv[] = nullptr);
public:
virtual ~GlfwApp(); // virtual dtor
......
#include "LambdaApp.hh"
namespace glow
{
namespace glfw
{
LambdaApp::LambdaApp(std::function<void(LambdaApp *)> fInit, //
std::function<void(LambdaApp *, float)> fRender,
std::function<void(LambdaApp *, float)> fUpdate)
: mInitFunc(fInit), //
mRenderFunc(fRender),
mUpdateFunc(fUpdate)
{
}
void LambdaApp::init()
{
GlfwApp::init();
if (mInitFunc)
mInitFunc(this);
}
void LambdaApp::update(float elapsedSeconds)
{
GlfwApp::update(elapsedSeconds);
if (mUpdateFunc)
mUpdateFunc(this, elapsedSeconds);
}
void LambdaApp::render(float elapsedSeconds)
{
GlfwApp::render(elapsedSeconds);
if (mRenderFunc)
mRenderFunc(this, elapsedSeconds);
}
SharedLambdaApp make_app(std::function<void(LambdaApp *)> fInit, std::function<void(LambdaApp *, float)> fRender, std::function<void(LambdaApp *, float)> fUpdate)
{
return std::make_shared<LambdaApp>(fInit, fRender, fUpdate);
}
}
}
#pragma once
#include <functional>
#include "GlfwApp.hh"
namespace glow
{
namespace glfw
{
GLOW_SHARED(class, LambdaApp);
/// creates a lambda app
SharedLambdaApp make_app(std::function<void(LambdaApp*)> fInit, //
std::function<void(LambdaApp*, float)> fRender, //
std::function<void(LambdaApp*, float)> fUpdate = nullptr);
/// forwards all arguments to make_app(...) and shows the result
template <typename... Args>
void show_app(Args&&... args)
{
auto v = make_app(std::forward<Args>(args)...);
v->run();
}
class LambdaApp : public GlfwApp
{
public:
LambdaApp(std::function<void(LambdaApp*)> fInit, //
std::function<void(LambdaApp*, float)> fRender, //
std::function<void(LambdaApp*, float)> fUpdate = nullptr);
void init() override;
void update(float elapsedSeconds) override;
void render(float elapsedSeconds) override;
private:
std::function<void(LambdaApp*)> mInitFunc;
std::function<void(LambdaApp*, float)> mRenderFunc;
std::function<void(LambdaApp*, float)> mUpdateFunc;
};
}
}
cmake_minimum_required(VERSION 3.0)
file(GLOB_RECURSE SOURCE_FILES "*.cc")
file(GLOB_RECURSE HEADER_FILES "*.hh")
add_library(glow-extras-viewer ${GLOW_LINK_TYPE} ${SOURCE_FILES} ${HEADER_FILES})
target_include_directories(glow-extras-viewer PUBLIC ./)
target_compile_options(glow-extras-viewer PRIVATE ${GLOW_EXTRAS_DEF_OPTIONS})
target_link_libraries(glow-extras-viewer PUBLIC
glow
polymesh
glow-extras-camera
glow-extras-colors
glow-extras-glfw
)
#include "Label.hh"
using namespace glow;
using namespace glow::viewer;
Label::Label() {}
#pragma once
#include <glow/common/shared.hh>
namespace glow
{
namespace viewer
{
GLOW_SHARED(class, Label);
class Label : public std::enable_shared_from_this<Label>
{
public:
Label();
};
}
}
#include "Light.hh"
using namespace glow;
using namespace glow::viewer;
Light::Light() {}
SharedLight Light::create() { return std::make_shared<Light>(); }
#pragma once
#include <glow/common/shared.hh>
namespace glow
{
namespace viewer
{
GLOW_SHARED(class, Light);
class Light: public std::enable_shared_from_this<Light>
{
public:
// ctor
public:
Light();
static SharedLight create();
};
}
}
#include "Renderable.hh"
#include <glow/objects/Program.hh>
#include <glow/objects/VertexArray.hh>
using namespace glow;
using namespace glow::viewer;
Renderable::Renderable() {}
#pragma once
#include <glm/glm.hpp>
#include <glow/fwd.hh>
#include <glow/common/property.hh>
#include <glow/common/shared.hh>
#include "aabb.hh"
namespace glow
{
namespace viewer
{
GLOW_SHARED(class, Renderable);
class Renderable : public std::enable_shared_from_this<Renderable>
{
// member
private:
glm::mat4 mTransform;
// properties
public:
GLOW_BUILDER(transform, Transform);
// methods
public:
/// renders this renderable
virtual void render() = 0;
/// computes the AABB (update min/max)
virtual aabb computeAabb() = 0;
// ctor
public:
Renderable();
virtual ~Renderable() {}
// create a renderable from a lambda function
template <class RenderF>
static SharedRenderable create(aabb const& aabb, RenderF&& f);
};
/// general purpose renderable
///
/// CAUTION: the lambda should always capture by value! (unless you know the scope)
///
/// Signature:
/// RenderF is void(glm::mat4)
template <class RenderF>
class LambdaRenderable : public Renderable
{
private:
aabb mAabb;
RenderF mRenderFunction;
public:
aabb computeAabb() override { return mAabb.transformed(transform()); }
void render() override { mRenderFunction(transform()); }
public:
LambdaRenderable(aabb const& aabb, RenderF&& f) : mAabb(aabb), mRenderFunction(f) {}
};
template <class RenderF>
SharedRenderable Renderable::create(aabb const& aabb, RenderF&& f)
{
return std::make_shared<LambdaRenderable>(aabb, f);
}
}
}
#include "Renderables.hh"
using namespace polymesh;
using namespace glow::colors;
namespace glow
{
namespace viewer{
namespace detail {
static SharedRenderable make_colored_mesh(const vertex_attribute<glm::vec3> &pos, halfedge_attribute<color> const& colors)
{
// auto bounds = pos.aabb();
return nullptr;
// return Renderable::create(aabb(bounds.min, bounds.max), [](glm::mat4 const& transform) {
//
// });
}
static SharedRenderable make_mapped_mesh(const vertex_attribute<glm::vec3> &pos, halfedge_attribute<float> const& data, colormap const& cmap, datascale scale)
{
// auto bounds = pos.aabb();
return nullptr;
}
}
SharedRenderable make_vertex_renderable(const vertex_attribute<glm::vec3> &pos, const vertex_attribute<color> &colors)
{
return detail::make_colored_mesh(pos, pos.mesh().halfedges().map([&](halfedge_handle h) { return colors[h.vertex_to()];}));
}
SharedRenderable make_vertex_renderable(const vertex_attribute<glm::vec3> &pos, const vertex_attribute<float> &data, const colormap &cmap, datascale scale)
{
return detail::make_mapped_mesh(pos, pos.mesh().halfedges().map([&](halfedge_handle h) { return data[h.vertex_to()];}), cmap, scale);
}
SharedRenderable make_face_renderable(const vertex_attribute<glm::vec3> &pos, const face_attribute<color> &colors)
{
return detail::make_colored_mesh(pos, pos.mesh().halfedges().map([&](halfedge_handle h) { return colors[h.face()];}));
}
SharedRenderable make_face_renderable(const vertex_attribute<glm::vec3> &pos, const face_attribute<float> &data, const colormap &cmap, datascale scale)
{
return detail::make_mapped_mesh(pos, pos.mesh().halfedges().map([&](halfedge_handle h) { return data[h.face()];}), cmap, scale);
}
}
}
#pragma once
#include "Renderable.hh"
#include <glow-extras/colors/color.hh>
#include <glow-extras/colors/colormap.hh>
#include <polymesh/Mesh.hh>
#include "datascale.hh"
namespace glow
{
namespace viewer
{
/**
* @brief convenience functions for creating renderables
*/
SharedRenderable make_vertex_renderable(polymesh::vertex_attribute<glm::vec3> const& pos, polymesh::vertex_attribute<colors::color> const& colors);
SharedRenderable make_vertex_renderable(polymesh::vertex_attribute<glm::vec3> const& pos, polymesh::vertex_attribute<float> const& data, colors::colormap const& cmap, datascale scale = {});
SharedRenderable make_face_renderable(polymesh::vertex_attribute<glm::vec3> const& pos, polymesh::face_attribute<colors::color> const& colors);
SharedRenderable make_face_renderable(polymesh::vertex_attribute<glm::vec3> const& pos, polymesh::face_attribute<float> const& data, colors::colormap const& cmap, datascale scale = {});
}
}
#include "Scene.hh"
#include "Renderable.hh"
using namespace glow;
using namespace glow::viewer;
SharedScene Scene::add(const SharedRenderable &r)
{
mRenderables.push_back(r);
return shared_from_this();
}
SharedScene Scene::add(const SharedLight &l)
{
mLights.push_back(l);
return shared_from_this();
}
aabb Scene::computeAabb() const
{
aabb bounds;
for (auto const &r : mRenderables)
bounds.add(r->computeAabb());
return bounds;
}
Scene::Scene() {}
SharedScene Scene::create() { return std::make_shared<Scene>(); }
#pragma once
#include <vector>
#include <glow/common/shared.hh>
#include "aabb.hh"
namespace glow
{
namespace viewer
{
GLOW_SHARED(class, Scene);
GLOW_SHARED(class, Renderable);
GLOW_SHARED(class, Light);
class Scene : public std::enable_shared_from_this<Scene>
{
// members
private:
std::vector<SharedRenderable> mRenderables;
std::vector<SharedLight> mLights;
// methods
public:
/// adds a renderable
/// returns this
SharedScene add(SharedRenderable const& r);
/// adds a light
/// returns this
SharedScene add(SharedLight const& l);
/// computes the AABB of the scene
aabb computeAabb() const;
// ctor
public:
Scene();
static SharedScene create();
};
}
}
#include "SubView.hh"
#include <glow-extras/glfw/LambdaApp.hh>
#include "Renderable.hh"
#include "Scene.hh"
using namespace glow;
using namespace glow::viewer;
using namespace glow::camera;
void SubView::show()
{
auto aabb = mScene->computeAabb();
if (aabb.isEmpty())
glow::warning() << "Scene has empty AABB";
else
{
// TODO: shared camera setup!
// camera position
auto size = aabb.max - aabb.min;
auto center = (aabb.max + aabb.min) * 0.5f;
auto dir = aabb.max - center;
auto diameter = length(size);
dir.y += diameter * 0.1f;
mCamera->setLookAtMatrix(center + dir * 1.1f, center, {0, 1, 0});
mCamera->setNearClippingPlane(diameter * 1e-4f);
mCamera->setFarClippingPlane(diameter * 3);
}
glfw::show_app(
[&](glfw::LambdaApp* app) {
},
[&](glfw::LambdaApp* app, float elapsedSeconds) {
});
}
SubView::SubView()
{
mScene = Scene::create();
mCamera = std::make_shared<GenericCamera>();
}
SharedSubView SubView::create() { return std::make_shared<SubView>(); }
#pragma once
#include <glow/common/property.hh>
#include <glow/common/shared.hh>
#include <glow-extras/camera/GenericCamera.hh>
namespace glow
{
namespace viewer
{
GLOW_SHARED(class, SubView);
GLOW_SHARED(class, Scene);
class SubView : public std::enable_shared_from_this<SubView>
{
// members
private:
SharedScene mScene;
camera::SharedGenericCamera mCamera;
// properties
public:
GLOW_BUILDER(scene, Scene);
GLOW_BUILDER(camera, Camera);
// methods
public:
/// Creates a windows and shows this view
void show();
// ctor
public:
SubView();
/// creates a new, empty 3D view
static SharedSubView create();
};
}
}
#pragma once
#include <initializer_list>
#include <glm/glm.hpp>
namespace glow
{
namespace viewer
{
struct aabb
{
// member
public:
glm::vec3 min = glm::vec3(+std::numeric_limits<float>::max());
glm::vec3 max = glm::vec3(-std::numeric_limits<float>::max());
// properties
public:
glm::vec3 size() const;
float volume() const;
bool isEmpty() const;
// mutating methods
public:
/// includes a given point
void add(glm::vec3 const& p);
/// includes a given aabb
void add(aabb const& rhs);
// non-mutating
public:
/// calculates a transformed aabb
aabb transformed(glm::mat4 const& transform) const;
// ctor
public:
aabb() = default;
aabb(glm::vec3 min, glm::vec3 max) : min(min), max(max) {}
static aabb empty() { return {}; }
};
/// ======== IMPLEMENTATION ========
inline glm::vec3 aabb::size() const { return isEmpty() ? glm::vec3() : max - min; }
inline float aabb::volume() const
{
if (isEmpty())
return 0;
auto s = size();
return s.x * s.y * s.z;
}
inline bool aabb::isEmpty() const { return max.x <= min.x || max.y <= min.y || max.z <= min.z; }
inline void aabb::add(const glm::vec3& p)
{
min = glm::min(min, p);
max = glm::max(max, p);
}
inline void aabb::add(const aabb& rhs)
{
add(rhs.min);
add(rhs.max);
}
inline aabb aabb::transformed(const glm::mat4& transform) const
{
aabb r;
for (float dz : {0, 1})
for (float dy : {0, 1})
for (float dx : {0, 1})
{
auto p = min + (max - min) * glm::vec3(dx, dy, dz);
p = glm::vec3(transform * glm::vec4(p, 1.0f));
r.add(p);
}
return r;
}
}
}
#pragma once
namespace glow
{
namespace viewer
{
struct datascale
{
float min = 0;
float max = 1;
datascale() = default;
datascale(float max) : min(0), max(max) {}
datascale(float min, float max) : min(min), max(max) {}
};
}
}
#include "view.hh"
#include "Renderables.hh"
#include "Scene.hh"
namespace glow
{
namespace viewer
{
SharedSubView view() { return SubView::create(); }
SharedSubView view(const polymesh::vertex_attribute<glm::vec3> &position, const polymesh::vertex_attribute<colors::color> &colors)
{
auto v = view();
v->scene()->add(make_vertex_renderable(position, colors));
return v;
}
SharedSubView view(const polymesh::vertex_attribute<glm::vec3> &position, const polymesh::face_attribute<colors::color> &colors)
{
auto v = view();
v->scene()->add(make_face_renderable(position, colors));
return v;
}
SharedSubView view(const polymesh::vertex_attribute<glm::vec3> &position, const polymesh::vertex_attribute<float> &data, const colors::colormap &cmap, datascale scale)
{
auto v = view();
v->scene()->add(make_vertex_renderable(position, data, cmap, scale));
return v;
}
SharedSubView view(const polymesh::vertex_attribute<glm::vec3> &position, const polymesh::face_attribute<float> &data, const colors::colormap &cmap, datascale scale)
{
auto v = view();
v->scene()->add(make_face_renderable(position, data, cmap, scale));
return v;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment