Skip to content
This repository has been archived by the owner on Aug 16, 2018. It is now read-only.

Commit

Permalink
Added 1st (ugly) version of viewer window
Browse files Browse the repository at this point in the history
  • Loading branch information
Tony Gonçalves committed Jan 31, 2011
1 parent 5b427fb commit cc9c3e9
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 44 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ liboscpack:
cd oscpack; make

osceleton: liboscpack
g++ src/OSCeleton.cpp -O3 -Wno-write-strings -Ioscpack -I/usr/include/ni -lOpenNI -lstdc++ oscpack/ip/*.o oscpack/ip/posix/*.o oscpack/osc/*.o -o osceleton
g++ src/OSCeleton.cpp src/viewer.cpp -O3 -Wno-write-strings -Ioscpack -I/usr/include/ni -lOpenNI -lstdc++ -lGL -lGLU -lglut oscpack/ip/*.o oscpack/ip/posix/*.o oscpack/osc/*.o -o osceleton

clean:
rm -f osceleton ; cd oscpack ; make clean
117 changes: 74 additions & 43 deletions src/OSCeleton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@
#include <cstdio>
#include <csignal>

#include <GL/glut.h>

#include <XnCppWrapper.h>

#include <ip/UdpSocket.h>
#include <osc/OscOutboundPacketStream.h>

#include "viewer.h"



char *ADDRESS = "127.0.0.1";
Expand All @@ -35,18 +39,20 @@ int PORT = 7110;
char osc_buffer[OUTPUT_BUFFER_SIZE];
UdpTransmitSocket *transmitSocket;

char tmp[50]; //Temp buffer for OSC address pattern
char tmp[50]; //Temp buffer for OSC address pattern
int userID;
float jointCoords[3];

//Multipliers for coordinate system. This is useful if you use software like animata,
//that needs OSC messages to use an arbitrary coordinate system.
//Multipliers for coordinate system. This is useful if you use
//software like animata, that needs OSC messages to use an arbitrary
//coordinate system.
double mult_x = 1;
double mult_y = 1;
double mult_z = 1;

//Offsets for coordinate system. This is useful if you use software like animata,
//that needs OSC messages to use an arbitrary coordinate system.
//Offsets for coordinate system. This is useful if you use software
//like animata, that needs OSC messages to use an arbitrary coordinate
//system.
double off_x = 0.0;
double off_y = 0.0;
double off_z = 0.0;
Expand All @@ -59,24 +65,26 @@ bool sendRot = false;
bool filter = false;
int nDimensions = 3;

void (*oscFunc)(osc::OutboundPacketStream* , char*) = NULL;
void (*oscFunc)(osc::OutboundPacketStream*, char*) = NULL;

xn::Context context;
xn::DepthGenerator depth;
xn::DepthMetaData depthMD;
xn::UserGenerator userGenerator;
XnChar g_strPose[20];
XnChar g_strPose[20] = "";



// Callback: New user was detected
void XN_CALLBACK_TYPE User_NewUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie) {
void XN_CALLBACK_TYPE new_user(xn::UserGenerator& generator, XnUserID nId, void* pCookie) {
printf("New User %d\n", nId);
userGenerator.GetSkeletonCap().RequestCalibration(nId, TRUE);

if (kitchenMode) return;

osc::OutboundPacketStream p( osc_buffer, OUTPUT_BUFFER_SIZE );
osc::OutboundPacketStream p(osc_buffer, OUTPUT_BUFFER_SIZE);
p << osc::BeginBundleImmediate;
p << osc::BeginMessage( "/new_user" );
p << osc::BeginMessage("/new_user");
p << (int)nId;
p << osc::EndMessage;
p << osc::EndBundle;
Expand All @@ -86,14 +94,14 @@ void XN_CALLBACK_TYPE User_NewUser(xn::UserGenerator& generator, XnUserID nId, v


// Callback: An existing user was lost
void XN_CALLBACK_TYPE User_LostUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie) {
void XN_CALLBACK_TYPE lost_user(xn::UserGenerator& generator, XnUserID nId, void* pCookie) {
printf("Lost user %d\n", nId);

if (kitchenMode) return;

osc::OutboundPacketStream p( osc_buffer, OUTPUT_BUFFER_SIZE );
p << osc::BeginBundleImmediate;
p << osc::BeginMessage( "/lost_user" );
p << osc::BeginMessage("/lost_user");
p << (int)nId;
p << osc::EndMessage;
p << osc::EndBundle;
Expand All @@ -103,7 +111,7 @@ void XN_CALLBACK_TYPE User_LostUser(xn::UserGenerator& generator, XnUserID nId,


// Callback: Detected a pose
void XN_CALLBACK_TYPE UserPose_PoseDetected(xn::PoseDetectionCapability& capability, const XnChar* strPose, XnUserID nId, void* pCookie) {
void XN_CALLBACK_TYPE pose_detected(xn::PoseDetectionCapability& capability, const XnChar* strPose, XnUserID nId, void* pCookie) {
printf("Pose %s detected for user %d\n", strPose, nId);
userGenerator.GetPoseDetectionCap().StopPoseDetection(nId);
userGenerator.GetSkeletonCap().RequestCalibration(nId, TRUE);
Expand All @@ -112,14 +120,14 @@ void XN_CALLBACK_TYPE UserPose_PoseDetected(xn::PoseDetectionCapability& capabil


// Callback: Started calibration
void XN_CALLBACK_TYPE UserCalibration_CalibrationStart(xn::SkeletonCapability& capability, XnUserID nId, void* pCookie) {
void XN_CALLBACK_TYPE calibration_started(xn::SkeletonCapability& capability, XnUserID nId, void* pCookie) {
printf("Calibration started for user %d\n", nId);
}



// Callback: Finished calibration
void XN_CALLBACK_TYPE UserCalibration_CalibrationEnd(xn::SkeletonCapability& capability, XnUserID nId, XnBool bSuccess, void* pCookie) {
void XN_CALLBACK_TYPE calibration_ended(xn::SkeletonCapability& capability, XnUserID nId, XnBool bSuccess, void* pCookie) {
if (bSuccess) {
printf("Calibration complete, start tracking user %d\n", nId);
userGenerator.GetSkeletonCap().StartTracking(nId);
Expand All @@ -143,16 +151,16 @@ void XN_CALLBACK_TYPE UserCalibration_CalibrationEnd(xn::SkeletonCapability& cap


int jointPos(XnUserID player, XnSkeletonJoint eJoint) {
XnSkeletonJointTransformation joint;
userGenerator.GetSkeletonCap().GetSkeletonJoint(player, eJoint, joint);
XnSkeletonJointPosition joint;
userGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, eJoint, joint);

if ((joint.position.fConfidence < 0.5))// || (joint.orientation.fConfidence < 0.5))
if (joint.fConfidence < 0.5)
return -1;

userID = player;
jointCoords[0] = off_x + (mult_x * (1280 + joint.position.position.X) / 2560); //Normalize coords to 0..1 interval
jointCoords[1] = off_y + (mult_y * (1280 - joint.position.position.Y) / 2560); //Normalize coords to 0..1 interval
jointCoords[2] = off_z + (mult_z * joint.position.position.Z * 7.8125 / 10000); //Normalize coords to 0..7.8125 interval
jointCoords[0] = off_x + (mult_x * (1280 - joint.position.X) / 2560); //Normalize coords to 0..1 interval
jointCoords[1] = off_y + (mult_y * (1280 - joint.position.Y) / 2560); //Normalize coords to 0..1 interval
jointCoords[2] = off_z + (mult_z * joint.position.Z * 7.8125 / 10000); //Normalize coords to 0..7.8125 interval

//for (int i=0; i<9; i++)
// jointRots[i] = joint.orientation.orientation.elements[i];
Expand Down Expand Up @@ -188,14 +196,30 @@ void genQCMsg(osc::OutboundPacketStream *p, char *name) {



void sendUserPosMsg(XnUserID id) {
osc::OutboundPacketStream p(osc_buffer, OUTPUT_BUFFER_SIZE);
XnPoint3D com;
sprintf(tmp, "/user/%d", id);
p << osc::BeginBundleImmediate;
p << osc::BeginMessage(tmp);
userGenerator.GetCoM(id, com);
p << (float)(off_x + (mult_x * (1280 - com.X) / 2560));
p << (float)(off_y + (mult_y * (1280 - com.Y) / 2560));
p << (float)(off_z + (mult_z * com.Z * 7.8125 / 10000));
p << osc::EndMessage;
p << osc::EndBundle;
transmitSocket->Send(p.Data(), p.Size());
}



void sendOSC() {
XnUserID aUsers[15];
XnUInt16 nUsers = 15;
userGenerator.GetUsers(aUsers, nUsers);
for (int i = 0; i < nUsers; ++i)
{
for (int i = 0; i < nUsers; ++i) {
if (userGenerator.GetSkeletonCap().IsTracking(aUsers[i])) {
osc::OutboundPacketStream p( osc_buffer, OUTPUT_BUFFER_SIZE );
osc::OutboundPacketStream p(osc_buffer, OUTPUT_BUFFER_SIZE);
p << osc::BeginBundleImmediate;

if (jointPos(aUsers[i], XN_SKEL_HEAD) == 0) {
Expand Down Expand Up @@ -274,6 +298,10 @@ void sendOSC() {
p << osc::EndBundle;
transmitSocket->Send(p.Data(), p.Size());
}
else {
//Send user's center of mass
sendUserPosMsg(aUsers[i]);
}
}
}

Expand Down Expand Up @@ -310,8 +338,8 @@ For a more detailed explanation of options consult the README file.\n\n",

void checkRetVal(XnStatus nRetVal) {
if (nRetVal != XN_STATUS_OK) {
printf("There was a problem initializing kinect... Make sure you have\
connected both usb and power cables and that the driver and OpenNI framework\
printf("There was a problem initializing kinect... Make sure you have \
connected both usb and power cables and that the driver and OpenNI framework \
are correctly installed.\n\n");
exit(1);
}
Expand All @@ -327,12 +355,20 @@ void terminate(int ignored) {



int main(int argc, char **argv)
{
void main_loop() {
// Read next available data
context.WaitAnyUpdateAll();
// Process the data
depth.GetMetaData(depthMD);
sendOSC();
draw();
}



int main(int argc, char **argv) {
unsigned int arg = 1,
require_argument = 0;
xn::DepthGenerator depth;
xn::DepthMetaData depthMD;
XnMapOutputMode mapMode;
XnStatus nRetVal = XN_STATUS_OK;
XnCallbackHandle hUserCallbacks, hCalibrationCallbacks, hPoseCallbacks;
Expand Down Expand Up @@ -438,7 +474,7 @@ int main(int argc, char **argv)
case 'f':
filter = true;
break;
case 'k': // Set "Kitchen" mode (for Kitchen Budapest's animata)
case 'k':
kitchenMode = true;
break;
case 'q': // Set Quartz Composer mode
Expand All @@ -462,7 +498,7 @@ int main(int argc, char **argv)
if (oscFunc == NULL)
oscFunc = genOscMsg;

depth.Create(context);
checkRetVal(depth.Create(context));

if (!play) {
mapMode.nXRes = XN_VGA_X_RES;
Expand All @@ -475,14 +511,14 @@ int main(int argc, char **argv)
if (nRetVal != XN_STATUS_OK)
nRetVal = userGenerator.Create(context);

checkRetVal(userGenerator.RegisterUserCallbacks(User_NewUser, User_LostUser, NULL, hUserCallbacks));
checkRetVal(userGenerator.GetSkeletonCap().RegisterCalibrationCallbacks(UserCalibration_CalibrationStart, UserCalibration_CalibrationEnd, NULL, hCalibrationCallbacks));
checkRetVal(userGenerator.GetPoseDetectionCap().RegisterToPoseCallbacks(UserPose_PoseDetected, NULL, NULL, hPoseCallbacks));
checkRetVal(userGenerator.RegisterUserCallbacks(new_user, lost_user, NULL, hUserCallbacks));
checkRetVal(userGenerator.GetSkeletonCap().RegisterCalibrationCallbacks(calibration_started, calibration_ended, NULL, hCalibrationCallbacks));
checkRetVal(userGenerator.GetPoseDetectionCap().RegisterToPoseCallbacks(pose_detected, NULL, NULL, hPoseCallbacks));
checkRetVal(userGenerator.GetSkeletonCap().GetCalibrationPose(g_strPose));
checkRetVal(userGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL));
if (filter)
userGenerator.GetSkeletonCap().SetSmoothing(0.8);
xnSetMirror(depth, mirrorMode);
xnSetMirror(depth, !mirrorMode);

transmitSocket = new UdpTransmitSocket(IpEndpointName(ADDRESS, PORT));
signal(SIGTERM, terminate);
Expand All @@ -506,13 +542,8 @@ int main(int argc, char **argv)
if (record)
recorder.AddNodeToRecording(depth, XN_CODEC_16Z_EMB_TABLES);

while (true) {
// Read next available data
context.WaitAnyUpdateAll();
// Process the data
depth.GetMetaData(depthMD);
sendOSC();
}
init_window(argc, argv, 640, 480, main_loop);
glutMainLoop();

terminate(0);
}
Expand Down
112 changes: 112 additions & 0 deletions src/viewer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include "viewer.h"



int window; // GLUT window id
int width;
int height;
GLuint tex_id;
int buf_size;
GLubyte *buf;


/* The main drawing function. */
void draw() {
const XnDepthPixel *data = depthMD.Data();
GLubyte tmp;
for (int i = 0; i < width*height; i++) {
tmp = (10000 - data[i]) / 80;
//printf("tmp = %d\n", tmp);
buf[i*3] = tmp;
buf[i*3+1] = tmp;
buf[i*3+2] = tmp;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buf);


// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glLoadIdentity();

// glTranslatef(0.0f,0.0f,-3.0f);

// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.

glBindTexture(GL_TEXTURE_2D, tex_id);
glColor4f(1.0, 1.0, 1.0, 1.0);
// draw a square (quadrilateral)
glBegin(GL_QUADS); // start drawing a polygon (4 sided)
glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0); // Top Left
glTexCoord2f(1.0f, 0.0f); glVertex2i(width, 0); // Top Right
glTexCoord2f(1.0f, 1.0f); glVertex2i(width, height); // Bottom Right
glTexCoord2f(0.0f, 1.0f); glVertex2i(0, height); // Bottom Left
glEnd(); // done with the polygon

