From 3089c4bbc10e98d18f43e8a70e7a3d0c0eaf0900 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 22 Mar 2013 20:48:17 +0100 Subject: Downcase. PLEASE TURN OFF IGNORING CASE IN GIT CONFIG!!! .git/config: [core] ignorecase = false --- faceAPI/FaceAPI2FSX_vc8.vcproj | 233 ------------------ faceAPI/FaceAPI2FSX_vc9.vcproj | 232 ------------------ faceAPI/build_options.h | 8 - faceAPI/lock.h | 35 --- faceAPI/lockfree.h | 65 ----- faceAPI/main.cpp | 543 ----------------------------------------- faceAPI/mutex.h | 44 ---- faceAPI/stdafx.cpp | 8 - faceAPI/stdafx.h | 21 -- faceAPI/utils.h | 346 -------------------------- 10 files changed, 1535 deletions(-) delete mode 100644 faceAPI/FaceAPI2FSX_vc8.vcproj delete mode 100644 faceAPI/FaceAPI2FSX_vc9.vcproj delete mode 100644 faceAPI/build_options.h delete mode 100644 faceAPI/lock.h delete mode 100644 faceAPI/lockfree.h delete mode 100644 faceAPI/main.cpp delete mode 100644 faceAPI/mutex.h delete mode 100644 faceAPI/stdafx.cpp delete mode 100644 faceAPI/stdafx.h delete mode 100644 faceAPI/utils.h (limited to 'faceAPI') diff --git a/faceAPI/FaceAPI2FSX_vc8.vcproj b/faceAPI/FaceAPI2FSX_vc8.vcproj deleted file mode 100644 index 8e2fc936..00000000 --- a/faceAPI/FaceAPI2FSX_vc8.vcproj +++ /dev/null @@ -1,233 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/faceAPI/FaceAPI2FSX_vc9.vcproj b/faceAPI/FaceAPI2FSX_vc9.vcproj deleted file mode 100644 index 227d872d..00000000 --- a/faceAPI/FaceAPI2FSX_vc9.vcproj +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/faceAPI/build_options.h b/faceAPI/build_options.h deleted file mode 100644 index 6bc6a44c..00000000 --- a/faceAPI/build_options.h +++ /dev/null @@ -1,8 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Build Options -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//controls whether or not FaceAPI should use the callback or poll -#define USE_HEADPOSE_CALLBACK 1 diff --git a/faceAPI/lock.h b/faceAPI/lock.h deleted file mode 100644 index efe38605..00000000 --- a/faceAPI/lock.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef SM_API_TESTAPPCONSOLE_LOCK_H -#define SM_API_TESTAPPCONSOLE_LOCK_H - -#include "mutex.h" - -namespace sm -{ - namespace faceapi - { - namespace samplecode - { - // A very simple scoped-lock class for sample code purposes. - // It is recommended that you use the boost threads library. - class Lock - { - public: - Lock(const Mutex &mutex): _mutex(mutex) - { - _mutex.lock(); - } - ~Lock() - { - _mutex.unlock(); - } - private: - // Noncopyable - Lock(const Lock &); - Lock &operator=(const Lock &); - private: - const Mutex &_mutex; - }; - } - } -} -#endif diff --git a/faceAPI/lockfree.h b/faceAPI/lockfree.h deleted file mode 100644 index ce7d2a64..00000000 --- a/faceAPI/lockfree.h +++ /dev/null @@ -1,65 +0,0 @@ -//lock free queue template class by Herb Sutter -//Dr Dobbs Journal article http://www.drdobbs.com/cpp/210604448;jsessionid=OQGQPSMNL4X4XQE1GHPSKH4ATMY32JVN?pgno=1 - -template class LockFreeQueue -{ -private: - struct Node - { - Node( T val ) : value(val), next(nullptr) { } - T value; - Node* next; - }; - - Node* first; // for producer only - Node* divider, last; // shared - - //not working in VC2008 - //atomic divider, last; // shared - -public: - LockFreeQueue() - { - // add dummy separator - first = divider = last = new Node( T() ); - } - - ~LockFreeQueue() - { - while( first != nullptr ) - { - // release the list - Node* tmp = first; - first = tmp->next; - delete tmp; - } - } - - void Produce( const T& t ) - { - last->next = new Node(t); // add the new item - last = last->next; // publish it - - while( first != divider ) - { - // trim unused nodes - Node* tmp = first; - first = first->next; - delete tmp; - } - } - - bool Consume( T& result ) - { - if( divider != last ) - { - // if queue is nonempty - result = divider->next->value; // copy it back - divider = divider->next; // publish that we took it - return true; // and report success - } - - return false; // else report empty - } -}; - diff --git a/faceAPI/main.cpp b/faceAPI/main.cpp deleted file mode 100644 index 46732cb3..00000000 --- a/faceAPI/main.cpp +++ /dev/null @@ -1,543 +0,0 @@ -/******************************************************************************** -* FaceTrackNoIR This program is a private project of the some enthusiastic * -* gamers from Holland, who don't like to pay much for * -* head-tracking. * -* * -* Copyright (C) 2013 Wim Vriend (Developing) * -* Ron Hendriks (Researching and Testing) * -* * -* Homepage * -* * -* This program is free software; you can redistribute it and/or modify it * -* under the terms of the GNU General Public License as published by the * -* Free Software Foundation; either version 3 of the License, or (at your * -* option) any later version. * -* * -* This program 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. See the GNU General Public License for * -* more details. * -* * -* You should have received a copy of the GNU General Public License along * -* with this program; if not, see . * -*********************************************************************************/ -/* - Modifications (last one on top): - 20130105 - WVR: Set engine state to TERMINATED, when EXIT. - 20110501 - WVR: Added some command to be handled from FaceTrackNoIR (settings dialog). - 20110322 - WVR: Somehow the video-widget of faceAPI version 3.2.6. does not - work with FaceTrackNoIR (Qt issue?!). To be able to use - release 3.2.6 of faceAPI anyway, this console-app is used. - It exchanges data with FaceTrackNoIR via shared-memory... -*/ - -//Precompiled header -#include "stdafx.h" - -//FaceAPI headers -#include -#include "ftnoir_tracker_sm_types.h" -#include "utils.h" - -//local headers -#include "build_options.h" - -//namespaces -using namespace std; -using namespace sm::faceapi::samplecode; - -// -// global variables -// -HANDLE hSMMemMap = NULL; -SMMemMap *pMemData; -HANDLE hSMMutex; -smEngineHeadPoseData new_head_pose; -bool stopCommand = false; -bool ftnoirConnected = false; - -//enums -enum GROUP_ID -{ - GROUP0=0, -}; - -enum EVENT_ID -{ - EVENT_PING=0, - EVENT_INIT, -}; - -enum INPUT_ID -{ - INPUT0=0, -}; - -//function definitions -void updateHeadPose(smEngineHeadPoseData* temp_head_pose); -bool SMCreateMapping(); - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -//FaceAPI function implementations -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void STDCALL receiveLogMessage(void *, const char *buf, int /*buf_len*/) -{ - Lock lock(g_mutex); // serialize logging calls from different threads to avoid garbled output. - //cout << string(buf); -} - -// Callback function for face-data -void STDCALL receiveFaceData(void *, smEngineFaceData face_data, smCameraVideoFrame video_frame) -{ - Lock lock(g_mutex); - - // Get info including data pointer to original image from camera - smImageInfo video_frame_image_info; - THROW_ON_ERROR(smImageGetInfo(video_frame.image_handle, &video_frame_image_info)); // reentrant, so ok - - // video_frame_image_info.plane_addr[*] now point to the image memory planes. - // The memory is only valid until the end of this routine unless you call smImageAddRef(video_frame.image_handle). - // So you can deep copy the image data here, or use smImageAddRef() and just copy the pointer. - // If you use smImageAddRef() you are responsible for calling smImageDestroy() to avoid a memory leak later. - - // In this callback you will typically want to copy the smEngineFaceData data into your own data-structure. - // Since the smEngineFaceData contains multiple pod types copying it is not atomic and - // a mutex is required to avoid the race-condition with any thread simultaneously - // reading from your data-structure. - // Such a race condition will not crash your code but will create weird noise in the tracking data. - - if (g_do_face_data_printing) - { - //cout << video_frame << " " << face_data; - - // Save any face texture to a PNG file - if (face_data.texture) - { - // Create a unique filename - std::stringstream filename; - filename << "face_" << video_frame.frame_num << ".png"; - // Try saving to a file - if (saveToPNGFile(filename.str(), face_data.texture->image_info) == SM_API_OK) - { - cout << "Saved face-texture to " << filename.str() << std::endl; - } - else - { - cout << "Error saving face-texture to " << filename.str() << std::endl; - } - } - } -} - -// Callback function for head-pose -void STDCALL receiveHeadPose(void *,smEngineHeadPoseData head_pose, smCameraVideoFrame video_frame) -{ - Lock lock(g_mutex); - - // Get info including data pointer to original image from camera - smImageInfo video_frame_image_info; - THROW_ON_ERROR(smImageGetInfo(video_frame.image_handle, &video_frame_image_info)); // reentrant, so ok - - // video_frame_image_info.plane_addr[*] now point to the image memory planes. - // The memory is only valid until the end of this routine unless you call smImageAddRef(video_frame.image_handle). - // So you can deep copy the image data here, or use smImageAddRef() and just copy the pointer. - // If you use smImageAddRef() you are responsible for calling smImageDestroy() to avoid a memory leak later. - - // In this callback you will typically want to copy the smEngineFaceData data into your own data-structure. - // Since the smEngineFaceData contains multiple pod types copying it is not atomic and - // a mutex is required to avoid the race-condition with any thread simultaneously - // reading from your data-structure. - // Such a race condition will not crash your code but will create weird noise in the tracking data. - - if (g_do_head_pose_printing) - { - //cout << video_frame << " " << head_pose << std::endl; - } - - //make a copy of the new head pose data and send it to simconnect - //when we get a simmconnect frame event the new offset will be applied to the camera - updateHeadPose(&head_pose); -} - -// Create the first available camera detected on the system, and return its handle -smCameraHandle createFirstCamera() -{ - // Detect cameras - smCameraInfoList info_list; - THROW_ON_ERROR(smCameraCreateInfoList(&info_list)); - - if (info_list.num_cameras == 0) - { - throw runtime_error("No cameras were detected"); - } - else - { - cout << "The followings cameras were detected: " << endl; - for (int i=0; ihandle,TRUE)); - THROW_ON_ERROR(smHTV2SetHeadPoseFilterLevel(engine_handle, pMemData->initial_filter_level)); - pMemData->handshake = 0; - } - else { - THROW_ON_ERROR(smVideoDisplayCreate(engine_handle,&video_display_handle,0,TRUE)); - } - - // Setup the VideoDisplay - THROW_ON_ERROR(smVideoDisplaySetFlags(video_display_handle,g_overlay_flags)); - - // Get the handle to the window and change the title to "Hello World" - smWindowHandle win_handle = 0; - THROW_ON_ERROR(smVideoDisplayGetWindowHandle(video_display_handle,&win_handle)); - SetWindowText(win_handle, _T("faceAPI Video-widget")); - MoveWindow(win_handle, 0, 0, 250, 180, true); - - // Loop on the keyboard - while (processKeyPress(engine_handle, video_display_handle) && !stopCommand) - { - // Read and print the current head-pose (if not using the callback mechanism) - #if (USE_HEADPOSE_CALLBACK==0) - #pragma message("Polling Headpose Manually") - if (engine_licensed) - { - smEngineHeadPoseData head_pose; - Lock lock(g_mutex); - - THROW_ON_ERROR(smHTCurrentHeadPose(engine_handle,&head_pose)); - if (g_do_head_pose_printing) - { - std::cout << head_pose << std::endl; - } - - } - #endif - - // NOTE: If you have a windows event loop in your program you - // will not need to call smAPIProcessEvents(). This manually redraws the video window. - THROW_ON_ERROR(smAPIProcessEvents()); - - // Prevent CPU overload in our simple loop. - const int frame_period_ms = 10; - Sleep(frame_period_ms); - - // - // Process the command sent by FaceTrackNoIR. - // - if (ftnoirConnected && (pMemData != 0)) { - - sprintf_s(msg, "Command: %d, \n", pMemData->command, pMemData->par_val_int); - OutputDebugStringA(msg); - std::cout << msg; - - // - // - // Determine the trackers' state and send it to FaceTrackNoIR. - // - THROW_ON_ERROR(smEngineGetState(engine_handle, &state)); - pMemData->state = state; - pMemData->handshake += 1; - - // - // Check if FaceTrackNoIR is still 'in contact'. - // FaceTrackNoIR will reset the handshake, every time in writes data. - // If the value rises too high, this exe will stop itself... - // - if ( pMemData->handshake > 200) { - stopCommand = TRUE; - } - - // - // Check if a command was issued and do something with it! - // - switch (pMemData->command) { - case FT_SM_START: - - // - // Only execute Start, if the engine is not yet tracking. - // - if (state != SM_API_ENGINE_STATE_HT_TRACKING) { - THROW_ON_ERROR(smEngineStart(engine_handle)); // Start tracking - } - pMemData->command = 0; // Reset - break; - - case FT_SM_STOP: - THROW_ON_ERROR(smEngineStop(engine_handle)); // Stop tracking - pMemData->command = 0; // Reset - break; - - case FT_SM_EXIT: - THROW_ON_ERROR(smEngineStop(engine_handle)); // Stop tracking - stopCommand = TRUE; - pMemData->command = 0; // Reset - pMemData->state = SM_API_ENGINE_STATE_TERMINATED; // One last update, before quitting... - break; - - case FT_SM_SET_PAR_FILTER: - THROW_ON_ERROR(smHTV2SetHeadPoseFilterLevel(engine_handle, pMemData->par_val_int)); - pMemData->command = 0; // Reset - break; - - case FT_SM_SHOW_CAM: - THROW_ON_ERROR(smEngineShowCameraControlPanel(engine_handle)); - pMemData->command = 0; // Reset - break; - - default: - pMemData->command = 0; // Reset - // should never be reached - break; - } - } - } // While(1) - - // Destroy engine - THROW_ON_ERROR(smEngineDestroy(&engine_handle)); - // Destroy video display - THROW_ON_ERROR(smVideoDisplayDestroy(&video_display_handle)); - - if (ftnoirConnected) { - if ( pMemData != NULL ) { - UnmapViewOfFile ( pMemData ); - } - - if (hSMMutex != 0) { - CloseHandle( hSMMutex ); - } - hSMMutex = 0; - - if (hSMMemMap != 0) { - CloseHandle( hSMMemMap ); - } - hSMMemMap = 0; - } - -} // run() - -// Application entry point -int _tmain(int /*argc*/, _TCHAR** /*argv*/) -{ - OutputDebugString(_T("_tmain() says: Starting Function\n")); - - try - { - if (SMCreateMapping()) { - run(); - } - } - catch (exception &e) - { - cerr << e.what() << endl; - } - - return smAPIQuit(); -} - -// -// This is called exactly once for each FaceAPI callback and must be within an exclusive lock -// -void updateHeadPose(smEngineHeadPoseData* temp_head_pose) -{ - // - // Check if the pointer is OK and wait for the Mutex. - // - if ( (pMemData != NULL) && (WaitForSingleObject(hSMMutex, 100) == WAIT_OBJECT_0) ) { - - // - // Copy the Raw measurements directly to the client. - // - if (temp_head_pose->confidence > 0.0f) - { - memcpy(&pMemData->data.new_pose,temp_head_pose,sizeof(smEngineHeadPoseData)); - } - ReleaseMutex(hSMMutex); - } -}; - -// -// Create a memory-mapping to the faceAPI data. -// It contains the tracking data, a command-code from FaceTrackNoIR -// -// -bool SMCreateMapping() -{ - OutputDebugString(_T("FTCreateMapping says: Starting Function\n")); - - // - // A FileMapping is used to create 'shared memory' between the faceAPI and FaceTrackNoIR. - // FaceTrackNoIR creates the mapping, this program only opens it. - // If it's not there: the program was apparently started by the user instead of FaceTrackNoIR... - // - // Open an existing FileMapping, Read/Write access - // - hSMMemMap = OpenFileMappingA( FILE_MAP_ALL_ACCESS , false , (LPCSTR) SM_MM_DATA ); - if ( ( hSMMemMap != 0 ) ) { - ftnoirConnected = true; - OutputDebugString(_T("FTCreateMapping says: FileMapping opened successfully...\n")); - pMemData = (SMMemMap *) MapViewOfFile(hSMMemMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TFaceData)); - if (pMemData != NULL) { - OutputDebugString(_T("FTCreateMapping says: MapViewOfFile OK.\n")); - pMemData->state = 0; - } - hSMMutex = CreateMutexA(NULL, false, SM_MUTEX); - } - else { - OutputDebugString(_T("FTCreateMapping says: FileMapping not opened...FaceTrackNoIR not connected!\n")); - ftnoirConnected = false; - pMemData = 0; - } - - return true; -} diff --git a/faceAPI/mutex.h b/faceAPI/mutex.h deleted file mode 100644 index 11aabafc..00000000 --- a/faceAPI/mutex.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SM_API_TESTAPPCONSOLE_MUTEX_H -#define SM_API_TESTAPPCONSOLE_MUTEX_H - -namespace sm -{ - namespace faceapi - { - namespace samplecode - { - // A very simple mutex class for sample code purposes. - // It is recommended that you use the boost threads library. - class Mutex - { - public: - Mutex() - { - if (!InitializeCriticalSectionAndSpinCount(&_cs,0x80000400)) - { - throw std::runtime_error("Failed to initialize Mutex"); - } - } - ~Mutex() - { - DeleteCriticalSection(&_cs); - } - void lock() const - { - EnterCriticalSection(&_cs); - } - void unlock() const - { - LeaveCriticalSection(&_cs); - } - private: - // Noncopyable - Mutex(const Mutex &); - Mutex &operator=(const Mutex &); - private: - mutable CRITICAL_SECTION _cs; - }; - } - } -} -#endif diff --git a/faceAPI/stdafx.cpp b/faceAPI/stdafx.cpp deleted file mode 100644 index b4263f59..00000000 --- a/faceAPI/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// TestAppConsole.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/faceAPI/stdafx.h b/faceAPI/stdafx.h deleted file mode 100644 index d97c9353..00000000 --- a/faceAPI/stdafx.h +++ /dev/null @@ -1,21 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#include -#include - -// TODO: reference additional headers your program requires here -#include -#include -#include -#include -#include -#include diff --git a/faceAPI/utils.h b/faceAPI/utils.h deleted file mode 100644 index 1fdb35b5..00000000 --- a/faceAPI/utils.h +++ /dev/null @@ -1,346 +0,0 @@ -#ifndef SM_API_TESTAPPCONSOLE_UTILS_H -#define SM_API_TESTAPPCONSOLE_UTILS_H - -#include "lock.h" - -#define THROW_ON_ERROR(x) \ -{ \ - smReturnCode result = (x); \ - if (result < 0) \ - { \ - std::stringstream s; \ - s << "API error code: " << result; \ - throw std::runtime_error(s.str()); \ - } \ -} - -namespace sm -{ - namespace faceapi - { - namespace samplecode - { - // Global variables - Mutex g_mutex; - bool g_ctrl_c_detected(false); - bool g_do_head_pose_printing(false); - bool g_do_face_data_printing(false); - unsigned short g_overlay_flags(SM_API_VIDEO_DISPLAY_HEAD_MESH | SM_API_VIDEO_DISPLAY_PERFORMANCE); - - // CTRL-C handler function - void __cdecl CtrlCHandler(int) - { - Lock lock(g_mutex); - std::cout << "Ctrl-C detected, stopping..." << std::endl; - g_ctrl_c_detected = true; - } - - // Radians to degrees conversion - float rad2deg(float rad) - { - return rad*57.2957795f; - } - - void toggleFlag(unsigned short &val, unsigned short flag) - { - if (val & flag) - { - val = val & ~flag; - } - else - { - val = val | flag; - } - } - - // Save an image to PNG file - smReturnCode saveToPNGFile(const std::string& filepath, smImageInfo image_info) - { - smBool ok; - smReturnCode error; - - // Create an API string - smStringHandle filepath_handle = 0; - ok = (error = smStringCreate(&filepath_handle)) == SM_API_OK; - ok = ok && (error = smStringReadBuffer(filepath_handle,filepath.c_str(),filepath.size())) == SM_API_OK; - - // Create an API image - smImageHandle image_handle = 0; - smImageMemoryCopyMode copy_mode = SM_API_IMAGE_MEMORYCOPYMODE_AUTO; - ok = ok && (error = smImageCreateFromInfo(&image_info,©_mode,&image_handle)) == SM_API_OK; - - // Save the image as PNG - ok = ok && (error = smImageSaveToPNG(image_handle,filepath_handle)) == SM_API_OK; - - // Destroy the image and string - smStringDestroy(&filepath_handle); - smImageDestroy(&image_handle); - return error; - } - - // Stream operators for printing - - std::ostream &operator<<(std::ostream & os, const smSize2i &s) - { - return os << "[" << s.h << "," << s.h << "]"; - } - - std::ostream &operator<<(std::ostream & os, const smCoord3f &pos) - { - return os << "(" << pos.x << "," << pos.y << "," << pos.z << ")"; - } - - std::ostream &operator<<(std::ostream & os, const smRotEuler &rot) - { - return os << "(" << rad2deg(rot.x_rads) << "," << rad2deg(rot.y_rads) << "," << rad2deg(rot.z_rads) << ")"; - } - - std::ostream &operator<<(std::ostream & os, const smPixel &p) - { - return os << "[" << static_cast(p.x) << "," << static_cast(p.y) << "]"; - } - - std::ostream &operator<<(std::ostream & os, const smFaceTexCoord &ftc) - { - return os << "{" << ftc.u << "," << ftc.v << "}"; - } - - std::ostream &operator<<(std::ostream & os, const smFaceLandmark &lm) - { - return os << "id "<< lm.id << " fc" << lm.fc << " ftc" << lm.ftc << " pc" << lm.pc << " wc" << lm.wc; - } - - std::ostream &operator<<(std::ostream & os, const smImageInfo &im) - { - os << "format "; - switch (im.format) - { - case SM_API_IMAGECODE_GRAY_8U: - os << "GRAY_8U"; - break; - case SM_API_IMAGECODE_GRAY_16U: - os << "GRAY_16U"; - break; - case SM_API_IMAGECODE_YUY2: - os << "YUY2"; - break; - case SM_API_IMAGECODE_I420: - os << "I420"; - break; - case SM_API_IMAGECODE_BGRA_32U: - os << "BGRA_32U"; - break; - case SM_API_IMAGECODE_ARGB_32U: - os << "ARGB_32U"; - break; - case SM_API_IMAGECODE_BGR_24U: - os << "BGR_24U"; - break; - case SM_API_IMAGECODE_RGB_24U: - os << "RGB_24U"; - break; - default: - os << "unknown"; - break; - } - os << " res" << im.res; - os << " plane_addr(" << static_cast(im.plane_addr[0]) << "," - << static_cast(im.plane_addr[1]) << "," - << static_cast(im.plane_addr[2]) << "," - << static_cast(im.plane_addr[3]) << ")"; - os << " step_bytes(" << im.step_bytes[0] << "," << im.step_bytes[1] << "," << im.step_bytes[2] << "," << im.step_bytes[3] << ")"; - os << " user_data " << im.user_data; - return os; - } - - std::ostream &operator<<(std::ostream & os, const smFaceTexture &t) - { - os << "type "; - switch (t.type) - { - case SM_ORTHOGRAPHIC_PROJECTION: - os << "orthographic"; - break; - default: - os << "unknown"; - break; - } - os << " origin" << t.origin << " scale" << t.scale << std::endl; - os << " image_info " << t.image_info << std::endl; - os << " num_mask_landmarks " << t.num_mask_landmarks << std::endl; - for (int i=0; i