Skip to content

Instantly share code, notes, and snippets.

@kylemcdonald
Last active October 11, 2017 18:20
Show Gist options
  • Save kylemcdonald/7f414f4d9a70fc6a233eeebd27bb56eb to your computer and use it in GitHub Desktop.
Save kylemcdonald/7f414f4d9a70fc6a233eeebd27bb56eb to your computer and use it in GitHub Desktop.
Seene Viewer with C++ in openFrameworks.
// Based on https://github.com/detunized/seene-viewer
#include "ofMain.h"
inline bool ends_with(std::string const & value, std::string const & ending)
{
if (ending.size() > value.size()) return false;
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}
class Seene {
private:
int readInt(ofBuffer buffer, int offset) {
return ((int*) (buffer.getData() + offset))[0];
}
float readFloat(ofBuffer buffer, int offset) {
return ((float*) (buffer.getData() + offset))[0];
}
public:
ofImage tex;
ofMesh mesh;
ofBuffer buffer;
int version;
int cameraWidth, cameraHeight;
float cameraFx, cameraFy, cameraK1, cameraK2;
int depthMapWidth, depthMapHeight;
int headerSize;
float* depthMap;
void load(string sceneFilename, string textureFilename="", bool rotateTexture=true) {
if(textureFilename != "") {
loadTexture(textureFilename, rotateTexture);
}
loadScene(sceneFilename);
buildMesh();
}
void loadScene(string sceneFilename) {
buffer = ofBufferFromFile(sceneFilename);
ofLogVerbose("Seene") << "Loaded " << sceneFilename;
// read header
version = readInt(buffer, 0);
cameraWidth = readInt(buffer, 4);
cameraHeight = readInt(buffer, 8);
cameraFx = readFloat(buffer, 12);
cameraFy = readFloat(buffer, 16);
cameraK1 = readFloat(buffer, 20);
cameraK2 = readFloat(buffer, 24);
depthMapWidth = readInt(buffer, 28);
depthMapHeight = readInt(buffer, 32);
headerSize = 36;
if(version == 3) {
float unknownA = readFloat(buffer, 36); // e.g. 0.4
float unknownB = readFloat(buffer, 40); // e.g. 110
ofLogVerbose() << "Unknown " << unknownA << ", " << unknownB;
headerSize = 44;
}
depthMap = (float*) (buffer.getData() + headerSize);
ofLogVerbose("Seene") << "Version " << version;
ofLogVerbose("Seene") << "Camera " << cameraWidth << "x" << cameraHeight <<
" fx: " << cameraFx << " " <<
" fy: " << cameraFy << " " <<
" k1: " << cameraK1 << " " <<
" k2: " << cameraK2;
ofLogVerbose("Seene") << "Depth " << depthMapWidth << "x" << depthMapHeight;
// read camera
// var camera = new THREE.PerspectiveCamera(
// Math.atan2(0.495 * header.camera_width, header.camera_fx) * 360 / Math.PI,
// this.width / this.height,
// .01,
// 100
// );
}
void loadTexture(string textureFilename, bool rotateTexture=true) {
tex.load(textureFilename);
if(rotateTexture) {
tex.rotate90(3);
tex.update();
}
}
void buildMesh() {
// read scene
float xk = cameraFx / cameraWidth;
float yk = cameraFy / cameraHeight;
mesh = ofMesh::plane(0, 0, depthMapWidth, depthMapHeight, OF_PRIMITIVE_TRIANGLES);
int i = 0;
// the depth image is stored with a -90 degree rotation
for (int y = 0; y < depthMapHeight; y++) {
for (int x = 0; x < depthMapWidth; x++) {
float depth = depthMap[i];
mesh.setVertex(i, ofVec3f(
depth * ((x + 0.5) / depthMapWidth - 0.5) / xk,
depth * ((y + 0.5) / depthMapHeight - 0.5) / yk,
-(depth - 1)
));
mesh.setTexCoord(i, tex.getTexture().getCoordFromPercent(x / (float) depthMapWidth, y / (float) depthMapHeight));
i++;
}
}
}
void saveDepthMap(string filename) {
ofFloatPixels img;
img.allocate(depthMapWidth, depthMapHeight, OF_IMAGE_GRAYSCALE);
img.setFromPixels(depthMap, depthMapWidth, depthMapHeight, 1);
if(ends_with(filename, ".exr")) {
ofSaveImage(img, filename);
} else {
int n = depthMapWidth * depthMapHeight;
float* data = img.getData();
float min = data[0], max = data[0];
for(int i = 0; i < n; i++) {
float& p = data[i];
min = p < min ? p : min;
max = p > max ? p : max;
}
float range = max - min;
for(int i = 0; i < n; i++) {
float& p = data[i];
p -= min;
p /= range;
}
ofSaveImage(ofPixels(img), filename);
}
}
void draw() {
if(tex.isAllocated()) {
tex.bind();
mesh.draw();
tex.unbind();
} else {
mesh.draw();
}
}
};
class ofApp : public ofBaseApp {
public:
Seene scene;
ofEasyCam cam;
void setup() {
ofSetLogLevel(OF_LOG_VERBOSE);
scene.loadScene("another.oemodel");
scene.saveDepthMap("out.exr");
scene.saveDepthMap("out.jpg");
scene.saveDepthMap("out.png");
scene.load("scene.oemodel", "texture.jpg");
ofBackground(240);
}
void update() {
}
void draw() {
ofEnableDepthTest();
cam.begin();
float scale = 800;
ofScale(scale, -scale, scale);
ofRotate(90);
scene.draw();
cam.end();
}
};
int main() {
ofSetupOpenGL(800, 800, OF_WINDOW);
ofRunApp(new ofApp());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment