From 9af4b10400dcb473ee0d86d07af0ffffd7635eee Mon Sep 17 00:00:00 2001 From: Vache Katsadze Date: Wed, 16 Mar 2022 14:33:46 +0400 Subject: [PATCH] Updated BT samples to use the BT SDK 1.1.1 (#66) * Fixed cmake issues * Update BT samples to use the Body Tracking SDK 1.1.1 Co-authored-by: Vache Katsadze --- CMakeLists.txt | 2 +- body-tracking-samples/CMakeLists.txt | 27 + .../CMakeLists.txt | 11 + .../camera_space_transform_sample.vcxproj | 22 +- ...era_space_transform_sample.vcxproj.filters | 4 +- .../camera_space_transform_sample/main.cpp | 55 +- .../packages.config | 7 +- .../cmake/FetchContent.cmake | 916 ++++++++++++++++++ .../cmake/FetchContent/CMakeLists.cmake.in | 21 + .../csharp_3d_viewer/Csharp_3d_viewer.csproj | 2 +- body-tracking-samples/extern/CMakeLists.txt | 1 + .../extern/nlohmann_json/CMakeLists.txt | 16 + .../floor_detector_sample/CMakeLists.txt | 18 + .../floor_detector_sample.vcxproj | 20 +- .../floor_detector_sample/packages.config | 7 +- .../jump_analysis_sample/CMakeLists.txt | 20 + .../jump_analysis_sample.vcxproj | 20 +- .../jump_analysis_sample/main.cpp | 58 +- .../jump_analysis_sample/packages.config | 7 +- .../offline_processor/CMakeLists.txt | 15 + .../offline_processor/main.cpp | 68 +- .../offline_processor.vcxproj | 22 +- .../offline_processor/packages.config | 7 +- .../window_controller_3d/glad/glad.h | 7 + .../window_controller_3d/packages.config | 4 +- .../window_controller_3d.vcxproj | 12 +- .../simple_3d_viewer/CMakeLists.txt | 1 + .../simple_3d_viewer/main.cpp | 176 ++-- .../simple_3d_viewer/packages.config | 7 +- .../simple_3d_viewer/simple_3d_viewer.vcxproj | 18 +- .../simple_cpp_sample/packages.config | 7 +- .../simple_cpp_sample.vcxproj | 22 +- body-tracking-samples/simple_sample/main.c | 19 + .../simple_sample/packages.config | 7 +- .../simple_sample/simple_sample.vcxproj | 22 +- 35 files changed, 1449 insertions(+), 199 deletions(-) create mode 100644 body-tracking-samples/camera_space_transform_sample/CMakeLists.txt create mode 100644 body-tracking-samples/cmake/FetchContent.cmake create mode 100644 body-tracking-samples/cmake/FetchContent/CMakeLists.cmake.in create mode 100644 body-tracking-samples/extern/nlohmann_json/CMakeLists.txt create mode 100644 body-tracking-samples/floor_detector_sample/CMakeLists.txt create mode 100644 body-tracking-samples/jump_analysis_sample/CMakeLists.txt create mode 100644 body-tracking-samples/offline_processor/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 56be49bf..c9f2304a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.9.0) -cmake_policy(SET CMP0048 NEW) +set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) project(Azure-Kinect-Samples LANGUAGES C CXX VERSION 1.4) diff --git a/body-tracking-samples/CMakeLists.txt b/body-tracking-samples/CMakeLists.txt index 2992139a..d307c457 100644 --- a/body-tracking-samples/CMakeLists.txt +++ b/body-tracking-samples/CMakeLists.txt @@ -1,7 +1,34 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/extern/glfw/src/CMakeLists.txt") + find_package(Git REQUIRED QUIET) + if (Git_FOUND) + message(STATUS "Fetching git modules...") + execute_process( + COMMAND + ${GIT_EXECUTABLE} submodule update --init --recursive + WORKING_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE + GIT_SUBMODULE_UPDATE_RESULT + OUTPUT_VARIABLE + GIT_SUBMODULE_UPDATE_OUTPUT + ) + + if (NOT (${GIT_SUBMODULE_UPDATE_RESULT} EQUAL 0)) + message(FATAL_ERROR "git submodule update failed: ${GIT_SUBMODULE_UDPATE_OUTPUT}") + endif() + endif() +endif() + +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_LIST_DIR}/cmake) + add_subdirectory(extern) +add_subdirectory(camera_space_transform_sample) +add_subdirectory(floor_detector_sample) +add_subdirectory(jump_analysis_sample) +add_subdirectory(offline_processor) add_subdirectory(simple_3d_viewer) add_subdirectory(simple_sample) add_subdirectory(sample_helper_libs) diff --git a/body-tracking-samples/camera_space_transform_sample/CMakeLists.txt b/body-tracking-samples/camera_space_transform_sample/CMakeLists.txt new file mode 100644 index 00000000..703b25ea --- /dev/null +++ b/body-tracking-samples/camera_space_transform_sample/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +add_executable(camera_space_transform_sample + main.cpp +) + +target_link_libraries(camera_space_transform_sample PRIVATE + k4a + k4abt +) diff --git a/body-tracking-samples/camera_space_transform_sample/camera_space_transform_sample.vcxproj b/body-tracking-samples/camera_space_transform_sample/camera_space_transform_sample.vcxproj index 53f6a886..270571af 100644 --- a/body-tracking-samples/camera_space_transform_sample/camera_space_transform_sample.vcxproj +++ b/body-tracking-samples/camera_space_transform_sample/camera_space_transform_sample.vcxproj @@ -14,19 +14,19 @@ 15.0 {A7D2F1BE-0030-4436-B391-FEDE1E756B02} cameraspacetransformsample - 10.0.17134.0 + 10.0 Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte @@ -91,18 +91,16 @@ - - - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + - + \ No newline at end of file diff --git a/body-tracking-samples/camera_space_transform_sample/camera_space_transform_sample.vcxproj.filters b/body-tracking-samples/camera_space_transform_sample/camera_space_transform_sample.vcxproj.filters index f85b9e2f..85ab78ad 100644 --- a/body-tracking-samples/camera_space_transform_sample/camera_space_transform_sample.vcxproj.filters +++ b/body-tracking-samples/camera_space_transform_sample/camera_space_transform_sample.vcxproj.filters @@ -15,7 +15,7 @@ - + Source Files @@ -24,4 +24,4 @@ - + \ No newline at end of file diff --git a/body-tracking-samples/camera_space_transform_sample/main.cpp b/body-tracking-samples/camera_space_transform_sample/main.cpp index 4ed4bfa6..6ae9cec8 100644 --- a/body-tracking-samples/camera_space_transform_sample/main.cpp +++ b/body-tracking-samples/camera_space_transform_sample/main.cpp @@ -80,7 +80,58 @@ void transform_body_index_map_from_depth_to_color( K4ABT_BODY_INDEX_MAP_BACKGROUND), "Failed to transform body index map to color space!"); } -int main() +bool ProcessArguments(k4abt_tracker_configuration_t& tracker_config, int argc, char** argv) +{ +#ifdef _WIN32 + printf("Usage: k4abt_camera_space_transform_sample PROCESSING_MODE[CUDA, CPU, DirectML ( default ), or TensorRT](optional) -model MODEL_FILEPATH(optional).\n"); +#else + printf("Usage: k4abt_camera_space_transform_sample PROCESSING_MODE[CUDA ( default ), CPU, or TensorRT](optional) -model MODEL_FILEPATH(optional).\n"); +#endif + + for (int i = 1; i < argc; i++) + { + if (0 == strcmp(argv[i], "TensorRT")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_TENSORRT; + } + else if (0 == strcmp(argv[i], "CUDA")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_CUDA; + } + else if (0 == strcmp(argv[i], "CPU")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_CPU; + } +#ifdef _WIN32 + else if (0 == strcmp(argv[i], "DirectML")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_DIRECTML; + } +#endif + else if (0 == strcmp(argv[i], "-model")) + { + if( i < argc - 1 ) + tracker_config.model_path = argv[++i]; + else + { + printf("Error: model filepath missing\n"); + return false; + } + } + else + { +#ifdef _WIN32 + printf("Invalid processing mode ! Accepted values are CUDA, CPU, DirectML ( default ), or TensorRT.\n"); +#else + printf("Invalid processing mode ! Accepted values are CUDA ( default ), CPU, or TensorRT.\n"); +#endif + return false; + } + } + return true; +} + +int main(int argc, char** argv) { k4a_device_configuration_t device_config = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL; device_config.depth_mode = K4A_DEPTH_MODE_NFOV_UNBINNED; @@ -106,6 +157,8 @@ int main() k4abt_tracker_t tracker = NULL; k4abt_tracker_configuration_t tracker_config = K4ABT_TRACKER_CONFIG_DEFAULT; + if (!ProcessArguments(tracker_config, argc, argv)) + exit(1); VERIFY(k4abt_tracker_create(&sensor_calibration, tracker_config, &tracker), "Body tracker initialization failed!"); // Preallocated the buffers to hold the depth image in color space and the body index map in color space diff --git a/body-tracking-samples/camera_space_transform_sample/packages.config b/body-tracking-samples/camera_space_transform_sample/packages.config index 8dbd4bd4..66a075e3 100644 --- a/body-tracking-samples/camera_space_transform_sample/packages.config +++ b/body-tracking-samples/camera_space_transform_sample/packages.config @@ -1,7 +1,6 @@ - - - - + + + diff --git a/body-tracking-samples/cmake/FetchContent.cmake b/body-tracking-samples/cmake/FetchContent.cmake new file mode 100644 index 00000000..98cdf6cb --- /dev/null +++ b/body-tracking-samples/cmake/FetchContent.cmake @@ -0,0 +1,916 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FetchContent +------------------ + +.. only:: html + + .. contents:: + +Overview +^^^^^^^^ + +This module enables populating content at configure time via any method +supported by the :module:`ExternalProject` module. Whereas +:command:`ExternalProject_Add` downloads at build time, the +``FetchContent`` module makes content available immediately, allowing the +configure step to use the content in commands like :command:`add_subdirectory`, +:command:`include` or :command:`file` operations. + +Content population details would normally be defined separately from the +command that performs the actual population. Projects should also +check whether the content has already been populated somewhere else in the +project hierarchy. Typical usage would look something like this: + +.. code-block:: cmake + + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + ) + + FetchContent_GetProperties(googletest) + if(NOT googletest_POPULATED) + FetchContent_Populate(googletest) + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) + endif() + +When using the above pattern with a hierarchical project arrangement, +projects at higher levels in the hierarchy are able to define or override +the population details of content specified anywhere lower in the project +hierarchy. The ability to detect whether content has already been +populated ensures that even if multiple child projects want certain content +to be available, the first one to populate it wins. The other child project +can simply make use of the already available content instead of repeating +the population for itself. See the +:ref:`Examples ` section which demonstrates +this scenario. + +The ``FetchContent`` module also supports defining and populating +content in a single call, with no check for whether the content has been +populated elsewhere in the project already. This is a more low level +operation and would not normally be the way the module is used, but it is +sometimes useful as part of implementing some higher level feature or to +populate some content in CMake's script mode. + + +Declaring Content Details +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. command:: FetchContent_Declare + + .. code-block:: cmake + + FetchContent_Declare( ...) + + The ``FetchContent_Declare()`` function records the options that describe + how to populate the specified content, but if such details have already + been recorded earlier in this project (regardless of where in the project + hierarchy), this and all later calls for the same content ```` are + ignored. This "first to record, wins" approach is what allows hierarchical + projects to have parent projects override content details of child projects. + + The content ```` can be any string without spaces, but good practice + would be to use only letters, numbers and underscores. The name will be + treated case-insensitively and it should be obvious for the content it + represents, often being the name of the child project or the value given + to its top level :command:`project` command (if it is a CMake project). + For well-known public projects, the name should generally be the official + name of the project. Choosing an unusual name makes it unlikely that other + projects needing that same content will use the same name, leading to + the content being populated multiple times. + + The ```` can be any of the download or update/patch options + that the :command:`ExternalProject_Add` command understands. The configure, + build, install and test steps are explicitly disabled and therefore options + related to them will be ignored. In most cases, ```` will + just be a couple of options defining the download method and method-specific + details like a commit tag or archive hash. For example: + + .. code-block:: cmake + + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + ) + + FetchContent_Declare( + myCompanyIcons + URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz + URL_HASH 5588a7b18261c20068beabfb4f530b87 + ) + + FetchContent_Declare( + myCompanyCertificates + SVN_REPOSITORY svn+ssh://svn.mycompany.com/srv/svn/trunk/certs + SVN_REVISION -r12345 + ) + +Populating The Content +^^^^^^^^^^^^^^^^^^^^^^ + +.. command:: FetchContent_Populate + + .. code-block:: cmake + + FetchContent_Populate( ) + + In most cases, the only argument given to ``FetchContent_Populate()`` is the + ````. When used this way, the command assumes the content details have + been recorded by an earlier call to :command:`FetchContent_Declare`. The + details are stored in a global property, so they are unaffected by things + like variable or directory scope. Therefore, it doesn't matter where in the + project the details were previously declared, as long as they have been + declared before the call to ``FetchContent_Populate()``. Those saved details + are then used to construct a call to :command:`ExternalProject_Add` in a + private sub-build to perform the content population immediately. The + implementation of ``ExternalProject_Add()`` ensures that if the content has + already been populated in a previous CMake run, that content will be reused + rather than repopulating them again. For the common case where population + involves downloading content, the cost of the download is only paid once. + + An internal global property records when a particular content population + request has been processed. If ``FetchContent_Populate()`` is called more + than once for the same content name within a configure run, the second call + will halt with an error. Projects can and should check whether content + population has already been processed with the + :command:`FetchContent_GetProperties` command before calling + ``FetchContent_Populate()``. + + ``FetchContent_Populate()`` will set three variables in the scope of the + caller; ``_POPULATED``, ``_SOURCE_DIR`` and + ``_BINARY_DIR``, where ```` is the lowercased ````. + ``_POPULATED`` will always be set to ``True`` by the call. + ``_SOURCE_DIR`` is the location where the + content can be found upon return (it will have already been populated), while + ``_BINARY_DIR`` is a directory intended for use as a corresponding + build directory. The main use case for the two directory variables is to + call :command:`add_subdirectory` immediately after population, i.e.: + + .. code-block:: cmake + + FetchContent_Populate(FooBar ...) + add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR}) + + The values of the three variables can also be retrieved from anywhere in the + project hierarchy using the :command:`FetchContent_GetProperties` command. + + A number of cache variables influence the behavior of all content population + performed using details saved from a :command:`FetchContent_Declare` call: + + ``FETCHCONTENT_BASE_DIR`` + In most cases, the saved details do not specify any options relating to the + directories to use for the internal sub-build, final source and build areas. + It is generally best to leave these decisions up to the ``FetchContent`` + module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR`` + cache variable controls the point under which all content population + directories are collected, but in most cases developers would not need to + change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if + developers change this value, they should aim to keep the path short and + just below the top level of the build tree to avoid running into path + length problems on Windows. + + ``FETCHCONTENT_QUIET`` + The logging output during population can be quite verbose, making the + configure stage quite noisy. This cache option (``ON`` by default) hides + all population output unless an error is encountered. If experiencing + problems with hung downloads, temporarily switching this option off may + help diagnose which content population is causing the issue. + + ``FETCHCONTENT_FULLY_DISCONNECTED`` + When this option is enabled, no attempt is made to download or update + any content. It is assumed that all content has already been populated in + a previous run or the source directories have been pointed at existing + contents the developer has provided manually (using options described + further below). When the developer knows that no changes have been made to + any content details, turning this option ``ON`` can significantly speed up + the configure stage. It is ``OFF`` by default. + + ``FETCHCONTENT_UPDATES_DISCONNECTED`` + This is a less severe download/update control compared to + ``FETCHCONTENT_FULLY_DISCONNECTED``. Instead of bypassing all download and + update logic, the ``FETCHCONTENT_UPDATES_DISCONNECTED`` only disables the + update stage. Therefore, if content has not been downloaded previously, + it will still be downloaded when this option is enabled. This can speed up + the configure stage, but not as much as + ``FETCHCONTENT_FULLY_DISCONNECTED``. It is ``OFF`` by default. + + In addition to the above cache variables, the following cache variables are + also defined for each content name (```` is the uppercased value of + ````): + + ``FETCHCONTENT_SOURCE_DIR_`` + If this is set, no download or update steps are performed for the specified + content and the ``_SOURCE_DIR`` variable returned to the caller is + pointed at this location. This gives developers a way to have a separate + checkout of the content that they can modify freely without interference + from the build. The build simply uses that existing source, but it still + defines ``_BINARY_DIR`` to point inside its own build area. + Developers are strongly encouraged to use this mechanism rather than + editing the sources populated in the default location, as changes to + sources in the default location can be lost when content population details + are changed by the project. + + ``FETCHCONTENT_UPDATES_DISCONNECTED_`` + This is the per-content equivalent of + ``FETCHCONTENT_UPDATES_DISCONNECTED``. If the global option or this option + is ``ON``, then updates will be disabled for the named content. + Disabling updates for individual content can be useful for content whose + details rarely change, while still leaving other frequently changing + content with updates enabled. + + + The ``FetchContent_Populate()`` command also supports a syntax allowing the + content details to be specified directly rather than using any saved + details. This is more low-level and use of this form is generally to be + avoided in favour of using saved content details as outlined above. + Nevertheless, in certain situations it can be useful to invoke the content + population as an isolated operation (typically as part of implementing some + other higher level feature or when using CMake in script mode): + + .. code-block:: cmake + + FetchContent_Populate( + [QUIET] + [SUBBUILD_DIR ] + [SOURCE_DIR ] + [BINARY_DIR ] + ... + ) + + This form has a number of key differences to that where only ```` is + provided: + + - All required population details are assumed to have been provided directly + in the call to ``FetchContent_Populate()``. Any saved details for + ```` are ignored. + - No check is made for whether content for ```` has already been + populated. + - No global property is set to record that the population has occurred. + - No global properties record the source or binary directories used for the + populated content. + - The ``FETCHCONTENT_FULLY_DISCONNECTED`` and + ``FETCHCONTENT_UPDATES_DISCONNECTED`` cache variables are ignored. + + The ``_SOURCE_DIR`` and ``_BINARY_DIR`` variables are still + returned to the caller, but since these locations are not stored as global + properties when this form is used, they are only available to the calling + scope and below rather than the entire project hierarchy. No + ``_POPULATED`` variable is set in the caller's scope with this form. + + The supported options for ``FetchContent_Populate()`` are the same as those + for :command:`FetchContent_Declare()`. Those few options shown just + above are either specific to ``FetchContent_Populate()`` or their behavior is + slightly modified from how :command:`ExternalProject_Add` treats them. + + ``QUIET`` + The ``QUIET`` option can be given to hide the output associated with + populating the specified content. If the population fails, the output will + be shown regardless of whether this option was given or not so that the + cause of the failure can be diagnosed. The global ``FETCHCONTENT_QUIET`` + cache variable has no effect on ``FetchContent_Populate()`` calls where the + content details are provided directly. + + ``SUBBUILD_DIR`` + The ``SUBBUILD_DIR`` argument can be provided to change the location of the + sub-build created to perform the population. The default value is + ``${CMAKE_CURRENT_BINARY_DIR}/-subbuild`` and it would be unusual + to need to override this default. If a relative path is specified, it will + be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. + + ``SOURCE_DIR``, ``BINARY_DIR`` + The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by + :command:`ExternalProject_Add`, but different default values are used by + ``FetchContent_Populate()``. ``SOURCE_DIR`` defaults to + ``${CMAKE_CURRENT_BINARY_DIR}/-src`` and ``BINARY_DIR`` defaults to + ``${CMAKE_CURRENT_BINARY_DIR}/-build``. If a relative path is + specified, it will be interpreted as relative to + :variable:`CMAKE_CURRENT_BINARY_DIR`. + + In addition to the above explicit options, any other unrecognized options are + passed through unmodified to :command:`ExternalProject_Add` to perform the + download, patch and update steps. The following options are explicitly + prohibited (they are disabled by the ``FetchContent_Populate()`` command): + + - ``CONFIGURE_COMMAND`` + - ``BUILD_COMMAND`` + - ``INSTALL_COMMAND`` + - ``TEST_COMMAND`` + + If using ``FetchContent_Populate()`` within CMake's script mode, be aware + that the implementation sets up a sub-build which therefore requires a CMake + generator and build tool to be available. If these cannot be found by + default, then the :variable:`CMAKE_GENERATOR` and/or + :variable:`CMAKE_MAKE_PROGRAM` variables will need to be set appropriately + on the command line invoking the script. + + +Retrieve Population Properties +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. command:: FetchContent_GetProperties + + When using saved content details, a call to :command:`FetchContent_Populate` + records information in global properties which can be queried at any time. + This information includes the source and binary directories associated with + the content and also whether or not the content population has been processed + during the current configure run. + + .. code-block:: cmake + + FetchContent_GetProperties( + [SOURCE_DIR ] + [BINARY_DIR ] + [POPULATED ] + ) + + The ``SOURCE_DIR``, ``BINARY_DIR`` and ``POPULATED`` options can be used to + specify which properties should be retrieved. Each option accepts a value + which is the name of the variable in which to store that property. Most of + the time though, only ```` is given, in which case the call will then + set the same variables as a call to + :command:`FetchContent_Populate(name) `. This allows + the following canonical pattern to be used, which ensures that the relevant + variables will always be defined regardless of whether or not the population + has been performed elsewhere in the project already: + + .. code-block:: cmake + + FetchContent_GetProperties(foobar) + if(NOT foobar_POPULATED) + FetchContent_Populate(foobar) + + # Set any custom variables, etc. here, then + # populate the content as part of this build + + add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR}) + endif() + + The above pattern allows other parts of the overall project hierarchy to + re-use the same content and ensure that it is only populated once. + + +.. _`fetch-content-examples`: + +Examples +^^^^^^^^ + +Consider a project hierarchy where ``projA`` is the top level project and it +depends on projects ``projB`` and ``projC``. Both ``projB`` and ``projC`` +can be built standalone and they also both depend on another project +``projD``. For simplicity, this example will assume that all four projects +are available on a company git server. The ``CMakeLists.txt`` of each project +might have sections like the following: + +*projA*: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + projB + GIT_REPOSITORY git@mycompany.com/git/projB.git + GIT_TAG 4a89dc7e24ff212a7b5167bef7ab079d + ) + FetchContent_Declare( + projC + GIT_REPOSITORY git@mycompany.com/git/projC.git + GIT_TAG 4ad4016bd1d8d5412d135cf8ceea1bb9 + ) + FetchContent_Declare( + projD + GIT_REPOSITORY git@mycompany.com/git/projD.git + GIT_TAG origin/integrationBranch + ) + + FetchContent_GetProperties(projB) + if(NOT projb_POPULATED) + FetchContent_Populate(projB) + add_subdirectory(${projb_SOURCE_DIR} ${projb_BINARY_DIR}) + endif() + + FetchContent_GetProperties(projC) + if(NOT projc_POPULATED) + FetchContent_Populate(projC) + add_subdirectory(${projc_SOURCE_DIR} ${projc_BINARY_DIR}) + endif() + +*projB*: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + projD + GIT_REPOSITORY git@mycompany.com/git/projD.git + GIT_TAG 20b415f9034bbd2a2e8216e9a5c9e632 + ) + + FetchContent_GetProperties(projD) + if(NOT projd_POPULATED) + FetchContent_Populate(projD) + add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR}) + endif() + + +*projC*: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + projD + GIT_REPOSITORY git@mycompany.com/git/projD.git + GIT_TAG 7d9a17ad2c962aa13e2fbb8043fb6b8a + ) + + FetchContent_GetProperties(projD) + if(NOT projd_POPULATED) + FetchContent_Populate(projD) + add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR}) + endif() + +A few key points should be noted in the above: + +- ``projB`` and ``projC`` define different content details for ``projD``, + but ``projA`` also defines a set of content details for ``projD`` and + because ``projA`` will define them first, the details from ``projB`` and + ``projC`` will not be used. The override details defined by ``projA`` + are not required to match either of those from ``projB`` or ``projC``, but + it is up to the higher level project to ensure that the details it does + define still make sense for the child projects. +- While ``projA`` defined content details for ``projD``, it did not need + to explicitly call ``FetchContent_Populate(projD)`` itself. Instead, it + leaves that to a child project to do (in this case it will be ``projB`` + since it is added to the build ahead of ``projC``). If ``projA`` needed to + customize how the ``projD`` content was brought into the build as well + (e.g. define some CMake variables before calling + :command:`add_subdirectory` after populating), it would do the call to + ``FetchContent_Populate()``, etc. just as it did for the ``projB`` and + ``projC`` content. For higher level projects, it is usually enough to + just define the override content details and leave the actual population + to the child projects. This saves repeating the same thing at each level + of the project hierarchy unnecessarily. +- Even though ``projA`` is the top level project in this example, it still + checks whether ``projB`` and ``projC`` have already been populated before + going ahead to do those populations. This makes ``projA`` able to be more + easily incorporated as a child of some other higher level project in the + future if required. Always protect a call to + :command:`FetchContent_Populate` with a check to + :command:`FetchContent_GetProperties`, even in what may be considered a top + level project at the time. + + +The following example demonstrates how one might download and unpack a +firmware tarball using CMake's :manual:`script mode `. The call to +:command:`FetchContent_Populate` specifies all the content details and the +unpacked firmware will be placed in a ``firmware`` directory below the +current working directory. + +*getFirmware.cmake*: + +.. code-block:: cmake + + # NOTE: Intended to be run in script mode with cmake -P + include(FetchContent) + FetchContent_Populate( + firmware + URL https://mycompany.com/assets/firmware-1.23-arm.tar.gz + URL_HASH MD5=68247684da89b608d466253762b0ff11 + SOURCE_DIR firmware + ) + +#]=======================================================================] + + +set(__FetchContent_privateDir "${CMAKE_CURRENT_LIST_DIR}/FetchContent") + +#======================================================================= +# Recording and retrieving content details for later population +#======================================================================= + +# Internal use, projects must not call this directly. It is +# intended for use by FetchContent_Declare() only. +# +# Sets a content-specific global property (not meant for use +# outside of functions defined here in this file) which can later +# be retrieved using __FetchContent_getSavedDetails() with just the +# same content name. If there is already a value stored in the +# property, it is left unchanged and this call has no effect. +# This allows parent projects to define the content details, +# overriding anything a child project may try to set (properties +# are not cached between runs, so the first thing to set it in a +# build will be in control). +function(__FetchContent_declareDetails contentName) + + string(TOLOWER ${contentName} contentNameLower) + set(propertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) + if(NOT alreadyDefined) + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${ARGN}) + endif() + +endfunction() + + +# Internal use, projects must not call this directly. It is +# intended for use by the FetchContent_Declare() function. +# +# Retrieves details saved for the specified content in an +# earlier call to __FetchContent_declareDetails(). +function(__FetchContent_getSavedDetails contentName outVar) + + string(TOLOWER ${contentName} contentNameLower) + set(propertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) + if(NOT alreadyDefined) + message(FATAL_ERROR "No content details recorded for ${contentName}") + endif() + get_property(propertyValue GLOBAL PROPERTY ${propertyName}) + set(${outVar} "${propertyValue}" PARENT_SCOPE) + +endfunction() + + +# Saves population details of the content, sets defaults for the +# SOURCE_DIR and BUILD_DIR. +function(FetchContent_Declare contentName) + + set(options "") + set(oneValueArgs SVN_REPOSITORY) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + unset(srcDirSuffix) + unset(svnRepoArgs) + if(ARG_SVN_REPOSITORY) + # Add a hash of the svn repository URL to the source dir. This works + # around the problem where if the URL changes, the download would + # fail because it tries to checkout/update rather than switch the + # old URL to the new one. We limit the hash to the first 7 characters + # so that the source path doesn't get overly long (which can be a + # problem on windows due to path length limits). + string(SHA1 urlSHA ${ARG_SVN_REPOSITORY}) + string(SUBSTRING ${urlSHA} 0 7 urlSHA) + set(srcDirSuffix "-${urlSHA}") + set(svnRepoArgs SVN_REPOSITORY ${ARG_SVN_REPOSITORY}) + endif() + + string(TOLOWER ${contentName} contentNameLower) + __FetchContent_declareDetails( + ${contentNameLower} + SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src${srcDirSuffix}" + BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build" + ${svnRepoArgs} + # List these last so they can override things we set above + ${ARG_UNPARSED_ARGUMENTS} + ) + +endfunction() + + +#======================================================================= +# Set/get whether the specified content has been populated yet. +# The setter also records the source and binary dirs used. +#======================================================================= + +# Internal use, projects must not call this directly. It is +# intended for use by the FetchContent_Populate() function to +# record when FetchContent_Populate() is called for a particular +# content name. +function(__FetchContent_setPopulated contentName sourceDir binaryDir) + + string(TOLOWER ${contentName} contentNameLower) + set(prefix "_FetchContent_${contentNameLower}") + + set(propertyName "${prefix}_sourceDir") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${sourceDir}) + + set(propertyName "${prefix}_binaryDir") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${binaryDir}) + + set(propertyName "${prefix}_populated") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} True) + +endfunction() + + +# Set variables in the calling scope for any of the retrievable +# properties. If no specific properties are requested, variables +# will be set for all retrievable properties. +# +# This function is intended to also be used by projects as the canonical +# way to detect whether they should call FetchContent_Populate() +# and pull the populated source into the build with add_subdirectory(), +# if they are using the populated content in that way. +function(FetchContent_GetProperties contentName) + + string(TOLOWER ${contentName} contentNameLower) + + set(options "") + set(oneValueArgs SOURCE_DIR BINARY_DIR POPULATED) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ARG_SOURCE_DIR AND + NOT ARG_BINARY_DIR AND + NOT ARG_POPULATED) + # No specific properties requested, provide them all + set(ARG_SOURCE_DIR ${contentNameLower}_SOURCE_DIR) + set(ARG_BINARY_DIR ${contentNameLower}_BINARY_DIR) + set(ARG_POPULATED ${contentNameLower}_POPULATED) + endif() + + set(prefix "_FetchContent_${contentNameLower}") + + if(ARG_SOURCE_DIR) + set(propertyName "${prefix}_sourceDir") + get_property(value GLOBAL PROPERTY ${propertyName}) + if(value) + set(${ARG_SOURCE_DIR} ${value} PARENT_SCOPE) + endif() + endif() + + if(ARG_BINARY_DIR) + set(propertyName "${prefix}_binaryDir") + get_property(value GLOBAL PROPERTY ${propertyName}) + if(value) + set(${ARG_BINARY_DIR} ${value} PARENT_SCOPE) + endif() + endif() + + if(ARG_POPULATED) + set(propertyName "${prefix}_populated") + get_property(value GLOBAL PROPERTY ${propertyName} DEFINED) + set(${ARG_POPULATED} ${value} PARENT_SCOPE) + endif() + +endfunction() + + +#======================================================================= +# Performing the population +#======================================================================= + +# The value of contentName will always have been lowercased by the caller. +# All other arguments are assumed to be options that are understood by +# ExternalProject_Add(), except for QUIET and SUBBUILD_DIR. +function(__FetchContent_directPopulate contentName) + + set(options + QUIET + ) + set(oneValueArgs + SUBBUILD_DIR + SOURCE_DIR + BINARY_DIR + # Prevent the following from being passed through + CONFIGURE_COMMAND + BUILD_COMMAND + INSTALL_COMMAND + TEST_COMMAND + ) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ARG_SUBBUILD_DIR) + message(FATAL_ERROR "Internal error: SUBBUILD_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_SUBBUILD_DIR}") + set(ARG_SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBBUILD_DIR}") + endif() + + if(NOT ARG_SOURCE_DIR) + message(FATAL_ERROR "Internal error: SOURCE_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_SOURCE_DIR}") + set(ARG_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SOURCE_DIR}") + endif() + + if(NOT ARG_BINARY_DIR) + message(FATAL_ERROR "Internal error: BINARY_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_BINARY_DIR}") + set(ARG_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY_DIR}") + endif() + + # Ensure the caller can know where to find the source and build directories + # with some convenient variables. Doing this here ensures the caller sees + # the correct result in the case where the default values are overridden by + # the content details set by the project. + set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE) + set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE) + + # The unparsed arguments may contain spaces, so build up ARG_EXTRA + # in such a way that it correctly substitutes into the generated + # CMakeLists.txt file with each argument quoted. + unset(ARG_EXTRA) + foreach(arg IN LISTS ARG_UNPARSED_ARGUMENTS) + set(ARG_EXTRA "${ARG_EXTRA} \"${arg}\"") + endforeach() + + # Hide output if requested, but save it to a variable in case there's an + # error so we can show the output upon failure. When not quiet, don't + # capture the output to a variable because the user may want to see the + # output as it happens (e.g. progress during long downloads). Combine both + # stdout and stderr in the one capture variable so the output stays in order. + if (ARG_QUIET) + set(outputOptions + OUTPUT_VARIABLE capturedOutput + ERROR_VARIABLE capturedOutput + ) + else() + set(capturedOutput) + set(outputOptions) + message(STATUS "Populating ${contentName}") + endif() + + if(CMAKE_GENERATOR) + set(generatorOpts "-G${CMAKE_GENERATOR}") + if(CMAKE_GENERATOR_PLATFORM) + list(APPEND generatorOpts "-A${CMAKE_GENERATOR_PLATFORM}") + endif() + if(CMAKE_GENERATOR_TOOLSET) + list(APPEND generatorOpts "-T${CMAKE_GENERATOR_TOOLSET}") + endif() + + if(CMAKE_MAKE_PROGRAM) + list(APPEND generatorOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}") + endif() + + else() + # Likely we've been invoked via CMake's script mode where no + # generator is set (and hence CMAKE_MAKE_PROGRAM could not be + # trusted even if provided). We will have to rely on being + # able to find the default generator and build tool. + unset(generatorOpts) + endif() + + # Create and build a separate CMake project to carry out the population. + # If we've already previously done these steps, they will not cause + # anything to be updated, so extra rebuilds of the project won't occur. + # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project + # has this set to something not findable on the PATH. + configure_file("${__FetchContent_privateDir}/CMakeLists.cmake.in" + "${ARG_SUBBUILD_DIR}/CMakeLists.txt") + execute_process( + COMMAND ${CMAKE_COMMAND} ${generatorOpts} . + RESULT_VARIABLE result + ${outputOptions} + WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" + ) + if(result) + if(capturedOutput) + message("${capturedOutput}") + endif() + message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}") + endif() + execute_process( + COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + ${outputOptions} + WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" + ) + if(result) + if(capturedOutput) + message("${capturedOutput}") + endif() + message(FATAL_ERROR "Build step for ${contentName} failed: ${result}") + endif() + +endfunction() + + +option(FETCHCONTENT_FULLY_DISCONNECTED "Disables all attempts to download or update content and assumes source dirs already exist") +option(FETCHCONTENT_UPDATES_DISCONNECTED "Enables UPDATE_DISCONNECTED behavior for all content population") +option(FETCHCONTENT_QUIET "Enables QUIET option for all content population" ON) +set(FETCHCONTENT_BASE_DIR "${CMAKE_BINARY_DIR}/_deps" CACHE PATH "Directory under which to collect all populated content") + +# Populate the specified content using details stored from +# an earlier call to FetchContent_Declare(). +function(FetchContent_Populate contentName) + + if(NOT contentName) + message(FATAL_ERROR "Empty contentName not allowed for FetchContent_Populate()") + endif() + + string(TOLOWER ${contentName} contentNameLower) + + if(ARGN) + # This is the direct population form with details fully specified + # as part of the call, so we already have everything we need + __FetchContent_directPopulate( + ${contentNameLower} + SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-subbuild" + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-build" + ${ARGN} # Could override any of the above ..._DIR variables + ) + + # Pass source and binary dir variables back to the caller + set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE) + set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE) + + # Don't set global properties, or record that we did this population, since + # this was a direct call outside of the normal declared details form. + # We only want to save values in the global properties for content that + # honours the hierarchical details mechanism so that projects are not + # robbed of the ability to override details set in nested projects. + return() + endif() + + # No details provided, so assume they were saved from an earlier call + # to FetchContent_Declare(). Do a check that we haven't already + # populated this content before in case the caller forgot to check. + FetchContent_GetProperties(${contentName}) + if(${contentNameLower}_POPULATED) + message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}") + endif() + + string(TOUPPER ${contentName} contentNameUpper) + set(FETCHCONTENT_SOURCE_DIR_${contentNameUpper} + "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}" + CACHE PATH "When not empty, overrides where to find pre-populated content for ${contentName}") + + if(FETCHCONTENT_SOURCE_DIR_${contentNameUpper}) + # The source directory has been explicitly provided in the cache, + # so no population is required + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + + elseif(FETCHCONTENT_FULLY_DISCONNECTED) + # Bypass population and assume source is already there from a previous run + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src") + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + + else() + # Support both a global "disconnect all updates" and a per-content + # update test (either one being set disables updates for this content). + option(FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper} + "Enables UPDATE_DISCONNECTED behavior just for population of ${contentName}") + if(FETCHCONTENT_UPDATES_DISCONNECTED OR + FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper}) + set(disconnectUpdates True) + else() + set(disconnectUpdates False) + endif() + + if(FETCHCONTENT_QUIET) + set(quietFlag QUIET) + else() + unset(quietFlag) + endif() + + __FetchContent_getSavedDetails(${contentName} contentDetails) + if("${contentDetails}" STREQUAL "") + message(FATAL_ERROR "No details have been set for content: ${contentName}") + endif() + + __FetchContent_directPopulate( + ${contentNameLower} + ${quietFlag} + UPDATE_DISCONNECTED ${disconnectUpdates} + SUBBUILD_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-subbuild" + SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src" + BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build" + # Put the saved details last so they can override any of the + # the options we set above (this can include SOURCE_DIR or + # BUILD_DIR) + ${contentDetails} + ) + endif() + + __FetchContent_setPopulated( + ${contentName} + ${${contentNameLower}_SOURCE_DIR} + ${${contentNameLower}_BINARY_DIR} + ) + + # Pass variables back to the caller. The variables passed back here + # must match what FetchContent_GetProperties() sets when it is called + # with just the content name. + set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE) + set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE) + set(${contentNameLower}_POPULATED True PARENT_SCOPE) + +endfunction() diff --git a/body-tracking-samples/cmake/FetchContent/CMakeLists.cmake.in b/body-tracking-samples/cmake/FetchContent/CMakeLists.cmake.in new file mode 100644 index 00000000..9a7a7715 --- /dev/null +++ b/body-tracking-samples/cmake/FetchContent/CMakeLists.cmake.in @@ -0,0 +1,21 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION ${CMAKE_VERSION}) + +# We name the project and the target for the ExternalProject_Add() call +# to something that will highlight to the user what we are working on if +# something goes wrong and an error message is produced. + +project(${contentName}-populate NONE) + +include(ExternalProject) +ExternalProject_Add(${contentName}-populate + ${ARG_EXTRA} + SOURCE_DIR "${ARG_SOURCE_DIR}" + BINARY_DIR "${ARG_BINARY_DIR}" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/body-tracking-samples/csharp_3d_viewer/Csharp_3d_viewer.csproj b/body-tracking-samples/csharp_3d_viewer/Csharp_3d_viewer.csproj index 19197a0b..b4d7a3a0 100644 --- a/body-tracking-samples/csharp_3d_viewer/Csharp_3d_viewer.csproj +++ b/body-tracking-samples/csharp_3d_viewer/Csharp_3d_viewer.csproj @@ -8,7 +8,7 @@ - + diff --git a/body-tracking-samples/extern/CMakeLists.txt b/body-tracking-samples/extern/CMakeLists.txt index 3cbb1d46..615c63e6 100644 --- a/body-tracking-samples/extern/CMakeLists.txt +++ b/body-tracking-samples/extern/CMakeLists.txt @@ -2,3 +2,4 @@ # Licensed under the MIT License. add_subdirectory(glfw) +add_subdirectory(nlohmann_json) diff --git a/body-tracking-samples/extern/nlohmann_json/CMakeLists.txt b/body-tracking-samples/extern/nlohmann_json/CMakeLists.txt new file mode 100644 index 00000000..15612ca5 --- /dev/null +++ b/body-tracking-samples/extern/nlohmann_json/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +include(FetchContent) + +FetchContent_Declare(nlohmann_json + GIT_REPOSITORY https://github.com/nlohmann/json.git + GIT_TAG v3.7.0 +) +FetchContent_GetProperties(nlohmann_json) +if (NOT nlohmann_json_POPULATED) + FetchContent_Populate(nlohmann_json) + add_subdirectory(${nlohmann_json_SOURCE_DIR} ${nlohmann_json_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() + +add_library(nlohmann::json ALIAS nlohmann_json) diff --git a/body-tracking-samples/floor_detector_sample/CMakeLists.txt b/body-tracking-samples/floor_detector_sample/CMakeLists.txt new file mode 100644 index 00000000..add45911 --- /dev/null +++ b/body-tracking-samples/floor_detector_sample/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +add_executable(floor_detector_sample + FloorDetector.cpp + PointCloudGenerator.cpp + main.cpp +) + +target_include_directories(floor_detector_sample PRIVATE ../sample_helper_includes) + +# Dependencies of this library +target_link_libraries(floor_detector_sample PRIVATE + k4a + k4arecord + window_controller_3d::window_controller_3d + glfw::glfw +) diff --git a/body-tracking-samples/floor_detector_sample/floor_detector_sample.vcxproj b/body-tracking-samples/floor_detector_sample/floor_detector_sample.vcxproj index 3077d6b2..06068366 100644 --- a/body-tracking-samples/floor_detector_sample/floor_detector_sample.vcxproj +++ b/body-tracking-samples/floor_detector_sample/floor_detector_sample.vcxproj @@ -20,13 +20,13 @@ Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte @@ -104,20 +104,18 @@ - - - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + - + \ No newline at end of file diff --git a/body-tracking-samples/floor_detector_sample/packages.config b/body-tracking-samples/floor_detector_sample/packages.config index ef4f251c..befd8f99 100644 --- a/body-tracking-samples/floor_detector_sample/packages.config +++ b/body-tracking-samples/floor_detector_sample/packages.config @@ -1,8 +1,7 @@ - - - - + + + diff --git a/body-tracking-samples/jump_analysis_sample/CMakeLists.txt b/body-tracking-samples/jump_analysis_sample/CMakeLists.txt new file mode 100644 index 00000000..9e746f1b --- /dev/null +++ b/body-tracking-samples/jump_analysis_sample/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +add_executable(jump_analysis_sample + DigitalSignalProcessing.cpp + HandRaisedDetector.cpp + JumpEvaluator.cpp + main.cpp +) + +target_include_directories(jump_analysis_sample PRIVATE ../sample_helper_includes) + +# Dependencies of this library +target_link_libraries(jump_analysis_sample PRIVATE + k4a + k4abt + k4arecord + window_controller_3d::window_controller_3d + glfw::glfw +) diff --git a/body-tracking-samples/jump_analysis_sample/jump_analysis_sample.vcxproj b/body-tracking-samples/jump_analysis_sample/jump_analysis_sample.vcxproj index 3fce0a10..a33eb624 100644 --- a/body-tracking-samples/jump_analysis_sample/jump_analysis_sample.vcxproj +++ b/body-tracking-samples/jump_analysis_sample/jump_analysis_sample.vcxproj @@ -20,13 +20,13 @@ Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte @@ -106,20 +106,18 @@ - - - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + - + \ No newline at end of file diff --git a/body-tracking-samples/jump_analysis_sample/main.cpp b/body-tracking-samples/jump_analysis_sample/main.cpp index 1e7b79b8..4d795f45 100644 --- a/body-tracking-samples/jump_analysis_sample/main.cpp +++ b/body-tracking-samples/jump_analysis_sample/main.cpp @@ -58,7 +58,59 @@ int64_t CloseCallback(void* /*context*/) return 1; } -int main() +void PrintUsage() +{ +#ifdef _WIN32 + printf("Usage: k4abt_jump_analysis_sample PROCESSING_MODE[CUDA, DirectML ( default ), or TensorRT](optional) -model MODEL_FILEPATH(optional).\n"); +#else + printf("Usage: k4abt_jump_analysis_sample PROCESSING_MODE[CUDA ( default ) or TensorRT](optional) -model MODEL_FILEPATH(optional).\n"); +#endif +} + +bool ProcessArguments(k4abt_tracker_configuration_t& tracker_config, int argc, char** argv) +{ + PrintUsage(); + + for (int i = 1; i < argc; i++ ) + { + if (0 == strcmp(argv[i], "TensorRT")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_TENSORRT; + } + else if (0 == strcmp(argv[i], "CUDA")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_CUDA; + } +#ifdef _WIN32 + else if (0 == strcmp(argv[i], "DirectML")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_DIRECTML; + } +#endif + else if (0 == strcmp(argv[i], "-model")) + { + if (i < argc - 1) + tracker_config.model_path = argv[++i]; + else + { + printf("Error: model filepath missing\n"); + return false; + } + } + else + { +#ifdef _WIN32 + printf("Invalid processing mode ! Accepted values are CUDA, DirectML ( default ), or TensorRT.\n"); +#else + printf("Invalid processing mode ! Accepted values are CUDA ( default ) or TensorRT.\n"); +#endif + return false; + } + } + return true; +} + +int main(int argc, char** argv) { PrintAppUsage(); @@ -79,6 +131,10 @@ int main() // Create Body Tracker k4abt_tracker_t tracker = nullptr; k4abt_tracker_configuration_t tracker_config = K4ABT_TRACKER_CONFIG_DEFAULT; + if( !ProcessArguments( tracker_config, argc, argv)) + { + exit(1); + } VERIFY(k4abt_tracker_create(&sensorCalibration, tracker_config, &tracker), "Body tracker initialization failed!"); // Initialize the 3d window controller diff --git a/body-tracking-samples/jump_analysis_sample/packages.config b/body-tracking-samples/jump_analysis_sample/packages.config index ef4f251c..befd8f99 100644 --- a/body-tracking-samples/jump_analysis_sample/packages.config +++ b/body-tracking-samples/jump_analysis_sample/packages.config @@ -1,8 +1,7 @@ - - - - + + + diff --git a/body-tracking-samples/offline_processor/CMakeLists.txt b/body-tracking-samples/offline_processor/CMakeLists.txt new file mode 100644 index 00000000..e9362cdf --- /dev/null +++ b/body-tracking-samples/offline_processor/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +add_executable(offline_processor + main.cpp +) + +target_include_directories(offline_processor PRIVATE ../sample_helper_includes) + +target_link_libraries(offline_processor PRIVATE + k4a + k4abt + k4arecord + nlohmann::json +) diff --git a/body-tracking-samples/offline_processor/main.cpp b/body-tracking-samples/offline_processor/main.cpp index 14429b33..7e54b4e0 100644 --- a/body-tracking-samples/offline_processor/main.cpp +++ b/body-tracking-samples/offline_processor/main.cpp @@ -83,7 +83,7 @@ bool check_depth_image_exists(k4a_capture_t capture) } } -bool process_mkv_offline(const char* input_path, const char* output_path) +bool process_mkv_offline(const char* input_path, const char* output_path, k4abt_tracker_configuration_t tracker_config = K4ABT_TRACKER_CONFIG_DEFAULT ) { k4a_playback_t playback_handle = nullptr; k4a_result_t result = k4a_playback_open(input_path, &playback_handle); @@ -102,7 +102,6 @@ bool process_mkv_offline(const char* input_path, const char* output_path) } k4abt_tracker_t tracker = NULL; - k4abt_tracker_configuration_t tracker_config = K4ABT_TRACKER_CONFIG_DEFAULT; if (K4A_RESULT_SUCCEEDED != k4abt_tracker_create(&calibration, tracker_config, &tracker)) { cerr << "Body tracker initialization failed!" << endl; @@ -178,18 +177,73 @@ bool process_mkv_offline(const char* input_path, const char* output_path) cout << "Results saved in " << output_path; } + k4abt_tracker_shutdown(tracker); + k4abt_tracker_destroy(tracker); k4a_playback_close(playback_handle); return success; } -int main(int argc, char **argv) +void PrintUsage() +{ +#ifdef _WIN32 + cout << "Usage: k4abt_offline_processor.exe [processing_mode] [-model MODEL_FILE_PATH]\n\t[Optional] processing_mode\n\t\tCPU\n\t\tCUDA\n\t\tTensorRT\n\t\tDirectML ( default )" << endl; +#else + cout << "Usage: k4abt_offline_processor.exe [processing_mode] [-model MODEL_FILE_PATH]\n\t[Optional] processing_mode\n\t\tCPU\n\t\tCUDA ( default )\n\t\tTensorRT" << endl; +#endif +} + +bool ProcessArguments(k4abt_tracker_configuration_t &tracker_config, int argc, char** argv) { - if (argc != 3) + if (argc < 3) { - cout << "Usage: k4abt_offline_processor.exe " << endl; - return -1; + PrintUsage(); + return false; + } + for( int i = 3; i < argc; i++ ) + { + if (0 == strcmp(argv[i], "TensorRT")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_TENSORRT; + } + else if (0 == strcmp(argv[i], "CUDA")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_CUDA; + } + else if (0 == strcmp(argv[i], "CPU")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_CPU; + } +#ifdef _WIN32 + else if (0 == strcmp(argv[i], "DirectML")) + { + tracker_config.processing_mode = K4ABT_TRACKER_PROCESSING_MODE_GPU_DIRECTML; + } +#endif + else if (0 == strcmp(argv[i], "-model")) + { + if (i < argc - 1) + tracker_config.model_path = argv[++i]; + else + { + printf("Error: model filepath missing\n"); + PrintUsage(); + return false; + } + } + else + { + PrintUsage(); + return false; + } } + return true; +} - return process_mkv_offline(argv[1], argv[2]) ? 0 : -1; +int main(int argc, char **argv) +{ + k4abt_tracker_configuration_t tracker_config = K4ABT_TRACKER_CONFIG_DEFAULT; + if (!ProcessArguments(tracker_config, argc, argv)) + return -1; + return process_mkv_offline(argv[1], argv[2], tracker_config) ? 0 : -1; } diff --git a/body-tracking-samples/offline_processor/offline_processor.vcxproj b/body-tracking-samples/offline_processor/offline_processor.vcxproj index e1a3b1ca..076064b2 100644 --- a/body-tracking-samples/offline_processor/offline_processor.vcxproj +++ b/body-tracking-samples/offline_processor/offline_processor.vcxproj @@ -14,19 +14,19 @@ 15.0 {A7D2F1BE-0030-4436-B391-FEDE1E756B02} offline_processor - 10.0.17134.0 + 10.0 Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte @@ -91,20 +91,18 @@ - - - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + - + \ No newline at end of file diff --git a/body-tracking-samples/offline_processor/packages.config b/body-tracking-samples/offline_processor/packages.config index 72a6bca6..b11d2be6 100644 --- a/body-tracking-samples/offline_processor/packages.config +++ b/body-tracking-samples/offline_processor/packages.config @@ -1,8 +1,7 @@ - - - - + + + diff --git a/body-tracking-samples/sample_helper_libs/window_controller_3d/glad/glad.h b/body-tracking-samples/sample_helper_libs/window_controller_3d/glad/glad.h index 28fb918c..10cfcc16 100644 --- a/body-tracking-samples/sample_helper_libs/window_controller_3d/glad/glad.h +++ b/body-tracking-samples/sample_helper_libs/window_controller_3d/glad/glad.h @@ -34,6 +34,13 @@ #ifndef NOMINMAX #define NOMINMAX 1 #endif +#ifdef _MSC_VER + +#if _MSC_VER >= 1915 +#pragma warning( disable : 5105 ) +#endif +#endif + #include #endif diff --git a/body-tracking-samples/sample_helper_libs/window_controller_3d/packages.config b/body-tracking-samples/sample_helper_libs/window_controller_3d/packages.config index faf99cd6..6f4f4bf9 100644 --- a/body-tracking-samples/sample_helper_libs/window_controller_3d/packages.config +++ b/body-tracking-samples/sample_helper_libs/window_controller_3d/packages.config @@ -1,6 +1,6 @@ - - + + diff --git a/body-tracking-samples/sample_helper_libs/window_controller_3d/window_controller_3d.vcxproj b/body-tracking-samples/sample_helper_libs/window_controller_3d/window_controller_3d.vcxproj index 78372326..0cbd4a6d 100644 --- a/body-tracking-samples/sample_helper_libs/window_controller_3d/window_controller_3d.vcxproj +++ b/body-tracking-samples/sample_helper_libs/window_controller_3d/window_controller_3d.vcxproj @@ -20,13 +20,13 @@ StaticLibrary true - v142 + v143 MultiByte StaticLibrary false - v142 + v143 true MultiByte @@ -115,16 +115,16 @@ - - + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + diff --git a/body-tracking-samples/simple_3d_viewer/CMakeLists.txt b/body-tracking-samples/simple_3d_viewer/CMakeLists.txt index 18b21c2f..98926c1d 100644 --- a/body-tracking-samples/simple_3d_viewer/CMakeLists.txt +++ b/body-tracking-samples/simple_3d_viewer/CMakeLists.txt @@ -9,6 +9,7 @@ target_include_directories(simple_3d_viewer PRIVATE ../sample_helper_includes) target_link_libraries(simple_3d_viewer PRIVATE k4a k4abt + k4arecord window_controller_3d::window_controller_3d glfw::glfw ) diff --git a/body-tracking-samples/simple_3d_viewer/main.cpp b/body-tracking-samples/simple_3d_viewer/main.cpp index 76451ca1..b29a4ba7 100644 --- a/body-tracking-samples/simple_3d_viewer/main.cpp +++ b/body-tracking-samples/simple_3d_viewer/main.cpp @@ -15,12 +15,21 @@ void PrintUsage() { - printf("\nUSAGE: (k4abt_)simple_3d_viewer.exe SensorMode[NFOV_UNBINNED, WFOV_BINNED](optional) RuntimeMode[CPU](optional)\n"); +#ifdef _WIN32 + printf("\nUSAGE: (k4abt_)simple_3d_viewer.exe SensorMode[NFOV_UNBINNED, WFOV_BINNED](optional) RuntimeMode[CPU, CUDA, DIRECTML, TENSORRT](optional) -model MODEL_PATH(optional)\n"); +#else + printf("\nUSAGE: (k4abt_)simple_3d_viewer.exe SensorMode[NFOV_UNBINNED, WFOV_BINNED](optional) RuntimeMode[CPU, CUDA, TENSORRT](optional)\n"); +#endif printf(" - SensorMode: \n"); printf(" NFOV_UNBINNED (default) - Narrow Field of View Unbinned Mode [Resolution: 640x576; FOI: 75 degree x 65 degree]\n"); printf(" WFOV_BINNED - Wide Field of View Binned Mode [Resolution: 512x512; FOI: 120 degree x 120 degree]\n"); printf(" - RuntimeMode: \n"); printf(" CPU - Use the CPU only mode. It runs on machines without a GPU but it will be much slower\n"); + printf(" CUDA - Use CUDA for processing.\n"); +#ifdef _WIN32 + printf(" DIRECTML - Use the DirectML processing mode.\n"); +#endif + printf(" TENSORRT - Use the TensorRT processing mode.\n"); printf(" OFFLINE - Play a specified file. Does not require Kinect device\n"); printf("e.g. (k4abt_)simple_3d_viewer.exe WFOV_BINNED CPU\n"); printf("e.g. (k4abt_)simple_3d_viewer.exe CPU\n"); @@ -82,9 +91,14 @@ int64_t CloseCallback(void* /*context*/) struct InputSettings { k4a_depth_mode_t DepthCameraMode = K4A_DEPTH_MODE_NFOV_UNBINNED; - bool CpuOnlyMode = false; +#ifdef _WIN32 + k4abt_tracker_processing_mode_t processingMode = K4ABT_TRACKER_PROCESSING_MODE_GPU_DIRECTML; +#else + k4abt_tracker_processing_mode_t processingMode = K4ABT_TRACKER_PROCESSING_MODE_GPU_CUDA; +#endif bool Offline = false; std::string FileName; + std::string ModelPath; }; bool ParseInputSettingsFromArg(int argc, char** argv, InputSettings& inputSettings) @@ -102,8 +116,22 @@ bool ParseInputSettingsFromArg(int argc, char** argv, InputSettings& inputSettin } else if (inputArg == std::string("CPU")) { - inputSettings.CpuOnlyMode = true; + inputSettings.processingMode = K4ABT_TRACKER_PROCESSING_MODE_CPU; } + else if (inputArg == std::string("TENSORRT")) + { + inputSettings.processingMode = K4ABT_TRACKER_PROCESSING_MODE_GPU_TENSORRT; + } + else if (inputArg == std::string("CUDA")) + { + inputSettings.processingMode = K4ABT_TRACKER_PROCESSING_MODE_GPU_CUDA; + } +#ifdef _WIN32 + else if (inputArg == std::string("DIRECTML")) + { + inputSettings.processingMode = K4ABT_TRACKER_PROCESSING_MODE_GPU_DIRECTML; + } +#endif else if (inputArg == std::string("OFFLINE")) { inputSettings.Offline = true; @@ -116,14 +144,23 @@ bool ParseInputSettingsFromArg(int argc, char** argv, InputSettings& inputSettin return false; } } + else if (inputArg == std::string("-model")) + { + if (i < argc - 1) + inputSettings.ModelPath = argv[++i]; + else + { + printf("Error: model path missing\n"); + return false; + } + } else { - printf("Error command not understood: %s\n", inputArg.c_str()); + printf("Error: command not understood: %s\n", inputArg.c_str()); return false; } } return true; - } void VisualizeResult(k4abt_frame_t bodyFrame, Window3dWrapper& window3d, int depthWidth, int depthHeight) { @@ -205,79 +242,82 @@ void VisualizeResult(k4abt_frame_t bodyFrame, Window3dWrapper& window3d, int dep } -void PlayFile(InputSettings inputSettings) { +void PlayFile(InputSettings inputSettings) +{ // Initialize the 3d window controller Window3dWrapper window3d; //create the tracker and playback handle - k4a_calibration_t sensor_calibration; - k4abt_tracker_t tracker = NULL; - k4a_playback_t playback_handle = NULL; + k4a_calibration_t sensorCalibration; + k4abt_tracker_t tracker = nullptr; + k4a_playback_t playbackHandle = nullptr; const char* file = inputSettings.FileName.c_str(); - if (k4a_playback_open(file, &playback_handle) != K4A_RESULT_SUCCEEDED) + if (k4a_playback_open(file, &playbackHandle) != K4A_RESULT_SUCCEEDED) { printf("Failed to open recording: %s\n", file); return; } - - if (k4a_playback_get_calibration(playback_handle, &sensor_calibration) != K4A_RESULT_SUCCEEDED) + if (k4a_playback_get_calibration(playbackHandle, &sensorCalibration) != K4A_RESULT_SUCCEEDED) { printf("Failed to get calibration\n"); return; } - - - k4a_capture_t capture = NULL; - k4a_stream_result_t result = K4A_STREAM_RESULT_SUCCEEDED; - - k4abt_tracker_configuration_t tracker_config = { K4ABT_SENSOR_ORIENTATION_DEFAULT }; - tracker_config.processing_mode = inputSettings.CpuOnlyMode ? K4ABT_TRACKER_PROCESSING_MODE_CPU : K4ABT_TRACKER_PROCESSING_MODE_GPU; + k4a_capture_t capture = nullptr; + k4a_stream_result_t playbackResult = K4A_STREAM_RESULT_SUCCEEDED; - VERIFY(k4abt_tracker_create(&sensor_calibration, tracker_config, &tracker), "Body tracker initialization failed!"); + k4abt_tracker_configuration_t trackerConfig = K4ABT_TRACKER_CONFIG_DEFAULT; + trackerConfig.processing_mode = inputSettings.processingMode; + trackerConfig.model_path = inputSettings.ModelPath.c_str(); + VERIFY(k4abt_tracker_create(&sensorCalibration, trackerConfig, &tracker), "Body tracker initialization failed!"); - k4abt_tracker_set_temporal_smoothing(tracker, 1); - - int depthWidth = sensor_calibration.depth_camera_calibration.resolution_width; - int depthHeight = sensor_calibration.depth_camera_calibration.resolution_height; + int depthWidth = sensorCalibration.depth_camera_calibration.resolution_width; + int depthHeight = sensorCalibration.depth_camera_calibration.resolution_height; - window3d.Create("3D Visualization", sensor_calibration); + window3d.Create("3D Visualization", sensorCalibration); window3d.SetCloseCallback(CloseCallback); window3d.SetKeyCallback(ProcessKey); - while (result == K4A_STREAM_RESULT_SUCCEEDED) + while (playbackResult == K4A_STREAM_RESULT_SUCCEEDED && s_isRunning) { - result = k4a_playback_get_next_capture(playback_handle, &capture); - // check to make sure we have a depth image - // if we are not at the end of the file - if (result != K4A_STREAM_RESULT_EOF) { - k4a_image_t depth_image = k4a_capture_get_depth_image(capture); - if (depth_image == NULL) { + playbackResult = k4a_playback_get_next_capture(playbackHandle, &capture); + if (playbackResult == K4A_STREAM_RESULT_EOF) + { + // End of file reached + break; + } + + if (playbackResult == K4A_STREAM_RESULT_SUCCEEDED) + { + // check to make sure we have a depth image + k4a_image_t depthImage = k4a_capture_get_depth_image(capture); + if (depthImage == nullptr) { //If no depth image, print a warning and skip to next frame - printf("Warning: No depth image, skipping frame\n"); + std::cout << "Warning: No depth image, skipping frame!" << std::endl; k4a_capture_release(capture); continue; } // Release the Depth image - k4a_image_release(depth_image); - } - if (result == K4A_STREAM_RESULT_SUCCEEDED) - { - + k4a_image_release(depthImage); + //enque capture and pop results - synchronous - k4a_wait_result_t queue_capture_result = k4abt_tracker_enqueue_capture(tracker, capture, K4A_WAIT_INFINITE); + k4a_wait_result_t queueCaptureResult = k4abt_tracker_enqueue_capture(tracker, capture, K4A_WAIT_INFINITE); // Release the sensor capture once it is no longer needed. k4a_capture_release(capture); - k4abt_frame_t bodyFrame = NULL; - k4a_wait_result_t pop_frame_result = k4abt_tracker_pop_result(tracker, &bodyFrame, K4A_WAIT_INFINITE); - if (pop_frame_result == K4A_WAIT_RESULT_SUCCEEDED) + if (queueCaptureResult == K4A_WAIT_RESULT_FAILED) + { + std::cout << "Error! Add capture to tracker process queue failed!" << std::endl; + break; + } + + k4abt_frame_t bodyFrame = nullptr; + k4a_wait_result_t popFrameResult = k4abt_tracker_pop_result(tracker, &bodyFrame, K4A_WAIT_INFINITE); + if (popFrameResult == K4A_WAIT_RESULT_SUCCEEDED) { - size_t num_bodies = k4abt_frame_get_num_bodies(bodyFrame); - printf("%zu bodies are detected\n", num_bodies); /************* Successfully get a body tracking result, process the result here ***************/ VisualizeResult(bodyFrame, window3d, depthWidth, depthHeight); //Release the bodyFrame @@ -285,31 +325,25 @@ void PlayFile(InputSettings inputSettings) { } else { - printf("Pop body frame result failed!\n"); + std::cout << "Pop body frame result failed!" << std::endl; break; } - } window3d.SetLayout3d(s_layoutMode); window3d.SetJointFrameVisualization(s_visualizeJointFrame); window3d.Render(); - - if (result == K4A_STREAM_RESULT_EOF) - { - // End of file reached - break; - } } + k4abt_tracker_shutdown(tracker); k4abt_tracker_destroy(tracker); window3d.Delete(); printf("Finished body tracking processing!\n"); - k4a_playback_close(playback_handle); - + k4a_playback_close(playbackHandle); } -void PlayFromDevice(InputSettings inputSettings) { +void PlayFromDevice(InputSettings inputSettings) +{ k4a_device_t device = nullptr; VERIFY(k4a_device_open(0, &device), "Open K4A Device failed!"); @@ -328,9 +362,11 @@ void PlayFromDevice(InputSettings inputSettings) { // Create Body Tracker k4abt_tracker_t tracker = nullptr; - k4abt_tracker_configuration_t tracker_config = K4ABT_TRACKER_CONFIG_DEFAULT; - tracker_config.processing_mode = inputSettings.CpuOnlyMode ? K4ABT_TRACKER_PROCESSING_MODE_CPU : K4ABT_TRACKER_PROCESSING_MODE_GPU; - VERIFY(k4abt_tracker_create(&sensorCalibration, tracker_config, &tracker), "Body tracker initialization failed!"); + k4abt_tracker_configuration_t trackerConfig = K4ABT_TRACKER_CONFIG_DEFAULT; + trackerConfig.processing_mode = inputSettings.processingMode; + trackerConfig.model_path = inputSettings.ModelPath.c_str(); + VERIFY(k4abt_tracker_create(&sensorCalibration, trackerConfig, &tracker), "Body tracker initialization failed!"); + // Initialize the 3d window controller Window3dWrapper window3d; window3d.Create("3D Visualization", sensorCalibration); @@ -387,28 +423,28 @@ void PlayFromDevice(InputSettings inputSettings) { k4a_device_stop_cameras(device); k4a_device_close(device); - - } int main(int argc, char** argv) { InputSettings inputSettings; - if (ParseInputSettingsFromArg(argc, argv, inputSettings)) { - // Either play the offline file or play from the device - if (inputSettings.Offline == true) { - PlayFile(inputSettings); - } - else { - PlayFromDevice(inputSettings); - } - } - else { + if (!ParseInputSettingsFromArg(argc, argv, inputSettings)) + { // Print app usage if user entered incorrect arguments. PrintUsage(); return -1; } + // Either play the offline file or play from the device + if (inputSettings.Offline == true) + { + PlayFile(inputSettings); + } + else + { + PlayFromDevice(inputSettings); + } + return 0; } diff --git a/body-tracking-samples/simple_3d_viewer/packages.config b/body-tracking-samples/simple_3d_viewer/packages.config index ef4f251c..befd8f99 100644 --- a/body-tracking-samples/simple_3d_viewer/packages.config +++ b/body-tracking-samples/simple_3d_viewer/packages.config @@ -1,8 +1,7 @@ - - - - + + + diff --git a/body-tracking-samples/simple_3d_viewer/simple_3d_viewer.vcxproj b/body-tracking-samples/simple_3d_viewer/simple_3d_viewer.vcxproj index e93e9751..d1a8effd 100644 --- a/body-tracking-samples/simple_3d_viewer/simple_3d_viewer.vcxproj +++ b/body-tracking-samples/simple_3d_viewer/simple_3d_viewer.vcxproj @@ -20,13 +20,13 @@ Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte @@ -98,20 +98,18 @@ - - - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + diff --git a/body-tracking-samples/simple_cpp_sample/packages.config b/body-tracking-samples/simple_cpp_sample/packages.config index 8dbd4bd4..66a075e3 100644 --- a/body-tracking-samples/simple_cpp_sample/packages.config +++ b/body-tracking-samples/simple_cpp_sample/packages.config @@ -1,7 +1,6 @@ - - - - + + + diff --git a/body-tracking-samples/simple_cpp_sample/simple_cpp_sample.vcxproj b/body-tracking-samples/simple_cpp_sample/simple_cpp_sample.vcxproj index c8bf6c4c..c6462b4a 100644 --- a/body-tracking-samples/simple_cpp_sample/simple_cpp_sample.vcxproj +++ b/body-tracking-samples/simple_cpp_sample/simple_cpp_sample.vcxproj @@ -14,19 +14,19 @@ 15.0 {A7D2F1BE-0030-4436-B391-FEDE1E756B02} simplecppsample - 10.0.17134.0 + 10.0 Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte @@ -91,18 +91,16 @@ - - - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + - + \ No newline at end of file diff --git a/body-tracking-samples/simple_sample/main.c b/body-tracking-samples/simple_sample/main.c index 459a46ba..630ccf77 100644 --- a/body-tracking-samples/simple_sample/main.c +++ b/body-tracking-samples/simple_sample/main.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,10 @@ int main() k4abt_tracker_configuration_t tracker_config = K4ABT_TRACKER_CONFIG_DEFAULT; VERIFY(k4abt_tracker_create(&sensor_calibration, tracker_config, &tracker), "Body tracker initialization failed!"); + double total_success_tracker_time = 0.; + uint32_t total_success_body_count = 0; + int success_frame_count = 0; + int frame_count = 0; do { @@ -79,6 +84,8 @@ int main() printf("Start processing frame %d\n", frame_count); + clock_t begin_clock = clock(); + k4a_wait_result_t queue_capture_result = k4abt_tracker_enqueue_capture(tracker, sensor_capture, K4A_WAIT_INFINITE); k4a_capture_release(sensor_capture); @@ -98,8 +105,16 @@ int main() k4a_wait_result_t pop_frame_result = k4abt_tracker_pop_result(tracker, &body_frame, K4A_WAIT_INFINITE); if (pop_frame_result == K4A_WAIT_RESULT_SUCCEEDED) { + clock_t end_clock = clock(); + double time_spent = (double)(end_clock - begin_clock) / CLOCKS_PER_SEC; + total_success_tracker_time += time_spent; + success_frame_count++; + + printf("Time spent for this frame: %f s\n", time_spent); + uint32_t num_bodies = k4abt_frame_get_num_bodies(body_frame); printf("%u bodies are detected!\n", num_bodies); + total_success_body_count += num_bodies; for (uint32_t i = 0; i < num_bodies; i++) { @@ -151,6 +166,10 @@ int main() printf("Finished body tracking processing!\n"); + printf("Total body tracking success frame count: %d\n", success_frame_count); + printf("Average number of body detected per frame: %f\n", (double)total_success_body_count / success_frame_count); + printf("Average success frame tracker processing time: %f\n", total_success_tracker_time / success_frame_count); + k4abt_tracker_shutdown(tracker); k4abt_tracker_destroy(tracker); k4a_device_stop_cameras(device); diff --git a/body-tracking-samples/simple_sample/packages.config b/body-tracking-samples/simple_sample/packages.config index 8dbd4bd4..66a075e3 100644 --- a/body-tracking-samples/simple_sample/packages.config +++ b/body-tracking-samples/simple_sample/packages.config @@ -1,7 +1,6 @@ - - - - + + + diff --git a/body-tracking-samples/simple_sample/simple_sample.vcxproj b/body-tracking-samples/simple_sample/simple_sample.vcxproj index c6202731..e0966a88 100644 --- a/body-tracking-samples/simple_sample/simple_sample.vcxproj +++ b/body-tracking-samples/simple_sample/simple_sample.vcxproj @@ -14,19 +14,19 @@ 15.0 {A7D2F1BE-0030-4436-B391-FEDE1E756B02} simplesample - 10.0.17134.0 + 10.0 Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte @@ -91,18 +91,16 @@ - - - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + - + \ No newline at end of file