Skip to content

Commit 110a58b

Browse files
committed
Merge pull request #409 from pAIgn10/master
Add cpp_pcview point cloud example Reviewed-by: Benn Snyder <[email protected]>
2 parents 8d95792 + 811950a commit 110a58b

File tree

2 files changed

+340
-0
lines changed

2 files changed

+340
-0
lines changed

wrappers/cpp/CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ endif()
1313
include_directories(.)
1414

1515
add_executable(freenect-cppview cppview.cpp)
16+
add_executable(freenect-cpp_pcview cpp_pc_view.cpp)
1617

1718
# Mac just has everything already
1819
if(APPLE)
@@ -26,9 +27,13 @@ else()
2627
include_directories(${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${USB_INCLUDE_DIRS})
2728

2829
target_link_libraries(freenect-cppview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB})
30+
target_link_libraries(freenect-cpp_pcview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
2931
endif()
3032

3133
install (TARGETS freenect-cppview
3234
DESTINATION bin)
3335

36+
install (TARGETS freenect-cpp_pcview
37+
DESTINATION bin)
38+
3439
ENDIF()

wrappers/cpp/cpp_pc_view.cpp

+335
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
/*
2+
* This file is part of the OpenKinect Project. http://www.openkinect.org
3+
*
4+
* Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
5+
* for details.
6+
*
7+
* This code is licensed to you under the terms of the Apache License, version
8+
* 2.0, or, at your option, the terms of the GNU General Public License,
9+
* version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
10+
* or the following URLs:
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
* http://www.gnu.org/licenses/gpl-2.0.txt
13+
*
14+
* If you redistribute this file in source form, modified or unmodified, you
15+
* may:
16+
* 1) Leave this header intact and distribute it under the same terms,
17+
* accompanying it with the APACHE20 and GPL20 files, or
18+
* 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
19+
* 3) Delete the GPL v2 clause and accompany it with the APACHE20 file
20+
* In all cases you must keep the copyright notice intact and include a copy
21+
* of the CONTRIB file.
22+
*
23+
* Binary distributions must follow the binary distribution requirements of
24+
* either License.
25+
*/
26+
27+
#include <iostream>
28+
#include <vector>
29+
#include <pthread.h>
30+
#include <libfreenect.hpp>
31+
32+
#if defined(__APPLE__)
33+
#include <GLUT/glut.h>
34+
#else
35+
#include <GL/glut.h>
36+
#endif
37+
38+
39+
class Mutex
40+
{
41+
public:
42+
Mutex()
43+
{
44+
pthread_mutex_init(&m_mutex, NULL);
45+
}
46+
47+
void lock()
48+
{
49+
pthread_mutex_lock(&m_mutex);
50+
}
51+
52+
void unlock()
53+
{
54+
pthread_mutex_unlock(&m_mutex);
55+
}
56+
57+
class ScopedLock
58+
{
59+
public:
60+
ScopedLock(Mutex &mutex) : _mutex(mutex)
61+
{
62+
_mutex.lock();
63+
}
64+
65+
~ScopedLock()
66+
{
67+
_mutex.unlock();
68+
}
69+
70+
private:
71+
Mutex &_mutex;
72+
};
73+
74+
private:
75+
pthread_mutex_t m_mutex;
76+
};
77+
78+
79+
class MyFreenectDevice : public Freenect::FreenectDevice
80+
{
81+
public:
82+
MyFreenectDevice(freenect_context *_ctx, int _index)
83+
: Freenect::FreenectDevice(_ctx, _index),
84+
m_buffer_video(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB).bytes),
85+
m_buffer_depth(freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_REGISTERED).bytes / 2),
86+
m_new_rgb_frame(false), m_new_depth_frame(false)
87+
{
88+
setDepthFormat(FREENECT_DEPTH_REGISTERED);
89+
}
90+
91+
// Do not call directly, even in child
92+
void VideoCallback(void *_rgb, uint32_t timestamp)
93+
{
94+
Mutex::ScopedLock lock(m_rgb_mutex);
95+
uint8_t* rgb = static_cast<uint8_t*>(_rgb);
96+
copy(rgb, rgb+getVideoBufferSize(), m_buffer_video.begin());
97+
m_new_rgb_frame = true;
98+
}
99+
100+
// Do not call directly, even in child
101+
void DepthCallback(void *_depth, uint32_t timestamp)
102+
{
103+
Mutex::ScopedLock lock(m_depth_mutex);
104+
uint16_t* depth = static_cast<uint16_t*>(_depth);
105+
copy(depth, depth+getDepthBufferSize()/2, m_buffer_depth.begin());
106+
m_new_depth_frame = true;
107+
}
108+
109+
bool getRGB(std::vector<uint8_t> &buffer)
110+
{
111+
Mutex::ScopedLock lock(m_rgb_mutex);
112+
113+
if (!m_new_rgb_frame)
114+
return false;
115+
116+
buffer.swap(m_buffer_video);
117+
m_new_rgb_frame = false;
118+
119+
return true;
120+
}
121+
122+
bool getDepth(std::vector<uint16_t> &buffer)
123+
{
124+
Mutex::ScopedLock lock(m_depth_mutex);
125+
126+
if (!m_new_depth_frame)
127+
return false;
128+
129+
buffer.swap(m_buffer_depth);
130+
m_new_depth_frame = false;
131+
132+
return true;
133+
}
134+
135+
private:
136+
Mutex m_rgb_mutex;
137+
Mutex m_depth_mutex;
138+
std::vector<uint8_t> m_buffer_video;
139+
std::vector<uint16_t> m_buffer_depth;
140+
bool m_new_rgb_frame;
141+
bool m_new_depth_frame;
142+
};
143+
144+
145+
Freenect::Freenect freenect;
146+
MyFreenectDevice* device;
147+
148+
int window(0); // Glut window identifier
149+
int mx = -1, my = -1; // Prevous mouse coordinates
150+
float anglex = 0, angley = 0; // Panning angles
151+
float zoom = 1; // Zoom factor
152+
bool color = true; // Flag to indicate to use of color in the cloud
153+
154+
155+
void DrawGLScene()
156+
{
157+
static std::vector<uint8_t> rgb(640*480*3);
158+
static std::vector<uint16_t> depth(640*480);
159+
160+
device->getRGB(rgb);
161+
device->getDepth(depth);
162+
163+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
164+
165+
glPointSize(1.0f);
166+
167+
glBegin(GL_POINTS);
168+
169+
if (!color) glColor3ub(255, 255, 255);
170+
for (int i = 0; i < 480*640; ++i)
171+
{
172+
if (color)
173+
glColor3ub( rgb[3*i+0], // R
174+
rgb[3*i+1], // G
175+
rgb[3*i+2] ); // B
176+
177+
float f = 595.f;
178+
// Convert from image plane coordinates to world coordinates
179+
glVertex3f( (i%640 - (640-1)/2.f) * depth[i] / f, // X = (x - cx) * d / fx
180+
(i/640 - (480-1)/2.f) * depth[i] / f, // Y = (y - cy) * d / fy
181+
depth[i] ); // Z = d
182+
}
183+
184+
glEnd();
185+
186+
// Draw the world coordinate frame
187+
glLineWidth(2.0f);
188+
glBegin(GL_LINES);
189+
glColor3ub(255, 0, 0); // X-axis
190+
glVertex3f( 0, 0, 0);
191+
glVertex3f( 50, 0, 0);
192+
glColor3ub(0, 255, 0); // Y-axis
193+
glVertex3f(0, 0, 0);
194+
glVertex3f(0, 50, 0);
195+
glColor3ub(0, 0, 255); // Z-axis
196+
glVertex3f(0, 0, 0);
197+
glVertex3f(0, 0, 50);
198+
glEnd();
199+
200+
// Place the camera
201+
glMatrixMode(GL_MODELVIEW);
202+
glLoadIdentity();
203+
glScalef(zoom, zoom, 1);
204+
gluLookAt( -7*anglex, -7*angley, -1000.0,
205+
0.0, 0.0, 2000.0,
206+
0.0, -1.0, 0.0 );
207+
208+
glutSwapBuffers();
209+
}
210+
211+
212+
void keyPressed(unsigned char key, int x, int y)
213+
{
214+
switch (key)
215+
{
216+
case 'C':
217+
case 'c':
218+
color = !color;
219+
break;
220+
221+
case 'Q':
222+
case 'q':
223+
case 0x1B: // ESC
224+
glutDestroyWindow(window);
225+
device->stopDepth();
226+
device->stopVideo();
227+
exit(0);
228+
}
229+
}
230+
231+
232+
void mouseMoved(int x, int y)
233+
{
234+
if (mx >= 0 && my >= 0)
235+
{
236+
anglex += x - mx;
237+
angley += y - my;
238+
}
239+
240+
mx = x;
241+
my = y;
242+
}
243+
244+
245+
void mouseButtonPressed(int button, int state, int x, int y)
246+
{
247+
if (state == GLUT_DOWN)
248+
{
249+
switch (button)
250+
{
251+
case GLUT_LEFT_BUTTON:
252+
mx = x;
253+
my = y;
254+
break;
255+
256+
case 3:
257+
zoom *= 1.2f;
258+
break;
259+
260+
case 4:
261+
zoom /= 1.2f;
262+
break;
263+
}
264+
}
265+
else if (state == GLUT_UP && button == GLUT_LEFT_BUTTON)
266+
{
267+
mx = -1;
268+
my = -1;
269+
}
270+
}
271+
272+
273+
void resizeGLScene(int width, int height)
274+
{
275+
glViewport(0, 0, width, height);
276+
glMatrixMode(GL_PROJECTION);
277+
glLoadIdentity();
278+
gluPerspective(50.0, (float)width / height, 900.0, 11000.0);
279+
280+
glMatrixMode(GL_MODELVIEW);
281+
}
282+
283+
284+
void idleGLScene()
285+
{
286+
glutPostRedisplay();
287+
}
288+
289+
290+
void printInfo()
291+
{
292+
std::cout << "\nAvailable Controls:" << std::endl;
293+
std::cout << "===================" << std::endl;
294+
std::cout << "Rotate : Mouse Left Button" << std::endl;
295+
std::cout << "Zoom : Mouse Wheel" << std::endl;
296+
std::cout << "Toggle Color : C" << std::endl;
297+
std::cout << "Quit : Q or Esc\n" << std::endl;
298+
}
299+
300+
301+
int main(int argc, char **argv)
302+
{
303+
device = &freenect.createDevice<MyFreenectDevice>(0);
304+
device->startVideo();
305+
device->startDepth();
306+
307+
glutInit(&argc, argv);
308+
309+
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
310+
glutInitWindowSize(640, 480);
311+
glutInitWindowPosition(0, 0);
312+
313+
window = glutCreateWindow("LibFreenect");
314+
glClearColor(0.45f, 0.45f, 0.45f, 0.0f);
315+
316+
glEnable(GL_DEPTH_TEST);
317+
glEnable(GL_ALPHA_TEST);
318+
glAlphaFunc(GL_GREATER, 0.0f);
319+
320+
glMatrixMode(GL_PROJECTION);
321+
gluPerspective(50.0, 1.0, 900.0, 11000.0);
322+
323+
glutDisplayFunc(&DrawGLScene);
324+
glutIdleFunc(&idleGLScene);
325+
glutReshapeFunc(&resizeGLScene);
326+
glutKeyboardFunc(&keyPressed);
327+
glutMotionFunc(&mouseMoved);
328+
glutMouseFunc(&mouseButtonPressed);
329+
330+
printInfo();
331+
332+
glutMainLoop();
333+
334+
return 0;
335+
}

0 commit comments

Comments
 (0)