source/viewer/GlViewer.cpp (127 lines of code) (raw):
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <boost/algorithm/string.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "source/gpu/GlfwUtil.h"
#include "source/render/RigScene.h"
#include "source/render/VideoFile.h"
#include "source/util/SystemUtil.h"
using namespace fb360_dep;
const std::string kUsageMessage = R"(
- OpenGL-based viewer for binary 6dof data files.
Keyboard navigation:
- w, a, s, d as well as the arrow keyes will rotate the view.
- z, and x move forward and backward.
Mouse navigation:
- Left button drag the mouse to rotate.
- Right button drag the mouse to pan.
Misc:
- Hit 'r' to reset the view to what was on the command line.
- Hit 'p' to dump the current view parameters in the command line format.
- Example:
./GlViewer \
--rig=/path/to/output/fused/rig_calibrated.json \
--catalog=/path/to/output/fused/fused.json \
--strip_files=/path/to/output/fused/fused_0.bin
)";
DEFINE_string(catalog, "", "json file describing strip files");
DEFINE_string(strip_files, "", "comma-separated list of strip files");
DEFINE_int32(readahead, 3, "how many frames to read ahead");
DEFINE_string(rig, "", "path to rig .json file (required)");
static const float kEffectIncrement = 1; // meters per frame
static const float kEffectMax = 15; // meters
// Rig scene use a flipped coordinate system relative to canopy scene
// so we permute the coordinates on the way to the graphics pipeline
// match opengl's coordinate system.
static const Eigen::Matrix4f kPermutationMatrix(
(Eigen::Matrix4f() << 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1).finished());
class GlViewer : public GlWindow {
private:
public:
RigScene scene;
std::unique_ptr<AsyncLoader> asyncLoader;
std::unique_ptr<VideoFile> videoFile;
GlViewer() : GlWindow("GL viewer", 512, 512), scene(RigScene(FLAGS_rig)) {
// Initialize the viewer
CHECK_NE(FLAGS_strip_files, "");
std::vector<std::string> disks;
boost::split(disks, FLAGS_strip_files, boost::is_any_of(","));
videoFile = std::make_unique<VideoFile>(FLAGS_catalog, disks);
if (videoFile->frames.size() == 1) {
videoFile->readBegin(scene);
scene.subframes = videoFile->readEnd(scene);
} else {
for (int i = 0; i < FLAGS_readahead; ++i) {
videoFile->readBegin(scene);
}
}
}
void keyPress(int key, int s, int action, int mods) override {
GlWindow::keyPress(key, s, action, mods);
if (action != GLFW_PRESS) {
switch (key) {
case GLFW_KEY_0:
scene.debug = 0;
break;
case GLFW_KEY_1:
scene.debug = 1;
break;
case GLFW_KEY_2:
scene.debug = 2;
break;
case GLFW_KEY_3:
scene.debug = 3;
break;
case GLFW_KEY_4:
scene.debug = 4;
break;
case GLFW_KEY_5:
scene.debug = 5;
break;
case GLFW_KEY_6:
scene.debug = 6;
break;
case GLFW_KEY_7:
scene.debug = 7;
break;
case GLFW_KEY_8:
scene.debug = 8;
break;
case GLFW_KEY_9:
scene.debug = 9;
break;
case GLFW_KEY_L:
effectBegin();
break;
}
}
}
void effectBegin() {
scene.effect = kEffectIncrement;
}
void effectUpdate() {
if (scene.effect != 0) {
scene.effect += kEffectIncrement;
}
if (scene.effect > kEffectMax) {
scene.effect = 0;
}
}
void display() override {
if (videoFile->frames.size() > 1) {
scene.destroyFrame(scene.subframes);
scene.subframes = videoFile->readEnd(scene);
videoFile->readBegin(scene, true);
}
// Loop effect
effectUpdate();
// draw the scene
scene.render(projection * transform.matrix() * kPermutationMatrix, 0, true, wireframe);
// Let the read thread drain if when we finish
if (done && asyncLoader) {
asyncLoader->wait();
}
}
};
int main(int argc, char* argv[]) {
FLAGS_stderrthreshold = 0;
FLAGS_logtostderr = 0;
system_util::initDep(argc, argv, kUsageMessage);
CHECK_NE(FLAGS_rig, "");
CHECK_NE(FLAGS_catalog, "");
GlViewer glViewer;
GlWindow::mainLoop();
return EXIT_SUCCESS;
}