Select Git revision
ProjectorModule.cpp
-
Florent Berthaut authoredFlorent Berthaut authored
ProjectorModule.cpp 94.26 KiB
/***************************************************************************
* ProjectorModule.cpp
* Part of Reveal
* 2015- Florent Berthaut
* hitmuri.net
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 130, Boston, MA 02111-1307, USA.
*/
/*////////////
Calibration heavily relies on code from :
https://github.com/Kj1/ofxProjectorKinectCalibration
https://github.com/kylemcdonald/ofxCv
*/////////////////////
#include "ProjectorModule.hpp"
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "../Reveal.hpp"
#include "DepthCamModule.hpp"
#include "SpaceModule.hpp"
#include "RevealedModule.hpp"
using namespace std;
using namespace glm;
using namespace cv;
ProjectorModule::ProjectorModule(): Module() {
m_type="Projector";
m_name="projector";
m_space=NULL;
m_width=640;
m_height=480;
m_posX=0;
m_posY=0;
m_processOutput=true;
m_active=true;
m_postFilter=0;
m_transparentBackground=false;
//create window
m_projWindow = glfwCreateWindow(m_width, m_height,
"Rivill - Projector", NULL, NULL);
if(!m_projWindow) {
glfwTerminate();
exit(EXIT_FAILURE);
}
m_rttWidth=1920;
m_rttHeight=1080;
glfwSetWindowUserPointer(m_projWindow, this);
glfwSetWindowSizeCallback(m_projWindow, windowSizeCallback);
glfwSetWindowPosCallback(m_projWindow, windowPositionCallback);
glfwSetFramebufferSizeCallback(m_projWindow, framebufferSizeCallback);
glfwSetInputMode(m_projWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
addNameAttribute();
addRemoveAttribute();
addAttribute(new Attribute("active",
Attribute::BOOL_ATTRIBUTE,
activeCallback, this, 1,
Attribute::LOCAL));
addAttribute(new Attribute("window_dimensions",
Attribute::INT_ATTRIBUTE,
windowDimensionsCallback, this, 4,
Attribute::LOCAL));
addAttribute(new Attribute("fullscreen_monitor",
Attribute::STRING_ATTRIBUTE,
fullscreenMonitorCallback, this, 1,
Attribute::LOCAL));
addAttribute(new Attribute("view_matrix",
Attribute::FLOAT_ATTRIBUTE,
viewMatrixCallback, this, 16,
Attribute::HIDDEN));
addAttribute(new Attribute("projection_matrix",
Attribute::FLOAT_ATTRIBUTE,
projectionMatrixCallback, this, 16,
Attribute::HIDDEN));
addAttribute(new Attribute("mirrored",
Attribute::BOOL_ATTRIBUTE,
mirroredCallback, this, 1,
Attribute::LOCAL));
addTransformationAttributes();
m_attributesMap["scale"]->setAccessibility(Attribute::HIDDEN);
vector<float> posVec(3,0);
posVec[2]=-700;
m_attributesMap["position"]->setFloats(posVec);
addAttribute(new Attribute("attached_to_camera",
Attribute::STRING_ATTRIBUTE,
attachToCamCallback, this, 1,
Attribute::LOCAL));
addAttribute(new Attribute("calibrate_with_camera",
Attribute::ACTION_STRING_ATTRIBUTE,
calibrateCallback, this, 1,
Attribute::LOCAL,
false));
addAttribute(new Attribute("output_revealed",
Attribute::BOOL_ATTRIBUTE,
outputRevealedCallback, this, 1,
Attribute::LOCAL));
addAttribute(new Attribute("post_filter",
Attribute::INT_ATTRIBUTE,
postFilterCallback, this, 1,
Attribute::LOCAL));
addAttribute(new Attribute("transparent_window",
Attribute::BOOL_ATTRIBUTE,
transparentWindowCallback, this, 1,
Attribute::LOCAL));
//initialize attributes
vector<string> labels;
labels.push_back("none");
m_attributesMap["attached_to_camera"]
->editStringValuesChoices().assign(1, labels);
m_attributesMap["attached_to_camera"]
->initStrings(vector<string>(1, labels[0]));
m_attributesMap["calibrate_with_camera"]
->editStringValuesChoices().assign(1, labels);
m_attributesMap["calibrate_with_camera"]
->initStrings(vector<string>(1, labels[0]));
refreshMonitors();
m_attributesMap["fullscreen_monitor"]
->initStrings(vector<string>(1, "windowed"));
m_attachedToCam=NULL;
m_attributesMap["output_revealed"]->initBools(vector<bool>(1, true));
m_attributesMap["post_filter"]->initInts(vector<int>(1, 0));
m_attributesMap["active"]->initBools(vector<bool>(1, true));
m_mirrored=false;
//initialize matrices
m_viewMat = lookAt(vec3(0.0, 0.0, 0.0),
vec3(0.0, 0.0, 1.0),
vec3(0.0, 1.0, 0.0));
mat4 glCoordsMat(-1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
m_viewMat=glCoordsMat*m_viewMat;
m_attributesMap["view_matrix"]->setFloats(vector<float>(
value_ptr(m_viewMat),
value_ptr(m_viewMat)+16));
m_projMat = perspective(45.0, 4.0/3.0, 100.0, 10000.0);
m_attributesMap["projection_matrix"]->setFloats(vector<float>(
value_ptr(m_projMat),
value_ptr(m_projMat)+16));
vector<int> dims(4,0);
dims[0]=m_posX;
dims[1]=m_posY;
dims[2]=m_width;
dims[3]=m_height;
m_attributesMap["window_dimensions"]->setInts(dims);
//calibration
m_calibrated=false;
m_patternSquareWidth = 40;
m_patternPosition = Size(100, 200);
m_patternSize = Size(6,4);
m_patternBrightness = 100;
m_patternPosRange = Size(m_width, m_height);
m_patternPosOffset = Size(0,0);
Reveal::getInstance()->addContextHandler(this);
m_initialized=false;
}
ProjectorModule::~ProjectorModule() {}
void ProjectorModule::draw() {
if(!m_active) {
return;
}
glfwMakeContextCurrent(m_projWindow);
if(!m_initialized) {
initGL();
m_initialized=true;
}
//slice to texture
glBindFramebuffer(GL_FRAMEBUFFER, m_sliceFBO);
glViewport(0, 0, m_rttWidth, m_rttHeight);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(m_programs[Reveal::SLICEPROG]);
glUniform1f(m_uniforms[Reveal::SLICEPROG][Reveal::MIRRORED],
float(m_mirrored));
glUniformMatrix4fv(m_uniforms[Reveal::SLICEPROG][Reveal::VIEWPROJMAT], 1,
GL_FALSE, value_ptr(m_viewProjMat));
glUniformMatrix4fv(m_uniforms[Reveal::SLICEPROG][Reveal::VIEWMAT], 1,
GL_FALSE, value_ptr(m_transViewMat));
const vector<Geometry*>& depthGeoms = m_space->getGeoms();
vector<Geometry*>::const_iterator itDGeom=depthGeoms.begin();
for(; itDGeom!=depthGeoms.end(); ++itDGeom) {
(*itDGeom)->draw(m_contextHandlerID,
Reveal::SLICEPROG,
m_uniforms[Reveal::SLICEPROG],
m_visibilityMask);
}
//select to texture for 3D models only (GEOM_MODEL)
glBindFramebuffer(GL_FRAMEBUFFER, m_selectFBO);
glViewport(0, 0, m_rttWidth, m_rttHeight);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(m_programs[Reveal::SELECTPROG]);
glUniform1f(m_uniforms[Reveal::SELECTPROG][Reveal::MIRRORED],
float(m_mirrored));
glUniformMatrix4fv(m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPROJMAT], 1,
GL_FALSE, value_ptr(m_viewProjMat));
glUniformMatrix4fv(m_uniforms[Reveal::SELECTPROG][Reveal::VIEWMAT], 1,
GL_FALSE, value_ptr(m_transViewMat));
glUniform1f(m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPORTWIDTH],
m_rttWidth);
glUniform1f(m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPORTHEIGHT],
m_rttHeight);
glUniform1i(m_uniforms[Reveal::SELECTPROG][Reveal::SLICETEX], 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_sliceRttTex);
const vector<Geometry*>& sceneGeoms = Reveal::getInstance()->getGeoms();
for(auto& geom : sceneGeoms) {
if(geom->getGeomID()>=Reveal::GEOM_MODEL) {
geom->draw(m_contextHandlerID,
Reveal::SELECTPROG,
m_uniforms[Reveal::SELECTPROG],
m_visibilityMask);
}
}
//RENDER TO SCREEN
if(m_postFilter>0) {
glBindFramebuffer(GL_FRAMEBUFFER, m_renderFBO);
glViewport(0, 0, m_rttWidth, m_rttHeight);
}
else {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, m_width, m_height);
}
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glEnable(GL_CULL_FACE);
if(m_mirrored) {
glCullFace(GL_FRONT);
}
else {
glCullFace(GL_BACK);
}
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
glClearColor(0.0, 0.0, 0.0, !m_transparentBackground);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUseProgram(m_programs[Reveal::RENDERPROG]);
glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::MIRRORED],
float(m_mirrored));
glUniformMatrix4fv(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPROJMAT], 1,
GL_FALSE, value_ptr(m_viewProjMat));
glUniformMatrix4fv(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWMAT], 1,
GL_FALSE, value_ptr(m_transViewMat));
if(m_postFilter>0) {
glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTWIDTH],
m_rttWidth);
glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTHEIGHT],
m_rttHeight);
}
else {
glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTWIDTH],
m_width);
glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTHEIGHT],
m_height);
}
glActiveTexture(GL_TEXTURE0);
glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::SLICETEX], 0);
glBindTexture(GL_TEXTURE_2D, m_sliceRttTex);
glActiveTexture(GL_TEXTURE1);
glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::SELECTTEX], 1);
glBindTexture(GL_TEXTURE_2D, m_selectTex);
#ifdef GL42
glActiveTexture(GL_TEXTURE7);
glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTPUTTEX], 7);
glBindImageTexture(7, m_outputTex, 0, GL_FALSE, 0,
GL_READ_WRITE, GL_R32UI);
glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTSHAPESIZE],
m_outShapeSize);
glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTDEPTHSIZE],
m_outDepthSize);
glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTNBDEPTH],
m_outNbDepth);
#endif
for(auto& geom : sceneGeoms) {
geom->draw(m_contextHandlerID,
Reveal::RENDERPROG,
m_uniforms[Reveal::RENDERPROG],
m_visibilityMask);
}
//POST PROCESSING
if(m_postFilter>0) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, m_width, m_height);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glDisable(GL_BLEND);
glClearColor(0.0, 0.0, 0.0, !m_transparentBackground);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUseProgram(m_programs[Reveal::POSTPROG]);
glActiveTexture(GL_TEXTURE0);
glUniform1i(m_uniforms[Reveal::POSTPROG][Reveal::RENDERTEX], 0);
glBindTexture(GL_TEXTURE_2D, m_renderTex);
glUniform1f(m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTWIDTH],
m_width);
glUniform1f(m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTHEIGHT],
m_height);
glUniform1f(m_uniforms[Reveal::POSTPROG][Reveal::POSTFILTER],
m_postFilter);
m_calibGeom->drawDirect(m_contextHandlerID);
}
//SWAP
glfwSwapInterval(0);
glfwSwapBuffers(m_projWindow);
//PROCESS OUTPUT
#ifdef GL42
if(m_processOutput) {
processOutput();
}
#endif
}
void ProjectorModule::initGL() {
#ifdef OSX
glewExperimental = GL_TRUE;
#endif
glewInit();
//POSTPROCESSING
{
const char * vertSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
"in vec3 vertex; \n"
" \n"
"void main(void) {\n"
" gl_Position = vec4(vertex, 1.0);\n"
"}\n"};
const char * fragSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
"uniform float viewportWidth;\n"
"uniform float viewportHeight;\n"
"uniform float postFilter;\n"
#ifdef GL42
"layout(binding=0) uniform sampler2D renderTex;\n"
#else
"uniform sampler2D renderTex;\n"
#endif
" \n"
"out vec4 color;\n"
" \n"
"void main(void) {\n"
" float coordX = gl_FragCoord.x;\n"
" float coordY = gl_FragCoord.y;\n"
" ivec2 patSize = textureSize(renderTex, 0);\n"
" vec3 sumCol = vec3(0,0,0);\n"
" float cnt=0;\n"
" for(float dX = coordX-postFilter; dX <= coordX+postFilter; ++dX) {\n"
" for(float dY = coordY-postFilter; dY <= coordY+postFilter; ++dY) {\n"
" if(dX>=0 && dX<viewportWidth \n"
" && dY>=0 && dY<viewportHeight) {\n"
" sumCol+=texelFetch(renderTex, \n"
" ivec2((dX-0.5)/viewportWidth*patSize.x,\n"
" (dY-0.5)/viewportHeight*patSize.y),\n"
" 0).xyz; \n"
" cnt+=1;\n"
" }\n"
" }\n"
" }\n"
" color=vec4(sumCol.xyz/cnt, 1.0);\n"
"}\n"};
m_programs[Reveal::POSTPROG]
= Reveal::getInstance()->createProgram(vertSource, fragSource);
m_uniforms[Reveal::POSTPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTWIDTH]
= glGetUniformLocation(m_programs[Reveal::POSTPROG],"viewportWidth");
m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTHEIGHT]
= glGetUniformLocation(m_programs[Reveal::POSTPROG],"viewportHeight");
m_uniforms[Reveal::POSTPROG][Reveal::POSTFILTER]
= glGetUniformLocation(m_programs[Reveal::POSTPROG],"postFilter");
m_uniforms[Reveal::POSTPROG][Reveal::RENDERTEX]
= glGetUniformLocation(m_programs[Reveal::POSTPROG],"renderTex");
}
//RENDER
{
const char * vertSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
"in vec3 vertex; \n"
"in vec2 texCoords;\n"
" \n"
"uniform mat4 modelMat;\n"
"uniform mat4 viewMat;\n"
"uniform mat4 viewProjMat;\n"
"uniform float mirrored;\n"
" \n"
"out vec3 viewRay;\n"
"out vec2 uvCoords;\n"
" \n"
"void main(void) {\n"
" vec4 posWS = modelMat * vec4(vertex, 1.0);\n"
" if(mirrored<1) {\n"
" posWS.x = -posWS.x;\n"
" }\n"
" gl_Position = viewProjMat * posWS;\n"
" viewRay = posWS.xyz - vec3(viewMat[3][0],\n"
" viewMat[3][1],\n"
" viewMat[3][2]);\n"
" uvCoords=texCoords;\n"
"}\n"};
const char * fragSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
"\n"//defined in Reveal.hpp
"const int BOX=0;\n"
"const int SPHERE=1;\n"
"const int TUBE=2;\n"
"const int CONE=3;\n"
"const int FRAME=4;\n"
"const int PATH=5;\n"
"const int MODEL=10;\n"
"\n"
"in vec3 viewRay;\n"
"in vec2 uvCoords;\n"
" \n"
#ifdef GL42
"layout(binding=0) uniform sampler2D sliceTex;\n"
"layout(binding=1) uniform sampler2D selectTex;\n"
"layout(binding=2) uniform sampler3D insideTex;\n"
"layout(binding=3) uniform sampler2D surfaceTex;\n"
"layout(binding=4) uniform sampler3D reactTex;\n"
"layout(binding=5) uniform sampler3D surfDistTex;\n"
"layout(binding=6) uniform sampler2D gradientTex;\n"
"layout(r32ui, binding=7) uniform coherent uimage2D outputTex;\n"
#else
"uniform sampler2D sliceTex;\n"
"uniform sampler2D selectTex;\n"
"uniform sampler3D insideTex;\n"
"uniform sampler2D surfaceTex;\n"
"uniform sampler3D reactTex;\n"
"uniform sampler3D surfDistTex;\n"
"uniform sampler2D gradientTex;\n"
#endif
"uniform float viewportWidth;\n"
"uniform float viewportHeight;\n"
"uniform float mirrored;\n"
"uniform float shapeID;\n"
"uniform float shapeIDBit;\n"
"uniform int shapeGeom;\n"
"uniform float subShapeID;\n"
"uniform float subShapesNb;\n"
"uniform mat4 subShapeInvMat;\n"
"uniform mat4 viewMat;\n"
"uniform mat4 modelMat;\n"
"uniform mat4 invModelMat;\n"
"uniform vec3 modelScale;\n"
"uniform int revealedBy;\n"
"\n"
"uniform vec3 shapeColor;\n"
//0: none, 1:color, 2:texture
"uniform int surface;\n"
"uniform vec3 surfaceColor;\n"
"uniform int insideOutputOnly;\n"
"uniform int reactivity;\n"
"uniform float thickness;\n"
"\n"
"uniform int insideVisible;\n"
//0:from center, 1:along x, 2: along y, 3:along z, 4 :from surface
"uniform int insideStructure;\n"
"uniform float structureRatio;\n"
"\n"
"uniform float gradientAlpha;\n"
//0:greyscale, 1:texture
"uniform int gradientType;\n"
"uniform int gradientSteps;\n"
"uniform float gradientCurveRatio;\n"
"\n"
"uniform float densityAlpha;\n"
//0:layers, 1:grid, 2:pointcloud
"uniform int densityType;\n"
"uniform float densityRatio;\n"
"uniform float densitySize;\n"
"uniform float densityCurveRatio;\n"
"\n"
"uniform float texAlpha;\n"
"uniform vec3 texOffset;\n"
"uniform vec3 texScale;\n"
"uniform int texGray;\n"
#ifdef GL42
"uniform int revSize;\n"
"uniform int revSurface;\n"
"uniform int revInside;\n"
"uniform int revCenter;\n"
"uniform int revCursor;\n"
"uniform int revColor;\n"
"uniform int revHisto;\n"
"uniform int revVoxels;\n"
"uniform float revSubShapeID;\n"
"uniform int shapeOutSize;\n"
"uniform int histoOutSize;\n"
"uniform int voxelOutSize;\n"
"uniform int depthOutSize;\n"
"uniform int depthOutNb;\n"
"uniform vec4 boundingRect;\n"
#endif
" \n"
"vec3 rgb2hsv(vec3 c) {\n"
" vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"
" vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"
" vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"
" float d = q.x - min(q.w, q.y);\n"
" float e = 1.0e-10;\n"
" return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),d/(q.x + e), q.x);\n"
"}\n"
"float random (vec3 st) {\n"
" return fract(sin(dot(st.xyz,\n"
" vec3(12.9898,78.233, 102.234)))*\n"
" 43758.5453123);\n"
"}\n"
"out vec4 color;\n"
" \n"
"void main(void) {\n"
//get fragment coordinates
" float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
" float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
" ivec2 sliSize = textureSize(sliceTex, 0);\n"
//retrieve pixel in slicing texture
" vec4 sli = texelFetch(sliceTex,\n"
" ivec2(coordX*float(sliSize.x), \n"
" coordY*float(sliSize.y)), \n"
" 0);\n"
" float pixZ=abs(gl_FragCoord.z);\n"
" float cutZ=abs(sli.z);\n"
" int depthID=int(sli.y)-1;\n"
#ifdef GL42
" int outCols=imageSize(outputTex).x;\n"
" int outOffset=(int(shapeID-1)*depthOutNb+(depthID-1))*revSize;\n"
#endif
" int rendered=0;\n"
" vec3 finalColor = shapeColor;\n"
" float alpha=0;\n"
" vec3 pixelPosW;\n"
" vec3 pixelPos = vec3(0.0, 0.0, 1.0);\n"
" vec3 ratioWithinBox = vec3(0.0, 0.0, 0.0);\n"
" vec3 outRatioWithinBox = vec3(0.0, 0.0, 0.0);\n"
//if there is a slicing pixel aligned with our coordinate
//and we are revealed by this depth module
" if(cutZ>0 && (revealedBy & (1<<(1+depthID)))>0 ) { \n"
//compute the slicing pixel world position
" pixelPosW = vec3(viewMat[3][0], \n"
" viewMat[3][1], \n"
" viewMat[3][2])\n"
" + vec3(normalize(viewRay) * sli.w);\n"
" pixelPosW.x = pixelPosW.x*(-2.0*(1-mirrored)+1.0);\n"
//compute the slicing pixel position in model coords
" pixelPos = (invModelMat * vec4(pixelPosW,1.0)).xyz;\n"
"\n"
//depending on type, test if slicing pixel inside
//and retrieve distance to the surface on each axis
" vec3 diffMin = vec3(1.0);\n"
" vec3 diffMax = vec3(1.0);\n"
" switch(shapeGeom) {\n"
" case PATH : {\n"//use min/max/size of current segment
" pixelPos = (subShapeInvMat*vec4(pixelPos,1.0)).xyz;\n"
" if(length(vec2(pixelPos.x, pixelPos.y))<=0.5\n"
" && (pixelPos.z>-0.5 && pixelPos.z<0.5)) { \n"
" float xx = (pixelPos.x)*(pixelPos.x);\n"
" float yy = (pixelPos.y)*(pixelPos.y);\n"
" float ax = sqrt(0.25-yy);\n"
" diffMin.x = pixelPos.x+ax;\n"
" diffMax.x = ax-pixelPos.x;\n"
" float ay = sqrt(0.25-xx);\n"
" diffMin.y = pixelPos.y+ay;\n"
" diffMax.y = ay-pixelPos.y;\n"
" diffMin.z = pixelPos.z+0.5;\n"
" diffMax.z = 0.5-pixelPos.z;\n"
" rendered=1;\n"
" }\n"
" }break;\n"
" case CONE : {\n"
" if(pixelPos.y<0.5 && pixelPos.y>-0.5) {\n"
" float xx = (pixelPos.x)*(pixelPos.x);\n"
" float yy = (pixelPos.y-0.5)*(pixelPos.y-0.5);\n"
" float zz = (pixelPos.z)*(pixelPos.z);\n"
" if((xx+zz)/yy<0.25){ \n"
" float ax = sqrt(0.25*yy-zz);\n"
" diffMin.x = pixelPos.x+ax;\n"
" diffMax.x = ax-pixelPos.x;\n"
" float ay = sqrt((yy+xx)/0.25);\n"
" diffMin.y = pixelPos.y+0.5;\n"
" diffMax.y = 0.5-pixelPos.y;\n"
" float az = sqrt(0.25*yy-xx);\n"
" diffMin.z = pixelPos.z+az;\n"
" diffMax.z = az-pixelPos.z;\n"
" rendered=1;\n"
" }\n"
" }\n"
" } break;\n"
" case TUBE : {\n"
" if(length(vec2(pixelPos.x, pixelPos.z))<=0.5\n"
" && (pixelPos.y>-0.5 && pixelPos.y<0.5)) { \n"
" float xx = (pixelPos.x)*(pixelPos.x);\n"
" float zz = (pixelPos.z)*(pixelPos.z);\n"
" float ax = sqrt(0.25-zz);\n"
" diffMin.x = pixelPos.x+ax;\n"
" diffMax.x = ax-pixelPos.x;\n"
" float az = sqrt(0.25-xx);\n"
" diffMin.z = pixelPos.z+az;\n"
" diffMax.z = az-pixelPos.z;\n"
" diffMin.y = pixelPos.y+0.5;\n"
" diffMax.y = 0.5-pixelPos.y;\n"
" rendered=1;\n"
" }\n"
" } break;\n"
" case SPHERE : {\n"
" if(length(pixelPos)<=0.5) { \n"
" float xx = (pixelPos.x)*(pixelPos.x);\n"
" float yy = (pixelPos.y)*(pixelPos.y);\n"
" float zz = (pixelPos.z)*(pixelPos.z);\n"
" float ax = sqrt(0.25-yy-zz);\n"
" diffMin.x = pixelPos.x+ax;\n"
" diffMax.x = ax-pixelPos.x;\n"
" float ay = sqrt(0.25-xx-zz);\n"
" diffMin.y = pixelPos.y+ay;\n"
" diffMax.y = ay-pixelPos.y;\n"
" float az = sqrt(0.25-xx-yy);\n"
" diffMin.z = pixelPos.z+az;\n"
" diffMax.z = az-pixelPos.z;\n"
" rendered=1;\n"
" }\n"
" } break;\n"
" case BOX : {\n"
" diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
" diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
" if(diffMin.x>0 && diffMax.x>0\n"
" && diffMin.y>0 && diffMax.y>0\n"
" && diffMin.z>0 && diffMax.z>0){\n"
" rendered=1;\n"
" } \n"
" } break;\n"
" case FRAME : {\n"
" diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
" diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
" if(diffMin.x>0 && diffMax.x>0\n"
" && diffMin.y>0 && diffMax.y>0\n"
" && diffMin.z>0 && diffMax.z>0){\n"
" rendered=1;\n"
" } \n"
" } break;\n"
" case MODEL : {\n"
" ivec2 selSize = textureSize(selectTex, 0);\n"
" vec4 sel = texelFetch(selectTex,\n"
" ivec2(coordX*float(selSize.x), \n"
" coordY*float(selSize.y)), \n"
" 0);\n"
//get front surfaces before depth map
" if(pixZ<=cutZ+thickness/1000.0) { \n"
" if(sel.z==0) {\n"
" if(sel.x==shapeID) {\n"
" rendered=1;\n"
" }\n"
" else if((int(shapeIDBit)&int(sel.w))>0) {\n"
" diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
" diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
" if(diffMin.x>0 && diffMax.x>0\n"
" && diffMin.y>0 && diffMax.y>0\n"
" && diffMin.z>0 && diffMax.z>0){\n"
" rendered=1;\n"
" }\n"
" }\n"
" }\n"
" if(surface>0 \n"
" && (pixZ>cutZ \n"
" || (sel.z>0 && (int(shapeIDBit)&int(sel.w))>0))) {\n"
" rendered=2;\n"
" }\n"
" }\n"
" } break;\n"
" }\n"
" if(rendered>0) {\n"
" ratioWithinBox = (pixelPos)+0.5;\n"
//test if on the surface
" if(diffMin.x*modelScale.x<thickness || \n"
" diffMax.x*modelScale.x<thickness || \n"
" diffMin.y*modelScale.y<thickness || \n"
" diffMax.y*modelScale.y<thickness || \n"
" diffMin.z*modelScale.z<thickness || \n"
" diffMax.z*modelScale.z<thickness) { \n"
" rendered=2;\n"
" } \n"
//extend ratiowithinbox to multiplesubshapes
//and get gradient ratio according to type
" float gradRatio = 0;\n"
" vec3 subAdd;\n"
" vec3 subDiv;\n"
" if(insideStructure==0) {\n"//from center
" subAdd = vec3(subShapeID, subShapeID, subShapeID);\n"
" subDiv = vec3(subShapesNb, subShapesNb, subShapesNb);\n"
" ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;\n"
" outRatioWithinBox.xyz=ratioWithinBox.xyz;\n"
" gradRatio = length(ratioWithinBox.xyz\n"
" - vec3(0.5,0.5,0.5))/0.5;\n"
" }\n"
" else {\n"//from surface or along axes
" subAdd = vec3(0,0, subShapeID);\n"
" subDiv = vec3(1,1, subShapesNb);\n"
" ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;\n"
" outRatioWithinBox.xyz=ratioWithinBox.xyz;\n"
" if(insideStructure==1) {\n"
" ratioWithinBox.x=0.5;\n"
" }\n"
" else if(insideStructure==2) {\n"
" ratioWithinBox.y=0.5;\n"
" }\n"
" else if(insideStructure==3 && shapeGeom!=PATH) {\n"
" ratioWithinBox.z=0.5;\n"
" }\n"
" switch(shapeGeom) {\n"
" case BOX : {\n"
" vec3 q = abs(ratioWithinBox.xyz\n"
" -vec3(0.5,0.5,0.5))*2.0\n"
" - vec3(1.0,1.0,1.0);\n"
" gradRatio = 1.0-abs(length(max(q,0.0)) \n"
" + min(max(q.x,max(q.y,q.z)),0.0));\n"
" } break;\n"
" case SPHERE : {\n"
" gradRatio = length(ratioWithinBox.xyz\n"
" - vec3(0.5,0.5,0.5))/0.5;\n"
" } break;\n"
" case PATH : {\n"
" vec2 d = abs(vec2(length((ratioWithinBox.xy-vec2(0.5, 0.5))*2.0), \n"
" (ratioWithinBox.z-0.5)*2.0)) \n"
" - vec2(1.0,1.0);\n"
" gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0)\n"
" + length(max(d,0.0)));\n"
" } break;\n"
" case TUBE : {\n"
" vec2 d = abs(vec2(length((ratioWithinBox.xz-vec2(0.5, 0.5))*2.0), \n"
" (ratioWithinBox.y-0.5)*2.0)) \n"
" - vec2(1.0,1.0);\n"
" gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0)\n"
" + length(max(d,0.0)));\n"
" } break;\n"
" case CONE : {\n"
" float q = length((ratioWithinBox.xz\n"
" - vec2(0.5,0.5))*2.0);\n"
" gradRatio = 1.0-abs(max(dot(vec2(0.5,0.5),\n"
" vec2(q,(ratioWithinBox.y-1.0))),\n"
" -1.0-(ratioWithinBox.y-1.0)));\n"
" } break;\n"
" case FRAME : {\n" //FIXME compute frame SDF
" vec3 q = abs(ratioWithinBox.xyz\n"
" -vec3(0.5,0.5,0.5))*2.0\n"
" - vec3(1.0,1.0,1.0);\n"
" gradRatio = 1.0-abs(length(max(q,0.0)) \n"
" + min(max(q.x,max(q.y,q.z)),0.0));\n"
" } break;\n"
" case MODEL : {\n"
" gradRatio = texture(surfDistTex, \n"
" ratioWithinBox).r\n"
" * structureRatio;\n"
" } break;\n"
" default :{\n"//defaults to sphere
" gradRatio = length(ratioWithinBox.xyz\n"
" - vec3(0.5,0.5,0.5))/0.5;\n"
" } break;\n"
" }\n"
" }\n"
//texture coordinates
" vec3 texCoords = vec3(1-ratioWithinBox.x,\n"
" 1-ratioWithinBox.y,\n"
" ratioWithinBox.z);\n"
"\n"
//start with shapeColor
" finalColor = shapeColor;\n"
//test gradient
" if(gradientAlpha>0) {\n"
" float gradColor = \n"
" pow(gradientCurveRatio<0?1.0-gradRatio:gradRatio,\n"
" abs(gradientCurveRatio));\n"
" if(gradientSteps>1) {\n"
" gradColor = floor(gradColor*gradientSteps)\n"
" / gradientSteps;\n"
" }\n"
" gradColor*=(gradRatio<=1.0)?1.0:0.0;\n"
" if(gradientType>0) {\n"//gradient texture
" finalColor=finalColor*(1.0-gradientAlpha) \n"
" + finalColor*gradientAlpha\n"
" * texture(gradientTex, \n"
" vec2(gradRatio, 0.0)).xyz;\n"
" }\n"
" else {\n"
" finalColor=finalColor*(1.0-gradientAlpha) \n"
" + finalColor*gradColor*gradientAlpha;\n"
" }\n"
" }\n"
//test density
" if(densityAlpha>0) {\n"
" float densColor = \n"
" pow(densityCurveRatio<0?1.0-gradRatio:gradRatio,\n"
" abs(densityCurveRatio));\n"
" if(densityType==0 && \n" //layers
" length(mod(densColor*100.0, \n"
" densitySize*100.0))\n"
" < densityRatio*densitySize*100.0) {\n"
" densColor = 1.0;\n"
" densColor*=(gradRatio<=1.0)?1.0:0.0;\n"
" }\n"
" else if(densityType==1\n" //grid
" && (length(mod(ratioWithinBox.x*100,\n"
" densitySize*100.0))\n"
" <densitySize*densityRatio*100.0 \n"
" || length(mod(ratioWithinBox.y*100,\n"
" densitySize*100.0))\n"
" <densitySize*densityRatio*100.0 \n"
" || length(mod(ratioWithinBox.z*100,\n"
" densitySize*100.0))\n"
" <densitySize*densityRatio*100.0)) { \n"
" densColor = 1.0;\n"
" }\n"
" else if(densityType==2 \n" //pointcloud
" && floor(random(ratioWithinBox.xyz)\n"
" *floor(100.0))>100.0*densColor) {\n"
" densColor = 1.0; \n"
" densColor*=(gradRatio<=1.0)?1.0:0.0;\n"
" }\n"
" else {\n"
" densColor = 0.0;\n"
" }\n"
" finalColor=finalColor*(1.0-densityAlpha) \n"
" + finalColor*densColor*densityAlpha;\n"
" }\n"
//test texture
" if(texAlpha>0) {\n"
" vec3 texColor = texture(insideTex, \n"
" texOffset+texScale*texCoords).xyz;\n"
" if(texGray>0) {\n"
" texColor=vec3((texColor.r+texColor.g+texColor.b)\n"
" / 3.0);\n"
" }\n"
" finalColor=finalColor*(1.0-texAlpha) \n"
" + finalColor*texColor*texAlpha;\n"
" }\n"
#ifdef GL42
//if revealing something, output values
" if(sli.x>=1.0 && depthID<=depthOutNb) {\n"
//inside output
" if(revInside>0 && rendered==1) {\n"
" imageAtomicMax(outputTex, \n"
" ivec2(mod(outOffset+revInside,outCols), \n"
" floor((outOffset+revInside))/outCols),\n"
" 1);\n"
" }\n"
" outRatioWithinBox.x=clamp(outRatioWithinBox.x, 0, 1);\n"
" outRatioWithinBox.y=clamp(outRatioWithinBox.y, 0, 1);\n"
" outRatioWithinBox.z=clamp(outRatioWithinBox.z, 0, 1);\n"
//compute min,max on the three axes
" int xk=int(outRatioWithinBox.x*1000.0);\n"
" int yk=int(outRatioWithinBox.y*1000.0);\n"
" int zk=int(outRatioWithinBox.z*1000.0);\n"
//output min/max ratios
" if(revCenter>0) {\n"
" imageAtomicMax(outputTex, \n"
" ivec2(mod(outOffset+revCenter+0,outCols), \n"
" floor((outOffset+revCenter+0)/outCols)),\n"
" 1000-xk);\n"
" imageAtomicMax(outputTex, \n"
" ivec2(mod(outOffset+revCenter+1,outCols), \n"
" floor((outOffset+revCenter+1)/outCols)),\n"
" xk);\n"
" imageAtomicMax(outputTex, \n"
" ivec2(mod(outOffset+revCenter+2,outCols), \n"
" floor((outOffset+revCenter+2)/outCols)),\n"
" 1000-yk);\n"
" imageAtomicMax(outputTex, \n"
" ivec2(mod(outOffset+revCenter+3,outCols), \n"
" floor((outOffset+revCenter+3)/outCols)),\n"
" yk);\n"
" imageAtomicMax(outputTex, \n"
" ivec2(mod(outOffset+revCenter+4,outCols), \n"
" floor((outOffset+revCenter+4)/outCols)),\n"
" 1000-zk);\n"
" imageAtomicMax(outputTex, \n"
" ivec2(mod(outOffset+revCenter+5,outCols), \n"
" floor((outOffset+revCenter+5)/outCols)),\n"
" zk);\n"
" }\n"
//convert from rgb to hsv
" vec3 hsv = rgb2hsv(finalColor);\n"
//Sum color channels
" if(revColor>0) {\n"
//count nb revealed points
" imageAtomicAdd(outputTex,\n"
" ivec2(mod(outOffset+revColor+0,outCols), \n"
" floor((outOffset+revColor+0)/outCols)),\n"
" 1);\n"
//sum point h
" imageAtomicAdd(outputTex,\n"
" ivec2(mod(outOffset+revColor+1,outCols), \n"
" floor((outOffset+revColor+1)/outCols)),\n"
" clamp(int(hsv.x*1000.0),0,1000));\n"
//sum s
" imageAtomicAdd(outputTex,\n"
" ivec2(mod(outOffset+revColor+2,outCols), \n"
" floor((outOffset+revColor+2)/outCols)),\n"
" clamp(int(hsv.y*1000.0),0,1000));\n"
//sum v
" imageAtomicAdd(outputTex,\n"
" ivec2(mod(outOffset+revColor+3,outCols), \n"
" floor((outOffset+revColor+3)/outCols)),\n"
" clamp(int(hsv.z*1000.0),0,1000));\n"
" }\n"
//histo : accumulate on luminance bins
" if(revHisto>0) {\n"
//count nb revealed points
" imageAtomicAdd(outputTex,\n"
" ivec2(mod(outOffset+revHisto,outCols), \n"
" floor((outOffset+revHisto)/outCols)),\n"
" 1);\n"
" int bin = int(hsv.z*float(histoOutSize-1));\n"
" imageAtomicAdd(outputTex,\n"
" ivec2(mod(outOffset+revHisto+1+bin,outCols), \n"
" floor((outOffset+revHisto+1+bin)/outCols)),\n"
" 1);\n"
" }\n"
//2D grid of projected voxels (nbvox, 3D coords, lum)
" if(revVoxels>0) {\n"
//compute pixel ratio within 2D bounding rect
" vec2 pixRatio = (vec2(coordX, coordY)\n"
" - boundingRect.xy) / \n"
" (boundingRect.zw-boundingRect.xy);\n"
" pixRatio.x = clamp(pixRatio.x, 0.0, 1.0);\n"
" pixRatio.y = clamp(pixRatio.y, 0.0, 1.0);\n"
//compute offset in voxel output
" int voxOff = outOffset+revVoxels;\n"
" voxOff+=5*(int(pixRatio.x*voxelOutSize)\n"
" + int((1.0-pixRatio.y)*voxelOutSize)\n"
" *voxelOutSize);\n"
//accumulate points
" imageAtomicAdd(outputTex,\n"
" ivec2(mod(voxOff,outCols), \n"
" floor((voxOff)/outCols)),\n"
" 1);\n"
//accumulate coords
" imageAtomicAdd(outputTex, \n"
" ivec2(mod(voxOff+1,outCols), \n"
" floor((voxOff+1)/outCols)),\n"
" clamp(int(outRatioWithinBox.x*1000.0),0,1000));\n"
" imageAtomicAdd(outputTex, \n"
" ivec2(mod(voxOff+2,outCols), \n"
" floor((voxOff+2)/outCols)),\n"
" clamp(int(outRatioWithinBox.y*1000.0),0,1000));\n"
" imageAtomicAdd(outputTex, \n"
" ivec2(mod(voxOff+3,outCols), \n"
" floor((voxOff+3)/outCols)),\n"
" clamp(int(outRatioWithinBox.z*1000.0),0,1000));\n"
//accumulate lum
" imageAtomicAdd(outputTex, \n"
" ivec2(mod(voxOff+4,outCols), \n"
" floor((voxOff+4)/outCols)),\n"
" clamp(int(hsv.z*1000.0),0,1000));\n"
" }\n"
" }\n"
#endif
" }\n"
//SURFACE test
" if(rendered>1) { \n"
" finalColor = surfaceColor;\n"
#ifdef GL42
" if(revSurface>0 && sli.x>=1.0 && depthID<=depthOutNb) {\n"
" imageAtomicMax(outputTex,\n"
" ivec2(mod(outOffset+revSurface,outCols), \n"
" floor((outOffset+revSurface)/outCols)),\n"
" 1);\n"
" }\n"
#endif
" }\n"
" }\n"
//final test, output if rendered or not, output final color
" if(rendered>0 && length(finalColor)>0) { \n"
#ifdef GL42
" if(revSize>0) {\n"
" imageAtomicOr(outputTex, \n"
" ivec2(mod(outOffset,outCols), \n"
" floor((outOffset))/outCols),\n"
" rendered);\n"
" }\n"
#endif
" if((insideVisible>0 && rendered==1) \n"
" || (surface>0 && rendered==2)) {\n"
" color = vec4(finalColor, 1.0);\n"//display
//" color = vec4(finalColor, sli.x);\n"//display
/*
" if(sli.x>0.5) {\n"
" color = vec4(1.0, 0.0, 0.0, 1.0);\n"//display
" }\n"
" else {\n"
" color = vec4(0.0, 1.0, 0.0, 1.0);\n"//display
" }\n"
*/
" }\n"
" else {\n"
" color = vec4(0.0, 0.0, 0.0, 1.0);\n"
" }\n"
//" color = vec4((pixelPos+0.5)/2.0, 1.0);\n"//debug pix coords
//" color = vec4(cutZ*10.0, pixZ*10.0, 0.0, 1.0);\n"//debug slice texture
//" color = vec4(texture(surfDistTex, ratioWithinBox).r*10.0, 1.0,1.0,1.0);\n"
//" color = vec4(texture(insideTex, ratioWithinBox).r*10.0, 1.0,1.0,1.0);\n"
//" color = vec4(ratioWithinBox.xyz, 1.0);\n"
" }\n"
" else {\n" //DISCARD
//" color = vec4(1.0,0.0,0.0,1.0);\n"
" discard;\n"
" }\n"
"}\n"};
m_programs[Reveal::RENDERPROG]
= Reveal::getInstance()->createProgram(vertSource, fragSource);
m_uniforms[Reveal::RENDERPROG] = map<Reveal::REVIL_UNIFORM, GLint>();
m_uniforms[Reveal::RENDERPROG][Reveal::MIRRORED]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "mirrored");
m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPROJMAT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "viewProjMat");
m_uniforms[Reveal::RENDERPROG][Reveal::VIEWMAT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "viewMat");
m_uniforms[Reveal::RENDERPROG][Reveal::MODELMAT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "modelMat");
m_uniforms[Reveal::RENDERPROG][Reveal::INVMODELMAT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "invModelMat");
m_uniforms[Reveal::RENDERPROG][Reveal::MODELSCALE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "modelScale");
m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTWIDTH]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "viewportWidth");
m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTHEIGHT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG],"viewportHeight");
m_uniforms[Reveal::RENDERPROG][Reveal::SLICETEX]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "sliceTex");
m_uniforms[Reveal::RENDERPROG][Reveal::SELECTTEX]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "selectTex");
m_uniforms[Reveal::RENDERPROG][Reveal::INSIDETEX]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "insideTex");
m_uniforms[Reveal::RENDERPROG][Reveal::COORDSTEX]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "coordsTex");
m_uniforms[Reveal::RENDERPROG][Reveal::TEXGRAY]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "texGray");
m_uniforms[Reveal::RENDERPROG][Reveal::REACTTEX]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "reactTex");
m_uniforms[Reveal::RENDERPROG][Reveal::SURFDISTEX]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "surfDistTex");
m_uniforms[Reveal::RENDERPROG][Reveal::SHAPEID]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeID");
m_uniforms[Reveal::RENDERPROG][Reveal::SHAPEIDBIT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeIDBit");
m_uniforms[Reveal::RENDERPROG][Reveal::SHAPEGEOM]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeGeom");
m_uniforms[Reveal::RENDERPROG][Reveal::SHAPECOLOR]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeColor");
m_uniforms[Reveal::RENDERPROG][Reveal::SUBSHAPEID]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "subShapeID");
m_uniforms[Reveal::RENDERPROG][Reveal::SUBSHAPESNB]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "subShapesNb");
m_uniforms[Reveal::RENDERPROG][Reveal::SUBSHAPEINVMAT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG],"subShapeInvMat");
m_uniforms[Reveal::RENDERPROG][Reveal::REVEALEDBY]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revealedBy");
m_uniforms[Reveal::RENDERPROG][Reveal::SURFACE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "surface");
m_uniforms[Reveal::RENDERPROG][Reveal::SURFACECOLOR]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "surfaceColor");
m_uniforms[Reveal::RENDERPROG][Reveal::SURFACETHICKNESS]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "thickness");
m_uniforms[Reveal::RENDERPROG][Reveal::SURFACETEX]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "surfaceTex");
m_uniforms[Reveal::RENDERPROG][Reveal::INSIDEVISIBLE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "insideVisible");
m_uniforms[Reveal::RENDERPROG][Reveal::INSIDESTRUCT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "insideStructure");
m_uniforms[Reveal::RENDERPROG][Reveal::STRUCTRATIO]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "structureRatio");
m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTALPHA]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientAlpha");
m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTTYPE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientType");
m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTSTEPS]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientSteps");
m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTCURVERATIO]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientCurveRatio");
m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTTEXTURE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientTex");
m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYALPHA]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densityAlpha");
m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYTYPE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densityType");
m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYRATIO]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densityRatio");
m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYSIZE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densitySize");
m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYCURVERATIO]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densityCurveRatio");
m_uniforms[Reveal::RENDERPROG][Reveal::TEXALPHA]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "texAlpha");
m_uniforms[Reveal::RENDERPROG][Reveal::TEXOFFSET]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "texOffset");
m_uniforms[Reveal::RENDERPROG][Reveal::TEXSCALE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "texScale");
m_uniforms[Reveal::RENDERPROG][Reveal::REACTIVITY]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "reactivity");
m_uniforms[Reveal::RENDERPROG][Reveal::BBOXMIN]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxMin");
m_uniforms[Reveal::RENDERPROG][Reveal::BBOXSIZE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxSize");
m_uniforms[Reveal::RENDERPROG][Reveal::BBOXLOCALSIZE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxLocalSize");
m_uniforms[Reveal::RENDERPROG][Reveal::BBOXROT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxRot");
#ifdef GL42
//output texture
m_outputImg = new unsigned int[m_outputImgSize*m_outputImgSize];
m_outputImgInit = new unsigned int[m_outputImgSize*m_outputImgSize];
memset(&m_outputImgInit[0], 0, m_outputImgSize*m_outputImgSize*4);
glGenTextures(1, &m_outputTex);
glBindTexture(GL_TEXTURE_2D, m_outputTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI,
m_outputImgSize, m_outputImgSize, 0,
GL_RED_INTEGER, GL_UNSIGNED_INT, m_outputImgInit);
m_uniforms[Reveal::RENDERPROG][Reveal::OUTPUTTEX]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "outputTex");
m_uniforms[Reveal::RENDERPROG][Reveal::REVSIZE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revSize");
m_uniforms[Reveal::RENDERPROG][Reveal::REVSURFACE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revSurface");
m_uniforms[Reveal::RENDERPROG][Reveal::REVINSIDE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revInside");
m_uniforms[Reveal::RENDERPROG][Reveal::REVCENTER]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revCenter");
m_uniforms[Reveal::RENDERPROG][Reveal::REVCURSOR]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revCursor");
m_uniforms[Reveal::RENDERPROG][Reveal::REVCOLOR]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revColor");
m_uniforms[Reveal::RENDERPROG][Reveal::REVHISTO]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revHisto");
m_uniforms[Reveal::RENDERPROG][Reveal::REVVOXELS]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revVoxels");
m_uniforms[Reveal::RENDERPROG][Reveal::OUTSHAPESIZE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeOutSize");
m_uniforms[Reveal::RENDERPROG][Reveal::OUTHISTOSIZE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "histoOutSize");
m_uniforms[Reveal::RENDERPROG][Reveal::OUTVOXELSIZE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "voxelOutSize");
m_uniforms[Reveal::RENDERPROG][Reveal::OUTDEPTHSIZE]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "depthOutSize");
m_uniforms[Reveal::RENDERPROG][Reveal::OUTNBDEPTH]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "depthOutNb");
m_uniforms[Reveal::RENDERPROG][Reveal::BRECT]
= glGetUniformLocation(m_programs[Reveal::RENDERPROG], "boundingRect");
createRTT(m_renderTex, m_renderFBO, m_rttWidth, m_rttHeight, false);
#endif
}
{
//select prog
const char * vertSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
"in vec3 vertex;\n"
" \n"
"uniform mat4 modelMat;\n"
"uniform mat4 viewMat;\n"
"uniform mat4 viewProjMat;\n"
"uniform float mirrored;\n"
" \n"
"void main(void) {\n"
" vec4 posWS = modelMat * vec4(vertex, 1.0);\n"
" if(mirrored<1) {\n"
" posWS.x = -posWS.x;\n"
" }\n"
" gl_Position = viewProjMat * posWS;\n"
"}\n"};
const char * fragSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
#ifdef GL42
"layout(binding=0) uniform sampler2D sliceTex;\n"
#else
"uniform sampler2D sliceTex;\n"
#endif
"uniform float viewportWidth;\n"
"uniform float viewportHeight;\n"
"uniform float shapeID;\n"
"uniform float shapeIDBit;\n"
"uniform float mirrored;\n"
"uniform float thickness;\n"
"uniform int surface;\n"
" \n"
"out vec4 color;\n"
" \n"
"void main(void) {\n"
" float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
" float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
" ivec2 sliSize = textureSize(sliceTex, 0);\n"
" vec4 sli = texelFetch(sliceTex,\n"
" ivec2(coordX*float(sliSize.x),\n"
" coordY*float(sliSize.y)),\n"
" 0);\n"
" float pixZ=abs(gl_FragCoord.z);\n"
" float cutZ=abs(sli.z);\n"
// keep all ids of back surfaces after depth map
" if(pixZ>cutZ && cutZ>0) {\n"
" if((mirrored<1 && !gl_FrontFacing)\n"
" || (mirrored>0 && gl_FrontFacing)) {\n"
" color = vec4(shapeID, 0, \n"
" (abs(pixZ-cutZ)<thickness/1000.0 && surface>0)?1:0, \n"
" shapeIDBit);\n"
" }\n"
" else {\n" //occlude back when front face also behind
" color = vec4(-shapeID, 0, 0, -shapeIDBit);\n"
" }\n"
" }\n"
" else {\n"
" discard;\n"
" }\n"
"}\n"};
m_programs[Reveal::SELECTPROG]
= Reveal::getInstance()->createProgram(vertSource, fragSource);
m_uniforms[Reveal::SELECTPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
m_uniforms[Reveal::SELECTPROG][Reveal::MIRRORED]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "mirrored");
m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPROJMAT]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "viewProjMat");
m_uniforms[Reveal::SELECTPROG][Reveal::VIEWMAT]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "viewMat");
m_uniforms[Reveal::SELECTPROG][Reveal::MODELMAT]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "modelMat");
m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPORTWIDTH]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "viewportWidth");
m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPORTHEIGHT]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG],"viewportHeight");
m_uniforms[Reveal::SELECTPROG][Reveal::SLICETEX]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "sliceTex");
m_uniforms[Reveal::SELECTPROG][Reveal::SHAPEID]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "shapeID");
m_uniforms[Reveal::SELECTPROG][Reveal::SHAPEIDBIT]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "shapeIDBit");
m_uniforms[Reveal::SELECTPROG][Reveal::SURFACETHICKNESS]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "thickness");
m_uniforms[Reveal::SELECTPROG][Reveal::SURFACE]
= glGetUniformLocation(m_programs[Reveal::SELECTPROG], "surface");
createRTT(m_selectTex, m_selectFBO, m_rttWidth, m_rttHeight, false);
}
//SLICE
{
const char * vertSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
"#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b);\n"
"#define mn3(a, b, c) s2(a, b); s2(a, c);\n"
"#define mx3(a, b, c) s2(b, c); s2(a, c);\n"
"#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b);\n"
"#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d);\n"
"#define mnmx5(a, b, c, d, e) s2(a,b); s2(c,d);mn3(a,c,e);mx3(b,d,e);\n"
"#define mnmx6(a,b,c,d,e,f) s2(a,d);s2(b,e);s2(c,f);mn3(a,b,c);mx3(d,e,f);\n"
"in vec3 vertex; \n"
" \n"
#ifdef GL42
"layout(binding=0) uniform sampler2D depthCamTex;\n"
"layout(binding=1) uniform sampler2D depthCamTexFil;\n"
"layout(binding=2) uniform sampler2D markersTex;\n"
//"layout(r32ui, binding=2) uniform coherent uimage2D outputTex;\n"
#else
"uniform sampler2D depthCamTex;\n"
"uniform sampler2D depthCamTexFil;\n"
"uniform sampler2D markersTex;\n"
#endif
"uniform mat4 modelMat;\n"
"uniform mat4 viewMat;\n"
"uniform mat4 viewProjMat;\n"
"uniform float camXReso;\n"
"uniform float camYReso;\n"
"uniform float camXZFactor;\n"
"uniform float camYZFactor;\n"
"uniform int camFilter;\n"
"uniform int background;\n"
"uniform float camContThresh;\n"
"uniform float camMarkers;\n"
"uniform int depthType;\n"
"uniform int depthID;\n"
"uniform float outputCurs;\n"
"uniform float mirrored;\n"
" \n"
"out vec3 viewRay;\n"
"out float kept;\n"
"flat out int outDepthID;\n"
" \n"
"void main(void) {\n"
" vec4 depthPos = vec4(0, 0, 0, 1);\n"
" vec4 posWS = vec4(0, 0, 0, 1);\n"
//depth camera
" if(depthType==0) {\n"
" vec2 coords = vertex.xy;\n"
//get marker if any
" if(camMarkers>0) {\n"
" outDepthID = int(float(texture(markersTex,\n"
" vec2(coords.x/camXReso,\n"
" coords.y/camYReso)).r)\n"
" * 255.0);\n"
" }\n"
" else {\n"
" outDepthID=depthID+1;\n"
" }\n"
//get depth pixel in camera texture
" float depth = \n"
" float(texture(depthCamTex,\n"
" vec2(coords.x/camXReso,\n"
" coords.y/camYReso)).r)\n"
" * 65535.0;\n"
" kept=1.0;\n"
" float backgroundDepth=0;\n"
" if(background>0) {\n"
" float backDepth = float(texture(depthCamTex,\n"
" vec2(coords.x/camXReso,\n"
" coords.y/camYReso)).r)\n"
" * 65535.0;\n"
" if(backDepth<depth) {\n"
" depth=backDepth;\n"
" backgroundDepth=1;\n"
" }\n"
" }\n"
" if(depth<=500.0 || depth>8000.0) {\n"
" kept=0.0;\n"
" }\n"
" else if(backgroundDepth==0) {\n"
//filter out contours
" float maxD=camContThresh;\n"
" bool contour=false;\n"
" for(int dX = -1; dX <= 1; ++dX) {\n"
" for(int dY = -1; dY <= 1; ++dY) {\n"
" if(abs(float(texture(depthCamTex,\n"
" vec2((coords.x+dX)/camXReso,\n"
" (coords.y+dY)/camYReso)).r)\n"
" * 65535.0\n"
" - depth) > maxD) {\n"
" contour=true;\n"
" }\n"
" }\n"
" }\n"
" if(contour) {\n"
" kept=0.0;\n"
" }\n"
//see if needs filtering
" if(camFilter>0) {\n"
" float filtDepth = float(texture(depthCamTexFil,\n"
" vec2(coords.x/camXReso,\n"
" coords.y/camYReso)).r)\n"
" * 65535.0;\n"
//select either filtered version or current one
//depending on movement
" if(abs(filtDepth-depth)<camContThresh) {\n"
" float filRatio = abs(filtDepth-depth)/camContThresh;\n"
" depth=(1-filRatio)*filtDepth+(filRatio)*depth;\n"
" }\n"
" }\n"
" }\n"
//test distance again
" if(depth<=500.0 || depth>8000.0) {\n"
" kept=0.0;\n"
" }\n"
//compute position in world units
" depthPos = vec4((vertex.x/camXReso-0.5)\n"
" *depth*camXZFactor,\n"
" (0.5-(vertex.y/camYReso))\n"
" *depth*camYZFactor,\n"
" depth,\n"
" 1.0);\n"
//get world pos
" posWS = modelMat * depthPos;\n"
" }\n"
//other slicing shapes
" else {\n"
" outDepthID=depthID+1;\n"
" kept=1.0;\n"
" depthPos=vec4(vertex, 1.0);\n"
" posWS = modelMat * depthPos;\n"
" if(mirrored<1) {\n"
" posWS.x = -posWS.x;\n"
" }\n"
" }\n"
#ifdef GL42
/*
//output minimum point on z axis if output is active
" if(outputCurs>0 && kept>0.0) {\n"
" imageAtomicMin(outputTex,ivec2(0,int(depthID)+500),\n"
" int(floor(1000.0+posWS.z/10.0)*1000000\n"
" +floor(posWS.y/10.0+500.0)*1000\n"
" +floor(posWS.x/10.0+500.0)));\n"
//" imageAtomicMin(outputTex,ivec2(0, int(depthID)+500),4400600);\n"
//" imageAtomicMin(outputTex,ivec2(0, int(depthID)+500),6400600);\n"
" }\n"
*/
#endif
//keep/interpolate ray from view to each vertex
" viewRay = (posWS.xyz - vec3(viewMat[3][0],\n"
" viewMat[3][1],\n"
" viewMat[3][2]));\n"
" gl_Position = viewProjMat * posWS;\n"
"}\n"};
const char * fragSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
"in float kept;\n"
"in vec3 viewRay;\n"
"flat in int outDepthID;\n"
" \n"
"out vec4 color;\n"
" \n"
"void main(void) {\n"
" float thresh=0.8;\n"
" if(kept>=thresh) {\n"
" color = vec4((kept-thresh)/(1.0-thresh),\n"
" float(outDepthID),\n"
" gl_FragCoord.z,\n"
" length(viewRay));\n"
" }\n"
" else {\n"
" discard;\n"
" }\n"
// " color = vec4(1.0, 1.0, 0.0, 1.0);\n"
"}\n"};
m_programs[Reveal::SLICEPROG]
= Reveal::getInstance()->createProgram(vertSource, fragSource);
m_uniforms[Reveal::SLICEPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
m_uniforms[Reveal::SLICEPROG][Reveal::BACKGROUND]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "background");
m_uniforms[Reveal::SLICEPROG][Reveal::MIRRORED]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "mirrored");
m_uniforms[Reveal::SLICEPROG][Reveal::VIEWPROJMAT]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "viewProjMat");
m_uniforms[Reveal::SLICEPROG][Reveal::VIEWMAT]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "viewMat");
m_uniforms[Reveal::SLICEPROG][Reveal::MODELMAT]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "modelMat");
m_uniforms[Reveal::SLICEPROG][Reveal::DEPTHTYPE]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "depthType");
m_uniforms[Reveal::SLICEPROG][Reveal::DEPTHID]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "depthID");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMXRESO]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camXReso");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMYRESO]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camYReso");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMXZFACTOR]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camXZFactor");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMYZFACTOR]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camYZFactor");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMTEX]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "depthCamTex");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMTEXFIL]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "depthCamTexFil");
m_uniforms[Reveal::SLICEPROG][Reveal::MARKTEX]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "markersTex");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMFILTER]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camFilter");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMCONTOURTHRESH]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camContThresh");
m_uniforms[Reveal::SLICEPROG][Reveal::CAMMARKERS]
= glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camMarkers");
createRTT(m_sliceRttTex, m_sliceFBO, m_rttWidth, m_rttHeight, false);
}
//Calibration
{
const char * vertSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
"in vec3 vertex; \n"
" \n"
"void main(void) {\n"
" gl_Position = vec4(vertex, 1.0);\n"
"}\n"};
const char * fragSource = {
#ifdef GL42
"#version 430 \n"
#else
"#version 410 \n"
#endif
" \n"
"uniform float viewportWidth;\n"
"uniform float viewportHeight;\n"
"uniform float patW;\n"
"uniform float patPosX;\n"
"uniform float patPosY;\n"
"uniform float patNbX;\n"
"uniform float patNbY;\n"
"uniform float patBright;\n"
"uniform vec2 patOffset;\n"
"uniform vec2 patRange;\n"
#ifdef GL42
"layout(binding=0) uniform sampler2D patternTex;\n"
#else
"uniform sampler2D patternTex;\n"
#endif
" \n"
"out vec4 color;\n"
" \n"
"void main(void) {\n"
/*
" float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
" float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
" ivec2 patSize = textureSize(patternTex, 0);\n"
" float pat = texelFetch(patternTex,\n"
" ivec2(coordX*float(patSize.x),\n"
" (1.0-coordY)*float(patSize.y)),\n"
" 0).r;\n"
" color=vec4(pat, pat, pat, 1.0);\n"
//" color=vec4(1.0,1.0,1.0,1.0);\n"
*/
//pixel is white by default
" color = vec4(patBright);\n"
" float offX = gl_FragCoord.x - patPosX;\n"
" float offY = (viewportHeight-gl_FragCoord.y) - patPosY;\n"
//black squares
" if(offX>=0 && offX<patW*(patNbX+1)\n"
" && offY>=0 && offY<patW*(patNbY+1)) {\n"
" if((mod(offX,patW*2)<patW && mod(offY,patW*2)<patW) \n"
" || (mod(offX,patW*2)>patW && mod(offY,patW*2)>patW)) {\n"
" color = vec4(0, 0, 0, 1);\n"
" }\n"
" }\n"
//color in red the pattern range border
" float thick=2;\n"
" float coordY = viewportHeight-gl_FragCoord.y;\n"
" if(((abs(gl_FragCoord.x-patOffset.x)<thick\n"
" || abs(gl_FragCoord.x-(patOffset.x+patRange.x))<thick)\n"
" && coordY>patOffset.y\n"
" && coordY<(patOffset.y+patRange.y))\n"
" ||((abs(coordY-patOffset.y)<thick\n"
" || abs(coordY-(patOffset.y+patRange.y))<thick)\n"
" && gl_FragCoord.x>patOffset.x\n"
" && gl_FragCoord.x<(patOffset.x+patRange.x))) {\n"
" color=vec4(1,0,0,1);\n"
" }\n"
"}\n"};
m_programs[Reveal::CALIBPROG]
= Reveal::getInstance()->createProgram(vertSource, fragSource);
m_uniforms[Reveal::CALIBPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTWIDTH]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"viewportWidth");
m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTHEIGHT]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"viewportHeight");
/*
m_uniforms[Reveal::CALIBPROG][Reveal::PATTERNTEX]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patternTex");
*/
m_uniforms[Reveal::CALIBPROG][Reveal::PATW]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patW");
m_uniforms[Reveal::CALIBPROG][Reveal::PATPOSX]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patPosX");
m_uniforms[Reveal::CALIBPROG][Reveal::PATPOSY]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patPosY");
m_uniforms[Reveal::CALIBPROG][Reveal::PATNBX]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patNbX");
m_uniforms[Reveal::CALIBPROG][Reveal::PATNBY]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patNbY");
m_uniforms[Reveal::CALIBPROG][Reveal::PATRANGE]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patRange");
m_uniforms[Reveal::CALIBPROG][Reveal::PATOFFSET]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patOffset");
m_uniforms[Reveal::CALIBPROG][Reveal::PATBRIGHT]
= glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patBright");
m_calibGeom = new QuadGeometry();
}
}
void ProjectorModule::createRTT(GLuint& tex, GLuint& fbo,
const int& width, const int& height,
bool filter) {
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height,
0, GL_RGBA, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
filter?GL_LINEAR:GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
filter?GL_LINEAR:GL_NEAREST);
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);
GLenum drawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, drawBuffers);
GLuint idDepthrenderbuffer;
glGenRenderbuffers(1, &idDepthrenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, idDepthrenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, idDepthrenderbuffer);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void ProjectorModule::deleteModule() {
if(m_space) {
m_space->removeProj(this);
}
glfwDestroyWindow(m_projWindow);
Module::deleteModule();
}
void ProjectorModule::setSpace(SpaceModule* space) {
m_space=space;
}
void ProjectorModule::refreshDepthCamList(const vector<DepthCamModule*> cams) {
vector<string> labels;
labels.push_back("none");
vector<DepthCamModule*>::const_iterator itCam=cams.begin();
for(; itCam!=cams.end(); ++itCam) {
labels.push_back((*itCam)->getName());
}
m_attributesMap["attached_to_camera"]
->editStringValuesChoices().assign(1, labels);
m_attributesMap["calibrate_with_camera"]
->editStringValuesChoices().assign(1, labels);
}
void ProjectorModule::attachToCam(const string& camName) {
if(m_space) {
if(m_attachedToCam) {
m_attachedToCam->detachProj(this);
}
m_attachedToCam = m_space->getDepthCamModule(camName);
if(m_attachedToCam) {
m_attachedToCam->attachProj(this);
}
}
}
void ProjectorModule::setWindowDimensions(const int& x, const int& y,
const int& w, const int& h) {
glfwSetWindowPos(m_projWindow, x, y);
glfwSetWindowSize(m_projWindow, w, h);
m_width=w;
m_height=h;
}
void ProjectorModule::setWindowDecoration(bool d) {
//m_window->setWindowDecoration(d);
}
void ProjectorModule::fullscreenMonitor(const std::string& monitorName) {
int count;
GLFWmonitor** monitors = glfwGetMonitors(&count);
GLFWmonitor* monitor = NULL;
for(int m=0; m<count; ++m) {
if(monitorName.compare(glfwGetMonitorName(monitors[m]))==0) {
monitor=monitors[m];
}
}
int posX=0;
int posY=0;
m_width=640;
m_height=480;
if(monitor) {
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
m_width=mode->width;
m_height=mode->height;
glfwGetMonitorPos(monitor, &posX, &posY);
}
m_posX=posX;
m_posY=posY;
glfwSetWindowMonitor(m_projWindow, monitor, 0, 0,
m_width, m_height, GLFW_DONT_CARE);
updateWindowDims();
refreshMonitors();
}
void ProjectorModule::refreshMonitors(){
int count;
GLFWmonitor** monitors = glfwGetMonitors(&count);
vector<string> monitorNames;
monitorNames.push_back("windowed");
for(int m=0; m<count; ++m) {
monitorNames.push_back(glfwGetMonitorName(monitors[m]));
}
m_attributesMap["fullscreen_monitor"]
->editStringValuesChoices().assign(count, monitorNames);
}
void ProjectorModule::setViewMatrix(const vector<float>& vals) {
m_viewMat = mat4(vals[0], vals[1], vals[2], vals[3],
vals[4], vals[5], vals[6], vals[7],
vals[8], vals[9], vals[10], vals[11],
vals[12], vals[13], vals[14], vals[15]);
updateViewProjMatrix();
}
void ProjectorModule::setProjectionMatrix(const vector<float>& vals) {
m_projMat = mat4(vals[0], vals[1], vals[2], vals[3],
vals[4], vals[5], vals[6], vals[7],
vals[8], vals[9], vals[10], vals[11],
vals[12], vals[13], vals[14], vals[15]);
updateViewProjMatrix();
}
void ProjectorModule::updateModelMatrix() {
if(!m_attachedToCam) {
Module::updateModelMatrix();
}
updateViewProjMatrix();
}
void ProjectorModule::setModelMat(const glm::mat4& mat) {
Module::setModelMat(mat);
updateViewProjMatrix();
}
void ProjectorModule::updateViewProjMatrix() {
m_transViewMat = m_modelMat * inverse(m_viewMat);
m_viewProjMat = m_projMat * inverse(m_transViewMat);
}
void ProjectorModule::setModuleName(const string& name) {
Module::setModuleName(name);
glfwSetWindowTitle(m_projWindow, name.c_str());
if(m_space) {
m_space->refreshProjList();
}
}
void ProjectorModule::outputRevealed(bool output) {
m_processOutput=output;
}
void ProjectorModule::postFilter(const int& filt) {
m_postFilter=filt;
}
void ProjectorModule::setTransparentWindow(const bool& transp) {
m_transparentBackground=transp;
}
void ProjectorModule::processOutput() {
bool outputProcessed=false;
//retrieve active revealed modules
vector<RevealedModule*>& revModules
= Reveal::getInstance()->editRegisteredOutputRevealed();
vector<DepthCamModule*>& camModules
= Reveal::getInstance()->editRegisteredOutputDepthCams();
if(revModules.size()>0 || camModules.size()>0) {
//retrieve output image
glBindTexture(GL_TEXTURE_2D, m_outputTex);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA,
GL_UNSIGNED_BYTE,
m_outputImg);
}
//process shape revealing output
if(revModules.size()>0) {
m_outNbDepth = m_space->getNbDepthModulesFromID();
//get output values for revealed modules with active output
vector<RevealedModule*>::iterator itSh = revModules.begin();
for(; itSh!=revModules.end(); ++itSh) {
//test if shape is visible from this projector
if((*itSh)->getVisibilityMask() & m_visibilityMask) {
for(int d=1; d<m_outNbDepth+1; ++d) {
DepthModule* mod = m_space->getDepthModuleFromID(d);
if(mod) {
if(mod->isDepthVisible(d)) {
(*itSh)->processReveal(d,
mod->getName(),
m_outNbDepth,
m_outputImg);
outputProcessed=true;
}
}
}
}
}
}
/*
//process cam
if(camModules.size()>0) {
unsigned int curs;
vector<float> pos(3,0);
vector<DepthCamModule*>::iterator itCa = camModules.begin();
for(; itCa!=camModules.end(); ++itCa) {
extractOutputValue((*itCa)->getDepthID()+500, 0, curs);
pos[0] = (int(curs) - int(curs/1000)*1000)*10-5000;
pos[1] = (int(curs/1000) - int(curs/1000000)*1000)*10-5000;
pos[2] = 10000-int(curs/1000000)*10;
//cout<<"got cursor "<<curs<<" from cam at pos "
// <<pos[0]<<" "<<pos[1]<<" "<<pos[2]<<endl;
(*itCa)->processCursor(pos);
}
outputProcessed=true;
}
*/
if(outputProcessed) {
//reset output image to 0
glBindTexture(GL_TEXTURE_2D, m_outputTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
m_outputImgSize, m_outputImgSize, 0,
GL_RGBA, GL_UNSIGNED_BYTE, m_outputImgInit);
}
}
void ProjectorModule::updateWindowSize(const int& w, const int& h) {
m_height=h;
m_width=w;
updateWindowDims();
}
void ProjectorModule::updateWindowPos(const int& x, const int& y) {
m_posX=x;
m_posY=y;
updateWindowDims();
}
void ProjectorModule::updateWindowDims() {
vector<int> dims(4,0);
dims[0]=m_posX;
dims[1]=m_posY;
dims[2]=m_width;
dims[3]=m_height;
m_attributesMap["window_dimensions"]->initInts(dims);
m_patternPosRange = Size(m_width, m_height);
}
//-------------------------Calibration----------------------------------
/*
static void cbPatternSquareWidth(int w, void* mod) {
if(w>10) {
ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
proj->setPatternSquareWidth(w);
}
}*/
void ProjectorModule::setPatternSquareWidth(const int& w) {
m_patternSquareWidth=w;
updateCalibrationPattern();
}
static void cbPatternPosOX(int x, void* mod) {
ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
proj->setPatternPosOX(x);
}
void ProjectorModule::setPatternPosOX(const int& x) {
m_patternPosOffset.width=x;
updateCalibrationPattern();
}
static void cbPatternPosOY(int y, void* mod) {
ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
proj->setPatternPosOY(y);
}
void ProjectorModule::setPatternPosOY(const int& y) {
m_patternPosOffset.height=y;
updateCalibrationPattern();
}
static void cbPatternPosRX(int x, void* mod) {
ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
proj->setPatternPosRX(x);
}
void ProjectorModule::setPatternPosRX(const int& x) {
m_patternPosRange.width=x;
updateCalibrationPattern();
}
static void cbPatternPosRY(int y, void* mod) {
ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
proj->setPatternPosRY(y);
}
void ProjectorModule::setPatternPosRY(const int& y) {
m_patternPosRange.height=y;
updateCalibrationPattern();
}
static void cbCalib(int c, void* mod) {
ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
proj->setCalib(c);
}
void ProjectorModule::setCalib(const int& c) {
if(m_calibrating==1 && c==0) {
m_calibrationStopped=true;
}
m_calibrating=c;
}
static void cbPatternBrightness(int b, void* mod) {
ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
proj->setPatternBrightness(b);
}
void ProjectorModule::setPatternBrightness(const int& b) {
m_patternBrightness=b;
}
void ProjectorModule::updateCalibrationPattern() {
m_generatedCorners.clear();
for(int j=1; j<m_patternSize.height+1; ++j) {
for(int i=1; i<m_patternSize.width+1; ++i) {
int cornerX=m_patternSquareWidth*i+m_patternPosition.width;
int cornerY=m_patternSquareWidth*j+m_patternPosition.height;
m_generatedCorners.push_back(Point2f(cornerX, cornerY));
}
}
}
void ProjectorModule::calibrate(const std::string& camName) {
//get depth camera module and activate color image
DepthCamModule* cam = NULL;
if(m_space) {
cam = m_space->getDepthCamModule(camName);
}
if(cam==NULL) {
cout<<"No camera attached to projector"<<endl;
return;
}
//close cam and reopen in calibration mode
cam->closeDevice();
cam->openDevice(cam->getDeviceID(), true);
//check cam is open
if(!cam->isOpen()) {
cout<<"Camera "<<cam->getName()<<"is not open"<<endl;
return;
}
cout<<"Calibrating projector ..."<<endl;
//create opencv windows, trackbars and initialize variables
m_imageSize = cv::Size(640 ,480); //fixme, get from cam color image size
m_calibrating=0;
m_calibrationStopped=false;
m_neededFramesNb=9;
cv::Mat kinectRgbImg = Mat::zeros(m_imageSize, CV_8UC3);
namedWindow("DepthCamRGB");
namedWindow("Controls");
createTrackbar("Pattern Offset X", "Controls",
&m_patternPosOffset.width, 1000, cbPatternPosOX, this);
createTrackbar("Pattern Offset Y", "Controls",
&m_patternPosOffset.height, 500, cbPatternPosOY, this);
createTrackbar("Pattern Range X", "Controls",
&m_patternPosRange.width, 1920, cbPatternPosRX, this);
createTrackbar("Pattern Range Y", "Controls",
&m_patternPosRange.height, 1080, cbPatternPosRY, this);
createTrackbar("Pattern Brightness", "Controls",
&m_patternBrightness, 100, cbPatternBrightness, this);
createTrackbar("Calibrate (1:Start, 0:Cancel)", "Controls",
NULL, 1, cbCalib, this);
vector<vector<Point3f> > objectPoints;
vector<vector<Point2f> > imagePoints;
Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
Mat distCoeffs = Mat::zeros(8, 1, CV_64F);
vector<Mat> rvecs;
vector<Mat> tvecs;
cam->activateColor();
for(int f=0; f<m_neededFramesNb && !m_calibrationStopped;) {
//update pattern position
m_patternSquareWidth = m_height/20;
m_patternPosition.width = (m_patternPosRange.width-m_patternSquareWidth)
/ sqrt(m_neededFramesNb)
*(fmod(f,sqrt(m_neededFramesNb)))
+m_patternSquareWidth
+m_patternPosOffset.width;
m_patternPosition.height=(m_patternPosRange.height-m_patternSquareWidth)
/ sqrt(m_neededFramesNb)
*(floor(f/sqrt(m_neededFramesNb)))
+m_patternSquareWidth
+m_patternPosOffset.height;
updateCalibrationPattern();
//display frame with calibration pattern
glfwMakeContextCurrent(m_projWindow);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, m_width, m_height);
glDisable(GL_CULL_FACE);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUseProgram(m_programs[Reveal::CALIBPROG]);
glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTWIDTH],
m_width);
glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTHEIGHT],
m_height);
glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATW],
m_patternSquareWidth);
glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATPOSX],
m_patternPosition.width);
glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATPOSY],
m_patternPosition.height);
glUniform2f(m_uniforms[Reveal::CALIBPROG][Reveal::PATOFFSET],
m_patternPosOffset.width, m_patternPosOffset.height);
glUniform2f(m_uniforms[Reveal::CALIBPROG][Reveal::PATRANGE],
m_patternPosRange.width, m_patternPosRange.height);
glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATNBX],
m_patternSize.width);
glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATNBY],
m_patternSize.height);
glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATBRIGHT],
float(m_patternBrightness)/100.0);
m_calibGeom->drawDirect(m_contextHandlerID);
glfwSwapBuffers(m_projWindow);
waitKey(10);
sleep(1);
//grab frame
if(cam->getFrames()) {
openni::VideoFrameRef depthFrame = cam->getDepthFrame();
openni::VideoFrameRef colorFrame = cam->getColorFrame();
//copy to opencv mat
for(int j=0; j<m_imageSize.height; ++j) {
for(int i=0; i<m_imageSize.width; ++i) {
cv::Vec3b& pix = kinectRgbImg.at<cv::Vec3b>(j,i);
int coord=0;
coord=j*m_imageSize.width+i;
openni::RGB888Pixel colorPix =
((openni::RGB888Pixel*) colorFrame.getData())[coord];
pix[0]=colorPix.r;
pix[1]=colorPix.g;
pix[2]=colorPix.b;
}
}
imshow("DepthCamRGB", kinectRgbImg);
if(m_calibrating) {
m_foundCorners.clear();
//find chessboard in image
bool patternFound = findChessboardCorners(
kinectRgbImg,
m_patternSize,
m_foundCorners,
CALIB_CB_ADAPTIVE_THRESH);
//if we found it
if(patternFound) {
//refine
Mat gray;
cvtColor(kinectRgbImg, gray, COLOR_RGB2GRAY);
cornerSubPix(gray, m_foundCorners,
cv::Size(1, 1), cv::Size(-1, -1),
TermCriteria(TermCriteria::EPS,
30, 0.1));
bool validDepths=true;
//retrieve the corresponding position and depth
vector<Point3f> worldCorners;
vector<Point2f>::iterator itPnt=m_foundCorners.begin();
for(; itPnt!=m_foundCorners.end(); ++itPnt) {
float posX, posY, posZ;
Point2f coord = Point2f((*itPnt).x,(*itPnt).y);
Point2f depthCoord = coord;
openni::DepthPixel depthPix =
((openni::DepthPixel*)depthFrame.getData())[int(
depthCoord.y*m_imageSize.width +
depthCoord.x)];
posZ=depthPix;
//filter the depth
int size=6;
vector<double> vals;
for(int x=depthCoord.x-size/2;
x<depthCoord.x+size/2; ++x) {
for(int y=depthCoord.y-size/2;
y<depthCoord.y+size/2; ++y) {
if(x>=0 && x<m_imageSize.width &&
y>=0 && y<m_imageSize.height) {
vals.push_back(
((openni::DepthPixel*)depthFrame.getData())
[int(y*m_imageSize.width + x)]);
}
}
}
sort(vals.begin(), vals.end());
posZ=vals[vals.size()/2];
depthPix=posZ;
openni::CoordinateConverter::convertDepthToWorld(
cam->getDepthStream(),
int(depthCoord.x),
int(depthCoord.y),
depthPix,
&posX, &posY, &posZ);
//if(reversed) {
// posX=-posX;
// posY=-posY;
//}
if(posZ<=500.0 || posZ>4000.0) {
validDepths=false;
}
else {
worldCorners.push_back(Point3f(posX, posY, posZ));
}
}
//if everything is valid
if(validDepths) {
cout<<"Pattern found "<<f<<"/"<<m_neededFramesNb<<endl;
//add the generated corners
imagePoints.push_back(m_generatedCorners);
cout<<m_generatedCorners[0]<<endl;
//add the detected world corners
objectPoints.push_back(worldCorners);
cout<<worldCorners[0]<<endl;
//cout<<m_generatedCorners<<endl;
//cout<<worldCorners<<endl;
//draw corners
drawChessboardCorners(kinectRgbImg, m_patternSize,
m_foundCorners, patternFound);
imshow("DepthCamRGB", kinectRgbImg);
waitKey(10);
//wait
#ifdef POSIX
sleep(1);
#else
Sleep(1000);
#endif
//increase frame count
++f;
}
}
}
waitKey(10);
}
}
double rms=0;
if(objectPoints.size()>0) {
//put the image and object points in the right order for opencv
vector<vector<Point3f> > vvo(1); //object points
vector<vector<Point2f> > vvi(1); //image points
for (unsigned int i=0; i<objectPoints.size(); ++i) {
for (unsigned int j = 0; j<objectPoints[i].size(); j++) {
vvo[0].push_back(objectPoints[i][j]);
vvi[0].push_back(imagePoints[i][j]);
}
}
//when enough points found, get the extrinsics/intrisics parameter
float w = m_width;
float h = m_height;
cameraMatrix = (Mat1d(3, 3) << w, 0, w/2.,
0, h, h / 2.,
0, 0, 1);
distCoeffs = Mat::zeros(8, 1, CV_64F);
rms=calibrateCamera(vvo, vvi,
Size(w, h), cameraMatrix,
distCoeffs, rvecs, tvecs,
CALIB_FIX_K1+
CALIB_FIX_K2+
CALIB_FIX_K3+
CALIB_FIX_K4+
CALIB_FIX_K5+
CALIB_FIX_K6+
CALIB_ZERO_TANGENT_DIST+
CALIB_USE_INTRINSIC_GUESS);
cout<<"... done , RMS="<<rms<<endl;
//Build the opengl view matrix
Mat rot;
rvecs[0].copyTo(rot);
Mat rotMat = Mat::zeros(3, 3, CV_64F);
Rodrigues(rot, rotMat);
mat4 viewMatrix(rotMat.at<double>(0,0), rotMat.at<double>(1,0),
rotMat.at<double>(2,0), 0,
rotMat.at<double>(0,1), rotMat.at<double>(1,1),
rotMat.at<double>(2,1), 0,
rotMat.at<double>(0,2), rotMat.at<double>(1,2),
rotMat.at<double>(2,2), 0,
tvecs[0].at<double>(0,0), tvecs[0].at<double>(1,0),
tvecs[0].at<double>(2,0), 1);
mat4 glCoordsMat(-1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
m_viewMat=glCoordsMat*viewMatrix;
m_attributesMap["view_matrix"]->setFloats(
vector<float>(
value_ptr(m_viewMat),
value_ptr(m_viewMat)+16));
//build the opengl projection matrix
double fx=cameraMatrix.at<double>(0,0);
double cx=cameraMatrix.at<double>(0,2);
double fy=cameraMatrix.at<double>(1,1);
double cy=cameraMatrix.at<double>(1,2);
double l=0;
double r=w;
double b=h;
double t=0;
double n=100;
double f=10000;
mat4 projMatrix(
2.0*fx/w, 0, 0, 0,
0, 2.0*fy/h, 0, 0,
1.0-2.0*(cx)/w,-1.0+(2.0*(cy)+2.0)/h, (f+n)/(n-f), -1,
0, 0, (2.0*f*n)/(n-f), 0);
m_attributesMap["projection_matrix"]->setFloats(
vector<float>(value_ptr(projMatrix),
value_ptr(projMatrix)+16));
m_attributesMap["attached_to_camera"]
->setStrings(vector<string>(1, cam->getName()));
}
ostringstream oss;
oss<<rms;
cv::Mat reconstructionImg = Mat::zeros(Size(m_width, m_height), CV_8UC3);
//project reconstructed kinect
while(!m_calibrationStopped) {
if(cam->getFrames()) {
openni::VideoFrameRef depthFrame = cam->getDepthFrame();
openni::VideoFrameRef colorFrame = cam->getColorFrame();
//get points from the kinect and their actual 3D positions
reconstructionImg.setTo(cv::Vec3b(0,0,0));
vector<Point3f> objPnts;
vector<cv::Vec3b> kinPnts;
vector<Point2f> imgPnts;
for(int j=0; j<m_imageSize.height; ++j) {
for(int i=0; i<m_imageSize.width; ++i) {
float posX, posY, posZ;
int coord = m_imageSize.width*j+i;
openni::DepthPixel depthPix =
((openni::DepthPixel*)depthFrame.getData())[coord];
openni::CoordinateConverter::convertDepthToWorld(
cam->getDepthStream(),
i, j, depthPix,
&posX, &posY, &posZ);
objPnts.push_back(Point3f(posX,posY,posZ));
const openni::RGB888Pixel& colorPix =
((openni::RGB888Pixel*) colorFrame.getData())[coord];
kinPnts.push_back(cv::Vec3b(colorPix.r,
colorPix.g,
colorPix.b));
}
}
projectPoints(objPnts, rvecs[0], tvecs[0],
cameraMatrix, distCoeffs, imgPnts);
//for each of the image points
vector<Point2f>::iterator itPnt=imgPnts.begin();
vector<cv::Vec3b>::iterator itKin=kinPnts.begin();
vector<Point3f>::iterator itObj=objPnts.begin();
for(; itPnt!=imgPnts.end() && itKin!=kinPnts.end();
++itPnt, ++itKin, ++itObj) {
if((*itPnt).x<reconstructionImg.cols &&
(*itPnt).y<reconstructionImg.rows &&
(*itPnt).x>0 &&
(*itPnt).y>0) {
reconstructionImg.at<cv::Vec3b>(
(*itPnt).y,
(*itPnt).x)
=(*itKin);
}
}
putText(reconstructionImg, "RMS="+oss.str(), Point(0,50),
cv::FONT_HERSHEY_SIMPLEX, 2,
Scalar(255, 255, 255));
imshow( "DepthCamRGB", reconstructionImg);
}
waitKey(10);
}
//close opencv windows
destroyWindow("DepthCamRGB");
destroyWindow("Controls");
waitKey(10);
//reopen cam in normal mode
cam->closeDevice();
cam->openDevice(cam->getDeviceID());
}
void ProjectorModule::calibrateCamWithMarker(const std::string& camName) {
}