00001
00002
00003
00004 #define GLFW_INCLUDE_GLU
00005 #include <GLFW/glfw3.h>
00006
00007 #include <sstream>
00008 #include <vector>
00009
00010 inline void make_depth_histogram(uint8_t rgb_image[640*480*3], const uint16_t depth_image[], int width, int height)
00011 {
00012 static uint32_t histogram[0x10000];
00013 memset(histogram, 0, sizeof(histogram));
00014
00015 for(int i = 0; i < width*height; ++i) ++histogram[depth_image[i]];
00016 for(int i = 2; i < 0x10000; ++i) histogram[i] += histogram[i-1];
00017 for(int i = 0; i < width*height; ++i)
00018 {
00019 if(uint16_t d = depth_image[i])
00020 {
00021 int f = histogram[d] * 255 / histogram[0xFFFF];
00022 rgb_image[i*3 + 0] = 255 - f;
00023 rgb_image[i*3 + 1] = 0;
00024 rgb_image[i*3 + 2] = f;
00025 }
00026 else
00027 {
00028 rgb_image[i*3 + 0] = 20;
00029 rgb_image[i*3 + 1] = 5;
00030 rgb_image[i*3 + 2] = 0;
00031 }
00032 }
00033 }
00034
00036
00038
00039 #include "third_party/stb_easy_font.h"
00040
00041 inline int get_text_width(const char * text)
00042 {
00043 return stb_easy_font_width((char *)text);
00044 }
00045
00046 inline void draw_text(int x, int y, const char * text)
00047 {
00048 char buffer[60000];
00049 glEnableClientState(GL_VERTEX_ARRAY);
00050 glVertexPointer(2, GL_FLOAT, 16, buffer);
00051 glDrawArrays(GL_QUADS, 0, 4*stb_easy_font_print((float)x, (float)(y-7), (char *)text, nullptr, buffer, sizeof(buffer)));
00052 glDisableClientState(GL_VERTEX_ARRAY);
00053 }
00054
00056
00058
00059 class texture_buffer
00060 {
00061 GLuint texture;
00062 double last_timestamp;
00063 std::vector<uint8_t> rgb;
00064
00065 int fps, num_frames;
00066 double next_time;
00067
00068 public:
00069 texture_buffer() : texture(), last_timestamp(-1), fps(), num_frames(), next_time(1000) {}
00070
00071 GLuint get_gl_handle() const { return texture; }
00072
00073 void upload(const void * data, int width, int height, rs::format format, int stride = 0)
00074 {
00075
00076 if(!texture) glGenTextures(1, &texture);
00077 glBindTexture(GL_TEXTURE_2D, texture);
00078 stride = stride == 0 ? width : stride;
00079 glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
00080 switch(format)
00081 {
00082 case rs::format::any:
00083 throw std::runtime_error("not a valid format");
00084 case rs::format::z16:
00085 case rs::format::disparity16:
00086 rgb.resize(stride * height * 3);
00087 make_depth_histogram(rgb.data(), reinterpret_cast<const uint16_t *>(data), stride, height);
00088 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, stride, height, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb.data());
00089
00090 break;
00091 case rs::format::xyz32f:
00092 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, data);
00093 break;
00094 case rs::format::yuyv:
00095 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
00096 break;
00097 case rs::format::rgb8: case rs::format::bgr8:
00098 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
00099 break;
00100 case rs::format::rgba8: case rs::format::bgra8:
00101 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
00102 break;
00103 case rs::format::y8:
00104 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
00105 break;
00106 case rs::format::y16:
00107 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, data);
00108 break;
00109 case rs::format::raw8:
00110 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
00111 break;
00112 case rs::format::raw10:
00113 {
00114
00115 rgb.clear(); rgb.resize(width/2 * height/2 * 3);
00116 auto out = rgb.data(); auto in0 = reinterpret_cast<const uint8_t *>(data), in1 = in0 + width*5/4;
00117 for(int y=0; y<height; y+=2)
00118 {
00119 for(int x=0; x<width; x+=4)
00120 {
00121 *out++ = in0[0]; *out++ = (in0[1] + in1[0]) / 2; *out++ = in1[1];
00122 *out++ = in0[2]; *out++ = (in0[3] + in1[2]) / 2; *out++ = in1[3];
00123 in0 += 5; in1 += 5;
00124 }
00125 in0 = in1; in1 += width*5/4;
00126 }
00127 glPixelStorei(GL_UNPACK_ROW_LENGTH, width / 2);
00128 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width/2, height/2, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb.data());
00129 }
00130 break;
00131 case rs::format::raw16:
00132
00133 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, data);
00134 break;
00135 default:
00136 {
00137 std::stringstream ss;
00138 ss << rs_format_to_string((rs_format)format) << " pixel format is not supported by the demo";
00139 throw std::runtime_error(ss.str().c_str());
00140 }
00141 }
00142 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00143 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00146 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00147 glBindTexture(GL_TEXTURE_2D, 0);
00148 }
00149
00150 void upload(rs::device & dev, rs::stream stream)
00151 {
00152 if (stream <= rs::stream::fisheye)
00153 assert(dev.is_stream_enabled(stream));
00154
00155 const double timestamp = dev.get_frame_timestamp(stream);
00156 if(timestamp != last_timestamp)
00157 {
00158 upload(dev.get_frame_data(stream), dev.get_stream_width(stream), dev.get_stream_height(stream), dev.get_stream_format(stream));
00159 last_timestamp = timestamp;
00160
00161 ++num_frames;
00162 if(timestamp >= next_time)
00163 {
00164 fps = num_frames;
00165 num_frames = 0;
00166 next_time += 1000;
00167 }
00168 }
00169 }
00170
00171 void upload(rs::frame& frame)
00172 {
00173 const double timestamp = frame.get_timestamp();
00174 if(timestamp != last_timestamp)
00175 {
00176 upload(frame.get_data(), frame.get_width(), frame.get_height(), frame.get_format(), (frame.get_stride() * 8) / frame.get_bpp());
00177 last_timestamp = timestamp;
00178
00179 ++num_frames;
00180 if(timestamp >= next_time)
00181 {
00182 fps = num_frames;
00183 num_frames = 0;
00184 next_time += 1000;
00185 }
00186 }
00187 }
00188
00189 void show(float rx, float ry, float rw, float rh) const
00190 {
00191 glBindTexture(GL_TEXTURE_2D, texture);
00192 glEnable(GL_TEXTURE_2D);
00193 glBegin(GL_QUADS);
00194 glTexCoord2f(0, 0); glVertex2f(rx, ry );
00195 glTexCoord2f(1, 0); glVertex2f(rx+rw, ry );
00196 glTexCoord2f(1, 1); glVertex2f(rx+rw, ry+rh);
00197 glTexCoord2f(0, 1); glVertex2f(rx, ry+rh);
00198 glEnd();
00199 glDisable(GL_TEXTURE_2D);
00200 glBindTexture(GL_TEXTURE_2D, 0);
00201 }
00202
00203 void print(int x, int y, const char * text)
00204 {
00205 char buffer[20000];
00206
00207 glEnableClientState(GL_VERTEX_ARRAY);
00208 glVertexPointer(2, GL_FLOAT, 16, buffer);
00209 glDrawArrays(GL_QUADS, 0, 4*stb_easy_font_print((float)x, (float)y, (char *)text, nullptr, buffer, sizeof(buffer)));
00210 glDisableClientState(GL_VERTEX_ARRAY);
00211 }
00212
00213 void show(rs::device & dev, rs::stream stream, int rx, int ry, int rw, int rh)
00214 {
00215 if((stream <= rs::stream::fisheye) && (!dev.is_stream_enabled(stream))) return;
00216
00217 upload(dev, stream);
00218
00219 int width = dev.get_stream_width(stream), height = dev.get_stream_height(stream);
00220 float h = (float)rh, w = (float)rh * width / height;
00221 if(w > rw)
00222 {
00223 float scale = rw/w;
00224 w *= scale;
00225 h *= scale;
00226 }
00227
00228 show(rx + (rw - w)/2, ry + (rh - h)/2, w, h);
00229 std::ostringstream ss; ss << stream << ": " << width << " x " << height << " " << dev.get_stream_format(stream) << " (" << fps << "/" << dev.get_stream_framerate(stream) << ")" << ", F#: " << dev.get_frame_number(stream);
00230 glColor3f(0,0,0);
00231 draw_text(rx+9, ry+17, ss.str().c_str());
00232 glColor3f(1,1,1);
00233 draw_text(rx+8, ry+16, ss.str().c_str());
00234 }
00235
00236 void show(rs::stream stream, rs::format format, int stream_framerate, unsigned long long frame_number, double timestamp, int rx, int ry, int rw, int rh, int width, int height)
00237 {
00238 show(rx, ry, rw, rh, width, height);
00239
00240 std::ostringstream ss; ss << stream << ": " << width << " x " << height << " " << format << " (" << fps << "/" << stream_framerate << ")" << ", F#: " << frame_number << ", TS: " << timestamp;
00241 glColor3f(0,0,0);
00242 draw_text(rx+9, ry+17, ss.str().c_str());
00243 glColor3f(1,1,1);
00244 draw_text(rx+8, ry+16, ss.str().c_str());
00245 }
00246
00247 void show(int rx, int ry, int rw, int rh, int width, int height)
00248 {
00249 float h = (float)rh, w = (float)rh * width / height;
00250 if (w > rw)
00251 {
00252 float scale = rw / w;
00253 w *= scale;
00254 h *= scale;
00255 }
00256
00257 show(rx + (rw - w) / 2, ry + (rh - h) / 2, w, h);
00258 }
00259
00260 void show(const void * data, int width, int height, rs::format format, const std::string & caption, int rx, int ry, int rw, int rh)
00261 {
00262 if(!data) return;
00263
00264 upload(data, width, height, format);
00265
00266 float h = (float)rh, w = (float)rh * width / height;
00267 if(w > rw)
00268 {
00269 float scale = rw/w;
00270 w *= scale;
00271 h *= scale;
00272 }
00273
00274 show(rx + (rw - w)/2, ry + (rh - h)/2, w, h);
00275
00276 std::ostringstream ss; ss << caption << ": " << width << " x " << height << " " << format;
00277 glColor3f(0,0,0);
00278 draw_text(rx+9, ry+17, ss.str().c_str());
00279 glColor3f(1,1,1);
00280 draw_text(rx+8, ry+16, ss.str().c_str());
00281 }
00282 };
00283
00284 inline void draw_depth_histogram(const uint16_t depth_image[], int width, int height)
00285 {
00286 static uint8_t rgb_image[640*480*3];
00287 make_depth_histogram(rgb_image, depth_image, width, height);
00288 glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb_image);
00289 }