// swap buffers to display, since we're double buffered.
glutSwapBuffers();
}



void init_tex() {
// Create Texture
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}



void init_window(int argc, char **argv, int w, int h, void main_loop(void)) {
width = w;
height = h;
buf_size = 3*width*height*sizeof(GLubyte);
buf = (GLubyte*)malloc(buf_size);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutInitWindowPosition(0, 0);
window = glutCreateWindow("OSCeleton");

/* Register the function to do all our OpenGL drawing. */
glutDisplayFunc(main_loop);

/* Go fullscreen. This is the soonest we could possibly go fullscreen. */
//glutFullScreen();

/* Even if there are no events, redraw our gl scene. */
glutIdleFunc(main_loop);

/* Register the function called when our window is resized. */
//glutReshapeFunc(&ReSizeGLScene);

/* Register the function called when the keyboard is pressed. */
//glutKeyboardFunc(&keyPressed);



gluOrtho2D(0.0, width, height, 0.0);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
init_tex();

//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//glClearDepth(1.0);
//glDepthFunc(GL_LESS);
//glEnable(GL_DEPTH_TEST);
//glShadeModel(GL_SMOOTH);

//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();

//gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window

//glMatrixMode(GL_MODELVIEW);
}
Loading

0 comments on commit cc9c3e9

Please sign in to comment.