Repository: patrikhuber/eos-model-viewer
Branch: master
Commit: bf3722a678f9
Files: 10
Total size: 83.7 KB
Directory structure:
gitextract_ir1lx7s3/
├── .clang-format
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake/
│ └── FindLIBIGL.cmake
├── cxxopts.hpp
├── eos-model-viewer.cpp
└── initial_cache.cmake.template
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
---
BasedOnStyle: LLVM
AccessModifierOffset: '-4'
AlwaysBreakTemplateDeclarations: 'true'
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
ColumnLimit: '110'
Cpp11BracedListStyle: 'true'
PointerAlignment: Left
IndentWidth: '4'
Language: Cpp
NamespaceIndentation: None
SortIncludes: false
Standard: Cpp11
UseTab: Never
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
...
================================================
FILE: .gitignore
================================================
# Ignore (optional) configuration files with user-specific paths:
initial_cache.cmake
================================================
FILE: .gitmodules
================================================
[submodule "external/eos"]
path = external/eos
url = https://github.com/patrikhuber/eos.git
[submodule "external/libigl"]
path = external/libigl
url = https://github.com/libigl/libigl.git
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.1.3)
project(eos-model-viewer)
set(eos-model-viewer_VERSION 0.2.0.alpha)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# This sets the C++ standard to c++14 and required for all the following targets that we define.
# It has no effect on MSVC though - we thus define more specific requirements for each executable target respectively.
# Also it will not apply to the eos library target, since it is an INTERFACE_LIBRARY, and these properties do not apply to interface libraries.
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # This makes CMake use -std=c++11 instead of -std=gnu++11
# This list is likely not complete, but it should be sufficient to error out on old compilers that we cannot build on:
set(eos-model-viewer_CXX_COMPILE_FEATURES cxx_defaulted_functions cxx_generalized_initializers cxx_generic_lambdas cxx_lambdas cxx_nonstatic_member_init cxx_range_for cxx_right_angle_brackets cxx_strong_enums)
# Build a CPack driven installer package:
include(InstallRequiredSystemLibraries) # This module will include any runtime libraries that are needed by the project for the current platform
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR "${eos-model-viewer_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${eos-model-viewer_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${eos-model-viewer_VERSION_PATCH}")
include(CPack)
# Find dependencies:
find_package(OpenCV REQUIRED core)
#check installed version in order to include the correct OpenCV libraries
#version variable is defined from project root's CMakeLists
if("${OpenCV_VERSION_MAJOR}$" EQUAL 2)
message(STATUS "OpenCV 2.x detected")
find_package(OpenCV 2.4.3 REQUIRED core)
elseif("${OpenCV_VERSION_MAJOR}$" EQUAL 3)
message(STATUS "OpenCV 3.x detected - including imgcodecs for compatibility")
find_package(OpenCV 3 REQUIRED core)
endif()
# This allows us to compile in RelWithDebInfo. It'll use the Release-version of OpenCV:
set_target_properties(${OpenCV_LIBS} PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE)
# Include eos. Todo: We should really rather use an import target approach rather than running add_subdirectory here.
set(eos_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/eos")
set(EOS_BUILD_EXAMPLES OFF)
add_subdirectory(${eos_DIR})
######### The following will find libigl, and build everything that's required for the viewer - e.g. GLFW:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(LIBIGL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/libigl/include")
option(LIBIGL_USE_STATIC_LIBRARY "Use libigl as static library" OFF)
option(LIBIGL_WITH_ANTTWEAKBAR "Use AntTweakBar" OFF)
option(LIBIGL_WITH_CGAL "Use CGAL" OFF)
option(LIBIGL_WITH_COMISO "Use CoMiso" OFF)
option(LIBIGL_WITH_CORK "Use Cork" OFF)
option(LIBIGL_WITH_EMBREE "Use Embree" OFF)
option(LIBIGL_WITH_LIM "Use LIM" OFF)
option(LIBIGL_WITH_MATLAB "Use Matlab" OFF)
option(LIBIGL_WITH_MOSEK "Use MOSEK" OFF)
option(LIBIGL_WITH_OPENGL "Use OpenGL" ON)
option(LIBIGL_WITH_OPENGL_GLFW "Use GLFW" ON)
option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui" ON)
option(LIBIGL_WITH_PNG "Use PNG" OFF)
option(LIBIGL_WITH_PYTHON "Use Python" OFF)
option(LIBIGL_WITH_TETGEN "Use Tetgen" OFF)
option(LIBIGL_WITH_TRIANGLE "Use Triangle" OFF)
option(LIBIGL_WITH_VIEWER "Use OpenGL viewer" ON)
option(LIBIGL_WITH_XML "Use XML" OFF)
find_package(LIBIGL REQUIRED)
######### libigl should be set up by now.
# Set up the eos-model-viewer target:
add_executable(eos-model-viewer eos-model-viewer.cpp cxxopts.hpp)
#target_include_directories(eos-model-viewer PRIVATE ${LIBIGL_INCLUDE_DIRS})
#add_definitions(${LIBIGL_DEFINITIONS})
target_compile_features(eos-model-viewer PRIVATE ${eos-model-viewer_CXX_COMPILE_FEATURES})
target_link_libraries(eos-model-viewer eos ${OpenCV_LIBS} igl::core igl::opengl_glfw igl::opengl_glfw_imgui)
target_link_libraries(eos-model-viewer "$<$<CXX_COMPILER_ID:GNU>:-pthread>$<$<CXX_COMPILER_ID:Clang>:-pthreads>")
# Install the binary:
install(TARGETS eos-model-viewer DESTINATION bin)
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# eos-model-viewer
3D model viewer for the eos Morphable Model library
This is a viewer that displays Morphable Models from the eos Morphable Model library ([github.com/patrikhuber/eos](https://github.com/patrikhuber/eos)).
It allows to play around with the shape and colour PCA models as well as the blendshapes.

## Build & installation
It uses libigl's 3D viewer.
**Note:** The viewer works well, but the code is not very polished and will crash if you do unexpected things (e.g. cancel the loading dialogues).
The CMake scripts are in serious alpha-stage - You are on your own compiling it!
Make sure to clone the repository with `--recursive`, or, if already cloned, run `git submodule update --init --recursive`.
## Running the viewer
The viewer can be given a `-m` and `-b` options to open a specific model and blendshapes. If you don't specify these options, a GUI file dialog will pop up, asking you to first select the model, and then the blendshapes file.
================================================
FILE: cmake/FindLIBIGL.cmake
================================================
# - Try to find the LIBIGL library
# Once done this will define
#
# LIBIGL_FOUND - system has LIBIGL
# LIBIGL_INCLUDE_DIR - **the** LIBIGL include directory
if(LIBIGL_FOUND)
return()
endif()
find_path(LIBIGL_INCLUDE_DIR igl/readOBJ.h
HINTS
ENV LIBIGL
ENV LIBIGLROOT
ENV LIBIGL_ROOT
ENV LIBIGL_DIR
PATHS
${CMAKE_SOURCE_DIR}/../..
${CMAKE_SOURCE_DIR}/..
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/libigl
${CMAKE_SOURCE_DIR}/../libigl
${CMAKE_SOURCE_DIR}/../../libigl
/usr
/usr/local
/usr/local/igl/libigl
PATH_SUFFIXES include
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LIBIGL
"\nlibigl not found --- You can download it using:\n\tgit clone --recursive https://github.com/libigl/libigl.git ${CMAKE_SOURCE_DIR}/../libigl"
LIBIGL_INCLUDE_DIR)
mark_as_advanced(LIBIGL_INCLUDE_DIR)
list(APPEND CMAKE_MODULE_PATH "${LIBIGL_INCLUDE_DIR}/../cmake")
include(libigl)
================================================
FILE: cxxopts.hpp
================================================
/*
Copyright (c) 2014, 2015, 2016, 2017 Jarryd Beck
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef CXXOPTS_HPP_INCLUDED
#define CXXOPTS_HPP_INCLUDED
#include <cstring>
#include <cctype>
#include <exception>
#include <iostream>
#include <map>
#include <memory>
#include <regex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#ifdef __cpp_lib_optional
#include <optional>
#define CXXOPTS_HAS_OPTIONAL
#endif
namespace cxxopts
{
static constexpr struct {
uint8_t major, minor, patch;
} version = {2, 1, 0};
}
//when we ask cxxopts to use Unicode, help strings are processed using ICU,
//which results in the correct lengths being computed for strings when they
//are formatted for the help output
//it is necessary to make sure that <unicode/unistr.h> can be found by the
//compiler, and that icu-uc is linked in to the binary.
#ifdef CXXOPTS_USE_UNICODE
#include <unicode/unistr.h>
namespace cxxopts
{
typedef icu::UnicodeString String;
inline
String
toLocalString(std::string s)
{
return icu::UnicodeString::fromUTF8(std::move(s));
}
class UnicodeStringIterator : public
std::iterator<std::forward_iterator_tag, int32_t>
{
public:
UnicodeStringIterator(const icu::UnicodeString* string, int32_t pos)
: s(string)
, i(pos)
{
}
value_type
operator*() const
{
return s->char32At(i);
}
bool
operator==(const UnicodeStringIterator& rhs) const
{
return s == rhs.s && i == rhs.i;
}
bool
operator!=(const UnicodeStringIterator& rhs) const
{
return !(*this == rhs);
}
UnicodeStringIterator&
operator++()
{
++i;
return *this;
}
UnicodeStringIterator
operator+(int32_t v)
{
return UnicodeStringIterator(s, i + v);
}
private:
const icu::UnicodeString* s;
int32_t i;
};
inline
String&
stringAppend(String&s, String a)
{
return s.append(std::move(a));
}
inline
String&
stringAppend(String& s, int n, UChar32 c)
{
for (int i = 0; i != n; ++i)
{
s.append(c);
}
return s;
}
template <typename Iterator>
String&
stringAppend(String& s, Iterator begin, Iterator end)
{
while (begin != end)
{
s.append(*begin);
++begin;
}
return s;
}
inline
size_t
stringLength(const String& s)
{
return s.length();
}
inline
std::string
toUTF8String(const String& s)
{
std::string result;
s.toUTF8String(result);
return result;
}
inline
bool
empty(const String& s)
{
return s.isEmpty();
}
}
namespace std
{
inline
cxxopts::UnicodeStringIterator
begin(const icu::UnicodeString& s)
{
return cxxopts::UnicodeStringIterator(&s, 0);
}
inline
cxxopts::UnicodeStringIterator
end(const icu::UnicodeString& s)
{
return cxxopts::UnicodeStringIterator(&s, s.length());
}
}
//ifdef CXXOPTS_USE_UNICODE
#else
namespace cxxopts
{
typedef std::string String;
template <typename T>
T
toLocalString(T&& t)
{
return t;
}
inline
size_t
stringLength(const String& s)
{
return s.length();
}
inline
String&
stringAppend(String&s, String a)
{
return s.append(std::move(a));
}
inline
String&
stringAppend(String& s, size_t n, char c)
{
return s.append(n, c);
}
template <typename Iterator>
String&
stringAppend(String& s, Iterator begin, Iterator end)
{
return s.append(begin, end);
}
template <typename T>
std::string
toUTF8String(T&& t)
{
return std::forward<T>(t);
}
inline
bool
empty(const std::string& s)
{
return s.empty();
}
}
//ifdef CXXOPTS_USE_UNICODE
#endif
namespace cxxopts
{
namespace
{
#ifdef _WIN32
const std::string LQUOTE("\'");
const std::string RQUOTE("\'");
#else
const std::string LQUOTE("‘");
const std::string RQUOTE("’");
#endif
}
class Value : public std::enable_shared_from_this<Value>
{
public:
virtual ~Value() = default;
virtual
std::shared_ptr<Value>
clone() const = 0;
virtual void
parse(const std::string& text) const = 0;
virtual void
parse() const = 0;
virtual bool
has_default() const = 0;
virtual bool
is_container() const = 0;
virtual bool
has_implicit() const = 0;
virtual std::string
get_default_value() const = 0;
virtual std::string
get_implicit_value() const = 0;
virtual std::shared_ptr<Value>
default_value(const std::string& value) = 0;
virtual std::shared_ptr<Value>
implicit_value(const std::string& value) = 0;
virtual bool
is_boolean() const = 0;
};
class OptionException : public std::exception
{
public:
OptionException(const std::string& message)
: m_message(message)
{
}
virtual const char*
what() const noexcept
{
return m_message.c_str();
}
private:
std::string m_message;
};
class OptionSpecException : public OptionException
{
public:
OptionSpecException(const std::string& message)
: OptionException(message)
{
}
};
class OptionParseException : public OptionException
{
public:
OptionParseException(const std::string& message)
: OptionException(message)
{
}
};
class option_exists_error : public OptionSpecException
{
public:
option_exists_error(const std::string& option)
: OptionSpecException(u8"Option " + LQUOTE + option + RQUOTE + u8" already exists")
{
}
};
class invalid_option_format_error : public OptionSpecException
{
public:
invalid_option_format_error(const std::string& format)
: OptionSpecException(u8"Invalid option format " + LQUOTE + format + RQUOTE)
{
}
};
class option_not_exists_exception : public OptionParseException
{
public:
option_not_exists_exception(const std::string& option)
: OptionParseException(u8"Option " + LQUOTE + option + RQUOTE + u8" does not exist")
{
}
};
class missing_argument_exception : public OptionParseException
{
public:
missing_argument_exception(const std::string& option)
: OptionParseException(
u8"Option " + LQUOTE + option + RQUOTE + u8" is missing an argument"
)
{
}
};
class option_requires_argument_exception : public OptionParseException
{
public:
option_requires_argument_exception(const std::string& option)
: OptionParseException(
u8"Option " + LQUOTE + option + RQUOTE + u8" requires an argument"
)
{
}
};
class option_not_has_argument_exception : public OptionParseException
{
public:
option_not_has_argument_exception
(
const std::string& option,
const std::string& arg
)
: OptionParseException(
u8"Option " + LQUOTE + option + RQUOTE +
u8" does not take an argument, but argument " +
LQUOTE + arg + RQUOTE + " given"
)
{
}
};
class option_not_present_exception : public OptionParseException
{
public:
option_not_present_exception(const std::string& option)
: OptionParseException(u8"Option " + LQUOTE + option + RQUOTE + u8" not present")
{
}
};
class argument_incorrect_type : public OptionParseException
{
public:
argument_incorrect_type
(
const std::string& arg
)
: OptionParseException(
u8"Argument " + LQUOTE + arg + RQUOTE + u8" failed to parse"
)
{
}
};
class option_required_exception : public OptionParseException
{
public:
option_required_exception(const std::string& option)
: OptionParseException(
u8"Option " + LQUOTE + option + RQUOTE + u8" is required but not present"
)
{
}
};
namespace values
{
namespace
{
std::basic_regex<char> integer_pattern
("(-)?(0x)?([1-9a-zA-Z][0-9a-zA-Z]*)|((0x)?0)");
std::basic_regex<char> truthy_pattern
("(t|T)(rue)?");
std::basic_regex<char> falsy_pattern
("((f|F)(alse)?)?");
}
namespace detail
{
template <typename T, bool B>
struct SignedCheck;
template <typename T>
struct SignedCheck<T, true>
{
template <typename U>
void
operator()(bool negative, U u, const std::string& text)
{
if (negative)
{
if (u > static_cast<U>(-std::numeric_limits<T>::min()))
{
throw argument_incorrect_type(text);
}
}
else
{
if (u > static_cast<U>(std::numeric_limits<T>::max()))
{
throw argument_incorrect_type(text);
}
}
}
};
template <typename T>
struct SignedCheck<T, false>
{
template <typename U>
void
operator()(bool, U, const std::string&) {}
};
template <typename T, typename U>
void
check_signed_range(bool negative, U value, const std::string& text)
{
SignedCheck<T, std::numeric_limits<T>::is_signed>()(negative, value, text);
}
}
template <typename R, typename T>
R
checked_negate(T&& t, const std::string&, std::true_type)
{
// if we got to here, then `t` is a positive number that fits into
// `R`. So to avoid MSVC C4146, we first cast it to `R`.
// See https://github.com/jarro2783/cxxopts/issues/62 for more details.
return -static_cast<R>(t);
}
template <typename R, typename T>
T
checked_negate(T&&, const std::string& text, std::false_type)
{
throw argument_incorrect_type(text);
}
template <typename T>
void
integer_parser(const std::string& text, T& value)
{
std::smatch match;
std::regex_match(text, match, integer_pattern);
if (match.length() == 0)
{
throw argument_incorrect_type(text);
}
if (match.length(4) > 0)
{
value = 0;
return;
}
using US = typename std::make_unsigned<T>::type;
constexpr auto umax = std::numeric_limits<US>::max();
constexpr bool is_signed = std::numeric_limits<T>::is_signed;
const bool negative = match.length(1) > 0;
const uint8_t base = match.length(2) > 0 ? 16 : 10;
auto value_match = match[3];
US result = 0;
for (auto iter = value_match.first; iter != value_match.second; ++iter)
{
size_t digit = 0;
if (*iter >= '0' && *iter <= '9')
{
digit = *iter - '0';
}
else if (base == 16 && *iter >= 'a' && *iter <= 'f')
{
digit = *iter - 'a' + 10;
}
else if (base == 16 && *iter >= 'A' && *iter <= 'F')
{
digit = *iter - 'A' + 10;
}
else
{
throw argument_incorrect_type(text);
}
if (umax - digit < result * base)
{
throw argument_incorrect_type(text);
}
result = result * base + digit;
}
detail::check_signed_range<T>(negative, result, text);
if (negative)
{
value = checked_negate<T>(result,
text,
std::integral_constant<bool, is_signed>());
}
else
{
value = result;
}
}
template <typename T>
void stringstream_parser(const std::string& text, T& value)
{
std::stringstream in(text);
in >> value;
if (!in) {
throw argument_incorrect_type(text);
}
}
inline
void
parse_value(const std::string& text, uint8_t& value)
{
integer_parser(text, value);
}
inline
void
parse_value(const std::string& text, int8_t& value)
{
integer_parser(text, value);
}
inline
void
parse_value(const std::string& text, uint16_t& value)
{
integer_parser(text, value);
}
inline
void
parse_value(const std::string& text, int16_t& value)
{
integer_parser(text, value);
}
inline
void
parse_value(const std::string& text, uint32_t& value)
{
integer_parser(text, value);
}
inline
void
parse_value(const std::string& text, int32_t& value)
{
integer_parser(text, value);
}
inline
void
parse_value(const std::string& text, uint64_t& value)
{
integer_parser(text, value);
}
inline
void
parse_value(const std::string& text, int64_t& value)
{
integer_parser(text, value);
}
inline
void
parse_value(const std::string& text, bool& value)
{
std::smatch result;
std::regex_match(text, result, truthy_pattern);
if (!result.empty())
{
value = true;
return;
}
std::regex_match(text, result, falsy_pattern);
if (!result.empty())
{
value = false;
return;
}
throw argument_incorrect_type(text);
}
inline
void
parse_value(const std::string& text, std::string& value)
{
value = text;
}
// The fallback parser. It uses the stringstream parser to parse all types
// that have not been overloaded explicitly. It has to be placed in the
// source code before all other more specialized templates.
template <typename T>
void
parse_value(const std::string& text, T& value) {
stringstream_parser(text, value);
}
template <typename T>
void
parse_value(const std::string& text, std::vector<T>& value)
{
T v;
parse_value(text, v);
value.push_back(v);
}
#ifdef CXXOPTS_HAS_OPTIONAL
template <typename T>
void
parse_value(const std::string& text, std::optional<T>& value)
{
T result;
parse_value(text, result);
value = std::move(result);
}
#endif
template <typename T>
struct type_is_container
{
static constexpr bool value = false;
};
template <typename T>
struct type_is_container<std::vector<T>>
{
static constexpr bool value = true;
};
template <typename T>
class abstract_value : public Value
{
using Self = abstract_value<T>;
public:
abstract_value()
: m_result(std::make_shared<T>())
, m_store(m_result.get())
{
}
abstract_value(T* t)
: m_store(t)
{
}
virtual ~abstract_value() = default;
abstract_value(const abstract_value& rhs)
{
if (rhs.m_result)
{
m_result = std::make_shared<T>();
m_store = m_result.get();
}
else
{
m_store = rhs.m_store;
}
m_default = rhs.m_default;
m_implicit = rhs.m_implicit;
m_default_value = rhs.m_default_value;
m_implicit_value = rhs.m_implicit_value;
}
void
parse(const std::string& text) const
{
parse_value(text, *m_store);
}
bool
is_container() const
{
return type_is_container<T>::value;
}
void
parse() const
{
parse_value(m_default_value, *m_store);
}
bool
has_default() const
{
return m_default;
}
bool
has_implicit() const
{
return m_implicit;
}
std::shared_ptr<Value>
default_value(const std::string& value)
{
m_default = true;
m_default_value = value;
return shared_from_this();
}
std::shared_ptr<Value>
implicit_value(const std::string& value)
{
m_implicit = true;
m_implicit_value = value;
return shared_from_this();
}
std::string
get_default_value() const
{
return m_default_value;
}
std::string
get_implicit_value() const
{
return m_implicit_value;
}
bool
is_boolean() const
{
return std::is_same<T, bool>::value;
}
const T&
get() const
{
if (m_store == nullptr)
{
return *m_result;
}
else
{
return *m_store;
}
}
protected:
std::shared_ptr<T> m_result;
T* m_store;
bool m_default = false;
bool m_implicit = false;
std::string m_default_value;
std::string m_implicit_value;
};
template <typename T>
class standard_value : public abstract_value<T>
{
public:
using abstract_value<T>::abstract_value;
std::shared_ptr<Value>
clone() const
{
return std::make_shared<standard_value<T>>(*this);
}
};
template <>
class standard_value<bool> : public abstract_value<bool>
{
public:
~standard_value() = default;
standard_value()
{
set_default_and_implicit();
}
standard_value(bool* b)
: abstract_value(b)
{
set_default_and_implicit();
}
std::shared_ptr<Value>
clone() const
{
return std::make_shared<standard_value<bool>>(*this);
}
private:
void
set_default_and_implicit()
{
m_default = true;
m_default_value = "false";
m_implicit = true;
m_implicit_value = "true";
}
};
}
template <typename T>
std::shared_ptr<Value>
value()
{
return std::make_shared<values::standard_value<T>>();
}
template <typename T>
std::shared_ptr<Value>
value(T& t)
{
return std::make_shared<values::standard_value<T>>(&t);
}
class OptionAdder;
class OptionDetails
{
public:
OptionDetails
(
const std::string& short_,
const std::string& long_,
const String& desc,
std::shared_ptr<const Value> val
)
: m_short(short_)
, m_long(long_)
, m_desc(desc)
, m_value(val)
, m_count(0)
{
}
OptionDetails(const OptionDetails& rhs)
: m_desc(rhs.m_desc)
, m_count(rhs.m_count)
{
m_value = rhs.m_value->clone();
}
OptionDetails(OptionDetails&& rhs) = default;
const String&
description() const
{
return m_desc;
}
const Value& value() const {
return *m_value;
}
std::shared_ptr<Value>
make_storage() const
{
return m_value->clone();
}
const std::string&
short_name() const
{
return m_short;
}
const std::string&
long_name() const
{
return m_long;
}
private:
std::string m_short;
std::string m_long;
String m_desc;
std::shared_ptr<const Value> m_value;
int m_count;
};
struct HelpOptionDetails
{
std::string s;
std::string l;
String desc;
bool has_default;
std::string default_value;
bool has_implicit;
std::string implicit_value;
std::string arg_help;
bool is_container;
bool is_boolean;
};
struct HelpGroupDetails
{
std::string name;
std::string description;
std::vector<HelpOptionDetails> options;
};
class OptionValue
{
public:
void
parse
(
std::shared_ptr<const OptionDetails> details,
const std::string& text
)
{
ensure_value(details);
++m_count;
m_value->parse(text);
}
void
parse_default(std::shared_ptr<const OptionDetails> details)
{
ensure_value(details);
m_value->parse();
}
size_t
count() const
{
return m_count;
}
template <typename T>
const T&
as() const
{
#ifdef CXXOPTS_NO_RTTI
return static_cast<const values::standard_value<T>&>(*m_value).get();
#else
return dynamic_cast<const values::standard_value<T>&>(*m_value).get();
#endif
}
private:
void
ensure_value(std::shared_ptr<const OptionDetails> details)
{
if (m_value == nullptr)
{
m_value = details->make_storage();
}
}
std::shared_ptr<Value> m_value;
size_t m_count = 0;
};
class KeyValue
{
public:
KeyValue(std::string key_, std::string value_)
: m_key(std::move(key_))
, m_value(std::move(value_))
{
}
const
std::string&
key() const
{
return m_key;
}
const std::string
value() const
{
return m_value;
}
template <typename T>
T
as() const
{
T result;
values::parse_value(m_value, result);
return result;
}
private:
std::string m_key;
std::string m_value;
};
class ParseResult
{
public:
ParseResult(
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>&,
std::vector<std::string>,
int&, const char**&);
size_t
count(const std::string& o) const
{
auto iter = m_options.find(o);
if (iter == m_options.end())
{
return 0;
}
auto riter = m_results.find(iter->second);
return riter->second.count();
}
const OptionValue&
operator[](const std::string& option) const
{
auto iter = m_options.find(option);
if (iter == m_options.end())
{
throw option_not_present_exception(option);
}
auto riter = m_results.find(iter->second);
return riter->second;
}
const std::vector<KeyValue>&
arguments() const
{
return m_sequential;
}
private:
OptionValue&
get_option(std::shared_ptr<OptionDetails>);
void
parse(int& argc, const char**& argv);
void
add_to_option(const std::string& option, const std::string& arg);
bool
consume_positional(std::string a);
void
parse_option
(
std::shared_ptr<OptionDetails> value,
const std::string& name,
const std::string& arg = ""
);
void
parse_default(std::shared_ptr<OptionDetails> details);
void
checked_parse_arg
(
int argc,
const char* argv[],
int& current,
std::shared_ptr<OptionDetails> value,
const std::string& name
);
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
&m_options;
std::vector<std::string> m_positional;
std::vector<std::string>::iterator m_next_positional;
std::unordered_set<std::string> m_positional_set;
std::unordered_map<std::shared_ptr<OptionDetails>, OptionValue> m_results;
std::vector<KeyValue> m_sequential;
};
class Options
{
public:
Options(std::string program, std::string help_string = "")
: m_program(std::move(program))
, m_help_string(toLocalString(std::move(help_string)))
, m_custom_help("[OPTION...]")
, m_positional_help("positional parameters")
, m_show_positional(false)
, m_next_positional(m_positional.end())
{
}
Options&
positional_help(std::string help_text)
{
m_positional_help = std::move(help_text);
return *this;
}
Options&
custom_help(std::string help_text)
{
m_custom_help = std::move(help_text);
return *this;
}
Options&
show_positional_help()
{
m_show_positional = true;
return *this;
}
ParseResult
parse(int& argc, const char**& argv);
OptionAdder
add_options(std::string group = "");
void
add_option
(
const std::string& group,
const std::string& s,
const std::string& l,
std::string desc,
std::shared_ptr<const Value> value,
std::string arg_help
);
//parse positional arguments into the given option
void
parse_positional(std::string option);
void
parse_positional(std::vector<std::string> options);
void
parse_positional(std::initializer_list<std::string> options);
std::string
help(const std::vector<std::string>& groups = {""}) const;
const std::vector<std::string>
groups() const;
const HelpGroupDetails&
group_help(const std::string& group) const;
private:
void
add_one_option
(
const std::string& option,
std::shared_ptr<OptionDetails> details
);
String
help_one_group(const std::string& group) const;
void
generate_group_help
(
String& result,
const std::vector<std::string>& groups
) const;
void
generate_all_groups_help(String& result) const;
std::string m_program;
String m_help_string;
std::string m_custom_help;
std::string m_positional_help;
bool m_show_positional;
std::unordered_map<std::string, std::shared_ptr<OptionDetails>> m_options;
std::vector<std::string> m_positional;
std::vector<std::string>::iterator m_next_positional;
std::unordered_set<std::string> m_positional_set;
//mapping from groups to help options
std::map<std::string, HelpGroupDetails> m_help;
};
class OptionAdder
{
public:
OptionAdder(Options& options, std::string group)
: m_options(options), m_group(std::move(group))
{
}
OptionAdder&
operator()
(
const std::string& opts,
const std::string& desc,
std::shared_ptr<const Value> value
= ::cxxopts::value<bool>(),
std::string arg_help = ""
);
private:
Options& m_options;
std::string m_group;
};
namespace
{
constexpr int OPTION_LONGEST = 30;
constexpr int OPTION_DESC_GAP = 2;
std::basic_regex<char> option_matcher
("--([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([[:alnum:]]+)");
std::basic_regex<char> option_specifier
("(([[:alnum:]]),)?[ ]*([[:alnum:]][-_[:alnum:]]*)?");
String
format_option
(
const HelpOptionDetails& o
)
{
auto& s = o.s;
auto& l = o.l;
String result = " ";
if (s.size() > 0)
{
result += "-" + toLocalString(s) + ",";
}
else
{
result += " ";
}
if (l.size() > 0)
{
result += " --" + toLocalString(l);
}
auto arg = o.arg_help.size() > 0 ? toLocalString(o.arg_help) : "arg";
if (!o.is_boolean)
{
if (o.has_implicit)
{
result += " [=" + arg + "(=" + toLocalString(o.implicit_value) + ")]";
}
else
{
result += " " + arg;
}
}
return result;
}
String
format_description
(
const HelpOptionDetails& o,
size_t start,
size_t width
)
{
auto desc = o.desc;
if (o.has_default && (!o.is_boolean || o.default_value != "false"))
{
desc += toLocalString(" (default: " + o.default_value + ")");
}
String result;
auto current = std::begin(desc);
auto startLine = current;
auto lastSpace = current;
auto size = size_t{};
while (current != std::end(desc))
{
if (*current == ' ')
{
lastSpace = current;
}
if (size > width)
{
if (lastSpace == startLine)
{
stringAppend(result, startLine, current + 1);
stringAppend(result, "\n");
stringAppend(result, start, ' ');
startLine = current + 1;
lastSpace = startLine;
}
else
{
stringAppend(result, startLine, lastSpace);
stringAppend(result, "\n");
stringAppend(result, start, ' ');
startLine = lastSpace + 1;
}
size = 0;
}
else
{
++size;
}
++current;
}
//append whatever is left
stringAppend(result, startLine, current);
return result;
}
}
inline
ParseResult::ParseResult
(
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>& options,
std::vector<std::string> positional,
int& argc, const char**& argv
)
: m_options(options)
, m_positional(std::move(positional))
, m_next_positional(m_positional.begin())
{
parse(argc, argv);
}
inline
OptionAdder
Options::add_options(std::string group)
{
return OptionAdder(*this, std::move(group));
}
inline
OptionAdder&
OptionAdder::operator()
(
const std::string& opts,
const std::string& desc,
std::shared_ptr<const Value> value,
std::string arg_help
)
{
std::match_results<const char*> result;
std::regex_match(opts.c_str(), result, option_specifier);
if (result.empty())
{
throw invalid_option_format_error(opts);
}
const auto& short_match = result[2];
const auto& long_match = result[3];
if (!short_match.length() && !long_match.length())
{
throw invalid_option_format_error(opts);
} else if (long_match.length() == 1 && short_match.length())
{
throw invalid_option_format_error(opts);
}
auto option_names = []
(
const std::sub_match<const char*>& short_,
const std::sub_match<const char*>& long_
)
{
if (long_.length() == 1)
{
return std::make_tuple(long_.str(), short_.str());
}
else
{
return std::make_tuple(short_.str(), long_.str());
}
}(short_match, long_match);
m_options.add_option
(
m_group,
std::get<0>(option_names),
std::get<1>(option_names),
desc,
value,
std::move(arg_help)
);
return *this;
}
inline
void
ParseResult::parse_default(std::shared_ptr<OptionDetails> details)
{
m_results[details].parse_default(details);
}
inline
void
ParseResult::parse_option
(
std::shared_ptr<OptionDetails> value,
const std::string& /*name*/,
const std::string& arg
)
{
auto& result = m_results[value];
result.parse(value, arg);
m_sequential.emplace_back(value->long_name(), arg);
}
inline
void
ParseResult::checked_parse_arg
(
int argc,
const char* argv[],
int& current,
std::shared_ptr<OptionDetails> value,
const std::string& name
)
{
if (current + 1 >= argc)
{
if (value->value().has_implicit())
{
parse_option(value, name, value->value().get_implicit_value());
}
else
{
throw missing_argument_exception(name);
}
}
else
{
if (value->value().has_implicit())
{
parse_option(value, name, value->value().get_implicit_value());
}
else
{
parse_option(value, name, argv[current + 1]);
++current;
}
}
}
inline
void
ParseResult::add_to_option(const std::string& option, const std::string& arg)
{
auto iter = m_options.find(option);
if (iter == m_options.end())
{
throw option_not_exists_exception(option);
}
parse_option(iter->second, option, arg);
}
inline
bool
ParseResult::consume_positional(std::string a)
{
while (m_next_positional != m_positional.end())
{
auto iter = m_options.find(*m_next_positional);
if (iter != m_options.end())
{
auto& result = m_results[iter->second];
if (!iter->second->value().is_container())
{
if (result.count() == 0)
{
add_to_option(*m_next_positional, a);
++m_next_positional;
return true;
}
else
{
++m_next_positional;
continue;
}
}
else
{
add_to_option(*m_next_positional, a);
return true;
}
}
++m_next_positional;
}
return false;
}
inline
void
Options::parse_positional(std::string option)
{
parse_positional(std::vector<std::string>{std::move(option)});
}
inline
void
Options::parse_positional(std::vector<std::string> options)
{
m_positional = std::move(options);
m_next_positional = m_positional.begin();
m_positional_set.insert(m_positional.begin(), m_positional.end());
}
inline
void
Options::parse_positional(std::initializer_list<std::string> options)
{
parse_positional(std::vector<std::string>(std::move(options)));
}
inline
ParseResult
Options::parse(int& argc, const char**& argv)
{
ParseResult result(m_options, m_positional, argc, argv);
return result;
}
inline
void
ParseResult::parse(int& argc, const char**& argv)
{
int current = 1;
int nextKeep = 1;
bool consume_remaining = false;
while (current != argc)
{
if (strcmp(argv[current], "--") == 0)
{
consume_remaining = true;
++current;
break;
}
std::match_results<const char*> result;
std::regex_match(argv[current], result, option_matcher);
if (result.empty())
{
//not a flag
//if true is returned here then it was consumed, otherwise it is
//ignored
if (consume_positional(argv[current]))
{
}
else
{
argv[nextKeep] = argv[current];
++nextKeep;
}
//if we return from here then it was parsed successfully, so continue
}
else
{
//short or long option?
if (result[4].length() != 0)
{
const std::string& s = result[4];
for (std::size_t i = 0; i != s.size(); ++i)
{
std::string name(1, s[i]);
auto iter = m_options.find(name);
if (iter == m_options.end())
{
throw option_not_exists_exception(name);
}
auto value = iter->second;
if (i + 1 == s.size())
{
//it must be the last argument
checked_parse_arg(argc, argv, current, value, name);
}
else if (value->value().has_implicit())
{
parse_option(value, name, value->value().get_implicit_value());
}
else
{
//error
throw option_requires_argument_exception(name);
}
}
}
else if (result[1].length() != 0)
{
const std::string& name = result[1];
auto iter = m_options.find(name);
if (iter == m_options.end())
{
throw option_not_exists_exception(name);
}
auto opt = iter->second;
//equals provided for long option?
if (result[2].length() != 0)
{
//parse the option given
parse_option(opt, name, result[3]);
}
else
{
//parse the next argument
checked_parse_arg(argc, argv, current, opt, name);
}
}
}
++current;
}
for (auto& opt : m_options)
{
auto& detail = opt.second;
auto& value = detail->value();
auto& store = m_results[detail];
if(!store.count() && value.has_default()){
parse_default(detail);
}
}
if (consume_remaining)
{
while (current < argc)
{
if (!consume_positional(argv[current])) {
break;
}
++current;
}
//adjust argv for any that couldn't be swallowed
while (current != argc) {
argv[nextKeep] = argv[current];
++nextKeep;
++current;
}
}
argc = nextKeep;
}
inline
void
Options::add_option
(
const std::string& group,
const std::string& s,
const std::string& l,
std::string desc,
std::shared_ptr<const Value> value,
std::string arg_help
)
{
auto stringDesc = toLocalString(std::move(desc));
auto option = std::make_shared<OptionDetails>(s, l, stringDesc, value);
if (s.size() > 0)
{
add_one_option(s, option);
}
if (l.size() > 0)
{
add_one_option(l, option);
}
//add the help details
auto& options = m_help[group];
options.options.emplace_back(HelpOptionDetails{s, l, stringDesc,
value->has_default(), value->get_default_value(),
value->has_implicit(), value->get_implicit_value(),
std::move(arg_help),
value->is_container(),
value->is_boolean()});
}
inline
void
Options::add_one_option
(
const std::string& option,
std::shared_ptr<OptionDetails> details
)
{
auto in = m_options.emplace(option, details);
if (!in.second)
{
throw option_exists_error(option);
}
}
inline
String
Options::help_one_group(const std::string& g) const
{
typedef std::vector<std::pair<String, String>> OptionHelp;
auto group = m_help.find(g);
if (group == m_help.end())
{
return "";
}
OptionHelp format;
size_t longest = 0;
String result;
if (!g.empty())
{
result += toLocalString(" " + g + " options:\n");
}
for (const auto& o : group->second.options)
{
if (o.is_container &&
m_positional_set.find(o.l) != m_positional_set.end() &&
!m_show_positional)
{
continue;
}
auto s = format_option(o);
longest = std::max(longest, stringLength(s));
format.push_back(std::make_pair(s, String()));
}
longest = std::min(longest, static_cast<size_t>(OPTION_LONGEST));
//widest allowed description
auto allowed = size_t{76} - longest - OPTION_DESC_GAP;
auto fiter = format.begin();
for (const auto& o : group->second.options)
{
if (o.is_container &&
m_positional_set.find(o.l) != m_positional_set.end() &&
!m_show_positional)
{
continue;
}
auto d = format_description(o, longest + OPTION_DESC_GAP, allowed);
result += fiter->first;
if (stringLength(fiter->first) > longest)
{
result += '\n';
result += toLocalString(std::string(longest + OPTION_DESC_GAP, ' '));
}
else
{
result += toLocalString(std::string(longest + OPTION_DESC_GAP -
stringLength(fiter->first),
' '));
}
result += d;
result += '\n';
++fiter;
}
return result;
}
inline
void
Options::generate_group_help
(
String& result,
const std::vector<std::string>& print_groups
) const
{
for (size_t i = 0; i != print_groups.size(); ++i)
{
const String& group_help_text = help_one_group(print_groups[i]);
if (empty(group_help_text))
{
continue;
}
result += group_help_text;
if (i < print_groups.size() - 1)
{
result += '\n';
}
}
}
inline
void
Options::generate_all_groups_help(String& result) const
{
std::vector<std::string> all_groups;
all_groups.reserve(m_help.size());
for (auto& group : m_help)
{
all_groups.push_back(group.first);
}
generate_group_help(result, all_groups);
}
inline
std::string
Options::help(const std::vector<std::string>& help_groups) const
{
String result = m_help_string + "\nUsage:\n " +
toLocalString(m_program) + " " + toLocalString(m_custom_help);
if (m_positional.size() > 0 && m_positional_help.size() > 0) {
result += " " + toLocalString(m_positional_help);
}
result += "\n\n";
if (help_groups.size() == 0)
{
generate_all_groups_help(result);
}
else
{
generate_group_help(result, help_groups);
}
return toUTF8String(result);
}
inline
const std::vector<std::string>
Options::groups() const
{
std::vector<std::string> g;
std::transform(
m_help.begin(),
m_help.end(),
std::back_inserter(g),
[] (const std::map<std::string, HelpGroupDetails>::value_type& pair)
{
return pair.first;
}
);
return g;
}
inline
const HelpGroupDetails&
Options::group_help(const std::string& group) const
{
return m_help.at(group);
}
}
#endif //CXXOPTS_HPP_INCLUDED
================================================
FILE: eos-model-viewer.cpp
================================================
/*
* eos - A 3D Morphable Model fitting library written in modern C++11/14.
*
* File: eos-model-viewer.cpp
*
* Copyright 2017, 2018 Patrik Huber
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cxxopts.hpp"
#include "eos/core/Mesh.hpp"
#include "eos/morphablemodel/MorphableModel.hpp"
#include "eos/morphablemodel/io/cvssp.hpp"
#include "eos/morphablemodel/Blendshape.hpp"
#include "eos/cpp17/variant.hpp"
#include "igl/opengl/glfw/Viewer.h"
#include "igl/opengl/glfw/imgui/ImGuiMenu.h"
#include "igl/opengl/glfw/imgui/ImGuiHelpers.h"
#include "imgui/imgui.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <random>
#include <algorithm>
template <typename T>
std::string to_string(const T a_value, const int n = 6)
{
std::ostringstream out;
out << std::setprecision(n) << a_value;
return out.str();
};
// From: https://stackoverflow.com/a/1493195/1345959
template <class ContainerType>
void tokenize(const std::string& str, ContainerType& tokens, const std::string& delimiters = " ",
bool trim_empty = false)
{
std::string::size_type pos, last_pos = 0;
const auto length = str.length();
using value_type = typename ContainerType::value_type;
using size_type = typename ContainerType::size_type;
while (last_pos < length + 1)
{
pos = str.find_first_of(delimiters, last_pos);
if (pos == std::string::npos)
{
pos = length;
}
if (pos != last_pos || !trim_empty)
tokens.push_back(value_type(str.data() + last_pos, (size_type)pos - last_pos));
last_pos = pos + 1;
}
};
eos::morphablemodel::MorphableModel load_bin_or_scm_model(std::string model_file)
{
using namespace eos;
using eos::morphablemodel::MorphableModel;
MorphableModel morphable_model;
std::vector<std::string> tokens;
tokenize(model_file, tokens, ".");
const auto model_file_extension = tokens.back();
// Todo: Add try-catch to all these?
if (model_file_extension == "scm")
{
morphable_model = morphablemodel::load_scm_model(model_file);
} else if (model_file_extension == "bin")
{
morphable_model = morphablemodel::load_model(model_file);
} else
{
throw std::runtime_error("Error: Please load a model with .bin or .scm extension.");
}
return morphable_model;
}
/**
*
*/
eos::morphablemodel::MorphableModel load_model(std::string model_file, std::string blendshapes_file)
{
using namespace eos;
using eos::morphablemodel::MorphableModel;
MorphableModel morphable_model;
// Todo: Add try-catch to all these?
morphable_model = load_bin_or_scm_model(model_file);
// If separate blendshapes are given, load them, and construct a model with expressions:
if (!blendshapes_file.empty())
{
const auto blendshapes = morphablemodel::load_blendshapes(blendshapes_file);
morphable_model = MorphableModel(
morphable_model.get_shape_model(), blendshapes, morphable_model.get_color_model(),
morphable_model.get_landmark_definitions(), morphable_model.get_texture_coordinates());
}
return morphable_model;
};
/**
* Model viewer for 3D Morphable Models.
*/
int main(int argc, const char* argv[])
{
using namespace eos;
using Eigen::VectorXf;
using std::begin;
using std::cout;
using std::end;
using std::endl;
using std::for_each;
using std::string;
using std::vector;
string model_file, blendshapes_file;
try
{
cxxopts::Options options("eos-model-viewer", "OpenGL viewer for eos's 3D morphable models.");
// clang-format off
options.add_options()
("h,help", "display the help message")
("m,model", "an eos 3D Morphable Model stored as cereal BinaryArchive (.bin)",
cxxopts::value(model_file))
("b,blendshapes", "an eos file with blendshapes (.bin)",
cxxopts::value(blendshapes_file));
// clang-format on
const auto result = options.parse(argc, argv);
if (result.count("help"))
{
cout << options.help() << endl;
return EXIT_SUCCESS;
}
} catch (const cxxopts::OptionException& e)
{
cout << "Error parsing options: " << e.what() << endl;
return EXIT_FAILURE;
}
// Note: Take the vertices here directly, so we can maybe avoid ever generating a Mesh instance
auto get_V = [](const core::Mesh& mesh) {
Eigen::MatrixXd V(mesh.vertices.size(), 3);
for (int i = 0; i < mesh.vertices.size(); ++i)
{
V(i, 0) = mesh.vertices[i](0);
V(i, 1) = mesh.vertices[i](1);
V(i, 2) = mesh.vertices[i](2);
}
return V;
};
auto get_F = [](const core::Mesh& mesh) {
Eigen::MatrixXi F(mesh.tvi.size(), 3);
for (int i = 0; i < mesh.tvi.size(); ++i)
{
F(i, 0) = mesh.tvi[i][0];
F(i, 1) = mesh.tvi[i][1];
F(i, 2) = mesh.tvi[i][2];
}
return F;
};
auto get_C = [](const core::Mesh& mesh) {
Eigen::MatrixXd C(mesh.colors.size(), 3);
for (int i = 0; i < mesh.colors.size(); ++i)
{
C(i, 0) = mesh.colors[i](0);
C(i, 1) = mesh.colors[i](1);
C(i, 2) = mesh.colors[i](2);
}
return C;
};
// Init the viewer:
igl::opengl::glfw::Viewer viewer;
// Attach a menu plugin:
igl::opengl::glfw::imgui::ImGuiMenu menu;
viewer.plugins.push_back(&menu);
morphablemodel::MorphableModel morphable_model;
// Load the model right away on start up, if it was given via command-line parameters:
if (!model_file.empty())
{
try
{
// Loads a .bin or .scm model, with or without blendshapes:
morphable_model = load_model(model_file, blendshapes_file);
const auto& mean = morphable_model.get_mean();
viewer.data().set_mesh(get_V(mean), get_F(mean));
viewer.core.align_camera_center(viewer.data().V, viewer.data().F);
if (!mean.colors.empty())
{
viewer.data().set_colors(get_C(mean));
}
} catch (const std::runtime_error& e)
{
cout << "Error loading the given model: " << e.what() << endl;
return EXIT_FAILURE;
}
}
// These are the coefficients of the currently active mesh instance:
vector<float> shape_coefficients;
vector<float> color_coefficients;
vector<float> expression_coefficients;
bool display_identity_model_only = true;
std::default_random_engine rng;
std::array<float, 3> random_sample_sdev = {1.0f, 1.0f, 1.0f}; // shp, exp, col
// Draw our viewers windows:
menu.callback_draw_custom_window = [&]() {
// Load model & draw sample options:
ImGui::SetNextWindowPos(ImVec2(0.f * menu.menu_scaling(), 585), ImGuiSetCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(240, 280), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Morphable Model", nullptr, ImGuiWindowFlags_NoSavedSettings);
if (ImGui::Button("Load Morphable Model", ImVec2(-1, 0)))
{
const string mm_fn = igl::file_dialog_open();
cout << "Loading Morphable Model " << mm_fn << "..." << endl;
try
{
morphable_model = load_bin_or_scm_model(mm_fn);
const auto& mean = morphable_model.get_mean();
viewer.data().clear();
viewer.data().set_mesh(get_V(mean), get_F(mean));
viewer.core.align_camera_center(viewer.data().V, viewer.data().F);
if (!mean.colors.empty())
{
viewer.data().set_colors(get_C(mean));
}
} catch (const std::runtime_error&
e) // Todo: I think we have to catch more errors here, like cereal exceptions
{
cout << "Error loading the given model: " << e.what() << endl;
}
if (morphable_model.has_separate_expression_model())
{
// Just a sensible default - if the loaded model has expressions, use them by default:
display_identity_model_only = false;
}
}
if (ImGui::Button("Load Blendshapes", ImVec2(-1, 0)))
{
const string bs_fn = igl::file_dialog_open();
cout << "Loading Blendshapes " << bs_fn << "..." << endl;
morphablemodel::Blendshapes blendshapes;
try
{
blendshapes = morphablemodel::load_blendshapes(bs_fn);
cout << "Blendshapes loaded. Constructing a new model consisting of the loaded identity and "
"colour PCA models, and the loaded blendshapes..."
<< endl;
morphable_model = morphablemodel::MorphableModel(
morphable_model.get_shape_model(), blendshapes, morphable_model.get_color_model(),
morphable_model.get_landmark_definitions(), morphable_model.get_texture_coordinates());
const auto& mean = morphable_model.get_mean();
viewer.data().clear();
viewer.data().set_mesh(get_V(mean), get_F(mean));
viewer.core.align_camera_center(viewer.data().V, viewer.data().F);
if (!mean.colors.empty())
{
viewer.data().set_colors(get_C(mean));
}
} catch (const std::runtime_error&
e) // Todo: I think we have to catch more errors here, like cereal exceptions
{
cout << "Error loading the given blendshapes: " << e.what() << endl;
}
display_identity_model_only = false;
}
ImGui::Separator();
if (ImGui::Button("Mean (id)", ImVec2(-1, 0)))
{
Eigen::VectorXf mean = morphable_model.get_shape_model().get_mean();
// Take 3 at a piece, then transpose:
const auto num_vertices = mean.rows() / 3;
Eigen::Map<Eigen::MatrixXf> mean_reshaped(mean.data(), 3, num_vertices);
viewer.data().set_vertices(mean_reshaped.transpose().cast<double>());
if (morphable_model.get_color_model().get_mean().size() > 0)
{
Eigen::VectorXf color_mean = morphable_model.get_color_model().get_mean();
Eigen::Map<Eigen::MatrixXf> color_mean_reshaped(
color_mean.data(), 3,
color_mean.rows() / 3); // Todo: This will fail for gray-level models
viewer.data().set_colors(color_mean_reshaped.transpose().cast<double>());
}
for_each(begin(shape_coefficients), end(shape_coefficients), [](auto& coeff) { coeff = 0.0f; });
for_each(begin(color_coefficients), end(color_coefficients), [](auto& coeff) { coeff = 0.0f; });
for_each(begin(expression_coefficients), end(expression_coefficients),
[](auto& coeff) { coeff = 0.0f; });
display_identity_model_only = true;
}
if (ImGui::Button("Mean (id+exp)", ImVec2(-1, 0)))
{
const auto mean = morphable_model.get_mean();
viewer.data().set_vertices(get_V(mean));
if (!mean.colors.empty())
{
viewer.data().set_colors(get_C(mean));
}
for_each(begin(shape_coefficients), end(shape_coefficients), [](auto& coeff) { coeff = 0.0f; });
for_each(begin(color_coefficients), end(color_coefficients), [](auto& coeff) { coeff = 0.0f; });
for_each(begin(expression_coefficients), end(expression_coefficients),
[](auto& coeff) { coeff = 0.0f; });
display_identity_model_only = false;
}
ImGui::Separator();
if (ImGui::Button("Random face sample", ImVec2(-1, 0)))
{
// Shape sample:
std::normal_distribution<float> shape_coeffs_dist(0.0f,
random_sample_sdev[0]); // c'tor takes stddev
shape_coefficients =
vector<float>(morphable_model.get_shape_model().get_num_principal_components());
for_each(begin(shape_coefficients), end(shape_coefficients),
[&rng, &shape_coeffs_dist](auto& coeff) { coeff = shape_coeffs_dist(rng); });
// Expression sample:
if (morphable_model.has_separate_expression_model())
{
if (eos::cpp17::holds_alternative<morphablemodel::Blendshapes>(
morphable_model.get_expression_model().value()))
{
std::uniform_real_distribution<float> expression_coeffs_dist(
0.0f,
random_sample_sdev[1]); // using the interval [0, sdev] (so it's not really an sdev
// here!)
const auto expression_model_num_coeffs =
eos::cpp17::get<morphablemodel::Blendshapes>(
morphable_model.get_expression_model().value())
.size();
expression_coefficients = vector<float>(expression_model_num_coeffs);
for_each(begin(expression_coefficients), end(expression_coefficients),
[&rng, &expression_coeffs_dist](auto& coeff) {
coeff = expression_coeffs_dist(rng);
});
} else if (eos::cpp17::holds_alternative<morphablemodel::PcaModel>(
morphable_model.get_expression_model().value()))
{
std::normal_distribution<float> expression_coeffs_dist(0.0f, random_sample_sdev[1]);
const auto expression_model_num_coeffs =
eos::cpp17::get<morphablemodel::PcaModel>(
morphable_model.get_expression_model().value())
.get_num_principal_components();
expression_coefficients = vector<float>(expression_model_num_coeffs);
for_each(begin(expression_coefficients), end(expression_coefficients),
[&rng, &expression_coeffs_dist](auto& coeff) {
coeff = expression_coeffs_dist(rng);
});
}
}
// Colour sample:
std::normal_distribution<float> color_coeffs_dist(0.0f, random_sample_sdev[2]);
color_coefficients =
vector<float>(morphable_model.get_color_model().get_num_principal_components());
for_each(begin(color_coefficients), end(color_coefficients),
[&rng, &color_coeffs_dist](auto& coeff) { coeff = color_coeffs_dist(rng); });
// Now generate the sample:
core::Mesh sample;
// Note: Can it happen that we pass in colour-coeffs, but it's a model without colour?
if (morphable_model.has_separate_expression_model())
{
sample = morphable_model.draw_sample(shape_coefficients, expression_coefficients,
color_coefficients);
} else
{
sample = morphable_model.draw_sample(shape_coefficients, color_coefficients);
}
viewer.data().set_vertices(get_V(sample));
if (!sample.colors.empty())
{
viewer.data().set_colors(get_C(sample));
}
}
/* // Not yet implemented:
if (ImGui::Button("Random identity sample", ImVec2(-1, 0)))
{
}
if (ImGui::Button("Random expression sample", ImVec2(-1, 0)))
{
}
if (ImGui::Button("Random color sample", ImVec2(-1, 0)))
{
}
*/
ImGui::InputFloat3("sdev [shp, exp, col]", &random_sample_sdev[0], 2);
ImGui::Checkbox("Identity model only", &display_identity_model_only);
ImGui::End(); // end "Morphable Model" window
// PCA shape coefficients:
ImGui::SetNextWindowPos(ImVec2(180.f * menu.menu_scaling(), 0), ImGuiSetCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(200, 160), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Shape PCA", nullptr, ImGuiWindowFlags_NoSavedSettings);
ImGui::Text("Coefficients");
if (morphable_model.get_shape_model().get_num_principal_components() > 0) // a model was loaded
{
int num_shape_coeffs_to_display =
std::min(morphable_model.get_shape_model().get_num_principal_components(), 30);
if (shape_coefficients.empty() || shape_coefficients.size() != num_shape_coeffs_to_display)
{
// no coeffs yet, or number of coeffs has changed for some reason:
shape_coefficients.resize(num_shape_coeffs_to_display);
}
// shape_coefficients are always initialised now.
ImGui::BeginGroup();
for (int i = 0; i < num_shape_coeffs_to_display; ++i)
{
const string label = std::to_string(i);
ImGui::SliderFloat(label.c_str(), &shape_coefficients[i], -3.0, 3.0);
}
ImGui::EndGroup();
string coeffs_displayed =
"Displaying " + std::to_string(num_shape_coeffs_to_display) + "/" +
std::to_string(morphable_model.get_shape_model().get_num_principal_components()) +
" coefficients.";
ImGui::Text(coeffs_displayed.c_str());
// We've got a shape model. So update the mesh that's been drawn with the value of the
// coefficients. Note that we are currently doing this every draw call, not only when the
// slider changes. See eos-model-viewer/issues/5.
VectorXf shape_instance = morphable_model.get_shape_model().draw_sample(shape_coefficients);
const auto num_vertices = morphable_model.get_shape_model().get_data_dimension() / 3;
// If expression coeffs are set, add the expression part:
if (!expression_coefficients.empty() && morphable_model.has_separate_expression_model() &&
!display_identity_model_only)
{
if (eos::cpp17::holds_alternative<morphablemodel::PcaModel>(
morphable_model.get_expression_model().value()))
{
const auto& expression_model = eos::cpp17::get<morphablemodel::PcaModel>(
morphable_model.get_expression_model().value());
const VectorXf expression_instance =
expression_model.draw_sample(expression_coefficients);
shape_instance += expression_instance;
} else if (eos::cpp17::holds_alternative<morphablemodel::Blendshapes>(
morphable_model.get_expression_model().value()))
{
const auto& blendshapes = eos::cpp17::get<morphablemodel::Blendshapes>(
morphable_model.get_expression_model().value());
for (int i = 0; i < blendshapes.size(); ++i)
{
shape_instance += blendshapes[i].deformation * expression_coefficients[i];
}
}
}
Eigen::Map<Eigen::MatrixXf> shape_instance_reshaped(
shape_instance.data(), 3, num_vertices); // Take 3 at a piece, then transpose below
viewer.data().set_vertices(shape_instance_reshaped.transpose().cast<double>());
}
ImGui::End(); // end "Shape PCA" window
// PCA colour coefficients:
ImGui::SetNextWindowPos(ImVec2(380.f * menu.menu_scaling(), 0), ImGuiSetCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(200, 160), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Colour PCA", nullptr, ImGuiWindowFlags_NoSavedSettings);
ImGui::Text("Coefficients");
if (morphable_model.get_color_model().get_num_principal_components() > 0) // a model was loaded
{
int num_color_coeffs_to_display =
std::min(morphable_model.get_color_model().get_num_principal_components(), 30);
if (color_coefficients.empty() || color_coefficients.size() != num_color_coeffs_to_display)
{
color_coefficients.resize(num_color_coeffs_to_display);
}
// color_coefficients are always initialised now.
ImGui::BeginGroup();
for (int i = 0; i < num_color_coeffs_to_display; ++i)
{
const string label = std::to_string(i);
ImGui::SliderFloat(label.c_str(), &color_coefficients[i], -3.0, 3.0);
}
ImGui::EndGroup();
string coeffs_displayed =
"Displaying " + std::to_string(num_color_coeffs_to_display) + "/" +
std::to_string(morphable_model.get_color_model().get_num_principal_components()) +
" coefficients.";
ImGui::Text(coeffs_displayed.c_str());
// We've got a colour model. So update the mesh that's been drawn with the value of the
// coefficients. Note that we are currently doing this every draw call, not only when the
// slider changes. See eos-model-viewer/issues/5.
VectorXf color_instance = morphable_model.get_color_model().draw_sample(color_coefficients);
const auto num_vertices = morphable_model.get_color_model().get_data_dimension() /
3; // will break for gray-level models!
Eigen::Map<Eigen::MatrixXf> color_instance_reshaped(
color_instance.data(), 3, num_vertices); // Take 3 at a piece, then transpose below
viewer.data().set_colors(color_instance_reshaped.transpose().cast<double>());
}
ImGui::End(); // end "Colour PCA" window
// PCA expression coefficients:
ImGui::SetNextWindowPos(ImVec2(580.f * menu.menu_scaling(), 0), ImGuiSetCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(200, 160), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Expression PCA", nullptr, ImGuiWindowFlags_NoSavedSettings);
ImGui::Text("Coefficients");
if (morphable_model.has_separate_expression_model()) // a model was loaded
{
int expression_model_num_coeffs = 0;
float slider_min_range = -3.0f;
float slider_max_range = +3.0f;
if (eos::cpp17::holds_alternative<morphablemodel::Blendshapes>(
morphable_model.get_expression_model().value()))
{
expression_model_num_coeffs = eos::cpp17::get<morphablemodel::Blendshapes>(
morphable_model.get_expression_model().value())
.size();
slider_min_range = -1.0f;
} else if (eos::cpp17::holds_alternative<morphablemodel::PcaModel>(
morphable_model.get_expression_model().value()))
{
expression_model_num_coeffs =
eos::cpp17::get<morphablemodel::PcaModel>(morphable_model.get_expression_model().value())
.get_num_principal_components();
}
int num_expression_coeffs_to_display = std::min(expression_model_num_coeffs, 30);
if (expression_coefficients.empty() ||
expression_coefficients.size() != num_expression_coeffs_to_display)
{
expression_coefficients.resize(num_expression_coeffs_to_display);
}
// expression_coefficients are always initialised now.
ImGui::BeginGroup();
for (int i = 0; i < num_expression_coeffs_to_display; ++i)
{
const string label = std::to_string(i);
ImGui::SliderFloat(label.c_str(), &expression_coefficients[i], slider_min_range,
slider_max_range);
}
ImGui::EndGroup();
string coeffs_displayed = "Displaying " + std::to_string(num_expression_coeffs_to_display) + "/" +
std::to_string(expression_model_num_coeffs) + " coefficients.";
ImGui::Text(coeffs_displayed.c_str());
// We're not updating the mesh here. The identity-update above already updates it, since we update
// in each frame, and not just when a slider has moved. As long as we always have an identity
// model, this is fine.
}
ImGui::End(); // end "Expression PCA" window
};
viewer.launch();
return EXIT_SUCCESS;
}
================================================
FILE: initial_cache.cmake.template
================================================
# Mechanism via FindLIB.cmake
# ==============================
# Boost:
# -------
# Windows: Download the pre-built binaries from http://sourceforge.net/projects/boost/files/boost-binaries/ for VS2015 (msvc-14 64bit).
# Either set the windows PATH variable to "<YOUR_BOOST_DIRECTORY>\lib64-msvc-14.0" and CMake will find it, or, set:
#set(BOOST_ROOT "C:/boost" CACHE PATH "Boost search location" FORCE)
# Linux: Boost can usually be installed via a package manager (e.g. apt-get install boost-all-dev) and this variable can be left uncommented.
#set(BOOST_ROOT "/home/user/boost/install" CACHE PATH "Boost search location" FORCE)
# Mechanism via ConfigLIB.cmake in 3rd party library directory
# ==============================
# OpenCV:
# -------
# Windows: Download the package from opencv.org, use 2.4.7.2 or never. It includes binaries for VS2013. Set this path accordingly.
#set(OpenCV_DIR "C:/opencv/install" CACHE PATH "Location of OpenCVConfig.cmake" FORCE)
# Linux: Usually can be left blank but it can be used if OpenCV is not found.
#set(OpenCV_DIR "/home/user/opencv/install/share/OpenCV" CACHE PATH "Location of OpenCVConfig.cmake" FORCE)
gitextract_ir1lx7s3/ ├── .clang-format ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake/ │ └── FindLIBIGL.cmake ├── cxxopts.hpp ├── eos-model-viewer.cpp └── initial_cache.cmake.template
SYMBOL INDEX (142 symbols across 2 files)
FILE: cxxopts.hpp
type cxxopts (line 46) | namespace cxxopts
function String (line 66) | inline
class UnicodeStringIterator (line 73) | class UnicodeStringIterator : public
method UnicodeStringIterator (line 78) | UnicodeStringIterator(const icu::UnicodeString* string, int32_t pos)
method value_type (line 84) | value_type
method UnicodeStringIterator (line 102) | UnicodeStringIterator&
method UnicodeStringIterator (line 109) | UnicodeStringIterator
function String (line 120) | inline
function String (line 127) | inline
function String (line 140) | String&
function stringLength (line 152) | inline
function toUTF8String (line 159) | inline
function empty (line 169) | inline
function T (line 202) | T
function stringLength (line 208) | inline
function String (line 215) | inline
function String (line 222) | inline
function String (line 230) | String&
function toUTF8String (line 237) | std::string
function empty (line 243) | inline
class Value (line 267) | class Value : public std::enable_shared_from_this<Value>
class OptionException (line 308) | class OptionException : public std::exception
method OptionException (line 311) | OptionException(const std::string& message)
class OptionSpecException (line 326) | class OptionSpecException : public OptionException
method OptionSpecException (line 330) | OptionSpecException(const std::string& message)
class OptionParseException (line 336) | class OptionParseException : public OptionException
method OptionParseException (line 339) | OptionParseException(const std::string& message)
class option_exists_error (line 345) | class option_exists_error : public OptionSpecException
method option_exists_error (line 348) | option_exists_error(const std::string& option)
class invalid_option_format_error (line 354) | class invalid_option_format_error : public OptionSpecException
method invalid_option_format_error (line 357) | invalid_option_format_error(const std::string& format)
class option_not_exists_exception (line 363) | class option_not_exists_exception : public OptionParseException
method option_not_exists_exception (line 366) | option_not_exists_exception(const std::string& option)
class missing_argument_exception (line 372) | class missing_argument_exception : public OptionParseException
method missing_argument_exception (line 375) | missing_argument_exception(const std::string& option)
class option_requires_argument_exception (line 383) | class option_requires_argument_exception : public OptionParseException
method option_requires_argument_exception (line 386) | option_requires_argument_exception(const std::string& option)
class option_not_has_argument_exception (line 394) | class option_not_has_argument_exception : public OptionParseException
method option_not_has_argument_exception (line 397) | option_not_has_argument_exception
class option_not_present_exception (line 411) | class option_not_present_exception : public OptionParseException
method option_not_present_exception (line 414) | option_not_present_exception(const std::string& option)
class argument_incorrect_type (line 420) | class argument_incorrect_type : public OptionParseException
method argument_incorrect_type (line 423) | argument_incorrect_type
class option_required_exception (line 434) | class option_required_exception : public OptionParseException
method option_required_exception (line 437) | option_required_exception(const std::string& option)
type values (line 445) | namespace values
type detail (line 457) | namespace detail
type SignedCheck (line 460) | struct SignedCheck
type SignedCheck<T, true> (line 463) | struct SignedCheck<T, true>
type SignedCheck<T, false> (line 487) | struct SignedCheck<T, false>
function check_signed_range (line 495) | void
function R (line 503) | R
function T (line 513) | T
function integer_parser (line 520) | void
function stringstream_parser (line 592) | void stringstream_parser(const std::string& text, T& value)
function parse_value (line 601) | inline
function parse_value (line 608) | inline
function parse_value (line 615) | inline
function parse_value (line 622) | inline
function parse_value (line 629) | inline
function parse_value (line 636) | inline
function parse_value (line 643) | inline
function parse_value (line 650) | inline
function parse_value (line 657) | inline
function parse_value (line 680) | inline
function parse_value (line 691) | void
function parse_value (line 697) | void
function parse_value (line 707) | void
type type_is_container (line 717) | struct type_is_container
type type_is_container<std::vector<T>> (line 723) | struct type_is_container<std::vector<T>>
class abstract_value (line 729) | class abstract_value : public Value
method abstract_value (line 734) | abstract_value()
method abstract_value (line 740) | abstract_value(T* t)
method abstract_value (line 747) | abstract_value(const abstract_value& rhs)
method parse (line 765) | void
method is_container (line 771) | bool
method parse (line 777) | void
method has_default (line 783) | bool
method has_implicit (line 789) | bool
method default_value (line 795) | std::shared_ptr<Value>
method implicit_value (line 803) | std::shared_ptr<Value>
method get_default_value (line 811) | std::string
method get_implicit_value (line 817) | std::string
method is_boolean (line 823) | bool
method T (line 829) | const T&
class standard_value (line 854) | class standard_value : public abstract_value<T>
method clone (line 859) | std::shared_ptr<Value>
class standard_value<bool> (line 867) | class standard_value<bool> : public abstract_value<bool>
method standard_value (line 872) | standard_value()
method standard_value (line 877) | standard_value(bool* b)
method clone (line 883) | std::shared_ptr<Value>
method set_default_and_implicit (line 891) | void
function value (line 903) | std::shared_ptr<Value>
function value (line 910) | std::shared_ptr<Value>
class OptionAdder (line 916) | class OptionAdder
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
class OptionDetails (line 918) | class OptionDetails
method OptionDetails (line 921) | OptionDetails
method OptionDetails (line 936) | OptionDetails(const OptionDetails& rhs)
method OptionDetails (line 943) | OptionDetails(OptionDetails&& rhs) = default;
method String (line 945) | const String&
method Value (line 951) | const Value& value() const {
method make_storage (line 955) | std::shared_ptr<Value>
type HelpOptionDetails (line 981) | struct HelpOptionDetails
type HelpGroupDetails (line 995) | struct HelpGroupDetails
class OptionValue (line 1002) | class OptionValue
method parse (line 1005) | void
method parse_default (line 1017) | void
method count (line 1024) | size_t
method T (line 1031) | const T&
method ensure_value (line 1042) | void
class KeyValue (line 1055) | class KeyValue
method KeyValue (line 1058) | KeyValue(std::string key_, std::string value_)
method value (line 1071) | const std::string
method T (line 1078) | T
class ParseResult (line 1091) | class ParseResult
method count (line 1100) | size_t
method OptionValue (line 1114) | const OptionValue&
class Options (line 1180) | class Options
method Options (line 1184) | Options(std::string program, std::string help_string = "")
method Options (line 1194) | Options&
method Options (line 1201) | Options&
method Options (line 1208) | Options&
class OptionAdder (line 1288) | class OptionAdder
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function String (line 1323) | String
function String (line 1365) | String
function OptionAdder (line 1443) | inline
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function OptionAdder (line 1450) | inline
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function ParseResult (line 1640) | inline
method count (line 1100) | size_t
method OptionValue (line 1114) | const OptionValue&
function String (line 1839) | inline
function HelpGroupDetails (line 1996) | inline
type cxxopts (line 62) | namespace cxxopts
function String (line 66) | inline
class UnicodeStringIterator (line 73) | class UnicodeStringIterator : public
method UnicodeStringIterator (line 78) | UnicodeStringIterator(const icu::UnicodeString* string, int32_t pos)
method value_type (line 84) | value_type
method UnicodeStringIterator (line 102) | UnicodeStringIterator&
method UnicodeStringIterator (line 109) | UnicodeStringIterator
function String (line 120) | inline
function String (line 127) | inline
function String (line 140) | String&
function stringLength (line 152) | inline
function toUTF8String (line 159) | inline
function empty (line 169) | inline
function T (line 202) | T
function stringLength (line 208) | inline
function String (line 215) | inline
function String (line 222) | inline
function String (line 230) | String&
function toUTF8String (line 237) | std::string
function empty (line 243) | inline
class Value (line 267) | class Value : public std::enable_shared_from_this<Value>
class OptionException (line 308) | class OptionException : public std::exception
method OptionException (line 311) | OptionException(const std::string& message)
class OptionSpecException (line 326) | class OptionSpecException : public OptionException
method OptionSpecException (line 330) | OptionSpecException(const std::string& message)
class OptionParseException (line 336) | class OptionParseException : public OptionException
method OptionParseException (line 339) | OptionParseException(const std::string& message)
class option_exists_error (line 345) | class option_exists_error : public OptionSpecException
method option_exists_error (line 348) | option_exists_error(const std::string& option)
class invalid_option_format_error (line 354) | class invalid_option_format_error : public OptionSpecException
method invalid_option_format_error (line 357) | invalid_option_format_error(const std::string& format)
class option_not_exists_exception (line 363) | class option_not_exists_exception : public OptionParseException
method option_not_exists_exception (line 366) | option_not_exists_exception(const std::string& option)
class missing_argument_exception (line 372) | class missing_argument_exception : public OptionParseException
method missing_argument_exception (line 375) | missing_argument_exception(const std::string& option)
class option_requires_argument_exception (line 383) | class option_requires_argument_exception : public OptionParseException
method option_requires_argument_exception (line 386) | option_requires_argument_exception(const std::string& option)
class option_not_has_argument_exception (line 394) | class option_not_has_argument_exception : public OptionParseException
method option_not_has_argument_exception (line 397) | option_not_has_argument_exception
class option_not_present_exception (line 411) | class option_not_present_exception : public OptionParseException
method option_not_present_exception (line 414) | option_not_present_exception(const std::string& option)
class argument_incorrect_type (line 420) | class argument_incorrect_type : public OptionParseException
method argument_incorrect_type (line 423) | argument_incorrect_type
class option_required_exception (line 434) | class option_required_exception : public OptionParseException
method option_required_exception (line 437) | option_required_exception(const std::string& option)
type values (line 445) | namespace values
type detail (line 457) | namespace detail
type SignedCheck (line 460) | struct SignedCheck
type SignedCheck<T, true> (line 463) | struct SignedCheck<T, true>
type SignedCheck<T, false> (line 487) | struct SignedCheck<T, false>
function check_signed_range (line 495) | void
function R (line 503) | R
function T (line 513) | T
function integer_parser (line 520) | void
function stringstream_parser (line 592) | void stringstream_parser(const std::string& text, T& value)
function parse_value (line 601) | inline
function parse_value (line 608) | inline
function parse_value (line 615) | inline
function parse_value (line 622) | inline
function parse_value (line 629) | inline
function parse_value (line 636) | inline
function parse_value (line 643) | inline
function parse_value (line 650) | inline
function parse_value (line 657) | inline
function parse_value (line 680) | inline
function parse_value (line 691) | void
function parse_value (line 697) | void
function parse_value (line 707) | void
type type_is_container (line 717) | struct type_is_container
type type_is_container<std::vector<T>> (line 723) | struct type_is_container<std::vector<T>>
class abstract_value (line 729) | class abstract_value : public Value
method abstract_value (line 734) | abstract_value()
method abstract_value (line 740) | abstract_value(T* t)
method abstract_value (line 747) | abstract_value(const abstract_value& rhs)
method parse (line 765) | void
method is_container (line 771) | bool
method parse (line 777) | void
method has_default (line 783) | bool
method has_implicit (line 789) | bool
method default_value (line 795) | std::shared_ptr<Value>
method implicit_value (line 803) | std::shared_ptr<Value>
method get_default_value (line 811) | std::string
method get_implicit_value (line 817) | std::string
method is_boolean (line 823) | bool
method T (line 829) | const T&
class standard_value (line 854) | class standard_value : public abstract_value<T>
method clone (line 859) | std::shared_ptr<Value>
class standard_value<bool> (line 867) | class standard_value<bool> : public abstract_value<bool>
method standard_value (line 872) | standard_value()
method standard_value (line 877) | standard_value(bool* b)
method clone (line 883) | std::shared_ptr<Value>
method set_default_and_implicit (line 891) | void
function value (line 903) | std::shared_ptr<Value>
function value (line 910) | std::shared_ptr<Value>
class OptionAdder (line 916) | class OptionAdder
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
class OptionDetails (line 918) | class OptionDetails
method OptionDetails (line 921) | OptionDetails
method OptionDetails (line 936) | OptionDetails(const OptionDetails& rhs)
method OptionDetails (line 943) | OptionDetails(OptionDetails&& rhs) = default;
method String (line 945) | const String&
method Value (line 951) | const Value& value() const {
method make_storage (line 955) | std::shared_ptr<Value>
type HelpOptionDetails (line 981) | struct HelpOptionDetails
type HelpGroupDetails (line 995) | struct HelpGroupDetails
class OptionValue (line 1002) | class OptionValue
method parse (line 1005) | void
method parse_default (line 1017) | void
method count (line 1024) | size_t
method T (line 1031) | const T&
method ensure_value (line 1042) | void
class KeyValue (line 1055) | class KeyValue
method KeyValue (line 1058) | KeyValue(std::string key_, std::string value_)
method value (line 1071) | const std::string
method T (line 1078) | T
class ParseResult (line 1091) | class ParseResult
method count (line 1100) | size_t
method OptionValue (line 1114) | const OptionValue&
class Options (line 1180) | class Options
method Options (line 1184) | Options(std::string program, std::string help_string = "")
method Options (line 1194) | Options&
method Options (line 1201) | Options&
method Options (line 1208) | Options&
class OptionAdder (line 1288) | class OptionAdder
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function String (line 1323) | String
function String (line 1365) | String
function OptionAdder (line 1443) | inline
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function OptionAdder (line 1450) | inline
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function ParseResult (line 1640) | inline
method count (line 1100) | size_t
method OptionValue (line 1114) | const OptionValue&
function String (line 1839) | inline
function HelpGroupDetails (line 1996) | inline
type std (line 177) | namespace std
function begin (line 179) | inline
function end (line 186) | inline
type cxxopts (line 197) | namespace cxxopts
function String (line 66) | inline
class UnicodeStringIterator (line 73) | class UnicodeStringIterator : public
method UnicodeStringIterator (line 78) | UnicodeStringIterator(const icu::UnicodeString* string, int32_t pos)
method value_type (line 84) | value_type
method UnicodeStringIterator (line 102) | UnicodeStringIterator&
method UnicodeStringIterator (line 109) | UnicodeStringIterator
function String (line 120) | inline
function String (line 127) | inline
function String (line 140) | String&
function stringLength (line 152) | inline
function toUTF8String (line 159) | inline
function empty (line 169) | inline
function T (line 202) | T
function stringLength (line 208) | inline
function String (line 215) | inline
function String (line 222) | inline
function String (line 230) | String&
function toUTF8String (line 237) | std::string
function empty (line 243) | inline
class Value (line 267) | class Value : public std::enable_shared_from_this<Value>
class OptionException (line 308) | class OptionException : public std::exception
method OptionException (line 311) | OptionException(const std::string& message)
class OptionSpecException (line 326) | class OptionSpecException : public OptionException
method OptionSpecException (line 330) | OptionSpecException(const std::string& message)
class OptionParseException (line 336) | class OptionParseException : public OptionException
method OptionParseException (line 339) | OptionParseException(const std::string& message)
class option_exists_error (line 345) | class option_exists_error : public OptionSpecException
method option_exists_error (line 348) | option_exists_error(const std::string& option)
class invalid_option_format_error (line 354) | class invalid_option_format_error : public OptionSpecException
method invalid_option_format_error (line 357) | invalid_option_format_error(const std::string& format)
class option_not_exists_exception (line 363) | class option_not_exists_exception : public OptionParseException
method option_not_exists_exception (line 366) | option_not_exists_exception(const std::string& option)
class missing_argument_exception (line 372) | class missing_argument_exception : public OptionParseException
method missing_argument_exception (line 375) | missing_argument_exception(const std::string& option)
class option_requires_argument_exception (line 383) | class option_requires_argument_exception : public OptionParseException
method option_requires_argument_exception (line 386) | option_requires_argument_exception(const std::string& option)
class option_not_has_argument_exception (line 394) | class option_not_has_argument_exception : public OptionParseException
method option_not_has_argument_exception (line 397) | option_not_has_argument_exception
class option_not_present_exception (line 411) | class option_not_present_exception : public OptionParseException
method option_not_present_exception (line 414) | option_not_present_exception(const std::string& option)
class argument_incorrect_type (line 420) | class argument_incorrect_type : public OptionParseException
method argument_incorrect_type (line 423) | argument_incorrect_type
class option_required_exception (line 434) | class option_required_exception : public OptionParseException
method option_required_exception (line 437) | option_required_exception(const std::string& option)
type values (line 445) | namespace values
type detail (line 457) | namespace detail
type SignedCheck (line 460) | struct SignedCheck
type SignedCheck<T, true> (line 463) | struct SignedCheck<T, true>
type SignedCheck<T, false> (line 487) | struct SignedCheck<T, false>
function check_signed_range (line 495) | void
function R (line 503) | R
function T (line 513) | T
function integer_parser (line 520) | void
function stringstream_parser (line 592) | void stringstream_parser(const std::string& text, T& value)
function parse_value (line 601) | inline
function parse_value (line 608) | inline
function parse_value (line 615) | inline
function parse_value (line 622) | inline
function parse_value (line 629) | inline
function parse_value (line 636) | inline
function parse_value (line 643) | inline
function parse_value (line 650) | inline
function parse_value (line 657) | inline
function parse_value (line 680) | inline
function parse_value (line 691) | void
function parse_value (line 697) | void
function parse_value (line 707) | void
type type_is_container (line 717) | struct type_is_container
type type_is_container<std::vector<T>> (line 723) | struct type_is_container<std::vector<T>>
class abstract_value (line 729) | class abstract_value : public Value
method abstract_value (line 734) | abstract_value()
method abstract_value (line 740) | abstract_value(T* t)
method abstract_value (line 747) | abstract_value(const abstract_value& rhs)
method parse (line 765) | void
method is_container (line 771) | bool
method parse (line 777) | void
method has_default (line 783) | bool
method has_implicit (line 789) | bool
method default_value (line 795) | std::shared_ptr<Value>
method implicit_value (line 803) | std::shared_ptr<Value>
method get_default_value (line 811) | std::string
method get_implicit_value (line 817) | std::string
method is_boolean (line 823) | bool
method T (line 829) | const T&
class standard_value (line 854) | class standard_value : public abstract_value<T>
method clone (line 859) | std::shared_ptr<Value>
class standard_value<bool> (line 867) | class standard_value<bool> : public abstract_value<bool>
method standard_value (line 872) | standard_value()
method standard_value (line 877) | standard_value(bool* b)
method clone (line 883) | std::shared_ptr<Value>
method set_default_and_implicit (line 891) | void
function value (line 903) | std::shared_ptr<Value>
function value (line 910) | std::shared_ptr<Value>
class OptionAdder (line 916) | class OptionAdder
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
class OptionDetails (line 918) | class OptionDetails
method OptionDetails (line 921) | OptionDetails
method OptionDetails (line 936) | OptionDetails(const OptionDetails& rhs)
method OptionDetails (line 943) | OptionDetails(OptionDetails&& rhs) = default;
method String (line 945) | const String&
method Value (line 951) | const Value& value() const {
method make_storage (line 955) | std::shared_ptr<Value>
type HelpOptionDetails (line 981) | struct HelpOptionDetails
type HelpGroupDetails (line 995) | struct HelpGroupDetails
class OptionValue (line 1002) | class OptionValue
method parse (line 1005) | void
method parse_default (line 1017) | void
method count (line 1024) | size_t
method T (line 1031) | const T&
method ensure_value (line 1042) | void
class KeyValue (line 1055) | class KeyValue
method KeyValue (line 1058) | KeyValue(std::string key_, std::string value_)
method value (line 1071) | const std::string
method T (line 1078) | T
class ParseResult (line 1091) | class ParseResult
method count (line 1100) | size_t
method OptionValue (line 1114) | const OptionValue&
class Options (line 1180) | class Options
method Options (line 1184) | Options(std::string program, std::string help_string = "")
method Options (line 1194) | Options&
method Options (line 1201) | Options&
method Options (line 1208) | Options&
class OptionAdder (line 1288) | class OptionAdder
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function String (line 1323) | String
function String (line 1365) | String
function OptionAdder (line 1443) | inline
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function OptionAdder (line 1450) | inline
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function ParseResult (line 1640) | inline
method count (line 1100) | size_t
method OptionValue (line 1114) | const OptionValue&
function String (line 1839) | inline
function HelpGroupDetails (line 1996) | inline
type cxxopts (line 254) | namespace cxxopts
function String (line 66) | inline
class UnicodeStringIterator (line 73) | class UnicodeStringIterator : public
method UnicodeStringIterator (line 78) | UnicodeStringIterator(const icu::UnicodeString* string, int32_t pos)
method value_type (line 84) | value_type
method UnicodeStringIterator (line 102) | UnicodeStringIterator&
method UnicodeStringIterator (line 109) | UnicodeStringIterator
function String (line 120) | inline
function String (line 127) | inline
function String (line 140) | String&
function stringLength (line 152) | inline
function toUTF8String (line 159) | inline
function empty (line 169) | inline
function T (line 202) | T
function stringLength (line 208) | inline
function String (line 215) | inline
function String (line 222) | inline
function String (line 230) | String&
function toUTF8String (line 237) | std::string
function empty (line 243) | inline
class Value (line 267) | class Value : public std::enable_shared_from_this<Value>
class OptionException (line 308) | class OptionException : public std::exception
method OptionException (line 311) | OptionException(const std::string& message)
class OptionSpecException (line 326) | class OptionSpecException : public OptionException
method OptionSpecException (line 330) | OptionSpecException(const std::string& message)
class OptionParseException (line 336) | class OptionParseException : public OptionException
method OptionParseException (line 339) | OptionParseException(const std::string& message)
class option_exists_error (line 345) | class option_exists_error : public OptionSpecException
method option_exists_error (line 348) | option_exists_error(const std::string& option)
class invalid_option_format_error (line 354) | class invalid_option_format_error : public OptionSpecException
method invalid_option_format_error (line 357) | invalid_option_format_error(const std::string& format)
class option_not_exists_exception (line 363) | class option_not_exists_exception : public OptionParseException
method option_not_exists_exception (line 366) | option_not_exists_exception(const std::string& option)
class missing_argument_exception (line 372) | class missing_argument_exception : public OptionParseException
method missing_argument_exception (line 375) | missing_argument_exception(const std::string& option)
class option_requires_argument_exception (line 383) | class option_requires_argument_exception : public OptionParseException
method option_requires_argument_exception (line 386) | option_requires_argument_exception(const std::string& option)
class option_not_has_argument_exception (line 394) | class option_not_has_argument_exception : public OptionParseException
method option_not_has_argument_exception (line 397) | option_not_has_argument_exception
class option_not_present_exception (line 411) | class option_not_present_exception : public OptionParseException
method option_not_present_exception (line 414) | option_not_present_exception(const std::string& option)
class argument_incorrect_type (line 420) | class argument_incorrect_type : public OptionParseException
method argument_incorrect_type (line 423) | argument_incorrect_type
class option_required_exception (line 434) | class option_required_exception : public OptionParseException
method option_required_exception (line 437) | option_required_exception(const std::string& option)
type values (line 445) | namespace values
type detail (line 457) | namespace detail
type SignedCheck (line 460) | struct SignedCheck
type SignedCheck<T, true> (line 463) | struct SignedCheck<T, true>
type SignedCheck<T, false> (line 487) | struct SignedCheck<T, false>
function check_signed_range (line 495) | void
function R (line 503) | R
function T (line 513) | T
function integer_parser (line 520) | void
function stringstream_parser (line 592) | void stringstream_parser(const std::string& text, T& value)
function parse_value (line 601) | inline
function parse_value (line 608) | inline
function parse_value (line 615) | inline
function parse_value (line 622) | inline
function parse_value (line 629) | inline
function parse_value (line 636) | inline
function parse_value (line 643) | inline
function parse_value (line 650) | inline
function parse_value (line 657) | inline
function parse_value (line 680) | inline
function parse_value (line 691) | void
function parse_value (line 697) | void
function parse_value (line 707) | void
type type_is_container (line 717) | struct type_is_container
type type_is_container<std::vector<T>> (line 723) | struct type_is_container<std::vector<T>>
class abstract_value (line 729) | class abstract_value : public Value
method abstract_value (line 734) | abstract_value()
method abstract_value (line 740) | abstract_value(T* t)
method abstract_value (line 747) | abstract_value(const abstract_value& rhs)
method parse (line 765) | void
method is_container (line 771) | bool
method parse (line 777) | void
method has_default (line 783) | bool
method has_implicit (line 789) | bool
method default_value (line 795) | std::shared_ptr<Value>
method implicit_value (line 803) | std::shared_ptr<Value>
method get_default_value (line 811) | std::string
method get_implicit_value (line 817) | std::string
method is_boolean (line 823) | bool
method T (line 829) | const T&
class standard_value (line 854) | class standard_value : public abstract_value<T>
method clone (line 859) | std::shared_ptr<Value>
class standard_value<bool> (line 867) | class standard_value<bool> : public abstract_value<bool>
method standard_value (line 872) | standard_value()
method standard_value (line 877) | standard_value(bool* b)
method clone (line 883) | std::shared_ptr<Value>
method set_default_and_implicit (line 891) | void
function value (line 903) | std::shared_ptr<Value>
function value (line 910) | std::shared_ptr<Value>
class OptionAdder (line 916) | class OptionAdder
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
class OptionDetails (line 918) | class OptionDetails
method OptionDetails (line 921) | OptionDetails
method OptionDetails (line 936) | OptionDetails(const OptionDetails& rhs)
method OptionDetails (line 943) | OptionDetails(OptionDetails&& rhs) = default;
method String (line 945) | const String&
method Value (line 951) | const Value& value() const {
method make_storage (line 955) | std::shared_ptr<Value>
type HelpOptionDetails (line 981) | struct HelpOptionDetails
type HelpGroupDetails (line 995) | struct HelpGroupDetails
class OptionValue (line 1002) | class OptionValue
method parse (line 1005) | void
method parse_default (line 1017) | void
method count (line 1024) | size_t
method T (line 1031) | const T&
method ensure_value (line 1042) | void
class KeyValue (line 1055) | class KeyValue
method KeyValue (line 1058) | KeyValue(std::string key_, std::string value_)
method value (line 1071) | const std::string
method T (line 1078) | T
class ParseResult (line 1091) | class ParseResult
method count (line 1100) | size_t
method OptionValue (line 1114) | const OptionValue&
class Options (line 1180) | class Options
method Options (line 1184) | Options(std::string program, std::string help_string = "")
method Options (line 1194) | Options&
method Options (line 1201) | Options&
method Options (line 1208) | Options&
class OptionAdder (line 1288) | class OptionAdder
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function String (line 1323) | String
function String (line 1365) | String
function OptionAdder (line 1443) | inline
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function OptionAdder (line 1450) | inline
method OptionAdder (line 1292) | OptionAdder(Options& options, std::string group)
function ParseResult (line 1640) | inline
method count (line 1100) | size_t
method OptionValue (line 1114) | const OptionValue&
function String (line 1839) | inline
function HelpGroupDetails (line 1996) | inline
FILE: eos-model-viewer.cpp
function to_string (line 40) | std::string to_string(const T a_value, const int n = 6)
function tokenize (line 49) | void tokenize(const std::string& str, ContainerType& tokens, const std::...
function load_bin_or_scm_model (line 73) | eos::morphablemodel::MorphableModel load_bin_or_scm_model(std::string mo...
function load_model (line 101) | eos::morphablemodel::MorphableModel load_model(std::string model_file, s...
function main (line 124) | int main(int argc, const char* argv[])
Condensed preview — 10 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (90K chars).
[
{
"path": ".clang-format",
"chars": 655,
"preview": "---\nBasedOnStyle: LLVM\nAccessModifierOffset: '-4'\nAlwaysBreakTemplateDeclarations: 'true'\nBreakBeforeBraces: Custom\nBrac"
},
{
"path": ".gitignore",
"chars": 86,
"preview": "# Ignore (optional) configuration files with user-specific paths:\ninitial_cache.cmake\n"
},
{
"path": ".gitmodules",
"chars": 192,
"preview": "[submodule \"external/eos\"]\n\tpath = external/eos\n\turl = https://github.com/patrikhuber/eos.git\n[submodule \"external/libig"
},
{
"path": "CMakeLists.txt",
"chars": 4452,
"preview": "cmake_minimum_required(VERSION 3.1.3)\nproject(eos-model-viewer)\nset(eos-model-viewer_VERSION 0.2.0.alpha)\n\nset_property("
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 1090,
"preview": "# eos-model-viewer\n3D model viewer for the eos Morphable Model library\n\nThis is a viewer that displays Morphable Models "
},
{
"path": "cmake/FindLIBIGL.cmake",
"chars": 1018,
"preview": "# - Try to find the LIBIGL library\n# Once done this will define\n#\n# LIBIGL_FOUND - system has LIBIGL\n# LIBIGL_INCLUDE_"
},
{
"path": "cxxopts.hpp",
"chars": 39945,
"preview": "/*\n\nCopyright (c) 2014, 2015, 2016, 2017 Jarryd Beck\n\nPermission is hereby granted, free of charge, to any person obtain"
},
{
"path": "eos-model-viewer.cpp",
"chars": 25784,
"preview": "/*\n * eos - A 3D Morphable Model fitting library written in modern C++11/14.\n *\n * File: eos-model-viewer.cpp\n *\n * Copy"
},
{
"path": "initial_cache.cmake.template",
"chars": 1152,
"preview": "# Mechanism via FindLIB.cmake\n# ==============================\n# Boost:\n# -------\n# Windows: Download the pre-built bina"
}
]
About this extraction
This page contains the full source code of the patrikhuber/eos-model-viewer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 10 files (83.7 KB), approximately 20.6k tokens, and a symbol index with 142 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.