From 1f468a77f2a767963265959a5f35c5cb80fcceed Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 30 Aug 2013 17:19:41 -0700 Subject: [PATCH] Added Faceshift-network library. --- interface/external/faceshift/CMakeLists.txt | 11 + .../faceshift/include/fsbinarystream.h | 410 ++++++++++++++ .../faceshift/lib/UNIX/libfaceshift.a | Bin 0 -> 523750 bytes .../external/faceshift/src/fsbinarystream.cpp | 502 ++++++++++++++++++ 4 files changed, 923 insertions(+) create mode 100644 interface/external/faceshift/CMakeLists.txt create mode 100644 interface/external/faceshift/include/fsbinarystream.h create mode 100644 interface/external/faceshift/lib/UNIX/libfaceshift.a create mode 100644 interface/external/faceshift/src/fsbinarystream.cpp diff --git a/interface/external/faceshift/CMakeLists.txt b/interface/external/faceshift/CMakeLists.txt new file mode 100644 index 0000000000..d6c44c5cd8 --- /dev/null +++ b/interface/external/faceshift/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.8) + +set(TARGET_NAME faceshift) +project(${TARGET_NAME}) + +# grab the implemenation and header files +file(GLOB FACESHIFT_SRCS include/*.h src/*.cpp) + +include_directories(include) + +add_library(${TARGET_NAME} ${FACESHIFT_SRCS}) diff --git a/interface/external/faceshift/include/fsbinarystream.h b/interface/external/faceshift/include/fsbinarystream.h new file mode 100644 index 0000000000..8fa585397b --- /dev/null +++ b/interface/external/faceshift/include/fsbinarystream.h @@ -0,0 +1,410 @@ +#pragma once + +#ifndef FSBINARYSTREAM_H +#define FSBINARYSTREAM_H + +// ========================================================================== +// Copyright (C) 2012 faceshift AG, and/or its licensors. All rights reserved. +// +// the software is free to use and provided "as is", without warranty of any kind. +// faceshift AG does not make and hereby disclaims any express or implied +// warranties including, but not limited to, the warranties of +// non-infringement, merchantability or fitness for a particular purpose, +// or arising from a course of dealing, usage, or trade practice. in no +// event will faceshift AG and/or its licensors be liable for any lost +// revenues, data, or profits, or special, direct, indirect, or +// consequential damages, even if faceshift AG and/or its licensors has +// been advised of the possibility or probability of such damages. +// ========================================================================== + + +/** + * Define the HAVE_EIGEN preprocessor define, if you are using the Eigen library, it allows you to easily convert our tracked data from and to eigen + * See fsVector3f and fsQuaternionf for more details + **/ + +#ifdef HAVE_EIGEN +#include +#include +#endif + +#ifdef _MSC_VER +#include +#else +#include +#endif + +#include +#include +#include + +/******************************************************************************************* + * This first part of the file contains a definition of the datastructures holding the + * tracking results + ******************************************************************************************/ + +namespace fs { + +/** + * A floating point three-vector. + * + * To keep these networking classes as simple as possible, we do not implement the + * vector semantics here, use Eigen for that purpose. The class just holds three named floats, + * and you have to interpret them yourself. + **/ +struct fsVector3f { + float x,y,z; + + fsVector3f() {} +#ifdef HAVE_EIGEN + explicit fsVector3f(const Eigen::Matrix &v) : x(v[0]), y(v[1]), z(v[2]) {} + Eigen::Map< Eigen::Matrix > eigen() const { return Eigen::Map >((float*)this); } +#endif +}; + +/** + * An integer three-vector. + **/ +struct fsVector3i { + int32_t x,y,z; + + fsVector3i() {} +#ifdef HAVE_EIGEN + explicit fsVector3i(const Eigen::Matrix &v) : x(v[0]), y(v[1]), z(v[2]) {} + Eigen::Map > eigen() const { return Eigen::Map >((int32_t*)this); } +#endif +}; + +/** + * An integer four-vector. + **/ +struct fsVector4i { + int32_t x,y,z,w; + + fsVector4i() {} +#ifdef HAVE_EIGEN + explicit fsVector4i(const Eigen::Matrix &v) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {} + Eigen::Map > eigen() const { return Eigen::Map >((int32_t*)this); } +#endif +}; + +/** + * Structure holding the data of a quaternion. + * + *To keep these networking classes as simple as possible, we do not implement the + * quaternion semantics here. The class just holds four named floats, and you have to interpret them yourself. + * + * If you have Eigen you can just cast this class to an Eigen::Quaternionf and use it. + * + * The quaternion is defined as w+xi+yj+zk + **/ +struct fsQuaternionf { + float x,y,z,w; + + fsQuaternionf() {} +#ifdef HAVE_EIGEN + explicit fsQuaternionf(const Eigen::Quaternionf &q) : x(q.x()), y(q.y()), z(q.z()), w(q.w()) {} + Eigen::Quaternionf eigen() const { return Eigen::Quaternionf(w,x,y,z); } +#endif +}; + +/** + * A structure containing the data tracked for a single frame. + **/ +class fsTrackingData { + public: + //! time stamp in ms + double m_timestamp; + + //! flag whether tracking was successful [0,1] + bool m_trackingSuccessful; + + //! head pose + fsQuaternionf m_headRotation; + fsVector3f m_headTranslation; + + //! eye gaze in degrees + float m_eyeGazeLeftPitch; + float m_eyeGazeLeftYaw; + float m_eyeGazeRightPitch; + float m_eyeGazeRightYaw; + + //! blendshape coefficients + std::vector m_coeffs; + + //! marker positions - format specified in faceshift + std::vector< fsVector3f > m_markers; +}; + +/** + * A structure containing vertex information + */ +class fsVertexData { +public: + //! vertex data + std::vector m_vertices; + +#ifdef HAVE_EIGEN + Eigen::Map > eigen() { return Eigen::Map >((float*)m_vertices.data(),3,m_vertices.size()); } +#endif +}; + +/** + * A strucutre containing mesh information + */ +class fsMeshData { +public: + //! topology (quads) + std::vector m_quads; + + //! topology (triangles) + std::vector m_tris; + + //! vertex data + fsVertexData m_vertex_data; + +#ifdef HAVE_EIGEN + Eigen::Map > quads_eigen() { return Eigen::Map >((int32_t*)m_quads.data(),4,m_quads.size()); } + Eigen::Map > tris_eigen() { return Eigen::Map >((int32_t*)m_tris.data(),3,m_tris.size()); } + Eigen::Map > vertices_eigen() { return m_vertex_data.eigen(); } +#endif + +}; + +/******************************************************************************************* + * Now follows a definition of datastructures encapsulating the network messages + ******************************************************************************************/ + +/** Predeclaration of the message types available in faceshift **/ + +// Inbound +class fsMsgStartCapturing; +class fsMsgStopCapturing; +class fsMsgCalibrateNeutral; +class fsMsgSendMarkerNames; +class fsMsgSendBlendshapeNames; +class fsMsgSendRig; + +// Outbound +class fsMsgTrackingState; +class fsMsgMarkerNames; +class fsMsgBlendshapeNames; +class fsMsgRig; + +/** + * Base class of all message that faceshift is sending. + * A class can be queried for its type, using the id() function for use in a switch statement, or by using a dynamic_cast. + **/ +class fsMsg { +public: + virtual ~fsMsg() {} + + enum MessageType { + // Messages to control faceshift via the network + // These are sent from the client to faceshift + MSG_IN_START_TRACKING = 44344, + MSG_IN_STOP_TRACKING = 44444, + MSG_IN_CALIBRATE_NEUTRAL = 44544, + MSG_IN_SEND_MARKER_NAMES = 44644, + MSG_IN_SEND_BLENDSHAPE_NAMES = 44744, + MSG_IN_SEND_RIG = 44844, + MSG_IN_HEADPOSE_RELATIVE = 44944, + MSG_IN_HEADPOSE_ABSOLUTE = 44945, + + // Messages containing tracking information + // These are sent form faceshift to the client application + MSG_OUT_TRACKING_STATE = 33433, + MSG_OUT_MARKER_NAMES = 33533, + MSG_OUT_BLENDSHAPE_NAMES = 33633, + MSG_OUT_RIG = 33733 + }; + + virtual MessageType id() const = 0; +}; +typedef std::tr1::shared_ptr fsMsgPtr; + + +/************* + * Inbound + ***********/ +class fsMsgStartCapturing : public fsMsg { +public: + virtual ~fsMsgStartCapturing() {} + virtual MessageType id() const { return MSG_IN_START_TRACKING; } +}; +class fsMsgStopCapturing : public fsMsg { +public: + virtual ~fsMsgStopCapturing() {} + virtual MessageType id() const { return MSG_IN_STOP_TRACKING; } +}; +class fsMsgCalibrateNeutral : public fsMsg { +public: + virtual ~fsMsgCalibrateNeutral() {} + virtual MessageType id() const { return MSG_IN_CALIBRATE_NEUTRAL; } +}; +class fsMsgSendMarkerNames : public fsMsg { +public: + virtual ~fsMsgSendMarkerNames() {} + virtual MessageType id() const { return MSG_IN_SEND_MARKER_NAMES; } +}; +class fsMsgSendBlendshapeNames : public fsMsg { +public: + virtual ~fsMsgSendBlendshapeNames() {} + virtual MessageType id() const { return MSG_IN_SEND_BLENDSHAPE_NAMES; } +}; +class fsMsgSendRig : public fsMsg { +public: + virtual ~fsMsgSendRig() {} + virtual MessageType id() const { return MSG_IN_SEND_RIG; } +}; +class fsMsgHeadPoseRelative : public fsMsg { +public: + virtual ~fsMsgHeadPoseRelative() {} + virtual MessageType id() const { return MSG_IN_HEADPOSE_RELATIVE; } +}; +class fsMsgHeadPoseAbsolute : public fsMsg { +public: + virtual ~fsMsgHeadPoseAbsolute() {} + virtual MessageType id() const { return MSG_IN_HEADPOSE_ABSOLUTE; } +}; + +/************* + * Outbound + ***********/ +class fsMsgTrackingState : public fsMsg { +public: + virtual ~fsMsgTrackingState() {} + + /* */ fsTrackingData & tracking_data() /* */ { return m_tracking_data; } + const fsTrackingData & tracking_data() const { return m_tracking_data; } + + virtual MessageType id() const { return MSG_OUT_TRACKING_STATE; } + +private: + fsTrackingData m_tracking_data; +}; +class fsMsgMarkerNames : public fsMsg { +public: + virtual ~fsMsgMarkerNames() {} + + /* */ std::vector & marker_names() /* */ { return m_marker_names; } + const std::vector & marker_names() const { return m_marker_names; } + + virtual MessageType id() const { return MSG_OUT_MARKER_NAMES; } +private: + std::vector m_marker_names; +}; +class fsMsgBlendshapeNames : public fsMsg { +public: + virtual ~fsMsgBlendshapeNames() {} + + /* */ std::vector & blendshape_names() /* */ { return m_blendshape_names; } + const std::vector & blendshape_names() const { return m_blendshape_names; } + + virtual MessageType id() const { return MSG_OUT_BLENDSHAPE_NAMES; } +private: + std::vector m_blendshape_names; +}; +class fsMsgRig : public fsMsg { +public: + virtual ~fsMsgRig() {} + + virtual MessageType id() const { return MSG_OUT_RIG; } + + /* */ fsMeshData & mesh() /* */ { return m_mesh; } + const fsMeshData & mesh() const { return m_mesh; } + + /* */ std::vector & blendshape_names() /* */ { return m_blendshape_names; } + const std::vector & blendshape_names() const { return m_blendshape_names; } + + /* */ std::vector & blendshapes() /* */ { return m_blendshapes; } + const std::vector & blendshapes() const { return m_blendshapes; } + +private: + //! neutral mesh + fsMeshData m_mesh; + //! blendshape names + std::vector m_blendshape_names; + //! blendshapes + std::vector m_blendshapes; +}; +class fsMsgSignal : public fsMsg { + MessageType m_id; +public: + explicit fsMsgSignal(MessageType id) : m_id(id) {} + virtual ~fsMsgSignal() {} + virtual MessageType id() const { return m_id; } +}; + +/** + * Class to parse a faceshift data stream, and to create message to write into such a stream + * + * This needs to be connected with your networking methods by calling + * + * void received(int, const char *); + * + * whenever new data is available. After adding received data to the parser you can parse faceshift messages using the + * + * std::tr1::shared_ptr get_message(); + * + * to get the next message, if a full block of data has been received. This should be iterated until no more messages are in the buffer. + * + * You can also use this to encode messages to send back to faceshift. This works by calling the + * + * void encode_message(std::string &msg_out, const fsMsg &msg); + * + * methods (actually the specializations existing for each of our message types). This will encode the message into a + * binary string in msg_out. You then only need to push the resulting string over the network to faceshift. + * + * This class does not handle differences in endianness or other strange things that can happen when pushing data over the network. + * Should you have to adapt this to such a system, then it should be possible to do this by changing only the write_... and read_... + * functions in the accompanying cpp file, but so far there was no need for it. + **/ +class fsBinaryStream { +public: + fsBinaryStream(); + + /** + * Use to push data into the parser. Typically called inside of your network receiver routine + **/ + void received(long int, const char *); + /** + * After pushing data, you can try to extract messages from the stream. Process messages until a null pointer is returned. + **/ + fsMsgPtr get_message(); + /** + * When an invalid message is received, the valid field is set to false. No attempt is made to recover from the problem, you will have to disconnect. + **/ + bool valid() const { return m_valid; } + void clear() { m_start = 0; m_end = 0; m_valid=true; } + + // Inbound + static void encode_message(std::string &msg_out, const fsMsgTrackingState &msg); + static void encode_message(std::string &msg_out, const fsMsgStartCapturing &msg); + static void encode_message(std::string &msg_out, const fsMsgStopCapturing &msg); + static void encode_message(std::string &msg_out, const fsMsgCalibrateNeutral &msg); + static void encode_message(std::string &msg_out, const fsMsgSendMarkerNames &msg); + static void encode_message(std::string &msg_out, const fsMsgSendBlendshapeNames &msg); + static void encode_message(std::string &msg_out, const fsMsgSendRig &msg); + static void encode_message(std::string &msg_out, const fsMsgHeadPoseRelative &msg); + static void encode_message(std::string &msg_out, const fsMsgHeadPoseAbsolute &msg); + + // Outbound + static void encode_message(std::string &msg_out, const fsTrackingData &msg); + static void encode_message(std::string &msg_out, const fsMsgMarkerNames &msg); + static void encode_message(std::string &msg_out, const fsMsgBlendshapeNames &msg); + static void encode_message(std::string &msg_out, const fsMsgRig &msg); + static void encode_message(std::string &msg_out, const fsMsgSignal &msg); // Generic Signal + +private: + std::string m_buffer; + long int m_start; + long int m_end; + bool m_valid; + +}; + +} + + +#endif // FSBINARYSTREAM_H diff --git a/interface/external/faceshift/lib/UNIX/libfaceshift.a b/interface/external/faceshift/lib/UNIX/libfaceshift.a new file mode 100644 index 0000000000000000000000000000000000000000..4d53de7ab5602a22650db8fb82253c60028eb323 GIT binary patch literal 523750 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 NKk +#include +#include + +#define FSNETWORKVERSION 1 + +#ifdef FS_INTERNAL +#include +#else +#define LOG_RELEASE_ERROR(...) { printf("ERROR: %20s:%6d", __FILE__, __LINE__); printf(__VA_ARGS__); } +#define LOG_RELEASE_WARNING(...) { printf("WARNING: %20s:%6d", __FILE__, __LINE__); printf(__VA_ARGS__); } +#define LOG_RELEASE_INFO(...) { printf("INFO: %20s:%6d", __FILE__, __LINE__); printf(__VA_ARGS__); } +#endif + + +namespace fs { + +// Ids of the submessages for the tracking state +enum BlockId { + BLOCKID_INFO = 101, + BLOCKID_POSE = 102, + BLOCKID_BLENDSHAPES = 103, + BLOCKID_EYES = 104, + BLOCKID_MARKERS = 105 +}; + + +typedef long int Size; + +struct BlockHeader { + uint16_t id; + uint16_t version; + uint32_t size; + BlockHeader(uint16_t _id=0, + uint32_t _size=0, + uint16_t _version=FSNETWORKVERSION + ) : id(_id), version(_version), size(_size) {} +}; + +// Interprets the data at the position start in buffer as a T and increments start by sizeof(T) +// It should be sufficient to change/overload this function when you are on a wierd endian system +template bool read_pod(T &value, const std::string &buffer, Size &start) { + if(start+sizeof(T) > buffer.size()) return false; + value = *(const T*)(&buffer[start]); + start += sizeof(T); + return true; +} +bool read_pod(std::string &value, const std::string &buffer, Size &start) { + uint16_t len = 0; + if(!read_pod(len, buffer, start)) return false; + if(start+len>Size(buffer.size())) return false; // check whether we have enough data available + value.resize(len); + memcpy(&(value[0]), &buffer[start], len); + start+=len; + return true; +} +template bool read_vector(std::vector & values, const std::string & buffer, Size & start) { + uint32_t len = 0; + if( !read_pod(len, buffer, start)) return false; + if( start+len*sizeof(T) > buffer.size() ) return false; + values.resize(len); + for(uint32_t i = 0; i < len; ++i) { + read_pod(values[i],buffer,start); + } + return true; +} +template bool read_small_vector(std::vector & values, const std::string & buffer, Size & start) { + uint16_t len = 0; + if( !read_pod(len, buffer, start)) return false; + if( start+len*sizeof(T) > buffer.size() ) return false; + values.resize(len); + bool success = true; + for(uint16_t i = 0; i < len; ++i) { + success &= read_pod(values[i],buffer,start); + } + return success; +} + +// Adds the bitpattern of the data to the end of the buffer. +// It should be sufficient to change/overload this function when you are on a wierd endian system +template +void write_pod(std::string &buffer, const T &value) { + Size start = buffer.size(); + buffer.resize(start + sizeof(T)); + *(T*)(&buffer[start]) = value; + start += sizeof(T); +} +// special write function for strings +void write_pod(std::string &buffer, const std::string &value) { + uint16_t len = uint16_t(value.size()); write_pod(buffer, len); + buffer.append(value); +} +template void write_vector(std::string & buffer, const std::vector & values) { + uint32_t len = values.size(); + write_pod(buffer,len); + for(uint32_t i = 0; i < len; ++i) + write_pod(buffer,values[i]); +} +template void write_small_vector(std::string & buffer, const std::vector & values) { + uint16_t len = values.size(); + write_pod(buffer,len); + for(uint16_t i = 0; i < len; ++i) + write_pod(buffer,values[i]); +} +void update_msg_size(std::string &buffer, Size start) { + *(uint32_t*)(&buffer[start+4]) = buffer.size() - sizeof(BlockHeader) - start; +} +void update_msg_size(std::string &buffer) { + *(uint32_t*)(&buffer[4]) = buffer.size() - sizeof(BlockHeader); +} + +static void skipHeader( Size &start) { + start += sizeof(BlockHeader); +} + +//! returns whether @param data contains enough data to read the block header +static bool headerAvailable(BlockHeader &header, const std::string &buffer, Size &start, const Size &end) { + if (end-start >= Size(sizeof(BlockHeader))) { + header = *(BlockHeader*)(&buffer[start]); + return true; + } else { + return false; + } +} + +//! returns whether @param data contains data for a full block +static bool blockAvailable(const std::string &buffer, Size &start, const Size &end) { + BlockHeader header; + if (!headerAvailable(header, buffer, start, end)) return false; + return end-start >= Size(sizeof(header)+header.size); +} + +fsBinaryStream::fsBinaryStream() : m_buffer(), m_start(0), m_end(0), m_valid(true) { m_buffer.resize(64*1024); } // Use a 64kb buffer by default + +void fsBinaryStream::received(long int sz, const char *data) { + + long int new_end = m_end + sz; + if (new_end > Size(m_buffer.size()) && m_start>0) { + // If newly received block is too large to fit into the buffer, but we already have processed data from the start of the buffer, then + // move memory to the front of the buffer + // The buffer only grows, such that it is always large enough to contain the largest message seen so far. + if (m_end>m_start) memmove(&m_buffer[0], &m_buffer[0] + m_start, m_end - m_start); + m_end = m_end - m_start; + m_start = 0; + new_end = m_end + sz; + } + + if (new_end > Size(m_buffer.size())) m_buffer.resize(1.5*new_end); + + memcpy(&m_buffer[0] + m_end, data, sz); + m_end += sz; + +} + +static bool decodeInfo(fsTrackingData & _trackingData, const std::string &buffer, Size &start) { + bool success = true; + success &= read_pod(_trackingData.m_timestamp, buffer, start); + unsigned char tracking_successfull = 0; + success &= read_pod( tracking_successfull, buffer, start ); + _trackingData.m_trackingSuccessful = bool(tracking_successfull); + return success; +} + +static bool decodePose(fsTrackingData & _trackingData, const std::string &buffer, Size &start) { + bool success = true; + success &= read_pod(_trackingData.m_headRotation.x, buffer, start); + success &= read_pod(_trackingData.m_headRotation.y, buffer, start); + success &= read_pod(_trackingData.m_headRotation.z, buffer, start); + success &= read_pod(_trackingData.m_headRotation.w, buffer, start); + success &= read_pod(_trackingData.m_headTranslation.x, buffer, start); + success &= read_pod(_trackingData.m_headTranslation.y, buffer, start); + success &= read_pod(_trackingData.m_headTranslation.z, buffer, start); + return success; +} + +static bool decodeBlendshapes(fsTrackingData & _trackingData, const std::string &buffer, Size &start) { + return read_vector(_trackingData.m_coeffs, buffer, start); +} + +static bool decodeEyeGaze(fsTrackingData & _trackingData, const std::string &buffer, Size &start) { + bool success = true; + success &= read_pod(_trackingData.m_eyeGazeLeftPitch , buffer, start); + success &= read_pod(_trackingData.m_eyeGazeLeftYaw , buffer, start); + success &= read_pod(_trackingData.m_eyeGazeRightPitch, buffer, start); + success &= read_pod(_trackingData.m_eyeGazeRightYaw , buffer, start); + return success; +} + +static bool decodeMarkers(fsTrackingData & _trackingData, const std::string &buffer, Size &start) { + return read_small_vector( _trackingData.m_markers, buffer, start ); +} + +static bool decodeMarkerNames(fsMsgMarkerNames &_msg, const std::string &buffer, Size &start) { + return read_small_vector(_msg.marker_names(), buffer, start); +} +static bool decodeBlendshapeNames(fsMsgBlendshapeNames &_msg, const std::string &buffer, Size &start) { + return read_small_vector(_msg.blendshape_names(), buffer, start); +} +static bool decodeRig(fsMsgRig &_msg, const std::string &buffer, Size &start) { + bool success = true; + success &= read_vector(_msg.mesh().m_quads,buffer,start); // read quads + success &= read_vector(_msg.mesh().m_tris,buffer,start); // read triangles + success &= read_vector(_msg.mesh().m_vertex_data.m_vertices,buffer,start);// read neutral vertices + success &= read_small_vector(_msg.blendshape_names(),buffer,start); // read names + uint16_t bsize = 0; + success &= read_pod(bsize,buffer,start); + _msg.blendshapes().resize(bsize); + for(uint16_t i = 0;i < bsize; i++) + success &= read_vector(_msg.blendshapes()[i].m_vertices,buffer,start); // read blendshapes + return success; +} + +bool is_valid_msg(int id) { + switch(id) { + case fsMsg::MSG_IN_START_TRACKING : + case fsMsg::MSG_IN_STOP_TRACKING : + case fsMsg::MSG_IN_CALIBRATE_NEUTRAL : + case fsMsg::MSG_IN_SEND_MARKER_NAMES : + case fsMsg::MSG_IN_SEND_BLENDSHAPE_NAMES: + case fsMsg::MSG_IN_SEND_RIG : + case fsMsg::MSG_IN_HEADPOSE_RELATIVE : + case fsMsg::MSG_IN_HEADPOSE_ABSOLUTE : + case fsMsg::MSG_OUT_TRACKING_STATE : + case fsMsg::MSG_OUT_MARKER_NAMES : + case fsMsg::MSG_OUT_BLENDSHAPE_NAMES : + case fsMsg::MSG_OUT_RIG : return true; + default: + LOG_RELEASE_ERROR("Invalid Message ID %d", id); + return false; + } +} + +fsMsgPtr fsBinaryStream::get_message() { + BlockHeader super_block; + if( !headerAvailable(super_block, m_buffer, m_start, m_end) ) return fsMsgPtr(); + if (!is_valid_msg(super_block.id)) { LOG_RELEASE_ERROR("Invalid superblock id"); m_valid = false; return fsMsgPtr(); } + if( !blockAvailable( m_buffer, m_start, m_end) ) return fsMsgPtr(); + skipHeader(m_start); + long super_block_data_start = m_start; + switch (super_block.id) { + case fsMsg::MSG_IN_START_TRACKING: { + if (super_block.size > 0) { LOG_RELEASE_ERROR("Expected Size to be 0, not %d", super_block.size); m_valid = false; return fsMsgPtr(); } + return fsMsgPtr(new fsMsgStartCapturing() ); + }; break; + case fsMsg::MSG_IN_STOP_TRACKING: { + if (super_block.size > 0) { LOG_RELEASE_ERROR("Expected Size to be 0, not %d", super_block.size); m_valid = false; return fsMsgPtr(); } + return fsMsgPtr(new fsMsgStopCapturing() ); + }; break; + case fsMsg::MSG_IN_CALIBRATE_NEUTRAL: { + if (super_block.size > 0) { LOG_RELEASE_ERROR("Expected Size to be 0, not %d", super_block.size); m_valid = false; return fsMsgPtr(); } + return fsMsgPtr(new fsMsgCalibrateNeutral() ); + }; break; + case fsMsg::MSG_IN_SEND_MARKER_NAMES: { + if (super_block.size > 0) { LOG_RELEASE_ERROR("Expected Size to be 0, not %d", super_block.size); m_valid = false; return fsMsgPtr(); } + return fsMsgPtr(new fsMsgSendMarkerNames() ); + }; break; + case fsMsg::MSG_IN_SEND_BLENDSHAPE_NAMES: { + if (super_block.size > 0) { LOG_RELEASE_ERROR("Expected Size to be 0, not %d", super_block.size); m_valid = false; return fsMsgPtr(); } + return fsMsgPtr(new fsMsgSendBlendshapeNames() ); + }; break; + case fsMsg::MSG_IN_SEND_RIG: { + if (super_block.size > 0) { LOG_RELEASE_ERROR("Expected Size to be 0, not %d", super_block.size); m_valid = false; return fsMsgPtr(); } + return fsMsgPtr(new fsMsgSendRig() ); + }; break; + case fsMsg::MSG_IN_HEADPOSE_RELATIVE: { + if (super_block.size > 0) { LOG_RELEASE_ERROR("Expected Size to be 0, not %d", super_block.size); m_valid = false; return fsMsgPtr(); } + return fsMsgPtr(new fsMsgHeadPoseRelative() ); + }; break; + case fsMsg::MSG_IN_HEADPOSE_ABSOLUTE: { + if (super_block.size > 0) { LOG_RELEASE_ERROR("Expected Size to be 0, not %d", super_block.size); m_valid = false; return fsMsgPtr(); } + return fsMsgPtr(new fsMsgHeadPoseAbsolute() ); + }; break; + case fsMsg::MSG_OUT_MARKER_NAMES: { + std::tr1::shared_ptr< fsMsgMarkerNames > msg(new fsMsgMarkerNames()); + if( !decodeMarkerNames(*msg, m_buffer, m_start )) { LOG_RELEASE_ERROR("Could not decode marker names"); m_valid = false; return fsMsgPtr(); } + uint64_t actual_size = m_start-super_block_data_start; + if( actual_size != super_block.size ) { LOG_RELEASE_ERROR("Block was promised to be of size %d, not %d", super_block.size, actual_size); m_valid = false; return fsMsgPtr(); } + return msg; + }; break; + case fsMsg::MSG_OUT_BLENDSHAPE_NAMES: { + std::tr1::shared_ptr< fsMsgBlendshapeNames > msg(new fsMsgBlendshapeNames() ); + if( !decodeBlendshapeNames(*msg, m_buffer, m_start) ) { LOG_RELEASE_ERROR("Could not decode blendshape names"); m_valid = false; return fsMsgPtr(); } + uint64_t actual_size = m_start-super_block_data_start; + if( actual_size != super_block.size ) { LOG_RELEASE_ERROR("Block was promised to be of size %d, not %d", super_block.size, actual_size); m_valid = false; return fsMsgPtr(); } + return msg; + }; break; + case fsMsg::MSG_OUT_TRACKING_STATE: { + BlockHeader sub_block; + uint16_t num_blocks = 0; + if( !read_pod(num_blocks, m_buffer, m_start) ) { LOG_RELEASE_ERROR("Could not read num_blocks"); m_valid = false; return fsMsgPtr(); } + std::tr1::shared_ptr msg = std::tr1::shared_ptr(new fsMsgTrackingState()); + for(int i = 0; i < num_blocks; i++) { + if( !headerAvailable(sub_block, m_buffer, m_start, m_end) ) { LOG_RELEASE_ERROR("could not read sub-header %d", i); m_valid = false; return fsMsgPtr(); } + if( !blockAvailable( m_buffer, m_start, m_end) ) { LOG_RELEASE_ERROR("could not read sub-block %d", i); m_valid = false; return fsMsgPtr(); } + skipHeader(m_start); + long sub_block_data_start = m_start; + bool success = true; + switch(sub_block.id) { + case BLOCKID_INFO: success &= decodeInfo( msg->tracking_data(), m_buffer, m_start); break; + case BLOCKID_POSE: success &= decodePose( msg->tracking_data(), m_buffer, m_start); break; + case BLOCKID_BLENDSHAPES: success &= decodeBlendshapes(msg->tracking_data(), m_buffer, m_start); break; + case BLOCKID_EYES: success &= decodeEyeGaze( msg->tracking_data(), m_buffer, m_start); break; + case BLOCKID_MARKERS: success &= decodeMarkers( msg->tracking_data(), m_buffer, m_start); break; + default: + LOG_RELEASE_ERROR("Unexpected subblock id %d", sub_block.id); + m_valid = false; return msg; + break; + } + if(!success) { + LOG_RELEASE_ERROR("Could not decode subblock with id %d", sub_block.id); + m_valid = false; return fsMsgPtr(); + } + uint64_t actual_size = m_start-sub_block_data_start; + if( actual_size != sub_block.size ) { + LOG_RELEASE_ERROR("Unexpected number of bytes consumed %d instead of %d for subblock %d id:%d", actual_size, sub_block.size, i, sub_block.id); + m_valid = false; return fsMsgPtr(); + } + } + uint64_t actual_size = m_start-super_block_data_start; + if( actual_size != super_block.size ) { + LOG_RELEASE_ERROR("Unexpected number of bytes consumed %d instead of %d", actual_size, super_block.size); + m_valid = false; return fsMsgPtr(); + } + return msg; + }; break; + case fsMsg::MSG_OUT_RIG: { + std::tr1::shared_ptr< fsMsgRig > msg(new fsMsgRig() ); + if( !decodeRig(*msg, m_buffer, m_start) ) { LOG_RELEASE_ERROR("Could not decode rig"); m_valid = false; return fsMsgPtr(); } + if( m_start-super_block_data_start != super_block.size ) { LOG_RELEASE_ERROR("Could not decode rig unexpected size"); m_valid = false; return fsMsgPtr(); } + return msg; + }; break; + default: { + LOG_RELEASE_ERROR("Unexpected superblock id %d", super_block.id); + m_valid = false; return fsMsgPtr(); + }; break; + } + return fsMsgPtr(); +} + +static void encodeInfo(std::string &buffer, const fsTrackingData & _trackingData) { + BlockHeader header(BLOCKID_INFO, sizeof(double) + 1); + write_pod(buffer, header); + + write_pod(buffer, _trackingData.m_timestamp); + unsigned char tracking_successfull = _trackingData.m_trackingSuccessful; + write_pod( buffer, tracking_successfull ); +} + +static void encodePose(std::string &buffer, const fsTrackingData & _trackingData) { + BlockHeader header(BLOCKID_POSE, sizeof(float)*7); + write_pod(buffer, header); + + write_pod(buffer, _trackingData.m_headRotation.x); + write_pod(buffer, _trackingData.m_headRotation.y); + write_pod(buffer, _trackingData.m_headRotation.z); + write_pod(buffer, _trackingData.m_headRotation.w); + write_pod(buffer, _trackingData.m_headTranslation.x); + write_pod(buffer, _trackingData.m_headTranslation.y); + write_pod(buffer, _trackingData.m_headTranslation.z); +} + +static void encodeBlendshapes(std::string &buffer, const fsTrackingData & _trackingData) { + uint32_t num_parameters = _trackingData.m_coeffs.size(); + BlockHeader header(BLOCKID_BLENDSHAPES, sizeof(uint32_t) + sizeof(float)*num_parameters); + write_pod(buffer, header); + write_pod(buffer, num_parameters); + for(uint32_t i = 0; i < num_parameters; i++) + write_pod(buffer, _trackingData.m_coeffs[i]); +} + +static void encodeEyeGaze(std::string &buffer, const fsTrackingData & _trackingData) { + BlockHeader header(BLOCKID_EYES, sizeof(float)*4); + write_pod(buffer, header); + write_pod(buffer, _trackingData.m_eyeGazeLeftPitch ); + write_pod(buffer, _trackingData.m_eyeGazeLeftYaw ); + write_pod(buffer, _trackingData.m_eyeGazeRightPitch); + write_pod(buffer, _trackingData.m_eyeGazeRightYaw ); +} + +static void encodeMarkers(std::string &buffer, const fsTrackingData & _trackingData) { + uint16_t numMarkers = _trackingData.m_markers.size(); + BlockHeader header(BLOCKID_MARKERS, sizeof(uint16_t) + sizeof(float)*3*numMarkers); + write_pod(buffer, header); + write_pod(buffer, numMarkers); + for(int i = 0; i < numMarkers; i++) { + write_pod(buffer, _trackingData.m_markers[i].x); + write_pod(buffer, _trackingData.m_markers[i].y); + write_pod(buffer, _trackingData.m_markers[i].z); + } +} + +// Inbound +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgTrackingState &msg) { + encode_message(msg_out, msg.tracking_data()); +} + +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgStartCapturing &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgStopCapturing &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgCalibrateNeutral &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgSendMarkerNames &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgSendBlendshapeNames &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgSendRig &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgHeadPoseRelative &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgHeadPoseAbsolute &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} + +// Outbound +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgSignal &msg) { + BlockHeader header(msg.id()); + write_pod(msg_out, header); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsTrackingData &tracking_data) { + Size start = msg_out.size(); + + BlockHeader header(fsMsg::MSG_OUT_TRACKING_STATE); + write_pod(msg_out, header); + + uint16_t N_blocks = 5; + write_pod(msg_out, N_blocks); + encodeInfo( msg_out, tracking_data); + encodePose( msg_out, tracking_data); + encodeBlendshapes(msg_out, tracking_data); + encodeEyeGaze( msg_out, tracking_data); + encodeMarkers( msg_out, tracking_data); + + update_msg_size(msg_out, start); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgMarkerNames &msg) { + Size start = msg_out.size(); + + BlockHeader header(msg.id()); + write_pod(msg_out, header); + + write_small_vector(msg_out,msg.marker_names()); + + update_msg_size(msg_out, start); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgBlendshapeNames &msg) { + Size start = msg_out.size(); + + BlockHeader header(msg.id()); + write_pod(msg_out, header); + + write_small_vector(msg_out,msg.blendshape_names()); + + update_msg_size(msg_out, start); +} +void fsBinaryStream::encode_message(std::string &msg_out, const fsMsgRig &msg) { + Size start = msg_out.size(); + + BlockHeader header(msg.id()); + write_pod(msg_out, header); + + write_vector(msg_out, msg.mesh().m_quads); // write quads + write_vector(msg_out, msg.mesh().m_tris);// write triangles + write_vector(msg_out, msg.mesh().m_vertex_data.m_vertices);// write neutral vertices + write_small_vector(msg_out, msg.blendshape_names());// write names + write_pod(msg_out,uint16_t(msg.blendshapes().size())); + for(uint16_t i = 0;i < uint16_t(msg.blendshapes().size()); i++) + write_vector(msg_out, msg.blendshapes()[i].m_vertices); // write blendshapes + + update_msg_size(msg_out, start); +} +}