📄 lasview.cpp
字号:
/*
===============================================================================
FILE: lasview.cpp
CONTENTS:
This little tool is just a quick little hack to visualize an LAS files.
PROGRAMMERS:
martin isenburg@cs.unc.edu
COPYRIGHT:
copyright (C) 2005 martin isenburg@cs.unc.edu
This software 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.
CHANGE HISTORY:
9 May 2007 -- adapted from my streaming point viewer
===============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glut.h>
#include "lasreader.h"
#ifdef _WIN32
extern "C" FILE* fopenGzipped(const char* filename, const char* mode);
#endif
// MOUSE INTERFACE
static int LeftButtonDown=0;
static int MiddleButtonDown=0;
static int RightButtonDown=0;
static int OldX,OldY;
static float Elevation=0;
static float Azimuth=0;
static float DistX=0;
static float DistY=0;
static float DistZ=2;
// VISUALIZATION SETTINGS
static float boundingBoxMin[3];
static float boundingBoxMax[3];
static float boundingBoxHeight;
static float boundingBoxScale=1.0f;
static float boundingBoxTranslateX = 0.0f;
static float boundingBoxTranslateY = 0.0f;
static float boundingBoxTranslateZ = 0.0f;
// GLOBAL CONTROL VARIABLES
static int WindowW=1024, WindowH=768;
static int InteractionMode=0;
static int AnimationOn=0;
static int WorkingOn=0;
// COLORS
static float colours_diffuse[10][4];
static float colours_white[4];
static float colours_light_blue[4];
// DATA STORAGE FOR STREAM VISUALIZER OUTPUT
static FILE* file = 0;
static char* file_name = 0;
static LASreader* lasreader = 0;
static int p_count = 0;
static int npoints = 0;
static float* point_buffer = 0;
static int point_buffer_alloc = 0;
static bool only_first = false;
static bool only_last = false;
static int EXACTLY_N_STEPS = 100;
static int EVERY_NTH_STEP = -1;
static int NEXT_STEP;
static int EXACTLY_N_POINTS = 1000000;
static int EVERY_NTH_POINT = 0;
static int NEXT_POINT;
static int DIRTY_POINTS=1;
static int REPLAY_IT=0;
static int REPLAY_COUNT=0;
static int STREAM_COLORING = 3;
static int POINT_SIZE = 2;
static int RENDER_BOUNDINGBOX = 1;
static int EXTRA_Z_SCALE = 1;
static void InitColors()
{
colours_diffuse[0][0] = 0.0f; colours_diffuse[0][1] = 0.0f; colours_diffuse[0][2] = 0.0f; colours_diffuse[0][3] = 1.0f; // black
colours_diffuse[1][0] = 0.6f; colours_diffuse[1][1] = 0.0f; colours_diffuse[1][2] = 0.0f; colours_diffuse[1][3] = 1.0f; // red
colours_diffuse[2][0] = 0.0f; colours_diffuse[2][1] = 0.8f; colours_diffuse[2][2] = 0.0f; colours_diffuse[2][3] = 1.0f; // green
colours_diffuse[3][0] = 0.0f; colours_diffuse[3][1] = 0.0f; colours_diffuse[3][2] = 0.6f; colours_diffuse[3][3] = 1.0f; // blue
colours_diffuse[4][0] = 0.6f; colours_diffuse[4][1] = 0.6f; colours_diffuse[4][2] = 0.0f; colours_diffuse[4][3] = 1.0f; // yellow
colours_diffuse[5][0] = 0.6f; colours_diffuse[5][1] = 0.0f; colours_diffuse[5][2] = 0.6f; colours_diffuse[5][3] = 1.0f; // purple
colours_diffuse[6][0] = 0.0f; colours_diffuse[6][1] = 0.6f; colours_diffuse[6][2] = 0.6f; colours_diffuse[6][3] = 0.3f; // cyan (tranparent)
colours_diffuse[7][0] = 0.7f; colours_diffuse[7][1] = 0.7f; colours_diffuse[7][2] = 0.7f; colours_diffuse[7][3] = 1.0f; // white
colours_diffuse[8][0] = 0.2f; colours_diffuse[8][1] = 0.2f; colours_diffuse[8][2] = 0.6f; colours_diffuse[8][3] = 1.0f; // light blue
colours_diffuse[9][0] = 0.9f; colours_diffuse[9][1] = 0.4f; colours_diffuse[9][2] = 0.7f; colours_diffuse[9][3] = 0.5f; // violett
colours_white[0] = 0.7f; colours_white[1] = 0.7f; colours_white[2] = 0.7f; colours_white[3] = 1.0f; // white
colours_light_blue[0] = 0.2f; colours_light_blue[1] = 0.2f; colours_light_blue[2] = 0.6f; colours_light_blue[3] = 1.0f; // light blue
}
static void InitLight()
{
float intensity[] = {1,1,1,1};
float position[] = {1,1,5,0}; // directional behind the viewer
glLightfv(GL_LIGHT0,GL_DIFFUSE,intensity);
glLightfv(GL_LIGHT0,GL_SPECULAR,intensity);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_FALSE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
}
static void usage()
{
fprintf(stderr,"usage:\n");
fprintf(stderr,"lasview -i terrain.las\n");
fprintf(stderr,"lasview -i terrain.las -win 1600 1200 -steps 10 -points 200000\n");
fprintf(stderr,"lasview -h\n");
fprintf(stderr,"\n");
}
static void vizBegin()
{
REPLAY_IT = 0; // just making sure
DIRTY_POINTS = 1;
if (file_name)
{
fprintf(stderr,"loading '%s'...\n",file_name);
if (strstr(file_name, ".gz"))
{
#ifdef _WIN32
file = fopenGzipped(file_name, "rb");
#else
fprintf(stderr,"ERROR: cannot open gzipped file %s\n",file_name);
exit(1);
#endif
}
else
{
file = fopen(file_name, "rb");
}
if (file == 0)
{
fprintf(stderr,"ERROR: cannot open %s\n",file_name);
exit(1);
}
lasreader = new LASreader();
if (lasreader->open(file) == false)
{
fprintf(stderr,"ERROR: no input\n");
exit(1);
}
}
else
{
fprintf(stderr,"ERROR: no input\n");
exit(1);
}
// scale and translate bounding box for rendering
boundingBoxMin[0] = lasreader->header.min_x;
boundingBoxMin[1] = lasreader->header.min_y;
boundingBoxMin[2] = lasreader->header.min_z;
boundingBoxMax[0] = lasreader->header.max_x;
boundingBoxMax[1] = lasreader->header.max_y;
boundingBoxMax[2] = lasreader->header.max_z;
boundingBoxHeight = boundingBoxMax[2]-boundingBoxMin[2];
if ((boundingBoxMax[1]-boundingBoxMin[1]) > (boundingBoxMax[0]-boundingBoxMin[0]))
{
if ((boundingBoxMax[1]-boundingBoxMin[1]) > (boundingBoxMax[2]-boundingBoxMin[2]))
{
boundingBoxScale = 1.0f/(boundingBoxMax[1]-boundingBoxMin[1]);
}
else
{
boundingBoxScale = 1.0f/(boundingBoxMax[2]-boundingBoxMin[2]);
}
}
else
{
if ((boundingBoxMax[0]-boundingBoxMin[0]) > (boundingBoxMax[2]-boundingBoxMin[2]))
{
boundingBoxScale = 1.0f/(boundingBoxMax[0]-boundingBoxMin[0]);
}
else
{
boundingBoxScale = 1.0f/(boundingBoxMax[2]-boundingBoxMin[2]);
}
}
boundingBoxTranslateX = - boundingBoxScale * (boundingBoxMin[0] + 0.5f * (boundingBoxMax[0]-boundingBoxMin[0]));
boundingBoxTranslateY = - boundingBoxScale * (boundingBoxMin[1] + 0.5f * (boundingBoxMax[1]-boundingBoxMin[1]));
boundingBoxTranslateZ = - boundingBoxScale * (boundingBoxMin[2] + 0.5f * (boundingBoxMax[2]-boundingBoxMin[2]));
p_count = 0;
npoints = lasreader->npoints;
fprintf(stderr,"number of points in file %d\n", npoints);
if (EVERY_NTH_STEP == -1)
{
EVERY_NTH_STEP = npoints / EXACTLY_N_STEPS;
}
if (EVERY_NTH_STEP == 0)
{
EVERY_NTH_STEP = 1;
}
NEXT_STEP = EVERY_NTH_STEP;
if (EXACTLY_N_POINTS)
{
EVERY_NTH_POINT = npoints/EXACTLY_N_POINTS;
}
if (EVERY_NTH_POINT == 0)
{
EVERY_NTH_POINT = 1;
}
NEXT_POINT = 0;
// make sure we have enough memory
if (point_buffer_alloc < ((npoints / EVERY_NTH_POINT) + 500))
{
if (point_buffer) free(point_buffer);
point_buffer_alloc = ((npoints / EVERY_NTH_POINT) + 500);
point_buffer = (float*)malloc(sizeof(float)*3*point_buffer_alloc);
}
}
static void vizEnd()
{
REPLAY_IT = 0; // just making sure
REPLAY_COUNT = p_count;
DIRTY_POINTS = 0;
fprintf(stderr,"number of points sampled %d\n",p_count);
lasreader->close();
fclose(file);
delete lasreader;
lasreader = 0;
}
static int vizContinue()
{
int more;
REPLAY_IT = 0; // just making sure
while (more = lasreader->read_point(&(point_buffer[p_count*3])))
{
if (lasreader->p_count > NEXT_POINT)
{
p_count++;
NEXT_POINT += ((EVERY_NTH_POINT/2) + (rand()%EVERY_NTH_POINT) + 1);
}
if (lasreader->p_count > NEXT_STEP)
{
NEXT_STEP += EVERY_NTH_STEP;
break;
}
}
return more;
}
static void myReshape(int w, int h)
{
glutReshapeWindow(WindowW,WindowH);
}
static void myIdle()
{
if (AnimationOn)
{
AnimationOn = vizContinue();
if (!AnimationOn)
{
WorkingOn = 0;
vizEnd();
}
glutPostRedisplay();
}
else if (REPLAY_IT)
{
REPLAY_COUNT += NEXT_STEP;
glutPostRedisplay();
}
}
static void full_resolution_rendering()
{
if (file_name == 0)
{
fprintf(stderr,"ERROR: no input file\n");
}
int p_count;
if (lasreader)
{
p_count = lasreader->p_count;
fprintf(stderr,"out-of-core rendering of %d points ... \n",p_count);
lasreader->close();
fclose(file);
delete lasreader;
lasreader = 0;
}
else
{
p_count = 2000000000;
fprintf(stderr,"out-of-core rendering of all points ... \n");
}
if (strstr(file_name, ".gz"))
{
#ifdef _WIN32
file = fopenGzipped(file_name, "rb");
#else
fprintf(stderr,"ERROR: cannot open gzipped file %s\n",file_name);
exit(1);
#endif
}
else
{
file = fopen(file_name, "rb");
}
if (file == 0)
{
fprintf(stderr,"ERROR: cannot open %s\n",file_name);
exit(1);
}
lasreader = new LASreader();
if (lasreader->open(file) == false)
{
fprintf(stderr,"ERROR: no input\n");
exit(1);
}
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,WindowW,WindowH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0f,(float)WindowW/WindowH,0.0625f,5.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(DistX,DistY,DistZ, DistX,DistY,0, 0,1,0);
glRotatef(Elevation,1,0,0);
glRotatef(Azimuth,0,1,0);
glTranslatef(boundingBoxTranslateX,boundingBoxTranslateY,boundingBoxTranslateZ*EXTRA_Z_SCALE);
glScalef(boundingBoxScale,boundingBoxScale,boundingBoxScale*EXTRA_Z_SCALE);
glEnable(GL_DEPTH_TEST);
if (p_count == 0)
{
p_count = lasreader->npoints;
}
double point[3];
glBegin(GL_POINTS);
glColor3f(0,0,0);
while (lasreader->p_count < p_count)
{
if (lasreader->read_point(point))
{
glVertex3dv(point);
}
else
{
glEnd();
lasreader->close();
fclose(file);
delete lasreader;
lasreader = 0;
glutSwapBuffers();
return;
}
}
glEnd();
glDisable(GL_DEPTH_TEST);
glutSwapBuffers();
}
static void myMouseFunc(int button, int state, int x, int y)
{
OldX=x;
OldY=y;
if (button == GLUT_LEFT_BUTTON)
{
LeftButtonDown = !state;
MiddleButtonDown = 0;
RightButtonDown = 0;
}
else if (button == GLUT_RIGHT_BUTTON)
{
LeftButtonDown = 0;
MiddleButtonDown = 0;
RightButtonDown = !state;
}
else if (button == GLUT_MIDDLE_BUTTON)
{
LeftButtonDown = 0;
MiddleButtonDown = !state;
RightButtonDown = 0;
}
}
static void myMotionFunc(int x, int y)
{
float RelX = (x-OldX) / (float)glutGet((GLenum)GLUT_WINDOW_WIDTH);
float RelY = (y-OldY) / (float)glutGet((GLenum)GLUT_WINDOW_HEIGHT);
OldX=x;
OldY=y;
if (LeftButtonDown)
{
if (InteractionMode == 0)
{
Azimuth += (RelX*180);
Elevation += (RelY*180);
}
else if (InteractionMode == 1)
{
DistX-=RelX;
DistY+=RelY;
}
else if (InteractionMode == 2)
{
DistZ-=RelY*DistZ;
}
}
else if (MiddleButtonDown)
{
DistX-=RelX*1.0f;
DistY+=RelY*1.0f;
}
glutPostRedisplay();
}
static void MyMenuFunc(int value);
static void myKeyboard(unsigned char Key, int x, int y)
{
switch(Key)
{
case 'Q':
case 'q':
case 27:
exit(0);
break;
case ' ': // rotate, translate, or zoom
if (InteractionMode == 2)
{
InteractionMode = 0;
}
else
{
InteractionMode += 1;
}
glutPostRedisplay();
break;
case '>': //zoom in
DistZ-=0.1f;
break;
case '<': //zoom out
DistZ+=0.1f;
break;
case '_':
break;
case '+':
break;
case '-':
POINT_SIZE -= 1;
if (POINT_SIZE < 0) POINT_SIZE = 0;
fprintf(stderr,"POINT_SIZE %d\n",POINT_SIZE);
glutPostRedisplay();
break;
case '=':
POINT_SIZE += 1;
fprintf(stderr,"POINT_SIZE %d\n",POINT_SIZE);
glutPostRedisplay();
break;
case '[':
if (EXTRA_Z_SCALE > 1)
{
EXTRA_Z_SCALE = EXTRA_Z_SCALE >> 1;
glutPostRedisplay();
}
fprintf(stderr,"EXTRA_Z_SCALE %d\n",EXTRA_Z_SCALE);
break;
case ']':
EXTRA_Z_SCALE = EXTRA_Z_SCALE << 1;
fprintf(stderr,"EXTRA_Z_SCALE %d\n",EXTRA_Z_SCALE);
glutPostRedisplay();
break;
case 'O':
case 'o':
AnimationOn = 0;
REPLAY_IT = 0;
break;
case 'B':
case 'b':
RENDER_BOUNDINGBOX = !RENDER_BOUNDINGBOX;
fprintf(stderr,"RENDER_BOUNDINGBOX %d\n",RENDER_BOUNDINGBOX);
break;
case 'R':
case 'r':
if (file_name)
{
full_resolution_rendering();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -