3dpcp/.svn/pristine/7e/7e83972a871ef8774dfcdd91945515d308e06b77.svn-base
2012-10-05 08:55:14 +02:00

2047 lines
54 KiB
Text

/*
* show_gl implementation
*
* Copyright (C) Kai Lingemann, Andreas Nuechter, Jan Elseberg, Dorit Borrmann
*
* Released under the GPL version 3.
*
*/
#include <string.h>
#include <stdlib.h>
#include "show/viewcull.h"
#include "show/scancolormanager.h"
bool fullydisplayed = true; // true if all points have been drawn to the screen
bool mousemoving = false; // true iff a mouse button has been pressed inside a window,
// but hs not been released
bool keypressed = false; // true iff a key button has been pressed inside a window,
// but hs not been released
double ptstodisplay = 100000;
double lastfps = idealfps; // last frame rate
int pointmode = -1;
bool smallfont = true;
bool label = true;
/**
* Displays all data (i.e., points) that are to be displayed
* @param mode spezification for drawing to screen or in selection mode
*/
void DrawPoints(GLenum mode, bool interruptable)
{
long time = GetCurrentTimeInMilliSec();
double min = 0.000000001;
double max = 1.0;
LevelOfDetail *= 1.0 + adaption_rate*(lastfps - idealfps)/idealfps;
if (LevelOfDetail > max) LevelOfDetail = max;
else if (LevelOfDetail < min) LevelOfDetail = min;
// In case of animation
if(frameNr != 0) {
cm->setMode(ScanColorManager::MODE_ANIMATION);
#ifdef USE_GL_POINTS
for(int iterator = (int)octpts.size()-1; iterator >= 0; iterator--) {
#else
for(int iterator = (int)Scan::allScans.size()-1; iterator >= 0; iterator--) {
#endif
// ignore scans that don't have any frames associated with them
if((unsigned int)iterator >= MetaMatrix.size()) continue;
// set usable frame
double* frame;
Scan::AlgoType type;
if((unsigned int)frameNr >= MetaMatrix[iterator].size()) {
// use last possible frame
frame = MetaMatrix[iterator].back();
type = MetaAlgoType[iterator].back();
} else {
frame = MetaMatrix[iterator][frameNr];
type = MetaAlgoType[iterator][frameNr];
}
if(type == Scan::INVALID) continue;
cm->selectColors(type);
glPushMatrix();
glMultMatrixd(frame);
glPointSize(pointsize);
#ifdef USE_GL_POINTS
ExtractFrustum(pointsize);
cm->selectColors(type);
if (pointmode == 1 ) {
octpts[iterator]->display();
} else {
octpts[iterator]->displayLOD(LevelOfDetail);
}
#else
for (unsigned int jterator = 0; jterator < vvertexArrayList[iterator].size(); jterator++) {
if ((jterator == 0) && vvertexArrayList[iterator][jterator]->numPointsToRender > 0) {
cm->selectColors(type);
}
if (vvertexArrayList[iterator][jterator]->numPointsToRender > 0) {
glCallList(vvertexArrayList[iterator][jterator]->name);
}
}
#endif
glPopMatrix();
}
setScansColored(0);
} else {
if(mode == GL_SELECT){
// select points mode
// ------------------
GLuint name = 0;
for(int iterator = (int)octpts.size()-1; iterator >= 0; iterator--) {
glPushMatrix();
glMultMatrixd(MetaMatrix[iterator].back());
glColor4f(1.0, 0.0, 0.0,1.0);
glPointSize(pointsize + 2.0);
for ( set<sfloat*>::iterator it = selected_points[iterator].begin();
it != selected_points[iterator].end(); it++) {
glLoadName(name++);
glBegin(GL_POINTS);
glVertex3d((*it)[0], (*it)[1], (*it)[2]);
glEnd();
}
glPointSize(pointsize);
glFlush();
glPopMatrix();
}
} else {
// draw point is normal mode
// -------------------------
if (interruptable) {
glDrawBuffer (GL_FRONT);
}
glPointSize(pointsize);
vector<int> sequence;
calcPointSequence(sequence, current_frame);
#ifdef USE_GL_POINTS
//for(int iterator = (int)octpts.size()-1; iterator >= 0; iterator--) {
for(unsigned int i = 0; i < sequence.size(); i++) {
int iterator = sequence[i];
#else
for(int iterator = (int)Scan::allScans.size()-1; iterator >= 0; iterator--) {
#endif
// ignore scans that don't have any frames associated with them
if((unsigned int)iterator >= MetaMatrix.size()) continue;
// set usable frame
double* frame;
Scan::AlgoType type;
if((unsigned int)current_frame >= MetaMatrix[iterator].size()) {
// use last possible frame
frame = MetaMatrix[iterator].back();
type = MetaAlgoType[iterator].back();
} else {
frame = MetaMatrix[iterator][current_frame];
type = MetaAlgoType[iterator][current_frame];
}
if (type == Scan::INVALID) continue;
glPushMatrix();
if (invert) // default: white points on black background
glColor4d(1.0, 1.0, 1.0, 0.0);
else // black points on white background
glColor4d(0.0, 0.0, 0.0, 0.0);
// glMultMatrixd(MetaMatrix[iterator].back());
if (current_frame != (int)MetaMatrix.back().size() - 1) {
cm->setMode(ScanColorManager::MODE_ANIMATION);
cm->selectColors(type);
}
glMultMatrixd(frame);
#ifdef USE_GL_POINTS
//cout << endl << endl; calcRay(570, 266, 1.0, 40000.0);
/* // for height mapped color in the vertex shader
GLfloat v[16];
for (unsigned int l = 0; l < 16; l++)
v[l] = MetaMatrix[iterator].back()[l];
glUniformMatrix4fvARB(glGetUniformLocationARB(p, "MYMAT"), 1, 0, v);
*/
ExtractFrustum(pointsize);
if (pointmode == 1 ) {
octpts[iterator]->display();
} else if (interruptable) {
checkForInterrupt();
glFlush();
glFinish();
if (isInterrupted()) {
glPopMatrix();
return;
}
octpts[iterator]->display();
} else {
octpts[iterator]->displayLOD(LevelOfDetail);
}
if (!selected_points[iterator].empty()) {
glColor4f(1.0, 0.0, 0.0, 1.0);
glPointSize(pointsize + 2.0);
glBegin(GL_POINTS);
for ( set<sfloat*>::iterator it = selected_points[iterator].begin();
it != selected_points[iterator].end(); it++) {
glVertex3d((*it)[0], (*it)[1], (*it)[2]);
}
glEnd();
glPointSize(pointsize);
}
#else
for (unsigned int jterator = 0; jterator < vvertexArrayList[iterator].size(); jterator++) {
if (vvertexArrayList[iterator][jterator]->numPointsToRender > 0) {
glCallList(vvertexArrayList[iterator][jterator]->name);
}
}
#endif
glPopMatrix();
}
}
}
if (pointmode == 1 ) {
fullydisplayed = true;
} else {
unsigned long td = (GetCurrentTimeInMilliSec() - time);
if (td > 0)
lastfps = 1000.0/td;
else
lastfps = 1000.0;
fullydisplayed = false;
}
if (interruptable)
fullydisplayed = true;
}
void DrawObjects(GLenum mode) {
for (unsigned int i = 0; i < displays.size(); i++)
displays[i]->displayAll();
}
/**
* Draw a smooth path passing from all the camera points.
*
*/
void DrawPath()
{
glLineWidth(10.0);
// draw path
glBegin(GL_LINE_STRIP);
for(unsigned int j = 0; j < path_vectorX.size(); j++){
// set the color
glColor4f(0.0, 1.0, 0.0, 1.0);
// set the points
glVertex3f(path_vectorX.at(j).x,path_vectorX.at(j).y,path_vectorZ.at(j).y);
}
glEnd();
// draw lookat path
glBegin(GL_LINE_STRIP);
for(unsigned int j = 0; j < lookat_vectorX.size(); j++){
//set the color
glColor4d(1.0, 1.0, 0.0, 1.0);
//set the points
glVertex3f(lookat_vectorX.at(j).x,lookat_vectorX.at(j).y,lookat_vectorZ.at(j).y);
}
glEnd();
// draw up path
/*
glBegin(GL_LINE_STRIP);
for(unsigned int j = 0; j < ups_vectorX.size(); j++){
//set the color
glColor4d(0.0, 1.0, 0.0, 0.7);
//set the points
glVertex3f(ups_vectorX.at(j).x,ups_vectorX.at(j).y,ups_vectorZ.at(j).y);
}
glEnd();
*/
}
/**
* Draw the camera boxes in the viewer
*
*/
void DrawCameras(void)
{
for (unsigned int i = 0; i < cams.size(); i++) {
glPushMatrix();
// TODO improve upon this primitive camera
Point p = cams[i];
Point l = Point::norm( lookats[i] - p ); // forward vector
Point u = Point::norm( ups[i] - p ); // up vector
Point r = Point::cross(l,u); // right vector
l = 5 * l;
r = 5 * r;
u = 5 * u;
Point cube[8];
cube[0] = p + l - r - u;
cube[1] = p + l + r - u;
cube[2] = p - l + r - u;
cube[3] = p - l - r - u;
cube[4] = p + l - r + u;
cube[5] = p + l + r + u;
cube[6] = p - l + r + u;
cube[7] = p - l - r + u;
int sides[6][4] = {{0,1,2,3}, {4,5,6,7}, {0,1,5,4},
{3,2,6,7}, {1,2,6,5}, {0,3,7,4}};
if (i+1 == cam_choice) {
glColor4f(1, 0, 1, 1);
} else {
glColor4f(0, 1, 0, 1);
}
// camera cube
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_QUADS);
for (int j = 0; j < 6; j++) {
if (j == 2) continue;
for (int k = 0; k < 4; k++) {
int index = sides[j][k];
glVertex3d(cube[index].x, cube[index].y, cube[index].z);
}
}
glEnd();
r = 5 * r;
u = 5 * u;
glColor4f(1, 1, 0, 1);
if (i+1 == cam_choice) {
glPointSize(10);
} else {
glPointSize(5);
}
glBegin(GL_POINTS);
glVertex3d( lookats[i].x, lookats[i].y, lookats[i].z);
glEnd();
Point fcube[8];
fcube[0] = cube[4];
fcube[1] = cube[5];
fcube[2] = cube[1];
fcube[3] = cube[0];
fcube[4] = lookats[i] - r + u;
fcube[5] = lookats[i] + r + u;
fcube[6] = lookats[i] + r - u;
fcube[7] = lookats[i] - r - u;
glLineWidth(2.0);
glLineStipple(1, 0x0C0F);
glEnable(GL_LINE_STIPPLE);
glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
// camera FOV
glBegin(GL_QUADS);
for (int j = 0; j < 6; j++) {
for (int k = 0; k < 4; k++) {
int index = sides[j][k];
glVertex3d(fcube[index].x, fcube[index].y, fcube[index].z);
}
}
glEnd();
glDisable(GL_LINE_STIPPLE);
/*
if (i+1 == cam_choice) {
glColor3f(1, 1, 0);
glPointSize(20);
} else {
glColor3f(0, 0, 1);
glPointSize(10);
}
glBegin(GL_POINTS);
glVertex3d(p.x, p.y, p.z);
glEnd();
if (i+1 == cam_choice) {
glColor3f(0, 1, 1);
glPointSize(20);
} else {
glColor3f(1, 0, 0);
glPointSize(10);
}
glBegin(GL_POINTS);
glVertex3d( l.x, l.y, l.z);
glEnd();
if (i+1 == cam_choice) {
glColor3f(1, 0, 1);
glPointSize(20);
} else {
glColor3f(0, 1, 0);
glPointSize(10);
}
glBegin(GL_POINTS);
glVertex3d( u.x, u.y, u.z);
glEnd();
*/
glPopMatrix();
}
}
//-----------------------------------------------------------------------------------
/**
* Display function
*/
void DisplayItFunc(GLenum mode, bool interruptable)
{
/**
* Color of the fog
*/
GLfloat fogColor[4];
if(!invert) {
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_COPY_INVERTED);
}
// set the clear color buffer in case of
// both invert and non invert mode
if (invert)
glClearColor(0.0, 0.0, 0.0, 0.0);
else
glClearColor(1.0, 1.0, 1.0, 1.0);
// clear the color and depth buffer bit
if (!interruptable) { // single buffer mode, we need the depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
glPushMatrix();
// set the matrix mode
glMatrixMode(GL_MODELVIEW);
// init modelview matrix
glLoadIdentity();
// set the polygon mode
glPolygonMode(GL_FRONT/*_AND_BACK*/, GL_LINE);
// do the model-transformation
if (haveToUpdate == 6 && path_iterator < path_vectorX.size() ) {
gluLookAt(path_vectorX.at(path_iterator).x,
path_vectorX.at(path_iterator).y,
path_vectorZ.at(path_iterator).y,
lookat_vectorX.at(path_iterator).x,
lookat_vectorX.at(path_iterator).y,
lookat_vectorZ.at(path_iterator).y,
ups_vectorX.at(path_iterator).x - path_vectorX.at(path_iterator).x,
ups_vectorX.at(path_iterator).y - path_vectorX.at(path_iterator).y,
ups_vectorZ.at(path_iterator).y - path_vectorZ.at(path_iterator).y);
} else {
if (cameraNavMouseMode == 1) {
glRotated( mouseRotX, 1, 0, 0);
glRotated( mouseRotY, 0, 1, 0);
glRotated( mouseRotZ, 0, 0, 1);
glGetFloatv(GL_MODELVIEW_MATRIX, view_rotate_button);
update_view_rotate(0);
} else {
double t[3] = {0,0,0};
double mat[16];
QuatToMatrix4(quat, t, mat);
glMultMatrixd(mat);
glGetFloatv(GL_MODELVIEW_MATRIX, view_rotate_button);
//glRotated(angle, axis[0], axis[1], axis[2]); // rotate the camera
double rPT[3];
Matrix4ToEuler(mat, rPT);
mouseRotX = deg(rPT[0]);
mouseRotY = deg(rPT[1]);
mouseRotZ = deg(rPT[2]);
}
updateControls();
glTranslated(X, Y, Z); // move camera
}
// cout << "Position :" << X << " " << Y << " " << Z << endl;
// cout << "Quaternion:" << quat[0] << " " << quat[1] << " " << quat[2] << " " << quat[3] << endl;
// cout << "Axis/Angle:" << axis[0] << " " << axis[1] << " " << axis[2] << " " << angle << endl;
// cout << "Apex angle:" << cangle << endl;
// cout << endl;
// process fog
if (show_fog > 0) {
if (show_fog > 3)
fogColor[0] = fogColor[1] = fogColor[2] = fogColor[3] = 1.0;
else
fogColor[0] = fogColor[1] = fogColor[2] = fogColor[3] = 0.0;
glEnable(GL_FOG);
{
// ln(1/2^8) = -5.54517744 -> threshold at which the last color bit is gone due to fog
if (show_fog==1) {fogMode = GL_EXP; fardistance = min(5.54517744 / fogDensity, (double)maxfardistance);}
else if (show_fog==2) {fogMode = GL_EXP2; fardistance = min(sqrt(5.54517744) / fogDensity, (double)maxfardistance);}
else if (show_fog==3) {fogMode = GL_LINEAR; fardistance = 32000.0;}
else if (show_fog==4) {fogMode = GL_EXP; fardistance = (double)maxfardistance; }
else if (show_fog==5) {fogMode = GL_EXP2; fardistance = (double)maxfardistance; }
else if (show_fog==6) {fogMode = GL_LINEAR; fardistance = (double)maxfardistance;}
glFogi(GL_FOG_MODE, fogMode);
glFogfv(GL_FOG_COLOR, fogColor);
glFogf(GL_FOG_DENSITY, fogDensity);
glHint(GL_FOG_HINT, GL_FASTEST);
glFogf(GL_FOG_START, neardistance);
glFogf(GL_FOG_END, maxfardistance);
}
} else {
glDisable(GL_FOG);
fardistance = maxfardistance;
}
if (fardistance > maxfardistance) fardistance = maxfardistance;
if ( fabs(oldfardistance - fardistance) > 0.00001 || fabs(oldneardistance - neardistance) > 0.00001 ) {
oldfardistance = fardistance;
oldneardistance = neardistance;
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
CallBackReshapeFunc(viewport[2],viewport[3]);
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// show the objects __after__ the model-transformation
// for all status variables we show the appropiated thing
// using the drawing functions
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (show_path == 1) {
double *pose;
glColor4d(1.0, 0.0, 0.0, 1.0);
glLineWidth(5);
glBegin(GL_LINE_STRIP);
for(unsigned int i = 0; i < MetaMatrix.size(); i++){
// set usable type
Scan::AlgoType type;
if((unsigned int)frameNr >= MetaMatrix[i].size()) {
type = MetaAlgoType[i].back();
} else {
type = MetaAlgoType[i][frameNr];
}
if(frameNr >= 1 && frameNr < (int)MetaMatrix[i].size()) {
if(type == Scan::INVALID) continue;
// avoid incomplete frames in a scan
if((unsigned int)frameNr >= MetaMatrix[i].size())
pose = MetaMatrix[i].back();
else
pose = MetaMatrix[i][frameNr];
} else {
//pose = MetaMatrix[i].back();
// avoid incomplete frames in a scan
if((unsigned int)current_frame >= MetaMatrix[i].size())
pose = MetaMatrix[i].back();
else
pose = MetaMatrix[i][current_frame];
}
if(showTopView) {
glVertex3f(pose[12], 2000, pose[14]);
} else {
glVertex3f(pose[12], pose[13], pose[14]);
}
}
glEnd();
}
// if show camera is true then draw cameras.
if (show_cameras == 1) {
DrawCameras();
}
// if show path is true the draw path.
if (show_path == 1) {
DrawPath();
}
DrawObjects(mode);
if (label) DrawUrl();
// if show points is true the draw points
if (show_points == 1) DrawPoints(mode, interruptable);
glPopMatrix();
if (!invert) {
glDisable(GL_COLOR_LOGIC_OP);
}
// force draw the scene
glFlush();
glFinish();
}
void DrawUrl() {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
// Save the current projection matrix
glPushMatrix();
// Make the current matrix the identity matrix
glLoadIdentity();
// Set the projection (to 2D orthographic)
glOrtho(0.0,100.0,0.0,100.0,-1.5,1.5);
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // TODO
glColor4d(0.0,0.0,0.0,0.7);
glBegin(GL_QUADS);
glVertex3f(0,0,1.49);
glVertex3f(0,6,1.49);
if(smallfont) {
glVertex3f(22,6,1.49);
glVertex3f(22,0,1.49);
} else {
glVertex3f(25,6,1.49);
glVertex3f(25,0,1.49);
}
glEnd();
glBlendFunc(GL_ONE, GL_ZERO);
glColor3f(1,1,1);
if(smallfont) {
glRasterPos3f(1,3.5,1.5);
_glutBitmapString(GLUT_BITMAP_8_BY_13, "created by 3DTK");
glRasterPos3f(1,1,1.5);
_glutBitmapString(GLUT_BITMAP_8_BY_13, "http://threedtk.de");
} else {
glRasterPos3f(1,3.5,1.5);
_glutBitmapString(GLUT_BITMAP_9_BY_15, "created by 3DTK");
glRasterPos3f(1,1,1.5);
_glutBitmapString(GLUT_BITMAP_9_BY_15, "http://threedtk.de");
}
// Restore the original projection matrix
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
/**
* Function topview. Set the screen for top view.
*/
void topView()
{
static GLdouble save_qx, save_qy, save_qz, save_qangle, save_X, save_Y, save_Z;
static GLdouble saveMouseRotX, saveMouseRotY, saveMouseRotZ;
if (!showTopView) // set to top view
{
showTopView = true;
// save current pose
save_X = X;
save_Y = Y;
save_Z = Z;
save_qx = quat[0];
save_qy = quat[1];
save_qz = quat[2];
save_qangle = quat[3];
saveMouseRotX = mouseRotX;
saveMouseRotY = mouseRotY;
saveMouseRotZ = mouseRotZ;
Y = Y - 350.0;
Z = Z + 500.0;
quat[0] = quat[1] = sqrt(0.5);
quat[2] = quat[3] = 0.0;
mouseRotX = 90;
mouseRotY = 0;
mouseRotZ = 0;
haveToUpdate = 2;
} else {
showTopView = false;
// restore old settings
X = save_X;
Y = save_Y;
Z = save_Z;
quat[0] = save_qx;
quat[1] = save_qy;
quat[2] = save_qz;
quat[3] = save_qangle;
mouseRotX = saveMouseRotX;
mouseRotY = saveMouseRotY;
mouseRotZ = saveMouseRotZ;
haveToUpdate = 2;
}
}
//---------------------------------------------------------------------------
/**
* This function is called when the user wants to
* delete a camera.
*/
void callDeleteCamera(int dummy){
//iterator for the position of camera
//in the camera list
vector<Point>::iterator position;
vector<Point>::iterator positionL;
vector<Point>::iterator positionU;
//calculate the position of the camera. we are referring
//to the selected camera
position = cams.begin()+ (cam_choice-1);
positionL = lookats.begin()+ (cam_choice-1);
positionU = ups.begin()+ (cam_choice-1);
//if no camera present then return
if(cam_choice == 0)
return;
//if the list is not empty then
if(!cams.empty()){
//delete the camera from the position
cams.erase(position);
lookats.erase(positionL);
ups.erase(positionU);
//reset the cam_choice spinner values
}
updateCamera();
}
//---------------------------------------------------------------------------
/**
* Function to reset the viewer window.
*/
void resetView(int dummy)
{
cangle = 60.0;
pzoom = defaultZoom;
X = RVX;
Y = RVY;
Z = RVZ;
quat[0] = Rquat[0];
quat[1] = Rquat[1];
quat[2] = Rquat[2];
quat[3] = Rquat[3];
haveToUpdate = 2;
mouseRotX = 0;
mouseRotY = 0;
mouseRotZ = 0;
resetRotationButton();
}
/**
* Function to set the viewer window back to a previously saved state.
*/
void setView(double pos[3], double new_quat[4],
double newMouseRotX, double newMouseRotY, double newMouseRotZ,
double newCangle,
bool sTV, bool cNMM, double pzoom_new,
bool s_points, bool s_path, bool s_cameras, double ps, int
sf, double fD, bool inv)
{
X = pos[0];
Y = pos[1];
Z = pos[2];
for(int i = 0; i < 4; i++) {
quat[i] = new_quat[i];
}
cangle = newCangle;
mouseRotX = newMouseRotX;
mouseRotY = newMouseRotY;
mouseRotZ = newMouseRotZ;
showTopView = sTV,
cameraNavMouseMode = cNMM;
pzoom = pzoom_new;
updateTopViewControls();
show_points = s_points;
show_path = s_path;
show_cameras = s_cameras;
pointsize = ps;
show_fog = sf;
fogDensity = fD;
invert = inv;
haveToUpdate = 2;
}
/**
* This function is called when the viewer is created. This
* acts as the display function.
*/
void CallBackDisplayFunc()
{
if ((cangle_spinner != 0 && (fabs(cangle_old - cangle) > 0.5)) ||
(pzoom_spinner != 0 && (fabs(pzoom_old - pzoom) > 0.5))) {
cangle_old = cangle;
pzoom_old = pzoom;
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
CallBackReshapeFunc(viewport[2],viewport[3]);
#ifdef _MSC_VER
Sleep(25);
#else
usleep(250000);
#endif
}
glDrawBuffer(buffermode);
// delete framebuffer and z-buffer
//Call the display function
DisplayItFunc(GL_RENDER );
// show the rednered scene
glutSwapBuffers();
}
/**
* This function is called when there is nothing to be done
* in the screen.
*/
void CallBackIdleFunc(void)
{
#ifdef _MSC_VER
Sleep(1);
#else
usleep(1000);
#endif
if(glutGetWindow() != window_id)
glutSetWindow(window_id);
// return as nothing has to be updated
if (haveToUpdate == 0) {
if (!fullydisplayed && !mousemoving && !keypressed && pointmode == 0
) {
glDrawBuffer(buffermode);
//Call the display function
DisplayItFunc(GL_RENDER, true);
}
return;
}
// case: display is invalid - update it
if (haveToUpdate == 1) {
glutPostRedisplay();
haveToUpdate = 0;
return;
}
// case: display is invalid - update it with all points
/* if (haveToUpdate == 7) {
showall = true;
glutPostRedisplay();
haveToUpdate = 0;
return;
}*/
// case: camera angle is changed - instead of repeating code call Reshape,
// since these OpenGL commands are the same
if (haveToUpdate == 2) {
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
CallBackReshapeFunc(viewport[2],viewport[3]);
glutPostRedisplay();
haveToUpdate = 0;
return;
}
// case: animation
if(haveToUpdate == 3 ){
frameNr += 1;
if(!(MetaMatrix.size() > 1 && frameNr < (int) MetaMatrix[1].size())){
frameNr = 0;
haveToUpdate = 4;
return;
}
glutPostRedisplay();
if(save_animation){
string filename = scan_dir + "animframe" + to_string(frameNr,5) + ".ppm";
cout << "write " << filename << endl;
int tmpUpdate = haveToUpdate;
glWriteImagePPM(filename.c_str(), factor, 0);
haveToUpdate = tmpUpdate;
string jpgname = scan_dir + "animframe" + to_string(frameNr,5) + ".jpg";
string systemcall = "convert -quality 100 -type TrueColor " + filename + " " + jpgname;
// cout << systemcall << endl;
system(systemcall.c_str());
systemcall = "rm " + filename;
system(systemcall.c_str());
// cout << systemcall << endl;
// for f in *ppm ; do convert -quality 100 -type TrueColor $f `basename $f ppm`jpg; done
}
}
#ifdef _MSC_VER
Sleep(300);
Sleep(anim_delay);
#else
usleep(anim_delay * 10000);
#endif
if (haveToUpdate == 4) { // stop animation
frameNr = 0; // delete these lines if you want a 'continue' functionality.
haveToUpdate = 1;
}
// case: path animation
if(haveToUpdate == 6){
if (path_iterator == 0) {
oldcamNavMode = cameraNavMouseMode; // remember state of old mousenav
cameraNavMouseMode = 0;
}
// check if the user wants to animate both
// scan matching and the path at the same
//time
// cout << "path_iterator: " << path_iterator << endl;
if(path_iterator < path_vectorX.size()){ // standard animation case
// call the path animation function
// hide both the cameras and the path
show_cameras = 0;
show_path = 0;
// increase the iteration count
path_iterator += 1;
// repaint the screen
glutPostRedisplay();
// save the animation
if(save_animation){
string filename = scan_dir + "animframe" + to_string(path_iterator,5) + ".ppm";
string jpgname = scan_dir + "animframe" + to_string(path_iterator,5) + ".jpg";
cout << "written " << filename << " of " << path_vectorX.size() << " files" << endl;
glWriteImagePPM(filename.c_str(), factor, 0);
string systemcall = "convert -quality 100 " + filename + " " + jpgname;
system(systemcall.c_str());
systemcall = "rm " + filename;
system(systemcall.c_str());
haveToUpdate = 6;
}
}else{ // animation has just ended
cameraNavMouseMode = oldcamNavMode;
show_cameras = 1;
show_path = 1;
haveToUpdate = 0;
}
}
}
/**
* This function handles the rotation of the view
*/
void update_view_rotate(int t)
{
double view_rotate_button_quat[4];
// convert the rotate button matrix to quaternion
//Matrix4ToQuaternion(view_rotate_button, view_rotate_button_quat);
double mat[16];
for (int i = 0; i < 16; i++)
mat[i] = view_rotate_button[i];
Matrix4ToQuat(mat, view_rotate_button_quat);
// normalize the quartenion
QuatNormalize(view_rotate_button_quat);
// copy it to the global quartenion quat
memcpy(quat, view_rotate_button_quat, sizeof(quat));
}
/**
* This function handles the translation of view.
*/
void update_view_translation(int t)
{
double obj_pos_button1[3];
for (int i = 0; i < 3; i++) {
if (fabs(obj_pos_button_old[i] - obj_pos_button[i]) > COMPARE_EPSILON) {
obj_pos_button1[i] = obj_pos_button[i] - obj_pos_button_old[i];
obj_pos_button_old[i] = obj_pos_button[i];
} else obj_pos_button1[i] = 0.0;
}
X = X + obj_pos_button1[0] * view_rotate_button[0] + obj_pos_button1[1] * view_rotate_button[1] + obj_pos_button1[2] * view_rotate_button[2];
Y = Y + obj_pos_button1[0] * view_rotate_button[4] + obj_pos_button1[1] * view_rotate_button[5] + obj_pos_button1[2] * view_rotate_button[6];
Z = Z + obj_pos_button1[0] * view_rotate_button[8] + obj_pos_button1[1] * view_rotate_button[9] + obj_pos_button1[2] * view_rotate_button[10];
}
/**
* handles the animation button
* @param dummy not needed necessary for glui
*/
void startAnimation(int dummy)
{
if (MetaMatrix.size() > 0) {
if (haveToUpdate != 3) {
haveToUpdate = 3;
}
else // stop animation
haveToUpdate = 4;
}
}
/**
* calls the resetView function
* @param dummy not needed necessary for glui
*/
void callResetView(int dummy)
{
if (showTopView) callTopView(dummy);
resetView(0);
}
/**
* calls the resetView function
* @param dummy not needed necessary for glui
*/
void invertView(int dummy)
{
invert = !invert;
}
/**
* calls the topView function
* @param dummy not needed necessary for glui
*/
void callTopView(int dummy)
{
topView();
if (showTopView) {
rotButton->disable();
cangle_spinner->disable();
pzoom_spinner->enable();
} else {
rotButton->enable();
cangle_spinner->enable();
pzoom_spinner->disable();
}
}
/**
* calls the cameraView function
* @param dummy not needed necessary for glui
*/
void callAddCamera(int dummy)
{
Point campos(-X, -Y, -Z);
// calculate lookat point
Point lookat;
Point up(0, 0, 0);
double tmat[16];
for (int i =0;i<16;i++) tmat[i] = view_rotate_button[i];
lookat.x = -50*tmat[2] -X;
lookat.y = -50*tmat[6] -Y;
lookat.z = -50*tmat[10] -Z;
up.x = 50*tmat[1] -X;
up.y = 50*tmat[5] -Y;
up.z = 50*tmat[9] -Z;
cams.push_back(campos);
lookats.push_back(lookat);
ups.push_back(up);
updateCamera();
// signal to repaint screen
haveToUpdate = 1;
}
void selectPoints(int x, int y) {
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];
if (selectOrunselect) {
// set the matrix mode
glMatrixMode(GL_MODELVIEW);
// init modelview matrix
glLoadIdentity();
// do the model-transformation
if (cameraNavMouseMode == 1) {
glRotated( mouseRotX, 1, 0, 0);
glRotated( mouseRotY, 0, 1, 0);
glRotated( mouseRotZ, 0, 0, 1);
} else {
double t[3] = {0,0,0};
double mat[16];
QuatToMatrix4(quat, t, mat);
glMultMatrixd(mat);
glGetFloatv(GL_MODELVIEW_MATRIX, view_rotate_button);
double rPT[3];
Matrix4ToEuler(mat, rPT);
mouseRotX = deg(rPT[0]);
mouseRotY = deg(rPT[1]);
mouseRotZ = deg(rPT[2]);
}
updateControls();
glTranslated(X, Y, Z); // move camera
static sfloat *sp2 = 0;
/* for(int iterator = (int)octpts.size()-1; iterator >= 0; iterator--) {
if (!selected_points[iterator].empty()) sp2 = *selected_points[iterator].begin();
// selected_points[iterator].clear();
}*/
for(int iterator = (int)octpts.size()-1; iterator >= 0; iterator--) {
glPushMatrix();
glMultMatrixd(MetaMatrix[iterator].back());
calcRay(x, y, 1.0, 40000.0);
if (select_voxels) {
octpts[iterator]->selectRay(selected_points[iterator], selection_depth);
} else if (brush_size == 0) {
sfloat *sp = 0;
octpts[iterator]->selectRay(sp);
if (sp != 0) {
cout << "Selected point: " << sp[0] << " " << sp[1] << " " << sp[2] << endl;
if (sp2 != 0) {
cout << "Distance to last point: "
<< sqrt( sqr(sp2[0] - sp[0]) + sqr(sp2[1] - sp[1]) + sqr(sp2[2] - sp[2]) ) << endl;
}
sp2 = sp;
selected_points[iterator].insert(sp);
}
} else { // select multiple points with a given brushsize
octpts[iterator]->selectRayBrushSize(selected_points[iterator], brush_size);
}
glPopMatrix();
}
} else {
// unselect points
glGetIntegerv(GL_VIEWPORT, viewport);
glSelectBuffer(BUFSIZE, selectBuf);
(void) glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// gluPickMatrix((GLdouble)x, (GLdouble)(viewport[3]-y), 10.0, 10.0, viewport);
gluPickMatrix((GLdouble)x, (GLdouble)(viewport[3]-y), brush_size*2, brush_size*2, viewport);
gluPerspective(cangle, aspect, neardistance, fardistance);
glMatrixMode(GL_MODELVIEW);
DisplayItFunc(GL_SELECT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
hits = glRenderMode(GL_RENDER); // get hits
ProcessHitsFunc(hits, selectBuf);
}
glPopMatrix();
glutPostRedisplay();
}
void CallBackMouseFuncMoving(int button, int state, int x, int y)
{
if( state == GLUT_DOWN) {
mousemoving = true;
} else {
mousemoving = false;
}
}
/**
* This function is called after a mousebutton has been pressed.
*/
void CallBackMouseFunc(int button, int state, int x, int y)
{
// Are we selecting points or moving the camera?
if(cameraNavMouseMode != 1) { // selecting points
if (state == GLUT_DOWN && (button == GLUT_LEFT_BUTTON || button == GLUT_RIGHT_BUTTON)) {
selectPoints(x,y);
}
} else {
if( state == GLUT_DOWN) {
mouseNavX = x;
mouseNavY = y;
mouseNavButton = button;
mousemoving = true;
} else {
mouseNavButton = -1;
mousemoving = false;
}
}
}
void moveCamera(double x, double y, double z, double rotx, double roty, double rotz) {
interruptDrawing();
double mat[9];
double xr = M_PI * mouseRotX / 180;
double yr = M_PI * mouseRotY / 180;
double zr = M_PI * mouseRotZ / 180;
double c1,c2,c3,s1,s2,s3;
s1 = sin(xr); c1 = cos(xr);
s2 = sin(yr); c2 = cos(yr);
s3 = sin(zr); c3 = cos(zr);
mat[0] = c2*c3;
mat[1] = -c2*s3;
mat[2] = s2;
mat[3] = c1*s3+c3*s1*s2;
mat[4] = c1*c3-s1*s2*s3;
mat[5] = -c2*s1;
mat[6] = s1*s3-c1*c3*s2;
mat[7] = c1*s2*s3+c3*s1;
mat[8] = c1*c2;
double transX, transY, transZ;
transX = transY = transZ = 0.0;
mouseRotX += rotx;
mouseRotY -= roty;
mouseRotZ -= rotz;
if (mouseRotX < -90) mouseRotX=-90;
else if (mouseRotX > 90) mouseRotX=90;
if (mouseRotY > 360) mouseRotY-=360;
else if (mouseRotY < 0) mouseRotY+=360;
if (mouseRotZ > 360) mouseRotZ-=360;
else if (mouseRotZ < 0) mouseRotZ+=360;
transX += x * mat[0] + y * mat[3] + z * mat[6];
transY += x * mat[1] + y * mat[4] + z * mat[7];
transZ += x * mat[2] + y * mat[5] + z * mat[8];
X += transX;
Y += transY;
Z += transZ;
haveToUpdate = 1;
}
void KeyboardFunc(int key, bool control, bool alt, bool shift) {
double stepsize = movementSpeed;
if (shift) stepsize *= 10.0;
if (control) stepsize *= 0.1;
double rotsize = 0.2 * stepsize;
switch (key) {
case 'w':
case 'W':
moveCamera(0,0,stepsize,0,0,0);
break;
case 'a':
case 'A':
moveCamera(stepsize,0,0,0,0,0);
break;
case 's':
case 'S':
moveCamera(0,0,-stepsize,0,0,0);
break;
case 'd':
case 'D':
moveCamera(-stepsize,0,0,0,0,0);
break;
case 'c':
case 'C':
moveCamera(0,stepsize,0,0,0,0);
break;
case 32: // WXK_SPACE
moveCamera(0,-stepsize,0,0,0,0);
break;
case 314: // WXK_LEFT
moveCamera(0,0,0,0,rotsize,0);
break;
case 315: // WXK_UP
moveCamera(0,0,0,rotsize,0,0);
break;
case 316: // WXK_RIGHT
moveCamera(0,0,0,0,-rotsize,0);
break;
case 317: // WXK_DOWN
moveCamera(0,0,0,-rotsize,0,0);
break;
case 'q':
case 'Q':
case 366: // WXK_PAGEUP
moveCamera(0,0,0,0,0,rotsize);
break;
case 'e':
case 'E':
case 367: // WXK_PAGEDOWN
moveCamera(0,0,0,0,0,-rotsize);
break;
case 'f':
if (!fullscreen) {
fullscreen = true;
glutFullScreen();
} else {
fullscreen = false;
glutReshapeWindow(current_width, current_height);
}
break;
default:
break;
}
}
void CallBackMouseMotionFunc(int x, int y) {
double deltaMouseX = x - mouseNavX;
double deltaMouseY = mouseNavY - y;
mouseNavX = x;
mouseNavY = y;
if(cameraNavMouseMode == 1) {
if( mouseNavButton == GLUT_RIGHT_BUTTON){
if ( showTopView ) {
deltaMouseX *= 5;
deltaMouseY *= 5;
}
deltaMouseX *= movementSpeed/10.0; // moving 10 pixels is equivalent to one key stroke
deltaMouseY *= movementSpeed/10.0;
moveCamera(deltaMouseX, deltaMouseY, 0, 0,0,0);
} else if( mouseNavButton == GLUT_MIDDLE_BUTTON ){
if ( !showTopView ) {
deltaMouseY *= -5;
}
deltaMouseX *= movementSpeed/10.0; // moving 10 pixels is equivalent to one key stroke
deltaMouseY *= movementSpeed/10.0;
moveCamera(deltaMouseX, 0, deltaMouseY, 0,0,0);
} else if ( mouseNavButton == GLUT_LEFT_BUTTON ){
moveCamera(0, 0, 0, deltaMouseY,deltaMouseX,0);
} else {
return;
}
} else {
selectPoints(x,y);
}
}
void initScreenWindow()
{
// init display
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA | GLUT_DOUBLE);
// define the window position and size
glutInitWindowPosition(START_X, START_Y);
glutInitWindowSize( START_WIDTH, START_HEIGHT );
// create window and append callback functions
window_id = glutCreateWindow("3D_Viewer");
glutDisplayFunc( CallBackDisplayFunc );
glutReshapeFunc( CallBackReshapeFunc );
glutMouseFunc ( CallBackMouseFunc );
glutKeyboardFunc ( CallBackKeyboardFunc);
glutKeyboardUpFunc ( CallBackKeyboardUpFunc);
glutMotionFunc ( CallBackMouseMotionFunc);
glutSpecialFunc ( CallBackSpecialFunc);
// glutEntryFunc ( CallBackEntryFunc);
GLUI_Master.set_glutReshapeFunc( CallBackReshapeFunc );
GLUI_Master.set_glutIdleFunc( CallBackIdleFunc );
update_view_rotate(0);
glClearColor(0.0, 0.0, 0.0, 0.0);
// glClearColor(1.0, 1.0, 1.0, 1.0);
}
/* +++++++++-------------++++++++++++
* NAME
* glDumpWindowPPM
* DESCRIPTION
* writes an ppm file of the window
* content
* PARAMETERS
* filename
* RESULT
* writes the framebuffer content
* to a ppm file
+++++++++-------------++++++++++++ */
void glDumpWindowPPM(const char *filename, GLenum mode)
{
int win_height, win_width;
int i,j,k,l; // Counter variables
GLubyte *buffer; // The GL Frame Buffer
unsigned char *ibuffer; // The PPM Output Buffer
ofstream fp; // The PPM File
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
win_height = viewport[3];
win_width = viewport[2];
// Allocate memory for the the frame buffer and output buffer
buffer = new GLubyte[win_width * win_height * RGBA];
ibuffer = new unsigned char[win_width * win_height * RGB];
// Read window contents from GL frame buffer with glReadPixels
glFinish();
glReadBuffer(buffermode);
glReadPixels(0, 0, win_width, win_height,
GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Open the output file
fp.open(filename, ios::out);
// Write a proper P6 PPM header
fp << "P6" << endl << "# CREATOR: 3D_Viewer by Andreas Nuechter, University of Osnabrueck"
<< endl << win_width << " " << win_height << " " << UCHAR_MAX << endl;
// Loop through the frame buffer data, writing to the PPM file. Be careful
// to account for the frame buffer having 4 bytes per pixel while the
// output file has 3 bytes per pixel
l = 0;
for (i = 0; i < win_height; i++) { // For each row
for (j = 0; j < win_width; j++) { // For each column
for (k = 0; k < RGB; k++) { // For each RGB component
//cout << (RGBA*((win_height-1-i)*win_width+j)+k) << endl;
ibuffer[l++] = (unsigned char)
*(buffer + (RGBA*((win_height-1-i)*win_width+j)+k));
} // end RGB
} // end column
} // end row
// to make a video do:
// for f in *ppm ; do convert -quality 100 $f `basename $f ppm`jpg; done
// mencoder "mf://*.jpg" -mf fps=10 -o test.avi -ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=800
// Write output buffer to the file */
fp.write((const char*)ibuffer, sizeof(unsigned char) * (RGB * win_width * win_height));
fp.close();
fp.clear();
delete [] buffer;
delete [] ibuffer;
}
/* +++++++++-------------++++++++++++
* NAME
* glDumpWindowPPM
* DESCRIPTION
* writes an ppm file of the window
* content
* size is scale times the window size
* PARAMETERS
* filename
* RESULT
* writes the framebuffer content
* to a ppm file
+++++++++-------------++++++++++++ */
void glWriteImagePPM(const char *filename, int scale, GLenum mode)
{
//if(!showTopView) {
int m,o,k; // Counter variables
// Get viewport parameters
double left, right, top, bottom;
double tmp = 1.0/tan(rad(cangle)/2.0);
// Save camera parameters
GLdouble savedMatrix[16];
glGetDoublev(GL_PROJECTION_MATRIX,savedMatrix);
GLdouble savedModel[16];
glGetDoublev(GL_MODELVIEW_MATRIX,savedModel);
//glMatrixMode(GL_PROJECTION);
//glPushMatrix();
//glMatrixMode(GL_MODELVIEW);
//glPushMatrix();
top = 1.0/tmp;
bottom = -top;
right = (aspect)/tmp;
left = -right;
double part_height, part_width;
if(!showTopView) {
part_width = (right - left)/(double)scale;
part_height = (top - bottom)/(double)scale;
} else {
part_height = (2*pzoom)/scale;
part_width = (2*pzoom*aspect)/scale;
cout << part_width << " " << part_height << endl;
}
// Calculate part parameters
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
int win_width = viewport[2];
int win_height = viewport[3];
int image_width = scale * win_width;
int image_height = scale * win_height;
// Allocate memory for the the frame buffer and output buffer
GLubyte *buffer; // The GL Frame Buffer
unsigned char *ibuffer; // The PPM Output Buffer
buffer = new GLubyte[win_width * win_height * RGBA];
ibuffer = new unsigned char[image_width * image_height * RGB];
smallfont = (scale==1);
double height;
if(!showTopView) {
height = bottom;
} else {
height = -pzoom;
}
for(int i = 0; i < scale; i++) {
double width;
if(!showTopView) {
width = left;
} else {
width = -pzoom*aspect;
}
for(int j = 0; j < scale; j++) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
label = false;
if(!showTopView) {
glFrustum(neardistance*width, neardistance*(width + part_width),
neardistance*(height),
neardistance*(height + part_height),
neardistance, fardistance);
glMatrixMode(GL_MODELVIEW);
if(i==0 && j==0) {
label = true;
}
DisplayItFunc(mode);
} else {
glOrtho( width, width + part_width,
height, height + part_height,
1.0, 32000.0 );
glMatrixMode(GL_MODELVIEW);
if(i==0 && j==0) {
label = true;
}
DisplayItFunc(mode);
}
// Read window contents from GL frame buffer with glReadPixels
glFinish();
glReadBuffer(buffermode);
glReadPixels(0, 0, win_width, win_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Loop through the frame buffer data, writing to the PPM file. Be careful
// to account for the frame buffer having 4 bytes per pixel while the
// output file has 3 bytes per pixel
// end row
for (m = 0; m < win_height; m++) { // For each row
for (o = 0; o < win_width; o++) { // For each column
for (k = 0; k < RGB; k++) { // For each RGB component
int l = (k+RGB*(image_width*((scale - 1 - i)*win_height + m) + j*win_width + o));
ibuffer[l] = (unsigned char) *(buffer + (RGBA*((win_height-1-m)*win_width+o)+k));
} // end RGB
} // end column
}
width += part_width;
}
height += part_height;
}
// show the starting scene
// Restore the original projection matrix
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(savedMatrix);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(savedModel);
// show the rednered scene
label = true;
smallfont = true;
haveToUpdate=2;
DisplayItFunc(mode);
ofstream fp; // The PPM File
// Open the output file
fp.open(filename, ios::out);
// Write a proper P6 PPM header
fp << "P6" << endl << "# CREATOR: 3D_Viewer by Dorit Borrmann, Jacobs University Bremen gGmbH"
<< endl << image_width << " " << image_height << " " << UCHAR_MAX << endl;
// Write output buffer to the file
fp.write((const char*)ibuffer, sizeof(unsigned char) * (RGB * image_width * image_height));
fp.close();
fp.clear();
delete [] buffer;
delete [] ibuffer;
}
/** Reshape Function
* TODO: have to describe it.
*
*/
void CallBackReshapeFunc(int width, int height)
{
if (!fullscreen) {
current_height = height;
current_width = width;
}
aspect = (double)width/(double)height;
if (!showTopView) {
// usage of the vsize of a structiewport
glViewport(0, 0, (GLint)width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// angle, aspect, near clip, far clip
// get matrix
gluPerspective(cangle, aspect, neardistance, fardistance);
// now use modelview-matrix as current matrix
glMatrixMode(GL_MODELVIEW);
haveToUpdate = 1;
} else {
// usage of the viewport
glViewport ( 0, 0, width, height);
glMatrixMode ( GL_PROJECTION );
glLoadIdentity ();
// get matrix
glOrtho ( -aspect * pzoom, aspect * pzoom,
-1 * pzoom, pzoom,
1.0, 32000.0 );
// now use modelview-matrix as current matrix
glMatrixMode(GL_MODELVIEW);
haveToUpdate = 1;
}
// glDepthMask(false);
glEnable(GL_BLEND); // TODO
glBlendFunc(GL_ONE, GL_ZERO); // TODO
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // TODO
// glBlendFunc(GL_ONE, GL_ONE); // TODO
// glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
// TODO glDepthFunc(GL_LEQUAL);
glDepthFunc(GL_LESS); //TODO
glEnable(GL_DEPTH_TEST);
glEnable (GL_POINT_SMOOTH);
}
/**
* Prints out which points were clicked on
*/
void ProcessHitsFunc(GLint hits, GLuint buffer[])
{
//cout << "SIZE " << selected_points[0].size() << endl;
//cout << "processing " << endl;
set<int> names;
set<sfloat *> unsel_points;
GLuint *ptr, nr_names;
ptr = (GLuint *)buffer;
for(int i = 0 ; i < hits ; i++) {
nr_names = *ptr;
ptr+=3; // skip 2 z values
for(unsigned int j = 0;j < nr_names ; j++){ // iterate over all names
names.insert(*ptr);
ptr++;
}
}
//cout << "number of names " << names.size() << endl;
if (names.empty()) return;
int index = 0;
set<int>::iterator nit = names.begin();
// find the respective name
for(int iterator = (int)octpts.size()-1; iterator >= 0; iterator--) {
// iterate over the selected points as in DrawPoints
for ( set<sfloat*>::iterator it = selected_points[iterator].begin();
it != selected_points[iterator].end(); it++) {
if (index == *nit) { // if the current index is the current name
unsel_points.insert(*it);
nit++;
}
if (nit == names.end()) goto Done; // break out of the loop
index++;
}
}
Done:
cout << "Erasing " << endl;
for (set<sfloat*>::iterator it = unsel_points.begin();
it != unsel_points.end(); it++) { // iterate to the index as indicated by the name *ptr
for(int iterator = (int)octpts.size()-1; iterator >= 0; iterator--) { // erase for all scans
selected_points[iterator].erase(*it);
}
}
cout << "processing done" << endl;
}
//------------------------------------------------------------------
/**
* This function deals with all our keyboard activities
*/
void InterfaceFunc(unsigned char key){
strncpy(path_file_name, path_filename_edit->get_text(), 1024);
strncpy(pose_file_name, pose_filename_edit->get_text(), 1024);
return;
}
void CallBackSpecialFunc(int key , int x, int y) {
//KeyboardFunc(key + 214, false, false, false);
// return;
}
/**
* Function drawRobotPath
* \brief This functions draws the path where the
* robot has travelled along while taking the scans
*/
void drawRobotPath(int dummy){
// clear the camera list as we are going to add the cameras
// in the path where the robot travelled.
// lets loop through the entire frame files to extract the
// total number of places where the robot has taken the scans from
for(unsigned int i = 0; i < MetaMatrix.size(); i++){
//temp variable
double *temp;
// Now, lets go to the last of each frame file to
// extract the transformation matrix obtained
// after scan matching has been done.
glMultMatrixd(MetaMatrix[i].back());
// temp is final transformation matrix
temp = MetaMatrix[i].back();
Point campos(temp[12], temp[13] + 100, temp[14]);
// calculate lookat point
Point lookat(0, 0, 50);
Point up(0, 50, 0);
double tmat[16];
for (int i =0;i<16;i++) tmat[i] = temp[i];
lookat.transform(tmat);
lookat.x = lookat.x ;
lookat.y = lookat.y + 100;
lookat.z = lookat.z ;
up.transform(tmat);
up.x = up.x ;
up.y = up.y + 100;
up.z = up.z ;
cams.push_back(campos);
lookats.push_back(lookat);
ups.push_back(up);
}
updateCamera();
// signal for the update of scene
haveToUpdate = 1;
}
/**
* Calculates the positions of the interpolated camera path positions on the
* Nurbs path. There will be an equal number of intermediate positions between
* neighboring cameras.
*/
void calcInterpolatedCameras(vector<PointXY> vec1, vector<PointXY> vec2) {
NurbsPath::camRatio.clear();
double distance = 0.0;
double dx, dy, dz;
for(unsigned int i=0;i<vec1.size()-1;i++){
dx = vec1.at(i+1).x - vec1.at(i).x;
dy = vec1.at(i+1).y - vec1.at(i).y;
dz = vec2.at(i+1).y - vec2.at(i).y;
distance += sqrt(dx*dx + dy*dy + dz*dz );
}
double distance2 = 0.0;
int im_per_cam = (distance/2.0)/(vec1.size() - 1);
int count = 0;
for(unsigned int i = 0; i < vec1.size()-1; i++) {
dx = vec1.at(i+1).x - vec1.at(i).x;
dy = vec1.at(i+1).y - vec1.at(i).y;
dz = vec2.at(i+1).y - vec2.at(i).y;
double curr_dist = sqrt(dx*dx + dy*dy + dz*dz);
for(int j = 0; j < im_per_cam; j++) {
count++;
NurbsPath::camRatio.push_back((distance2 + ((double)j * (curr_dist/(double)im_per_cam)))/(distance + 0.1));
}
distance2 += sqrt(dx*dx + dy*dy + dz*dz);
}
}
/**
* Calculates the number of interpolation points for the camera path based on
* the length of the path
*/
int calcNoOfPoints(vector<PointXY> vec1, vector<PointXY> vec2)
{
double distance = 0.0;
double dx, dy, dz;
for(unsigned int i=0;i<vec1.size()-1;i++){
dx = vec1.at(i+1).x - vec1.at(i).x;
dy = vec1.at(i+1).y - vec1.at(i).y;
dz = vec2.at(i+1).y - vec2.at(i).y;
distance += sqrt(dx*dx + dy*dy + dz*dz );
}
return distance/2;
}
/**
* This function handles the the keyboard input
*/
void CallBackInterfaceFunc(unsigned char key, int x, int y) {
//call the interfacefunc. it deals with all our
//keyboard activities
InterfaceFunc(key);
}
void CallBackKeyboardUpFunc(unsigned char key, int x, int y) {
keymap[key] = false;
if (key >= 'A' && key <= 'Z') {
keymap[key+ ('a'-'A')] = false;
}
if (key >= 'a' && key <= 'z') {
keymap[key+ ('A'-'a')] = false;
}
for (unsigned int i = 0; i < 256; i++) {
if (keymap[i]) {
keypressed = true;
return;
}
}
keypressed = false;
}
void CallBackKeyboardFunc(unsigned char key, int x, int y) {
keymap[key] = true;
keypressed = true;
bool cmd,alt,shift;
cmd = glutGetModifiers() & GLUT_ACTIVE_CTRL;
alt = glutGetModifiers() & GLUT_ACTIVE_ALT;
shift = glutGetModifiers() & GLUT_ACTIVE_SHIFT;
if (cmd) {
key += 96;
}
KeyboardFunc(key, cmd, alt, shift);
}
void mapColorToValue(int dummy) {
switch (listboxColorVal) {
case 0:
cm->setCurrentType(PointType::USE_HEIGHT);
break;
case 1:
cm->setCurrentType(PointType::USE_REFLECTANCE);
break;
case 2:
cm->setCurrentType(PointType::USE_TEMPERATURE);
break;
case 3:
cm->setCurrentType(PointType::USE_AMPLITUDE);
break;
case 4:
cm->setCurrentType(PointType::USE_DEVIATION);
break;
case 5:
cm->setCurrentType(PointType::USE_TYPE);
break;
case 6:
cm->setCurrentType(PointType::USE_COLOR);
break;
default:
break;
};
resetMinMax(0);
}
void changeColorMap(int dummy) {
ColorMap c;
GreyMap gm;
HSVMap hsv;
SHSVMap shsv;
JetMap jm;
HotMap hot;
DiffMap diff;
TempMap temp;
switch (listboxColorMapVal) {
case 0:
// TODO implement no color map
cm->setColorMap(c);
break;
case 1:
cm->setColorMap(gm);
break;
case 2:
cm->setColorMap(hsv);
break;
case 3:
cm->setColorMap(jm);
break;
case 4:
cm->setColorMap(hot);
break;
case 5:
cm->setColorMap(diff);
break;
case 6:
cm->setColorMap(shsv);
break;
case 7:
cm->setColorMap(temp);
break;
default:
break;
}
}
void minmaxChanged(int dummy) {
cm->setMinMax(mincolor_value, maxcolor_value);
}
void resetMinMax(int dummy) {
mincolor_value = cm->getMin();
maxcolor_value = cm->getMax();
minmaxChanged(0);
}
void setScansColored(int dummy) {
switch(colorScanVal) {
case 0:
cm->setMode(ScanColorManager::MODE_STATIC);
break;
case 1:
cm->setMode(ScanColorManager::MODE_COLOR_SCAN);
break;
case 2:
cm->setMode(ScanColorManager::MODE_POINT_COLOR);
break;
default:
break;
}
}
void changePointMode(int dummy) {
if (dummy == 0) { // always display
if (pointmode != 1) { // standard mode
pointmode = 1;
//never_box->set_int_val(0);
} else {
pointmode = 0;
}
} else if (dummy == 1) { // never display
if (pointmode != -1) { // standard mode
pointmode = -1;
//always_box->set_int_val(0);
} else {
pointmode = 0;
}
}
updatePointModeControls();
}
void callCameraUpdate(int dummy) {
updateCamera();
}
void calcPointSequence(vector<int> &sequence, int frameNr) {
sequence.clear();
vector<pair<double, int> > dists;
double x,y,z;
for (unsigned int i = 0; i < octpts.size(); i++) {
// stop at scans that don't have any frames associated with them
if(i >= MetaMatrix.size()) break;
// set usable frame
double* frame;
if((unsigned int)frameNr >= MetaMatrix[i].size()) {
// use last possible frame
frame = MetaMatrix[i].back();
} else {
frame = MetaMatrix[i][frameNr];
}
x = frame[12];
y = frame[13];
z = frame[14];
dists.push_back( pair<double, int>(sqr(X + x) + sqr(Y + y) + sqr(Z + z), i) );
}
sort( dists.begin(), dists.end());
for (unsigned int i = 0; i < dists.size(); i++) {
sequence.push_back( dists[i].second);
}
}