Skip to content

Commit

Permalink
Add dynamic updates and various temporary testing routines for 3d views.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kasper Peeters committed Nov 13, 2024
1 parent a818dfc commit 2cba748
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 35 deletions.
4 changes: 4 additions & 0 deletions core/DataCell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,10 @@ void cadabra::JSON_in_recurse(DTree& doc, DTree::iterator loc, const nlohmann::j
DataCell dc(id, cadabra::DataCell::CellType::image_svg, textbuf.get<std::string>(), hide);
last=doc.append_child(loc, dc);
}
else if(cell_type=="graphics_view") {
DataCell dc(id, cadabra::DataCell::CellType::graphics_view, textbuf.get<std::string>(), hide);
last=doc.append_child(loc, dc);
}
else {
std::cerr << "cadabra-client: found unknown cell type '"+cell_type+"', ignoring" << std::endl;
continue;
Expand Down
81 changes: 81 additions & 0 deletions examples/gltf.cnb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"cell_id": 16461605748738409030,
"cells": [
{
"cell_id": 10635152356046299518,
"cell_origin": "client",
"cell_type": "input",
"source": "a=server.send(\"hello\", \"graphics_view\", 0, 123, False)"
},
{
"cell_id": 11350501809507979634,
"cell_origin": "client",
"cell_type": "input",
"source": "from pathlib import Path\ngltf = Path('test.glb').read_bytes()"
},
{
"cell_id": 13867252481123575504,
"cell_origin": "client",
"cell_type": "input",
"source": "gltf64=base64.b64encode(gltf)"
},
{
"cell_id": 2928652340647885648,
"cell_origin": "client",
"cell_type": "input",
"cells": [
{
"cell_id": 123,
"cell_origin": "server",
"cell_type": "graphics_view",
"source": "Z2xURgIAAAAoDAAAOAgAAEpTT057ImFzc2V0Ijp7ImdlbmVyYXRvciI6Iktocm9ub3MgZ2xURiBCbGVuZGVyIEkvTyB2NC4xLjYzIiwidmVyc2lvbiI6IjIuMCJ9LCJleHRlbnNpb25zVXNlZCI6WyJLSFJfbWF0ZXJpYWxzX3NoZWVuIl0sInNjZW5lIjowLCJzY2VuZXMiOlt7Im5hbWUiOiJTY2VuZSIsIm5vZGVzIjpbMCwxXX1dLCJub2RlcyI6W3sibWVzaCI6MCwibmFtZSI6IkN1YmUifSx7Im1lc2giOjEsIm5hbWUiOiJQbGFuZSIsInJvdGF0aW9uIjpbMCwwLC0wLjcwNTk0NDQxODkwNzE2NTUsMC43MDgyNjcyMTE5MTQwNjI1XSwic2NhbGUiOlsyLjU3Mjk3MzcyODE3OTkzMTYsMi41NzI5NzM3MjgxNzk5MzE2LDIuNTcyOTczNzI4MTc5OTMxNl0sInRyYW5zbGF0aW9uIjpbLTEuMDc0NTU1Mzk3MDMzNjkxNCwtMC44MDY2MzAxMzQ1ODI1MTk1LC0wLjYwNDcxNDAzNTk4Nzg1NF19XSwibWF0ZXJpYWxzIjpbeyJkb3VibGVTaWRlZCI6dHJ1ZSwiZXh0ZW5zaW9ucyI6eyJLSFJfbWF0ZXJpYWxzX3NoZWVuIjp7InNoZWVuQ29sb3JGYWN0b3IiOlsxLjAsMS4wLDEuMF0sInNoZWVuUm91Z2huZXNzRmFjdG9yIjowLjYzMDQzNDc1MTUxMDYyMDF9fSwibmFtZSI6Ik1hdGVyaWFsIiwicGJyTWV0YWxsaWNSb3VnaG5lc3MiOnsiYmFzZUNvbG9yRmFjdG9yIjpbMC44MDAwMDAwMTE5MjA5MjksMC44MDAwMDAwMTE5MjA5MjksMC44MDAwMDAwMTE5MjA5MjksMC40MjkzNDc4MTMxMjk0MjUwNV0sIm1ldGFsbGljRmFjdG9yIjowLCJyb3VnaG5lc3NGYWN0b3IiOjAuNTIxNzM5MTI1MjUxNzd9fV0sIm1lc2hlcyI6W3sibmFtZSI6IkN1YmUiLCJwcmltaXRpdmVzIjpbeyJhdHRyaWJ1dGVzIjp7IlBPU0lUSU9OIjowLCJOT1JNQUwiOjEsIlRFWENPT1JEXzAiOjJ9LCJpbmRpY2VzIjozLCJtYXRlcmlhbCI6MH1dfSx7Im5hbWUiOiJQbGFuZSIsInByaW1pdGl2ZXMiOlt7ImF0dHJpYnV0ZXMiOnsiUE9TSVRJT04iOjQsIk5PUk1BTCI6NSwiVEVYQ09PUkRfMCI6Nn0sImluZGljZXMiOjd9XX1dLCJhY2Nlc3NvcnMiOlt7ImJ1ZmZlclZpZXciOjAsImNvbXBvbmVudFR5cGUiOjUxMjYsImNvdW50IjoyNCwibWF4IjpbMSwxLDFdLCJtaW4iOlstMSwtMSwtMV0sInR5cGUiOiJWRUMzIn0seyJidWZmZXJWaWV3IjoxLCJjb21wb25lbnRUeXBlIjo1MTI2LCJjb3VudCI6MjQsInR5cGUiOiJWRUMzIn0seyJidWZmZXJWaWV3IjoyLCJjb21wb25lbnRUeXBlIjo1MTI2LCJjb3VudCI6MjQsInR5cGUiOiJWRUMyIn0seyJidWZmZXJWaWV3IjozLCJjb21wb25lbnRUeXBlIjo1MTIzLCJjb3VudCI6MzYsInR5cGUiOiJTQ0FMQVIifSx7ImJ1ZmZlclZpZXciOjQsImNvbXBvbmVudFR5cGUiOjUxMjYsImNvdW50Ijo0LCJtYXgiOlsxLDAsMV0sIm1pbiI6Wy0xLDAsLTFdLCJ0eXBlIjoiVkVDMyJ9LHsiYnVmZmVyVmlldyI6NSwiY29tcG9uZW50VHlwZSI6NTEyNiwiY291bnQiOjQsInR5cGUiOiJWRUMzIn0seyJidWZmZXJWaWV3Ijo2LCJjb21wb25lbnRUeXBlIjo1MTI2LCJjb3VudCI6NCwidHlwZSI6IlZFQzIifSx7ImJ1ZmZlclZpZXciOjcsImNvbXBvbmVudFR5cGUiOjUxMjMsImNvdW50Ijo2LCJ0eXBlIjoiU0NBTEFSIn1dLCJidWZmZXJWaWV3cyI6W3siYnVmZmVyIjowLCJieXRlTGVuZ3RoIjoyODgsImJ5dGVPZmZzZXQiOjAsInRhcmdldCI6MzQ5NjJ9LHsiYnVmZmVyIjowLCJieXRlTGVuZ3RoIjoyODgsImJ5dGVPZmZzZXQiOjI4OCwidGFyZ2V0IjozNDk2Mn0seyJidWZmZXIiOjAsImJ5dGVMZW5ndGgiOjE5MiwiYnl0ZU9mZnNldCI6NTc2LCJ0YXJnZXQiOjM0OTYyfSx7ImJ1ZmZlciI6MCwiYnl0ZUxlbmd0aCI6NzIsImJ5dGVPZmZzZXQiOjc2OCwidGFyZ2V0IjozNDk2M30seyJidWZmZXIiOjAsImJ5dGVMZW5ndGgiOjQ4LCJieXRlT2Zmc2V0Ijo4NDAsInRhcmdldCI6MzQ5NjJ9LHsiYnVmZmVyIjowLCJieXRlTGVuZ3RoIjo0OCwiYnl0ZU9mZnNldCI6ODg4LCJ0YXJnZXQiOjM0OTYyfSx7ImJ1ZmZlciI6MCwiYnl0ZUxlbmd0aCI6MzIsImJ5dGVPZmZzZXQiOjkzNiwidGFyZ2V0IjozNDk2Mn0seyJidWZmZXIiOjAsImJ5dGVMZW5ndGgiOjEyLCJieXRlT2Zmc2V0Ijo5NjgsInRhcmdldCI6MzQ5NjN9XSwiYnVmZmVycyI6W3siYnl0ZUxlbmd0aCI6OTgwfV191AMAAEJJTgAAAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgL8AAAAAAACAvwAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAACAvwAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAIC/AAAAAAAAAAAAAAAAAAAAAAAAgL8AAAAAAACAvwAAAAAAAIC/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAIC/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAACAvwAAAAAAAIC/AAAAAAAAAAAAACA/AAAAPwAAID8AAAA/AAAgPwAAAD8AAMA+AAAAPwAAwD4AAAA/AADAPgAAAD8AACA/AACAPgAAID8AAIA+AAAgPwAAgD4AAMA+AACAPgAAwD4AAIA+AADAPgAAgD4AACA/AABAPwAAYD8AAAA/AAAgPwAAQD8AAMA+AABAPwAAAD4AAAA/AADAPgAAQD8AACA/AAAAAAAAYD8AAIA+AAAgPwAAgD8AAMA+AAAAAAAAAD4AAIA+AADAPgAAgD8BAA0AEwABABMABwAJAAYAEgAJABIAFQAXABQADgAXAA4AEQAQAAQACgAQAAoAFgAFAAIACAAFAAgACwAPAAwAAAAPAAAAAwAAAIC/AAAAAAAAgD8AAIA/AAAAAAAAgD8AAIC/AAAAAAAAgL8AAIA/AAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAgD8AAIA/AAAAAAAAAAAAAIA/AAAAAAAAAQADAAAAAwACAA=="
}
],
"source": "a=server.send(gltf64, \"graphics_view\", 0, 123, False)"
},
{
"cell_id": 15466627643580859060,
"cell_origin": "client",
"cell_type": "input",
"cells": [
{
"cell_id": 13223587008277543184,
"cell_origin": "server",
"cell_type": "latex_view",
"cells": [
{
"cell_id": 10140132123478261128,
"cell_origin": "server",
"cell_type": "input_form",
"source": "A_{m n}"
}
],
"source": "\\begin{dmath*}{}A_{m n}\\end{dmath*}"
}
],
"source": "ex:=A_{m n};"
},
{
"cell_id": 528262603261906739,
"cell_origin": "client",
"cell_type": "input",
"cells": [
{
"cell_id": 2406524992584598329,
"cell_origin": "server",
"cell_type": "error",
"source": "{\\color{red}{\\begin{verbatim}NameError: name 'GraphicsView' is not defined\n\nAt:\n cadabra2_defaults.py(323): display\n Notebook Cell (Line 1): _ = print(\"hi\"); display(_)\n\\end{verbatim}}}"
}
],
"source": "print(\"hi\");"
},
{
"cell_id": 7971209662709436916,
"cell_origin": "client",
"cell_type": "input",
"source": ""
}
],
"description": "Cadabra JSON notebook format",
"version": 1.0
}
Binary file added examples/test.glb
Binary file not shown.
89 changes: 75 additions & 14 deletions frontend/gtkmm/GraphicsView.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <gltfio/AssetLoader.h>
#include <gltfio/ResourceLoader.h>
#include <filament/LightManager.h>
#include <filament/Texture.h>
#include <filament/IndirectLight.h>

