├── test ├── oni │ ├── user_new.oni │ ├── depth_only.oni │ ├── image_depth.oni │ ├── image_only.oni │ ├── user_calibrate.oni │ └── user_calibrate_failure.oni ├── MockTimer.h ├── main.cc ├── LocusDetectorTest.cc ├── TimerTest.cc ├── CrossArmBlockPoseDetectorTest.cc ├── UserFactoryTest.cc ├── AbstractDetectorTest.cc ├── MockVector.h ├── ThanksCommandDetectorTest.cc ├── LeftJabCommandDetectorTest.cc ├── OwataPoseDetectorTest.cc ├── RightStraightCommandDetectorTest.cc ├── WorldContextTest.cc ├── CommandDetectorTest.cc ├── UserContextTest.cc ├── MockUser.h ├── UserTest.cc └── VectorTest.cc ├── .gitignore ├── src ├── Detector │ ├── PoseDetector.cc │ ├── CrossArmBlockPoseDetector.cc │ ├── AbstractDetector.cc │ ├── LocusDetector.cc │ ├── OwataPoseDetector.cc │ ├── LeftJabCommandDetector.cc │ ├── RightStraightCommandDetector.cc │ ├── ThanksCommandDetector.cc │ ├── LeftHookCommandDetector.cc │ ├── RightUpperCommandDetector.cc │ └── CommandDetector.cc ├── Timer.cc ├── User │ ├── UserFactory.cc │ └── UserContext.cc ├── WorldContext.cc ├── Vector.cc └── User.cc ├── samples └── language │ ├── include │ ├── DefaultInputMethod.h │ ├── Instruction.h │ ├── AbstractRenderer.h │ ├── AbstractInputMethod.h │ ├── Controller.h │ ├── Compiler.h │ └── VM.h │ ├── test │ ├── main.cc │ ├── CompilerTest.cc │ └── VMTest.cc │ ├── src │ ├── main.cc │ ├── InputMethod │ │ ├── AbstractInputMethod.cc │ │ └── DefaultInputMethod.cc │ ├── Renderer │ │ └── AbstractRenderer.cc │ ├── Controller.cc │ ├── VM.cc │ └── Compiler.cc │ ├── Makefile.coverage │ ├── Tython.xml │ ├── Makefile │ └── Makefile.defs ├── include ├── PoseDetector.h ├── CrossArmBlockPoseDetector.h ├── LeftJabCommandDetector.h ├── OwataPoseDetector.h ├── ThanksCommandDetector.h ├── RightStraightCommandDetector.h ├── RightUpperCommandDetector.h ├── LeftHookCommandDetector.h ├── Timer.h ├── util.h ├── AbstractDetector.h ├── UserFactory.h ├── LocusDetector.h ├── CommandDetector.h ├── WorldContext.h ├── Vector.h ├── UserContext.h └── User.h ├── LICENSE-ja ├── Makefile.coverage ├── Makefile.defs ├── LICENSE-en ├── Makefile └── README.mkdn /test/oni/user_new.oni: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gongo/Tython/HEAD/test/oni/user_new.oni -------------------------------------------------------------------------------- /test/oni/depth_only.oni: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gongo/Tython/HEAD/test/oni/depth_only.oni -------------------------------------------------------------------------------- /test/oni/image_depth.oni: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gongo/Tython/HEAD/test/oni/image_depth.oni -------------------------------------------------------------------------------- /test/oni/image_only.oni: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gongo/Tython/HEAD/test/oni/image_only.oni -------------------------------------------------------------------------------- /test/oni/user_calibrate.oni: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gongo/Tython/HEAD/test/oni/user_calibrate.oni -------------------------------------------------------------------------------- /test/oni/user_calibrate_failure.oni: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gongo/Tython/HEAD/test/oni/user_calibrate_failure.oni -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.gcda 3 | *.gcno 4 | Tython 5 | .cimg/ 6 | libTython.so 7 | libTythonTest 8 | GPATH 9 | GRTAGS 10 | GSYMS 11 | GTAGS 12 | -------------------------------------------------------------------------------- /src/Detector/PoseDetector.cc: -------------------------------------------------------------------------------- 1 | #include "PoseDetector.h" 2 | 3 | namespace ty { 4 | 5 | PoseDetector::PoseDetector(User* _user) : AbstractDetector(_user) 6 | { 7 | } 8 | 9 | PoseDetector::~PoseDetector(void) 10 | { 11 | } 12 | 13 | } // namespace ty 14 | -------------------------------------------------------------------------------- /src/Detector/CrossArmBlockPoseDetector.cc: -------------------------------------------------------------------------------- 1 | #include "CrossArmBlockPoseDetector.h" 2 | 3 | namespace ty { 4 | 5 | bool CrossArmBlockPoseDetector::isPosing(void) 6 | { 7 | Vector rarm = user->vectorRightForearm(); 8 | Vector larm = user->vectorLeftForearm(); 9 | return rarm.isOrthogonal(larm); 10 | } 11 | 12 | } // namespace ty 13 | -------------------------------------------------------------------------------- /src/Detector/AbstractDetector.cc: -------------------------------------------------------------------------------- 1 | #include "AbstractDetector.h" 2 | 3 | namespace ty { 4 | 5 | AbstractDetector::AbstractDetector(User* _user) : user(_user) 6 | { 7 | timer = Timer::instance(); 8 | } 9 | 10 | AbstractDetector::~AbstractDetector(void) 11 | { 12 | } 13 | 14 | bool AbstractDetector::detect() 15 | { 16 | return user->isTracking() && isPosing(); 17 | } 18 | 19 | } // namespace ty 20 | -------------------------------------------------------------------------------- /samples/language/include/DefaultInputMethod.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_DEFAULT_INPUT_METHOD_H_ 4 | #define _TYTHON_DEFAULT_INPUT_METHOD_H_ 5 | 6 | #include "AbstractInputMethod.h" 7 | 8 | class DefaultInputMethod : public AbstractInputMethod { 9 | public: 10 | DefaultInputMethod(void); 11 | DefaultInputMethod(ty::User* _user); 12 | }; 13 | 14 | #endif // _TYTHON_DEFAULT_INPUT_METHOD_H_ 15 | -------------------------------------------------------------------------------- /src/Timer.cc: -------------------------------------------------------------------------------- 1 | #include "Timer.h" 2 | 3 | namespace ty { 4 | 5 | Timer* Timer::_instance = new Timer; 6 | 7 | Timer::Timer(void) 8 | { 9 | xnOSStartTimer(&tick); 10 | } 11 | 12 | Timer* Timer::instance(void) 13 | { 14 | return _instance; 15 | } 16 | 17 | XnUInt64 Timer::current(void) 18 | { 19 | XnUInt64 now; 20 | xnOSQueryTimer(tick, &now); 21 | 22 | return now / 1000000; 23 | } 24 | 25 | } // namespace ty 26 | -------------------------------------------------------------------------------- /include/PoseDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_POSE_DETECTOR_H_ 4 | #define _TYTHON_POSE_DETECTOR_H_ 5 | 6 | #include "AbstractDetector.h" 7 | 8 | namespace ty { 9 | 10 | class PoseDetector : public AbstractDetector { 11 | public: 12 | PoseDetector(User* _user); 13 | virtual ~PoseDetector(void); 14 | protected: 15 | 16 | private: 17 | }; 18 | 19 | } // namespace ty 20 | 21 | #endif // _TYTHON_POSE_DETECTOR_H_ 22 | -------------------------------------------------------------------------------- /test/MockTimer.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_MOCK_TIMER_H 4 | #define _TYTHON_MOCK_TIMER_H 5 | 6 | #include 7 | #include "Timer.h" 8 | 9 | class MockTimer : public ty::Timer { 10 | public: 11 | MockTimer(void) { 12 | ON_CALL(*this, current()).WillByDefault(::testing::Return(0)); 13 | } 14 | virtual ~MockTimer(void) {} 15 | 16 | MOCK_METHOD0(current, XnUInt64(void)); 17 | }; 18 | 19 | #endif // _TYTHON_MOCK_TIMER_H 20 | -------------------------------------------------------------------------------- /samples/language/include/Instruction.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_INSTRUCTION_H_ 4 | #define _TYTHON_INSTRUCTION_H_ 5 | 6 | #include 7 | 8 | using std::string; 9 | 10 | typedef struct Instruction { 11 | public: 12 | Instruction(void) {} 13 | Instruction(std::string _s) : op(_s), arg(NULL) {} 14 | Instruction(std::string _s, int _v) : op(_s), arg(_v) {} 15 | 16 | std::string op; 17 | int arg; 18 | } Instruction; 19 | 20 | #endif // _TYTHON_INSTRUCTION_H_ 21 | -------------------------------------------------------------------------------- /test/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Vector.h" 4 | 5 | using ::testing::DefaultValue; 6 | 7 | void setMockDefaultValue(void) 8 | { 9 | DefaultValue::Set(ty::Vector(0.0f, 0.0f, 0.0f)); 10 | DefaultValue::Set(0); 11 | } 12 | 13 | int main(int argc, char **argv) { 14 | ::testing::InitGoogleMock(&argc, argv); 15 | ::testing::FLAGS_gmock_verbose = "error"; 16 | 17 | setMockDefaultValue(); 18 | 19 | return RUN_ALL_TESTS(); 20 | } 21 | -------------------------------------------------------------------------------- /samples/language/test/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Vector.h" 4 | 5 | using ::testing::DefaultValue; 6 | 7 | void setMockDefaultValue(void) 8 | { 9 | DefaultValue::Set(ty::Vector(0.0f, 0.0f, 0.0f)); 10 | DefaultValue::Set(0); 11 | } 12 | 13 | int main(int argc, char **argv) { 14 | ::testing::InitGoogleMock(&argc, argv); 15 | ::testing::FLAGS_gmock_verbose = "error"; 16 | 17 | setMockDefaultValue(); 18 | 19 | return RUN_ALL_TESTS(); 20 | } 21 | -------------------------------------------------------------------------------- /test/LocusDetectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "LocusDetector.h" 3 | 4 | class LocusDetectorTest : public testing::Test { 5 | protected: 6 | void SetUp(void) 7 | { 8 | object = new ty::LocusDetector(NULL); 9 | } 10 | 11 | ty::LocusDetector* object; 12 | }; 13 | 14 | // TEST_F(LocusDetectorTest, TestIsTraceCondition) { 15 | // TyVector v1(0.0f, 0.0f, 0.0f); 16 | // TyVector v2(1.0f, 0.0f, 0.0f); 17 | 18 | // ASSERT_FALSE(object->isTraceCondition(v1, v1)); 19 | // ASSERT_TRUE(object->isTraceCondition(v1, v2)); 20 | // } 21 | -------------------------------------------------------------------------------- /src/Detector/LocusDetector.cc: -------------------------------------------------------------------------------- 1 | #include "LocusDetector.h" 2 | 3 | namespace ty { 4 | 5 | LocusDetector::LocusDetector(User* _user) 6 | : AbstractDetector(_user), timeLimit(0.0f), moveThreshold(0.0f) 7 | { 8 | } 9 | 10 | LocusDetector::~LocusDetector(void) 11 | { 12 | } 13 | 14 | bool LocusDetector::isPosing(void) 15 | { 16 | return true; 17 | } 18 | 19 | bool LocusDetector::isTraceCondition (const Vector& v_st, 20 | const Vector& v_ed) const 21 | { 22 | return v_st.distance(v_ed) > moveThreshold; 23 | } 24 | 25 | } // namespace ty 26 | -------------------------------------------------------------------------------- /samples/language/include/AbstractRenderer.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_ABSTRACT_RENDERER_H_ 4 | #define _TYTHON_ABSTRACT_RENDERER_H_ 5 | 6 | #include 7 | #include 8 | #include "User.h" 9 | #include "WorldContext.h" 10 | #include "Vector.h" 11 | 12 | class AbstractRenderer { 13 | public: 14 | AbstractRenderer(ty::WorldContext *ctx, ty::User* _user); 15 | virtual ~AbstractRenderer(void); 16 | void draw(void); 17 | protected: 18 | ty::WorldContext* ctx; 19 | ty::User* user; 20 | private: 21 | cv::Ptr camera; 22 | }; 23 | 24 | #endif // _TYTHON_ABSTRACT_RENDERER_H_ 25 | -------------------------------------------------------------------------------- /test/TimerTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Timer.h" 3 | 4 | class TimerTest : public testing::Test { 5 | public: 6 | ty::Timer *object; 7 | protected: 8 | virtual void SetUp() { 9 | object = ty::Timer::instance(); 10 | } 11 | }; 12 | 13 | /** 14 | * シングルトンが機能しているか 15 | */ 16 | TEST_F(TimerTest, TestGetInstance) { 17 | ty::Timer *object2 = ty::Timer::instance(); 18 | 19 | ASSERT_TRUE(NULL != object); 20 | ASSERT_TRUE(object == object2); 21 | } 22 | 23 | TEST_F(TimerTest, TestCurrent) { 24 | int time1 = object->current(); 25 | int time2 = object->current(); 26 | 27 | ASSERT_LE(time1, time2); 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE-ja: -------------------------------------------------------------------------------- 1 | MAHALO License (based on MIT License) 2 | 3 | Copyright (c) 2011 Wataru MIYAGUNI 4 | 5 | 以下に定める条件に従い、本ソフトウェアおよび関連文書のファイル(以下「ソフトウェア」)の 6 | 複製を取得するすべての人に対し、ソフトウェアを無制限に扱うことを無償で許可します。 7 | これには、ソフトウェアの複製を使用、複写、変更、結合、掲載、頒布、サブライセンス、および/または販売する権利、 8 | およびソフトウェアを提供する相手に同じことを許可する権利も無制限に含まれます。 9 | 10 | 1. 上記の著作権表示および本許諾表示を、ソフトウェアのすべての複製または重要な部分に記載するものとします。 11 | 2. ソフトウェアを使用する際、(ソフトウェアに限らず)何かに対して「感謝」をすることとします。 12 | 13 | ソフトウェアは「現状のまま」で、明示であるか暗黙であるかを問わず、何らの保証もなく提供されます。 14 | ここでいう保証とは、商品性、特定の目的への適合性、および権利非侵害についての保証も含みますが、 15 | それに限定されるものではありません。 作者または著作権者は、契約行為、不法行為、またはそれ以外であろうと、 16 | ソフトウェアに起因または関連し、あるいはソフトウェアの使用またはその他の扱いによって生じる 17 | 一切の請求、損害、その他の義務について何らの責任も負わないものとします。 18 | -------------------------------------------------------------------------------- /include/CrossArmBlockPoseDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_CROSS_ARM_BLOCK_POSE_DETECTOR_H_ 4 | #define _TYTHON_CROSS_ARM_BLOCK_POSE_DETECTOR_H_ 5 | 6 | #include "PoseDetector.h" 7 | 8 | namespace ty { 9 | 10 | class CrossArmBlockPoseDetector : public PoseDetector { 11 | public: 12 | CrossArmBlockPoseDetector(User* _user) : PoseDetector(_user) {} 13 | virtual ~CrossArmBlockPoseDetector(void) {} 14 | 15 | /** 16 | * クロスアームブロックのポーズをとっているか判定 17 | * 18 | * 両腕を 90 度に交差 19 | * 20 | * @return ポーズを検出できれば true / できなければ false 21 | */ 22 | bool isPosing(void); 23 | }; 24 | 25 | } // namespace ty 26 | 27 | #endif // _TYTHON_CROSS_ARM_BLOCK_POSE_DETECTOR_H_ 28 | -------------------------------------------------------------------------------- /samples/language/src/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Controller.h" 4 | #include 5 | 6 | Controller *controller; 7 | 8 | const GLfloat vertex[] = { 9 | -0.0, 0.9, 0.9, 0.9, 0.0, -0.9 10 | }; 11 | 12 | int main(int argc, char **argv) 13 | { 14 | try { 15 | if (argc > 1) { 16 | controller = new Controller(argv[1]); 17 | } else { 18 | controller = new Controller(); 19 | } 20 | controller->main(); 21 | delete controller; 22 | } catch (std::runtime_error e) { 23 | std::cout << e.what() << std::endl; 24 | return EXIT_FAILURE; 25 | } 26 | 27 | return EXIT_SUCCESS; 28 | } 29 | -------------------------------------------------------------------------------- /include/LeftJabCommandDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_LEFT_JAB_COMMAND_DETECTOR_H_ 4 | #define _TYTHON_LEFT_JAB_COMMAND_DETECTOR_H_ 5 | 6 | #include "CommandDetector.h" 7 | 8 | namespace ty { 9 | 10 | class LeftJabCommandDetector : public CommandDetector { 11 | public: 12 | LeftJabCommandDetector(User* _user); 13 | virtual ~LeftJabCommandDetector(void); 14 | 15 | /** 16 | * 構え状態かチェックする 17 | * 18 | * @return 構え状態であれば true 19 | */ 20 | bool isStand(void) const; 21 | 22 | /** 23 | * ジャブ構え状態かチェックする 24 | * 25 | * @return ジャブ構え状態であれば true 26 | */ 27 | bool isLeftJab(void) const; 28 | }; 29 | 30 | } // namespace ty 31 | 32 | #endif // _TYTHON_LEFT_JAB_COMMAND_DETECTOR_H_ 33 | -------------------------------------------------------------------------------- /samples/language/src/InputMethod/AbstractInputMethod.cc: -------------------------------------------------------------------------------- 1 | #include "AbstractInputMethod.h" 2 | 3 | AbstractInputMethod::AbstractInputMethod(void) 4 | { 5 | } 6 | 7 | AbstractInputMethod::~AbstractInputMethod(void) 8 | { 9 | IMmap::iterator ip = inputList.begin(); 10 | IMquit::iterator qu = quitList.end(); 11 | 12 | // while (ip != inputList.end()) { 13 | // delete ip->second; 14 | // ++ip; 15 | // } 16 | 17 | // while (qu != quitList.end()) { 18 | // AbstractDetector* quit = *(qu++); 19 | // delete quit; 20 | // } 21 | } 22 | 23 | IMmap AbstractInputMethod::input(void) 24 | { 25 | return inputList; 26 | } 27 | 28 | IMquit AbstractInputMethod::quit(void) 29 | { 30 | return quitList; 31 | } 32 | -------------------------------------------------------------------------------- /include/OwataPoseDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_OWATA_POSE_DETECTOR_H_ 4 | #define _TYTHON_OWATA_POSE_DETECTOR_H_ 5 | 6 | #include "PoseDetector.h" 7 | 8 | namespace ty { 9 | 10 | class OwataPoseDetector : public PoseDetector { 11 | public: 12 | OwataPoseDetector(User* _user) : PoseDetector(_user) {} 13 | virtual ~OwataPoseDetector(void) {} 14 | 15 | /** 16 | *
17 |      * \(^o^)/
18 |      *     |
19 |      *    / \
20 |      * 
21 | * 22 | * 1. 両腕はまっすぐ 23 | * @todo 2. 正中線と両腕は角度45度 24 | * 3. 手は頭の上 25 | * 26 | * @return ポーズを検出できれば true / できなければ false 27 | */ 28 | bool isPosing(void); 29 | }; 30 | 31 | } // namespace ty 32 | 33 | #endif // _TYTHON_OWATA_POSE_DETECTOR_H_ 34 | -------------------------------------------------------------------------------- /samples/language/Makefile.coverage: -------------------------------------------------------------------------------- 1 | include Makefile 2 | 3 | CXXFLAGS += -fprofile-arcs -ftest-coverage 4 | LIBS += -lgcov 5 | 6 | GCOV_OBJS = $(OBJS:.o=.gcno) $(TEST_OBJS:.o=.gcno) $(OBJS:.o=.gcda) $(TEST_OBJS:.o=.gcda) 7 | LCOV_INFO = lcov.info 8 | LCOV_DIR = gcov 9 | 10 | coverage: test 11 | $(RM) $(LCOV_INFO) $(LCOV_DIR) 12 | lcov -c -b . -d $(SRCS_DIR) -d $(TEST_SRCS_DIR) -o lcov2.info 13 | lcov -r lcov2.info '/usr/include/*' \ 14 | '/usr/local/include/*' \ 15 | 'test/*' \ 16 | 'include/*.h' \ 17 | -o $(LCOV_INFO) 18 | rm lcov2.info 19 | genhtml -o $(LCOV_DIR) $(LCOV_INFO) 20 | 21 | coverage-clean: clean 22 | $(RM) $(GCOV_OBJS) $(LCOV_INFO) $(LCOV_DIR) 23 | -------------------------------------------------------------------------------- /src/Detector/OwataPoseDetector.cc: -------------------------------------------------------------------------------- 1 | #include "OwataPoseDetector.h" 2 | 3 | namespace ty { 4 | 5 | bool OwataPoseDetector::isPosing(void) 6 | { 7 | Vector rightUpperArm = user->vectorRightUpperArm(); 8 | Vector leftUpperArm = user->vectorLeftUpperArm(); 9 | Vector medianLine = user->vectorHead(); 10 | Vector rightHand = user->rightHand(); 11 | Vector leftHand = user->leftHand(); 12 | Vector head = user->head(); 13 | 14 | return user->rightArmIsStraight() 15 | && user->leftArmIsStraight() 16 | && medianLine.betweenAngle(rightUpperArm, 45.0f) 17 | && medianLine.betweenAngle(leftUpperArm, 45.0f) 18 | && head.Y < rightHand.Y 19 | && head.Y < leftHand.Y; 20 | } 21 | 22 | } // namespace ty 23 | -------------------------------------------------------------------------------- /include/ThanksCommandDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_LEFT_THANKS_DETECTOR_H_ 4 | #define _TYTHON_LEFT_THANKS_DETECTOR_H_ 5 | 6 | #include "CommandDetector.h" 7 | 8 | namespace ty { 9 | 10 | /** 11 | * 十字礼を検知する CommandDetector 12 | */ 13 | class ThanksCommandDetector : public CommandDetector { 14 | public: 15 | ThanksCommandDetector(User* _user); 16 | virtual ~ThanksCommandDetector(void); 17 | 18 | /** 19 | * 胴の前で腕を十字にしているかチェックする 20 | * 21 | * @return 構え状態であれば true 22 | */ 23 | bool isCrossArm(void); 24 | 25 | /** 26 | * 両手を下に払っているかチェックする 27 | * 28 | * @return 構え状態であれば true 29 | */ 30 | bool isBottomArm(void); 31 | }; 32 | 33 | } // namespace ty 34 | 35 | #endif // _TYTHON_LEFT_THANKS_DETECTOR_H_ 36 | -------------------------------------------------------------------------------- /include/RightStraightCommandDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_RIGHT_STRAIGHT_COMMAND_DETECTOR_H_ 4 | #define _TYTHON_RIGHT_STRAIGHT_COMMAND_DETECTOR_H_ 5 | 6 | #include "CommandDetector.h" 7 | 8 | namespace ty { 9 | 10 | class RightStraightCommandDetector : public CommandDetector { 11 | public: 12 | RightStraightCommandDetector(User* _user); 13 | virtual ~RightStraightCommandDetector(void); 14 | 15 | /** 16 | * 構え状態かチェックする 17 | * 18 | * @return 構え状態であれば true 19 | */ 20 | bool isStand(void) const; 21 | 22 | /** 23 | * 左ジャブ状態かチェックする 24 | * 25 | * @return 左ジャブ状態であれば true 26 | */ 27 | bool isRightStraight(void) const; 28 | }; 29 | 30 | } //namespace 31 | 32 | #endif // _TYTHON_RIGHT_STRAIGHT_COMMAND_DETECTOR_H_ 33 | -------------------------------------------------------------------------------- /samples/language/Tython.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /samples/language/src/InputMethod/DefaultInputMethod.cc: -------------------------------------------------------------------------------- 1 | #include "DefaultInputMethod.h" 2 | #include "RightStraightCommandDetector.h" 3 | #include "RightUpperCommandDetector.h" 4 | #include "LeftJabCommandDetector.h" 5 | #include "LeftHookCommandDetector.h" 6 | #include "ThanksCommandDetector.h" 7 | #include "OwataPoseDetector.h" 8 | 9 | DefaultInputMethod::DefaultInputMethod(void) 10 | { 11 | } 12 | 13 | DefaultInputMethod::DefaultInputMethod(ty::User* _user) 14 | { 15 | inputList.insert(std::make_pair("a", new ty::LeftJabCommandDetector(_user))); 16 | inputList.insert(std::make_pair("@", new ty::RightStraightCommandDetector(_user))); 17 | inputList.insert(std::make_pair("g", new ty::RightUpperCommandDetector(_user))); 18 | inputList.insert(std::make_pair(" ", new ty::LeftHookCommandDetector(_user))); 19 | 20 | quitList.push_back(new ty::OwataPoseDetector(_user)); 21 | } 22 | -------------------------------------------------------------------------------- /Makefile.coverage: -------------------------------------------------------------------------------- 1 | include Makefile 2 | 3 | CXX = g++-4.2 4 | CXXFLAGS += -fprofile-arcs -ftest-coverage -g -arch x86_64 5 | LIBS += -lgcov -fprofile-arcs -ftest-coverage 6 | 7 | GCOV_OBJS = $(OBJS:.o=.gcno) $(TEST_OBJS:.o=.gcno) $(OBJS:.o=.gcda) $(TEST_OBJS:.o=.gcda) 8 | LCOV_INFO = lcov.info 9 | LCOV_DIR = gcov 10 | 11 | COVERAGE_XML = coverage.xml 12 | 13 | COVERAGE += $(GCOV_OBJS) $(LCOV_INFO) $(LCOV_DIR) $(COVERAGE_XML) 14 | 15 | coverage: test-all 16 | $(RM) -r $(LCOV_INFO) $(LCOV_DIR) 17 | gcovr -f "`pwd`/(src|include)" -b -x > $(COVERAGE_XML) 18 | lcov -c -b . -d $(SRCS_DIR) -d $(TEST_SRCS_DIR) -o lcov2.info 19 | lcov -r lcov2.info '/usr/include/*' \ 20 | '/usr/local/include/*' \ 21 | 'test/*' \ 22 | 'include/*.h' \ 23 | -o $(LCOV_INFO) 24 | rm lcov2.info 25 | genhtml -t Tython -o $(LCOV_DIR) $(LCOV_INFO) 26 | -------------------------------------------------------------------------------- /include/RightUpperCommandDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_RIGHT_UPPDER_COMMAND_DETECTOR_H_ 4 | #define _TYTHON_RIGHT_UPPDER_COMMAND_DETECTOR_H_ 5 | 6 | #include "CommandDetector.h" 7 | 8 | namespace ty { 9 | 10 | class RightUpperCommandDetector : public CommandDetector { 11 | public: 12 | RightUpperCommandDetector(User* _user); 13 | virtual ~RightUpperCommandDetector(void); 14 | 15 | /** 16 | * 構え状態かチェックする 17 | * 18 | * @return 構え状態であれば true 19 | */ 20 | bool isStand(void) const; 21 | 22 | /** 23 | * アッパー打つ前の体勢かどうかチェックする 24 | * 25 | * @return 構え状態であれば true 26 | */ 27 | bool isRightUpperBefore(void) const; 28 | 29 | /** 30 | * アッパー打った後の体勢かどうかチェックする 31 | * 32 | * @return 構え状態であれば true 33 | */ 34 | bool isRightUpperAfter(void) const; 35 | }; 36 | 37 | } // namespace ty 38 | 39 | #endif // _TYTHON_RIGHT_UPPDER_COMMAND_DETECTOR_H_ 40 | -------------------------------------------------------------------------------- /src/User/UserFactory.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "UserFactory.h" 3 | 4 | namespace ty { 5 | 6 | UserContext* UserFactory::context = NULL; 7 | User* UserFactory::list[UserFactory::MAX]; 8 | 9 | void UserFactory::setContext(xn::Context *ctx) 10 | { 11 | if (context != NULL) { 12 | deleteContext(); 13 | } 14 | 15 | context = new UserContext(ctx); 16 | 17 | for (int i = 0; i < UserFactory::MAX; i++) { 18 | list[i] = new User(context, i + 1); 19 | } 20 | } 21 | 22 | void UserFactory::deleteContext(void) 23 | { 24 | for (int i = 0; i < UserFactory::MAX; i++) { 25 | delete list[i]; 26 | } 27 | 28 | delete context; 29 | context = NULL; 30 | } 31 | 32 | User* UserFactory::get(int userId) 33 | { 34 | if (MAX < userId || userId < 1) { 35 | throw std::out_of_range("\"userId\" must between 1 and UserFactory::MAX"); 36 | } 37 | 38 | return list[userId - 1]; 39 | } 40 | 41 | } // namespace ty 42 | -------------------------------------------------------------------------------- /include/LeftHookCommandDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_LEFT_HOOK_COMMAND_DETECTOR_H_ 4 | #define _TYTHON_LEFT_HOOK_COMMAND_DETECTOR_H_ 5 | 6 | #include "CommandDetector.h" 7 | 8 | namespace ty { 9 | 10 | class LeftHookCommandDetector : public CommandDetector { 11 | public: 12 | LeftHookCommandDetector(User* _user); 13 | virtual ~LeftHookCommandDetector(void); 14 | 15 | /** 16 | * 構え状態かチェックする 17 | * 18 | * @return 構え状態であれば true 19 | */ 20 | bool isStand(void) const; 21 | 22 | /** 23 | * フックを撃つ前の体勢かどうかチェックする 24 | * 25 | * 左腕が身体の外にある感じ 26 | * 27 | * @return 構え状態であれば true 28 | */ 29 | bool isLeftHookBefore(void) const; 30 | 31 | /** 32 | * フックを撃った後の体勢かどうかチェックする 33 | * 34 | * 左腕が身体の右側にある感じ 35 | * 36 | * @return 構え状態であれば true 37 | */ 38 | bool isLeftHookAfter(void) const; 39 | }; 40 | 41 | } // namespace ty 42 | 43 | #endif // _TYTHON_LEFT_HOOK_COMMAND_DETECTOR_H_ 44 | -------------------------------------------------------------------------------- /include/Timer.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_TIMER_H_ 4 | #define _TYTHON_TIMER_H_ 5 | 6 | #include 7 | 8 | namespace ty { 9 | 10 | class Timer { 11 | public: 12 | /** 13 | * インスタンス取得 14 | * 15 | * @return Timer のインスタンス 16 | */ 17 | static Timer* instance(void); 18 | 19 | /** 20 | * プログラム起動から現在までの経過秒数を返す 21 | * 22 | * @return プログラム起動から現在までの経過秒数 23 | */ 24 | virtual XnUInt64 current(void); 25 | 26 | protected: 27 | /** 28 | * コンストラクタ 29 | * 30 | * Singleton だが、MockTimer のため protected で定義 31 | */ 32 | Timer(void); 33 | 34 | /** 35 | * コピーコンストラクタ 36 | * 37 | * Singleton だが、 MockTimer のため protected で定義 38 | */ 39 | Timer(const Timer& obj) {} 40 | 41 | private: 42 | /** 43 | * Timer インスタンス 44 | */ 45 | static Timer* _instance; 46 | 47 | /** 48 | * XnOSTimer 49 | */ 50 | XnOSTimer tick; 51 | }; 52 | 53 | } // namespace ty 54 | 55 | #endif // _TYTHON_TIMER_H_ 56 | -------------------------------------------------------------------------------- /test/CrossArmBlockPoseDetectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "CrossArmBlockPoseDetector.h" 3 | #include "MockUser.h" 4 | 5 | using ::testing::Return; 6 | 7 | class CrossArmBlockPoseDetectorTest : public testing::Test { 8 | public: 9 | virtual void SetUp() { 10 | mock = new MockUser; 11 | object = new ty::CrossArmBlockPoseDetector(mock); 12 | } 13 | 14 | virtual void TearDown() { 15 | delete object; 16 | delete mock; 17 | } 18 | protected: 19 | ty::CrossArmBlockPoseDetector* object; 20 | MockUser* mock; 21 | }; 22 | 23 | TEST_F(CrossArmBlockPoseDetectorTest, TestIsPosing) { 24 | EXPECT_CALL(*mock, vectorRightForearm()) 25 | .WillOnce(Return(ty::Vector(0, 100, 0))); 26 | EXPECT_CALL(*mock, vectorLeftForearm()) 27 | .WillOnce(Return(ty::Vector(100, 0, 0))); 28 | 29 | ASSERT_TRUE(object->isPosing()); 30 | } 31 | 32 | TEST_F(CrossArmBlockPoseDetectorTest, TestIsPosingError) { 33 | ASSERT_FALSE(object->isPosing()); 34 | } 35 | -------------------------------------------------------------------------------- /samples/language/include/AbstractInputMethod.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_ABSTRACT_INPUT_METHOD_H_ 4 | #define _TYTHON_ABSTRACT_INPUT_METHOD_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "AbstractDetector.h" 10 | 11 | using std::map; 12 | using std::vector; 13 | using std::string; 14 | 15 | typedef map IMmap; 16 | typedef vector IMquit; 17 | 18 | class AbstractInputMethod { 19 | public: 20 | 21 | AbstractInputMethod(void); 22 | virtual ~AbstractInputMethod(void); 23 | 24 | /** 25 | * ソースコード入力する Detector と対応するソースコードの map を返す 26 | */ 27 | IMmap input(void); 28 | 29 | /** 30 | * ソースコード入力を終了する Detector のリスト 31 | */ 32 | IMquit quit(void); 33 | 34 | protected: 35 | /** 36 | * ソースコード入力する Detector と対応するソースコードの map 37 | */ 38 | IMmap inputList; 39 | 40 | /** 41 | * ソースコード入力を終了する Detector のリスト 42 | */ 43 | IMquit quitList; 44 | }; 45 | 46 | #endif // _TYTHON_ABSTRACT_INPUT_METHOD_H_ 47 | -------------------------------------------------------------------------------- /include/util.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_UTIL_H_ 4 | #define _TYTHON_UTIL_H_ 5 | 6 | #include 7 | 8 | namespace ty { 9 | 10 | /** 11 | * XnStatus が正常値かどうかをチェックする 12 | * 13 | * @param rc XnStatus 14 | * @return rc が正常値であれば true 15 | */ 16 | inline static bool xnCheck(XnStatus rc) 17 | { 18 | return (rc == XN_STATUS_OK); 19 | } 20 | 21 | /** 22 | * XnStatus が異常値の場合、runtime_error を throw する 23 | 24 | * @param rc XnStatus 25 | * @throw std::runtime_error rc is failure status code 26 | */ 27 | inline static void xnRuntimeCheck(XnStatus rc) 28 | { 29 | if (!ty::xnCheck(rc)) { 30 | throw std::runtime_error(xnGetStatusString(rc)); 31 | } 32 | } 33 | 34 | #define DIE_IF(rc, message) do { \ 35 | if (rc) { \ 36 | fprintf(stderr, "%s\n", message); \ 37 | exit(EXIT_FAILURE); \ 38 | } \ 39 | } while (0) 40 | 41 | } // namespace ty 42 | 43 | #endif // _TYTHON_UTIL_H_ 44 | -------------------------------------------------------------------------------- /include/AbstractDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_ABSTRACT_DETECTOR_H_ 4 | #define _TYTHON_ABSTRACT_DETECTOR_H_ 5 | 6 | #include "User.h" 7 | #include "Timer.h" 8 | 9 | namespace ty { 10 | 11 | class AbstractDetector { 12 | public: 13 | /** 14 | * @brief コンストラクタ 15 | * 16 | * Timer のインスタンスを取得する 17 | * 18 | * @param _user User インスタンス 19 | */ 20 | AbstractDetector(User* _user); 21 | 22 | /** 23 | * @brief デストラクタ 24 | */ 25 | virtual ~AbstractDetector(void); 26 | 27 | /** 28 | * @brief ポーズをとっているか判定 29 | * 30 | * @return ポーズを検出できれば true 31 | */ 32 | virtual bool isPosing(void) = 0; 33 | 34 | /** 35 | * @brief キャリブレーション済みのユーザがポーズを取っているか判定 36 | * 37 | * @return 条件を満たしていれば true 38 | */ 39 | bool detect(void); 40 | protected: 41 | /** 42 | * User インスタンス 43 | */ 44 | User* user; 45 | 46 | /** 47 | * Timer インスタンス 48 | */ 49 | Timer* timer; 50 | private: 51 | }; 52 | 53 | } // namespace ty 54 | 55 | #endif // _TYTHON_ABSTRACT_DETECTOR_H_ 56 | -------------------------------------------------------------------------------- /Makefile.defs: -------------------------------------------------------------------------------- 1 | # Source Path 2 | SRCS_DIR = src 3 | SRCS = $(wildcard $(SRCS_DIR)/**/*.cc) $(wildcard $(SRCS_DIR)/*.cc) 4 | OBJS = $(SRCS:.cc=.o) 5 | 6 | TEST_SRCS_DIR = test 7 | TEST_SRCS = $(wildcard $(TEST_SRCS_DIR)/*.cc) 8 | TEST_OBJS = $(TEST_SRCS:.cc=.o) 9 | 10 | # OpenNI Path 11 | OPENNI_INCLUDE_PATH = $(HOME)/.kinect/usr/include/ni 12 | OPENNI_LIBRARY_PATH = $(HOME)/.kinect/usr/lib 13 | 14 | # Compile Option 15 | CXX = g++ 16 | INCLUDE = -I./include -I$(OPENNI_INCLUDE_PATH) 17 | CXXFLAGS = -Wall -g \ 18 | -fno-tree-pre -fno-strict-aliasing \ 19 | -msse3 -mssse3 \ 20 | $(INCLUDE) 21 | LIBS = -lm -L$(OPENNI_LIBRARY_PATH) -lOpenNI 22 | 23 | TEST_CXXFLAGS = $(shell gmock-config --cppflags --cxxflags) $(CXXFLAGS) 24 | TEST_LIBS = -L$(shell gtest-config --libdir) \ 25 | -lgtest -L$(shell gmock-config --libdir) -lgmock \ 26 | $(LIBS) 27 | 28 | # Other Command 29 | AR = ar 30 | ARFLAGS = r 31 | RANLIB = ranlib 32 | RM = rm -f 33 | RM_GC = *~ \#* 34 | TAGS = gtags 35 | TAGSOPTION = 36 | TAGSFILE = GPATH GRTAGS GSYMS GTAGS 37 | -------------------------------------------------------------------------------- /samples/language/Makefile: -------------------------------------------------------------------------------- 1 | include ./Makefile.defs 2 | 3 | TARGET = Tython 4 | TEST_TARGET = TestTython 5 | 6 | RM = rm -rf 7 | RM_GC = *~ \#* 8 | 9 | TAGS = gtags 10 | TAGSOPTION = 11 | TAGSFILE = GPATH GRTAGS GSYMS GTAGS 12 | 13 | OBJS_GCOV = $(OBJS:.o=.gcno) $(TEST_OBJS:.o=.gcno) lcov.info 14 | 15 | .SUFFIXES: .cc .o 16 | 17 | %.o : %.cc 18 | $(TEST_SRCS_DIR)/%.o : test/%.cc 19 | $(CXX) $(TEST_CXXFLAGS) -c $< -o $@ 20 | %.o : %.cc 21 | $(CXX) $(CXXFLAGS) -c $< -o $@ 22 | 23 | 24 | $(TARGET): $(OBJS_ALL) 25 | $(CXX) $(LIBS) $(OBJS_ALL) -o $@ 26 | 27 | $(TEST_TARGET): $(OBJS) $(TEST_OBJS) 28 | $(CXX) $(TEST_LIBS) $(OBJS) $(TEST_OBJS) -o $@ 29 | 30 | test: $(TEST_TARGET) force 31 | ./$(TEST_TARGET) --gtest_output=xml 32 | 33 | clean: 34 | $(RM) $(RM_GC) 35 | $(RM) $(TARGET) $(TEST_TARGET) 36 | $(RM) $(OBJS_ALL) $(TEST_OBJS) 37 | $(RM) $(DEPEND) 38 | $(RM) $(TAGSFILE) 39 | $(RM) $(OBJS_GCOV) 40 | $(RM) test_detail.xml 41 | cd $(SRCS_DIR) && $(RM) $(RM_GC) 42 | cd $(TEST_SRCS_DIR) && $(RM) $(RM_GC) 43 | 44 | 45 | tags: 46 | @$(TAGS) $(TAGSOPTION) 47 | 48 | force: 49 | 50 | all: $(TARGET) 51 | -------------------------------------------------------------------------------- /src/Detector/LeftJabCommandDetector.cc: -------------------------------------------------------------------------------- 1 | #include "LeftJabCommandDetector.h" 2 | 3 | namespace ty { 4 | 5 | LeftJabCommandDetector::LeftJabCommandDetector(User* _user) : CommandDetector(_user) 6 | { 7 | setCommand(1, 3, 8 | &LeftJabCommandDetector::isStand, 9 | &LeftJabCommandDetector::isLeftJab, 10 | &LeftJabCommandDetector::isStand); 11 | } 12 | 13 | LeftJabCommandDetector::~LeftJabCommandDetector(void) 14 | { 15 | } 16 | 17 | bool LeftJabCommandDetector::isStand(void) const 18 | { 19 | Vector shoulder = user->leftShoulder(); 20 | Vector elbow = user->leftElbow(); 21 | Vector hand = user->leftHand(); 22 | 23 | return user->leftArmIsBentRightAngle() 24 | && hand.Y > shoulder.Y 25 | && hand.Y > elbow.Y; 26 | } 27 | 28 | bool LeftJabCommandDetector::isLeftJab(void) const 29 | { 30 | Vector shoulder = user->leftShoulder(); 31 | Vector elbow = user->leftElbow(); 32 | Vector hand = user->leftHand(); 33 | 34 | return user->leftArmIsStraight() 35 | && hand.Y > shoulder.Y 36 | && hand.Y > elbow.Y; 37 | } 38 | 39 | } // namespace ty 40 | -------------------------------------------------------------------------------- /test/UserFactoryTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "UserFactory.h" 4 | 5 | TEST(UserFactoryTest, TestSetAndDeleteContext) { 6 | xn::Context context; 7 | xn::Player player; 8 | ty::User *user; 9 | 10 | // Init 11 | context.Init(); 12 | context.OpenFileRecording("./test/oni/depth_only.oni", player); 13 | player.SetRepeat(false); 14 | ty::UserFactory::setContext(&context); 15 | 16 | // Play 17 | context.StartGeneratingAll(); 18 | while (!player.IsEOF()) { context.WaitAndUpdateAll(); } 19 | 20 | user = ty::UserFactory::get(1); 21 | ASSERT_EQ(1, user->id()); 22 | 23 | // Stop 24 | context.StopGeneratingAll(); 25 | 26 | // Release 27 | ty::UserFactory::deleteContext(); 28 | player.Release(); 29 | context.Release(); 30 | } 31 | 32 | TEST(UserFactoryTest, TestGetThrowException) { 33 | ASSERT_THROW(ty::UserFactory::get(0), std::out_of_range); 34 | ASSERT_THROW(ty::UserFactory::get(ty::UserFactory::MAX + 1), std::out_of_range); 35 | 36 | ASSERT_NO_THROW(ty::UserFactory::get(1)); 37 | ASSERT_NO_THROW(ty::UserFactory::get(ty::UserFactory::MAX)); 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE-en: -------------------------------------------------------------------------------- 1 | MAHALO License (based on MIT License) 2 | 3 | Copyright (c) 2011 Wataru MIYAGUNI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | 1. The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 2. Shall be grateful for something (including, but not limited this software). 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/Detector/RightStraightCommandDetector.cc: -------------------------------------------------------------------------------- 1 | #include "RightStraightCommandDetector.h" 2 | 3 | namespace ty { 4 | 5 | RightStraightCommandDetector::RightStraightCommandDetector(User* _user) : CommandDetector(_user) 6 | { 7 | setCommand(1, 3, 8 | &RightStraightCommandDetector::isStand, 9 | &RightStraightCommandDetector::isRightStraight, 10 | &RightStraightCommandDetector::isStand); 11 | } 12 | 13 | RightStraightCommandDetector::~RightStraightCommandDetector(void) 14 | { 15 | } 16 | 17 | bool RightStraightCommandDetector::isStand(void) const 18 | { 19 | Vector shoulder = user->rightShoulder(); 20 | Vector elbow = user->rightElbow(); 21 | Vector hand = user->rightHand(); 22 | Vector upperArm = user->vectorRightUpperArm().reverse(); 23 | Vector forearm = user->vectorRightForearm(); 24 | 25 | return upperArm.withinAngle(forearm, 90.0f) 26 | && hand.Y > shoulder.Y 27 | && hand.Y > elbow.Y; 28 | } 29 | 30 | bool RightStraightCommandDetector::isRightStraight(void) const 31 | { 32 | Vector shoulder = user->rightShoulder(); 33 | Vector hand = user->rightHand(); 34 | 35 | return user->rightArmIsStraight() 36 | && hand.Y > shoulder.Y; 37 | } 38 | 39 | } // namespace ty 40 | -------------------------------------------------------------------------------- /samples/language/include/Controller.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_CONTROLLER_H_ 4 | #define _TYTHON_CONTROLLER_H_ 5 | 6 | #include 7 | #include 8 | #include "User.h" 9 | #include "WorldContext.h" 10 | #include "Compiler.h" 11 | #include "VM.h" 12 | #include "AbstractInputMethod.h" 13 | 14 | using std::string; 15 | 16 | class Controller { 17 | public: 18 | Controller(void); 19 | Controller(const XnChar* recordFileName); 20 | virtual ~Controller(void); 21 | 22 | void main(void); 23 | protected: 24 | 25 | private: 26 | /** 27 | * @return void 28 | */ 29 | void initXN(void); 30 | 31 | /** 32 | * 33 | */ 34 | xn::Context ctxGlobal; 35 | 36 | /** 37 | * 38 | */ 39 | ty::UserContext *ctxUser; 40 | 41 | ty::User *user; 42 | 43 | ty::WorldContext *world; 44 | 45 | /** 46 | * 47 | */ 48 | xn::DepthGenerator ctxDepth; 49 | 50 | /** 51 | * source code 52 | */ 53 | string source; 54 | 55 | /** 56 | * 57 | */ 58 | Compiler *compiler; 59 | 60 | /** 61 | * VM 62 | */ 63 | VM* vm; 64 | 65 | /** 66 | * InputMethod 67 | */ 68 | AbstractInputMethod* im; 69 | }; 70 | 71 | #endif // _TYTHON_CONTROLLER_H_ 72 | -------------------------------------------------------------------------------- /include/UserFactory.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_USER_FACTORY_H 4 | #define _TYTHON_USER_FACTORY_H 5 | 6 | #include "UserContext.h" 7 | #include "User.h" 8 | 9 | namespace ty { 10 | 11 | class UserFactory { 12 | public: 13 | /** 14 | * xn::Context をセットする 15 | * 16 | * UserContext を生成し、User List を構築する 17 | */ 18 | static void setContext(xn::Context *ctx); 19 | 20 | /** 21 | * User プールを破棄する 22 | */ 23 | static void deleteContext(void); 24 | 25 | /** 26 | * User を取得する 27 | * 28 | * @return ユーザID が userId の User 29 | */ 30 | static User* get(int userId); 31 | 32 | /** 33 | * User 最大数 34 | */ 35 | static const int MAX = 8; 36 | 37 | private: 38 | /** 39 | * コンストラクタ 40 | */ 41 | UserFactory(void) {} 42 | 43 | /** 44 | * コピーコンストラクタ 45 | */ 46 | UserFactory(const UserFactory& obj) {} 47 | 48 | /** 49 | * デストラクタ 50 | */ 51 | ~UserFactory(void); 52 | 53 | /** 54 | * UserContext インスタンス 55 | */ 56 | static UserContext* context; 57 | 58 | /** 59 | * User リスト 60 | * 61 | * @see UserFactory::MAX 62 | */ 63 | static User* list[UserFactory::MAX]; 64 | }; 65 | 66 | } // namespace ty 67 | 68 | #endif // _TYTHON_USER_FACTORY_H 69 | -------------------------------------------------------------------------------- /include/LocusDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_LOCUS_DETECTOR_H_ 4 | #define _TYTHON_LOCUS_DETECTOR_H_ 5 | 6 | #include "AbstractDetector.h" 7 | #include "Vector.h" 8 | 9 | namespace ty { 10 | 11 | class LocusDetector : public AbstractDetector { 12 | public: 13 | LocusDetector(User* _user); 14 | virtual ~LocusDetector(void); 15 | 16 | /** 17 | * ポーズをとっているか判定 18 | * 19 | * 定められた時間内に軌跡通りの動きをするか確認する 20 | * 21 | * @see trace() 22 | * @see timeLimit() 23 | * @see moveThreshold() 24 | * @return ポーズを検出できれば true 25 | */ 26 | bool isPosing(void); 27 | 28 | protected: 29 | /** 30 | * Function to detect trace 31 | */ 32 | bool trace(void) const; 33 | 34 | /** 35 | * トレース開始とみなせる移動量かどうかを判定する 36 | * 37 | * @param v_st 移動前のベクトル 38 | * @param v_ed 移動後のベクトル 39 | * 40 | * @return しきい値を超えていれば true 41 | */ 42 | bool isTraceCondition (const Vector& v_st, const Vector& v_ed) const; 43 | 44 | /** 45 | * Detection time limit (sec) 46 | */ 47 | const float timeLimit; 48 | 49 | /** 50 | * Move threshold distance 51 | * 52 | * トレース開始とみなす為の、座標移動距離のしきい値 53 | */ 54 | const float moveThreshold; 55 | 56 | private: 57 | }; 58 | 59 | } // namespace ty 60 | 61 | #endif // _TYTHON_LOCUS_DETECTOR_H_ 62 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include ./Makefile.defs 2 | 3 | TARGET_LIB = Tython 4 | TARGET = lib$(TARGET_LIB).so 5 | TEST_TARGET = libTythonTest 6 | TEST_XML = unittest.xml 7 | 8 | DOXYGEN = doxygen 9 | DOXYCONF = Tython.doxygen 10 | DOXYOUT = docs 11 | COVERAGE = $(TEST_XML) 12 | 13 | .SUFFIXES: .cc .o 14 | 15 | .PHONY: test test-all clean tags force all 16 | 17 | %.o : %.cc 18 | $(TEST_SRCS_DIR)/%.o : $(TEST_SRCS_DIR)/%.cc 19 | $(CXX) $(TEST_CXXFLAGS) -c $< -o $@ 20 | %.o : %.cc 21 | $(CXX) -fPIC $(CXXFLAGS) -c $< -o $@ 22 | 23 | $(TARGET): $(OBJS) 24 | $(CXX) -shared -o $@ $(OBJS) $(LIBS) 25 | 26 | $(TEST_TARGET): $(TARGET) $(TEST_OBJS) 27 | $(CXX) $(TEST_LIBS) -L. -l$(TARGET_LIB) $(TEST_OBJS) -o $@ 28 | 29 | test: $(TEST_TARGET) force 30 | GTEST_FILTER="-UserContextTest.*:UserFactoryTest.TestSetAndDeleteContext" \ 31 | ./$(TEST_TARGET) --gtest_output="xml:$(TEST_XML)" 32 | 33 | test-all: $(TEST_TARGET) force 34 | ./$(TEST_TARGET) --gtest_output="xml:$(TEST_XML)" 35 | 36 | clean: 37 | $(RM) $(RM_GC) 38 | $(RM) $(TARGET) $(TEST_TARGET) 39 | $(RM) $(OBJS) $(TEST_OBJS) 40 | $(RM) $(TAGSFILE) 41 | $(RM) $(OBJS_GCOV) 42 | $(RM) -r $(DOXYOUT) $(COVERAGE) 43 | cd $(SRCS_DIR) && $(RM) $(RM_GC) 44 | cd $(TEST_SRCS_DIR) && $(RM) $(RM_GC) 45 | 46 | 47 | tags: 48 | @$(TAGS) $(TAGSOPTION) 49 | 50 | doxygen: 51 | $(DOXYGEN) $(DOXYCONF) 52 | 53 | force: 54 | 55 | all: $(TARGET) 56 | -------------------------------------------------------------------------------- /samples/language/Makefile.defs: -------------------------------------------------------------------------------- 1 | # Source Path 2 | SRCS_DIR = src 3 | SRCS = $(wildcard $(SRCS_DIR)/**/*.cc) $(wildcard $(SRCS_DIR)/*.cc) 4 | OBJS_ALL = $(SRCS:.cc=.o) 5 | OBJS_MAIN = $(SRCS_DIR)/main.o 6 | OBJS = $(filter-out $(OBJS_MAIN), $(OBJS_ALL)) 7 | 8 | TEST_SRCS_DIR = test 9 | TEST_SRCS = $(wildcard $(TEST_SRCS_DIR)/*.cc) 10 | TEST_OBJS = $(TEST_SRCS:.cc=.o) 11 | 12 | # Tython Path 13 | TYTHON_INCLUDE_PATH = ../../include 14 | TYTHON_LIBRARY_PATH = ../../ 15 | 16 | # OpenNI Path 17 | OPENNI_INCLUDE_PATH = $(HOME)/.kinect/usr/include/ni 18 | OPENNI_LIBRARY_PATH = $(HOME)/.kinect/usr/lib 19 | 20 | # OpenCV Path 21 | OPENCV_INCLUDE_PATH = $(HOME)/.homebrew/include 22 | OPENCV_LIBRARY_PATH = $(HOME)/.homebrew/lib 23 | 24 | # Compile Option 25 | INCLUDE = -I./include -I$(OPENNI_INCLUDE_PATH) \ 26 | -I$(TYTHON_INCLUDE_PATH) \ 27 | -I$(OPENCV_INCLUDE_PATH) 28 | LIBS = -lm \ 29 | -L$(OPENNI_LIBRARY_PATH) -lOpenNI \ 30 | -L$(TYTHON_LIBRARY_PATH) -lTython \ 31 | -L$(OPENCV_LIBRARY_PATH) -lopencv_core -lopencv_highgui -lopencv_video -lopencv_imgproc 32 | CXXFLAGS = -Wall -fno-tree-pre -fno-strict-aliasing -msse3 -mssse3 $(INCLUDE) -g 33 | CXX = g++ 34 | 35 | TEST_CXXFLAGS = $(shell gmock-config --cppflags --cxxflags) $(CXXFLAGS) 36 | TEST_LIBS = -L$(shell gtest-config --libdir) -lgtest -L$(shell gmock-config --libdir) -lgmock $(LIBS) 37 | -------------------------------------------------------------------------------- /test/AbstractDetectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "AbstractDetector.h" 3 | #include "MockUser.h" 4 | 5 | using ::testing::Return; 6 | 7 | class SuccessAbstractDetector : public ty::AbstractDetector { 8 | public: 9 | SuccessAbstractDetector(ty::User* _user) : AbstractDetector(_user) {} 10 | 11 | bool isPosing(void) { 12 | return true; 13 | } 14 | }; 15 | 16 | class FailureAbstractDetector : public ty::AbstractDetector { 17 | public: 18 | FailureAbstractDetector(ty::User* _user) : AbstractDetector(_user) {} 19 | 20 | bool isPosing(void) { 21 | return false; 22 | } 23 | }; 24 | 25 | class AbstractDetectorTest : public testing::Test { 26 | public: 27 | virtual void SetUp() { 28 | user = new MockUser; 29 | s_object = new SuccessAbstractDetector(user); 30 | f_object = new FailureAbstractDetector(user); 31 | } 32 | 33 | virtual void TearDown() { 34 | delete f_object; 35 | delete s_object; 36 | delete user; 37 | } 38 | 39 | protected: 40 | SuccessAbstractDetector* s_object; 41 | FailureAbstractDetector* f_object; 42 | MockUser* user; 43 | }; 44 | 45 | TEST_F(AbstractDetectorTest, TestIsDetect) { 46 | ASSERT_TRUE(s_object->detect()); 47 | } 48 | 49 | TEST_F(AbstractDetectorTest, TestIsDetectError) { 50 | ASSERT_FALSE(f_object->detect()); 51 | } 52 | 53 | TEST_F(AbstractDetectorTest, TestIsDetectErrorNoCalibrated) { 54 | EXPECT_CALL(*user, isTracking()).WillOnce(Return(false)); 55 | ASSERT_FALSE(s_object->detect()); 56 | } 57 | -------------------------------------------------------------------------------- /src/Detector/ThanksCommandDetector.cc: -------------------------------------------------------------------------------- 1 | #include "ThanksCommandDetector.h" 2 | 3 | namespace ty { 4 | 5 | ThanksCommandDetector::ThanksCommandDetector(User* _user) : CommandDetector(_user) 6 | { 7 | setCommand(1, 2, 8 | &ThanksCommandDetector::isCrossArm, 9 | &ThanksCommandDetector::isBottomArm); 10 | } 11 | 12 | ThanksCommandDetector::~ThanksCommandDetector(void) 13 | { 14 | } 15 | 16 | bool ThanksCommandDetector::isCrossArm(void) 17 | { 18 | Vector rightForearm= user->vectorRightForearm(); 19 | Vector leftForearm = user->vectorLeftForearm(); 20 | Vector rightHand = user->rightHand(); 21 | Vector leftHand = user->leftHand(); 22 | Vector neck = user->neck(); 23 | Vector waist = user->waist(); 24 | 25 | return rightForearm.isOrthogonal(leftForearm) 26 | && rightHand.Y < neck.Y 27 | && leftHand.Y < neck.Y 28 | && rightHand.Y > waist.Y 29 | && leftHand.Y > waist.Y; 30 | } 31 | 32 | bool ThanksCommandDetector::isBottomArm(void) 33 | { 34 | Vector rightForearm= user->vectorRightForearm(); 35 | Vector rightUpperArm= user->vectorRightUpperArm(); 36 | Vector leftForearm = user->vectorLeftForearm(); 37 | Vector leftUpperArm = user->vectorLeftUpperArm(); 38 | Vector rightHand = user->rightHand(); 39 | Vector leftHand = user->leftHand(); 40 | Vector waist = user->waist(); 41 | 42 | return rightForearm.isStraight(rightUpperArm) 43 | && leftForearm.isStraight(leftUpperArm) 44 | && rightHand.Y < waist.Y 45 | && leftHand.Y < waist.Y; 46 | } 47 | 48 | } // namespace ty 49 | -------------------------------------------------------------------------------- /src/Detector/LeftHookCommandDetector.cc: -------------------------------------------------------------------------------- 1 | #include "LeftHookCommandDetector.h" 2 | 3 | namespace ty { 4 | 5 | LeftHookCommandDetector::LeftHookCommandDetector(User* _user) : CommandDetector(_user) 6 | { 7 | setCommand(1, 4, 8 | &LeftHookCommandDetector::isStand, 9 | &LeftHookCommandDetector::isLeftHookBefore, 10 | &LeftHookCommandDetector::isLeftHookAfter, 11 | &LeftHookCommandDetector::isStand); 12 | } 13 | 14 | LeftHookCommandDetector::~LeftHookCommandDetector(void) 15 | { 16 | } 17 | 18 | bool LeftHookCommandDetector::isStand(void) const 19 | { 20 | Vector shoulder = user->leftShoulder(); 21 | Vector elbow = user->leftElbow(); 22 | Vector hand = user->leftHand(); 23 | 24 | return user->leftArmIsBentRightAngle() 25 | && hand.Y > shoulder.Y 26 | && hand.Y > elbow.Y; 27 | } 28 | 29 | bool LeftHookCommandDetector::isLeftHookBefore(void) const 30 | { 31 | Vector shoulder = user->leftShoulder(); 32 | Vector elbow = user->leftElbow(); 33 | Vector hand = user->leftHand(); 34 | 35 | return user->leftArmIsBentRightAngle() 36 | && shoulder.X > hand.X 37 | && shoulder.X > elbow.X; 38 | } 39 | 40 | bool LeftHookCommandDetector::isLeftHookAfter(void) const 41 | { 42 | Vector shoulder = user->leftShoulder(); 43 | Vector elbow = user->leftElbow(); 44 | Vector hand = user->leftHand(); 45 | Vector neck = user->neck(); 46 | 47 | return shoulder.X < elbow.X 48 | && elbow.X < hand.X 49 | && neck.X < hand.X; 50 | } 51 | 52 | } // namespace ty 53 | -------------------------------------------------------------------------------- /samples/language/src/Renderer/AbstractRenderer.cc: -------------------------------------------------------------------------------- 1 | #include "AbstractRenderer.h" 2 | #include "util.h" 3 | 4 | AbstractRenderer::AbstractRenderer(ty::WorldContext *_ctx, ty::User* _user) 5 | : ctx(_ctx), user(_user) 6 | { 7 | XnMapOutputMode outputMode; 8 | ctx->imageGenerator()->GetMapOutputMode(outputMode); 9 | camera = ::cvCreateImage(cvSize(outputMode.nXRes, outputMode.nYRes), 10 | IPL_DEPTH_8U, 3); 11 | if (!camera) { 12 | throw std::runtime_error( "error : cvCreateImage" ); 13 | } 14 | } 15 | 16 | AbstractRenderer::~AbstractRenderer(void) 17 | { 18 | } 19 | 20 | void AbstractRenderer::draw(void) 21 | { 22 | ctx->updateImage(); 23 | ctx->updateDepth(); 24 | 25 | xn::ImageMetaData imageMD; 26 | ctx->imageGenerator()->GetMetaData(imageMD); 27 | 28 | char* dest = camera->imageData; 29 | const xn::RGB24Map& rgb = ctx->imageRGB24Map(); 30 | const XnLabel* label = user->scene()->Data(); 31 | 32 | for (int y = 0; y < ctx->imageHeight(); ++y) { 33 | for (int x = 0; x < ctx->imageWidth(); ++x) { 34 | XnRGB24Pixel pixel = rgb(x, y); 35 | 36 | if (label[y*ctx->imageWidth() + x]) { 37 | dest[0] = 255; 38 | dest[1] = 0; 39 | dest[2] = 0; 40 | } else { 41 | dest[0] = pixel.nRed; 42 | dest[1] = pixel.nGreen; 43 | dest[2] = pixel.nBlue; 44 | } 45 | dest += 3; 46 | } 47 | } 48 | 49 | ::cvCvtColor(camera, camera, CV_BGR2RGB); 50 | ::cvShowImage("KinectImage", camera); 51 | } 52 | -------------------------------------------------------------------------------- /src/Detector/RightUpperCommandDetector.cc: -------------------------------------------------------------------------------- 1 | #include "RightUpperCommandDetector.h" 2 | 3 | namespace ty { 4 | 5 | RightUpperCommandDetector::RightUpperCommandDetector(User* _user) : CommandDetector(_user) 6 | { 7 | setCommand(1, 4, 8 | &RightUpperCommandDetector::isStand, 9 | &RightUpperCommandDetector::isRightUpperBefore, 10 | &RightUpperCommandDetector::isRightUpperAfter, 11 | &RightUpperCommandDetector::isStand); 12 | } 13 | 14 | RightUpperCommandDetector::~RightUpperCommandDetector(void) 15 | { 16 | } 17 | 18 | bool RightUpperCommandDetector::isStand(void) const 19 | { 20 | Vector shoulder = user->rightShoulder(); 21 | Vector elbow = user->rightElbow(); 22 | Vector hand = user->rightHand(); 23 | 24 | return user->rightArmIsBentRightAngle() 25 | && hand.Y > shoulder.Y 26 | && hand.Y > elbow.Y; 27 | } 28 | 29 | bool RightUpperCommandDetector::isRightUpperBefore(void) const 30 | { 31 | Vector shoulder = user->rightShoulder(); 32 | Vector elbow = user->rightElbow(); 33 | Vector hand = user->rightHand(); 34 | Vector neck = user->neck(); 35 | 36 | return user->rightArmIsBentRightAngle() 37 | && shoulder.Y > hand.Y 38 | && shoulder.Y > elbow.Y 39 | && neck.X < hand.X; 40 | } 41 | 42 | bool RightUpperCommandDetector::isRightUpperAfter(void) const 43 | { 44 | Vector shoulder = user->rightShoulder(); 45 | Vector elbow = user->rightElbow(); 46 | Vector hand = user->rightHand(); 47 | Vector neck = user->neck(); 48 | 49 | return user->rightArmIsBentRightAngle() 50 | && shoulder.Y < hand.Y 51 | && neck.X < hand.X 52 | && neck.X < elbow.X; 53 | } 54 | 55 | } // namespace ty 56 | -------------------------------------------------------------------------------- /src/Detector/CommandDetector.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "CommandDetector.h" 3 | #include "Timer.h" 4 | 5 | namespace ty { 6 | 7 | CommandDetector::CommandDetector(User* _user) : AbstractDetector(_user) 8 | { 9 | commandList = NULL; 10 | resetCommand(); 11 | } 12 | 13 | CommandDetector::~CommandDetector(void) 14 | { 15 | if (commandList != NULL) { 16 | delete [] commandList; 17 | } 18 | } 19 | 20 | void CommandDetector::setCommand(XnUInt64 _timeLimit, int _commandNum, ...) 21 | { 22 | va_list ap; 23 | 24 | timeLimit = _timeLimit; 25 | commandNum = _commandNum; 26 | commandList = new Command[_commandNum]; 27 | 28 | va_start(ap, _commandNum); 29 | while (_commandNum > 0) { 30 | commandList[commandNum - _commandNum] = va_arg(ap, Command); 31 | _commandNum--; 32 | } 33 | va_end(ap); 34 | } 35 | 36 | bool CommandDetector::isPosing(void) 37 | { 38 | if (commandList == NULL) { 39 | return false; 40 | } 41 | 42 | if (!withinTimeLimit()) { 43 | resetCommand(); 44 | return false; 45 | } 46 | 47 | if ((this->*commandList[commandIndex])()) { 48 | nextCommand(); 49 | } 50 | 51 | if (commandIndex == commandNum) { 52 | resetCommand(); 53 | return true; 54 | } 55 | 56 | return false; 57 | } 58 | 59 | void CommandDetector::resetCommand(void) 60 | { 61 | detectionTime = 0; 62 | commandIndex = 0; 63 | } 64 | 65 | void CommandDetector::nextCommand(void) 66 | { 67 | if (commandIndex == 0) { 68 | detectionTime = timer->current(); 69 | } 70 | 71 | commandIndex++; 72 | } 73 | 74 | bool CommandDetector::withinTimeLimit(void) 75 | { 76 | return (commandIndex == 0) || ((timer->current() - detectionTime) <= timeLimit); 77 | } 78 | 79 | } // namespace ty 80 | -------------------------------------------------------------------------------- /test/MockVector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_MOCK_VECTOR_H 4 | #define _TYTHON_MOCK_VECTOR_H 5 | 6 | #include "Vector.h" 7 | 8 | namespace MockVector { 9 | const ty::Vector v00 = ty::Vector( 2.0f, 0.0f, 0.0f); 10 | const ty::Vector v30 = ty::Vector( 1.7320f, 1.0f, 0.0f); 11 | const ty::Vector v45 = ty::Vector( 1.4142f, 1.4142f, 0.0f); 12 | const ty::Vector v60 = ty::Vector( 1.0f, 1.7320f, 0.0f); 13 | const ty::Vector v90 = ty::Vector( 0.0f, 2.0f, 0.0f); 14 | const ty::Vector v120 = ty::Vector( -1.0f, 1.7320f, 0.0f); 15 | const ty::Vector v135 = ty::Vector(-1.4142f, 1.4142f, 0.0f); 16 | const ty::Vector v150 = ty::Vector(-1.7320f, 1.0f, 0.0f); 17 | const ty::Vector v180 = ty::Vector( -2.0f, 0.0f, 0.0f); 18 | const ty::Vector v210 = v30*-1; 19 | const ty::Vector v225 = v45*-1; 20 | const ty::Vector v240 = v60*-1; 21 | const ty::Vector v270 = v90*-1; 22 | const ty::Vector v300 = v120*-1; 23 | const ty::Vector v315 = v135*-1; 24 | const ty::Vector v330 = v150*-1; 25 | 26 | // [img:https://cacoo.com/diagrams/Bb3xMwCFtoBe92mD-EEFFA.png] 27 | const ty::Vector vHEAD = ty::Vector(0.0f, 5.0f, 0.0f); 28 | const ty::Vector vNECK = ty::Vector(0.0f, 3.0f, 0.0f); 29 | const ty::Vector vRIGHT_SHOULDER = ty::Vector(3.0f, 3.0f, 0.0f); 30 | const ty::Vector vRIGHT_ELBOW = ty::Vector(3.0f, 1.0f, 0.0f); 31 | const ty::Vector vRIGHT_HAND = ty::Vector(3.0f, -1.0f, 0.0f); 32 | const ty::Vector vLEFT_SHOULDER = ty::Vector(-3.0f, 3.0f, 0.0f); 33 | const ty::Vector vLEFT_ELBOW = ty::Vector(-3.0f, 1.0f, 0.0f); 34 | const ty::Vector vLEFT_HAND = ty::Vector(-3.0f, -1.0f, 0.0f); 35 | const ty::Vector vWAIST = ty::Vector(0.0f, 0.0f, 0.0f); 36 | 37 | }; 38 | 39 | #endif // _TYTHON_MOCK_VECTOR_H 40 | -------------------------------------------------------------------------------- /test/ThanksCommandDetectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ThanksCommandDetector.h" 3 | #include "MockUser.h" 4 | #include "MockVector.h" 5 | 6 | using ::testing::Return; 7 | 8 | class ThanksCommandDetectorTest : public testing::Test { 9 | public: 10 | virtual void SetUp() { 11 | mock = new MockUser; 12 | object = new ty::ThanksCommandDetector(mock); 13 | } 14 | 15 | virtual void TearDown() { 16 | delete object; 17 | delete mock; 18 | } 19 | protected: 20 | ty::ThanksCommandDetector* object; 21 | MockUser* mock; 22 | }; 23 | 24 | TEST_F(ThanksCommandDetectorTest, TestIsPosing) { 25 | EXPECT_CALL(*mock, neck()) 26 | .WillRepeatedly(Return(ty::Vector(0.0f, 1.0f, 0.0f))); 27 | EXPECT_CALL(*mock, waist()) 28 | .WillRepeatedly(Return(ty::Vector(0.0f, -1.0f, 0.0f))); 29 | EXPECT_CALL(*mock, rightHand()) 30 | .WillOnce(Return(ty::Vector(-1.0f, 0.5f, 0.0f))) 31 | .WillOnce(Return(ty::Vector(1.0f, -1.5f, 0.0f))); 32 | EXPECT_CALL(*mock, leftHand()) 33 | .WillOnce(Return(ty::Vector(1.0f, 0.5f, 0.0f))) 34 | .WillOnce(Return(ty::Vector(-1.0f, -1.5f, 0.0f))); 35 | 36 | EXPECT_CALL(*mock, vectorRightUpperArm()) 37 | .WillOnce(Return(MockVector::v225)); 38 | EXPECT_CALL(*mock, vectorLeftUpperArm()) 39 | .WillOnce(Return(MockVector::v315)); 40 | EXPECT_CALL(*mock, vectorRightForearm()) 41 | .WillOnce(Return(MockVector::v45)) 42 | .WillOnce(Return(MockVector::v225)); 43 | EXPECT_CALL(*mock, vectorLeftForearm()) 44 | .WillOnce(Return(MockVector::v135)) 45 | .WillOnce(Return(MockVector::v315)); 46 | 47 | ASSERT_FALSE(object->isPosing()); 48 | ASSERT_TRUE(object->isPosing()); 49 | } 50 | 51 | TEST_F(ThanksCommandDetectorTest, TestIsPosingError) { 52 | ASSERT_FALSE(object->isPosing()); 53 | ASSERT_FALSE(object->isPosing()); 54 | } 55 | -------------------------------------------------------------------------------- /test/LeftJabCommandDetectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "LeftJabCommandDetector.h" 3 | #include "MockUser.h" 4 | #include "MockVector.h" 5 | 6 | using ::testing::Return; 7 | 8 | class LeftJabCommandDetectorTest : public testing::Test { 9 | public: 10 | virtual void SetUp() { 11 | mock = new MockUser; 12 | object = new ty::LeftJabCommandDetector(mock); 13 | } 14 | 15 | virtual void TearDown() { 16 | delete object; 17 | delete mock; 18 | } 19 | protected: 20 | ty::LeftJabCommandDetector* object; 21 | MockUser* mock; 22 | }; 23 | 24 | #define SET_SKELETON_CALL() do { \ 25 | EXPECT_CALL(*mock, leftShoulder()) \ 26 | .WillRepeatedly(Return(ty::Vector(0.0f, 1.0f, 0.0f))); \ 27 | EXPECT_CALL(*mock, leftElbow()) \ 28 | .WillRepeatedly(Return(ty::Vector(0.0f, 1.0f, 0.0f))); \ 29 | EXPECT_CALL(*mock, leftHand()) \ 30 | .WillRepeatedly(Return(ty::Vector(0.0f, 3.0f, 0.0f))); \ 31 | } while (0) 32 | 33 | TEST_F(LeftJabCommandDetectorTest, TestIsStand) { 34 | SET_SKELETON_CALL(); 35 | EXPECT_CALL(*mock, leftArmIsBentRightAngle()).WillOnce(Return(true)); 36 | ASSERT_TRUE(object->isStand()); 37 | } 38 | 39 | TEST_F(LeftJabCommandDetectorTest, TestIsStandError) { 40 | SET_SKELETON_CALL(); 41 | EXPECT_CALL(*mock, leftArmIsBentRightAngle()).WillOnce(Return(false)); 42 | ASSERT_FALSE(object->isStand()); 43 | } 44 | 45 | TEST_F(LeftJabCommandDetectorTest, TestIsLeftJab) { 46 | SET_SKELETON_CALL(); 47 | EXPECT_CALL(*mock, leftArmIsStraight()).WillOnce(Return(true)); 48 | ASSERT_TRUE(object->isLeftJab()); 49 | } 50 | 51 | TEST_F(LeftJabCommandDetectorTest, TestIsLeftJabError) { 52 | SET_SKELETON_CALL(); 53 | EXPECT_CALL(*mock, leftArmIsStraight()).WillOnce(Return(false)); 54 | ASSERT_FALSE(object->isLeftJab()); 55 | } 56 | -------------------------------------------------------------------------------- /test/OwataPoseDetectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "OwataPoseDetector.h" 3 | #include "MockUser.h" 4 | 5 | using ::testing::Return; 6 | 7 | class OwataPoseDetectorTest : public testing::Test { 8 | public: 9 | virtual void SetUp() { 10 | mock = new MockUser; 11 | object = new ty::OwataPoseDetector(mock); 12 | } 13 | 14 | virtual void TearDown() { 15 | delete object; 16 | delete mock; 17 | } 18 | protected: 19 | ty::OwataPoseDetector* object; 20 | MockUser* mock; 21 | }; 22 | 23 | #define SET_SKELETON_CALL() do { \ 24 | EXPECT_CALL(*mock, vectorRightUpperArm()) \ 25 | .WillRepeatedly(Return(ty::Vector(1.4f, 1.4f, 0.0f))); \ 26 | EXPECT_CALL(*mock, vectorLeftUpperArm()) \ 27 | .WillRepeatedly(Return(ty::Vector(-1.4f, 1.4f, 0.0f))); \ 28 | EXPECT_CALL(*mock, vectorHead()) \ 29 | .WillRepeatedly(Return(ty::Vector(0.0f, 1.4f, 0.0f))); \ 30 | EXPECT_CALL(*mock, head()) \ 31 | .WillRepeatedly(Return(ty::Vector(0.0f, 1.0f, 0.0f))); \ 32 | EXPECT_CALL(*mock, rightHand()) \ 33 | .WillRepeatedly(Return(ty::Vector(0.0f, 2.0f, 0.0f))); \ 34 | EXPECT_CALL(*mock, leftHand()) \ 35 | .WillRepeatedly(Return(ty::Vector(0.0f, 2.0f, 0.0f))); \ 36 | } while (0) 37 | 38 | TEST_F(OwataPoseDetectorTest, TestIsPosing) { 39 | SET_SKELETON_CALL(); 40 | EXPECT_CALL(*mock, rightArmIsStraight()).WillRepeatedly(Return(true)); 41 | EXPECT_CALL(*mock, leftArmIsStraight()).WillRepeatedly(Return(true)); 42 | 43 | ASSERT_TRUE(object->isPosing()); 44 | } 45 | 46 | TEST_F(OwataPoseDetectorTest, TestIsPosingError) { 47 | SET_SKELETON_CALL(); 48 | EXPECT_CALL(*mock, rightArmIsStraight()).WillRepeatedly(Return(true)); 49 | EXPECT_CALL(*mock, leftArmIsStraight()).WillRepeatedly(Return(false)); 50 | 51 | ASSERT_FALSE(object->isPosing()); 52 | } 53 | -------------------------------------------------------------------------------- /test/RightStraightCommandDetectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "RightStraightCommandDetector.h" 3 | #include "MockUser.h" 4 | #include "MockVector.h" 5 | 6 | using ::testing::Return; 7 | 8 | class RightStraightCommandDetectorTest : public testing::Test { 9 | public: 10 | virtual void SetUp() { 11 | mock = new MockUser; 12 | object = new ty::RightStraightCommandDetector(mock); 13 | } 14 | 15 | virtual void TearDown() { 16 | delete object; 17 | delete mock; 18 | } 19 | protected: 20 | ty::RightStraightCommandDetector* object; 21 | MockUser* mock; 22 | }; 23 | 24 | #define SET_SKELETON_CALL() do { \ 25 | EXPECT_CALL(*mock, rightShoulder()) \ 26 | .WillRepeatedly(Return(ty::Vector(0.0f, 1.0f, 0.0f))); \ 27 | EXPECT_CALL(*mock, rightElbow()) \ 28 | .WillRepeatedly(Return(ty::Vector(0.0f, 1.0f, 0.0f))); \ 29 | EXPECT_CALL(*mock, rightHand()) \ 30 | .WillRepeatedly(Return(ty::Vector(0.0f, 3.0f, 0.0f))); \ 31 | } while (0) 32 | 33 | TEST_F(RightStraightCommandDetectorTest, TestIsStand) { 34 | SET_SKELETON_CALL(); 35 | EXPECT_CALL(*mock, vectorRightUpperArm()) 36 | .WillRepeatedly(Return(MockVector::v00)); 37 | EXPECT_CALL(*mock, vectorRightForearm()) 38 | .WillRepeatedly(Return(MockVector::v120)); 39 | 40 | ASSERT_TRUE(object->isStand()); 41 | } 42 | 43 | TEST_F(RightStraightCommandDetectorTest, TestIsStandError) { 44 | SET_SKELETON_CALL(); 45 | EXPECT_CALL(*mock, vectorRightUpperArm()) 46 | .WillOnce(Return(MockVector::v00)); 47 | EXPECT_CALL(*mock, vectorRightForearm()) 48 | .WillOnce(Return(MockVector::v60)); 49 | 50 | ASSERT_FALSE(object->isStand()); 51 | } 52 | 53 | TEST_F(RightStraightCommandDetectorTest, TestIsRightStraight) { 54 | SET_SKELETON_CALL(); 55 | EXPECT_CALL(*mock, rightArmIsStraight()).WillOnce(Return(true)); 56 | ASSERT_TRUE(object->isRightStraight()); 57 | } 58 | 59 | TEST_F(RightStraightCommandDetectorTest, TestIsRightStraightError) { 60 | SET_SKELETON_CALL(); 61 | EXPECT_CALL(*mock, rightArmIsStraight()).WillOnce(Return(false)); 62 | ASSERT_FALSE(object->isRightStraight()); 63 | } 64 | -------------------------------------------------------------------------------- /README.mkdn: -------------------------------------------------------------------------------- 1 | 肉体言語 Tython 2 | ================== 3 | 4 | [![Stillmaintained](http://stillmaintained.com/gongo/Tython.png)](http://stillmaintained.com/gongo/Tython) 5 | 6 | Tython is programming language, interface and exercise. 7 | 8 | News 9 | --------- 10 | 11 | OpenNI 1 is closed on April 23, 2014. Thanks for muscle play!! :pizza: 12 | 13 | Article 14 | --------- 15 | 16 | [肉体言語 Tython - 質のないDiary H](http://d.hatena.ne.jp/gongoZ/20110514/1305372647) 17 | 18 | ### Demo 19 | [Youtube - 肉体言語 Tython 「Hello, World!」](http://www.youtube.com/watch?v=4iSzg9bOtCY) 20 | 21 | ### Presentation 22 | [肉体言語 Tython - slideshare](http://www.slideshare.net/gongoZ/tython-7953587) 23 | 24 | Requirements 25 | ---------------- 26 | 27 | ### Devices 28 | 29 | 1. Xbox 360® Kinect™ Sensor [http://www.xbox.com/ja-JP/xbox360/accessories/kinect/Home](http://www.xbox.com/ja-JP/xbox360/accessories/kinect/Home) 30 | 31 | ### Libraries 32 | 33 | 1. OpenNI v1.3.2.3 34 | * source [https://github.com/OpenNI/OpenNI/tree/unstable](https://github.com/OpenNI/OpenNI/tree/unstable) 35 | * binary [http://www.openni.org/downloadfiles/opennimodules/openni-binaries/20-latest-unstable](http://www.openni.org/downloadfiles/opennimodules/openni-binaries/20-latest-unstable) 36 | 2. SensorKinect v5.0.3.4 - OpenNI Compliant Hardware 37 | * source/binary [https://github.com/avin2/SensorKinect](https://github.com/avin2/SensorKinect) 38 | 3. NITE v1.4.1.2 - OpenNI Compliant Middleware 39 | * binary [http://www.openni.org/downloadfiles/opennimodules/openni-compliant-middleware-binaries/33-latest-unstable](http://www.openni.org/downloadfiles/opennimodules/openni-compliant-middleware-binaries/33-latest-unstable) 40 | 41 | ### Optional (To test) 42 | 43 | 1. GoogleTest v1.5.0 - Google C++ Testing Framework 44 | [http://code.google.com/p/googletest/](http://code.google.com/p/googletest/) 45 | 2. GoogleMock v1.5.0 - Google C++ Mocking Framework 46 | [http://code.google.com/p/googlemock/](http://code.google.com/p/googlemock/) 47 | 48 | Make Tython Library 49 | -------------------- 50 | 51 | ### Build 52 | 53 | $ make 54 | 55 | ### Run tests 56 | 57 | $ make test 58 | $ make test-all # slow test with .oni file 59 | 60 | ### Coverage measure 61 | 62 | $ make -f Makefile.coverage coverage 63 | $ $(BROWSER) ./gcov/index.html 64 | 65 | 66 | Future 67 | --------- 68 | 69 | -------------------------------------------------------------------------------- /include/CommandDetector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_COMMAND_DETECTOR_H_ 4 | #define _TYTHON_COMMAND_DETECTOR_H_ 5 | 6 | #include "AbstractDetector.h" 7 | 8 | namespace ty { 9 | 10 | class CommandDetector : public AbstractDetector { 11 | public: 12 | /** 13 | * @brief コンストラクタ 14 | * 15 | * コマンドのリストと経過時間を初期化する 16 | * 17 | * @param _user User インスタンス 18 | */ 19 | CommandDetector(User* _user); 20 | 21 | /** 22 | * @brief デストラクタ 23 | * 24 | * コマンドリストがセットされていれば、delete する 25 | */ 26 | virtual ~CommandDetector(void); 27 | 28 | /** 29 | * @brief ポーズをとっているか判定 30 | * 31 | * 定められた時間内に指定された順番の Pose をしたかを確認する 32 | * 33 | * @return ポーズを検出できれば true 34 | */ 35 | bool isPosing(void); 36 | 37 | protected: 38 | /** 39 | * @brief 制限時間やポーズなど、コマンドに関する設定を行う 40 | * 41 | * @param _timeLimit this->timeLimit 42 | * @param _commandNum this->commandNum 43 | * @param ... ポーズ検出関数 44 | */ 45 | void setCommand(XnUInt64 _timeLimit, int _commandNum, ...); 46 | 47 | /** 48 | * @brief コマンドとなるポーズを検出するメソッドの typename 49 | */ 50 | typedef bool (CommandDetector::*Command)(void); 51 | 52 | private: 53 | /** 54 | * @brief 検出状況をリセットする 55 | */ 56 | void resetCommand(void); 57 | 58 | /** 59 | * @brief 次のポーズの検出を開始する 60 | */ 61 | void nextCommand(void); 62 | 63 | /** 64 | * @brief 制限時間内かどうかを判定する 65 | * 66 | * @return 制限時間内であれば true 67 | */ 68 | bool withinTimeLimit(void); 69 | 70 | /** 71 | * @brief 最初のポーズ検出後からの経過時間 72 | */ 73 | XnUInt64 elapsedTime; 74 | 75 | /** 76 | * @brief 一番最後にポーズ検出したときの時間 77 | */ 78 | XnUInt64 detectionTime; 79 | 80 | /** 81 | * @brief ポーズを検出するメソッドのリスト 82 | */ 83 | Command *commandList; 84 | 85 | /** 86 | * @brief Current index of traceList[] 87 | * 88 | * @see commandList 89 | */ 90 | int commandIndex; 91 | 92 | /** 93 | * @brief コマンド達成に必要なポーズの数 94 | */ 95 | int commandNum; 96 | 97 | /** 98 | * @brief 制限時間 99 | */ 100 | XnUInt64 timeLimit; 101 | }; 102 | 103 | } // namespace 104 | 105 | #endif // _TYTHON_COMMAND_DETECTOR_H_ 106 | -------------------------------------------------------------------------------- /samples/language/test/CompilerTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Compiler.h" 3 | 4 | class CompilerTest : public testing::Test { 5 | public: 6 | Compiler *object; 7 | protected: 8 | virtual void SetUp() { 9 | object = Compiler::instance(); 10 | } 11 | }; 12 | 13 | TEST_F(CompilerTest, TestGetInstance) { 14 | Compiler *object2 = Compiler::instance(); 15 | 16 | ASSERT_TRUE(NULL != object); 17 | ASSERT_TRUE(object == object2); 18 | } 19 | 20 | TEST_F(CompilerTest, TestCompile) { 21 | std::vector insns = object->compile("@aaa@aa@"); 22 | ASSERT_EQ("add", insns.at(0)->op); 23 | ASSERT_EQ("sub", insns.at(1)->op); 24 | } 25 | 26 | TEST_F(CompilerTest, TestCompileErrorOfSyntax) { 27 | ASSERT_TRUE(object->compile("ag").empty()); 28 | } 29 | 30 | TEST_F(CompilerTest, TestCompileErrorOfUnableToTreat) { 31 | //ASSERT_TRUE(object->compile("a@a! ").empty()); 32 | } 33 | 34 | TEST_F(CompilerTest, TestScan) { 35 | string str = "Thanks!!"; 36 | string key1 = "T"; 37 | string key2 = "Tha"; 38 | string key3 = "Thanks!!"; 39 | string key4 = "Thanks!!!"; 40 | string key5 = "ank"; 41 | 42 | ASSERT_EQ(1, object->scan(str, key1, 0)); 43 | ASSERT_EQ(1, object->scan(str, key1, 1)); 44 | 45 | ASSERT_EQ(3, object->scan(str, key2, 0)); 46 | ASSERT_EQ(1, object->scan(str, key2, 1)); 47 | 48 | ASSERT_EQ(8, object->scan(str, key3, 0)); 49 | ASSERT_EQ(1, object->scan(str, key3, 1)); 50 | 51 | ASSERT_EQ(0, object->scan(str, key4, 0)); 52 | 53 | ASSERT_EQ(0, object->scan(str, key5, 0)); 54 | ASSERT_EQ(5, object->scan(str, key5, 2)); 55 | ASSERT_EQ(3, object->scan(str, key5, 3)); 56 | } 57 | 58 | TEST_F(CompilerTest, TestInput) { 59 | unsigned int index = 0; 60 | 61 | ASSERT_EQ(26, object->input("aaa@a@g", index)); // +11010 = 26 62 | ASSERT_EQ(7, index); 63 | 64 | index = 3; 65 | ASSERT_EQ(2, object->input("aaaaa@g", index)); // +10 = 2 66 | ASSERT_EQ(7, index); 67 | 68 | index = 0; 69 | ASSERT_EQ(1, object->input("aagaa", index)); // +1 = 1 70 | ASSERT_EQ(3, index); 71 | 72 | index = 0; 73 | ASSERT_EQ(-26, object->input("@aa@a@g", index)); // -11010 = -26 74 | ASSERT_EQ(7, index); 75 | 76 | index = 3; 77 | ASSERT_EQ(-2, object->input("@aa@a@g", index)); // -10 = -2 78 | ASSERT_EQ(7, index); 79 | 80 | index = 0; 81 | ASSERT_EQ(-1, object->input("@agaa", index)); // -1 = -1 82 | ASSERT_EQ(3, index); 83 | 84 | index = 3; 85 | ASSERT_THROW(object->input("agaaa", index), int); 86 | } 87 | -------------------------------------------------------------------------------- /src/WorldContext.cc: -------------------------------------------------------------------------------- 1 | #include "WorldContext.h" 2 | #include "util.h" 3 | 4 | namespace ty { 5 | 6 | WorldContext::WorldContext(xn::Context *_ctx, const int nodeType) : ctxGlobal(_ctx) 7 | { 8 | if (nodeType & NODE_USE_IMAGE) { 9 | xnRuntimeCheck(ctxGlobal->FindExistingNode(XN_NODE_TYPE_IMAGE, ctxImage)); 10 | } 11 | 12 | if (nodeType & NODE_USE_DEPTH) { 13 | xnRuntimeCheck(ctxGlobal->FindExistingNode(XN_NODE_TYPE_DEPTH, ctxDepth)); 14 | } 15 | 16 | if (ctxDepth.IsValid() 17 | && ctxDepth.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT) 18 | && ctxImage.IsValid()) { 19 | xnRuntimeCheck(ctxDepth.GetAlternativeViewPointCap().SetViewPoint(ctxImage)); 20 | } 21 | 22 | updateDepth(); 23 | updateImage(); 24 | } 25 | 26 | WorldContext::~WorldContext(void) 27 | { 28 | ctxImage.Release(); 29 | ctxDepth.Release(); 30 | } 31 | 32 | void WorldContext::updateDepth(void) 33 | { 34 | if (ctxDepth.IsValid()) { 35 | ctxDepth.GetMetaData(metaDepth); 36 | } 37 | } 38 | 39 | void WorldContext::updateImage(void) 40 | { 41 | if (ctxImage.IsValid()) { 42 | ctxImage.GetMetaData(metaImage); 43 | } 44 | } 45 | 46 | xn::DepthGenerator* WorldContext::depthGenerator(void) 47 | { 48 | return &ctxDepth; 49 | } 50 | 51 | xn::ImageGenerator* WorldContext::imageGenerator(void) 52 | { 53 | return &ctxImage; 54 | } 55 | 56 | XnUInt32 WorldContext::imageWidth(void) const 57 | { 58 | return metaImage.XRes(); 59 | } 60 | 61 | XnUInt32 WorldContext::imageHeight(void) const 62 | { 63 | return metaImage.YRes(); 64 | } 65 | 66 | XnUInt32 WorldContext::depthWidth(void) const 67 | { 68 | return metaDepth.XRes(); 69 | } 70 | 71 | XnUInt32 WorldContext::depthHeight(void) const 72 | { 73 | return metaDepth.YRes(); 74 | } 75 | 76 | const XnDepthPixel* WorldContext::depthData(void) const 77 | { 78 | return metaDepth.Data(); 79 | } 80 | 81 | const xn::RGB24Map& WorldContext::imageRGB24Map(void) const 82 | { 83 | return metaImage.RGB24Map(); 84 | } 85 | 86 | void WorldContext::enableRecord(const XnChar* recordFileName) 87 | { 88 | xnRuntimeCheck(ctxRecorder.Create(*ctxGlobal)); 89 | xnRuntimeCheck(ctxRecorder.SetDestination(XN_RECORD_MEDIUM_FILE, recordFileName)); 90 | 91 | if (ctxImage.IsValid()) { 92 | xnRuntimeCheck(ctxRecorder.AddNodeToRecording(ctxImage, XN_CODEC_NULL)); 93 | } 94 | 95 | if (ctxDepth.IsValid()) { 96 | xnRuntimeCheck(ctxRecorder.AddNodeToRecording(ctxDepth, XN_CODEC_NULL)); 97 | } 98 | 99 | xnRuntimeCheck(ctxRecorder.Record()); 100 | } 101 | 102 | } // namespace ty 103 | -------------------------------------------------------------------------------- /samples/language/include/Compiler.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_COMPILER_H_ 4 | #define _TYTHON_COMPILER_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "Instruction.h" 10 | 11 | using std::string; 12 | using std::stack; 13 | using std::vector; 14 | 15 | class Compiler { 16 | public: 17 | /** 18 | * Compiler インスタンスを返す 19 | * 20 | * @return Compiler インスタンス 21 | */ 22 | static Compiler* instance(void); 23 | 24 | /** 25 | * コンパイル 26 | * 27 | * @param sourceCode コンパイルするコード 28 | * @return 命令のリスト / コンパイルに失敗した場合 NULL 29 | */ 30 | std::vector compile(string sourceCode); 31 | 32 | /** 33 | * target が str[index] から全文字含まれているか調べる 34 | * 35 | * 36 | * Compiler object = Compiler::instance(); 37 | * object->scan("aiueo", "aiu", 0); // -> 4 38 | * object->scan("aiueo", "iu", 0); // -> 0 39 | * object->scan("aiueo", "iu", 1); // -> 4 40 | * 41 | * 42 | * @param str 検索対象文字列 43 | * @param target 検索する文字列 44 | * @param index 検索開始する str の位置 45 | * @return target が見つかった場合、target の最後の文字 + 1に位置する str のインデックス 46 | * 見つからなければ index 47 | */ 48 | int scan(string str, string target, int index); 49 | 50 | /** 51 | * str[index] から、指定された区切り文字までの間にある文字を 52 | * 2進数として認識し、その値を返す 53 | * 54 | * インデックスはこのメソッド内で更新される 55 | * 56 | * @todo 区切り文字とか、2進数変換用文字をちゃんと定義しなきゃ 57 | * 58 | * 59 | * // a = 1, @ = 0, g = 区切り文字とする 60 | * // 負数を表す場合、先頭文字を @ にする 61 | * 62 | * Compiler object = Compiler::instance(); 63 | * object->input("aa@a@g", 0); // -> +(1010)2 = 10 64 | * object->input("aa@a@g", 2); // -> +(10)2 = 10 65 | * object->input("aaag@@a", 0); // -> +(11)2 = 3 66 | * object->input("@a@a@g", 0); // -> -(1010)2 = -10 67 | * object->input("@aag@@a", 0); // -> -(11)2 = -3 68 | * object->input("aaaaa", 0); // -> throw "区切り文字がない" 69 | * 70 | * 71 | * @param str 解析対象文字列 72 | * @param index 解析開始インデックス 73 | * @retrun 解析された値 74 | * @throw 75 | */ 76 | int input(string str, unsigned int& index); 77 | 78 | Instruction* op(string str, int arg); 79 | Instruction* op(string str); 80 | 81 | /** 82 | * スタック 83 | */ 84 | stack _stack; 85 | 86 | private: 87 | /** 88 | * コンストラクタ 89 | * 90 | * Singleton のため、private で定義 91 | */ 92 | Compiler(void) {} 93 | 94 | /** 95 | * コピーコンストラクタ 96 | * 97 | * Singleton のため、private で定義 98 | */ 99 | Compiler(const Compiler& obj) {} 100 | 101 | /** 102 | * Compiler クラスインスタンス 103 | */ 104 | static Compiler* _instance; 105 | 106 | /** 107 | * コンパイラが扱える文字群 108 | */ 109 | static string _treat; 110 | }; 111 | 112 | #endif // _TYTHON_COMPILER_H_ 113 | -------------------------------------------------------------------------------- /test/WorldContextTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "WorldContext.h" 4 | 5 | #define ONI_INIT(onifile) do { \ 6 | context.Init(); \ 7 | context.OpenFileRecording(onifile, player); \ 8 | player.SetRepeat(false); \ 9 | } while (0) 10 | 11 | #define ONI_FINISH() do { \ 12 | player.Release(); \ 13 | context.Release(); \ 14 | } while (0) 15 | 16 | 17 | TEST(WorldContextTest, TestDepth) { 18 | xn::Context context; 19 | xn::Player player; 20 | ty::WorldContext *world; 21 | 22 | ONI_INIT("./test/oni/depth_only.oni"); 23 | 24 | ASSERT_NO_THROW(world = new ty::WorldContext(&context, 25 | ty::WorldContext::NODE_USE_DEPTH)); 26 | ASSERT_EQ(640, (int)world->depthWidth()); 27 | ASSERT_EQ(480, (int)world->depthHeight()); 28 | 29 | ONI_FINISH(); 30 | } 31 | 32 | TEST(WorldContextTest, TestImage) { 33 | xn::Context context; 34 | xn::Player player; 35 | ty::WorldContext *world; 36 | 37 | ONI_INIT("./test/oni/image_only.oni"); 38 | 39 | ASSERT_NO_THROW(world = new ty::WorldContext(&context, 40 | ty::WorldContext::NODE_USE_IMAGE)); 41 | ASSERT_EQ(640, (int)world->imageWidth()); 42 | ASSERT_EQ(480, (int)world->imageHeight()); 43 | 44 | ONI_FINISH(); 45 | } 46 | 47 | TEST(WorldContextTest, TestDepthAndImage) { 48 | xn::Context context; 49 | xn::Player player; 50 | 51 | ONI_INIT("./test/oni/image_depth.oni"); 52 | ASSERT_NO_THROW(ty::WorldContext world(&context, 53 | ty::WorldContext::NODE_USE_IMAGE | 54 | ty::WorldContext::NODE_USE_DEPTH)); 55 | ONI_FINISH(); 56 | } 57 | 58 | TEST(WorldContextTest, TestImageFailure) { 59 | xn::Context context; 60 | xn::Player player; 61 | 62 | ONI_INIT("./test/oni/depth_only.oni"); 63 | ASSERT_THROW(ty::WorldContext world(&context, 64 | ty::WorldContext::NODE_USE_IMAGE | 65 | ty::WorldContext::NODE_USE_DEPTH), 66 | std::runtime_error); 67 | ONI_FINISH(); 68 | } 69 | 70 | TEST(WorldContextTest, TestDepthFailure) { 71 | xn::Context context; 72 | xn::Player player; 73 | 74 | ONI_INIT("./test/oni/image_only.oni"); 75 | ASSERT_THROW(ty::WorldContext world(&context, 76 | ty::WorldContext::NODE_USE_IMAGE | 77 | ty::WorldContext::NODE_USE_DEPTH), 78 | std::runtime_error); 79 | ONI_FINISH(); 80 | } 81 | 82 | // TEST(UserFactoryTest, TestGetThrowException) { 83 | // ASSERT_THROW(ty::UserFactory::get(0), std::out_of_range); 84 | // ASSERT_THROW(ty::UserFactory::get(ty::UserFactory::MAX + 1), std::out_of_range); 85 | 86 | // ASSERT_NO_THROW(ty::UserFactory::get(1)); 87 | // ASSERT_NO_THROW(ty::UserFactory::get(ty::UserFactory::MAX)); 88 | // } 89 | -------------------------------------------------------------------------------- /samples/language/src/Controller.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Controller.h" 4 | #include "DefaultInputMethod.h" 5 | #include "AbstractRenderer.h" 6 | #include "util.h" 7 | #include "Instruction.h" 8 | #include "UserFactory.h" 9 | #include 10 | #include 11 | 12 | AbstractRenderer *renderer; 13 | xn::Player player; 14 | Controller::Controller(const XnChar* recordFileName) 15 | { 16 | ty::xnRuntimeCheck(ctxGlobal.Init()); 17 | ty::xnRuntimeCheck(ctxGlobal.OpenFileRecording(recordFileName, player)); 18 | player.SetRepeat(false); 19 | 20 | initXN(); 21 | 22 | ctxGlobal.StartGeneratingAll(); 23 | } 24 | Controller::Controller(void) 25 | { 26 | ty::xnRuntimeCheck(ctxGlobal.InitFromXmlFile("Tython.xml")); 27 | ty::xnRuntimeCheck(ctxGlobal.SetGlobalMirror(true)); 28 | 29 | initXN(); 30 | 31 | world->enableRecord("hoge.oni"); 32 | ctxGlobal.StartGeneratingAll(); 33 | } 34 | 35 | Controller::~Controller(void) 36 | { 37 | delete im; 38 | delete renderer; 39 | delete user; 40 | delete ctxUser; 41 | delete world; 42 | ctxGlobal.StopGeneratingAll(); 43 | ctxGlobal.Release(); 44 | } 45 | 46 | void Controller::main(void) 47 | { 48 | while (!player.IsValid() || !player.IsEOF()) { 49 | ctxGlobal.WaitAndUpdateAll(); 50 | 51 | renderer->draw(); 52 | 53 | if ((cvWaitKey(30) & 0xff) == 'q') break; 54 | 55 | IMmap inputList = im->input(); 56 | IMquit quitList = im->quit(); 57 | 58 | for (IMmap::iterator it = inputList.begin(); it != inputList.end(); ++it) { 59 | if (it->second->detect()) { 60 | source += it->first; 61 | //printf("%s\n", it->first.c_str()); 62 | switch ((int)(*it->first.c_str())) { 63 | case 97: 64 | printf("左ジャブ\n"); 65 | break; 66 | case 64: 67 | printf("右ストレート\n"); 68 | break; 69 | case 32: 70 | printf("左フック\n"); 71 | break; 72 | case 103: 73 | printf("右アッパー\n"); 74 | break; 75 | } 76 | } 77 | } 78 | 79 | for (IMquit::iterator it = quitList.begin(); it != quitList.end(); ++it) { 80 | if ((*it)->detect()) { 81 | printf("%s\n", source.c_str()); 82 | std::vector insns = compiler->compile(source); 83 | vm->run(insns); 84 | printf("\n"); 85 | return; 86 | } 87 | } 88 | } 89 | } 90 | 91 | void Controller::initXN(void) 92 | { 93 | ty::UserFactory::setContext(&ctxGlobal); 94 | user = ty::UserFactory::get(1); 95 | world = new ty::WorldContext(&ctxGlobal, 96 | ty::WorldContext::NODE_USE_IMAGE | 97 | ty::WorldContext::NODE_USE_DEPTH 98 | ); 99 | renderer = new AbstractRenderer(world, user); 100 | im = new DefaultInputMethod(user); 101 | compiler = Compiler::instance(); 102 | vm = VM::instance(); 103 | } 104 | 105 | -------------------------------------------------------------------------------- /src/Vector.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vector.h" 3 | 4 | namespace ty { 5 | 6 | static float deg2rad(float degree) 7 | { 8 | return degree * M_PI / 180.0f; 9 | } 10 | 11 | static float rad2deg(float radian) 12 | { 13 | return radian * 180.0f / M_PI; 14 | } 15 | 16 | const float Vector::THRESHOLD_ORTHOGONAL = 90.0f; 17 | const float Vector::THRESHOLD_STRAIGHT = 170.0f; 18 | const float Vector::THRESHOLD_TOLERANCE = 20.0f; 19 | 20 | Vector::Vector(void) 21 | { 22 | X = 0.0f; 23 | Y = 0.0f; 24 | Z = 0.0f; 25 | } 26 | 27 | Vector::Vector(const XnVector3D& v) 28 | { 29 | X = v.X; 30 | Y = v.Y; 31 | Z = v.Z; 32 | } 33 | 34 | Vector::Vector(float x, float y, float z) 35 | { 36 | X = x; 37 | Y = y; 38 | Z = z; 39 | } 40 | 41 | Vector& Vector::operator+=(const Vector& v) 42 | { 43 | X += v.X; 44 | Y += v.Y; 45 | Z += v.Z; 46 | return *this; 47 | } 48 | 49 | Vector& Vector::operator-=(const Vector& v) 50 | { 51 | X -= v.X; 52 | Y -= v.Y; 53 | Z -= v.Z; 54 | return *this; 55 | } 56 | 57 | Vector& Vector::operator*=(float f) 58 | { 59 | X *= f; 60 | Y *= f; 61 | Z *= f; 62 | return *this; 63 | } 64 | 65 | Vector& Vector::operator/=(float f) 66 | { 67 | X /= f; 68 | Y /= f; 69 | Z /= f; 70 | return *this; 71 | } 72 | 73 | Vector Vector::operator+(const Vector& v) const 74 | { 75 | return Vector(X + v.X, Y + v.Y, Z + v.Z); 76 | } 77 | 78 | Vector Vector::operator-(const Vector& v) const 79 | { 80 | return Vector(X - v.X, Y - v.Y, Z - v.Z); 81 | } 82 | 83 | Vector Vector::operator*(float f) const 84 | { 85 | return Vector(X * f, Y * f, Z * f); 86 | } 87 | 88 | Vector Vector::operator/(float f) const 89 | { 90 | return Vector(X / f, Y / f, Z / f); 91 | } 92 | 93 | bool Vector::operator==(const Vector& v) const 94 | { 95 | return X == v.X && Y == v.Y && Z == v.Z; 96 | } 97 | 98 | float Vector::magnitude(void) const 99 | { 100 | return sqrtf(X*X + Y*Y + Z*Z); 101 | } 102 | 103 | Vector Vector::normalize(void) const 104 | { 105 | float m = magnitude(); 106 | return Vector(X/m, Y/m, Z/m); 107 | } 108 | 109 | float Vector::dot(const Vector& v) const 110 | { 111 | return (X*v.X + Y*v.Y + Z*v.Z) / magnitude() / v.magnitude(); 112 | } 113 | 114 | Vector Vector::cross(const Vector& v) const 115 | { 116 | return Vector(Y*v.Z - Z*v.Y, Z*v.X - X*v.Z, X*v.Y - Y*v.X).normalize(); 117 | } 118 | 119 | float Vector::distance(const Vector& v) const 120 | { 121 | return (*this - v).magnitude(); 122 | } 123 | 124 | Vector Vector::reverse(void) const 125 | { 126 | return Vector(-X, -Y, -Z); 127 | } 128 | 129 | bool Vector::withinAngle(const Vector& v, float angle) const 130 | { 131 | return dot(v) >= cosf(deg2rad(angle)); 132 | } 133 | 134 | bool Vector::withoutAngle(const Vector& v, float angle) const 135 | { 136 | return !withinAngle(v, angle); 137 | } 138 | 139 | bool Vector::betweenAngle(const Vector& v, float angle) const 140 | { 141 | return withoutAngle(v, angle - THRESHOLD_TOLERANCE) 142 | && withinAngle(v, angle + THRESHOLD_TOLERANCE); 143 | } 144 | 145 | bool Vector::isOrthogonal(const Vector& v) const 146 | { 147 | return betweenAngle(v, THRESHOLD_ORTHOGONAL); 148 | } 149 | 150 | bool Vector::isStraight(const Vector& v) const 151 | { 152 | return withinAngle(v, THRESHOLD_TOLERANCE); 153 | } 154 | 155 | bool Vector::isParallel(const Vector& v) const 156 | { 157 | return isStraight(v) || withoutAngle(v, THRESHOLD_STRAIGHT - THRESHOLD_TOLERANCE); 158 | } 159 | 160 | } // namespace ty 161 | -------------------------------------------------------------------------------- /test/CommandDetectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "CommandDetector.h" 3 | #include "MockTimer.h" 4 | using ::testing::Return; 5 | 6 | #define TIMELIMIT 2 7 | 8 | class ExampleCommandDetector : public ty::CommandDetector { 9 | public: 10 | ExampleCommandDetector(void) : CommandDetector(NULL) { } 11 | 12 | void setTimer(ty::Timer *_timer) { 13 | timer = _timer; 14 | } 15 | 16 | bool successProc(void) { 17 | return true; 18 | } 19 | 20 | bool failureProc(void) { 21 | return false; 22 | } 23 | }; 24 | 25 | class ExampleSuccessCommandDetector : public ExampleCommandDetector { 26 | public: 27 | ExampleSuccessCommandDetector(void) : ExampleCommandDetector() { 28 | setCommand(TIMELIMIT, 3, 29 | &ExampleCommandDetector::successProc, 30 | &ExampleCommandDetector::successProc, 31 | &ExampleCommandDetector::successProc); 32 | } 33 | }; 34 | 35 | class ExampleFailureCommandDetector : public ExampleCommandDetector { 36 | public: 37 | ExampleFailureCommandDetector(void) : ExampleCommandDetector() { 38 | setCommand(TIMELIMIT, 2, 39 | &ExampleCommandDetector::successProc, 40 | &ExampleCommandDetector::failureProc); 41 | } 42 | }; 43 | 44 | class ExampleNoSetCommandDetector : public ExampleCommandDetector { 45 | public: 46 | ExampleNoSetCommandDetector(void) : ExampleCommandDetector() {} 47 | }; 48 | 49 | class CommandDetectorTest : public testing::Test { 50 | public: 51 | ExampleSuccessCommandDetector *object; 52 | ExampleFailureCommandDetector *object2; 53 | ExampleNoSetCommandDetector *object3; 54 | 55 | protected: 56 | virtual void SetUp() { 57 | timer = new MockTimer; 58 | object = new ExampleSuccessCommandDetector(); 59 | object2 = new ExampleFailureCommandDetector(); 60 | object3 = new ExampleNoSetCommandDetector(); 61 | object->setTimer(timer); 62 | object2->setTimer(timer); 63 | object3->setTimer(timer); 64 | } 65 | 66 | virtual void TearDown() { 67 | delete object; 68 | delete object2; 69 | delete object3; 70 | delete timer; 71 | } 72 | 73 | MockTimer* timer; 74 | }; 75 | 76 | TEST_F(CommandDetectorTest, TestIsPosing) { 77 | EXPECT_CALL(*timer, current()) 78 | .Times(6) 79 | .WillRepeatedly(Return(0)); 80 | 81 | // 1週目 82 | ASSERT_FALSE(object->isPosing()); 83 | ASSERT_FALSE(object->isPosing()); 84 | ASSERT_TRUE(object->isPosing()); 85 | 86 | // 2週目 87 | ASSERT_FALSE(object->isPosing()); 88 | ASSERT_FALSE(object->isPosing()); 89 | ASSERT_TRUE(object->isPosing()); 90 | } 91 | 92 | TEST_F(CommandDetectorTest, TestIsPosingErrorTimeLimit) { 93 | EXPECT_CALL(*timer, current()) 94 | .Times(3) 95 | .WillOnce(Return(0)) 96 | .WillOnce(Return(0)) 97 | .WillOnce(Return(TIMELIMIT+1)); 98 | 99 | ASSERT_FALSE(object->isPosing()); 100 | ASSERT_FALSE(object->isPosing()); 101 | ASSERT_FALSE(object->isPosing()); 102 | } 103 | 104 | TEST_F(CommandDetectorTest, TestIsPosingError) { 105 | EXPECT_CALL(*timer, current()) 106 | .Times(4) 107 | .WillRepeatedly(Return(0)); 108 | 109 | // 1週目 110 | ASSERT_FALSE(object2->isPosing()); 111 | ASSERT_FALSE(object2->isPosing()); 112 | 113 | // 2週目 114 | ASSERT_FALSE(object2->isPosing()); 115 | ASSERT_FALSE(object2->isPosing()); 116 | } 117 | 118 | TEST_F(CommandDetectorTest, TestIsPosingErrorNoSetCommand) { 119 | ASSERT_FALSE(object3->isPosing()); 120 | } 121 | -------------------------------------------------------------------------------- /include/WorldContext.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_WORLD_CONTEXT_H_ 4 | #define _TYTHON_WORLD_CONTEXT_H_ 5 | 6 | #include 7 | 8 | namespace ty { 9 | 10 | class WorldContext { 11 | public: 12 | /** 13 | * @brief コンストラクタ 14 | * 15 | * nodeType で生成する Generator を選択する 16 | * 17 | * @code 18 | * WorldContext *world = new WorldContext(ctx, NODE_USE_DEPTH | NODE_USE_IMAGE); 19 | * @endcode 20 | * 21 | * @param _ctx Init 済みの xn::Context のインスタンス 22 | * @param nodeType 生成するノード 23 | */ 24 | WorldContext(xn::Context* _ctx, const int nodeType); 25 | 26 | /** 27 | * @brief デストラクタ 28 | */ 29 | virtual ~WorldContext(void); 30 | 31 | /** 32 | * xn::DepthGenerator インスタンスを返す 33 | * 34 | * @return xn::DepthGenerator インスタンスポインタ 35 | */ 36 | xn::DepthGenerator* depthGenerator(void); 37 | 38 | /** 39 | * xn::ImageGenerator インスタンスを返す 40 | * 41 | * @return xn::ImageGenerator インスタンスポインタ 42 | */ 43 | xn::ImageGenerator* imageGenerator(void); 44 | 45 | /** 46 | * 深度データを返す 47 | */ 48 | const XnDepthPixel* depthData(void) const; 49 | 50 | /** 51 | * RGB24Map を返す 52 | */ 53 | const xn::RGB24Map& imageRGB24Map(void) const; 54 | 55 | /** 56 | * @brief Image の横ピクセル数を返す 57 | * 58 | * Image が登録されていない場合は 0 を返す 59 | * 60 | * @return Image の横ピクセル数 61 | */ 62 | XnUInt32 imageWidth(void) const; 63 | 64 | /** 65 | * @brief Image の縦ピクセル数を返す 66 | * 67 | * Image が登録されていない場合は 0 を返す 68 | * 69 | * @return Image の縦ピクセル数 70 | */ 71 | XnUInt32 imageHeight(void) const; 72 | 73 | /** 74 | * @brief Depth の横ピクセル数を返す 75 | * 76 | * Depth が登録されていない場合は 0 を返す 77 | * 78 | * @return Depth の横ピクセル数 79 | */ 80 | XnUInt32 depthWidth(void) const; 81 | 82 | /** 83 | * @brief Depth の縦ピクセル数を返す 84 | * 85 | * Depth が登録されていない場合は 0 を返す 86 | * 87 | * @return Depth の縦ピクセル数 88 | */ 89 | XnUInt32 depthHeight(void) const; 90 | 91 | /** 92 | * @brief Depth Meta Data の更新 93 | */ 94 | void updateDepth(void); 95 | 96 | /** 97 | * @brief Image Meta Data の更新 98 | */ 99 | void updateImage(void); 100 | 101 | /** 102 | * @brief Recorder を有効化する 103 | * 104 | * ImageNode が有効であれば、圧縮形式をノードのデフォルト設定として保存する 105 | * DepthNode が有効であれば、圧縮形式をノードのデフォルト設定として保存する 106 | * 107 | * @param recordFileName 記録するファイル名 108 | */ 109 | void enableRecord(const XnChar* recordFileName); 110 | 111 | /** 112 | * Depth Node を使うフラグ値 113 | */ 114 | static const int NODE_USE_DEPTH = (1 << 0); 115 | 116 | /** 117 | * Image Node を使うフラグ値 118 | */ 119 | static const int NODE_USE_IMAGE = (1 << 1); 120 | 121 | protected: 122 | /** 123 | * @brief OpenNI 初期化 124 | * 125 | * xn::Context, xn::DepthGenerator, xn::ImageGenerator の初期化 126 | */ 127 | void initXN(void); 128 | 129 | private: 130 | /** 131 | * xn::Context インスタンス 132 | */ 133 | xn::Context* ctxGlobal; 134 | 135 | /** 136 | * xn::DepthGenerator インスタンス 137 | */ 138 | xn::DepthGenerator ctxDepth; 139 | 140 | /** 141 | * xn::ImageGenerator インスタンス 142 | */ 143 | xn::ImageGenerator ctxImage; 144 | 145 | /** 146 | * xn::Recorder インスタンス 147 | */ 148 | xn::Recorder ctxRecorder; 149 | 150 | /** 151 | * xn::DepthMetaData インスタンス 152 | */ 153 | xn::DepthMetaData metaDepth; 154 | 155 | /** 156 | * xn::DepthMetaData インスタンス 157 | */ 158 | xn::ImageMetaData metaImage; 159 | }; 160 | 161 | } // namespace ty 162 | 163 | #endif // _TYTHON_WORLD_CONTEXT_H_ 164 | -------------------------------------------------------------------------------- /include/Vector.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_VECTOR_H_ 4 | #define _TYTHON_VECTOR_H_ 5 | 6 | #include 7 | 8 | namespace ty { 9 | 10 | class Vector : public XnVector3D { 11 | public: 12 | Vector(void); 13 | Vector(const XnVector3D& v); 14 | Vector(float x, float y, float z); 15 | 16 | /** 17 | * 直交を判断するしきい値 18 | */ 19 | static const float THRESHOLD_ORTHOGONAL; 20 | 21 | /** 22 | * 平行を判断するしきい値 23 | */ 24 | static const float THRESHOLD_STRAIGHT; 25 | 26 | /** 27 | * 各しきい値に対する誤差許容範囲値 28 | */ 29 | static const float THRESHOLD_TOLERANCE; 30 | 31 | Vector& operator+=(const Vector& v); 32 | Vector& operator-=(const Vector& v); 33 | Vector& operator*=(float f); 34 | Vector& operator/=(float f); 35 | Vector operator+(const Vector& v) const; 36 | Vector operator-(const Vector& v) const; 37 | Vector operator*(float f) const; 38 | Vector operator/(float f) const; 39 | bool operator==(const Vector& v) const; 40 | 41 | /** 42 | * ベクトルの大きさ 43 | * 44 | * @return 大きさ |v| 45 | */ 46 | float magnitude(void) const; 47 | 48 | /** 49 | * ベクトルの内積を返す 50 | * 51 | * @param v 対象のベクトル 52 | * @return 内積 |v1 ・ v2| 53 | */ 54 | float dot(const Vector& v) const; 55 | 56 | /** 57 | * ベクトルの外積を返す 58 | * 59 | * @param v 対象のベクトル 60 | * @return 外積 |v1 × v2| 61 | */ 62 | Vector cross(const Vector& v) const; 63 | 64 | /** 65 | * ベクトルの正規化 66 | * 67 | * @return 正規化されたベクトル 68 | */ 69 | Vector normalize(void) const; 70 | 71 | /** 72 | * ベクトルの距離を測る 73 | * 74 | * @param v 対象のベクトル 75 | * @return 2ベクトルの距離 76 | */ 77 | float distance(const Vector& v) const; 78 | 79 | /** 80 | * 逆ベクトルを返す 81 | * 82 | * @return 自身の逆ベクトル 83 | */ 84 | Vector reverse(void) const; 85 | 86 | /** 87 | * 2つのベクトルが成す角度が、指定した角度かチェックする 88 | * 89 | * @param v 角度をチェックするベクトル 90 | * @param angle 判定基準とする角度 91 | * @return 指定した角度であれば true 92 | */ 93 | bool betweenAngle(const Vector& v, float angle) const; 94 | 95 | /** 96 | * 2つのベクトルが指定した角度より鋭角かチェックする 97 | * 98 | * @param v 角度をチェックするベクトル 99 | * @param angle 鋭角と判定基準とする角度 100 | * @return 鋭角と判断されれば true 101 | */ 102 | bool withinAngle(const Vector& v, float angle) const; 103 | 104 | /** 105 | * 2つのベクトルが指定した角度より鈍角かチェックする 106 | * 107 | * @see Vector::THRESHOLD_ORTHOGONAL 108 | * 109 | * @param v 角度をチェックするベクトル 110 | * @param angle 鈍角の判定基準とする角度 111 | * @return 鈍角と判断されれば true 112 | */ 113 | bool withoutAngle(const Vector& v, float angle) const; 114 | 115 | /** 116 | * 2つのベクトルが直交しているかチェックする 117 | * 118 | * @see Vector::THRESHOLD_ORTHOGONAL 119 | * 120 | * @param v this と直行しているか確認するベクトル 121 | * @return 直交していれば true 122 | */ 123 | bool isOrthogonal(const Vector& v) const; 124 | 125 | /** 126 | * 2つのベクトルがなす角度が直線かどうかチェックする 127 | * 128 | * ベクトルの向きに注意。 129 | * 130 | * A B 131 | * true <- -> 132 | * false -> -> 133 | * 134 | * @see Vector::THRESHOLD_STRAIGHT 135 | * @see Vector::isParallel() 136 | * 137 | * @param v this と直線か確認するベクトル 138 | * @return 平行であれば true 139 | */ 140 | bool isStraight(const Vector& v) const; 141 | 142 | /** 143 | * 2つのベクトルが平行かどうかチェックする 144 | * 145 | * isStraight() と違うのは、ベクトルの向きは気にしない 146 | * 147 | * A B 148 | * true <- -> 149 | * true -> -> 150 | * 151 | * @see Vector::THRESHOLD_STRAIGHT 152 | * @see Vector::isParallel() 153 | * 154 | * @param v this と平行か確認するベクトル 155 | * @return 平行であれば true 156 | */ 157 | bool isParallel(const Vector& v) const; 158 | }; 159 | 160 | } // namespace ty 161 | 162 | #endif // _TYTHON_VECTOR_H_ 163 | -------------------------------------------------------------------------------- /samples/language/include/VM.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_VM_H_ 4 | #define _TYTHON_VM_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "Instruction.h" 10 | 11 | using std::string; 12 | using std::vector; 13 | using std::map; 14 | 15 | class VM { 16 | public: 17 | /** 18 | * VM インスタンスを返す 19 | * 20 | * @return VM インスタンス 21 | */ 22 | static VM* instance(void); 23 | 24 | /** 25 | * 26 | * @todo 知らぬ命令がきたとき例外を投げるとか 27 | * 28 | * @param 29 | * @return 30 | */ 31 | bool run(vector insns); 32 | 33 | /** 34 | * スタックにプッシュ 35 | * 36 | * @param arg 特に使わず 37 | */ 38 | void push(int arg); 39 | 40 | /** 41 | * スタックトップを削除 42 | */ 43 | void discard(int arg); 44 | 45 | /** 46 | * スタックトップを複製し、プッシュする 47 | * 48 | * @param arg 特に使わず 49 | */ 50 | void dup(int arg); 51 | 52 | /** 53 | * スタックの 0 番目と 1 番目を入れ替える 54 | * 55 | * @param arg 特に使わず 56 | */ 57 | void swap(int arg); 58 | 59 | /** 60 | * スタックトップの下から指定した数だけスタックから削除する 61 | * 62 | * @param arg 削除する数 63 | */ 64 | void slide(int arg); 65 | 66 | /** 67 | * 0 番目と 1 番目 をスタックから取り出し、加算結果([0]*[1])をプッシュする 68 | * 69 | * @param arg 特に使わず 70 | */ 71 | void add(int arg); 72 | 73 | /** 74 | * 0 番目と 1 番目 をスタックから取り出し、減算結果([0]-[1])をプッシュする 75 | * 76 | * @param arg 特に使わず 77 | */ 78 | void sub(int arg); 79 | 80 | /** 81 | * 0 番目と 1 番目 をスタックから取り出し、乗算結果([0]*[1])をプッシュする 82 | * 83 | * @param arg 特に使わず 84 | */ 85 | void mul(int arg); 86 | 87 | /** 88 | * 0 番目と 1 番目 をスタックから取り出し、除算結果([0]/[1])をプッシュする 89 | * 90 | * @param arg 特に使わず 91 | */ 92 | void div(int arg); 93 | 94 | /** 95 | * 0 番目と 1 番目 をスタックから取り出し、除算結果([0]%[1])をプッシュする 96 | * 97 | * @param arg 特に使わず 98 | */ 99 | void mod(int arg); 100 | 101 | /** 102 | * セットされたラベルを表す。処理はしない 103 | */ 104 | void label(int arg); 105 | 106 | /** 107 | * 指定したラベルにジャンプする 108 | */ 109 | void jump(int arg); 110 | 111 | /** 112 | * スタックトップが 0 の時、指定したラベルにジャンプする 113 | */ 114 | void jump_zero(int arg); 115 | 116 | /** 117 | * スタックトップが 0 未満の時、、指定したラベルにジャンプする 118 | */ 119 | void jump_negative(int arg); 120 | 121 | /** 122 | * スタックトップを文字で標準出力する 123 | * 124 | * @param arg 特に使わず 125 | */ 126 | void char_out(int arg); 127 | 128 | /** 129 | * スタックトップを整数で標準出力する 130 | * 131 | * @param arg 特に使わず 132 | */ 133 | void num_out(int arg); 134 | 135 | /** 136 | * スタックトップを返す。 137 | * 138 | * @return スタックトップ 139 | */ 140 | int top(void); 141 | 142 | /** 143 | * スタックトップを取り出して返す。 144 | * 145 | * @return スタックトップ 146 | */ 147 | int pop(void); 148 | 149 | /** 150 | * スタックの全要素を削除 151 | */ 152 | void clear(void); 153 | 154 | /** 155 | * スタックの要素数を返す 156 | * 157 | * @return スタックの要素数 158 | */ 159 | int size(void); 160 | 161 | void refresh(vector insns); 162 | 163 | private: 164 | /** 165 | * コンストラクタ 166 | * 167 | * Singleton のため、private で定義 168 | */ 169 | VM(void); 170 | 171 | /** 172 | * コピーコンストラクタ 173 | * 174 | * Singleton のため、private で定義 175 | */ 176 | VM(const VM& obj) {} 177 | 178 | /** 179 | * VM クラスインスタンス 180 | */ 181 | static VM* _instance; 182 | 183 | void findLabel(vector insns); 184 | 185 | void jump_to(int pc); 186 | 187 | /** 188 | * Operation Set 189 | */ 190 | typedef void (VM::*opfunc)(int arg); 191 | map _opset; 192 | 193 | /** 194 | * プログラムカウンタ 195 | */ 196 | unsigned int _pc; 197 | 198 | /** 199 | * スタック 200 | */ 201 | vector _stack; 202 | 203 | /** 204 | * ラベルセット 205 | */ 206 | map _labels; 207 | }; 208 | 209 | #endif // _TYTHON_VM_H_ 210 | -------------------------------------------------------------------------------- /samples/language/src/VM.cc: -------------------------------------------------------------------------------- 1 | #include "VM.h" 2 | #include 3 | 4 | VM* VM::_instance = new VM; 5 | 6 | VM::VM(void) : _pc(0) 7 | { 8 | _opset["push"] = &VM::push; 9 | _opset["dup"] = &VM::dup; 10 | _opset["swap"] = &VM::swap; 11 | _opset["discard"] = &VM::discard; 12 | _opset["slide"] = &VM::slide; 13 | _opset["add"] = &VM::add; 14 | _opset["sub"] = &VM::sub; 15 | _opset["mul"] = &VM::mul; 16 | _opset["div"] = &VM::div; 17 | _opset["mod"] = &VM::mod; 18 | _opset["label"] = &VM::label; 19 | //_opset["call"] = &VM::call; 20 | _opset["jump"] = &VM::jump; 21 | _opset["jump_zero"] = &VM::jump_zero; 22 | _opset["jump_negative"] = &VM::jump_negative; 23 | _opset["char_out"] = &VM::char_out; 24 | _opset["num_out"] = &VM::num_out; 25 | } 26 | 27 | VM* VM::instance(void) 28 | { 29 | return VM::_instance; 30 | } 31 | 32 | void VM::findLabel(vector insns) 33 | { 34 | for (unsigned int i = 0; i < insns.size(); i++) { 35 | if (insns.at(i)->op.compare("label")) { 36 | _labels[insns.at(i)->arg] = i; 37 | } 38 | } 39 | } 40 | 41 | bool VM::run(vector insns) 42 | { 43 | findLabel(insns); 44 | 45 | for (_pc = 0; _pc < insns.size(); _pc++) { 46 | string op = insns.at(_pc)->op; 47 | int arg = insns.at(_pc)->arg; 48 | 49 | if (_opset.find(op) != _opset.end()) { 50 | (this->*_opset[op])(arg); 51 | } 52 | } 53 | 54 | refresh(insns); 55 | clear(); 56 | 57 | return true; 58 | } 59 | 60 | void VM::dup(int arg) 61 | { 62 | push(top()); 63 | } 64 | 65 | void VM::swap(int arg) 66 | { 67 | int p1 = pop(); 68 | int p2 = pop(); 69 | 70 | push(p1); 71 | push(p2); 72 | } 73 | 74 | void VM::discard(int arg) 75 | { 76 | pop(); 77 | } 78 | 79 | void VM::slide(int arg) 80 | { 81 | int p = pop(); 82 | for (; arg > 0; arg--) { 83 | pop(); 84 | } 85 | push(p); 86 | } 87 | 88 | void VM::add(int arg) 89 | { 90 | int p1 = pop(); 91 | int p2 = pop(); 92 | 93 | push(p1 + p2); 94 | } 95 | 96 | void VM::sub(int arg) 97 | { 98 | int p1 = pop(); 99 | int p2 = pop(); 100 | 101 | push(p1 - p2); 102 | } 103 | 104 | void VM::mul(int arg) 105 | { 106 | int p1 = pop(); 107 | int p2 = pop(); 108 | 109 | push(p1 * p2); 110 | } 111 | 112 | void VM::div(int arg) 113 | { 114 | int p1 = pop(); 115 | int p2 = pop(); 116 | 117 | push(p1 / p2); 118 | } 119 | 120 | void VM::mod(int arg) 121 | { 122 | int p1 = pop(); 123 | int p2 = pop(); 124 | 125 | push(p1 % p2); 126 | } 127 | 128 | void VM::label(int arg) 129 | { 130 | } 131 | 132 | void VM::jump(int arg) 133 | { 134 | jump_to(arg); 135 | } 136 | 137 | void VM::jump_zero(int arg) 138 | { 139 | if (pop() == 0) { 140 | jump(arg); 141 | } 142 | } 143 | 144 | void VM::jump_negative(int arg) 145 | { 146 | if (pop() == 0) { 147 | jump(arg); 148 | } 149 | } 150 | 151 | void VM::char_out(int arg) 152 | { 153 | std::cout << (char)pop(); 154 | } 155 | 156 | void VM::num_out(int arg) 157 | { 158 | std::cout << pop(); 159 | } 160 | 161 | void VM::push(int arg) 162 | { 163 | vector::iterator it = _stack.begin(); 164 | _stack.insert(it, arg); 165 | } 166 | 167 | int VM::top(void) 168 | { 169 | return _stack.front(); 170 | } 171 | 172 | int VM::pop(void) 173 | { 174 | int p = _stack.front(); 175 | vector::iterator it = _stack.begin(); 176 | _stack.erase(it); 177 | return p; 178 | } 179 | 180 | void VM::clear(void) 181 | { 182 | _stack.clear(); 183 | _labels.clear(); 184 | } 185 | 186 | int VM::size(void) 187 | { 188 | return _stack.size(); 189 | } 190 | 191 | void VM::refresh(vector insns) 192 | { 193 | vector::iterator it = insns.begin(); 194 | 195 | while (it != insns.end()) { 196 | Instruction *ins = *it; 197 | it++; 198 | delete ins; 199 | } 200 | 201 | clear(); 202 | } 203 | 204 | void VM::jump_to(int pc) 205 | { 206 | _pc = _labels[pc]; 207 | } 208 | -------------------------------------------------------------------------------- /src/User/UserContext.cc: -------------------------------------------------------------------------------- 1 | #include "UserContext.h" 2 | #include "util.h" 3 | 4 | namespace ty { 5 | 6 | UserContext::UserContext(xn::Context *ctx) 7 | { 8 | XnStatus rc; 9 | 10 | if (!ty::xnCheck(ctx->FindExistingNode(XN_NODE_TYPE_USER, generator))) { 11 | ty::xnRuntimeCheck(generator.Create(*ctx)); 12 | } 13 | 14 | skeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL); 15 | 16 | DIE_IF(!generator.IsCapabilitySupported(XN_CAPABILITY_SKELETON), 17 | "This configuration is not supported."); 18 | 19 | skeletonCap().GetCalibrationPose(poseName); 20 | ty::xnRuntimeCheck(generator.RegisterUserCallbacks(UserContext::onNewUserCallback, 21 | UserContext::onLostUserCallback, 22 | this, 23 | handleUserCallbacks)); 24 | 25 | ty::xnRuntimeCheck(poseDetectionCap().RegisterToPoseDetected(UserContext::onPoseStartCallback, 26 | this, 27 | handlePoseCallbacks)); 28 | ty::xnRuntimeCheck(skeletonCap().RegisterToCalibrationStart(UserContext::onCalibrationStartCallback, 29 | this, 30 | handleCalibrationCallbacks)); 31 | ty::xnRuntimeCheck(skeletonCap().RegisterToCalibrationComplete(UserContext::onCalibrationEndCallback, 32 | this, 33 | handleCalibrationCallbacks)); 34 | } 35 | 36 | UserContext::~UserContext(void) 37 | { 38 | generator.Release(); 39 | } 40 | 41 | void UserContext::setSceneData(int userId, xn::SceneMetaData* data) 42 | { 43 | generator.GetUserPixels(userId, *data); 44 | } 45 | 46 | bool UserContext::isTracking(int userId) 47 | { 48 | return generator.IsValid() 49 | && skeletonCap().IsTracking(userId); 50 | } 51 | 52 | bool UserContext::isCalibrated(int userId) 53 | { 54 | return generator.IsValid() 55 | && skeletonCap().IsCalibrated(userId); 56 | } 57 | 58 | /** 59 | * @todo マジックナンバーぇ... 60 | * @todo 標準で準備されてそうなもんだけど見つからない 61 | */ 62 | bool UserContext::isAvailable(int userId) 63 | { 64 | XnUserID aUsers[15]; 65 | XnUInt16 nUsers = 15; 66 | 67 | generator.GetUsers(aUsers, nUsers); 68 | 69 | for (int i = 0; i < nUsers; i++) { 70 | if (aUsers[i] == (XnUserID)userId) { 71 | return true; 72 | } 73 | } 74 | 75 | return false; 76 | } 77 | 78 | XnSkeletonJointPosition UserContext::getSkeletonJointPosition(int userId, XnSkeletonJoint joint) 79 | { 80 | XnSkeletonJointPosition p; 81 | skeletonCap().GetSkeletonJointPosition(userId, joint, p); 82 | return p; 83 | } 84 | 85 | xn::SkeletonCapability UserContext::skeletonCap(void) 86 | { 87 | return generator.GetSkeletonCap(); 88 | } 89 | 90 | xn::PoseDetectionCapability UserContext::poseDetectionCap(void) 91 | { 92 | return generator.GetPoseDetectionCap(); 93 | } 94 | 95 | void UserContext::onNewUser(XnUserID uid) 96 | { 97 | printf("onNewUser[%02d]\n", uid); 98 | ty::xnRuntimeCheck(poseDetectionCap().StartPoseDetection(poseName, uid)); 99 | } 100 | 101 | void UserContext::onLostUser(XnUserID uid) 102 | { 103 | printf("onLostUser[%02d]\n", uid); 104 | } 105 | 106 | void UserContext::onCalibrationStart(XnUserID uid) 107 | { 108 | printf("onCalibrationStart user[%02d]\n", uid); 109 | } 110 | 111 | void UserContext::onCalibrationEnd(XnUserID uid, bool isCalibration) 112 | { 113 | if (isCalibration) { 114 | printf("onCalibrationEnd - user[%02d] Success!\n", uid); 115 | ty::xnRuntimeCheck(skeletonCap().StartTracking(uid)); 116 | } else { 117 | printf("onCalibrationEnd - user[%02d] Failure...\n", uid); 118 | ty::xnRuntimeCheck(poseDetectionCap().StartPoseDetection(poseName, uid)); 119 | } 120 | } 121 | 122 | void UserContext::onPoseStart(XnUserID uid) 123 | { 124 | printf("onPoseStart user[%02d]\n", uid); 125 | ty::xnRuntimeCheck(poseDetectionCap().StopPoseDetection(uid)); 126 | ty::xnRuntimeCheck(skeletonCap().RequestCalibration(uid, true)); 127 | } 128 | 129 | } // namespace ty 130 | -------------------------------------------------------------------------------- /samples/language/src/Compiler.cc: -------------------------------------------------------------------------------- 1 | #include "Compiler.h" 2 | 3 | Compiler* Compiler::_instance = new Compiler; 4 | string Compiler::_treat = " a@g"; 5 | 6 | Compiler* Compiler::instance(void) 7 | { 8 | return Compiler::_instance; 9 | } 10 | 11 | vector Compiler::compile(string source) 12 | { 13 | unsigned int index = 0; 14 | unsigned int cur = 0; 15 | 16 | std::vector insns; 17 | 18 | /** 19 | * @todo 縺薙%縺ッ萓句、悶r謚輔£繧医≧ 20 | */ 21 | if (source.find_first_not_of(Compiler::_treat) != string::npos) { 22 | //return insns; 23 | } 24 | 25 | while (index < source.length()) { 26 | if ((cur = scan(source, "aa", index)) != index) { 27 | insns.push_back(op("push", input(source, cur))); 28 | } else if ((cur = scan(source, "a a", index)) != index) { 29 | insns.push_back(op("dup")); 30 | } else if ((cur = scan(source, "a@a", index)) != index) { 31 | insns.push_back(op("copy", input(source, cur))); 32 | } else if ((cur = scan(source, "a @", index)) != index) { 33 | insns.push_back(op("swap")); 34 | } else if ((cur = scan(source, "a ", index)) != index) { 35 | insns.push_back(op("discard")); 36 | } else if ((cur = scan(source, "a@ ", index)) != index) { 37 | insns.push_back(op("slide", input(source, cur))); 38 | } else if ((cur = scan(source, "@aaa", index)) != index) { 39 | insns.push_back(op("add")); 40 | } else if ((cur = scan(source, "@aa@", index)) != index) { 41 | insns.push_back(op("sub")); 42 | } else if ((cur = scan(source, "@aa ", index)) != index) { 43 | insns.push_back(op("mul")); 44 | } else if ((cur = scan(source, "@a@a", index)) != index) { 45 | insns.push_back(op("div")); 46 | } else if ((cur = scan(source, "@a@@", index)) != index) { 47 | insns.push_back(op("mod")); 48 | } else if ((cur = scan(source, "@@ ", index)) != index) { 49 | insns.push_back(op("heap_write")); 50 | } else if ((cur = scan(source, "@@@", index)) != index) { 51 | insns.push_back(op("heap_read")); 52 | } else if ((cur = scan(source, " aa", index)) != index) { 53 | insns.push_back(op("label", input(source, cur))); 54 | } else if ((cur = scan(source, " a@", index)) != index) { 55 | insns.push_back(op("call", input(source, cur))); 56 | } else if ((cur = scan(source, " a ", index)) != index) { 57 | insns.push_back(op("jump", input(source, cur))); 58 | } else if ((cur = scan(source, " @a", index)) != index) { 59 | insns.push_back(op("jump_zero", input(source, cur))); 60 | } else if ((cur = scan(source, " @@", index)) != index) { 61 | insns.push_back(op("jump_negative", input(source, cur))); 62 | } else if ((cur = scan(source, " @ ", index)) != index) { 63 | insns.push_back(op("return")); 64 | } else if ((cur = scan(source, " ", index)) != index) { 65 | insns.push_back(op("exit")); 66 | } else if ((cur = scan(source, "@ aa", index)) != index) { 67 | insns.push_back(op("char_out")); 68 | } else if ((cur = scan(source, "@ a@", index)) != index) { 69 | insns.push_back(op("num_out")); 70 | } else { 71 | insns.clear(); 72 | break; 73 | } 74 | 75 | index = cur; 76 | } 77 | 78 | return insns; 79 | } 80 | 81 | int Compiler::scan(string str, string target, int index) 82 | { 83 | return (str.find(target, index) == index) ? index + target.length() : index; 84 | } 85 | 86 | int Compiler::input(string str, unsigned int& index) 87 | { 88 | int endIndex; 89 | int num = 0; 90 | int digit = 0; 91 | 92 | if ((endIndex = str.find('g', index)) == string::npos) { 93 | throw 3; 94 | } 95 | 96 | string::iterator itSt = str.begin() + index; 97 | string::iterator itEd = str.begin() + endIndex - 1; 98 | 99 | while (itSt < itEd) { 100 | char c = *itEd; 101 | num += (((c == 'a') ? 1 : 0) << digit++); 102 | itEd--; 103 | } 104 | 105 | if (*itSt == '@') { 106 | num = ~num + 1; 107 | } 108 | 109 | index = endIndex + 1; 110 | return num; 111 | } 112 | 113 | Instruction* Compiler::op(string str, int arg) 114 | { 115 | return new Instruction(str, arg); 116 | } 117 | 118 | Instruction* Compiler::op(string str) 119 | { 120 | return new Instruction(str); 121 | } 122 | -------------------------------------------------------------------------------- /include/UserContext.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_USER_CONTEXT_H 4 | #define _TYTHON_USER_CONTEXT_H 5 | 6 | #include 7 | #include "Vector.h" 8 | 9 | namespace ty { 10 | 11 | class UserContext { 12 | public: 13 | UserContext(xn::Context *ctx); 14 | ~UserContext(void); 15 | 16 | /** 17 | * 指定したユーザの SceneMetaData を取得する 18 | * 19 | * @param userId ユーザID 20 | * @param data 取得したデータを格納する 21 | */ 22 | void setSceneData(int userId, xn::SceneMetaData* data); 23 | 24 | /** 25 | * 指定したユーザがトラッキングされているかチェックする 26 | * 27 | * @param userId ユーザID 28 | * @return トラッキングされていれば true 29 | */ 30 | bool isTracking(int userId); 31 | 32 | /** 33 | * 指定したユーザがキャリブレーションされているかチェックする 34 | * 35 | * @param userId ユーザID 36 | * @return キャリブレーションされていれば true 37 | */ 38 | bool isCalibrated(int userId); 39 | 40 | /** 41 | * 指定したユーザが認識されているかチェックする 42 | * 43 | * @param userId ユーザID 44 | * @return 認識されていれば true 45 | */ 46 | bool isAvailable(int userId); 47 | 48 | XnSkeletonJointPosition getSkeletonJointPosition(int userId, XnSkeletonJoint joint); 49 | 50 | /** 51 | * @brief ユーザを検出したときにコールバックされる関数 52 | * 53 | * generator.RegisterUserCallbacks() に登録するため 54 | * static として宣言している。 55 | * ty::UserContext::onNewUser へのつなぎ役 56 | * 57 | * @see ty::onNewUser 58 | */ 59 | static void XN_CALLBACK_TYPE onNewUserCallback(xn::UserGenerator& generator, 60 | XnUserID uid, 61 | void* t) { 62 | static_cast(t)->onNewUser(uid); 63 | } 64 | 65 | /** 66 | * @brief ユーザを見失ったときにコールバックされる関数 67 | * 68 | * generator.RegisterUserCallbacks() に登録するため 69 | * static として宣言している。 70 | * ty::UserContext::onLostUser へのつなぎ役 71 | * 72 | * @see ty::onListUser 73 | */ 74 | static void XN_CALLBACK_TYPE onLostUserCallback(xn::UserGenerator& generator, 75 | XnUserID uid, 76 | void* t) { 77 | static_cast(t)->onLostUser(uid); 78 | } 79 | 80 | /** 81 | * @brief 検出されたユーザがポーズを取り始めたときにコールバックされる関数 82 | * 83 | * generator.RegisterUserCallbacks() に登録するため 84 | * static として宣言している。 85 | * ty::UserContext::onPoseStart へのつなぎ役 86 | * 87 | * @see ty::onPoseStart 88 | */ 89 | static void XN_CALLBACK_TYPE onPoseStartCallback(xn::PoseDetectionCapability& capability, 90 | const XnChar* strPose, 91 | XnUserID uid, 92 | void* t) { 93 | static_cast(t)->onPoseStart(uid); 94 | } 95 | 96 | /** 97 | * @brief ポーズをとっているユーザのキャリブレーションが開始された時にコールバックされる関数 98 | * 99 | * generator.GetSkeletonCap().RegisterCalibrationCallbacks() に登録するため 100 | * static として宣言している。 101 | * ty::UserContext::onCalibrationStart へのつなぎ役 102 | * 103 | * @see ty::onPoseStart 104 | */ 105 | static void XN_CALLBACK_TYPE onCalibrationStartCallback(xn::SkeletonCapability& capability, 106 | XnUserID uid, 107 | void* t) { 108 | static_cast(t)->onCalibrationStart(uid); 109 | } 110 | 111 | /** 112 | * @brief ポーズをとっているユーザのキャリブレーションが終了した時にコールバックされる関数 113 | * 114 | * generator.GetSkeletonCap().RegisterCalibrationCallbacks() に登録するため 115 | * static として宣言している。 116 | * ty::UserContext::onCalibrationEnd へのつなぎ役 117 | * 118 | * @see ty::onPoseStart 119 | */ 120 | static void XN_CALLBACK_TYPE onCalibrationEndCallback(xn::SkeletonCapability& capability, 121 | XnUserID uid, 122 | XnCalibrationStatus status, 123 | void* t) { 124 | static_cast(t)->onCalibrationEnd(uid, (status == XN_CALIBRATION_STATUS_OK)); 125 | } 126 | 127 | protected: 128 | /** 129 | * デフォルトコンストラクタ 130 | * 131 | * 1. 継承するクラスのみ呼び出し可能 132 | * 2. 主に MockUser 用 133 | * 134 | * @see MockUser 135 | */ 136 | UserContext(void); 137 | 138 | virtual void onNewUser(XnUserID uid); 139 | virtual void onLostUser(XnUserID uid); 140 | virtual void onPoseStart(XnUserID uid); 141 | virtual void onCalibrationStart(XnUserID uid); 142 | virtual void onCalibrationEnd(XnUserID uid, bool isCalibration); 143 | 144 | private: 145 | /** 146 | * UserGenerator の SkeletonCapability を返す 147 | * 148 | * @return SkeletonCapability 149 | */ 150 | xn::SkeletonCapability skeletonCap(void); 151 | 152 | /** 153 | * UserGenerator の PoseDetectionCapability を返す 154 | * 155 | * @return PoseDetectionCapability 156 | */ 157 | xn::PoseDetectionCapability poseDetectionCap(void); 158 | 159 | /** 160 | * UserGenerator インスタンス 161 | */ 162 | xn::UserGenerator generator; 163 | 164 | /** 165 | * 166 | */ 167 | XnChar poseName[20]; 168 | 169 | XnCallbackHandle handleUserCallbacks; 170 | XnCallbackHandle handleCalibrationCallbacks; 171 | XnCallbackHandle handlePoseCallbacks; 172 | }; 173 | 174 | } // namespace ty 175 | 176 | #endif // _TYTHON_USER_CONTEXT_H 177 | -------------------------------------------------------------------------------- /test/UserContextTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "UserContext.h" 3 | #include "User.h" 4 | #include "util.h" 5 | 6 | using ::testing::Return; 7 | using ::testing::Invoke; 8 | using ::testing::_; 9 | 10 | class MockUserContext : public ty::UserContext { 11 | public: 12 | MockUserContext(xn::Context *context) : ty::UserContext(context) {} 13 | 14 | MOCK_METHOD1(onNewUser, void(XnUserID)); 15 | MOCK_METHOD1(onPoseStart, void(XnUserID)); 16 | MOCK_METHOD1(onCalibrationStart, void(XnUserID)); 17 | MOCK_METHOD2(onCalibrationEnd, void(XnUserID, bool)); 18 | 19 | void fakeOnNewUser(XnUserID uid) { 20 | ty::UserContext::onNewUser(uid); 21 | } 22 | void fakeOnPoseStart(XnUserID uid) { 23 | ty::UserContext::onPoseStart(uid); 24 | } 25 | void fakeOnCalibrationStart(XnUserID uid) { 26 | ty::UserContext::onCalibrationStart(uid); 27 | } 28 | void fakeOnCalibrationEnd(XnUserID uid, bool isCalibration) { 29 | ty::UserContext::onCalibrationEnd(uid, isCalibration); 30 | } 31 | }; 32 | 33 | class UserContextTest : public testing::Test { 34 | public: 35 | virtual void SetUp() { 36 | context.Init(); 37 | } 38 | 39 | virtual void TearDown() { 40 | context.Release(); 41 | 42 | if (player.IsValid()) { 43 | player.Release(); 44 | } 45 | } 46 | 47 | protected: 48 | xn::Context context; 49 | xn::Player player; 50 | }; 51 | 52 | #define SET_ONIFILE(file) do { \ 53 | context.OpenFileRecording(file, player); \ 54 | player.SetRepeat(false); \ 55 | } while (0) 56 | 57 | #define EXEC_ONIFILE() do { \ 58 | context.StartGeneratingAll(); \ 59 | while (!player.IsEOF()) { \ 60 | context.WaitAndUpdateAll(); \ 61 | } \ 62 | } while (0) 63 | 64 | #define FINISH_ONIFILE() do { \ 65 | context.StopGeneratingAll(); \ 66 | } while (0) 67 | 68 | 69 | TEST_F(UserContextTest, NoNewUser) { 70 | SET_ONIFILE("./test/oni/depth_only.oni"); 71 | MockUserContext object(&context); 72 | int userId = 1; 73 | ty::User user(&object, userId); 74 | 75 | EXPECT_CALL(object, onNewUser(userId)).Times(0); 76 | 77 | EXEC_ONIFILE(); 78 | 79 | ASSERT_FALSE(user.isAvailable()); 80 | ASSERT_FALSE(user.isCalibrated()); 81 | ASSERT_FALSE(object.isTracking(userId)); 82 | 83 | FINISH_ONIFILE(); 84 | } 85 | 86 | TEST_F(UserContextTest, NewUserAndNoPoseUser) { 87 | SET_ONIFILE("./test/oni/user_new.oni"); 88 | MockUserContext object(&context); 89 | int userId = 1; 90 | ty::User user(&object, userId); 91 | 92 | ON_CALL(object, onNewUser(_)) 93 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnNewUser)); 94 | 95 | EXPECT_CALL(object, onNewUser(userId)).Times(1); 96 | EXPECT_CALL(object, onPoseStart(userId)).Times(0); 97 | 98 | EXEC_ONIFILE(); 99 | 100 | ASSERT_TRUE(user.isAvailable()); 101 | ASSERT_FALSE(user.isCalibrated()); 102 | ASSERT_FALSE(user.isTracking()); 103 | 104 | FINISH_ONIFILE(); 105 | } 106 | 107 | TEST_F(UserContextTest, NewUserAndCalibrateUser) { 108 | SET_ONIFILE("./test/oni/user_calibrate.oni"); 109 | MockUserContext object(&context); 110 | int userId = 1; 111 | ty::User user(&object, userId); 112 | 113 | ON_CALL(object, onNewUser(_)) 114 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnNewUser)); 115 | ON_CALL(object, onPoseStart(_)) 116 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnPoseStart)); 117 | ON_CALL(object, onCalibrationStart(_)) 118 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnCalibrationStart)); 119 | ON_CALL(object, onCalibrationEnd(_, _)) 120 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnCalibrationEnd)); 121 | 122 | EXPECT_CALL(object, onNewUser(userId)).Times(1); 123 | EXPECT_CALL(object, onPoseStart(userId)).Times(1); 124 | EXPECT_CALL(object, onCalibrationStart(userId)).Times(1); 125 | EXPECT_CALL(object, onCalibrationEnd(userId, true)).Times(1); 126 | 127 | EXEC_ONIFILE(); 128 | 129 | ASSERT_TRUE(user.isAvailable()); 130 | ASSERT_TRUE(user.isCalibrated()); 131 | ASSERT_TRUE(user.isTracking()); 132 | 133 | FINISH_ONIFILE(); 134 | } 135 | 136 | TEST_F(UserContextTest, NewUserAndCalibrateUserFailure) { 137 | SET_ONIFILE("./test/oni/user_calibrate_failure.oni"); 138 | MockUserContext object(&context); 139 | int userId = 1; 140 | ty::User user(&object, userId); 141 | 142 | ON_CALL(object, onNewUser(_)) 143 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnNewUser)); 144 | ON_CALL(object, onPoseStart(_)) 145 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnPoseStart)); 146 | ON_CALL(object, onCalibrationStart(_)) 147 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnCalibrationStart)); 148 | ON_CALL(object, onCalibrationEnd(_, _)) 149 | .WillByDefault(Invoke(&object, &MockUserContext::fakeOnCalibrationEnd)); 150 | 151 | EXPECT_CALL(object, onNewUser(userId)).Times(1); 152 | EXPECT_CALL(object, onPoseStart(userId)).Times(1); 153 | EXPECT_CALL(object, onCalibrationStart(userId)).Times(1); 154 | EXPECT_CALL(object, onCalibrationEnd(userId, false)).Times(1); 155 | 156 | EXEC_ONIFILE(); 157 | 158 | ASSERT_TRUE(user.isAvailable()); 159 | ASSERT_FALSE(user.isTracking()); 160 | ASSERT_FALSE(user.isCalibrated()); 161 | 162 | FINISH_ONIFILE(); 163 | } 164 | 165 | -------------------------------------------------------------------------------- /samples/language/test/VMTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "VM.h" 5 | #include "Compiler.h" 6 | 7 | class VMTest : public testing::Test { 8 | public: 9 | VM *object; 10 | protected: 11 | virtual void SetUp() { 12 | object = VM::instance(); 13 | object->clear(); 14 | } 15 | }; 16 | 17 | TEST_F(VMTest, TestGetInstance) { 18 | VM *object2 = VM::instance(); 19 | 20 | ASSERT_TRUE(NULL != object); 21 | ASSERT_TRUE(object == object2); 22 | } 23 | 24 | TEST_F(VMTest, TestRun) { 25 | Compiler *compiler = Compiler::instance(); 26 | vector insns; 27 | 28 | // 2 + 7 = 9 を stdout 29 | insns = compiler->compile("aaaaaagaaa@a@g@aaa@ a@"); 30 | testing::internal::CaptureStdout(); 31 | object->run(insns); 32 | ASSERT_STREQ("9", testing::internal::GetCapturedStdout().c_str()); 33 | 34 | // 11 * 23 = 253 を stdout 35 | insns = compiler->compile("aaaa@aagaaaa@aaag@aa @ a@"); 36 | testing::internal::CaptureStdout(); 37 | object->run(insns); 38 | ASSERT_STREQ("253", testing::internal::GetCapturedStdout().c_str()); 39 | 40 | // 10010111 = 'H' + 1101110 = 'i' = Hi を stdout 41 | insns = compiler->compile("aaaa@@a@@@g@ aaaaaaa@a@@ag@ aa"); 42 | testing::internal::CaptureStdout(); 43 | object->run(insns); 44 | ASSERT_STREQ("Hi", testing::internal::GetCapturedStdout().c_str()); 45 | 46 | // 1010100(T) 1101000(h) 1100001(a) 1101110(n) 47 | // 1101011(k) 1110011(s) 100001(!) 100001(!) 48 | insns = compiler->compile("aaaa@@@@agaaaa@@@@agaaaaaa@@aagaaaaa@a@aagaaaaa@aaa@gaaaaa@@@@agaaaaa@a@@@gaaaa@a@a@@g@ aa@ aa@ aa@ aa@ aa@ aa@ aa@ aa"); 49 | testing::internal::CaptureStdout(); 50 | object->run(insns); 51 | ASSERT_STREQ("Thanks!!", testing::internal::GetCapturedStdout().c_str()); 52 | 53 | // 1001000(H) 1100101(e) 1101100(l) 1101100(l) 1101111(o) 101100(,) 100000( ) 54 | // 1010111(W) 1101111(o) 1110010(r) 1101100(l) 1100100(d) 100001(!) 55 | insns = compiler->compile("aaaa@@@@agaaaaa@@a@@gaaaaa@aa@@gaaaaaa@@a@gaaaaa@aaaagaaaa@a@aaagaaaa@@@@@gaaaa@aa@@gaaaaa@aaaagaaaaa@aa@@gaaaaa@aa@@gaaaaa@@a@agaaaa@@a@@@g@ aa@ aa@ aa@ aa@ aa@ aa@ aa@ aa@ aa@ aa@ aa@ aa@ aa"); 56 | testing::internal::CaptureStdout(); 57 | object->run(insns); 58 | ASSERT_STREQ("Hello, World!", testing::internal::GetCapturedStdout().c_str()); 59 | } 60 | 61 | TEST_F(VMTest, TestPush) { 62 | object->push(10); 63 | ASSERT_EQ(10, object->top()); 64 | } 65 | 66 | TEST_F(VMTest, TestDup) { 67 | int p = 10; 68 | 69 | object->push(p); 70 | object->dup(NULL); 71 | 72 | ASSERT_EQ(p, object->top()); 73 | } 74 | 75 | TEST_F(VMTest, TestSwap) { 76 | object->push(10); 77 | object->push(20); 78 | 79 | object->swap(0); 80 | 81 | ASSERT_EQ(10, object->top()); 82 | object->pop(); 83 | ASSERT_EQ(20, object->top()); 84 | } 85 | 86 | TEST_F(VMTest, TestAdd) { 87 | int size = object->size(); 88 | 89 | object->push(10); 90 | object->push(20); 91 | object->add(NULL); 92 | 93 | ASSERT_EQ(30, object->top()); 94 | ASSERT_EQ(size + 1, object->size()); 95 | } 96 | 97 | TEST_F(VMTest, TestSub) { 98 | int size = object->size(); 99 | 100 | object->push(10); 101 | object->push(20); 102 | object->sub(NULL); 103 | 104 | ASSERT_EQ(10, object->top()); 105 | ASSERT_EQ(size + 1, object->size()); 106 | } 107 | 108 | TEST_F(VMTest, TestMul) { 109 | int size = object->size(); 110 | 111 | object->push(10); 112 | object->push(20); 113 | object->mul(NULL); 114 | 115 | ASSERT_EQ(200, object->top()); 116 | ASSERT_EQ(size + 1, object->size()); 117 | } 118 | 119 | TEST_F(VMTest, TestDiv) { 120 | int size = object->size(); 121 | 122 | object->push(10); 123 | object->push(20); 124 | object->div(NULL); 125 | 126 | ASSERT_EQ(2, object->top()); 127 | ASSERT_EQ(size + 1, object->size()); 128 | } 129 | 130 | TEST_F(VMTest, TestMod) { 131 | int size = object->size(); 132 | 133 | object->push(20); 134 | object->push(30); 135 | object->mod(NULL); 136 | 137 | ASSERT_EQ(10, object->top()); 138 | ASSERT_EQ(size + 1, object->size()); 139 | } 140 | 141 | TEST_F(VMTest, TestDiscard) { 142 | int p1 = 3; 143 | int p2 = 4; 144 | 145 | object->push(p1); 146 | object->push(p2); 147 | object->discard(NULL); 148 | 149 | ASSERT_NE(p2, object->top()); 150 | ASSERT_EQ(p1, object->top()); 151 | } 152 | 153 | TEST_F(VMTest, TestPop) { 154 | int p1 = 3; 155 | int p2 = 4; 156 | 157 | object->push(p1); 158 | object->push(p2); 159 | 160 | ASSERT_EQ(p2, object->pop()); 161 | ASSERT_NE(p2, object->top()); 162 | ASSERT_EQ(p1, object->pop()); 163 | } 164 | 165 | TEST_F(VMTest, TestTop) { 166 | int p1 = 3; 167 | int p2 = 4; 168 | 169 | object->push(p1); 170 | object->push(p2); 171 | 172 | ASSERT_EQ(p2, object->top()); 173 | ASSERT_EQ(p2, object->top()); 174 | ASSERT_NE(p1, object->top()); 175 | } 176 | 177 | 178 | TEST_F(VMTest, TestClear) { 179 | object->push(10); 180 | object->push(10); 181 | object->push(10); 182 | object->clear(); 183 | 184 | ASSERT_EQ(0, object->size()); 185 | } 186 | 187 | TEST_F(VMTest, TestNum_Out) { 188 | object->push(20); 189 | 190 | testing::internal::CaptureStdout(); 191 | object->num_out(NULL); 192 | ASSERT_STREQ("20", testing::internal::GetCapturedStdout().c_str()); 193 | } 194 | 195 | TEST_F(VMTest, TestChar_Out) { 196 | object->push(105); 197 | 198 | testing::internal::CaptureStdout(); 199 | object->char_out(NULL); 200 | ASSERT_STREQ("i", testing::internal::GetCapturedStdout().c_str()); 201 | } 202 | 203 | TEST_F(VMTest, TestSlide) { 204 | int p1 = 1; 205 | int p2 = 2; 206 | int p3 = 3; 207 | int p4 = 4; 208 | int size; 209 | int slide = 3; 210 | 211 | object->push(p1); 212 | object->push(p2); 213 | object->push(p3); 214 | object->push(p4); 215 | size = object->size(); 216 | 217 | object->slide(slide); 218 | 219 | ASSERT_EQ(p4, object->top()); 220 | ASSERT_EQ(size - slide, object->size()); 221 | } 222 | -------------------------------------------------------------------------------- /src/User.cc: -------------------------------------------------------------------------------- 1 | #include "User.h" 2 | 3 | namespace ty { 4 | 5 | const float User::THRESHOLD_CONFIDENCE = 0.5; 6 | 7 | /** 8 | * @todo delegating constructor みたいにしたいよね... 9 | */ 10 | User::User(UserContext *_context) : context(_context), userId(1) 11 | { 12 | sceneData = new xn::SceneMetaData; 13 | } 14 | 15 | User::User(UserContext *_context, int id) : context(_context), userId(id) 16 | { 17 | sceneData = new xn::SceneMetaData; 18 | } 19 | 20 | User::~User(void) 21 | { 22 | delete sceneData; 23 | } 24 | 25 | int User::id(void) const 26 | { 27 | return userId; 28 | } 29 | 30 | xn::SceneMetaData* User::scene(void) 31 | { 32 | context->setSceneData(userId, sceneData); 33 | return sceneData; 34 | } 35 | 36 | bool User::isTracking(void) const 37 | { 38 | return context->isTracking(userId); 39 | } 40 | 41 | bool User::isCalibrated(void) const 42 | { 43 | return context->isCalibrated(userId); 44 | } 45 | 46 | bool User::isAvailable(void) const 47 | { 48 | return context->isAvailable(userId); 49 | } 50 | 51 | void User::updateSkeletonJointPosition(XnSkeletonJoint j) 52 | { 53 | XnSkeletonJointPosition p = context->getSkeletonJointPosition(userId, j); 54 | 55 | if (isConfident(p)) { 56 | skeletonPosition[j - 1] = p; 57 | } 58 | } 59 | 60 | Vector User::getSkeletonPosition(XnSkeletonJoint j) 61 | { 62 | updateSkeletonJointPosition(j); 63 | return Vector(skeletonPosition[j - 1].position); 64 | } 65 | 66 | inline bool User::isConfident(XnSkeletonJointPosition p) const 67 | { 68 | return p.fConfidence >= THRESHOLD_CONFIDENCE; 69 | } 70 | 71 | inline Vector User::head(void) 72 | { 73 | return getSkeletonPosition(XN_SKEL_HEAD); 74 | } 75 | 76 | inline Vector User::neck(void) 77 | { 78 | return getSkeletonPosition(XN_SKEL_NECK); 79 | } 80 | 81 | inline Vector User::torso(void) 82 | { 83 | return getSkeletonPosition(XN_SKEL_TORSO); 84 | } 85 | 86 | inline Vector User::waist(void) 87 | { 88 | return getSkeletonPosition(XN_SKEL_WAIST); 89 | } 90 | 91 | inline Vector User::leftCollar(void) 92 | { 93 | return getSkeletonPosition(XN_SKEL_LEFT_COLLAR); 94 | } 95 | 96 | inline Vector User::leftShoulder(void) 97 | { 98 | return getSkeletonPosition(XN_SKEL_LEFT_SHOULDER); 99 | } 100 | 101 | inline Vector User::leftElbow(void) 102 | { 103 | return getSkeletonPosition(XN_SKEL_LEFT_ELBOW); 104 | } 105 | 106 | inline Vector User::leftWrist(void) 107 | { 108 | return getSkeletonPosition(XN_SKEL_LEFT_WRIST); 109 | } 110 | 111 | inline Vector User::leftHand(void) 112 | { 113 | return getSkeletonPosition(XN_SKEL_LEFT_HAND); 114 | } 115 | 116 | inline Vector User::leftFingertip(void) 117 | { 118 | return getSkeletonPosition(XN_SKEL_LEFT_FINGERTIP); 119 | } 120 | 121 | inline Vector User::rightCollar(void) 122 | { 123 | return getSkeletonPosition(XN_SKEL_RIGHT_COLLAR); 124 | } 125 | 126 | inline Vector User::rightShoulder(void) 127 | { 128 | return getSkeletonPosition(XN_SKEL_RIGHT_SHOULDER); 129 | } 130 | 131 | inline Vector User::rightElbow(void) 132 | { 133 | return getSkeletonPosition(XN_SKEL_RIGHT_ELBOW); 134 | } 135 | 136 | inline Vector User::rightWrist(void) 137 | { 138 | return getSkeletonPosition(XN_SKEL_RIGHT_WRIST); 139 | } 140 | 141 | inline Vector User::rightHand(void) 142 | { 143 | return getSkeletonPosition(XN_SKEL_RIGHT_HAND); 144 | } 145 | 146 | inline Vector User::rightFingertip(void) 147 | { 148 | return getSkeletonPosition(XN_SKEL_RIGHT_FINGERTIP); 149 | } 150 | 151 | inline Vector User::leftHip(void) 152 | { 153 | return getSkeletonPosition(XN_SKEL_LEFT_HIP); 154 | } 155 | 156 | inline Vector User::leftKnee(void) 157 | { 158 | return getSkeletonPosition(XN_SKEL_LEFT_KNEE); 159 | } 160 | 161 | inline Vector User::leftAnkle(void) 162 | { 163 | return getSkeletonPosition(XN_SKEL_LEFT_ANKLE); 164 | } 165 | 166 | inline Vector User::leftFoot(void) 167 | { 168 | return getSkeletonPosition(XN_SKEL_LEFT_FOOT); 169 | } 170 | 171 | inline Vector User::rightHip(void) 172 | { 173 | return getSkeletonPosition(XN_SKEL_RIGHT_HIP); 174 | } 175 | 176 | inline Vector User::rightKnee(void) 177 | { 178 | return getSkeletonPosition(XN_SKEL_RIGHT_KNEE); 179 | } 180 | 181 | inline Vector User::rightAnkle(void) 182 | { 183 | return getSkeletonPosition(XN_SKEL_RIGHT_ANKLE); 184 | } 185 | 186 | inline Vector User::rightFoot(void) 187 | { 188 | return getSkeletonPosition(XN_SKEL_RIGHT_FOOT); 189 | } 190 | 191 | inline Vector User::vectorHead(void) 192 | { 193 | return head() - neck(); 194 | } 195 | 196 | inline Vector User::vectorMedianLine(void) 197 | { 198 | return waist() - head(); 199 | } 200 | 201 | inline Vector User::vectorRightUpperArm(void) 202 | { 203 | return rightElbow() - rightShoulder(); 204 | } 205 | 206 | inline Vector User::vectorRightForearm(void) 207 | { 208 | return rightHand() - rightElbow(); 209 | } 210 | 211 | inline Vector User::vectorLeftUpperArm(void) 212 | { 213 | return leftElbow() - leftShoulder(); 214 | } 215 | 216 | inline Vector User::vectorLeftForearm(void) 217 | { 218 | return leftHand() - leftElbow(); 219 | } 220 | 221 | inline Vector User::vectorLeftUpperThigh(void) 222 | { 223 | return leftKnee() - leftHip(); 224 | } 225 | 226 | inline Vector User::vectorLeftLowerThigh(void) 227 | { 228 | return leftAnkle() - leftKnee(); 229 | } 230 | 231 | inline Vector User::vectorRightUpperThigh(void) 232 | { 233 | return rightKnee() - rightHip(); 234 | } 235 | 236 | inline Vector User::vectorRightLowerThigh(void) 237 | { 238 | return rightAnkle() - rightKnee(); 239 | } 240 | 241 | inline Vector User::vectorUpperBodyForward(void) 242 | { 243 | return (rightShoulder() - torso()).cross(leftShoulder() - torso()).reverse(); 244 | } 245 | 246 | inline bool User::rightArmIsStraight(void) 247 | { 248 | return vectorRightForearm().isStraight(vectorRightUpperArm()); 249 | } 250 | 251 | inline bool User::leftArmIsStraight(void) 252 | { 253 | return vectorLeftForearm().isStraight(vectorLeftUpperArm()); 254 | } 255 | 256 | inline bool User::rightArmIsBentRightAngle(void) 257 | { 258 | return vectorRightUpperArm().isOrthogonal(vectorRightForearm()); 259 | } 260 | 261 | inline bool User::leftArmIsBentRightAngle(void) 262 | { 263 | return vectorLeftUpperArm().isOrthogonal(vectorLeftForearm()); 264 | } 265 | 266 | } // namespace ty 267 | -------------------------------------------------------------------------------- /test/MockUser.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_MOCK_USER_H 4 | #define _TYTHON_MOCK_USER_H 5 | 6 | #include 7 | #include "User.h" 8 | 9 | using ::testing::Return; 10 | using ::testing::_; 11 | 12 | class MockUser : public ty::User { 13 | public: 14 | MockUser(void) : User(NULL) { 15 | ON_CALL(*this, isTracking()).WillByDefault(Return(true)); 16 | ON_CALL(*this, isCalibrated()).WillByDefault(Return(true)); 17 | ON_CALL(*this, isAvailable()).WillByDefault(Return(true)); 18 | ON_CALL(*this, isConfident(_)).WillByDefault(Return(true)); 19 | } 20 | virtual ~MockUser(void) {} 21 | 22 | void setFakeSkeletonPosition(XnSkeletonJoint j, ty::Vector v) { 23 | skeletonPosition[j - 1].position = v; 24 | } 25 | 26 | void updateSkeletonJointPosition(XnSkeletonJoint j) {} 27 | 28 | MOCK_METHOD0(vectorRightUpperArm, ty::Vector(void)); 29 | MOCK_METHOD0(vectorRightForearm, ty::Vector(void)); 30 | MOCK_METHOD0(vectorLeftUpperArm, ty::Vector(void)); 31 | MOCK_METHOD0(vectorLeftForearm, ty::Vector(void)); 32 | MOCK_METHOD0(vectorRightUpperThigh, ty::Vector(void)); 33 | MOCK_METHOD0(vectorRightLowerThigh, ty::Vector(void)); 34 | MOCK_METHOD0(vectorLeftUpperThigh, ty::Vector(void)); 35 | MOCK_METHOD0(vectorLeftLowerThigh, ty::Vector(void)); 36 | MOCK_METHOD0(vectorHead, ty::Vector(void)); 37 | MOCK_METHOD0(vectorUpperBodyForward, ty::Vector(void)); 38 | MOCK_METHOD0(head, ty::Vector(void)); 39 | MOCK_METHOD0(neck, ty::Vector(void)); 40 | MOCK_METHOD0(torso, ty::Vector(void)); 41 | MOCK_METHOD0(rightCollar, ty::Vector(void)); 42 | MOCK_METHOD0(rightShoulder, ty::Vector(void)); 43 | MOCK_METHOD0(rightElbow, ty::Vector(void)); 44 | MOCK_METHOD0(rightWrist, ty::Vector(void)); 45 | MOCK_METHOD0(rightHand, ty::Vector(void)); 46 | MOCK_METHOD0(rightFingertip, ty::Vector(void)); 47 | MOCK_METHOD0(leftCollar, ty::Vector(void)); 48 | MOCK_METHOD0(leftShoulder, ty::Vector(void)); 49 | MOCK_METHOD0(leftElbow, ty::Vector(void)); 50 | MOCK_METHOD0(leftWrist, ty::Vector(void)); 51 | MOCK_METHOD0(leftHand, ty::Vector(void)); 52 | MOCK_METHOD0(leftFingertip, ty::Vector(void)); 53 | MOCK_METHOD0(rightHip, ty::Vector(void)); 54 | MOCK_METHOD0(rightKnee, ty::Vector(void)); 55 | MOCK_METHOD0(rightAnkle, ty::Vector(void)); 56 | MOCK_METHOD0(rightFoot, ty::Vector(void)); 57 | MOCK_METHOD0(leftHip, ty::Vector(void)); 58 | MOCK_METHOD0(leftKnee, ty::Vector(void)); 59 | MOCK_METHOD0(leftAnkle, ty::Vector(void)); 60 | MOCK_METHOD0(leftFoot, ty::Vector(void)); 61 | MOCK_METHOD0(waist, ty::Vector(void)); 62 | MOCK_METHOD0(rightArmIsStraight, bool(void)); 63 | MOCK_METHOD0(leftArmIsStraight, bool(void)); 64 | MOCK_METHOD0(rightArmIsBentRightAngle, bool(void)); 65 | MOCK_METHOD0(leftArmIsBentRightAngle, bool(void)); 66 | MOCK_CONST_METHOD0(isTracking, bool(void)); 67 | MOCK_CONST_METHOD0(isCalibrated, bool(void)); 68 | MOCK_CONST_METHOD0(isAvailable, bool(void)); 69 | MOCK_CONST_METHOD1(isConfident, bool(XnSkeletonJointPosition p)); 70 | 71 | ty::Vector FakeVectorRightUpperArm(void) { 72 | return ty::User::vectorRightUpperArm(); 73 | } 74 | ty::Vector FakeVectorRightForearm(void) { 75 | return ty::User::vectorRightForearm(); 76 | } 77 | ty::Vector FakeVectorLeftUpperArm(void) { 78 | return ty::User::vectorLeftUpperArm(); 79 | } 80 | ty::Vector FakeVectorLeftForearm(void) { 81 | return ty::User::vectorLeftForearm(); 82 | } 83 | ty::Vector FakeVectorRightUpperThigh(void) { 84 | return ty::User::vectorRightUpperThigh(); 85 | } 86 | ty::Vector FakeVectorRightLowerThigh(void) { 87 | return ty::User::vectorRightLowerThigh(); 88 | } 89 | ty::Vector FakeVectorLeftUpperThigh(void) { 90 | return ty::User::vectorLeftUpperThigh(); 91 | } 92 | ty::Vector FakeVectorLeftLowerThigh(void) { 93 | return ty::User::vectorLeftLowerThigh(); 94 | } 95 | ty::Vector FakeVectorHead(void) { 96 | return ty::User::vectorHead(); 97 | } 98 | ty::Vector FakeVectorUpperBodyForward(void) { 99 | return ty::User::vectorUpperBodyForward(); 100 | } 101 | ty::Vector FakeHead(void) { 102 | return ty::User::head(); 103 | } 104 | ty::Vector FakeNeck(void) { 105 | return ty::User::neck(); 106 | } 107 | ty::Vector FakeTorso(void) { 108 | return ty::User::torso(); 109 | } 110 | ty::Vector FakeRightCollar(void) { 111 | return ty::User::rightCollar(); 112 | } 113 | ty::Vector FakeRightShoulder(void) { 114 | return ty::User::rightShoulder(); 115 | } 116 | ty::Vector FakeRightElbow(void) { 117 | return ty::User::rightElbow(); 118 | } 119 | ty::Vector FakeRightWrist(void) { 120 | return ty::User::rightWrist(); 121 | } 122 | ty::Vector FakeRightHand(void) { 123 | return ty::User::rightHand(); 124 | } 125 | ty::Vector FakeRightFingertip(void) { 126 | return ty::User::rightFingertip(); 127 | } 128 | ty::Vector FakeLeftCollar(void) { 129 | return ty::User::leftCollar(); 130 | } 131 | ty::Vector FakeLeftShoulder(void) { 132 | return ty::User::leftShoulder(); 133 | } 134 | ty::Vector FakeLeftElbow(void) { 135 | return ty::User::leftElbow(); 136 | } 137 | ty::Vector FakeLeftWrist(void) { 138 | return ty::User::leftWrist(); 139 | } 140 | ty::Vector FakeLeftHand(void) { 141 | return ty::User::leftHand(); 142 | } 143 | ty::Vector FakeLeftFingertip(void) { 144 | return ty::User::leftFingertip(); 145 | } 146 | ty::Vector FakeRightHip(void) { 147 | return ty::User::rightHip(); 148 | } 149 | ty::Vector FakeRightKnee(void) { 150 | return ty::User::rightKnee(); 151 | } 152 | ty::Vector FakeRightAnkle(void) { 153 | return ty::User::rightAnkle(); 154 | } 155 | ty::Vector FakeRightFoot(void) { 156 | return ty::User::rightFoot(); 157 | } 158 | ty::Vector FakeLeftHip(void) { 159 | return ty::User::leftHip(); 160 | } 161 | ty::Vector FakeLeftKnee(void) { 162 | return ty::User::leftKnee(); 163 | } 164 | ty::Vector FakeLeftAnkle(void) { 165 | return ty::User::leftAnkle(); 166 | } 167 | ty::Vector FakeLeftFoot(void) { 168 | return ty::User::leftFoot(); 169 | } 170 | ty::Vector FakeWaist(void) { 171 | return ty::User::waist(); 172 | } 173 | bool FakeRightArmIsStraight(void) { 174 | return ty::User::rightArmIsStraight(); 175 | } 176 | bool FakeLeftArmIsStraight(void) { 177 | return ty::User::leftArmIsStraight(); 178 | } 179 | bool FakeRightArmIsBentRightAngle(void) { 180 | return ty::User::rightArmIsBentRightAngle(); 181 | } 182 | bool FakeLeftArmIsBentRightAngle(void) { 183 | return ty::User::leftArmIsBentRightAngle(); 184 | } 185 | bool FakeIsTracking(void) { 186 | return ty::User::isTracking(); 187 | } 188 | bool FakeIsCalibrated(void) { 189 | return ty::User::isCalibrated(); 190 | } 191 | bool FakeIsAvailable(void) { 192 | return ty::User::isAvailable(); 193 | } 194 | bool FakeIsConfident(XnSkeletonJointPosition p) { 195 | return ty::User::isConfident(p); 196 | } 197 | }; 198 | 199 | #endif // _TYTHON_MOCK_USER_H 200 | -------------------------------------------------------------------------------- /include/User.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _TYTHON_USER_H 4 | #define _TYTHON_USER_H 5 | 6 | #include "UserContext.h" 7 | 8 | namespace ty { 9 | 10 | class User { 11 | public: 12 | /** 13 | * コンストラクタ 14 | * 15 | * ユーザID が 1 の User を生成 16 | */ 17 | User(UserContext *_context); 18 | 19 | /** 20 | * コンストラクタ 21 | * 22 | * ユーザID が id の User を生成 23 | */ 24 | User(UserContext *_context, int id); 25 | 26 | /** 27 | * デストラクタ 28 | */ 29 | ~User(void); 30 | 31 | /** 32 | * 指定したパーツの座標を取得する 33 | * 34 | * @param j パーツ 35 | * @return パーツの座標 36 | */ 37 | virtual ty::Vector getSkeletonPosition(XnSkeletonJoint j); 38 | 39 | /** 40 | * ユーザの SceneMetaData を取得する 41 | * 42 | * @param data 取得したデータを格納する 43 | */ 44 | xn::SceneMetaData* scene(void); 45 | 46 | /** 47 | * ユーザがトラッキングされているかチェックする 48 | * 49 | * @see userId 50 | * 51 | * @return トラッキングされていれば true 52 | */ 53 | virtual bool isTracking(void) const; 54 | 55 | /** 56 | * ユーザがキャリブレーションされているかチェックする 57 | * 58 | * @see userId 59 | * 60 | * @return キャリブレーションされていれば true 61 | */ 62 | virtual bool isCalibrated(void) const; 63 | 64 | /** 65 | * ユーザが認識されているかチェックする 66 | * 67 | * @see userId 68 | * 69 | * @return 認識されていれば true 70 | */ 71 | bool isAvailable(void) const; 72 | 73 | /** 74 | * ユーザの ID を返す 75 | * 76 | * @see userId 77 | * 78 | * @return ユーザ ID 79 | */ 80 | int id(void) const; 81 | 82 | /** 83 | * 頭の座標を取得する 84 | * 85 | * @return 頭の座標(ベクトル) 86 | */ 87 | virtual ty::Vector head(void); 88 | 89 | /** 90 | * 首の座標を取得する 91 | * 92 | * @return 首の座標(ベクトル) 93 | */ 94 | virtual ty::Vector neck(void); 95 | 96 | /** 97 | * 胴の座標を取得する 98 | * 99 | * @return 胴の座標(ベクトル) 100 | */ 101 | virtual ty::Vector torso(void); 102 | 103 | /** 104 | * 腰の座標を取得する 105 | * 106 | * @return 腰の座標(ベクトル) 107 | */ 108 | virtual ty::Vector waist(void); 109 | 110 | /** 111 | * 左鎖骨の座標を取得する 112 | * 113 | * @return 左鎖骨の座標(ベクトル) 114 | */ 115 | virtual ty::Vector leftCollar(void); 116 | 117 | /** 118 | * 左肩の座標を取得する 119 | * 120 | * @return 左肩の座標(ベクトル) 121 | */ 122 | virtual ty::Vector leftShoulder(void); 123 | 124 | /** 125 | * 左肘の座標を取得する 126 | * 127 | * @return 左肘の座標(ベクトル) 128 | */ 129 | virtual ty::Vector leftElbow(void); 130 | 131 | /** 132 | * 左手首の座標を取得する 133 | * 134 | * @return 左手首の座標(ベクトル) 135 | */ 136 | virtual ty::Vector leftWrist(void); 137 | 138 | /** 139 | * 左手の座標を取得する 140 | * 141 | * @return 左手の座標(ベクトル) 142 | */ 143 | virtual ty::Vector leftHand(void); 144 | 145 | /** 146 | * 左手先の座標を取得する 147 | * 148 | * @return 左手先の座標(ベクトル) 149 | */ 150 | virtual ty::Vector leftFingertip(void); 151 | 152 | /** 153 | * 右鎖骨の座標を取得する 154 | * 155 | * @return 右鎖骨の座標(ベクトル) 156 | */ 157 | virtual ty::Vector rightCollar(void); 158 | 159 | /** 160 | * 右肩の座標を取得する 161 | * 162 | * @return 右肩の座標(ベクトル) 163 | */ 164 | virtual ty::Vector rightShoulder(void); 165 | 166 | /** 167 | * 右肘の座標を取得する 168 | * 169 | * @return 右肘の座標(ベクトル) 170 | */ 171 | virtual ty::Vector rightElbow(void); 172 | 173 | /** 174 | * 右手首の座標を取得する 175 | * 176 | * @return 右手首の座標(ベクトル) 177 | */ 178 | virtual ty::Vector rightWrist(void); 179 | 180 | /** 181 | * 右手の座標を取得する 182 | * 183 | * @return 右手の座標(ベクトル) 184 | */ 185 | virtual ty::Vector rightHand(void); 186 | 187 | /** 188 | * 右手先の座標を取得する 189 | * 190 | * @return 右手先の座標(ベクトル) 191 | */ 192 | virtual ty::Vector rightFingertip(void); 193 | 194 | /** 195 | * 左尻の座標を取得する 196 | * 197 | * @return 左尻の座標(ベクトル) 198 | */ 199 | virtual ty::Vector leftHip(void); 200 | 201 | /** 202 | * 左膝の座標を取得する 203 | * 204 | * @return 左膝の座標(ベクトル) 205 | */ 206 | virtual ty::Vector leftKnee(void); 207 | 208 | /** 209 | * 左足首の座標を取得する 210 | * 211 | * @return 左足首の座標(ベクトル) 212 | */ 213 | virtual ty::Vector leftAnkle(void); 214 | 215 | /** 216 | * 左足の座標を取得する 217 | * 218 | * @return 左足の座標(ベクトル) 219 | */ 220 | virtual ty::Vector leftFoot(void); 221 | 222 | /** 223 | * 右尻の座標を取得する 224 | * 225 | * @return 右尻の座標(ベクトル) 226 | */ 227 | virtual ty::Vector rightHip(void); 228 | 229 | /** 230 | * 右膝の座標を取得する 231 | * 232 | * @return 右膝の座標(ベクトル) 233 | */ 234 | virtual ty::Vector rightKnee(void); 235 | 236 | /** 237 | * 右足首の座標を取得する 238 | * 239 | * @return 右足首の座標(ベクトル) 240 | */ 241 | virtual ty::Vector rightAnkle(void); 242 | 243 | /** 244 | * 右足の座標を取得する 245 | * 246 | * @return 右足の座標(ベクトル) 247 | */ 248 | virtual ty::Vector rightFoot(void); 249 | 250 | /** 251 | * 首から頭へのベクトルを取得する 252 | * 253 | * @return 首から頭へのベクトル 254 | */ 255 | virtual ty::Vector vectorHead(void); 256 | 257 | /** 258 | * 正中線(頭から腰にかけて)のベクトルを取得する 259 | * 260 | * @return 正中線のベクトル 261 | */ 262 | virtual ty::Vector vectorMedianLine(void); 263 | 264 | /** 265 | * 右上腕(右肩から右肘にかけて)のベクトルを取得する 266 | * 267 | * @return 右上腕のベクトル 268 | */ 269 | virtual ty::Vector vectorRightUpperArm(void); 270 | 271 | /** 272 | * 右前腕(右肘から右手にかけて)のベクトルを取得する 273 | * 274 | * @return 右前腕のベクトル 275 | */ 276 | virtual ty::Vector vectorRightForearm(void); 277 | 278 | /** 279 | * 左上腕(左肩から左肘にかけて)のベクトルを取得する 280 | * 281 | * @return 左上腕のベクトル 282 | */ 283 | virtual ty::Vector vectorLeftUpperArm(void); 284 | 285 | /** 286 | * 左前腕(左肘から左手にかけて)のベクトルを取得する 287 | * 288 | * @return 左前腕のベクトル 289 | */ 290 | virtual ty::Vector vectorLeftForearm(void); 291 | 292 | /** 293 | * 左上腿(左尻から左膝にかけて)のベクトルを取得する 294 | * 295 | * @return 左上腿のベクトル 296 | */ 297 | virtual ty::Vector vectorLeftUpperThigh(void); 298 | 299 | /** 300 | * 左下腿(左膝から左足首にかけて)のベクトルを取得する 301 | * 302 | * @return 左下腿のベクトル 303 | */ 304 | virtual ty::Vector vectorLeftLowerThigh(void); 305 | 306 | /** 307 | * 右上腿(右尻から右膝にかけて)のベクトルを取得する 308 | * 309 | * @return 右上腿のベクトル 310 | */ 311 | virtual ty::Vector vectorRightUpperThigh(void); 312 | 313 | /** 314 | * 右下腿(右膝から右足首にかけて)のベクトルを取得する 315 | * 316 | * @return 右下腿のベクトル 317 | */ 318 | virtual ty::Vector vectorRightLowerThigh(void); 319 | 320 | /** 321 | * 上半身が向いているベクトルを取得する 322 | * 323 | * @return 上半身の向いているベクトル 324 | */ 325 | virtual ty::Vector vectorUpperBodyForward(void); 326 | 327 | /** 328 | * 右腕がまっすぐ伸びているかどうか 329 | * 330 | * @see vectorRightForearm() 331 | * @see vectorRightUpperArm() 332 | * 333 | * @return 右腕がまっすぐ伸びていれば true 334 | */ 335 | virtual bool rightArmIsStraight(void); 336 | 337 | /** 338 | * 左腕がまっすぐ伸びているかどうか 339 | * 340 | * @see vectorLeftForearm() 341 | * @see vectorLeftUpperArm() 342 | * 343 | * return 左腕がまっすぐ伸びていれば true 344 | */ 345 | virtual bool leftArmIsStraight(void); 346 | 347 | /** 348 | * 右腕が直角に曲がっているか 349 | * 350 | * @see vectorRightForearm() 351 | * @see vectorRightUpperArm() 352 | * 353 | * @return 右腕が直角に曲がっていれば true 354 | */ 355 | virtual bool rightArmIsBentRightAngle(void); 356 | 357 | /** 358 | * 左腕が直角に曲がっているか 359 | * 360 | * @see vectorLeftForearm() 361 | * @see vectorLeftUpperArm() 362 | * 363 | * @return 左腕が直角に曲がっていれば true 364 | */ 365 | virtual bool leftArmIsBentRightAngle(void); 366 | 367 | /** 368 | * 認識のしきい値 369 | * 370 | * @see isConfident 371 | */ 372 | static const float THRESHOLD_CONFIDENCE; 373 | 374 | protected: 375 | /** 376 | * デフォルトコンストラクタ 377 | * 378 | * 1. 継承するクラスのみ呼び出し可能 379 | * 2. 主に MockUser 用 380 | * 381 | * @see MockUser 382 | */ 383 | User(void); 384 | 385 | /** 386 | * @brief 座標の認識度がしきい値を超えているかチェックする 387 | * 388 | * 超えていなければ、認識できていないと判断し、 389 | * skeletonPosition に保存された値を使うようにする 390 | * 391 | * @see updateSkeletonJointPosition 392 | * 393 | * @param p 394 | * @return しきい値を超えていれば true 395 | */ 396 | bool isConfident(XnSkeletonJointPosition p) const; 397 | 398 | /** 399 | * 自身の骨格座標を持つ 400 | * 401 | * @see XnSkeletonJoint 402 | */ 403 | XnSkeletonJointPosition skeletonPosition[24]; 404 | 405 | private: 406 | /** 407 | * 指定したパーツの座標を更新する 408 | * 409 | * @see skeletonPosition 410 | * 411 | * @param j パーツ 412 | */ 413 | virtual void updateSkeletonJointPosition(XnSkeletonJoint j); 414 | 415 | /** 416 | * UserContext のインスタンス 417 | */ 418 | UserContext* context; 419 | 420 | /** 421 | * xn::SceneMetaData のインスタンス 422 | */ 423 | xn::SceneMetaData* sceneData; 424 | 425 | /** 426 | * ユーザ ID 427 | */ 428 | const int userId; 429 | }; 430 | 431 | } // namespace ty 432 | 433 | #endif // _TYTHON_USER_H 434 | -------------------------------------------------------------------------------- /test/UserTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MockUser.h" 3 | 4 | using ::testing::Return; 5 | using ::testing::Invoke; 6 | 7 | class UserTest : public testing::Test { 8 | public: 9 | virtual void SetUp() { 10 | object = new MockUser; 11 | } 12 | 13 | virtual void TearDown() { 14 | delete object; 15 | } 16 | protected: 17 | MockUser* object; 18 | }; 19 | 20 | TEST_F(UserTest, TestHead) { 21 | ty::Vector v(1.0f, 2.0f, 3.0f); 22 | 23 | ON_CALL(*object, head()) 24 | .WillByDefault(Invoke(object, &MockUser::FakeHead)); 25 | object->setFakeSkeletonPosition(XN_SKEL_HEAD, v); 26 | 27 | ASSERT_TRUE(v == object->head()); 28 | } 29 | 30 | TEST_F(UserTest, TestNeck) { 31 | ty::Vector v(1.0f, 2.0f, 3.0f); 32 | 33 | ON_CALL(*object, neck()) 34 | .WillByDefault(Invoke(object, &MockUser::FakeNeck)); 35 | object->setFakeSkeletonPosition(XN_SKEL_NECK, v); 36 | 37 | ASSERT_TRUE(v == object->neck()); 38 | } 39 | 40 | TEST_F(UserTest, TestTorso) { 41 | ty::Vector v(1.0f, 2.0f, 3.0f); 42 | 43 | ON_CALL(*object, torso()) 44 | .WillByDefault(Invoke(object, &MockUser::FakeTorso)); 45 | object->setFakeSkeletonPosition(XN_SKEL_TORSO, v); 46 | 47 | ASSERT_TRUE(v == object->torso()); 48 | } 49 | 50 | TEST_F(UserTest, TestWaist) { 51 | ty::Vector v(1.0f, 2.0f, 3.0f); 52 | 53 | ON_CALL(*object, waist()) 54 | .WillByDefault(Invoke(object, &MockUser::FakeWaist)); 55 | object->setFakeSkeletonPosition(XN_SKEL_WAIST, v); 56 | 57 | ASSERT_TRUE(v == object->waist()); 58 | } 59 | 60 | TEST_F(UserTest, TestLeftCollar) { 61 | ty::Vector v(1.0f, 2.0f, 3.0f); 62 | 63 | ON_CALL(*object, leftCollar()) 64 | .WillByDefault(Invoke(object, &MockUser::FakeLeftCollar)); 65 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_COLLAR, v); 66 | 67 | ASSERT_TRUE(v == object->leftCollar()); 68 | } 69 | 70 | TEST_F(UserTest, TestLeftShoulder) { 71 | ty::Vector v(1.0f, 2.0f, 3.0f); 72 | 73 | ON_CALL(*object, leftShoulder()) 74 | .WillByDefault(Invoke(object, &MockUser::FakeLeftShoulder)); 75 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_SHOULDER, v); 76 | 77 | ASSERT_TRUE(v == object->leftShoulder()); 78 | } 79 | 80 | TEST_F(UserTest, TestLeftElbow) { 81 | ty::Vector v(1.0f, 2.0f, 3.0f); 82 | 83 | ON_CALL(*object, leftElbow()) 84 | .WillByDefault(Invoke(object, &MockUser::FakeLeftElbow)); 85 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_ELBOW, v); 86 | 87 | ASSERT_TRUE(v == object->leftElbow()); 88 | } 89 | 90 | TEST_F(UserTest, TestLeftWrist) { 91 | ty::Vector v(1.0f, 2.0f, 3.0f); 92 | 93 | ON_CALL(*object, leftWrist()) 94 | .WillByDefault(Invoke(object, &MockUser::FakeLeftWrist)); 95 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_WRIST, v); 96 | 97 | ASSERT_TRUE(v == object->leftWrist()); 98 | } 99 | 100 | TEST_F(UserTest, TestLeftHand) { 101 | ty::Vector v(1.0f, 2.0f, 3.0f); 102 | 103 | ON_CALL(*object, leftHand()) 104 | .WillByDefault(Invoke(object, &MockUser::FakeLeftHand)); 105 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_HAND, v); 106 | 107 | ASSERT_TRUE(v == object->leftHand()); 108 | } 109 | 110 | TEST_F(UserTest, TestLeftFingertip) { 111 | ty::Vector v(1.0f, 2.0f, 3.0f); 112 | 113 | ON_CALL(*object, leftFingertip()) 114 | .WillByDefault(Invoke(object, &MockUser::FakeLeftFingertip)); 115 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_FINGERTIP, v); 116 | 117 | ASSERT_TRUE(v == object->leftFingertip()); 118 | } 119 | 120 | TEST_F(UserTest, TestRightCollar) { 121 | ty::Vector v(1.0f, 2.0f, 3.0f); 122 | 123 | ON_CALL(*object, rightCollar()) 124 | .WillByDefault(Invoke(object, &MockUser::FakeRightCollar)); 125 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_COLLAR, v); 126 | 127 | ASSERT_TRUE(v == object->rightCollar()); 128 | } 129 | 130 | TEST_F(UserTest, TestRightShoulder) { 131 | ty::Vector v(1.0f, 2.0f, 3.0f); 132 | 133 | ON_CALL(*object, rightShoulder()) 134 | .WillByDefault(Invoke(object, &MockUser::FakeRightShoulder)); 135 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_SHOULDER, v); 136 | 137 | ASSERT_TRUE(v == object->rightShoulder()); 138 | } 139 | 140 | TEST_F(UserTest, TestRightElbow) { 141 | ty::Vector v(1.0f, 2.0f, 3.0f); 142 | 143 | ON_CALL(*object, rightElbow()) 144 | .WillByDefault(Invoke(object, &MockUser::FakeRightElbow)); 145 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_ELBOW, v); 146 | 147 | ASSERT_TRUE(v == object->rightElbow()); 148 | } 149 | 150 | TEST_F(UserTest, TestRightWrist) { 151 | ty::Vector v(1.0f, 2.0f, 3.0f); 152 | 153 | ON_CALL(*object, rightWrist()) 154 | .WillByDefault(Invoke(object, &MockUser::FakeRightWrist)); 155 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_WRIST, v); 156 | 157 | ASSERT_TRUE(v == object->rightWrist()); 158 | } 159 | 160 | TEST_F(UserTest, TestRightHand) { 161 | ty::Vector v(1.0f, 2.0f, 3.0f); 162 | 163 | ON_CALL(*object, rightHand()) 164 | .WillByDefault(Invoke(object, &MockUser::FakeRightHand)); 165 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_HAND, v); 166 | 167 | ASSERT_TRUE(v == object->rightHand()); 168 | } 169 | 170 | TEST_F(UserTest, TestRightFingertip) { 171 | ty::Vector v(1.0f, 2.0f, 3.0f); 172 | 173 | ON_CALL(*object, rightFingertip()) 174 | .WillByDefault(Invoke(object, &MockUser::FakeRightFingertip)); 175 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_FINGERTIP, v); 176 | 177 | ASSERT_TRUE(v == object->rightFingertip()); 178 | } 179 | 180 | TEST_F(UserTest, TestLeftHip) { 181 | ty::Vector v(1.0f, 2.0f, 3.0f); 182 | 183 | ON_CALL(*object, leftHip()) 184 | .WillByDefault(Invoke(object, &MockUser::FakeLeftHip)); 185 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_HIP, v); 186 | 187 | ASSERT_TRUE(v == object->leftHip()); 188 | } 189 | 190 | TEST_F(UserTest, TestLeftKnee) { 191 | ty::Vector v(1.0f, 2.0f, 3.0f); 192 | 193 | ON_CALL(*object, leftKnee()) 194 | .WillByDefault(Invoke(object, &MockUser::FakeLeftKnee)); 195 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_KNEE, v); 196 | 197 | ASSERT_TRUE(v == object->leftKnee()); 198 | } 199 | 200 | TEST_F(UserTest, TestLeftAnkle) { 201 | ty::Vector v(1.0f, 2.0f, 3.0f); 202 | 203 | ON_CALL(*object, leftAnkle()) 204 | .WillByDefault(Invoke(object, &MockUser::FakeLeftAnkle)); 205 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_ANKLE, v); 206 | 207 | ASSERT_TRUE(v == object->leftAnkle()); 208 | } 209 | 210 | TEST_F(UserTest, TestLeftFoot) { 211 | ty::Vector v(1.0f, 2.0f, 3.0f); 212 | 213 | ON_CALL(*object, leftFoot()) 214 | .WillByDefault(Invoke(object, &MockUser::FakeLeftFoot)); 215 | object->setFakeSkeletonPosition(XN_SKEL_LEFT_FOOT, v); 216 | 217 | ASSERT_TRUE(v == object->leftFoot()); 218 | } 219 | 220 | TEST_F(UserTest, TestRightHip) { 221 | ty::Vector v(1.0f, 2.0f, 3.0f); 222 | 223 | ON_CALL(*object, rightHip()) 224 | .WillByDefault(Invoke(object, &MockUser::FakeRightHip)); 225 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_HIP, v); 226 | 227 | ASSERT_TRUE(v == object->rightHip()); 228 | } 229 | 230 | TEST_F(UserTest, TestRightKnee) { 231 | ty::Vector v(1.0f, 2.0f, 3.0f); 232 | 233 | ON_CALL(*object, rightKnee()) 234 | .WillByDefault(Invoke(object, &MockUser::FakeRightKnee)); 235 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_KNEE, v); 236 | 237 | ASSERT_TRUE(v == object->rightKnee()); 238 | } 239 | 240 | TEST_F(UserTest, TestRightAnkle) { 241 | ty::Vector v(1.0f, 2.0f, 3.0f); 242 | 243 | ON_CALL(*object, rightAnkle()) 244 | .WillByDefault(Invoke(object, &MockUser::FakeRightAnkle)); 245 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_ANKLE, v); 246 | 247 | ASSERT_TRUE(v == object->rightAnkle()); 248 | } 249 | 250 | TEST_F(UserTest, TestRightFoot) { 251 | ty::Vector v(1.0f, 2.0f, 3.0f); 252 | 253 | ON_CALL(*object, rightFoot()) 254 | .WillByDefault(Invoke(object, &MockUser::FakeRightFoot)); 255 | object->setFakeSkeletonPosition(XN_SKEL_RIGHT_FOOT, v); 256 | 257 | ASSERT_TRUE(v == object->rightFoot()); 258 | } 259 | 260 | TEST_F(UserTest, TesVectorRightUpperArm) { 261 | ON_CALL(*object, vectorRightUpperArm()) 262 | .WillByDefault(Invoke(object, &MockUser::FakeVectorRightUpperArm)); 263 | 264 | EXPECT_CALL(*object, rightShoulder()) 265 | .WillOnce(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 266 | EXPECT_CALL(*object, rightElbow()) 267 | .WillOnce(Return(ty::Vector(3.0f, 3.0f, 0.0f))); 268 | 269 | ASSERT_TRUE(ty::Vector(3.0f, 3.0f, 0.0f) == object->vectorRightUpperArm()); 270 | } 271 | 272 | TEST_F(UserTest, TesVectorRightForearm) { 273 | ON_CALL(*object, vectorRightForearm()) 274 | .WillByDefault(Invoke(object, &MockUser::FakeVectorRightForearm)); 275 | 276 | EXPECT_CALL(*object, rightElbow()) 277 | .WillOnce(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 278 | EXPECT_CALL(*object, rightHand()) 279 | .WillOnce(Return(ty::Vector(3.0f, 3.0f, 0.0f))); 280 | 281 | ASSERT_TRUE(ty::Vector(3.0f, 3.0f, 0.0f) == object->vectorRightForearm()); 282 | } 283 | 284 | TEST_F(UserTest, TesVectorLeftUpperArm) { 285 | ON_CALL(*object, vectorLeftUpperArm()) 286 | .WillByDefault(Invoke(object, &MockUser::FakeVectorLeftUpperArm)); 287 | 288 | EXPECT_CALL(*object, leftShoulder()) 289 | .WillOnce(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 290 | EXPECT_CALL(*object, leftElbow()) 291 | .WillOnce(Return(ty::Vector(3.0f, 3.0f, 0.0f))); 292 | 293 | ASSERT_TRUE(ty::Vector(3.0f, 3.0f, 0.0f) == object->vectorLeftUpperArm()); 294 | } 295 | 296 | TEST_F(UserTest, TesVectorLeftForearm) { 297 | ON_CALL(*object, vectorLeftForearm()) 298 | .WillByDefault(Invoke(object, &MockUser::FakeVectorLeftForearm)); 299 | 300 | EXPECT_CALL(*object, leftElbow()) 301 | .WillOnce(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 302 | EXPECT_CALL(*object, leftHand()) 303 | .WillOnce(Return(ty::Vector(3.0f, 3.0f, 0.0f))); 304 | 305 | ASSERT_TRUE(ty::Vector(3.0f, 3.0f, 0.0f) == object->vectorLeftForearm()); 306 | } 307 | 308 | TEST_F(UserTest, TesVectorRightUpperThigh) { 309 | ON_CALL(*object, vectorRightUpperThigh()) 310 | .WillByDefault(Invoke(object, &MockUser::FakeVectorRightUpperThigh)); 311 | 312 | EXPECT_CALL(*object, rightHip()) 313 | .WillOnce(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 314 | EXPECT_CALL(*object, rightKnee()) 315 | .WillOnce(Return(ty::Vector(3.0f, 3.0f, 0.0f))); 316 | 317 | ASSERT_TRUE(ty::Vector(3.0f, 3.0f, 0.0f) == object->vectorRightUpperThigh()); 318 | } 319 | 320 | TEST_F(UserTest, TesVectorRightLowerThigh) { 321 | ON_CALL(*object, vectorRightLowerThigh()) 322 | .WillByDefault(Invoke(object, &MockUser::FakeVectorRightLowerThigh)); 323 | 324 | EXPECT_CALL(*object, rightKnee()) 325 | .WillOnce(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 326 | EXPECT_CALL(*object, rightAnkle()) 327 | .WillOnce(Return(ty::Vector(3.0f, 3.0f, 0.0f))); 328 | 329 | ASSERT_TRUE(ty::Vector(3.0f, 3.0f, 0.0f) == object->vectorRightLowerThigh()); 330 | } 331 | 332 | TEST_F(UserTest, TesVectorLeftUpperThigh) { 333 | ON_CALL(*object, vectorLeftUpperThigh()) 334 | .WillByDefault(Invoke(object, &MockUser::FakeVectorLeftUpperThigh)); 335 | 336 | EXPECT_CALL(*object, leftHip()) 337 | .WillOnce(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 338 | EXPECT_CALL(*object, leftKnee()) 339 | .WillOnce(Return(ty::Vector(3.0f, 3.0f, 0.0f))); 340 | 341 | ASSERT_TRUE(ty::Vector(3.0f, 3.0f, 0.0f) == object->vectorLeftUpperThigh()); 342 | } 343 | 344 | TEST_F(UserTest, TesVectorLeftLowerThigh) { 345 | ON_CALL(*object, vectorLeftLowerThigh()) 346 | .WillByDefault(Invoke(object, &MockUser::FakeVectorLeftLowerThigh)); 347 | 348 | EXPECT_CALL(*object, leftKnee()) 349 | .WillOnce(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 350 | EXPECT_CALL(*object, leftAnkle()) 351 | .WillOnce(Return(ty::Vector(3.0f, 3.0f, 0.0f))); 352 | 353 | ASSERT_TRUE(ty::Vector(3.0f, 3.0f, 0.0f) == object->vectorLeftLowerThigh()); 354 | } 355 | 356 | TEST_F(UserTest, TesVectorUpperBodyForward) { 357 | ON_CALL(*object, vectorUpperBodyForward()) 358 | .WillByDefault(Invoke(object, &MockUser::FakeVectorUpperBodyForward)); 359 | 360 | EXPECT_CALL(*object, torso()) 361 | .WillRepeatedly(Return(ty::Vector(0.0f, 0.0f, 0.0f))); 362 | EXPECT_CALL(*object, rightShoulder()) 363 | .WillOnce(Return(ty::Vector( 3.0f, 3.0f, 0.0f))) 364 | .WillOnce(Return(ty::Vector( 0.0f, 3.0f, 3.0f))) 365 | .WillOnce(Return(ty::Vector(-3.0f, 3.0f, 0.0f))) 366 | .WillOnce(Return(ty::Vector( 0.0f, 3.0f, -3.0f))); 367 | EXPECT_CALL(*object, leftShoulder()) 368 | .WillOnce(Return(ty::Vector(-3.0f, 3.0f, 0.0f))) 369 | .WillOnce(Return(ty::Vector( 0.0f, 3.0f, -3.0f))) 370 | .WillOnce(Return(ty::Vector( 3.0f, 3.0f, 0.0f))) 371 | .WillOnce(Return(ty::Vector( 0.0f, 3.0f, 3.0f))); 372 | 373 | ASSERT_TRUE(ty::Vector( 0.0f, 0.0f, -1.0f) == object->vectorUpperBodyForward()); 374 | ASSERT_TRUE(ty::Vector( 1.0f, 0.0f, 0.0f) == object->vectorUpperBodyForward()); 375 | ASSERT_TRUE(ty::Vector( 0.0f, 0.0f, 1.0f) == object->vectorUpperBodyForward()); 376 | ASSERT_TRUE(ty::Vector(-1.0f, 0.0f, 0.0f) == object->vectorUpperBodyForward()); 377 | } 378 | 379 | TEST_F(UserTest, TestLeftArmIsStriaght) { 380 | ON_CALL(*object, leftArmIsStraight()) 381 | .WillByDefault(Invoke(object, &MockUser::FakeLeftArmIsStraight)); 382 | 383 | EXPECT_CALL(*object, vectorLeftUpperArm()) 384 | .WillRepeatedly(Return(ty::Vector(3.0f, 0.0f, 0.0f))); 385 | EXPECT_CALL(*object, vectorLeftForearm()) 386 | .WillOnce(Return(ty::Vector(3.0f, 0.0f, 0.0f))) 387 | .WillOnce(Return(ty::Vector(0.0f, 3.0f, 0.0f))); 388 | 389 | ASSERT_TRUE(object->leftArmIsStraight()); 390 | ASSERT_FALSE(object->leftArmIsStraight()); 391 | } 392 | 393 | TEST_F(UserTest, TestLeftArmIsBentRightAngle) { 394 | ON_CALL(*object, leftArmIsBentRightAngle()) 395 | .WillByDefault(Invoke(object, &MockUser::FakeLeftArmIsBentRightAngle)); 396 | 397 | EXPECT_CALL(*object, vectorLeftUpperArm()) 398 | .WillRepeatedly(Return(ty::Vector(3.0f, 0.0f, 0.0f))); 399 | EXPECT_CALL(*object, vectorLeftForearm()) 400 | .WillOnce(Return(ty::Vector(0.0f, 3.0f, 0.0f))) 401 | .WillOnce(Return(ty::Vector(3.0f, 0.0f, 0.0f))); 402 | 403 | ASSERT_TRUE(object->leftArmIsBentRightAngle()); 404 | ASSERT_FALSE(object->leftArmIsBentRightAngle()); 405 | } 406 | 407 | TEST_F(UserTest, TestRightArmIsBentRightAngle) { 408 | ON_CALL(*object, rightArmIsBentRightAngle()) 409 | .WillByDefault(Invoke(object, &MockUser::FakeRightArmIsBentRightAngle)); 410 | 411 | EXPECT_CALL(*object, vectorRightUpperArm()) 412 | .WillRepeatedly(Return(ty::Vector(3.0f, 0.0f, 0.0f))); 413 | EXPECT_CALL(*object, vectorRightForearm()) 414 | .WillOnce(Return(ty::Vector(0.0f, 3.0f, 0.0f))) 415 | .WillOnce(Return(ty::Vector(3.0f, 0.0f, 0.0f))); 416 | 417 | ASSERT_TRUE(object->rightArmIsBentRightAngle()); 418 | ASSERT_FALSE(object->rightArmIsBentRightAngle()); 419 | } 420 | 421 | TEST_F(UserTest, TestRightArmIsStriaght) { 422 | ON_CALL(*object, rightArmIsStraight()) 423 | .WillByDefault(Invoke(object, &MockUser::FakeRightArmIsStraight)); 424 | 425 | EXPECT_CALL(*object, vectorRightUpperArm()) 426 | .WillRepeatedly(Return(ty::Vector(3.0f, 0.0f, 0.0f))); 427 | EXPECT_CALL(*object, vectorRightForearm()) 428 | .WillOnce(Return(ty::Vector(3.0f, 0.0f, 0.0f))) 429 | .WillOnce(Return(ty::Vector(0.0f, 3.0f, 0.0f))); 430 | 431 | ASSERT_TRUE(object->rightArmIsStraight()); 432 | ASSERT_FALSE(object->rightArmIsStraight()); 433 | } 434 | 435 | TEST_F(UserTest, TestIsConfident) { 436 | ON_CALL(*object, isConfident(_)) 437 | .WillByDefault(Invoke(object, &MockUser::FakeIsConfident)); 438 | 439 | XnSkeletonJointPosition p; 440 | p.position = ty::Vector(0.0f, 0.0f, 0.0f); 441 | 442 | p.fConfidence = ty::User::THRESHOLD_CONFIDENCE; 443 | ASSERT_TRUE(object->isConfident(p)); 444 | 445 | p.fConfidence = ty::User::THRESHOLD_CONFIDENCE + 0.1; 446 | ASSERT_TRUE(object->isConfident(p)); 447 | 448 | p.fConfidence = ty::User::THRESHOLD_CONFIDENCE - 0.1; 449 | ASSERT_FALSE(object->isConfident(p)); 450 | } 451 | -------------------------------------------------------------------------------- /test/VectorTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Vector.h" 4 | #include "MockVector.h" 5 | 6 | class VectorTest : public testing::Test { 7 | public: 8 | virtual void SetUp() { 9 | x = 100.0f; 10 | y = -12.0f; 11 | z = 0.0f; 12 | } 13 | 14 | float x, y, z; 15 | }; 16 | 17 | TEST_F(VectorTest, TestConstructor) { 18 | ty::Vector vec; 19 | 20 | ASSERT_EQ(0.0f, vec.X); 21 | ASSERT_EQ(0.0f, vec.Y); 22 | ASSERT_EQ(0.0f, vec.Z); 23 | } 24 | 25 | TEST_F(VectorTest, TestConstructorWithXnVector3D) { 26 | XnVector3D v = {x, y, z}; 27 | ty::Vector vec(v); 28 | 29 | ASSERT_EQ(v.X, vec.X); 30 | ASSERT_EQ(v.Y, vec.Y); 31 | ASSERT_EQ(v.Z, vec.Z); 32 | } 33 | 34 | TEST_F(VectorTest, TestConstructorWithFloat) { 35 | ty::Vector vec(x, y, z); 36 | 37 | ASSERT_EQ(x, vec.X); 38 | ASSERT_EQ(y, vec.Y); 39 | ASSERT_EQ(z, vec.Z); 40 | } 41 | 42 | TEST_F(VectorTest, TestAssignOperatorPlus) { 43 | ty::Vector vec1(x, y, z); 44 | ty::Vector vec2(x, y, z); 45 | 46 | vec1 += vec2; 47 | 48 | ASSERT_EQ(x + x, vec1.X); 49 | ASSERT_EQ(y + y, vec1.Y); 50 | ASSERT_EQ(z + z, vec1.Z); 51 | } 52 | 53 | TEST_F(VectorTest, TestAssignOperatorMinus) { 54 | ty::Vector vec1(x, y, z); 55 | ty::Vector vec2(x, y, z); 56 | 57 | vec1 -= vec2; 58 | 59 | ASSERT_EQ(x - x, vec1.X); 60 | ASSERT_EQ(y - y, vec1.Y); 61 | ASSERT_EQ(z - z, vec1.Z); 62 | } 63 | 64 | TEST_F(VectorTest, TestAssignOperatorMulti) { 65 | ty::Vector vec(x, y, z); 66 | float f = 3.0f; 67 | 68 | vec *= f; 69 | 70 | ASSERT_EQ(x * f, vec.X); 71 | ASSERT_EQ(y * f, vec.Y); 72 | ASSERT_EQ(z * f, vec.Z); 73 | } 74 | 75 | TEST_F(VectorTest, TestAssignOperatorDiv) { 76 | ty::Vector vec(x, y, z); 77 | float f = 3.0f; 78 | 79 | vec /= f; 80 | 81 | ASSERT_EQ(x / f, vec.X); 82 | ASSERT_EQ(y / f, vec.Y); 83 | ASSERT_EQ(z / f, vec.Z); 84 | } 85 | 86 | TEST_F(VectorTest, TestOperatorPlus) { 87 | ty::Vector vec1(x, y, z); 88 | ty::Vector vec2(x, y, z); 89 | 90 | ty::Vector vec3 = vec1 + vec2; 91 | 92 | ASSERT_EQ(x + x, vec3.X); 93 | ASSERT_EQ(y + y, vec3.Y); 94 | ASSERT_EQ(z + z, vec3.Z); 95 | } 96 | 97 | TEST_F(VectorTest, TestOperatorMinus) { 98 | ty::Vector vec1(x, y, z); 99 | ty::Vector vec2(x, y, z); 100 | 101 | ty::Vector vec3 = vec1 - vec2; 102 | 103 | ASSERT_EQ(x - x, vec3.X); 104 | ASSERT_EQ(y - y, vec3.Y); 105 | ASSERT_EQ(z - z, vec3.Z); 106 | } 107 | 108 | TEST_F(VectorTest, TestOperatorMulti) { 109 | ty::Vector vec1(x, y, z); 110 | float f = 3.0f; 111 | 112 | ty::Vector vec2 = vec1 * f; 113 | 114 | ASSERT_EQ(x * f, vec2.X); 115 | ASSERT_EQ(y * f, vec2.Y); 116 | ASSERT_EQ(z * f, vec2.Z); 117 | } 118 | 119 | TEST_F(VectorTest, TestOperatorDiv) { 120 | ty::Vector vec1(x, y, z); 121 | float f = 3.0f; 122 | 123 | ty::Vector vec2 = vec1 / f; 124 | 125 | ASSERT_EQ(x / f, vec2.X); 126 | ASSERT_EQ(y / f, vec2.Y); 127 | ASSERT_EQ(z / f, vec2.Z); 128 | } 129 | 130 | TEST_F(VectorTest, TestOperatorEqual) { 131 | ty::Vector vec1(x, y, z); 132 | ty::Vector vec2(x, y, z); 133 | ty::Vector vec3(x, y + 1, z + 1); 134 | 135 | ASSERT_TRUE(vec1 == vec2); 136 | ASSERT_FALSE(vec1 == vec3); 137 | } 138 | 139 | TEST_F(VectorTest, TestMagnitude) { 140 | ty::Vector vec(x, y, z); 141 | ASSERT_EQ(sqrtf(x*x + y*y + z*z), vec.magnitude()); 142 | } 143 | 144 | TEST_F(VectorTest, TestNormalize) { 145 | ty::Vector v(x, y, z); 146 | ty::Vector nv = v.normalize(); 147 | 148 | ASSERT_GE(1.0f, nv.magnitude()); // 誤差範囲内をテスト 149 | ASSERT_LT(0.999f, nv.magnitude()); // 1.0 >= magnitude > 0.999 150 | } 151 | 152 | TEST_F(VectorTest, TestDot) { 153 | ty::Vector vec1(3.0f, 0.0f, 0.0f); 154 | ty::Vector vec2(0.0f, 1.0f, 0.0f); 155 | ty::Vector vec3(1.0f, 1.0f, 1.0f); 156 | ty::Vector vec4(-12.0f, 0.0f, 0.0f); 157 | 158 | ASSERT_EQ( 1.0f, vec1.dot(vec1)); // 平行(同方向) 159 | ASSERT_EQ( 0.0f, vec1.dot(vec2)); // 直行 160 | ASSERT_LT( 0.0f, vec1.dot(vec3)); // 鋭角 161 | ASSERT_EQ(-1.0f, vec1.dot(vec4)); // 平行(逆方向) 162 | ASSERT_GT( 0.0f, vec3.dot(vec4)); // 鈍角 163 | } 164 | 165 | TEST_F(VectorTest, TestCross) { 166 | ty::Vector vec0; 167 | ty::Vector vecX(1.0f, 0.0f, 0.0f); 168 | ty::Vector vecY(0.0f, 1.0f, 0.0f); 169 | ty::Vector vecZ(0.0f, 0.0f, 1.0f); 170 | 171 | ASSERT_TRUE(ty::Vector(0.0f, 0.0f, 1.0f) == vecX.cross(vecY)); 172 | ASSERT_TRUE(ty::Vector(0.0f, 0.0f, -1.0f) == vecY.cross(vecX)); 173 | ASSERT_TRUE(ty::Vector(0.0f, -1.0f, 0.0f) == vecX.cross(vecZ)); 174 | ASSERT_TRUE(ty::Vector(0.0f, 1.0f, 0.0f) == vecZ.cross(vecX)); 175 | ASSERT_TRUE(ty::Vector( 1.0f, 0.0f, 0.0f) == vecY.cross(vecZ)); 176 | ASSERT_TRUE(ty::Vector(-1.0f, 0.0f, 0.0f) == vecZ.cross(vecY)); 177 | } 178 | 179 | TEST_F(VectorTest, TestDistance) { 180 | ty::Vector v1(1.0f, 0.0f, 3.0f); 181 | ty::Vector v2(3.0f, 0.0f, 0.0f); 182 | ty::Vector v3(-3.0f, 0.0f, 0.0f); 183 | 184 | ASSERT_EQ(0.0f, v1.distance(v1)); 185 | ASSERT_EQ(6.0f, v2.distance(v3)); 186 | } 187 | 188 | TEST_F(VectorTest, TestReverse) { 189 | ty::Vector vec(x, y, z); 190 | ty::Vector rev = vec.reverse(); 191 | 192 | ASSERT_EQ(-x, rev.X); 193 | ASSERT_EQ(-y, rev.Y); 194 | ASSERT_EQ(-z, rev.Z); 195 | } 196 | 197 | TEST_F(VectorTest, TestWithinAngle) { 198 | ASSERT_FALSE(MockVector::v00.withinAngle(MockVector::v30, 29.0f)); 199 | ASSERT_FALSE(MockVector::v00.withinAngle(MockVector::v60, 59.0f)); 200 | ASSERT_FALSE(MockVector::v00.withinAngle(MockVector::v90, 89.0f)); 201 | ASSERT_FALSE(MockVector::v00.withinAngle(MockVector::v120, 119.0f)); 202 | ASSERT_FALSE(MockVector::v00.withinAngle(MockVector::v150, 149.0f)); 203 | ASSERT_FALSE(MockVector::v00.withinAngle(MockVector::v180, 179.0f)); 204 | ASSERT_FALSE(MockVector::v30.withinAngle(MockVector::v60, 29.0f)); 205 | ASSERT_FALSE(MockVector::v30.withinAngle(MockVector::v90, 59.0f)); 206 | ASSERT_FALSE(MockVector::v30.withinAngle(MockVector::v120, 89.0f)); 207 | ASSERT_FALSE(MockVector::v30.withinAngle(MockVector::v150, 119.0f)); 208 | ASSERT_FALSE(MockVector::v30.withinAngle(MockVector::v180, 149.0f)); 209 | ASSERT_FALSE(MockVector::v60.withinAngle(MockVector::v90, 29.0f)); 210 | ASSERT_FALSE(MockVector::v60.withinAngle(MockVector::v120, 59.0f)); 211 | ASSERT_FALSE(MockVector::v60.withinAngle(MockVector::v150, 89.0f)); 212 | ASSERT_FALSE(MockVector::v60.withinAngle(MockVector::v180, 119.0f)); 213 | ASSERT_FALSE(MockVector::v90.withinAngle(MockVector::v120, 29.0f)); 214 | ASSERT_FALSE(MockVector::v90.withinAngle(MockVector::v150, 59.0f)); 215 | ASSERT_FALSE(MockVector::v90.withinAngle(MockVector::v180, 89.0f)); 216 | ASSERT_FALSE(MockVector::v120.withinAngle(MockVector::v150, 29.0f)); 217 | ASSERT_FALSE(MockVector::v120.withinAngle(MockVector::v180, 59.0f)); 218 | ASSERT_FALSE(MockVector::v150.withinAngle(MockVector::v180, 29.0f)); 219 | 220 | ASSERT_TRUE(MockVector::v00.withinAngle(MockVector::v30, 31.0f)); 221 | ASSERT_TRUE(MockVector::v00.withinAngle(MockVector::v60, 61.0f)); 222 | ASSERT_TRUE(MockVector::v00.withinAngle(MockVector::v90, 91.0f)); 223 | ASSERT_TRUE(MockVector::v00.withinAngle(MockVector::v120, 121.0f)); 224 | ASSERT_TRUE(MockVector::v00.withinAngle(MockVector::v150, 151.0f)); 225 | ASSERT_TRUE(MockVector::v30.withinAngle(MockVector::v60, 31.0f)); 226 | ASSERT_TRUE(MockVector::v30.withinAngle(MockVector::v90, 61.0f)); 227 | ASSERT_TRUE(MockVector::v30.withinAngle(MockVector::v120, 91.0f)); 228 | ASSERT_TRUE(MockVector::v30.withinAngle(MockVector::v150, 121.0f)); 229 | ASSERT_TRUE(MockVector::v30.withinAngle(MockVector::v180, 151.0f)); 230 | ASSERT_TRUE(MockVector::v60.withinAngle(MockVector::v90, 31.0f)); 231 | ASSERT_TRUE(MockVector::v60.withinAngle(MockVector::v120, 61.0f)); 232 | ASSERT_TRUE(MockVector::v60.withinAngle(MockVector::v150, 91.0f)); 233 | ASSERT_TRUE(MockVector::v60.withinAngle(MockVector::v180, 121.0f)); 234 | ASSERT_TRUE(MockVector::v90.withinAngle(MockVector::v120, 31.0f)); 235 | ASSERT_TRUE(MockVector::v90.withinAngle(MockVector::v150, 61.0f)); 236 | ASSERT_TRUE(MockVector::v90.withinAngle(MockVector::v180, 91.0f)); 237 | ASSERT_TRUE(MockVector::v120.withinAngle(MockVector::v150, 31.0f)); 238 | ASSERT_TRUE(MockVector::v120.withinAngle(MockVector::v180, 61.0f)); 239 | ASSERT_TRUE(MockVector::v150.withinAngle(MockVector::v180, 31.0f)); 240 | } 241 | 242 | TEST_F(VectorTest, TestWithoutAngle) { 243 | ASSERT_TRUE(MockVector::v00.withoutAngle(MockVector::v30, 29.0f)); 244 | ASSERT_TRUE(MockVector::v00.withoutAngle(MockVector::v60, 59.0f)); 245 | ASSERT_TRUE(MockVector::v00.withoutAngle(MockVector::v90, 89.0f)); 246 | ASSERT_TRUE(MockVector::v00.withoutAngle(MockVector::v120, 119.0f)); 247 | ASSERT_TRUE(MockVector::v00.withoutAngle(MockVector::v150, 149.0f)); 248 | ASSERT_TRUE(MockVector::v00.withoutAngle(MockVector::v180, 179.0f)); 249 | ASSERT_TRUE(MockVector::v30.withoutAngle(MockVector::v60, 29.0f)); 250 | ASSERT_TRUE(MockVector::v30.withoutAngle(MockVector::v90, 59.0f)); 251 | ASSERT_TRUE(MockVector::v30.withoutAngle(MockVector::v120, 89.0f)); 252 | ASSERT_TRUE(MockVector::v30.withoutAngle(MockVector::v150, 119.0f)); 253 | ASSERT_TRUE(MockVector::v30.withoutAngle(MockVector::v180, 149.0f)); 254 | ASSERT_TRUE(MockVector::v60.withoutAngle(MockVector::v90, 29.0f)); 255 | ASSERT_TRUE(MockVector::v60.withoutAngle(MockVector::v120, 59.0f)); 256 | ASSERT_TRUE(MockVector::v60.withoutAngle(MockVector::v150, 89.0f)); 257 | ASSERT_TRUE(MockVector::v60.withoutAngle(MockVector::v180, 119.0f)); 258 | ASSERT_TRUE(MockVector::v90.withoutAngle(MockVector::v120, 29.0f)); 259 | ASSERT_TRUE(MockVector::v90.withoutAngle(MockVector::v150, 59.0f)); 260 | ASSERT_TRUE(MockVector::v90.withoutAngle(MockVector::v180, 89.0f)); 261 | ASSERT_TRUE(MockVector::v120.withoutAngle(MockVector::v150, 29.0f)); 262 | ASSERT_TRUE(MockVector::v120.withoutAngle(MockVector::v180, 59.0f)); 263 | ASSERT_TRUE(MockVector::v150.withoutAngle(MockVector::v180, 29.0f)); 264 | 265 | ASSERT_FALSE(MockVector::v00.withoutAngle(MockVector::v30, 31.0f)); 266 | ASSERT_FALSE(MockVector::v00.withoutAngle(MockVector::v60, 61.0f)); 267 | ASSERT_FALSE(MockVector::v00.withoutAngle(MockVector::v90, 91.0f)); 268 | ASSERT_FALSE(MockVector::v00.withoutAngle(MockVector::v120, 121.0f)); 269 | ASSERT_FALSE(MockVector::v00.withoutAngle(MockVector::v150, 151.0f)); 270 | ASSERT_FALSE(MockVector::v30.withoutAngle(MockVector::v60, 31.0f)); 271 | ASSERT_FALSE(MockVector::v30.withoutAngle(MockVector::v90, 61.0f)); 272 | ASSERT_FALSE(MockVector::v30.withoutAngle(MockVector::v120, 91.0f)); 273 | ASSERT_FALSE(MockVector::v30.withoutAngle(MockVector::v150, 121.0f)); 274 | ASSERT_FALSE(MockVector::v30.withoutAngle(MockVector::v180, 151.0f)); 275 | ASSERT_FALSE(MockVector::v60.withoutAngle(MockVector::v90, 31.0f)); 276 | ASSERT_FALSE(MockVector::v60.withoutAngle(MockVector::v120, 61.0f)); 277 | ASSERT_FALSE(MockVector::v60.withoutAngle(MockVector::v150, 91.0f)); 278 | ASSERT_FALSE(MockVector::v60.withoutAngle(MockVector::v180, 121.0f)); 279 | ASSERT_FALSE(MockVector::v90.withoutAngle(MockVector::v120, 31.0f)); 280 | ASSERT_FALSE(MockVector::v90.withoutAngle(MockVector::v150, 61.0f)); 281 | ASSERT_FALSE(MockVector::v90.withoutAngle(MockVector::v180, 91.0f)); 282 | ASSERT_FALSE(MockVector::v120.withoutAngle(MockVector::v150, 31.0f)); 283 | ASSERT_FALSE(MockVector::v120.withoutAngle(MockVector::v180, 61.0f)); 284 | ASSERT_FALSE(MockVector::v150.withoutAngle(MockVector::v180, 31.0f)); 285 | } 286 | 287 | TEST_F(VectorTest, TestIsOrthogonal) { 288 | ASSERT_FALSE(MockVector::v00.isOrthogonal(MockVector::v30)); 289 | ASSERT_FALSE(MockVector::v00.isOrthogonal(MockVector::v60)); 290 | ASSERT_TRUE(MockVector::v00.isOrthogonal(MockVector::v90)); 291 | ASSERT_FALSE(MockVector::v00.isOrthogonal(MockVector::v120)); 292 | ASSERT_FALSE(MockVector::v00.isOrthogonal(MockVector::v150)); 293 | ASSERT_FALSE(MockVector::v00.isOrthogonal(MockVector::v180)); 294 | 295 | ASSERT_FALSE(MockVector::v30.isOrthogonal(MockVector::v60)); 296 | ASSERT_FALSE(MockVector::v30.isOrthogonal(MockVector::v90)); 297 | ASSERT_TRUE(MockVector::v30.isOrthogonal(MockVector::v120)); 298 | ASSERT_FALSE(MockVector::v30.isOrthogonal(MockVector::v150)); 299 | ASSERT_FALSE(MockVector::v30.isOrthogonal(MockVector::v180)); 300 | 301 | ASSERT_FALSE(MockVector::v60.isOrthogonal(MockVector::v90)); 302 | ASSERT_FALSE(MockVector::v60.isOrthogonal(MockVector::v120)); 303 | ASSERT_TRUE(MockVector::v60.isOrthogonal(MockVector::v150)); 304 | ASSERT_FALSE(MockVector::v60.isOrthogonal(MockVector::v180)); 305 | 306 | ASSERT_FALSE(MockVector::v90.isOrthogonal(MockVector::v120)); 307 | ASSERT_FALSE(MockVector::v90.isOrthogonal(MockVector::v150)); 308 | ASSERT_TRUE(MockVector::v90.isOrthogonal(MockVector::v180)); 309 | 310 | ASSERT_FALSE(MockVector::v120.isOrthogonal(MockVector::v150)); 311 | ASSERT_FALSE(MockVector::v120.isOrthogonal(MockVector::v180)); 312 | 313 | ASSERT_FALSE(MockVector::v150.isOrthogonal(MockVector::v180)); 314 | } 315 | 316 | TEST_F(VectorTest, TestIsStraight) { 317 | ASSERT_TRUE(MockVector::v00.isStraight(MockVector::v00)); 318 | ASSERT_FALSE(MockVector::v00.isStraight(MockVector::v30)); 319 | ASSERT_FALSE(MockVector::v00.isStraight(MockVector::v60)); 320 | ASSERT_FALSE(MockVector::v00.isStraight(MockVector::v90)); 321 | ASSERT_FALSE(MockVector::v00.isStraight(MockVector::v120)); 322 | ASSERT_FALSE(MockVector::v00.isStraight(MockVector::v150)); 323 | ASSERT_FALSE(MockVector::v00.isStraight(MockVector::v180)); 324 | 325 | ASSERT_TRUE(MockVector::v30.isStraight(MockVector::v30)); 326 | ASSERT_FALSE(MockVector::v30.isStraight(MockVector::v60)); 327 | ASSERT_FALSE(MockVector::v30.isStraight(MockVector::v90)); 328 | ASSERT_FALSE(MockVector::v30.isStraight(MockVector::v120)); 329 | ASSERT_FALSE(MockVector::v30.isStraight(MockVector::v150)); 330 | ASSERT_FALSE(MockVector::v30.isStraight(MockVector::v180)); 331 | 332 | ASSERT_TRUE(MockVector::v60.isStraight(MockVector::v60)); 333 | ASSERT_FALSE(MockVector::v60.isStraight(MockVector::v90)); 334 | ASSERT_FALSE(MockVector::v60.isStraight(MockVector::v120)); 335 | ASSERT_FALSE(MockVector::v60.isStraight(MockVector::v150)); 336 | ASSERT_FALSE(MockVector::v60.isStraight(MockVector::v180)); 337 | 338 | ASSERT_TRUE(MockVector::v90.isStraight(MockVector::v90)); 339 | ASSERT_FALSE(MockVector::v90.isStraight(MockVector::v120)); 340 | ASSERT_FALSE(MockVector::v90.isStraight(MockVector::v150)); 341 | ASSERT_FALSE(MockVector::v90.isStraight(MockVector::v180)); 342 | 343 | ASSERT_TRUE(MockVector::v120.isStraight(MockVector::v120)); 344 | ASSERT_FALSE(MockVector::v120.isStraight(MockVector::v150)); 345 | ASSERT_FALSE(MockVector::v120.isStraight(MockVector::v180)); 346 | 347 | ASSERT_TRUE(MockVector::v150.isStraight(MockVector::v150)); 348 | ASSERT_FALSE(MockVector::v150.isStraight(MockVector::v180)); 349 | 350 | ASSERT_TRUE(MockVector::v180.isStraight(MockVector::v180)); 351 | } 352 | 353 | TEST_F(VectorTest, TestIsParallel) { 354 | ASSERT_TRUE(MockVector::v00.isParallel(MockVector::v00)); 355 | ASSERT_FALSE(MockVector::v00.isParallel(MockVector::v30)); 356 | ASSERT_FALSE(MockVector::v00.isParallel(MockVector::v60)); 357 | ASSERT_FALSE(MockVector::v00.isParallel(MockVector::v90)); 358 | ASSERT_FALSE(MockVector::v00.isParallel(MockVector::v120)); 359 | ASSERT_FALSE(MockVector::v00.isParallel(MockVector::v150)); 360 | ASSERT_TRUE(MockVector::v00.isParallel(MockVector::v180)); 361 | 362 | ASSERT_TRUE(MockVector::v30.isParallel(MockVector::v30)); 363 | ASSERT_FALSE(MockVector::v30.isParallel(MockVector::v60)); 364 | ASSERT_FALSE(MockVector::v30.isParallel(MockVector::v90)); 365 | ASSERT_FALSE(MockVector::v30.isParallel(MockVector::v120)); 366 | ASSERT_FALSE(MockVector::v30.isParallel(MockVector::v150)); 367 | ASSERT_FALSE(MockVector::v30.isParallel(MockVector::v180)); 368 | 369 | ASSERT_TRUE(MockVector::v60.isParallel(MockVector::v60)); 370 | ASSERT_FALSE(MockVector::v60.isParallel(MockVector::v90)); 371 | ASSERT_FALSE(MockVector::v60.isParallel(MockVector::v120)); 372 | ASSERT_FALSE(MockVector::v60.isParallel(MockVector::v150)); 373 | ASSERT_FALSE(MockVector::v60.isParallel(MockVector::v180)); 374 | 375 | ASSERT_TRUE(MockVector::v90.isParallel(MockVector::v90)); 376 | ASSERT_FALSE(MockVector::v90.isParallel(MockVector::v120)); 377 | ASSERT_FALSE(MockVector::v90.isParallel(MockVector::v150)); 378 | ASSERT_FALSE(MockVector::v90.isParallel(MockVector::v180)); 379 | 380 | ASSERT_TRUE(MockVector::v120.isParallel(MockVector::v120)); 381 | ASSERT_FALSE(MockVector::v120.isParallel(MockVector::v150)); 382 | ASSERT_FALSE(MockVector::v120.isParallel(MockVector::v180)); 383 | 384 | ASSERT_TRUE(MockVector::v150.isParallel(MockVector::v150)); 385 | ASSERT_FALSE(MockVector::v150.isParallel(MockVector::v180)); 386 | 387 | ASSERT_TRUE(MockVector::v180.isParallel(MockVector::v180)); 388 | } 389 | --------------------------------------------------------------------------------