### Install the library Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Standard installation command. ```shell sudo make install ``` -------------------------------- ### Install the library to a custom directory Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Installation command with a specified destination directory. ```shell sudo make install DESTDIR=/opt/mydir ``` -------------------------------- ### Python Example Source: https://github.com/nmwsharp/polyscope/blob/master/README.md Example of how to initialize Polyscope, register a point cloud and a surface mesh, add scalar and vector quantities, and display them in the UI using Python. ```python import polyscope as ps # Initialize polyscope ps.init() ### Register a point cloud # `my_points` is a Nx3 numpy array ps.register_point_cloud("my points", my_points) ### Register a mesh # `verts` is a Nx3 numpy array of vertex positions # `faces` is a Fx3 array of indices, or a nested list ps.register_surface_mesh("my mesh", verts, faces, smooth_shade=True) # Add a scalar function and a vector function defined on the mesh # vertex_scalar is a length V numpy array of values # face_vectors is an Fx3 array of vectors per face ps.get_surface_mesh("my mesh").add_scalar_quantity("my_scalar", vertex_scalar, defined_on='vertices', cmap='blues') ps.get_surface_mesh("my mesh").add_vector_quantity("my_vector", face_vectors, defined_on='faces', color=(0.2, 0.5, 0.5)) # View the point cloud and mesh we just registered in the 3D UI ps.show() ``` -------------------------------- ### Install Target and Headers Source: https://github.com/nmwsharp/polyscope/blob/master/src/CMakeLists.txt Installs the 'polyscope' library target and its associated header files to the specified installation prefix. ```cmake install(TARGETS polyscope) install(DIRECTORY ${INCLUDE_ROOT}/ DESTINATION "${CMAKE_INSTALL_PREFIX}/include/polyscope") ``` -------------------------------- ### C++ Example Source: https://github.com/nmwsharp/polyscope/blob/master/README.md Example of how to initialize Polyscope, register a point cloud and a surface mesh, add scalar and vector quantities, and display them in the UI using C++. ```C++ #include "polyscope/polyscope.h" #include "polyscope/point_cloud.h" #include "polyscope/surface_mesh.h" // Initialize polyscope polyscope::init(); // Register a point cloud // `points` is a Nx3 array-like container of points polyscope::registerPointCloud("my points", points); // Register a surface mesh structure // `meshVerts` is a Vx3 array-like container of vertex positions // `meshFaces` is a Fx3 array-like container of face indices polyscope::registerSurfaceMesh("my mesh", meshVerts, meshFaces); // Add a scalar and a vector function defined on the mesh // `scalarQuantity` is a length V array-like container of values // `vectorQuantity` is an Fx3 array-like container of vectors per face polyscope::getSurfaceMesh("my mesh")->addVertexScalarQuantity("my_scalar", scalarQuantity); polyscope::getSurfaceMesh("my mesh")->addFaceVectorQuantity("my_vector", vectorQuantity); // View the point cloud and mesh we just registered in the 3D UI polyscope::show(); ``` -------------------------------- ### Install man pages Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Commands to generate and install man pages. ```shell make doc/man sudo make installman ``` -------------------------------- ### Simple C++ example Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md A basic C++ program demonstrating the ArgumentParser, HelpFlag, and basic parsing with error handling. ```cpp #include #include int main(int argc, char **argv) { args::ArgumentParser parser("This is a test program.", "This goes after the options."); args::HelpFlag help(parser, "help", "Display this help menu", {'h', "help"}); try { parser.ParseCLI(argc, argv); } catch (args::Help) { std::cout << parser; return 0; } catch (args::ParseError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } return 0; } ``` -------------------------------- ### Dear ImGui Example Source: https://github.com/nmwsharp/polyscope/blob/master/deps/IconFontCppHeaders/README.md Demonstrates how to load and use Font Awesome icons within a Dear ImGui application. ```Cpp #include "IconsFontAwesome5.h" ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontDefault(); float baseFontSize = 13.0f; // 13.0f is the size of the default font. Change to the font size you use. float iconFontSize = baseFontSize * 2.0f / 3.0f; // FontAwesome fonts need to have their sizes reduced by 2.0f/3.0f in order to align correctly // merge in icons from Font Awesome static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_16_FA, 0 }; ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true; icons_config.GlyphMinAdvanceX = iconFontSize; io.Fonts->AddFontFromFileTTF( FONT_ICON_FILE_NAME_FAS, iconFontSize, &icons_config, icons_ranges ); // use FONT_ICON_FILE_NAME_FAR if you want regular instead of solid // in an imgui window somewhere... ImGui::Text( ICON_FA_PAINT_BRUSH " Paint" ); // use string literal concatenation // outputs a paint brush icon and 'Paint' as a string. ``` -------------------------------- ### Example output for simple C++ program Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Example output when running the simple C++ program without arguments and with the help flag. ```shell % ./test % ./test -h ./test {OPTIONS} This is a test program. OPTIONS: -h, --help Display this help menu This goes after the options. % ``` -------------------------------- ### Windows style parser prefixes Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Example demonstrating the use of Windows-style prefixes (e.g., '/') and separators (e.g., ':') for command-line arguments in C++. ```cpp parser.LongPrefix("/"); parser.LongSeparator(":"); ``` ```shell % ./test /help ./test {OPTIONS} This command likes to break your disks OPTIONS: /help Show this help menu. /bs:[BYTES] Block size /skip:[BYTES] Bytes to skip /if:[BLOCK SIZE] Block size /of:[BLOCK SIZE] Block size % ./test /bs:72 /skip:87 /if:/tmp/test.txt bs = 72 skip = 87 if = /tmp/test.txt % ``` -------------------------------- ### Basic Usage Example Source: https://github.com/nmwsharp/polyscope/blob/master/deps/MarchingCubeCpp/README.md This example demonstrates how to include the MC.h header and use the marching_cube function to compute an isosurface mesh from a scalar field. ```cpp #define MC_IMPLEM_ENABLE #include "MC.h" int main() { // First compute a scalar field const int n = 100; MC::MC_FLOAT* field = new MC::MC_FLOAT[n * n * n]; // [...] // Compute isosurface using marching cube MC::mcMesh mesh; MC::marching_cube(field, n, n, n, mesh); // Dot whatever you want with the mesh // [...] return 0; } ``` -------------------------------- ### Run regression tests Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Commands to compile and run the regression tests, showing example output. ```shell % make runtests g++ test.cxx -o test.o -I. -std=c++11 -O2 -c -MMD g++ -o test test.o -std=c++11 -O2 ./test =============================================================================== All tests passed (74 assertions in 15 test cases) % ``` -------------------------------- ### dd-style parser prefixes Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Example demonstrating the use of dd-style prefixes (e.g., '--') and separators (e.g., '=') for command-line arguments in C++. ```cpp #include #include int main(int argc, char **argv) { args::ArgumentParser parser("This command likes to break your disks"); parser.LongPrefix(""); parser.LongSeparator("="); args::HelpFlag help(parser, "HELP", "Show this help menu.", {"help"}); args::ValueFlag bs(parser, "BYTES", "Block size", {"bs"}, 512); args::ValueFlag skip(parser, "BYTES", "Bytes to skip", {"skip"}, 0); args::ValueFlag input(parser, "BLOCK SIZE", "Block size", {"if"}); args::ValueFlag output(parser, "BLOCK SIZE", "Block size", {"of"}); try { parser.ParseCLI(argc, argv); } catch (args::Help) { std::cout << parser; return 0; } catch (args::ParseError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } catch (args::ValidationError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } std::cout << "bs = " << args::get(bs) << std::endl; std::cout << "skip = " << args::get(skip) << std::endl; if (input) { std::cout << "if = " << args::get(input) << std::endl; } if (output) { std::cout << "of = " << args::get(output) << std::endl; } return 0; } ``` ```shell % ./test help ./test {OPTIONS} This command likes to break your disks OPTIONS: help Show this help menu. bs=[BYTES] Block size skip=[BYTES] Bytes to skip if=[BLOCK SIZE] Block size of=[BLOCK SIZE] Block size % ./test bs=1024 skip=7 if=/tmp/input bs = 1024 skip = 7 if = /tmp/input ``` -------------------------------- ### JSON Pointer and JSON Patch examples Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md Demonstrates the usage of JSON Pointer for addressing values and JSON Patch for describing differences between JSON values, including applying patches and calculating diffs. ```cpp // a JSON value json j_original = R"({ "baz": ["one", "two", "three"], "foo": "bar" })"_json; // access members with a JSON pointer (RFC 6901) j_original["/baz/1"_json_pointer]; // "two" // a JSON patch (RFC 6902) json j_patch = R"([ { "op": "replace", "path": "/baz", "value": "boo" }, { "op": "add", "path": "/hello", "value": ["world"] }, { "op": "remove", "path": "/foo"} ])"_json; // apply the patch json j_result = j_original.patch(j_patch); // { // "baz": "boo", // "hello": ["world"] // } // calculate a JSON patch from two JSON values json::diff(j_result, j_original); // [ // { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] }, // { "op": "remove","path": "/hello" }, // { "op": "add", "path": "/foo", "value": "bar" } // ] ``` -------------------------------- ### Shell Command Examples Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md These shell commands demonstrate various ways to invoke the compiled C++ program with different inputs for the integer and double tuple arguments, including successful parsing and error cases. ```shell % ./test -h Argument could not be matched: 'h' ./test [INTS] [DOUBLES] This is a test program. OPTIONS: INTS This takes a pair of integers. DOUBLES This takes a pair of doubles. % ./test 5 ints found: 5 and 0 % ./test 5,8 ints found: 5 and 8 % ./test 5,8 2.4,8 ints found: 5 and 8 doubles found: 2.4 and 8 % ./test 5,8 2.4, terminate called after throwing an instance of 'std::invalid_argument' what(): stod zsh: abort ./test 5,8 2.4, % ./test 5,8 2.4 terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::basic_string: __pos (which is 4) > this->size() (which is 3) zsh: abort ./test 5,8 2.4 % ./test 5,8 2.4-7 ints found: 5 and 8 doubles found: 2.4 and 7 % ./test 5,8 2.4,-7 ints found: 5 and 8 doubles found: 2.4 and -7 ``` -------------------------------- ### C++ Example with std::tuple Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md This C++ code demonstrates how to define custom input stream operators and reader functions to parse std::tuple types for command-line arguments. ```cpp #include #include std::istream& operator>>(std::istream& is, std::tuple& ints) { is >> std::get<0>(ints); is.get(); is >> std::get<1>(ints); return is; } #include struct DoublesReader { void operator()(const std::string &name, const std::string &value, std::tuple &destination) { size_t commapos = 0; std::get<0>(destination) = std::stod(value, &commapos); std::get<1>(destination) = std::stod(std::string(value, commapos + 1)); } }; int main(int argc, char **argv) { args::ArgumentParser parser("This is a test program."); args::Positional> ints(parser, "INTS", "This takes a pair of integers."); args::Positional, DoublesReader> doubles(parser, "DOUBLES", "This takes a pair of doubles."); try { parser.ParseCLI(argc, argv); } catch (args::Help) { std::cout << parser; return 0; } catch (args::ParseError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } if (ints) { std::cout << "ints found: " << std::get<0>(args::get(ints)) << " and " << std::get<1>(args::get(ints)) << std::endl; } if (doubles) { std::cout << "doubles found: " << std::get<0>(args::get(doubles)) << " and " << std::get<1>(args::get(doubles)) << std::endl; } return 0; } ``` -------------------------------- ### JSON Object Creation Example Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md Demonstrates creating a JSON object with various data types using C++ syntax, including nested objects and arrays. ```cpp // create an empty structure (null) json j; // add a number that is stored as double (note the implicit conversion of j to an object) j["pi"] = 3.141; // add a Boolean that is stored as bool j["happy"] = true; // add a string that is stored as std::string j["name"] = "Niels"; // add another null object by passing nullptr j["nothing"] = nullptr; // add an object inside the object j["answer"]["everything"] = 42; // add an array that is stored as std::vector (using an initializer list) j["list"] = { 1, 0, 2 }; // add another object (using an initializer list of pairs) j["object"] = { {"currency", "USD"}, {"value", 42.99} }; // instead, you could also write (which looks very similar to the JSON above) json j2 = { {"pi", 3.141}, {"happy", true}, {"name", "Niels"}, {"nothing", nullptr}, {"answer", { {"everything", 42} }}, {"list", {1, 0, 2}}, {"object", { {"currency", "USD"}, {"value", 42.99} }} }; ``` -------------------------------- ### Custom Serializer Example Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md An example of a custom serializer that accepts types with a size less than or equal to 32, demonstrating the use of ADL (Argument-Dependent Lookup) for `to_json` and `from_json` methods. ```cpp // You should use void as a second template argument // if you don't need compile-time checks on T template::type> struct less_than_32_serializer { template static void to_json(BasicJsonType& j, T value) { // we want to use ADL, and call the correct to_json overload using nlohmann::to_json; // this method is called by adl_serializer, // this is where the magic happens to_json(j, value); } template static void from_json(const BasicJsonType& j, T& value) { // same thing here using nlohmann::from_json; from_json(j, value); } }; ``` -------------------------------- ### Explicitly getting values Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md Shows how to explicitly retrieve values from JSON objects using the get() method with a specified type. ```cpp std::string vs = js.get(); bool vb = jb.get(); int vi = jn.get(); // etc. ``` -------------------------------- ### Per-backend settings for OpenGL Mock Source: https://github.com/nmwsharp/polyscope/blob/master/deps/imgui/CMakeLists.txt Configures include directories for the OpenGL Mock backend and includes commented-out definitions for disabling platform-specific functions. ```cmake if("${POLYSCOPE_BACKEND_OPENGL_MOCK}") # Disable every platform-specific thing I can find in imgui # add_definitions(-DIMGUI_DISABLE_OSX_FUNCTIONS) # add_definitions(-DIMGUI_DISABLE_WIN32_FUNCTIONS) # add_definitions(-DIMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) # add_definitions(-DIMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/imgui/") target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/custom_backends/") endif() ``` -------------------------------- ### Bad Serializer Example (Stack Overflow Risk) Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md An example illustrating a potential stack overflow issue when reimplementing a serializer incorrectly, where the serializer might recursively call itself. ```cpp template struct bad_serializer { template static void to_json(BasicJsonType& j, const T& value) { // this calls BasicJsonType::json_serializer::to_json(j, value); // if BasicJsonType::json_serializer == bad_serializer ... oops! j = value; } template static void to_json(const BasicJsonType& j, T& value) { // this calls BasicJsonType::json_serializer::from_json(j, value); // if BasicJsonType::json_serializer == bad_serializer ... oops! value = j.template get(); // oops! } }; ``` -------------------------------- ### Generate Doxygen documentation locally Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Command to generate local Doxygen documentation. ```shell doxygen Doxyfile ``` -------------------------------- ### Specialization of adl_serializer for boost::optional Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md An example of specializing adl_serializer for boost::optional to handle conversion to and from JSON. ```cpp // partial specialization (full specialization works too) namespace nlohmann { template struct adl_serializer> { static void to_json(json& j, const boost::optional& opt) { if (opt == boost::none) { j = nullptr; } else { j = *opt; // this will call adl_serializer::to_json which will // find the free function to_json in T's namespace! } } static void from_json(const json& j, boost::optional& opt) { if (j.is_null()) { opt = boost::none; } else { opt = j.get(); // same as above, but with // adl_serializer::from_json } } }; } ``` -------------------------------- ### CBOR and MessagePack Serialization Example Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md Demonstrates how to serialize a JSON value to CBOR and MessagePack byte vectors, and then deserialize them back into JSON objects. ```cpp // create a JSON value json j = R"({\"compact\": true, \"schema\": 0})"_json; // serialize to CBOR std::vector v_cbor = json::to_cbor(j); // 0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00 // roundtrip json j_from_cbor = json::from_cbor(v_cbor); // serialize to MessagePack std::vector v_msgpack = json::to_msgpack(j); // 0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00 // roundtrip json j_from_msgpack = json::from_msgpack(v_msgpack); ``` -------------------------------- ### Per-backend settings for OpenGL3 GLFW Source: https://github.com/nmwsharp/polyscope/blob/master/deps/imgui/CMakeLists.txt Configures include directories, defines, and linked libraries for the OpenGL3 GLFW backend, including platform-specific handling for macOS and other systems. ```cmake if("${POLYSCOPE_BACKEND_OPENGL3_GLFW}") target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/imgui/") target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/custom_backends/") target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/implot/") target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/ImGuizmo/") target_include_directories(imgui PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../glad/include/") target_link_libraries(imgui PRIVATE glfw) if(APPLE) # On macOS, get openGL & friends from Frameworks; do not use GLAD at all add_definitions(-DGLFW_INCLUDE_GLCOREARB) # NOTE: This code is essentially duplicated here and in polyscope/src/CMakeLists.txt # Apple is playing hardball and deprecating openGL... we'll cross that bridge when we come to it # Silence warnings about openGL deprecation add_definitions(-DGL_SILENCE_DEPRECATION) find_library(opengl_library OpenGL) target_link_libraries(imgui PRIVATE ${opengl_library}) else() # On Windows/Linux, use the glad openGL loader add_definitions(-DIMGUI_IMPL_OPENGL_LOADER_GLAD) target_link_libraries(imgui PRIVATE glad) endif() endif() ``` -------------------------------- ### Per-backend settings for OpenGL3 EGL Source: https://github.com/nmwsharp/polyscope/blob/master/deps/imgui/CMakeLists.txt Configures include directories, defines, and linked libraries for the OpenGL3 EGL backend, specifically for Linux. ```cmake if("${POLYSCOPE_BACKEND_OPENGL3_EGL}") # this backend supports linux only target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/imgui/") target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/implot/") target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/ImGuizmo/") target_include_directories(imgui PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../glad/include/") # linux only add_definitions(-DIMGUI_IMPL_OPENGL_LOADER_GLAD) target_link_libraries(imgui PRIVATE glad) endif() ``` -------------------------------- ### Conversion from STL associative containers Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md Examples of converting C++ STL associative containers (std::map, std::multimap, std::unordered_map, std::unordered_multimap) into JSON objects. ```cpp std::map c_map { {"one", 1}, {"two", 2}, {"three", 3} }; json j_map(c_map); // {"one": 1, "three": 3, "two": 2 } std::unordered_map c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} }; json j_umap(c_umap); // {"one": 1.2, "two": 2.3, "three": 3.4} std::multimap c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; json j_mmap(c_mmap); // only one entry for key "three" is used // maybe {"one": true, "two": true, "three": true} std::unordered_multimap c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; json j_ummap(c_ummap); // only one entry for key "three" is used // maybe {"one": true, "two": true, "three": true} ``` -------------------------------- ### Basic CMake Configuration Source: https://github.com/nmwsharp/polyscope/blob/master/examples/demo-app/CMakeLists.txt Sets the minimum CMake version, project name, and checks for source/build directory consistency. ```cmake cmake_minimum_required(VERSION 2.8.9...3.22) project(polyscope-demo-app) # Maybe stop from CMAKEing in the wrong place if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR) message(FATAL_ERROR "Source and build directories cannot be the same. Go use the /build directory.") endif() ``` -------------------------------- ### Help menu output Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md This shell command shows the generated help menu output for the C++ program, demonstrating how nested groups are displayed. ```shell % /tmp/test -h /tmp/test {OPTIONS} This is a test program. OPTIONS: this group provides xor validation: -a test flag -b test flag -c test flag this group provides all-or-none (nxor) validation: -d test flag -e test flag -f test flag this group provides all-or-none (nxor2) validation: -i test flag -j test flag -k test flag this group provides all-or-none (nxor3) validation: -l test flag -m test flag -n test flag this group provides at-least-one validation: -g test flag -o test flag -h, --help Show this help menu This goes after the options. % ``` -------------------------------- ### Create Executable Source: https://github.com/nmwsharp/polyscope/blob/master/examples/demo-app/CMakeLists.txt Defines the main executable target 'polyscopedemo' and lists its source files. ```cmake # Create an executable add_executable( polyscopedemo demo_app.cpp simple_dot_mesh_parser.cpp surface_mesh_io.cpp ) ``` -------------------------------- ### C++ Argument Parser Example Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md This C++ code snippet demonstrates the use of the args library to define a parser with long descriptions and multiple flags, showcasing how the library handles wrapping. ```cpp #include #include int main(int argc, char **argv) { args::ArgumentParser parser("This is a test program with a really long description that is probably going to have to be wrapped across multiple different lines. This is a test to see how the line wrapping works", "This goes after the options. This epilog is also long enough that it will have to be properly wrapped to display correctly on the screen"); args::HelpFlag help(parser, "HELP", "Show this help menu.", {'h', "help"}); args::ValueFlag foo(parser, "FOO", "The foo flag.", {'a', 'b', 'c', "a", "b", "c", "the-foo-flag"}); args::ValueFlag bar(parser, "BAR", "The bar flag. This one has a lot of options, and will need wrapping in the description, along with its long flag list.", {'d', 'e', 'f', "d", "e", "f"}); args::ValueFlag baz(parser, "FOO", "The baz flag. This one has a lot of options, and will need wrapping in the description, even with its short flag list.", {"baz"}); args::Positional pos1(parser, "POS1", "The pos1 argument."); args::PositionalList poslist1(parser, "POSLIST1", "The poslist1 argument."); args::Positional pos2(parser, "POS2", "The pos2 argument."); args::PositionalList poslist2(parser, "POSLIST2", "The poslist2 argument."); args::Positional pos3(parser, "POS3", "The pos3 argument."); args::PositionalList poslist3(parser, "POSLIST3", "The poslist3 argument."); args::Positional pos4(parser, "POS4", "The pos4 argument."); args::PositionalList poslist4(parser, "POSLIST4", "The poslist4 argument."); args::Positional pos5(parser, "POS5", "The pos5 argument."); args::PositionalList poslist5(parser, "POSLIST5", "The poslist5 argument."); args::Positional pos6(parser, "POS6", "The pos6 argument."); args::PositionalList poslist6(parser, "POSLIST6", "The poslist6 argument."); args::Positional pos7(parser, "POS7", "The pos7 argument."); args::PositionalList poslist7(parser, "POSLIST7", "The poslist7 argument."); args::Positional pos8(parser, "POS8", "The pos8 argument."); args::PositionalList poslist8(parser, "POSLIST8", "The poslist8 argument."); args::Positional pos9(parser, "POS9", "The pos9 argument."); args::PositionalList poslist9(parser, "POSLIST9", "The poslist9 argument."); try { parser.ParseCLI(argc, argv); } catch (args::Help) { std::cout << parser; return 0; } catch (args::ParseError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } catch (args::ValidationError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } return 0; } ``` -------------------------------- ### Project Options - Backend Source: https://github.com/nmwsharp/polyscope/blob/master/CMakeLists.txt Defines cache variables for different backend options. ```cmake set(POLYSCOPE_BACKEND_OPENGL3_GLFW "ON" CACHE BOOL "Enable openGL3_glfw backend") set(POLYSCOPE_BACKEND_OPENGL_MOCK "ON" CACHE BOOL "Enable openGL_mock backend") set(POLYSCOPE_BACKEND_OPENGL3_EGL "AUTO" CACHE STRING "Enable openGL3_egl backend") # 'AUTO' means "if we're on linux and EGL.h is available" ``` -------------------------------- ### Conversion from STL sequence containers Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md Examples of converting various C++ STL sequence containers (std::vector, std::deque, std::list, std::forward_list, std::array) into JSON arrays. ```cpp std::vector c_vector {1, 2, 3, 4}; json j_vec(c_vector); // [1, 2, 3, 4] std::deque c_deque {1.2, 2.3, 3.4, 5.6}; json j_deque(c_deque); // [1.2, 2.3, 3.4, 5.6] std::list c_list {true, true, false, true}; json j_list(c_list); // [true, true, false, true] std::forward_list c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543}; json j_flist(c_flist); // [12345678909876, 23456789098765, 34567890987654, 45678909876543] std::array c_array {{1, 2, 3, 4}}; json j_array(c_array); // [1, 2, 3, 4] ``` ```cpp std::set c_set {"one", "two", "three", "four", "one"}; json j_set(c_set); // only one entry for "one" is used // ["four", "one", "three", "two"] std::unordered_set c_uset {"one", "two", "three", "four", "one"}; json j_uset(c_uset); // only one entry for "one" is used // maybe ["two", "three", "four", "one"] std::multiset c_mset {"one", "two", "one", "four"}; json j_mset(c_mset); // both entries for "one" are used // maybe ["one", "two", "one", "four"] std::unordered_multiset c_umset {"one", "two", "one", "four"}; json j_umset(c_umset); // both entries for "one" are used // maybe ["one", "two", "one", "four"] ``` -------------------------------- ### Create Library Source: https://github.com/nmwsharp/polyscope/blob/master/src/CMakeLists.txt Creates a static library named 'polyscope' including source files, backend source files, headers, and backend headers. ```cmake add_library(polyscope ${SRCS} ${BACKEND_SRCS} ${HEADERS} ${BACKEND_HEADERS}) ``` -------------------------------- ### Terminating Flag Options Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Demonstrates how '--' can be used to terminate flag options and force all following arguments to be treated as positional options. Also shows how an epilog will be wrapped. ```text --" can be used to terminate flag options and force all following arguments to be treated as positional options This goes after the options. This epilog is also long enough that it will have to be properly wrapped to display correctly on the screen % ``` -------------------------------- ### Mock OpenGL Backend Enablement Source: https://github.com/nmwsharp/polyscope/blob/master/src/CMakeLists.txt This snippet configures the mock OpenGL backend, adding necessary headers and definitions when enabled. ```cmake if("${POLYSCOPE_BACKEND_OPENGL_MOCK}") message("Polyscope backend openGL_mock enabled") list(APPEND BACKEND_HEADERS ${INCLUDE_ROOT}render/mock_opengl/mock_gl_engine.h ${INCLUDE_ROOT}render/opengl/shaders/common.h ) add_definitions(-DPOLYSCOPE_BACKEND_OPENGL_MOCK_ENABLED) endif() ``` -------------------------------- ### Argument flags, Positional arguments, lists Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md Illustrates the usage of argument flags, positional arguments, and lists of values in args.hxx. ```cpp #include #include int main(int argc, char **argv) { args::ArgumentParser parser("This is a test program.", "This goes after the options."); args::HelpFlag help(parser, "help", "Display this help menu", {'h', "help"}); args::ValueFlag integer(parser, "integer", "The integer flag", {'i'}); args::ValueFlagList characters(parser, "characters", "The character flag", {'c'}); args::Positional foo(parser, "foo", "The foo position"); args::PositionalList numbers(parser, "numbers", "The numbers position list"); try { parser.ParseCLI(argc, argv); } catch (args::Help) { std::cout << parser; return 0; } catch (args::ParseError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } catch (args::ValidationError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } if (integer) { std::cout << "i: " << args::get(integer) << std::endl; } if (characters) { for (const auto ch: args::get(characters)) { std::cout << "c: " << ch << std::endl; } } if (foo) { std::cout << "f: " << args::get(foo) << std::endl; } if (numbers) { for (const auto nm: args::get(numbers)) { std::cout << "n: " << nm << std::endl; } } return 0; } ``` ```shell % ./test -h ./test {OPTIONS} [foo] [numbers...] This is a test program. OPTIONS: -h, --help Display this help menu -i integer The integer flag -c characters The character flag foo The foo position numbers The numbers position list "--" can be used to terminate flag options and force all following arguments to be treated as positional options This goes after the options. % ./test -i 5 i: 5 % ./test -i 5.2 Argument 'integer' received invalid value type '5.2' ./test {OPTIONS} [foo] [numbers...] % ./test -c 1 -c 2 -c 3 c: 1 c: 2 c: 3 % % ./test 1 2 3 4 5 6 7 8 9 f: 1 n: 2 n: 3 n: 4 n: 5 n: 6 n: 7 n: 8 n: 9 % ./test 1 2 3 4 5 6 7 8 9 a Argument 'numbers' received invalid value type 'a' ./test {OPTIONS} [foo] [numbers...] This is a test program. ... ``` -------------------------------- ### Help Output with Wrapped Descriptions Source: https://github.com/nmwsharp/polyscope/blob/master/deps/args/README.md This shell command output shows the result of running the C++ program with the help flag, demonstrating how the argument parser wraps long descriptions for the program, options, and positional arguments. ```shell % ./test -h ./test {OPTIONS} [POS1] [POSLIST1...] [POS2] [POSLIST2...] [POS3] [POSLIST3...] [POS4] [POSLIST4...] [POS5] [POSLIST5...] [POS6] [POSLIST6...] [POS7] [POSLIST7...] [POS8] [POSLIST8...] [POS9] [POSLIST9...] This is a test program with a really long description that is probably going to have to be wrapped across multiple different lines. This is a test to see how the line wrapping works OPTIONS: -h, --help Show this help menu. -a FOO, -b FOO, -c FOO, --a FOO, --b FOO, --c FOO, --the-foo-flag FOO The foo flag. -d BAR, -e BAR, -f BAR, --d BAR, --e BAR, --f BAR The bar flag. This one has a lot of options, and will need wrapping in the description, along with its long flag list. --baz FOO The baz flag. This one has a lot of options, and will need wrapping in the description, even with its short flag list. POS1 The pos1 argument. POSLIST1 The poslist1 argument. POS2 The pos2 argument. POSLIST2 The poslist2 argument. POS3 The pos3 argument. POSLIST3 The poslist3 argument. POS4 The pos4 argument. POSLIST4 The poslist4 argument. POS5 The pos5 argument. POSLIST5 The poslist5 argument. POS6 The pos6 argument. POSLIST6 The poslist6 argument. POS7 The pos7 argument. POSLIST7 The poslist7 argument. POS8 The pos8 argument. POSLIST8 The poslist8 argument. POS9 The pos9 argument. POSLIST9 The poslist9 argument. ``` -------------------------------- ### Output Locations Configuration Source: https://github.com/nmwsharp/polyscope/blob/master/examples/demo-app/CMakeLists.txt Configures the output directories for archives, libraries, and executables. ```cmake ### Configure output locations set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) ``` -------------------------------- ### glad Library Build Configuration Source: https://github.com/nmwsharp/polyscope/blob/master/deps/glad/src/CMakeLists.txt This snippet shows the CMake configuration for creating the 'glad' library, including handling shared library exports and include directories. ```cmake cmake_minimum_required(VERSION 3.5) # Create a library for the viewer code add_library( glad glad.c ) # Are we building a shared library? get_target_property(library_type glad TYPE) if (library_type STREQUAL SHARED_LIBRARY) # If so, define the macro GLAD_API_EXPORT on the command line. target_compile_definitions(glad PUBLIC GLAD_GLAPI_EXPORT PRIVATE GLAD_GLAPI_EXPORT_BUILD) endif() target_include_directories(glad PUBLIC "../include") set_target_properties(glad PROPERTIES POSITION_INDEPENDENT_CODE TRUE) ``` -------------------------------- ### Android NDK configuration for C++11 Source: https://github.com/nmwsharp/polyscope/blob/master/deps/json/README.md Configuration snippet for Android.mk to enable C++11 and other features when using older NDK versions. ```makefile APP_STL := c++_shared NDK_TOOLCHAIN_VERSION := clang3.6 APP_CPPFLAGS += -frtti -fexceptions ```