using namespace cadabra;

Expand All @@ -23,8 +25,8 @@ static constexpr uint8_t RESOURCES_BAKEDCOLOR_DATA[] = {
#include "bakedcolor.inc"
};

GraphicsView::GraphicsView(filament::Engine *engine_)
: glview(engine_), sizing(false), prev_x(0), prev_y(0), height_at_press(0), width_at_press(0)
GraphicsView::GraphicsView(filament::Engine *engine_, filament::Renderer *renderer_)
: glview(engine_, renderer_), sizing(false), prev_x(0), prev_y(0), height_at_press(0), width_at_press(0)
{
add(vbox);
vbox.add(glview);
Expand All @@ -35,7 +37,7 @@ GraphicsView::GraphicsView(filament::Engine *engine_)
| Gdk::POINTER_MOTION_MASK);

set_name("GraphicsView"); // to be able to style it with CSS
set_size_request( 400, 400 );
set_size_request( 400, 600 );
show_all();
}

Expand All @@ -44,8 +46,8 @@ void GraphicsView::set_gltf(const std::string& str)
glview.set_gltf(str);
}

GraphicsView::GLView::GLView(filament::Engine *engine_)
: engine(engine_), zoom(1.0)
GraphicsView::GLView::GLView(filament::Engine *engine_, filament::Renderer *renderer_)
: engine(engine_), renderer(renderer_), need_setup_on_first_render(true), zoom(1.0)
{
}

