v01
This commit is contained in:
17
thirdparty/Pangolin/tools/CMakeLists.txt
vendored
Normal file
17
thirdparty/Pangolin/tools/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
if(BUILD_PANGOLIN_GUI AND BUILD_PANGOLIN_VARS )
|
||||
if(BUILD_PANGOLIN_VIDEO)
|
||||
add_subdirectory(VideoViewer)
|
||||
add_subdirectory(VideoConvert)
|
||||
add_subdirectory(VideoJson)
|
||||
add_subdirectory(Plotter)
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_EIGEN "Build support for Eigen matrix types" ON)
|
||||
if(BUILD_PANGOLIN_EIGEN)
|
||||
find_package(Eigen QUIET)
|
||||
if(EIGEN_FOUND)
|
||||
add_subdirectory(ModelViewer)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif()
|
||||
6
thirdparty/Pangolin/tools/ModelViewer/CMakeLists.txt
vendored
Normal file
6
thirdparty/Pangolin/tools/ModelViewer/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Find Pangolin (https://github.com/stevenlovegrove/Pangolin)
|
||||
find_package(Pangolin 0.3 REQUIRED)
|
||||
include_directories(${Pangolin_INCLUDE_DIRS})
|
||||
|
||||
add_executable(ModelViewer main.cpp)
|
||||
target_link_libraries(ModelViewer ${Pangolin_LIBRARIES})
|
||||
270
thirdparty/Pangolin/tools/ModelViewer/main.cpp
vendored
Normal file
270
thirdparty/Pangolin/tools/ModelViewer/main.cpp
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <queue>
|
||||
|
||||
#include <pangolin/pangolin.h>
|
||||
#include <pangolin/geometry/geometry.h>
|
||||
#include <pangolin/gl/glsl.h>
|
||||
#include <pangolin/gl/glvbo.h>
|
||||
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
|
||||
#include <pangolin/geometry/geometry_ply.h>
|
||||
#include <pangolin/geometry/glgeometry.h>
|
||||
|
||||
#include <pangolin/utils/argagg.hpp>
|
||||
|
||||
#include "shader.h"
|
||||
#include "rendertree.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <Eigen/SVD>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
const float w = 640.0f;
|
||||
const float h = 480.0f;
|
||||
const float f = 300.0f;
|
||||
|
||||
using namespace pangolin;
|
||||
|
||||
argagg::parser argparser {{
|
||||
{ "help", {"-h", "--help"}, "Print usage information and exit.", 0},
|
||||
{ "model", {"-m","--model","--mesh"}, "3D Model to load (obj or ply)", 1},
|
||||
{ "matcap", {"--matcap"}, "Matcap (material capture) images to load for shading", 1},
|
||||
{ "envmap", {"--envmap","-e"}, "Equirect environment map for skybox", 1},
|
||||
{ "mode", {"--mode"}, "Render mode to use {show_uv, show_texture, show_color, show_normal, show_matcap, show_vertex}", 1},
|
||||
{ "bounds", {"--aabb"}, "Show axis-aligned bounding-box", 0},
|
||||
{ "cull_backfaces", {"--cull"}, "Enable backface culling", 0},
|
||||
{ "spin", {"--spin"}, "Spin models around an axis {none, negx, x, negy, y, negz, z}", 1},
|
||||
}};
|
||||
|
||||
argagg::parser_results args = argparser.parse(argc, argv);
|
||||
if ( (bool)args["help"] || !args.has_option("model")) {
|
||||
std::cerr << "usage: ModelViewer [options]" << std::endl
|
||||
<< argparser << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Options
|
||||
enum class RenderMode { uv=0, tex, color, normal, matcap, vertex, num_modes };
|
||||
const std::string mode_names[] = {"SHOW_UV", "SHOW_TEXTURE", "SHOW_COLOR", "SHOW_NORMAL", "SHOW_MATCAP", "SHOW_VERTEX"};
|
||||
const std::string spin_names[] = {"NONE", "NEGX", "X", "NEGY", "Y", "NEGZ", "Z"};
|
||||
const char mode_key[] = {'u','t','c','n','m','v'};
|
||||
RenderMode current_mode = RenderMode::normal;
|
||||
for(int i=0; i < (int)RenderMode::num_modes; ++i)
|
||||
if(pangolin::ToUpperCopy(args["mode"].as<std::string>("SHOW_NORMAL")) == mode_names[i])
|
||||
current_mode = RenderMode(i);
|
||||
pangolin::AxisDirection spin_direction = pangolin::AxisNone;
|
||||
for(int i=0; i <= (int)pangolin::AxisZ; ++i)
|
||||
if(pangolin::ToUpperCopy(args["spin"].as<std::string>("none")) == spin_names[i])
|
||||
spin_direction = pangolin::AxisDirection(i);
|
||||
|
||||
bool show_bounds = args.has_option("bounds");
|
||||
bool show_axis = args.has_option("show_axis");
|
||||
bool show_x0 = args.has_option("show_x0");
|
||||
bool show_y0 = args.has_option("show_y0");
|
||||
bool show_z0 = args.has_option("show_z0");
|
||||
bool cull_backfaces = args.has_option("cull_backfaces");
|
||||
int mesh_to_show = -1;
|
||||
|
||||
// Create Window for rendering
|
||||
pangolin::CreateWindowAndBind("Main",w, h);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Define Projection and initial ModelView matrix
|
||||
pangolin::OpenGlRenderState s_cam(
|
||||
pangolin::ProjectionMatrix(w, h, f, f, w/2.0, h/2.0, 0.2, 1000),
|
||||
pangolin::ModelViewLookAt(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, pangolin::AxisY)
|
||||
);
|
||||
|
||||
// Create Interactive View in window
|
||||
pangolin::Handler3D handler(s_cam);
|
||||
pangolin::View& d_cam = pangolin::CreateDisplay()
|
||||
.SetBounds(0.0, 1.0, 0.0, 1.0, -w/h)
|
||||
.SetHandler(&handler);
|
||||
|
||||
// Load Geometry asynchronously
|
||||
std::vector<std::future<pangolin::Geometry>> geom_to_load;
|
||||
for(const auto& f : ExpandGlobOption(args["model"]))
|
||||
{
|
||||
geom_to_load.emplace_back( std::async(std::launch::async,[f](){
|
||||
return pangolin::LoadGeometry(f);
|
||||
}) );
|
||||
}
|
||||
|
||||
// Render tree for holding object position
|
||||
RenderNode root;
|
||||
std::vector<std::shared_ptr<GlGeomRenderable>> renderables;
|
||||
pangolin::AxisDirection spin_other = pangolin::AxisNone;
|
||||
auto spin_transform = std::make_shared<SpinTransform>(spin_direction);
|
||||
auto show_renderable = [&](int index){
|
||||
mesh_to_show = index;
|
||||
for(size_t i=0; i < renderables.size(); ++i) {
|
||||
if(renderables[i]) renderables[i]->show = (index == -1 || index == (int)i) ? true : false;
|
||||
}
|
||||
};
|
||||
|
||||
// Pull one piece of loaded geometry onto the GPU if ready
|
||||
Eigen::AlignedBox3f total_aabb;
|
||||
auto LoadGeometryToGpu = [&]()
|
||||
{
|
||||
for(auto& future_geom : geom_to_load) {
|
||||
if( future_geom.valid() && is_ready(future_geom) ) {
|
||||
auto geom = future_geom.get();
|
||||
auto aabb = pangolin::GetAxisAlignedBox(geom);
|
||||
total_aabb.extend(aabb);
|
||||
const Eigen::Vector3f center = total_aabb.center();
|
||||
const Eigen::Vector3f view = center + Eigen::Vector3f(1.2f,1.2f,1.2f) * std::max( (total_aabb.max() - center).norm(), (center - total_aabb.min()).norm());
|
||||
const auto mvm = pangolin::ModelViewLookAt(view[0], view[1], view[2], center[0], center[1], center[2], pangolin::AxisY);
|
||||
s_cam.SetModelViewMatrix(mvm);
|
||||
auto renderable = std::make_shared<GlGeomRenderable>(pangolin::ToGlGeometry(geom), aabb);
|
||||
renderables.push_back(renderable);
|
||||
RenderNode::Edge edge = { spin_transform, { renderable, {} } };
|
||||
root.edges.emplace_back(std::move(edge));
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Load Any matcap materials
|
||||
size_t matcap_index = 0;
|
||||
std::vector<pangolin::GlTexture> matcaps = TryLoad<pangolin::GlTexture>(ExpandGlobOption(args["matcap"]), [](const std::string& f){
|
||||
return pangolin::GlTexture(pangolin::LoadImage(f));
|
||||
});
|
||||
|
||||
// Load Any Environment maps
|
||||
size_t envmap_index = 0;
|
||||
std::vector<pangolin::GlTexture> envmaps = TryLoad<pangolin::GlTexture>(ExpandGlobOption(args["envmap"]), [](const std::string& f){
|
||||
return pangolin::GlTexture(pangolin::LoadImage(f));
|
||||
});
|
||||
|
||||
// GlSl Graphics shader program for display
|
||||
pangolin::GlSlProgram default_prog;
|
||||
auto LoadProgram = [&](const RenderMode mode){
|
||||
current_mode = mode;
|
||||
default_prog.ClearShaders();
|
||||
std::map<std::string,std::string> prog_defines;
|
||||
for(int i=0; i < (int)RenderMode::num_modes-1; ++i) {
|
||||
prog_defines[mode_names[i]] = std::to_string((int)mode == i);
|
||||
}
|
||||
default_prog.AddShader(pangolin::GlSlAnnotatedShader, default_model_shader, prog_defines);
|
||||
default_prog.Link();
|
||||
};
|
||||
LoadProgram(current_mode);
|
||||
|
||||
pangolin::GlSlProgram env_prog;
|
||||
if(envmaps.size()) {
|
||||
env_prog.AddShader(pangolin::GlSlAnnotatedShader, equi_env_shader);
|
||||
env_prog.Link();
|
||||
}
|
||||
|
||||
// Setup keyboard shortcuts.
|
||||
for(int i=0; i < (int)RenderMode::num_modes; ++i)
|
||||
pangolin::RegisterKeyPressCallback(mode_key[i], [&,i](){LoadProgram((RenderMode)i);});
|
||||
|
||||
pangolin::RegisterKeyPressCallback(PANGO_SPECIAL + PANGO_KEY_RIGHT, [&](){if(renderables.size()) show_renderable((mesh_to_show + 1) % renderables.size());});
|
||||
pangolin::RegisterKeyPressCallback(PANGO_SPECIAL + PANGO_KEY_LEFT, [&](){if(renderables.size()) show_renderable((mesh_to_show + renderables.size()-1) % renderables.size());});
|
||||
pangolin::RegisterKeyPressCallback(' ', [&](){show_renderable(-1);});
|
||||
|
||||
if(matcaps.size()) {
|
||||
pangolin::RegisterKeyPressCallback('=', [&](){matcap_index = (matcap_index+1)%matcaps.size();});
|
||||
pangolin::RegisterKeyPressCallback('-', [&](){matcap_index = (matcap_index+matcaps.size()-1)%matcaps.size();});
|
||||
}
|
||||
if(envmaps.size()) {
|
||||
pangolin::RegisterKeyPressCallback(']', [&](){envmap_index = ((envmap_index + 1) % envmaps.size());});
|
||||
pangolin::RegisterKeyPressCallback('[', [&](){envmap_index = ((envmap_index + envmaps.size()-1) % envmaps.size());});
|
||||
}
|
||||
pangolin::RegisterKeyPressCallback('s', [&](){std::swap(spin_transform->dir, spin_other);});
|
||||
pangolin::RegisterKeyPressCallback('b', [&](){show_bounds = !show_bounds;});
|
||||
pangolin::RegisterKeyPressCallback('0', [&](){cull_backfaces = !cull_backfaces;});
|
||||
|
||||
// Show axis and axis planes
|
||||
pangolin::RegisterKeyPressCallback('a', [&](){show_axis = !show_axis;});
|
||||
pangolin::RegisterKeyPressCallback('x', [&](){show_x0 = !show_x0;});
|
||||
pangolin::RegisterKeyPressCallback('y', [&](){show_y0 = !show_y0;});
|
||||
pangolin::RegisterKeyPressCallback('z', [&](){show_z0 = !show_z0;});
|
||||
|
||||
Eigen::Vector3d Pick_w = handler.Selected_P_w();
|
||||
std::vector<Eigen::Vector3d> Picks_w;
|
||||
|
||||
while( !pangolin::ShouldQuit() )
|
||||
{
|
||||
if( (handler.Selected_P_w() - Pick_w).norm() > 1E-6)
|
||||
{
|
||||
Pick_w = handler.Selected_P_w();
|
||||
Picks_w.push_back(Pick_w);
|
||||
std::cout << pangolin::FormatString("\"Translation\": [%,%,%]", Pick_w[0], Pick_w[1], Pick_w[2])
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Load any pending geometry to the GPU.
|
||||
LoadGeometryToGpu();
|
||||
|
||||
|
||||
if(d_cam.IsShown()) {
|
||||
d_cam.Activate();
|
||||
|
||||
if(cull_backfaces) {
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
|
||||
if(env_prog.Valid()) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
env_prog.Bind();
|
||||
const Eigen::Matrix4d mvmat = s_cam.GetModelViewMatrix();
|
||||
const Eigen::Matrix3f R_env_cam = mvmat.block<3,3>(0,0).cast<float>().transpose();
|
||||
Eigen::Matrix3f Kinv;
|
||||
Kinv << 1.0/f, 0.0, -(w/2.0)/f,
|
||||
0.0, 1.0/f, -(h/2.0)/f,
|
||||
0.0, 0.0, 1.0;
|
||||
|
||||
env_prog.SetUniform("R_env_camKinv", (R_env_cam*Kinv).eval());
|
||||
|
||||
const GLint vertex_handle = env_prog.GetAttributeHandle("vertex");
|
||||
const GLint xy_handle = env_prog.GetAttributeHandle("xy");
|
||||
|
||||
if(vertex_handle >= 0 && xy_handle >= 0 ) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
envmaps[envmap_index].Bind();
|
||||
const GLfloat ndc[] = { 1.0f,1.0f, -1.0f,1.0f, -1.0f,-1.0f, 1.0f,-1.0f };
|
||||
const GLfloat pix[] = { 0.0f,0.0f, w,0.0f, w,h, 0.0f,h };
|
||||
|
||||
glEnableVertexAttribArray(vertex_handle);
|
||||
glVertexAttribPointer(vertex_handle, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), ndc );
|
||||
glEnableVertexAttribArray(xy_handle);
|
||||
glVertexAttribPointer(xy_handle, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), pix );
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableVertexAttribArray(vertex_handle);
|
||||
glDisableVertexAttribArray(xy_handle);
|
||||
|
||||
env_prog.Unbind();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
default_prog.Bind();
|
||||
render_tree(
|
||||
default_prog, root, s_cam.GetProjectionMatrix(), s_cam.GetModelViewMatrix(),
|
||||
matcaps.size() ? &matcaps[matcap_index] : nullptr
|
||||
);
|
||||
default_prog.Unbind();
|
||||
|
||||
s_cam.Apply();
|
||||
if(show_x0) pangolin::glDraw_x0(10.0, 10);
|
||||
if(show_y0) pangolin::glDraw_y0(10.0, 10);
|
||||
if(show_z0) pangolin::glDraw_z0(10.0, 10);
|
||||
if(show_axis) pangolin::glDrawAxis(10.0);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
pangolin::FinishFrame();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
97
thirdparty/Pangolin/tools/ModelViewer/rendertree.h
vendored
Normal file
97
thirdparty/Pangolin/tools/ModelViewer/rendertree.h
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <pangolin/scene/tree.h>
|
||||
#include <pangolin/geometry/glgeometry.h>
|
||||
|
||||
struct Renderable
|
||||
{
|
||||
virtual ~Renderable() {}
|
||||
Renderable() : show(true) {}
|
||||
virtual void Render(pangolin::GlSlProgram& /*prog*/, const pangolin::GlTexture* /*matcap*/) const {}
|
||||
inline virtual Eigen::AlignedBox3f GetAABB() const {
|
||||
return Eigen::AlignedBox3f();
|
||||
}
|
||||
bool show;
|
||||
};
|
||||
|
||||
struct GlGeomRenderable : public Renderable
|
||||
{
|
||||
GlGeomRenderable(pangolin::GlGeometry&& glgeom, const Eigen::AlignedBox3f& aabb)
|
||||
: glgeom(std::move(glgeom)), aabb(aabb)
|
||||
{
|
||||
}
|
||||
|
||||
void Render(pangolin::GlSlProgram& prog, const pangolin::GlTexture* matcap) const override {
|
||||
if(show) {
|
||||
pangolin::GlDraw( prog, glgeom, matcap );
|
||||
}
|
||||
}
|
||||
|
||||
Eigen::AlignedBox3f GetAABB() const override {
|
||||
return aabb;
|
||||
}
|
||||
|
||||
pangolin::GlGeometry glgeom;
|
||||
Eigen::AlignedBox3f aabb;
|
||||
};
|
||||
|
||||
struct RenderableTransform
|
||||
{
|
||||
virtual ~RenderableTransform() {}
|
||||
virtual Eigen::Matrix4f GetT_pc() const = 0;
|
||||
};
|
||||
|
||||
struct FixedTransform : public RenderableTransform
|
||||
{
|
||||
FixedTransform(Eigen::Matrix4f T_pc = Eigen::Matrix4f::Identity())
|
||||
: T_pc(T_pc)
|
||||
{
|
||||
}
|
||||
|
||||
Eigen::Matrix4f GetT_pc() const override
|
||||
{
|
||||
return T_pc;
|
||||
}
|
||||
Eigen::Matrix4f T_pc;
|
||||
};
|
||||
|
||||
struct SpinTransform : public RenderableTransform
|
||||
{
|
||||
SpinTransform(pangolin::AxisDirection dir)
|
||||
:dir(dir), start(std::chrono::steady_clock::now())
|
||||
{
|
||||
}
|
||||
|
||||
Eigen::Matrix4f GetT_pc() const override
|
||||
{
|
||||
if(dir != pangolin::AxisNone) {
|
||||
const double rad_per_sec = 0.5;
|
||||
const double rad = rad_per_sec * (std::chrono::steady_clock::now() - start).count() / 1E9;
|
||||
const Eigen::Map<const Eigen::Matrix<pangolin::GLprecision,3,1>> axis(pangolin::AxisDirectionVector[dir]);
|
||||
Eigen::AngleAxisf aa(rad, axis.cast<float>());
|
||||
Eigen::Matrix4f T_pc = Eigen::Matrix4f::Identity();
|
||||
T_pc.block<3,3>(0,0) = aa.toRotationMatrix();
|
||||
return T_pc;
|
||||
}else{
|
||||
return Eigen::Matrix4f::Identity();
|
||||
}
|
||||
}
|
||||
|
||||
pangolin::AxisDirection dir;
|
||||
std::chrono::steady_clock::time_point start;
|
||||
};
|
||||
|
||||
using RenderNode = pangolin::TreeNode<std::shared_ptr<Renderable>,std::shared_ptr<RenderableTransform>>;
|
||||
void render_tree(pangolin::GlSlProgram& prog, RenderNode& node, const pangolin::OpenGlMatrix& K, const pangolin::OpenGlMatrix& T_camera_node, pangolin::GlTexture* matcap)
|
||||
{
|
||||
if(node.item) {
|
||||
prog.SetUniform("KT_cw", K * T_camera_node);
|
||||
prog.SetUniform("T_cam_norm", T_camera_node );
|
||||
node.item->Render(prog, matcap);
|
||||
}
|
||||
for(auto& e : node.edges) {
|
||||
render_tree(prog, e.node, K, T_camera_node * (pangolin::OpenGlMatrix)e.parent_child->GetT_pc(), matcap);
|
||||
}
|
||||
}
|
||||
134
thirdparty/Pangolin/tools/ModelViewer/shader.h
vendored
Normal file
134
thirdparty/Pangolin/tools/ModelViewer/shader.h
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
const std::string default_model_shader = R"Shader(
|
||||
/////////////////////////////////////////
|
||||
@start vertex
|
||||
#version 120
|
||||
|
||||
#expect SHOW_COLOR
|
||||
#expect SHOW_NORMAL
|
||||
#expect SHOW_TEXTURE
|
||||
#expect SHOW_MATCAP
|
||||
#expect SHOW_UV
|
||||
|
||||
uniform mat4 T_cam_norm;
|
||||
uniform mat4 KT_cw;
|
||||
attribute vec3 vertex;
|
||||
|
||||
#if SHOW_COLOR
|
||||
attribute vec4 color;
|
||||
varying vec4 vColor;
|
||||
void main() {
|
||||
vColor = color;
|
||||
#elif SHOW_NORMAL
|
||||
attribute vec3 normal;
|
||||
varying vec3 vNormal;
|
||||
void main() {
|
||||
vNormal = mat3(T_cam_norm) * normal;
|
||||
#elif SHOW_TEXTURE
|
||||
attribute vec2 uv;
|
||||
varying vec2 vUV;
|
||||
void main() {
|
||||
vUV = uv;
|
||||
#elif SHOW_MATCAP
|
||||
attribute vec3 normal;
|
||||
varying vec3 vNormalCam;
|
||||
void main() {
|
||||
vNormalCam = mat3(T_cam_norm) * normal;
|
||||
#elif SHOW_UV
|
||||
attribute vec2 uv;
|
||||
varying vec2 vUV;
|
||||
void main() {
|
||||
vUV = uv;
|
||||
#else
|
||||
varying vec3 vP;
|
||||
void main() {
|
||||
vP = vertex;
|
||||
#endif
|
||||
gl_Position = KT_cw * vec4(vertex, 1.0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
@start fragment
|
||||
#version 120
|
||||
#expect SHOW_COLOR
|
||||
#expect SHOW_NORMAL
|
||||
#expect SHOW_TEXTURE
|
||||
#expect SHOW_MATCAP
|
||||
#expect SHOW_UV
|
||||
|
||||
#if SHOW_COLOR
|
||||
varying vec4 vColor;
|
||||
#elif SHOW_NORMAL
|
||||
varying vec3 vNormal;
|
||||
#elif SHOW_TEXTURE
|
||||
varying vec2 vUV;
|
||||
uniform sampler2D texture_0;
|
||||
#elif SHOW_MATCAP
|
||||
varying vec3 vNormalCam;
|
||||
uniform sampler2D matcap;
|
||||
#elif SHOW_UV
|
||||
varying vec2 vUV;
|
||||
#else
|
||||
varying vec3 vP;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
#if SHOW_COLOR
|
||||
gl_FragColor = vColor;
|
||||
#elif SHOW_NORMAL
|
||||
gl_FragColor = vec4((vNormal + vec3(1.0,1.0,1.0)) / 2.0, 1.0);
|
||||
#elif SHOW_TEXTURE
|
||||
gl_FragColor = texture2D(texture_0, vUV);
|
||||
#elif SHOW_MATCAP
|
||||
vec2 uv = 0.5 * vNormalCam.xy + vec2(0.5, 0.5);
|
||||
gl_FragColor = texture2D(matcap, uv);
|
||||
#elif SHOW_UV
|
||||
gl_FragColor = vec4(vUV,1.0-vUV.x,1.0);
|
||||
#else
|
||||
gl_FragColor = vec4(vP / 100.0,1.0);
|
||||
#endif
|
||||
}
|
||||
)Shader";
|
||||
|
||||
const std::string equi_env_shader = R"Shader(
|
||||
/////////////////////////////////////////
|
||||
@start vertex
|
||||
#version 120
|
||||
attribute vec2 vertex;
|
||||
attribute vec2 xy;
|
||||
varying vec2 vXY;
|
||||
|
||||
void main() {
|
||||
vXY = xy;
|
||||
gl_Position = vec4(vertex,0.0,1.0);
|
||||
}
|
||||
|
||||
@start fragment
|
||||
#version 120
|
||||
#define M_PI 3.1415926538
|
||||
uniform sampler2D texture_0;
|
||||
uniform mat3 R_env_camKinv;
|
||||
varying vec2 vXY;
|
||||
|
||||
vec2 RayToEquirect(vec3 ray)
|
||||
{
|
||||
float n = 1.0;
|
||||
float m = 1.0;
|
||||
float lamda = acos(ray.y/sqrt(1.0-ray.z*ray.z));
|
||||
if(ray.x < 0) lamda = -lamda;
|
||||
float phi = asin(ray.z);
|
||||
float u = n*lamda/(2.0*M_PI)+n/2.0;
|
||||
float v = m/2.0 + m*phi/M_PI;
|
||||
return vec2(u,v);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 ray_env = normalize(R_env_camKinv * vec3(vXY, 1.0));
|
||||
gl_FragColor = texture2D(texture_0, RayToEquirect(ray_env));
|
||||
}
|
||||
)Shader";
|
||||
|
||||
}
|
||||
30
thirdparty/Pangolin/tools/ModelViewer/util.h
vendored
Normal file
30
thirdparty/Pangolin/tools/ModelViewer/util.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
template<typename R>
|
||||
bool is_ready(std::future<R> const& f)
|
||||
{ return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready; }
|
||||
|
||||
inline std::vector<std::string> ExpandGlobOption(const argagg::option_results& opt)
|
||||
{
|
||||
std::vector<std::string> expanded;
|
||||
for(const auto& o : opt.all)
|
||||
{
|
||||
const std::string r = o.as<std::string>();
|
||||
pangolin::FilesMatchingWildcard(r, expanded);
|
||||
}
|
||||
return expanded;
|
||||
}
|
||||
|
||||
template<typename Tout, typename Tin, typename F>
|
||||
inline std::vector<Tout> TryLoad(const std::vector<Tin>& in, const F& load_func)
|
||||
{
|
||||
std::vector<Tout> loaded;
|
||||
for(const Tin& file : in)
|
||||
{
|
||||
try {
|
||||
loaded.emplace_back(load_func(file));
|
||||
}catch(const std::exception&) {
|
||||
}
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
53
thirdparty/Pangolin/tools/Plotter/CMakeLists.txt
vendored
Normal file
53
thirdparty/Pangolin/tools/Plotter/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
# Find Pangolin (https://github.com/stevenlovegrove/Pangolin)
|
||||
find_package(Pangolin 0.4 REQUIRED)
|
||||
include_directories(${Pangolin_INCLUDE_DIRS})
|
||||
|
||||
add_executable(Plotter main.cpp)
|
||||
target_link_libraries(Plotter ${Pangolin_LIBRARIES})
|
||||
|
||||
|
||||
# Make file association
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" AND ${CMAKE_MAJOR_VERSION} VERSION_GREATER "2.9.9" )
|
||||
file( GENERATE
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pangoplot.desktop"
|
||||
CONTENT
|
||||
"[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Categories=Utility
|
||||
Name=PangoPlotter
|
||||
GenericName=Plotter
|
||||
Comment=View CSV data series
|
||||
Exec=$<TARGET_FILE:Plotter> %U
|
||||
TryExec=$<TARGET_FILE:Plotter>
|
||||
Icon=application-x-pango
|
||||
Terminal=false
|
||||
StartupNotify=false
|
||||
MimeType=text/csv;text/comma-separated-values;application/x-pangoplot;application/csv"
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
register-mime-info-plotter
|
||||
COMMAND mkdir -p $ENV{HOME}/.local/share/mime/packages/
|
||||
COMMAND mkdir -p $ENV{HOME}/.local/share/applications/
|
||||
COMMAND mkdir -p $ENV{HOME}/.local/share/icons/hicolor/scalable/mimetypes/
|
||||
COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/application-x-pangoplot.xml" $ENV{HOME}/.local/share/mime/packages/
|
||||
COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/../VideoViewer/application-x-pango.svg" $ENV{HOME}/.local/share/icons/hicolor/scalable/mimetypes/
|
||||
COMMAND cp "${CMAKE_CURRENT_BINARY_DIR}/pangoplot.desktop" $ENV{HOME}/.local/share/applications/
|
||||
COMMAND gtk-update-icon-cache $ENV{HOME}/.local/share/icons/hicolor -f -t
|
||||
COMMAND update-mime-database $ENV{HOME}/.local/share/mime
|
||||
COMMAND update-desktop-database $ENV{HOME}/.local/share/applications
|
||||
DEPENDS Plotter
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
#######################################################
|
||||
## Install
|
||||
|
||||
install(TARGETS Plotter
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
9
thirdparty/Pangolin/tools/Plotter/application-x-pangoplot.xml
vendored
Normal file
9
thirdparty/Pangolin/tools/Plotter/application-x-pangoplot.xml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
<mime-type type="application/x-pangoplot">
|
||||
<comment>Pangolin Video File</comment>
|
||||
<icon name="application-x-pango"/>
|
||||
<glob-deleteall/>
|
||||
<glob pattern="*.csv"/>
|
||||
</mime-type>
|
||||
</mime-info>
|
||||
87
thirdparty/Pangolin/tools/Plotter/csv_data_loader.h
vendored
Normal file
87
thirdparty/Pangolin/tools/Plotter/csv_data_loader.h
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include <pangolin/platform.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
class CsvDataLoader
|
||||
{
|
||||
public:
|
||||
CsvDataLoader(const std::vector<std::string>& csv_files, char delim = ',')
|
||||
: delim(delim)
|
||||
{
|
||||
for(const auto& f : csv_files) {
|
||||
if(f == "-") {
|
||||
streams.push_back(&std::cin);
|
||||
}else{
|
||||
std::ifstream* pFile = new std::ifstream(f);
|
||||
owned_streams.emplace_back(pFile);
|
||||
streams.push_back(pFile);
|
||||
PANGO_ASSERT(pFile->is_open());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SkipStreamRows(const std::vector<size_t>& rows_to_skip)
|
||||
{
|
||||
if(rows_to_skip.size()) {
|
||||
PANGO_ASSERT(rows_to_skip.size() == streams.size());
|
||||
std::vector<std::string> dummy_row;
|
||||
|
||||
for(size_t i=0; i < streams.size(); ++i) {
|
||||
for(size_t r=0; r < rows_to_skip[i]; ++r) {
|
||||
if(!AppendColumns(dummy_row, *streams[i], delim)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadRow(std::vector<std::string>& row)
|
||||
{
|
||||
row.clear();
|
||||
|
||||
for(auto& s : streams) {
|
||||
if(!AppendColumns(row, *s, delim)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool AppendColumns(std::vector<std::string>& cols, std::istream& s, char delim)
|
||||
{
|
||||
// Read line from stream
|
||||
std::string row;
|
||||
std::getline(s,row);
|
||||
|
||||
// Failure if no lines to read
|
||||
if(!s.good()) return false;
|
||||
|
||||
std::stringstream row_stream(row);
|
||||
std::string cell;
|
||||
|
||||
// Read cells
|
||||
while(std::getline(row_stream, cell, delim)) {
|
||||
cols.push_back(cell);
|
||||
}
|
||||
|
||||
// Check for an empty trailing cell
|
||||
if (!row_stream && cell.empty()) {
|
||||
cols.push_back("");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char delim;
|
||||
std::vector<std::istream*> streams;
|
||||
std::vector<std::unique_ptr<std::istream>> owned_streams;
|
||||
};
|
||||
126
thirdparty/Pangolin/tools/Plotter/main.cpp
vendored
Normal file
126
thirdparty/Pangolin/tools/Plotter/main.cpp
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
#include <pangolin/pangolin.h>
|
||||
#include <pangolin/utils/argagg.hpp>
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
|
||||
#include "csv_data_loader.h"
|
||||
|
||||
namespace argagg{ namespace convert {
|
||||
|
||||
template<>
|
||||
pangolin::Rangef arg<pangolin::Rangef>(char const* str)
|
||||
{
|
||||
std::stringstream ss(str);
|
||||
pangolin::Rangef r;
|
||||
ss >> r.min; ss.get(); ss >> r.max;
|
||||
return r;
|
||||
}
|
||||
}}
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
// Parse command line
|
||||
argagg::parser argparser {{
|
||||
{ "help", {"-h", "--help"}, "Print usage information and exit.", 0},
|
||||
{ "header", {"-H","--header"}, "Treat 1st row as column titles", 0},
|
||||
{ "x", {"-x"}, "X-axis series to plot, seperated by commas (default: '$i')", 1},
|
||||
{ "y", {"-y"}, "Y-axis series to plot, seperated by commas (eg: '$0,sin($1),sqrt($2+$3)' )", 1},
|
||||
{ "delim", {"-d"}, "Expected column delimitter (default: ',')", 1},
|
||||
{ "xrange", {"-X","--x-range"}, "X-Axis min:max view (default: '0:100')", 1},
|
||||
{ "yrange", {"-Y","--y-range"}, "Y-Axis min:max view (default: '0:100')", 1},
|
||||
{ "skip", {"-s","--skip"}, "Skip n rows of file, seperated by commas per file (default: '0,...')", 1},
|
||||
}};
|
||||
|
||||
argagg::parser_results args = argparser.parse(argc, argv);
|
||||
if ( (bool)args["help"] || !args.pos.size()) {
|
||||
std::cerr << "Usage: Plotter [options] file1.csv [fileN.csv]*" << std::endl
|
||||
<< argparser << std::endl
|
||||
<< " where: $i is a placeholder for the datum index," << std::endl
|
||||
<< " $0, $1, ... are placeholders for the 0th, 1st, ... sequential datum values over the input files" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Default values
|
||||
const std::string xs = args["x"].as<std::string>("$i");
|
||||
const std::string ys = args["y"].as<std::string>("$0");
|
||||
const char delim = args["delim"].as<char>(',');
|
||||
const pangolin::Rangef xrange = args["xrange"].as<>(pangolin::Rangef(0.0f,100.0f));
|
||||
const pangolin::Rangef yrange = args["yrange"].as<>(pangolin::Rangef(0.0f,100.0f));
|
||||
const std::string skips = args["skip"].as<std::string>("");
|
||||
const std::vector<std::string> skipvecstr = pangolin::Split(skips,',');
|
||||
std::vector<size_t> skipvec;
|
||||
for(const std::string& s : skipvecstr) {
|
||||
skipvec.push_back(std::stoul(s));
|
||||
}
|
||||
if( !(skipvec.size() == 0 || skipvec.size() == args.count()) )
|
||||
{
|
||||
std::cerr << "Skip argument must be empty or correspond to the number of files specified (" << args.count() << ")" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pangolin::DataLog log;
|
||||
|
||||
CsvDataLoader csv_loader(args.all_as<std::string>(), delim);
|
||||
|
||||
if(args["header"]) {
|
||||
std::vector<std::string> labels;
|
||||
csv_loader.ReadRow(labels);
|
||||
log.SetLabels(labels);
|
||||
}
|
||||
|
||||
// Load asynchronously incase the file is large or is being read interactively from stdin
|
||||
bool keep_loading = true;
|
||||
std::thread data_thread([&](){
|
||||
if(!csv_loader.SkipStreamRows(skipvec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> row;
|
||||
|
||||
while(keep_loading && csv_loader.ReadRow(row)) {
|
||||
std::vector<float> row_num(row.size(), std::numeric_limits<float>::quiet_NaN() );
|
||||
for(size_t i=0; i< row_num.size(); ++i) {
|
||||
try{
|
||||
row_num[i] = std::stof(row[i]);
|
||||
}catch(const std::invalid_argument& e){
|
||||
std::cerr << "Warning: couldn't parse '" << row[i] << "' as numeric data (use -H option to include header)" << std::endl;
|
||||
}
|
||||
}
|
||||
log.Log(row_num);
|
||||
}
|
||||
});
|
||||
|
||||
pangolin::CreateWindowAndBind("Plotter", 640, 480);
|
||||
|
||||
pangolin::Plotter plotter(&log, xrange.min, xrange.max, yrange.min, yrange.max, 0.001, 0.001);
|
||||
if( (bool)args["x"] || (bool)args["y"]) {
|
||||
plotter.ClearSeries();
|
||||
std::vector<std::string> xvec = pangolin::Split(xs,',');
|
||||
std::vector<std::string> yvec = pangolin::Split(ys,',');
|
||||
|
||||
if( !(xvec.size() == 1 || xvec.size() == yvec.size()) ) {
|
||||
std::cout << "x-series dimensions must be one, or equal to y-series dimensions" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(size_t i=0; i < yvec.size(); ++i) {
|
||||
plotter.AddSeries( (xvec.size()==1) ? xvec[0] : xvec[i],yvec[i]);
|
||||
}
|
||||
}
|
||||
|
||||
plotter.SetBounds(0.0, 1.0, 0.0, 1.0);
|
||||
pangolin::DisplayBase().AddDisplay(plotter);
|
||||
|
||||
while( !pangolin::ShouldQuit() )
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
pangolin::FinishFrame();
|
||||
}
|
||||
|
||||
keep_loading = false;
|
||||
data_thread.join();
|
||||
|
||||
return 0;
|
||||
}
|
||||
15
thirdparty/Pangolin/tools/VideoConvert/CMakeLists.txt
vendored
Normal file
15
thirdparty/Pangolin/tools/VideoConvert/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Find Pangolin (https://github.com/stevenlovegrove/Pangolin)
|
||||
find_package(Pangolin 0.4 REQUIRED)
|
||||
include_directories(${Pangolin_INCLUDE_DIRS})
|
||||
|
||||
add_executable(VideoConvert main.cpp)
|
||||
target_link_libraries(VideoConvert ${Pangolin_LIBRARIES})
|
||||
|
||||
#######################################################
|
||||
## Install
|
||||
|
||||
install(TARGETS VideoConvert
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
75
thirdparty/Pangolin/tools/VideoConvert/main.cpp
vendored
Normal file
75
thirdparty/Pangolin/tools/VideoConvert/main.cpp
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
#include <pangolin/pangolin.h>
|
||||
#include <pangolin/video/video_input.h>
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
#include <pangolin/utils/timer.h>
|
||||
|
||||
void VideoViewer(const std::string& input_uri, const std::string& output_uri)
|
||||
{
|
||||
pangolin::Var<bool> video_wait("video.wait", true);
|
||||
pangolin::Var<bool> video_newest("video.newest", false);
|
||||
|
||||
// Open Video by URI
|
||||
pangolin::VideoInput video(input_uri, output_uri);
|
||||
const size_t num_streams = video.Streams().size();
|
||||
|
||||
pangolin::VideoPlaybackInterface* playback = pangolin::FindFirstMatchingVideoInterface<pangolin::VideoPlaybackInterface>(video);
|
||||
|
||||
// Output details of video stream
|
||||
for(size_t s = 0; s < num_streams; ++s)
|
||||
{
|
||||
const pangolin::StreamInfo& si = video.Streams()[s];
|
||||
std::cout << "Stream " << s << ": " << si.Width() << " x " << si.Height()
|
||||
<< " " << si.PixFormat().format << " (pitch: " << si.Pitch() << " bytes)" << std::endl;
|
||||
}
|
||||
|
||||
// Image buffers
|
||||
std::vector<pangolin::Image<unsigned char> > images;
|
||||
std::vector<unsigned char> buffer;
|
||||
buffer.resize(video.SizeBytes()+1);
|
||||
|
||||
// Record all frames
|
||||
video.Record();
|
||||
|
||||
// Stream and display video
|
||||
while(true)
|
||||
{
|
||||
if( !video.Grab(&buffer[0], images, video_wait, video_newest) ) {
|
||||
break;
|
||||
}
|
||||
if( playback ) {
|
||||
std::cout << "Frames complete: " << playback->GetCurrentFrameId() << " / " << playback->GetTotalFrames() << '\r';
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
const std::string dflt_output_uri = "pango:[unique_filename]//video.pango";
|
||||
|
||||
if( argc > 1 ) {
|
||||
const std::string input_uri = std::string(argv[1]);
|
||||
const std::string output_uri = (argc > 2) ? std::string(argv[2]) : dflt_output_uri;
|
||||
try{
|
||||
VideoViewer(input_uri, output_uri);
|
||||
} catch (const pangolin::VideoException& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}else{
|
||||
std::cout << "Usage : VideoConvert [video-in-uri] [video-out-uri]" << std::endl << std::endl;
|
||||
std::cout << "Where video-in-uri describes a stream or file resource, e.g." << std::endl;
|
||||
std::cout << "\tfile:[realtime=1]///home/user/video/movie.pvn" << std::endl;
|
||||
std::cout << "\tfile:///home/user/video/movie.avi" << std::endl;
|
||||
std::cout << "\tfiles:///home/user/seqiemce/foo*.jpeg" << std::endl;
|
||||
std::cout << "\tdc1394:[fmt=RGB24,size=640x480,fps=30,iso=400,dma=10]//0" << std::endl;
|
||||
std::cout << "\tdc1394:[fmt=FORMAT7_1,size=640x480,pos=2+2,iso=400,dma=10]//0" << std::endl;
|
||||
std::cout << "\tv4l:///dev/video0" << std::endl;
|
||||
std::cout << "\tconvert:[fmt=RGB24]//v4l:///dev/video0" << std::endl;
|
||||
std::cout << "\tmjpeg://http://127.0.0.1/?action=stream" << std::endl;
|
||||
std::cout << "\topenni:[img1=rgb]//" << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
18
thirdparty/Pangolin/tools/VideoJson/CMakeLists.txt
vendored
Normal file
18
thirdparty/Pangolin/tools/VideoJson/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Find Pangolin (https://github.com/stevenlovegrove/Pangolin)
|
||||
find_package(Pangolin 0.4 REQUIRED)
|
||||
include_directories(${Pangolin_INCLUDE_DIRS})
|
||||
|
||||
add_executable(VideoJsonPrint main-print.cpp)
|
||||
target_link_libraries(VideoJsonPrint ${Pangolin_LIBRARIES})
|
||||
|
||||
add_executable(VideoJsonTransform main-transform.cpp)
|
||||
target_link_libraries(VideoJsonTransform ${Pangolin_LIBRARIES})
|
||||
|
||||
#######################################################
|
||||
## Install
|
||||
|
||||
install(TARGETS VideoJsonPrint VideoJsonTransform
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
36
thirdparty/Pangolin/tools/VideoJson/main-print.cpp
vendored
Normal file
36
thirdparty/Pangolin/tools/VideoJson/main-print.cpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <pangolin/pangolin.h>
|
||||
|
||||
#include <pangolin/log/packetstream_reader.h>
|
||||
#include <pangolin/log/packetstream_writer.h>
|
||||
#include <pangolin/video/video.h>
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
if( argc == 2) {
|
||||
const std::string filename = std::string(argv[1]);
|
||||
pangolin::PacketStreamReader reader(filename);
|
||||
|
||||
// Extract JSON
|
||||
picojson::value all_properties;
|
||||
|
||||
for(size_t i=0; i < reader.Sources().size(); ++i) {
|
||||
picojson::value source_props;
|
||||
|
||||
const pangolin::PacketStreamSource& src = reader.Sources()[i];
|
||||
source_props["device_properties"] = src.info["device"];
|
||||
|
||||
// Seek through index, loading frame properties
|
||||
for(size_t framenum=0; framenum < src.index.size(); ++framenum) {
|
||||
reader.Seek(src.id, framenum);
|
||||
pangolin::Packet pkt = reader.NextFrame();
|
||||
source_props["frame_properties"].push_back(pkt.meta);
|
||||
}
|
||||
|
||||
all_properties.push_back(source_props);
|
||||
}
|
||||
|
||||
std::cout << all_properties.serialize(true) << std::endl;
|
||||
}else{
|
||||
std::cout << "Usage: \n\tPangoJsonPrint filename.pango" << std::endl;
|
||||
}
|
||||
}
|
||||
63
thirdparty/Pangolin/tools/VideoJson/main-transform.cpp
vendored
Normal file
63
thirdparty/Pangolin/tools/VideoJson/main-transform.cpp
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <pangolin/pangolin.h>
|
||||
|
||||
#include <pangolin/log/packetstream_reader.h>
|
||||
#include <pangolin/log/packetstream_writer.h>
|
||||
#include <pangolin/video/video.h>
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
if( argc == 3) {
|
||||
const std::string filein = std::string(argv[1]);
|
||||
const std::string fileout = std::string(argv[2]);
|
||||
PANGO_ASSERT(filein != fileout);
|
||||
|
||||
pangolin::PacketStreamReader reader(filein);
|
||||
pangolin::PacketStreamWriter writer(fileout);
|
||||
|
||||
// Read new JSON from command line
|
||||
picojson::value all_properties;
|
||||
|
||||
std::cout << "Reading JSON from input" << std::endl;
|
||||
std::cin >> all_properties;
|
||||
std::cout << "+ done" << std::endl;
|
||||
|
||||
PANGO_ASSERT(all_properties.size() == reader.Sources().size());
|
||||
|
||||
for(size_t i=0; i < reader.Sources().size(); ++i) {
|
||||
const picojson::value& src_json = all_properties[i];
|
||||
pangolin::PacketStreamSource src = reader.Sources()[i];
|
||||
|
||||
PANGO_ASSERT(src_json.contains("frame_properties"));
|
||||
PANGO_ASSERT(src_json.contains("device_properties"));
|
||||
PANGO_ASSERT(src_json["frame_properties"].size() == src.index.size());
|
||||
|
||||
// Ensure the index gets rewritten, and update the device properties.
|
||||
src.index.clear();
|
||||
src.info["device"] = src_json["device_properties"];
|
||||
writer.AddSource(src);
|
||||
}
|
||||
|
||||
std::cout << "Writing video with new JSON to '" << fileout << "'" << std::endl;
|
||||
try{
|
||||
std::vector<char> buffer;
|
||||
|
||||
while(true)
|
||||
{
|
||||
pangolin::Packet pkt = reader.NextFrame();
|
||||
buffer.resize(pkt.BytesRemaining());
|
||||
pkt.Stream().read(buffer.data(), buffer.size());
|
||||
|
||||
const picojson::value& new_frame_json = all_properties[pkt.src]["frame_properties"][pkt.sequence_num];
|
||||
writer.WriteSourcePacket(pkt.src, buffer.data(), pkt.time, buffer.size(), new_frame_json);
|
||||
std::cout << "Frames complete: " << pkt.sequence_num << " / " << reader.Sources()[pkt.src].index.size() << '\r';
|
||||
std::cout.flush();
|
||||
}
|
||||
}catch(const std::runtime_error &)
|
||||
{
|
||||
}
|
||||
std::cout << std::endl << "+ done" << std::endl;
|
||||
|
||||
}else{
|
||||
std::cout << "Usage: \n\tPangoJsonTransform file_in.pango file_out.pango" << std::endl;
|
||||
}
|
||||
}
|
||||
53
thirdparty/Pangolin/tools/VideoViewer/CMakeLists.txt
vendored
Normal file
53
thirdparty/Pangolin/tools/VideoViewer/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
# Find Pangolin (https://github.com/stevenlovegrove/Pangolin)
|
||||
find_package(Pangolin 0.4 REQUIRED)
|
||||
include_directories(${Pangolin_INCLUDE_DIRS})
|
||||
|
||||
add_executable(VideoViewer main.cpp)
|
||||
target_link_libraries(VideoViewer ${Pangolin_LIBRARIES})
|
||||
|
||||
|
||||
# Make file association
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" AND ${CMAKE_MAJOR_VERSION} VERSION_GREATER "2.9.9" )
|
||||
file( GENERATE
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pango.desktop"
|
||||
CONTENT
|
||||
"[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Categories=AudioVideo;Player;Video;
|
||||
Name=PangoVideoViewer
|
||||
GenericName=Video Viewer
|
||||
Comment=View images and video
|
||||
Exec=$<TARGET_FILE:VideoViewer> %U
|
||||
TryExec=$<TARGET_FILE:VideoViewer>
|
||||
Icon=application-x-pango
|
||||
Terminal=false
|
||||
StartupNotify=false
|
||||
MimeType=application/x-pango;image/x-portable-graymap;image/x-portable-pixmap;image/x-tga;image/tiff;image/jpeg;image/png;"
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
register-mime-info-videoviewer
|
||||
COMMAND mkdir -p $ENV{HOME}/.local/share/mime/packages/
|
||||
COMMAND mkdir -p $ENV{HOME}/.local/share/applications/
|
||||
COMMAND mkdir -p $ENV{HOME}/.local/share/icons/hicolor/scalable/mimetypes/
|
||||
COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/application-x-pango.xml" $ENV{HOME}/.local/share/mime/packages/
|
||||
COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/application-x-pango.svg" $ENV{HOME}/.local/share/icons/hicolor/scalable/mimetypes/
|
||||
COMMAND cp "${CMAKE_CURRENT_BINARY_DIR}/pango.desktop" $ENV{HOME}/.local/share/applications/
|
||||
COMMAND gtk-update-icon-cache $ENV{HOME}/.local/share/icons/hicolor -f -t
|
||||
COMMAND update-mime-database $ENV{HOME}/.local/share/mime
|
||||
COMMAND update-desktop-database $ENV{HOME}/.local/share/applications
|
||||
DEPENDS VideoViewer
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
#######################################################
|
||||
## Install
|
||||
|
||||
install(TARGETS VideoViewer
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
424
thirdparty/Pangolin/tools/VideoViewer/application-x-pango.svg
vendored
Normal file
424
thirdparty/Pangolin/tools/VideoViewer/application-x-pango.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 199 KiB |
10
thirdparty/Pangolin/tools/VideoViewer/application-x-pango.xml
vendored
Normal file
10
thirdparty/Pangolin/tools/VideoViewer/application-x-pango.xml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
<mime-type type="application/x-pango">
|
||||
<comment>Pangolin Video File</comment>
|
||||
<icon name="application-x-pango"/>
|
||||
<glob-deleteall/>
|
||||
<glob pattern="*.pango"/>
|
||||
<glob pattern="*.oni"/>
|
||||
</mime-type>
|
||||
</mime-info>
|
||||
51
thirdparty/Pangolin/tools/VideoViewer/main.cpp
vendored
Normal file
51
thirdparty/Pangolin/tools/VideoViewer/main.cpp
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <pangolin/pangolin.h>
|
||||
#include <pangolin/tools/video_viewer.h>
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
const std::string dflt_output_uri = "pango:[unique_filename]//video.pango";
|
||||
|
||||
if( argc > 1 ) {
|
||||
const std::string input_uri = std::string(argv[1]);
|
||||
const std::string output_uri = (argc > 2) ? std::string(argv[2]) : dflt_output_uri;
|
||||
try{
|
||||
pangolin::RunVideoViewerUI(input_uri, output_uri);
|
||||
} catch (const pangolin::VideoException& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}else{
|
||||
const std::string input_uris[] = {
|
||||
"dc1394:[fps=30,dma=10,size=640x480,iso=400]//0",
|
||||
"convert:[fmt=RGB24]//v4l:///dev/video0",
|
||||
"convert:[fmt=RGB24]//v4l:///dev/video1",
|
||||
"openni:[img1=rgb]//",
|
||||
"test:[size=160x120,n=1,fmt=RGB24]//"
|
||||
""
|
||||
};
|
||||
|
||||
std::cout << "Usage : VideoViewer [video-uri]" << std::endl << std::endl;
|
||||
std::cout << "Where video-uri describes a stream or file resource, e.g." << std::endl;
|
||||
std::cout << "\tfile:[realtime=1]///home/user/video/movie.pvn" << std::endl;
|
||||
std::cout << "\tfile:///home/user/video/movie.avi" << std::endl;
|
||||
std::cout << "\tfiles:///home/user/seqiemce/foo*.jpeg" << std::endl;
|
||||
std::cout << "\tdc1394:[fmt=RGB24,size=640x480,fps=30,iso=400,dma=10]//0" << std::endl;
|
||||
std::cout << "\tdc1394:[fmt=FORMAT7_1,size=640x480,pos=2+2,iso=400,dma=10]//0" << std::endl;
|
||||
std::cout << "\tv4l:///dev/video0" << std::endl;
|
||||
std::cout << "\tconvert:[fmt=RGB24]//v4l:///dev/video0" << std::endl;
|
||||
std::cout << "\tmjpeg://http://127.0.0.1/?action=stream" << std::endl;
|
||||
std::cout << "\topenni:[img1=rgb]//" << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// Try to open some video device
|
||||
for(int i=0; !input_uris[i].empty(); ++i )
|
||||
{
|
||||
try{
|
||||
pango_print_info("Trying: %s\n", input_uris[i].c_str());
|
||||
pangolin::RunVideoViewerUI(input_uris[i], dflt_output_uri);
|
||||
return 0;
|
||||
}catch(const pangolin::VideoException&) { }
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user