Expand All @@ -71,6 +73,11 @@ void GraphicsView::GLView::set_gltf(const std::string& str)
gltf_str = Glib::Base64::decode(str);
}

GraphicsView::GLView::~GLView()
{
std::cerr << "GLView going away, still implement! ****" << std::endl;
}

void GraphicsView::GLView::first_render()
{
// Setup swapchain.
Expand All @@ -79,10 +86,16 @@ void GraphicsView::GLView::first_render()
throw std::logic_error("GraphicsView::GLView::first_render: not inside an X11 window?");

Window x11_window_id = gdk_x11_window_get_xid(gdk_window->gobj());

if(engine==0)
throw std::logic_error("GraphicsView: engine not initialised.");

swapChain = engine->createSwapChain((void*)x11_window_id,
filament::SwapChain::CONFIG_TRANSPARENT);

if(swapChain==0)
throw std::logic_error("GraphicsView: cannot create swapchain.");

// Setup buffers.
vb = filament::VertexBuffer::Builder()
.vertexCount(3)
Expand Down Expand Up @@ -113,22 +126,65 @@ void GraphicsView::GLView::first_render()
.build(*engine, renderable);

scene = engine->createScene();
if(scene==0)
throw std::logic_error("GraphicsView: cannot create scene.");

view = engine->createView();
if(view==0)
throw std::logic_error("GraphicsView: cannot create view.");

view->setViewport(filament::Viewport(0, 0, 400, 400));
camera = utils::EntityManager::get().create();
cam = engine->createCamera(camera);
view->setCamera(cam);
view->setScene(scene);

// Main sun light overhead.
mainlight = utils::EntityManager::get().create();
filament::LightManager::Builder(filament::LightManager::Type::DIRECTIONAL)
.color(filament::Color::toLinear<filament::ACCURATE>(filament::sRGBColor(1.0f, 1.0f, 1.0f)))
.intensity(100000.0)
.intensity(800000.0)
.position({0.0, 10.0, 0.0})
.direction({0.0, -1.0, 0.0})
.castShadows(true)
.build(*engine, mainlight);
scene->addEntity(mainlight);

// Spotlight for structure
spotlight = utils::EntityManager::get().create();
filament::LightManager::Builder(filament::LightManager::Type::SPOT)
.color(filament::Color::toLinear<filament::ACCURATE>(filament::sRGBColor(1.0f, 1.0f, 1.0f)))
.falloff(10)
.intensity(100000000.0)
.spotLightCone(0.001, 0.4)
.position({5.0, 0, 5})
.direction({-0.71, 0.0, -0.71})
.castShadows(true)
.build(*engine, spotlight);
scene->addEntity(spotlight);

// Ambient light using a white texture.
static unsigned char oneWhitePixel[] = { 0xFF, 0xFF, 0xFF };
filament::backend::PixelBufferDescriptor whitePixBuf( oneWhitePixel, sizeof(oneWhitePixel),
filament::backend::PixelDataFormat::RGB,
filament::backend::PixelDataType::UBYTE );
static const filament::math::float3 irr[]={ filament::math::float3({1.0f, 1.0f, 1.0f}) };
ambient_texture = filament::Texture::Builder()
.width(1)
.height(1)
.levels(1)
.sampler( filament::backend::SamplerType::SAMPLER_CUBEMAP )
.format( filament::backend::TextureFormat::RGB8 )
.build( *engine );
filament::Texture::FaceOffsets offsets( 0 );
ambient_texture->setImage( *engine, 0, std::move(whitePixBuf), offsets );
ambient_light = filament::IndirectLight::Builder()
.reflections(ambient_texture)
.radiance(1, irr)
.intensity(10000.0)
.build(*engine);
scene->setIndirectLight(ambient_light);


// skybox = filament::Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*engine);
skybox = filament::Skybox::Builder().color({4.0, 4.0, 4.0, 1.0}).build(*engine);
Expand All @@ -137,7 +193,6 @@ void GraphicsView::GLView::first_render()
auto color_grading = filament::ColorGrading::Builder().toneMapper(&tone_mapper).build(*engine);
view->setColorGrading(color_grading);

renderer = engine->createRenderer();
view->setPostProcessingEnabled(true);
filament::Renderer::ClearOptions co;
co.clear=true;
Expand All @@ -161,22 +216,22 @@ void GraphicsView::GLView::first_render()
//bool GraphicsView::GLView::on_render(const Glib::RefPtr< Gdk::GLContext > &context)
bool GraphicsView::GLView::on_draw(const Cairo::RefPtr<Cairo::Context>& context)
{
static bool first=true;

int a, b;
// context->get_version(a, b);
std::cerr << "GLView::on_render " << std::endl;
// std::cerr << "GLView::on_render " << std::endl;

if(first) {
first=false;
if(need_setup_on_first_render) {
need_setup_on_first_render=false;
std::cerr << "first render" << std::endl;
first_render();
}

// Always set camera, as its position may change from one frame
// to the next.
setup_camera();

if(renderer->beginFrame(swapChain) || true /* always render */) {
std::cerr << "filament rendering" << std::endl;
// std::cerr << "filament rendering" << std::endl;
renderer->render(view);
renderer->endFrame();
}
Expand Down Expand Up @@ -231,7 +286,7 @@ void GraphicsView::GLView::setup_camera()

// setup view matrix
// const filament::math::float3 eye(0.f, 0.f, 1.f);
const filament::math::float3 eye(2.f, 2.f, 1.f);
const filament::math::float3 eye(2.f, 2.0f*(std::cos(6.28*angle/1000.0)), 1.f);
const filament::math::float3 target(0.f, 0.f, 0.f);
const filament::math::float3 up(0.f, 1.f, 0.f);
cam->lookAt(eye, target, up);
Expand All @@ -254,6 +309,12 @@ void GraphicsView::GLView::setup_camera()
// cam->setExposure(1); //, 1.2, 100.0);
}

bool GraphicsView::update(long timestamp_millis)
{
glview.angle = (glview.angle+1)%1000;
return true;
}

bool GraphicsView::GLView::load(const std::string& gltf)
{
auto materials = filament::gltfio::createJitShaderProvider(engine);
Expand Down
47 changes: 30 additions & 17 deletions frontend/gtkmm/GraphicsView.hh
Original file line number Diff line number Diff line change
Expand Up @@ -31,52 +31,65 @@ namespace cadabra {

class GraphicsView : public Gtk::EventBox {
public:
GraphicsView(filament::Engine *);
GraphicsView(filament::Engine *, filament::Renderer *);
virtual ~GraphicsView();

virtual bool on_motion_notify_event(GdkEventMotion *event) override;
virtual bool on_button_press_event(GdkEventButton *event) override;
virtual bool on_button_release_event(GdkEventButton *event) override;

/// Update the data visualised.
bool update(long timestamp_millis);

/// Set the content of this 3d view to be the gltf (json).
void set_gltf(const std::string&);

class GLView :
public Gtk::DrawingArea {
// public Gtk::GLArea {
public:
GLView(filament::Engine *);
GLView(filament::Engine *, filament::Renderer *);
virtual ~GLView();

//virtual bool on_render (const Glib::RefPtr< Gdk::GLContext > &context);
virtual bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;

void set_gltf(const std::string&);

int angle=0;
private:
bool need_setup_on_first_render;

void first_render();
void setup_camera();
bool load(const std::string& gltf_data);

std::string gltf_str;

// Filament things. The engine is owned by the NotebookWindow and passed
// in on creation of GraphicsView. The swapchain, on the other hand, is
// Filament things. The engine and renderer are owned
// by the NotebookWindow and passed in on creation of
// GraphicsView. The swapchain, on the other hand, is
// per-view, so we are responsible for it.
filament::Engine *engine=0;
filament::SwapChain *swapChain=0;
filament::Engine *engine=0;
filament::Renderer *renderer=0;
filament::SwapChain *swapChain=0;

// Test stuff for filament.
filament::VertexBuffer* vb;
filament::IndexBuffer* ib;
filament::Material* mat;
filament::Camera* cam;
filament::Scene* scene;
filament::Skybox *skybox;
filament::View* view;
utils::Entity camera;
utils::Entity renderable;
utils::Entity mainlight;
filament::Renderer *renderer;
filament::VertexBuffer *vb=0;
filament::IndexBuffer *ib=0;
filament::Material *mat=0;
filament::Camera *cam=0;
filament::Scene *scene=0;
filament::Skybox *skybox=0;
filament::View *view=0;
utils::Entity camera;
utils::Entity renderable;
utils::Entity mainlight, spotlight;
filament::Texture *ambient_texture=0;
filament::IndirectLight *ambient_light=0;

float zoom;

};

private:
Expand Down
Loading

0 comments on commit 2cba748

Please sign in to comment.