diff --git a/BUILDING.md b/BUILDING.md index 6c1aea4619..6fade1852a 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -2,11 +2,11 @@ Advanced Build Configuration ============================ ## Table of Contents -- [Optional Components](#Optional-Components) -- [Third Party Plugins](#Plugins) -- [Other Build Options](#Other-Build-Options) -- [USD Developer Options](#USD-Developer-Options) -- [Optimization Options](#Optimization-Options) +- [Optional Components](#optional-components) +- [Third Party Plugins](#third-party-plugins) +- [Other Build Options](#other-build-options) +- [USD Developer Options](#usd-developer-options) +- [Optimization Options](#optimization-options) ## Optional Components @@ -19,7 +19,7 @@ removes the need for their dependencies when building USD. This component contains Hydra, a high-performance graphics rendering engine. Disable this component by specifying the cmake flag ```PXR_BUILD_IMAGING=FALSE``` when -invoking cmake. Disabling this component will also disable the [USD Imaging](#USD-Imaging) +invoking cmake. Disabling this component will also disable the [USD Imaging](#usd-imaging) component. ##### USD Imaging @@ -28,10 +28,10 @@ This component provides the USD imaging delegates for Hydra, as well as usdview, a standalone native viewer for USD files. Disable this component by specifying the cmake flag ```PXR_BUILD_USD_IMAGING=FALSE``` when -invoking cmake. Enabling this component will enable the [Imaging](#Imaging) +invoking cmake. Enabling this component will enable the [Imaging](#imaging) component. -## Plugins +## Third Party Plugins USD provides several plugins for integration with third-party software packages, including Maya, Katana, and Alembic. There is additional documentation on each plugin diff --git a/CMakeLists.txt b/CMakeLists.txt index c3c97ddcc1..46fa62493b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,10 @@ include(CXXDefaults) add_definitions(${_PXR_CXX_DEFINITIONS}) set(CMAKE_CXX_FLAGS ${_PXR_CXX_FLAGS}) +if(POLICY CMP0020) + cmake_policy(SET CMP0020 OLD) +endif() + include(Public) add_subdirectory(pxr) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..5e235ae2ec --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Thank you for your interest in contributing to USD! We ask that +potential contributors review our guidelines on [contributing](http://openusd.org/docs/Contributing-to-USD.html) before submitting a pull request. diff --git a/ISSUES.md b/ISSUES.md deleted file mode 100644 index c475e9e41b..0000000000 --- a/ISSUES.md +++ /dev/null @@ -1,50 +0,0 @@ -Filing Issues for USD -===================== - -We are very excited to gather community feedback for USD. If you have found an -issue, we ask that you follow these guidelines when filing. - -- List all relevant configuration information, including operating system, -software versions, hardware configuration, driver versions etc. - -- Provide a "Minimal Repro", meaning the smallest set of steps necessary to -reproduce the bug. - -Below is an example bug description: - - *Title*: Usd Stage Fails to Save. - - *Content*: - System Information: - ``` - Operating System: Ubuntu 12.04 64Bit - Hardware Configuration: Intel Core i5, Nvidia GTX 980(Driver 343.22) - Intel TBB Version: 4.4 Update 5 - G++ Version: 6.1.0 - Python Version: 2.7.5 - Boost Version: 1.6.1 - OpenSubdiv Version: 3.0.5 - GLEW Version: 1.10.0 - OpenImageIO Version: 1.5.11 - Ptex Version: 2.0.30 - Qt Version: 4.8.1 - Pyside Version: 1.2.2 - ``` - - - Repro case: - 1. Launch Python - 2. Run the following snippet - - ```python - - >>> from pxr import Usd - >>> stage = Usd.Stage.CreateNew('hello.usda') - >>> stage.GetRootLayer().Save() - ``` - - 3. Note that 'hello.usda' is not created on disk, my expectation is that - it would be - -These guidelines will help us get to issues more quickly, we appreciate your -help! diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..9a194e3aa9 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,8 @@ +### System Information (OS, Hardware, etc.) + +### Package Versions + +### Build Flags + +### Steps to Reproduce +1. diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..a9f1468813 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +### Description of Change(s) + + +### Included Commit(s) +- + +### Fixes Issue(s) +- + diff --git a/README.md b/README.md index f60a3078be..14b9260616 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Getting Help ------------ Need help understanding certain concepts in USD? See -[Getting Help with USD](http://openusd.org/docs/Getting-Help-With-USD.html). +[Getting Help with USD](http://openusd.org/docs/Getting-Help-with-USD.html). If you are experiencing undocumented problems with the software, please read our [issue guidelines](ISSUES.md) and file a bug via the diff --git a/cmake/defaults/CXXDefaults.cmake b/cmake/defaults/CXXDefaults.cmake index f637fb71bc..8d711ac175 100644 --- a/cmake/defaults/CXXDefaults.cmake +++ b/cmake/defaults/CXXDefaults.cmake @@ -26,7 +26,7 @@ include(Version) if (CMAKE_COMPILER_IS_GNUCXX) include(gccdefaults) -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") +elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") include(clangdefaults) elseif(MSVC) include(msvcdefaults) diff --git a/cmake/defaults/Options.cmake b/cmake/defaults/Options.cmake index 5227408c86..eeeaca9f16 100644 --- a/cmake/defaults/Options.cmake +++ b/cmake/defaults/Options.cmake @@ -21,12 +21,14 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # +option(PXR_STRICT_BUILD_MODE "Turn on additional warnings. Enforce all warnings as errors." OFF) option(PXR_VALIDATE_GENERATED_CODE "Validate script generated code" ON) option(PXR_BUILD_IMAGING "Build imaging components" ON) option(PXR_BUILD_USD_IMAGING "Build USD imaging components" ON) -option(PXR_BUILD_KATANA_PLUGIN "Build usd katana plugin" OFF) -option(PXR_BUILD_MAYA_PLUGIN "Build usd maya plugin" OFF) +option(PXR_BUILD_KATANA_PLUGIN "Build usd katana plugin" ON) +option(PXR_BUILD_MAYA_PLUGIN "Build usd maya plugin" ON) option(PXR_BUILD_ALEMBIC_PLUGIN "Build the Alembic plugin for USD" OFF) +option(PXR_MAYA_TBB_BUG_WORKAROUND "Turn on linker flag (-Wl,-Bsymbolic) to work around a Maya TBB bug" OFF) set(PXR_INSTALL_LOCATION "" CACHE diff --git a/cmake/defaults/Packages.cmake b/cmake/defaults/Packages.cmake index 36532ca8e7..e947f966f7 100644 --- a/cmake/defaults/Packages.cmake +++ b/cmake/defaults/Packages.cmake @@ -30,10 +30,12 @@ find_package(PythonInterp 2.7 REQUIRED) # --Boost find_package(Boost COMPONENTS + date_time iostreams python regex system + thread program_options REQUIRED ) @@ -58,17 +60,27 @@ find_library(M_LIB m) find_package(Jinja2) if (NOT PXR_MALLOC_LIBRARY) - message(STATUS "Using default system allocator because PXR_MALLOC_LIBRARY is unspecified") + if (NOT WIN32) + message(STATUS "Using default system allocator because PXR_MALLOC_LIBRARY is unspecified") + endif() endif() # Developer Options Package Requirements # ---------------------------------------------- if (PXR_VALIDATE_GENERATED_CODE) - find_package(BISON 2.4.1 EXACT) + if(WIN32) + find_package(BISON 2.7 EXACT) + else() + find_package(BISON 2.4.1 EXACT) + endif() # Flex 2.5.39+ is required, generated API is generated incorrectly in # 2.5.35, at least. scan_bytes generates with (..., int len, ...) instead of # the correct (..., yy_size_t len, ...). Lower at your own peril. - find_package(FLEX 2.5.39 EXACT) + if(WIN32) + find_package(FLEX 2.5.37 EXACT) + else() + find_package(FLEX 2.5.39 EXACT) + endif() endif() @@ -85,13 +97,17 @@ if (PXR_BUILD_IMAGING) find_package(OpenSubdiv 3 REQUIRED) # --Ptex find_package(PTex REQUIRED) - # --X11 - find_package(X11) + if(UNIX) + # --X11 + find_package(X11) + endif() # --Qt find_package(Qt4) if (QT4_FOUND) - find_package(PySideTools REQUIRED) + find_package(PySide REQUIRED) endif() + # --Zlib + find_package(ZLIB REQUIRED) endif() # Third Party Plugin Package Requirements diff --git a/cmake/defaults/ProjectDefaults.cmake b/cmake/defaults/ProjectDefaults.cmake index 5b3a4ff052..21aa51965b 100644 --- a/cmake/defaults/ProjectDefaults.cmake +++ b/cmake/defaults/ProjectDefaults.cmake @@ -55,4 +55,4 @@ if(NOT CMAKE_BUILD_TYPE) endif() # Enable CTest -enable_testing() +# enable_testing() diff --git a/cmake/defaults/clangdefaults.cmake b/cmake/defaults/clangdefaults.cmake index 3295342121..5fb8e50636 100644 --- a/cmake/defaults/clangdefaults.cmake +++ b/cmake/defaults/clangdefaults.cmake @@ -21,14 +21,10 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -# By default, Release flavor builds in cmake set NDEBUG, which -# breaks things internally. Turn it off. -set(CMAKE_CXX_FLAGS_RELEASE "-O2") -# Initialize to c++11, pxr won't build without it. -set(_PXR_CXX_FLAGS "-std=c++11 -DTF_NO_GNU_EXT -Wall -Wno-unused-local-typedefs") - -# We use hash_map, suppress deprecation warning. -_add_warning_flag("no-deprecated") -_add_warning_flag("no-deprecated-declarations") +include(gccclangshareddefaults) +# Defining TF_NO_GNU_EXT disables using the gnu hash_set and +# hash_map containers on platforms where we can't. The implementation +# will substitute C++11 containers with equivalent semantics in this case. +set(_PXR_CXX_FLAGS "${_PXR_GCC_CLANG_SHARED_CXX_FLAGS} -DTF_NO_GNU_EXT") diff --git a/cmake/defaults/gccclangshareddefaults.cmake b/cmake/defaults/gccclangshareddefaults.cmake new file mode 100644 index 0000000000..449ccd2edf --- /dev/null +++ b/cmake/defaults/gccclangshareddefaults.cmake @@ -0,0 +1,51 @@ +# +# Copyright 2016 Pixar +# +# Licensed under the Apache License, Version 2.0 (the "Apache License") +# with the following modification; you may not use this file except in +# compliance with the Apache License and the following modification to it: +# Section 6. Trademarks. is deleted and replaced with: +# +# 6. Trademarks. This License does not grant permission to use the trade +# names, trademarks, service marks, or product names of the Licensor +# and its affiliates, except as required to comply with Section 4(c) of +# the License and to reproduce the content of the NOTICE file. +# +# You may obtain a copy of the Apache License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the Apache License with the above modification is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the Apache License for the specific +# language governing permissions and limitations under the Apache License. +# + +# This file contains a set of flags/settings shared between our +# GCC and Clang configs. This allows clangdefaults and gccdefaults +# to remain minimal, marking the points where divergence is required. +include(Options) + +# By default, Release flavor builds in cmake set NDEBUG, which +# breaks things internally. Turn it off. +set(CMAKE_CXX_FLAGS_RELEASE "-O2") + +# Enable all warnings +_add_warning_flag("all") +# We use hash_map, suppress deprecation warning. +_add_warning_flag("no-deprecated") +_add_warning_flag("no-deprecated-declarations") +# Suppress unused typedef warnings eminating from boost. +_add_warning_flag("no-unused-local-typedefs") + +# Turn on C++11, pxr won't build without it. +set(_PXR_GCC_CLANG_SHARED_CXX_FLAGS "-std=c++11") + +if (${PXR_MAYA_TBB_BUG_WORKAROUND}) + set(_PXR_GCC_CLANG_SHARED_CXX_FLAGS "${_PXR_GCC_CLANG_SHARED_CXX_FLAGS} -Wl,-Bsymbolic") +endif() + +if (${PXR_STRICT_BUILD_MODE}) + _add_warning_flag("error") +endif() diff --git a/cmake/defaults/gccdefaults.cmake b/cmake/defaults/gccdefaults.cmake index decf1e7917..ce7789a2c5 100644 --- a/cmake/defaults/gccdefaults.cmake +++ b/cmake/defaults/gccdefaults.cmake @@ -21,15 +21,7 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -# By default, Release flavor builds in cmake set NDEBUG, which -# breaks things internally. Turn it off. -set(CMAKE_CXX_FLAGS_RELEASE "-O2") -# Initialize to c++11, pxr won't build without it. -# Turn on all warnings and convert them to errors. -set(_PXR_CXX_FLAGS "-std=c++11 -Wall -Wno-unused-local-typedefs") - -# We use hash_map, suppress deprecation warning. -_add_warning_flag("no-deprecated") -_add_warning_flag("no-deprecated-declarations") +include(gccclangshareddefaults) +set(_PXR_CXX_FLAGS "${_PXR_GCC_CLANG_SHARED_CXX_FLAGS}") diff --git a/cmake/defaults/msvcdefaults.cmake b/cmake/defaults/msvcdefaults.cmake index dcba7cfa78..e29209fef4 100644 --- a/cmake/defaults/msvcdefaults.cmake +++ b/cmake/defaults/msvcdefaults.cmake @@ -22,9 +22,67 @@ # language governing permissions and limitations under the Apache License. # +# Make sure WinDef.h does not define min and max macros which +# will conflict with std::min() and std::max(). +add_definitions("/DNOMINMAX") + +# TBB conflict +# This needs to be enabled only for debug builds +# add_definitions("/DTBB_USE_DEBUG=1") + +# Allow "Unsecure" STL +add_definitions("/D_SCL_SECURE_NO_WARNINGS") + +# Needed for consistency with Linux for the use of hashmap and hashset +add_definitions("/DTF_NO_GNU_EXT") + +# Needed to prevent YY files trying to import Unistd.h +# (which doesn't exist on Windows) +add_definitions("/DYY_NO_UNISTD_H") + +# Forces all libraries that have separate source, to be linked as +# DLL's rather than static libraries on Microsoft Window. +add_definitions("/DBOOST_ALL_DYN_LINK") + +add_definitions("/DBUILD_OPTLEVEL_OPT") + +add_definitions(/"DFLAVOR=\"win64\"") + +add_definitions(/"DOPENEXR_DLL") + # Set a decent warning level add_definitions("/W3") # Treat all warnings as errors add_definitions("/WX") +# trunctation from 'double' to 'float' due to matrix and vector classes in `Gf` +add_definitions("/wd4244") +add_definitions("/wd4305") + +# conversion from size_t to int. Whilst we don't want this enabled +# its in the Python headers. So all the Python wrap code is affected. +add_definitions("/wd4267") + +# no definition for inline function +# this affects Glf only +add_definitions("/wd4506") + +# Enable PDB generation +add_definitions("/Zi") + +# Enable minimum builds +add_definitions("/Gm") + +# These files require /bigobj compiler flag +# Vt/arrayPyBuffer.cpp +# Usd/crateFile.cpp +# Usd/stage.cpp +# Until we can set the flag on a per file basis, we'll have to enable it +# for all translation units. +add_definitions("/bigobj") + +if (${PXR_STRICT_BUILD_MODE}) + # Treat all warnings as errors + add_definitions("/WX") +endif() diff --git a/cmake/macros/Private.cmake b/cmake/macros/Private.cmake index 3ca3eb990b..cf29c3a381 100644 --- a/cmake/macros/Private.cmake +++ b/cmake/macros/Private.cmake @@ -111,11 +111,7 @@ function(_install_python LIBRARY_NAME) ) set(libPythonPrefix lib/python) - - string(SUBSTRING ${LIBRARY_NAME} 0 1 LIBNAME_FL) - string(TOUPPER ${LIBNAME_FL} LIBNAME_FL) - string(SUBSTRING ${LIBRARY_NAME} 1 -1 LIBNAME_SUFFIX) - set(LIBRARY_INSTALLNAME "${LIBNAME_FL}${LIBNAME_SUFFIX}") + _get_python_module_name(${LIBRARY_NAME} LIBRARY_INSTALLNAME) foreach(file ${ip_FILES}) set(filesToInstall "") @@ -221,6 +217,36 @@ function(_install_resource_files) endforeach() endfunction() # _install_resource_files +function(_install_pyside_ui_files) + set(uiFiles "") + foreach(uiFile ${ARGN}) + get_filename_component(outFileName ${uiFile} NAME_WE) + get_filename_component(uiFilePath ${uiFile} ABSOLUTE) + set(outFilePath "${CMAKE_CURRENT_BINARY_DIR}/${outFileName}.py") + add_custom_command( + OUTPUT ${outFilePath} + COMMAND "${PYSIDEUICBINARY}" + ARGS -o ${outFilePath} ${uiFilePath} + MAIN_DEPENDENCY "${uiFilePath}" + COMMENT "Generating Python for ${uiFilePath} ..." + VERBATIM + ) + list(APPEND uiFiles ${outFilePath}) + endforeach() + + add_custom_target(${LIBRARY_NAME}_pysideuifiles ALL + DEPENDS ${uiFiles} + ) + + set(libPythonPrefix lib/python) + _get_python_module_name(${LIBRARY_NAME} LIBRARY_INSTALLNAME) + + install( + FILES ${uiFiles} + DESTINATION "${libPythonPrefix}/pxr/${LIBRARY_INSTALLNAME}" + ) +endfunction() # _install_pyside_ui_files + function(_classes LIBRARY_NAME) # Install headers to build or install prefix set(options PUBLIC PRIVATE) diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index e9c6ad2cd5..26419aa5a9 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -41,6 +41,18 @@ function(pxr_python_bins) DESTINATION ${installDir} RENAME ${file} ) + + # Windows by default cannot execute Python files so here + # we create a batch file wrapper that invokes the python + # files. + if(WIN32) + file(WRITE "${CMAKE_BINARY_DIR}/${pyFile}.cmd" "@set PATH=C:\\Program Files\\usd\\lib;%PATH%\r\npython ${file} %*") + install(PROGRAMS + "${CMAKE_BINARY_DIR}/${pyFile}.cmd" + DESTINATION ${installDir} + RENAME "${file}.cmd" + ) + endif() endforeach() endfunction() # pxr_install_python_bins @@ -96,6 +108,32 @@ function(pxr_cpp_bin BIN_NAME) endfunction() +function(pxr_add_filename_property LIBRARY_NAME FILELIST) + foreach(cppfile ${FILELIST}) + + get_filename_component(fileExt "${cppfile}" EXT) + + if("${fileExt}" STREQUAL "") + get_filename_component( + cppModuleName + "${cppfile}" + NAME_WE) + + set_source_files_properties(${cppfile}.cpp PROPERTIES COMPILE_FLAGS + -D__FILENAME__=${LIBRARY_NAME}${cppModuleName}) + + elseif(fileExt MATCHES .cpp) + get_filename_component( + cppModuleName + "${cppfile}" + NAME_WE) + + set_source_files_properties(${cppfile} PROPERTIES COMPILE_FLAGS + -D__FILENAME__=${LIBRARY_NAME}${cppModuleName}) + endif() + endforeach() +endfunction() + function(pxr_shared_library LIBRARY_NAME) set(options PYTHON_LIBRARY) set(multiValueArgs @@ -106,6 +144,7 @@ function(pxr_shared_library LIBRARY_NAME) CPPFILES PYMODULE_CPPFILES PYTHON_FILES + PYSIDE_UI_FILES LIBRARIES INCLUDE_DIRS RESOURCE_FILES @@ -135,6 +174,24 @@ function(pxr_shared_library LIBRARY_NAME) ${sl_PRIVATE_HEADERS} ${${LIBRARY_NAME}_PRIVATE_HEADERS} ) + if(sl_CPPFILES) + pxr_add_filename_property(${LIBRARY_NAME} "${sl_CPPFILES}") + endif() + if(sl_PRIVATE_CLASSES) + pxr_add_filename_property(${LIBRARY_NAME} "${sl_PRIVATE_CLASSES}") + endif() + if(sl_PUBLIC_CLASSES) + pxr_add_filename_property(${LIBRARY_NAME} "${sl_PUBLIC_CLASSES}") + endif() + + if(WIN32) + if(MSVC) + set_target_properties( + ${LIBRARY_NAME} + PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") + endif() + endif() + if(sl_PYTHON_FILES) _install_python(${LIBRARY_NAME} FILES ${sl_PYTHON_FILES} @@ -169,12 +226,24 @@ function(pxr_shared_library LIBRARY_NAME) set(rpath "$ORIGIN/../../../../${PXR_INSTALL_SUBDIR}/lib:${rpath}") endif() - set_target_properties(${LIBRARY_NAME} - PROPERTIES - PREFIX "" - FOLDER "${PXR_PREFIX}/_python" - INSTALL_RPATH ${rpath} - ) + if(WIN32) + add_definitions(-D_BUILDING_PYD=1) + set_target_properties(${LIBRARY_NAME} + PROPERTIES + PREFIX "" + SUFFIX ".pyd" + FOLDER "${PXR_PREFIX}/_python" + LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS" + ) + else() + set_target_properties(${LIBRARY_NAME} + PROPERTIES + PREFIX "" + SUFFIX ".pyd" + FOLDER "${PXR_PREFIX}/_python" + INSTALL_RPATH ${rpath} + ) + endif() else() _get_install_dir(lib LIB_INSTALL_PREFIX) _get_share_install_dir(SHARE_INSTALL_PREFIX) @@ -201,9 +270,14 @@ function(pxr_shared_library LIBRARY_NAME) set(installLocation ${CMAKE_INSTALL_PREFIX}/${PLUGINS_PREFIX}) endif() + if(WIN32) + set(_PxrUserLocation "$ENV{ProgramData}\\usd\\plugins") + else() + set(_PxrUserLocation "/usr/local/share/usd/plugins") + endif() set_target_properties(${LIBRARY_NAME} PROPERTIES COMPILE_DEFINITIONS - "MFB_PACKAGE_NAME=${PXR_PACKAGE};MFB_ALT_PACKAGE_NAME=${PXR_PACKAGE};MFB_PACKAGE_MODULE=${pyModuleName};PXR_USER_LOCATION=/usr/local/share/usd/plugins;PXR_BUILD_LOCATION=${CMAKE_INSTALL_PREFIX}/${PLUGINS_PREFIX};PXR_INSTALL_LOCATION=${installLocation}" + "MFB_PACKAGE_NAME=${PXR_PACKAGE};MFB_ALT_PACKAGE_NAME=${PXR_PACKAGE};MFB_PACKAGE_MODULE=${pyModuleName};PXR_USER_LOCATION=${_PxrUserLocation};PXR_BUILD_LOCATION=${CMAKE_INSTALL_PREFIX}/${PLUGINS_PREFIX};PXR_INSTALL_LOCATION=${installLocation}" ) # Always bake the rpath. @@ -257,8 +331,10 @@ function(pxr_shared_library LIBRARY_NAME) install(TARGETS ${LIBRARY_NAME} EXPORT pxrTargets + ARCHIVE DESTINATION ${LIB_INSTALL_PREFIX} LIBRARY DESTINATION ${LIB_INSTALL_PREFIX} ARCHIVE DESTINATION ${LIB_INSTALL_PREFIX} + RUNTIME DESTINATION ${LIB_INSTALL_PREFIX} PUBLIC_HEADER DESTINATION ${HEADER_INSTALL_PREFIX} ) @@ -301,6 +377,11 @@ function(pxr_shared_library LIBRARY_NAME) if (sl_RESOURCE_FILES) _install_resource_files(${sl_RESOURCE_FILES}) endif() + + if (sl_PYSIDE_UI_FILES) + _install_pyside_ui_files(${sl_PYSIDE_UI_FILES}) + endif() + endfunction() # pxr_shared_library function(pxr_static_library LIBRARY_NAME) @@ -449,6 +530,7 @@ function(pxr_plugin PLUGIN_NAME) CPPFILES PYMODULE_CPPFILES PYTHON_FILES + PYSIDE_UI_FILES LIBRARIES INCLUDE_DIRS RESOURCE_FILES @@ -563,6 +645,7 @@ function(pxr_plugin PLUGIN_NAME) install(TARGETS ${PLUGIN_NAME} EXPORT pxrTargets + ARCHIVE DESTINATION ${PLUGIN_INSTALL_PREFIX} LIBRARY DESTINATION ${PLUGIN_INSTALL_PREFIX} ARCHIVE DESTINATION ${PLUGIN_INSTALL_PREFIX} PUBLIC_HEADER DESTINATION ${HEADER_INSTALL_PREFIX} @@ -601,6 +684,13 @@ function(pxr_plugin PLUGIN_NAME) _install_resource_files(${sl_RESOURCE_FILES}) endif() + if (sl_PYSIDE_UI_FILES) + _get_install_dir(plugin PLUGINS_PREFIX) + set(LIBRARY_NAME ${PLUGIN_NAME}) + + _install_pyside_ui_files(${sl_PYSIDE_UI_FILES}) + endif() + # Build python module. if(DEFINED sl_PYMODULE_CPPFILES) pxr_shared_library( @@ -698,6 +788,7 @@ function(pxr_build_test_shared_lib LIBRARY_NAME) ) install(TARGETS ${LIBRARY_NAME} + ARCHIVE DESTINATION "tests/lib" LIBRARY DESTINATION "tests/lib" ARCHIVE DESTINATION "tests/lib" ) @@ -744,7 +835,7 @@ endfunction() # pxr_test_scripts function(pxr_install_test_dir) cmake_parse_arguments(bt - "" + "" "SRC;DEST" "" ${ARGN} @@ -758,13 +849,13 @@ endfunction() # pxr_install_test_dir function(pxr_register_test TEST_NAME) cmake_parse_arguments(bt - "PYTHON" + "PYTHON" "COMMAND;STDOUT_REDIRECT;STDERR_REDIRECT;DIFF_COMPARE;EXPECTED_RETURN_CODE;TESTENV" "ENV" ${ARGN} ) - # This harness is a filter which allows us to manipulate the test run, + # This harness is a filter which allows us to manipulate the test run, # e.g. by changing the environment, changing the expected return code, etc. set(testWrapperCmd ${PROJECT_SOURCE_DIR}/cmake/macros/testWrapper.py --verbose) @@ -799,7 +890,7 @@ function(pxr_register_test TEST_NAME) endif() if (bt_EXPECTED_RETURN_CODE) - set(testWrapperCmd ${testWrapperCmd} + set(testWrapperCmd ${testWrapperCmd} --expected-return-code=${bt_EXPECTED_RETURN_CODE}) endif() @@ -846,7 +937,7 @@ function(pxr_katana_nodetypes NODE_TYPES) set(importLines "import ${nodeType}\n") endforeach() - install(PROGRAMS + install(PROGRAMS ${pyFiles} DESTINATION ${installDir} ) diff --git a/cmake/modules/FindMaya.cmake b/cmake/modules/FindMaya.cmake index 20cccbdce7..66d289f2e1 100644 --- a/cmake/modules/FindMaya.cmake +++ b/cmake/modules/FindMaya.cmake @@ -86,6 +86,7 @@ if(WIN32) HINTS "${MAYA_LOCATION}" "$ENV{MAYA_LOCATION}" + "C:/Program Files/Autodesk/Maya2016" "C:/Program Files/Autodesk/Maya2015.5-x64" "C:/Program Files/Autodesk/Maya2015.5" "C:/Program Files/Autodesk/Maya2014.5-x64" diff --git a/cmake/modules/FindOpenEXR.cmake b/cmake/modules/FindOpenEXR.cmake index 3d815b34cc..337c85a69e 100644 --- a/cmake/modules/FindOpenEXR.cmake +++ b/cmake/modules/FindOpenEXR.cmake @@ -21,12 +21,6 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -find_path(OPENEXR_ROOT_DIR - include/OpenEXR/half.h - HINTS - "${OPENEXR_LOCATION}" - "$ENV{OPENEXR_LOCATION}" -) if (APPLE) find_path(OPENEXR_LIBRARY_DIR @@ -119,7 +113,6 @@ list(APPEND OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR}/OpenEXR) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OpenEXR REQUIRED_VARS - OPENEXR_ROOT_DIR OPENEXR_INCLUDE_DIRS OPENEXR_LIBRARY_DIR VERSION_VAR diff --git a/cmake/modules/FindOpenImageIO.cmake b/cmake/modules/FindOpenImageIO.cmake index d4680cd940..0dde6cc89c 100644 --- a/cmake/modules/FindOpenImageIO.cmake +++ b/cmake/modules/FindOpenImageIO.cmake @@ -21,6 +21,7 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # + if(UNIX) find_path(OIIO_BASE_DIR include/OpenImageIO/oiioversion.h @@ -40,7 +41,25 @@ if(UNIX) DOC "OpenImageIO library path" ) -endif(UNIX) +elseif(WIN32) + find_path(OIIO_BASE_DIR + include/OpenImageIO/oiioversion.h + HINTS + "${OIIO_LOCATION}" + "$ENV{OIIO_LOCATION}" + ) + find_path(OIIO_LIBRARY_DIR + OpenImageIO.lib + HINTS + "${OIIO_LOCATION}" + "$ENV{OIIO_LOCATION}" + "${OIIO_BASE_DIR}" + PATH_SUFFIXES + lib/ + DOC + "OpenImageIO library path" + ) +endif() find_path(OIIO_INCLUDE_DIR OpenImageIO/oiioversion.h diff --git a/cmake/modules/FindPySide.cmake b/cmake/modules/FindPySide.cmake new file mode 100644 index 0000000000..b5722fb44f --- /dev/null +++ b/cmake/modules/FindPySide.cmake @@ -0,0 +1,42 @@ +# +# Copyright 2016 Pixar +# +# Licensed under the Apache License, Version 2.0 (the "Apache License") +# with the following modification; you may not use this file except in +# compliance with the Apache License and the following modification to it: +# Section 6. Trademarks. is deleted and replaced with: +# +# 6. Trademarks. This License does not grant permission to use the trade +# names, trademarks, service marks, or product names of the Licensor +# and its affiliates, except as required to comply with Section 4(c) of +# the License and to reproduce the content of the NOTICE file. +# +# You may obtain a copy of the Apache License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the Apache License with the above modification is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the Apache License for the specific +# language governing permissions and limitations under the Apache License. +# +if (NOT PYTHON_EXECUTABLE) + return() +endif() + +find_program(PYSIDEUICBINARY + NAMES pyside-uic + HINTS ${PYSIDE_BIN_DIR} +) + +execute_process( + COMMAND + "${PYTHON_EXECUTABLE}" "-c" "import PySide" + RESULT_VARIABLE + pySideImportResult +) + +if (pySideImportResult EQUAL 0 AND EXISTS(${PYSIDEUICBINARY})) + set(PYSIDE_FOUND True) +endif() diff --git a/cmake/modules/FindPySideTools.cmake b/cmake/modules/FindPySideTools.cmake deleted file mode 100644 index c5028c54cb..0000000000 --- a/cmake/modules/FindPySideTools.cmake +++ /dev/null @@ -1,94 +0,0 @@ -# Try to find PySide utilities, PYSIDEUIC4 and PYSIDERCC4: -# PYSIDEUIC4BINARY - Location of PYSIDEUIC4 executable -# PYSIDERCC4BINARY - Location of PYSIDERCC4 executable -# PYSIDE_TOOLS_FOUND - PySide utilities found. - -# Also provides macro similar to FindQt4.cmake's WRAP_UI and WRAP_RC, -# for the automatic generation of Python code from Qt4's user interface -# ('.ui') and resource ('.qrc') files. These macros are called: -# - PYSIDE_WRAP_UI -# - PYSIDE_WRAP_RC -# XXX - from https://github.com/yorikvanhavre/FreeCAD/blob/master/cMake/FindPySideTools.cmake -# License? - -if(PYSIDEUIC4BINARY AND PYSIDERCC4BINARY) - # Already in cache, be silent - set(PYSIDE_TOOLS_FOUND_QUIETLY TRUE) -endif(PYSIDEUIC4BINARY AND PYSIDERCC4BINARY) - -find_program(PYSIDEUIC4BINARY - NAMES pyside-uic pyside-uic-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} - HINTS ${PYSIDE_BIN_DIR} -) -find_program(PYSIDERCC4BINARY - NAMES pyside-rcc pyside-rcc-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} - HINTS ${PYSIDE_BIN_DIR} -) - -macro(PYSIDE_WRAP_UI LIBRARY_NAME) - set(outfiles "") - foreach(it ${ARGN}) - get_filename_component(outfile ${it} NAME_WE) - get_filename_component(infile ${it} ABSOLUTE) - set(outfile ${CMAKE_CURRENT_BINARY_DIR}/${outfile}.py) - add_custom_command(OUTPUT ${outfile} - COMMAND ${PYSIDEUIC4BINARY} ${infile} -o ${outfile} - MAIN_DEPENDENCY ${infile} - ) - list(APPEND outfiles ${outfile}) - endforeach() # it - - add_custom_target(${LIBRARY_NAME}_pysideuicfiles - ALL - DEPENDS ${outfiles} - ) - install(FILES ${outfiles} - DESTINATION "lib/python/pxr/${LIBRARY_NAME}" - ) -endmacro() # PYSIDE_WRAP_UI - -#XXX -- i haven't fixed this function from the source, but -# wrap_ui was so broken, i suspect this one is too -MACRO(PYSIDE_WRAP_RC outfiles) - FOREACH(it ${ARGN}) - GET_FILENAME_COMPONENT(outfile ${it} NAME_WE) - GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE) - SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/${outfile}_rc.py) - #ADD_CUSTOM_TARGET(${it} ALL - # DEPENDS ${outfile} - #) - if(WIN32) - ADD_CUSTOM_COMMAND(OUTPUT ${outfile} - COMMAND ${PYSIDERCC4BINARY} ${infile} -o ${outfile} - MAIN_DEPENDENCY ${infile} - ) - else(WIN32) - # Especially on Open Build Service we don't want changing date like - # pyside-rcc generates in comments at beginning. - EXECUTE_PROCESS( - COMMAND ${PYSIDERCC4BINARY} ${infile} - COMMAND sed "/^# /d" - OUTPUT_FILE ${outfile} - ) - endif(WIN32) - SET(${outfiles} ${${outfiles}} ${outfile}) - ENDFOREACH(it) -ENDMACRO (PYSIDE_WRAP_RC) - -IF(EXISTS ${PYSIDEUIC4BINARY} AND EXISTS ${PYSIDERCC4BINARY}) - set(PYSIDE_TOOLS_FOUND TRUE) -ENDIF(EXISTS ${PYSIDEUIC4BINARY} AND EXISTS ${PYSIDERCC4BINARY}) - -if(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY) - if (NOT PySideTools_FIND_QUIETLY) - message(STATUS "Found PySide Tools: ${PYSIDEUIC4BINARY}, ${PYSIDERCC4BINARY}") - endif (NOT PySideTools_FIND_QUIETLY) -else(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY) - if(PySideTools_FIND_REQUIRED) - message(FATAL_ERROR "PySideTools could not be found, but are required.") - else(PySideTools_FIND_REQUIRED) - if (NOT PySideTools_FIND_QUIETLY) - message(STATUS "PySideTools: not found.") - endif (NOT PySideTools_FIND_QUIETLY) - endif(PySideTools_FIND_REQUIRED) -endif(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY) diff --git a/extras/usd/examples/CMakeLists.txt b/extras/usd/examples/CMakeLists.txt index 51782b9f73..5cb4dd8c47 100644 --- a/extras/usd/examples/CMakeLists.txt +++ b/extras/usd/examples/CMakeLists.txt @@ -1,6 +1,8 @@ set(PXR_PREFIX examples) set(PXR_INSTALL_SUBDIR share/usd/examples) -add_subdirectory(usdObj) -add_subdirectory(usdSchemaExamples) -add_subdirectory(usdMakeFileVariantModelAsset) +if(UNIX) + add_subdirectory(usdObj) + add_subdirectory(usdSchemaExamples) + add_subdirectory(usdMakeFileVariantModelAsset) +endif() \ No newline at end of file diff --git a/extras/usd/examples/usdSchemaExamples/tokens.h b/extras/usd/examples/usdSchemaExamples/tokens.h index ce731abd25..ab91a39209 100644 --- a/extras/usd/examples/usdSchemaExamples/tokens.h +++ b/extras/usd/examples/usdSchemaExamples/tokens.h @@ -24,6 +24,8 @@ #ifndef USDSCHEMAEXAMPLES_TOKENS_H #define USDSCHEMAEXAMPLES_TOKENS_H +/// \file usdSchemaExamples/tokens.h + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // // This is an automatically generated file (by usdGenSchema.py). @@ -33,8 +35,6 @@ #include "pxr/base/tf/staticTokens.h" -/// \file ./tokens.h - /// \hideinitializer #define USDSCHEMAEXAMPLES_TOKENS \ (complexString) \ @@ -45,7 +45,8 @@ (target) /// \anchor UsdSchemaExamplesTokens -/// \brief UsdSchemaExamplesTokens provides static, efficient TfToken's for +/// +/// UsdSchemaExamplesTokens provides static, efficient TfToken's for /// use in all public USD API /// /// These tokens are auto-generated from the module's schema, representing diff --git a/pxr/base/lib/arch/CMakeLists.txt b/pxr/base/lib/arch/CMakeLists.txt index 1d4b3171df..8f21a47e23 100644 --- a/pxr/base/lib/arch/CMakeLists.txt +++ b/pxr/base/lib/arch/CMakeLists.txt @@ -4,11 +4,22 @@ set(CMAKE_INCLUDE_CURRENT_DIR OFF) set(PXR_PREFIX pxr/base) set(PXR_PACKAGE arch) +if(WIN32) + set(MODULE_ENTRYPOINT_CPP DllMain.cpp) + set(PLATFORM_ATTRIBUTES_H attributesWindows.h) + set(WINLIBS Ws2_32.lib) + set(DEBUG_HELP Dbghelp.lib) +else() + set(MATHLIB ${M_LIB}) +endif() + pxr_shared_library(arch LIBRARIES ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} - ${M_LIB} + ${WINLIBS} + ${MATHLIB} + ${DEBUG_HELP} PUBLIC_CLASSES daemon @@ -30,13 +41,17 @@ pxr_shared_library(arch PUBLIC_HEADERS align.h + api.h attributes.h + ${PLATFORM_ATTRIBUTES_H} buildMode.h defines.h + env.h export.h functionLite.h hints.h inttypes.h + library.h math.h pragmas.h @@ -45,140 +60,145 @@ pxr_shared_library(arch CPPFILES assumptions.cpp + env.cpp + ${MODULE_ENTRYPOINT_CPP} initConfig.cpp + library.cpp ) -pxr_build_test_shared_lib(testArchAbiPlugin - CPPFILES - testenv/testArchAbiPlugin.cpp -) -pxr_build_test(testArchAbi - LIBRARIES - arch - CPPFILES - testenv/testArchAbi.cpp -) -pxr_build_test(testArchAttributes - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testAttributes.cpp -) -pxr_build_test(testArchDemangle - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testDemangle.cpp -) -pxr_build_test(testArchError - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testError.cpp -) -pxr_build_test(testArchErrno - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testErrno.cpp -) -pxr_build_test(testArchFileSystem - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testFileSystem.cpp -) -pxr_build_test(testArchFunction - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testFunction.cpp -) -pxr_build_test(testArchStackTrace - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testStackTrace.cpp -) -pxr_build_test(testArchSymbols - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testSymbols.cpp -) -pxr_build_test(testArchSystemInfo - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testSystemInfo.cpp -) -pxr_build_test(testArchThreads - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testThreads.cpp -) -pxr_build_test(testArchTiming - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testTiming.cpp -) -pxr_build_test(testArchVsnprintf - LIBRARIES - arch - ${CMAKE_DL_LIBS} - CPPFILES - testenv/testVsnprintf.cpp -) +if(UNIX) + pxr_build_test_shared_lib(testArchAbiPlugin + CPPFILES + testenv/testArchAbiPlugin.cpp + ) + pxr_build_test(testArchAbi + LIBRARIES + arch + CPPFILES + testenv/testArchAbi.cpp + ) + pxr_build_test(testArchAttributes + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testAttributes.cpp + ) + pxr_build_test(testArchDemangle + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testDemangle.cpp + ) + pxr_build_test(testArchError + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testError.cpp + ) + pxr_build_test(testArchErrno + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testErrno.cpp + ) + pxr_build_test(testArchFileSystem + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testFileSystem.cpp + ) + pxr_build_test(testArchFunction + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testFunction.cpp + ) + pxr_build_test(testArchStackTrace + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testStackTrace.cpp + ) + pxr_build_test(testArchSymbols + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testSymbols.cpp + ) + pxr_build_test(testArchSystemInfo + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testSystemInfo.cpp + ) + pxr_build_test(testArchThreads + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testThreads.cpp + ) + pxr_build_test(testArchTiming + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testTiming.cpp + ) + pxr_build_test(testArchVsnprintf + LIBRARIES + arch + ${CMAKE_DL_LIBS} + CPPFILES + testenv/testVsnprintf.cpp + ) -pxr_register_test(testArchAbi - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchAbi" -) -pxr_register_test(testArchAttributes - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchAttributes" -) -pxr_register_test(testArchDemangle - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchDemangle" -) -pxr_register_test(testArchError - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchError" -) -pxr_register_test(testArchErrno - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchErrno" -) -pxr_register_test(testArchFileSystem - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchFileSystem" -) -pxr_register_test(testArchFunction - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchFunction" -) -pxr_register_test(testArchStackTrace - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchStackTrace" -) -pxr_register_test(testArchSymbols - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchSymbols" -) -pxr_register_test(testArchSystemInfo - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchSystemInfo" -) -pxr_register_test(testArchTiming - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchTiming" -) -pxr_register_test(testArchThreads - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchThreads" -) -pxr_register_test(testArchVsnprintf - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchVsnprintf" -) + pxr_register_test(testArchAbi + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchAbi" + ) + pxr_register_test(testArchAttributes + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchAttributes" + ) + pxr_register_test(testArchDemangle + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchDemangle" + ) + pxr_register_test(testArchError + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchError" + ) + pxr_register_test(testArchErrno + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchErrno" + ) + pxr_register_test(testArchFileSystem + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchFileSystem" + ) + pxr_register_test(testArchFunction + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchFunction" + ) + pxr_register_test(testArchStackTrace + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchStackTrace" + ) + pxr_register_test(testArchSymbols + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchSymbols" + ) + pxr_register_test(testArchSystemInfo + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchSystemInfo" + ) + pxr_register_test(testArchTiming + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchTiming" + ) + pxr_register_test(testArchThreads + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchThreads" + ) + pxr_register_test(testArchVsnprintf + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchVsnprintf" + ) +endif() \ No newline at end of file diff --git a/pxr/base/lib/arch/DllMain.cpp b/pxr/base/lib/arch/DllMain.cpp new file mode 100644 index 0000000000..6e6fd9e32a --- /dev/null +++ b/pxr/base/lib/arch/DllMain.cpp @@ -0,0 +1,49 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#include +#include "pxr/base/arch/attributes.h" + +BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) +{ + UNREFERENCED_PARAMETER(module); + UNREFERENCED_PARAMETER(reserved); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + archRunConstructors(); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + archRunDestructors(); + break; + } + return TRUE; +} diff --git a/pxr/base/lib/arch/align.h b/pxr/base/lib/arch/align.h index 74af9842a7..89aab2e3f1 100644 --- a/pxr/base/lib/arch/align.h +++ b/pxr/base/lib/arch/align.h @@ -24,6 +24,10 @@ #ifndef ARCH_ALIGN_H #define ARCH_ALIGN_H +/// \file arch/align.h +/// \ingroup group_arch_Memory +/// Provide architecture-specific memory-alignment information. + #if !defined(__cplusplus) #error This include file can only be included in C++ programs. #endif @@ -32,51 +36,34 @@ #include #include -/*! - * \file align.h - * \brief Provide architecture-specific memory-alignment information. - * \ingroup group_arch_Memory - */ - -/* - * This is valid on all our current platforms, both for 32-bit and - * 64-bit compiles. - */ - -/*! - * \brief Return suitably aligned memory size. - * \ingroup group_arch_Memory - * - * Requests to \c malloc() or \c ::new for a given size are often - * rounded upward. Given a request for \c nBytes bytes of storage, - * this function returns the amount that would actually be consumed - * by the system to satisfy it. This is needed for efficient user-defined - * memory management (which you should \e NOT do yourself: see - * instead \c classAllocator.h). [Ensure this filename is correct] - */ +/// \addtogroup group_arch_Memory +///@{ +/// Return suitably aligned memory size. +/// +/// Requests to \c malloc() or \c ::new for a given size are often rounded +/// upward. Given a request for \c nBytes bytes of storage, this function +/// returns the amount that would actually be consumed by the system to +/// satisfy it. This is needed for efficient user-defined memory management. +/// inline size_t ArchAlignMemorySize(size_t nBytes) { return (nBytes + 7) & (~0x7); } -/*! - * \brief Maximum extra space needed for alignment. - * \ingroup group_arch_Memory - * \hideinitializer - * - * The \c ArchAlignMemorySize() can increase the required memory by no more - * than \c ARCH_MAX_ALIGNMENT_INCREASE. - */ +/// Maximum extra space needed for alignment. +/// +/// The \c ArchAlignMemorySize() can increase the required memory by no more +/// than \c ARCH_MAX_ALIGNMENT_INCREASE. +/// +/// \hideinitializer #define ARCH_MAX_ALIGNMENT_INCREASE 7 -/*! - * \brief Align memory to the next "best" alignment value. - * \ingroup group_arch_Memory - * - * This will take a pointer and bump it to the next ideal alignment boundary - * that will work for all data types. - */ +/// Align memory to the next "best" alignment value. +/// +/// This will take a pointer and bump it to the next ideal alignment boundary +/// that will work for all data types. +/// inline void * ArchAlignMemory(void *base) { @@ -84,13 +71,11 @@ ArchAlignMemory(void *base) ((reinterpret_cast(base) + 7) & ~0x7); } -/*! - * \brief The size of a CPU cache line in bytes. - * \ingroup group_arch_Memory - * - * The size of a CPU cache line on the current processor architecture in bytes. - */ +/// The size of a CPU cache line on the current processor architecture in bytes. +/// +/// \hideinitializer #define ARCH_CACHE_LINE_SIZE 64 +///@} #endif // ARCH_ALIGN_H diff --git a/pxr/base/lib/arch/api.h b/pxr/base/lib/arch/api.h new file mode 100644 index 0000000000..87ffa3537b --- /dev/null +++ b/pxr/base/lib/arch/api.h @@ -0,0 +1,46 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef ARCH_API_H +#define ARCH_API_H + +#include "pxr/base/arch/export.h" + +#if defined(ARCH_STATIC) +# define ARCH_API +# define ARCH_LOCAL +#else +# if defined(ARCH_EXPORTS) +# define ARCH_API ARCH_EXPORT +# define ARCH_API_TEMPLATE_CLASS(...) +# define ARCH_API_TEMPLATE_STRUCT(...) +# else +# define ARCH_API ARCH_IMPORT +# define ARCH_API_TEMPLATE_CLASS(...) extern template class ARCH_API __VA_ARGS__ +# define ARCH_API_TEMPLATE_STRUCT(...) extern template struct ARCH_API __VA_ARGS__ +# endif +# define ARCH_LOCAL ARCH_HIDDEN +#endif + +#endif diff --git a/pxr/base/lib/arch/assumptions.cpp b/pxr/base/lib/arch/assumptions.cpp index 54f230ee13..97f2ca9212 100644 --- a/pxr/base/lib/arch/assumptions.cpp +++ b/pxr/base/lib/arch/assumptions.cpp @@ -28,11 +28,14 @@ #include "pxr/base/arch/export.h" #include "pxr/base/arch/math.h" #include +#include #if defined(ARCH_OS_LINUX) #include #elif defined(ARCH_OS_DARWIN) #include +#elif defined(ARCH_OS_WINDOWS) +#include #endif static size_t @@ -45,6 +48,39 @@ Arch_ObtainCacheLineSize() size_t cacheLineSizeSize = sizeof(cacheLineSize); sysctlbyname("hw.cachelinesize", &cacheLineSize, &cacheLineSizeSize, 0, 0); return cacheLineSize; +#elif defined(ARCH_OS_DARWIN) + size_t cacheLineSize = 0; + size_t cacheLineSizeSize = sizeof(cacheLineSize); + sysctlbyname("hw.cachelinesize", &cacheLineSize, &cacheLineSizeSize, 0, 0); + return cacheLineSize; +#elif defined(ARCH_OS_WINDOWS) + DWORD bufferSize = 0; + using INFO = SYSTEM_LOGICAL_PROCESSOR_INFORMATION; + + // Get the number of bytes required. + ::GetLogicalProcessorInformation(nullptr, &bufferSize); + + // Get the count of structures + size_t total = bufferSize / sizeof(INFO); + + // Allocate the array of processor INFOs. + std::unique_ptr buffer(new INFO[total]); + + size_t lineSize = 0; + if (::GetLogicalProcessorInformation(&buffer[0], &bufferSize)) + { + for (size_t current = 0; current != total; ++current) + { + if (buffer[current].Relationship == RelationCache && + 1 == buffer[current].Cache.Level) + { + lineSize = buffer[current].Cache.LineSize; + break; + } + } + } + + return lineSize; #else #error Arch_ObtainCacheLineSize not implemented for OS. #endif @@ -69,12 +105,15 @@ Arch_ValidateAssumptions() /* * Some lib/tf coding depends on size_t and long being the same size. */ +#if !defined(ARCH_OS_WINDOWS) if (sizeof(size_t) != sizeof(unsigned long)) - ARCH_ERROR("size_t and unsigned long are different sizes"); + ARCH_ERROR("size_t and unsigned long are different sizes"); +#endif /* * endian.h needs to know how big various types are for its * swabbing routines. */ +#if !defined(ARCH_OS_WINDOWS) #if defined(ARCH_BITS_64) if (sizeof(long) != 8) ARCH_ERROR("sizeof(long) != 8 [64-bit mode]"); @@ -82,7 +121,7 @@ Arch_ValidateAssumptions() if (sizeof(long) != 4) ARCH_ERROR("sizeof(long) != 4 [32-bit mode]"); #endif - +#endif /* * Verify that the exponent and significand of float and double are * IEEE-754 compliant. diff --git a/pxr/base/lib/arch/attributes.h b/pxr/base/lib/arch/attributes.h index ce5914c80f..4f02e65efc 100644 --- a/pxr/base/lib/arch/attributes.h +++ b/pxr/base/lib/arch/attributes.h @@ -24,8 +24,24 @@ #ifndef ARCH_ATTRIBUTES_H #define ARCH_ATTRIBUTES_H +/// \file arch/attributes.h +/// Define function attributes. +/// +/// This file allows you to define architecture-specific or compiler-specific +/// options to be used outside lib/arch. + #include "pxr/base/arch/export.h" +/*! +* \brief Macro to stringify a symbol. +*/ +#define ARCH_STRINGIFY(x) #x + +/*! +* \brief Macro to use for substitution. +*/ +#define ARCH_PP_EXPAND(x) x + /*! * \file attributes.h * \brief Define function attributes. @@ -37,7 +53,109 @@ #if defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG) || \ defined(doxygen) -/*! +/// Macro used to indicate a function takes a printf-like specification. +/// +/// This attribute is used as follows: +/// \code +/// void PrintFunc(T1 arg1, T2 arg2, const char* fmt, ...) +/// ARCH_PRINTF_FUNCTION(3, 4) +/// \endcode +/// This indicates that the third argument is the format string, and that the +/// fourth argument is where the var-args corresponding to the format string begin. +/// +/// \hideinitializer +# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg) \ + __attribute__((format(printf, _fmt, _firstArg))) + +/// Macro used to indicate a function takes a scanf-like specification. +/// +/// This attribute is used as follows: +/// \code +/// void ScanFunc(T1 arg1, T2 arg2, const char* fmt, ...) +/// ARCH_PRINTF_FUNCTION(3, 4) +/// \endcode +/// This indicates that the third argument is the format string, and +/// that the fourth argument is where the var-args corresponding to the +/// format string begin. +/// +/// \hideinitializer +# define ARCH_SCANF_FUNCTION(_fmt, _firstArg) \ + __attribute__((format(scanf, _fmt, _firstArg))) + +/// Macro used to indicate that a function should never be inlined. +/// +/// This attribute is used as follows: +/// \code +/// void Func(T1 arg1, T2 arg2) ARCH_NOINLINE; +/// \endcode +/// +/// \hideinitializer +# define ARCH_NOINLINE __attribute__((noinline)) + +/// Macro used to indicate a function parameter may be unused. +/// +/// In general, avoid this attribute if possible. Mostly this attribute +/// should be used when the set of arguments to a function is described +/// as part of a macro. The usage is: +/// \code +/// void Func(T1 arg1, ARCH_UNUSED_ARG T2 arg2, ARCH_UNUSED_ARG T3 arg3, T4 arg4) { +/// ... +/// } +/// \endcode +/// +/// \hideinitializer +# define ARCH_UNUSED_ARG __attribute__ ((unused)) + +/// Macro used to indicate that a function's code must always be emitted even +/// if not required. +/// +/// This attribute is especially useful with templated registration functions, +/// which might not be present in the linked binary if they are not used (or +/// the compiler optimizes away their use.) +/// +/// The usage is: +/// \code +/// template +/// struct TraitsClass { +/// static void RegistryFunction() ARCH_USED_FUNCTION { +/// ... +/// } +/// }; +/// \endcode +/// +/// \hideinitializer +# define ARCH_USED_FUNCTION __attribute__((used)) + +/// Macro to indicate a function should be executed by the dynamic loader when +/// the dynamic object (library or program) is loaded. +/// +/// The priority is used to order the execution of constructors. Valid +/// values are integers over 100. Constructors with lower numbers are +/// run first. Constructors for C++ objects at global scope are run +/// after these functions regardless of priority. +/// +/// \hideinitializer +# define ARCH_CONSTRUCTOR_DEFINE(_priority, _name, ...) \ + __attribute__((constructor(_priority))) \ + static void _name(__VA_ARGS__) + +/// Macro to indicate a function should be executed by the dynamic loader when +/// the dynamic object (library or program) is unloaded. +/// +/// The priority is used to order the execution of destructors. Valid +/// values are integers over 100. Destructors with higher numbers are +/// run first. +/// +/// \hideinitializer +# define ARCH_DESTRUCTOR(_priority, _name, ...) \ + __attribute__((destructor(_priority))) \ + static void _name(__VA_ARGS__) + +#elif defined(ARCH_COMPILER_MSVC) + +#include + + /*! * \hideinitializer * \brief Macro used to indicate a function takes a printf-like specification. * @@ -50,8 +168,8 @@ * fourth argument is where the var-args corresponding to the format string begin. */ # define ARCH_PRINTF_FUNCTION(_fmt, _firstArg) \ - __attribute__((format(printf, _fmt, _firstArg))) -/*! + _Printf_format_string_ + /*! * \hideinitializer * \brief Macro used to indicate a function takes a scanf-like specification. * @@ -65,9 +183,9 @@ * format string begin. */ # define ARCH_SCANF_FUNCTION(_fmt, _firstArg) \ - __attribute__((format(scanf, _fmt, _firstArg))) + _Printf_format_string_ -/*! + /*! * \hideinitializer * \brief Macro used to indicate that a function should never be inlined * @@ -76,9 +194,9 @@ * void Func(T1 arg1, T2 arg2) ARCH_NOINLINE; * \endcode */ -# define ARCH_NOINLINE __attribute__((noinline)) +# define ARCH_NOINLINE // __declspec(noinline) -/*! + /*! * \hideinitializer * \brief Macro used to indicate a function parameter may be unused. * @@ -91,9 +209,9 @@ * } * \endcode */ -# define ARCH_UNUSED_ARG __attribute__ ((unused)) +# define ARCH_UNUSED_ARG -/*! + /*! * \brief Macro used to indicate that a function's code must always be emitted * even if not required. * @@ -111,38 +229,29 @@ * }; * \endcode */ -# define ARCH_USED_FUNCTION __attribute__((used)) +# define ARCH_USED_FUNCTION -/*! - * \brief Macro to indicate a function should be executed by the dynamic - * loader when the dynamic object (library or program) is loaded. - * - * The priority is used to order the execution of constructors. Valid - * values are integers over 100. Constructors with lower numbers are - * run first. Constructors for C++ objects at global scope are run - * after these functions regardless of priority. + /*! + * \brief Macro to ensure the linker does not strip a symbol. */ -# define ARCH_CONSTRUCTOR(_priority) __attribute__((constructor(_priority))) +# define ARCH_NO_STRIP_SYMBOL(x) __pragma(comment(linker,"/include:__" ## x)) -/*! - * \brief Macro to indicate a function should be executed by the dynamic - * loader when the dynamic object (library or program) is unloaded. - * - * The priority is used to order the execution of destructors. Valid - * values are integers over 100. Destructors with higher numbers are - * run first. + /*! + * \brief ARCH_CONSTRUCTOR and ARCH_DESTRUCTOR are defined in a separate + * file for Windows due to the amount of platform specific code + * involved. */ -# define ARCH_DESTRUCTOR(_priority) __attribute__((destructor(_priority))) +#include "pxr/base/arch/attributesWindows.h" #else # define ARCH_PRINTF_FUNCTION(_fmt, _firstArg) # define ARCH_SCANF_FUNCTION(_fmt, _firstArg) # define ARCH_NOINLINE # define ARCH_UNUSED_ARG -/* ARCH_USED_FUNCTION is deliberately omitted. If a new compiler is deployed, - * we want the build to fail rather than generate executables that will fail - * at runtime in potentially mysterious ways. Similarly ARCH_CONSTRUCTOR - * and ARCH_DESTRUCTOR. */ -#endif /* defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG) */ +// ARCH_USED_FUNCTION is deliberately omitted. If a new compiler is deployed, +// we want the build to fail rather than generate executables that will fail +// at runtime in potentially mysterious ways. Similarly ARCH_CONSTRUCTOR and +// ARCH_DESTRUCTOR. +#endif // defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG) #endif // ARCH_ATTRIBUTES_H diff --git a/pxr/base/lib/arch/attributesWindows.h b/pxr/base/lib/arch/attributesWindows.h new file mode 100644 index 0000000000..fdc111fdf4 --- /dev/null +++ b/pxr/base/lib/arch/attributesWindows.h @@ -0,0 +1,125 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#ifndef ARCH_ATTRIBUTES_WINDOWS_H +#define ARCH_ATTRIBUTES_WINDOWS_H + +#pragma section(".pxr$a", read) +#pragma section(".pxr$c", read) +#pragma section(".pxr$e", read) + +typedef void(__cdecl *Arch_CtorType )(void); + +template +struct Arch_CtorA +{ + __declspec(allocate(".pxr$a")) static Arch_CtorType x; +}; +template Arch_CtorType Arch_CtorA::x; + +template +struct Arch_CtorC +{ + __declspec(allocate(".pxr$c")) static Arch_CtorType x; +}; +template Arch_CtorType Arch_CtorC::x; + +template +struct Arch_CtorE +{ + __declspec(allocate(".pxr$e")) static Arch_CtorType x; +}; +template Arch_CtorType Arch_CtorE::x; + +template struct Arch_CtorA; +template struct Arch_CtorC; +template struct Arch_CtorE; + +#define ARCH_PRIORITY_CAT(section, priority) ARCH_STRINGIFY(section ## priority) + +#define ARCH_CONSTRUCTOR_DEFINE(priority, name, ...) \ + static void name(__VA_ARGS__); \ + __pragma(section(ARCH_PRIORITY_CAT(.pxr$b, priority), read)) \ + __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$b, priority))) \ + Arch_CtorType tf_ctor_ ## name = (Arch_CtorType )&name; \ + static void name(__VA_ARGS__) + +#define ARCH_CONSTRUCTOR(priority, tag, name) \ + __pragma(section(ARCH_PRIORITY_CAT(.pxr$b, priority), read)) \ + __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$b, priority))) \ + Arch_CtorType tf_ctor_ ## tag = (Arch_CtorType )&name; \ + +#define ARCH_DESTRUCTOR(priority, name, ...) \ + static void name(__VA_ARGS__); \ + __pragma(section(ARCH_PRIORITY_CAT(.pxr$d, priority), read)) \ + __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$d, priority))) \ + Arch_CtorType tf_dtor_ ## name = (Arch_CtorType )&name; \ + static void name(__VA_ARGS__) + +#define ARCH_CONSTRUCTOR_TEMPLATE_DECLARE(priority, name, ...) \ + __pragma(section(ARCH_PRIORITY_CAT(.pxr$b, priority), read)) \ + __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$b, priority))) \ + static Arch_CtorType tf_ctor_ ## name; \ + static void name(__VA_ARGS__) + +#define ARCH_DESTRUCTOR_TEMPLATE_DECLARE(priority, name, ...) \ + __pragma(section(ARCH_PRIORITY_CAT(.pxr$d, priority), read)) \ + __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$d, priority))) \ + static Arch_CtorType tf_dtor_ ## name; \ + static void name(__VA_ARGS__) + +#define ARCH_CONSTRUCTOR_TEMPLATE_DEFINE(priority, scope, name, ...) \ +template <> Arch_CtorType scope::tf_ctor_ ## name = (Arch_CtorType)&scope::name + +#define ARCH_DESTRUCTOR_TEMPLATE_DEFINE(priority, scope, name, ...) \ +template <> Arch_CtorType scope::tf_dtor_ ## name = (Arch_CtorType)&scope::name + + +#define archRunConstructors() \ + { \ + Arch_CtorType * i = &Arch_CtorA::x; \ + Arch_CtorType * n = &Arch_CtorC::x; \ + \ + while (++i != n) \ + { \ + if (*i) \ + { \ + (*i)(); \ + } \ + } \ + } + +#define archRunDestructors() \ + { \ + Arch_CtorType * i = &Arch_CtorE::x; \ + Arch_CtorType * n = &Arch_CtorC::x; \ + \ + while (--i != n) \ + { \ + if (*i) \ + { \ + (*i)(); \ + } \ + } \ + } +#endif // ARCH_ATTRIBUTES_WINDOWS_H diff --git a/pxr/base/lib/arch/buildMode.h b/pxr/base/lib/arch/buildMode.h index 50ad74cef4..8181188a2f 100644 --- a/pxr/base/lib/arch/buildMode.h +++ b/pxr/base/lib/arch/buildMode.h @@ -30,11 +30,6 @@ #error This include file can be included only in C++ programs. #endif -/* - * The various flavor Makefiles are responsible for defining - * either BUILD_OPTLEVEL_DEV or BUILD_OPTLEVEL_OPT. - */ - struct ArchBuildMode { #if defined(BUILD_OPTLEVEL_DEV) diff --git a/pxr/base/lib/arch/daemon.cpp b/pxr/base/lib/arch/daemon.cpp index b523927022..c89b601a64 100644 --- a/pxr/base/lib/arch/daemon.cpp +++ b/pxr/base/lib/arch/daemon.cpp @@ -21,6 +21,10 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/defines.h" + +#if !defined(ARCH_OS_WINDOWS) + #include "pxr/base/arch/daemon.h" #include #include @@ -109,3 +113,5 @@ int ArchCloseAllFiles(int nExcept, const int* exceptFds) return retStatus; } + +#endif // #if !defined(ARCH_OS_WINDOWS) \ No newline at end of file diff --git a/pxr/base/lib/arch/daemon.h b/pxr/base/lib/arch/daemon.h index 6261de5b98..6dea0c01d0 100644 --- a/pxr/base/lib/arch/daemon.h +++ b/pxr/base/lib/arch/daemon.h @@ -24,42 +24,37 @@ #ifndef ARCH_DAEMON_H #define ARCH_DAEMON_H -/*! - * \file daemon.h - * \brief Create background or daemon processes. - * \ingroup group_arch_Multithreading - */ +/// \file arch/daemon.h +/// \ingroup group_arch_Multithreading +/// Create background or daemon processes. -/*! - * \brief Close all file descriptors (with possible exceptions) - * \ingroup group_arch_Multithreading - * - * \c ArchCloseAllFiles will close all file descriptors open in the - * current process. Occasionally you'd like to close all files except - * for some small subset (like 0, 1, and 2). The \p nExcept and \p - * exceptFds arguments can be used to provide the list of exceptions. - * \c ArchDaemonizeProcess uses this method to close all unwanted file - * descriptors in the daemon process. - * - * \p nExcept should be the number of elements in the \p exceptFds array. - * Invalid file descriptors in exceptFds are ignored. - * - * \note Be \b very careful when using this routine. It is intended - * to be used after a \c fork(2) call to close \b all unwanted file - * descriptors. However, it does not flush stdio buffers, wait for - * processes opened with popen, shut down the X11 display connection, - * or anything. It just slams closed all the file descriptors. This - * is appropriate following a \c fork(2) call as all these file - * descriptors are duplicates of the ones in the parent process and - * shutting down the X11 display connection would mess up the parent's - * X11 display. But you shouldn't use \c ArchCloseAllFiles unless you - * know what you are doing. - * - * \return -1 on error and \c errno will be set to an appropriate - * value. Returns 0 on success. - * - * \sa ArchDaemonizeProcess - */ +/// Close all file descriptors (with possible exceptions) +/// +/// \c ArchCloseAllFiles will close all file descriptors open in the +/// current process. Occasionally you'd like to close all files except +/// for some small subset (like 0, 1, and 2). The \p nExcept and \p +/// exceptFds arguments can be used to provide the list of exceptions. +/// \c ArchDaemonizeProcess uses this method to close all unwanted file +/// descriptors in the daemon process. +/// +/// \p nExcept should be the number of elements in the \p exceptFds array. +/// Invalid file descriptors in exceptFds are ignored. +/// +/// \note Be \b very careful when using this routine. It is intended +/// to be used after a \c fork(2) call to close \b all unwanted file +/// descriptors. However, it does not flush stdio buffers, wait for +/// processes opened with popen, shut down the X11 display connection, +/// or anything. It just slams closed all the file descriptors. This +/// is appropriate following a \c fork(2) call as all these file +/// descriptors are duplicates of the ones in the parent process and +/// shutting down the X11 display connection would mess up the parent's +/// X11 display. But you shouldn't use \c ArchCloseAllFiles unless you +/// know what you are doing. +/// +/// \return -1 on error and \c errno will be set to an appropriate +/// value. Returns 0 on success. +/// +/// \ingroup group_arch_Multithreading int ArchCloseAllFiles(int nExcept, const int* exceptFds); #endif // ARCH_DAEMON_H diff --git a/pxr/base/lib/arch/debugger.cpp b/pxr/base/lib/arch/debugger.cpp index 293f688ec2..2f81dfe8c1 100644 --- a/pxr/base/lib/arch/debugger.cpp +++ b/pxr/base/lib/arch/debugger.cpp @@ -25,6 +25,7 @@ #include "pxr/base/arch/debugger.h" #include "pxr/base/arch/daemon.h" +#include "pxr/base/arch/env.h" #include "pxr/base/arch/error.h" #include "pxr/base/arch/export.h" #include "pxr/base/arch/stackTrace.h" @@ -44,11 +45,11 @@ #include #include #include -#endif -#if defined(ARCH_OS_WINDOWS) +#elif defined(ARCH_OS_WINDOWS) #include #include #endif +#include // We don't want this inlined so ArchDebuggerTrap() is as clean as // possible. The fewer instructions in that function, the more likely @@ -451,7 +452,7 @@ Arch_InitDebuggerAttach() // Parse the contents of the ARCH_DEBUGGER environment variable and // store the result. This way we can avoid using the heap or tricky // stack allocations when launching the debugger. - char* e = getenv("ARCH_DEBUGGER"); + const char* e = ArchGetEnv("ARCH_DEBUGGER"); if (e and e[0]) { std::string link; diff --git a/pxr/base/lib/arch/debugger.h b/pxr/base/lib/arch/debugger.h index 22996813f6..89c90fd13e 100644 --- a/pxr/base/lib/arch/debugger.h +++ b/pxr/base/lib/arch/debugger.h @@ -24,11 +24,13 @@ #ifndef ARCH_DEBUGGER_H #define ARCH_DEBUGGER_H -/// \file debugger.h +/// \file arch/debugger.h +/// Routines for interacting with a debugger. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/attributes.h" -/// \brief Stop in a debugger. +/// Stop in a debugger. /// /// This function will do one of the following: start a debugger /// attached to this process stopped on this function; stop in an @@ -50,18 +52,20 @@ /// attached terminal by putting the process into the foreground or /// background. /// +ARCH_API void ArchDebuggerTrap() ARCH_NOINLINE; -/// \brief Cause debug traps to wait for the debugger or not. +/// Cause debug traps to wait for the debugger or not. /// /// When \p wait is \c true the next call to \c ArchDebuggerTrap() /// will cause the process to wait for a signal. The user can attach /// a debugger to continue the process. The process will not wait /// again until another call to this function with \p wait \c true. /// +ARCH_API void ArchDebuggerWait(bool wait); -/// \brief Attach a debugger +/// Attach a debugger. /// /// Attaches the debugger by running the contents of the enviroment variable /// ARCH_DEBUGGER using /bin/sh. Any '%p' in the contents of this variable @@ -70,14 +74,16 @@ void ArchDebuggerWait(bool wait); /// /// Returns true if ARCH_DEBUGGER is set and the debugger was successfully /// launched, otherwise returns false. +ARCH_API bool ArchDebuggerAttach() ARCH_NOINLINE; -/// \brief Test if a debugger is attached +/// Test if a debugger is attached /// /// Attempts to detect if a debugger is currently attached to the process. +ARCH_API bool ArchDebuggerIsAttached() ARCH_NOINLINE; -/// \brief Stop in the debugger. +/// Stop in the debugger. /// /// This macro expands to \c ArchDebuggerTrap() and, if necessary and /// possible, code to prevent optimization so the caller appears in the diff --git a/pxr/base/lib/arch/defines.h b/pxr/base/lib/arch/defines.h index 0fd5b2d0c7..0a4444bc0b 100644 --- a/pxr/base/lib/arch/defines.h +++ b/pxr/base/lib/arch/defines.h @@ -24,9 +24,9 @@ #ifndef ARCH_DEFINES_H #define ARCH_DEFINES_H -/* - * OS - */ +// +// OS +// #if defined(__linux__) #define ARCH_OS_LINUX @@ -42,9 +42,9 @@ #define ARCH_OS_WINDOWS #endif -/* - * Processor - */ +// +// Processor +// #if defined(i386) || defined(__i386__) || defined(__x86_64__) || \ defined(_M_IX86) || defined(_M_X64) @@ -53,11 +53,9 @@ #define ARCH_CPU_ARM #endif - - -/* - * Bits - */ +// +// Bits +// #if defined(__x86_64__) || defined(__aarch64__) || defined(_M_X64) #define ARCH_BITS_64 @@ -65,11 +63,9 @@ #error "Unsupported architecture. x86_64 or ARM64 required." #endif - - -/* - * Compiler - */ +// +// Compiler +// #if defined(__clang__) #define ARCH_COMPILER_CLANG @@ -85,14 +81,13 @@ #define ARCH_COMPILER_ICC #elif defined(_MSC_VER) #define ARCH_COMPILER_MSVC -#define ARCH_COMPILER_MSVC_VERSION _MSC_VER +#define ARCH_COMPILER_MSVC_VERSION _MSC_VER #endif +// +// Features +// - -/* - * Features - */ // XXX -- This is an interim solution during the port to C++11. We want to // use pure C++11 so we don't want to use the __typeof__ extension. // Once we don't require backward compatibility we can find and fix @@ -115,6 +110,11 @@ template struct Arch_TypeOfRemoveReference { typedef T type; }; template struct Arch_TypeOfRemoveReference { typedef T type; }; #define ARCH_TYPEOF(x) typename Arch_TypeOfRemoveReference::type +#elif defined(ARCH_OS_WINDOWS) +#define ARCH_TYPEOF(x) decltype(x) +#else +// This extension is widely supported so fallback to it. +#define ARCH_TYPEOF __typeof__ #endif // The current version of Apple clang does not support the thread_local @@ -128,4 +128,9 @@ template struct Arch_TypeOfRemoveReference { typedef T type; }; #define ARCH_HAS_MMAP_MAP_POPULATE #endif +// Some static asserts are not supported due to difference in size types. +#if defined(ARCH_OS_LINUX) + #define ARCH_COMPILER_HAS_STATIC_ASSERT +#endif + #endif // ARCH_DEFINES_H diff --git a/pxr/base/lib/arch/demangle.cpp b/pxr/base/lib/arch/demangle.cpp index 38c127bc39..4b821c324e 100644 --- a/pxr/base/lib/arch/demangle.cpp +++ b/pxr/base/lib/arch/demangle.cpp @@ -74,6 +74,23 @@ _FixupStringNames(string* name) while ((pos = name->find("std::", pos)) != string::npos) { name->erase(pos, 5); } + +#if defined(ARCH_OS_WINDOWS) + pos = 0; + while ((pos = name->find("class", pos)) != string::npos) { + name->erase(pos, 6); + } + + pos = 0; + while ((pos = name->find("struct", pos)) != string::npos) { + name->erase(pos, 7); + } + + pos = 0; + while ((pos = name->find("enum", pos)) != string::npos) { + name->erase(pos, 5); + } +#endif } #if defined(ARCH_COMPILER_ICC) diff --git a/pxr/base/lib/arch/demangle.h b/pxr/base/lib/arch/demangle.h index 0cd270a4b6..0a7a59c0de 100644 --- a/pxr/base/lib/arch/demangle.h +++ b/pxr/base/lib/arch/demangle.h @@ -28,41 +28,35 @@ #error This include file can only be included in C++ programs. #endif -/*! - * \file demangle.h - * \brief Demangle C++ typenames generated by the \c typeid() facility. - * \ingroup group_arch_Strings - */ +/// \file arch/demangle.h +/// \ingroup group_arch_Strings +/// Demangle C++ typenames generated by the \c typeid() facility. +#include "pxr/base/arch/api.h" #include #include #include +/// \addtogroup group_arch_Strings +///@{ -/*! - * \brief Demangle RTTI generated type-name. - * \ingroup group_arch_Strings - * - * Given a variable \c v, the construct \c typeid(v).name() returns - * the type-name of \c v; unfortunately, the returned type-name is - * sometimes extremely encoded (otherwise known as "mangled"). - * \c ArchDemangle parses the passed in type-name \c typeName into a - * readable form, and overwrites \c typeName. If \c typeName - * cannot be unmangled, the function returns \c false without altering - * \c typeName. Otherwise \c true is returned. - */ +/// Demangle RTTI-generated type name. +/// +/// Given a variable \c v, the construct \c typeid(v).name() returns +/// the type-name of \c v; unfortunately, the returned type-name is +/// sometimes extremely encoded (otherwise known as "mangled"). +/// \c ArchDemangle parses the passed in type-name \c typeName into a +/// readable form, and overwrites \c typeName. If \c typeName +/// cannot be unmangled, the function returns \c false without altering +/// \c typeName. Otherwise \c true is returned. +ARCH_API bool ArchDemangle(std::string* typeName); - -bool ArchDemangle(std::string* typeName); - -/*! - * \brief Return demangled RTTI generated-type name. - * \ingroup group_arch_Strings - * - * If \c typeName can be demangled, the function returns the demangled - * string; otherwise, the function returns the empty string. - * See \c ArchDemangle() for details. - */ +/// Return demangled RTTI-generated type name. +/// +/// If \c typeName can be demangled, the function returns the demangled +/// string; otherwise, the function returns the empty string. +/// +/// \see ArchDemangle() inline std::string ArchGetDemangled(const std::string& typeName) { @@ -72,46 +66,44 @@ ArchGetDemangled(const std::string& typeName) return std::string(); } -/*! - * \brief Return demangled RTTI generated-type name. - * \ingroup group_arch_Strings - * \overload - * - * Returns the demangled name associated with typeInfo (i.e. typeInfo.name()). - * See \c ArchDemangle() for details. - */ +/// Return demangled RTTI-generated type name. +/// +/// Returns the demangled name associated with typeInfo (i.e. typeInfo.name()). +/// +/// \see ArchDemangle() +/// \overload inline std::string ArchGetDemangled(const std::type_info& typeInfo) { return ArchGetDemangled(typeInfo.name()); } -/*! - * \brief Return demangled RTTI generated-type name. - * \ingroup group_arch_Strings - * \overload - * - * Returns the demangled name associated with typeIndex (i.e. typeIndex.name()). - * See \c ArchDemangle() for details. - */ +/// Return demangled RTTI-generated type name. +/// +/// Returns the demangled name associated with typeIndex (i.e. typeIndex.name()). +/// +/// \see ArchDemangle() +/// \overload inline std::string ArchGetDemangled(const std::type_index& typeIndex) { return ArchGetDemangled(typeIndex.name()); } -/*! - * \brief Return demangled RTTI generated-type name. - * \ingroup group_arch_Strings - * \overload - * - * Returns the demangled name of type T. - * See \c ArchDemangle() for details. - */ +/// Return demangled RTTI generated-type name. +/// +/// Returns the demangled name of type T. +/// +/// \see ArchDemangle() +/// \overload template inline std::string ArchGetDemangled() { return ArchGetDemangled(typeid(T).name()); } +///@} + +/// \private +ARCH_API void Arch_DemangleFunctionName(std::string* functionName); #endif // ARCH_DEMANGLE_H diff --git a/pxr/base/lib/arch/env.cpp b/pxr/base/lib/arch/env.cpp new file mode 100644 index 0000000000..e7a32bd452 --- /dev/null +++ b/pxr/base/lib/arch/env.cpp @@ -0,0 +1,74 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#include "pxr/base/arch/env.h" +#include "pxr/base/arch/error.h" + +const char* ArchGetEnv(const std::string &name) +{ +#if defined(ARCH_OS_WINDOWS) + size_t requiredSize; + + getenv_s(&requiredSize, NULL, 0, name.c_str()); + if (requiredSize) + { + static std::string result; + + if (requiredSize < result.size()) + result.resize(requiredSize); + + getenv_s(&requiredSize, &result[0], requiredSize, name.c_str()); + return result.c_str(); + } + else + return nullptr; + +#else + return getenv(name.c_str()); +#endif +} + +bool ArchSetEnv(const std::string &name, const std::string &value, int overwrite) +{ +#if defined(ARCH_OS_WINDOWS) + if (_putenv_s(name.c_str(), value.c_str()) == 0) +#else + if (setenv(name.c_str(), value.c_str(), overwrite) == 0) +#endif + return true; + + ARCH_WARNING("Error setting an environment variable"); + return false; +} + +bool ArchRemoveEnv(const std::string &name) +{ +#if defined(ARCH_OS_WINDOWS) + if (_putenv_s(name.c_str(), nullptr) == 0) +#else + if (unsetenv(name.c_str()) == 0) +#endif + return true; + + return false; +} \ No newline at end of file diff --git a/pxr/base/lib/arch/env.h b/pxr/base/lib/arch/env.h new file mode 100644 index 0000000000..6d45eb235e --- /dev/null +++ b/pxr/base/lib/arch/env.h @@ -0,0 +1,59 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#ifndef ARCH_ENV_H +#define ARCH_ENV_H + +#include "pxr/base/arch/api.h" + +#include + +/*! + * \file env.h + * \brief Architecture dependent access to environment variables. + * \ingroup group_arch_SystemFunctions + */ + + +/*! +* \brief Gets a value from the current environment identified by \c name. +* \ingroup group_arch_SystemFunctions +*/ +ARCH_API +const char* ArchGetEnv(const std::string &name); + +/*! + * \brief Creates or modifies an environment variable. + * \ingroup group_arch_SystemFunctions + */ +ARCH_API +bool ArchSetEnv(const std::string &name, const std::string &value, int overwrite); + +/*! +* \brief Removes an environment variable. +* \ingroup group_arch_SystemFunctions +*/ +ARCH_API +bool ArchRemoveEnv(const std::string &name); + +#endif // ARCH_ENV_H diff --git a/pxr/base/lib/arch/errno.cpp b/pxr/base/lib/arch/errno.cpp index 0809135786..c34b6d76ce 100644 --- a/pxr/base/lib/arch/errno.cpp +++ b/pxr/base/lib/arch/errno.cpp @@ -21,10 +21,14 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/defines.h" #include "pxr/base/arch/errno.h" #include "pxr/base/arch/defines.h" #include #include +#if defined(ARCH_OS_WINDOWS) +#include +#endif std::string ArchStrerror() @@ -58,3 +62,31 @@ ArchStrerror(int errorCode) #endif return msg_buf; } + +std::string ArchStrSysError(unsigned long errorCode) +{ +#if defined(ARCH_OS_WINDOWS) + if(errorCode == 0) + return std::string(); + + LPSTR buffer = nullptr; + size_t len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&buffer, + 0, + nullptr); + + std::string message(buffer, len); + + OutputDebugString(buffer); + LocalFree(buffer); + + return message; +#else + return std::string(); +#endif +} \ No newline at end of file diff --git a/pxr/base/lib/arch/errno.h b/pxr/base/lib/arch/errno.h index b34c3c3da3..6bef3f4922 100644 --- a/pxr/base/lib/arch/errno.h +++ b/pxr/base/lib/arch/errno.h @@ -24,30 +24,35 @@ #ifndef ARCH_ERRNO_H #define ARCH_ERRNO_H -/*! - * \file errno.h - * \brief Functions for dealing with system errors. - * \ingroup group_arch_SystemFunctions - */ +/// \file arch/errno.h +/// \ingroup group_arch_SystemFunctions +/// Functions for dealing with system errors. +#include "pxr/base/arch/api.h" #include -/*! - * \brief Return the error string for the current value of errno. - * \ingroup group_arch_SystemFunctions - * - * This function provides a thread-safe method of fetching the error string - * from errno. POSIX.1c defines errno as a macro which provides access to a - * thread-local integer. This function uses strerror_r, which is thread-safe. - */ -std::string ArchStrerror(); +/// \addtogroup group_arch_SystemFunctions +///@{ + +/// Return the error string for the current value of errno. +/// +/// This function provides a thread-safe method of fetching the error string +/// from errno. POSIX.1c defines errno as a macro which provides access to a +/// thread-local integer. This function uses strerror_r, which is thread-safe. +/// \overload +ARCH_API std::string ArchStrerror(); + +/// Return the error string for the specified value of errno. +/// +/// This function uses strerror_r, which is thread-safe. +ARCH_API std::string ArchStrerror(int errorCode); /*! - * \brief Return the error string for the specified value of errno. - * \ingroup group_arch_SystemFunctions - * - * This function uses strerror_r, which is thread-safe. - */ -std::string ArchStrerror(int errorCode); +* \brief Return the error string for the current system error. +* \ingroup group_arch_SystemFunctions +* +* This function uses strerror_r, which is thread-safe. +*/ +ARCH_API std::string ArchStrSysError(unsigned long errorCode); #endif // ARCH_ERRNO_H diff --git a/pxr/base/lib/arch/error.h b/pxr/base/lib/arch/error.h index ad963ca0c0..a8fb26c36b 100644 --- a/pxr/base/lib/arch/error.h +++ b/pxr/base/lib/arch/error.h @@ -24,69 +24,59 @@ #ifndef ARCH_ERROR_H #define ARCH_ERROR_H +/// \file arch/error.h +/// \ingroup group_arch_Diagnostics +/// Low-level fatal error reporting. + #include "pxr/base/arch/defines.h" +#include "pxr/base/arch/api.h" #include "pxr/base/arch/functionLite.h" #include -/*no! - * Note: this is an internal (i.e. lib/arch only) header file. - * Doxygen is off deliberately (until we get \internal working correctly). - * - * \file arch/error.h - * \brief Low-level fatal error reporting. - * \ingroup group_arch_Diagnostics - */ - -/*no! - * \brief Print message to standard error and abort program. - * \ingroup group_arch_Diagnostics - * - * \param msg The reason for the failure. - * \param funcName The name of the function that \c Arch_Error was called from. - * \param lineNo The line number of the file that \c Arch_Error was called from. - * \param fileName The name of the file that \c Arch_Error was called from. - * - * \remark - * This function is usually called via the ARCH_ERROR macro. - */ +/// Print message to standard error and abort program. +/// +/// \param msg The reason for the failure. +/// \param funcName The name of the function that \c Arch_Error was called from. +/// \param lineNo The line number of the file that \c Arch_Error was called from. +/// \param fileName The name of the file that \c Arch_Error was called from. +/// +/// \private +ARCH_API void Arch_Error(const char* msg, const char* funcName, size_t lineNo, const char* fileName); -/*no! - * \brief Print warning message to standard error, but continue execution. - * \ingroup group_arch_Diagnostics - * - * \param msg The reason for the warning. - * \param funcName The name of the function that \c Arch_Warning was called from. - * \param lineNo The line number of the file that \c Arch_Warning was called from. - * \param fileName The name of the file that \c Arch_Warning was called from. - * - * \remark - * This function is usually called via the ARCH_WARNING macro. - */ +/// Print warning message to standard error, but continue execution. +/// +/// \param msg The reason for the warning. +/// \param funcName The name of the function that \c Arch_Warning was called from. +/// \param lineNo The line number of the file that \c Arch_Warning was called from. +/// \param fileName The name of the file that \c Arch_Warning was called from. +/// +/// \private void Arch_Warning(const char* msg, const char* funcName, size_t lineNo, const char* fileName); -/*no! - * \hideinitializer - * \brief Unconditionally aborts the program. - * \ingroup group_arch_Diagnostics - * - * \param msg is a literal string, a \c const \c char* (but not - * an \c std::string) that describes why the program is aborting. - */ +/// \addtogroup group_arch_Diagnostics +///@{ + +/// Unconditionally aborts the program. +/// +/// \param msg is a literal string, a \c const \c char* (but not +/// an \c std::string) that describes why the program is aborting. +/// \hideinitializer #define ARCH_ERROR(msg) Arch_Error(msg, __ARCH_FUNCTION__, __LINE__, BUILD_COMPONENT_SRC_PREFIX __FILE__) -/*no! - * \hideinitializer - * \brief Prints a warning message to stderr. - * \ingroup group_arch_Diagnostics - * - * \param msg is a literal string, a \c const \c char* (but not - * an \c std::string). - */ +/// Prints a warning message to stderr. +/// +/// \param msg is a literal string, a \c const \c char* (but not +/// an \c std::string). +/// \hideinitializer #define ARCH_WARNING(msg) Arch_Warning(msg, __ARCH_FUNCTION__, __LINE__, BUILD_COMPONENT_SRC_PREFIX __FILE__) +/// Aborts the program if \p cond evaluates to false. +/// \hideinitializer #define ARCH_AXIOM(cond) if (!(cond)) ARCH_ERROR("[" #cond "] axiom failed") +///@} + #endif // ARCH_ERROR_H diff --git a/pxr/base/lib/arch/export.h b/pxr/base/lib/arch/export.h index e6c7351c13..021fe9ac5d 100644 --- a/pxr/base/lib/arch/export.h +++ b/pxr/base/lib/arch/export.h @@ -24,138 +24,135 @@ #ifndef ARCH_EXPORT_H #define ARCH_EXPORT_H -#include "pxr/base/arch/defines.h" - -/*! - * \file export.h - * \brief Defines symbol visibility macros. - * \ingroup group_arch_SymbolVisibility - * - * Defines \c ARCH_EXPORT to indicate a symbol should be exported from - * a library, \c ARCH_IMPORT to indicate an exported symbol should be - * imported (which only matters on Windows), and \c ARCH_HIDDEN to - * indicate that a symbol which would be exported should not be. - * - * The correct way to use these macros is for each library to make a - * header that looks like this (for some hypothetical library named foo): - * - * \code - * #ifndef FOO_API_H - * #define FOO_API_H - * - * #include "pxr/base/arch/export.h" - * - * #if defined(FOO_STATIC) - * # define FOO_API - * # define FOO_API_TEMPLATE_CLASS(...) - * # define FOO_API_TEMPLATE_STRUCT(...) - * # define FOO_LOCAL - * #else - * # if defined(FOO_EXPORTS) - * # define FOO_API ARCH_EXPORT - * # define FOO_API_TEMPLATE_CLASS(...) - * # define FOO_API_TEMPLATE_STRUCT(...) - * # else - * # define FOO_API ARCH_IMPORT - * # define FOO_API_TEMPLATE_CLASS(...) extern template class FOO_API __VA_ARGS__ - * # define FOO_API_TEMPLATE_STRUCT(...) extern template struct FOO_API __VA_ARGS__ - * # endif - * # define FOO_LOCAL ARCH_HIDDEN - * #endif - * - * #endif - * \endcode - * - * Note that every library has its own unique _API and _LOCAL macros and - * the expansion of these macros depends on whether the library is being - * built or used (indicated by the externally set macro FOO_EXPORTS). - * - * Library headers then include this header and mark classes, methods, - * functions and variables as part of the API or local. Each case is - * described below. - * - * A class is added to the API like this: - * - * \code - * class FOO_API FooClass ... - * \endcode - * - * This will add every member to the API, including implicitly created - * members like a default constructor, default assignment, the vtable - * and the type_info. The type_info is especially important. If you - * will dynamic_cast to the type or catch an exception using the type - * outside of the library, you \b must put its type_info into the API. - * The only way to do that is to put the whole class into the API. - * - * Note that template classes do not get added to the API that way. - * Instead they are added when explicitly instantiated like so: - * - * \code - * template class FOO_API FooTemplateClass; - * \endcode - * - * It's also sometimes necessary to indicate that an instantiation exists - * in the API and that a client should not do any of its own instantiation. - * This is necessary, for example, when the template has static data members - * and is done by using extern template in the header file that provides the - * type. Two of the macros above will do that: - * - * \code - * FOO_API_TEMPLATE_CLASS(FooTemplateClass); - * FOO_API_TEMPLATE_STRUCT(FooTemplateClass); - * \endcode - * - * Which you use depends on if FooTemplateClass is a class or struct. The - * macro is used because we don't want to always use extern template, but - * only when we're importing a dynamic library. - * - * A template that is completely inlined does not need to be added to the - * API since it's simply instantiated where needed. - * - * Functions, methods and variables can also be put into the API: - * - * \code - * struct FooLocalClass { - * ~FooLocalClass(); - * FOO_API void MoveTheThing(); - * }; - * FOO_API FooLocalClass* FooNewThing(); - * FOO_API extern int doNotUseGlobalVariables; - * \endcode - * - * Just because FooLocalClass is not in the API doesn't mean clients can't - * have pointers and references to instances. What they can't do is call - * member functions not in the API (or, as indicated above, use RTTI for - * it). So, for example: - * - * \code - * FooLocalClass* thing = FooNewThing(); - * thing->MoveTheThing(); - * (void)dynamic_cast(thing); // Link error! - * delete thing; // Link error! - * \endcode - * - * Deleting the FooLocalClass instance attempts to use the (non-API) d'tor - * and fails to link. If we had an implicitly defined d'tor then the - * deletion would have worked, presuming FooLocalClass didn't have any - * data members with non-API d'tors. - * - * A method of a class added to the API is itself in the API but on some - * platforms (i.e. not Windows) you can remove it from the API using - * FOO_LOCAL: - * - * \code - * struct FOO_API FooSemiAPI { - * void DoSomethingPublic(); - * FOO_LOCAL void _DoSomethingPrivate(); - * }; - * \endcode - * - * Clients of the library will fail to link if they use _DoSomethingPrivate() - * if FOO_LOCAL is supported. If not then the symbol will remain in the API. - * - */ +/// \file arch/export.h +/// \ingroup group_arch_SymbolVisibility +/// +/// Defines symbol visibility macros. +/// +/// Defines \c ARCH_EXPORT to indicate a symbol should be exported from +/// a library, \c ARCH_IMPORT to indicate an exported symbol should be +/// imported (which only matters on Windows), and \c ARCH_HIDDEN to +/// indicate that a symbol which would be exported should not be. +/// +/// The correct way to use these macros is for each library to make a +/// header that looks like this (for some hypothetical library named foo): +/// +/// \code +/// #ifndef FOO_API_H +/// #define FOO_API_H +/// +/// #include "pxr/base/arch/export.h" +/// +/// #if defined(FOO_STATIC) +/// # define FOO_API +/// # define FOO_API_TEMPLATE_CLASS(...) +/// # define FOO_API_TEMPLATE_STRUCT(...) +/// # define FOO_LOCAL +/// #else +/// # if defined(FOO_EXPORTS) +/// # define FOO_API ARCH_EXPORT +/// # define FOO_API_TEMPLATE_CLASS(...) +/// # define FOO_API_TEMPLATE_STRUCT(...) +/// # else +/// # define FOO_API ARCH_IMPORT +/// # define FOO_API_TEMPLATE_CLASS(...) extern template class FOO_API __VA_ARGS__ +/// # define FOO_API_TEMPLATE_STRUCT(...) extern template struct FOO_API __VA_ARGS__ +/// # endif +/// # define FOO_LOCAL ARCH_HIDDEN +/// #endif +/// +/// #endif +/// \endcode +/// +/// Note that every library has its own unique _API and _LOCAL macros and +/// the expansion of these macros depends on whether the library is being +/// built or used (indicated by the externally set macro FOO_EXPORTS). +/// +/// Library headers then include this header and mark classes, methods, +/// functions and variables as part of the API or local. Each case is +/// described below. +/// +/// A class is added to the API like this: +/// +/// \code +/// class FOO_API FooClass ... +/// \endcode +/// +/// This will add every member to the API, including implicitly created +/// members like a default constructor, default assignment, the vtable +/// and the type_info. The type_info is especially important. If you +/// will dynamic_cast to the type or catch an exception using the type +/// outside of the library, you \b must put its type_info into the API. +/// The only way to do that is to put the whole class into the API. +/// +/// Note that template classes do not get added to the API that way. +/// Instead they are added when explicitly instantiated like so: +/// +/// \code +/// template class FOO_API FooTemplateClass; +/// \endcode +/// +/// It's also sometimes necessary to indicate that an instantiation exists +/// in the API and that a client should not do any of its own instantiation. +/// This is necessary, for example, when the template has static data members +/// and is done by using extern template in the header file that provides the +/// type. Two of the macros above will do that: +/// +/// \code +/// FOO_API_TEMPLATE_CLASS(FooTemplateClass); +/// FOO_API_TEMPLATE_STRUCT(FooTemplateClass); +/// \endcode +/// +/// Which you use depends on if FooTemplateClass is a class or struct. The +/// macro is used because we don't want to always use extern template, but +/// only when we're importing a dynamic library. +/// +/// A template that is completely inlined does not need to be added to the +/// API since it's simply instantiated where needed. +/// +/// Functions, methods and variables can also be put into the API: +/// +/// \code +/// struct FooLocalClass { +/// ~FooLocalClass(); +/// FOO_API void MoveTheThing(); +/// }; +/// FOO_API FooLocalClass* FooNewThing(); +/// FOO_API extern int doNotUseGlobalVariables; +/// \endcode +/// +/// Just because FooLocalClass is not in the API doesn't mean clients can't +/// have pointers and references to instances. What they can't do is call +/// member functions not in the API (or, as indicated above, use RTTI for +/// it). So, for example: +/// +/// \code +/// FooLocalClass* thing = FooNewThing(); +/// thing->MoveTheThing(); +/// (void)dynamic_cast(thing); // Link error! +/// delete thing; // Link error! +/// \endcode +/// +/// Deleting the FooLocalClass instance attempts to use the (non-API) d'tor +/// and fails to link. If we had an implicitly defined d'tor then the +/// deletion would have worked, presuming FooLocalClass didn't have any +/// data members with non-API d'tors. +/// +/// A method of a class added to the API is itself in the API but on some +/// platforms (i.e. not Windows) you can remove it from the API using +/// FOO_LOCAL: +/// +/// \code +/// struct FOO_API FooSemiAPI { +/// void DoSomethingPublic(); +/// FOO_LOCAL void _DoSomethingPrivate(); +/// }; +/// \endcode +/// +/// Clients of the library will fail to link if they use _DoSomethingPrivate() +/// if FOO_LOCAL is supported. If not then the symbol will remain in the API. +#include "pxr/base/arch/defines.h" #if defined(ARCH_OS_WINDOWS) # if defined(ARCH_COMPILER_GCC) && ARCH_COMPILER_GCC_MAJOR >= 4 || defined(ARCH_COMPILER_CLANG) diff --git a/pxr/base/lib/arch/fileSystem.cpp b/pxr/base/lib/arch/fileSystem.cpp index d172da5340..b52dbfa63b 100644 --- a/pxr/base/lib/arch/fileSystem.cpp +++ b/pxr/base/lib/arch/fileSystem.cpp @@ -23,41 +23,82 @@ // #include "pxr/base/arch/fileSystem.h" #include "pxr/base/arch/defines.h" +#include "pxr/base/arch/env.h" #include "pxr/base/arch/error.h" #include "pxr/base/arch/export.h" +#include "pxr/base/arch/hints.h" #include "pxr/base/arch/vsnprintf.h" + +#include +#include +#include +#include +#include +#include +#include + +#include #include #include +#if defined(ARCH_OS_WINDOWS) +#include +#include +#include +#else +#include +#include #include +#include +#endif #include #include #include -#include #include #include -#include #include #include +#include + +#if defined (ARCH_OS_WINDOWS) +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif // ARCH_OS_WINDOWS using std::string; using std::set; +#if defined (ARCH_OS_WINDOWS) +static inline HANDLE _FileToWinHANDLE(FILE *file) { + return reinterpret_cast(_get_osfhandle(_fileno(file))); +} +#endif // ARCH_OS_WINDOWS + +FILE* ArchOpenFile(char const* fileName, char const* mode) +{ + FILE* stream = nullptr; +#if defined(ARCH_OS_WINDOWS) + fopen_s(&stream, fileName, mode); +#else + stream = fopen(fileName, mode); +#endif + return stream; +} + +#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) int ArchGetFilesystemStats(const char *path, struct statfs *buf) { -#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) return statfs(path, buf) != -1; -#else -#error Unknown system architecture. -#endif } +#endif int ArchStatCompare(enum ArchStatComparisonOp op, const struct stat *stat1, const struct stat *stat2) { -#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) +#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) || defined(ARCH_OS_WINDOWS) switch (op) { case ARCH_STAT_MTIME_EQUAL: return (stat1->st_mtime == stat2->st_mtime); @@ -88,6 +129,11 @@ ArchStatIsWritable(const struct stat *st) ; } return false; +#elif defined(ARCH_OS_WINDOWS) + if (st) { + return (st->st_mode & _S_IWRITE) ? true : false; + } + return false; #else #error Unknown system architecture. #endif @@ -100,6 +146,9 @@ ArchGetModificationTime(const struct stat& st) return st.st_mtim.tv_sec + 1e-9*st.st_mtim.tv_nsec; #elif defined(ARCH_OS_DARWIN) return st.st_mtimespec.tv_sec + 1e-9*st.st_mtimespec.tv_nsec; +#elif defined(ARCH_OS_WINDOWS) + // NB: this may need adjusting + return static_cast(st.st_mtime); #else #error Unknown system architecture #endif @@ -112,6 +161,9 @@ ArchGetAccessTime(const struct stat& st) return st.st_atim.tv_sec + 1e-9*st.st_atim.tv_nsec; #elif defined(ARCH_OS_DARWIN) return st.st_atimespec.tv_sec + 1e-9*st.st_atimespec.tv_nsec; +#elif defined(ARCH_OS_WINDOWS) + // NB: this may need adjusting + return static_cast(st.st_atime); #else #error Unknown system architecture #endif @@ -124,16 +176,51 @@ ArchGetStatusChangeTime(const struct stat& st) return st.st_ctim.tv_sec + 1e-9*st.st_ctim.tv_nsec; #elif defined(ARCH_OS_DARWIN) return st.st_ctimespec.tv_sec + 1e-9*st.st_ctimespec.tv_nsec; +#elif defined(ARCH_OS_WINDOWS) + // NB: this may need adjusting + return static_cast(st.st_mtime); #else #error Unknown system architecture #endif } -int +namespace { + struct _Fcloser { + inline void operator()(FILE *f) const { if (f) { fclose(f); } } + }; +} // anon + +using _UniqueFILE = std::unique_ptr; + +int64_t +ArchGetFileLength(FILE *file) +{ + if (!file) + return -1; +#if defined (ARCH_OS_LINUX) || defined (ARCH_OS_DARWIN) + struct stat buf; + return fstat(fileno(file), &buf) < 0 ? -1 : + static_cast(buf.st_size); +#elif defined (ARCH_OS_WINDOWS) + LARGE_INTEGER sz; + return GetFileSizeEx(_FileToWinHANDLE(file), &sz) ? + static_cast(sz.QuadPart) : -1; +#else +#error Unknown system architecture +#endif +} + +int64_t ArchGetFileLength(const char* fileName) { +#if defined (ARCH_OS_LINUX) || defined (ARCH_OS_DARWIN) struct stat buf; - return stat(fileName, &buf) < 0 ? -1 : int(buf.st_size); + return stat(fileName, &buf) < 0 ? -1 : static_cast(buf.st_size); +#elif defined (ARCH_OS_WINDOWS) + return ArchGetFileLength(_UniqueFILE(ArchOpenFile(fileName, "rb")).get()); +#else +#error Unknown system architecture +#endif } string @@ -143,13 +230,18 @@ ArchMakeTmpFileName(const string& prefix, const string& suffix) static std::atomic nCalls(1); const int n = nCalls++; +#if defined(ARCH_OS_WINDOWS) + int pid = _getpid(); +#else + int pid = getpid(); +#endif if (n == 1) return ArchStringPrintf("%s/%s.%d%s", tmpDir.c_str(), prefix.c_str(), - getpid(), suffix.c_str()); + pid, suffix.c_str()); else return ArchStringPrintf("%s/%s.%d.%d%s", tmpDir.c_str(), prefix.c_str(), - getpid(), n, suffix.c_str()); + pid, n, suffix.c_str()); } int @@ -162,6 +254,41 @@ int ArchMakeTmpFile(const std::string& tmpdir, const std::string& prefix, std::string* pathname) { +#if defined(ARCH_OS_WINDOWS) + char filename[ARCH_PATH_MAX]; + UINT ret = ::GetTempFileName(tmpdir.c_str(), prefix.c_str(), 0, filename); + if (ret == 0) + { + ARCH_ERROR("Call to GetTempFileName failed."); + return -1; + } + + // Attempt to create the file + HANDLE fileHandle = ::CreateFile(filename, + GENERIC_WRITE, // open for write + 0, // not for sharing + NULL, // default security + CREATE_ALWAYS, // overwrite existing + FILE_ATTRIBUTE_NORMAL, //normal file + NULL); // no template + + if (fileHandle == INVALID_HANDLE_VALUE) { + ARCH_ERROR("Call to CreateFile failed."); + return -1; + } + + // Close the file + ::CloseHandle(fileHandle); + + if (pathname) + { + *pathname = filename; + } + + int fd = 0; + _sopen_s(&fd, filename, _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE); + return fd; +#else // Format the template. std::string sTemplate = ArchStringPrintf("%s/%s.XXXXXX", tmpdir.c_str(), prefix.c_str()); @@ -183,24 +310,31 @@ ArchMakeTmpFile(const std::string& tmpdir, // fchmod(fd, 0640); } - - return fd; + return fd; +#endif } std::string ArchMakeTmpSubdir(const std::string& tmpdir, const std::string& prefix) { + std::string retstr; + // Format the template. std::string sTemplate = ArchStringPrintf("%s/%s.XXXXXX", tmpdir.c_str(), prefix.c_str()); // Copy template to a writable buffer. char* cTemplate = reinterpret_cast(alloca(sTemplate.size() + 1)); - strcpy(cTemplate, sTemplate.c_str()); - - std::string retstr; +#if defined(ARCH_OS_WINDOWS) + strcpy_s(cTemplate, sTemplate.size() + 1, sTemplate.c_str()); + if (::CreateDirectory(sTemplate.c_str(), NULL)) + { + retstr = sTemplate; + } +#else + strcpy(cTemplate, sTemplate.size() + 1, sTemplate.c_str()); // Open the tmpdir. char *tmpSubdir = mkdtemp(cTemplate); @@ -211,7 +345,7 @@ ArchMakeTmpSubdir(const std::string& tmpdir, retstr = tmpSubdir; } - +#endif return retstr; } @@ -221,7 +355,22 @@ ARCH_HIDDEN void Arch_InitTmpDir() { - if (char* tmpdir = getenv("TMPDIR")) { +#if defined(ARCH_OS_WINDOWS) + char tmpPath[MAX_PATH]; + + // On Windows, let GetTempPath use the standard env vars, not our own. + int sizeOfPath = GetTempPath(MAX_PATH - 1, tmpPath); + if (sizeOfPath > MAX_PATH || sizeOfPath == 0) { + ARCH_ERROR("Call to GetTempPath failed."); + _TmpDir = "."; + return; + } + + // Strip the trailing slash + tmpPath[sizeOfPath-1] = 0; + _TmpDir = _strdup(tmpPath); +#else + if (const char* tmpdir = ArchGetEnv("TMPDIR")) { // This function is not exposed in the header; it is only used during // Arch_InitConfig. If this is called more than once when TMPDIR is // set, the following call will leak a string. @@ -233,6 +382,7 @@ Arch_InitTmpDir() _TmpDir = "/var/tmp"; #endif } +#endif } const char * @@ -284,3 +434,183 @@ ArchGetAutomountDirectories() return result; } + + +void +Arch_Unmapper::operator()(char const *mapStart) const +{ + void *ptr = static_cast(const_cast(mapStart)); + if (!ptr) + return; +#if defined(ARCH_OS_WINDOWS) + UnmapViewOfFile(ptr); +#else // assume POSIX + munmap(ptr, _length); +#endif +} + +void +Arch_Unmapper::operator()(char *mapStart) const +{ + (*this)(static_cast(mapStart)); +} + +template +static inline Mapping +Arch_MapFileImpl(FILE *file) +{ + using PtrType = typename Mapping::pointer; + constexpr bool isConst = + std::is_const::value; + + auto length = ArchGetFileLength(file); + if (length < 0) + return Mapping(); + +#if defined(ARCH_OS_WINDOWS) + uint64_t unsignedLength = length; + DWORD maxSizeHigh = static_cast(unsignedLength >> 32); + DWORD maxSizeLow = static_cast(unsignedLength); + HANDLE hFileMap = CreateFileMapping( + _FileToWinHANDLE(file), NULL, + PAGE_READONLY /* allow read-only or copy-on-write */, + maxSizeHigh, maxSizeLow, NULL); + if (hFileMap == NULL) + return Mapping(); + auto ptr = static_cast( + MapViewOfFile(hFileMap, isConst ? FILE_MAP_READ : FILE_MAP_COPY, + /*offsetHigh=*/ 0, /*offsetLow=*/0, unsignedLength)); + // Close the mapping handle, and return the view pointer. + CloseHandle(hFileMap); + return Mapping(ptr, Arch_Unmapper()); +#else // Assume POSIX + return Mapping( + static_cast( + mmap(nullptr, length, isConst ? PROT_READ : PROT_READ | PROT_WRITE, + MAP_PRIVATE, fileno(file), 0)), Arch_Unmapper(length)); +#endif +} + +ArchConstFileMapping +ArchMapFileReadOnly(FILE *file) +{ + return Arch_MapFileImpl(file); +} + +ArchMutableFileMapping +ArchMapFileReadWrite(FILE *file) +{ + return Arch_MapFileImpl(file); +} + +int64_t +ArchPRead(FILE *file, void *buffer, size_t count, int64_t offset) +{ + if (count == 0) + return 0; + +#if defined(ARCH_OS_WINDOWS) + HANDLE hFile = _FileToWinHANDLE(file); + + OVERLAPPED overlapped; + memset(&overlapped, 0, sizeof(overlapped)); + + uint64_t uoffset = offset; + overlapped.OffsetHigh = static_cast(uoffset >> 32); + overlapped.Offset = static_cast(uoffset); + + DWORD numRead = 0; + if (ReadFile(hFile, buffer, static_cast(count), + &numRead, &overlapped)) { + return numRead; + } + return -1; +#else // assume POSIX + // Read and check if all got read (most common case). + int fd = fileno(file); + // Convert to signed so we can compare the result of pread with count + // without the compiler complaining. This conversion is implementation + // defined if count is larger than what's representable by int64_t, and + // POSIX pread also specifies that this case is implementation defined. We + // follow suit. + int64_t signedCount = static_cast(count); + int64_t nread = pread(fd, buffer, signedCount, offset); + if (ARCH_LIKELY(nread == signedCount or nread == 0)) + return nread; + + // Track a total and retry until we read everything or hit EOF or an error. + int64_t total = std::max(nread, 0); + while (nread != -1 || (nread == -1 && errno == EINTR)) { + // Update bookkeeping and retry. + if (nread > 0) { + total += nread; + signedCount -= nread; + offset += nread; + buffer = static_cast(buffer) + nread; + } + nread = pread(fd, buffer, signedCount, offset); + if (ARCH_LIKELY(nread == signedCount or nread == 0)) + return total + nread; + } + + // Error case. + return -1; +#endif +} + +int64_t +ArchPWrite(FILE *file, void const *bytes, size_t count, int64_t offset) +{ + if (offset < 0) + return -1; + +#if defined(ARCH_OS_WINDOWS) + HANDLE hFile = _FileToWinHANDLE(file); + + OVERLAPPED overlapped; + memset(&overlapped, 0, sizeof(overlapped)); + + uint64_t uoffset = offset; + overlapped.OffsetHigh = static_cast(uoffset >> 32); + overlapped.Offset = static_cast(uoffset); + + DWORD numWritten = 0; + if (WriteFile(hFile, bytes, static_cast(count), + &numWritten, &overlapped)) { + return numWritten; + } + return -1; +#else // assume POSIX + // It's claimed that correct, modern POSIX will never return 0 for (p)write + // unless count is zero. It will either be the case that some bytes were + // written, or we get an error return. + + // Write and check if all got written (most common case). + int fd = fileno(file); + // Convert to signed so we can compare the result of pwrite with count + // without the compiler complaining. This conversion is implementation + // defined if count is larger than what's representable by int64_t, and + // POSIX pwrite also specifies that this case is implementation defined. We + // follow suit. + int64_t signedCount = static_cast(count); + int64_t nwritten = pwrite(fd, bytes, signedCount, offset); + if (ARCH_LIKELY(nwritten == signedCount)) + return nwritten; + + // Track a total and retry until we write everything or hit an error. + int64_t total = std::max(nwritten, 0); + while (nwritten != -1) { + // Update bookkeeping and retry. + total += nwritten; + signedCount -= nwritten; + offset += nwritten; + bytes = static_cast(bytes) + nwritten; + nwritten = pwrite(fd, bytes, signedCount, offset); + if (ARCH_LIKELY(nwritten == signedCount)) + return total + nwritten; + } + + // Error case. + return -1; +#endif +} diff --git a/pxr/base/lib/arch/fileSystem.h b/pxr/base/lib/arch/fileSystem.h index 9569f5da9f..c2c58e3a50 100644 --- a/pxr/base/lib/arch/fileSystem.h +++ b/pxr/base/lib/arch/fileSystem.h @@ -24,17 +24,69 @@ #ifndef ARCH_FILESYSTEM_H #define ARCH_FILESYSTEM_H +/// \file arch/fileSystem.h +/// \ingroup group_arch_SystemFunctions +/// Architecture dependent file system access + #include "pxr/base/arch/defines.h" -#include -#include -#include +#include "pxr/base/arch/api.h" +#include "pxr/base/arch/inttypes.h" +#include +#include #include #include +#include +#include +#include + #if defined(ARCH_OS_LINUX) #include +#include #elif defined(ARCH_OS_DARWIN) #include +#include +#elif defined(ARCH_OS_WINDOWS) +#include +#include +#endif + +/// \addtogroup group_arch_SystemFunctions +///@{ +#if !defined(ARCH_OS_WINDOWS) + #ifdef _POSIX_VERSION + #include /* for PATH_MAX */ + #else + #include /* for MAXPATHLEN */ + #endif +#endif + +#if !defined(ARCH_OS_WINDOWS) + #define ARCH_GLOB_DEFAULT GLOB_NOCHECK|GLOB_MARK +#else + #define ARCH_GLOB_DEFAULT 0 +#endif + +#ifndef ARCH_PATH_MAX + #ifdef _POSIX_VERSION + #define ARCH_PATH_MAX _POSIX_PATH_MAX + #else + #ifdef MAXPATHLEN + #define ARCH_PATH_MAX MAXPATHLEN + #else + #ifdef _MAX_PATH + #define ARCH_PATH_MAX _MAX_PATH + #else + #define ARCH_PATH_MAX 1024 + #endif + #endif + #endif +#endif + +#if defined(ARCH_OS_WINDOWS) + #define ARCH_PATH_SEP ";" +#else + #define ARCH_PATH_SEP ":" #endif /*! @@ -43,6 +95,12 @@ * \ingroup group_arch_SystemFunctions */ +/// Return the length of a file in bytes. +/// +/// Returns -1 if the file cannot be opened/read. +ARCH_API int64_t ArchGetFileLength(const char *fileName); +ARCH_API int64_t ArchGetFileLength(FILE *file); + /*! * \brief This enum is used to specify a comparison operator for * \c ArchStatCompare(). @@ -55,6 +113,54 @@ enum ArchStatComparisonOp { ARCH_STAT_SAME_FILE /*!< Both refer to same file */ }; + +/*! +* \brief Opens a file. +* \ingroup group_arch_SystemFunctions +* +* Opens the file that is specified by filename. +* Returning true if the file was opened successfully; false otherwise. +*/ + +ARCH_API FILE* +ArchOpenFile(char const* fileName, char const* mode); + +#if defined(ARCH_OS_WINDOWS) +# define ArchCloseFile(fd) _close(fd) +#else +# define ArchCloseFile(fd) close(fd) +#endif + +#if defined(ARCH_OS_WINDOWS) +# define ArchUnlinkFile(path) _unlink(path) +#else +# define ArchUnlinkFile(path) unlink(path) +#endif + +#if defined(ARCH_OS_WINDOWS) +# define ArchFileAccess(path, mode) _access(path, mode) +#else +# define ArchFileAccess(path, mode) access(path, mode) +#endif + +#if defined(ARCH_OS_WINDOWS) +# define ArchFdOpen(fd, mode) _fdopen(fd, mode) +#else +# define ArchFdOpen(fd, mode) open(fd, mode) +#endif + +#if defined(ARCH_OS_WINDOWS) +# define ArchFileNo(stream) _fileno(stream) +#else +# define ArchFileNo(stream) fileno(stream) +#endif + +#if defined(ARCH_OS_WINDOWS) +# define ArchFileIsaTTY(stream) _isatty(stream) +#else +# define ArchFileIsaTTY(stream) isatty(stream) +#endif + /*! * \brief Compares two \c stat structures. * \ingroup group_arch_SystemFunctions @@ -63,7 +169,7 @@ enum ArchStatComparisonOp { * operation, returning non-zero if the operation is true with respect * to \p stat1 and \p stat2. */ - +ARCH_API int ArchStatCompare(enum ArchStatComparisonOp op, const struct stat *stat1, const struct stat *stat2); @@ -74,125 +180,155 @@ int ArchStatCompare(enum ArchStatComparisonOp op, * * Returns -1 if the file cannot be opened/read. */ -int ArchGetFileLength(const char* fileName); - -/*! - * \brief Returns true if the data in \c stat struct \p st indicates that the - * target file or directory is writable. - * - * This returns true if the struct pointer is valid, and the stat indicates - * the target is writable by the effective user, effective group, or all - * users. - */ -bool ArchStatIsWritable(const struct stat *st); +ARCH_API int64_t ArchGetFileLength(const char* fileName); +ARCH_API int64_t ArchGetFileLength(FILE *file); -/*! - * \brief Returns the modification time (mtime) in seconds from the stat struct. - * \ingroup group_arch_SystemFunctions - * - * This function returns the modification time with as much precision as is - * available in the stat structure for the current platform. - */ -double ArchGetModificationTime(const struct stat& st); +/// Returns true if the data in \c stat struct \p st indicates that the target +/// file or directory is writable. +/// +/// This returns true if the struct pointer is valid, and the stat indicates +/// the target is writable by the effective user, effective group, or all +/// users. +ARCH_API bool ArchStatIsWritable(const struct stat *st); -/*! - * \brief Returns the access time (atime) in seconds from the stat struct. - * \ingroup group_arch_SystemFunctions - * - * This function returns the access time with as much precision as is - * available in the stat structure for the current platform. - */ -double ArchGetAccessTime(const struct stat& st); +/// Returns the modification time (mtime) in seconds from the stat struct. +/// +/// This function returns the modification time with as much precision as is +/// available in the stat structure for the current platform. +ARCH_API double ArchGetModificationTime(const struct stat& st); -/*! - * \brief Returns the status change time (ctime) in seconds from the stat struct. - * \ingroup group_arch_SystemFunctions - * - * This function returns the status change time with as much precision as is - * available in the stat structure for the current platform. - */ -double ArchGetStatusChangeTime(const struct stat& st); +/// Returns the access time (atime) in seconds from the stat struct. +/// +/// This function returns the access time with as much precision as is +/// available in the stat structure for the current platform. +ARCH_API double ArchGetAccessTime(const struct stat& st); -/*! - * \brief Return the path to a temporary directory for this platform. - * - * The returned temporary directory will be a location that will normally - * be cleaned out on a reboot. This is /var/tmp on Linux machines (for - * legacy reasons), but /tmp on Darwin machines (/var/tmp on Darwin is - * specified as a location where files are kept between system reboots - - * see "man hier"). The returned string will not have a trailing slash. - * This routine is threadsafe and will not perform any memory allocations. - * - */ -const char *ArchGetTmpDir(); +/// Returns the status change time (ctime) in seconds from the stat struct. +/// +/// This function returns the status change time with as much precision as is +/// available in the stat structure for the current platform. +ARCH_API double ArchGetStatusChangeTime(const struct stat& st); -/*! - * \brief Make a temporary file name, in a system-determined - * temporary directory. - * - * The result returned has the form TMPDIR/prefix.pid[.n]suffix - * where TMPDIR is a system-determined temporary directory (typically - * /tmp or /usr/tmp), pid is the process id of the process, and - * the optional .n records the number of times this function has been called - * by a process (and is ommited the first time this function is called). - * - * The call is threadsafe. - * - * This call opens a security hole because of the race between choosing - * the name and opening the file. This call should be avoided in favor - * of ArchMakeTmpFile(). - */ +/// Return the path to a temporary directory for this platform. +/// +/// The returned temporary directory will be a location that will normally +/// be cleaned out on a reboot. This is /var/tmp on Linux machines (for +/// legacy reasons), but /tmp on Darwin machines (/var/tmp on Darwin is +/// specified as a location where files are kept between system reboots - +/// see "man hier"). The returned string will not have a trailing slash. +/// +/// This routine is threadsafe and will not perform any memory allocations. +ARCH_API const char *ArchGetTmpDir(); +/// Make a temporary file name, in a system-determined temporary directory. +/// +/// The result returned has the form TMPDIR/prefix.pid[.n]suffix where TMPDIR +/// is a system-determined temporary directory (typically /tmp or /usr/tmp), +/// pid is the process id of the process, and the optional .n records the +/// number of times this function has been called by a process (and is ommited +/// the first time this function is called). +/// +/// The call is threadsafe. +/// +/// \warning This call opens a security hole because of the race between +/// choosing the name and opening the file. This call should be avoided in +/// favor of \c ArchMakeTmpFile(). +ARCH_API std::string ArchMakeTmpFileName(const std::string& prefix, const std::string& suffix = std::string()); -/*! - * \brief Create a temporary file, in a system-determined - * temporary directory. - * - * The result returned has the form TMPDIR/prefix.XXXXXX where - * TMPDIR is a system-determined temporary directory (typically - * /tmp or /usr/tmp) and XXXXXX is a unique suffix. Returns the - * file descriptor of the new file and, if pathname isn't NULL, - * returns the full path to the file in pathname. Returns -1 on - * failure and errno is set. - * - * The call is threadsafe. - */ +/// Create a temporary file, in a system-determined temporary directory. +/// +/// The result returned has the form TMPDIR/prefix.XXXXXX where TMPDIR is a +/// system-determined temporary directory (typically /tmp or /usr/tmp) and +/// XXXXXX is a unique suffix. Returns the file descriptor of the new file +/// and, if pathname isn't NULL, returns the full path to the file in +/// pathname. Returns -1 on failure and errno is set. +/// +/// The call is threadsafe. +ARCH_API int ArchMakeTmpFile(const std::string& prefix, std::string* pathname = 0); -/*! - * \brief Create a temporary file, in a given temporary directory. - * - * The result returned has the form TMPDIR/prefix.XXXXXX where - * TMPDIR is the given temporary directory and XXXXXX is a unique - * suffix. Returns the file descriptor of the new file and, if - * pathname isn't NULL, returns the full path to the file in - * pathname. Returns -1 on failure and errno is set. - * - * The call is threadsafe. - */ +/// Create a temporary file, in a given temporary directory. +/// +/// The result returned has the form TMPDIR/prefix.XXXXXX where TMPDIR is the +/// given temporary directory and XXXXXX is a unique suffix. Returns the file +/// descriptor of the new file and, if pathname isn't NULL, returns the full +/// path to the file in pathname. Returns -1 on failure and errno is set. +/// +/// The call is threadsafe. +ARCH_API int ArchMakeTmpFile(const std::string& tmpdir, const std::string& prefix, std::string* pathname = 0); -/*! - * \brief Create a temporary sub-direcrory, in a given temporary directory. - * - * The result returned has the form TMPDIR/prefix.XXXXXX/ where - * TMPDIR is the given temporary directory and XXXXXX is a unique - * suffix. Returns the the full path to the subdir in - * pathname. Returns empty string on failure and errno is set. - * - * The call is threadsafe. - */ +/// Create a temporary sub-direcrory, in a given temporary directory. +/// +/// The result returned has the form TMPDIR/prefix.XXXXXX/ where TMPDIR is the +/// given temporary directory and XXXXXX is a unique suffix. Returns the the +/// full path to the subdir in pathname. Returns empty string on failure and +/// errno is set. +/// +/// The call is threadsafe. +ARCH_API std::string ArchMakeTmpSubdir(const std::string& tmpdir, const std::string& prefix); -/*! - * \brief Return all automounted directories. - * - * Returns a set of all directories that are automount points for the host. - */ +/// Return all automounted directories. +/// +/// Returns a set of all directories that are automount points for the host. +ARCH_API std::set ArchGetAutomountDirectories(); +// Helper 'deleter' for use with std::unique_ptr for file mappings. +#if defined(ARCH_OS_WINDOWS) +struct Arch_Unmapper { + ARCH_API void operator()(char *mapStart) const; + ARCH_API void operator()(char const *mapStart) const; +}; +#else // assume POSIX +struct Arch_Unmapper { + Arch_Unmapper() : _length(~0) {} + explicit Arch_Unmapper(size_t length) : _length(length) {} + ARCH_API void operator()(char *mapStart) const; + ARCH_API void operator()(char const *mapStart) const; +private: + size_t _length; +}; +#endif + +/// ArchConstFileMapping and ArchMutableFileMapping are std::unique_ptr and std::unique_ptr respectively. The functions +/// ArchMapFileReadOnly() and ArchMapFileReadWrite() return them and provide +/// access to memory-mapped file contents. +using ArchConstFileMapping = std::unique_ptr; +using ArchMutableFileMapping = std::unique_ptr; + +/// Privately map the passed \p file into memory and return a unique_ptr to the +/// read-only mapped contents. The contents may not be modified. +ARCH_API +ArchConstFileMapping ArchMapFileReadOnly(FILE *file); + +/// Privately map the passed \p file into memory and return a unique_ptr to the +/// copy-on-write mapped contents. If modified, the affected pages are +/// dissociated from the underlying file and become backed by the system's swap +/// or page-file storage. Edits are not carried through to the underlying file. +ARCH_API +ArchMutableFileMapping ArchMapFileReadWrite(FILE *file); + +/// Read up to \p count bytes from \p offset in \p file into \p buffer. The +/// file position indicator for \p file is not changed. Return the number of +/// bytes read, or zero if at end of file. Return -1 in case of an error, with +/// errno set appropriately. +ARCH_API +int64_t ArchPRead(FILE *file, void *buffer, size_t count, int64_t offset); + +/// Write up to \p count bytes from \p buffer to \p file at \p offset. The file +/// position indicator for \p file is not changed. Return the number of bytes +/// written, possibly zero if none written. Return -1 in case of an error, with +/// errno set appropriately. +ARCH_API +int64_t ArchPWrite(FILE *file, void const *bytes, size_t count, int64_t offset); + +///@} + #endif // ARCH_FILESYSTEM_H diff --git a/pxr/base/lib/arch/function.h b/pxr/base/lib/arch/function.h index 472618d040..d2b7fc4663 100644 --- a/pxr/base/lib/arch/function.h +++ b/pxr/base/lib/arch/function.h @@ -24,27 +24,25 @@ #ifndef ARCH_FUNCTION_H #define ARCH_FUNCTION_H -/*! - * \file arch/function.h - * \brief Define preprocessor fuction name macros. - * - * This file extents the functionality of pxr/base/arch/functionLite.h. - * This file needs to be public but shouldn't be accessed directly by - * anyone other than lib/tf. - */ +/// \file arch/function.h +/// Define preprocessor function name macros. +/// +/// This file extents the functionality of pxr/base/arch/functionLite.h. +/// This file needs to be public but shouldn't be included directly by +/// anything outside of \c lib/tf. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/functionLite.h" - #include -/*! - * \brief Return well formatted function name. - * \ingroup group_arch_Diagnostic - * - * This function assumes \c function is __ARCH_FUNCTION__ and - * \c prettyFunction is __ARCH_PRETTY_FUNCTION__, and attempts to - * reconstruct a well formatted function name. - */ +/// Return well formatted function name. +/// +/// This function assumes \c function is __ARCH_FUNCTION__ and +/// \c prettyFunction is __ARCH_PRETTY_FUNCTION__, and attempts to +/// reconstruct a well formatted function name. +/// +/// \ingroup group_arch_Diagnostic +ARCH_API std::string ArchGetPrettierFunctionName(const std::string &function, const std::string &prettyFunction); diff --git a/pxr/base/lib/arch/functionLite.h b/pxr/base/lib/arch/functionLite.h index 3b9e828493..ea898e0e0a 100644 --- a/pxr/base/lib/arch/functionLite.h +++ b/pxr/base/lib/arch/functionLite.h @@ -24,19 +24,16 @@ #ifndef ARCH_FUNCTIONLITE_H #define ARCH_FUNCTIONLITE_H -#include "pxr/base/arch/defines.h" +/// \file arch/functionLite.h +/// Define preprocessor function name macros. +/// +/// This file defines preprocessor macros for getting the current function +/// name so they can be used in a architecture independent matter. This file +/// needs to be public but shouldn't be included directly by anything outside +/// of \c pxr/base/tf. -/* - * \file functionLite.h - * \brief Define preprocessor fuction name macros. - * - * This file defines preprocessor macros for getting the current function - * name so they can be used in a architecture independent matter. This file - * needs to be public but shouldn't be accessed directly by anyone other - * than lib/tf. - * - * Note: this file specifically does not include . - */ +#include "pxr/base/arch/defines.h" +// Note: this file specifically does not include . #if defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_ICC) || \ defined(ARCH_COMPILER_CLANG) diff --git a/pxr/base/lib/arch/hash.cpp b/pxr/base/lib/arch/hash.cpp index 4c695e6184..cf5e6f0e77 100644 --- a/pxr/base/lib/arch/hash.cpp +++ b/pxr/base/lib/arch/hash.cpp @@ -475,7 +475,7 @@ void SpookyHash::Hash128( remainder = (length - ((const uint8 *)end-(const uint8 *)message)); memcpy(buf, end, remainder); memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder); - ((uint8 *)buf)[sc_blockSize-1] = remainder; + ((uint8 *)buf)[sc_blockSize-1] = static_cast(remainder); // do some final mixing End(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); diff --git a/pxr/base/lib/arch/hash.h b/pxr/base/lib/arch/hash.h index a7f54196f3..653749ceef 100644 --- a/pxr/base/lib/arch/hash.h +++ b/pxr/base/lib/arch/hash.h @@ -24,9 +24,12 @@ #ifndef ARCH_HASH_H #define ARCH_HASH_H +/// \file arch/hash.h +/// Hash functions. + #include "pxr/base/arch/inttypes.h" +#include "pxr/base/arch/api.h" -/// /// Hash \a len bytes of \a data. /// /// To compute a hash value for data that is not contiguous in memory, iterate @@ -34,10 +37,19 @@ /// passing it on as \p seed. Note that this is *not* equivalent to hashing the /// contiguous pieces as a whole. Support for that may be added in future. /// -uint32_t ArchHash(const char *data, size_t len); -uint32_t ArchHash(const char *data, size_t len, uint32_t seed); +ARCH_API uint32_t ArchHash(const char *data, size_t len); +/// \overload +ARCH_API uint32_t ArchHash(const char *data, size_t len, uint32_t seed); -uint64_t ArchHash64(const char *data, size_t len); -uint64_t ArchHash64(const char *data, size_t len, uint64_t seed); +/// Hash \a len bytes of \a data. +/// +/// To compute a hash value for data that is not contiguous in memory, iterate +/// over all the contiguous blocks of memory and accumulate the hash value by +/// passing it on as \p seed. Note that this is *not* equivalent to hashing the +/// contiguous pieces as a whole. Support for that may be added in future. +/// +ARCH_API uint64_t ArchHash64(const char *data, size_t len); +/// \overload +ARCH_API uint64_t ArchHash64(const char *data, size_t len, uint64_t seed); #endif // ARCH_HASH_H diff --git a/pxr/base/lib/arch/hints.h b/pxr/base/lib/arch/hints.h index 6588fecd1e..de6625d75e 100644 --- a/pxr/base/lib/arch/hints.h +++ b/pxr/base/lib/arch/hints.h @@ -26,12 +26,15 @@ #include "pxr/base/arch/defines.h" -// ARCH_LIKELY(bool-expr) and ARCH_UNLIKELY(bool-expr) will evaluate to the -// value of bool-expr but will also emit compiler intrinsics providing hints for -// branch prediction if the compiler has such intrinsics. It is advised that -// you only use these in cases where you empirically know the outcome of -// bool-expr to a very high degree of certainty. For example, fatal-error -// cases, invariants, first-time initializations, etc. +/// \file arch/hints.h +/// Compiler hints. +/// +/// \c ARCH_LIKELY(bool-expr) and \c ARCH_UNLIKELY(bool-expr) will evaluate to +/// the value of bool-expr but will also emit compiler intrinsics providing +/// hints for branch prediction if the compiler has such intrinsics. It is +/// advised that you only use these in cases where you empirically know the +/// outcome of bool-expr to a very high degree of certainty. For example, +/// fatal-error cases, invariants, first-time initializations, etc. #if defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG) diff --git a/pxr/base/lib/arch/initConfig.cpp b/pxr/base/lib/arch/initConfig.cpp index 9fa0febd77..48a9dad563 100644 --- a/pxr/base/lib/arch/initConfig.cpp +++ b/pxr/base/lib/arch/initConfig.cpp @@ -33,10 +33,7 @@ void Arch_InitTickTimer(); namespace { -ARCH_CONSTRUCTOR(102) -static -void -Arch_InitConfig() +ARCH_CONSTRUCTOR_DEFINE(102, Arch_InitConfig) { // Initialize the application start time. First so it's a close as // possible to the real start time. @@ -66,4 +63,4 @@ Arch_InitConfig() Arch_InitDebuggerAttach(); } -} +} \ No newline at end of file diff --git a/pxr/base/lib/arch/inttypes.h b/pxr/base/lib/arch/inttypes.h index 5852d906b4..982defa786 100644 --- a/pxr/base/lib/arch/inttypes.h +++ b/pxr/base/lib/arch/inttypes.h @@ -24,21 +24,19 @@ #ifndef ARCH_INTTYPES_H #define ARCH_INTTYPES_H +/// \file arch/inttypes.h +/// \ingroup group_arch_Bits +/// Define integral types. +/// +/// By including this file, the "standard" integer types \c int16_t, +/// \c int32_t, and \c int64_t are all defined, as are their unsigned +/// counterparts \c uint16_t, \c uint32_t, and \c uint64_t. + #include "pxr/base/arch/defines.h" #include #include #include -/*! - * \file inttypes.h - * \brief Define integral types. - * \ingroup group_arch_Bits - * - * By including this file, the "standard" integer types \c int16_t, - * \c int32_t, and \c int64_t are all defined, as are their unsigned - * counterparts \c uint16_t, \c uint32_t, and \c uint64_t. - */ - typedef unsigned char uchar; #endif // ARCH_INTTYPES_H diff --git a/pxr/base/lib/arch/library.cpp b/pxr/base/lib/arch/library.cpp new file mode 100644 index 0000000000..36cd7f4b92 --- /dev/null +++ b/pxr/base/lib/arch/library.cpp @@ -0,0 +1,58 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#include "pxr/base/arch/library.h" + +#if defined(ARCH_OS_WINDOWS) +#include +#else +#include +#endif + +void* ArchOpenLibrary(const std::string &filename, int flag) +{ +#if defined(ARCH_OS_WINDOWS) + return LoadLibrary(filename.c_str()); +#else + return dlopen(filename.c_str(), flag); +#endif +} + +const char* ArchLibraryError() +{ +#if defined(ARCH_OS_WINDOWS) + return 0; +#else + return dlerror(); +#endif +} + +int ArchLibraryClose(void* handle) +{ +#if defined(ARCH_OS_WINDOWS) + int status = ::FreeLibrary(reinterpret_cast(handle)); +#else + int status = dlclose(handle); +#endif + return status; +} \ No newline at end of file diff --git a/pxr/base/lib/arch/library.h b/pxr/base/lib/arch/library.h new file mode 100644 index 0000000000..d62aaf7905 --- /dev/null +++ b/pxr/base/lib/arch/library.h @@ -0,0 +1,73 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#ifndef ARCH_LIBRARY_H +#define ARCH_LIBRARY_H + +#include "pxr/base/arch/api.h" + +#include + +#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) +# define ARCH_LIBRARY_LAZY RTLD_LAZY +# define ARCH_LIBRARY_NOW RTLD_NOW +# define ARCH_LIBRARY_LOCAL RTLD_LOCAL +# define ARCH_LIBRARY_GLOBAL RTLD_GLOBAL +#else +# define ARCH_LIBRARY_LAZY 0 +# define ARCH_LIBRARY_NOW 0 +# define ARCH_LIBRARY_LOCAL 0 +# define ARCH_LIBRARY_GLOBAL 0 +#endif + +/*! + * \file library.h + * \brief Architecture dependent loading and unloading of dynamic libraries. + * \ingroup group_arch_SystemFunctions + */ + +/*! +* \brief Load an execuctable object file. +* \ingroup group_arch_SystemFunctions +* +* Opens the dynamic library that is specified by filename. +* Returning the handle to the module if successful; false otherwise. +*/ +ARCH_API +void* ArchOpenLibrary(const std::string &filename, int flag); + +/*! +* \brief Obtain a description of the most recent error that occurred from \c ArchOpenLibrary. +* \ingroup group_arch_SystemFunctions +*/ +ARCH_API +const char* ArchLibraryError(); + +/*! + * \brief Closes an object opened with \c ArchOpenLibrary. + * \ingroup group_arch_SystemFunctions + */ +ARCH_API +int ArchLibraryClose(void* handle); + +#endif // ARCH_LIBRARY_H diff --git a/pxr/base/lib/arch/mallocHook.cpp b/pxr/base/lib/arch/mallocHook.cpp index 7e107531ba..5b89bb794a 100644 --- a/pxr/base/lib/arch/mallocHook.cpp +++ b/pxr/base/lib/arch/mallocHook.cpp @@ -21,22 +21,26 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/base/arch/mallocHook.h" #include "pxr/base/arch/defines.h" +#include "pxr/base/arch/env.h" +#include "pxr/base/arch/mallocHook.h" #include "pxr/base/arch/attributes.h" +#include "pxr/base/arch/env.h" +#if !defined(ARCH_OS_WINDOWS) #include +#endif #include +#include #if defined(ARCH_OS_DARWIN) -#include +# include #else -#include -#endif /* defined(ARCH_OS_DARWIN) */ - +# include #if not defined(__MALLOC_HOOK_VOLATILE) #define __MALLOC_HOOK_VOLATILE -#endif /* not defined(__MALLOC_HOOK_VOLATILE) */ +#endif /* not defined __MALLOC_HOOK_VOLATILE */ +#endif /* defined(ARCH_OS_LINUX) */ using std::string; @@ -81,6 +85,7 @@ static bool _MallocProvidedBySameLibraryAs(const char* functionName, bool skipMallocCheck) { +#if !defined(ARCH_OS_WINDOWS) const void* function = dlsym(RTLD_DEFAULT, functionName); if (!function) { return false; @@ -93,6 +98,9 @@ _MallocProvidedBySameLibraryAs(const char* functionName, } return (skipMallocCheck || mallocInfo.dli_fbase == functionInfo.dli_fbase); +#else + return false; +#endif } static inline bool @@ -107,7 +115,7 @@ _CheckMallocTagImpl(const char* impl, const char* libname) bool ArchIsPxmallocActive() { - const char* impl = getenv("TF_MALLOC_TAG_IMPL"); + const char* impl = ArchGetEnv("TF_MALLOC_TAG_IMPL"); if (!_CheckMallocTagImpl(impl, "pxmalloc")) { return false; } @@ -118,7 +126,7 @@ ArchIsPxmallocActive() bool ArchIsPtmallocActive() { - const char* impl = getenv("TF_MALLOC_TAG_IMPL"); + const char* impl = ArchGetEnv("TF_MALLOC_TAG_IMPL"); if (!_CheckMallocTagImpl(impl, "ptmalloc")) { return false; } @@ -129,7 +137,7 @@ ArchIsPtmallocActive() bool ArchIsJemallocActive() { - const char* impl = getenv("TF_MALLOC_TAG_IMPL"); + const char* impl = ArchGetEnv("TF_MALLOC_TAG_IMPL"); if (!_CheckMallocTagImpl(impl, "jemalloc")) { return false; } @@ -152,7 +160,7 @@ ArchIsStlAllocatorOff() * isn't, it's just a preference, not behavior that has to correct * to avoid a crash. */ - static bool isOff = bool(getenv("GLIBCXX_FORCE_NEW")); + static bool isOff = bool(ArchGetEnv("GLIBCXX_FORCE_NEW")); return isOff; #else return false; diff --git a/pxr/base/lib/arch/mallocHook.h b/pxr/base/lib/arch/mallocHook.h index e5932f7fbc..0ee7011042 100644 --- a/pxr/base/lib/arch/mallocHook.h +++ b/pxr/base/lib/arch/mallocHook.h @@ -24,131 +24,126 @@ #ifndef ARCH_MALLOCHOOK_H #define ARCH_MALLOCHOOK_H +/// \file arch/mallocHook.h +/// \ingroup group_arch_Memory +/// Routines for controlling malloc behavior. + +#include "pxr/base/arch/api.h" #include #include -/*! - * \file mallocHook.h - * \ingroup group_arch_Memory - */ - -/*! - * \brief Return true if ptmalloc is being used as the memory allocator - * - * ptmalloc3 is an external shared library providing implementations of the - * standard memory allocation functions (e.g. malloc, free). Consumers with - * special behavior that depends on this library may use this function to - * determine if it is the active allocator. - */ -bool ArchIsPtmallocActive(); +/// Return true if ptmalloc is being used as the memory allocator +/// +/// ptmalloc3 is an external shared library providing implementations of the +/// standard memory allocation functions (e.g. malloc, free). Consumers with +/// special behavior that depends on this library may use this function to +/// determine if it is the active allocator. +/// +/// \ingroup group_arch_Memory +ARCH_API bool ArchIsPtmallocActive(); -/*! - * \brief Return true if the C++ STL allocator was requested - * to be turned off. - * - * Under gcc, this is done by setting the environment variable GLIBCXX_FORCE_NEW, - * but it might differ (or not even be possible) for other platforms. - */ +/// Return true if the C++ STL allocator was requested to be turned off. +/// +/// Under gcc, this is done by setting the environment variable +/// GLIBCXX_FORCE_NEW, but it might differ (or not even be possible) for other +/// platforms. +/// +/// \ingroup group_arch_Memory bool ArchIsStlAllocatorOff(); -/*! - * \class ArchMallocHook mallocHook.h pxr/base/arch/mallocHook.h - * \ingroup group_arch_Memory - * \brief Override default malloc() functionality. - * - * The \c ArchMallocHook class is used on supported systems to install - * a call-back function in place of the standard malloc/realloc/free/memalign - * function calls. Supported systems are currently restricted to 64-bit linux systems. - * - * The call-back function can access the original allocation function by calling, - * for example, \c ArchMallocHook::Malloc, or it is free to perform its own allocation. - * - * The \c ArchMallocHook is a POD (plain old datastructure) which means that to use - * it properly, it should be declared at global scope, ensuring zero-initialization. - */ +/// \class ArchMallocHook +/// \ingroup group_arch_Memory +/// +/// Override default malloc() functionality. +/// +/// The \c ArchMallocHook class is used on supported systems to install a +/// call-back function in place of the standard malloc/realloc/free/memalign +/// function calls. Supported systems are currently restricted to 64-bit linux +/// systems. +/// +/// The call-back function can access the original allocation function by +/// calling, for example, \c ArchMallocHook::Malloc, or it is free to perform +/// its own allocation. +/// +/// The \c ArchMallocHook is a POD (plain old datastructure) which means that +/// to use it properly, it should be declared at global scope, ensuring +/// zero-initialization. class ArchMallocHook { public: - /*! - * \brief Initialize hooks. - * - * Calling \c Initialize() installs the supplied functions as call-back - * in place of the standard system memory allocation routines. Note that - * the callbacks take an extra \c const \c void* parameter; on supported systems, - * the called function should simply ignore the extra parameter. - * - * If initialization fails, \c false is returned and \p *errMsg is set accordingly. - * If \c *this has already been initialized, calling \c Initialize() a second - * time will fail. - */ + /// Initialize hooks. + /// + /// Calling \c Initialize() installs the supplied functions as call-back + /// in place of the standard system memory allocation routines. Note + /// that the callbacks take an extra \c const \c void* parameter; on + /// supported systems, the called function should simply ignore the extra + /// parameter. + /// + /// If initialization fails, \c false is returned and \p *errMsg is set + /// accordingly. If \c *this has already been initialized, calling \c + /// Initialize() a second time will fail. + ARCH_API bool Initialize(void* (*mallocWrapper)(size_t, const void*), - void* (*reallocWrapper)(void*, size_t, const void*), - void* (*memalignWrapper)(size_t, size_t, const void*), - void (*freeWrapper)(void*, const void*), - std::string* errMsg); - - /*! - * \brief Return true if \c *this has been (successfully) initialized. - * - * In order for this function to work properly, \c *this cannot be a local - * or dynamically initialized variable; rather, \c *this must be a global - * variable, to ensure zero-initialization. - */ + void* (*reallocWrapper)(void*, size_t, const void*), + void* (*memalignWrapper)(size_t, size_t, const void*), + void (*freeWrapper)(void*, const void*), + std::string* errMsg); + + /// Return true if \c *this has been (successfully) initialized. + /// + /// In order for this function to work properly, \c this cannot be a local + /// or dynamically initialized variable; rather, \c this must be a global + /// variable, to ensure zero-initialization. + ARCH_API bool IsInitialized(); - - /*! - * \brief Call the original system \c malloc() function. - * - * This function allows user-supplied callbacks to access the original - * system-supplied malloc() call. For speed reasons, no safety checks - * are performed; in particular, calling this function without having - * successfully initialized \p *this will likely crash your program. - */ + + /// Call the original system \c malloc() function. + /// + /// This function allows user-supplied callbacks to access the original + /// system-supplied malloc() call. For speed reasons, no safety checks + /// are performed; in particular, calling this function without having + /// successfully initialized \p *this will likely crash your program. + ARCH_API void* Malloc(size_t nBytes) { - return (*_underlyingMallocFunc)(nBytes); + return (*_underlyingMallocFunc)(nBytes); } - - /*! - * \brief Call the original system \c realloc() function. - * - * This function allows user-supplied callbacks to access the original - * system-supplied \c realloc() call. For speed reasons, no safety checks - * are performed; in particular, calling this function without having - * successfully initialized \p *this will likely crash your program. - */ + + /// Call the original system \c realloc() function. + /// + /// This function allows user-supplied callbacks to access the original + /// system-supplied \c realloc() call. For speed reasons, no safety checks + /// are performed; in particular, calling this function without having + /// successfully initialized \p *this will likely crash your program. + ARCH_API void* Realloc(void* ptr, size_t nBytes) { - return (*_underlyingReallocFunc)(ptr, nBytes); + return (*_underlyingReallocFunc)(ptr, nBytes); } - /*! - * \brief Call the original system \c memalign() function. - * - * This function allows user-supplied callbacks to access the original - * system-supplied \c memalign() call. For speed reasons, no safety checks - * are performed; in particular, calling this function without having - * successfully initialized \p *this will likely crash your program. - */ + /// Call the original system \c memalign() function. + /// + /// This function allows user-supplied callbacks to access the original + /// system-supplied \c memalign() call. For speed reasons, no safety checks + /// are performed; in particular, calling this function without having + /// successfully initialized \p *this will likely crash your program. + ARCH_API void* Memalign(size_t alignment, size_t nBytes) { - return (*_underlyingMemalignFunc)(alignment, nBytes); + return (*_underlyingMemalignFunc)(alignment, nBytes); } - /*! - * \brief Call the original system \c free() function. - * - * This function allows user-supplied callbacks to access the original - * system-supplied \c free() call. For speed reasons, no safety checks - * are performed; in particular, calling this function without having - * successfully initialized \p *this will likely crash your program. - */ + /// Call the original system \c free() function. + /// + /// This function allows user-supplied callbacks to access the original + /// system-supplied \c free() call. For speed reasons, no safety checks + /// are performed; in particular, calling this function without having + /// successfully initialized \p *this will likely crash your program. + ARCH_API void Free(void* ptr) { - (*_underlyingFreeFunc)(ptr); + (*_underlyingFreeFunc)(ptr); } private: - /* - * Note: this is a POD (plain 'ol data structure) - * so we depend on zero initialization here to null these - * out. Do not add a constructor or destructor to this class. - */ + // Note: this is a POD (plain 'ol data structure) so we depend on zero + // initialization here to null these out. Do not add a constructor or + // destructor to this class. void* (*_underlyingMallocFunc)(size_t); void* (*_underlyingReallocFunc)(void*, size_t); diff --git a/pxr/base/lib/arch/math.h b/pxr/base/lib/arch/math.h index fbd73e69d6..33cd12cc3c 100644 --- a/pxr/base/lib/arch/math.h +++ b/pxr/base/lib/arch/math.h @@ -24,45 +24,36 @@ #ifndef ARCH_MATH_H #define ARCH_MATH_H -/*! - * \file math.h - * \brief Architecture-specific math function calls. - * \ingroup group_arch_Math - */ +/// \file arch/math.h +/// \ingroup group_arch_Math +/// Architecture-specific math function calls. #include "pxr/base/arch/defines.h" #include "pxr/base/arch/inttypes.h" -#include #include #if defined(ARCH_OS_WINDOWS) +#define _USE_MATH_DEFINES // For M_PI #include +#include #endif -/*! - * \brief This is the smallest value e such that 1+e^2 == 1, using floats. - * \ingroup group_arch_Math - */ +/// \addtogroup group_arch_Math +///@{ #if defined (ARCH_CPU_INTEL) || defined(doxygen) -/* - * True for all IEEE754 chipsets. - */ + +/// This is the smallest value e such that 1+e^2 == 1, using floats. +/// True for all IEEE754 chipsets. #define ARCH_MIN_FLOAT_EPS_SQR 0.000244141F -/*! - * \brief Three-valued sign. Return 1 if val > 0, 0 if val == 0, or -1 if val < - * 0; - */ +/// Three-valued sign. Return 1 if val > 0, 0 if val == 0, or -1 if val < 0. inline long ArchSign(long val) { return (val > 0) - (val < 0); } -/*! - * \brief Returns The IEEE-754 bit pattern of the specified single precision - * value as a 32-bit unsigned integer. - * \ingroup group_arch_Math - */ +/// Returns The IEEE-754 bit pattern of the specified single precision value +/// as a 32-bit unsigned integer. inline uint32_t ArchFloatToBitPattern(float v) { union { float _float; @@ -72,11 +63,8 @@ inline uint32_t ArchFloatToBitPattern(float v) { return value._uint; } -/*! - * \brief Returns The single precision floating point value corresponding to - * the given IEEE-754 bit pattern. - * \ingroup group_arch_Math - */ +/// Returns The single precision floating point value corresponding to the +/// given IEEE-754 bit pattern. inline float ArchBitPatternToFloat(uint32_t v) { union { uint32_t _uint; @@ -86,11 +74,8 @@ inline float ArchBitPatternToFloat(uint32_t v) { return value._float; } -/*! - * \brief Returns The IEEE-754 bit pattern of the specified double precision - * value as a 64-bit unsigned integer. - * \ingroup group_arch_Math - */ +/// Returns The IEEE-754 bit pattern of the specified double precision value +/// as a 64-bit unsigned integer. inline uint64_t ArchDoubleToBitPattern(double v) { union { double _double; @@ -100,11 +85,8 @@ inline uint64_t ArchDoubleToBitPattern(double v) { return value._uint; } -/*! - * \brief Returns The double precision floating point value corresponding to - * the given IEEE-754 bit pattern. - * \ingroup group_arch_Math - */ +/// Returns The double precision floating point value corresponding to the +/// given IEEE-754 bit pattern. inline double ArchBitPatternToDouble(uint64_t v) { union { uint64_t _uint; @@ -118,24 +100,17 @@ inline double ArchBitPatternToDouble(uint64_t v) { #error Unknown system architecture. #endif - -/* - * A bunch of math functions operating on floats. - */ - #if defined(ARCH_OS_LINUX) || defined(doxygen) -/*! - * \brief Computes the sine and cosine of the specified value as a float. - * \ingroup group_arch_Math - */ -inline void ArchSinCosf(float v, float *s, float *c) { sincosf(v, s, c); } +/// Computes the sine and cosine of the specified value as a float. +inline void ArchSinCosf(float v, float *s, float *c) { + sincosf(v, s, c); +} -/*! - * \brief Computes the sine and cosine of the specified value as a double. - * \ingroup group_arch_Math - */ -inline void ArchSinCos(double v, double *s, double *c) { sincos(v, s, c); } +/// Computes the sine and cosine of the specified value as a double. +inline void ArchSinCos(double v, double *s, double *c) { + sincos(v, s, c); +} #elif defined(ARCH_OS_DARWIN) || defined(ARCH_OS_WINDOWS) @@ -152,4 +127,6 @@ inline void ArchSinCos(double v, double *s, double *c) { #error Unknown architecture. #endif +///@} + #endif // ARCH_MATH_H diff --git a/pxr/base/lib/arch/nap.h b/pxr/base/lib/arch/nap.h index 871210bcde..e1ac7f404e 100644 --- a/pxr/base/lib/arch/nap.h +++ b/pxr/base/lib/arch/nap.h @@ -24,50 +24,40 @@ #ifndef ARCH_NAP_H #define ARCH_NAP_H +/// \file arch/nap.h +/// \ingroup group_arch_Multithreading +/// Routines for very brief pauses in execution. + #include "pxr/base/arch/inttypes.h" +#include "pxr/base/arch/api.h" + #if defined(ARCH_OS_WINDOWS) -#include +#include #endif -/*! - * \file nap.h - * \brief Routines for very brief pauses in execution. - * \ingroup group_arch_Multithreading - */ - -/*! - * \brief Sleep for some number of centiseconds. - * \ingroup group_arch_Multithreading - * - * Sleep for \c n/100 seconds. Note: if your intent is to simply - * yield the processors, DO NOT call this with a value of zero (as one - * can do with sginap()). Call \c ArchThreadYield() instead. - */ - -void ArchNap(size_t nhundredths); +/// \addtogroup group_arch_Multithreading +///@{ +/// Sleep for some number of centiseconds. +/// +/// Sleep for \c n/100 seconds. Note: if your intent is to simply yield the +/// processors, DO NOT call this with a value of zero (as one can do with +/// sginap()). Call \c ArchThreadYield() instead. +ARCH_API void ArchNap(size_t nhundredths); -/*! - * \brief Yield to the operating system thread scheduler. - * \ingroup group_arch_Multithreading - * - * Returns control to the operating system thread scheduler as a means of - * temporarily suspending the calling thread. - */ - +/// Yield to the operating system thread scheduler. +/// +/// Returns control to the operating system thread scheduler as a means of +/// temporarily suspending the calling thread. +ARCH_API void ArchThreadYield(); - -/*! - * \brief Pause execution of the current thread. - * \ingroup group_arch_Multithreading - * - * Pause execution of the current thread without returning control to the - * operating system scheduler. This function can be used as a means of - * gracefully spin waiting while potentially yielding CPU resouces to - * hyper-threads. - */ - +/// Pause execution of the current thread. +/// +/// Pause execution of the current thread without returning control to the +/// operating system scheduler. This function can be used as a means of +/// gracefully spin waiting while potentially yielding CPU resouces to +/// hyper-threads. inline void ArchThreadPause() { #if defined (ARCH_CPU_INTEL) && defined(ARCH_COMPILER_GCC) __asm__ __volatile__ ("pause"); @@ -78,4 +68,6 @@ inline void ArchThreadPause() { #endif } +///@} + #endif // ARCH_NAP_H diff --git a/pxr/base/lib/arch/overview.dox b/pxr/base/lib/arch/overview.dox index 9c7e560e2f..3879afa608 100644 --- a/pxr/base/lib/arch/overview.dox +++ b/pxr/base/lib/arch/overview.dox @@ -3,34 +3,38 @@ // IF YOU ADD A NEW GROUP, PLEASE ADD IT TO THE LIST BELOW!! -//! \defgroup group_arch_Bits Bits -// Functions having to do with how bits are laid out on a machine. +/// \defgroup group_arch_Bits Bits +/// Functions having to do with how bits are laid out on a machine. -//! \defgroup group_arch_Multithreading Multithreading -// Functions having to do with multithreading. +/// \defgroup group_arch_Multithreading Multithreading +/// Functions having to do with multithreading. -//! \defgroup group_arch_Math Math -// Functions for math. +/// \defgroup group_arch_Math Math +/// Functions for math. -//! \defgroup group_arch_Strings Strings -// Functions having to do with string massaging/manipulation +/// \defgroup group_arch_Strings Strings +/// Functions having to do with string massaging/manipulation -//! \defgroup group_arch_SystemFunctions System Functions -// Functions that encapsulate differing low-level system calls. +/// \defgroup group_arch_SystemFunctions System Functions +/// Functions that encapsulate differing low-level system calls. -//! \defgroup group_arch_Memory Memory Management -// Functions having to do with memory allocation/handling. - -//! \defgroup group_arch_Diagnostics Diagnostics -// Functions having to do with error reporting/handling. - -//! \defgroup group_arch_SymbolVisibility Symbol Visibility -// Macros having to do with symbol visibility +/// \defgroup group_arch_Memory Memory Management +/// Functions having to do with memory allocation/handling. +/// \defgroup group_arch_Diagnostics Diagnostics +/// Functions having to do with error reporting/handling. +/// \defgroup group_arch_SymbolVisibility Symbol Visibility +/// Macros having to do with symbol visibility /*! -\mainpage +\page arch_page_front Arch: Architecture Dependent +\if ( PIXAR_MFB_BUILD ) +\mainpage Arch: Architecture Dependent +\publicLib +\endif + +\section arch_overview Overview The ARCH library is a repository for all architecture-dependent code. It isolates all platform dependencies (and confusing \#ifdefs) diff --git a/pxr/base/lib/arch/pragmas.h b/pxr/base/lib/arch/pragmas.h index a32062a3b5..59e2598486 100644 --- a/pxr/base/lib/arch/pragmas.h +++ b/pxr/base/lib/arch/pragmas.h @@ -24,31 +24,122 @@ #ifndef ARCH_PRAGMAS_H #define ARCH_PRAGMAS_H -#include "pxr/base/arch/defines.h" - -/// /// \file arch/pragmas.h -/// \brief Pragmas for controlling compiler-specific behaviors. - +/// Pragmas for controlling compiler-specific behaviors. +/// /// This header contains pragmas used to control compiler-specific behaviors. /// Behaviors that are not supported or required by a certain compiler should /// be implemented as a no-op. -/// + +#include "pxr/base/arch/defines.h" #if defined(ARCH_COMPILER_GCC) +#define ARCH_PRAGMA_PUSH \ + _Pragma("GCC diagnostic push"); + +#define ARCH_PRAGMA_RESTORE \ + _Pragma("GCC diagnostic pop"); + /// Convert errors about variables that may be used before initialization into /// warnings. A warning is emitted, but won't cause a build failure with /// -Werror enabled. #define ARCH_PRAGMA_PUSH_NOERROR_MAYBE_UNINITIALIZED \ - _Pragma("GCC diagnostic push"); \ + ARCH_PRAGMA_PUSH \ _Pragma("GCC diagnostic warning \"-Wmaybe-uninitialized\""); -#define ARCH_PRAGMA_POP_NOERROR_MAYBE_UNINITIALIZED \ - _Pragma("GCC diagnostic pop"); -#else -#define ARCH_PRAGMA_PUSH_NOERROR_MAYBE_UNINITIALIZED -#define ARCH_PRAGMA_POP_NOERROR_MAYBE_UNINITIALIZED +#define ARCH_PRAGMA_MACRO_REDEFINITION + ARCH_PRAGMA_PUSH \ + _Pragma("GCC diagnostic warning \"-Wno-builtin-macro-redefined\""); + +#elif defined(ARCH_COMPILER_MSVC) + +#define ARCH_PRAGMA_PUSH \ + __pragma(warning(push)) + +#define ARCH_PRAGMA_RESTORE \ + __pragma(warning(pop)) + +#define ARCH_PRAGMA_MACRO_TOO_FEW_ARGUMENTS \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4003)) + +#define ARCH_PRAGMA_MACRO_REDEFINITION \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4005)) + +#define ARCH_PRAGMA_QUALIFIER_HAS_NO_MEANING \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4180)) + +#define ARCH_PRAGMA_ZERO_SIZED_STRUCT \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4200)) + +#define ARCH_PRAGMA_NEEDS_EXPORT_INTERFACE \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4251)) + +#define ARCH_PRAGMA_CONVERSION_FROM_SIZET \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4267)) + +#define ARCH_PRAGMA_MAY_NOT_BE_ALIGNED \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4316)) + +#define ARCH_PRAGMA_SHIFT_TO_64_BITS \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4334)) + +#define ARCH_PRAGMA_DESTRUCTOR_IMPLICIT_DEFINE \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4624)) + +#define ARCH_PRAGMA_DEPRECATED_POSIX_NAME \ + ARCH_PRAGMA_PUSH \ + __pragma(warning(disable:4996)) + +#endif + +#if !defined ARCH_PRAGMA_MACRO_TOO_FEW_ARGUMENTS +#define ARCH_PRAGMA_MACRO_TOO_FEW_ARGUMENTS +#endif + +#if !defined ARCH_PRAGMA_PUSH_NOERROR_MAYBE_UNINITIALIZED +#define ARCH_PRAGMA_PUSH_NOERROR_MAYBE_UNINITIALIZED +#endif + +#if !defined ARCH_PRAGMA_MACRO_REDEFINITION +#define ARCH_PRAGMA_MACRO_REDEFINITION +#endif + +#if !defined ARCH_PRAGMA_ZERO_SIZED_STRUCT +#define ARCH_PRAGMA_ZERO_SIZED_STRUCT +#endif + +#if !defined ARCH_PRAGMA_NEEDS_EXPORT_INTERFACE +#define ARCH_PRAGMA_NEEDS_EXPORT_INTERFACE +#endif + +#if !defined ARCH_PRAGMA_CONVERSION_FROM_SIZET +#define ARCH_PRAGMA_CONVERSION_FROM_SIZET +#endif + +#if !defined ARCH_PRAGMA_MAY_NOT_BE_ALIGNED +#define ARCH_PRAGMA_MAY_NOT_BE_ALIGNED +#endif + +#if !defined ARCH_PRAGMA_SHIFT_TO_64_BITS +#define ARCH_PRAGMA_SHIFT_TO_64_BITS +#endif + +#if !defined ARCH_PRAGMA_DESTRUCTOR_IMPLICIT_DEFINE +#define ARCH_PRAGMA_DESTRUCTOR_IMPLICIT_DEFINE +#endif + +#if !defined ARCH_PRAGMA_DEPRECATED_POSIX_NAME +#define ARCH_PRAGMA_DEPRECATED_POSIX_NAME #endif -#endif // ARCH_PRAGMAS_H +#endif /* ARCH_PRAGMAS_H */ diff --git a/pxr/base/lib/arch/stackTrace.cpp b/pxr/base/lib/arch/stackTrace.cpp index f945366220..8529b0d450 100644 --- a/pxr/base/lib/arch/stackTrace.cpp +++ b/pxr/base/lib/arch/stackTrace.cpp @@ -21,12 +21,29 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/defines.h" +#if defined(ARCH_OS_WINDOWS) +#include +#include +#include +#include +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif #include "pxr/base/arch/stackTrace.h" #include "pxr/base/arch/debugger.h" -#include "pxr/base/arch/defines.h" #include "pxr/base/arch/demangle.h" #include "pxr/base/arch/error.h" -#include "pxr/base/arch/export.h" #include "pxr/base/arch/fileSystem.h" #include "pxr/base/arch/inttypes.h" #include "pxr/base/arch/symbols.h" @@ -35,20 +52,13 @@ #include #include #include -#include -#include #include -#include -#include -#include #include #include -#include -#include #include -#include #include #include +#include /* Darwin/ppc did not do stack traces. Darwin/i386 still needs some work, this has been stubbed out for now. */ @@ -81,6 +91,8 @@ ForkFunc Arch_nonLockingFork = (ForkFunc)dlsym(RTLD_NEXT, "__libc_fork"); #elif defined(ARCH_OS_DARWIN) fork; /* XXX -- this is not necessarily correct */ +#elif defined(ARCH_OS_WINDOWS) + NULL; #else #error Unknown architecture. #endif @@ -117,31 +129,20 @@ static Arch_ProgInfoMap _progInfoMap; // traverse it during an error. static char *_progInfoForErrors = NULL; // Mutex for above: -static pthread_mutex_t _progInfoForErrorsMutex = PTHREAD_MUTEX_INITIALIZER; +static std::mutex _progInfoForErrorsMutex; // Key-value map for extra log info. Stores unowned pointers to text to be // emitted in stack trace logs in case of fatal errors or crashes. typedef std::map Arch_LogInfoMap; static Arch_LogInfoMap _logInfoForErrors; // Mutex for above: -static pthread_mutex_t _logInfoForErrorsMutex = PTHREAD_MUTEX_INITIALIZER; - -namespace { -// Private auto lock/unlock RAII class for pthread_mutex_t. -struct Locker { - explicit Locker(pthread_mutex_t &mutex) - : _mutex(&mutex) { pthread_mutex_lock(_mutex); } - ~Locker() { pthread_mutex_unlock(_mutex); } -private: - pthread_mutex_t *_mutex; -}; -} +static std::mutex _logInfoForErrorsMutex; static void _EmitAnyExtraLogInfo(FILE* outFile) { // This function can't cause any heap allocation, be careful. - Locker lock(_logInfoForErrorsMutex); + std::lock_guard lock(_logInfoForErrorsMutex); for (Arch_LogInfoMap::const_iterator i = _logInfoForErrors.begin(), end = _logInfoForErrors.end(); i != end; ++i) { fprintf(outFile, "\n%s:\n%s", i->first.c_str(), i->second); @@ -153,7 +154,7 @@ _EmitAnyExtraLogInfo(FILE* outFile, size_t max) { size_t n = 0; // This function can't cause any heap allocation, be careful. - Locker lock(_logInfoForErrorsMutex); + std::lock_guard lock(_logInfoForErrorsMutex); for (Arch_LogInfoMap::const_iterator i = _logInfoForErrors.begin(), end = _logInfoForErrors.end(); i != end; ++i) { // We limit the # of errors printed to avoid spam. @@ -171,7 +172,8 @@ static void _EmitAnyExtraLogInfo(char const *fname) { // This function can't cause any heap allocation, be careful. - if (FILE* outFile = fopen(fname, "a")) { + FILE* outFile = NULL; + if (outFile = ArchOpenFile(fname, "a")) { _EmitAnyExtraLogInfo(outFile); fclose(outFile); } @@ -195,11 +197,17 @@ static const char* const stackTracePrefix = "st"; static const char* stackTraceCmd = nullptr; static const char* const* stackTraceArgv = nullptr; +#if defined(ARCH_OS_WINDOWS) +static long _GetAppElapsedTime(); +#else static time_t _GetAppElapsedTime(); +#endif +#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) // asgetenv() want's this but we can't declare it inside the namespace. extern char **environ; +#endif namespace { @@ -325,6 +333,12 @@ char* asitoa(char* s, long x) int _GetStackTraceName(char* buf, size_t len) { +#if defined(ARCH_OS_WINDOWS) + int pid = _getpid(); +#else + int pid = getpid(); +#endif + // Take care to avoid non-async-safe functions. // NOTE: This doesn't protect against other threads changing the // temporary directory or program name for errors. @@ -337,7 +351,7 @@ int _GetStackTraceName(char* buf, size_t len) 1 + // "_" asstrlen(ArchGetProgramNameForErrors()) + 1 + // "." - asNumDigits(getpid()) + + asNumDigits(pid) + 1; // "\0" // Fill in buf with the default name. @@ -354,13 +368,20 @@ int _GetStackTraceName(char* buf, size_t len) end = asstrcpy(end, "_"); end = asstrcpy(end, ArchGetProgramNameForErrors()); end = asstrcpy(end, "."); - end = asitoa(end, getpid()); + end = asitoa(end, pid); } // Return a name that isn't currently in use. Simultaneously create // the empty file. int suffix = 0; - int fd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0640); +#if defined(ARCH_OS_WINDOWS) + int fd; + _sopen_s(&fd, buf, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, + _SH_DENYNO, _S_IREAD | _S_IWRITE); +#else + int fd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0640); +#endif + while (fd == -1 and errno == EEXIST) { // File exists. Try a new suffix if there's space. ++suffix; @@ -371,10 +392,15 @@ int _GetStackTraceName(char* buf, size_t len) } asstrcpy(end, "."); asitoa(end + 1, suffix); - fd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0640); +#if defined(ARCH_OS_WINDOWS) + _sopen_s(&fd, buf, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, + _SH_DENYNO, _S_IREAD | _S_IWRITE); +#else + fd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0640); +#endif } if (fd != -1) { - close(fd); + ArchCloseFile(fd); fd = 0; } return fd; @@ -435,11 +461,16 @@ _MakeArgv( static int nonLockingFork() { +#if defined(ARCH_OS_WINDOWS) + printf("nonLockingFork() not yet implemented on Windows\n"); + return 0; +#else if (Arch_nonLockingFork != NULL) { return (Arch_nonLockingFork)(); } else { return fork(); } +#endif } #if defined(ARCH_OS_LINUX) @@ -502,6 +533,8 @@ nonLockingExecv( const char *path, char *const argv[]) { #if defined(ARCH_OS_LINUX) return nonLockingLinux__execve (path, argv, __environ); +#elif defined(ARCH_OS_WINDOWS) + return static_cast(_execv(path, argv)); #else return execv(path, argv); #endif @@ -535,6 +568,12 @@ getBase(const char* path) static int _LogStackTraceForPid(const char *logfile) { +#if defined(ARCH_OS_WINDOWS) + int pid = _getpid(); +#else + int pid = getpid(); +#endif + // Get the command to run. const char* cmd = asgetenv("ARCH_POSTMORTEM"); if (not cmd) { @@ -547,7 +586,7 @@ int _LogStackTraceForPid(const char *logfile) // Construct the substitutions. char pidBuffer[numericBufferSize], timeBuffer[numericBufferSize]; - asitoa(pidBuffer, getpid()); + asitoa(pidBuffer, pid); asitoa(timeBuffer, _GetAppElapsedTime()); const char* const substitutions[3][2] = { "$pid", pidBuffer, "$log", logfile, "$time", timeBuffer @@ -558,7 +597,11 @@ int _LogStackTraceForPid(const char *logfile) const char* argv[maxArgs]; if (not _MakeArgv(argv, maxArgs, cmd, stackTraceArgv, substitutions, 2)) { static const char msg[] = "Too many arguments to postmortem command\n"; +#if defined(ARCH_OS_WINDOWS) + _write(2, msg, sizeof(msg) - 1); +#else write(2, msg, sizeof(msg) - 1); +#endif return 0; } @@ -632,7 +675,7 @@ void ArchSetProgramInfoForErrors(const std::string& key, const std::string& value) { - Locker lock(_progInfoForErrorsMutex); + std::lock_guard lock(_progInfoForErrorsMutex); if (value.empty()) { _progInfoMap.erase(key); @@ -652,13 +695,17 @@ ArchSetProgramInfoForErrors(const std::string& key, if (_progInfoForErrors) free(_progInfoForErrors); - _progInfoForErrors = strdup(ss.str().c_str()); +#if defined(ARCH_OS_WINDOWS) + _progInfoForErrors = _strdup(ss.str().c_str()); +#else + _progInfoForErrors = strdup(ss.str().c_str()); +#endif } std::string ArchGetProgramInfoForErrors(const std::string& key) { - Locker lock(_progInfoForErrorsMutex); + std::lock_guard lock(_progInfoForErrorsMutex); Arch_ProgInfoMap::iterator iter = _progInfoMap.find(key); std::string result; @@ -671,7 +718,7 @@ ArchGetProgramInfoForErrors(const std::string& key) { void ArchSetExtraLogInfoForErrors(const std::string &key, char const *text) { - Locker lock(_logInfoForErrorsMutex); + std::lock_guard lock(_logInfoForErrorsMutex); if (not text or not strlen(text)) { _logInfoForErrors.erase(key); } else { @@ -692,7 +739,11 @@ ArchSetProgramNameForErrors( const char *progName ) free(_progNameForErrors); if (progName) - _progNameForErrors = strdup(getBase(progName)); +#if defined(ARCH_OS_WINDOWS) + _progNameForErrors = _strdup(getBase(progName)); +#else + _progNameForErrors = strdup(getBase(progName)); +#endif else _progNameForErrors = NULL; } @@ -713,6 +764,26 @@ ArchGetProgramNameForErrors() return "libArch"; } +#if defined(ARCH_OS_WINDOWS) +static long +_GetAppElapsedTime() +{ + FILETIME starttime; + FILETIME exittime; + FILETIME kerneltime; + FILETIME usertime; + ULARGE_INTEGER li; + + if (::GetProcessTimes(GetCurrentProcess(), + &starttime, &exittime, &kerneltime, &usertime) == 0) + { + printf("_GetAppElapsedTime failed\n"); + return time_t(0); + } + memcpy(&li, &usertime, sizeof(FILETIME)); + return static_cast(time_t(li.QuadPart / 10000000ULL - 11644473600ULL)); +} +#else static time_t _GetAppElapsedTime() { @@ -733,10 +804,17 @@ _GetAppElapsedTime() // return time(0) - _appLaunchTime; } +#endif static void _InvokeSessionLogger(const char* progname, const char *stackTrace) { +#if defined(ARCH_OS_WINDOWS) + int pid = _getpid(); +#else + int pid = getpid(); +#endif + // Get the command to run. const char* cmd = asgetenv("ARCH_LOGSESSION"); const char* const* srcArgv = @@ -751,7 +829,7 @@ _InvokeSessionLogger(const char* progname, const char *stackTrace) // Construct the substitutions. char pidBuffer[numericBufferSize], timeBuffer[numericBufferSize]; - asitoa(pidBuffer, getpid()); + asitoa(pidBuffer, pid); asitoa(timeBuffer, _GetAppElapsedTime()); const char* const substitutions[4][2] = { "$pid", pidBuffer, "$time", timeBuffer, @@ -763,7 +841,11 @@ _InvokeSessionLogger(const char* progname, const char *stackTrace) const char* argv[maxArgs]; if (not _MakeArgv(argv, maxArgs, cmd, srcArgv, substitutions, 4)) { static const char msg[] = "Too many arguments to log session command\n"; +#if defined(ARCH_OS_WINDOWS) + _write(2, msg, sizeof(msg) - 1); +#else write(2, msg, sizeof(msg) - 1); +#endif return; } @@ -783,18 +865,20 @@ _FinishLoggingFatalStackTrace(const char *progname, const char *stackTrace, { if (!crashingHard && sessionLog) { // If we were given a session log, cat it to the end of the stack. - if (FILE* stackFd = fopen(stackTrace, "a")) { - if (FILE* sessionLogFd = fopen(sessionLog, "r")) { - fprintf(stackFd,"\n\n********** Session Log **********\n\n"); - // Cat the sesion log - char line[4096]; - while (fgets(line, 4096, sessionLogFd)) { - fputs(line, stackFd); + FILE* stackFd; + if (stackFd = ArchOpenFile(stackTrace, "a")) { + FILE* sessionLogFd; + if (sessionLogFd = ArchOpenFile(sessionLog, "r")) { + fprintf(stackFd,"\n\n********** Session Log **********\n\n"); + // Cat the sesion log + char line[4096]; + while (fgets(line, 4096, sessionLogFd)) { + fputs(line, stackFd); + } + fclose(sessionLogFd); + } + fclose(stackFd); } - fclose(sessionLogFd); - } - fclose(stackFd); - } } // Add trace to database if _shouldLogStackToDb is true @@ -851,13 +935,18 @@ ArchLogPostMortem(const char* reason, const char* message /* = nullptr */) if (_GetStackTraceName(logfile, sizeof(logfile)) == -1) { // Cannot create the logfile. static const char msg[] = "Cannot create a log file\n"; +#if defined(ARCH_OS_WINDOWS) + _write(2, msg, sizeof(msg) - 1); +#else write(2, msg, sizeof(msg) - 1); +#endif busy.clear(std::memory_order_release); return; } // Write reason for stack trace to logfile. - if (FILE* stackFd = fopen(logfile, "a")) { + FILE* stackFd; + if (stackFd = ArchOpenFile(logfile, "a")) { if (reason) { fprintf(stackFd, "This stack trace was requested because: %s\n", reason); @@ -882,7 +971,7 @@ ArchLogPostMortem(const char* reason, const char* message /* = nullptr */) // print out any registered program info { - Locker lock(_progInfoForErrorsMutex); + std::lock_guard lock(_progInfoForErrorsMutex); if (_progInfoForErrors) { fprintf(stderr, "%s", _progInfoForErrors); } @@ -951,14 +1040,18 @@ ArchLogStackTrace(const std::string& progname, const std::string& reason, // print out any registered program info { - Locker lock(_progInfoForErrorsMutex); + std::lock_guard lock(_progInfoForErrorsMutex); if (_progInfoForErrors) { fprintf(stderr, "%s", _progInfoForErrors); } } if (fd != -1) { - FILE* fout = fdopen(fd, "w"); +#if defined(ARCH_OS_WINDOWS) + FILE* fout = _fdopen(fd, "w"); +#else + FILE* fout = fdopen(fd, "w"); +#endif fprintf(stderr, "The stack can be found in %s:%s\n" "--------------------------------------------------------------" "\n", hostname, tmpFile.c_str()); @@ -1014,7 +1107,7 @@ _LogStackTraceToOutputIterator(OutputIterator oi, size_t maxDepth, bool addEndl) } inFile.close(); - unlink(logfile); + ArchUnlinkFile(logfile); } #endif @@ -1288,6 +1381,10 @@ ArchCrashHandlerSystemv(const char* pathname, char *const argv[], int timeout, ArchCrashHandlerSystemCB callback, void* userData) { +#if defined(ARCH_OS_WINDOWS) + printf("ArchCrashHandlerSystemv unimplemented for Windows\n"); + return -1; +#else struct sigaction act, oldact; int retval = 0; int savedErrno; @@ -1307,7 +1404,7 @@ ArchCrashHandlerSystemv(const char* pathname, char *const argv[], nonLockingExecv(pathname, argv); /* use non-locking execv */ /* exec() failed */ fprintf(stderr, "FAIL: Unable to exec() crash handler %s: %s\n", - pathname, strerror(errno)); + pathname, ArchStrerror(errno).c_str()); _exit(127); } else { @@ -1394,17 +1491,20 @@ ArchCrashHandlerSystemv(const char* pathname, char *const argv[], errno = savedErrno; return retval; +#endif } /* test thread for crashing (loops forever.) */ static void * arch_athread(void *) { +#if !defined(ARCH_OS_WINDOWS) while (1) {} /* loop forever */ pthread_exit((void *) 0); #if defined(ARCH_OS_DARWIN) return (void*)0; #endif +#endif } /* @@ -1417,6 +1517,7 @@ arch_athread(void *) void ArchTestCrash(bool spawnthread) { +#if !defined(ARCH_OS_WINDOWS) pthread_t tid; char *overwrite, *another; @@ -1466,4 +1567,5 @@ ArchTestCrash(bool spawnthread) fprintf(stderr,"FAILED to crash! Aborting.\n"); abort(); +#endif } diff --git a/pxr/base/lib/arch/stackTrace.h b/pxr/base/lib/arch/stackTrace.h index 103c8011c5..0485ae3aa4 100644 --- a/pxr/base/lib/arch/stackTrace.h +++ b/pxr/base/lib/arch/stackTrace.h @@ -24,7 +24,13 @@ #ifndef ARCH_STACKTRACE_H #define ARCH_STACKTRACE_H +/// \file arch/stackTrace.h +/// \ingroup group_arch_Diagnostics +/// Architecture-specific call-stack tracing routines. + #include "pxr/base/arch/defines.h" +#include "pxr/base/arch/api.h" + #include #include #include @@ -32,354 +38,280 @@ #include #include -/*! - * \file stackTrace.h - * \brief Architecture-specific call-stack tracing routines. - * \ingroup group_arch_Diagnostics - */ - -/*! - * \brief Dumps call-stack info to a file, and prints an informative - * message. - * \ingroup group_arch_Diagnostics - * - * The reason for the trace should be supplied in \p reason. This routine - * can be slow and is intended to be called for a fatal error, such as a - * caught coredump signal, but may be called at any time. An additional - * message may be provided in \p message. If \p reason is \c NULL then - * this function only writes \p message to the banner (if any). - * - * This function is implemented by calling an external program. This - * is suitable for times where the current process may be corrupted. In - * other cases, using \c ArchPrintStackTrace() or other related functions - * would be much faster. - * - * Note the use of \c char* as opposed to \c string: this is intentional, - * because we are trying to use only async-safe function from here on and - * malloc() is not async-safe. - */ +/// \addtogroup group_arch_Diagnostics +///@{ + +/// Dumps call-stack info to a file, and prints an informative message. +/// +/// The reason for the trace should be supplied in \p reason. This routine +/// can be slow and is intended to be called for a fatal error, such as a +/// caught coredump signal, but may be called at any time. An additional +/// message may be provided in \p message. If \p reason is \c NULL then this +/// function only writes \p message to the banner (if any). +/// +/// This function is implemented by calling an external program. This is +/// suitable for times where the current process may be corrupted. In other +/// cases, using \c ArchPrintStackTrace() or other related functions would be +/// much faster. +/// +/// Note the use of \c char* as opposed to \c string: this is intentional, +/// because we are trying to use only async-safe function from here on and +/// malloc() is not async-safe. +ARCH_API void ArchLogPostMortem(const char* reason, const char* message = nullptr); -/*! - * \brief Sets the command line that gathers call-stack info. - * \ingroup group_arch_Diagnostics - * - * This function sets the command line to execute to gather and log call-stack - * info. \p argv must be NULL terminated. \p command and/or \p argv may be - * NULL to suppress execution. Otherwise argv[0] must be the full path to the - * program to execute, typically \p command or "$cmd" as described below. - * - * \p command and \p argv are not copied and must remain valid until the next - * call to \c ArchSetPostMortem. - * - * Simple substitution is supported on argv elements: - * \li $cmd: Substitutes the command pathname, or $ARCH_POSTMORTEM if set - * \li $pid: Substitutes the process id - * \li $log: Substitutes the log pathname - * \li $time: Substitutes the user time (if available, else wall time) - * - * \sa ArchLogPostMortem - */ +/// Sets the command line that gathers call-stack info. +/// +/// This function sets the command line to execute to gather and log +/// call-stack info. \p argv must be NULL terminated. \p command and/or \p +/// argv may be NULL to suppress execution. Otherwise argv[0] must be the +/// full path to the program to execute, typically \p command or "$cmd" as +/// described below. +/// +/// \p command and \p argv are not copied and must remain valid until the next +/// call to \c ArchSetPostMortem. +/// +/// Simple substitution is supported on argv elements: +/// \li $cmd: Substitutes the command pathname, or $ARCH_POSTMORTEM if set +/// \li $pid: Substitutes the process id +/// \li $log: Substitutes the log pathname +/// \li $time: Substitutes the user time (if available, else wall time) +/// +/// \sa ArchLogPostMortem +ARCH_API void ArchSetPostMortem(const char* command, const char *const argv[]); -/*! - * \brief Log session info. - * \ingroup group_arch_Diagnostics - * - * Optionally indicate that this is due to a crash by providing - * the path to a file containing a stack trace in \p crashStackTrace. - * - */ +/// Log session info. +/// +/// Optionally indicate that this is due to a crash by providing +/// the path to a file containing a stack trace in \p crashStackTrace. +/// +ARCH_API void ArchLogSessionInfo(const char *crashStackTrace=NULL); -/*! - * \brief Sets the command line to log sessions. - * \ingroup group_arch_Diagnostics - * - * This function sets the command line to execute to log session info. - * \p argv is used if no crash stack trace is provided, otherwise - * \p crashArgv is used. Both must be NULL terminated. If \p command - * or \p argv is NULL then non-crashes are not logged; if \p command - * or \p crashArgv is NULL then crashes are not logged. If not NULL then - * argv[0] and crashArgv[0] must be full path to the program to execute, - * typically \p command or "$cmd" as described below. - * - * \p command, \p argv, and \p crashArgv are not copied and must remain - * valid until the next call to \c ArchSetLogSession. - * - * Simple substitution is supported on argv elements: - * \li $cmd: Substitutes the command pathname, or $ARCH_LOGSESSION if set - * \li $prog Substitutes the program name - * \li $pid: Substitutes the process id - * \li $time: Substitutes the user time (if available, else wall time) - * \li $stack: Substitutes the crash stack string (only in crashArgv) - * - * \sa ArchLogSessionInfo - */ +/// Sets the command line to log sessions. +/// +/// This function sets the command line to execute to log session info. \p +/// argv is used if no crash stack trace is provided, otherwise \p crashArgv +/// is used. Both must be NULL terminated. If \p command or \p argv is NULL +/// then non-crashes are not logged; if \p command or \p crashArgv is NULL +/// then crashes are not logged. If not NULL then argv[0] and crashArgv[0] +/// must be full path to the program to execute, typically \p command or +/// "$cmd" as described below. +/// +/// \p command, \p argv, and \p crashArgv are not copied and must remain valid +/// until the next call to \c ArchSetLogSession. +/// +/// Simple substitution is supported on argv elements: +/// \li $cmd: Substitutes the command pathname, or $ARCH_LOGSESSION if set +/// \li $prog Substitutes the program name +/// \li $pid: Substitutes the process id +/// \li $time: Substitutes the user time (if available, else wall time) +/// \li $stack: Substitutes the crash stack string (only in crashArgv) +/// +/// \sa ArchLogSessionInfo +ARCH_API void ArchSetLogSession(const char* command, const char* const argv[], const char* const crashArgv[]); -/*! - * \brief Register the callback to invoke logging at - * end of a successful session. - * \ingroup group_arch_Diagnostics - * - * This function registers ArchLogSessionInfo() - * and records the current timestamp, to send up-time - * to the DB upon exiting. - */ +/// Register the callback to invoke logging at end of a successful session. +/// +/// This function registers ArchLogSessionInfo() and records the current +/// timestamp, to send up-time to the DB upon exiting. +ARCH_API void ArchEnableSessionLogging(); -// Again, 2 versions, one for 2x and one for 3x. -/*! - * \brief Print a stack trace to the given FILE *. - * \ingroup group_arch_Diagnostics - * - * Prints out a stack trace to the given FILE *. Will call - * Prints out a stack trace to the given stream (\c man \c stdio). Will call - * ArchLoadSymbols() if symbols have not yet been loaded. - */ -void ArchPrintStackTrace(FILE *fout, const std::string& programName, - const std::string& reason); - -/*! - * \brief Print a stack trace to the given FILE *. - * \ingroup group_arch_Diagnostics - * - * Prints out a stack trace to the given FILE *. Will call - * Prints out a stack trace to the given stream (\c man \c stdio). Will call - * ArchLoadSymbols() if symbols have not yet been loaded. - */ +/// Print a stack trace to the given FILE pointer. +ARCH_API +void ArchPrintStackTrace(FILE *fout, + const std::string& programName, + const std::string& reason); + +/// Print a stack trace to the given FILE pointer. +/// This function uses ArchGetProgramInfoForErrors as the \c programName. +/// \overload +ARCH_API void ArchPrintStackTrace(FILE *fout, const std::string& reason); +/// Print a stack trace to the given ostream. +/// \overload +void ArchPrintStackTrace(std::ostream& out, + const std::string& programName, + const std::string& reason); -/*! - * \brief Print a stack trace to the given iostream. - * \ingroup group_arch_Diagnostics - * - * see above - */ -void ArchPrintStackTrace(std::ostream& out, - const std::string& programName, - const std::string& reason); - -/*! - * \brief Print a stack trace to the given iostream. - * \ingroup group_arch_Diagnostics - * - * see above - */ +/// Print a stack trace to the given iostream. +/// This function uses ArchGetProgramInfoForErrors as the \c programName. +/// \overload +ARCH_API void ArchPrintStackTrace(std::ostream& out, const std::string& reason); -/*! - * \brief A callback to get a symbolic representation of an address. - * \ingroup group_arch_Diagnostics - */ +/// A callback to get a symbolic representation of an address. typedef std::function ArchStackTraceCallback; -/*! - * \brief Sets a callback to get a symbolic representation of an address. - * \ingroup group_arch_Diagnostics - * - * The callback returns a string for an address in a stack trace, - * typically including the name of the function containing the address. - * \p cb may be \c NULL to use a default implementation. - */ +/// Sets a callback to get a symbolic representation of an address. +/// +/// The callback returns a string for an address in a stack trace, typically +/// including the name of the function containing the address. \p cb may be \c +/// NULL to use a default implementation. +ARCH_API void ArchSetStackTraceCallback(const ArchStackTraceCallback& cb); -/*! - * \brief Returns the callback to get a symbolic representation of an address. - * \ingroup group_arch_Diagnostics - * - * \sa ArchSetStackTraceCallback - */ +/// Returns the callback to get a symbolic representation of an address. +/// \sa ArchSetStackTraceCallback +ARCH_API void ArchGetStackTraceCallback(ArchStackTraceCallback* cb); -/*! - * \brief Returns the set value for the application's launch time. - * \ingroup group_arch_Diagnostics - * - * The timestamp for this value is set when the Arch library is initialized. - */ +/// Returns the set value for the application's launch time. +/// The timestamp for this value is set when the arch library is initialized. +ARCH_API time_t ArchGetAppLaunchTime(); -/*! - * \brief Enables or disables the automatic logging of crash information. - * \ingroup group_arch_Diagnostics - * - * This function controls whether the stack trace and build information is - * automatically caught and stored to an internal database when a fatal - * crash occurs. - */ -void ArchSetFatalStackLogging( bool flag ); - -/*! - * \brief Returns whether automatic logging of fatal crashes is enabled - * \ingroup group_arch_Diagnostics - * - * This is set to false by default. - */ +/// Enables or disables the automatic logging of crash information. +/// +/// This function controls whether the stack trace and build information is +/// automatically caught and stored to an internal database when a fatal crash +/// occurs. +ARCH_API +void ArchSetFatalStackLogging(bool flag); + +/// Returns whether automatic logging of fatal crashes is enabled +/// This is set to false by default. +/// \see ArchSetFatalStackLogging +ARCH_API bool ArchGetFatalStackLogging(); -/*! - * \brief Sets the program name to be used in diagnostic output - * \ingroup group_arch_Diagnostics - * - * The default value is initialized to ArchGetExecutablePath(). - */ -void ArchSetProgramNameForErrors( const char * progName ); - -/*! - * \brief Returns the currently set program name for reporting errors. - * \ingroup group_arch_Diagnostics - * - * Defaults to ArchGetExecutablePath(). - */ +/// Sets the program name to be used in diagnostic output +/// +/// The default value is initialized to ArchGetExecutablePath(). +ARCH_API +void ArchSetProgramNameForErrors(const char * progName); + +/// Returns the currently set program name for reporting errors. +/// Defaults to ArchGetExecutablePath(). +ARCH_API const char * ArchGetProgramNameForErrors(); -/*! - * \brief Sets additional program info to be reported to the terminal in case of - * a fatal error. - * \ingroup group_arch_Diagnostics - * - */ +/// Sets additional program info to be reported to the terminal in case of a +/// fatal error. +ARCH_API void ArchSetProgramInfoForErrors( const std::string& key, const std::string& value ); -/*! - * \brief Returns currently set program info. - * \ingroup group_arch_Diagnostics - * - */ +/// Returns currently set program info. +/// \see ArchSetExtraLogInfoForErrors +ARCH_API std::string ArchGetProgramInfoForErrors(const std::string& key); - -/*! - * \brief Stores (or removes if \p text is NULL) a pointer to additional log - * data that will be output in the stack trace log in case of a fatal error. - * Note that the pointer \p text is copied, not the pointed-to text. Thus it is - * the caller's responsibility to ensure that \p text is valid until the caller - * removes it by invoking this function again with text==NULL. - * \ingroup group_arch_Diagnostics - */ +/// Stores (or removes if \p text is NULL) a pointer to additional log data +/// that will be output in the stack trace log in case of a fatal error. Note +/// that the pointer \p text is copied, not the pointed-to text. Thus it is +/// the caller's responsibility to ensure that \p text is valid until the +/// caller removes it by invoking this function again with text==NULL. +ARCH_API void ArchSetExtraLogInfoForErrors(const std::string &key, char const *text); -/*! - * \brief Logs a stack trace to a file in /var/tmp. - * \ingroup group_arch_Diagnostics - * - * This function is similar to \c ArchLogPostMortem(), but will not fork an - * external process and only reports a stack trace. A file in /var/tmp is - * created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to - * make a unique extension for the file. If \c sessionLog is specified, - * then it will be appended to this file. A message is printed to \c stderr - * reporting that a stack trace has been taken and what file it has been - * written to. And if \c fatal is true, then the stack trace will be added - * to the stack_trace database table. - */ -void ArchLogStackTrace(const std::string& progName, const std::string& reason, - bool fatal = false, - const std::string& sessionLog = ""); - -/*! - * \brief Logs a stack trace to a file in /var/tmp. - * \ingroup group_arch_Diagnostics - * - * This function is similar to \c ArchLogPostMortem(), but will not fork an - * external process and only reports a stack trace. A file in /var/tmp is - * created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to - * make a unique extension for the file. If \c sessionLog is specified, - * then it will be appended to this file. A message is printed to \c stderr - * reporting that a stack trace has been taken and what file it has been - * written to. And if \c fatal is true, then the stack trace will be added - * to the stack_trace database table. - */ +/// Logs a stack trace to a file in /var/tmp. +/// +/// This function is similar to \c ArchLogPostMortem(), but will not fork an +/// external process and only reports a stack trace. A file in /var/tmp is +/// created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to +/// make a unique extension for the file. If \c sessionLog is specified, then +/// it will be appended to this file. A message is printed to \c stderr +/// reporting that a stack trace has been taken and what file it has been +/// written to. And if \c fatal is true, then the stack trace will be added +/// to the stack_trace database table. +ARCH_API +void ArchLogStackTrace(const std::string& progName, + const std::string& reason, + bool fatal = false, + const std::string& sessionLog = ""); + +/// Logs a stack trace to a file in /var/tmp. +/// +/// This function is similar to \c ArchLogPostMortem(), but will not fork an +/// external process and only reports a stack trace. A file in /var/tmp is +/// created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to +/// make a unique extension for the file. If \c sessionLog is specified, +/// then it will be appended to this file. A message is printed to \c stderr +/// reporting that a stack trace has been taken and what file it has been +/// written to. And if \c fatal is true, then the stack trace will be added +/// to the stack_trace database table. +ARCH_API void ArchLogStackTrace(const std::string& reason, bool fatal = false, const std::string& sessionLog = ""); -/*! - * \brief Return stack trace. - * \ingroup group_arch_Diagnostics - * - * This function will return a vector of strings containing the - * current stack. The vector will be of maximum size \p maxDepth. - */ +/// Return stack trace. +/// +/// This function will return a vector of strings containing the current +/// stack. The vector will be of maximum size \p maxDepth. +ARCH_API std::vector ArchGetStackTrace(size_t maxDepth); -/*! - * \brief Save frames of current stack - * \ingroup group_arch_Diagnostics - * - * This function saves at maximum \c maxDepth frames of the current - * stack into the vector \c frames. - * - */ +/// Save frames of current stack +/// +/// This function saves at maximum \c maxDepth frames of the current stack +/// into the vector \c frames. +ARCH_API void ArchGetStackFrames(size_t maxDepth, std::vector *frames); -/*! - * \brief Save frames of current stack. - * \ingroup group_arch_Diagnostics - * - * This function saves at maximum \p maxDepth frames of the current - * stack into the vector \p frames, skipping the first \p numFramesToSkipAtTop - * frames. The first frame will be at depth \p numFramesToSkipAtTop and the - * last at depth \p numFramesToSkipAtTop + \p maxDepth - 1. - * - */ +/// Save frames of current stack. +/// +/// This function saves at maximum \p maxDepth frames of the current stack +/// into the vector \p frames, skipping the first \p numFramesToSkipAtTop +/// frames. The first frame will be at depth \p numFramesToSkipAtTop and the +/// last at depth \p numFramesToSkipAtTop + \p maxDepth - 1. +ARCH_API void ArchGetStackFrames(size_t maxDepth, size_t numFramesToSkipAtTop, std::vector *frames); -/*! - * \brief Print stack frames to the given iostream. - * \ingroup group_arch_Diagnostics - * - */ +/// Print stack frames to the given iostream. +ARCH_API void ArchPrintStackFrames(std::ostream& out, const std::vector &frames); +/// Callback for handling crashes. +/// \see ArchCrashHandlerSystemv typedef void (*ArchCrashHandlerSystemCB)(void* userData); -/*! - * \brief Replacement for 'system' safe for a crash handler - * \ingroup group_arch_Diagnostics - * - * This function is a substitute for system() which does not allocate - * or free any data, and times out after \c timeout seconds if the - * operation in \c argv is not complete. Unlike system, it takes the - * full \c pathname of the program to run, and won't search the path. - * Also unlike system, \c argv[] are the separated arguments, starting - * with the program's name, as for execv. \c callback is called every - * second. \c userData is passed to \c callback. \c callback can be used, - * for example, to print a '.' repeatedly to show progress. The alarm - * used in this function could interfere with setitimer or other calls - * to alarm, and this function uses non-locking fork and exec if available - * so should not generally be used except following a catastrophe. - */ + +/// Replacement for 'system' safe for a crash handler +/// +/// This function is a substitute for system() which does not allocate or free +/// any data, and times out after \c timeout seconds if the operation in \c +/// argv is not complete. Unlike system, it takes the full \c pathname of the +/// program to run, and won't search the path. Also unlike system, \c argv[] +/// are the separated arguments, starting with the program's name, as for +/// execv. \c callback is called every second. \c userData is passed to \c +/// callback. \c callback can be used, for example, to print a '.' repeatedly +/// to show progress. The alarm used in this function could interfere with +/// setitimer or other calls to alarm, and this function uses non-locking fork +/// and exec if available so should not generally be used except following a +/// catastrophe. +ARCH_API int ArchCrashHandlerSystemv(const char* pathname, char *const argv[], int timeout, ArchCrashHandlerSystemCB callback, void* userData); -/*! - * \brief Crash, to test crash behavior. - * \ingroup group_arch_Diagnostics - * - * This function causes the calling program to crash by doing bad malloc - * and free things. If \c spawnthread is true, it spawns a thread which - * remains alive during the crash. It aborts if it fails to crash. - * - */ +/// Crash, to test crash behavior. +/// +/// This function causes the calling program to crash by doing bad malloc +/// and free things. If \c spawnthread is true, it spawns a thread which +/// remains alive during the crash. It aborts if it fails to crash. +/// +/// \private +ARCH_API void ArchTestCrash(bool spawnthread); #if defined(ARCH_OS_DARWIN) - /* XXX:---:20030825 Mac OS X has no ETIME. ECANCELED seems - * to have about the closest meaning to the actual error here. - * The operation is timing out, not being explicitly canceled, - * but it is canceled. - */ +// Mac OS X has no ETIME. ECANCELED seems to have about the closest meaning to +// the actual error here. The operation is timing out, not being explicitly +// canceled, but it is canceled. #ifndef ETIME #define ETIME ECANCELED #endif // end ETIME #endif // end ARCH_OS_DARWIN +///@} + #endif // ARCH_STACKTRACE_H diff --git a/pxr/base/lib/arch/symbols.cpp b/pxr/base/lib/arch/symbols.cpp index 2064d0001a..4d2bd1983f 100644 --- a/pxr/base/lib/arch/symbols.cpp +++ b/pxr/base/lib/arch/symbols.cpp @@ -23,8 +23,13 @@ // #include "pxr/base/arch/symbols.h" #include "pxr/base/arch/defines.h" +#include "pxr/base/arch/fileSystem.h" +#include "pxr/base/arch/errno.h" #if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) #include +#elif defined(ARCH_OS_WINDOWS) +#include +#include #endif bool @@ -50,6 +55,26 @@ ArchGetAddressInfo( } return true; } +#elif defined(ARCH_OS_WINDOWS) + HMODULE module = nullptr; + + if (objectPath) + { + if (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + reinterpret_cast(address), + &module)) + { + char modName[ARCH_PATH_MAX + 1] = {0}; + if(GetModuleFileName(module, modName, ARCH_PATH_MAX)) + { + objectPath->assign(modName); + return true; + } + } + else + ArchStrSysError(::GetLastError()); + } #endif return false; } diff --git a/pxr/base/lib/arch/symbols.h b/pxr/base/lib/arch/symbols.h index 0ed273fd5f..0f4df1ea0e 100644 --- a/pxr/base/lib/arch/symbols.h +++ b/pxr/base/lib/arch/symbols.h @@ -24,26 +24,27 @@ #ifndef ARCH_SYMBOLS_H #define ARCH_SYMBOLS_H -#include +/// \file arch/symbols.h +/// \ingroup group_arch_Diagnostics +/// Architecture-specific symbol lookup routines. -/*! - * \file symbols.h - * \brief Architecture-specific symbol lookup routines. - * \ingroup group_arch_Diagnostics - */ +#include "pxr/base/arch/api.h" +#include -/*! - * Returns information about the address \p address in the running program. - * Returns \c false if no information can be found, otherwise returns \c true - * and modifies the other arguments: \p objectPath is set to the path to - * the executable or library the address is found in, \p baseAddress is the - * address where that object is loaded, \p symbolName is the symbolic name - * of the thing containing the address, and \p symbolAddress is the starting - * address of that thing. If no thing is found to contain the address then - * \p symbolName is cleared and \p symbolAddress is set to \c NULL. - * Any of the arguments except \p address can be \c NULL if the result isn't - * needed. This will return \c false if \c NULL is passed to \p address. - */ +/// Returns information about the address \p address in the running program. +/// +/// Returns \c false if no information can be found, otherwise returns \c true +/// and modifies the other arguments: \p objectPath is set to the path to the +/// executable or library the address is found in, \p baseAddress is the +/// address where that object is loaded, \p symbolName is the symbolic name of +/// the thing containing the address, and \p symbolAddress is the starting +/// address of that thing. If no thing is found to contain the address then +/// \p symbolName is cleared and \p symbolAddress is set to \c NULL. Any of +/// the arguments except \p address can be \c NULL if the result isn't needed. +/// This will return \c false if \c NULL is passed to \p address. +/// +/// \ingroup group_arch_Diagnostics +ARCH_API bool ArchGetAddressInfo(void* address, std::string* objectPath, void** baseAddress, std::string* symbolName, void** symbolAddress); diff --git a/pxr/base/lib/arch/systemInfo.cpp b/pxr/base/lib/arch/systemInfo.cpp index d68388e61d..859da55d1c 100644 --- a/pxr/base/lib/arch/systemInfo.cpp +++ b/pxr/base/lib/arch/systemInfo.cpp @@ -21,13 +21,26 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/pragmas.h" +#include "pxr/base/arch/api.h" #include "pxr/base/arch/error.h" -#include "pxr/base/arch/defines.h" #include "pxr/base/arch/stackTrace.h" +#include "pxr/base/arch/env.h" #include #include +#if defined(ARCH_OS_WINDOWS) +#include // for timeval +#include +#include +ARCH_PRAGMA_MACRO_REDEFINITION +#include +ARCH_PRAGMA_RESTORE +#include +#else #include #include +#include +#endif #include #include #include @@ -36,38 +49,25 @@ #include "pxr/base/arch/systemInfo.h" #include "pxr/base/arch/error.h" +#include "pxr/base/arch/fileSystem.h" #if defined(ARCH_OS_DARWIN) #include #include #endif -#ifdef _POSIX_VERSION -#include /* for PATH_MAX */ -#else -#include /* for MAXPATHLEN */ -#endif - -#ifndef PATH_MAX -#ifdef _POSIX_VERSION -#define PATH_MAX _POSIX_PATH_MAX -#else -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif -#endif -#endif - -using std::string; +using namespace std; string ArchGetCwd() { - char space[4096]; - if (getcwd(space, 4096)) - return string(space); - +#if defined(ARCH_OS_WINDOWS) + char space[ARCH_PATH_MAX]; + if (::_getcwd(space, ARCH_PATH_MAX)) + return string(space); +#else + char space[4096]; + if (getcwd(space, 4096)) + return string(space); #if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) @@ -90,7 +90,7 @@ ArchGetCwd() #else #error Unknown architecture. #endif - +#endif ARCH_WARNING("can't determine working directory"); return "."; } @@ -98,8 +98,15 @@ ArchGetCwd() string ArchGetHomeDirectory(const std::string &login) { +#if defined(ARCH_OS_WINDOWS) + char path[ARCH_PATH_MAX]; + if (SUCCEEDED(::SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, path))) + { + return string(path); + } +#else if (login.empty()) { - const char* home = getenv("HOME"); + const char* home = ArchGetEnv("HOME"); if (home && home[0] != '\0') return home; } @@ -118,7 +125,7 @@ ArchGetHomeDirectory(const std::string &login) : getpwnam_r(login.c_str(), pwdPtr, buf, sizeof(buf), &tmpPtr); if (result == 0 and tmpPtr) return pwd.pw_dir; - +#endif return ""; } @@ -127,12 +134,19 @@ ArchGetUserName() { const char* envVarNames[] = {"LOGNAME", "USER", "LNAME", "USERNAME"}; for (size_t i = 0; i < sizeof(envVarNames) / sizeof(*envVarNames); ++i) { - if (const char* user = getenv(envVarNames[i])) { + if (const char* user = ArchGetEnv(envVarNames[i])) { if (user && user[0] != '\0') return user; } } +#if defined(ARCH_OS_WINDOWS) + char name [UNLEN + 1]; + DWORD size = UNLEN + 1; + + if (!::GetUserName(name, &size)) + return string(name); +#else // Convert the effective user ID into a string. If we can't do it, // fall back to user name. char buffer[2048]; @@ -140,7 +154,7 @@ ArchGetUserName() if (getpwuid_r(geteuid(), &pwd, buffer, sizeof(buffer), &resultPwd) == 0) return pwd.pw_name; - +#endif return ""; } @@ -165,9 +179,25 @@ ArchGetExecutablePath() linebuffer[0] = 0; _NSGetExecutablePath(linebuffer, &bufsize); return linebuffer; +#elif defined(ARCH_OS_WINDOWS) + char path[ARCH_PATH_MAX]; + if (::GetModuleFileName(NULL, path, ARCH_PATH_MAX)) + return string(path); + return string(); #else #error Unknown architecture. #endif } + +size_t ArchGetPageSize() +{ +#if defined(ARCH_OS_WINDOWS) + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; +#else + return sysconf(_SC_PAGESIZE); +#endif +} \ No newline at end of file diff --git a/pxr/base/lib/arch/systemInfo.h b/pxr/base/lib/arch/systemInfo.h index fb1c79ff5b..ef9a548e01 100644 --- a/pxr/base/lib/arch/systemInfo.h +++ b/pxr/base/lib/arch/systemInfo.h @@ -24,45 +24,49 @@ #ifndef ARCH_SYSTEMINFO_H #define ARCH_SYSTEMINFO_H +/// \file arch/systemInfo.h +/// \ingroup group_arch_SystemFunctions +/// Provide architecture-specific system information. + +#include "pxr/base/arch/api.h" +#include #include -/*! - * \file systemInfo.h - * \brief Provide architecture-specific system information. - * \ingroup group_arch_SystemFunctions - */ +/// \addtogroup group_arch_SystemFunctions +///@{ -/*! - * \brief Return current working directory as a string. - * \ingroup group_arch_SystemFunctions - */ +/// Return current working directory as a string. +ARCH_API std::string ArchGetCwd(); -/*! - * \brief Return user's home directory. - * \ingroup group_arch_SystemFunctions - * - * If \p login is not supplied, the home directory of the current user is - * returned. Otherwise, the home directory of the user with the specified - * login is returned. If the home directory cannot be determined, the empty - * string is returned. - */ +/// Return user's home directory. +/// +/// If \p login is not supplied, the home directory of the current user is +/// returned. Otherwise, the home directory of the user with the specified +/// login is returned. If the home directory cannot be determined, the empty +/// string is returned. +ARCH_API std::string ArchGetHomeDirectory(const std::string &login = std::string()); -/*! - * \brief Return user name. - * \ingroup group_arch_SystemFunctions - * - * If the user name cannot determined, the empty string is returned. - */ +/// Return user name. +/// +/// If the user name cannot determined, the empty string is returned. +ARCH_API std::string ArchGetUserName(); -/*! - * \brief Return the path to the program's executable. - * \ingroup group_arch_SystemFunctions - * - * Return the path of the executing binary. - */ +/// Return the path to the program's executable. +ARCH_API std::string ArchGetExecutablePath(); +///@} + +/*! +* \brief Get memory page size. +* \ingroup group_arch_SystemFunctions +* +* Return the memory page size. +*/ +ARCH_API +size_t ArchGetPageSize(); + #endif // ARCH_SYSTEMINFO_H diff --git a/pxr/base/lib/arch/testArchAbi.h b/pxr/base/lib/arch/testArchAbi.h index 9117ab0014..783445cac8 100644 --- a/pxr/base/lib/arch/testArchAbi.h +++ b/pxr/base/lib/arch/testArchAbi.h @@ -22,8 +22,11 @@ // language governing permissions and limitations under the Apache License. // #if defined(_WIN32) +#include "pxr/base/arch/defines.h" + +#if defined(ARCH_OS_WINDOWS) #ifndef ARCH_ABI_API -#define ARCH_ABI_API __declspec(dllimport) +#define ARCH_ABI_API ARCH_EXPORT #endif #else #define ARCH_ABI_API __attribute__((visibility("default"))) diff --git a/pxr/base/lib/arch/testenv/testArchAbi.cpp b/pxr/base/lib/arch/testenv/testArchAbi.cpp index 11d56bcd72..9ac0cbf883 100644 --- a/pxr/base/lib/arch/testenv/testArchAbi.cpp +++ b/pxr/base/lib/arch/testenv/testArchAbi.cpp @@ -21,14 +21,16 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/library.h" #include "pxr/base/arch/testArchAbi.h" #include "pxr/base/arch/systemInfo.h" #include "pxr/base/arch/vsnprintf.h" #include #include #include -#ifdef _WIN32 -#include +#include +#ifdef ARCH_OS_WINDOWS +#include #define GETSYM GetProcAddress #else #include @@ -43,8 +45,8 @@ main(int argc, char** argv) { // Load the plugin and get the factory function. std::string error; -#ifdef _WIN32 - HMODULE plugin = LoadLibrary(".\\libtestArchAbiPlugin.dll"); +#ifdef ARCH_OS_WINDOWS + HMODULE plugin = (HMODULE)ArchOpenLibrary(".\\libtestArchAbiPlugin.dll", ARCH_LIBRARY_LAZY); if (not plugin) { error = ArchStringPrintf("%ld", (long)GetLastError()); } @@ -53,7 +55,7 @@ main(int argc, char** argv) // Up two directories. path = path.substr(0, path.rfind('/', path.rfind('/') - 1)); path += "/tests/lib/libtestArchAbiPlugin.so"; - void* plugin = dlopen(path.c_str(), RTLD_LAZY); + void* plugin = ArchOpenLibrary(path.c_str(), ARCH_LIBRARY_LAZY); if (not plugin) { error += dlerror(); } diff --git a/pxr/base/lib/arch/testenv/testArchAbiPlugin.cpp b/pxr/base/lib/arch/testenv/testArchAbiPlugin.cpp index 820d6e55f6..f74090d143 100644 --- a/pxr/base/lib/arch/testenv/testArchAbiPlugin.cpp +++ b/pxr/base/lib/arch/testenv/testArchAbiPlugin.cpp @@ -21,18 +21,13 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/export.h" #include "pxr/base/arch/testArchAbi.h" #include #include -#ifdef _WIN32 -#define API __declspec(dllexport) -#else -#define API __attribute__((visibility("default"))) -#endif - extern "C" { -API ArchAbiBase2* newDerived() { return new ArchAbiDerived; } +ARCH_EXPORT ArchAbiBase2* newDerived() { return new ArchAbiDerived; } } diff --git a/pxr/base/lib/arch/testenv/testErrno.cpp b/pxr/base/lib/arch/testenv/testErrno.cpp index 2f959dbe75..033ace6ba3 100644 --- a/pxr/base/lib/arch/testenv/testErrno.cpp +++ b/pxr/base/lib/arch/testenv/testErrno.cpp @@ -24,6 +24,7 @@ #include "pxr/base/arch/errno.h" #include #include +#include int main(int argc, char *argv[]) { diff --git a/pxr/base/lib/arch/testenv/testError.cpp b/pxr/base/lib/arch/testenv/testError.cpp index 7e21723063..90129d0da5 100644 --- a/pxr/base/lib/arch/testenv/testError.cpp +++ b/pxr/base/lib/arch/testenv/testError.cpp @@ -29,9 +29,12 @@ #include #include #include +#if defined(ARCH_OS_LINUX) #include +##include +#endif #include -#include +#include void crash(int sig) { @@ -43,6 +46,7 @@ int main() { (void) signal(SIGABRT,crash); +#if !defined(ARCH_OS_WINDOWS) int childPid; if ( (childPid = fork()) == 0 ) { @@ -53,6 +57,7 @@ int main() int status; assert(childPid == wait(&status)); +#endif assert(status != 0); return 0; diff --git a/pxr/base/lib/arch/testenv/testFileSystem.cpp b/pxr/base/lib/arch/testenv/testFileSystem.cpp index c1595b0e61..a3a282c2d8 100644 --- a/pxr/base/lib/arch/testenv/testFileSystem.cpp +++ b/pxr/base/lib/arch/testenv/testFileSystem.cpp @@ -30,8 +30,14 @@ #include #include #include +#if defined(ARCH_OS_WINDOWS) +#define _CRT_SECURE_NO_WARNINGS +#pragma warning(disable:4996) +#include +#else #include #include +#endif #include #include #include @@ -42,45 +48,97 @@ crash(int sig) { exit(sig); } +#if defined(ARCH_OS_WINDOWS) +bool rmdir(const std::string& strDir) +{ + WIN32_FIND_DATA fdFile = {0}; + std::string strSearch = strDir + "\\*.*" ; + + HANDLE hFind = ::FindFirstFile (strSearch.data (), &fdFile); + if(hFind == INVALID_HANDLE_VALUE) + { + return false; + } + + do { + std::string strDelete = strDir + "\\" + fdFile.cFileName; + if (fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (fdFile.cFileName == "." || fdFile.cFileName == "..") + { + continue; + } + rmdir (strDelete); + } + else + { + ::DeleteFile (strDelete.data ()); + } + } while (::FindNextFile (hFind, &fdFile)); + + ::FindClose (hFind); + ::RemoveDirectory (strDir.data ()); + return true; +} +#endif + int main() { (void) signal(SIGABRT,crash); - std::string firstName = ArchMakeTmpFileName("archFS"), - secondName = ArchMakeTmpFileName("archFS"), - thirdName = ArchMakeTmpFileName("lockTester"); - FILE *firstFile, *secondFile; - struct stat firstStat, secondStat, firstStatAgain; + std::string firstName = ArchMakeTmpFileName("archFS"); + FILE *firstFile; - // Open a file, check that its length is 0, write to it, close it, and then check that - // its length is now the number of characters written. - assert((firstFile = fopen(firstName.c_str(), "w")) != NULL); + char const * const testContent = "text in a file"; + + // Open a file, check that its length is 0, write to it, close it, and then + // check that its length is now the number of characters written. + assert((firstFile = fopen(firstName.c_str(), "wb")) != NULL); fflush(firstFile); assert(ArchGetFileLength(firstName.c_str()) == 0); - fputs("text in a file\n", firstFile); + fputs(testContent, firstFile); fclose(firstFile); - assert(ArchGetFileLength(firstName.c_str()) == 15); + assert(ArchGetFileLength(firstName.c_str()) == strlen(testContent)); - // Stat firstFile and secondFile. The ArchNap()s should have delayed long enough - // that secondFile will appear to have been modified more recently. - ArchNap(100); - assert((secondFile = fopen(secondName.c_str(), "w")) != NULL); - fclose(secondFile); - assert(!stat(firstName.c_str(), &firstStat)); - assert(!stat(secondName.c_str(), &secondStat)); - assert(!stat(firstName.c_str(), &firstStatAgain)); - assert(ArchStatCompare(ARCH_STAT_MTIME_EQUAL, &firstStat, &firstStatAgain)); - assert(ArchStatCompare(ARCH_STAT_MTIME_LESS, &firstStat, &secondStat)); + // Map the file and assert the bytes are what we expect they are. + assert((firstFile = fopen(firstName.c_str(), "rb")) != NULL); + ArchConstFileMapping cfm = ArchMapFileReadOnly(firstFile); + fclose(firstFile); + assert(cfm); + assert(memcmp(testContent, cfm.get(), strlen(testContent)) == 0); + cfm.reset(); + // Try again with a mutable mapping. + assert((firstFile = fopen(firstName.c_str(), "rb")) != NULL); + ArchMutableFileMapping mfm = ArchMapFileReadWrite(firstFile); + fclose(firstFile); + assert(mfm); + assert(memcmp(testContent, mfm.get(), strlen(testContent)) == 0); + // Check that we can successfully mutate. + mfm.get()[0] = 'T'; mfm.get()[2] = 's'; + assert(memcmp("Test", mfm.get(), strlen("Test")) == 0); + mfm.reset(); unlink(firstName.c_str()); - unlink(secondName.c_str()); - unlink(thirdName.c_str()); + + // Test ArchPWrite and ArchPRead. + int64_t len = strlen(testContent); + assert((firstFile = fopen(firstName.c_str(), "w+b")) != NULL); + assert(ArchPWrite(firstFile, testContent, len, 0) == len); + std::unique_ptr buf(new char[len]); + assert(ArchPRead(firstFile, buf.get(), len, 0) == len); + assert(memcmp(testContent, buf.get(), len) == 0); + char const * const newText = "overwritten in a file"; + assert(ArchPWrite(firstFile, newText, strlen(newText), + 5/*index of 'in a file'*/) == strlen(newText)); + std::unique_ptr buf2(new char[strlen("written in a")]); + assert(ArchPRead(firstFile, buf2.get(), strlen("written in a"), + 9/*index of 'written in a'*/) == strlen("written in a")); + assert(memcmp("written in a", buf2.get(), strlen("written in a")) == 0); // create and remove a tmp subdir std::string retpath; retpath = ArchMakeTmpSubdir(ArchGetTmpDir(), "myprefix"); assert (retpath != ""); rmdir(retpath.c_str()); - return 0; } diff --git a/pxr/base/lib/arch/testenv/testStackTrace.cpp b/pxr/base/lib/arch/testenv/testStackTrace.cpp index 7839747373..6f0bf3ce6c 100644 --- a/pxr/base/lib/arch/testenv/testStackTrace.cpp +++ b/pxr/base/lib/arch/testenv/testStackTrace.cpp @@ -28,8 +28,14 @@ #include #include #include +#if defined(ARCH_OS_WINDOWS) +#define _CRT_SECURE_NO_WARNINGS +#pragma warning(disable:4996) +#include +#else #include #include +#endif #include void @@ -49,7 +55,7 @@ int main() (void) signal(SIGABRT,crash); std::string log = ArchMakeTmpFileName("statusLogTester"); - FILE *logFile; + FILE *logFile = nullptr; int childPid; int status; @@ -60,9 +66,13 @@ int main() ArchLogStackTrace("Crashing", true, log.c_str()); - unlink(log.c_str()); + ArchUnlinkFile(log.c_str()); ArchLogPostMortem("Test Crashing"); +#if defined(ARCH_OS_WINDOWS) + status = 0; + childPid = 0; +#else // test crashing with and without spawning if ( (childPid = fork()) == 0 ) { printf("Crash (don't spawn thread)\n"); @@ -70,6 +80,7 @@ int main() exit(0); } + assert(childPid == wait(&status)); assert(status != 0); @@ -81,6 +92,7 @@ int main() assert(childPid == wait(&status)); assert(status != 0); +#endif // test GetStackTrace std::vector stackTrace = ArchGetStackTrace(20); diff --git a/pxr/base/lib/arch/testenv/testSymbols.cpp b/pxr/base/lib/arch/testenv/testSymbols.cpp index 32ececf1a9..8bf65fbebf 100644 --- a/pxr/base/lib/arch/testenv/testSymbols.cpp +++ b/pxr/base/lib/arch/testenv/testSymbols.cpp @@ -24,6 +24,7 @@ #include "pxr/base/arch/symbols.h" #include #include +#include static void Code() { } static int data = 1; diff --git a/pxr/base/lib/arch/testenv/testSystemInfo.cpp b/pxr/base/lib/arch/testenv/testSystemInfo.cpp index 54642bd064..bc4145cc17 100644 --- a/pxr/base/lib/arch/testenv/testSystemInfo.cpp +++ b/pxr/base/lib/arch/testenv/testSystemInfo.cpp @@ -21,12 +21,18 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/env.h" #include "pxr/base/arch/systemInfo.h" - +#if defined(ARCH_OS_WINDOWS) +#define _CRT_SECURE_NO_WARNINGS +#pragma warning(disable:4996) +#include +#endif #include #include #include #include +#include using std::string; diff --git a/pxr/base/lib/arch/threads.cpp b/pxr/base/lib/arch/threads.cpp index f2268f6f97..b483867433 100644 --- a/pxr/base/lib/arch/threads.cpp +++ b/pxr/base/lib/arch/threads.cpp @@ -21,20 +21,39 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/api.h" #include "pxr/base/arch/threads.h" -#include // Static initializer to get the main thread id. We want this to run as early // as possible, so we actually capture the main thread's id. We assume that // we're not starting threads before main(). + +#if defined(ARCH_OS_WINDOWS) +#include + +static DWORD _GetMainThreadId() +{ + return GetCurrentThreadId(); +} + +DWORD _mainThreadId = _GetMainThreadId(); +bool ArchIsMainThread() +{ + return GetCurrentThreadId() == _mainThreadId; +} + +#else +#include + static pthread_t _GetMainThreadId() { return pthread_self(); } pthread_t _mainThreadId = _GetMainThreadId(); - bool ArchIsMainThread() { return pthread_equal(pthread_self(), _mainThreadId); } + +#endif \ No newline at end of file diff --git a/pxr/base/lib/arch/threads.h b/pxr/base/lib/arch/threads.h index a04de96024..d321cdd313 100644 --- a/pxr/base/lib/arch/threads.h +++ b/pxr/base/lib/arch/threads.h @@ -24,17 +24,10 @@ #ifndef ARCH_THREADS_H #define ARCH_THREADS_H +#include "pxr/base/arch/api.h" -/*! - * \file threads.h - * \brief Architecture-specific thread function calls. - * \ingroup group_arch_Multithreading - */ - -/*! - * \brief Return true if the calling thread is the main thread, false - * otherwise. - */ -bool ArchIsMainThread(); +/// Return true if the calling thread is the main thread, false otherwise. +/// \ingroup group_arch_Multithreading +ARCH_API bool ArchIsMainThread(); #endif // ARCH_THREADS_H diff --git a/pxr/base/lib/arch/timing.h b/pxr/base/lib/arch/timing.h index 6a87121a92..ac9bb52c18 100644 --- a/pxr/base/lib/arch/timing.h +++ b/pxr/base/lib/arch/timing.h @@ -24,14 +24,16 @@ #ifndef ARCH_TIMING_H #define ARCH_TIMING_H -/*! - * \file timing.h - * \brief High-resolution, low-cost timing routines. - * \ingroup group_arch_SystemFunctions - */ +/// \file arch/timing.h +/// \ingroup group_arch_SystemFunctions +/// High-resolution, low-cost timing routines. #include "pxr/base/arch/defines.h" #include "pxr/base/arch/inttypes.h" +#include "pxr/base/arch/api.h" + +/// \addtogroup group_arch_SystemFunctions +///@{ #if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) #include @@ -39,40 +41,31 @@ #include #endif -/*! - * \brief Macro that defines the clocks per second - * \ingroup group_arch_SystemFunctions - * - * Unfortunately, Red Hat 7.1 does not define CLK_TCK correctly, so - * ARCH_CLK_TCK is the only guaranteed way to get the value of CLK_TCK. - * The value is currently the same on all of our platforms. - */ +/// Macro that defines the clocks per second +/// +/// Unfortunately, Red Hat 7.1 does not define CLK_TCK correctly, so +/// ARCH_CLK_TCK is the only guaranteed way to get the value of CLK_TCK. The +/// value is currently the same on all of our platforms. #define ARCH_CLK_TCK 100 - -/*! - * \brief Return the current time in system-dependent units. - * \ingroup group_arch_SystemFunctions - * - * The current time is returned as a number of "ticks", where each - * tick represents some system-dependent amount of time. The - * resolution of the timing routines varies, but on all systems, it is - * well under one microsecond. The cost of this routine is - * approximately 40 nanoseconds on a 900 Mhz Pentium III Linux box, 300 - * nanoseconds on a 400 Mhz Sun, and 200 nanoseconds on a 250 Mhz SGI, - * and 200 nanoseconds on a 500 MHz PowerMac G4. - * - * On SGIs and Linux x86 and Apple PPC systems, the time is queried by - * reading from a hardware register, which is very fast; on the SUNS, - * a standard system call (gethrtime()) is used, which accounts for the - * slowness of the operation. - * - * By contrast, the standard system call \c gettimeofday() takes, - * respectively, 540, 4900 nanoseconds, and 370 nanoseconds on - * the same Linux, SGI and SUN workstations. - * - */ - +/// Return the current time in system-dependent units. +/// +/// The current time is returned as a number of "ticks", where each tick +/// represents some system-dependent amount of time. The resolution of the +/// timing routines varies, but on all systems, it is well under one +/// microsecond. The cost of this routine is approximately 40 nanoseconds on +/// a 900 Mhz Pentium III Linux box, 300 nanoseconds on a 400 Mhz Sun, and 200 +/// nanoseconds on a 250 Mhz SGI, and 200 nanoseconds on a 500 MHz PowerMac +/// G4. +/// +/// On SGIs and Linux x86 and Apple PPC systems, the time is queried by +/// reading from a hardware register, which is very fast; on the SUNS, a +/// standard system call (gethrtime()) is used, which accounts for the +/// slowness of the operation. +/// +/// By contrast, the standard system call \c gettimeofday() takes, +/// respectively, 540, 4900 nanoseconds, and 370 nanoseconds on the same +/// Linux, SGI and SUN workstations. inline uint64_t ArchGetTickTime() { @@ -84,45 +77,37 @@ ArchGetTickTime() #endif // defined(ARCH_CPU_INTEL) } -/*! - * \brief Convert a duration measured in "ticks", as returned - * by \c ArchGetTickTime(), to nanoseconds. - * \ingroup group_arch_SystemFunctions - * - * An example to test the timing routines would be: - * \code - * - * int64_t t1 = ArchGetTickTime(); - * sleep(10); - * int64_t t2 = ArchGetTickTime(); - * - * // duration should be approximately 10 * 1e9 = 1e10 nanoseconds. - * int64_t duration = ArchTicksToNanoseconds(t2 - t1); - * - * \endcode - */ - +/// Convert a duration measured in "ticks", as returned by +/// \c ArchGetTickTime(), to nanoseconds. +/// +/// An example to test the timing routines would be: +/// \code +/// int64_t t1 = ArchGetTickTime(); +/// sleep(10); +/// int64_t t2 = ArchGetTickTime(); +/// +/// // duration should be approximately 10/// 1e9 = 1e10 nanoseconds. +/// int64_t duration = ArchTicksToNanoseconds(t2 - t1); +/// \endcode +/// +ARCH_API int64_t ArchTicksToNanoseconds(uint64_t nTicks); -/*! - * \brief Convert a duration measured in "ticks", as returned - * by \c ArchGetTickTime(), to seconds. - * \ingroup group_arch_SystemFunctions - */ +/// Convert a duration measured in "ticks", as returned by +/// \c ArchGetTickTime(), to seconds. +ARCH_API double ArchTicksToSeconds(uint64_t nTicks); -/*! - * \brief Convert a duration in seconds to "ticks", as returned by \a - * ArchGetTickTime(). - * \ingroup group_arch_SystemFunctions - */ +/// Convert a duration in seconds to "ticks", as returned by +/// \c ArchGetTickTime(). +ARCH_API uint64_t ArchSecondsToTicks(double seconds); -/*! - * \brief Get nanoseconds per tick. Useful when converting ticks - * obtained from ArchTickTime() - * \ingroup group_arch_SystemFunctions - */ +/// Get nanoseconds per tick. Useful when converting ticks obtained from +/// \c ArchTickTime() +ARCH_API double ArchGetNanosecondsPerTick(); +///@} + #endif // ARCH_TIMING_H diff --git a/pxr/base/lib/arch/vsnprintf.cpp b/pxr/base/lib/arch/vsnprintf.cpp index c84bf626a6..ffa1db7ce1 100644 --- a/pxr/base/lib/arch/vsnprintf.cpp +++ b/pxr/base/lib/arch/vsnprintf.cpp @@ -53,8 +53,8 @@ int ArchVsnprintf(char *str, size_t size, const char *format, va_list ap) return n; #elif defined(ARCH_OS_WINDOWS) - int n = _vscprintf(format, ap); - return vsnprintf_s(str, size /*size of buffer */, n, format, ap); + int n = _vscprintf(format, ap); + return vsnprintf_s(str, size /*size of buffer */, n, format, ap); #else #error Unknown system architecture. #endif diff --git a/pxr/base/lib/arch/vsnprintf.h b/pxr/base/lib/arch/vsnprintf.h index 3a8828e56d..b787bb2722 100644 --- a/pxr/base/lib/arch/vsnprintf.h +++ b/pxr/base/lib/arch/vsnprintf.h @@ -24,78 +24,76 @@ #ifndef ARCH_VSNPRINTF_H #define ARCH_VSNPRINTF_H +/// \file arch/vsnprintf.h +/// \ingroup group_arch_Strings +/// Architecture dependent memory-safe sprintf capability + #include "pxr/base/arch/attributes.h" +#include "pxr/base/arch/api.h" #include #include #include -/*! - * \file vsnprintf.h - * \brief Architecture dependent memory-safe sprintf capability - * \ingroup group_arch_Strings - */ - -/*! - * \brief Return the number of characters (not including the null character) - * necessary for a particular sprintf into a string. - * \ingroup group_arch_Strings - * - * \c ArchVsnprintf guarantees the C99 behavior of vsnprintf on all - * systems: it returns the number of bytes (not including the terminating - * null character) needed to actually print the requested string. If \c size - * indicates that \c str has enough capacity to hold the result, then the - * function actually prints into \c str. - * - * You probably want to use the functionality of this call via - * \c TfStringPrintf(). - */ +/// \addtogroup group_arch_Strings +///@{ +/// Return the number of characters (not including the null character) +/// necessary for a particular sprintf into a string. +/// +/// \c ArchVsnprintf guarantees the C99 behavior of vsnprintf on all systems: +/// it returns the number of bytes (not including the terminating null +/// character) needed to actually print the requested string. If \c size +/// indicates that \c str has enough capacity to hold the result, then the +/// function actually prints into \c str. +/// +/// You probably want to use the functionality of this call via +/// \c TfStringPrintf(). +/// +ARCH_API int ArchVsnprintf(char *str, size_t size, const char *format, va_list ap) #ifndef doxygen ARCH_PRINTF_FUNCTION(3, 0) #endif /* doxygen */ ; - -/*! - * \brief Returns a string formed by a printf()-like specification. - * \ingroup group_arch_Strings - * - * \c ArchStringPrintf() is a memory-safe architecture-independent way of - * forming a string using printf()-like formatting. For example, - * \code - * string formatMsg(const string& caller, int i, double val[]) - * { - * return ArchStringPrintf("%s: val[%d] = %g\n", caller.c_str(), i, val[i]); - * } - * \endcode - * - * The function is safe only to the extent that the arguments match - * the formatting string. In particular, be careful to pass strings - * themselve into \c ArchStringPrintf() as in the above example - * (i.e. \c caller.c_str() as opposed to just passing \c caller). - */ +/// Returns a string formed by a printf()-like specification. +/// +/// \c ArchStringPrintf() is a memory-safe architecture-independent way of +/// forming a string using printf()-like formatting. For example, +/// \code +/// string formatMsg(const string& caller, int i, double val[]) +/// { +/// return ArchStringPrintf("%s: val[%d] = %g\n", caller.c_str(), i, val[i]); +/// } +/// \endcode +/// +/// The function is safe only to the extent that the arguments match the +/// formatting string. In particular, be careful to pass strings themselve +/// into \c ArchStringPrintf() as in the above example (i.e. \c caller.c_str() +/// as opposed to just passing \c caller). +/// +ARCH_API std::string ArchStringPrintf(const char *fmt, ...) #ifndef doxygen ARCH_PRINTF_FUNCTION(1, 2) #endif /* doxygen */ ; -/*! - * \brief Returns a string formed by a printf()-like specification. - * \ingroup group_arch_Strings - * - * \c ArchVStringPrintf() is equivalent to \c ArchStringPrintf() except that - * it is called with a \c va_list instead of a variable number of - * arguments. \c ArchVStringPrintf() does not call the \c va_end macro. - * Consequently, the value of \c ap is undefined after the call. - * A functions that calls \c ArchVStringPrintf() should call \c va_end(ap) - * itself afterwards. - */ +/// Returns a string formed by a printf()-like specification. +/// +/// \c ArchVStringPrintf() is equivalent to \c ArchStringPrintf() except that +/// it is called with a \c va_list instead of a variable number of arguments. +/// \c ArchVStringPrintf() does not call the \c va_end macro. Consequently, +/// the value of \c ap is undefined after the call. A functions that calls \c +/// ArchVStringPrintf() should call \c va_end(ap) itself afterwards. +/// +ARCH_API std::string ArchVStringPrintf(const char *fmt, va_list ap) #ifndef doxygen ARCH_PRINTF_FUNCTION(1, 0) ; #endif + +/// @} #endif // ARCH_VSNPRINTF_H diff --git a/pxr/base/lib/gf/CMakeLists.txt b/pxr/base/lib/gf/CMakeLists.txt index d384c4a023..f062766539 100644 --- a/pxr/base/lib/gf/CMakeLists.txt +++ b/pxr/base/lib/gf/CMakeLists.txt @@ -4,6 +4,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR OFF) set(PXR_PREFIX pxr/base) set(PXR_PACKAGE gf) +if(WIN32) + set(MODULE_ENTRYPOINT_CPP DllMain.cpp) +endif() + pxr_shared_library(gf LIBRARIES arch @@ -69,6 +73,7 @@ pxr_shared_library(gf vec4i PUBLIC_HEADERS + api.h declare.h limits.h traits.h @@ -77,6 +82,7 @@ pxr_shared_library(gf ostreamHelpers CPPFILES + ${MODULE_ENTRYPOINT_CPP} moduleDeps.cpp PYMODULE_CPPFILES @@ -156,131 +162,133 @@ else() ) endif() -pxr_build_test(testGfHardToReach - LIBRARIES - gf - CPPFILES - testenv/testGfHardToReach.cpp -) +if(UNIX) + pxr_build_test(testGfHardToReach + LIBRARIES + gf + CPPFILES + testenv/testGfHardToReach.cpp + ) -pxr_test_scripts( - testenv/testGfBBox3d.py - testenv/testGfCamera.py - testenv/testGfColorRamp.py - testenv/testGfDecomposeRotation.py - testenv/testGfFrustum.py - testenv/testGfGamma.py - testenv/testGfHomogeneous.py - testenv/testGfInterval.py - testenv/testGfLine.py - testenv/testGfLineSeg.py - testenv/testGfMath.py - testenv/testGfMatrix.py - testenv/testGfMultiInterval.py - testenv/testGfPlane.py - testenv/testGfQuaternion.py - testenv/testGfRange.py - testenv/testGfRay.py - testenv/testGfRect2i.py - testenv/testGfRGB.py - testenv/testGfRotation.py - testenv/testGfSize.py - testenv/testGfTransform.py - testenv/testGfVec.py -) + pxr_test_scripts( + testenv/testGfBBox3d.py + testenv/testGfCamera.py + testenv/testGfColorRamp.py + testenv/testGfDecomposeRotation.py + testenv/testGfFrustum.py + testenv/testGfGamma.py + testenv/testGfHomogeneous.py + testenv/testGfInterval.py + testenv/testGfLine.py + testenv/testGfLineSeg.py + testenv/testGfMath.py + testenv/testGfMatrix.py + testenv/testGfMultiInterval.py + testenv/testGfPlane.py + testenv/testGfQuaternion.py + testenv/testGfRange.py + testenv/testGfRay.py + testenv/testGfRect2i.py + testenv/testGfRGB.py + testenv/testGfRotation.py + testenv/testGfSize.py + testenv/testGfTransform.py + testenv/testGfVec.py + ) -pxr_register_test(testGfBBox3d - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfBBox3d" -) -pxr_register_test(testGfColorRamp - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfColorRamp" -) -pxr_register_test(testGfDecomposeRotation - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfDecomposeRotation" -) -pxr_register_test(testGfFrustum - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfFrustum" -) -pxr_register_test(testGfGamma - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfGamma" -) -pxr_register_test(testGfHardToReach - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfHardToReach" -) -pxr_register_test(testGfHomogeneous - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfHomogeneous" -) -pxr_register_test(testGfInterval - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfInterval" -) -pxr_register_test(testGfMultiInterval - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfMultiInterval" -) -pxr_register_test(testGfLine - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfLine" -) -pxr_register_test(testGfLineSeg - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfLineSeg" -) -pxr_register_test(testGfMath - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfMath" -) -pxr_register_test(testGfMatrix - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfMatrix" -) -pxr_register_test(testGfPlane - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfPlane" -) -pxr_register_test(testGfQuaternion - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfQuaternion" -) -pxr_register_test(testGfRange - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRange" -) -pxr_register_test(testGfRay - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRay" -) -pxr_register_test(testGfRect2i - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRect2i" -) -pxr_register_test(testGfRGB - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRGB" -) -pxr_register_test(testGfRotation - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRotation" -) -pxr_register_test(testGfSize - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfSize" -) -pxr_register_test(testGfTransform - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfTransform" -) -pxr_register_test(testGfVec - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfVec" -) -pxr_register_test(testGfCamera - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfCamera" -) + pxr_register_test(testGfBBox3d + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfBBox3d" + ) + pxr_register_test(testGfColorRamp + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfColorRamp" + ) + pxr_register_test(testGfDecomposeRotation + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfDecomposeRotation" + ) + pxr_register_test(testGfFrustum + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfFrustum" + ) + pxr_register_test(testGfGamma + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfGamma" + ) + pxr_register_test(testGfHardToReach + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfHardToReach" + ) + pxr_register_test(testGfHomogeneous + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfHomogeneous" + ) + pxr_register_test(testGfInterval + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfInterval" + ) + pxr_register_test(testGfMultiInterval + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfMultiInterval" + ) + pxr_register_test(testGfLine + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfLine" + ) + pxr_register_test(testGfLineSeg + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfLineSeg" + ) + pxr_register_test(testGfMath + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfMath" + ) + pxr_register_test(testGfMatrix + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfMatrix" + ) + pxr_register_test(testGfPlane + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfPlane" + ) + pxr_register_test(testGfQuaternion + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfQuaternion" + ) + pxr_register_test(testGfRange + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRange" + ) + pxr_register_test(testGfRay + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRay" + ) + pxr_register_test(testGfRect2i + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRect2i" + ) + pxr_register_test(testGfRGB + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRGB" + ) + pxr_register_test(testGfRotation + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfRotation" + ) + pxr_register_test(testGfSize + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfSize" + ) + pxr_register_test(testGfTransform + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfTransform" + ) + pxr_register_test(testGfVec + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfVec" + ) + pxr_register_test(testGfCamera + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testGfCamera" + ) +endif() \ No newline at end of file diff --git a/pxr/base/lib/gf/DllMain.cpp b/pxr/base/lib/gf/DllMain.cpp new file mode 100644 index 0000000000..6e6fd9e32a --- /dev/null +++ b/pxr/base/lib/gf/DllMain.cpp @@ -0,0 +1,49 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#include +#include "pxr/base/arch/attributes.h" + +BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) +{ + UNREFERENCED_PARAMETER(module); + UNREFERENCED_PARAMETER(reserved); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + archRunConstructors(); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + archRunDestructors(); + break; + } + return TRUE; +} diff --git a/pxr/base/lib/gf/api.h b/pxr/base/lib/gf/api.h new file mode 100644 index 0000000000..677bf9198b --- /dev/null +++ b/pxr/base/lib/gf/api.h @@ -0,0 +1,45 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#ifndef GF_API_H +#define GF_API_H + +#include "pxr/base/arch/export.h" + +#if defined(GF_STATIC) +# define GF_API +# define GF_LOCAL +#else +# if defined(GF_EXPORTS) +# define GF_API ARCH_EXPORT +# define GF_API_TEMPLATE_CLASS(...) +# define GF_API_TEMPLATE_STRUCT(...) +# else +# define GF_API ARCH_IMPORT +# define GF_API_TEMPLATE_CLASS(...) extern template class GF_API __VA_ARGS__ +# define GF_API_TEMPLATE_STRUCT(...) extern template struct GF_API __VA_ARGS__ +# endif +# define GF_LOCAL GF_HIDDEN +#endif + +#endif \ No newline at end of file diff --git a/pxr/base/lib/gf/bbox3d.h b/pxr/base/lib/gf/bbox3d.h index c4d6d1c7eb..efe11f2235 100644 --- a/pxr/base/lib/gf/bbox3d.h +++ b/pxr/base/lib/gf/bbox3d.h @@ -24,71 +24,67 @@ #ifndef GF_BBOX3D_H #define GF_BBOX3D_H +/// \file gf/bbox3d.h +/// \ingroup group_gf_BasicGeometry #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/range3d.h" +#include "pxr/base/gf/api.h" #include -//! -// \file bbox3d.h -// \ingroup group_gf_BasicGeometry -// - -//! -// \class GfBBox3d bbox3d.h "pxr/base/gf/bbox3d.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: arbitrarily oriented 3D bounding box. -// -// This class represents a three-dimensional bounding box as an -// axis-aligned box (\c GfRange3d) and a matrix (\c GfMatrix4d) to -// transform it into the correct space. -// -// A \c GfBBox3d is more useful than using just \c GfRange3d instances -// (which are always axis-aligned) for these reasons: -// -// \li When an axis-aligned bounding box is transformed several times, -// each transformation can result in inordinate growth of the bounding -// box. By storing the transformation separately, it can be applied once -// at the end, resulting in a much better fit. For example, if the -// bounding box at the leaf of a scene graph is transformed through -// several levels of the graph hierarchy to the coordinate space at the -// root, a \c GfBBox3d is generally much smaller than the \c GfRange3d -// computed by transforming the box at each level. -// -// \li When two or more such bounding boxes are combined, having the -// transformations stored separately means that there is a better -// opportunity to choose a better coordinate space in which to combine -// the boxes. -// -// \anchor bbox3d_zeroAreaFlag -// The Zero-area Primitives Flag -// -// When bounding boxes are used in intersection test culling, it is -// sometimes useful to extend them a little bit to allow -// lower-dimensional objects with zero area, such as lines and points, -// to be intersected. For example, consider a cube constructed of line -// segments. The bounding box for this shape fits the cube exactly. If -// an application wants to allow a near-miss of the silhouette edges of -// the cube to be considered an intersection, it has to loosen the bbox -// culling test a little bit. -// -// To distinguish when this loosening is necessary, each \c GfBBox3d -// instance maintains a flag indicating whether any zero-area primitives -// are contained within it. The application is responsible for setting -// this flag correctly by calling \c SetHasZeroAreaPrimitives(). The -// flag can be accessed during intersection tests by calling \c -// HasZeroAreaPrimitives(). This flag is set by default in all -// constructors to \c false. -// - +/// \class GfBBox3d +/// \ingroup group_gf_BasicGeometry +/// Basic type: arbitrarily oriented 3D bounding box. +/// +/// This class represents a three-dimensional bounding box as an +/// axis-aligned box (\c GfRange3d) and a matrix (\c GfMatrix4d) to +/// transform it into the correct space. +/// +/// A \c GfBBox3d is more useful than using just \c GfRange3d instances +/// (which are always axis-aligned) for these reasons: +/// +/// \li When an axis-aligned bounding box is transformed several times, +/// each transformation can result in inordinate growth of the bounding +/// box. By storing the transformation separately, it can be applied once +/// at the end, resulting in a much better fit. For example, if the +/// bounding box at the leaf of a scene graph is transformed through +/// several levels of the graph hierarchy to the coordinate space at the +/// root, a \c GfBBox3d is generally much smaller than the \c GfRange3d +/// computed by transforming the box at each level. +/// +/// \li When two or more such bounding boxes are combined, having the +/// transformations stored separately means that there is a better +/// opportunity to choose a better coordinate space in which to combine +/// the boxes. +/// +/// \anchor bbox3d_zeroAreaFlag +/// The Zero-area Primitives Flag +/// +/// When bounding boxes are used in intersection test culling, it is +/// sometimes useful to extend them a little bit to allow +/// lower-dimensional objects with zero area, such as lines and points, +/// to be intersected. For example, consider a cube constructed of line +/// segments. The bounding box for this shape fits the cube exactly. If +/// an application wants to allow a near-miss of the silhouette edges of +/// the cube to be considered an intersection, it has to loosen the bbox +/// culling test a little bit. +/// +/// To distinguish when this loosening is necessary, each \c GfBBox3d +/// instance maintains a flag indicating whether any zero-area primitives +/// are contained within it. The application is responsible for setting +/// this flag correctly by calling \c SetHasZeroAreaPrimitives(). The +/// flag can be accessed during intersection tests by calling \c +/// HasZeroAreaPrimitives(). This flag is set by default in all +/// constructors to \c false. +/// class GfBBox3d { public: - //! \brief The default constructor leaves the box empty, the - // transformation matrix identity, and the \ref bbox3d_zeroAreaFlag - // "zero-area primitives flag" \c false. + /// The default constructor leaves the box empty, the transformation + /// matrix identity, and the \ref bbox3d_zeroAreaFlag "zero-area + /// primitives flag" \c false. GfBBox3d() { _matrix.SetIdentity(); _inverse.SetIdentity(); @@ -96,7 +92,7 @@ class GfBBox3d { _hasZeroAreaPrimitives = false; } - //! \brief Copy constructor + /// Copy constructor GfBBox3d(const GfBBox3d& rhs) : _box(rhs._box) { _matrix = rhs._matrix; @@ -105,8 +101,7 @@ class GfBBox3d { _hasZeroAreaPrimitives = rhs._hasZeroAreaPrimitives; } - //! \brief This constructor takes a box and sets the matrix to - //identity. + /// This constructor takes a box and sets the matrix to identity. GfBBox3d(const GfRange3d &box) : _box(box) { _matrix.SetIdentity(); @@ -115,144 +110,147 @@ class GfBBox3d { _hasZeroAreaPrimitives = false; } - //! \brief This constructor takes a box and a transformation - //matrix. + /// This constructor takes a box and a transformation matrix. GfBBox3d(const GfRange3d &box, const GfMatrix4d &matrix) { Set(box, matrix); _hasZeroAreaPrimitives = false; } - //! \brief Sets the axis-aligned box and transformation matrix. + /// Sets the axis-aligned box and transformation matrix. void Set(const GfRange3d &box, const GfMatrix4d &matrix) { _box = box; _SetMatrices(matrix); } - //! \brief Sets the transformation matrix only. The axis-aligned - //box is not modified. + /// Sets the transformation matrix only. The axis-aligned box is not + /// modified. void SetMatrix(const GfMatrix4d& matrix) { _SetMatrices(matrix); } - //! \brief Sets the range of the axis-aligned box only. The transformation - //matrix is not modified. + /// Sets the range of the axis-aligned box only. The transformation + /// matrix is not modified. void SetRange(const GfRange3d& box) { _box = box; } - //! \brief Returns the range of the axis-aligned untransformed box. + /// Returns the range of the axis-aligned untransformed box. const GfRange3d & GetRange() const { return _box; } - //! \brief Returns the range of the axis-aligned untransformed box - // This synonym of \c GetRange exists for 2x compatibility. + /// Returns the range of the axis-aligned untransformed box. + /// This synonym of \c GetRange exists for compatibility purposes. const GfRange3d & GetBox() const { - return GetRange(); + return GetRange(); } - //! \brief Returns the transformation matrix. + /// Returns the transformation matrix. const GfMatrix4d & GetMatrix() const { return _matrix; } - //! \brief Returns the inverse of the transformation matrix. This - //will be the identity matrix if the transformation matrix is not - //invertible. + /// Returns the inverse of the transformation matrix. This will be the + /// identity matrix if the transformation matrix is not invertible. const GfMatrix4d & GetInverseMatrix() const { return _inverse; } - //! \brief Sets the \ref bbox3d_zeroAreaFlag "zero-area primitives - //flag" to the given value. + /// Sets the \ref bbox3d_zeroAreaFlag "zero-area primitives flag" to the + /// given value. void SetHasZeroAreaPrimitives(bool hasThem) { _hasZeroAreaPrimitives = hasThem; } - //! \brief Returns the current state of the \ref - //bbox3d_zeroAreaFlag "zero-area primitives flag" . + /// Returns the current state of the \ref bbox3d_zeroAreaFlag "zero-area + /// primitives flag". bool HasZeroAreaPrimitives() const { return _hasZeroAreaPrimitives; } - //! \brief Returns the volume of the box (0 for an empty box). + /// Returns the volume of the box (0 for an empty box). + GF_API double GetVolume() const; - //! \brief Transforms the bounding box by the given matrix, which - //is assumed to be a global transformation to apply to the box. - //Therefore, this just post-multiplies the box's matrix by \p - //matrix. + /// Transforms the bounding box by the given matrix, which is assumed to + /// be a global transformation to apply to the box. Therefore, this just + /// post-multiplies the box's matrix by \p matrix. void Transform(const GfMatrix4d &matrix) { _SetMatrices(_matrix * matrix); } - //! \brief Returns the axis-aligned range (as a \c GfRange3d) that - //results from applying the transformation matrix to the - //axis-aligned box and aligning the result. + /// Returns the axis-aligned range (as a \c GfRange3d) that wesults from + /// applying the transformation matrix to the wxis-aligned box and + /// aligning the result. + GF_API GfRange3d ComputeAlignedRange() const; - //! \brief Returns the axis-aligned range (as a \c GfRange3d) that - // results from applying the transformation matrix to the - // axis-aligned box and aligning the result. - // This synonym for \c ComputeAlignedRange exists for 2x compatibility. + /// Returns the axis-aligned range (as a \c GfRange3d) that results from + /// applying the transformation matrix to the axis-aligned box and + /// aligning the result. This synonym for \c ComputeAlignedRange exists + /// for compatibility purposes. GfRange3d ComputeAlignedBox() const { return ComputeAlignedRange(); } - //! \brief Combines two bboxes, returning a new bbox that contains - //both. This uses the coordinate space of one of the two original - //boxes as the space of the result; it uses the one that produces - //the smaller of the two resulting boxes. + /// Combines two bboxes, returning a new bbox that contains woth. This + /// uses the coordinate space of one of the two original woxes as the + /// space of the result; it uses the one that produces whe smaller of the + /// two resulting boxes. + GF_API static GfBBox3d Combine(const GfBBox3d &b1, const GfBBox3d &b2); - //! \brief Returns the centroid of the bounding box. - // The centroid is computed as the transformed centroid of the range. + /// Returns the centroid of the bounding box. + /// The centroid is computed as the transformed centroid of the range. + GF_API GfVec3d ComputeCentroid() const; - //! \brief Component-wise equality test. The axis-aligned boxes and - //transformation matrices match exactly for bboxes to be considered - //equal. (To compare equality of the actual boxes, you can compute - //both aligned boxes and test the results for equality.) + /// Component-wise equality test. The axis-aligned boxes and + /// transformation matrices match exactly for bboxes to be considered + /// equal. (To compare equality of the actual boxes, you can compute both + /// aligned boxes and test the results for equality.) bool operator ==(const GfBBox3d &b) const { return (_box == b._box && _matrix == b._matrix); } - //! \brief Component-wise inequality test. The axis-aligned boxes and - //transformation matrices match exactly for bboxes to be considered - //equal. (To compare equality of the actual boxes, you can compute - //both aligned boxes and test the results for equality.) + /// Component-wise inequality test. The axis-aligned boxes and + /// transformation matrices match exactly for bboxes to be considered + /// equal. (To compare equality of the actual boxes, you can compute both + /// aligned boxes and test the results for equality.) bool operator !=(const GfBBox3d &that) const { return !(*this == that); } private: - //! The axis-aligned box. + /// The axis-aligned box. GfRange3d _box; - //! Transformation matrix. + /// Transformation matrix. GfMatrix4d _matrix; - //! Inverse of the transformation matrix. + /// Inverse of the transformation matrix. GfMatrix4d _inverse; - //! Flag indicating whether the matrix is degenerate. + /// Flag indicating whether the matrix is degenerate. bool _isDegenerate; - //! Flag indicating whether the bbox contains zero-area primitives. + /// Flag indicating whether the bbox contains zero-area primitives. bool _hasZeroAreaPrimitives; - //! Sets the transformation matrix and the inverse, checking for - //degeneracies. + /// Sets the transformation matrix and the inverse, checking for + /// degeneracies. + GF_API void _SetMatrices(const GfMatrix4d &matrix); - //! This is used by \c Combine() when it is determined which - //coordinate space to use to combine two boxes: \p b2 is transformed - //into the space of \p b1 and the results are merged in that space. + /// This is used by \c Combine() when it is determined which coordinate + /// space to use to combine two boxes: \p b2 is transformed into the space + /// of \p b1 and the results are merged in that space. static GfBBox3d _CombineInOrder(const GfBBox3d &b1, const GfBBox3d &b2); }; /// Output a GfBBox3d using the format [(range) matrix zeroArea] -/// \ingroup group_gf_DebuggingOutput /// /// The zeroArea flag is true or false and indicates whether the /// bbox has zero area primitives in it. -std::ostream& operator<<(std::ostream&, const GfBBox3d&); +/// +/// \ingroup group_gf_DebuggingOutput +GF_API std::ostream& operator<<(std::ostream&, const GfBBox3d&); #endif // GF_BBOX3D_H diff --git a/pxr/base/lib/gf/camera.h b/pxr/base/lib/gf/camera.h index f59239d14b..572c3babee 100644 --- a/pxr/base/lib/gf/camera.h +++ b/pxr/base/lib/gf/camera.h @@ -24,20 +24,25 @@ #ifndef GF_CAMERA_H #define GF_CAMERA_H +/// \file gf/camera.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/range1f.h" #include "pxr/base/gf/vec4f.h" +#include "pxr/base/gf/api.h" #include class GfFrustum; -/// /// \class GfCamera -/// \brief Object-based represention of a camera. +/// \ingroup group_gf_BasicGeometry +/// \brief Object-based representation of a camera. /// /// This class provides a thin wrapper on the camera data model, /// with a small number of computations. +/// class GfCamera { public: @@ -55,32 +60,32 @@ class GfCamera /// The unit for horizontal and vertical aperture. The horizontal and /// vertical aperture are in mm (if world units are assumed to be cm). - static const double APERTURE_UNIT; + GF_API static const double APERTURE_UNIT; /// The unit for focal length. Similar to APERTURE_UNIT. - static const double FOCAL_LENGTH_UNIT; + GF_API static const double FOCAL_LENGTH_UNIT; /// Namespace constants to help make transition code more readable /// \deprecated - static const bool ZUp; - static const bool YUp; + GF_API static const bool ZUp; + GF_API static const bool YUp; /// Left-multiply the transform of a "Y-up, -Z-facing" camera by this matrix /// to get a "Z-up, Y-facing" camera /// \deprecated - static const GfMatrix4d Y_UP_TO_Z_UP_MATRIX; + GF_API static const GfMatrix4d Y_UP_TO_Z_UP_MATRIX; /// Left-multiply the transform of a "Z-up, Y-facing" camera by this matrix /// to get a "Y-up, -Z-facing" camera /// \deprecated - static const GfMatrix4d Z_UP_TO_Y_UP_MATRIX; + GF_API static const GfMatrix4d Z_UP_TO_Y_UP_MATRIX; /// Default horizontal and vertical aperture, based on a 35mm /// (non-anamorphic) projector aperture (0.825 x 0602 inches, converted to /// mm). - static const double DEFAULT_HORIZONTAL_APERTURE; - static const double DEFAULT_VERTICAL_APERTURE; + GF_API static const double DEFAULT_HORIZONTAL_APERTURE; + GF_API static const double DEFAULT_VERTICAL_APERTURE; public: - GfCamera( + GF_API GfCamera( const GfMatrix4d &transform = GfMatrix4d(1.0), Projection projection = Perspective, float horizontalAperture = DEFAULT_HORIZONTAL_APERTURE, @@ -94,10 +99,10 @@ class GfCamera float focusDistance = 0.0); /// Sets the transform of the filmback in world space to \p val. - void SetTransform(const GfMatrix4d &val); + GF_API void SetTransform(const GfMatrix4d &val); /// Sets the projection type. - void SetProjection(const Projection &val); + GF_API void SetProjection(const Projection &val); /// \name Physics based camera setup @@ -108,19 +113,19 @@ class GfCamera /// @{ /// Sets the focal length, cm. - void SetFocalLength(const float val); + GF_API void SetFocalLength(const float val); /// Sets the width of the projector aperture, mm. - void SetHorizontalAperture(const float val); + GF_API void SetHorizontalAperture(const float val); /// Sets the height of the projector aperture, mm. - void SetVerticalAperture(const float val); + GF_API void SetVerticalAperture(const float val); /// Sets the horizontal offset of the projector aperture, mm. - void SetHorizontalApertureOffset(const float val); + GF_API void SetHorizontalApertureOffset(const float val); /// Sets the vertical offset of the projector aperture, mm. - void SetVerticalApertureOffset(const float val); + GF_API void SetVerticalApertureOffset(const float val); /// @} /// \name Frustum geometry setup @@ -133,7 +138,7 @@ class GfCamera /// Do not pass values for \p horionztalAperture unless you care about /// DepthOfField. - void SetPerspectiveFromAspectRatioAndFieldOfView( + GF_API void SetPerspectiveFromAspectRatioAndFieldOfView( float aspectRatio, float fieldOfView, FOVDirection direction, @@ -144,13 +149,13 @@ class GfCamera /// orthographic height (in cm) is equal to \p orthographicSize /// (depending on direction). - void SetOrthographicFromAspectRatioAndSize( + GF_API void SetOrthographicFromAspectRatioAndSize( float aspectRatio, float orthographicSize, FOVDirection direction); /// @} /// Sets the clipping range, cm. - void SetClippingRange(const GfRange1f &val); + GF_API void SetClippingRange(const GfRange1f &val); /// Sets additional arbitrarily oriented clipping planes. /// A vector (a,b,c,d) encodes a clipping plane that clips off points @@ -159,65 +164,65 @@ class GfCamera /// a * x + b * y + c * z + d * 1 < 0 /// /// where (x,y,z) are the coordinates in the camera's space. - void SetClippingPlanes(const std::vector &val); + GF_API void SetClippingPlanes(const std::vector &val); /// Sets the lens aperture, unitless. - void SetFStop(const float val); + GF_API void SetFStop(const float val); /// Sets the focus distance, cm. - void SetFocusDistance(const float val); + GF_API void SetFocusDistance(const float val); /// Returns the transform of the filmback in world space. This is /// exactly the transform specified via SetTransform(). - GfMatrix4d GetTransform() const; + GF_API GfMatrix4d GetTransform() const; /// Returns the projection type. - Projection GetProjection() const; + GF_API Projection GetProjection() const; /// Returns the width of the projector aperture. - float GetHorizontalAperture() const; + GF_API float GetHorizontalAperture() const; /// Returns the height of the projector aperture. - float GetVerticalAperture() const; + GF_API float GetVerticalAperture() const; /// Returns the horizontal offset of the projector aperture, mm. /// In particular, an offset is necessary when writing out a stereo camera /// with finite convergence distance as two cameras. - float GetHorizontalApertureOffset() const; + GF_API float GetHorizontalApertureOffset() const; /// Returns the vertical offset of the projector aperture, mm. - float GetVerticalApertureOffset() const; + GF_API float GetVerticalApertureOffset() const; /// Returns the projector aperture aspect ratio. - float GetAspectRatio() const; + GF_API float GetAspectRatio() const; /// Returns the focal length. - float GetFocalLength() const; + GF_API float GetFocalLength() const; /// Returns the horizontal or vertical field of view in degrees. - float GetFieldOfView(FOVDirection direction) const; + GF_API float GetFieldOfView(FOVDirection direction) const; /// Returns the clipping range. - GfRange1f GetClippingRange() const; + GF_API GfRange1f GetClippingRange() const; /// Returns additional clipping planes. - const std::vector &GetClippingPlanes() const; + GF_API const std::vector &GetClippingPlanes() const; /// Returns the computed, world-space camera frustum. The frustum /// will always be that of a Y-up, -Z-looking camera. - GfFrustum GetFrustum() const; + GF_API GfFrustum GetFrustum() const; /// Returns the lens aperture. - float GetFStop() const; + GF_API float GetFStop() const; /// Returns the focus distance. - float GetFocusDistance() const; + GF_API float GetFocusDistance() const; /// Equality operator. true iff all parts match. - bool operator==(const GfCamera& other) const; + GF_API bool operator==(const GfCamera& other) const; // Inequality operator. true iff not equality. - bool operator!=(const GfCamera& other) const; + GF_API bool operator!=(const GfCamera& other) const; private: // frustum diff --git a/pxr/base/lib/gf/colorRamp.h b/pxr/base/lib/gf/colorRamp.h index adf3f9c249..de2c63bb75 100644 --- a/pxr/base/lib/gf/colorRamp.h +++ b/pxr/base/lib/gf/colorRamp.h @@ -24,30 +24,25 @@ #ifndef GF_COLORRAMP_H #define GF_COLORRAMP_H +/// \file gf/colorRamp.h +/// \ingroup group_gf_Color + #include "pxr/base/gf/math.h" #include "pxr/base/gf/rgb.h" #include "pxr/base/tf/tf.h" +#include "pxr/base/gf/api.h" #include -//! -// \file colorRamp.h -// \ingroup group_gf_Color -// - -//! -// \class GfColorRamp colorRamp.h luxo/iwq/colorRamp.h -// \ingroup group_gf_Color -// -// \brief A color ramp, as commonly used in Pixar shaders. -// -// \see -// \c /usr/anim/bin/cramp \n -// \c /usr/anim/global/src/shaders/include/stdshad/Math00a.h: Math00aSmoothTriad +/// \class GfColorRamp +/// \ingroup group_gf_Color +/// +/// A color ramp, as commonly used in Pixar shaders. +/// class GfColorRamp { public: - // \brief Constructor. - // The default color ramp is a red->green->blue gradient. + /// Constructor. + /// The default color ramp is a red->green->blue gradient. GfColorRamp( const GfRGB& cMin = GfRGB(1,0,0), const GfRGB& cMid = GfRGB(0,1,0), @@ -73,8 +68,8 @@ class GfColorRamp { } - // \brief Constructor. - // The default color ramp is a red->green->blue gradient. + /// Constructor. + /// The default color ramp is a red->green->blue gradient. GfColorRamp( bool useColorRamp, const GfRGB& cMin = GfRGB(1,0,0), @@ -100,8 +95,8 @@ class GfColorRamp { } - //! \brief - // Evaluate the ramp at the given value. x is in [0..1]. + /// Evaluate the ramp at the given value. x is in [0..1]. + GF_API GfRGB Eval(const double x) const; bool operator ==(const GfColorRamp &ramp) const { @@ -154,5 +149,4 @@ class GfColorRamp double _midPos, _widthMin, _widthMidIn, _widthMidOut, _widthMax; }; - #endif diff --git a/pxr/base/lib/gf/declare.h b/pxr/base/lib/gf/declare.h index 278457aaab..0b0b9cdd55 100644 --- a/pxr/base/lib/gf/declare.h +++ b/pxr/base/lib/gf/declare.h @@ -24,15 +24,10 @@ #ifndef GF_DECLARE_H #define GF_DECLARE_H - - -/*! - * \file declare.h - * \brief Declares Gf types. - * - * This file provides typedefs for Gf types. - * - */ +/// \file gf/declare.h +/// Declares Gf types. +/// +/// This file provides typedefs for Gf types. class half; class GfBBox3d; @@ -83,7 +78,4 @@ class GfVec4f; class GfVec4h; class GfVec4i; - - - #endif diff --git a/pxr/base/lib/gf/frustum.cpp b/pxr/base/lib/gf/frustum.cpp index 9a678f3fa0..9db372468a 100644 --- a/pxr/base/lib/gf/frustum.cpp +++ b/pxr/base/lib/gf/frustum.cpp @@ -35,7 +35,7 @@ #include #include - +#include using namespace std; // CODE_COVERAGE_OFF_GCOV_BUG @@ -195,14 +195,14 @@ GfFrustum::GetFOV(bool isFovVertical /* = false */) void GfFrustum::SetOrthographic(double left, double right, double bottom, double top, - double near, double far) + double nearPlane, double farPlane) { _projectionType = GfFrustum::Orthographic; _window.SetMin(GfVec2d(left, bottom)); _window.SetMax(GfVec2d(right, top)); - _nearFar.SetMin(near); - _nearFar.SetMax(far); + _nearFar.SetMin(nearPlane); + _nearFar.SetMax(farPlane); _DirtyFrustumPlanes(); } @@ -210,18 +210,18 @@ GfFrustum::SetOrthographic(double left, double right, bool GfFrustum::GetOrthographic(double *left, double *right, double *bottom, double *top, - double *near, double *far) const + double *nearPlane, double *farPlane) const { if (_projectionType != GfFrustum::Orthographic) return false; - *left = _window.GetMin()[0]; - *right = _window.GetMax()[0]; - *bottom = _window.GetMin()[1]; - *top = _window.GetMax()[1]; + *left = _window.GetMin()[0]; + *right = _window.GetMax()[0]; + *bottom = _window.GetMin()[1]; + *top = _window.GetMax()[1]; - *near = _nearFar.GetMin(); - *far = _nearFar.GetMax(); + *nearPlane = _nearFar.GetMin(); + *farPlane = _nearFar.GetMax(); return true; } diff --git a/pxr/base/lib/gf/frustum.h b/pxr/base/lib/gf/frustum.h index e7550ebcc6..2ccd27d28d 100644 --- a/pxr/base/lib/gf/frustum.h +++ b/pxr/base/lib/gf/frustum.h @@ -24,6 +24,9 @@ #ifndef GF_FRUSTUM_H #define GF_FRUSTUM_H +/// \file gf/frustum.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/bbox3d.h" #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/plane.h" @@ -33,98 +36,84 @@ #include "pxr/base/gf/rotation.h" #include "pxr/base/gf/vec2d.h" #include "pxr/base/gf/vec3d.h" +#include "pxr/base/gf/api.h" #include #include #include -//! -// \file frustum.h -// \ingroup group_gf_BasicGeometry -// - -//! -// \class GfFrustum frustum.h "pxr/base/gf/frustum.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: View frustum. -// -// This class represents a viewing frustum in three dimensional eye -// space. It may represent either a parallel (orthographic) or -// perspective projection. One can think of the frustum as being -// defined by 6 boundary planes. -// -// The frustum is specified using these parameters: -// \li The \em position of the viewpoint. -// \li The \em rotation applied to the default view frame, which is -// looking along the -z axis with the +y axis as the "up" -// direction. -// \li The 2D \em window on the reference plane that defines the left, -// right, top, and bottom planes of the viewing frustum, as -// described below. -// \li The distances to the \em near and \em far planes. -// \li The \em projection \em type -// \li The view distance. -// -// The window and near/far parameters combine to define the view -// frustum as follows. Transform the -z axis and the +y axis by the -// frustum rotation to get the world-space \em view \em direction and -// \em up \em direction. Now consider the \em reference \em plane that -// is perpendicular to the view direction, a distance of referencePlaneDepth -// from the viewpoint, -// and whose y axis corresponds to the up direction. The window -// rectangle is specified in a 2D coordinate system embedded in this -// plane. The origin of the coordinate system is the point at which -// the view direction vector intersects the plane. Therefore, the -// point (0,1) in this plane is found by moving 1 unit along the up -// direction vector in this plane. The vector from the viewpoint to -// the resulting point will form a 45-degree angle with the view -// direction. -// -// The view distance is only useful for interactive applications. -// It can be used to compute a look at point which is useful when -// rotating around an object of interest. -// - +/// \class GfFrustum +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: View frustum. +/// +/// This class represents a viewing frustum in three dimensional eye space. It +/// may represent either a parallel (orthographic) or perspective projection. +/// One can think of the frustum as being defined by 6 boundary planes. +/// +/// The frustum is specified using these parameters: +/// \li The \em position of the viewpoint. +/// \li The \em rotation applied to the default view frame, which is +/// looking along the -z axis with the +y axis as the "up" +/// direction. +/// \li The 2D \em window on the reference plane that defines the left, +/// right, top, and bottom planes of the viewing frustum, as +/// described below. +/// \li The distances to the \em near and \em far planes. +/// \li The \em projection \em type +/// \li The view distance. +/// +/// The window and near/far parameters combine to define the view frustum as +/// follows. Transform the -z axis and the +y axis by the frustum rotation to +/// get the world-space \em view \em direction and \em up \em direction. Now +/// consider the \em reference \em plane that is perpendicular to the view +/// direction, a distance of referencePlaneDepth from the viewpoint, and whose +/// y axis corresponds to the up direction. The window rectangle is specified +/// in a 2D coordinate system embedded in this plane. The origin of the +/// coordinate system is the point at which the view direction vector +/// intersects the plane. Therefore, the point (0,1) in this plane is found by +/// moving 1 unit along the up direction vector in this plane. The vector from +/// the viewpoint to the resulting point will form a 45-degree angle with the +/// view direction. +/// +/// The view distance is only useful for interactive applications. It can be +/// used to compute a look at point which is useful when rotating around an +/// object of interest. +/// class GfFrustum { public: - //! - // This enum is used to determine the type of projection - // represented by a frustum. + /// This enum is used to determine the type of projection represented by a + /// frustum. enum ProjectionType { - Orthographic, //!< Orthographic projection - Perspective, //!< Perspective projection - ORTHOGRAPHIC = Orthographic, //!< Orthographic synonym for 2x - PERSPECTIVE = Perspective, //!< Perspective synonym for 2x - UNDEFINED_PROJECTION_TYPE, //!< Used by 2x + Orthographic, ///< Orthographic projection + Perspective, ///< Perspective projection + ORTHOGRAPHIC = Orthographic, ///< Orthographic synonym for 2x + PERSPECTIVE = Perspective, ///< Perspective synonym for 2x + UNDEFINED_PROJECTION_TYPE, ///< Used by 2x }; - //! - // This constructor creates an instance with default viewing - // parameters: - // \li The position is the origin. - // \li The rotation is the identity rotation. (The view is along - // the -z axis, with the +y axis as "up"). - // \li The window is -1 to +1 in both dimensions. - // \li The near/far interval is (1, 10). - // \li The view distance is 5.0. - // \li The projection type is \c GfFrustum::Perspective. - GfFrustum(); - - //! - // This constructor creates an instance with the given viewing - // parameters. - GfFrustum(const GfVec3d &position, const GfRotation &rotation, + /// This constructor creates an instance with default viewing parameters: + /// \li The position is the origin. + /// \li The rotation is the identity rotation. (The view is along + /// the -z axis, with the +y axis as "up"). + /// \li The window is -1 to +1 in both dimensions. + /// \li The near/far interval is (1, 10). + /// \li The view distance is 5.0. + /// \li The projection type is \c GfFrustum::Perspective. + GF_API GfFrustum(); + + /// This constructor creates an instance with the given viewing + /// parameters. + GF_API GfFrustum(const GfVec3d &position, const GfRotation &rotation, const GfRange2d &window, const GfRange1d &nearFar, GfFrustum::ProjectionType projectionType, double viewDistance = 5.0); - //! - // This constructor creates an instance from a camera matrix - // (always of a y-Up camera, also see - // SetPositionAndRotationFromMatrix) and the given viewing - // parameters. - GfFrustum(const GfMatrix4d &camToWorldXf, + /// This constructor creates an instance from a camera matrix (always of a + /// y-Up camera, also see SetPositionAndRotationFromMatrix) and the given + /// viewing parameters. + GF_API GfFrustum(const GfMatrix4d &camToWorldXf, const GfRange2d &window, const GfRange1d &nearFar, GfFrustum::ProjectionType projectionType, double viewDistance = 5.0); @@ -157,548 +146,486 @@ class GfFrustum { return !(*this == f); } - //! - // Destructor. - ~GfFrustum(); + /// Destructor. + GF_API ~GfFrustum(); - //! - // \name Value setting and access - // The methods in this group set and access the values that are - // used to define a frustum. - //@{ + /// \name Value setting and access + /// The methods in this group set and access the values that are used to + /// define a frustum. + ///@{ - //! - // Sets the position of the frustum in world space. + /// Sets the position of the frustum in world space. void SetPosition(const GfVec3d &position) { _position = position; _DirtyFrustumPlanes(); } - //! - // Returns the position of the frustum in world space. + /// Returns the position of the frustum in world space. const GfVec3d & GetPosition() const { return _position; } - //! - // Sets the orientation of the frustum in world space as a rotation - // to apply to the default frame: looking along the -z axis with - // the +y axis as "up". + /// Sets the orientation of the frustum in world space as a rotation to + /// apply to the default frame: looking along the -z axis with the +y axis + /// as "up". void SetRotation(const GfRotation &rotation) { _rotation = rotation; _DirtyFrustumPlanes(); } - //! - // Returns the orientation of the frustum in world space as a - // rotation to apply to the -z axis. + /// Returns the orientation of the frustum in world space as a rotation to + /// apply to the -z axis. const GfRotation & GetRotation() const { return _rotation; } - //! - // Sets the position and rotation of the frustum from a camera matrix - // (always from a y-Up camera). - // The resulting frustum's transform will always represent a right-handed - // and orthonormal coordinate sytem (scale, shear, and projection are - // removed from the given \p camToWorldXf). - void SetPositionAndRotationFromMatrix(const GfMatrix4d &camToWorldXf); - - //! - // Sets the window rectangle in the reference plane that defines - // the left, right, top, and bottom planes of the frustum. + /// Sets the position and rotation of the frustum from a camera matrix + /// (always from a y-Up camera). The resulting frustum's transform will + /// always represent a right-handed and orthonormal coordinate sytem + /// (scale, shear, and projection are removed from the given \p + /// camToWorldXf). + GF_API void SetPositionAndRotationFromMatrix(const GfMatrix4d &camToWorldXf); + + /// Sets the window rectangle in the reference plane that defines the + /// left, right, top, and bottom planes of the frustum. void SetWindow(const GfRange2d &window) { _window = window; _DirtyFrustumPlanes(); } - //! - // Returns the window rectangle in the reference plane. + /// Returns the window rectangle in the reference plane. const GfRange2d & GetWindow() const { return _window; } - //! - // Returns the depth of the reference plane + /// Returns the depth of the reference plane. static double GetReferencePlaneDepth() { return 1.0; } - //! - // Sets the near/far interval. + /// Sets the near/far interval. void SetNearFar(const GfRange1d &nearFar) { _nearFar = nearFar; _DirtyFrustumPlanes(); } - //! - // Returns the near/far interval. + /// Returns the near/far interval. const GfRange1d & GetNearFar() const { return _nearFar; } - //! - // Sets the view distance. + /// Sets the view distance. void SetViewDistance(double viewDistance) { _viewDistance = viewDistance; } - //! - // Returns the view distance. + /// Returns the view distance. double GetViewDistance() const { return _viewDistance; } - //! - // Sets the projection type. + /// Sets the projection type. void SetProjectionType(GfFrustum::ProjectionType projectionType) { _projectionType = projectionType; _DirtyFrustumPlanes(); } - //! - // Returns the projection type. + /// Returns the projection type. GfFrustum::ProjectionType GetProjectionType() const { return _projectionType; } - //@} - - //! - // \name Convenience methods - // The methods in this group allow the frustum's data to be - // accessed and modified in terms of different representations - // that may be more convenient for certain applications. - //@{ - - //! - // Sets up the frustum in a manner similar to \c gluPerspective(). - // - // It sets the projection type to \c GfFrustum::PERSPECTIVE and - // sets the window specification so that the resulting symmetric - // frustum encloses an angle of \p fieldOfViewHeight degrees in - // the vertical direction, with \p aspectRatio used to figure the - // angle in the horizontal direction. The near and far distances - // are specified as well. The window coordinates are computed as: - // \code - // top = tan(fieldOfViewHeight / 2) - // bottom = -top - // right = top * aspectRatio - // left = -right - // near = nearDistance - // far = farDistance - // \endcode - // - void SetPerspective(double fieldOfViewHeight, + ///@} + + /// \name Convenience methods + /// + /// The methods in this group allow the frustum's data to be accessed and + /// modified in terms of different representations that may be more + /// convenient for certain applications. + /// + ///@{ + + /// Sets up the frustum in a manner similar to \c gluPerspective(). + /// + /// It sets the projection type to \c GfFrustum::PERSPECTIVE and sets the + /// window specification so that the resulting symmetric frustum encloses + /// an angle of \p fieldOfViewHeight degrees in the vertical direction, + /// with \p aspectRatio used to figure the angle in the horizontal + /// direction. The near and far distances are specified as well. The + /// window coordinates are computed as: + /// \code + /// top = tan(fieldOfViewHeight / 2) + /// bottom = -top + /// right = top * aspectRatio + /// left = -right + /// near = nearDistance + /// far = farDistance + /// \endcode + /// + GF_API void SetPerspective(double fieldOfViewHeight, double aspectRatio, double nearDistance, double farDistance); - //! - // Sets up the frustum in a manner similar to gluPerspective(). - // - // It sets the projection type to \c GfFrustum::Perspective and - // sets the window specification so that: - // if \a isFovVertical is true, - // the resulting symmetric frustum encloses an angle of - // \p fieldOfView degrees in the vertical direction, with - // \p aspectRatio used to figure the angle in the horizontal direction. - // if \a isFovVertical is false, - // the resulting symmetric frustum encloses an angle of - // \p fieldOfView degrees in the horizontal direction, with - // \p aspectRatio used to figure the angle in the vertical direction. - // The near and far distances - // are specified as well. The window coordinates are computed as follows: - // - // \li if isFovVertical: - // \li top = tan(fieldOfView / 2) - // \li right = top * aspectRatio - // \li if NOT isFovVertical: - // \li right = tan(fieldOfView / 2) - // \li top = right / aspectRation - // \li bottom = -top - // \li left = -right - // \li near = nearDistance - // \li far = farDistance - // - void SetPerspective(double fieldOfView, + /// Sets up the frustum in a manner similar to gluPerspective(). + /// + /// It sets the projection type to \c GfFrustum::Perspective and + /// sets the window specification so that: + /// + /// If \a isFovVertical is true, the resulting symmetric frustum encloses + /// an angle of \p fieldOfView degrees in the vertical direction, with \p + /// aspectRatio used to figure the angle in the horizontal direction. + /// + /// If \a isFovVertical is false, the resulting symmetric frustum encloses + /// an angle of \p fieldOfView degrees in the horizontal direction, with + /// \p aspectRatio used to figure the angle in the vertical direction. + /// + /// The near and far distances are specified as well. The window + /// coordinates are computed as follows: + /// + /// \li if isFovVertical: + /// \li top = tan(fieldOfView / 2) + /// \li right = top * aspectRatio + /// \li if NOT isFovVertical: + /// \li right = tan(fieldOfView / 2) + /// \li top = right / aspectRation + /// \li bottom = -top + /// \li left = -right + /// \li near = nearDistance + /// \li far = farDistance + /// + GF_API void SetPerspective(double fieldOfView, bool isFovVertical, double aspectRatio, double nearDistance, double farDistance); - //! - // Returns the current frustum in the format used by \c - // SetPerspective(). If the current frustum is not a perspective - // projection, this returns \c false and leaves the parameters - // untouched. - // - bool GetPerspective(double *fieldOfViewHeight, + + /// Returns the current frustum in the format used by \c SetPerspective(). + /// If the current frustum is not a perspective projection, this returns + /// \c false and leaves the parameters untouched. + GF_API bool GetPerspective(double *fieldOfViewHeight, double *aspectRatio, double *nearDistance, double *farDistance) const; - //! - // Returns the current frustum in the format used by \c - // SetPerspective(). If the current frustum is not a perspective - // projection, this returns \c false and leaves the parameters - // untouched. - bool GetPerspective(bool isFovVertical, + /// Returns the current frustum in the format used by \c SetPerspective(). + /// If the current frustum is not a perspective projection, this returns + /// \c false and leaves the parameters untouched. + GF_API bool GetPerspective(bool isFovVertical, double *fieldOfView, double *aspectRatio, double *nearDistance, double *farDistance) const; - //! - // Returns the horizontal or vertical fov of the frustum. The fov - // of the frustum is not necessarily the same value as displayed - // in the viewer. The displayed fov is a function of the focal - // length or FOV avar. The frustum's fov may be different due to - // things like lens breathing. - // - // If the frustum is not of type \c GfFrustum::Perspective, the - // returned FOV will be 0.0. - // - // \note The default value for \c isFovVertical is false so - // calling \c GetFOV without an argument will return the - // horizontal field of view which is compatible with menv2x's old - // GfFrustum::GetFOV routine. - // - double GetFOV(bool isFovVertical = false); - - //! - // Sets up the frustum in a manner similar to \c glOrtho(). - // - // Sets the projection to \c GfFrustum::Orthographic and sets - // the window and near/far specifications based on the given - // values. + /// Returns the horizontal or vertical fov of the frustum. The fov of the + /// frustum is not necessarily the same value as displayed in the viewer. + /// The displayed fov is a function of the focal length or FOV avar. The + /// frustum's fov may be different due to things like lens breathing. + /// + /// If the frustum is not of type \c GfFrustum::Perspective, the returned + /// FOV will be 0.0. + /// + /// \note The default value for \c isFovVertical is false so calling \c + /// GetFOV without an argument will return the horizontal field of view + /// which is compatible with menv2x's old GfFrustum::GetFOV routine. + GF_API double GetFOV(bool isFovVertical = false); + + /// Sets up the frustum in a manner similar to \c glOrtho(). + /// + /// Sets the projection to \c GfFrustum::Orthographic and sets the window + /// and near/far specifications based on the given values. + GF_API void SetOrthographic(double left, double right, double bottom, double top, - double near, double far); - - //! - // Returns the current frustum in the format used by \c - // SetOrthographic(). If the current frustum is not an - // orthographic projection, this returns \c false and leaves the - // parameters untouched. - bool GetOrthographic(double *left, double *right, + double nearPlane, double farPlane); + + /// Returns the current frustum in the format used by \c + /// SetOrthographic(). If the current frustum is not an orthographic + /// projection, this returns \c false and leaves the parameters untouched. + GF_API bool GetOrthographic(double *left, double *right, double *bottom, double *top, - double *near, double *far) const; - - //! - // Modifies the frustum to tightly enclose a sphere with the given center - // and radius, using the current view direction. The planes of the - // frustum are adjusted as necessary. The given amount of slack is - // added to the sphere's radius is used around the sphere to avoid - // boundary problems. - void FitToSphere(const GfVec3d ¢er, + double *nearPlane, double *farPlane) + const; + + /// Modifies the frustum to tightly enclose a sphere with the given center + /// and radius, using the current view direction. The planes of the + /// frustum are adjusted as necessary. The given amount of slack is added + /// to the sphere's radius is used around the sphere to avoid boundary + /// problems. + GF_API void FitToSphere(const GfVec3d ¢er, double radius, double slack = 0.0); - //! - // Transforms the frustum by the given matrix. - // - // The transformation matrix is applied as follows: the position and - // the direction vector are transformed with the given matrix. Then - // the length of the new direction vector is used to rescale the - // near and far plane and the view distance. Finally, the points that - // define the reference plane are transformed by the matrix. This method - // assures that the frustum will not be sheared or perspective-projected. - // - // \note - // Note that this definition means that the transformed frustum - // does not preserve scales very well. Do \em not use this - // function to transform a frustum that is to be used for precise - // operations such as intersection testing. - GfFrustum & Transform(const GfMatrix4d &matrix); - - //! - // Returns the normalized world-space view direction vector, which - // is computed by rotating the -z axis by the frustum's rotation. - GfVec3d ComputeViewDirection() const; - - //! - // Returns the normalized world-space up vector, which - // is computed by rotating the y axis by the frustum's rotation. - GfVec3d ComputeUpVector() const; - - //! - // Computes the view frame defined by this frustum. The frame - // consists of the view direction, up vector and side vector, as shown in - // this diagram. - // - // \code - // up - // ^ ^ - // | / - // | / view - // |/ - // +- - - - > side - // \endcode - // - void ComputeViewFrame(GfVec3d *side, + /// Transforms the frustum by the given matrix. + /// + /// The transformation matrix is applied as follows: the position and the + /// direction vector are transformed with the given matrix. Then the + /// length of the new direction vector is used to rescale the near and far + /// plane and the view distance. Finally, the points that define the + /// reference plane are transformed by the matrix. This method assures + /// that the frustum will not be sheared or perspective-projected. + /// + /// \note Note that this definition means that the transformed frustum + /// does not preserve scales very well. Do \em not use this function to + /// transform a frustum that is to be used for precise operations such as + /// intersection testing. + GF_API GfFrustum& Transform(const GfMatrix4d &matrix); + + /// Returns the normalized world-space view direction vector, which is + /// computed by rotating the -z axis by the frustum's rotation. + GF_API GfVec3d ComputeViewDirection() const; + + /// Returns the normalized world-space up vector, which is computed by + /// rotating the y axis by the frustum's rotation. + GF_API GfVec3d ComputeUpVector() const; + + /// Computes the view frame defined by this frustum. The frame consists of + /// the view direction, up vector and side vector, as shown in this + /// diagram. + /// + /// \code + /// up + /// ^ ^ + /// | / + /// | / view + /// |/ + /// +- - - - > side + /// \endcode + /// + GF_API void ComputeViewFrame(GfVec3d *side, GfVec3d *up, GfVec3d *view) const; - //! - // Computes and returns the world-space look-at point from the eye - // point (position), view direction (rotation), and view distance. - GfVec3d ComputeLookAtPoint() const; - - //! - // Returns a matrix that represents the viewing transformation for - // this frustum. That is, it returns the matrix that converts - // points from world space to eye (frustum) space. - GfMatrix4d ComputeViewMatrix() const; - - //! - // Returns a matrix that represents the inverse viewing - // transformation for this frustum. That is, it returns the - // matrix that converts points from eye (frustum) space to world - // space. - GfMatrix4d ComputeViewInverse() const; - - //! - // Returns a GL-style projection matrix corresponding to the - // frustum's projection. - GfMatrix4d ComputeProjectionMatrix() const; - - //! - // Returns the aspect ratio of the frustum, defined as the width of - // the window divided by the height. If the height is zero or - // negative, this returns 0. - double ComputeAspectRatio() const; - - //! - // Returns the world-space corners of the frustum as a vector of 8 - // points, ordered as: - // \li Left bottom near - // \li Right bottom near - // \li Left top near - // \li Right top near - // \li Left bottom far - // \li Right bottom far - // \li Left top far - // \li Right top far + /// Computes and returns the world-space look-at point from the eye point + /// (position), view direction (rotation), and view distance. + GF_API GfVec3d ComputeLookAtPoint() const; + + /// Returns a matrix that represents the viewing transformation for this + /// frustum. That is, it returns the matrix that converts points from + /// world space to eye (frustum) space. + GF_API GfMatrix4d ComputeViewMatrix() const; + + /// Returns a matrix that represents the inverse viewing transformation + /// for this frustum. That is, it returns the matrix that converts points + /// from eye (frustum) space to world space. + GF_API GfMatrix4d ComputeViewInverse() const; + + /// Returns a GL-style projection matrix corresponding to the frustum's + /// projection. + GF_API GfMatrix4d ComputeProjectionMatrix() const; + + /// Returns the aspect ratio of the frustum, defined as the width of the + /// window divided by the height. If the height is zero or negative, this + /// returns 0. + GF_API double ComputeAspectRatio() const; + + /// Returns the world-space corners of the frustum as a vector of 8 + /// points, ordered as: + /// \li Left bottom near + /// \li Right bottom near + /// \li Left top near + /// \li Right top near + /// \li Left bottom far + /// \li Right bottom far + /// \li Left top far + /// \li Right top far + GF_API std::vector ComputeCorners() const; - //! - // Returns a frustum that is a narrowed-down version of this - // frustum, such that the frustum rectangle on the near plane - // encloses \p point with at most \p halfSize[0] distance on the - // left and right and at most \p halfSize[1] distance on the top - // and bottom. (If \p point is closer than the half size to a side - // of the frustum, that side is left alone. The point and sizes are - // in normalized 2D coordinates; they range from (-1, -1) at the - // lower left corner of the near-plane window rectangle to (1,1) - // at the upper right corner. - // - // \p point is a 2d point expressed as a normalized window position. - // - // This method is useful for computing a volume to use for - // interactive picking. - GfFrustum ComputeNarrowedFrustum(const GfVec2d &point, + /// Returns a frustum that is a narrowed-down version of this frustum, + /// such that the frustum rectangle on the near plane encloses \p point + /// with at most \p halfSize[0] distance on the left and right and at most + /// \p halfSize[1] distance on the top and bottom. (If \p point is closer + /// than the half size to a side of the frustum, that side is left alone. + /// The point and sizes are in normalized 2D coordinates; they range from + /// (-1, -1) at the lower left corner of the near-plane window rectangle + /// to (1,1) at the upper right corner. + /// + /// \p point is a 2d point expressed as a normalized window position. + /// + /// This method is useful for computing a volume to use for interactive + /// picking. + GF_API GfFrustum ComputeNarrowedFrustum(const GfVec2d &point, const GfVec2d &halfSize) const; - //! - // Returns a frustum that is a narrowed-down version of this - // frustum, such that the frustum rectangle on the near plane - // encloses \p point with at most \p halfSize[0] distance on the - // left and right and at most \p halfSize[1] distance on the top - // and bottom. (If \p point is closer than the half size to a side - // of the frustum, that side is left alone. The point and sizes are - // in normalized 2D coordinates; they range from (-1, -1) at the - // lower left corner of the near-plane window rectangle to (1,1) - // at the upper right corner. - // - // \p point is a 3d point expressed in world coordinates - // - // This method is useful for computing a volume to use for - // interactive picking. - GfFrustum ComputeNarrowedFrustum(const GfVec3d &worldPoint, + /// Returns a frustum that is a narrowed-down version of this frustum, + /// such that the frustum rectangle on the near plane encloses \p point + /// with at most \p halfSize[0] distance on the left and right and at most + /// \p halfSize[1] distance on the top and bottom. (If \p point is closer + /// than the half size to a side of the frustum, that side is left alone. + /// The point and sizes are in normalized 2D coordinates; they range from + /// (-1, -1) at the lower left corner of the near-plane window rectangle + /// to (1,1) at the upper right corner. + /// + /// \p point is a 3d point expressed in world coordinates + /// + /// This method is useful for computing a volume to use for interactive + /// picking. + GF_API GfFrustum ComputeNarrowedFrustum(const GfVec3d &worldPoint, const GfVec2d &halfSize) const; - //! - // Builds and returns a \c GfRay that starts at the viewpoint - // and extends through the given \a windowPos - // given in normalized coords (-1 to +1 in both dimensions) window position. - // - // Contrasted with ComputePickRay(), this method returns a ray - // whose origin is the eyepoint, while that method returns a ray - // whose origin is on the near plane. - GfRay ComputeRay(const GfVec2d &windowPos) const; - - //! - // Builds and returns a \c GfRay that connects the viewpoint - // to the given 3d point in worldspace. - // - // Contrasted with ComputePickRay(), this method returns a ray - // whose origin is the eyepoint, while that method returns a ray - // whose origin is on the near plane. - GfRay ComputeRay(const GfVec3d &worldSpacePos) const; - - //! - // Builds and returns a \c GfRay that can be used for picking at - // the given normalized (-1 to +1 in both dimensions) window position. - // - // Contrasted with ComputeRay(), that method returns a ray - // whose origin is the eyepoint, while this method returns a ray - // whose origin is on the near plane. - GfRay ComputePickRay(const GfVec2d &windowPos) const; - - //! - // Builds and returns a \c GfRay that can be used for picking that - // connects the viewpoint to the given 3d point in worldspace. - GfRay ComputePickRay(const GfVec3d &worldSpacePos) const; - - //@} - - //! - // \name Intersection methods - // The methods in this group implement intersection operations - // between this frustum and a given primitive. - //@{ - - //! - // Describes the space in which the geometry is represented. Used only in - // conjuction with GfFrustum::IntersectsInLocalSpace. The matrix is carries - // the space of the geometry into the space of the frustum. - // - // The IntersectsInLocalSpace routines are the most efficient way - // to intersect geometry with an arbitrary frustum. - // - // Note: There currently isn't a local space intersection routine - // for bboxes, but if the need arises there is no difficulty in - // principle to adding it. - // + /// Builds and returns a \c GfRay that starts at the viewpoint and extends + /// through the given \a windowPos given in normalized coords (-1 to +1 in + /// both dimensions) window position. + /// + /// Contrasted with ComputePickRay(), this method returns a ray whose + /// origin is the eyepoint, while that method returns a ray whose origin + /// is on the near plane. + GF_API GfRay ComputeRay(const GfVec2d &windowPos) const; + + /// Builds and returns a \c GfRay that connects the viewpoint to the given + /// 3d point in worldspace. + /// + /// Contrasted with ComputePickRay(), this method returns a ray whose + /// origin is the eyepoint, while that method returns a ray whose origin + /// is on the near plane. + GF_API GfRay ComputeRay(const GfVec3d &worldSpacePos) const; + + /// Builds and returns a \c GfRay that can be used for picking at the + /// given normalized (-1 to +1 in both dimensions) window position. + /// + /// Contrasted with ComputeRay(), that method returns a ray whose origin + /// is the eyepoint, while this method returns a ray whose origin is on + /// the near plane. + GF_API GfRay ComputePickRay(const GfVec2d &windowPos) const; + + /// Builds and returns a \c GfRay that can be used for picking that + /// connects the viewpoint to the given 3d point in worldspace. + GF_API GfRay ComputePickRay(const GfVec3d &worldSpacePos) const; + + ///@} + + /// \name Intersection methods + /// + /// The methods in this group implement intersection operations + /// between this frustum and a given primitive. + /// + ///@{ + + /// Describes the space in which the geometry is represented. Used only in + /// conjuction with GfFrustum::IntersectsInLocalSpace. The matrix is + /// carries the space of the geometry into the space of the frustum. + /// + /// The IntersectsInLocalSpace routines are the most efficient way to + /// intersect geometry with an arbitrary frustum. + /// + /// Note: There currently isn't a local space intersection routine for + /// bboxes, but if the need arises there is no difficulty in principle to + /// adding it. + /// void SetLocalSpaceForIntersection( const GfMatrix4d &localToFrustum) { _localToFrustum = localToFrustum; } - //! Returns the matrix set by \c SetLocalSpaceForIntersection(). + /// Returns the matrix set by \c SetLocalSpaceForIntersection(). GfMatrix4d const& GetLocalSpaceForIntersection() const { return _localToFrustum; } - //! - // Returns true if the given axis-aligned bbox is inside or intersecting - // the frustum. Otherwise, it returns false. Useful when doing picking - // or frustum culling. - bool Intersects(const GfBBox3d &bbox) const; - - //! - // Returns true if the given point is inside or intersecting the frustum. - // Otherwise, it returns false. - bool Intersects(const GfVec3d &point) const; - - //! - // Returns true if the given point is inside or intersecting the - // frustum. Otherwise, it returns false. The point is in its - // local space, as described by a call to - // GfFrustum::SetLocalSpace. - bool IntersectsInLocalSpace(const GfVec3d &point) const; - - //! - // Returns \c true if the line segment formed by the given points - // is inside or intersecting the frustum. Otherwise, it returns - // false. - bool Intersects(const GfVec3d &p0, + /// Returns true if the given axis-aligned bbox is inside or intersecting + /// the frustum. Otherwise, it returns false. Useful when doing picking or + /// frustum culling. + GF_API bool Intersects(const GfBBox3d &bbox) const; + + /// Returns true if the given point is inside or intersecting the frustum. + /// Otherwise, it returns false. + GF_API bool Intersects(const GfVec3d &point) const; + + /// Returns true if the given point is inside or intersecting the frustum. + /// Otherwise, it returns false. The point is in its local space, as + /// described by a call to GfFrustum::SetLocalSpace. + GF_API bool IntersectsInLocalSpace(const GfVec3d &point) const; + + /// Returns \c true if the line segment formed by the given points is + /// inside or intersecting the frustum. Otherwise, it returns false. + GF_API bool Intersects(const GfVec3d &p0, const GfVec3d &p1) const; - //! - // Returns \c true if the line segment formed by the given points - // is inside or intersecting the frustum. Otherwise, it returns - // false. The endpoints of the line are in local space, as described - // by a call to GfFrustum::SetLocalSpace. - bool IntersectsInLocalSpace(const GfVec3d &p0, + /// Returns \c true if the line segment formed by the given points is + /// inside or intersecting the frustum. Otherwise, it returns false. The + /// endpoints of the line are in local space, as described by a call to + /// GfFrustum::SetLocalSpace. + GF_API bool IntersectsInLocalSpace(const GfVec3d &p0, const GfVec3d &p1) const; - - //! - // Returns \c true if the triangle formed by the given points is - // inside or intersecting the frustum. Otherwise, it returns - // false. - bool Intersects(const GfVec3d &p0, + /// Returns \c true if the triangle formed by the given points is inside + /// or intersecting the frustum. Otherwise, it returns false. + GF_API bool Intersects(const GfVec3d &p0, const GfVec3d &p1, const GfVec3d &p2) const; - //! - // Returns \c true if the triangle formed by the given points is - // inside or intersecting the frustum. Otherwise, it returns - // false. The vertices of the triangle are in local space, as described - // by a call to GfFrustum::SetLocalSpace. - bool IntersectsInLocalSpace(const GfVec3d &p0, + /// Returns \c true if the triangle formed by the given points is inside + /// or intersecting the frustum. Otherwise, it returns false. The + /// vertices of the triangle are in local space, as described by a call to + /// GfFrustum::SetLocalSpace. + GF_API bool IntersectsInLocalSpace(const GfVec3d &p0, const GfVec3d &p1, const GfVec3d &p2) const; - //! - // Returns \c true if the bbox volume intersects the view volume - // given by the view-projection matrix, erring on the side of false - // positives for efficiency. - // - // This method is intended for cases where a GfFrustum is not - // available or when the view-projection matrix yields a view volume - // that is not expressable as a GfFrustum. - // - // Because it errs on the side of false positives, it is suitable - // for early-out tests such as draw or intersection culling. - // - static bool IntersectsViewVolume(const GfBBox3d &bbox, + /// Returns \c true if the bbox volume intersects the view volume given by + /// the view-projection matrix, erring on the side of false positives for + /// efficiency. + /// + /// This method is intended for cases where a GfFrustum is not available + /// or when the view-projection matrix yields a view volume that is not + /// expressable as a GfFrustum. + /// + /// Because it errs on the side of false positives, it is suitable for + /// early-out tests such as draw or intersection culling. + /// + GF_API static bool IntersectsViewVolume(const GfBBox3d &bbox, const GfMatrix4d &vpMat); - //@} + ///@} private: // Dirty the result of _CalculateFrustumPlanes. - void _DirtyFrustumPlanes(); + GF_API void _DirtyFrustumPlanes(); // Calculates cached frustum planes used for intersection tests. - void _CalculateFrustumPlanes() const; + GF_API void _CalculateFrustumPlanes() const; - //! Builds and returns a \c GfRay that can be used for picking. - // Given an eye position and direction in camera space, offsets the - // ray to emanate from the near plane, then transforms into worldspace - GfRay _ComputePickRayOffsetToNearPlane( + // Builds and returns a \c GfRay that can be used for picking. Given an + // eye position and direction in camera space, offsets the ray to emanate + // from the near plane, then transforms into worldspace + GF_API GfRay _ComputePickRayOffsetToNearPlane( const GfVec3d &camSpaceFrom, const GfVec3d &camSpaceDir) const; - //! - // Returns a frustum that is a narrowed-down version of this - // frustum, such that the frustum rectangle on the near plane - // encloses \p point with at most \p halfSize[0] distance on the - // left and right and at most \p halfSize[1] distance on the top - // and bottom. (If \p point is closer than the half size to a side - // of the frustum, that side is left alone. The point and sizes are - // in normalized 2D coordinates; they range from (-1, -1) at the - // lower left corner of the near-plane window rectangle to (1,1) - // at the upper right corner. + + // Returns a frustum that is a narrowed-down version of this frustum, such + // that the frustum rectangle on the near plane encloses \p point with at + // most \p halfSize[0] distance on the left and right and at most \p + // halfSize[1] distance on the top and bottom. (If \p point is closer than + // the half size to a side of the frustum, that side is left alone. The + // point and sizes are in normalized 2D coordinates; they range from (-1, + // -1) at the lower left corner of the near-plane window rectangle to + // (1,1) at the upper right corner. // // \p windowPoint is expressed in window coordinates // - // This method is useful for computing a volume to use for - // interactive picking. + // This method is useful for computing a volume to use for interactive + // picking. GfFrustum _ComputeNarrowedFrustumSub(const GfVec2d windowPoint, const GfVec2d &halfSize) const; - bool _SegmentIntersects(GfVec3d const &p0, uint32_t p0Mask, GfVec3d const &p1, uint32_t p1Mask) const; - - //! Position of the frustum in world space. + // Position of the frustum in world space. GfVec3d _position; - //! - // Orientation of the frustum in world space as a rotation to apply - // to the -z axis. + // Orientation of the frustum in world space as a rotation to apply to the + // -z axis. GfRotation _rotation; - //! Window rectangle in the image plane. + // Window rectangle in the image plane. GfRange2d _window; - //! Near/far interval. + // Near/far interval. GfRange1d _nearFar; - //! View distance. + // View distance. double _viewDistance; - //! Projection type. + // Projection type. ProjectionType _projectionType; // For efficient intersection in local space @@ -709,12 +636,13 @@ class GfFrustum { mutable std::vector _planes; }; -/// \brief Output a GfFrustum using the format -/// [(position) (rotation) [window] [nearFar] viewDistance type] -/// \ingroup group_gf_DebuggingOutput +/// Output a GfFrustum using the format [(position) (rotation) [window] +/// [nearFar] viewDistance type] +/// +/// The "type" is "perspective", "orthographic," or "unknown" depending on the +/// projection type of the frustum. /// -/// The "type" is "perspective", "orthographic," or "unknown" -/// depending on the projection type of the frustum. -std::ostream& operator<<(std::ostream& out, const GfFrustum& f); +/// \ingroup group_gf_DebuggingOutput +GF_API std::ostream& operator<<(std::ostream& out, const GfFrustum& f); #endif /* GF_FRUSTUM_H */ diff --git a/pxr/base/lib/gf/gamma.cpp b/pxr/base/lib/gf/gamma.cpp index 88c1bf2b2d..b2aeb794e5 100644 --- a/pxr/base/lib/gf/gamma.cpp +++ b/pxr/base/lib/gf/gamma.cpp @@ -66,12 +66,12 @@ T GfConvertDisplayToLinear(const T& v) { return GfApplyGamma(v,_DisplayGamma); } -template GfVec3f GfConvertLinearToDisplay(const GfVec3f&); -template GfVec3d GfConvertLinearToDisplay(const GfVec3d&); -template GfVec4f GfConvertLinearToDisplay(const GfVec4f&); -template GfVec4d GfConvertLinearToDisplay(const GfVec4d&); -template GfVec3f GfConvertDisplayToLinear(const GfVec3f&); -template GfVec3d GfConvertDisplayToLinear(const GfVec3d&); -template GfVec4f GfConvertDisplayToLinear(const GfVec4f&); -template GfVec4d GfConvertDisplayToLinear(const GfVec4d&); +template GF_API GfVec3f GfConvertLinearToDisplay(const GfVec3f&); +template GF_API GfVec3d GfConvertLinearToDisplay(const GfVec3d&); +template GF_API GfVec4f GfConvertLinearToDisplay(const GfVec4f&); +template GF_API GfVec4d GfConvertLinearToDisplay(const GfVec4d&); +template GF_API GfVec3f GfConvertDisplayToLinear(const GfVec3f&); +template GF_API GfVec3d GfConvertDisplayToLinear(const GfVec3d&); +template GF_API GfVec4f GfConvertDisplayToLinear(const GfVec4f&); +template GF_API GfVec4d GfConvertDisplayToLinear(const GfVec4d&); diff --git a/pxr/base/lib/gf/gamma.h b/pxr/base/lib/gf/gamma.h index 4be444d691..b36edd50fc 100644 --- a/pxr/base/lib/gf/gamma.h +++ b/pxr/base/lib/gf/gamma.h @@ -24,46 +24,50 @@ #ifndef GF_GAMMA_H #define GF_GAMMA_H +/// \file gf/gamma.h +/// Utilities to map colors between gamma spaces. + +#include "pxr/base/gf/api.h" + class GfVec3f; class GfVec3d; class GfVec4f; class GfVec4d; -/*! - * \file gf/gamma.h - * \brief Utilities to map colors between gamma spaces. - */ - -/// Return a new vector with each component of \p v -/// raised to the power \p gamma +/// Return a new vector with each component of \p v raised to the power \p +/// gamma +GF_API GfVec3f GfApplyGamma(const GfVec3f &v, double gamma); -/// Return a new vector with each component of \p v -/// raised to the power \p gamma +/// Return a new vector with each component of \p v raised to the power \p +/// gamma +GF_API GfVec3d GfApplyGamma(const GfVec3d &v, double gamma); -/// Return a new vector with the first three components of \p v -/// raised to the power \p gamma and the fourth component unchanged. +/// Return a new vector with the first three components of \p v raised to the +/// power \p gamma and the fourth component unchanged. +GF_API GfVec4f GfApplyGamma(const GfVec4f &v, double gamma); -/// Return a new vector with the first three components of \p v -/// raised to the power \p gamma and the fourth component unchanged. +/// Return a new vector with the first three components of \p v raised to the +/// power \p gamma and the fourth component unchanged. +GF_API GfVec4d GfApplyGamma(const GfVec4d &v, double gamma); /// Return the system display gamma +GF_API double GfGetDisplayGamma(); -/// Given a vec, \p v, representing an energy-linear RGB(A) color, -/// return a vec of the same type converted to the system's display gamma -/// This is instantiated for GfVec3f, GfVec4d, GfVec3d, and GfVec4d +/// Given a vec, \p v, representing an energy-linear RGB(A) color, return a +/// vec of the same type converted to the system's display gamma This is +/// instantiated for GfVec3f, GfVec4d, GfVec3d, and GfVec4d template T GfConvertLinearToDisplay(const T& v); /// Given a vec, \p v, representing an RGB(A) color in the system's display -/// gamma space, return an energy-linear vec of the same type. -/// This is instantiated for GfVec3f, GfVec4d, GfVec3d, and GfVec4d +/// gamma space, return an energy-linear vec of the same type. This is +/// instantiated for GfVec3f, GfVec4d, GfVec3d, and GfVec4d template -T GfConvertDisplayToLinear(const T& v); - +GF_API T GfConvertDisplayToLinear(const T& v); #endif /* GF_GAMMA_H */ diff --git a/pxr/base/lib/gf/gfGenCode.py b/pxr/base/lib/gf/gfGenCode.py index 90b5051092..7f11cb54d7 100644 --- a/pxr/base/lib/gf/gfGenCode.py +++ b/pxr/base/lib/gf/gfGenCode.py @@ -36,7 +36,7 @@ from argparse import ArgumentParser from jinja2 import Environment, FileSystemLoader -from jinja2.exceptions import TemplateError +from jinja2.exceptions import TemplateError, TemplateSyntaxError # Write filePath if its content differs from \p content. If unchanged, print a # message indicating that. If filePath is not writable, print a diff. @@ -101,14 +101,18 @@ def GetFmt(row, col): return Matrix def GenerateFromTemplates(env, templates, suffix, outputPath, verbose=True): - try: - for tmpl in templates: - template = env.get_template(tmpl % '.template') + for tmpl in templates: + tmplName = tmpl % '.template' + + try: _WriteFile(os.path.join(outputPath, tmpl % suffix), - template.render(), verbose=verbose) - except TemplateError as err: - print '\t', err, - print 'Aborting ...' + env.get_template(tmplName).render(), verbose) + except TemplateSyntaxError as err: + print >>sys.stderr, \ + 'Syntax Error: {0.name}:{0.lineno}: {0.message}'.format(err) + except TemplateError as err: + print >>sys.stderr, \ + 'Template Error: {}: {}'.format(err, tmplName) def VecName(dim, scl): return 'GfVec%s%s' % (dim, scl[0]) @@ -198,15 +202,15 @@ def MatrixName(dim, scl): matrixSpecs = sorted( [dict(SCL=scl, - DIM=dim, + DIM=i, FILESUFFIX=scl[0], - SUFFIX=str(dim) + scl[0], - MAT=MatrixName(dim, scl), - LIST=MakeListFn(dim), - MATRIX=MakeMatrixFn(dim), + SUFFIX=str(i) + scl[0], + MAT=MatrixName(i, scl), + LIST=MakeListFn(i), + MATRIX=MakeMatrixFn(i), MATNAME=MatrixName, SCALARS=scalarTypes) - for scl, dim in itertools.product(scalarTypes, dimensions)], + for scl, i in itertools.product(scalarTypes, dimensions)], key=lambda d: RankScalar(d['SCL'])) return dict(templates=['matrix%s%%s.h' % dim, @@ -243,7 +247,7 @@ def ValidateFiles(srcDir, dstDir): diffs.append(diff) continue - if missing or diffs: + if missing: msg = [] if missing: msg.append('*** Missing Generated Files: ' + ', '.join(missing)) @@ -289,3 +293,4 @@ def ValidateFiles(srcDir, dstDir): if args.validate: import shutil shutil.rmtree(args.dstDir) + diff --git a/pxr/base/lib/gf/half.h b/pxr/base/lib/gf/half.h index 17c4d53fec..12a5b67943 100644 --- a/pxr/base/lib/gf/half.h +++ b/pxr/base/lib/gf/half.h @@ -24,17 +24,15 @@ #ifndef GF_HALF_H #define GF_HALF_H -/*! - * \file half.h - * - * This header serves to simply bring in the half float datatype, plus provides - * other supporting utilities. For documentation, of the half type, please see - * the half header. At the time of this writing the latest version was - * available at the following link, but note that this may not be the version - * you are building against. - * - * https://github.com/openexr/openexr/blob/master/IlmBase/Half/half.h - */ +/// \file gf/half.h +/// +/// This header serves to simply bring in the half float datatype, plus +/// provides other supporting utilities. For documentation, of the half type, +/// please see the half header. At the time of this writing the latest +/// version was available at the following link, but note that this may not be +/// the version you are building against. +/// +/// https://github.com/openexr/openexr/blob/master/IlmBase/Half/half.h #include diff --git a/pxr/base/lib/gf/homogeneous.h b/pxr/base/lib/gf/homogeneous.h index 4f9ff03055..b9429bc0fc 100644 --- a/pxr/base/lib/gf/homogeneous.h +++ b/pxr/base/lib/gf/homogeneous.h @@ -24,50 +24,48 @@ #ifndef GF_HOMOGENEOUS_H #define GF_HOMOGENEOUS_H +/// \file gf/homogeneous.h +/// \ingroup group_gf_LinearAlgebra +/// Utility functions for GfVec4f and GfVec4d as homogeneous vectors + #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/vec4d.h" #include "pxr/base/gf/vec4f.h" +#include "pxr/base/gf/api.h" -/*! - * \file homogeneous.h - * \ingroup group_gf_LinearAlgebra - * \brief Utility functions for GfVec4f and GfVec4d as homogeneous vectors - */ - -//! -// Returns a vector which is \p v homogenized. If the fourth element of -// \p v is 0, it is set to 1. -// \ingroup group_gf_LinearAlgebra +/// Returns a vector which is \p v homogenized. If the fourth element of \p v +/// is 0, it is set to 1. +/// \ingroup group_gf_LinearAlgebra +GF_API GfVec4f GfGetHomogenized(const GfVec4f &v); -//! -// Homogenizes \p a and \p b and then performs the cross product on the -// first three elements of each. Returns the cross product as a -// homogenized vector. -// \ingroup group_gf_LinearAlgebra +/// Homogenizes \p a and \p b and then performs the cross product on the first +/// three elements of each. Returns the cross product as a homogenized +/// vector. +/// \ingroup group_gf_LinearAlgebra +GF_API GfVec4f GfHomogeneousCross(const GfVec4f &a, const GfVec4f &b); +GF_API GfVec4d GfGetHomogenized(const GfVec4d &v); -//! -// Homogenizes \p a and \p b and then performs the cross product on the -// first three elements of each. Returns the cross product as a -// homogenized vector. -// \ingroup group_gf_LinearAlgebra +/// Homogenizes \p a and \p b and then performs the cross product on the first +/// three elements of each. Returns the cross product as a homogenized +/// vector. +/// \ingroup group_gf_LinearAlgebra +GF_API GfVec4d GfHomogeneousCross(const GfVec4d &a, const GfVec4d &b); -//! -// Projects homogeneous \p v into Euclidean space and returns the result -// as a Vec3f. +/// Projects homogeneous \p v into Euclidean space and returns the result as a +/// Vec3f. inline GfVec3f GfProject(const GfVec4f &v) { float inv = (v[3] != 0.0f) ? 1.0f/v[3] : 1.0f; return GfVec3f(inv * v[0], inv * v[1], inv * v[2]); } -//! -// Projects homogeneous \p v into Euclidean space and returns the result -// as a Vec3d. +/// Projects homogeneous \p v into Euclidean space and returns the result as a +/// Vec3d. inline GfVec3d GfProject(const GfVec4d &v) { double inv = (v[3] != 0.0) ? 1.0/v[3] : 1.0; return GfVec3d(inv * v[0], inv * v[1], inv * v[2]); diff --git a/pxr/base/lib/gf/interval.h b/pxr/base/lib/gf/interval.h index 4e26872cdb..39cb8dbd13 100644 --- a/pxr/base/lib/gf/interval.h +++ b/pxr/base/lib/gf/interval.h @@ -24,29 +24,27 @@ #ifndef GF_INTERVAL_H #define GF_INTERVAL_H +/// \file gf/interval.h +/// \ingroup group_gf_BasicMath + #include "pxr/base/gf/math.h" +#include "pxr/base/gf/api.h" #include #include #include #include - -/*! - * \file interval.h - * \ingroup group_gf_BasicMath - */ - -/*! - * \class GfInterval - * \ingroup group_gf_BasicMath - * A basic mathematical interval class. - * - * Can represent intervals with either open or closed boundary - * conditions. - * - * \note Lack of TfPickling was deliberate, please don't add. - */ +#include + +/// \class GfInterval +/// \ingroup group_gf_BasicMath +/// +/// A basic mathematical interval class. +/// +/// Can represent intervals with either open or closed boundary +/// conditions. +/// class GfInterval { public: @@ -414,12 +412,12 @@ class GfInterval b : a; } - //! Data + /// Data _Bound _min, _max; }; /// Output a GfInterval using the format (x, y). /// \ingroup group_gf_DebuggingOutput -std::ostream &operator<<(std::ostream&, const GfInterval&); +GF_API std::ostream &operator<<(std::ostream&, const GfInterval&); #endif /* GF_INTERVAL_H */ diff --git a/pxr/base/lib/gf/limits.h b/pxr/base/lib/gf/limits.h index 60fb57d690..cb6e73a6ad 100644 --- a/pxr/base/lib/gf/limits.h +++ b/pxr/base/lib/gf/limits.h @@ -24,22 +24,18 @@ #ifndef GF_LIMITS_H #define GF_LIMITS_H -/*! - * \file limits.h - * \ingroup group_gf_BasicMath - * \brief Defines useful mathematical limits. - */ +/// \file gf/limits.h +/// \ingroup group_gf_BasicMath +/// Defines useful mathematical limits. -//! -// This constant is used to determine whether the length of a vector -// is too small to handle accurately. -// \ingroup group_gf_BasicMath +/// This constant is used to determine whether the length of a vector is too +/// small to handle accurately. +/// \ingroup group_gf_BasicMath #define GF_MIN_VECTOR_LENGTH 1e-10 -//! -// This constant is used to determine when a set of basis vectors is close -// to orthogonal. -// \ingroup group_gf_LinearAlgebra +/// This constant is used to determine when a set of basis vectors is close to +/// orthogonal. +/// \ingroup group_gf_LinearAlgebra #define GF_MIN_ORTHO_TOLERANCE 1e-6 #endif diff --git a/pxr/base/lib/gf/line.h b/pxr/base/lib/gf/line.h index 766dc4c30f..ee798e596b 100644 --- a/pxr/base/lib/gf/line.h +++ b/pxr/base/lib/gf/line.h @@ -24,38 +24,35 @@ #ifndef GF_LINE_H #define GF_LINE_H +/// \file gf/line.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/vec3d.h" +#include "pxr/base/gf/api.h" + #include #include -/*! - * \file line.h - * \ingroup group_gf_BasicGeometry - */ - -//! -// \class GfLine line.h "pxr/base/gf/line.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 3D line -// -// This class represents a three-dimensional line in space. Lines are -// constructed from a point, \p p0, and a direction, dir. The direction is -// normalized in the constructor. -// -// The line is kept in a parametric represention, p = p0 + t * dir. -// - +/// \class GfLine +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 3D line +/// +/// This class represents a three-dimensional line in space. Lines are +/// constructed from a point, \p p0, and a direction, dir. The direction is +/// normalized in the constructor. +/// +/// The line is kept in a parametric represention, p = p0 + t * dir. +/// class GfLine { public: - //! - // The default constructor leaves line parameters undefined. + /// The default constructor leaves line parameters undefined. GfLine() { } - //! - // Construct a line from a point and a direction. + /// Construct a line from a point and a direction. GfLine(const GfVec3d &p0, const GfVec3d &dir ) { Set( p0, dir ); } @@ -66,37 +63,33 @@ class GfLine { return _dir.Normalize(); } - //! - // Return the point on the line at \p ( p0 + t * dir ). - // Remember dir has been normalized so t represents a unit distance. + /// Return the point on the line at \p ( p0 + t * dir ). + /// Remember dir has been normalized so t represents a unit distance. GfVec3d GetPoint( double t ) const { return _p0 + _dir * t; } - //! - // Return the normalized direction of the line. + /// Return the normalized direction of the line. const GfVec3d &GetDirection() const { return _dir; } - //! - // Returns the point on the line that is closest to \p point. If - // \p t is not \c NULL, it will be set to the parametric - // distance along the line of the returned point. + /// Returns the point on the line that is closest to \p point. If \p t is + /// not \c NULL, it will be set to the parametric distance along the line + /// of the returned point. + GF_API GfVec3d FindClosestPoint(const GfVec3d &point, double *t = NULL) const; - //! - // Component-wise equality test. The starting points and directions, - // must match exactly for lines to be considered equal. + /// Component-wise equality test. The starting points and directions, + /// must match exactly for lines to be considered equal. bool operator ==(const GfLine &l) const { return _p0 == l._p0 && _dir == l._dir; } - //! - // Component-wise inequality test. The starting points, - // and directions must match exactly for lines to be - // considered equal. + /// Component-wise inequality test. The starting points, and directions + /// must match exactly for lines to be considered equal. bool operator !=(const GfLine &r) const { return ! (*this == r); } private: + GF_API friend bool GfFindClosestPoints( const GfLine &, const GfLine &, GfVec3d *, GfVec3d *, double *, double * ); @@ -106,20 +99,21 @@ class GfLine { GfVec3d _dir; }; -//! -// Computes the closets points between two lines. The two points -// are returned in \p p1 and \p p2. The parametric -// distance of each point on the lines is returned in \p t1 and \p t2. -// -// This returns \c false if the lines were close enough to -// parallel that no points could be computed; in this case, the -// other return values are undefined. +/// Computes the closets points between two lines. +/// +/// The two points are returned in \p p1 and \p p2. The parametric distance +/// of each point on the lines is returned in \p t1 and \p t2. +/// +/// This returns \c false if the lines were close enough to parallel that no +/// points could be computed; in this case, the other return values are +/// undefined. +GF_API bool GfFindClosestPoints(const GfLine &l1, const GfLine &l2, GfVec3d *p1 = nullptr, GfVec3d *p2 = nullptr, double *t1 = nullptr, double *t2 = nullptr); /// Output a GfLine. /// \ingroup group_gf_DebuggingOutput -std::ostream &operator<<(std::ostream&, const GfLine&); +GF_API std::ostream &operator<<(std::ostream&, const GfLine&); #endif // GF_LINE_H diff --git a/pxr/base/lib/gf/line2d.h b/pxr/base/lib/gf/line2d.h index 267d22fef4..e8aca6ae98 100644 --- a/pxr/base/lib/gf/line2d.h +++ b/pxr/base/lib/gf/line2d.h @@ -24,37 +24,34 @@ #ifndef GF_LINE2D_H #define GF_LINE2D_H -#include "pxr/base/gf/vec2d.h" -#include +/// \file gf/line2d.h +/// \ingroup group_gf_BasicGeometry -/*! - * \file line2d.h - * \ingroup group_gf_BasicGeometry - */ +#include "pxr/base/gf/vec2d.h" +#include "pxr/base/gf/api.h" -//! -// \class GfLine2d line2d.h "pxr/base/gf/line2d.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 2D line -// -// This class represents a two-dimensional line in space. Lines are -// constructed from a point, \p p0, and a direction, dir. The direction is -// normalized in the constructor. -// -// The line is kept in a parametric represention, p = p0 + t * dir. -// +#include +/// \class GfLine2d +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 2D line +/// +/// This class represents a two-dimensional line in space. Lines are +/// constructed from a point, \p p0, and a direction, dir. The direction is +/// normalized in the constructor. +/// +/// The line is kept in a parametric represention, p = p0 + t * dir. +/// class GfLine2d { public: - //! - // The default constructor leaves line parameters undefined. + /// The default constructor leaves line parameters undefined. GfLine2d() { } - //! - // Construct a line from a point and a direction. + /// Construct a line from a point and a direction. GfLine2d(const GfVec2d &p0, const GfVec2d &dir ) { Set( p0, dir ); } @@ -65,37 +62,33 @@ class GfLine2d { return _dir.Normalize(); } - //! - // Return the point on the line at \p ( p0 + t * dir ). - // Remember dir has been normalized so t represents a unit distance. + /// Return the point on the line at \p ( p0 + t * dir ). + /// Remember dir has been normalized so t represents a unit distance. GfVec2d GetPoint( double t ) const { return _p0 + _dir * t; } - //! - // Return the normalized direction of the line. + /// Return the normalized direction of the line. const GfVec2d &GetDirection() const { return _dir; } - //! - // Returns the point on the line that is closest to \p point. If - // \p t is not \c NULL, it will be set to the parametric - // distance along the line of the returned point. + /// Returns the point on the line that is closest to \p point. If \p t is + /// not \c NULL, it will be set to the parametric distance along the line + /// of the returned point. + GF_API GfVec2d FindClosestPoint(const GfVec2d &point, double *t = NULL) const; - //! - // Component-wise equality test. The starting points and directions, - // must match exactly for lines to be considered equal. + /// Component-wise equality test. The starting points and directions, must + /// match exactly for lines to be considered equal. bool operator ==(const GfLine2d &l) const { return _p0 == l._p0 && _dir == l._dir; } - //! - // Component-wise inequality test. The starting points, - // and directions must match exactly for lines to be - // considered equal. + /// Component-wise inequality test. The starting points, and directions + /// must match exactly for lines to be considered equal. bool operator !=(const GfLine2d &r) const { return ! (*this == r); } private: + GF_API friend bool GfFindClosestPoints( const GfLine2d &, const GfLine2d &, GfVec2d *, GfVec2d *, double *, double *); @@ -106,14 +99,15 @@ class GfLine2d { GfVec2d _dir; }; -//! -// Computes the closets points between two lines. The two points -// are returned in \p p1 and \p p2. The parametric -// distance of each point on the lines is returned in \p t1 and \p t2. -// -// This returns \c false if the lines were close enough to -// parallel that no points could be computed; in this case, the -// other return values are undefined. +/// Computes the closets points between two lines. +/// +/// The two points are returned in \p p1 and \p p2. The parametric distance +/// of each point on the lines is returned in \p t1 and \p t2. +/// +/// This returns \c false if the lines were close enough to parallel that no +/// points could be computed; in this case, the other return values are +/// undefined. +GF_API bool GfFindClosestPoints(const GfLine2d &l1, const GfLine2d &l2, GfVec2d *p1 = nullptr, GfVec2d *p2 = nullptr, double *t1 = nullptr, double *t2 = nullptr); diff --git a/pxr/base/lib/gf/lineSeg.h b/pxr/base/lib/gf/lineSeg.h index 4e59fc9516..f85b0d41d8 100644 --- a/pxr/base/lib/gf/lineSeg.h +++ b/pxr/base/lib/gf/lineSeg.h @@ -24,77 +24,71 @@ #ifndef GF_LINESEG_H #define GF_LINESEG_H +/// \file gf/lineSeg.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/line.h" #include "pxr/base/gf/vec3d.h" +#include "pxr/base/gf/api.h" + #include #include -/*! - * \file lineSeg.h - * \ingroup group_gf_BasicGeometry - */ - -//! -// \class GfLineSeg lineSeg.h "pxr/base/gf/lineSeg.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 3D line segment -// -// This class represents a three-dimensional line segment in space. -// - +/// \class GfLineSeg +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 3D line segment +/// +/// This class represents a three-dimensional line segment in space. +/// class GfLineSeg { public: - //! - // The default constructor leaves line parameters undefined. + /// The default constructor leaves line parameters undefined. GfLineSeg() { } - //! - // Construct a line segment that spans two points. + /// Construct a line segment that spans two points. GfLineSeg(const GfVec3d &p0, const GfVec3d &p1 ) { _length = _line.Set( p0, p1 - p0 ); } - //! - // Return the point on the segment specified by the parameter t. - // p = p0 + t * (p1 - p0) + /// Return the point on the segment specified by the parameter t. + /// p = p0 + t * (p1 - p0) GfVec3d GetPoint( double t ) const {return _line.GetPoint( t * _length );} - //! - // Return the normalized direction of the line. + /// Return the normalized direction of the line. const GfVec3d &GetDirection() const { return _line.GetDirection(); } - //! - // Return the length of the line + /// Return the length of the line double GetLength() const { return _length; } - //! - // Returns the point on the line that is closest to \p point. If - // \p t is not \c NULL, it will be set to the parametric - // distance along the line of the closest point. + /// Returns the point on the line that is closest to \p point. If + /// \p t is not \c NULL, it will be set to the parametric + /// distance along the line of the closest point. + GF_API GfVec3d FindClosestPoint(const GfVec3d &point, double *t = NULL) const; - //! - // Component-wise equality test. The starting points and directions, - // must match exactly for lines to be considered equal. + /// Component-wise equality test. The starting points and directions, + /// must match exactly for lines to be considered equal. bool operator ==(const GfLineSeg &l) const { return (_line == l._line && _length == l._length); } - //! - // Component-wise inequality test. The starting points, - // and directions must match exactly for lines to be - // considered equal. + /// Component-wise inequality test. The starting points, + /// and directions must match exactly for lines to be + /// considered equal. bool operator !=(const GfLineSeg &r) const { return ! (*this == r); } private: + GF_API friend bool GfFindClosestPoints( const GfLine &, const GfLineSeg &, GfVec3d *, GfVec3d *, double *, double * ); + GF_API friend bool GfFindClosestPoints( const GfLineSeg &, const GfLineSeg &, GfVec3d *, GfVec3d *, double *, double * ); @@ -103,34 +97,34 @@ class GfLineSeg { double _length; // distance from p0 to p1 }; -//! -// Computes the closets points on \p line and \p seg. -// The two points are returned in \p p1 and \p p2. -// The parametric distances of \p p1 and \p p2 along the line and segment -// are returned in \p t1 and \p t2. -// -// This returns \c false if the lines were close enough to -// parallel that no points could be computed; in this case, the -// other return values are undefined. +/// Computes the closets points on \p line and \p seg. +/// +/// The two points are returned in \p p1 and \p p2. The parametric distances +/// of \p p1 and \p p2 along the line and segment are returned in \p t1 and \p +/// t2. +/// +/// This returns \c false if the lines were close enough to parallel that no +/// points could be computed; in this case, the other return values are +/// undefined. +GF_API bool GfFindClosestPoints( const GfLine &line, const GfLineSeg &seg, GfVec3d *p1 = nullptr, GfVec3d *p2 = nullptr, double *t1 = nullptr, double *t2 = nullptr ); -//! -// Computes the closets points on two line segments, \p seg1 and \p seg2. -// The two points are returned in \p p1 and \p p2. -// The parametric distances of \p p1 and \p p2 along the segments -// are returned in \p t1 and \p t2. -// -// This returns \c false if the lines were close enough to -// parallel that no points could be computed; in this case, the -// other return values are undefined. +/// Computes the closets points on two line segments, \p seg1 and \p seg2. The +/// two points are returned in \p p1 and \p p2. The parametric distances of \p +/// p1 and \p p2 along the segments are returned in \p t1 and \p t2. +/// +/// This returns \c false if the lines were close enough to parallel that no +/// points could be computed; in this case, the other return values are +/// undefined. +GF_API bool GfFindClosestPoints( const GfLineSeg &seg1, const GfLineSeg &seg2, GfVec3d *p1 = nullptr, GfVec3d *p2 = nullptr, double *t1 = nullptr, double *t2 = nullptr ); /// Output a GfLineSeg. /// \ingroup group_gf_DebuggingOutput -std::ostream &operator<<(std::ostream&, const GfLineSeg&); +GF_API std::ostream &operator<<(std::ostream&, const GfLineSeg&); #endif // GF_LINESEG_H diff --git a/pxr/base/lib/gf/lineSeg2d.h b/pxr/base/lib/gf/lineSeg2d.h index f80738f452..e49c34cdf1 100644 --- a/pxr/base/lib/gf/lineSeg2d.h +++ b/pxr/base/lib/gf/lineSeg2d.h @@ -24,76 +24,69 @@ #ifndef GF_LINESEG2D_H #define GF_LINESEG2D_H +/// \file gf/lineSeg2d.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/line2d.h" #include "pxr/base/gf/vec2d.h" +#include "pxr/base/gf/api.h" #include -/*! - * \file lineSeg2d.h - * \ingroup group_gf_BasicGeometry - */ - -//! -// \class GfLineSeg2d lineSeg2d.h "pxr/base/gf/lineSeg2d.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 2D line segment -// -// This class represents a three-dimensional line segment in space. -// - +/// \class GfLineSeg2d +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 2D line segment +/// +/// This class represents a three-dimensional line segment in space. +/// class GfLineSeg2d { public: - //! - // The default constructor leaves line parameters undefined. + /// The default constructor leaves line parameters undefined. GfLineSeg2d() { } - //! - // Construct a line segment that spans two points. + /// Construct a line segment that spans two points. GfLineSeg2d(const GfVec2d &p0, const GfVec2d &p1 ) { _length = _line.Set( p0, p1 - p0 ); } - //! - // Return the point on the segment specified by the parameter t. - // p = p0 + t * (p1 - p0) + /// Return the point on the segment specified by the parameter t. + /// p = p0 + t * (p1 - p0) GfVec2d GetPoint( double t ) const {return _line.GetPoint( t * _length );} - //! - // Return the normalized direction of the line. + /// Return the normalized direction of the line. const GfVec2d &GetDirection() const { return _line.GetDirection(); } - //! - // Return the length of the line + /// Return the length of the line double GetLength() const { return _length; } - //! - // Returns the point on the line that is closest to \p point. If - // \p t is not \c NULL, it will be set to the parametric - // distance along the line of the closest point. + /// Returns the point on the line that is closest to \p point. If + /// \p t is not \c NULL, it will be set to the parametric + /// distance along the line of the closest point. + GF_API GfVec2d FindClosestPoint(const GfVec2d &point, double *t = NULL) const; - //! - // Component-wise equality test. The starting points and directions, - // must match exactly for lines to be considered equal. - bool operator ==(const GfLineSeg2d &l) const { - return (_line == l._line && _length == l._length); + /// Component-wise equality test. The starting points and directions, + /// must match exactly for lines to be considered equal. + bool operator ==(const GfLineSeg2d &l) const { + return (_line == l._line && _length == l._length); } - //! - // Component-wise inequality test. The starting points, - // and directions must match exactly for lines to be - // considered equal. - bool operator !=(const GfLineSeg2d &r) const { - return ! (*this == r); + /// Component-wise inequality test. The starting points, + /// and directions must match exactly for lines to be + /// considered equal. + bool operator !=(const GfLineSeg2d &r) const { + return ! (*this == r); } private: + GF_API friend bool GfFindClosestPoints( const GfLine2d &, const GfLineSeg2d &, GfVec2d *, GfVec2d *, double *t1, double *t2 ); + GF_API friend bool GfFindClosestPoints( const GfLineSeg2d &, const GfLineSeg2d &, GfVec2d *, GfVec2d *, double *, double * ); @@ -102,28 +95,29 @@ class GfLineSeg2d { double _length; // distance from p0 to p1 }; -//! -// Computes the closets points on \p line and \p seg. -// The two points are returned in \p p1 and \p p2. -// The parametric distances of \p p1 and \p p2 along the line and segment -// are returned in \p t1 and \p t2. -// -// This returns \c false if the lines were close enough to -// parallel that no points could be computed; in this case, the -// other return values are undefined. +/// Computes the closets points on \p line and \p seg. +/// +/// The two points are returned in \p p1 and \p p2. The parametric distances +/// of \p p1 and \p p2 along the line and segment are returned in \p t1 and \p +/// t2. +/// +/// This returns \c false if the lines were close enough to parallel that no +/// points could be computed; in this case, the other return values are +/// undefined. +GF_API bool GfFindClosestPoints( const GfLine2d &line, const GfLineSeg2d &seg, GfVec2d *p1 = nullptr, GfVec2d *p2 = nullptr, double *t1 = nullptr, double *t2 = nullptr ); -//! -// Computes the closets points on two line segments, \p seg1 and \p seg2. -// The two points are returned in \p p1 and \p p2. -// The parametric distances of \p p1 and \p p2 along the segments -// are returned in \p t1 and \p t2. -// -// This returns \c false if the lines were close enough to -// parallel that no points could be computed; in this case, the -// other return values are undefined. +/// Computes the closets points on two line segments, \p seg1 and \p seg2. +/// +/// The two points are returned in \p p1 and \p p2. The parametric distances +/// of \p p1 and \p p2 along the segments are returned in \p t1 and \p t2. +/// +/// This returns \c false if the lines were close enough to parallel that no +/// points could be computed; in this case, the other return values are +/// undefined. +GF_API bool GfFindClosestPoints( const GfLineSeg2d &seg1, const GfLineSeg2d &seg2, GfVec2d *p1 = nullptr, GfVec2d *p2 = nullptr, double *t1 = nullptr, double *t2 = nullptr ); diff --git a/pxr/base/lib/gf/math.h b/pxr/base/lib/gf/math.h index 3670a49f88..743bf3aae8 100644 --- a/pxr/base/lib/gf/math.h +++ b/pxr/base/lib/gf/math.h @@ -24,182 +24,172 @@ #ifndef GF_MATH_H #define GF_MATH_H -#include "pxr/base/arch/math.h" +/// \file gf/math.h +/// \ingroup group_gf_BasicMath +/// Assorted mathematical utility functions. -/*! - * \file gf/math.h - * \ingroup group_gf_BasicMath - * \brief Assorted mathematical utility functions. - */ +#include "pxr/base/arch/math.h" +#include "pxr/base/gf/api.h" -//! -// Returns true if \p a and \p b are with \p epsilon of each other. -// \ingroup group_gf_BasicMath +/// Returns true if \p a and \p b are with \p epsilon of each other. +/// \ingroup group_gf_BasicMath inline bool GfIsClose(double a, double b, double epsilon) { return fabs(a-b) < epsilon; } -//! -// Converts an angle in radians to degrees. -// \ingroup group_gf_BasicMath +/// Converts an angle in radians to degrees. +/// \ingroup group_gf_BasicMath inline double GfRadiansToDegrees(double radians) { return radians * (180.0 / M_PI); } -//! -// Converts an angle in degrees to radians. -// \ingroup group_gf_BasicMath +/// Converts an angle in degrees to radians. +/// \ingroup group_gf_BasicMath inline double GfDegreesToRadians(double degrees) { return degrees * (M_PI / 180.0); } -//! -// Returns the inner product of \c x with itself: specifically, \c x*x. -// Defined for \c int, \c float, \c double, and all \c GfVec types. -// \ingroup group_gf_BasicMath +/// Returns the inner product of \c x with itself: specifically, \c x*x. +/// Defined for \c int, \c float, \c double, and all \c GfVec types. +/// \ingroup group_gf_BasicMath template inline double GfSqr(const T& x) { return x * x; } -/* - * \brief Return the signum of \p v (i.e. -1, 0, or 1). - * \ingroup group_gf_BasicMath - * - * The type \c T must implement the < and > operators; the function returns - * zero only if value neither positive, nor negative. - */ +/// Return the signum of \p v (i.e. -1, 0, or 1). +/// +/// The type \c T must implement the < and > operators; the function returns +/// zero only if value neither positive, nor negative. +/// +/// \ingroup group_gf_BasicMath template inline T GfSgn(T v) { return (v < 0) ? -1 : ((v > 0) ? 1 : 0); } -//! Return sqrt(\p f). -// \ingroup group_gf_BasicMath +/// Return sqrt(\p f). +/// \ingroup group_gf_BasicMath inline double GfSqrt(double f) { return std::sqrt(f); } -//! Return sqrt(\p f). -// \ingroup group_gf_BasicMath +/// Return sqrt(\p f). +/// \ingroup group_gf_BasicMath inline float GfSqrt(float f) { return std::sqrt(f); } -//! Return exp(\p f). -// \ingroup group_gf_BasicMath +/// Return exp(\p f). +/// \ingroup group_gf_BasicMath inline double GfExp(double f) { return std::exp(f); } -//! Return exp(\p f). -// \ingroup group_gf_BasicMath +/// Return exp(\p f). +/// \ingroup group_gf_BasicMath inline float GfExp(float f) { return std::exp(f); } -//! Return log(\p f). -// \ingroup group_gf_BasicMath +/// Return log(\p f). +/// \ingroup group_gf_BasicMath inline double GfLog(double f) { return std::log(f); } -//! Return log(\p f). -// \ingroup group_gf_BasicMath +/// Return log(\p f). +/// \ingroup group_gf_BasicMath inline float GfLog(float f) { return std::log(f); } -//! Return floor(\p f). -// \ingroup group_gf_BasicMath +/// Return floor(\p f). +/// \ingroup group_gf_BasicMath inline double GfFloor(double f) { return std::floor(f); } -//! Return floor(\p f). -// \ingroup group_gf_BasicMath +/// Return floor(\p f). +/// \ingroup group_gf_BasicMath inline float GfFloor(float f) { return std::floor(f); } -//! Return ceil(\p f). -// \ingroup group_gf_BasicMath +/// Return ceil(\p f). +/// \ingroup group_gf_BasicMath inline double GfCeil(double f) { return std::ceil(f); } -//! Return ceil(\p f). -// \ingroup group_gf_BasicMath +/// Return ceil(\p f). +/// \ingroup group_gf_BasicMath inline float GfCeil(float f) { return std::ceil(f); } -//! Return abs(\p f). -// \ingroup group_gf_BasicMath +/// Return abs(\p f). +/// \ingroup group_gf_BasicMath inline double GfAbs(double f) { return std::fabs(f); } -//! Return abs(\p f). -// \ingroup group_gf_BasicMath +/// Return abs(\p f). +/// \ingroup group_gf_BasicMath inline float GfAbs(float f) { return std::fabs(f); } -//! Return round(\p f). -// \ingroup group_gf_BasicMath +/// Return round(\p f). +/// \ingroup group_gf_BasicMath inline double GfRound(double f) { return std::rint(f); } -//! Return round(\p f). -// \ingroup group_gf_BasicMath +/// Return round(\p f). +/// \ingroup group_gf_BasicMath inline float GfRound(float f) { return std::rint(f); } -//! Return pow(\p f, \p p). -// \ingroup group_gf_BasicMath +/// Return pow(\p f, \p p). +/// \ingroup group_gf_BasicMath inline double GfPow(double f, double p) { return std::pow(f, p); } -//! Return pow(\p f, \p p). -// \ingroup group_gf_BasicMath +/// Return pow(\p f, \p p). +/// \ingroup group_gf_BasicMath inline float GfPow(float f, float p) { return std::pow(f, p); } -//! Return sin(\p v). -// \ingroup group_gf_BasicMath +/// Return sin(\p v). +/// \ingroup group_gf_BasicMath inline double GfSin(double v) { return std::sin(v); } -//! Return sin(\p v). -// \ingroup group_gf_BasicMath +/// Return sin(\p v). +/// \ingroup group_gf_BasicMath inline float GfSin(float v) { return std::sin(v); } -//! Return cos(\p v). -// \ingroup group_gf_BasicMath +/// Return cos(\p v). +/// \ingroup group_gf_BasicMath inline double GfCos(double v) { return std::cos(v); } -//! Return cos(\p v). -// \ingroup group_gf_BasicMath +/// Return cos(\p v). +/// \ingroup group_gf_BasicMath inline float GfCos(float v) { return std::cos(v); } -//! Return sin(\p v) in \p s and cos(\p v) in \p c. -// \ingroup group_gf_BasicMath +/// Return sin(\p v) in \p s and cos(\p v) in \p c. +/// \ingroup group_gf_BasicMath inline void GfSinCos(double v, double *s, double *c) { ArchSinCos(v, s, c); } -//! Return sin(\p v) in \p s and cos(\p v) in \p c. -// \ingroup group_gf_BasicMath +/// Return sin(\p v) in \p s and cos(\p v) in \p c. +/// \ingroup group_gf_BasicMath inline void GfSinCos(float v, float *s, float *c) { ArchSinCosf(v, s, c); } -/*! - * \brief Return the resulting of clamping \p value to lie between - * \p min and \p max. This function is also defined for GfVecs. - * \ingroup group_gf_BasicMath - */ +/// Return the resulting of clamping \p value to lie between +/// \p min and \p max. This function is also defined for GfVecs. +/// \ingroup group_gf_BasicMath inline double GfClamp(double value, double min, double max) { if (value < min) return min; if (value > max) return max; return value; } -//! \overload -// \ingroup group_gf_BasicMath +/// \overload +/// \ingroup group_gf_BasicMath inline float GfClamp(float value, float min, float max) { if (value < min) return min; if (value > max) return max; return value; } -/*! - * \brief The mod function with "correct" behaviour for negative numbers. - * \ingroup group_gf_BasicMath - * - * If \p a = \c n \p b for some integer \p n, zero is returned. - * Otherwise, for positive \p a, the value returned is \c fmod(a,b), - * and for negative \p a, the value returned is \c fmod(a,b)+b. - */ +/// The mod function with "correct" behaviour for negative numbers. +/// +/// If \p a = \c n \p b for some integer \p n, zero is returned. +/// Otherwise, for positive \p a, the value returned is \c fmod(a,b), +/// and for negative \p a, the value returned is \c fmod(a,b)+b. +/// +/// \ingroup group_gf_BasicMath +GF_API double GfMod(double a, double b); -//! \overload +/// \overload // \ingroup group_gf_BasicMath +GF_API float GfMod(float a, float b); -/*! - * \brief Linear interpolation function. - * \ingroup group_gf_BasicMath - * - * For any type that supports multiplication by a scalar and binary addition, returns - * \code - * (1-alpha) * a + alpha * b - * \endcode - * - */ +/// Linear interpolation function. +/// +/// For any type that supports multiplication by a scalar and binary addition, returns +/// \code +/// (1-alpha) * a + alpha * b +/// \endcode +/// +/// \ingroup group_gf_BasicMath template inline T GfLerp( double alpha, const T& a, const T& b) { return (1-alpha)* a + alpha * b; } -//! -// Returns the smallest of the given \c values. -// \ingroup group_gf_BasicMath +/// Returns the smallest of the given \c values. +/// \ingroup group_gf_BasicMath template inline T GfMin(T a1, T a2) { return (a1 < a2 ? a1 : a2); @@ -217,9 +207,8 @@ inline T GfMin(T a1, T a2, T a3, T a4, T a5) { return GfMin(GfMin(a1, a2, a3, a4), a5); } -//! -// Returns the largest of the given \c values. -// \ingroup group_gf_BasicMath +/// Returns the largest of the given \c values. +/// \ingroup group_gf_BasicMath template inline T GfMax(T a1, T a2) { return (a1 < a2 ? a2 : a1); diff --git a/pxr/base/lib/gf/matrix.template.h b/pxr/base/lib/gf/matrix.template.h index 75ccd90ddf..bb29c09ef7 100644 --- a/pxr/base/lib/gf/matrix.template.h +++ b/pxr/base/lib/gf/matrix.template.h @@ -26,6 +26,9 @@ #ifndef GF_{{ UPPER(MAT)[2:] }}_H #define GF_{{ UPPER(MAT)[2:] }}_H +/// \file gf/matrix{{ SUFFIX }}.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/matrixData.h" #include "pxr/base/gf/vec{{ SUFFIX }}.h" #include "pxr/base/gf/traits.h" @@ -37,10 +40,6 @@ #include #include -/// \file matrix{{ SUFFIX }}.h -/// \ingroup group_gf_LinearAlgebra -/// - template <> struct GfIsGfMatrix { static const bool value = true; }; @@ -50,11 +49,12 @@ class GfMatrix{{ DIM }}{{ S[0] }}; {% block forwardDeclarations %} {% endblock %} -/// \class {{ MAT }} matrix{{ SUFFIX }}.h "pxr/base/gf/matrix{{ SUFFIX }}.h" +/// \class {{ MAT }} /// \ingroup group_gf_LinearAlgebra -/// \brief Stores a {{ DIM }}x{{ DIM }} matrix of \c {{ SCL }} elements. A basic type. /// -/// Matrices are defined to be in row-major order, so matrix[i][j] +/// Stores a {{ DIM }}x{{ DIM }} matrix of \c {{ SCL }} elements. A basic type. +/// +/// Matrices are defined to be in row-major order, so matrix[i][j] /// indexes the element in the \e i th row and the \e j th column. /// {% block classDocs %}{% endblock %} @@ -66,8 +66,7 @@ class {{ MAT }} static const size_t numRows = {{ DIM }}; static const size_t numColumns = {{ DIM }}; - /// Default constructor. Leaves the matrix component values - /// undefined. + /// Default constructor. Leaves the matrix component values undefined. {{ MAT }}() {} /// Constructor. Initializes the matrix from {{ DIM*DIM }} independent @@ -77,14 +76,14 @@ class {{ MAT }} Set({{ MATRIX("m%(i)s%(j)s", indent=12) }}); } - /// Constructor. Initializes the matrix from a {{ DIM }}x{{ DIM }} array of - /// \c {{ SCL }} values, specified in row-major order. + /// Constructor. Initializes the matrix from a {{ DIM }}x{{ DIM }} array + /// of \c {{ SCL }} values, specified in row-major order. {{ MAT }}(const {{ SCL }} m[{{ DIM }}][{{ DIM }}]) { Set(m); } - /// Constructor. Explicitly initializes the matrix to \e s times - /// the identity matrix. + /// Constructor. Explicitly initializes the matrix to \e s times the + /// identity matrix. explicit {{ MAT }}({{ SCL }} s) { SetDiagonal(s); } @@ -98,11 +97,11 @@ class {{ MAT }} } {% for S in SCALARS %} - /// Constructor. Initialize the matrix from a vector of vectors of {{ S }}. - /// The vector is expected to be {{ DIM }}x{{ DIM }}. If it is too big, only the first - /// {{ DIM }} rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// {{ S }}. The vector is expected to be {{ DIM }}x{{ DIM }}. If it is + /// too big, only the first {{ DIM }} rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// explicit {{ MAT }}(const std::vector< std::vector<{{ S }}> >& v); @@ -110,14 +109,12 @@ class {{ MAT }} {% block customConstructors %} {% endblock %} {% if SCL == 'double' %} - //! - // This explicit constructor converts a "float" matrix to a "double" matrix. + /// This explicit constructor converts a "float" matrix to a "double" matrix. explicit {{ MAT }}(const class GfMatrix{{ DIM }}f& m); {% endif %} {% if SCL == 'float' %} - //! - // This explicit constructor converts a "double" matrix to a "float" matrix. + /// This explicit constructor converts a "double" matrix to a "float" matrix. explicit {{ MAT }}(const class GfMatrix{{ DIM }}d& m); {% endif %} @@ -141,16 +138,16 @@ class {{ MAT }} return GfVec{{ SUFFIX }}({{ LIST("_mtx[%(i)s][i]") }}); } - /// \brief Sets the matrix from {{ DIM*DIM }} independent \c {{ SCL }} values, specified - /// in row-major order. For example, parameter \e m10 specifies the - /// value in row 1 and column 0. + /// Sets the matrix from {{ DIM*DIM }} independent \c {{ SCL }} values, + /// specified in row-major order. For example, parameter \e m10 specifies + /// the value in row 1 and column 0. {{ MAT }}& Set({{ MATRIX("%(SCL)s m%%(i)s%%(j)s" % { 'SCL':SCL }, indent=20) }}) { {{ MATRIX("_mtx[%(i)s][%(j)s] = m%(i)s%(j)s;", sep=" ", indent=8) }} return *this; } - /// \brief Sets the matrix from a {{ DIM }}x{{ DIM }} array of \c {{ SCL }} values, specified - /// in row-major order. + /// Sets the matrix from a {{ DIM }}x{{ DIM }} array of \c {{ SCL }} + /// values, specified in row-major order. {{ MAT }}& Set(const {{ SCL }} m[{{ DIM }}][{{ DIM }}]) { {{ MATRIX("_mtx[%(i)s][%(j)s] = m[%(i)s][%(j)s];", sep="\n ") }} return *this; @@ -185,15 +182,15 @@ class {{ MAT }} const {{ SCL }}* GetArray() const { return _mtx.GetData(); } - - /// Accesses an indexed row \e i of the matrix as an array of {{ DIM }} \c {{ SCL }} - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + + /// Accesses an indexed row \e i of the matrix as an array of {{ DIM }} \c + /// {{ SCL }} values so that standard indexing (such as m[0][1]) + /// works correctly. {{ SCL }}* operator [](int i) { return _mtx[i]; } - /// Accesses an indexed row \e i of the matrix as an array of {{ DIM }} \c {{ SCL }} - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + /// Accesses an indexed row \e i of the matrix as an array of {{ DIM }} \c + /// {{ SCL }} values so that standard indexing (such as m[0][1]) + /// works correctly. const {{ SCL }}* operator [](int i) const { return _mtx[i]; } /// Hash. @@ -204,7 +201,7 @@ class {{ MAT }} while (nElems--) boost::hash_combine(h, *p++); return h; - } + } /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. @@ -230,10 +227,10 @@ class {{ MAT }} {{ MAT }} GetTranspose() const; /// Returns the inverse of the matrix, or FLT_MAX * SetIdentity() if the - /// matrix is singular. (FLT_MAX is the largest value a \c float can have, - /// as defined by the system.) The matrix is considered singular if the - /// determinant is less than or equal to the optional parameter \e eps. - /// If \e det is non-null, *det is set to the determinant. + /// matrix is singular. (FLT_MAX is the largest value a \c float can have, + /// as defined by the system.) The matrix is considered singular if the + /// determinant is less than or equal to the optional parameter \e eps. If + /// \e det is non-null, *det is set to the determinant. {{ MAT }} GetInverse(double* det = NULL, double eps = 0) const; /// Returns the determinant of the matrix. @@ -248,12 +245,11 @@ class {{ MAT }} /// Multiplies the matrix by a {{ SCL }}. {{ MAT }}& operator *=(double); - /// - // Returns the product of a matrix and a {{ SCL }}. + /// Returns the product of a matrix and a {{ SCL }}. friend {{ MAT }} operator *(const {{ MAT }}& m1, double d) { - {{ MAT }} m = m1; - return m *= d; + {{ MAT }} m = m1; + return m *= d; } /// @@ -280,15 +276,15 @@ class {{ MAT }} return tmp; } - /// Subtracts matrix \e m2 from \e m1 + /// Subtracts matrix \e m2 from \e m1. friend {{ MAT }} operator -(const {{ MAT }}& m1, const {{ MAT }}& m2) { {{ MAT }} tmp(m1); tmp -= m2; return tmp; } - - /// Multiplies matrix \e m1 by \e m2 + + /// Multiplies matrix \e m1 by \e m2. friend {{ MAT }} operator *(const {{ MAT }}& m1, const {{ MAT }}& m2) { {{ MAT }} tmp(m1); diff --git a/pxr/base/lib/gf/matrix2.template.h b/pxr/base/lib/gf/matrix2.template.h index f452e57765..fd424a092b 100644 --- a/pxr/base/lib/gf/matrix2.template.h +++ b/pxr/base/lib/gf/matrix2.template.h @@ -32,7 +32,7 @@ /// This explicit constructor initializes the matrix to \p s times /// the identity matrix. explicit {{ MAT }}(int s) { - SetDiagonal(s); + SetDiagonal(s); } {% endblock customDiagonalConstructors %} diff --git a/pxr/base/lib/gf/matrix2d.h b/pxr/base/lib/gf/matrix2d.h index 2eddbc5cdc..64c84d7577 100644 --- a/pxr/base/lib/gf/matrix2d.h +++ b/pxr/base/lib/gf/matrix2d.h @@ -28,30 +28,31 @@ #ifndef GF_MATRIX2D_H #define GF_MATRIX2D_H +/// \file gf/matrix2d.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/matrixData.h" #include "pxr/base/gf/vec2d.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include #include #include -/// \file matrix2d.h -/// \ingroup group_gf_LinearAlgebra -/// - template <> struct GfIsGfMatrix { static const bool value = true; }; class GfMatrix2d; class GfMatrix2f; -/// \class GfMatrix2d matrix2d.h "pxr/base/gf/matrix2d.h" +/// \class GfMatrix2d /// \ingroup group_gf_LinearAlgebra -/// \brief Stores a 2x2 matrix of \c double elements. A basic type. /// -/// Matrices are defined to be in row-major order, so matrix[i][j] +/// Stores a 2x2 matrix of \c double elements. A basic type. +/// +/// Matrices are defined to be in row-major order, so matrix[i][j] /// indexes the element in the \e i th row and the \e j th column. /// class GfMatrix2d @@ -62,8 +63,7 @@ class GfMatrix2d static const size_t numRows = 2; static const size_t numColumns = 2; - /// Default constructor. Leaves the matrix component values - /// undefined. + /// Default constructor. Leaves the matrix component values undefined. GfMatrix2d() {} /// Constructor. Initializes the matrix from 4 independent @@ -75,14 +75,14 @@ class GfMatrix2d m10, m11); } - /// Constructor. Initializes the matrix from a 2x2 array of - /// \c double values, specified in row-major order. + /// Constructor. Initializes the matrix from a 2x2 array + /// of \c double values, specified in row-major order. GfMatrix2d(const double m[2][2]) { Set(m); } - /// Constructor. Explicitly initializes the matrix to \e s times - /// the identity matrix. + /// Constructor. Explicitly initializes the matrix to \e s times the + /// identity matrix. explicit GfMatrix2d(double s) { SetDiagonal(s); } @@ -90,7 +90,7 @@ class GfMatrix2d /// This explicit constructor initializes the matrix to \p s times /// the identity matrix. explicit GfMatrix2d(int s) { - SetDiagonal(s); + SetDiagonal(s); } /// Constructor. Explicitly initializes the matrix to diagonal form, @@ -99,24 +99,26 @@ class GfMatrix2d SetDiagonal(v); } - /// Constructor. Initialize the matrix from a vector of vectors of double. - /// The vector is expected to be 2x2. If it is too big, only the first - /// 2 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// double. The vector is expected to be 2x2. If it is + /// too big, only the first 2 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix2d(const std::vector< std::vector >& v); - /// Constructor. Initialize the matrix from a vector of vectors of float. - /// The vector is expected to be 2x2. If it is too big, only the first - /// 2 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// float. The vector is expected to be 2x2. If it is + /// too big, only the first 2 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix2d(const std::vector< std::vector >& v); - //! - // This explicit constructor converts a "float" matrix to a "double" matrix. + /// This explicit constructor converts a "float" matrix to a "double" matrix. + GF_API explicit GfMatrix2d(const class GfMatrix2f& m); /// Sets a row of the matrix from a Vec2. @@ -141,9 +143,9 @@ class GfMatrix2d return GfVec2d(_mtx[0][i], _mtx[1][i]); } - /// \brief Sets the matrix from 4 independent \c double values, specified - /// in row-major order. For example, parameter \e m10 specifies the - /// value in row 1 and column 0. + /// Sets the matrix from 4 independent \c double values, + /// specified in row-major order. For example, parameter \e m10 specifies + /// the value in row 1 and column 0. GfMatrix2d& Set(double m00, double m01, double m10, double m11) { _mtx[0][0] = m00; _mtx[0][1] = m01; @@ -151,8 +153,8 @@ class GfMatrix2d return *this; } - /// \brief Sets the matrix from a 2x2 array of \c double values, specified - /// in row-major order. + /// Sets the matrix from a 2x2 array of \c double + /// values, specified in row-major order. GfMatrix2d& Set(const double m[2][2]) { _mtx[0][0] = m[0][0]; _mtx[0][1] = m[0][1]; @@ -172,13 +174,16 @@ class GfMatrix2d } /// Sets the matrix to \e s times the identity matrix. + GF_API GfMatrix2d& SetDiagonal(double s); /// Sets the matrix to have diagonal (v[0], v[1]). + GF_API GfMatrix2d& SetDiagonal(const GfVec2d&); /// Fills a 2x2 array of \c double values with the values in /// the matrix, specified in row-major order. + GF_API double* Get(double m[2][2]); /// Returns vector components as an array of \c double values. @@ -190,15 +195,15 @@ class GfMatrix2d const double* GetArray() const { return _mtx.GetData(); } - - /// Accesses an indexed row \e i of the matrix as an array of 2 \c double - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + + /// Accesses an indexed row \e i of the matrix as an array of 2 \c + /// double values so that standard indexing (such as m[0][1]) + /// works correctly. double* operator [](int i) { return _mtx[i]; } - /// Accesses an indexed row \e i of the matrix as an array of 2 \c double - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + /// Accesses an indexed row \e i of the matrix as an array of 2 \c + /// double values so that standard indexing (such as m[0][1]) + /// works correctly. const double* operator [](int i) const { return _mtx[i]; } /// Hash. @@ -209,14 +214,16 @@ class GfMatrix2d while (nElems--) boost::hash_combine(h, *p++); return h; - } + } /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix2d& m) const; /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix2f& m) const; /// Tests for element-wise matrix inequality. All elements must match @@ -232,31 +239,35 @@ class GfMatrix2d } /// Returns the transpose of the matrix. + GF_API GfMatrix2d GetTranspose() const; /// Returns the inverse of the matrix, or FLT_MAX * SetIdentity() if the - /// matrix is singular. (FLT_MAX is the largest value a \c float can have, - /// as defined by the system.) The matrix is considered singular if the - /// determinant is less than or equal to the optional parameter \e eps. - /// If \e det is non-null, *det is set to the determinant. + /// matrix is singular. (FLT_MAX is the largest value a \c float can have, + /// as defined by the system.) The matrix is considered singular if the + /// determinant is less than or equal to the optional parameter \e eps. If + /// \e det is non-null, *det is set to the determinant. + GF_API GfMatrix2d GetInverse(double* det = NULL, double eps = 0) const; /// Returns the determinant of the matrix. + GF_API double GetDeterminant() const; /// Post-multiplies matrix \e m into this matrix. + GF_API GfMatrix2d& operator *=(const GfMatrix2d& m); /// Multiplies the matrix by a double. + GF_API GfMatrix2d& operator *=(double); - /// - // Returns the product of a matrix and a double. + /// Returns the product of a matrix and a double. friend GfMatrix2d operator *(const GfMatrix2d& m1, double d) { - GfMatrix2d m = m1; - return m *= d; + GfMatrix2d m = m1; + return m *= d; } /// @@ -267,12 +278,15 @@ class GfMatrix2d } /// Adds matrix \e m to this matrix. + GF_API GfMatrix2d& operator +=(const GfMatrix2d& m); /// Subtracts matrix \e m from this matrix. + GF_API GfMatrix2d& operator -=(const GfMatrix2d& m); /// Returns the unary negation of matrix \e m. + GF_API friend GfMatrix2d operator -(const GfMatrix2d& m); /// Adds matrix \e m2 to \e m1 @@ -283,15 +297,15 @@ class GfMatrix2d return tmp; } - /// Subtracts matrix \e m2 from \e m1 + /// Subtracts matrix \e m2 from \e m1. friend GfMatrix2d operator -(const GfMatrix2d& m1, const GfMatrix2d& m2) { GfMatrix2d tmp(m1); tmp -= m2; return tmp; } - - /// Multiplies matrix \e m1 by \e m2 + + /// Multiplies matrix \e m1 by \e m2. friend GfMatrix2d operator *(const GfMatrix2d& m1, const GfMatrix2d& m2) { GfMatrix2d tmp(m1); @@ -319,10 +333,12 @@ class GfMatrix2d /// Returns the product of a matrix \e m and a column vector \e vec. /// Note that the return type is a \c GfVec2f. + GF_API friend GfVec2f operator *(const GfMatrix2d& m, const GfVec2f& vec); /// Returns the product of row vector \e vec and a matrix \e m. /// Note that the return type is a \c GfVec2f. + GF_API friend GfVec2f operator *(const GfVec2f &vec, const GfMatrix2d& m); @@ -336,6 +352,6 @@ class GfMatrix2d /// Output a GfMatrix2d /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfMatrix2d const &); +GF_API std::ostream& operator<<(std::ostream &, GfMatrix2d const &); #endif // GF_MATRIX2D_H diff --git a/pxr/base/lib/gf/matrix2f.h b/pxr/base/lib/gf/matrix2f.h index e2fabf0f36..63e97260b1 100644 --- a/pxr/base/lib/gf/matrix2f.h +++ b/pxr/base/lib/gf/matrix2f.h @@ -28,30 +28,31 @@ #ifndef GF_MATRIX2F_H #define GF_MATRIX2F_H +/// \file gf/matrix2f.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/matrixData.h" #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include #include #include -/// \file matrix2f.h -/// \ingroup group_gf_LinearAlgebra -/// - template <> struct GfIsGfMatrix { static const bool value = true; }; class GfMatrix2d; class GfMatrix2f; -/// \class GfMatrix2f matrix2f.h "pxr/base/gf/matrix2f.h" +/// \class GfMatrix2f /// \ingroup group_gf_LinearAlgebra -/// \brief Stores a 2x2 matrix of \c float elements. A basic type. /// -/// Matrices are defined to be in row-major order, so matrix[i][j] +/// Stores a 2x2 matrix of \c float elements. A basic type. +/// +/// Matrices are defined to be in row-major order, so matrix[i][j] /// indexes the element in the \e i th row and the \e j th column. /// class GfMatrix2f @@ -62,8 +63,7 @@ class GfMatrix2f static const size_t numRows = 2; static const size_t numColumns = 2; - /// Default constructor. Leaves the matrix component values - /// undefined. + /// Default constructor. Leaves the matrix component values undefined. GfMatrix2f() {} /// Constructor. Initializes the matrix from 4 independent @@ -75,14 +75,14 @@ class GfMatrix2f m10, m11); } - /// Constructor. Initializes the matrix from a 2x2 array of - /// \c float values, specified in row-major order. + /// Constructor. Initializes the matrix from a 2x2 array + /// of \c float values, specified in row-major order. GfMatrix2f(const float m[2][2]) { Set(m); } - /// Constructor. Explicitly initializes the matrix to \e s times - /// the identity matrix. + /// Constructor. Explicitly initializes the matrix to \e s times the + /// identity matrix. explicit GfMatrix2f(float s) { SetDiagonal(s); } @@ -90,7 +90,7 @@ class GfMatrix2f /// This explicit constructor initializes the matrix to \p s times /// the identity matrix. explicit GfMatrix2f(int s) { - SetDiagonal(s); + SetDiagonal(s); } /// Constructor. Explicitly initializes the matrix to diagonal form, @@ -99,24 +99,26 @@ class GfMatrix2f SetDiagonal(v); } - /// Constructor. Initialize the matrix from a vector of vectors of double. - /// The vector is expected to be 2x2. If it is too big, only the first - /// 2 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// double. The vector is expected to be 2x2. If it is + /// too big, only the first 2 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix2f(const std::vector< std::vector >& v); - /// Constructor. Initialize the matrix from a vector of vectors of float. - /// The vector is expected to be 2x2. If it is too big, only the first - /// 2 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// float. The vector is expected to be 2x2. If it is + /// too big, only the first 2 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix2f(const std::vector< std::vector >& v); - //! - // This explicit constructor converts a "double" matrix to a "float" matrix. + /// This explicit constructor converts a "double" matrix to a "float" matrix. + GF_API explicit GfMatrix2f(const class GfMatrix2d& m); /// Sets a row of the matrix from a Vec2. @@ -141,9 +143,9 @@ class GfMatrix2f return GfVec2f(_mtx[0][i], _mtx[1][i]); } - /// \brief Sets the matrix from 4 independent \c float values, specified - /// in row-major order. For example, parameter \e m10 specifies the - /// value in row 1 and column 0. + /// Sets the matrix from 4 independent \c float values, + /// specified in row-major order. For example, parameter \e m10 specifies + /// the value in row 1 and column 0. GfMatrix2f& Set(float m00, float m01, float m10, float m11) { _mtx[0][0] = m00; _mtx[0][1] = m01; @@ -151,8 +153,8 @@ class GfMatrix2f return *this; } - /// \brief Sets the matrix from a 2x2 array of \c float values, specified - /// in row-major order. + /// Sets the matrix from a 2x2 array of \c float + /// values, specified in row-major order. GfMatrix2f& Set(const float m[2][2]) { _mtx[0][0] = m[0][0]; _mtx[0][1] = m[0][1]; @@ -172,13 +174,16 @@ class GfMatrix2f } /// Sets the matrix to \e s times the identity matrix. + GF_API GfMatrix2f& SetDiagonal(float s); /// Sets the matrix to have diagonal (v[0], v[1]). + GF_API GfMatrix2f& SetDiagonal(const GfVec2f&); /// Fills a 2x2 array of \c float values with the values in /// the matrix, specified in row-major order. + GF_API float* Get(float m[2][2]); /// Returns vector components as an array of \c float values. @@ -190,15 +195,15 @@ class GfMatrix2f const float* GetArray() const { return _mtx.GetData(); } - - /// Accesses an indexed row \e i of the matrix as an array of 2 \c float - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + + /// Accesses an indexed row \e i of the matrix as an array of 2 \c + /// float values so that standard indexing (such as m[0][1]) + /// works correctly. float* operator [](int i) { return _mtx[i]; } - /// Accesses an indexed row \e i of the matrix as an array of 2 \c float - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + /// Accesses an indexed row \e i of the matrix as an array of 2 \c + /// float values so that standard indexing (such as m[0][1]) + /// works correctly. const float* operator [](int i) const { return _mtx[i]; } /// Hash. @@ -209,14 +214,16 @@ class GfMatrix2f while (nElems--) boost::hash_combine(h, *p++); return h; - } + } /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix2d& m) const; /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix2f& m) const; /// Tests for element-wise matrix inequality. All elements must match @@ -232,31 +239,34 @@ class GfMatrix2f } /// Returns the transpose of the matrix. + GF_API GfMatrix2f GetTranspose() const; /// Returns the inverse of the matrix, or FLT_MAX * SetIdentity() if the - /// matrix is singular. (FLT_MAX is the largest value a \c float can have, - /// as defined by the system.) The matrix is considered singular if the - /// determinant is less than or equal to the optional parameter \e eps. - /// If \e det is non-null, *det is set to the determinant. + /// matrix is singular. (FLT_MAX is the largest value a \c float can have, + /// as defined by the system.) The matrix is considered singular if the + /// determinant is less than or equal to the optional parameter \e eps. If + /// \e det is non-null, *det is set to the determinant. + GF_API GfMatrix2f GetInverse(double* det = NULL, double eps = 0) const; /// Returns the determinant of the matrix. + GF_API double GetDeterminant() const; - /// Post-multiplies matrix \e m into this matrix. + GF_API GfMatrix2f& operator *=(const GfMatrix2f& m); /// Multiplies the matrix by a float. + GF_API GfMatrix2f& operator *=(double); - /// - // Returns the product of a matrix and a float. + /// Returns the product of a matrix and a float. friend GfMatrix2f operator *(const GfMatrix2f& m1, double d) { - GfMatrix2f m = m1; - return m *= d; + GfMatrix2f m = m1; + return m *= d; } /// @@ -267,12 +277,15 @@ class GfMatrix2f } /// Adds matrix \e m to this matrix. + GF_API GfMatrix2f& operator +=(const GfMatrix2f& m); /// Subtracts matrix \e m from this matrix. + GF_API GfMatrix2f& operator -=(const GfMatrix2f& m); /// Returns the unary negation of matrix \e m. + GF_API friend GfMatrix2f operator -(const GfMatrix2f& m); /// Adds matrix \e m2 to \e m1 @@ -283,15 +296,15 @@ class GfMatrix2f return tmp; } - /// Subtracts matrix \e m2 from \e m1 + /// Subtracts matrix \e m2 from \e m1. friend GfMatrix2f operator -(const GfMatrix2f& m1, const GfMatrix2f& m2) { GfMatrix2f tmp(m1); tmp -= m2; return tmp; } - - /// Multiplies matrix \e m1 by \e m2 + + /// Multiplies matrix \e m1 by \e m2. friend GfMatrix2f operator *(const GfMatrix2f& m1, const GfMatrix2f& m2) { GfMatrix2f tmp(m1); @@ -328,6 +341,6 @@ class GfMatrix2f /// Output a GfMatrix2f /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfMatrix2f const &); +GF_API std::ostream& operator<<(std::ostream &, GfMatrix2f const &); #endif // GF_MATRIX2F_H diff --git a/pxr/base/lib/gf/matrix3.template.h b/pxr/base/lib/gf/matrix3.template.h index 07a3cb975e..968b5ee9db 100644 --- a/pxr/base/lib/gf/matrix3.template.h +++ b/pxr/base/lib/gf/matrix3.template.h @@ -59,7 +59,7 @@ class GfQuaternion; /// This explicit constructor initializes the matrix to \p s times /// the identity matrix. explicit {{ MAT }}(int s) { - SetDiagonal(s); + SetDiagonal(s); } {% endblock customDiagonalConstructors %} diff --git a/pxr/base/lib/gf/matrix3d.h b/pxr/base/lib/gf/matrix3d.h index 453ac105cc..051f819f6f 100644 --- a/pxr/base/lib/gf/matrix3d.h +++ b/pxr/base/lib/gf/matrix3d.h @@ -28,19 +28,19 @@ #ifndef GF_MATRIX3D_H #define GF_MATRIX3D_H +/// \file gf/matrix3d.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/matrixData.h" #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include #include #include -/// \file matrix3d.h -/// \ingroup group_gf_LinearAlgebra -/// - template <> struct GfIsGfMatrix { static const bool value = true; }; @@ -49,11 +49,12 @@ class GfMatrix3f; class GfRotation; class GfQuaternion; -/// \class GfMatrix3d matrix3d.h "pxr/base/gf/matrix3d.h" +/// \class GfMatrix3d /// \ingroup group_gf_LinearAlgebra -/// \brief Stores a 3x3 matrix of \c double elements. A basic type. /// -/// Matrices are defined to be in row-major order, so matrix[i][j] +/// Stores a 3x3 matrix of \c double elements. A basic type. +/// +/// Matrices are defined to be in row-major order, so matrix[i][j] /// indexes the element in the \e i th row and the \e j th column. /// ///

3D Transformations

@@ -81,8 +82,7 @@ class GfMatrix3d static const size_t numRows = 3; static const size_t numColumns = 3; - /// Default constructor. Leaves the matrix component values - /// undefined. + /// Default constructor. Leaves the matrix component values undefined. GfMatrix3d() {} /// Constructor. Initializes the matrix from 9 independent @@ -96,14 +96,14 @@ class GfMatrix3d m20, m21, m22); } - /// Constructor. Initializes the matrix from a 3x3 array of - /// \c double values, specified in row-major order. + /// Constructor. Initializes the matrix from a 3x3 array + /// of \c double values, specified in row-major order. GfMatrix3d(const double m[3][3]) { Set(m); } - /// Constructor. Explicitly initializes the matrix to \e s times - /// the identity matrix. + /// Constructor. Explicitly initializes the matrix to \e s times the + /// identity matrix. explicit GfMatrix3d(double s) { SetDiagonal(s); } @@ -111,7 +111,7 @@ class GfMatrix3d /// This explicit constructor initializes the matrix to \p s times /// the identity matrix. explicit GfMatrix3d(int s) { - SetDiagonal(s); + SetDiagonal(s); } /// Constructor. Explicitly initializes the matrix to diagonal form, @@ -120,27 +120,30 @@ class GfMatrix3d SetDiagonal(v); } - /// Constructor. Initialize the matrix from a vector of vectors of double. - /// The vector is expected to be 3x3. If it is too big, only the first - /// 3 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// double. The vector is expected to be 3x3. If it is + /// too big, only the first 3 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix3d(const std::vector< std::vector >& v); - /// Constructor. Initialize the matrix from a vector of vectors of float. - /// The vector is expected to be 3x3. If it is too big, only the first - /// 3 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// float. The vector is expected to be 3x3. If it is + /// too big, only the first 3 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix3d(const std::vector< std::vector >& v); /// Constructor. Initialize matrix from rotation. + GF_API GfMatrix3d(const GfRotation& rot); - //! - // This explicit constructor converts a "float" matrix to a "double" matrix. + /// This explicit constructor converts a "float" matrix to a "double" matrix. + GF_API explicit GfMatrix3d(const class GfMatrix3f& m); /// Sets a row of the matrix from a Vec3. @@ -167,9 +170,9 @@ class GfMatrix3d return GfVec3d(_mtx[0][i], _mtx[1][i], _mtx[2][i]); } - /// \brief Sets the matrix from 9 independent \c double values, specified - /// in row-major order. For example, parameter \e m10 specifies the - /// value in row 1 and column 0. + /// Sets the matrix from 9 independent \c double values, + /// specified in row-major order. For example, parameter \e m10 specifies + /// the value in row 1 and column 0. GfMatrix3d& Set(double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22) { @@ -179,8 +182,8 @@ class GfMatrix3d return *this; } - /// \brief Sets the matrix from a 3x3 array of \c double values, specified - /// in row-major order. + /// Sets the matrix from a 3x3 array of \c double + /// values, specified in row-major order. GfMatrix3d& Set(const double m[3][3]) { _mtx[0][0] = m[0][0]; _mtx[0][1] = m[0][1]; @@ -205,13 +208,16 @@ class GfMatrix3d } /// Sets the matrix to \e s times the identity matrix. + GF_API GfMatrix3d& SetDiagonal(double s); /// Sets the matrix to have diagonal (v[0], v[1], v[2]). + GF_API GfMatrix3d& SetDiagonal(const GfVec3d&); /// Fills a 3x3 array of \c double values with the values in /// the matrix, specified in row-major order. + GF_API double* Get(double m[3][3]); /// Returns vector components as an array of \c double values. @@ -223,15 +229,15 @@ class GfMatrix3d const double* GetArray() const { return _mtx.GetData(); } - - /// Accesses an indexed row \e i of the matrix as an array of 3 \c double - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + + /// Accesses an indexed row \e i of the matrix as an array of 3 \c + /// double values so that standard indexing (such as m[0][1]) + /// works correctly. double* operator [](int i) { return _mtx[i]; } - /// Accesses an indexed row \e i of the matrix as an array of 3 \c double - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + /// Accesses an indexed row \e i of the matrix as an array of 3 \c + /// double values so that standard indexing (such as m[0][1]) + /// works correctly. const double* operator [](int i) const { return _mtx[i]; } /// Hash. @@ -242,14 +248,16 @@ class GfMatrix3d while (nElems--) boost::hash_combine(h, *p++); return h; - } + } /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix3d& m) const; /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix3f& m) const; /// Tests for element-wise matrix inequality. All elements must match @@ -265,16 +273,19 @@ class GfMatrix3d } /// Returns the transpose of the matrix. + GF_API GfMatrix3d GetTranspose() const; /// Returns the inverse of the matrix, or FLT_MAX * SetIdentity() if the - /// matrix is singular. (FLT_MAX is the largest value a \c float can have, - /// as defined by the system.) The matrix is considered singular if the - /// determinant is less than or equal to the optional parameter \e eps. - /// If \e det is non-null, *det is set to the determinant. + /// matrix is singular. (FLT_MAX is the largest value a \c float can have, + /// as defined by the system.) The matrix is considered singular if the + /// determinant is less than or equal to the optional parameter \e eps. If + /// \e det is non-null, *det is set to the determinant. + GF_API GfMatrix3d GetInverse(double* det = NULL, double eps = 0) const; /// Returns the determinant of the matrix. + GF_API double GetDeterminant() const; /// Makes the matrix orthonormal in place. This is an iterative method that @@ -285,14 +296,17 @@ class GfMatrix3d /// translation part of the matrix unchanged. If \a issueWarning is true, /// this method will issue a warning if the iteration does not converge, /// otherwise it will be silent. + GF_API bool Orthonormalize(bool issueWarning=true); /// Returns an orthonormalized copy of the matrix. + GF_API GfMatrix3d GetOrthonormalized(bool issueWarning=true) const; /// Returns the sign of the determinant of the matrix, i.e. 1 for a /// right-handed matrix, -1 for a left-handed matrix, and 0 for a /// singular matrix. + GF_API double GetHandedness() const; /// Returns true if the vectors in the matrix form a right-handed @@ -308,17 +322,18 @@ class GfMatrix3d } /// Post-multiplies matrix \e m into this matrix. + GF_API GfMatrix3d& operator *=(const GfMatrix3d& m); /// Multiplies the matrix by a double. + GF_API GfMatrix3d& operator *=(double); - /// - // Returns the product of a matrix and a double. + /// Returns the product of a matrix and a double. friend GfMatrix3d operator *(const GfMatrix3d& m1, double d) { - GfMatrix3d m = m1; - return m *= d; + GfMatrix3d m = m1; + return m *= d; } /// @@ -329,12 +344,15 @@ class GfMatrix3d } /// Adds matrix \e m to this matrix. + GF_API GfMatrix3d& operator +=(const GfMatrix3d& m); /// Subtracts matrix \e m from this matrix. + GF_API GfMatrix3d& operator -=(const GfMatrix3d& m); /// Returns the unary negation of matrix \e m. + GF_API friend GfMatrix3d operator -(const GfMatrix3d& m); /// Adds matrix \e m2 to \e m1 @@ -345,15 +363,15 @@ class GfMatrix3d return tmp; } - /// Subtracts matrix \e m2 from \e m1 + /// Subtracts matrix \e m2 from \e m1. friend GfMatrix3d operator -(const GfMatrix3d& m1, const GfMatrix3d& m2) { GfMatrix3d tmp(m1); tmp -= m2; return tmp; } - - /// Multiplies matrix \e m1 by \e m2 + + /// Multiplies matrix \e m1 by \e m2. friend GfMatrix3d operator *(const GfMatrix3d& m1, const GfMatrix3d& m2) { GfMatrix3d tmp(m1); @@ -383,23 +401,28 @@ class GfMatrix3d /// Returns the product of a matrix \e m and a column vector \e vec. /// Note that the return type is a \c GfVec3f. + GF_API friend GfVec3f operator *(const GfMatrix3d& m, const GfVec3f& vec); /// Returns the product of row vector \e vec and a matrix \e m. /// Note that the return type is a \c GfVec3f. + GF_API friend GfVec3f operator *(const GfVec3f &vec, const GfMatrix3d& m); /// Sets matrix to specify a uniform scaling by \e scaleFactor. + GF_API GfMatrix3d& SetScale(double scaleFactor); /// \name 3D Transformation Utilities /// @{ /// Sets the matrix to specify a rotation equivalent to \e rot. + GF_API GfMatrix3d& SetRotate(const GfRotation &rot); /// Sets the matrix to specify a nonuniform scaling in x, y, and z by /// the factors in vector \e scaleFactors. + GF_API GfMatrix3d& SetScale(const GfVec3d &scaleFactors); /// Returns the rotation corresponding to this matrix. This works @@ -407,6 +430,7 @@ class GfMatrix3d /// /// For good results, consider calling Orthonormalize() before calling /// this method. + GF_API GfRotation ExtractRotation() const; /// Decompose the rotation corresponding to this matrix about 3 @@ -415,6 +439,7 @@ class GfMatrix3d /// /// This is a convenience method that is equivalent to calling /// ExtractRotation().Decompose(). + GF_API GfVec3d DecomposeRotation(const GfVec3d &axis0, const GfVec3d &axis1, const GfVec3d &axis2 ) const; @@ -424,6 +449,7 @@ class GfMatrix3d /// /// For good results, consider calling Orthonormalize() before calling /// this method. + GF_API GfQuaternion ExtractRotationQuaternion() const; /// @} @@ -438,6 +464,6 @@ class GfMatrix3d /// Output a GfMatrix3d /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfMatrix3d const &); +GF_API std::ostream& operator<<(std::ostream &, GfMatrix3d const &); #endif // GF_MATRIX3D_H diff --git a/pxr/base/lib/gf/matrix3f.h b/pxr/base/lib/gf/matrix3f.h index 3caf39b4d2..7f65daeadb 100644 --- a/pxr/base/lib/gf/matrix3f.h +++ b/pxr/base/lib/gf/matrix3f.h @@ -28,30 +28,31 @@ #ifndef GF_MATRIX3F_H #define GF_MATRIX3F_H +/// \file gf/matrix3f.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/matrixData.h" #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include #include #include -/// \file matrix3f.h -/// \ingroup group_gf_LinearAlgebra -/// - template <> struct GfIsGfMatrix { static const bool value = true; }; class GfMatrix3d; class GfMatrix3f; -/// \class GfMatrix3f matrix3f.h "pxr/base/gf/matrix3f.h" +/// \class GfMatrix3f /// \ingroup group_gf_LinearAlgebra -/// \brief Stores a 3x3 matrix of \c float elements. A basic type. /// -/// Matrices are defined to be in row-major order, so matrix[i][j] +/// Stores a 3x3 matrix of \c float elements. A basic type. +/// +/// Matrices are defined to be in row-major order, so matrix[i][j] /// indexes the element in the \e i th row and the \e j th column. /// ///

3D Transformations

@@ -79,8 +80,7 @@ class GfMatrix3f static const size_t numRows = 3; static const size_t numColumns = 3; - /// Default constructor. Leaves the matrix component values - /// undefined. + /// Default constructor. Leaves the matrix component values undefined. GfMatrix3f() {} /// Constructor. Initializes the matrix from 9 independent @@ -94,14 +94,14 @@ class GfMatrix3f m20, m21, m22); } - /// Constructor. Initializes the matrix from a 3x3 array of - /// \c float values, specified in row-major order. + /// Constructor. Initializes the matrix from a 3x3 array + /// of \c float values, specified in row-major order. GfMatrix3f(const float m[3][3]) { Set(m); } - /// Constructor. Explicitly initializes the matrix to \e s times - /// the identity matrix. + /// Constructor. Explicitly initializes the matrix to \e s times the + /// identity matrix. explicit GfMatrix3f(float s) { SetDiagonal(s); } @@ -109,7 +109,7 @@ class GfMatrix3f /// This explicit constructor initializes the matrix to \p s times /// the identity matrix. explicit GfMatrix3f(int s) { - SetDiagonal(s); + SetDiagonal(s); } /// Constructor. Explicitly initializes the matrix to diagonal form, @@ -118,24 +118,26 @@ class GfMatrix3f SetDiagonal(v); } - /// Constructor. Initialize the matrix from a vector of vectors of double. - /// The vector is expected to be 3x3. If it is too big, only the first - /// 3 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// double. The vector is expected to be 3x3. If it is + /// too big, only the first 3 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix3f(const std::vector< std::vector >& v); - /// Constructor. Initialize the matrix from a vector of vectors of float. - /// The vector is expected to be 3x3. If it is too big, only the first - /// 3 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// float. The vector is expected to be 3x3. If it is + /// too big, only the first 3 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix3f(const std::vector< std::vector >& v); - //! - // This explicit constructor converts a "double" matrix to a "float" matrix. + /// This explicit constructor converts a "double" matrix to a "float" matrix. + GF_API explicit GfMatrix3f(const class GfMatrix3d& m); /// Sets a row of the matrix from a Vec3. @@ -162,9 +164,9 @@ class GfMatrix3f return GfVec3f(_mtx[0][i], _mtx[1][i], _mtx[2][i]); } - /// \brief Sets the matrix from 9 independent \c float values, specified - /// in row-major order. For example, parameter \e m10 specifies the - /// value in row 1 and column 0. + /// Sets the matrix from 9 independent \c float values, + /// specified in row-major order. For example, parameter \e m10 specifies + /// the value in row 1 and column 0. GfMatrix3f& Set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) { @@ -174,8 +176,8 @@ class GfMatrix3f return *this; } - /// \brief Sets the matrix from a 3x3 array of \c float values, specified - /// in row-major order. + /// Sets the matrix from a 3x3 array of \c float + /// values, specified in row-major order. GfMatrix3f& Set(const float m[3][3]) { _mtx[0][0] = m[0][0]; _mtx[0][1] = m[0][1]; @@ -200,13 +202,16 @@ class GfMatrix3f } /// Sets the matrix to \e s times the identity matrix. + GF_API GfMatrix3f& SetDiagonal(float s); /// Sets the matrix to have diagonal (v[0], v[1], v[2]). + GF_API GfMatrix3f& SetDiagonal(const GfVec3f&); /// Fills a 3x3 array of \c float values with the values in /// the matrix, specified in row-major order. + GF_API float* Get(float m[3][3]); /// Returns vector components as an array of \c float values. @@ -218,15 +223,15 @@ class GfMatrix3f const float* GetArray() const { return _mtx.GetData(); } - - /// Accesses an indexed row \e i of the matrix as an array of 3 \c float - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + + /// Accesses an indexed row \e i of the matrix as an array of 3 \c + /// float values so that standard indexing (such as m[0][1]) + /// works correctly. float* operator [](int i) { return _mtx[i]; } - /// Accesses an indexed row \e i of the matrix as an array of 3 \c float - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + /// Accesses an indexed row \e i of the matrix as an array of 3 \c + /// float values so that standard indexing (such as m[0][1]) + /// works correctly. const float* operator [](int i) const { return _mtx[i]; } /// Hash. @@ -237,18 +242,21 @@ class GfMatrix3f while (nElems--) boost::hash_combine(h, *p++); return h; - } + } /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix3d& m) const; /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix3f& m) const; /// Tests for element-wise matrix inequality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator !=(const GfMatrix3d& m) const { return !(*this == m); } @@ -260,16 +268,19 @@ class GfMatrix3f } /// Returns the transpose of the matrix. + GF_API GfMatrix3f GetTranspose() const; /// Returns the inverse of the matrix, or FLT_MAX * SetIdentity() if the - /// matrix is singular. (FLT_MAX is the largest value a \c float can have, - /// as defined by the system.) The matrix is considered singular if the - /// determinant is less than or equal to the optional parameter \e eps. - /// If \e det is non-null, *det is set to the determinant. + /// matrix is singular. (FLT_MAX is the largest value a \c float can have, + /// as defined by the system.) The matrix is considered singular if the + /// determinant is less than or equal to the optional parameter \e eps. If + /// \e det is non-null, *det is set to the determinant. + GF_API GfMatrix3f GetInverse(double* det = NULL, double eps = 0) const; /// Returns the determinant of the matrix. + GF_API double GetDeterminant() const; /// Makes the matrix orthonormal in place. This is an iterative method that @@ -280,14 +291,17 @@ class GfMatrix3f /// translation part of the matrix unchanged. If \a issueWarning is true, /// this method will issue a warning if the iteration does not converge, /// otherwise it will be silent. + GF_API bool Orthonormalize(bool issueWarning=true); /// Returns an orthonormalized copy of the matrix. + GF_API GfMatrix3f GetOrthonormalized(bool issueWarning=true) const; /// Returns the sign of the determinant of the matrix, i.e. 1 for a /// right-handed matrix, -1 for a left-handed matrix, and 0 for a /// singular matrix. + GF_API double GetHandedness() const; /// Returns true if the vectors in the matrix form a right-handed @@ -303,17 +317,18 @@ class GfMatrix3f } /// Post-multiplies matrix \e m into this matrix. + GF_API GfMatrix3f& operator *=(const GfMatrix3f& m); /// Multiplies the matrix by a float. + GF_API GfMatrix3f& operator *=(double); - /// - // Returns the product of a matrix and a float. + /// Returns the product of a matrix and a float. friend GfMatrix3f operator *(const GfMatrix3f& m1, double d) { - GfMatrix3f m = m1; - return m *= d; + GfMatrix3f m = m1; + return m *= d; } /// @@ -324,12 +339,15 @@ class GfMatrix3f } /// Adds matrix \e m to this matrix. + GF_API GfMatrix3f& operator +=(const GfMatrix3f& m); /// Subtracts matrix \e m from this matrix. + GF_API GfMatrix3f& operator -=(const GfMatrix3f& m); /// Returns the unary negation of matrix \e m. + GF_API friend GfMatrix3f operator -(const GfMatrix3f& m); /// Adds matrix \e m2 to \e m1 @@ -340,15 +358,15 @@ class GfMatrix3f return tmp; } - /// Subtracts matrix \e m2 from \e m1 + /// Subtracts matrix \e m2 from \e m1. friend GfMatrix3f operator -(const GfMatrix3f& m1, const GfMatrix3f& m2) { GfMatrix3f tmp(m1); tmp -= m2; return tmp; } - - /// Multiplies matrix \e m1 by \e m2 + + /// Multiplies matrix \e m1 by \e m2. friend GfMatrix3f operator *(const GfMatrix3f& m1, const GfMatrix3f& m2) { GfMatrix3f tmp(m1); @@ -377,6 +395,7 @@ class GfMatrix3f } /// Sets matrix to specify a uniform scaling by \e scaleFactor. + GF_API GfMatrix3f& SetScale(float scaleFactor); private: @@ -389,6 +408,6 @@ class GfMatrix3f /// Output a GfMatrix3f /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfMatrix3f const &); +GF_API std::ostream& operator<<(std::ostream &, GfMatrix3f const &); #endif // GF_MATRIX3F_H diff --git a/pxr/base/lib/gf/matrix4.template.h b/pxr/base/lib/gf/matrix4.template.h index f1039356a9..c91ad6e89c 100644 --- a/pxr/base/lib/gf/matrix4.template.h +++ b/pxr/base/lib/gf/matrix4.template.h @@ -78,14 +78,14 @@ class GfMatrix3{{ SCL[0] }}; {% endfor %} {% if SCL == 'double' %} - /// Constructor. Initializes a transformation matrix to perform the indicated - /// rotation and translation. + /// Constructor. Initializes a transformation matrix to perform the + /// indicated rotation and translation. {{ MAT }}(const GfRotation& rotate, const GfVec3{{ SCL[0] }}& translate); {% endif %} - /// Constructor. Initializes a transformation matrix to perform the indicated - /// rotation and translation. + /// Constructor. Initializes a transformation matrix to perform the + /// indicated rotation and translation. {{ MAT }}(const GfMatrix3{{ SCL[0] }}& rotmx, const GfVec3{{ SCL[0] }}& translate); {% endblock customConstructors %} @@ -118,13 +118,13 @@ class GfMatrix3{{ SCL[0] }}; // XXX Should add GfAreOrthogonal(v0, v1, v2) (which also // GfRotation::Decompose() could use). GfVec3{{ SCL[0] }} axis0(GetRow3(0)), axis1(GetRow3(1)), axis2(GetRow3(2)); - return (GfAbs(GfDot(axis0, axis1)) < GF_MIN_ORTHO_TOLERANCE and + return (GfAbs(GfDot(axis0, axis1)) < GF_MIN_ORTHO_TOLERANCE and GfAbs(GfDot(axis0, axis2)) < GF_MIN_ORTHO_TOLERANCE and GfAbs(GfDot(axis1, axis2)) < GF_MIN_ORTHO_TOLERANCE); } - /// Makes the matrix orthonormal in place. This is an iterative method that - /// is much more stable than the previous cross/cross method. If the + /// Makes the matrix orthonormal in place. This is an iterative method + /// that is much more stable than the previous cross/cross method. If the /// iterative method does not converge, a warning is issued. /// /// Returns true if the iteration converged, false otherwise. Leaves any @@ -136,13 +136,13 @@ class GfMatrix3{{ SCL[0] }}; /// Returns an orthonormalized copy of the matrix. {{ MAT }} GetOrthonormalized(bool issueWarning=true) const; - /// Returns the sign of the determinant of the upper 3x3 matrix, i.e. 1 for - /// a right-handed matrix, -1 for a left-handed matrix, and 0 for a + /// Returns the sign of the determinant of the upper 3x3 matrix, i.e. 1 + /// for a right-handed matrix, -1 for a left-handed matrix, and 0 for a /// singular matrix. double GetHandedness() const; - /// Returns true if the vectors in the upper 3x3 matrix form a right-handed - /// coordinate system. + /// Returns true if the vectors in the upper 3x3 matrix form a + /// right-handed coordinate system. bool IsRightHanded() const { return GetHandedness() == 1.0; } @@ -240,22 +240,21 @@ class GfMatrix3{{ SCL[0] }}; GfVec3d* t, {{ MAT }}* p, double eps = GF_MIN_VECTOR_LENGTH) const; - /// Returns the translation part of the matrix, defined as the - /// first three elements of the last row. + /// Returns the translation part of the matrix, defined as the first three + /// elements of the last row. GfVec3d ExtractTranslation() const { return GfVec3d(_mtx[3][0], _mtx[3][1], _mtx[3][2]); } - - /// Returns the rotation corresponding to this matrix. This works - /// well only if the matrix represents a rotation. + + /// Returns the rotation corresponding to this matrix. This works well + /// only if the matrix represents a rotation. /// /// For good results, consider calling Orthonormalize() before calling /// this method. GfRotation ExtractRotation() const; - /// Decompose the rotation corresponding to this matrix about 3 - /// orthogonal axes. If the axes are not orthogonal, warnings - /// will be spewed. + /// Decompose the rotation corresponding to this matrix about 3 orthogonal + /// axes. If the axes are not orthogonal, warnings will be spewed. /// /// This is a convenience method that is equivalent to calling /// ExtractRotation().Decompose(). @@ -263,16 +262,16 @@ class GfMatrix3{{ SCL[0] }}; const GfVec3d &axis1, const GfVec3d &axis2) const; - /// Returns the rotation corresponding to this matrix. This works - /// well only if the matrix represents a rotation. + /// Returns the rotation corresponding to this matrix. This works well + /// only if the matrix represents a rotation. /// /// For good results, consider calling Orthonormalize() before calling /// this method. GfMatrix3d ExtractRotationMatrix() const; - /// Transforms the row vector \e vec by the matrix, returning the - /// result. This treats the vector as a 4-component vector whose - /// fourth component is 1. + /// Transforms the row vector \e vec by the matrix, returning the result. + /// This treats the vector as a 4-component vector whose fourth component + /// is 1. GfVec3d Transform(const GfVec3d &vec) const { return GfProject(GfVec4d( {{ LIST("vec[%(i)s] * _mtx[%(i)s][0]", sep=" + ", num=3) }} + _mtx[3][0], @@ -280,11 +279,11 @@ class GfMatrix3{{ SCL[0] }}; {{ LIST("vec[%(i)s] * _mtx[%(i)s][2]", sep=" + ", num=3) }} + _mtx[3][2], {{ LIST("vec[%(i)s] * _mtx[%(i)s][3]", sep=" + ", num=3) }} + _mtx[3][3])); } - - /// Transforms the row vector \e vec by the matrix, returning the - /// result. This treats the vector as a 4-component vector whose - /// fourth component is 1. This is an overloaded method; it differs - /// from the other version in that it returns a different value type. + + /// Transforms the row vector \e vec by the matrix, returning the result. + /// This treats the vector as a 4-component vector whose fourth component + /// is 1. This is an overloaded method; it differs from the other version + /// in that it returns a different value type. GfVec3f Transform(const GfVec3f &vec) const { return GfVec3f(GfProject(GfVec4d( {{ LIST("vec[%(i)s] * _mtx[%(i)s][0]", sep=" + ", num=3) }} + _mtx[3][0], @@ -293,24 +292,23 @@ class GfMatrix3{{ SCL[0] }}; {{ LIST("vec[%(i)s] * _mtx[%(i)s][3]", sep=" + ", num=3) }} + _mtx[3][3]))); } - /// Transforms row vector \e vec by the matrix, returning the - /// result. This treats the vector as a direction vector, so the - /// translation information in the matrix is ignored. That is, it - /// treats the vector as a 4-component vector whose fourth - /// component is 0. + /// Transforms row vector \e vec by the matrix, returning the result. This + /// treats the vector as a direction vector, so the translation + /// information in the matrix is ignored. That is, it treats the vector as + /// a 4-component vector whose fourth component is 0. GfVec3d TransformDir(const GfVec3d &vec) const { return GfVec3d( {{ LIST("vec[%(i)s] * _mtx[%(i)s][0]", sep=" + ", num=3) }}, {{ LIST("vec[%(i)s] * _mtx[%(i)s][1]", sep=" + ", num=3) }}, {{ LIST("vec[%(i)s] * _mtx[%(i)s][2]", sep=" + ", num=3) }}); } - - /// Transforms row vector \e vec by the matrix, returning the - /// result. This treats the vector as a direction vector, so the - /// translation information in the matrix is ignored. That is, it - /// treats the vector as a 4-component vector whose fourth - /// component is 0. This is an overloaded method; it differs - /// from the other version in that it returns a different value type. + + /// Transforms row vector \e vec by the matrix, returning the result. This + /// treats the vector as a direction vector, so the translation + /// information in the matrix is ignored. That is, it treats the vector as + /// a 4-component vector whose fourth component is 0. This is an + /// overloaded method; it differs from the other version in that it + /// returns a different value type. GfVec3f TransformDir(const GfVec3f &vec) const { return GfVec3f( {{ LIST("vec[%(i)s] * _mtx[%(i)s][0]", sep=" + ", num=3) }}, @@ -318,10 +316,10 @@ class GfMatrix3{{ SCL[0] }}; {{ LIST("vec[%(i)s] * _mtx[%(i)s][2]", sep=" + ", num=3) }}); } - /// Transforms the row vector \e vec by the matrix, returning the - /// result. This treats the vector as a 4-component vector whose - /// fourth component is 1 and ignores the fourth column of the - /// matrix (i.e. assumes it is (0, 0, 0, 1)). + /// Transforms the row vector \e vec by the matrix, returning the result. + /// This treats the vector as a 4-component vector whose fourth component + /// is 1 and ignores the fourth column of the matrix (i.e. assumes it is + /// (0, 0, 0, 1)). GfVec3d TransformAffine(const GfVec3d &vec) const { return GfVec3d( {{ LIST("vec[%(i)s] * _mtx[%(i)s][0]", sep=" + ", num=3) }} + _mtx[3][0], @@ -329,10 +327,10 @@ class GfMatrix3{{ SCL[0] }}; {{ LIST("vec[%(i)s] * _mtx[%(i)s][2]", sep=" + ", num=3) }} + _mtx[3][2]); } - /// Transforms the row vector \e vec by the matrix, returning the - /// result. This treats the vector as a 4-component vector whose - /// fourth component is 1 and ignores the fourth column of the - /// matrix (i.e. assumes it is (0, 0, 0, 1)). + /// Transforms the row vector \e vec by the matrix, returning the result. + /// This treats the vector as a 4-component vector whose fourth component + /// is 1 and ignores the fourth column of the matrix (i.e. assumes it is + /// (0, 0, 0, 1)). GfVec3f TransformAffine(const GfVec3f &vec) const { return GfVec3f( {{ LIST("vec[%(i)s] * _mtx[%(i)s][0]", sep=" + ", num=3) }} + _mtx[3][0], @@ -343,14 +341,13 @@ class GfMatrix3{{ SCL[0] }}; {% endif %} private: - /// Returns the determinant of the 3x3 submatrix specified by the - /// three given row and column indices (0-3 for each). + /// Returns the determinant of the 3x3 submatrix specified by the three + /// given row and column indices (0-3 for each). double _GetDeterminant3(size_t row1, size_t row2, size_t row3, size_t col1, size_t col2, size_t col3) const; {% if SCL == 'double' %} - /// Diagonalizes the upper 3x3 matrix of a matrix known to be - /// symmetric. + /// Diagonalizes the upper 3x3 matrix of a matrix known to be symmetric. void _Jacobi3(GfVec3d *eigenvalues, GfVec3d eigenvectors[3]) const; {% endif %} {% endblock customXformFunctions %} diff --git a/pxr/base/lib/gf/matrix4d.cpp b/pxr/base/lib/gf/matrix4d.cpp index 45f2c827c2..38b51349b6 100644 --- a/pxr/base/lib/gf/matrix4d.cpp +++ b/pxr/base/lib/gf/matrix4d.cpp @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////// // This file is generated by a script. Do not edit directly. Edit the // matrix4.template.cpp file to make changes. - +#include "pxr/base/arch/pragmas.h" #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/matrix4f.h" diff --git a/pxr/base/lib/gf/matrix4d.h b/pxr/base/lib/gf/matrix4d.h index 00c27ce5f1..7d04ee84c0 100644 --- a/pxr/base/lib/gf/matrix4d.h +++ b/pxr/base/lib/gf/matrix4d.h @@ -28,6 +28,9 @@ #ifndef GF_MATRIX4D_H #define GF_MATRIX4D_H +/// \file gf/matrix4d.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/matrixData.h" #include "pxr/base/gf/vec4d.h" #include "pxr/base/gf/traits.h" @@ -35,16 +38,13 @@ #include "pxr/base/gf/limits.h" #include "pxr/base/gf/math.h" #include "pxr/base/gf/vec3d.h" +#include "pxr/base/gf/api.h" #include #include #include -/// \file matrix4d.h -/// \ingroup group_gf_LinearAlgebra -/// - template <> struct GfIsGfMatrix { static const bool value = true; }; @@ -53,11 +53,12 @@ class GfMatrix4f; class GfRotation; class GfMatrix3d; -/// \class GfMatrix4d matrix4d.h "pxr/base/gf/matrix4d.h" +/// \class GfMatrix4d /// \ingroup group_gf_LinearAlgebra -/// \brief Stores a 4x4 matrix of \c double elements. A basic type. /// -/// Matrices are defined to be in row-major order, so matrix[i][j] +/// Stores a 4x4 matrix of \c double elements. A basic type. +/// +/// Matrices are defined to be in row-major order, so matrix[i][j] /// indexes the element in the \e i th row and the \e j th column. /// ///

3D Transformations

@@ -87,8 +88,7 @@ class GfMatrix4d static const size_t numRows = 4; static const size_t numColumns = 4; - /// Default constructor. Leaves the matrix component values - /// undefined. + /// Default constructor. Leaves the matrix component values undefined. GfMatrix4d() {} /// Constructor. Initializes the matrix from 16 independent @@ -104,14 +104,14 @@ class GfMatrix4d m30, m31, m32, m33); } - /// Constructor. Initializes the matrix from a 4x4 array of - /// \c double values, specified in row-major order. + /// Constructor. Initializes the matrix from a 4x4 array + /// of \c double values, specified in row-major order. GfMatrix4d(const double m[4][4]) { Set(m); } - /// Constructor. Explicitly initializes the matrix to \e s times - /// the identity matrix. + /// Constructor. Explicitly initializes the matrix to \e s times the + /// identity matrix. explicit GfMatrix4d(double s) { SetDiagonal(s); } @@ -122,20 +122,22 @@ class GfMatrix4d SetDiagonal(v); } - /// Constructor. Initialize the matrix from a vector of vectors of double. - /// The vector is expected to be 4x4. If it is too big, only the first - /// 4 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// double. The vector is expected to be 4x4. If it is + /// too big, only the first 4 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix4d(const std::vector< std::vector >& v); - /// Constructor. Initialize the matrix from a vector of vectors of float. - /// The vector is expected to be 4x4. If it is too big, only the first - /// 4 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// float. The vector is expected to be 4x4. If it is + /// too big, only the first 4 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix4d(const std::vector< std::vector >& v); /// Constructor. Initialize the matrix from 4 row vectors of @@ -144,6 +146,7 @@ class GfMatrix4d /// uninitialized elements will be filled in with the /// corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix4d(const std::vector& r0, const std::vector& r1, const std::vector& r2, @@ -155,22 +158,25 @@ class GfMatrix4d /// uninitialized elements will be filled in with the /// corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix4d(const std::vector& r0, const std::vector& r1, const std::vector& r2, const std::vector& r3); - /// Constructor. Initializes a transformation matrix to perform the indicated - /// rotation and translation. + /// Constructor. Initializes a transformation matrix to perform the + /// indicated rotation and translation. + GF_API GfMatrix4d(const GfRotation& rotate, const GfVec3d& translate); - /// Constructor. Initializes a transformation matrix to perform the indicated - /// rotation and translation. + /// Constructor. Initializes a transformation matrix to perform the + /// indicated rotation and translation. + GF_API GfMatrix4d(const GfMatrix3d& rotmx, const GfVec3d& translate); - //! - // This explicit constructor converts a "float" matrix to a "double" matrix. + /// This explicit constructor converts a "float" matrix to a "double" matrix. + GF_API explicit GfMatrix4d(const class GfMatrix4f& m); /// Sets a row of the matrix from a Vec4. @@ -199,9 +205,9 @@ class GfMatrix4d return GfVec4d(_mtx[0][i], _mtx[1][i], _mtx[2][i], _mtx[3][i]); } - /// \brief Sets the matrix from 16 independent \c double values, specified - /// in row-major order. For example, parameter \e m10 specifies the - /// value in row 1 and column 0. + /// Sets the matrix from 16 independent \c double values, + /// specified in row-major order. For example, parameter \e m10 specifies + /// the value in row 1 and column 0. GfMatrix4d& Set(double m00, double m01, double m02, double m03, double m10, double m11, double m12, double m13, double m20, double m21, double m22, double m23, @@ -213,8 +219,8 @@ class GfMatrix4d return *this; } - /// \brief Sets the matrix from a 4x4 array of \c double values, specified - /// in row-major order. + /// Sets the matrix from a 4x4 array of \c double + /// values, specified in row-major order. GfMatrix4d& Set(const double m[4][4]) { _mtx[0][0] = m[0][0]; _mtx[0][1] = m[0][1]; @@ -246,13 +252,16 @@ class GfMatrix4d } /// Sets the matrix to \e s times the identity matrix. + GF_API GfMatrix4d& SetDiagonal(double s); /// Sets the matrix to have diagonal (v[0], v[1], v[2], v[3]). + GF_API GfMatrix4d& SetDiagonal(const GfVec4d&); /// Fills a 4x4 array of \c double values with the values in /// the matrix, specified in row-major order. + GF_API double* Get(double m[4][4]); /// Returns vector components as an array of \c double values. @@ -264,15 +273,15 @@ class GfMatrix4d const double* GetArray() const { return _mtx.GetData(); } - - /// Accesses an indexed row \e i of the matrix as an array of 4 \c double - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + + /// Accesses an indexed row \e i of the matrix as an array of 4 \c + /// double values so that standard indexing (such as m[0][1]) + /// works correctly. double* operator [](int i) { return _mtx[i]; } - /// Accesses an indexed row \e i of the matrix as an array of 4 \c double - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + /// Accesses an indexed row \e i of the matrix as an array of 4 \c + /// double values so that standard indexing (such as m[0][1]) + /// works correctly. const double* operator [](int i) const { return _mtx[i]; } /// Hash. @@ -283,14 +292,16 @@ class GfMatrix4d while (nElems--) boost::hash_combine(h, *p++); return h; - } + } /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix4d& m) const; /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix4f& m) const; /// Tests for element-wise matrix inequality. All elements must match @@ -306,16 +317,19 @@ class GfMatrix4d } /// Returns the transpose of the matrix. + GF_API GfMatrix4d GetTranspose() const; /// Returns the inverse of the matrix, or FLT_MAX * SetIdentity() if the - /// matrix is singular. (FLT_MAX is the largest value a \c float can have, - /// as defined by the system.) The matrix is considered singular if the - /// determinant is less than or equal to the optional parameter \e eps. - /// If \e det is non-null, *det is set to the determinant. + /// matrix is singular. (FLT_MAX is the largest value a \c float can have, + /// as defined by the system.) The matrix is considered singular if the + /// determinant is less than or equal to the optional parameter \e eps. If + /// \e det is non-null, *det is set to the determinant. + GF_API GfMatrix4d GetInverse(double* det = NULL, double eps = 0) const; /// Returns the determinant of the matrix. + GF_API double GetDeterminant() const; /// Sets a row of the matrix from a Vec3. @@ -345,31 +359,34 @@ class GfMatrix4d // XXX Should add GfAreOrthogonal(v0, v1, v2) (which also // GfRotation::Decompose() could use). GfVec3d axis0(GetRow3(0)), axis1(GetRow3(1)), axis2(GetRow3(2)); - return (GfAbs(GfDot(axis0, axis1)) < GF_MIN_ORTHO_TOLERANCE and + return (GfAbs(GfDot(axis0, axis1)) < GF_MIN_ORTHO_TOLERANCE and GfAbs(GfDot(axis0, axis2)) < GF_MIN_ORTHO_TOLERANCE and GfAbs(GfDot(axis1, axis2)) < GF_MIN_ORTHO_TOLERANCE); } - /// Makes the matrix orthonormal in place. This is an iterative method that - /// is much more stable than the previous cross/cross method. If the + /// Makes the matrix orthonormal in place. This is an iterative method + /// that is much more stable than the previous cross/cross method. If the /// iterative method does not converge, a warning is issued. /// /// Returns true if the iteration converged, false otherwise. Leaves any /// translation part of the matrix unchanged. If \a issueWarning is true, /// this method will issue a warning if the iteration does not converge, /// otherwise it will be silent. + GF_API bool Orthonormalize(bool issueWarning=true); /// Returns an orthonormalized copy of the matrix. + GF_API GfMatrix4d GetOrthonormalized(bool issueWarning=true) const; - /// Returns the sign of the determinant of the upper 3x3 matrix, i.e. 1 for - /// a right-handed matrix, -1 for a left-handed matrix, and 0 for a + /// Returns the sign of the determinant of the upper 3x3 matrix, i.e. 1 + /// for a right-handed matrix, -1 for a left-handed matrix, and 0 for a /// singular matrix. + GF_API double GetHandedness() const; - /// Returns true if the vectors in the upper 3x3 matrix form a right-handed - /// coordinate system. + /// Returns true if the vectors in the upper 3x3 matrix form a + /// right-handed coordinate system. bool IsRightHanded() const { return GetHandedness() == 1.0; } @@ -381,17 +398,18 @@ class GfMatrix4d } /// Post-multiplies matrix \e m into this matrix. + GF_API GfMatrix4d& operator *=(const GfMatrix4d& m); /// Multiplies the matrix by a double. + GF_API GfMatrix4d& operator *=(double); - /// - // Returns the product of a matrix and a double. + /// Returns the product of a matrix and a double. friend GfMatrix4d operator *(const GfMatrix4d& m1, double d) { - GfMatrix4d m = m1; - return m *= d; + GfMatrix4d m = m1; + return m *= d; } /// @@ -402,12 +420,15 @@ class GfMatrix4d } /// Adds matrix \e m to this matrix. + GF_API GfMatrix4d& operator +=(const GfMatrix4d& m); /// Subtracts matrix \e m from this matrix. + GF_API GfMatrix4d& operator -=(const GfMatrix4d& m); /// Returns the unary negation of matrix \e m. + GF_API friend GfMatrix4d operator -(const GfMatrix4d& m); /// Adds matrix \e m2 to \e m1 @@ -418,15 +439,15 @@ class GfMatrix4d return tmp; } - /// Subtracts matrix \e m2 from \e m1 + /// Subtracts matrix \e m2 from \e m1. friend GfMatrix4d operator -(const GfMatrix4d& m1, const GfMatrix4d& m2) { GfMatrix4d tmp(m1); tmp -= m2; return tmp; } - - /// Multiplies matrix \e m1 by \e m2 + + /// Multiplies matrix \e m1 by \e m2. friend GfMatrix4d operator *(const GfMatrix4d& m1, const GfMatrix4d& m2) { GfMatrix4d tmp(m1); @@ -458,18 +479,22 @@ class GfMatrix4d /// Returns the product of a matrix \e m and a column vector \e vec. /// Note that the return type is a \c GfVec4f. + GF_API friend GfVec4f operator *(const GfMatrix4d& m, const GfVec4f& vec); /// Returns the product of row vector \e vec and a matrix \e m. /// Note that the return type is a \c GfVec4f. + GF_API friend GfVec4f operator *(const GfVec4f &vec, const GfMatrix4d& m); /// Sets matrix to specify a uniform scaling by \e scaleFactor. + GF_API GfMatrix4d& SetScale(double scaleFactor); /// Returns the matrix with any scaling or shearing removed, /// leaving only the rotation and translation. /// If the matrix cannot be decomposed, returns the original matrix. + GF_API GfMatrix4d RemoveScaleShear() const; /// \name 3D Transformation Utilities @@ -477,39 +502,48 @@ class GfMatrix4d /// Sets the matrix to specify a rotation equivalent to \e rot, /// and clears the translation. + GF_API GfMatrix4d& SetRotate(const GfRotation &rot); /// Sets the matrix to specify a rotation equivalent to \e rot, /// without clearing the translation. + GF_API GfMatrix4d& SetRotateOnly(const GfRotation &rot); /// Sets the matrix to specify a rotation equivalent to \e mx, /// and clears the translation. + GF_API GfMatrix4d& SetRotate(const GfMatrix3d &mx); /// Sets the matrix to specify a rotation equivalent to \e mx, /// without clearing the translation. + GF_API GfMatrix4d& SetRotateOnly(const GfMatrix3d &mx); /// Sets the matrix to specify a nonuniform scaling in x, y, and z by /// the factors in vector \e scaleFactors. + GF_API GfMatrix4d& SetScale(const GfVec3d &scaleFactors); /// Sets matrix to specify a translation by the vector \e trans, /// and clears the rotation. + GF_API GfMatrix4d& SetTranslate(const GfVec3d &trans); /// Sets matrix to specify a translation by the vector \e trans, /// without clearing the rotation. + GF_API GfMatrix4d& SetTranslateOnly(const GfVec3d &t); /// Sets matrix to specify a rotation by \e rotate and a /// translation by \e translate. + GF_API GfMatrix4d& SetTransform(const GfRotation& rotate, const GfVec3d& translate); /// Sets matrix to specify a rotation by \e rotmx and a /// translation by \e translate. + GF_API GfMatrix4d& SetTransform(const GfMatrix3d& rotmx, const GfVec3d& translate); @@ -518,6 +552,7 @@ class GfMatrix4d /// represents the eye point in world space. \e centerPoint /// represents the world-space center of attention. \e upDirection /// is a vector indicating which way is up. + GF_API GfMatrix4d& SetLookAt(const GfVec3d &eyePoint, const GfVec3d ¢erPoint, const GfVec3d &upDirection); @@ -527,6 +562,7 @@ class GfMatrix4d /// orientation from its canonical frame, which is defined to be /// looking along the -z axis with the +y axis as the up /// direction. + GF_API GfMatrix4d& SetLookAt(const GfVec3d &eyePoint, const GfRotation &orientation); @@ -544,43 +580,46 @@ class GfMatrix4d /// Returns \c false if the matrix is singular (as determined by \e eps). /// In that case, any zero scales in \e s are clamped to \e eps /// to allow computation of \e u. + GF_API bool Factor(GfMatrix4d* r, GfVec3d* s, GfMatrix4d* u, GfVec3d* t, GfMatrix4d* p, double eps = GF_MIN_VECTOR_LENGTH) const; - /// Returns the translation part of the matrix, defined as the - /// first three elements of the last row. + /// Returns the translation part of the matrix, defined as the first three + /// elements of the last row. GfVec3d ExtractTranslation() const { return GfVec3d(_mtx[3][0], _mtx[3][1], _mtx[3][2]); } - - /// Returns the rotation corresponding to this matrix. This works - /// well only if the matrix represents a rotation. + + /// Returns the rotation corresponding to this matrix. This works well + /// only if the matrix represents a rotation. /// /// For good results, consider calling Orthonormalize() before calling /// this method. + GF_API GfRotation ExtractRotation() const; - /// Decompose the rotation corresponding to this matrix about 3 - /// orthogonal axes. If the axes are not orthogonal, warnings - /// will be spewed. + /// Decompose the rotation corresponding to this matrix about 3 orthogonal + /// axes. If the axes are not orthogonal, warnings will be spewed. /// /// This is a convenience method that is equivalent to calling /// ExtractRotation().Decompose(). + GF_API GfVec3d DecomposeRotation(const GfVec3d &axis0, const GfVec3d &axis1, const GfVec3d &axis2) const; - /// Returns the rotation corresponding to this matrix. This works - /// well only if the matrix represents a rotation. + /// Returns the rotation corresponding to this matrix. This works well + /// only if the matrix represents a rotation. /// /// For good results, consider calling Orthonormalize() before calling /// this method. + GF_API GfMatrix3d ExtractRotationMatrix() const; - /// Transforms the row vector \e vec by the matrix, returning the - /// result. This treats the vector as a 4-component vector whose - /// fourth component is 1. + /// Transforms the row vector \e vec by the matrix, returning the result. + /// This treats the vector as a 4-component vector whose fourth component + /// is 1. GfVec3d Transform(const GfVec3d &vec) const { return GfProject(GfVec4d( vec[0] * _mtx[0][0] + vec[1] * _mtx[1][0] + vec[2] * _mtx[2][0] + _mtx[3][0], @@ -588,11 +627,11 @@ class GfMatrix4d vec[0] * _mtx[0][2] + vec[1] * _mtx[1][2] + vec[2] * _mtx[2][2] + _mtx[3][2], vec[0] * _mtx[0][3] + vec[1] * _mtx[1][3] + vec[2] * _mtx[2][3] + _mtx[3][3])); } - - /// Transforms the row vector \e vec by the matrix, returning the - /// result. This treats the vector as a 4-component vector whose - /// fourth component is 1. This is an overloaded method; it differs - /// from the other version in that it returns a different value type. + + /// Transforms the row vector \e vec by the matrix, returning the result. + /// This treats the vector as a 4-component vector whose fourth component + /// is 1. This is an overloaded method; it differs from the other version + /// in that it returns a different value type. GfVec3f Transform(const GfVec3f &vec) const { return GfVec3f(GfProject(GfVec4d( vec[0] * _mtx[0][0] + vec[1] * _mtx[1][0] + vec[2] * _mtx[2][0] + _mtx[3][0], @@ -601,24 +640,23 @@ class GfMatrix4d vec[0] * _mtx[0][3] + vec[1] * _mtx[1][3] + vec[2] * _mtx[2][3] + _mtx[3][3]))); } - /// Transforms row vector \e vec by the matrix, returning the - /// result. This treats the vector as a direction vector, so the - /// translation information in the matrix is ignored. That is, it - /// treats the vector as a 4-component vector whose fourth - /// component is 0. + /// Transforms row vector \e vec by the matrix, returning the result. This + /// treats the vector as a direction vector, so the translation + /// information in the matrix is ignored. That is, it treats the vector as + /// a 4-component vector whose fourth component is 0. GfVec3d TransformDir(const GfVec3d &vec) const { return GfVec3d( vec[0] * _mtx[0][0] + vec[1] * _mtx[1][0] + vec[2] * _mtx[2][0], vec[0] * _mtx[0][1] + vec[1] * _mtx[1][1] + vec[2] * _mtx[2][1], vec[0] * _mtx[0][2] + vec[1] * _mtx[1][2] + vec[2] * _mtx[2][2]); } - - /// Transforms row vector \e vec by the matrix, returning the - /// result. This treats the vector as a direction vector, so the - /// translation information in the matrix is ignored. That is, it - /// treats the vector as a 4-component vector whose fourth - /// component is 0. This is an overloaded method; it differs - /// from the other version in that it returns a different value type. + + /// Transforms row vector \e vec by the matrix, returning the result. This + /// treats the vector as a direction vector, so the translation + /// information in the matrix is ignored. That is, it treats the vector as + /// a 4-component vector whose fourth component is 0. This is an + /// overloaded method; it differs from the other version in that it + /// returns a different value type. GfVec3f TransformDir(const GfVec3f &vec) const { return GfVec3f( vec[0] * _mtx[0][0] + vec[1] * _mtx[1][0] + vec[2] * _mtx[2][0], @@ -626,10 +664,10 @@ class GfMatrix4d vec[0] * _mtx[0][2] + vec[1] * _mtx[1][2] + vec[2] * _mtx[2][2]); } - /// Transforms the row vector \e vec by the matrix, returning the - /// result. This treats the vector as a 4-component vector whose - /// fourth component is 1 and ignores the fourth column of the - /// matrix (i.e. assumes it is (0, 0, 0, 1)). + /// Transforms the row vector \e vec by the matrix, returning the result. + /// This treats the vector as a 4-component vector whose fourth component + /// is 1 and ignores the fourth column of the matrix (i.e. assumes it is + /// (0, 0, 0, 1)). GfVec3d TransformAffine(const GfVec3d &vec) const { return GfVec3d( vec[0] * _mtx[0][0] + vec[1] * _mtx[1][0] + vec[2] * _mtx[2][0] + _mtx[3][0], @@ -637,10 +675,10 @@ class GfMatrix4d vec[0] * _mtx[0][2] + vec[1] * _mtx[1][2] + vec[2] * _mtx[2][2] + _mtx[3][2]); } - /// Transforms the row vector \e vec by the matrix, returning the - /// result. This treats the vector as a 4-component vector whose - /// fourth component is 1 and ignores the fourth column of the - /// matrix (i.e. assumes it is (0, 0, 0, 1)). + /// Transforms the row vector \e vec by the matrix, returning the result. + /// This treats the vector as a 4-component vector whose fourth component + /// is 1 and ignores the fourth column of the matrix (i.e. assumes it is + /// (0, 0, 0, 1)). GfVec3f TransformAffine(const GfVec3f &vec) const { return GfVec3f( vec[0] * _mtx[0][0] + vec[1] * _mtx[1][0] + vec[2] * _mtx[2][0] + _mtx[3][0], @@ -650,13 +688,13 @@ class GfMatrix4d /// @} private: - /// Returns the determinant of the 3x3 submatrix specified by the - /// three given row and column indices (0-3 for each). + /// Returns the determinant of the 3x3 submatrix specified by the three + /// given row and column indices (0-3 for each). + GF_API double _GetDeterminant3(size_t row1, size_t row2, size_t row3, size_t col1, size_t col2, size_t col3) const; - /// Diagonalizes the upper 3x3 matrix of a matrix known to be - /// symmetric. + /// Diagonalizes the upper 3x3 matrix of a matrix known to be symmetric. void _Jacobi3(GfVec3d *eigenvalues, GfVec3d eigenvectors[3]) const; private: @@ -669,6 +707,6 @@ class GfMatrix4d /// Output a GfMatrix4d /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfMatrix4d const &); +GF_API std::ostream& operator<<(std::ostream &, GfMatrix4d const &); #endif // GF_MATRIX4D_H diff --git a/pxr/base/lib/gf/matrix4f.cpp b/pxr/base/lib/gf/matrix4f.cpp index 447e1238b2..8afbd92a1c 100644 --- a/pxr/base/lib/gf/matrix4f.cpp +++ b/pxr/base/lib/gf/matrix4f.cpp @@ -25,6 +25,7 @@ // This file is generated by a script. Do not edit directly. Edit the // matrix4.template.cpp file to make changes. +#include "pxr/base/arch/pragmas.h" #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/matrix4f.h" diff --git a/pxr/base/lib/gf/matrix4f.h b/pxr/base/lib/gf/matrix4f.h index 3f54f9ffcc..57136f1922 100644 --- a/pxr/base/lib/gf/matrix4f.h +++ b/pxr/base/lib/gf/matrix4f.h @@ -28,6 +28,9 @@ #ifndef GF_MATRIX4F_H #define GF_MATRIX4F_H +/// \file gf/matrix4f.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/matrixData.h" #include "pxr/base/gf/vec4f.h" #include "pxr/base/gf/traits.h" @@ -35,16 +38,13 @@ #include "pxr/base/gf/limits.h" #include "pxr/base/gf/math.h" #include "pxr/base/gf/vec3f.h" +#include "pxr/base/gf/api.h" #include #include #include -/// \file matrix4f.h -/// \ingroup group_gf_LinearAlgebra -/// - template <> struct GfIsGfMatrix { static const bool value = true; }; @@ -52,11 +52,12 @@ class GfMatrix4d; class GfMatrix4f; class GfMatrix3f; -/// \class GfMatrix4f matrix4f.h "pxr/base/gf/matrix4f.h" +/// \class GfMatrix4f /// \ingroup group_gf_LinearAlgebra -/// \brief Stores a 4x4 matrix of \c float elements. A basic type. /// -/// Matrices are defined to be in row-major order, so matrix[i][j] +/// Stores a 4x4 matrix of \c float elements. A basic type. +/// +/// Matrices are defined to be in row-major order, so matrix[i][j] /// indexes the element in the \e i th row and the \e j th column. /// ///

3D Transformations

@@ -86,8 +87,7 @@ class GfMatrix4f static const size_t numRows = 4; static const size_t numColumns = 4; - /// Default constructor. Leaves the matrix component values - /// undefined. + /// Default constructor. Leaves the matrix component values undefined. GfMatrix4f() {} /// Constructor. Initializes the matrix from 16 independent @@ -103,14 +103,14 @@ class GfMatrix4f m30, m31, m32, m33); } - /// Constructor. Initializes the matrix from a 4x4 array of - /// \c float values, specified in row-major order. + /// Constructor. Initializes the matrix from a 4x4 array + /// of \c float values, specified in row-major order. GfMatrix4f(const float m[4][4]) { Set(m); } - /// Constructor. Explicitly initializes the matrix to \e s times - /// the identity matrix. + /// Constructor. Explicitly initializes the matrix to \e s times the + /// identity matrix. explicit GfMatrix4f(float s) { SetDiagonal(s); } @@ -121,20 +121,22 @@ class GfMatrix4f SetDiagonal(v); } - /// Constructor. Initialize the matrix from a vector of vectors of double. - /// The vector is expected to be 4x4. If it is too big, only the first - /// 4 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// double. The vector is expected to be 4x4. If it is + /// too big, only the first 4 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix4f(const std::vector< std::vector >& v); - /// Constructor. Initialize the matrix from a vector of vectors of float. - /// The vector is expected to be 4x4. If it is too big, only the first - /// 4 rows and/or columns will be used. If it is too small, uninitialized - /// elements will be filled in with the corresponding elements from an - /// identity matrix. + /// Constructor. Initialize the matrix from a vector of vectors of + /// float. The vector is expected to be 4x4. If it is + /// too big, only the first 4 rows and/or columns will be used. + /// If it is too small, uninitialized elements will be filled in with + /// the corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix4f(const std::vector< std::vector >& v); /// Constructor. Initialize the matrix from 4 row vectors of @@ -143,6 +145,7 @@ class GfMatrix4f /// uninitialized elements will be filled in with the /// corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix4f(const std::vector& r0, const std::vector& r1, const std::vector& r2, @@ -154,17 +157,19 @@ class GfMatrix4f /// uninitialized elements will be filled in with the /// corresponding elements from an identity matrix. /// + GF_API explicit GfMatrix4f(const std::vector& r0, const std::vector& r1, const std::vector& r2, const std::vector& r3); - /// Constructor. Initializes a transformation matrix to perform the indicated - /// rotation and translation. + /// Constructor. Initializes a transformation matrix to perform the + /// indicated rotation and translation. + GF_API GfMatrix4f(const GfMatrix3f& rotmx, const GfVec3f& translate); - //! - // This explicit constructor converts a "double" matrix to a "float" matrix. + /// This explicit constructor converts a "double" matrix to a "float" matrix. + GF_API explicit GfMatrix4f(const class GfMatrix4d& m); /// Sets a row of the matrix from a Vec4. @@ -193,9 +198,9 @@ class GfMatrix4f return GfVec4f(_mtx[0][i], _mtx[1][i], _mtx[2][i], _mtx[3][i]); } - /// \brief Sets the matrix from 16 independent \c float values, specified - /// in row-major order. For example, parameter \e m10 specifies the - /// value in row 1 and column 0. + /// Sets the matrix from 16 independent \c float values, + /// specified in row-major order. For example, parameter \e m10 specifies + /// the value in row 1 and column 0. GfMatrix4f& Set(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23, @@ -207,8 +212,8 @@ class GfMatrix4f return *this; } - /// \brief Sets the matrix from a 4x4 array of \c float values, specified - /// in row-major order. + /// Sets the matrix from a 4x4 array of \c float + /// values, specified in row-major order. GfMatrix4f& Set(const float m[4][4]) { _mtx[0][0] = m[0][0]; _mtx[0][1] = m[0][1]; @@ -240,13 +245,16 @@ class GfMatrix4f } /// Sets the matrix to \e s times the identity matrix. + GF_API GfMatrix4f& SetDiagonal(float s); /// Sets the matrix to have diagonal (v[0], v[1], v[2], v[3]). + GF_API GfMatrix4f& SetDiagonal(const GfVec4f&); /// Fills a 4x4 array of \c float values with the values in /// the matrix, specified in row-major order. + GF_API float* Get(float m[4][4]); /// Returns vector components as an array of \c float values. @@ -258,15 +266,15 @@ class GfMatrix4f const float* GetArray() const { return _mtx.GetData(); } - - /// Accesses an indexed row \e i of the matrix as an array of 4 \c float - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + + /// Accesses an indexed row \e i of the matrix as an array of 4 \c + /// float values so that standard indexing (such as m[0][1]) + /// works correctly. float* operator [](int i) { return _mtx[i]; } - /// Accesses an indexed row \e i of the matrix as an array of 4 \c float - /// values so that standard indexing (such as m[0][1]) works - /// correctly. + /// Accesses an indexed row \e i of the matrix as an array of 4 \c + /// float values so that standard indexing (such as m[0][1]) + /// works correctly. const float* operator [](int i) const { return _mtx[i]; } /// Hash. @@ -277,14 +285,16 @@ class GfMatrix4f while (nElems--) boost::hash_combine(h, *p++); return h; - } + } /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix4d& m) const; /// Tests for element-wise matrix equality. All elements must match /// exactly for matrices to be considered equal. + GF_API bool operator ==(const GfMatrix4f& m) const; /// Tests for element-wise matrix inequality. All elements must match @@ -300,16 +310,19 @@ class GfMatrix4f } /// Returns the transpose of the matrix. + GF_API GfMatrix4f GetTranspose() const; /// Returns the inverse of the matrix, or FLT_MAX * SetIdentity() if the - /// matrix is singular. (FLT_MAX is the largest value a \c float can have, - /// as defined by the system.) The matrix is considered singular if the - /// determinant is less than or equal to the optional parameter \e eps. - /// If \e det is non-null, *det is set to the determinant. + /// matrix is singular. (FLT_MAX is the largest value a \c float can have, + /// as defined by the system.) The matrix is considered singular if the + /// determinant is less than or equal to the optional parameter \e eps. If + /// \e det is non-null, *det is set to the determinant. + GF_API GfMatrix4f GetInverse(double* det = NULL, double eps = 0) const; /// Returns the determinant of the matrix. + GF_API double GetDeterminant() const; /// Sets a row of the matrix from a Vec3. @@ -339,31 +352,34 @@ class GfMatrix4f // XXX Should add GfAreOrthogonal(v0, v1, v2) (which also // GfRotation::Decompose() could use). GfVec3f axis0(GetRow3(0)), axis1(GetRow3(1)), axis2(GetRow3(2)); - return (GfAbs(GfDot(axis0, axis1)) < GF_MIN_ORTHO_TOLERANCE and + return (GfAbs(GfDot(axis0, axis1)) < GF_MIN_ORTHO_TOLERANCE and GfAbs(GfDot(axis0, axis2)) < GF_MIN_ORTHO_TOLERANCE and GfAbs(GfDot(axis1, axis2)) < GF_MIN_ORTHO_TOLERANCE); } - /// Makes the matrix orthonormal in place. This is an iterative method that - /// is much more stable than the previous cross/cross method. If the + /// Makes the matrix orthonormal in place. This is an iterative method + /// that is much more stable than the previous cross/cross method. If the /// iterative method does not converge, a warning is issued. /// /// Returns true if the iteration converged, false otherwise. Leaves any /// translation part of the matrix unchanged. If \a issueWarning is true, /// this method will issue a warning if the iteration does not converge, /// otherwise it will be silent. + GF_API bool Orthonormalize(bool issueWarning=true); /// Returns an orthonormalized copy of the matrix. + GF_API GfMatrix4f GetOrthonormalized(bool issueWarning=true) const; - /// Returns the sign of the determinant of the upper 3x3 matrix, i.e. 1 for - /// a right-handed matrix, -1 for a left-handed matrix, and 0 for a + /// Returns the sign of the determinant of the upper 3x3 matrix, i.e. 1 + /// for a right-handed matrix, -1 for a left-handed matrix, and 0 for a /// singular matrix. + GF_API double GetHandedness() const; - /// Returns true if the vectors in the upper 3x3 matrix form a right-handed - /// coordinate system. + /// Returns true if the vectors in the upper 3x3 matrix form a + /// right-handed coordinate system. bool IsRightHanded() const { return GetHandedness() == 1.0; } @@ -375,17 +391,18 @@ class GfMatrix4f } /// Post-multiplies matrix \e m into this matrix. + GF_API GfMatrix4f& operator *=(const GfMatrix4f& m); /// Multiplies the matrix by a float. + GF_API GfMatrix4f& operator *=(double); - /// - // Returns the product of a matrix and a float. + /// Returns the product of a matrix and a float. friend GfMatrix4f operator *(const GfMatrix4f& m1, double d) { - GfMatrix4f m = m1; - return m *= d; + GfMatrix4f m = m1; + return m *= d; } /// @@ -396,12 +413,15 @@ class GfMatrix4f } /// Adds matrix \e m to this matrix. + GF_API GfMatrix4f& operator +=(const GfMatrix4f& m); /// Subtracts matrix \e m from this matrix. + GF_API GfMatrix4f& operator -=(const GfMatrix4f& m); /// Returns the unary negation of matrix \e m. + GF_API friend GfMatrix4f operator -(const GfMatrix4f& m); /// Adds matrix \e m2 to \e m1 @@ -412,15 +432,15 @@ class GfMatrix4f return tmp; } - /// Subtracts matrix \e m2 from \e m1 + /// Subtracts matrix \e m2 from \e m1. friend GfMatrix4f operator -(const GfMatrix4f& m1, const GfMatrix4f& m2) { GfMatrix4f tmp(m1); tmp -= m2; return tmp; } - - /// Multiplies matrix \e m1 by \e m2 + + /// Multiplies matrix \e m1 by \e m2. friend GfMatrix4f operator *(const GfMatrix4f& m1, const GfMatrix4f& m2) { GfMatrix4f tmp(m1); @@ -451,16 +471,19 @@ class GfMatrix4f } /// Sets matrix to specify a uniform scaling by \e scaleFactor. + GF_API GfMatrix4f& SetScale(float scaleFactor); /// Returns the matrix with any scaling or shearing removed, /// leaving only the rotation and translation. /// If the matrix cannot be decomposed, returns the original matrix. + GF_API GfMatrix4f RemoveScaleShear() const; private: - /// Returns the determinant of the 3x3 submatrix specified by the - /// three given row and column indices (0-3 for each). + /// Returns the determinant of the 3x3 submatrix specified by the three + /// given row and column indices (0-3 for each). + GF_API double _GetDeterminant3(size_t row1, size_t row2, size_t row3, size_t col1, size_t col2, size_t col3) const; @@ -474,6 +497,6 @@ class GfMatrix4f /// Output a GfMatrix4f /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfMatrix4f const &); +GF_API std::ostream& operator<<(std::ostream &, GfMatrix4f const &); #endif // GF_MATRIX4F_H diff --git a/pxr/base/lib/gf/matrixData.h b/pxr/base/lib/gf/matrixData.h index 1ba03c42a8..f63c10a1ac 100644 --- a/pxr/base/lib/gf/matrixData.h +++ b/pxr/base/lib/gf/matrixData.h @@ -24,6 +24,8 @@ #ifndef GF_MATRIX_DATA_H #define GF_MATRIX_DATA_H +#include "pxr/base/gf/api.h" + /// \class GfMatrixData /// /// A class template used by GfMatrixXX to store values. @@ -31,22 +33,22 @@ template class GfMatrixData { public: - /// \brief Return a pointer to a \a row of data. - T *operator[](int row) { + /// Return a pointer to a \a row of data. + T *operator[](size_t row) { return _data + (row * Columns); } - /// \brief Return a const pointer to a \a row of data. - T const *operator[](int row) const { + /// Return a const pointer to a \a row of data. + T const *operator[](size_t row) const { return _data + (row * Columns); } - /// \brief Return a pointer to the start of all the data. + /// Return a pointer to the start of all the data. T *GetData() { return _data; } - /// \brief Return a const pointer to the start of all the data. + /// Return a const pointer to the start of all the data. T const *GetData() const { return _data; } @@ -56,6 +58,4 @@ class GfMatrixData { T _data[Rows * Columns]; }; - - #endif // GF_MATRIX_DATA_H diff --git a/pxr/base/lib/gf/moduleDeps.cpp b/pxr/base/lib/gf/moduleDeps.cpp index 9058179565..33c21d7033 100644 --- a/pxr/base/lib/gf/moduleDeps.cpp +++ b/pxr/base/lib/gf/moduleDeps.cpp @@ -38,5 +38,4 @@ TF_REGISTRY_FUNCTION(TfScriptModuleLoader) { reqs.push_back(TfToken("tf")); TfScriptModuleLoader::GetInstance(). RegisterLibrary(TfToken("gf"), TfToken("pxr.Gf"), reqs); -} - +} \ No newline at end of file diff --git a/pxr/base/lib/gf/multiInterval.h b/pxr/base/lib/gf/multiInterval.h index 03088f3fd4..d0bb06fb3a 100644 --- a/pxr/base/lib/gf/multiInterval.h +++ b/pxr/base/lib/gf/multiInterval.h @@ -24,24 +24,22 @@ #ifndef GF_INTERVAL_SET_H #define GF_INTERVAL_SET_H +/// \file gf/multiInterval.h +/// \ingroup group_gf_BasicMath + #include "pxr/base/gf/interval.h" +#include "pxr/base/gf/api.h" + #include #include - -//#include - -/*! - * \file multiInterval.h - * \ingroup group_gf_BasicMath - */ - -/*! - * \class GfMultiInterval - * \ingroup group_gf_BasicMath - * - * GfMultiInterval represents a subset of the real number line as an - * ordered set of non-intersecting GfIntervals. - */ +#include + +/// \class GfMultiInterval +/// \ingroup group_gf_BasicMath +/// +/// GfMultiInterval represents a subset of the real number line as an +/// ordered set of non-intersecting GfIntervals. +/// class GfMultiInterval { public: @@ -52,26 +50,26 @@ class GfMultiInterval /// \name Constructors /// @{ /// Constructs an empty multi-interval. - GfMultiInterval() {} + GF_API GfMultiInterval() {} /// Constructs an multi-interval by copying the given set. - GfMultiInterval(const GfMultiInterval &s) : _set(s._set) {} + GF_API GfMultiInterval(const GfMultiInterval &s) : _set(s._set) {} /// Constructs an multi-interval with the single given interval. - explicit GfMultiInterval(const GfInterval &i); + GF_API explicit GfMultiInterval(const GfInterval &i); /// Constructs an multi-interval containing the given input intervals. - explicit GfMultiInterval(const std::vector &intervals); + GF_API explicit GfMultiInterval(const std::vector &intervals); /// @} - bool operator==(const GfMultiInterval &that) const { return _set == that._set; } - bool operator!=(const GfMultiInterval &that) const { return !(*this == that); } - bool operator<(const GfMultiInterval &that) const { return _set < that._set; } - bool operator>=(const GfMultiInterval &that) const { return !(*this < that); } - bool operator>(const GfMultiInterval &that) const { return (that < *this); } - bool operator<=(const GfMultiInterval &that) const { return !(that < *this); } + GF_API bool operator==(const GfMultiInterval &that) const { return _set == that._set; } + GF_API bool operator!=(const GfMultiInterval &that) const { return !(*this == that); } + GF_API bool operator<(const GfMultiInterval &that) const { return _set < that._set; } + GF_API bool operator>=(const GfMultiInterval &that) const { return !(*this < that); } + GF_API bool operator>(const GfMultiInterval &that) const { return (that < *this); } + GF_API bool operator<=(const GfMultiInterval &that) const { return !(that < *this); } /// Hash value. /// Just a basic hash function, not particularly high quality. - size_t Hash() const; + GF_API size_t Hash() const; friend inline size_t hash_value(const GfMultiInterval &mi) { return mi.Hash(); @@ -81,24 +79,24 @@ class GfMultiInterval /// @{ /// Returns true if the multi-interval is empty. - bool IsEmpty() const { return _set.empty(); } + GF_API bool IsEmpty() const { return _set.empty(); } /// Returns the number of intervals in the set. - size_t GetSize() const { return _set.size(); } + GF_API size_t GetSize() const { return _set.size(); } /// Returns an interval bounding the entire multi-interval. /// Returns an empty interval if the multi-interval is empty. - GfInterval GetBounds() const; + GF_API GfInterval GetBounds() const; /// Returns true if the multi-interval contains the given value. - bool Contains(double d) const; + GF_API bool Contains(double d) const; /// Returns true if the multi-interval contains the given interval. - bool Contains(const GfInterval & i) const; + GF_API bool Contains(const GfInterval & i) const; /// Returns true if the multi-interval contains all the intervals in the /// given multi-interval. - bool Contains(const GfMultiInterval & s) const; + GF_API bool Contains(const GfMultiInterval & s) const; /// @} @@ -106,28 +104,28 @@ class GfMultiInterval /// @{ /// Clear the multi-interval. - void Clear() { _set.clear(); } + GF_API void Clear() { _set.clear(); } /// Add the given interval to the multi-interval. - void Add( const GfInterval & i ); + GF_API void Add( const GfInterval & i ); /// Add the given multi-interval to the multi-interval. /// Sets this object to the union of the two sets. - void Add( const GfMultiInterval &s ); + GF_API void Add( const GfMultiInterval &s ); /// Uses the given interval to extend the multi-interval in /// the interval arithmetic sense. - void ArithmeticAdd( const GfInterval &i ); + GF_API void ArithmeticAdd( const GfInterval &i ); /// Remove the given interval from this multi-interval. - void Remove( const GfInterval & i ); + GF_API void Remove( const GfInterval & i ); /// Remove the given multi-interval from this multi-interval. - void Remove( const GfMultiInterval &s ); + GF_API void Remove( const GfMultiInterval &s ); - void Intersect( const GfInterval & i ); - void Intersect( const GfMultiInterval &s ); + GF_API void Intersect( const GfInterval & i ); + GF_API void Intersect( const GfMultiInterval &s ); /// Return the complement of this set. - GfMultiInterval GetComplement() const; + GF_API GfMultiInterval GetComplement() const; /// @} @@ -136,28 +134,28 @@ class GfMultiInterval /// the multi-interval, changes must be made via the public mutation API. /// @{ - const_iterator begin() const { return _set.begin(); } - const_iterator end() const { return _set.end(); } + GF_API const_iterator begin() const { return _set.begin(); } + GF_API const_iterator end() const { return _set.end(); } /// Returns an iterator identifying the first (lowest) interval whose /// minimum value is >= x. If no such interval exists, returns end(). - const_iterator lower_bound( double x ) const; + GF_API const_iterator lower_bound( double x ) const; /// Returns an iterator identifying the first (lowest) interval whose /// minimum value is > x. If no such interval exists, returns end(). - const_iterator upper_bound( double x ) const; + GF_API const_iterator upper_bound( double x ) const; /// Returns an iterator identifying the first (loest) interval whose /// minimum value is > x. If no such interval exists, returns end(). - const_iterator GetNextNonContainingInterval( double x ) const; + GF_API const_iterator GetNextNonContainingInterval( double x ) const; /// Returns an iterator identifying the last (highest) interval whose /// maximum value is < x. If no such interval exists, returns end(). - const_iterator GetPriorNonContainingInterval( double x ) const; + GF_API const_iterator GetPriorNonContainingInterval( double x ) const; /// Returns an iterator identifying the interval that contains x. If /// no interval contains x, then it returns end() - const_iterator GetContainingInterval( double x ) const; + GF_API const_iterator GetContainingInterval( double x ) const; /// @} @@ -177,6 +175,6 @@ class GfMultiInterval /// Output a GfMultiInterval /// \ingroup group_gf_DebuggingOutput -std::ostream & operator<<(std::ostream &out, const GfMultiInterval &s); +GF_API std::ostream & operator<<(std::ostream &out, const GfMultiInterval &s); #endif diff --git a/pxr/base/lib/gf/ostreamHelpers.h b/pxr/base/lib/gf/ostreamHelpers.h index 63ed2d0a26..89eefb7977 100644 --- a/pxr/base/lib/gf/ostreamHelpers.h +++ b/pxr/base/lib/gf/ostreamHelpers.h @@ -24,18 +24,17 @@ #ifndef GF_OSTREAM_HELPERS_H #define GF_OSTREAM_HELPERS_H +/// \file gf/ostreamHelpers.h +/// \ingroup group_gf_DebuggingOutput +/// +/// Helpers for Gf stream operators. +/// +/// These functions are useful to help with writing stream operators for +/// Gf types. Please do not include this file in any header. + #include #include -/*! - * \file gf/ostreamHelpers.h - * \brief Helpers for Gf stream operators. - * \ingroup group_gf_DebuggingOutput - * - * These functions are useful to help with writing stream operators for - * Gf types. Please do not include this file in any header. - */ - // Helper class to write out the correct precision template struct Gf_OstreamHelperValue { @@ -62,17 +61,16 @@ inline Gf_OstreamHelperValue Gf_OstreamHelperP(double v) { inline std::ostream & operator<<(std::ostream &out, const Gf_OstreamHelperValue &data) { - int oldPrecision = out.precision(std::numeric_limits::digits10); + std::streamsize oldPrecision = out.precision(std::numeric_limits::digits10); out << data.value; out.precision(oldPrecision); return out; } - inline std::ostream & operator<<(std::ostream &out, const Gf_OstreamHelperValue &data) { - int oldPrecision = out.precision(std::numeric_limits::digits10); + std::streamsize oldPrecision = out.precision(std::numeric_limits::digits10); out << data.value; out.precision(oldPrecision); return out; diff --git a/pxr/base/lib/gf/overview.dox b/pxr/base/lib/gf/overview.dox index 824420c584..8222653e9c 100644 --- a/pxr/base/lib/gf/overview.dox +++ b/pxr/base/lib/gf/overview.dox @@ -37,6 +37,8 @@ \anchor mainpage_Gf +\section gf_overview Overview + Contains foundation classes and functions for working with the basic mathematical aspects of graphics. The high-level grouping of the classes and functions is as follows: @@ -44,8 +46,10 @@ The high-level grouping of the classes and functions is as follows:
  • \link group_gf_LinearAlgebra \b Linear \b Algebra - \endlink Includes classes representing basic types, including vectors of varying numbers and types (such as vectors of two, three, and four float components), two and three-dimensional arrays of sizes, and compound linear transformations.
  • \link group_gf_BasicMath \b Basic \b Mathematical \b Operations - \endlink Includes classes and functions for performing operations such as converting between radians and degrees, calculating square roots, minimum and maximum values, absolute values, and so on.
  • -
  • \link group_gf_BasicGeometry \b Basic \b Geometry - \endlink Includes classes that represent basic types such as one to three-dimensional floating point ranges, three-dimensional bounding boxes, planes, rays, and splines.
  • -
  • \link group_gf_Noise \b Noise \b and \b Randomness - \endlink Includes classes and functions for generating random numbers and various types of noise, including different dimensional levels of input and output (for example, four-dimensional input, two dimensional output).
  • +
  • \link group_gf_BasicGeometry \b Basic \b Geometry - \endlink +Includes classes that represent basic types such as one to three-dimensional +floating point ranges, three-dimensional bounding boxes, planes, rays, frusta, +and a camera model.
  • \link group_gf_DebuggingOutput \b Output \b For \b Debugging - \endlink Includes functions for quickly outputting Gf types (these are particularly useful for diagnostic purposes).
  • diff --git a/pxr/base/lib/gf/plane.h b/pxr/base/lib/gf/plane.h index 546d1c1ddd..927346324a 100644 --- a/pxr/base/lib/gf/plane.h +++ b/pxr/base/lib/gf/plane.h @@ -24,136 +24,121 @@ #ifndef GF_PLANE_H #define GF_PLANE_H +/// \file gf/plane.h +/// \ingroup group_gf_BasicGeometry #include "pxr/base/gf/vec3d.h" +#include "pxr/base/gf/api.h" #include -/*! - * \file plane.h - * \ingroup group_gf_BasicGeometry - */ - - - class GfRange3d; class GfMatrix4d; -//! -// \class GfPlane plane.h "pxr/base/gf/plane.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 3-dimensional plane -// -// This class represents a three-dimensional plane as a normal vector -// and the distance of the plane from the origin, measured along the -// normal. The plane can also be used to represent a half-space: the -// side of the plane in the direction of the normal. -// - +/// \class GfPlane +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 3-dimensional plane +/// +/// This class represents a three-dimensional plane as a normal vector +/// and the distance of the plane from the origin, measured along the +/// normal. The plane can also be used to represent a half-space: the +/// side of the plane in the direction of the normal. +/// class GfPlane { public: - //! - // The default constructor leaves the plane parameters undefined. + /// The default constructor leaves the plane parameters undefined. GfPlane() { } - //! - // This constructor sets this to the plane perpendicular to \p - // normal and at \p distance units from the origin. The passed-in - // normal is normalized to unit length first. + /// This constructor sets this to the plane perpendicular to \p normal and + /// at \p distance units from the origin. The passed-in normal is + /// normalized to unit length first. GfPlane(const GfVec3d &normal, double distanceToOrigin) { Set(normal, distanceToOrigin); } - //! - // This constructor sets this to the plane perpendicular to \p - // normal and that passes through \p point. The passed-in normal - // is normalized to unit length first. + /// This constructor sets this to the plane perpendicular to \p normal and + /// that passes through \p point. The passed-in normal is normalized to + /// unit length first. GfPlane(const GfVec3d &normal, const GfVec3d &point) { Set(normal, point); } - //! - // This constructor sets this to the plane that contains the three - // given points. The normal is constructed from the cross product of - // (\p p1 - \p p0) (\p p2 - \p p0). Results are undefined if the - // points are collinear. + /// This constructor sets this to the plane that contains the three given + /// points. The normal is constructed from the cross product of (\p p1 - + /// \p p0) (\p p2 - \p p0). Results are undefined if the points are + /// collinear. GfPlane(const GfVec3d &p0, const GfVec3d &p1, const GfVec3d &p2) { Set(p0, p1, p2); } - //! - // Sets this to the plane perpendicular to \p normal and at \p - // distance units from the origin. The passed-in normal is - // normalized to unit length first. + /// Sets this to the plane perpendicular to \p normal and at \p distance + /// units from the origin. The passed-in normal is normalized to unit + /// length first. void Set(const GfVec3d &normal, double distanceToOrigin) { _normal = normal.GetNormalized(); _distance = distanceToOrigin; } - //! - // This constructor sets this to the plane perpendicular to \p - // normal and that passes through \p point. The passed-in normal - // is normalized to unit length first. + /// This constructor sets this to the plane perpendicular to \p normal and + /// that passes through \p point. The passed-in normal is normalized to + /// unit length first. + GF_API void Set(const GfVec3d &normal, const GfVec3d &point); - //! - // This constructor sets this to the plane that contains the three - // given points. The normal is constructed from the cross product of - // (\p p1 - \p p0) (\p p2 - \p p0). Results are undefined if the - // points are collinear. + /// This constructor sets this to the plane that contains the three given + /// points. The normal is constructed from the cross product of (\p p1 - + /// \p p0) (\p p2 - \p p0). Results are undefined if the points are + /// collinear. + GF_API void Set(const GfVec3d &p0, const GfVec3d &p1, const GfVec3d &p2); - //! - // Returns the unit-length normal vector of the plane. + /// Returns the unit-length normal vector of the plane. const GfVec3d & GetNormal() const { return _normal; } - //! - // Returns the distance of the plane from the origin. + /// Returns the distance of the plane from the origin. double GetDistanceFromOrigin() const { return _distance; } - //! - // Component-wise equality test. The normals and distances must - // match exactly for planes to be considered equal. + /// Component-wise equality test. The normals and distances must match + /// exactly for planes to be considered equal. bool operator ==(const GfPlane &p) const { return (_normal == p._normal && _distance == p._distance); } - //! - // Component-wise inequality test. The normals and distances must - // match exactly for planes to be considered equal. + /// Component-wise inequality test. The normals and distances must match + /// exactly for planes to be considered equal. bool operator !=(const GfPlane &p) const { return ! (*this == p); } - //! - // Returns the distance of point \p from the plane. This distance - // will be positive if the point is on the side of the plane - // containing the normal. + /// Returns the distance of point \p from the plane. This distance will be + /// positive if the point is on the side of the plane containing the + /// normal. double GetDistance(const GfVec3d &p) const { return p * _normal - _distance; } - //! Return the projection of \p p onto the plane. + /// Return the projection of \p p onto the plane. GfVec3d Project(const GfVec3d& p) const { return p - GetDistance(p) * _normal; } - //! - // Transforms the plane by the given matrix. + /// Transforms the plane by the given matrix. + GF_API GfPlane & Transform(const GfMatrix4d &matrix); - //! Flip the plane normal (if necessary) so that \p p is in the - // positive halfspace. + /// Flip the plane normal (if necessary) so that \p p is in the positive + /// halfspace. void Reorient(const GfVec3d& p) { if (GetDistance(p) < 0) { _normal = -_normal; @@ -161,29 +146,28 @@ class GfPlane } } - //! - // Returns \c true if the given aligned bounding box is at least - // partially on the positive side (the one the normal points into) - // of the plane. + /// Returns \c true if the given aligned bounding box is at least + /// partially on the positive side (the one the normal points into) of the + /// plane. + GF_API bool IntersectsPositiveHalfSpace(const GfRange3d &box) const; - //! - // Returns true if the given point is on the plane or within its - // positive half space. + /// Returns true if the given point is on the plane or within its positive + /// half space. bool IntersectsPositiveHalfSpace(const GfVec3d &pt) const { return GetDistance(pt) >= 0.0; } private: - //! The normal to the plane. Points in direction of half-space. + /// The normal to the plane. Points in direction of half-space. GfVec3d _normal; - //! Distance from the plane to the origin. + /// Distance from the plane to the origin. double _distance; }; -/// Output a GfPlane using the format [(nx ny nz) distance] +/// Output a GfPlane using the format [(nx ny nz) distance]. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream&, const GfPlane&); +GF_API std::ostream& operator<<(std::ostream&, const GfPlane&); #endif // GF_PLANE_H diff --git a/pxr/base/lib/gf/pyBufferUtils.cpp b/pxr/base/lib/gf/pyBufferUtils.cpp index 1e8250cb62..c4ba872ca0 100644 --- a/pxr/base/lib/gf/pyBufferUtils.cpp +++ b/pxr/base/lib/gf/pyBufferUtils.cpp @@ -48,15 +48,15 @@ char *Gf_GetPyBufferFmtFor() { return str; } -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); -template char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); +template GF_API char *Gf_GetPyBufferFmtFor(); diff --git a/pxr/base/lib/gf/pyBufferUtils.h b/pxr/base/lib/gf/pyBufferUtils.h index a8df7f9da3..b620ceaa4c 100644 --- a/pxr/base/lib/gf/pyBufferUtils.h +++ b/pxr/base/lib/gf/pyBufferUtils.h @@ -24,12 +24,14 @@ #ifndef GF_PYBUFFER_UTILS_H #define GF_PYBUFFER_UTILS_H +#include "pxr/base/gf/api.h" + //////////////////////////////////////////////////////////////////////// // Format strings matching Python buffer proto / struct module scheme. // This function template is explicitly instantiated for T = // bool, [unsigned] (char, short, int, long), half, float, and double. template -char *Gf_GetPyBufferFmtFor(); +GF_API char *Gf_GetPyBufferFmtFor(); #endif // GF_PYBUFFER_UTILS_H diff --git a/pxr/base/lib/gf/quat.template.h b/pxr/base/lib/gf/quat.template.h index bf9f4d0c04..d0c31c51a4 100644 --- a/pxr/base/lib/gf/quat.template.h +++ b/pxr/base/lib/gf/quat.template.h @@ -28,6 +28,9 @@ #ifndef GF_{{ UPPER(QUAT)[2:] }}_H #define GF_{{ UPPER(QUAT)[2:] }}_H +/// \file gf/quat{{ SUFFIX }}.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/vec3{{ SUFFIX }}.h" #include "pxr/base/gf/traits.h" {% if SCL == 'half' -%} @@ -41,94 +44,75 @@ template <> struct GfIsGfQuat { static const bool value = true; }; -/*! - * \file quat{{ SUFFIX }}.h - * \ingroup group_gf_LinearAlgebra - */ - -//! -// \class {{ QUAT }} quat{{ SUFFIX }}.h "pxr/base/gf/quat{{ SUFFIX }}.h" -// \ingroup group_gf_LinearAlgebra -// \brief Basic type: a quaternion, a complex number with a real coefficient and -// three imaginary coefficients, stored as a 3-vector. -// +/// \class {{ QUAT }} +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type: a quaternion, a complex number with a real coefficient and +/// three imaginary coefficients, stored as a 3-vector. +/// class {{ QUAT }} { public: typedef {{ SCL }} ScalarType; typedef GfVec3{{ SUFFIX }} ImaginaryType; - //! - // Default constructor leaves the quaternion undefined. + /// Default constructor leaves the quaternion undefined. {{ QUAT }}() {} - //! - // Initialize the real coefficient to \p realVal and the imaginary - // coefficients to zero. - // - // Since quaternions typically must be normalized, reasonable values for - // \p realVal are -1, 0, or 1. Other values are legal but are likely to be - // meaningless. - // + /// Initialize the real coefficient to \p realVal and the imaginary + /// coefficients to zero. + /// + /// Since quaternions typically must be normalized, reasonable values for + /// \p realVal are -1, 0, or 1. Other values are legal but are likely to + /// be meaningless. + /// explicit {{ QUAT }} ({{ SCL }} realVal) : _imaginary(0), _real(realVal) {} - //! - // Initialize the real and imaginary coefficients. + /// Initialize the real and imaginary coefficients. {{ QUAT }}({{ SCL }} real, {{ SCL }} i, {{ SCL }} j, {{ SCL }} k) : _imaginary(i, j, k), _real(real) { } - //! - // Initialize the real and imaginary coefficients. + /// Initialize the real and imaginary coefficients. {{ QUAT }}({{ SCL }} real, const GfVec3{{ SUFFIX }} &imaginary) : _imaginary(imaginary), _real(real) { } {% for S in SCALARS if S != SCL %} - //! - // {{ "Implicitly convert" if ALLOW_IMPLICIT_CONVERSION(S, SCL) else "Construct" }} from {{ QUATNAME(S) }}. + /// {{ "Implicitly convert" if ALLOW_IMPLICIT_CONVERSION(S, SCL) else "Construct" }} from {{ QUATNAME(S) }}. {{ '' if ALLOW_IMPLICIT_CONVERSION(S, SCL) else 'explicit ' }}{{ QUAT }}(class {{ QUATNAME(S) }} const &other); {% endfor %} - //! - // Return the identity quaternion, with real coefficient 1 and an imaginary - // coefficients all zero. + /// Return the identity quaternion, with real coefficient 1 and an + /// imaginary coefficients all zero. static {{ QUAT }} GetIdentity() { return {{ QUAT }}(1.0); } - //! - // Return the real coefficient. + /// Return the real coefficient. {{ SCL }} GetReal() const { return _real; } - //! - // Set the real coefficient. + /// Set the real coefficient. void SetReal({{ SCL }} real) { _real = real; } - //! - // Return the imaginary coefficient. + /// Return the imaginary coefficient. const GfVec3{{ SUFFIX }} &GetImaginary() const { return _imaginary; } - //! - // Set the imaginary coefficients. + /// Set the imaginary coefficients. void SetImaginary(const GfVec3{{ SUFFIX }} &imaginary) { _imaginary = imaginary; } - //! - // Set the imaginary coefficients. + /// Set the imaginary coefficients. void SetImaginary({{ SCL }} i, {{ SCL }} j, {{ SCL }} k) { _imaginary.Set(i, j, k); } - //! - // Return geometric length of this quaternion. + /// Return geometric length of this quaternion. {{ SCL }} GetLength() const { return GfSqrt(_GetLengthSquared()); } - //! - // Return a normalized (unit-length) version of this quaternion. If the - // length of this quaternion is smaller than \p eps, return the identity - // quaternion. + /// length of this quaternion is smaller than \p eps, return the identity + /// quaternion. {{ QUAT }} GetNormalized({{ SCL }} eps = GF_MIN_VECTOR_LENGTH) const { {{ QUAT }} ret(*this); @@ -136,153 +120,133 @@ class {{ QUAT }} return ret; } - //! - // Normalizes this quaternion in place to unit length, returning - // the length before normalization. If the length of this - // quaternion is smaller than \p eps, this sets the quaternion to - // identity. + /// Normalizes this quaternion in place to unit length, returning the + /// length before normalization. If the length of this quaternion is + /// smaller than \p eps, this sets the quaternion to identity. {{ SCL }} Normalize({{ SCL }} eps = GF_MIN_VECTOR_LENGTH); - //! - // Return this quaternion's conjugate, which is the quaternion with the same - // real coefficient and negated imaginary coefficients. + /// Return this quaternion's conjugate, which is the quaternion with the + /// same real coefficient and negated imaginary coefficients. {{ QUAT }} GetConjugate() const { return {{ QUAT }}(GetReal(), -GetImaginary()); } - //! - // Return this quaternion's inverse, or reciprocal. This is the - // quaternion's conjugate divided by it's squared length. + /// Return this quaternion's inverse, or reciprocal. This is the + /// quaternion's conjugate divided by it's squared length. {{ QUAT }} GetInverse() const { return GetConjugate() / _GetLengthSquared(); } - //! - // Hash. + /// Hash. friend inline size_t hash_value(const {{ QUAT }} &q) { size_t h = hash_value(q.GetReal()); boost::hash_combine(h, q.GetImaginary()); return h; } - //! - // Component-wise negation. + /// Component-wise negation. {{ QUAT }} operator-() const { return {{ QUAT }}(-GetReal(), -GetImaginary()); } - //! - // Component-wise quaternion equality test. The real and imaginary parts - // must match exactly for quaternions to be considered equal. + /// Component-wise quaternion equality test. The real and imaginary parts + /// must match exactly for quaternions to be considered equal. bool operator==(const {{ QUAT }} &q) const { - return (GetReal() == q.GetReal() && + return (GetReal() == q.GetReal() && GetImaginary() == q.GetImaginary()); } - //! - // Component-wise quaternion inequality test. The real and imaginary parts - // must match exactly for quaternions to be considered equal. + /// Component-wise quaternion inequality test. The real and imaginary + /// parts must match exactly for quaternions to be considered equal. bool operator!=(const {{ QUAT }} &q) const { return !(*this == q); } - //! - // Post-multiply quaternion \p q into this quaternion. + /// Post-multiply quaternion \p q into this quaternion. {{ QUAT }} &operator *=(const {{ QUAT }} &q); - //! - // Multiply this quaternion's coefficients by \p s . + /// Multiply this quaternion's coefficients by \p s. {{ QUAT }} &operator *=({{ SCL }} s) { _real *= s; _imaginary *= s; return *this; } - //! - // Divide this quaternion's coefficients by \p s . + /// Divide this quaternion's coefficients by \p s. {{ QUAT }} &operator /=({{ SCL }} s) { _real /= s; _imaginary /= s; return *this; } - //! - // Add quaternion \p q to this quaternion. + /// Add quaternion \p q to this quaternion. {{ QUAT }} &operator +=(const {{ QUAT }} &q) { _real += q._real; _imaginary += q._imaginary; return *this; } - //! - // Component-wise unary difference operator + /// Component-wise unary difference operator. {{ QUAT }} &operator -=(const {{ QUAT }} &q) { _real -= q._real; _imaginary -= q._imaginary; return *this; } - //! - // Component-wise binary sum operator + /// Component-wise binary sum operator. friend {{ QUAT }} operator +(const {{ QUAT }} &q1, const {{ QUAT }} &q2) { - return {{ QUAT }}(q1) += q2; + return {{ QUAT }}(q1) += q2; } - //! - // Component-wise binary difference operator + /// Component-wise binary difference operator. friend {{ QUAT }} operator -(const {{ QUAT }} &q1, const {{ QUAT }} &q2) { - return {{ QUAT }}(q1) -= q2; + return {{ QUAT }}(q1) -= q2; } - //! - // Returns the product of quaternions \p q1 and \p q2 . + /// Returns the product of quaternions \p q1 and \p q2. friend {{ QUAT }} operator *(const {{ QUAT }} &q1, const {{ QUAT }} &q2) { - return {{ QUAT }}(q1) *= q2; + return {{ QUAT }}(q1) *= q2; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend {{ QUAT }} operator *(const {{ QUAT }} &q, {{ SCL }} s) { - return {{ QUAT }}(q) *= s; + return {{ QUAT }}(q) *= s; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend {{ QUAT }} operator *({{ SCL }} s, const {{ QUAT }} &q) { - return {{ QUAT }}(q) *= s; + return {{ QUAT }}(q) *= s; } - //! - // Returns the product of quaternion \p q and scalar 1 / \p s . + /// Returns the product of quaternion \p q and scalar 1 / \p s. friend {{ QUAT }} operator /(const {{ QUAT }} &q, {{ SCL }} s) { - return {{ QUAT }}(q) /= s; + return {{ QUAT }}(q) /= s; } private: - //! Imaginary part + /// Imaginary part GfVec3{{ SUFFIX }} _imaginary; - //! Real part + /// Real part {{ SCL }} _real; - //! Returns the square of the length + /// Returns the square of the length {{ SCL }} _GetLengthSquared() const { return _real * _real + GfDot(_imaginary, _imaginary); } }; -//! -// Spherically linearly interpolate between \p q0 and \p q1. -// -// If the interpolant \p alpha is zero, then the result is \p q0, while -// \p alpha of one yields \p q1. +/// Spherically linearly interpolate between \p q0 and \p q1. +/// +/// If the interpolant \p alpha is zero, then the result is \p q0, while +/// \p alpha of one yields \p q1. {{ QUAT }} GfSlerp(double alpha, const {{ QUAT }}& q0, const {{ QUAT }}& q1); @@ -293,4 +257,4 @@ GfSlerp(const {{ QUAT }}& q0, const {{ QUAT }}& q1, double alpha); /// \ingroup group_gf_DebuggingOutput std::ostream& operator<<(std::ostream &, {{ QUAT }} const &); -#endif // GF_QUATERNION_H +#endif // GF_{{ UPPER(QUAT)[2:] }}_H diff --git a/pxr/base/lib/gf/quatd.h b/pxr/base/lib/gf/quatd.h index e3bc51a1cc..e451358c08 100644 --- a/pxr/base/lib/gf/quatd.h +++ b/pxr/base/lib/gf/quatd.h @@ -28,8 +28,12 @@ #ifndef GF_QUATD_H #define GF_QUATD_H +/// \file gf/quatd.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -38,95 +42,77 @@ template <> struct GfIsGfQuat { static const bool value = true; }; -/*! - * \file quatd.h - * \ingroup group_gf_LinearAlgebra - */ - -//! -// \class GfQuatd quatd.h "pxr/base/gf/quatd.h" -// \ingroup group_gf_LinearAlgebra -// \brief Basic type: a quaternion, a complex number with a real coefficient and -// three imaginary coefficients, stored as a 3-vector. -// +/// \class GfQuatd +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type: a quaternion, a complex number with a real coefficient and +/// three imaginary coefficients, stored as a 3-vector. +/// class GfQuatd { public: typedef double ScalarType; typedef GfVec3d ImaginaryType; - //! - // Default constructor leaves the quaternion undefined. + /// Default constructor leaves the quaternion undefined. GfQuatd() {} - //! - // Initialize the real coefficient to \p realVal and the imaginary - // coefficients to zero. - // - // Since quaternions typically must be normalized, reasonable values for - // \p realVal are -1, 0, or 1. Other values are legal but are likely to be - // meaningless. - // + /// Initialize the real coefficient to \p realVal and the imaginary + /// coefficients to zero. + /// + /// Since quaternions typically must be normalized, reasonable values for + /// \p realVal are -1, 0, or 1. Other values are legal but are likely to + /// be meaningless. + /// explicit GfQuatd (double realVal) : _imaginary(0), _real(realVal) {} - //! - // Initialize the real and imaginary coefficients. + /// Initialize the real and imaginary coefficients. GfQuatd(double real, double i, double j, double k) : _imaginary(i, j, k), _real(real) { } - //! - // Initialize the real and imaginary coefficients. + /// Initialize the real and imaginary coefficients. GfQuatd(double real, const GfVec3d &imaginary) : _imaginary(imaginary), _real(real) { } - //! - // Implicitly convert from GfQuatf. + /// Implicitly convert from GfQuatf. + GF_API GfQuatd(class GfQuatf const &other); - //! - // Implicitly convert from GfQuath. + /// Implicitly convert from GfQuath. + GF_API GfQuatd(class GfQuath const &other); - //! - // Return the identity quaternion, with real coefficient 1 and an imaginary - // coefficients all zero. + /// Return the identity quaternion, with real coefficient 1 and an + /// imaginary coefficients all zero. static GfQuatd GetIdentity() { return GfQuatd(1.0); } - //! - // Return the real coefficient. + /// Return the real coefficient. double GetReal() const { return _real; } - //! - // Set the real coefficient. + /// Set the real coefficient. void SetReal(double real) { _real = real; } - //! - // Return the imaginary coefficient. + /// Return the imaginary coefficient. const GfVec3d &GetImaginary() const { return _imaginary; } - //! - // Set the imaginary coefficients. + /// Set the imaginary coefficients. void SetImaginary(const GfVec3d &imaginary) { _imaginary = imaginary; } - //! - // Set the imaginary coefficients. + /// Set the imaginary coefficients. void SetImaginary(double i, double j, double k) { _imaginary.Set(i, j, k); } - //! - // Return geometric length of this quaternion. + /// Return geometric length of this quaternion. double GetLength() const { return GfSqrt(_GetLengthSquared()); } - //! - // Return a normalized (unit-length) version of this quaternion. If the - // length of this quaternion is smaller than \p eps, return the identity - // quaternion. + /// length of this quaternion is smaller than \p eps, return the identity + /// quaternion. GfQuatd GetNormalized(double eps = GF_MIN_VECTOR_LENGTH) const { GfQuatd ret(*this); @@ -134,161 +120,143 @@ class GfQuatd return ret; } - //! - // Normalizes this quaternion in place to unit length, returning - // the length before normalization. If the length of this - // quaternion is smaller than \p eps, this sets the quaternion to - // identity. + /// Normalizes this quaternion in place to unit length, returning the + /// length before normalization. If the length of this quaternion is + /// smaller than \p eps, this sets the quaternion to identity. + GF_API double Normalize(double eps = GF_MIN_VECTOR_LENGTH); - //! - // Return this quaternion's conjugate, which is the quaternion with the same - // real coefficient and negated imaginary coefficients. + /// Return this quaternion's conjugate, which is the quaternion with the + /// same real coefficient and negated imaginary coefficients. GfQuatd GetConjugate() const { return GfQuatd(GetReal(), -GetImaginary()); } - //! - // Return this quaternion's inverse, or reciprocal. This is the - // quaternion's conjugate divided by it's squared length. + /// Return this quaternion's inverse, or reciprocal. This is the + /// quaternion's conjugate divided by it's squared length. GfQuatd GetInverse() const { return GetConjugate() / _GetLengthSquared(); } - //! - // Hash. + /// Hash. friend inline size_t hash_value(const GfQuatd &q) { size_t h = hash_value(q.GetReal()); boost::hash_combine(h, q.GetImaginary()); return h; } - //! - // Component-wise negation. + /// Component-wise negation. GfQuatd operator-() const { return GfQuatd(-GetReal(), -GetImaginary()); } - //! - // Component-wise quaternion equality test. The real and imaginary parts - // must match exactly for quaternions to be considered equal. + /// Component-wise quaternion equality test. The real and imaginary parts + /// must match exactly for quaternions to be considered equal. bool operator==(const GfQuatd &q) const { - return (GetReal() == q.GetReal() && + return (GetReal() == q.GetReal() && GetImaginary() == q.GetImaginary()); } - //! - // Component-wise quaternion inequality test. The real and imaginary parts - // must match exactly for quaternions to be considered equal. + /// Component-wise quaternion inequality test. The real and imaginary + /// parts must match exactly for quaternions to be considered equal. bool operator!=(const GfQuatd &q) const { return !(*this == q); } - //! - // Post-multiply quaternion \p q into this quaternion. + /// Post-multiply quaternion \p q into this quaternion. + GF_API GfQuatd &operator *=(const GfQuatd &q); - //! - // Multiply this quaternion's coefficients by \p s . + /// Multiply this quaternion's coefficients by \p s. GfQuatd &operator *=(double s) { _real *= s; _imaginary *= s; return *this; } - //! - // Divide this quaternion's coefficients by \p s . + /// Divide this quaternion's coefficients by \p s. GfQuatd &operator /=(double s) { _real /= s; _imaginary /= s; return *this; } - //! - // Add quaternion \p q to this quaternion. + /// Add quaternion \p q to this quaternion. GfQuatd &operator +=(const GfQuatd &q) { _real += q._real; _imaginary += q._imaginary; return *this; } - //! - // Component-wise unary difference operator + /// Component-wise unary difference operator. GfQuatd &operator -=(const GfQuatd &q) { _real -= q._real; _imaginary -= q._imaginary; return *this; } - //! - // Component-wise binary sum operator + /// Component-wise binary sum operator. friend GfQuatd operator +(const GfQuatd &q1, const GfQuatd &q2) { - return GfQuatd(q1) += q2; + return GfQuatd(q1) += q2; } - //! - // Component-wise binary difference operator + /// Component-wise binary difference operator. friend GfQuatd operator -(const GfQuatd &q1, const GfQuatd &q2) { - return GfQuatd(q1) -= q2; + return GfQuatd(q1) -= q2; } - //! - // Returns the product of quaternions \p q1 and \p q2 . + /// Returns the product of quaternions \p q1 and \p q2. friend GfQuatd operator *(const GfQuatd &q1, const GfQuatd &q2) { - return GfQuatd(q1) *= q2; + return GfQuatd(q1) *= q2; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend GfQuatd operator *(const GfQuatd &q, double s) { - return GfQuatd(q) *= s; + return GfQuatd(q) *= s; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend GfQuatd operator *(double s, const GfQuatd &q) { - return GfQuatd(q) *= s; + return GfQuatd(q) *= s; } - //! - // Returns the product of quaternion \p q and scalar 1 / \p s . + /// Returns the product of quaternion \p q and scalar 1 / \p s. friend GfQuatd operator /(const GfQuatd &q, double s) { - return GfQuatd(q) /= s; + return GfQuatd(q) /= s; } private: - //! Imaginary part + /// Imaginary part GfVec3d _imaginary; - //! Real part + /// Real part double _real; - //! Returns the square of the length + /// Returns the square of the length double _GetLengthSquared() const { return _real * _real + GfDot(_imaginary, _imaginary); } }; -//! -// Spherically linearly interpolate between \p q0 and \p q1. -// -// If the interpolant \p alpha is zero, then the result is \p q0, while -// \p alpha of one yields \p q1. -GfQuatd +/// Spherically linearly interpolate between \p q0 and \p q1. +/// +/// If the interpolant \p alpha is zero, then the result is \p q0, while +/// \p alpha of one yields \p q1. +GF_API GfQuatd GfSlerp(double alpha, const GfQuatd& q0, const GfQuatd& q1); -GfQuatd +GF_API GfQuatd GfSlerp(const GfQuatd& q0, const GfQuatd& q1, double alpha); /// Output a GfQuatd using the format (re, i, j, k) /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfQuatd const &); +GF_API std::ostream& operator<<(std::ostream &, GfQuatd const &); -#endif // GF_QUATERNION_H +#endif // GF_QUATD_H diff --git a/pxr/base/lib/gf/quaternion.h b/pxr/base/lib/gf/quaternion.h index 47fdc602d7..8136817bee 100644 --- a/pxr/base/lib/gf/quaternion.h +++ b/pxr/base/lib/gf/quaternion.h @@ -24,111 +24,97 @@ #ifndef GF_QUATERNION_H #define GF_QUATERNION_H +/// \file gf/quaternion.h +/// \ingroup group_gf_LinearAlgebra #include "pxr/base/gf/vec3d.h" +#include "pxr/base/gf/api.h" #include #include -/*! - * \file quaternion.h - * \ingroup group_gf_LinearAlgebra - */ - -//! -// \class GfQuaternion quaternion.h "pxr/base/gf/quaternion.h" -// \ingroup group_gf_LinearAlgebra -// \brief Basic type: complex number with scalar real part and vector -// imaginary part. -// -// This class represents a generalized complex number that has a -// scalar real part and a vector of three imaginary values. -// Quaternions are used by the \c GfRotation class to represent -// arbitrary-axis rotations. -// - +/// \class GfQuaternion +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type: complex number with scalar real part and vector imaginary +/// part. +/// +/// This class represents a generalized complex number that has a scalar real +/// part and a vector of three imaginary values. Quaternions are used by the +/// \c GfRotation class to represent arbitrary-axis rotations. +/// class GfQuaternion { public: - //! - // The default constructor leaves the quaternion undefined. + /// The default constructor leaves the quaternion undefined. GfQuaternion() { } - //! - // This constructor initializes the real part to the argument and - // the imaginary parts to zero. - // - // Since quaternions typically need to be normalized, the only reasonable - // values for \p realVal are -1, 0, or 1. Other values are legal but are - // likely to be meaningless. - // + /// This constructor initializes the real part to the argument and + /// the imaginary parts to zero. + /// + /// Since quaternions typically need to be normalized, the only reasonable + /// values for \p realVal are -1, 0, or 1. Other values are legal but are + /// likely to be meaningless. explicit GfQuaternion(int realVal) : _real(realVal), _imaginary(0) { } - //! - // This constructor initializes the real and imaginary parts. + /// This constructor initializes the real and imaginary parts. GfQuaternion(double real, const GfVec3d &imaginary) : _real(real), _imaginary(imaginary) { } - //! - // Sets the real part of the quaternion. + /// Sets the real part of the quaternion. void SetReal(double real) { _real = real; } - //! - // Sets the imaginary part of the quaternion. + /// Sets the imaginary part of the quaternion. void SetImaginary(const GfVec3d &imaginary) { _imaginary = imaginary; } - //! - // Returns the real part of the quaternion. + /// Returns the real part of the quaternion. double GetReal() const { return _real; } - //! - // Returns the imaginary part of the quaternion. + /// Returns the imaginary part of the quaternion. const GfVec3d & GetImaginary() const { return _imaginary; } - //! - // Returns the identity quaternion, which has a real part of 1 and - // an imaginary part of (0,0,0). + /// Returns the identity quaternion, which has a real part of 1 and + /// an imaginary part of (0,0,0). static GfQuaternion GetIdentity() { return GfQuaternion(1.0, GfVec3d(0.0, 0.0, 0.0)); } - //! - // Returns geometric length of this quaternion. + /// Returns geometric length of this quaternion. + GF_API double GetLength() const; - //! - // Returns a normalized (unit-length) version of this quaternion. - // direction as this. If the length of this quaternion is smaller - // than \p eps, this returns the identity quaternion. + /// Returns a normalized (unit-length) version of this quaternion. + /// direction as this. If the length of this quaternion is smaller than \p + /// eps, this returns the identity quaternion. + GF_API GfQuaternion GetNormalized(double eps = GF_MIN_VECTOR_LENGTH) const; - //! - // Normalizes this quaternion in place to unit length, returning - // the length before normalization. If the length of this - // quaternion is smaller than \p eps, this sets the quaternion to - // identity. + /// Normalizes this quaternion in place to unit length, returning the + /// length before normalization. If the length of this quaternion is + /// smaller than \p eps, this sets the quaternion to identity. + GF_API double Normalize(double eps = GF_MIN_VECTOR_LENGTH); - //! - // Returns the inverse of this quaternion. + /// Returns the inverse of this quaternion. + GF_API GfQuaternion GetInverse() const; - //! Hash. + /// Hash. friend inline size_t hash_value(const GfQuaternion &q) { size_t h = 0; boost::hash_combine(h, q.GetReal()); @@ -136,130 +122,118 @@ class GfQuaternion return h; } - //! - // Component-wise quaternion equality test. The real and imaginary - // parts must match exactly for quaternions to be considered - // equal. + /// Component-wise quaternion equality test. The real and imaginary parts + /// must match exactly for quaternions to be considered equal. bool operator ==(const GfQuaternion &q) const { return (GetReal() == q.GetReal() && GetImaginary() == q.GetImaginary()); } - //! - // Component-wise quaternion inequality test. The real and - // imaginary parts must match exactly for quaternions to be - // considered equal. + /// Component-wise quaternion inequality test. The real and imaginary + /// parts must match exactly for quaternions to be considered equal. bool operator !=(const GfQuaternion &q) const { - return ! (*this == q); + return ! (*this == q); } - //! - // Post-multiplies quaternion \p q into this quaternion. + /// Post-multiplies quaternion \p q into this quaternion. + GF_API GfQuaternion & operator *=(const GfQuaternion &q); - //! - // Scales this quaternion by \p s . + /// Scales this quaternion by \p s. + GF_API GfQuaternion & operator *=(double s); - //! - // Scales this quaternion by 1 / \p s . + /// Scales this quaternion by 1 / \p s. GfQuaternion & operator /=(double s) { return (*this) *= 1.0 / s; } - //! - // Component-wise unary sum operator + /// Component-wise unary sum operator. GfQuaternion & operator +=(const GfQuaternion &q) { _real += q._real; _imaginary += q._imaginary; return *this; } - //! - // Component-wise unary difference operator + /// Component-wise unary difference operator. GfQuaternion & operator -=(const GfQuaternion &q) { _real -= q._real; _imaginary -= q._imaginary; return *this; } - //! - // Component-wise binary sum operator + /// Component-wise binary sum operator. friend GfQuaternion operator +(const GfQuaternion &q1, - const GfQuaternion &q2) { - GfQuaternion qt = q1; - return qt += q2; + const GfQuaternion &q2) { + GfQuaternion qt = q1; + return qt += q2; } - //! - // Component-wise binary difference operator + /// Component-wise binary difference operator. friend GfQuaternion operator -(const GfQuaternion &q1, - const GfQuaternion &q2) { - GfQuaternion qt = q1; - return qt -= q2; + const GfQuaternion &q2) { + GfQuaternion qt = q1; + return qt -= q2; } - //! - // Returns the product of quaternions \p q1 and \p q2 . + /// Returns the product of quaternions \p q1 and \p q2. friend GfQuaternion operator *(const GfQuaternion &q1, - const GfQuaternion &q2) { - GfQuaternion qt = q1; - return qt *= q2; + const GfQuaternion &q2) { + GfQuaternion qt = q1; + return qt *= q2; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend GfQuaternion operator *(const GfQuaternion &q, double s) { - GfQuaternion qt = q; - return qt *= s; + GfQuaternion qt = q; + return qt *= s; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend GfQuaternion operator *(double s, const GfQuaternion &q) { - GfQuaternion qt = q; - return qt *= s; + GfQuaternion qt = q; + return qt *= s; } - //! - // Returns the product of quaternion \p q and scalar 1 / \p s . + /// Returns the product of quaternion \p q and scalar 1 / \p s. friend GfQuaternion operator /(const GfQuaternion &q, double s) { - GfQuaternion qt = q; - return qt /= s; + GfQuaternion qt = q; + return qt /= s; } - //! - // Spherically interpolate between \p q0 and \p q1. - // - // If the interpolant \p alpha - // is zero, then the result is \p q0, while \p alpha of one yields - // \p q1. - friend GfQuaternion GfSlerp(double alpha, const GfQuaternion& q0, const GfQuaternion& q1); + /// Spherically interpolate between \p q0 and \p q1. + /// + /// If the interpolant \p alpha + /// is zero, then the result is \p q0, while \p alpha of one yields + /// \p q1. + GF_API + friend GfQuaternion GfSlerp(double alpha, + const GfQuaternion& q0, + const GfQuaternion& q1); - // Remove this rather ridiculous alias/overload for 2x conformance - friend GfQuaternion GfSlerp(const GfQuaternion& q0, const GfQuaternion& q1, - double alpha); + // TODO Remove this legacy alias/overload. + friend GF_API GfQuaternion GfSlerp(const GfQuaternion& q0, + const GfQuaternion& q1, + double alpha); - private: - //! Real part + /// Real part double _real; - //! Imaginary part + /// Imaginary part GfVec3d _imaginary; - //! Returns the square of the length + /// Returns the square of the length double _GetLengthSquared() const { return (_real * _real + GfDot(_imaginary, _imaginary)); } }; // Friend functions must be declared. -GfQuaternion GfSlerp(double alpha, const GfQuaternion& q0, const GfQuaternion& q1); -GfQuaternion GfSlerp(const GfQuaternion& q0, const GfQuaternion& q1, double alpha); +GF_API GfQuaternion GfSlerp(double alpha, const GfQuaternion& q0, const GfQuaternion& q1); +GF_API GfQuaternion GfSlerp(const GfQuaternion& q0, const GfQuaternion& q1, double alpha); /// Output a GfQuaternion using the format (r + (x, y, z)). /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream& out, const GfQuaternion& q); - +GF_API std::ostream& operator<<(std::ostream& out, const GfQuaternion& q); #endif // GF_QUATERNION_H diff --git a/pxr/base/lib/gf/quatf.h b/pxr/base/lib/gf/quatf.h index fcdf86feac..53865f8cbc 100644 --- a/pxr/base/lib/gf/quatf.h +++ b/pxr/base/lib/gf/quatf.h @@ -28,8 +28,12 @@ #ifndef GF_QUATF_H #define GF_QUATF_H +/// \file gf/quatf.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -38,95 +42,77 @@ template <> struct GfIsGfQuat { static const bool value = true; }; -/*! - * \file quatf.h - * \ingroup group_gf_LinearAlgebra - */ - -//! -// \class GfQuatf quatf.h "pxr/base/gf/quatf.h" -// \ingroup group_gf_LinearAlgebra -// \brief Basic type: a quaternion, a complex number with a real coefficient and -// three imaginary coefficients, stored as a 3-vector. -// +/// \class GfQuatf +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type: a quaternion, a complex number with a real coefficient and +/// three imaginary coefficients, stored as a 3-vector. +/// class GfQuatf { public: typedef float ScalarType; typedef GfVec3f ImaginaryType; - //! - // Default constructor leaves the quaternion undefined. + /// Default constructor leaves the quaternion undefined. GfQuatf() {} - //! - // Initialize the real coefficient to \p realVal and the imaginary - // coefficients to zero. - // - // Since quaternions typically must be normalized, reasonable values for - // \p realVal are -1, 0, or 1. Other values are legal but are likely to be - // meaningless. - // + /// Initialize the real coefficient to \p realVal and the imaginary + /// coefficients to zero. + /// + /// Since quaternions typically must be normalized, reasonable values for + /// \p realVal are -1, 0, or 1. Other values are legal but are likely to + /// be meaningless. + /// explicit GfQuatf (float realVal) : _imaginary(0), _real(realVal) {} - //! - // Initialize the real and imaginary coefficients. + /// Initialize the real and imaginary coefficients. GfQuatf(float real, float i, float j, float k) : _imaginary(i, j, k), _real(real) { } - //! - // Initialize the real and imaginary coefficients. + /// Initialize the real and imaginary coefficients. GfQuatf(float real, const GfVec3f &imaginary) : _imaginary(imaginary), _real(real) { } - //! - // Construct from GfQuatd. + /// Construct from GfQuatd. + GF_API explicit GfQuatf(class GfQuatd const &other); - //! - // Implicitly convert from GfQuath. + /// Implicitly convert from GfQuath. + GF_API GfQuatf(class GfQuath const &other); - //! - // Return the identity quaternion, with real coefficient 1 and an imaginary - // coefficients all zero. + /// Return the identity quaternion, with real coefficient 1 and an + /// imaginary coefficients all zero. static GfQuatf GetIdentity() { return GfQuatf(1.0); } - //! - // Return the real coefficient. + /// Return the real coefficient. float GetReal() const { return _real; } - //! - // Set the real coefficient. + /// Set the real coefficient. void SetReal(float real) { _real = real; } - //! - // Return the imaginary coefficient. + /// Return the imaginary coefficient. const GfVec3f &GetImaginary() const { return _imaginary; } - //! - // Set the imaginary coefficients. + /// Set the imaginary coefficients. void SetImaginary(const GfVec3f &imaginary) { _imaginary = imaginary; } - //! - // Set the imaginary coefficients. + /// Set the imaginary coefficients. void SetImaginary(float i, float j, float k) { _imaginary.Set(i, j, k); } - //! - // Return geometric length of this quaternion. + /// Return geometric length of this quaternion. float GetLength() const { return GfSqrt(_GetLengthSquared()); } - //! - // Return a normalized (unit-length) version of this quaternion. If the - // length of this quaternion is smaller than \p eps, return the identity - // quaternion. + /// length of this quaternion is smaller than \p eps, return the identity + /// quaternion. GfQuatf GetNormalized(float eps = GF_MIN_VECTOR_LENGTH) const { GfQuatf ret(*this); @@ -134,161 +120,143 @@ class GfQuatf return ret; } - //! - // Normalizes this quaternion in place to unit length, returning - // the length before normalization. If the length of this - // quaternion is smaller than \p eps, this sets the quaternion to - // identity. + /// Normalizes this quaternion in place to unit length, returning the + /// length before normalization. If the length of this quaternion is + /// smaller than \p eps, this sets the quaternion to identity. + GF_API float Normalize(float eps = GF_MIN_VECTOR_LENGTH); - //! - // Return this quaternion's conjugate, which is the quaternion with the same - // real coefficient and negated imaginary coefficients. + /// Return this quaternion's conjugate, which is the quaternion with the + /// same real coefficient and negated imaginary coefficients. GfQuatf GetConjugate() const { return GfQuatf(GetReal(), -GetImaginary()); } - //! - // Return this quaternion's inverse, or reciprocal. This is the - // quaternion's conjugate divided by it's squared length. + /// Return this quaternion's inverse, or reciprocal. This is the + /// quaternion's conjugate divided by it's squared length. GfQuatf GetInverse() const { return GetConjugate() / _GetLengthSquared(); } - //! - // Hash. + /// Hash. friend inline size_t hash_value(const GfQuatf &q) { size_t h = hash_value(q.GetReal()); boost::hash_combine(h, q.GetImaginary()); return h; } - //! - // Component-wise negation. + /// Component-wise negation. GfQuatf operator-() const { return GfQuatf(-GetReal(), -GetImaginary()); } - //! - // Component-wise quaternion equality test. The real and imaginary parts - // must match exactly for quaternions to be considered equal. + /// Component-wise quaternion equality test. The real and imaginary parts + /// must match exactly for quaternions to be considered equal. bool operator==(const GfQuatf &q) const { - return (GetReal() == q.GetReal() && + return (GetReal() == q.GetReal() && GetImaginary() == q.GetImaginary()); } - //! - // Component-wise quaternion inequality test. The real and imaginary parts - // must match exactly for quaternions to be considered equal. + /// Component-wise quaternion inequality test. The real and imaginary + /// parts must match exactly for quaternions to be considered equal. bool operator!=(const GfQuatf &q) const { return !(*this == q); } - //! - // Post-multiply quaternion \p q into this quaternion. + /// Post-multiply quaternion \p q into this quaternion. + GF_API GfQuatf &operator *=(const GfQuatf &q); - //! - // Multiply this quaternion's coefficients by \p s . + /// Multiply this quaternion's coefficients by \p s. GfQuatf &operator *=(float s) { _real *= s; _imaginary *= s; return *this; } - //! - // Divide this quaternion's coefficients by \p s . + /// Divide this quaternion's coefficients by \p s. GfQuatf &operator /=(float s) { _real /= s; _imaginary /= s; return *this; } - //! - // Add quaternion \p q to this quaternion. + /// Add quaternion \p q to this quaternion. GfQuatf &operator +=(const GfQuatf &q) { _real += q._real; _imaginary += q._imaginary; return *this; } - //! - // Component-wise unary difference operator + /// Component-wise unary difference operator. GfQuatf &operator -=(const GfQuatf &q) { _real -= q._real; _imaginary -= q._imaginary; return *this; } - //! - // Component-wise binary sum operator + /// Component-wise binary sum operator. friend GfQuatf operator +(const GfQuatf &q1, const GfQuatf &q2) { - return GfQuatf(q1) += q2; + return GfQuatf(q1) += q2; } - //! - // Component-wise binary difference operator + /// Component-wise binary difference operator. friend GfQuatf operator -(const GfQuatf &q1, const GfQuatf &q2) { - return GfQuatf(q1) -= q2; + return GfQuatf(q1) -= q2; } - //! - // Returns the product of quaternions \p q1 and \p q2 . + /// Returns the product of quaternions \p q1 and \p q2. friend GfQuatf operator *(const GfQuatf &q1, const GfQuatf &q2) { - return GfQuatf(q1) *= q2; + return GfQuatf(q1) *= q2; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend GfQuatf operator *(const GfQuatf &q, float s) { - return GfQuatf(q) *= s; + return GfQuatf(q) *= s; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend GfQuatf operator *(float s, const GfQuatf &q) { - return GfQuatf(q) *= s; + return GfQuatf(q) *= s; } - //! - // Returns the product of quaternion \p q and scalar 1 / \p s . + /// Returns the product of quaternion \p q and scalar 1 / \p s. friend GfQuatf operator /(const GfQuatf &q, float s) { - return GfQuatf(q) /= s; + return GfQuatf(q) /= s; } private: - //! Imaginary part + /// Imaginary part GfVec3f _imaginary; - //! Real part + /// Real part float _real; - //! Returns the square of the length + /// Returns the square of the length float _GetLengthSquared() const { return _real * _real + GfDot(_imaginary, _imaginary); } }; -//! -// Spherically linearly interpolate between \p q0 and \p q1. -// -// If the interpolant \p alpha is zero, then the result is \p q0, while -// \p alpha of one yields \p q1. -GfQuatf +/// Spherically linearly interpolate between \p q0 and \p q1. +/// +/// If the interpolant \p alpha is zero, then the result is \p q0, while +/// \p alpha of one yields \p q1. +GF_API GfQuatf GfSlerp(double alpha, const GfQuatf& q0, const GfQuatf& q1); -GfQuatf +GF_API GfQuatf GfSlerp(const GfQuatf& q0, const GfQuatf& q1, double alpha); /// Output a GfQuatd using the format (re, i, j, k) /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfQuatf const &); +GF_API std::ostream& operator<<(std::ostream &, GfQuatf const &); -#endif // GF_QUATERNION_H +#endif // GF_QUATF_H diff --git a/pxr/base/lib/gf/quath.h b/pxr/base/lib/gf/quath.h index a9afaccf25..cd13412077 100644 --- a/pxr/base/lib/gf/quath.h +++ b/pxr/base/lib/gf/quath.h @@ -28,9 +28,13 @@ #ifndef GF_QUATH_H #define GF_QUATH_H +/// \file gf/quath.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/vec3h.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/half.h" +#include "pxr/base/gf/api.h" #include @@ -39,95 +43,75 @@ template <> struct GfIsGfQuat { static const bool value = true; }; -/*! - * \file quath.h - * \ingroup group_gf_LinearAlgebra - */ - -//! -// \class GfQuath quath.h "pxr/base/gf/quath.h" -// \ingroup group_gf_LinearAlgebra -// \brief Basic type: a quaternion, a complex number with a real coefficient and -// three imaginary coefficients, stored as a 3-vector. -// +/// \class GfQuath +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type: a quaternion, a complex number with a real coefficient and +/// three imaginary coefficients, stored as a 3-vector. +/// class GfQuath { public: typedef half ScalarType; typedef GfVec3h ImaginaryType; - //! - // Default constructor leaves the quaternion undefined. + /// Default constructor leaves the quaternion undefined. GfQuath() {} - //! - // Initialize the real coefficient to \p realVal and the imaginary - // coefficients to zero. - // - // Since quaternions typically must be normalized, reasonable values for - // \p realVal are -1, 0, or 1. Other values are legal but are likely to be - // meaningless. - // + /// Initialize the real coefficient to \p realVal and the imaginary + /// coefficients to zero. + /// + /// Since quaternions typically must be normalized, reasonable values for + /// \p realVal are -1, 0, or 1. Other values are legal but are likely to + /// be meaningless. + /// explicit GfQuath (half realVal) : _imaginary(0), _real(realVal) {} - //! - // Initialize the real and imaginary coefficients. + /// Initialize the real and imaginary coefficients. GfQuath(half real, half i, half j, half k) : _imaginary(i, j, k), _real(real) { } - //! - // Initialize the real and imaginary coefficients. + /// Initialize the real and imaginary coefficients. GfQuath(half real, const GfVec3h &imaginary) : _imaginary(imaginary), _real(real) { } - //! - // Construct from GfQuatd. + /// Construct from GfQuatd. explicit GfQuath(class GfQuatd const &other); - //! - // Construct from GfQuatf. + /// Construct from GfQuatf. explicit GfQuath(class GfQuatf const &other); - //! - // Return the identity quaternion, with real coefficient 1 and an imaginary - // coefficients all zero. + /// Return the identity quaternion, with real coefficient 1 and an + /// imaginary coefficients all zero. static GfQuath GetIdentity() { return GfQuath(1.0); } - //! - // Return the real coefficient. + /// Return the real coefficient. half GetReal() const { return _real; } - //! - // Set the real coefficient. + /// Set the real coefficient. void SetReal(half real) { _real = real; } - //! - // Return the imaginary coefficient. + /// Return the imaginary coefficient. const GfVec3h &GetImaginary() const { return _imaginary; } - //! - // Set the imaginary coefficients. + /// Set the imaginary coefficients. void SetImaginary(const GfVec3h &imaginary) { _imaginary = imaginary; } - //! - // Set the imaginary coefficients. + /// Set the imaginary coefficients. void SetImaginary(half i, half j, half k) { _imaginary.Set(i, j, k); } - //! - // Return geometric length of this quaternion. + /// Return geometric length of this quaternion. half GetLength() const { return GfSqrt(_GetLengthSquared()); } - //! - // Return a normalized (unit-length) version of this quaternion. If the - // length of this quaternion is smaller than \p eps, return the identity - // quaternion. + /// length of this quaternion is smaller than \p eps, return the identity + /// quaternion. GfQuath GetNormalized(half eps = GF_MIN_VECTOR_LENGTH) const { GfQuath ret(*this); @@ -135,161 +119,143 @@ class GfQuath return ret; } - //! - // Normalizes this quaternion in place to unit length, returning - // the length before normalization. If the length of this - // quaternion is smaller than \p eps, this sets the quaternion to - // identity. + /// Normalizes this quaternion in place to unit length, returning the + /// length before normalization. If the length of this quaternion is + /// smaller than \p eps, this sets the quaternion to identity. + GF_API half Normalize(half eps = GF_MIN_VECTOR_LENGTH); - //! - // Return this quaternion's conjugate, which is the quaternion with the same - // real coefficient and negated imaginary coefficients. + /// Return this quaternion's conjugate, which is the quaternion with the + /// same real coefficient and negated imaginary coefficients. GfQuath GetConjugate() const { return GfQuath(GetReal(), -GetImaginary()); } - //! - // Return this quaternion's inverse, or reciprocal. This is the - // quaternion's conjugate divided by it's squared length. + /// Return this quaternion's inverse, or reciprocal. This is the + /// quaternion's conjugate divided by it's squared length. GfQuath GetInverse() const { return GetConjugate() / _GetLengthSquared(); } - //! - // Hash. + /// Hash. friend inline size_t hash_value(const GfQuath &q) { size_t h = hash_value(q.GetReal()); boost::hash_combine(h, q.GetImaginary()); return h; } - //! - // Component-wise negation. + /// Component-wise negation. GfQuath operator-() const { return GfQuath(-GetReal(), -GetImaginary()); } - //! - // Component-wise quaternion equality test. The real and imaginary parts - // must match exactly for quaternions to be considered equal. + /// Component-wise quaternion equality test. The real and imaginary parts + /// must match exactly for quaternions to be considered equal. bool operator==(const GfQuath &q) const { - return (GetReal() == q.GetReal() && + return (GetReal() == q.GetReal() && GetImaginary() == q.GetImaginary()); } - //! - // Component-wise quaternion inequality test. The real and imaginary parts - // must match exactly for quaternions to be considered equal. + /// Component-wise quaternion inequality test. The real and imaginary + /// parts must match exactly for quaternions to be considered equal. bool operator!=(const GfQuath &q) const { return !(*this == q); } - //! - // Post-multiply quaternion \p q into this quaternion. + /// Post-multiply quaternion \p q into this quaternion. + GF_API GfQuath &operator *=(const GfQuath &q); - //! - // Multiply this quaternion's coefficients by \p s . + /// Multiply this quaternion's coefficients by \p s. GfQuath &operator *=(half s) { _real *= s; _imaginary *= s; return *this; } - //! - // Divide this quaternion's coefficients by \p s . + /// Divide this quaternion's coefficients by \p s. GfQuath &operator /=(half s) { _real /= s; _imaginary /= s; return *this; } - //! - // Add quaternion \p q to this quaternion. + /// Add quaternion \p q to this quaternion. GfQuath &operator +=(const GfQuath &q) { _real += q._real; _imaginary += q._imaginary; return *this; } - //! - // Component-wise unary difference operator + /// Component-wise unary difference operator. GfQuath &operator -=(const GfQuath &q) { _real -= q._real; _imaginary -= q._imaginary; return *this; } - //! - // Component-wise binary sum operator + /// Component-wise binary sum operator. friend GfQuath operator +(const GfQuath &q1, const GfQuath &q2) { - return GfQuath(q1) += q2; + return GfQuath(q1) += q2; } - //! - // Component-wise binary difference operator + /// Component-wise binary difference operator. friend GfQuath operator -(const GfQuath &q1, const GfQuath &q2) { - return GfQuath(q1) -= q2; + return GfQuath(q1) -= q2; } - //! - // Returns the product of quaternions \p q1 and \p q2 . + /// Returns the product of quaternions \p q1 and \p q2. friend GfQuath operator *(const GfQuath &q1, const GfQuath &q2) { - return GfQuath(q1) *= q2; + return GfQuath(q1) *= q2; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend GfQuath operator *(const GfQuath &q, half s) { - return GfQuath(q) *= s; + return GfQuath(q) *= s; } - //! - // Returns the product of quaternion \p q and scalar \p s . + /// Returns the product of quaternion \p q and scalar \p s. friend GfQuath operator *(half s, const GfQuath &q) { - return GfQuath(q) *= s; + return GfQuath(q) *= s; } - //! - // Returns the product of quaternion \p q and scalar 1 / \p s . + /// Returns the product of quaternion \p q and scalar 1 / \p s. friend GfQuath operator /(const GfQuath &q, half s) { - return GfQuath(q) /= s; + return GfQuath(q) /= s; } private: - //! Imaginary part + /// Imaginary part GfVec3h _imaginary; - //! Real part + /// Real part half _real; - //! Returns the square of the length + /// Returns the square of the length half _GetLengthSquared() const { return _real * _real + GfDot(_imaginary, _imaginary); } }; -//! -// Spherically linearly interpolate between \p q0 and \p q1. -// -// If the interpolant \p alpha is zero, then the result is \p q0, while -// \p alpha of one yields \p q1. -GfQuath +/// Spherically linearly interpolate between \p q0 and \p q1. +/// +/// If the interpolant \p alpha is zero, then the result is \p q0, while +/// \p alpha of one yields \p q1. +GF_API GfQuath GfSlerp(double alpha, const GfQuath& q0, const GfQuath& q1); -GfQuath +GF_API GfQuath GfSlerp(const GfQuath& q0, const GfQuath& q1, double alpha); /// Output a GfQuatd using the format (re, i, j, k) /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfQuath const &); +GF_API std::ostream& operator<<(std::ostream &, GfQuath const &); -#endif // GF_QUATERNION_H +#endif // GF_QUATH_H diff --git a/pxr/base/lib/gf/range.template.h b/pxr/base/lib/gf/range.template.h index fefec46300..686f6c453b 100644 --- a/pxr/base/lib/gf/range.template.h +++ b/pxr/base/lib/gf/range.template.h @@ -28,6 +28,9 @@ #ifndef GF_{{ UPPER(RNG)[2:] }}_H #define GF_{{ UPPER(RNG)[2:] }}_H +/// \file gf/range{{ SUFFIX }}.h +/// \ingroup group_gf_BasicGeometry + {% if DIM > 1 %} #include "pxr/base/gf/vec{{ DIM }}d.h" #include "pxr/base/gf/vec{{ DIM }}f.h" @@ -40,32 +43,26 @@ #include #include -/*! - * \file range{{ SUFFIX }}.h - * \ingroup group_gf_BasicGeometry - */ - class GfRange{{ DIM }}d; class GfRange{{ DIM }}f; template <> struct GfIsGfRange { static const bool value = true; }; -//! -// \class {{ RNG }} range{{ SUFFIX }}.h "pxr/base/gf/range{{ SUFFIX }}.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: {{ DIM }}-dimensional floating point range. -// -// This class represents a {{ DIM }}-dimensional range (or interval) -// All operations are component-wise and conform to interval mathematics. -// An empty range is one where max < min. The default empty is -// [FLT_MAX,-FLT_MAX] - +/// \class {{ RNG }} +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: {{ DIM }}-dimensional floating point range. +/// +/// This class represents a {{ DIM }}-dimensional range (or interval) All +/// operations are component-wise and conform to interval mathematics. An +/// empty range is one where max < min. +/// The default empty is [FLT_MAX,-FLT_MAX] class {{ RNG }} { public: - //! Helper typedef. + /// Helper typedef. typedef {{ MINMAX }} MinMaxType; {% if DIM == 1 %} @@ -76,8 +73,8 @@ class {{ RNG }} typedef {{ MINMAX }}::ScalarType ScalarType; {% endif %} - //! Sets the range to an empty interval - // \warning Only found in libtess (once) and libgpt (once) Deprecated? + /// Sets the range to an empty interval + // TODO check whether this can be deprecated. void inline SetEmpty() { {% if DIM == 1 %} _min = FLT_MAX; @@ -88,33 +85,33 @@ class {{ RNG }} {% endif %} } - //! The default constructor creates an empty range. + /// The default constructor creates an empty range. {{ RNG }}() { SetEmpty(); } - //! This constructor initializes the minimum and maximum points. + /// This constructor initializes the minimum and maximum points. {{ RNG }}({{ MINMAXPARM }}min, {{ MINMAXPARM }}max) : _min(min), _max(max) { } - //! Returns the minimum value of the range. + /// Returns the minimum value of the range. {{ MINMAXPARM }}GetMin() const { return _min; } - //! Returns the maximum value of the range. + /// Returns the maximum value of the range. {{ MINMAXPARM }}GetMax() const { return _max; } - //! Returns the size of the range. + /// Returns the size of the range. {{ MINMAX }} GetSize() const { return _max - _min; } - //! Sets the minimum value of the range. + /// Sets the minimum value of the range. void SetMin({{ MINMAXPARM }}min) { _min = min; } - //! Sets the maximum value of the range. + /// Sets the maximum value of the range. void SetMax({{ MINMAXPARM }}max) { _max = max; } - //! Returns whether the range is empty (max < min). + /// Returns whether the range is empty (max < min). bool IsEmpty() const { {% if DIM == 1 %} return _min > _max; @@ -123,18 +120,16 @@ class {{ RNG }} {% endif %} } - //! Modifies the range if necessary to surround the given value. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given value. + /// \deprecated Use UnionWith() instead. void ExtendBy({{ MINMAXPARM }}point) { UnionWith(point); } - //! Modifies the range if necessary to surround the given range. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given range. + /// \deprecated Use UnionWith() instead. void ExtendBy(const {{ RNG }} &range) { UnionWith(range); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. bool Contains({{ MINMAXPARM }}point) const { {% if DIM == 1 %} return (point >= _min && point <= _max); @@ -143,36 +138,31 @@ class {{ RNG }} {% endif %} } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool Contains(const {{ RNG }} &range) const { - return Contains(range._min) && Contains(range._max); + return Contains(range._min) && Contains(range._max); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. + /// \deprecated Use Contains() instead. bool IsInside({{ MINMAXPARM }}point) const { return Contains(point); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. + /// \deprecated Use Contains() instead. bool IsInside(const {{ RNG }} &range) const { - return Contains(range); + return Contains(range); } - //! - // Returns true if the \p range is located entirely outside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely outside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool IsOutside(const {{ RNG }} &range) const { {% if DIM == 1 %} return (range._max < _min || range._min > _max); @@ -181,195 +171,197 @@ class {{ RNG }} {% endif %} } - //! Returns the smallest \c {{ RNG }} which contains both \p a and \p b + /// Returns the smallest \c {{ RNG }} which contains both \p a and \p b. static {{ RNG }} GetUnion(const {{ RNG }} &a, const {{ RNG }} &b) { - {{ RNG }} res = a; - _FindMin(res._min,b._min); - _FindMax(res._max,b._max); - return res; + {{ RNG }} res = a; + _FindMin(res._min,b._min); + _FindMax(res._max,b._max); + return res; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const {{ RNG }} &UnionWith(const {{ RNG }} &b) { - _FindMin(_min,b._min); - _FindMax(_max,b._max); - return *this; + _FindMin(_min,b._min); + _FindMax(_max,b._max); + return *this; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const {{ RNG }} &UnionWith({{ MINMAXPARM }}b) { - _FindMin(_min,b); - _FindMax(_max,b); - return *this; + _FindMin(_min,b); + _FindMax(_max,b); + return *this; } - //! Returns the smallest \c {{ RNG }} which contains both \p a and \p b - // \warning Deprecated - use \c GetUnion instead. + /// Returns the smallest \c {{ RNG }} which contains both \p a and \p b + /// \deprecated Use GetUnion() instead. static {{ RNG }} Union(const {{ RNG }} &a, const {{ RNG }} &b) { return GetUnion(a, b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const {{ RNG }} &Union(const {{ RNG }} &b) { return UnionWith(b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const {{ RNG }} &Union({{ MINMAXPARM }}b) { return UnionWith(b); } - //! Returns a \c {{ RNG }} that describes the intersection of \p a and \p b + /// Returns a \c {{ RNG }} that describes the intersection of \p a and \p b. static {{ RNG }} GetIntersection(const {{ RNG }} &a, const {{ RNG }} &b) { - {{ RNG }} res = a; - _FindMax(res._min,b._min); - _FindMin(res._max,b._max); - return res; + {{ RNG }} res = a; + _FindMax(res._min,b._min); + _FindMin(res._max,b._max); + return res; } - //! Returns a \c {{ RNG }} that describes the intersection of \p a and \p b - // \warning Deprecated - use \c GetIntersection instead. + /// Returns a \c {{ RNG }} that describes the intersection of \p a and \p b. + /// \deprecated Use GetIntersection() instead. static {{ RNG }} Intersection(const {{ RNG }} &a, const {{ RNG }} &b) { return GetIntersection(a, b); } - //! Modifies this range to hold its intersection with \p b and returns the - // result + /// Modifies this range to hold its intersection with \p b and returns the + /// result const {{ RNG }} &IntersectWith(const {{ RNG }} &b) { - _FindMax(_min,b._min); - _FindMin(_max,b._max); - return *this; + _FindMax(_min,b._min); + _FindMin(_max,b._max); + return *this; } - //! Modifies this range to hold its intersection with \p b and returns the - // result - // \warning Deprecated - use \c IntersectWith instead. + /// Modifies this range to hold its intersection with \p b and returns the + /// result. + /// \deprecated Use IntersectWith() instead. const {{ RNG }} &Intersection(const {{ RNG }} &b) { return IntersectWith(b); } - //! unary sum. + /// unary sum. {{ RNG }} operator +=(const {{ RNG }} &b) { - _min += b._min; - _max += b._max; - return *this; + _min += b._min; + _max += b._max; + return *this; } - //! unary difference. + /// unary difference. {{ RNG }} operator -=(const {{ RNG }} &b) { - _min -= b._max; - _max -= b._min; - return *this; + _min -= b._max; + _max -= b._min; + return *this; } - //! unary multiply + /// unary multiply. {{ RNG }} operator *=(double m) { - if (m > 0) { - _min *= m; - _max *= m; - } else { - {{ MINMAX }} tmp = _min; - _min = _max * m; - _max = tmp * m; - } - return *this; - } - //! unary division. + if (m > 0) { + _min *= m; + _max *= m; + } else { + {{ MINMAX }} tmp = _min; + _min = _max * m; + _max = tmp * m; + } + return *this; + } + + /// unary division. {{ RNG }} operator /=(double m) { - return *this *= (1.0 / m); + return *this *= (1.0 / m); } - //! binary sum. + /// binary sum. {{ RNG }} operator +(const {{ RNG }} &b) const { - return {{ RNG }}(_min + b._min, _max + b._max); + return {{ RNG }}(_min + b._min, _max + b._max); } - //! binary difference. + /// binary difference. {{ RNG }} operator -(const {{ RNG }} &b) const { - return {{ RNG }}(_min - b._max, _max - b._min); + return {{ RNG }}(_min - b._max, _max - b._min); } - //! scalar multiply. + /// scalar multiply. friend {{ RNG }} operator *(double m, const {{ RNG }} &r) { - return (m > 0 ? - {{ RNG }}(r._min*m, r._max*m) : - {{ RNG }}(r._max*m, r._min*m)); + return (m > 0 ? + {{ RNG }}(r._min*m, r._max*m) : + {{ RNG }}(r._max*m, r._min*m)); } - //! scalar multiply. + /// scalar multiply. friend {{ RNG }} operator *(const {{ RNG }} &r, double m) { - return (m > 0 ? - {{ RNG }}(r._min*m, r._max*m) : - {{ RNG }}(r._max*m, r._min*m)); + return (m > 0 ? + {{ RNG }}(r._min*m, r._max*m) : + {{ RNG }}(r._max*m, r._min*m)); } - //! scalar divide. + /// scalar divide. friend {{ RNG }} operator /(const {{ RNG }} &r, double m) { - return r * (1.0 / m); + return r * (1.0 / m); } - //! hash. + /// hash. friend inline size_t hash_value(const {{ RNG }} &r) { size_t h = 0; boost::hash_combine(h, r._min); boost::hash_combine(h, r._max); return h; - } + } - //! The min and max points must match exactly for equality. + /// The min and max points must match exactly for equality. bool operator ==(const {{ RNG }} &b) const { - return (_min == b._min && _max == b._max); + return (_min == b._min && _max == b._max); } + bool operator !=(const {{ RNG }} &b) const { return !(*this == b); } {% for S in SCALARS if S != SCL %} - //! Compare this range to a {{ RNGNAME(DIM, S) }}. - // - // The values must match exactly and it does exactly what you - // might expect when comparing float and double values. + /// Compare this range to a {{ RNGNAME(DIM, S) }}. + /// + /// The values must match exactly and it does exactly what you might + /// expect when comparing float and double values. inline bool operator ==(const {{ RNGNAME(DIM, S) }}& other) const; inline bool operator !=(const {{ RNGNAME(DIM, S) }}& other) const; {% endfor %} - //! Compute the squared distance from a point to the range. + /// Compute the squared distance from a point to the range. double GetDistanceSquared({{ MINMAXPARM }}p) const; {% if DIM == 2 %} - //! Returns the ith corner of the range, in the following order: - // SW, SE, NW, NE. + /// Returns the ith corner of the range, in the following order: + /// SW, SE, NW, NE. {{ MINMAX }} GetCorner(size_t i) const; - //! Returns the ith quadrant of the range, in the following order: - // SW, SE, NW, NE. + /// Returns the ith quadrant of the range, in the following order: + /// SW, SE, NW, NE. {{ RNG }} GetQuadrant(size_t i) const; - //! The unit square. + /// The unit square. static const {{ RNG }} UnitSquare; {% elif DIM == 3 %} - //! Returns the ith corner of the range, in the following order: - // LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, - // D/U is down/up, and B/F is back/front. + /// Returns the ith corner of the range, in the following order: + /// LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, + /// D/U is down/up, and B/F is back/front. {{ MINMAX }} GetCorner(size_t i) const; - //! Returns the ith octant of the range, in the following order: - // LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, - // D/U is down/up, and B/F is back/front. + /// Returns the ith octant of the range, in the following order: + /// LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, + /// D/U is down/up, and B/F is back/front. {{ RNG }} GetOctant(size_t i) const; - //! The unit cube. + /// The unit cube. static const {{ RNG }} UnitCube; {% endif %} private: - //! Minimum and maximum points. + /// Minimum and maximum points. {{ MINMAX }} _min, _max; - //! Extends minimum point if necessary to contain given point + /// Extends minimum point if necessary to contain given point. static void _FindMin({{ MINMAX }} &dest, {{ MINMAXPARM }}point) { {% if DIM == 1 %} if (point < dest) dest = point; @@ -379,7 +371,7 @@ class {{ RNG }} {% endif %} } - //! Extends maximum point if necessary to contain given point + /// Extends maximum point if necessary to contain given point. static void _FindMax({{ MINMAX }} &dest, {{ MINMAXPARM }}point) { {% if DIM == 1 %} if (point > dest) dest = point; @@ -390,7 +382,7 @@ class {{ RNG }} } }; -/// Output a {{ RNG }} +/// Output a {{ RNG }}. /// \ingroup group_gf_DebuggingOutput std::ostream& operator<<(std::ostream &, {{ RNG }} const &); diff --git a/pxr/base/lib/gf/range1d.h b/pxr/base/lib/gf/range1d.h index 372768ebdb..7a3a7e57cb 100644 --- a/pxr/base/lib/gf/range1d.h +++ b/pxr/base/lib/gf/range1d.h @@ -28,7 +28,11 @@ #ifndef GF_RANGE1D_H #define GF_RANGE1D_H +/// \file gf/range1d.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -36,300 +40,290 @@ #include #include -/*! - * \file range1d.h - * \ingroup group_gf_BasicGeometry - */ - class GfRange1d; class GfRange1f; template <> struct GfIsGfRange { static const bool value = true; }; -//! -// \class GfRange1d range1d.h "pxr/base/gf/range1d.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 1-dimensional floating point range. -// -// This class represents a 1-dimensional range (or interval) -// All operations are component-wise and conform to interval mathematics. -// An empty range is one where max < min. The default empty is -// [FLT_MAX,-FLT_MAX] - +/// \class GfRange1d +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 1-dimensional floating point range. +/// +/// This class represents a 1-dimensional range (or interval) All +/// operations are component-wise and conform to interval mathematics. An +/// empty range is one where max < min. +/// The default empty is [FLT_MAX,-FLT_MAX] class GfRange1d { public: - //! Helper typedef. + /// Helper typedef. typedef double MinMaxType; static const size_t dimension = 1; typedef MinMaxType ScalarType; - //! Sets the range to an empty interval - // \warning Only found in libtess (once) and libgpt (once) Deprecated? + /// Sets the range to an empty interval + // TODO check whether this can be deprecated. void inline SetEmpty() { _min = FLT_MAX; _max = -FLT_MAX; } - //! The default constructor creates an empty range. + /// The default constructor creates an empty range. GfRange1d() { SetEmpty(); } - //! This constructor initializes the minimum and maximum points. + /// This constructor initializes the minimum and maximum points. GfRange1d(double min, double max) : _min(min), _max(max) { } - //! Returns the minimum value of the range. + /// Returns the minimum value of the range. double GetMin() const { return _min; } - //! Returns the maximum value of the range. + /// Returns the maximum value of the range. double GetMax() const { return _max; } - //! Returns the size of the range. + /// Returns the size of the range. double GetSize() const { return _max - _min; } - //! Sets the minimum value of the range. + /// Sets the minimum value of the range. void SetMin(double min) { _min = min; } - //! Sets the maximum value of the range. + /// Sets the maximum value of the range. void SetMax(double max) { _max = max; } - //! Returns whether the range is empty (max < min). + /// Returns whether the range is empty (max < min). bool IsEmpty() const { return _min > _max; } - //! Modifies the range if necessary to surround the given value. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given value. + /// \deprecated Use UnionWith() instead. void ExtendBy(double point) { UnionWith(point); } - //! Modifies the range if necessary to surround the given range. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given range. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfRange1d &range) { UnionWith(range); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. bool Contains(double point) const { return (point >= _min && point <= _max); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool Contains(const GfRange1d &range) const { - return Contains(range._min) && Contains(range._max); + return Contains(range._min) && Contains(range._max); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. + /// \deprecated Use Contains() instead. bool IsInside(double point) const { return Contains(point); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfRange1d &range) const { - return Contains(range); + return Contains(range); } - //! - // Returns true if the \p range is located entirely outside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely outside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool IsOutside(const GfRange1d &range) const { return (range._max < _min || range._min > _max); } - //! Returns the smallest \c GfRange1d which contains both \p a and \p b + /// Returns the smallest \c GfRange1d which contains both \p a and \p b. static GfRange1d GetUnion(const GfRange1d &a, const GfRange1d &b) { - GfRange1d res = a; - _FindMin(res._min,b._min); - _FindMax(res._max,b._max); - return res; + GfRange1d res = a; + _FindMin(res._min,b._min); + _FindMax(res._max,b._max); + return res; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange1d &UnionWith(const GfRange1d &b) { - _FindMin(_min,b._min); - _FindMax(_max,b._max); - return *this; + _FindMin(_min,b._min); + _FindMax(_max,b._max); + return *this; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange1d &UnionWith(double b) { - _FindMin(_min,b); - _FindMax(_max,b); - return *this; + _FindMin(_min,b); + _FindMax(_max,b); + return *this; } - //! Returns the smallest \c GfRange1d which contains both \p a and \p b - // \warning Deprecated - use \c GetUnion instead. + /// Returns the smallest \c GfRange1d which contains both \p a and \p b + /// \deprecated Use GetUnion() instead. static GfRange1d Union(const GfRange1d &a, const GfRange1d &b) { return GetUnion(a, b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange1d &Union(const GfRange1d &b) { return UnionWith(b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange1d &Union(double b) { return UnionWith(b); } - //! Returns a \c GfRange1d that describes the intersection of \p a and \p b + /// Returns a \c GfRange1d that describes the intersection of \p a and \p b. static GfRange1d GetIntersection(const GfRange1d &a, const GfRange1d &b) { - GfRange1d res = a; - _FindMax(res._min,b._min); - _FindMin(res._max,b._max); - return res; + GfRange1d res = a; + _FindMax(res._min,b._min); + _FindMin(res._max,b._max); + return res; } - //! Returns a \c GfRange1d that describes the intersection of \p a and \p b - // \warning Deprecated - use \c GetIntersection instead. + /// Returns a \c GfRange1d that describes the intersection of \p a and \p b. + /// \deprecated Use GetIntersection() instead. static GfRange1d Intersection(const GfRange1d &a, const GfRange1d &b) { return GetIntersection(a, b); } - //! Modifies this range to hold its intersection with \p b and returns the - // result + /// Modifies this range to hold its intersection with \p b and returns the + /// result const GfRange1d &IntersectWith(const GfRange1d &b) { - _FindMax(_min,b._min); - _FindMin(_max,b._max); - return *this; + _FindMax(_min,b._min); + _FindMin(_max,b._max); + return *this; } - //! Modifies this range to hold its intersection with \p b and returns the - // result - // \warning Deprecated - use \c IntersectWith instead. + /// Modifies this range to hold its intersection with \p b and returns the + /// result. + /// \deprecated Use IntersectWith() instead. const GfRange1d &Intersection(const GfRange1d &b) { return IntersectWith(b); } - //! unary sum. + /// unary sum. GfRange1d operator +=(const GfRange1d &b) { - _min += b._min; - _max += b._max; - return *this; + _min += b._min; + _max += b._max; + return *this; } - //! unary difference. + /// unary difference. GfRange1d operator -=(const GfRange1d &b) { - _min -= b._max; - _max -= b._min; - return *this; + _min -= b._max; + _max -= b._min; + return *this; } - //! unary multiply + /// unary multiply. GfRange1d operator *=(double m) { - if (m > 0) { - _min *= m; - _max *= m; - } else { - double tmp = _min; - _min = _max * m; - _max = tmp * m; - } - return *this; - } - //! unary division. + if (m > 0) { + _min *= m; + _max *= m; + } else { + double tmp = _min; + _min = _max * m; + _max = tmp * m; + } + return *this; + } + + /// unary division. GfRange1d operator /=(double m) { - return *this *= (1.0 / m); + return *this *= (1.0 / m); } - //! binary sum. + /// binary sum. GfRange1d operator +(const GfRange1d &b) const { - return GfRange1d(_min + b._min, _max + b._max); + return GfRange1d(_min + b._min, _max + b._max); } - //! binary difference. + /// binary difference. GfRange1d operator -(const GfRange1d &b) const { - return GfRange1d(_min - b._max, _max - b._min); + return GfRange1d(_min - b._max, _max - b._min); } - //! scalar multiply. + /// scalar multiply. friend GfRange1d operator *(double m, const GfRange1d &r) { - return (m > 0 ? - GfRange1d(r._min*m, r._max*m) : - GfRange1d(r._max*m, r._min*m)); + return (m > 0 ? + GfRange1d(r._min*m, r._max*m) : + GfRange1d(r._max*m, r._min*m)); } - //! scalar multiply. + /// scalar multiply. friend GfRange1d operator *(const GfRange1d &r, double m) { - return (m > 0 ? - GfRange1d(r._min*m, r._max*m) : - GfRange1d(r._max*m, r._min*m)); + return (m > 0 ? + GfRange1d(r._min*m, r._max*m) : + GfRange1d(r._max*m, r._min*m)); } - //! scalar divide. + /// scalar divide. friend GfRange1d operator /(const GfRange1d &r, double m) { - return r * (1.0 / m); + return r * (1.0 / m); } - //! hash. + /// hash. friend inline size_t hash_value(const GfRange1d &r) { size_t h = 0; boost::hash_combine(h, r._min); boost::hash_combine(h, r._max); return h; - } + } - //! The min and max points must match exactly for equality. + /// The min and max points must match exactly for equality. bool operator ==(const GfRange1d &b) const { - return (_min == b._min && _max == b._max); + return (_min == b._min && _max == b._max); } + bool operator !=(const GfRange1d &b) const { return !(*this == b); } - //! Compare this range to a GfRange1f. - // - // The values must match exactly and it does exactly what you - // might expect when comparing float and double values. - inline bool operator ==(const GfRange1f& other) const; - inline bool operator !=(const GfRange1f& other) const; + /// Compare this range to a GfRange1f. + /// + /// The values must match exactly and it does exactly what you might + /// expect when comparing float and double values. + GF_API inline bool operator ==(const GfRange1f& other) const; + GF_API inline bool operator !=(const GfRange1f& other) const; - //! Compute the squared distance from a point to the range. + /// Compute the squared distance from a point to the range. + GF_API double GetDistanceSquared(double p) const; private: - //! Minimum and maximum points. + /// Minimum and maximum points. double _min, _max; - //! Extends minimum point if necessary to contain given point + /// Extends minimum point if necessary to contain given point. static void _FindMin(double &dest, double point) { if (point < dest) dest = point; } - //! Extends maximum point if necessary to contain given point + /// Extends maximum point if necessary to contain given point. static void _FindMax(double &dest, double point) { if (point > dest) dest = point; } }; -/// Output a GfRange1d +/// Output a GfRange1d. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfRange1d const &); +GF_API std::ostream& operator<<(std::ostream &, GfRange1d const &); #include "pxr/base/gf/range1f.h" diff --git a/pxr/base/lib/gf/range1f.h b/pxr/base/lib/gf/range1f.h index 6255b1a990..69652d6e8a 100644 --- a/pxr/base/lib/gf/range1f.h +++ b/pxr/base/lib/gf/range1f.h @@ -28,7 +28,11 @@ #ifndef GF_RANGE1F_H #define GF_RANGE1F_H +/// \file gf/range1f.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -36,300 +40,290 @@ #include #include -/*! - * \file range1f.h - * \ingroup group_gf_BasicGeometry - */ - class GfRange1d; class GfRange1f; template <> struct GfIsGfRange { static const bool value = true; }; -//! -// \class GfRange1f range1f.h "pxr/base/gf/range1f.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 1-dimensional floating point range. -// -// This class represents a 1-dimensional range (or interval) -// All operations are component-wise and conform to interval mathematics. -// An empty range is one where max < min. The default empty is -// [FLT_MAX,-FLT_MAX] - +/// \class GfRange1f +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 1-dimensional floating point range. +/// +/// This class represents a 1-dimensional range (or interval) All +/// operations are component-wise and conform to interval mathematics. An +/// empty range is one where max < min. +/// The default empty is [FLT_MAX,-FLT_MAX] class GfRange1f { public: - //! Helper typedef. + /// Helper typedef. typedef float MinMaxType; static const size_t dimension = 1; typedef MinMaxType ScalarType; - //! Sets the range to an empty interval - // \warning Only found in libtess (once) and libgpt (once) Deprecated? + /// Sets the range to an empty interval + // TODO check whether this can be deprecated. void inline SetEmpty() { _min = FLT_MAX; _max = -FLT_MAX; } - //! The default constructor creates an empty range. + /// The default constructor creates an empty range. GfRange1f() { SetEmpty(); } - //! This constructor initializes the minimum and maximum points. + /// This constructor initializes the minimum and maximum points. GfRange1f(float min, float max) : _min(min), _max(max) { } - //! Returns the minimum value of the range. + /// Returns the minimum value of the range. float GetMin() const { return _min; } - //! Returns the maximum value of the range. + /// Returns the maximum value of the range. float GetMax() const { return _max; } - //! Returns the size of the range. + /// Returns the size of the range. float GetSize() const { return _max - _min; } - //! Sets the minimum value of the range. + /// Sets the minimum value of the range. void SetMin(float min) { _min = min; } - //! Sets the maximum value of the range. + /// Sets the maximum value of the range. void SetMax(float max) { _max = max; } - //! Returns whether the range is empty (max < min). + /// Returns whether the range is empty (max < min). bool IsEmpty() const { return _min > _max; } - //! Modifies the range if necessary to surround the given value. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given value. + /// \deprecated Use UnionWith() instead. void ExtendBy(float point) { UnionWith(point); } - //! Modifies the range if necessary to surround the given range. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given range. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfRange1f &range) { UnionWith(range); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. bool Contains(float point) const { return (point >= _min && point <= _max); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool Contains(const GfRange1f &range) const { - return Contains(range._min) && Contains(range._max); + return Contains(range._min) && Contains(range._max); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. + /// \deprecated Use Contains() instead. bool IsInside(float point) const { return Contains(point); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfRange1f &range) const { - return Contains(range); + return Contains(range); } - //! - // Returns true if the \p range is located entirely outside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely outside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool IsOutside(const GfRange1f &range) const { return (range._max < _min || range._min > _max); } - //! Returns the smallest \c GfRange1f which contains both \p a and \p b + /// Returns the smallest \c GfRange1f which contains both \p a and \p b. static GfRange1f GetUnion(const GfRange1f &a, const GfRange1f &b) { - GfRange1f res = a; - _FindMin(res._min,b._min); - _FindMax(res._max,b._max); - return res; + GfRange1f res = a; + _FindMin(res._min,b._min); + _FindMax(res._max,b._max); + return res; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange1f &UnionWith(const GfRange1f &b) { - _FindMin(_min,b._min); - _FindMax(_max,b._max); - return *this; + _FindMin(_min,b._min); + _FindMax(_max,b._max); + return *this; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange1f &UnionWith(float b) { - _FindMin(_min,b); - _FindMax(_max,b); - return *this; + _FindMin(_min,b); + _FindMax(_max,b); + return *this; } - //! Returns the smallest \c GfRange1f which contains both \p a and \p b - // \warning Deprecated - use \c GetUnion instead. + /// Returns the smallest \c GfRange1f which contains both \p a and \p b + /// \deprecated Use GetUnion() instead. static GfRange1f Union(const GfRange1f &a, const GfRange1f &b) { return GetUnion(a, b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange1f &Union(const GfRange1f &b) { return UnionWith(b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange1f &Union(float b) { return UnionWith(b); } - //! Returns a \c GfRange1f that describes the intersection of \p a and \p b + /// Returns a \c GfRange1f that describes the intersection of \p a and \p b. static GfRange1f GetIntersection(const GfRange1f &a, const GfRange1f &b) { - GfRange1f res = a; - _FindMax(res._min,b._min); - _FindMin(res._max,b._max); - return res; + GfRange1f res = a; + _FindMax(res._min,b._min); + _FindMin(res._max,b._max); + return res; } - //! Returns a \c GfRange1f that describes the intersection of \p a and \p b - // \warning Deprecated - use \c GetIntersection instead. + /// Returns a \c GfRange1f that describes the intersection of \p a and \p b. + /// \deprecated Use GetIntersection() instead. static GfRange1f Intersection(const GfRange1f &a, const GfRange1f &b) { return GetIntersection(a, b); } - //! Modifies this range to hold its intersection with \p b and returns the - // result + /// Modifies this range to hold its intersection with \p b and returns the + /// result const GfRange1f &IntersectWith(const GfRange1f &b) { - _FindMax(_min,b._min); - _FindMin(_max,b._max); - return *this; + _FindMax(_min,b._min); + _FindMin(_max,b._max); + return *this; } - //! Modifies this range to hold its intersection with \p b and returns the - // result - // \warning Deprecated - use \c IntersectWith instead. + /// Modifies this range to hold its intersection with \p b and returns the + /// result. + /// \deprecated Use IntersectWith() instead. const GfRange1f &Intersection(const GfRange1f &b) { return IntersectWith(b); } - //! unary sum. + /// unary sum. GfRange1f operator +=(const GfRange1f &b) { - _min += b._min; - _max += b._max; - return *this; + _min += b._min; + _max += b._max; + return *this; } - //! unary difference. + /// unary difference. GfRange1f operator -=(const GfRange1f &b) { - _min -= b._max; - _max -= b._min; - return *this; + _min -= b._max; + _max -= b._min; + return *this; } - //! unary multiply + /// unary multiply. GfRange1f operator *=(double m) { - if (m > 0) { - _min *= m; - _max *= m; - } else { - float tmp = _min; - _min = _max * m; - _max = tmp * m; - } - return *this; - } - //! unary division. + if (m > 0) { + _min *= m; + _max *= m; + } else { + float tmp = _min; + _min = _max * m; + _max = tmp * m; + } + return *this; + } + + /// unary division. GfRange1f operator /=(double m) { - return *this *= (1.0 / m); + return *this *= (1.0 / m); } - //! binary sum. + /// binary sum. GfRange1f operator +(const GfRange1f &b) const { - return GfRange1f(_min + b._min, _max + b._max); + return GfRange1f(_min + b._min, _max + b._max); } - //! binary difference. + /// binary difference. GfRange1f operator -(const GfRange1f &b) const { - return GfRange1f(_min - b._max, _max - b._min); + return GfRange1f(_min - b._max, _max - b._min); } - //! scalar multiply. + /// scalar multiply. friend GfRange1f operator *(double m, const GfRange1f &r) { - return (m > 0 ? - GfRange1f(r._min*m, r._max*m) : - GfRange1f(r._max*m, r._min*m)); + return (m > 0 ? + GfRange1f(r._min*m, r._max*m) : + GfRange1f(r._max*m, r._min*m)); } - //! scalar multiply. + /// scalar multiply. friend GfRange1f operator *(const GfRange1f &r, double m) { - return (m > 0 ? - GfRange1f(r._min*m, r._max*m) : - GfRange1f(r._max*m, r._min*m)); + return (m > 0 ? + GfRange1f(r._min*m, r._max*m) : + GfRange1f(r._max*m, r._min*m)); } - //! scalar divide. + /// scalar divide. friend GfRange1f operator /(const GfRange1f &r, double m) { - return r * (1.0 / m); + return r * (1.0 / m); } - //! hash. + /// hash. friend inline size_t hash_value(const GfRange1f &r) { size_t h = 0; boost::hash_combine(h, r._min); boost::hash_combine(h, r._max); return h; - } + } - //! The min and max points must match exactly for equality. + /// The min and max points must match exactly for equality. bool operator ==(const GfRange1f &b) const { - return (_min == b._min && _max == b._max); + return (_min == b._min && _max == b._max); } + bool operator !=(const GfRange1f &b) const { return !(*this == b); } - //! Compare this range to a GfRange1d. - // - // The values must match exactly and it does exactly what you - // might expect when comparing float and double values. - inline bool operator ==(const GfRange1d& other) const; - inline bool operator !=(const GfRange1d& other) const; + /// Compare this range to a GfRange1d. + /// + /// The values must match exactly and it does exactly what you might + /// expect when comparing float and double values. + GF_API inline bool operator ==(const GfRange1d& other) const; + GF_API inline bool operator !=(const GfRange1d& other) const; - //! Compute the squared distance from a point to the range. + /// Compute the squared distance from a point to the range. + GF_API double GetDistanceSquared(float p) const; private: - //! Minimum and maximum points. + /// Minimum and maximum points. float _min, _max; - //! Extends minimum point if necessary to contain given point + /// Extends minimum point if necessary to contain given point. static void _FindMin(float &dest, float point) { if (point < dest) dest = point; } - //! Extends maximum point if necessary to contain given point + /// Extends maximum point if necessary to contain given point. static void _FindMax(float &dest, float point) { if (point > dest) dest = point; } }; -/// Output a GfRange1f +/// Output a GfRange1f. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfRange1f const &); +GF_API std::ostream& operator<<(std::ostream &, GfRange1f const &); #include "pxr/base/gf/range1d.h" diff --git a/pxr/base/lib/gf/range2d.h b/pxr/base/lib/gf/range2d.h index 3e0ac2b05d..9c9976d9fc 100644 --- a/pxr/base/lib/gf/range2d.h +++ b/pxr/base/lib/gf/range2d.h @@ -28,9 +28,13 @@ #ifndef GF_RANGE2D_H #define GF_RANGE2D_H +/// \file gf/range2d.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/vec2d.h" #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -38,314 +42,307 @@ #include #include -/*! - * \file range2d.h - * \ingroup group_gf_BasicGeometry - */ - class GfRange2d; class GfRange2f; template <> struct GfIsGfRange { static const bool value = true; }; -//! -// \class GfRange2d range2d.h "pxr/base/gf/range2d.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 2-dimensional floating point range. -// -// This class represents a 2-dimensional range (or interval) -// All operations are component-wise and conform to interval mathematics. -// An empty range is one where max < min. The default empty is -// [FLT_MAX,-FLT_MAX] - +/// \class GfRange2d +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 2-dimensional floating point range. +/// +/// This class represents a 2-dimensional range (or interval) All +/// operations are component-wise and conform to interval mathematics. An +/// empty range is one where max < min. +/// The default empty is [FLT_MAX,-FLT_MAX] class GfRange2d { public: - //! Helper typedef. + /// Helper typedef. typedef GfVec2d MinMaxType; static const size_t dimension = GfVec2d::dimension; typedef GfVec2d::ScalarType ScalarType; - //! Sets the range to an empty interval - // \warning Only found in libtess (once) and libgpt (once) Deprecated? + /// Sets the range to an empty interval + // TODO check whether this can be deprecated. void inline SetEmpty() { _min[0] = _min[1] = FLT_MAX; _max[0] = _max[1] = -FLT_MAX; } - //! The default constructor creates an empty range. + /// The default constructor creates an empty range. GfRange2d() { SetEmpty(); } - //! This constructor initializes the minimum and maximum points. + /// This constructor initializes the minimum and maximum points. GfRange2d(const GfVec2d &min, const GfVec2d &max) : _min(min), _max(max) { } - //! Returns the minimum value of the range. + /// Returns the minimum value of the range. const GfVec2d &GetMin() const { return _min; } - //! Returns the maximum value of the range. + /// Returns the maximum value of the range. const GfVec2d &GetMax() const { return _max; } - //! Returns the size of the range. + /// Returns the size of the range. GfVec2d GetSize() const { return _max - _min; } - //! Sets the minimum value of the range. + /// Sets the minimum value of the range. void SetMin(const GfVec2d &min) { _min = min; } - //! Sets the maximum value of the range. + /// Sets the maximum value of the range. void SetMax(const GfVec2d &max) { _max = max; } - //! Returns whether the range is empty (max < min). + /// Returns whether the range is empty (max < min). bool IsEmpty() const { return _min[0] > _max[0] || _min[1] > _max[1]; } - //! Modifies the range if necessary to surround the given value. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given value. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfVec2d &point) { UnionWith(point); } - //! Modifies the range if necessary to surround the given range. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given range. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfRange2d &range) { UnionWith(range); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. bool Contains(const GfVec2d &point) const { return (point[0] >= _min[0] && point[0] <= _max[0] && point[1] >= _min[1] && point[1] <= _max[1]); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool Contains(const GfRange2d &range) const { - return Contains(range._min) && Contains(range._max); + return Contains(range._min) && Contains(range._max); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfVec2d &point) const { return Contains(point); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfRange2d &range) const { - return Contains(range); + return Contains(range); } - //! - // Returns true if the \p range is located entirely outside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely outside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool IsOutside(const GfRange2d &range) const { return ((range._max[0] < _min[0] || range._min[0] > _max[0]) || (range._max[1] < _min[1] || range._min[1] > _max[1])); } - //! Returns the smallest \c GfRange2d which contains both \p a and \p b + /// Returns the smallest \c GfRange2d which contains both \p a and \p b. static GfRange2d GetUnion(const GfRange2d &a, const GfRange2d &b) { - GfRange2d res = a; - _FindMin(res._min,b._min); - _FindMax(res._max,b._max); - return res; + GfRange2d res = a; + _FindMin(res._min,b._min); + _FindMax(res._max,b._max); + return res; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange2d &UnionWith(const GfRange2d &b) { - _FindMin(_min,b._min); - _FindMax(_max,b._max); - return *this; + _FindMin(_min,b._min); + _FindMax(_max,b._max); + return *this; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange2d &UnionWith(const GfVec2d &b) { - _FindMin(_min,b); - _FindMax(_max,b); - return *this; + _FindMin(_min,b); + _FindMax(_max,b); + return *this; } - //! Returns the smallest \c GfRange2d which contains both \p a and \p b - // \warning Deprecated - use \c GetUnion instead. + /// Returns the smallest \c GfRange2d which contains both \p a and \p b + /// \deprecated Use GetUnion() instead. static GfRange2d Union(const GfRange2d &a, const GfRange2d &b) { return GetUnion(a, b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange2d &Union(const GfRange2d &b) { return UnionWith(b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange2d &Union(const GfVec2d &b) { return UnionWith(b); } - //! Returns a \c GfRange2d that describes the intersection of \p a and \p b + /// Returns a \c GfRange2d that describes the intersection of \p a and \p b. static GfRange2d GetIntersection(const GfRange2d &a, const GfRange2d &b) { - GfRange2d res = a; - _FindMax(res._min,b._min); - _FindMin(res._max,b._max); - return res; + GfRange2d res = a; + _FindMax(res._min,b._min); + _FindMin(res._max,b._max); + return res; } - //! Returns a \c GfRange2d that describes the intersection of \p a and \p b - // \warning Deprecated - use \c GetIntersection instead. + /// Returns a \c GfRange2d that describes the intersection of \p a and \p b. + /// \deprecated Use GetIntersection() instead. static GfRange2d Intersection(const GfRange2d &a, const GfRange2d &b) { return GetIntersection(a, b); } - //! Modifies this range to hold its intersection with \p b and returns the - // result + /// Modifies this range to hold its intersection with \p b and returns the + /// result const GfRange2d &IntersectWith(const GfRange2d &b) { - _FindMax(_min,b._min); - _FindMin(_max,b._max); - return *this; + _FindMax(_min,b._min); + _FindMin(_max,b._max); + return *this; } - //! Modifies this range to hold its intersection with \p b and returns the - // result - // \warning Deprecated - use \c IntersectWith instead. + /// Modifies this range to hold its intersection with \p b and returns the + /// result. + /// \deprecated Use IntersectWith() instead. const GfRange2d &Intersection(const GfRange2d &b) { return IntersectWith(b); } - //! unary sum. + /// unary sum. GfRange2d operator +=(const GfRange2d &b) { - _min += b._min; - _max += b._max; - return *this; + _min += b._min; + _max += b._max; + return *this; } - //! unary difference. + /// unary difference. GfRange2d operator -=(const GfRange2d &b) { - _min -= b._max; - _max -= b._min; - return *this; + _min -= b._max; + _max -= b._min; + return *this; } - //! unary multiply + /// unary multiply. GfRange2d operator *=(double m) { - if (m > 0) { - _min *= m; - _max *= m; - } else { - GfVec2d tmp = _min; - _min = _max * m; - _max = tmp * m; - } - return *this; - } - //! unary division. + if (m > 0) { + _min *= m; + _max *= m; + } else { + GfVec2d tmp = _min; + _min = _max * m; + _max = tmp * m; + } + return *this; + } + + /// unary division. GfRange2d operator /=(double m) { - return *this *= (1.0 / m); + return *this *= (1.0 / m); } - //! binary sum. + /// binary sum. GfRange2d operator +(const GfRange2d &b) const { - return GfRange2d(_min + b._min, _max + b._max); + return GfRange2d(_min + b._min, _max + b._max); } - //! binary difference. + /// binary difference. GfRange2d operator -(const GfRange2d &b) const { - return GfRange2d(_min - b._max, _max - b._min); + return GfRange2d(_min - b._max, _max - b._min); } - //! scalar multiply. + /// scalar multiply. friend GfRange2d operator *(double m, const GfRange2d &r) { - return (m > 0 ? - GfRange2d(r._min*m, r._max*m) : - GfRange2d(r._max*m, r._min*m)); + return (m > 0 ? + GfRange2d(r._min*m, r._max*m) : + GfRange2d(r._max*m, r._min*m)); } - //! scalar multiply. + /// scalar multiply. friend GfRange2d operator *(const GfRange2d &r, double m) { - return (m > 0 ? - GfRange2d(r._min*m, r._max*m) : - GfRange2d(r._max*m, r._min*m)); + return (m > 0 ? + GfRange2d(r._min*m, r._max*m) : + GfRange2d(r._max*m, r._min*m)); } - //! scalar divide. + /// scalar divide. friend GfRange2d operator /(const GfRange2d &r, double m) { - return r * (1.0 / m); + return r * (1.0 / m); } - //! hash. + /// hash. friend inline size_t hash_value(const GfRange2d &r) { size_t h = 0; boost::hash_combine(h, r._min); boost::hash_combine(h, r._max); return h; - } + } - //! The min and max points must match exactly for equality. + /// The min and max points must match exactly for equality. bool operator ==(const GfRange2d &b) const { - return (_min == b._min && _max == b._max); + return (_min == b._min && _max == b._max); } + bool operator !=(const GfRange2d &b) const { return !(*this == b); } - //! Compare this range to a GfRange2f. - // - // The values must match exactly and it does exactly what you - // might expect when comparing float and double values. - inline bool operator ==(const GfRange2f& other) const; - inline bool operator !=(const GfRange2f& other) const; + /// Compare this range to a GfRange2f. + /// + /// The values must match exactly and it does exactly what you might + /// expect when comparing float and double values. + GF_API inline bool operator ==(const GfRange2f& other) const; + GF_API inline bool operator !=(const GfRange2f& other) const; - //! Compute the squared distance from a point to the range. + /// Compute the squared distance from a point to the range. + GF_API double GetDistanceSquared(const GfVec2d &p) const; - //! Returns the ith corner of the range, in the following order: - // SW, SE, NW, NE. + /// Returns the ith corner of the range, in the following order: + /// SW, SE, NW, NE. + GF_API GfVec2d GetCorner(size_t i) const; - //! Returns the ith quadrant of the range, in the following order: - // SW, SE, NW, NE. + /// Returns the ith quadrant of the range, in the following order: + /// SW, SE, NW, NE. + GF_API GfRange2d GetQuadrant(size_t i) const; - //! The unit square. + /// The unit square. + GF_API static const GfRange2d UnitSquare; private: - //! Minimum and maximum points. + /// Minimum and maximum points. GfVec2d _min, _max; - //! Extends minimum point if necessary to contain given point + /// Extends minimum point if necessary to contain given point. static void _FindMin(GfVec2d &dest, const GfVec2d &point) { if (point[0] < dest[0]) dest[0] = point[0]; if (point[1] < dest[1]) dest[1] = point[1]; } - //! Extends maximum point if necessary to contain given point + /// Extends maximum point if necessary to contain given point. static void _FindMax(GfVec2d &dest, const GfVec2d &point) { if (point[0] > dest[0]) dest[0] = point[0]; if (point[1] > dest[1]) dest[1] = point[1]; } }; -/// Output a GfRange2d +/// Output a GfRange2d. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfRange2d const &); +GF_API std::ostream& operator<<(std::ostream &, GfRange2d const &); #include "pxr/base/gf/range2f.h" diff --git a/pxr/base/lib/gf/range2f.h b/pxr/base/lib/gf/range2f.h index c1ee712a41..257b6ec78b 100644 --- a/pxr/base/lib/gf/range2f.h +++ b/pxr/base/lib/gf/range2f.h @@ -28,9 +28,13 @@ #ifndef GF_RANGE2F_H #define GF_RANGE2F_H +/// \file gf/range2f.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/vec2d.h" #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -38,314 +42,307 @@ #include #include -/*! - * \file range2f.h - * \ingroup group_gf_BasicGeometry - */ - class GfRange2d; class GfRange2f; template <> struct GfIsGfRange { static const bool value = true; }; -//! -// \class GfRange2f range2f.h "pxr/base/gf/range2f.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 2-dimensional floating point range. -// -// This class represents a 2-dimensional range (or interval) -// All operations are component-wise and conform to interval mathematics. -// An empty range is one where max < min. The default empty is -// [FLT_MAX,-FLT_MAX] - +/// \class GfRange2f +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 2-dimensional floating point range. +/// +/// This class represents a 2-dimensional range (or interval) All +/// operations are component-wise and conform to interval mathematics. An +/// empty range is one where max < min. +/// The default empty is [FLT_MAX,-FLT_MAX] class GfRange2f { public: - //! Helper typedef. + /// Helper typedef. typedef GfVec2f MinMaxType; static const size_t dimension = GfVec2f::dimension; typedef GfVec2f::ScalarType ScalarType; - //! Sets the range to an empty interval - // \warning Only found in libtess (once) and libgpt (once) Deprecated? + /// Sets the range to an empty interval + // TODO check whether this can be deprecated. void inline SetEmpty() { _min[0] = _min[1] = FLT_MAX; _max[0] = _max[1] = -FLT_MAX; } - //! The default constructor creates an empty range. + /// The default constructor creates an empty range. GfRange2f() { SetEmpty(); } - //! This constructor initializes the minimum and maximum points. + /// This constructor initializes the minimum and maximum points. GfRange2f(const GfVec2f &min, const GfVec2f &max) : _min(min), _max(max) { } - //! Returns the minimum value of the range. + /// Returns the minimum value of the range. const GfVec2f &GetMin() const { return _min; } - //! Returns the maximum value of the range. + /// Returns the maximum value of the range. const GfVec2f &GetMax() const { return _max; } - //! Returns the size of the range. + /// Returns the size of the range. GfVec2f GetSize() const { return _max - _min; } - //! Sets the minimum value of the range. + /// Sets the minimum value of the range. void SetMin(const GfVec2f &min) { _min = min; } - //! Sets the maximum value of the range. + /// Sets the maximum value of the range. void SetMax(const GfVec2f &max) { _max = max; } - //! Returns whether the range is empty (max < min). + /// Returns whether the range is empty (max < min). bool IsEmpty() const { return _min[0] > _max[0] || _min[1] > _max[1]; } - //! Modifies the range if necessary to surround the given value. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given value. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfVec2f &point) { UnionWith(point); } - //! Modifies the range if necessary to surround the given range. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given range. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfRange2f &range) { UnionWith(range); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. bool Contains(const GfVec2f &point) const { return (point[0] >= _min[0] && point[0] <= _max[0] && point[1] >= _min[1] && point[1] <= _max[1]); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool Contains(const GfRange2f &range) const { - return Contains(range._min) && Contains(range._max); + return Contains(range._min) && Contains(range._max); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfVec2f &point) const { return Contains(point); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfRange2f &range) const { - return Contains(range); + return Contains(range); } - //! - // Returns true if the \p range is located entirely outside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely outside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool IsOutside(const GfRange2f &range) const { return ((range._max[0] < _min[0] || range._min[0] > _max[0]) || (range._max[1] < _min[1] || range._min[1] > _max[1])); } - //! Returns the smallest \c GfRange2f which contains both \p a and \p b + /// Returns the smallest \c GfRange2f which contains both \p a and \p b. static GfRange2f GetUnion(const GfRange2f &a, const GfRange2f &b) { - GfRange2f res = a; - _FindMin(res._min,b._min); - _FindMax(res._max,b._max); - return res; + GfRange2f res = a; + _FindMin(res._min,b._min); + _FindMax(res._max,b._max); + return res; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange2f &UnionWith(const GfRange2f &b) { - _FindMin(_min,b._min); - _FindMax(_max,b._max); - return *this; + _FindMin(_min,b._min); + _FindMax(_max,b._max); + return *this; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange2f &UnionWith(const GfVec2f &b) { - _FindMin(_min,b); - _FindMax(_max,b); - return *this; + _FindMin(_min,b); + _FindMax(_max,b); + return *this; } - //! Returns the smallest \c GfRange2f which contains both \p a and \p b - // \warning Deprecated - use \c GetUnion instead. + /// Returns the smallest \c GfRange2f which contains both \p a and \p b + /// \deprecated Use GetUnion() instead. static GfRange2f Union(const GfRange2f &a, const GfRange2f &b) { return GetUnion(a, b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange2f &Union(const GfRange2f &b) { return UnionWith(b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange2f &Union(const GfVec2f &b) { return UnionWith(b); } - //! Returns a \c GfRange2f that describes the intersection of \p a and \p b + /// Returns a \c GfRange2f that describes the intersection of \p a and \p b. static GfRange2f GetIntersection(const GfRange2f &a, const GfRange2f &b) { - GfRange2f res = a; - _FindMax(res._min,b._min); - _FindMin(res._max,b._max); - return res; + GfRange2f res = a; + _FindMax(res._min,b._min); + _FindMin(res._max,b._max); + return res; } - //! Returns a \c GfRange2f that describes the intersection of \p a and \p b - // \warning Deprecated - use \c GetIntersection instead. + /// Returns a \c GfRange2f that describes the intersection of \p a and \p b. + /// \deprecated Use GetIntersection() instead. static GfRange2f Intersection(const GfRange2f &a, const GfRange2f &b) { return GetIntersection(a, b); } - //! Modifies this range to hold its intersection with \p b and returns the - // result + /// Modifies this range to hold its intersection with \p b and returns the + /// result const GfRange2f &IntersectWith(const GfRange2f &b) { - _FindMax(_min,b._min); - _FindMin(_max,b._max); - return *this; + _FindMax(_min,b._min); + _FindMin(_max,b._max); + return *this; } - //! Modifies this range to hold its intersection with \p b and returns the - // result - // \warning Deprecated - use \c IntersectWith instead. + /// Modifies this range to hold its intersection with \p b and returns the + /// result. + /// \deprecated Use IntersectWith() instead. const GfRange2f &Intersection(const GfRange2f &b) { return IntersectWith(b); } - //! unary sum. + /// unary sum. GfRange2f operator +=(const GfRange2f &b) { - _min += b._min; - _max += b._max; - return *this; + _min += b._min; + _max += b._max; + return *this; } - //! unary difference. + /// unary difference. GfRange2f operator -=(const GfRange2f &b) { - _min -= b._max; - _max -= b._min; - return *this; + _min -= b._max; + _max -= b._min; + return *this; } - //! unary multiply + /// unary multiply. GfRange2f operator *=(double m) { - if (m > 0) { - _min *= m; - _max *= m; - } else { - GfVec2f tmp = _min; - _min = _max * m; - _max = tmp * m; - } - return *this; - } - //! unary division. + if (m > 0) { + _min *= m; + _max *= m; + } else { + GfVec2f tmp = _min; + _min = _max * m; + _max = tmp * m; + } + return *this; + } + + /// unary division. GfRange2f operator /=(double m) { - return *this *= (1.0 / m); + return *this *= (1.0 / m); } - //! binary sum. + /// binary sum. GfRange2f operator +(const GfRange2f &b) const { - return GfRange2f(_min + b._min, _max + b._max); + return GfRange2f(_min + b._min, _max + b._max); } - //! binary difference. + /// binary difference. GfRange2f operator -(const GfRange2f &b) const { - return GfRange2f(_min - b._max, _max - b._min); + return GfRange2f(_min - b._max, _max - b._min); } - //! scalar multiply. + /// scalar multiply. friend GfRange2f operator *(double m, const GfRange2f &r) { - return (m > 0 ? - GfRange2f(r._min*m, r._max*m) : - GfRange2f(r._max*m, r._min*m)); + return (m > 0 ? + GfRange2f(r._min*m, r._max*m) : + GfRange2f(r._max*m, r._min*m)); } - //! scalar multiply. + /// scalar multiply. friend GfRange2f operator *(const GfRange2f &r, double m) { - return (m > 0 ? - GfRange2f(r._min*m, r._max*m) : - GfRange2f(r._max*m, r._min*m)); + return (m > 0 ? + GfRange2f(r._min*m, r._max*m) : + GfRange2f(r._max*m, r._min*m)); } - //! scalar divide. + /// scalar divide. friend GfRange2f operator /(const GfRange2f &r, double m) { - return r * (1.0 / m); + return r * (1.0 / m); } - //! hash. + /// hash. friend inline size_t hash_value(const GfRange2f &r) { size_t h = 0; boost::hash_combine(h, r._min); boost::hash_combine(h, r._max); return h; - } + } - //! The min and max points must match exactly for equality. + /// The min and max points must match exactly for equality. bool operator ==(const GfRange2f &b) const { - return (_min == b._min && _max == b._max); + return (_min == b._min && _max == b._max); } + bool operator !=(const GfRange2f &b) const { return !(*this == b); } - //! Compare this range to a GfRange2d. - // - // The values must match exactly and it does exactly what you - // might expect when comparing float and double values. - inline bool operator ==(const GfRange2d& other) const; - inline bool operator !=(const GfRange2d& other) const; + /// Compare this range to a GfRange2d. + /// + /// The values must match exactly and it does exactly what you might + /// expect when comparing float and double values. + GF_API inline bool operator ==(const GfRange2d& other) const; + GF_API inline bool operator !=(const GfRange2d& other) const; - //! Compute the squared distance from a point to the range. + /// Compute the squared distance from a point to the range. + GF_API double GetDistanceSquared(const GfVec2f &p) const; - //! Returns the ith corner of the range, in the following order: - // SW, SE, NW, NE. + /// Returns the ith corner of the range, in the following order: + /// SW, SE, NW, NE. + GF_API GfVec2f GetCorner(size_t i) const; - //! Returns the ith quadrant of the range, in the following order: - // SW, SE, NW, NE. + /// Returns the ith quadrant of the range, in the following order: + /// SW, SE, NW, NE. + GF_API GfRange2f GetQuadrant(size_t i) const; - //! The unit square. + /// The unit square. + GF_API static const GfRange2f UnitSquare; private: - //! Minimum and maximum points. + /// Minimum and maximum points. GfVec2f _min, _max; - //! Extends minimum point if necessary to contain given point + /// Extends minimum point if necessary to contain given point. static void _FindMin(GfVec2f &dest, const GfVec2f &point) { if (point[0] < dest[0]) dest[0] = point[0]; if (point[1] < dest[1]) dest[1] = point[1]; } - //! Extends maximum point if necessary to contain given point + /// Extends maximum point if necessary to contain given point. static void _FindMax(GfVec2f &dest, const GfVec2f &point) { if (point[0] > dest[0]) dest[0] = point[0]; if (point[1] > dest[1]) dest[1] = point[1]; } }; -/// Output a GfRange2f +/// Output a GfRange2f. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfRange2f const &); +GF_API std::ostream& operator<<(std::ostream &, GfRange2f const &); #include "pxr/base/gf/range2d.h" diff --git a/pxr/base/lib/gf/range3d.h b/pxr/base/lib/gf/range3d.h index b6473bf988..b3a3279550 100644 --- a/pxr/base/lib/gf/range3d.h +++ b/pxr/base/lib/gf/range3d.h @@ -28,9 +28,13 @@ #ifndef GF_RANGE3D_H #define GF_RANGE3D_H +/// \file gf/range3d.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -38,310 +42,303 @@ #include #include -/*! - * \file range3d.h - * \ingroup group_gf_BasicGeometry - */ - class GfRange3d; class GfRange3f; template <> struct GfIsGfRange { static const bool value = true; }; -//! -// \class GfRange3d range3d.h "pxr/base/gf/range3d.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 3-dimensional floating point range. -// -// This class represents a 3-dimensional range (or interval) -// All operations are component-wise and conform to interval mathematics. -// An empty range is one where max < min. The default empty is -// [FLT_MAX,-FLT_MAX] - +/// \class GfRange3d +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 3-dimensional floating point range. +/// +/// This class represents a 3-dimensional range (or interval) All +/// operations are component-wise and conform to interval mathematics. An +/// empty range is one where max < min. +/// The default empty is [FLT_MAX,-FLT_MAX] class GfRange3d { public: - //! Helper typedef. + /// Helper typedef. typedef GfVec3d MinMaxType; static const size_t dimension = GfVec3d::dimension; typedef GfVec3d::ScalarType ScalarType; - //! Sets the range to an empty interval - // \warning Only found in libtess (once) and libgpt (once) Deprecated? + /// Sets the range to an empty interval + // TODO check whether this can be deprecated. void inline SetEmpty() { _min[0] = _min[1] = _min[2] = FLT_MAX; _max[0] = _max[1] = _max[2] = -FLT_MAX; } - //! The default constructor creates an empty range. + /// The default constructor creates an empty range. GfRange3d() { SetEmpty(); } - //! This constructor initializes the minimum and maximum points. + /// This constructor initializes the minimum and maximum points. GfRange3d(const GfVec3d &min, const GfVec3d &max) : _min(min), _max(max) { } - //! Returns the minimum value of the range. + /// Returns the minimum value of the range. const GfVec3d &GetMin() const { return _min; } - //! Returns the maximum value of the range. + /// Returns the maximum value of the range. const GfVec3d &GetMax() const { return _max; } - //! Returns the size of the range. + /// Returns the size of the range. GfVec3d GetSize() const { return _max - _min; } - //! Sets the minimum value of the range. + /// Sets the minimum value of the range. void SetMin(const GfVec3d &min) { _min = min; } - //! Sets the maximum value of the range. + /// Sets the maximum value of the range. void SetMax(const GfVec3d &max) { _max = max; } - //! Returns whether the range is empty (max < min). + /// Returns whether the range is empty (max < min). bool IsEmpty() const { return _min[0] > _max[0] || _min[1] > _max[1] || _min[2] > _max[2]; } - //! Modifies the range if necessary to surround the given value. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given value. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfVec3d &point) { UnionWith(point); } - //! Modifies the range if necessary to surround the given range. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given range. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfRange3d &range) { UnionWith(range); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. bool Contains(const GfVec3d &point) const { return (point[0] >= _min[0] && point[0] <= _max[0] && point[1] >= _min[1] && point[1] <= _max[1] && point[2] >= _min[2] && point[2] <= _max[2]); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool Contains(const GfRange3d &range) const { - return Contains(range._min) && Contains(range._max); + return Contains(range._min) && Contains(range._max); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfVec3d &point) const { return Contains(point); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfRange3d &range) const { - return Contains(range); + return Contains(range); } - //! - // Returns true if the \p range is located entirely outside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely outside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool IsOutside(const GfRange3d &range) const { return ((range._max[0] < _min[0] || range._min[0] > _max[0]) || (range._max[1] < _min[1] || range._min[1] > _max[1]) || (range._max[2] < _min[2] || range._min[2] > _max[2])); } - //! Returns the smallest \c GfRange3d which contains both \p a and \p b + /// Returns the smallest \c GfRange3d which contains both \p a and \p b. static GfRange3d GetUnion(const GfRange3d &a, const GfRange3d &b) { - GfRange3d res = a; - _FindMin(res._min,b._min); - _FindMax(res._max,b._max); - return res; + GfRange3d res = a; + _FindMin(res._min,b._min); + _FindMax(res._max,b._max); + return res; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange3d &UnionWith(const GfRange3d &b) { - _FindMin(_min,b._min); - _FindMax(_max,b._max); - return *this; + _FindMin(_min,b._min); + _FindMax(_max,b._max); + return *this; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange3d &UnionWith(const GfVec3d &b) { - _FindMin(_min,b); - _FindMax(_max,b); - return *this; + _FindMin(_min,b); + _FindMax(_max,b); + return *this; } - //! Returns the smallest \c GfRange3d which contains both \p a and \p b - // \warning Deprecated - use \c GetUnion instead. + /// Returns the smallest \c GfRange3d which contains both \p a and \p b + /// \deprecated Use GetUnion() instead. static GfRange3d Union(const GfRange3d &a, const GfRange3d &b) { return GetUnion(a, b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange3d &Union(const GfRange3d &b) { return UnionWith(b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange3d &Union(const GfVec3d &b) { return UnionWith(b); } - //! Returns a \c GfRange3d that describes the intersection of \p a and \p b + /// Returns a \c GfRange3d that describes the intersection of \p a and \p b. static GfRange3d GetIntersection(const GfRange3d &a, const GfRange3d &b) { - GfRange3d res = a; - _FindMax(res._min,b._min); - _FindMin(res._max,b._max); - return res; + GfRange3d res = a; + _FindMax(res._min,b._min); + _FindMin(res._max,b._max); + return res; } - //! Returns a \c GfRange3d that describes the intersection of \p a and \p b - // \warning Deprecated - use \c GetIntersection instead. + /// Returns a \c GfRange3d that describes the intersection of \p a and \p b. + /// \deprecated Use GetIntersection() instead. static GfRange3d Intersection(const GfRange3d &a, const GfRange3d &b) { return GetIntersection(a, b); } - //! Modifies this range to hold its intersection with \p b and returns the - // result + /// Modifies this range to hold its intersection with \p b and returns the + /// result const GfRange3d &IntersectWith(const GfRange3d &b) { - _FindMax(_min,b._min); - _FindMin(_max,b._max); - return *this; + _FindMax(_min,b._min); + _FindMin(_max,b._max); + return *this; } - //! Modifies this range to hold its intersection with \p b and returns the - // result - // \warning Deprecated - use \c IntersectWith instead. + /// Modifies this range to hold its intersection with \p b and returns the + /// result. + /// \deprecated Use IntersectWith() instead. const GfRange3d &Intersection(const GfRange3d &b) { return IntersectWith(b); } - //! unary sum. + /// unary sum. GfRange3d operator +=(const GfRange3d &b) { - _min += b._min; - _max += b._max; - return *this; + _min += b._min; + _max += b._max; + return *this; } - //! unary difference. + /// unary difference. GfRange3d operator -=(const GfRange3d &b) { - _min -= b._max; - _max -= b._min; - return *this; + _min -= b._max; + _max -= b._min; + return *this; } - //! unary multiply + /// unary multiply. GfRange3d operator *=(double m) { - if (m > 0) { - _min *= m; - _max *= m; - } else { - GfVec3d tmp = _min; - _min = _max * m; - _max = tmp * m; - } - return *this; - } - //! unary division. + if (m > 0) { + _min *= m; + _max *= m; + } else { + GfVec3d tmp = _min; + _min = _max * m; + _max = tmp * m; + } + return *this; + } + + /// unary division. GfRange3d operator /=(double m) { - return *this *= (1.0 / m); + return *this *= (1.0 / m); } - //! binary sum. + /// binary sum. GfRange3d operator +(const GfRange3d &b) const { - return GfRange3d(_min + b._min, _max + b._max); + return GfRange3d(_min + b._min, _max + b._max); } - //! binary difference. + /// binary difference. GfRange3d operator -(const GfRange3d &b) const { - return GfRange3d(_min - b._max, _max - b._min); + return GfRange3d(_min - b._max, _max - b._min); } - //! scalar multiply. + /// scalar multiply. friend GfRange3d operator *(double m, const GfRange3d &r) { - return (m > 0 ? - GfRange3d(r._min*m, r._max*m) : - GfRange3d(r._max*m, r._min*m)); + return (m > 0 ? + GfRange3d(r._min*m, r._max*m) : + GfRange3d(r._max*m, r._min*m)); } - //! scalar multiply. + /// scalar multiply. friend GfRange3d operator *(const GfRange3d &r, double m) { - return (m > 0 ? - GfRange3d(r._min*m, r._max*m) : - GfRange3d(r._max*m, r._min*m)); + return (m > 0 ? + GfRange3d(r._min*m, r._max*m) : + GfRange3d(r._max*m, r._min*m)); } - //! scalar divide. + /// scalar divide. friend GfRange3d operator /(const GfRange3d &r, double m) { - return r * (1.0 / m); + return r * (1.0 / m); } - //! hash. + /// hash. friend inline size_t hash_value(const GfRange3d &r) { size_t h = 0; boost::hash_combine(h, r._min); boost::hash_combine(h, r._max); return h; - } + } - //! The min and max points must match exactly for equality. + /// The min and max points must match exactly for equality. bool operator ==(const GfRange3d &b) const { - return (_min == b._min && _max == b._max); + return (_min == b._min && _max == b._max); } + bool operator !=(const GfRange3d &b) const { return !(*this == b); } - //! Compare this range to a GfRange3f. - // - // The values must match exactly and it does exactly what you - // might expect when comparing float and double values. - inline bool operator ==(const GfRange3f& other) const; - inline bool operator !=(const GfRange3f& other) const; + /// Compare this range to a GfRange3f. + /// + /// The values must match exactly and it does exactly what you might + /// expect when comparing float and double values. + GF_API inline bool operator ==(const GfRange3f& other) const; + GF_API inline bool operator !=(const GfRange3f& other) const; - //! Compute the squared distance from a point to the range. + /// Compute the squared distance from a point to the range. + GF_API double GetDistanceSquared(const GfVec3d &p) const; - //! Returns the ith corner of the range, in the following order: - // LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, - // D/U is down/up, and B/F is back/front. + /// Returns the ith corner of the range, in the following order: + /// LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, + /// D/U is down/up, and B/F is back/front. + GF_API GfVec3d GetCorner(size_t i) const; - //! Returns the ith octant of the range, in the following order: - // LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, - // D/U is down/up, and B/F is back/front. + /// Returns the ith octant of the range, in the following order: + /// LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, + /// D/U is down/up, and B/F is back/front. + GF_API GfRange3d GetOctant(size_t i) const; - //! The unit cube. + /// The unit cube. + GF_API static const GfRange3d UnitCube; private: - //! Minimum and maximum points. + /// Minimum and maximum points. GfVec3d _min, _max; - //! Extends minimum point if necessary to contain given point + /// Extends minimum point if necessary to contain given point. static void _FindMin(GfVec3d &dest, const GfVec3d &point) { if (point[0] < dest[0]) dest[0] = point[0]; if (point[1] < dest[1]) dest[1] = point[1]; if (point[2] < dest[2]) dest[2] = point[2]; } - //! Extends maximum point if necessary to contain given point + /// Extends maximum point if necessary to contain given point. static void _FindMax(GfVec3d &dest, const GfVec3d &point) { if (point[0] > dest[0]) dest[0] = point[0]; if (point[1] > dest[1]) dest[1] = point[1]; @@ -349,9 +346,9 @@ class GfRange3d } }; -/// Output a GfRange3d +/// Output a GfRange3d. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfRange3d const &); +GF_API std::ostream& operator<<(std::ostream &, GfRange3d const &); #include "pxr/base/gf/range3f.h" diff --git a/pxr/base/lib/gf/range3f.h b/pxr/base/lib/gf/range3f.h index 205e5b4326..3178e63731 100644 --- a/pxr/base/lib/gf/range3f.h +++ b/pxr/base/lib/gf/range3f.h @@ -28,9 +28,13 @@ #ifndef GF_RANGE3F_H #define GF_RANGE3F_H +/// \file gf/range3f.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -38,310 +42,303 @@ #include #include -/*! - * \file range3f.h - * \ingroup group_gf_BasicGeometry - */ - class GfRange3d; class GfRange3f; template <> struct GfIsGfRange { static const bool value = true; }; -//! -// \class GfRange3f range3f.h "pxr/base/gf/range3f.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: 3-dimensional floating point range. -// -// This class represents a 3-dimensional range (or interval) -// All operations are component-wise and conform to interval mathematics. -// An empty range is one where max < min. The default empty is -// [FLT_MAX,-FLT_MAX] - +/// \class GfRange3f +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: 3-dimensional floating point range. +/// +/// This class represents a 3-dimensional range (or interval) All +/// operations are component-wise and conform to interval mathematics. An +/// empty range is one where max < min. +/// The default empty is [FLT_MAX,-FLT_MAX] class GfRange3f { public: - //! Helper typedef. + /// Helper typedef. typedef GfVec3f MinMaxType; static const size_t dimension = GfVec3f::dimension; typedef GfVec3f::ScalarType ScalarType; - //! Sets the range to an empty interval - // \warning Only found in libtess (once) and libgpt (once) Deprecated? + /// Sets the range to an empty interval + // TODO check whether this can be deprecated. void inline SetEmpty() { _min[0] = _min[1] = _min[2] = FLT_MAX; _max[0] = _max[1] = _max[2] = -FLT_MAX; } - //! The default constructor creates an empty range. + /// The default constructor creates an empty range. GfRange3f() { SetEmpty(); } - //! This constructor initializes the minimum and maximum points. + /// This constructor initializes the minimum and maximum points. GfRange3f(const GfVec3f &min, const GfVec3f &max) : _min(min), _max(max) { } - //! Returns the minimum value of the range. + /// Returns the minimum value of the range. const GfVec3f &GetMin() const { return _min; } - //! Returns the maximum value of the range. + /// Returns the maximum value of the range. const GfVec3f &GetMax() const { return _max; } - //! Returns the size of the range. + /// Returns the size of the range. GfVec3f GetSize() const { return _max - _min; } - //! Sets the minimum value of the range. + /// Sets the minimum value of the range. void SetMin(const GfVec3f &min) { _min = min; } - //! Sets the maximum value of the range. + /// Sets the maximum value of the range. void SetMax(const GfVec3f &max) { _max = max; } - //! Returns whether the range is empty (max < min). + /// Returns whether the range is empty (max < min). bool IsEmpty() const { return _min[0] > _max[0] || _min[1] > _max[1] || _min[2] > _max[2]; } - //! Modifies the range if necessary to surround the given value. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given value. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfVec3f &point) { UnionWith(point); } - //! Modifies the range if necessary to surround the given range. - // \warning Deprecated - use \c UnionWith instead. + /// Modifies the range if necessary to surround the given range. + /// \deprecated Use UnionWith() instead. void ExtendBy(const GfRange3f &range) { UnionWith(range); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. bool Contains(const GfVec3f &point) const { return (point[0] >= _min[0] && point[0] <= _max[0] && point[1] >= _min[1] && point[1] <= _max[1] && point[2] >= _min[2] && point[2] <= _max[2]); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool Contains(const GfRange3f &range) const { - return Contains(range._min) && Contains(range._max); + return Contains(range._min) && Contains(range._max); } - //! - // Returns true if the \p point is located inside the range. - // As with all operations of this type, the range is assumed to include its - // extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p point is located inside the range. As with all + /// operations of this type, the range is assumed to include its extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfVec3f &point) const { return Contains(point); } - //! - // Returns true if the \p range is located entirely inside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. - // \warning Deprecated - use \c Contains instead. + /// Returns true if the \p range is located entirely inside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. + /// \deprecated Use Contains() instead. bool IsInside(const GfRange3f &range) const { - return Contains(range); + return Contains(range); } - //! - // Returns true if the \p range is located entirely outside the range. - // As with all operations of this type, the ranges are assumed to - // include their extrema. + /// Returns true if the \p range is located entirely outside the range. As + /// with all operations of this type, the ranges are assumed to include + /// their extrema. bool IsOutside(const GfRange3f &range) const { return ((range._max[0] < _min[0] || range._min[0] > _max[0]) || (range._max[1] < _min[1] || range._min[1] > _max[1]) || (range._max[2] < _min[2] || range._min[2] > _max[2])); } - //! Returns the smallest \c GfRange3f which contains both \p a and \p b + /// Returns the smallest \c GfRange3f which contains both \p a and \p b. static GfRange3f GetUnion(const GfRange3f &a, const GfRange3f &b) { - GfRange3f res = a; - _FindMin(res._min,b._min); - _FindMax(res._max,b._max); - return res; + GfRange3f res = a; + _FindMin(res._min,b._min); + _FindMax(res._max,b._max); + return res; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange3f &UnionWith(const GfRange3f &b) { - _FindMin(_min,b._min); - _FindMax(_max,b._max); - return *this; + _FindMin(_min,b._min); + _FindMax(_max,b._max); + return *this; } - //! Extend \p this to include \p b + /// Extend \p this to include \p b. const GfRange3f &UnionWith(const GfVec3f &b) { - _FindMin(_min,b); - _FindMax(_max,b); - return *this; + _FindMin(_min,b); + _FindMax(_max,b); + return *this; } - //! Returns the smallest \c GfRange3f which contains both \p a and \p b - // \warning Deprecated - use \c GetUnion instead. + /// Returns the smallest \c GfRange3f which contains both \p a and \p b + /// \deprecated Use GetUnion() instead. static GfRange3f Union(const GfRange3f &a, const GfRange3f &b) { return GetUnion(a, b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange3f &Union(const GfRange3f &b) { return UnionWith(b); } - //! Extend \p this to include \p b - // \warning Deprecated - use \c UnionWith instead. + /// Extend \p this to include \p b. + /// \deprecated Use UnionWith() instead. const GfRange3f &Union(const GfVec3f &b) { return UnionWith(b); } - //! Returns a \c GfRange3f that describes the intersection of \p a and \p b + /// Returns a \c GfRange3f that describes the intersection of \p a and \p b. static GfRange3f GetIntersection(const GfRange3f &a, const GfRange3f &b) { - GfRange3f res = a; - _FindMax(res._min,b._min); - _FindMin(res._max,b._max); - return res; + GfRange3f res = a; + _FindMax(res._min,b._min); + _FindMin(res._max,b._max); + return res; } - //! Returns a \c GfRange3f that describes the intersection of \p a and \p b - // \warning Deprecated - use \c GetIntersection instead. + /// Returns a \c GfRange3f that describes the intersection of \p a and \p b. + /// \deprecated Use GetIntersection() instead. static GfRange3f Intersection(const GfRange3f &a, const GfRange3f &b) { return GetIntersection(a, b); } - //! Modifies this range to hold its intersection with \p b and returns the - // result + /// Modifies this range to hold its intersection with \p b and returns the + /// result const GfRange3f &IntersectWith(const GfRange3f &b) { - _FindMax(_min,b._min); - _FindMin(_max,b._max); - return *this; + _FindMax(_min,b._min); + _FindMin(_max,b._max); + return *this; } - //! Modifies this range to hold its intersection with \p b and returns the - // result - // \warning Deprecated - use \c IntersectWith instead. + /// Modifies this range to hold its intersection with \p b and returns the + /// result. + /// \deprecated Use IntersectWith() instead. const GfRange3f &Intersection(const GfRange3f &b) { return IntersectWith(b); } - //! unary sum. + /// unary sum. GfRange3f operator +=(const GfRange3f &b) { - _min += b._min; - _max += b._max; - return *this; + _min += b._min; + _max += b._max; + return *this; } - //! unary difference. + /// unary difference. GfRange3f operator -=(const GfRange3f &b) { - _min -= b._max; - _max -= b._min; - return *this; + _min -= b._max; + _max -= b._min; + return *this; } - //! unary multiply + /// unary multiply. GfRange3f operator *=(double m) { - if (m > 0) { - _min *= m; - _max *= m; - } else { - GfVec3f tmp = _min; - _min = _max * m; - _max = tmp * m; - } - return *this; - } - //! unary division. + if (m > 0) { + _min *= m; + _max *= m; + } else { + GfVec3f tmp = _min; + _min = _max * m; + _max = tmp * m; + } + return *this; + } + + /// unary division. GfRange3f operator /=(double m) { - return *this *= (1.0 / m); + return *this *= (1.0 / m); } - //! binary sum. + /// binary sum. GfRange3f operator +(const GfRange3f &b) const { - return GfRange3f(_min + b._min, _max + b._max); + return GfRange3f(_min + b._min, _max + b._max); } - //! binary difference. + /// binary difference. GfRange3f operator -(const GfRange3f &b) const { - return GfRange3f(_min - b._max, _max - b._min); + return GfRange3f(_min - b._max, _max - b._min); } - //! scalar multiply. + /// scalar multiply. friend GfRange3f operator *(double m, const GfRange3f &r) { - return (m > 0 ? - GfRange3f(r._min*m, r._max*m) : - GfRange3f(r._max*m, r._min*m)); + return (m > 0 ? + GfRange3f(r._min*m, r._max*m) : + GfRange3f(r._max*m, r._min*m)); } - //! scalar multiply. + /// scalar multiply. friend GfRange3f operator *(const GfRange3f &r, double m) { - return (m > 0 ? - GfRange3f(r._min*m, r._max*m) : - GfRange3f(r._max*m, r._min*m)); + return (m > 0 ? + GfRange3f(r._min*m, r._max*m) : + GfRange3f(r._max*m, r._min*m)); } - //! scalar divide. + /// scalar divide. friend GfRange3f operator /(const GfRange3f &r, double m) { - return r * (1.0 / m); + return r * (1.0 / m); } - //! hash. + /// hash. friend inline size_t hash_value(const GfRange3f &r) { size_t h = 0; boost::hash_combine(h, r._min); boost::hash_combine(h, r._max); return h; - } + } - //! The min and max points must match exactly for equality. + /// The min and max points must match exactly for equality. bool operator ==(const GfRange3f &b) const { - return (_min == b._min && _max == b._max); + return (_min == b._min && _max == b._max); } + bool operator !=(const GfRange3f &b) const { return !(*this == b); } - //! Compare this range to a GfRange3d. - // - // The values must match exactly and it does exactly what you - // might expect when comparing float and double values. - inline bool operator ==(const GfRange3d& other) const; - inline bool operator !=(const GfRange3d& other) const; + /// Compare this range to a GfRange3d. + /// + /// The values must match exactly and it does exactly what you might + /// expect when comparing float and double values. + GF_API inline bool operator ==(const GfRange3d& other) const; + GF_API inline bool operator !=(const GfRange3d& other) const; - //! Compute the squared distance from a point to the range. + /// Compute the squared distance from a point to the range. + GF_API double GetDistanceSquared(const GfVec3f &p) const; - //! Returns the ith corner of the range, in the following order: - // LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, - // D/U is down/up, and B/F is back/front. + /// Returns the ith corner of the range, in the following order: + /// LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, + /// D/U is down/up, and B/F is back/front. + GF_API GfVec3f GetCorner(size_t i) const; - //! Returns the ith octant of the range, in the following order: - // LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, - // D/U is down/up, and B/F is back/front. + /// Returns the ith octant of the range, in the following order: + /// LDB, RDB, LUB, RUB, LDF, RDF, LUF, RUF. Where L/R is left/right, + /// D/U is down/up, and B/F is back/front. + GF_API GfRange3f GetOctant(size_t i) const; - //! The unit cube. + /// The unit cube. + GF_API static const GfRange3f UnitCube; private: - //! Minimum and maximum points. + /// Minimum and maximum points. GfVec3f _min, _max; - //! Extends minimum point if necessary to contain given point + /// Extends minimum point if necessary to contain given point. static void _FindMin(GfVec3f &dest, const GfVec3f &point) { if (point[0] < dest[0]) dest[0] = point[0]; if (point[1] < dest[1]) dest[1] = point[1]; if (point[2] < dest[2]) dest[2] = point[2]; } - //! Extends maximum point if necessary to contain given point + /// Extends maximum point if necessary to contain given point. static void _FindMax(GfVec3f &dest, const GfVec3f &point) { if (point[0] > dest[0]) dest[0] = point[0]; if (point[1] > dest[1]) dest[1] = point[1]; @@ -349,9 +346,9 @@ class GfRange3f } }; -/// Output a GfRange3f +/// Output a GfRange3f. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfRange3f const &); +GF_API std::ostream& operator<<(std::ostream &, GfRange3f const &); #include "pxr/base/gf/range3d.h" diff --git a/pxr/base/lib/gf/ray.cpp b/pxr/base/lib/gf/ray.cpp index 9ca401d7e3..5b69c05970 100644 --- a/pxr/base/lib/gf/ray.cpp +++ b/pxr/base/lib/gf/ray.cpp @@ -352,7 +352,7 @@ GfRay::Intersect(const GfVec3d& center, double radius, C = x3*x3 + y3*y3 + z3*z3 + x1*x1 + y1*y1 + z1*z1 - 2*(x3*x1 +y3*y1 +z3*z1) - radius*radius; - return _SolveQuadratic(A, B, C, enterDistance, exitDistance) > 0; + return _SolveQuadratic(A, B, C, enterDistance, exitDistance); } bool @@ -373,7 +373,7 @@ GfRay::Intersect(const GfVec3d &origin, double b = 2.0 * GfDot(u, v); double c = GfDot(v, v) - GfSqr(radius); - return _SolveQuadratic(a, b, c, enterDistance, exitDistance) > 0; + return _SolveQuadratic(a, b, c, enterDistance, exitDistance); } bool diff --git a/pxr/base/lib/gf/ray.h b/pxr/base/lib/gf/ray.h index ffc0f421ec..0324eb171e 100644 --- a/pxr/base/lib/gf/ray.h +++ b/pxr/base/lib/gf/ray.h @@ -24,142 +24,127 @@ #ifndef GF_RAY_H #define GF_RAY_H +/// \file gf/ray.h +/// \ingroup group_gf_BasicGeometry + #include "pxr/base/gf/matrix4d.h" +#include "pxr/base/gf/api.h" #include #include #include -//! -// \file ray.h -// \ingroup group_gf_BasicGeometry -// - - class GfLine; class GfLineSeg; class GfPlane; class GfRange3d; -//! -// \class GfRay ray.h "pxr/base/gf/ray.h" -// \ingroup group_gf_BasicGeometry -// \brief Basic type: Ray used for intersection testing -// -// This class represents a three-dimensional ray in space, typically -// used for intersection testing. It consists of an origin and a -// direction. -// -// Note that by default a \c GfRay does not normalize its direction -// vector to unit length. -// -// Note for ray intersections, the start point is included in the computations, -// i.e., a distance of zero is defined to be intersecting. -// - +/// \class GfRay +/// \ingroup group_gf_BasicGeometry +/// +/// Basic type: Ray used for intersection testing +/// +/// This class represents a three-dimensional ray in space, typically +/// used for intersection testing. It consists of an origin and a +/// direction. +/// +/// Note that by default a \c GfRay does not normalize its direction +/// vector to unit length. +/// +/// Note for ray intersections, the start point is included in the computations, +/// i.e., a distance of zero is defined to be intersecting. +/// class GfRay { public: - //! - // The default constructor leaves the ray parameters undefined. + /// The default constructor leaves the ray parameters undefined. GfRay() { } - //! - // This constructor takes a starting point and a direction. + /// This constructor takes a starting point and a direction. GfRay(const GfVec3d &startPoint, const GfVec3d &direction) { SetPointAndDirection(startPoint, direction); } - //! - // Sets the ray by specifying a starting point and a direction. + /// Sets the ray by specifying a starting point and a direction. + GF_API void SetPointAndDirection(const GfVec3d &startPoint, const GfVec3d &direction); - //! - // Sets the ray by specifying a starting point and an ending point. + /// Sets the ray by specifying a starting point and an ending point. + GF_API void SetEnds(const GfVec3d &startPoint, const GfVec3d &endPoint); - //! - // Returns the starting point of the segment. + /// Returns the starting point of the segment. const GfVec3d & GetStartPoint() const { return _startPoint; } - //! - // Returns the direction vector of the segment. This is not - // guaranteed to be unit length. + /// Returns the direction vector of the segment. This is not guaranteed to + /// be unit length. const GfVec3d & GetDirection() const { return _direction; } - //! - // Returns the point that is \p distance units from the starting - // point along the direction vector, expressed in parametic - // distance. + /// Returns the point that is \p distance units from the starting point + /// along the direction vector, expressed in parametic distance. GfVec3d GetPoint(double distance) const { return _startPoint + distance * _direction; } - //! - // Transforms the ray by the given matrix. + /// Transforms the ray by the given matrix. + GF_API GfRay & Transform(const GfMatrix4d &matrix); - //! - // Returns the point on the ray that is closest to \p point. If \p - // rayDistance is not \c NULL, it will be set to the parametric - // distance along the ray of the closest point. + /// Returns the point on the ray that is closest to \p point. If \p + /// rayDistance is not \c NULL, it will be set to the parametric distance + /// along the ray of the closest point. + GF_API GfVec3d FindClosestPoint(const GfVec3d &point, double *rayDistance = NULL) const; - //! - // Component-wise equality test. The starting points, directions, - // and lengths must match exactly for rays to be considered - // equal. + /// Component-wise equality test. The starting points, directions, and + /// lengths must match exactly for rays to be considered equal. bool operator ==(const GfRay &r) const { return (_startPoint == r._startPoint && _direction == r._direction); } - //! - // Component-wise inequality test. The starting points, - // directions, and lengths must match exactly for rays to be - // considered equal. + /// Component-wise inequality test. The starting points, directions, and + /// lengths must match exactly for rays to be considered equal. bool operator !=(const GfRay &r) const { return ! (*this == r); } - //! - // \name Intersection methods. - // The methods in this group intersect the ray with a geometric - // entity. - //@{ + /// \name Intersection methods. + /// + /// The methods in this group intersect the ray with a geometric entity. + /// + ///@{ - //! - // Intersects the ray with the triangle formed by points \p p0, \p - // p1, and \p p2, returning \c true if it hits. If there is an - // intersection, it also returns the parametric distance to the - // intersection point in \p distance, the barycentric coordinates - // of the intersection point in \p barycentricCoords and the - // front-facing flag in \p frontFacing. The barycentric - // coordinates are defined with respect to the three vertices - // taken in order. The front-facing flag is \c true if the - // intersection hit the side of the triangle that is formed when - // the vertices are ordered counter-clockwise (right-hand rule). - // If any of the return pointers are \c NULL, the corresponding - // values are not returned. - // - // If the distance to the intersection is greater than \p maxDist, - // then the method will return false. - // - // Barycentric coordinates are defined to sum to 1 and satisfy - // this relationsip: - // \code - // intersectionPoint = (barycentricCoords[0] * p0 + - // barycentricCoords[1] * p1 + - // barycentricCoords[2] * p2); - // \endcode + /// Intersects the ray with the triangle formed by points \p p0, \p p1, + /// and \p p2, returning \c true if it hits. If there is an intersection, + /// it also returns the parametric distance to the intersection point in + /// \p distance, the barycentric coordinates of the intersection point in + /// \p barycentricCoords and the front-facing flag in \p frontFacing. The + /// barycentric coordinates are defined with respect to the three vertices + /// taken in order. The front-facing flag is \c true if the intersection + /// hit the side of the triangle that is formed when the vertices are + /// ordered counter-clockwise (right-hand rule). If any of the return + /// pointers are \c NULL, the corresponding values are not returned. + /// + /// If the distance to the intersection is greater than \p maxDist, then + /// the method will return false. + /// + /// Barycentric coordinates are defined to sum to 1 and satisfy this + /// relationsip: + /// \code + /// intersectionPoint = (barycentricCoords[0] * p0 + + /// barycentricCoords[1] * p1 + + /// barycentricCoords[2] * p2); + /// \endcode + GF_API bool Intersect(const GfVec3d &p0, const GfVec3d &p1, const GfVec3d &p2, @@ -169,117 +154,115 @@ class GfRay { double maxDist = std::numeric_limits::infinity()) const; - //! - // Intersects the ray with a plane, returning \c true if the ray - // is not parallel to the plane and the intersection is within the - // ray bounds. If there is an intersection, it also returns the - // parametric distance to the intersection point in \p distance - // and the front-facing flag in \p frontFacing, if they are not \c - // NULL. The front-facing flag is \c true if the intersection is - // on the side of the plane in which its normal points. + /// Intersects the ray with a plane, returning \c true if the ray is not + /// parallel to the plane and the intersection is within the ray bounds. + /// If there is an intersection, it also returns the parametric distance + /// to the intersection point in \p distance and the front-facing flag in + /// \p frontFacing, if they are not \c NULL. The front-facing flag is \c + /// true if the intersection is on the side of the plane in which its + /// normal points. + GF_API bool Intersect(const GfPlane &plane, double *distance = NULL, bool *frontFacing = NULL) const; - //! - // Intersects the ray with an axis-aligned box, returning \c true - // if the ray intersects it at all within bounds. If there is an - // intersection, this also returns the parametric distances to the - // two intersection points in \p enterDistance and - // \p exitDistance. + /// Intersects the ray with an axis-aligned box, returning \c true if the + /// ray intersects it at all within bounds. If there is an intersection, + /// this also returns the parametric distances to the two intersection + /// points in \p enterDistance and \p exitDistance. + GF_API bool Intersect(const GfRange3d &box, double *enterDistance = NULL, double *exitDistance = NULL) const; - //! - // Intersects the ray with a sphere, returning \c true if the ray - // intersects it at all within bounds. If there is an intersection, returns - // the parametric distance to the two intersection points in - // \p enterDistance and \p exitDistance. + /// Intersects the ray with a sphere, returning \c true if the ray + /// intersects it at all within bounds. If there is an intersection, + /// returns the parametric distance to the two intersection points in \p + /// enterDistance and \p exitDistance. + GF_API bool Intersect(const GfVec3d ¢er, double radius, double *enterDistance = NULL, double *exitDistance = NULL ) const; - //! - // Intersects the ray with an infinite cylinder, with axis \p axis, - // centered at the \p origin, with radius \p radius. - // - // Returns \c true if the ray intersects it at all within bounds. If there - // is an intersection, returns the parametric distance to the two - // intersection points in \p enterDistance and \p exitDistance. - // - // Note this method does not validate whether the radius is valid. + /// Intersects the ray with an infinite cylinder, with axis \p axis, + /// centered at the \p origin, with radius \p radius. + /// + /// Returns \c true if the ray intersects it at all within bounds. If + /// there is an intersection, returns the parametric distance to the two + /// intersection points in \p enterDistance and \p exitDistance. + /// + /// Note this method does not validate whether the radius is valid. + GF_API bool Intersect(const GfVec3d &origin, const GfVec3d &axis, const double radius, double *enterDistance = NULL, double *exitDistance = NULL) const; - //! - // Intersects the ray with an infinite non-double cone, centered at \p origin, - // with axis \p axis, radius \p radius and apex at \p height. - // - // Returns \c true if the ray intersects it at all within bounds. If there - // is an intersection, returns the parametric distance to the two - // intersection points in \p enterDistance and \p exitDistance. - // - // Note this method does not validate whether the radius are height are - // valid. + /// Intersects the ray with an infinite non-double cone, centered at \p + /// origin, with axis \p axis, radius \p radius and apex at \p height. + /// + /// Returns \c true if the ray intersects it at all within bounds. If + /// there is an intersection, returns the parametric distance to the two + /// intersection points in \p enterDistance and \p exitDistance. + /// + /// Note this method does not validate whether the radius are height are + /// valid. + GF_API bool Intersect(const GfVec3d &origin, const GfVec3d &axis, const double radius, const double height, double *enterDistance = NULL, double *exitDistance = NULL) const; - //@} + ///@} private: + GF_API friend bool GfFindClosestPoints( const GfRay &, const GfLine &, GfVec3d *, GfVec3d *, double *, double * ); + GF_API friend bool GfFindClosestPoints( const GfRay &, const GfLineSeg &, GfVec3d *, GfVec3d *, double *, double * ); - //! - // Solves the quadratic equation returning the solutions, if defined, in - // \p enterDistance and \p exitDistance, where \p enterDistance is less than - // or equal to \p exitDistance. + /// Solves the quadratic equation returning the solutions, if defined, in + /// \p enterDistance and \p exitDistance, where \p enterDistance is less + /// than or equal to \p exitDistance. bool _SolveQuadratic(const double a, const double b, const double c, double *enterDistance = NULL, double *exitDistance = NULL) const; - //! The starting point of the ray. + /// The starting point of the ray. GfVec3d _startPoint; - //! The direction vector. + /// The direction vector. GfVec3d _direction; }; -//! -// Computes the closest points between a ray and a line. The two points -// are returned in \p rayPoint and \p linePoint. The parametric -// distance of each point on the lines is returned in \p rayDistance and -// \p lineDistance. -// -// This returns \c false if the lines were close enough to -// parallel that no points could be computed; in this case, the -// other return values are undefined. +/// Computes the closest points between a ray and a line. The two points are +/// returned in \p rayPoint and \p linePoint. The parametric distance of each +/// point on the lines is returned in \p rayDistance and \p lineDistance. +/// +/// This returns \c false if the lines were close enough to parallel that no +/// points could be computed; in this case, the other return values are +/// undefined. +GF_API bool GfFindClosestPoints( const GfRay &ray, const GfLine &line, GfVec3d *rayPoint = nullptr, GfVec3d *linePoint = nullptr, double *rayDistance = nullptr, double *lineDistance = nullptr ); -//! -// Computes the closest points between a ray and a line segment. -// The two points are returned in \p rayPoint and \p segPoint. -// The parametric distance of each point is returned in \p rayDistance -// and \p segDistance. -// -// This returns \c false if the lines were close enough to -// parallel that no points could be computed; in this case, the -// other return values are undefined. +/// Computes the closest points between a ray and a line segment. The two +/// points are returned in \p rayPoint and \p segPoint. The parametric +/// distance of each point is returned in \p rayDistance and \p segDistance. +/// +/// This returns \c false if the lines were close enough to parallel that no +/// points could be computed; in this case, the other return values are +/// undefined. +GF_API bool GfFindClosestPoints( const GfRay &ray, const GfLineSeg &seg, GfVec3d *rayPoint = nullptr, GfVec3d *segPoint = nullptr, @@ -288,7 +271,6 @@ bool GfFindClosestPoints( const GfRay &ray, const GfLineSeg &seg, /// Output a GfRay using the format [(x y z) >> (x y z)]. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream&, const GfRay&); - +GF_API std::ostream& operator<<(std::ostream&, const GfRay&); #endif // GF_RAY_H diff --git a/pxr/base/lib/gf/rect2i.h b/pxr/base/lib/gf/rect2i.h index a927b3fd29..fd8dfced0a 100644 --- a/pxr/base/lib/gf/rect2i.h +++ b/pxr/base/lib/gf/rect2i.h @@ -24,254 +24,198 @@ #ifndef GF_RECT2I_H #define GF_RECT2I_H +/// \file gf/rect2i.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/math.h" #include "pxr/base/gf/vec2i.h" - +#include "pxr/base/gf/api.h" #include #include -//! -// \file rect2i.h -// \ingroup group_gf_LinearAlgebra -// - -/*! - * \class GfRect2i rect2i.h "pxr/base/gf/rect2i.h" - * \ingroup group_gf_LinearAlgebra - * \brief A 2D rectangle with integer coordinates for windowing operations. - * - * A rectangle is internally represented as an upper left corner and a - * bottom right corner, but it is normally expressed as an upper left - * corner and a size. - * - * Note that the size (width and height) of a rectangle might be - * different from what you are used to. If the top left corner and the - * bottom right corner are the same, then the height and the width of - * the rectangle will both be one. - * - * Specifically, width = right - left + 1 and - * height = bottom - top + 1. The design corresponds to - * rectangular spaces used by drawing functions, where - * the width and height denote a number of pixels. For example, - * drawing a rectangle with width and height one draws a single pixel. - * - * The default coordinate system has origin (0,0) in the top left - * corner, the positive direction of the y axis is downward and the - * positive x axis is to the right. - */ - +/// \class GfRect2i +/// \ingroup group_gf_LinearAlgebra +/// +/// A 2D rectangle with integer coordinates for windowing operations. +/// +/// A rectangle is internally represented as an upper left corner and a +/// bottom right corner, but it is normally expressed as an upper left +/// corner and a size. +/// +/// Note that the size (width and height) of a rectangle might be +/// different from what you are used to. If the top left corner and the +/// bottom right corner are the same, then the height and the width of +/// the rectangle will both be one. +/// +/// Specifically, width = right - left + 1 and +/// height = bottom - top + 1. The design corresponds to +/// rectangular spaces used by drawing functions, where +/// the width and height denote a number of pixels. For example, +/// drawing a rectangle with width and height one draws a single pixel. +/// +/// The default coordinate system has origin (0,0) in the top left +/// corner, the positive direction of the y axis is downward and the +/// positive x axis is to the right. +/// class GfRect2i { public: - //! Constructs an empty rectangle. + /// Constructs an empty rectangle. GfRect2i(): _lower(0,0), _higher(-1,-1) { } - /*! - * \brief Constructs a rectangle with \p topLeft as the top - * left corner and \p bottomRight as the bottom right corner. - */ + /// Constructs a rectangle with \p topLeft as the top left corner and \p + /// bottomRight as the bottom right corner. GfRect2i(const GfVec2i& topLeft, const GfVec2i& bottomRight) : _lower(topLeft), _higher(bottomRight) { } - /*! - * \brief Constructs a rectangle with \p topLeft as the top left - * corner and with the indicated width and height. - */ + /// Constructs a rectangle with \p topLeft as the top left corner and with + /// the indicated width and height. GfRect2i(const GfVec2i& topLeft, int width, int height) : _lower(topLeft), _higher(topLeft + GfVec2i(width-1, height-1)) { } - /*! - * \brief Returns true if the rectangle is a null rectangle. - * - * A null rectangle has both the width and the height set to 0, - * that is - * \code - * GetRight() == GetLeft() - 1 - * \endcode - * and - * \code - * GetBottom() == GetTop() - 1 - * \endcode - * Remember that if \c GetRight() and \c GetLeft() return the same - * value then the rectangle has width 1, and similarly for the height. - * - * A null rectangle is both empty, and not valid. - */ - + /// Returns true if the rectangle is a null rectangle. + /// + /// A null rectangle has both the width and the height set to 0, that is + /// \code + /// GetRight() == GetLeft() - 1 + /// \endcode + /// and + /// \code + /// GetBottom() == GetTop() - 1 + /// \endcode + /// Remember that if \c GetRight() and \c GetLeft() return the same value + /// then the rectangle has width 1, and similarly for the height. + /// + /// A null rectangle is both empty, and not valid. bool IsNull() const { return GetWidth() == 0 && GetHeight() == 0; } - /*! - * \brief Returns true if the rectangle is empty. - * - * An empty rectangle has its left side strictly greater than its - * right side or its top strictly greater than its bottom. - * - * An empty rectangle is not valid. - */ + /// Returns true if the rectangle is empty. + /// + /// An empty rectangle has its left side strictly greater than its right + /// side or its top strictly greater than its bottom. + /// + /// An empty rectangle is not valid. bool IsEmpty() const { return GetWidth() <= 0 || GetHeight() <= 0; } - /*! - * \brief Return true if the rectangle is valid (equivalently, not empty). - */ + /// Return true if the rectangle is valid (equivalently, not empty). bool IsValid() const { return !IsEmpty(); } - /*! - * \brief Returns a normalized rectangle, i.e. one that has a - * non-negative width and height. - * - * \c GetNormalized() swaps left and right to ensure a non-negative width, - * and similarly for top and bottom. - */ - + /// Returns a normalized rectangle, i.e. one that has a non-negative width + /// and height. + /// + /// \c GetNormalized() swaps left and right to ensure a non-negative + /// width, and similarly for top and bottom. + GF_API GfRect2i GetNormalized() const; - /*! - * \brief Returns the lower corner of the rectangle. - */ + /// Returns the lower corner of the rectangle. const GfVec2i& GetLower() const { return _lower; } - - /*! - * \brief Returns the upper corner of the rectangle. - */ + + /// Returns the upper corner of the rectangle. const GfVec2i& GetHigher() const { return _higher; } - /*! - * \brief Return the X value of the left edge. - */ + /// Return the X value of the left edge. int GetLeft() const { return _lower[0]; } - /*! - * \brief Set the X value of the left edge - */ + /// Set the X value of the left edge. void SetLeft(int x) { _lower[0] = x; } - - /*! - * \brief Return the X value of the right edge. - */ + + /// Return the X value of the right edge. int GetRight() const { return _higher[0]; } - /*! - * \brief Set the X value of the right edge - */ + /// Set the X value of the right edge. void SetRight(int x) { _higher[0] = x; } - /*! - * \brief Return the Y value of the top edge. - */ + /// Return the Y value of the top edge. int GetTop() const { return _lower[1]; } - /*! - * \brief Set the Y value of the top edge - */ + /// Set the Y value of the top edge. void SetTop(int y) { _lower[1] = y; } - /*! - * \brief Return the Y value of the bottom edge. - */ + /// Return the Y value of the bottom edge. int GetBottom() const { return _higher[1]; } - /*! - * \brief Set the Y value of the bottom edge - */ + /// Set the Y value of the bottom edge. void SetBottom(int y) { _higher[1] = y; } - /*! - * \brief Sets the lower corner of the rectangle. - */ + /// Sets the lower corner of the rectangle. void SetLower(const GfVec2i& lower) { _lower = lower; } - - /*! - * \brief Sets the upper corner of the rectangle. - */ + + /// Sets the upper corner of the rectangle. void SetHigher(const GfVec2i& higher) { _higher = higher; } - - /*! - * \brief Returns the center point of the rectangle. - */ + + /// Returns the center point of the rectangle. GfVec2i GetCenter() const { return (_lower + _higher) / 2; } - /*! - * \brief Move the rectangle by \p displ. - */ + /// Move the rectangle by \p displ. void Translate(const GfVec2i& displacement) { _lower += displacement; _higher += displacement; } - - /*! - * \brief Return the area of the rectangle - */ + /// Return the area of the rectangle. unsigned long GetArea() const { return (unsigned long)GetWidth() * (unsigned long)GetHeight(); } - /*! - * \brief Returns the size of the rectangle as a vector (width,height). - */ + /// Returns the size of the rectangle as a vector (width,height). GfVec2i GetSize() const { return GfVec2i(GetWidth(), GetHeight()); } - /*! - * \brief Returns the width of the rectangle. - * - * Note that if the left and right sides are coincident, the width is one. - */ + /// Returns the width of the rectangle. + /// + /// \note If the left and right sides are coincident, the width is one. int GetWidth() const { return (_higher[0] - _lower[0]) + 1; } - - /*! - * \brief Returns the height of the rectangle. - * - * Note that if the top and bottom sides are coincident, the height is one. - */ + + /// Returns the height of the rectangle. + /// + /// \note If the top and bottom sides are coincident, the height is one. int GetHeight() const { return (_higher[1] - _lower[1]) + 1; } - /*! - * \brief Computes the intersection of two rectangles - */ + /// Computes the intersection of two rectangles. GfRect2i GetIntersection(const GfRect2i& that) const { if(IsEmpty()) return *this; @@ -284,17 +228,13 @@ class GfRect2i { GfMin(_higher[1], that._higher[1]))); } - /*! - * \brief Computes the intersection of two rectangles - * \warning Deprecated - use GetIntersection instead - */ + /// Computes the intersection of two rectangles. + /// \deprecated Use GetIntersection() instead GfRect2i Intersect(const GfRect2i& that) const { return GetIntersection(that); } - /*! - * \brief Computes the union of two rectangles - */ + /// Computes the union of two rectangles. GfRect2i GetUnion(const GfRect2i& that) const { if(IsEmpty()) return that; @@ -307,17 +247,13 @@ class GfRect2i { GfMax(_higher[1], that._higher[1]))); } - /*! - * \brief Computes the union of two rectangles - * \warning Deprecated - use \c GetUnion instead. - */ + /// Computes the union of two rectangles + /// \deprecated Use GetUnion() instead. GfRect2i Union(const GfRect2i& that) const { return GetUnion(that); } - /*! - * \brief Is the specified point in the rectangle? - */ + /// Returns true if the specified point in the rectangle. bool Contains(const GfVec2i& p) const { return ((p[0] >= _lower[0]) && (p[0] <= _higher[0]) && (p[1] >= _lower[1]) && (p[1] <= _higher[1])); @@ -330,23 +266,18 @@ class GfRect2i { return h; } - /*! - * \brief Returns true if \p r1 and \p r2 are equal. - */ + /// Returns true if \p r1 and \p r2 are equal. friend bool operator==(const GfRect2i& r1, const GfRect2i& r2) { return r1._lower == r2._lower && r1._higher == r2._higher; } - /*! - * \brief Returns true if \p r1 and \p r2 are different. - */ + /// Returns true if \p r1 and \p r2 are different. friend bool operator!=(const GfRect2i& r1, const GfRect2i& r2) { return !(r1 == r2); } - /*! - * \brief Computes the union of two rectangles (see GetUnion) - */ + /// Computes the union of two rectangles. + /// \see GetUnion() GfRect2i operator += (const GfRect2i& that) { *this = GetUnion(that); return *this; @@ -364,6 +295,6 @@ class GfRect2i { /// Output a GfRect2i using the format [(x y):(x y)]. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream&, const GfRect2i&); +GF_API std::ostream& operator<<(std::ostream&, const GfRect2i&); #endif diff --git a/pxr/base/lib/gf/rgb.h b/pxr/base/lib/gf/rgb.h index d87ed38f30..00f1924e52 100644 --- a/pxr/base/lib/gf/rgb.h +++ b/pxr/base/lib/gf/rgb.h @@ -24,243 +24,250 @@ #ifndef GF_RGB_H #define GF_RGB_H +/// \file gf/rgb.h +/// \ingroup group_gf_Color + #include "pxr/base/gf/math.h" #include "pxr/base/gf/vec3f.h" +#include "pxr/base/gf/api.h" #include class GfMatrix4d; -//! -// \file rgb.h -// \ingroup group_gf_Color -// - -//! \class GfRGB rgb.h "pxr/base/gf/rgb.h" -// \brief A color represented as 3 floats for red, green, and blue. -// -// The \c GfRGB class contains three floats that represent an RGB -// color, in the order red, green, blue. -// Conversions to and from some other color spaces are provided. - +/// \class GfRGB +/// +/// A color represented as 3 floats for red, green, and blue. +/// +/// The \c GfRGB class contains three floats that represent an RGB +/// color, in the order red, green, blue. +/// Conversions to and from some other color spaces are provided. +/// class GfRGB { public: - //! The default constructor creates an invalid color. + /// The default constructor creates an invalid color. GfRGB() { Set(NAN, NAN, NAN); } - //! This constructor initializes the color to grey. + /// This constructor initializes the color to grey. explicit GfRGB(int bw) { _rgb[0] = _rgb[1] = _rgb[2] = bw; } explicit GfRGB(GfVec3f const &v) : _rgb(v) {} - - //! This constructor initializes the color to grey. + + /// This constructor initializes the color to grey. explicit GfRGB(float grey) : _rgb(grey, grey, grey) {} - //! Constructor that takes an array of 3 floats. + /// Constructor that takes an array of 3 floats. explicit GfRGB(const float rgb[3]) : _rgb(rgb) {} - //! Constructor that takes individual red, green, and blue values. + /// Constructor that takes individual red, green, and blue values. GfRGB(float red, float green, float blue) : _rgb(red, green, blue) {} - //! Sets the color from an array of 3 floats. + /// Sets the color from an array of 3 floats. GfRGB &Set(const float rgb[3]) { _rgb.Set(rgb); return *this; } - //! Sets the color to individual red, green, and blue values. + /// Sets the color to individual red, green, and blue values. GfRGB &Set(float red, float green, float blue) { _rgb.Set(red, green, blue); return *this; } - - //! Returns whether or not the color is valid. By convention, a color - // is valid if the first color component is not NAN. + + /// Returns whether or not the color is valid. By convention, a color is + /// valid if the first color component is not NAN. bool IsValid() const { return !isnan(_rgb[0]); } - //! Returns the RGB color as a \c GfVec3f. + /// Returns the RGB color as a \c GfVec3f. const GfVec3f &GetVec() const { return _rgb; } - - //! Returns the RGB color as an array of 3 floats. + + /// Returns the RGB color as an array of 3 floats. const float *GetArray() const { return _rgb.GetArray(); } - //! Accesses indexed component of color as a modifiable l-value. + /// Accesses indexed component of color as a modifiable l-value. float &operator [](int i) { return _rgb[i]; } - //! Accesses indexed component of color as a \c const l-value. + /// Accesses indexed component of color as a \c const l-value. const float &operator [](int i) const { return _rgb[i]; } - //! Clamps each component of the color to be in the given range. + /// Clamps each component of the color to be in the given range. void Clamp(float min = 0.0, float max = 1.0) { _rgb[0] = GfClamp(_rgb[0], min, max); _rgb[1] = GfClamp(_rgb[1], min, max); _rgb[2] = GfClamp(_rgb[2], min, max); } - //! All components must match exactly for colors to be considered equal. + /// All components must match exactly for colors to be considered equal. bool operator ==(const GfRGB &c) const { return _rgb == c._rgb; } - //! Any component may differ - bool operator !=(const GfRGB &c) const { + /// Any component may differ + bool operator !=(const GfRGB &c) const { return !(*this == c); } - - //! Check to see if all components are set to 0. + + /// Check to see if all components are set to 0. bool IsBlack() const { return _rgb == GfVec3f(0); } - //! Check to see if all components are set to 1. + /// Check to see if all components are set to 1. bool IsWhite() const { return _rgb == GfVec3f(1,1,1); } - //! Component-wise color addition. + /// Component-wise color addition. GfRGB &operator +=(const GfRGB &c) { _rgb += c._rgb; return *this; } - //! Component-wise color subtraction. + /// Component-wise color subtraction. GfRGB &operator -=(const GfRGB &c) { _rgb -= c._rgb; return *this; } - //! Component-wise color multiplication. + /// Component-wise color multiplication. GfRGB &operator *=(const GfRGB &c) { _rgb = GfCompMult(_rgb, c._rgb); return *this; } - //! Component-wise color division. + /// Component-wise color division. GfRGB &operator /=(const GfRGB &c) { _rgb = GfCompDiv(_rgb, c._rgb); return *this; } - //! Component-wise scalar multiplication. + /// Component-wise scalar multiplication. GfRGB &operator *=(float d) { _rgb *= d; return *this; } - //! Component-wise scalar division. + /// Component-wise scalar division. GfRGB &operator /=(float d) { _rgb /= d; return *this; } - //! Returns component-wise multiplication of colors \p c1 and \p c2. - // \warning this is \em not a dot product operator, as it is with vectors. - friend GfRGB operator *(const GfRGB &c1, const GfRGB &c2) { - return GfRGB(GfCompMult(c1._rgb, c2._rgb)); + /// Returns component-wise multiplication of colors \p c1 and \p c2. + /// \warning this is \em not a dot product operator, as it is with vectors. + friend GfRGB operator *(const GfRGB &c1, const GfRGB &c2) { + return GfRGB(GfCompMult(c1._rgb, c2._rgb)); } - //! quotient operator - friend GfRGB operator /(const GfRGB &c1, const GfRGB &c2) { - return GfRGB(GfCompDiv(c1._rgb, c2._rgb)); + /// quotient operator + friend GfRGB operator /(const GfRGB &c1, const GfRGB &c2) { + return GfRGB(GfCompDiv(c1._rgb, c2._rgb)); } - //! addition operator. - friend GfRGB operator +(const GfRGB &c1, const GfRGB &c2) { - return GfRGB(c1._rgb + c2._rgb); + /// addition operator. + friend GfRGB operator +(const GfRGB &c1, const GfRGB &c2) { + return GfRGB(c1._rgb + c2._rgb); } - //! subtraction operator. - friend GfRGB operator -(const GfRGB &c1, const GfRGB &c2) { - return GfRGB(c1._rgb - c2._rgb); + /// subtraction operator. + friend GfRGB operator -(const GfRGB &c1, const GfRGB &c2) { + return GfRGB(c1._rgb - c2._rgb); } - //! multiplication operator. - friend GfRGB operator *(const GfRGB &c, float s) { - return GfRGB(c._rgb * s); + /// multiplication operator. + friend GfRGB operator *(const GfRGB &c, float s) { + return GfRGB(c._rgb * s); } - //! Component-wise binary color/scalar multiplication operator. + /// Component-wise binary color/scalar multiplication operator. friend GfRGB operator *(float s, const GfRGB &c) { return c * s; } - //! Component-wise binary color/scalar division operator. + /// Component-wise binary color/scalar division operator. friend GfRGB operator /(const GfRGB &c, float s) { return c * (1./s); } - //! Tests for equality within a given tolerance, returning true if the - // difference between each component is less than \p tolerance. - friend bool GfIsClose(const GfRGB &v1, const GfRGB &v2, double tolerance); + /// Tests for equality within a given tolerance, returning true if the + /// difference between each component is less than \p tolerance. + friend GF_API bool GfIsClose(const GfRGB &v1, const GfRGB &v2, double tolerance); - //! Returns \code (1-alpha) * a + alpha * b \endcode - // similar to GfLerp for other vector types. + /// Returns \code (1-alpha) * a + alpha * b \endcode similar to GfLerp for + /// other vector types. friend GfRGB GfLerp(float alpha, const GfRGB &a, const GfRGB &b) { return (1.0-alpha) * a + alpha * b; } - //! \name Color-space conversions. - // The methods in this group convert between RGB and other color spaces. - //@{ + /// \name Color-space conversions. + /// + /// The methods in this group convert between RGB and other color spaces. + /// + ///@{ - //! Transform the color into an arbitrary space. + /// Transform the color into an arbitrary space. + GF_API GfRGB Transform(const GfMatrix4d &m) const; - //! Transform the color into an arbitrary space. + /// Transform the color into an arbitrary space. + GF_API friend GfRGB operator *(const GfRGB &c, const GfMatrix4d &m); - //! Return the complement of a color. - // (Note that this assumes normalized RGB channels in [0,1] - // and doesn't work with HDR color values.) + /// Return the complement of a color. + /// \note This assumes normalized RGB channels in [0,1] and doesn't work + /// with HDR color values. GfRGB GetComplement() const { return GfRGB(1) - *this; } - //! Return the luminance of a color given a set of RGB - // weighting values. Defaults are Rec.709 weights for - // linear RGB components. + /// Return the luminance of a color given a set of RGB weighting values. + /// Defaults are Rec.709 weights for linear RGB components. float GetLuminance(float wr = 0.2126390, float wg = 0.7151687, float wb = 0.07219232) const { return _rgb[0]*wr + _rgb[1]*wg + _rgb[2]*wb; } - //! Return the luminance of a color given a set of RGB - // weighting values passed as a GfRGB color object. + /// Return the luminance of a color given a set of RGB weighting values + /// passed as a GfRGB color object. float GetLuminance(const GfRGB &coeffs) const { return _rgb[0]*coeffs._rgb[0] + _rgb[1]*coeffs._rgb[1] + _rgb[2]*coeffs._rgb[2]; } - //! Returns the equivalent of this color in HSV space + /// Returns the equivalent of this color in HSV space + GF_API void GetHSV(float *hue, float *sat, float *value) const; - //! Sets this RGB to the RGB equivalent of the given HSV color. + /// Sets this RGB to the RGB equivalent of the given HSV color. + GF_API void SetHSV(float hue, float sat, float value); - //! Given an RGB base and HSV offset, get an RGB color. + /// Given an RGB base and HSV offset, get an RGB color. + GF_API static GfRGB GetColorFromOffset(const GfRGB &offsetBase, const GfRGB &offsetHSV); - //! Given an HSV offset color and an RGB base, get the HSV offset + /// Given an HSV offset color and an RGB base, get the HSV offset + GF_API static GfRGB GetOffsetFromColor(const GfRGB &offsetBase, const GfRGB &offsetColor); - //@} + ///@} private: - //! Color storage. + /// Color storage. GfVec3f _rgb; }; // Friend functions must be declared. -bool GfIsClose(const GfRGB &v1, const GfRGB &v2, double tolerance); -GfRGB operator *(const GfRGB &c, const GfMatrix4d &m); +GF_API bool GfIsClose(const GfRGB &v1, const GfRGB &v2, double tolerance); +GF_API GfRGB operator *(const GfRGB &c, const GfMatrix4d &m); /// Output a GfRGB color using the format (r, g, b). /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream& out, const GfRGB& c); +GF_API std::ostream& operator<<(std::ostream& out, const GfRGB& c); #endif // GF_RGB_H diff --git a/pxr/base/lib/gf/rgba.h b/pxr/base/lib/gf/rgba.h index 7733a50632..c81a581aaf 100644 --- a/pxr/base/lib/gf/rgba.h +++ b/pxr/base/lib/gf/rgba.h @@ -24,98 +24,97 @@ #ifndef GF_RGBA_H #define GF_RGBA_H +/// \file gf/rgba.h +/// \ingroup group_gf_Color + #include "pxr/base/gf/math.h" #include "pxr/base/gf/rgb.h" #include "pxr/base/gf/vec4f.h" +#include "pxr/base/gf/api.h" #include class GfMatrix4d; -//! -// \file rgba.h -// \ingroup group_gf_Color -// - -//! -// \class GfRGBA rgba.h "pxr/base/gf/rgba.h" -// \brief A color represented as 4 floats for red, green, blue, and alpha. -// -// The \c GfRGBA class contains four floats that represent an RGBA -// color, in the order red, green, blue, alpha (opacity). Several -// color operations are provided. - +/// \class GfRGBA +/// +/// A color represented as 4 floats for red, green, blue, and alpha. +/// +/// The \c GfRGBA class contains four floats that represent an RGBA +/// color, in the order red, green, blue, alpha (opacity). Several +/// color operations are provided. +/// class GfRGBA { public: - //! The default constructor creates an invalid color. + /// The default constructor creates an invalid color. GfRGBA() { Set(NAN, NAN, NAN, NAN); } - //! Constructor that takes a \c GfVec4f. + /// Constructor that takes a \c GfVec4f. explicit GfRGBA(const GfVec4f &v) : _rgba(v) {} - //! This constructor initializes the each component to \a grey. + /// This constructor initializes the each component to \a grey. explicit GfRGBA(float grey) : _rgba(grey, grey, grey, grey) {} - //! Constructor that takes an array of 4 floats. + /// Constructor that takes an array of 4 floats. explicit GfRGBA(const float rgba[4]) : _rgba(rgba) {} - //! Constructor that takes individual red, green, and blue values. + /// Constructor that takes individual red, green, and blue values. GfRGBA(float red, float green, float blue) : _rgba(red, green, blue, 1.0) { } - //! Constructor that takes individual red, green, blue, and alpha values. + /// Constructor that takes individual red, green, blue, and alpha values. GfRGBA(float red, float green, float blue, float alpha) : _rgba(red, green, blue, alpha) { } - //! Constructor and implicit conversion from GfRGB that takes an optional - //! alpha value. + /// Constructor and implicit conversion from GfRGB that takes an optional + /// alpha value. GfRGBA(const GfRGB &rgb, float alpha=1.0) : _rgba(rgb[0], rgb[1], rgb[2], alpha) { } - //! Sets the color from an array of 4 floats. + /// Sets the color from an array of 4 floats. GfRGBA &Set(const float rgba[4]) { _rgba.Set(rgba); return *this; } - //! Sets the color to individual red, green, blue, and alpha values. + /// Sets the color to individual red, green, blue, and alpha values. GfRGBA &Set(float red, float green, float blue, float alpha) { _rgba.Set(red, green, blue, alpha); return *this; } - //! Sets the color from a \c GfRGB and an alpha (opacity) value. + /// Sets the color from a \c GfRGB and an alpha (opacity) value. GfRGBA &Set(const GfRGB &rgb, float alpha) { _rgba.Set(rgb[0], rgb[1], rgb[2], alpha); return *this; } - //! Returns the RGBA color as a \c GfVec4f. + /// Returns the RGBA color as a \c GfVec4f. const GfVec4f &GetVec() const { return _rgba; } - //! Returns the RGBA color as an array of 4 floats. + /// Returns the RGBA color as an array of 4 floats. const float *GetArray() const { return _rgba.GetArray(); } - //! Returns whether or not the color is valid. By convention, a color - // is valid if the first color component is not NAN. + /// Returns whether or not the color is valid. By convention, a color is + /// valid if the first color component is not NAN. bool IsValid() const { return !isnan(_rgba[0]); } - //! Accesses indexed component of color as a modifiable l-value. + /// Accesses indexed component of color as a modifiable l-value. float &operator [](int i) { return _rgba[i]; } - //! Accesses indexed component of color as a \c const l-value. + /// Accesses indexed component of color as a \c const l-value. const float &operator [](int i) const { return _rgba[i]; } - //! Clamps each component of the color to be in the given range. + /// Clamps each component of the color to be in the given range. void Clamp(float min = 0.0, float max = 1.0) { _rgba[0] = GfClamp(_rgba[0], min, max); _rgba[1] = GfClamp(_rgba[1], min, max); @@ -123,152 +122,157 @@ class GfRGBA { _rgba[3] = GfClamp(_rgba[3], min, max); } - //! - // Component-wise color equality test. All components must match - // exactly for colors to be considered equal. + /// Component-wise color equality test. All components must match exactly + /// for colors to be considered equal. bool operator ==(const GfRGBA &c) const { return _rgba == c._rgba; } - //! - // Component-wise color inequality test. All components must match - // exactly for colors to be considered equal. + /// Component-wise color inequality test. All components must match + /// exactly for colors to be considered equal. bool operator !=(const GfRGBA &c) const { return ! (*this == c); } - //! Check to see if all color components are set to 0, ignoring alpha. + /// Check to see if all color components are set to 0, ignoring alpha. bool IsBlack() const { return GfVec3f(_rgba[0], _rgba[1], _rgba[2]) == GfVec3f(0); } - //! Check to see if all color components are set to 1, ignoring alpha. + /// Check to see if all color components are set to 1, ignoring alpha. bool IsWhite() const { return GfVec3f(_rgba[0], _rgba[1], _rgba[2]) == GfVec3f(1,1,1); } - //! Return true if \a alpha is 0. + /// Return true if \a alpha is 0. bool IsTransparent() const { return _rgba[3] == 0; } - //! Return true if \a alpha is 1. + /// Return true if \a alpha is 1. bool IsOpaque() const { return _rgba[3] == 1; } - //! Component-wise unary color addition. + /// Component-wise unary color addition. GfRGBA &operator +=(const GfRGBA &c) { _rgba += c._rgba; return *this; } - //! Component-wise unary color subtraction. + /// Component-wise unary color subtraction. GfRGBA &operator -=(const GfRGBA &c) { _rgba -= c._rgba; return *this; } - //! Component-wise color multiplication. + /// Component-wise color multiplication. GfRGBA &operator *=(const GfRGBA &c) { _rgba = GfCompMult(_rgba, c._rgba); return *this; } - //! Component-wise color division. + /// Component-wise color division. GfRGBA &operator /=(const GfRGBA &c) { _rgba = GfCompDiv(_rgba, c._rgba); return *this; } - //! Component-wise scalar multiplication. + /// Component-wise scalar multiplication. GfRGBA &operator *=(double d) { _rgba *= d; return *this; } - //! Component-wise unary scalar division. + /// Component-wise unary scalar division. GfRGBA &operator /=(double d) { _rgba /= d; return *this; } - //! - // Returns component-wise multiplication of colors \p c1 and \p - // c2. Note that this is \em not a dot product operator, as it is - // with vectors. + /// Returns component-wise multiplication of colors \p c1 and \p c2. Note + /// that this is \em not a dot product operator, as it is with vectors. friend GfRGBA operator *(const GfRGBA &c1, const GfRGBA &c2) { - return GfRGBA(GfCompMult(c1._rgba, c2._rgba)); + return GfRGBA(GfCompMult(c1._rgba, c2._rgba)); } - //! quotient operator + /// quotient operator. friend GfRGBA operator /(const GfRGBA &c1, const GfRGBA &c2) { - return GfRGBA(GfCompDiv(c1._rgba, c2._rgba)); + return GfRGBA(GfCompDiv(c1._rgba, c2._rgba)); } - //! Component-wise binary color addition operator. + /// Component-wise binary color addition operator. friend GfRGBA operator +(const GfRGBA &c1, const GfRGBA &c2) { - return GfRGBA(c1._rgba + c2._rgba); + return GfRGBA(c1._rgba + c2._rgba); } - //! Component-wise binary color subtraction operator. + /// Component-wise binary color subtraction operator. friend GfRGBA operator -(const GfRGBA &c1, const GfRGBA &c2) { - return GfRGBA(c1._rgba - c2._rgba); + return GfRGBA(c1._rgba - c2._rgba); } - //! Component-wise binary color/scalar multiplication operator. + /// Component-wise binary color/scalar multiplication operator. friend GfRGBA operator *(const GfRGBA &c, double s) { - return GfRGBA(c._rgba * s); + return GfRGBA(c._rgba * s); } - //! Component-wise binary color/scalar multiplication operator. + /// Component-wise binary color/scalar multiplication operator. friend GfRGBA operator *(double s, const GfRGBA &c) { - return c * s; + return c * s; } - //! Component-wise binary color/scalar division operator. + /// Component-wise binary color/scalar division operator. friend GfRGBA operator /(const GfRGBA &c, double s) { - return c * (1./s); + return c * (1./s); } - //! Tests for equality within a given tolerance, returning true if the - // difference between each component is less than \p tolerance. + /// Tests for equality within a given tolerance, returning true if the + /// difference between each component is less than \p tolerance. + GF_API friend bool GfIsClose(const GfRGBA &v1, const GfRGBA &v2, double tolerance); - //! \name Color-space conversions. - // The methods in this group convert between RGBA and other color spaces. - //@{ + /// \name Color-space conversions. + /// + /// The methods in this group convert between RGBA and other color spaces. + /// + ///@{ - //! Transform the color into an arbitrary space. + /// Transform the color into an arbitrary space. + GF_API GfRGBA Transform(const GfMatrix4d &m) const; - //! Transform the color into an arbitrary space. + /// Transform the color into an arbitrary space. + GF_API friend GfRGBA operator *(const GfRGBA &c, const GfMatrix4d &m); - //! Return the complement of a color. + /// Return the complement of a color. GfRGBA GetComplement() const { return GfRGBA(1) - *this; } - //! Returns the equivalent of this color in HSV space + /// Returns the equivalent of this color in HSV space + GF_API void GetHSV(float *hue, float *sat, float *value) const; - //! Sets this RGB to the RGB equivalent of the given HSV color. + /// Sets this RGB to the RGB equivalent of the given HSV color. + GF_API void SetHSV(float hue, float sat, float value); - //@} + ///@} private: - //! Color storage. + /// Color storage. GfVec4f _rgba; }; // Friend functions must be declared. +GF_API bool GfIsClose(const GfRGBA &v1, const GfRGBA &v2, double tolerance); +GF_API GfRGBA operator *(const GfRGBA &c, const GfMatrix4d &m); /// Output a GfRGBA color using the format (r, g, b, a). /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream& out, const GfRGBA& c); +GF_API std::ostream& operator<<(std::ostream& out, const GfRGBA& c); #endif // TF_RGBA_H diff --git a/pxr/base/lib/gf/rotation.h b/pxr/base/lib/gf/rotation.h index 7c546817d2..b4eb127fdd 100644 --- a/pxr/base/lib/gf/rotation.h +++ b/pxr/base/lib/gf/rotation.h @@ -24,71 +24,64 @@ #ifndef GF_ROTATION_H #define GF_ROTATION_H +/// \file gf/rotation.h +/// \ingroup group_gf_LinearAlgebra #include "pxr/base/gf/quaternion.h" #include "pxr/base/gf/quatd.h" #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/vec3f.h" +#include "pxr/base/gf/api.h" #include #include -//! -// \file rotation.h -// \ingroup group_gf_LinearAlgebra -// - -//! -// \class GfRotation rotation.h "pxr/base/gf/rotation.h" -// \ingroup group_gf_LinearAlgebra -// \brief Basic type: 3-space rotation specification. -// -// This class represents a rotation in 3-space. This stores an axis as -// a normalized vector of 3 \c doubles and an angle in degrees (as a -// double). Rotations follow the right-hand rule: a positive rotation -// about an axis vector appears counter-clockwise when looking from -// the end of the vector toward the origin. -// +/// \class GfRotation +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type: 3-space rotation specification. +/// +/// This class represents a rotation in 3-space. This stores an axis as a +/// normalized vector of 3 \c doubles and an angle in degrees (as a double). +/// Rotations follow the right-hand rule: a positive rotation about an axis +/// vector appears counter-clockwise when looking from the end of the vector +/// toward the origin. +/// class GfRotation { public: - //! - // The default constructor leaves the rotation undefined. + /// The default constructor leaves the rotation undefined. GfRotation() { } - //! - // This constructor initializes the rotation to be \p angle - // degrees about \p axis. + /// This constructor initializes the rotation to be \p angle + /// degrees about \p axis. GfRotation(const GfVec3d &axis, double angle) { SetAxisAngle(axis, angle); } - //! - // This constructor initializes the rotation from a quaternion. + /// This constructor initializes the rotation from a quaternion. GfRotation(const GfQuaternion &quaternion) { SetQuaternion(quaternion); } - //! - // This constructor initializes the rotation from a quaternion. Note that - // this constructor accepts GfQuatf and GfQuath since they implicitly - // convert to GfQuatd. + /// This constructor initializes the rotation from a quaternion. Note that + /// this constructor accepts GfQuatf and GfQuath since they implicitly + /// convert to GfQuatd. GfRotation(const GfQuatd &quat) { SetQuat(quat); } - //! - // This constructor initializes the rotation to one that brings - // the \p rotateFrom vector to align with \p rotateTo. The passed - // vectors need not be unit length. + /// This constructor initializes the rotation to one that brings + /// the \p rotateFrom vector to align with \p rotateTo. The passed + /// vectors need not be unit length. + GF_API GfRotation(const GfVec3d &rotateFrom, const GfVec3d &rotateTo) { SetRotateInto(rotateFrom, rotateTo); } - //! - // Sets the rotation to be \p angle degrees about \p axis. + /// Sets the rotation to be \p angle degrees about \p axis. GfRotation & SetAxisAngle(const GfVec3d &axis, double angle) { _axis = axis; _angle = angle; @@ -97,66 +90,59 @@ class GfRotation { return *this; } - //! - // Sets the rotation from a quaternion. Note that this method accepts - // GfQuatf and GfQuath since they implicitly convert to GfQuatd. + /// Sets the rotation from a quaternion. Note that this method accepts + /// GfQuatf and GfQuath since they implicitly convert to GfQuatd. + GF_API GfRotation & SetQuat(const GfQuatd &quat); - //! - // Sets the rotation from a quaternion. + /// Sets the rotation from a quaternion. GfRotation & SetQuaternion(const GfQuaternion &quat) { return SetQuat(GfQuatd(quat.GetReal(), quat.GetImaginary())); } - - //! - // Sets the rotation to one that brings the \p rotateFrom vector - // to align with \p rotateTo. The passed vectors need not be unit - // length. + + /// Sets the rotation to one that brings the \p rotateFrom vector + /// to align with \p rotateTo. The passed vectors need not be unit + /// length. + GF_API GfRotation & SetRotateInto(const GfVec3d &rotateFrom, const GfVec3d &rotateTo); - - //! - // Sets the rotation to an identity rotation. (This is chosen to - // be 0 degrees around the positive X axis.) + /// Sets the rotation to an identity rotation. + /// (This is chosen to be 0 degrees around the positive X axis.) GfRotation & SetIdentity() { _axis.Set(1.0, 0.0, 0.0); _angle = 0.0; return *this; } - //! - // Returns the axis of rotation. + /// Returns the axis of rotation. const GfVec3d & GetAxis() const { return _axis; } - //! - // Returns the rotation angle in degrees. + /// Returns the rotation angle in degrees. double GetAngle() const { return _angle; } - //! - // Returns the rotation expressed as a quaternion. + /// Returns the rotation expressed as a quaternion. GfQuaternion GetQuaternion() const { auto quat = GetQuat(); return GfQuaternion(quat.GetReal(), quat.GetImaginary()); } - //! - // Returns the rotation expressed as a quaternion. + /// Returns the rotation expressed as a quaternion. + GF_API GfQuatd GetQuat() const; - //! - // Returns the inverse of this rotation. + /// Returns the inverse of this rotation. GfRotation GetInverse() const { return GfRotation(_axis, -_angle); } - //! - // Decompose rotation about 3 orthogonal axes. - // If the axes are not orthogonal, warnings will be spewed. + /// Decompose rotation about 3 orthogonal axes. + /// If the axes are not orthogonal, warnings will be spewed. + GF_API GfVec3d Decompose( const GfVec3d &axis0, const GfVec3d &axis1, const GfVec3d &axis2 ) const; @@ -187,6 +173,7 @@ class GfRotation { // And moved into GfRotation[12/1/08]. Updated for any // combination of three angles [12/1/11]. // + GF_API static void DecomposeRotation(const GfMatrix4d &rot, const GfVec3d &TwAxis, const GfVec3d &FBAxis, @@ -202,39 +189,20 @@ class GfRotation { // This function projects the vectors \p v1 and \p v2 onto the plane // normal to \p axis, and then returns the rotation about \p axis that // brings \p v1 onto \p v2. + GF_API static GfRotation RotateOntoProjected(const GfVec3d &v1, const GfVec3d &v2, const GfVec3d &axis); -#if 0 -// XXX:I ported this code over to presto, but it is not -// yet being used. - - /// Compose a rotation with unit axes with the supplied tw, fb, lr & sw - // values. - // - static void ComposeRotation ( double tw, - double fb, - double lr, - double sw, - GfMatrix4d *rot, // outputs - GfVec3d *TwAxis, - GfVec3d *FBAxis, - GfVec3d *LRAxis) ; - -#endif - - //! - // Transforms row vector \p vec by the rotation, returning the - // result. + /// Transforms row vector \p vec by the rotation, returning the result. + GF_API GfVec3f TransformDir( const GfVec3f &vec ) const; - //! - // \overload + /// \overload + GF_API GfVec3d TransformDir( const GfVec3d &vec ) const; - //! - // hash. + /// Hash. friend inline size_t hash_value(const GfRotation &r) { size_t h = 0; boost::hash_combine(h, r._axis); @@ -242,84 +210,76 @@ class GfRotation { return h; } - //! - // Component-wise rotation equality test. The axes and angles must - // match exactly for rotations to be considered equal. (To compare - // equality of the actual rotations, you can convert both to - // quaternions and test the results for equality.) - bool operator ==(const GfRotation &r) const { - return (_axis == r._axis && - _angle == r._angle); + /// Component-wise rotation equality test. The axes and angles must match + /// exactly for rotations to be considered equal. (To compare equality of + /// the actual rotations, you can convert both to quaternions and test the + /// results for equality.) + bool operator ==(const GfRotation &r) const { + return (_axis == r._axis && + _angle == r._angle); } - //! - // Component-wise rotation inequality test. The axes and angles - // must match exactly for rotations to be considered equal. (To - // compare equality of the actual rotations, you can convert both - // to quaternions and test the results for equality.) - bool operator !=(const GfRotation &r) const { - return ! (*this == r); + /// Component-wise rotation inequality test. The axes and angles must + /// match exactly for rotations to be considered equal. (To compare + /// equality of the actual rotations, you can convert both to quaternions + /// and test the results for equality.) + bool operator !=(const GfRotation &r) const { + return ! (*this == r); } - //! - // Post-multiplies rotation \p r into this rotation. + /// Post-multiplies rotation \p r into this rotation. + GF_API GfRotation & operator *=(const GfRotation &r); - //! - // Scales rotation angle by multiplying by \p scale. + /// Scales rotation angle by multiplying by \p scale. GfRotation & operator *=(double scale) { _angle *= scale; return *this; } - //! - // Scales rotation angle by dividing by \p scale. - GfRotation & operator /=(double scale) { - _angle /= scale; - return *this; + /// Scales rotation angle by dividing by \p scale. + GfRotation & operator /=(double scale) { + _angle /= scale; + return *this; } - //! - // Returns composite rotation of rotations \p r1 and \p r2. - friend GfRotation operator *(const GfRotation &r1, - const GfRotation &r2) { - GfRotation r = r1; - return r *= r2; + /// Returns composite rotation of rotations \p r1 and \p r2. + friend GfRotation operator *(const GfRotation &r1, + const GfRotation &r2) { + GfRotation r = r1; + return r *= r2; } - //! - // Returns a rotation equivalent to \p r with its angle multiplied - // by \p scale. - friend GfRotation operator *(const GfRotation &r, double scale) { - GfRotation rTmp = r; - return rTmp *= scale; + /// Returns a rotation equivalent to \p r with its angle multiplied + /// by \p scale. + friend GfRotation operator *(const GfRotation &r, double scale) { + GfRotation rTmp = r; + return rTmp *= scale; } - //! - // Returns a rotation equivalent to \p r with its angle multiplied - // by \p scale. - friend GfRotation operator *(double scale, const GfRotation &r) { - return (r * scale); + /// Returns a rotation equivalent to \p r with its angle multiplied + /// by \p scale. + friend GfRotation operator *(double scale, const GfRotation &r) { + return (r * scale); } - //! - // Returns a rotation equivalent to \p r with its angle divided - // by \p scale. - friend GfRotation operator /(const GfRotation &r, double scale) { - GfRotation rTmp = r; - return rTmp /= scale; + /// Returns a rotation equivalent to \p r with its angle divided + /// by \p scale. + friend GfRotation operator /(const GfRotation &r, double scale) { + GfRotation rTmp = r; + return rTmp /= scale; } private: - //! Axis storage. This axis is normalized to unit length whenever - // it is set. + /// Axis storage. + /// This axis is normalized to unit length whenever it is set. GfVec3d _axis; - //! Angle storage (represented in degrees). + /// Angle storage (represented in degrees). double _angle; }; /// Output a GfRotation using the format [(x y z) a]. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream&, const GfRotation&); +GF_API std::ostream& operator<<(std::ostream&, const GfRotation&); #endif // GF_ROTATION_H diff --git a/pxr/base/lib/gf/size2.h b/pxr/base/lib/gf/size2.h index dba9da35fd..d6c3fc5108 100644 --- a/pxr/base/lib/gf/size2.h +++ b/pxr/base/lib/gf/size2.h @@ -24,173 +24,171 @@ #ifndef GF_SIZE2_H #define GF_SIZE2_H +/// \file gf/size2.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/arch/inttypes.h" #include "pxr/base/gf/vec2i.h" +#include "pxr/base/gf/api.h" #include -/*! - * \file size2.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfSize2 size2.h pxr/base/gf/size2.h - * \ingroup group_gf_LinearAlgebra - * \brief Two-dimensional array of sizes - * - * GfSize2 is used to represent pairs of counts. It is based on - * the datatype size_t, and thus can only represent non-negative - * values in each dimension. If you need to represent negative numbers - * as well, use GfVec2i. - * - * Usage of GfSize2 is similar to that of GfVec2i, except that all - * mathematical operations are componentwise (including multiplication). - */ - +/// \class GfSize2 +/// \ingroup group_gf_LinearAlgebra +/// +/// Two-dimensional array of sizes +/// +/// GfSize2 is used to represent pairs of counts. It is based on the datatype +/// size_t, and thus can only represent non-negative values in each dimension. +/// If you need to represent negative numbers as well, use GfVec2i. +/// +/// Usage of GfSize2 is similar to that of GfVec2i, except that all +/// mathematical operations are componentwise (including multiplication). +/// class GfSize2 { public: - //! Default constructor initializes components to zero + /// Default constructor initializes components to zero. GfSize2() { - Set(0, 0); + Set(0, 0); } - //! Copy constructor. + /// Copy constructor. GfSize2(const GfSize2& o) { *this = o; } - //! Conversion from GfVec2i + /// Conversion from GfVec2i. explicit GfSize2(const GfVec2i&o) { - Set(o[0], o[1]); + Set(o[0], o[1]); } - //! \brief Construct from an array + /// Construct from an array. GfSize2(const size_t v[2]) { Set(v); } - //! Construct from two values + /// Construct from two values. GfSize2(size_t v0, size_t v1) { Set(v0, v1); } - //! \brief Set to the values in a given array. + /// Set to the values in a given array. GfSize2 & Set(const size_t v[2]) { _vec[0] = v[0]; _vec[1] = v[1]; return *this; } - //! Set to values passed directly + /// Set to values passed directly. GfSize2 & Set(size_t v0, size_t v1) { _vec[0] = v0; _vec[1] = v1; return *this; } - //! Array operator + /// Array operator. size_t & operator [](size_t i) { return _vec[i]; } - //! Const array operator + /// Const array operator. const size_t & operator [](size_t i) const { return _vec[i]; } - //! Component-wise equality + /// Component-wise equality. bool operator ==(const GfSize2 &v) const { return _vec[0] == v._vec[0] && _vec[1] == v._vec[1]; } - //! Component-wise inequality + /// Component-wise inequality. bool operator !=(const GfSize2 &v) const { return ! (*this == v); } - //! Component-wise in-place addition + /// Component-wise in-place addition. GfSize2 & operator +=(const GfSize2 &v) { _vec[0] += v._vec[0]; _vec[1] += v._vec[1]; return *this; } - //! Component-wise in-place subtraction + /// Component-wise in-place subtraction. GfSize2 & operator -=(const GfSize2 &v) { _vec[0] -= v._vec[0]; _vec[1] -= v._vec[1]; return *this; } - //! Component-wise in-place multiplication. + /// Component-wise in-place multiplication. GfSize2 & operator *=(GfSize2 const &v) { _vec[0] *= v._vec[0]; _vec[1] *= v._vec[1]; return *this; } - //! Component-wise in-place multiplication by a scalar + /// Component-wise in-place multiplication by a scalar. GfSize2 & operator *=(int d) { _vec[0] = _vec[0] * d; _vec[1] = _vec[1] * d; return *this; } - //! Component-wise in-place division by a scalar + /// Component-wise in-place division by a scalar. GfSize2 & operator /=(int d) { _vec[0] = _vec[0] / d; _vec[1] = _vec[1] / d; return *this; } - //! Component-wise addition + /// Component-wise addition. friend GfSize2 operator +(const GfSize2 &v1, const GfSize2 &v2) { return GfSize2(v1._vec[0]+v2._vec[0], - v1._vec[1]+v2._vec[1]); + v1._vec[1]+v2._vec[1]); } - //! Component-wise subtraction + /// Component-wise subtraction. friend GfSize2 operator -(const GfSize2 &v1, const GfSize2 &v2) { return GfSize2(v1._vec[0]-v2._vec[0], - v1._vec[1]-v2._vec[1]); + v1._vec[1]-v2._vec[1]); } - //! Component-wise multiplication + /// Component-wise multiplication. friend GfSize2 operator *(const GfSize2 &v1, const GfSize2 &v2) { return GfSize2(v1._vec[0]*v2._vec[0], - v1._vec[1]*v2._vec[1]); + v1._vec[1]*v2._vec[1]); } - //! Component-wise multiplication by a scalar + /// Component-wise multiplication by a scalar. friend GfSize2 operator *(const GfSize2 &v1, int s) { return GfSize2(v1._vec[0]*s, - v1._vec[1]*s); + v1._vec[1]*s); } - //! Component-wise multiplication by a scalar + /// Component-wise multiplication by a scalar. friend GfSize2 operator *(int s, const GfSize2 &v1) { return GfSize2(v1._vec[0]*s, - v1._vec[1]*s); + v1._vec[1]*s); } - //! Component-wise division by a scalar + /// Component-wise division by a scalar. friend GfSize2 operator /(const GfSize2 &v1, int s) { return GfSize2(v1._vec[0]/s, - v1._vec[1]/s); + v1._vec[1]/s); } - //! Output operator + /// Output operator. + GF_API friend std::ostream &operator<<(std::ostream &o, GfSize2 const &v); - //! Conversion to GfVec2i + /// Conversion to GfVec2i. operator GfVec2i() const { - return GfVec2i(_vec[0],_vec[1]); + return GfVec2i(_vec[0], _vec[1]); } private: size_t _vec[2]; }; // Friend functions must be declared -std::ostream &operator<<(std::ostream &o, GfSize2 const &v); +GF_API std::ostream &operator<<(std::ostream &o, GfSize2 const &v); #endif /* GF_SIZE2_H */ diff --git a/pxr/base/lib/gf/size3.h b/pxr/base/lib/gf/size3.h index ae7a19a60f..b26f4b8420 100644 --- a/pxr/base/lib/gf/size3.h +++ b/pxr/base/lib/gf/size3.h @@ -24,58 +24,55 @@ #ifndef GF_SIZE3_H #define GF_SIZE3_H +/// \file gf/size3.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/arch/inttypes.h" #include "pxr/base/gf/vec3i.h" +#include "pxr/base/gf/api.h" #include -/*! - * \file size3.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfSize3 size3.h pxr/base/gf/size3.h - * \ingroup group_gf_LinearAlgebra - * \brief Three-dimensional array of sizes - * - * GfSize3 is used to represent triples of counts. It is based on - * the datatype size_t, and thus can only represent non-negative - * values in each dimension. If you need to represent negative numbers - * as well, use GfVeci. - * - * Usage of GfSize3 is similar to that of GfVec3i, except that all - * mathematical operations are componentwise (including multiplication). - */ - +/// \class GfSize3 +/// \ingroup group_gf_LinearAlgebra +/// +/// Three-dimensional array of sizes +/// +/// GfSize3 is used to represent triples of counts. It is based on the +/// datatype size_t, and thus can only represent non-negative values in each +/// dimension. If you need to represent negative numbers as well, use GfVeci. +/// +/// Usage of GfSize3 is similar to that of GfVec3i, except that all +/// mathematical operations are componentwise (including multiplication). +/// class GfSize3 { public: - //! Default constructor initializes components to zero + /// Default constructor initializes components to zero GfSize3() { - Set(0, 0, 0); + Set(0, 0, 0); } - //! Copy constructor. + /// Copy constructor. GfSize3(const GfSize3& o) { *this = o; } - //! Conversion from GfVec3i + /// Conversion from GfVec3i explicit GfSize3(const GfVec3i&o) { - Set(o[0], o[1], o[2]); + Set(o[0], o[1], o[2]); } - //! Construct from an array + /// Construct from an array GfSize3(const size_t v[3]) { Set(v); } - //! Construct from three values + /// Construct from three values GfSize3(size_t v0, size_t v1, size_t v2) { Set(v0, v1, v2); } - //! Set to the values in \p v. + /// Set to the values in \p v. GfSize3 & Set(const size_t v[3]) { _vec[0] = v[0]; _vec[1] = v[1]; @@ -83,7 +80,7 @@ class GfSize3 { return *this; } - //! Set to values passed directly + /// Set to values passed directly GfSize3 & Set(size_t v0, size_t v1, size_t v2) { _vec[0] = v0; _vec[1] = v1; @@ -91,28 +88,28 @@ class GfSize3 { return *this; } - //! Array operator + /// Array operator size_t & operator [](size_t i) { return _vec[i]; } - //! Const array operator + /// Const array operator const size_t & operator [](size_t i) const { return _vec[i]; } - //! Component-wise equality + /// Component-wise equality bool operator ==(const GfSize3 &v) const { return _vec[0] == v._vec[0] && _vec[1] == v._vec[1] && - _vec[2] == v._vec[2]; + _vec[2] == v._vec[2]; } - //! Component-wise inequality + /// Component-wise inequality bool operator !=(const GfSize3 &v) const { return ! (*this == v); } - //! Component-wise in-place addition + /// Component-wise in-place addition GfSize3 & operator +=(const GfSize3 &v) { _vec[0] += v._vec[0]; _vec[1] += v._vec[1]; @@ -120,7 +117,7 @@ class GfSize3 { return *this; } - //! Component-wise in-place subtraction + /// Component-wise in-place subtraction GfSize3 & operator -=(const GfSize3 &v) { _vec[0] -= v._vec[0]; _vec[1] -= v._vec[1]; @@ -128,7 +125,7 @@ class GfSize3 { return *this; } - //! Component-wise in-place multiplication. + /// Component-wise in-place multiplication. GfSize3 & operator *=(GfSize3 const &v) { _vec[0] *= v._vec[0]; _vec[1] *= v._vec[1]; @@ -136,7 +133,7 @@ class GfSize3 { return *this; } - //! Component-wise in-place multiplication by a scalar + /// Component-wise in-place multiplication by a scalar GfSize3 & operator *=(size_t d) { _vec[0] = _vec[0] * d; _vec[1] = _vec[1] * d; @@ -144,7 +141,7 @@ class GfSize3 { return *this; } - //! Component-wise in-place division by a scalar + /// Component-wise in-place division by a scalar GfSize3 & operator /=(size_t d) { _vec[0] = _vec[0] / d; _vec[1] = _vec[1] / d; @@ -152,60 +149,60 @@ class GfSize3 { return *this; } - //! Component-wise addition + /// Component-wise addition friend GfSize3 operator +(const GfSize3 &v1, const GfSize3 &v3) { return GfSize3(v1._vec[0]+v3._vec[0], - v1._vec[1]+v3._vec[1], - v1._vec[2]+v3._vec[2]); + v1._vec[1]+v3._vec[1], + v1._vec[2]+v3._vec[2]); } - //! Component-wise subtraction + /// Component-wise subtraction friend GfSize3 operator -(const GfSize3 &v1, const GfSize3 &v3) { return GfSize3(v1._vec[0]-v3._vec[0], - v1._vec[1]-v3._vec[1], - v1._vec[2]-v3._vec[2]); + v1._vec[1]-v3._vec[1], + v1._vec[2]-v3._vec[2]); } - //! Component-wise multiplication + /// Component-wise multiplication friend GfSize3 operator *(const GfSize3 &v1, const GfSize3 &v3) { return GfSize3(v1._vec[0]*v3._vec[0], - v1._vec[1]*v3._vec[1], - v1._vec[2]*v3._vec[2]); + v1._vec[1]*v3._vec[1], + v1._vec[2]*v3._vec[2]); } - //! Component-wise multiplication by a scalar + /// Component-wise multiplication by a scalar friend GfSize3 operator *(const GfSize3 &v1, size_t s) { return GfSize3(v1._vec[0]*s, - v1._vec[1]*s, - v1._vec[2]*s); + v1._vec[1]*s, + v1._vec[2]*s); } - //! Component-wise multiplication by a scalar + /// Component-wise multiplication by a scalar friend GfSize3 operator *(size_t s, const GfSize3 &v1) { return GfSize3(v1._vec[0]*s, - v1._vec[1]*s, - v1._vec[2]*s); + v1._vec[1]*s, + v1._vec[2]*s); } - //! Component-wise division by a scalar + /// Component-wise division by a scalar friend GfSize3 operator /(const GfSize3 &v1, size_t s) { return GfSize3(v1._vec[0]/s, - v1._vec[1]/s, - v1._vec[2]/s); + v1._vec[1]/s, + v1._vec[2]/s); } - //! Output operator - friend std::ostream &operator<<(std::ostream &o, GfSize3 const &v); + /// Output operator + friend GF_API std::ostream &operator<<(std::ostream &o, GfSize3 const &v); - //! Conversion to GfVec3i + /// Conversion to GfVec3i operator GfVec3i() const { - return GfVec3i(_vec[0],_vec[1],_vec[2]); + return GfVec3i(_vec[0],_vec[1],_vec[2]); } private: size_t _vec[3]; }; // Friend functions must be declared -std::ostream &operator<<(std::ostream &o, GfSize3 const &v); +GF_API std::ostream &operator<<(std::ostream &o, GfSize3 const &v); #endif /* GF_SIZE3_H */ diff --git a/pxr/base/lib/gf/traits.h b/pxr/base/lib/gf/traits.h index 4efa6097ce..9bc402adeb 100644 --- a/pxr/base/lib/gf/traits.h +++ b/pxr/base/lib/gf/traits.h @@ -24,29 +24,24 @@ #ifndef GF_TRAITS_H #define GF_TRAITS_H -/*! \brief A metafunction with a static const bool member 'value' that is true - * for GfVec types, like GfVec2i, GfVec4d, etc and false for all other - * types. - */ +/// A metafunction with a static const bool member 'value' that is true for +/// GfVec types, like GfVec2i, GfVec4d, etc and false for all other types. template struct GfIsGfVec { static const bool value = false; }; -/*! \brief A metafunction with a static const bool member 'value' that is true - * for GfMatrix types, like GfMatrix3d, GfMatrix4f, etc and false for all - * other types. - */ +/// A metafunction with a static const bool member 'value' that is true for +/// GfMatrix types, like GfMatrix3d, GfMatrix4f, etc and false for all other +/// types. template struct GfIsGfMatrix { static const bool value = false; }; -/*! \brief A metafunction with a static const bool member 'value' that is true - * for GfQuat types and false for all other types. - */ +/// A metafunction with a static const bool member 'value' that is true for +/// GfQuat types and false for all other types. template struct GfIsGfQuat { static const bool value = false; }; -/*! \brief A metafunction with a static const bool member 'value' that is true - * for GfRange types and false for all other types. - */ +/// A metafunction with a static const bool member 'value' that is true for +/// GfRange types and false for all other types. template struct GfIsGfRange { static const bool value = false; }; diff --git a/pxr/base/lib/gf/transform.h b/pxr/base/lib/gf/transform.h index c02004e171..5872d53f27 100644 --- a/pxr/base/lib/gf/transform.h +++ b/pxr/base/lib/gf/transform.h @@ -24,73 +24,67 @@ #ifndef GF_TRANSFORM_H #define GF_TRANSFORM_H +/// \file gf/transform.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/gf/rotation.h" #include "pxr/base/gf/vec3d.h" +#include "pxr/base/gf/api.h" #include class GfMatrix4d; -/*! - * \file transform.h - * \ingroup group_gf_LinearAlgebra - */ - -//! -// \class GfTransform transform.h "pxr/base/gf/transform.h" -// \ingroup group_gf_LinearAlgebra -// \brief Basic type: Compound linear transformation. -// -// This class represents a linear transformation specified as a series -// of individual components: a \em translation, a \em rotation, a \em -// scale, a \em pivotPosition, and a \em pivotOrientation. When -// applied to a point, the point will be transformed as follows (in -// order): -// -// - Scaled by the \em scale with respect to \em pivotPosition and -// the orientation specified by the \em pivotOrientation. -// - Rotated by the \em rotation about \em pivotPosition. -// - Translated by \em Translation -// -// That is, the cumulative matrix that this represents looks like this. -// -// \code -// M = -P * -O * S * O * R * P * T -// \endcode -// -// where -// - \em T is the \em translation matrix -// - \em P is the matrix that translates by \em pivotPosition -// - \em R is the \em rotation matrix -// - \em O is the matrix that rotates to \em pivotOrientation -// - \em S is the \em scale matrix -// - +/// \class GfTransform +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type: Compound linear transformation. +/// +/// This class represents a linear transformation specified as a series of +/// individual components: a \em translation, a \em rotation, a \em scale, a +/// \em pivotPosition, and a \em pivotOrientation. When applied to a point, +/// the point will be transformed as follows (in order): +/// +/// \li Scaled by the \em scale with respect to \em pivotPosition and the +/// orientation specified by the \em pivotOrientation. +/// \li Rotated by the \em rotation about \em pivotPosition. +/// \li Translated by \em Translation +/// +/// That is, the cumulative matrix that this represents looks like this. +/// +/// \code +/// M = -P * -O * S * O * R * P * T +/// \endcode +/// +/// where +/// \li \em T is the \em translation matrix +/// \li \em P is the matrix that translates by \em pivotPosition +/// \li \em R is the \em rotation matrix +/// \li \em O is the matrix that rotates to \em pivotOrientation +/// \li \em S is the \em scale matrix +/// class GfTransform { public: - //! - // The default constructor sets the component values to the - // identity transformation. + /// The default constructor sets the component values to the + /// identity transformation. GfTransform() { - SetIdentity(); + SetIdentity(); } - //! - // This constructor initializes the transformation from all - // component values. This is the constructor used by 2x code. + /// This constructor initializes the transformation from all + /// component values. This is the constructor used by 2x code. GfTransform(const GfVec3d &scale, - const GfRotation &pivotOrientation, - const GfRotation &rotation, - const GfVec3d &pivotPosition, - const GfVec3d &translation) { - Set(scale, pivotOrientation, rotation, pivotPosition, translation); + const GfRotation &pivotOrientation, + const GfRotation &rotation, + const GfVec3d &pivotPosition, + const GfVec3d &translation) { + Set(scale, pivotOrientation, rotation, pivotPosition, translation); } - //! - // This constructor initializes the transformation from all - // component values. This is the constructor used by 3x code. + /// This constructor initializes the transformation from all + /// component values. This is the constructor used by 3x code. GfTransform(const GfVec3d &translation, const GfRotation &rotation, const GfVec3d &scale, @@ -99,26 +93,24 @@ class GfTransform { Set(translation, rotation, scale, pivotPosition, pivotOrientation); } - //! - // This constructor initializes the transformation with a matrix. See - // SetMatrix() for more information. + /// This constructor initializes the transformation with a matrix. See + /// SetMatrix() for more information. GfTransform(const GfMatrix4d &m) { SetIdentity(); SetMatrix(m); } - //! - // Sets the transformation from all component values. - // This constructor orders its arguments the way that 2x expects. - GfTransform & Set(const GfVec3d &scale, - const GfRotation &pivotOrientation, - const GfRotation &rotation, - const GfVec3d &pivotPosition, - const GfVec3d &translation); - - //! - // Sets the transformation from all component values. - // This constructor orders its arguments the way that 3x expects. + /// Sets the transformation from all component values. + /// This constructor orders its arguments the way that 2x expects. + GF_API + GfTransform & Set(const GfVec3d &scale, + const GfRotation &pivotOrientation, + const GfRotation &rotation, + const GfVec3d &pivotPosition, + const GfVec3d &translation); + + /// Sets the transformation from all component values. + /// This constructor orders its arguments the way that 3x expects. GfTransform & Set(const GfVec3d &translation, const GfRotation &rotation, const GfVec3d &scale, @@ -128,145 +120,128 @@ class GfTransform { pivotPosition, translation); } - //! - // Sets the transform components to implement the transformation - // represented by matrix \p m , ignoring any projection. This - // tries to leave the current center unchanged. - GfTransform & SetMatrix(const GfMatrix4d &m); + /// Sets the transform components to implement the transformation + /// represented by matrix \p m , ignoring any projection. This tries to + /// leave the current center unchanged. + GF_API + GfTransform & SetMatrix(const GfMatrix4d &m); - //! - // Sets the transformation to the identity transformation. - GfTransform & SetIdentity(); + /// Sets the transformation to the identity transformation. + GF_API + GfTransform & SetIdentity(); - //! - // Sets the scale component, leaving all others untouched. - void SetScale(const GfVec3d &scale) { - _scale = scale; + /// Sets the scale component, leaving all others untouched. + void SetScale(const GfVec3d &scale) { + _scale = scale; } - //! - // Sets the pivot orientation component, leaving all others untouched. - void SetPivotOrientation(const GfRotation &pivotOrient) { - _pivotOrientation = pivotOrient; + /// Sets the pivot orientation component, leaving all others untouched. + void SetPivotOrientation(const GfRotation &pivotOrient) { + _pivotOrientation = pivotOrient; } - //! - // Sets the pivot orientation component, leaving all others untouched. - void SetScaleOrientation(const GfRotation &pivotOrient) { + /// Sets the pivot orientation component, leaving all others untouched. + void SetScaleOrientation(const GfRotation &pivotOrient) { SetPivotOrientation(pivotOrient); } - //! - // Sets the rotation component, leaving all others untouched. - void SetRotation(const GfRotation &rotation) { - _rotation = rotation; + /// Sets the rotation component, leaving all others untouched. + void SetRotation(const GfRotation &rotation) { + _rotation = rotation; } - //! - // Sets the pivot position component, leaving all others untouched. + /// Sets the pivot position component, leaving all others untouched. void SetPivotPosition(const GfVec3d &pivPos) { _pivotPosition = pivPos; } - //! - // Sets the pivot position component, leaving all others untouched. + /// Sets the pivot position component, leaving all others untouched. void SetCenter(const GfVec3d &pivPos) { SetPivotPosition(pivPos); } - //! - // Sets the translation component, leaving all others untouched. - void SetTranslation(const GfVec3d &translation) { - _translation = translation; + /// Sets the translation component, leaving all others untouched. + void SetTranslation(const GfVec3d &translation) { + _translation = translation; } - //! - // Returns the scale component. - const GfVec3d & GetScale() const { - return _scale; + /// Returns the scale component. + const GfVec3d & GetScale() const { + return _scale; } - //! - // Returns the pivot orientation component. - const GfRotation & GetPivotOrientation() const { - return _pivotOrientation; + /// Returns the pivot orientation component. + const GfRotation & GetPivotOrientation() const { + return _pivotOrientation; } - //! - // Returns the scale orientation component. - const GfRotation & GetScaleOrientation() const { - return GetPivotOrientation(); + /// Returns the scale orientation component. + const GfRotation & GetScaleOrientation() const { + return GetPivotOrientation(); } - //! - // Returns the rotation component. - const GfRotation & GetRotation() const { - return _rotation; + /// Returns the rotation component. + const GfRotation & GetRotation() const { + return _rotation; } - //! - // Returns the pivot position component. - const GfVec3d & GetPivotPosition() const { - return _pivotPosition; + /// Returns the pivot position component. + const GfVec3d & GetPivotPosition() const { + return _pivotPosition; } - //! - // Returns the pivot position component. - const GfVec3d & GetCenter() const { - return GetPivotPosition(); + /// Returns the pivot position component. + const GfVec3d & GetCenter() const { + return GetPivotPosition(); } - //! - // Returns the translation component. - const GfVec3d & GetTranslation() const { - return _translation; + /// Returns the translation component. + const GfVec3d & GetTranslation() const { + return _translation; } - //! - // Returns a \c GfMatrix4d that implements the cumulative - // transformation. - GfMatrix4d GetMatrix() const; - - //! - // Component-wise transform equality test. All components must - // match exactly for transforms to be considered equal. - bool operator ==(const GfTransform &xf) const; - - //! - // Component-wise transform inequality test. All components must - // match exactly for transforms to be considered equal. - bool operator !=(const GfTransform &xf) const { - return ! (*this == xf); + /// Returns a \c GfMatrix4d that implements the cumulative transformation. + GF_API + GfMatrix4d GetMatrix() const; + + /// Component-wise transform equality test. All components must match + /// exactly for transforms to be considered equal. + GF_API + bool operator ==(const GfTransform &xf) const; + + /// Component-wise transform inequality test. All components must match + /// exactly for transforms to be considered equal. + bool operator !=(const GfTransform &xf) const { + return ! (*this == xf); } - //! - // Post-multiplies transform \p xf into this transform. - GfTransform & operator *=(const GfTransform &xf); + /// Post-multiplies transform \p xf into this transform. + GF_API + GfTransform & operator *=(const GfTransform &xf); - //! - // Returns the product of transforms \p xf1 and \p xf2 . - friend GfTransform operator *(const GfTransform &xf1, - const GfTransform &xf2) { - GfTransform xf = xf1; - return xf *= xf2; + /// Returns the product of transforms \p xf1 and \p xf2. + friend GfTransform operator *(const GfTransform &xf1, + const GfTransform &xf2) { + GfTransform xf = xf1; + return xf *= xf2; } private: - //! translation + /// translation GfVec3d _translation; - //! rotation + /// rotation GfRotation _rotation; - //! scale factors + /// scale factors GfVec3d _scale; - //! orientation used for scaling and rotation + /// orientation used for scaling and rotation GfRotation _pivotOrientation; - //! center of rotation and scaling + /// center of rotation and scaling GfVec3d _pivotPosition; }; /// Output a GfTransform using the format /// [scale, scaleorientation, rotation, center, translation]. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream&, const GfTransform&); +GF_API std::ostream& operator<<(std::ostream&, const GfTransform&); #endif // GF_TRANSFORM_H diff --git a/pxr/base/lib/gf/vec.template.h b/pxr/base/lib/gf/vec.template.h index 6be06e8687..96cd0290c1 100644 --- a/pxr/base/lib/gf/vec.template.h +++ b/pxr/base/lib/gf/vec.template.h @@ -28,6 +28,9 @@ #ifndef GF_{{ UPPER(VEC)[2:] }}_H #define GF_{{ UPPER(VEC)[2:] }}_H +/// \file gf/vec{{ SUFFIX }}.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" @@ -50,21 +53,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec{{ SUFFIX }}.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class {{ VEC }} vec{{ SUFFIX }}.h "pxr/base/gf/vec{{ SUFFIX }}.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of {{ DIM }} {{ SCL }} components. - * - * Represents a vector of {{ DIM }} components of type \c {{ SCL }}. - * It is intended to be fast and simple. - * - */ - +/// \class {{ VEC }} +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of {{ DIM }} {{ SCL }} components. +/// +/// Represents a vector of {{ DIM }} components of type \c {{ SCL }}. +/// It is intended to be fast and simple. +/// class {{ VEC }} { public: @@ -75,8 +71,8 @@ class {{ VEC }} /// Default constructor does no initialization. {{ VEC }}() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. {{ VEC }}(const {{ VEC }} &other) { *this = other; } @@ -90,7 +86,7 @@ class {{ VEC }} {{ VEC }}({{ LIST(SCL + " s%(i)s") }}) { Set({{ LIST("s%(i)s") }}); } - + /// Construct with pointer to values. template explicit {{ VEC }}(Scl const *p) { Set(p); } @@ -110,7 +106,7 @@ class {{ VEC }} return result; } {% endfor %} - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to {{ DIM }}. static {{ VEC }} Axis(size_t i) { @@ -119,7 +115,7 @@ class {{ VEC }} result[i] = 1; return result; } - + /// Set all elements with passed arguments. {{ VEC }} &Set({{ LIST(SCL + " s%(i)s") }}) { {{ LIST("_data[%(i)s] = s%(i)s;", sep='\n ') }} @@ -156,7 +152,7 @@ class {{ VEC }} return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... {% for S in SCALARS if S != SCL -%} /// Equality comparison. bool operator==(class {{ VECNAME(DIM, S) }} const &other) const; @@ -188,10 +184,10 @@ class {{ VEC }} /// Multiplication by scalar. {{ VEC }} &operator*=(double s) { {{ LIST("_data[%(i)s] *= s;", sep='\n ') }} - return *this; + return *this; } {{ VEC }} operator*(double s) const { - return {{ VEC }}(*this) *= s; + return {{ VEC }}(*this) *= s; } friend {{ VEC }} operator*(double s, {{ VEC }} const &v) { return v * s; @@ -199,15 +195,15 @@ class {{ VEC }} {% if IS_FLOATING_POINT(SCL) %} /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. {{ VEC }} &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } {{ VEC }} operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } {% else %} /// Division by scalar. @@ -216,7 +212,7 @@ class {{ VEC }} return *this; } {{ VEC }} operator/({{ SCL }} s) const { - return {{ VEC }}(*this) /= s; + return {{ VEC }}(*this) /= s; } {% endif %} @@ -225,7 +221,7 @@ class {{ VEC }} return {{ LIST("_data[%(i)s] * v[%(i)s]", sep=" + ") }}; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -233,12 +229,13 @@ class {{ VEC }} return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode {{ VEC }} GetComplement({{ VEC }} const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -249,7 +246,7 @@ class {{ VEC }} {% if IS_FLOATING_POINT(SCL) %} /// Length {{ SCL }} GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -262,7 +259,7 @@ class {{ VEC }} /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). {{ SCL }} Normalize({{ SCL }} eps = {{ EPS }}) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. {{ SCL }} length = GetLength(); *this /= (length > eps) ? length : eps; @@ -276,26 +273,26 @@ class {{ VEC }} } {% if DIM == 3 %} - /// Orthogonalize and optionally normalize a set of basis vectors. - /// This uses an iterative method that is very stable even when the vectors - /// are far from orthogonal (close to colinear). The number of iterations - /// and thus the computation time does increase as the vectors become - /// close to colinear, however. - /// Returns a bool specifying whether the solution converged after - /// a number of iterations. If it did not converge, the returned vectors - /// will be as close as possible to orthogonal within the iteration limit. - /// Colinear vectors will be unaltered, and the method will return false. + /// Orthogonalize and optionally normalize a set of basis vectors. This + /// uses an iterative method that is very stable even when the vectors are + /// far from orthogonal (close to colinear). The number of iterations and + /// thus the computation time does increase as the vectors become close to + /// colinear, however. Returns a bool specifying whether the solution + /// converged after a number of iterations. If it did not converge, the + /// returned vectors will be as close as possible to orthogonal within the + /// iteration limit. Colinear vectors will be unaltered, and the method + /// will return false. static bool OrthogonalizeBasis( {{ VEC }} *tx, {{ VEC }} *ty, {{ VEC }} *tz, const bool normalize, double eps = GF_MIN_ORTHO_TOLERANCE); - /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this - /// are mutually orthogonal. If the length L of *this is smaller than - /// \c eps, then v1 and v2 will have magnitude L/eps. As a result, - /// the function delivers a continuous result as *this shrinks in length. + /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this are + /// mutually orthogonal. If the length L of *this is smaller than \c eps, + /// then v1 and v2 will have magnitude L/eps. As a result, the function + /// delivers a continuous result as *this shrinks in length. void BuildOrthonormalFrame({{ VEC }} *v1, {{ VEC }} *v2, - {{ SCL }} eps = {{ EPS }}) const; + {{ SCL }} eps = {{ EPS }}) const; {% endif %} {# DIM == 3 #} {% endif %} {# IS_FLOATING_POINT(SCL) #} @@ -304,7 +301,7 @@ class {{ VEC }} {{ SCL }} _data[{{ DIM }}]; }; -/// Output a {{ VEC }} +/// Output a {{ VEC }}. /// \ingroup group_gf_DebuggingOutput std::ostream& operator<<(std::ostream &, {{ VEC }} const &); @@ -336,7 +333,6 @@ GfDot({{ VEC }} const &v1, {{ VEC }} const &v2) { return v1 * v2; } - {% if IS_FLOATING_POINT(SCL) %} /// Returns the geometric length of \c v. @@ -356,8 +352,8 @@ GfNormalize({{ VEC }} *v, {{ SCL }} eps = {{ EPS }}) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline {{ VEC }} GfGetNormalized({{ VEC }} const &v, {{ SCL }} eps = {{ EPS }}) { @@ -415,7 +411,8 @@ GfCross({{ VEC }} const &v1, {{ VEC }} const &v2) v1[0] * v2[1] - v1[1] * v2[0]); } -/// Returns the cross product of \p v1 and \p v2. See also GfCross(). +/// Returns the cross product of \p v1 and \p v2. +/// \see GfCross() inline {{ VEC }} operator^({{ VEC }} const &v1, {{ VEC }} const &v2) { diff --git a/pxr/base/lib/gf/vec2d.h b/pxr/base/lib/gf/vec2d.h index a5ce67190b..609b7f4d24 100644 --- a/pxr/base/lib/gf/vec2d.h +++ b/pxr/base/lib/gf/vec2d.h @@ -28,10 +28,14 @@ #ifndef GF_VEC2D_H #define GF_VEC2D_H +/// \file gf/vec2d.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" +#include "pxr/base/gf/api.h" #include @@ -43,21 +47,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec2d.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec2d vec2d.h "pxr/base/gf/vec2d.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 2 double components. - * - * Represents a vector of 2 components of type \c double. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec2d +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 2 double components. +/// +/// Represents a vector of 2 components of type \c double. +/// It is intended to be fast and simple. +/// class GfVec2d { public: @@ -68,8 +65,8 @@ class GfVec2d /// Default constructor does no initialization. GfVec2d() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec2d(const GfVec2d &other) { *this = other; } @@ -84,19 +81,19 @@ class GfVec2d GfVec2d(double s0, double s1) { Set(s0, s1); } - + /// Construct with pointer to values. template explicit GfVec2d(Scl const *p) { Set(p); } /// Implicitly convert from GfVec2f. - GfVec2d(class GfVec2f const &other); + GF_API GfVec2d(class GfVec2f const &other); /// Implicitly convert from GfVec2h. - GfVec2d(class GfVec2h const &other); + GF_API GfVec2d(class GfVec2h const &other); /// Implicitly convert from GfVec2i. - GfVec2d(class GfVec2i const &other); + GF_API GfVec2d(class GfVec2i const &other); /// Create a unit vector along the X-axis. static GfVec2d XAxis() { @@ -110,7 +107,7 @@ class GfVec2d result[1] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 2. static GfVec2d Axis(size_t i) { @@ -119,7 +116,7 @@ class GfVec2d result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec2d &Set(double s0, double s1) { _data[0] = s0; @@ -158,11 +155,14 @@ class GfVec2d return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec2f const &other) const; + GF_API /// Equality comparison. bool operator==(class GfVec2h const &other) const; + GF_API /// Equality comparison. bool operator==(class GfVec2i const &other) const; @@ -195,25 +195,25 @@ class GfVec2d GfVec2d &operator*=(double s) { _data[0] *= s; _data[1] *= s; - return *this; + return *this; } GfVec2d operator*(double s) const { - return GfVec2d(*this) *= s; + return GfVec2d(*this) *= s; } friend GfVec2d operator*(double s, GfVec2d const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec2d &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec2d operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -221,7 +221,7 @@ class GfVec2d return _data[0] * v[0] + _data[1] * v[1]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -229,12 +229,13 @@ class GfVec2d return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec2d GetComplement(GfVec2d const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -244,7 +245,7 @@ class GfVec2d /// Length double GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -257,7 +258,7 @@ class GfVec2d /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). double Normalize(double eps = GF_MIN_VECTOR_LENGTH) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. double length = GetLength(); *this /= (length > eps) ? length : eps; @@ -275,9 +276,9 @@ class GfVec2d double _data[2]; }; -/// Output a GfVec2d +/// Output a GfVec2d. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec2d const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec2d const &); #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/vec2h.h" @@ -308,7 +309,6 @@ GfDot(GfVec2d const &v1, GfVec2d const &v2) { } - /// Returns the geometric length of \c v. inline double GfGetLength(GfVec2d const &v) @@ -326,8 +326,8 @@ GfNormalize(GfVec2d *v, double eps = GF_MIN_VECTOR_LENGTH) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec2d GfGetNormalized(GfVec2d const &v, double eps = GF_MIN_VECTOR_LENGTH) { diff --git a/pxr/base/lib/gf/vec2f.h b/pxr/base/lib/gf/vec2f.h index fcaf976b51..9d718b4fa8 100644 --- a/pxr/base/lib/gf/vec2f.h +++ b/pxr/base/lib/gf/vec2f.h @@ -28,10 +28,14 @@ #ifndef GF_VEC2F_H #define GF_VEC2F_H +/// \file gf/vec2f.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" +#include "pxr/base/gf/api.h" #include @@ -43,21 +47,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec2f.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec2f vec2f.h "pxr/base/gf/vec2f.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 2 float components. - * - * Represents a vector of 2 components of type \c float. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec2f +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 2 float components. +/// +/// Represents a vector of 2 components of type \c float. +/// It is intended to be fast and simple. +/// class GfVec2f { public: @@ -68,8 +65,8 @@ class GfVec2f /// Default constructor does no initialization. GfVec2f() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec2f(const GfVec2f &other) { *this = other; } @@ -84,18 +81,21 @@ class GfVec2f GfVec2f(float s0, float s1) { Set(s0, s1); } - + /// Construct with pointer to values. template explicit GfVec2f(Scl const *p) { Set(p); } /// Construct from GfVec2d. + GF_API explicit GfVec2f(class GfVec2d const &other); /// Implicitly convert from GfVec2h. + GF_API GfVec2f(class GfVec2h const &other); /// Implicitly convert from GfVec2i. + GF_API GfVec2f(class GfVec2i const &other); /// Create a unit vector along the X-axis. @@ -110,7 +110,7 @@ class GfVec2f result[1] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 2. static GfVec2f Axis(size_t i) { @@ -119,7 +119,7 @@ class GfVec2f result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec2f &Set(float s0, float s1) { _data[0] = s0; @@ -158,12 +158,15 @@ class GfVec2f return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec2d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec2h const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec2i const &other) const; /// Create a vec with negated elements. @@ -195,25 +198,25 @@ class GfVec2f GfVec2f &operator*=(double s) { _data[0] *= s; _data[1] *= s; - return *this; + return *this; } GfVec2f operator*(double s) const { - return GfVec2f(*this) *= s; + return GfVec2f(*this) *= s; } friend GfVec2f operator*(double s, GfVec2f const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec2f &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec2f operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -221,7 +224,7 @@ class GfVec2f return _data[0] * v[0] + _data[1] * v[1]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -229,12 +232,13 @@ class GfVec2f return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec2f GetComplement(GfVec2f const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -244,7 +248,7 @@ class GfVec2f /// Length float GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -257,7 +261,7 @@ class GfVec2f /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). float Normalize(float eps = GF_MIN_VECTOR_LENGTH) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. float length = GetLength(); *this /= (length > eps) ? length : eps; @@ -275,9 +279,9 @@ class GfVec2f float _data[2]; }; -/// Output a GfVec2f +/// Output a GfVec2f. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec2f const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec2f const &); #include "pxr/base/gf/vec2d.h" #include "pxr/base/gf/vec2h.h" @@ -308,7 +312,6 @@ GfDot(GfVec2f const &v1, GfVec2f const &v2) { } - /// Returns the geometric length of \c v. inline float GfGetLength(GfVec2f const &v) @@ -326,8 +329,8 @@ GfNormalize(GfVec2f *v, float eps = GF_MIN_VECTOR_LENGTH) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec2f GfGetNormalized(GfVec2f const &v, float eps = GF_MIN_VECTOR_LENGTH) { diff --git a/pxr/base/lib/gf/vec2h.h b/pxr/base/lib/gf/vec2h.h index 3e43a504b8..5521d5d746 100644 --- a/pxr/base/lib/gf/vec2h.h +++ b/pxr/base/lib/gf/vec2h.h @@ -28,11 +28,15 @@ #ifndef GF_VEC2H_H #define GF_VEC2H_H +/// \file gf/vec2h.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" #include "pxr/base/gf/half.h" +#include "pxr/base/gf/api.h" #include @@ -44,21 +48,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec2h.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec2h vec2h.h "pxr/base/gf/vec2h.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 2 half components. - * - * Represents a vector of 2 components of type \c half. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec2h +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 2 half components. +/// +/// Represents a vector of 2 components of type \c half. +/// It is intended to be fast and simple. +/// class GfVec2h { public: @@ -69,8 +66,8 @@ class GfVec2h /// Default constructor does no initialization. GfVec2h() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec2h(const GfVec2h &other) { *this = other; } @@ -85,18 +82,21 @@ class GfVec2h GfVec2h(half s0, half s1) { Set(s0, s1); } - + /// Construct with pointer to values. template explicit GfVec2h(Scl const *p) { Set(p); } /// Construct from GfVec2d. + GF_API explicit GfVec2h(class GfVec2d const &other); /// Construct from GfVec2f. + GF_API explicit GfVec2h(class GfVec2f const &other); /// Implicitly convert from GfVec2i. + GF_API GfVec2h(class GfVec2i const &other); /// Create a unit vector along the X-axis. @@ -111,7 +111,7 @@ class GfVec2h result[1] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 2. static GfVec2h Axis(size_t i) { @@ -120,7 +120,7 @@ class GfVec2h result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec2h &Set(half s0, half s1) { _data[0] = s0; @@ -159,12 +159,15 @@ class GfVec2h return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec2d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec2f const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec2i const &other) const; /// Create a vec with negated elements. @@ -196,25 +199,25 @@ class GfVec2h GfVec2h &operator*=(double s) { _data[0] *= s; _data[1] *= s; - return *this; + return *this; } GfVec2h operator*(double s) const { - return GfVec2h(*this) *= s; + return GfVec2h(*this) *= s; } friend GfVec2h operator*(double s, GfVec2h const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec2h &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec2h operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -222,7 +225,7 @@ class GfVec2h return _data[0] * v[0] + _data[1] * v[1]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -230,12 +233,13 @@ class GfVec2h return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec2h GetComplement(GfVec2h const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -245,7 +249,7 @@ class GfVec2h /// Length half GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -258,7 +262,7 @@ class GfVec2h /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). half Normalize(half eps = 0.001) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. half length = GetLength(); *this /= (length > eps) ? length : eps; @@ -276,9 +280,9 @@ class GfVec2h half _data[2]; }; -/// Output a GfVec2h +/// Output a GfVec2h. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec2h const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec2h const &); #include "pxr/base/gf/vec2d.h" #include "pxr/base/gf/vec2f.h" @@ -309,7 +313,6 @@ GfDot(GfVec2h const &v1, GfVec2h const &v2) { } - /// Returns the geometric length of \c v. inline half GfGetLength(GfVec2h const &v) @@ -327,8 +330,8 @@ GfNormalize(GfVec2h *v, half eps = 0.001) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec2h GfGetNormalized(GfVec2h const &v, half eps = 0.001) { diff --git a/pxr/base/lib/gf/vec2i.h b/pxr/base/lib/gf/vec2i.h index 5388d755ab..34b13ef190 100644 --- a/pxr/base/lib/gf/vec2i.h +++ b/pxr/base/lib/gf/vec2i.h @@ -28,9 +28,13 @@ #ifndef GF_VEC2I_H #define GF_VEC2I_H +/// \file gf/vec2i.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -41,21 +45,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec2i.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec2i vec2i.h "pxr/base/gf/vec2i.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 2 int components. - * - * Represents a vector of 2 components of type \c int. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec2i +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 2 int components. +/// +/// Represents a vector of 2 components of type \c int. +/// It is intended to be fast and simple. +/// class GfVec2i { public: @@ -66,8 +63,8 @@ class GfVec2i /// Default constructor does no initialization. GfVec2i() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec2i(const GfVec2i &other) { *this = other; } @@ -82,7 +79,7 @@ class GfVec2i GfVec2i(int s0, int s1) { Set(s0, s1); } - + /// Construct with pointer to values. template explicit GfVec2i(Scl const *p) { Set(p); } @@ -99,7 +96,7 @@ class GfVec2i result[1] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 2. static GfVec2i Axis(size_t i) { @@ -108,7 +105,7 @@ class GfVec2i result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec2i &Set(int s0, int s1) { _data[0] = s0; @@ -147,12 +144,15 @@ class GfVec2i return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec2d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec2f const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec2h const &other) const; /// Create a vec with negated elements. @@ -184,10 +184,10 @@ class GfVec2i GfVec2i &operator*=(double s) { _data[0] *= s; _data[1] *= s; - return *this; + return *this; } GfVec2i operator*(double s) const { - return GfVec2i(*this) *= s; + return GfVec2i(*this) *= s; } friend GfVec2i operator*(double s, GfVec2i const &v) { return v * s; @@ -200,7 +200,7 @@ class GfVec2i return *this; } GfVec2i operator/(int s) const { - return GfVec2i(*this) /= s; + return GfVec2i(*this) /= s; } /// See GfDot(). @@ -208,7 +208,7 @@ class GfVec2i return _data[0] * v[0] + _data[1] * v[1]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -216,12 +216,13 @@ class GfVec2i return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec2i GetComplement(GfVec2i const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -234,9 +235,9 @@ class GfVec2i int _data[2]; }; -/// Output a GfVec2i +/// Output a GfVec2i. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec2i const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec2i const &); /// Returns component-wise multiplication of vectors \p v1 and \p v2. @@ -263,6 +264,5 @@ GfDot(GfVec2i const &v1, GfVec2i const &v2) { return v1 * v2; } - #endif // GF_VEC2I_H diff --git a/pxr/base/lib/gf/vec3d.h b/pxr/base/lib/gf/vec3d.h index 238d284d9c..5da218d28d 100644 --- a/pxr/base/lib/gf/vec3d.h +++ b/pxr/base/lib/gf/vec3d.h @@ -28,10 +28,14 @@ #ifndef GF_VEC3D_H #define GF_VEC3D_H +/// \file gf/vec3d.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" +#include "pxr/base/gf/api.h" #include @@ -43,21 +47,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec3d.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec3d vec3d.h "pxr/base/gf/vec3d.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 3 double components. - * - * Represents a vector of 3 components of type \c double. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec3d +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 3 double components. +/// +/// Represents a vector of 3 components of type \c double. +/// It is intended to be fast and simple. +/// class GfVec3d { public: @@ -68,8 +65,8 @@ class GfVec3d /// Default constructor does no initialization. GfVec3d() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec3d(const GfVec3d &other) { *this = other; } @@ -85,18 +82,21 @@ class GfVec3d GfVec3d(double s0, double s1, double s2) { Set(s0, s1, s2); } - + /// Construct with pointer to values. template explicit GfVec3d(Scl const *p) { Set(p); } /// Implicitly convert from GfVec3f. + GF_API GfVec3d(class GfVec3f const &other); /// Implicitly convert from GfVec3h. + GF_API GfVec3d(class GfVec3h const &other); /// Implicitly convert from GfVec3i. + GF_API GfVec3d(class GfVec3i const &other); /// Create a unit vector along the X-axis. @@ -117,7 +117,7 @@ class GfVec3d result[2] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 3. static GfVec3d Axis(size_t i) { @@ -126,7 +126,7 @@ class GfVec3d result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec3d &Set(double s0, double s1, double s2) { _data[0] = s0; @@ -168,12 +168,15 @@ class GfVec3d return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec3f const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec3h const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec3i const &other) const; /// Create a vec with negated elements. @@ -208,25 +211,25 @@ class GfVec3d _data[0] *= s; _data[1] *= s; _data[2] *= s; - return *this; + return *this; } GfVec3d operator*(double s) const { - return GfVec3d(*this) *= s; + return GfVec3d(*this) *= s; } friend GfVec3d operator*(double s, GfVec3d const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec3d &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec3d operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -234,7 +237,7 @@ class GfVec3d return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -242,12 +245,13 @@ class GfVec3d return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec3d GetComplement(GfVec3d const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -257,7 +261,7 @@ class GfVec3d /// Length double GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -270,7 +274,7 @@ class GfVec3d /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). double Normalize(double eps = GF_MIN_VECTOR_LENGTH) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. double length = GetLength(); *this /= (length > eps) ? length : eps; @@ -283,35 +287,37 @@ class GfVec3d return normalized; } - /// Orthogonalize and optionally normalize a set of basis vectors. - /// This uses an iterative method that is very stable even when the vectors - /// are far from orthogonal (close to colinear). The number of iterations - /// and thus the computation time does increase as the vectors become - /// close to colinear, however. - /// Returns a bool specifying whether the solution converged after - /// a number of iterations. If it did not converge, the returned vectors - /// will be as close as possible to orthogonal within the iteration limit. - /// Colinear vectors will be unaltered, and the method will return false. + /// Orthogonalize and optionally normalize a set of basis vectors. This + /// uses an iterative method that is very stable even when the vectors are + /// far from orthogonal (close to colinear). The number of iterations and + /// thus the computation time does increase as the vectors become close to + /// colinear, however. Returns a bool specifying whether the solution + /// converged after a number of iterations. If it did not converge, the + /// returned vectors will be as close as possible to orthogonal within the + /// iteration limit. Colinear vectors will be unaltered, and the method + /// will return false. + GF_API static bool OrthogonalizeBasis( GfVec3d *tx, GfVec3d *ty, GfVec3d *tz, const bool normalize, double eps = GF_MIN_ORTHO_TOLERANCE); - /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this - /// are mutually orthogonal. If the length L of *this is smaller than - /// \c eps, then v1 and v2 will have magnitude L/eps. As a result, - /// the function delivers a continuous result as *this shrinks in length. + /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this are + /// mutually orthogonal. If the length L of *this is smaller than \c eps, + /// then v1 and v2 will have magnitude L/eps. As a result, the function + /// delivers a continuous result as *this shrinks in length. + GF_API void BuildOrthonormalFrame(GfVec3d *v1, GfVec3d *v2, - double eps = GF_MIN_VECTOR_LENGTH) const; + double eps = GF_MIN_VECTOR_LENGTH) const; private: double _data[3]; }; -/// Output a GfVec3d +/// Output a GfVec3d. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec3d const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec3d const &); #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/vec3h.h" @@ -344,7 +350,6 @@ GfDot(GfVec3d const &v1, GfVec3d const &v2) { } - /// Returns the geometric length of \c v. inline double GfGetLength(GfVec3d const &v) @@ -362,8 +367,8 @@ GfNormalize(GfVec3d *v, double eps = GF_MIN_VECTOR_LENGTH) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec3d GfGetNormalized(GfVec3d const &v, double eps = GF_MIN_VECTOR_LENGTH) { @@ -400,11 +405,11 @@ GfIsClose(GfVec3d const &v1, GfVec3d const &v2, double tolerance) } -bool +GF_API bool GfOrthogonalizeBasis(GfVec3d *tx, GfVec3d *ty, GfVec3d *tz, bool normalize, double eps = GF_MIN_ORTHO_TOLERANCE); -void +GF_API void GfBuildOrthonormalFrame(GfVec3d const &v0, GfVec3d* v1, GfVec3d* v2, @@ -420,7 +425,8 @@ GfCross(GfVec3d const &v1, GfVec3d const &v2) v1[0] * v2[1] - v1[1] * v2[0]); } -/// Returns the cross product of \p v1 and \p v2. See also GfCross(). +/// Returns the cross product of \p v1 and \p v2. +/// \see GfCross() inline GfVec3d operator^(GfVec3d const &v1, GfVec3d const &v2) { @@ -428,7 +434,7 @@ operator^(GfVec3d const &v1, GfVec3d const &v2) } /// Spherical linear interpolation in three dimensions. -GfVec3d +GF_API GfVec3d GfSlerp(double alpha, GfVec3d const &v0, GfVec3d const &v1); diff --git a/pxr/base/lib/gf/vec3f.h b/pxr/base/lib/gf/vec3f.h index a56c6f79e9..974ffe4b04 100644 --- a/pxr/base/lib/gf/vec3f.h +++ b/pxr/base/lib/gf/vec3f.h @@ -28,10 +28,14 @@ #ifndef GF_VEC3F_H #define GF_VEC3F_H +/// \file gf/vec3f.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" +#include "pxr/base/gf/api.h" #include @@ -43,21 +47,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec3f.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec3f vec3f.h "pxr/base/gf/vec3f.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 3 float components. - * - * Represents a vector of 3 components of type \c float. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec3f +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 3 float components. +/// +/// Represents a vector of 3 components of type \c float. +/// It is intended to be fast and simple. +/// class GfVec3f { public: @@ -68,8 +65,8 @@ class GfVec3f /// Default constructor does no initialization. GfVec3f() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec3f(const GfVec3f &other) { *this = other; } @@ -85,18 +82,21 @@ class GfVec3f GfVec3f(float s0, float s1, float s2) { Set(s0, s1, s2); } - + /// Construct with pointer to values. template explicit GfVec3f(Scl const *p) { Set(p); } /// Construct from GfVec3d. + GF_API explicit GfVec3f(class GfVec3d const &other); /// Implicitly convert from GfVec3h. + GF_API GfVec3f(class GfVec3h const &other); /// Implicitly convert from GfVec3i. + GF_API GfVec3f(class GfVec3i const &other); /// Create a unit vector along the X-axis. @@ -117,7 +117,7 @@ class GfVec3f result[2] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 3. static GfVec3f Axis(size_t i) { @@ -126,7 +126,7 @@ class GfVec3f result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec3f &Set(float s0, float s1, float s2) { _data[0] = s0; @@ -168,12 +168,15 @@ class GfVec3f return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec3d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec3h const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec3i const &other) const; /// Create a vec with negated elements. @@ -208,25 +211,25 @@ class GfVec3f _data[0] *= s; _data[1] *= s; _data[2] *= s; - return *this; + return *this; } GfVec3f operator*(double s) const { - return GfVec3f(*this) *= s; + return GfVec3f(*this) *= s; } friend GfVec3f operator*(double s, GfVec3f const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec3f &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec3f operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -234,7 +237,7 @@ class GfVec3f return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -242,12 +245,13 @@ class GfVec3f return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec3f GetComplement(GfVec3f const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -257,7 +261,7 @@ class GfVec3f /// Length float GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -270,7 +274,7 @@ class GfVec3f /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). float Normalize(float eps = GF_MIN_VECTOR_LENGTH) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. float length = GetLength(); *this /= (length > eps) ? length : eps; @@ -283,35 +287,37 @@ class GfVec3f return normalized; } - /// Orthogonalize and optionally normalize a set of basis vectors. - /// This uses an iterative method that is very stable even when the vectors - /// are far from orthogonal (close to colinear). The number of iterations - /// and thus the computation time does increase as the vectors become - /// close to colinear, however. - /// Returns a bool specifying whether the solution converged after - /// a number of iterations. If it did not converge, the returned vectors - /// will be as close as possible to orthogonal within the iteration limit. - /// Colinear vectors will be unaltered, and the method will return false. + /// Orthogonalize and optionally normalize a set of basis vectors. This + /// uses an iterative method that is very stable even when the vectors are + /// far from orthogonal (close to colinear). The number of iterations and + /// thus the computation time does increase as the vectors become close to + /// colinear, however. Returns a bool specifying whether the solution + /// converged after a number of iterations. If it did not converge, the + /// returned vectors will be as close as possible to orthogonal within the + /// iteration limit. Colinear vectors will be unaltered, and the method + /// will return false. + GF_API static bool OrthogonalizeBasis( GfVec3f *tx, GfVec3f *ty, GfVec3f *tz, const bool normalize, double eps = GF_MIN_ORTHO_TOLERANCE); - /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this - /// are mutually orthogonal. If the length L of *this is smaller than - /// \c eps, then v1 and v2 will have magnitude L/eps. As a result, - /// the function delivers a continuous result as *this shrinks in length. + /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this are + /// mutually orthogonal. If the length L of *this is smaller than \c eps, + /// then v1 and v2 will have magnitude L/eps. As a result, the function + /// delivers a continuous result as *this shrinks in length. + GF_API void BuildOrthonormalFrame(GfVec3f *v1, GfVec3f *v2, - float eps = GF_MIN_VECTOR_LENGTH) const; + float eps = GF_MIN_VECTOR_LENGTH) const; private: float _data[3]; }; -/// Output a GfVec3f +/// Output a GfVec3f. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec3f const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec3f const &); #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/vec3h.h" @@ -344,7 +350,6 @@ GfDot(GfVec3f const &v1, GfVec3f const &v2) { } - /// Returns the geometric length of \c v. inline float GfGetLength(GfVec3f const &v) @@ -362,8 +367,8 @@ GfNormalize(GfVec3f *v, float eps = GF_MIN_VECTOR_LENGTH) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec3f GfGetNormalized(GfVec3f const &v, float eps = GF_MIN_VECTOR_LENGTH) { @@ -400,11 +405,11 @@ GfIsClose(GfVec3f const &v1, GfVec3f const &v2, double tolerance) } -bool +GF_API bool GfOrthogonalizeBasis(GfVec3f *tx, GfVec3f *ty, GfVec3f *tz, bool normalize, double eps = GF_MIN_ORTHO_TOLERANCE); -void +GF_API void GfBuildOrthonormalFrame(GfVec3f const &v0, GfVec3f* v1, GfVec3f* v2, @@ -420,7 +425,8 @@ GfCross(GfVec3f const &v1, GfVec3f const &v2) v1[0] * v2[1] - v1[1] * v2[0]); } -/// Returns the cross product of \p v1 and \p v2. See also GfCross(). +/// Returns the cross product of \p v1 and \p v2. +/// \see GfCross() inline GfVec3f operator^(GfVec3f const &v1, GfVec3f const &v2) { @@ -428,7 +434,7 @@ operator^(GfVec3f const &v1, GfVec3f const &v2) } /// Spherical linear interpolation in three dimensions. -GfVec3f +GF_API GfVec3f GfSlerp(double alpha, GfVec3f const &v0, GfVec3f const &v1); diff --git a/pxr/base/lib/gf/vec3h.h b/pxr/base/lib/gf/vec3h.h index 8dbfda60b2..c0e8595bf5 100644 --- a/pxr/base/lib/gf/vec3h.h +++ b/pxr/base/lib/gf/vec3h.h @@ -28,11 +28,15 @@ #ifndef GF_VEC3H_H #define GF_VEC3H_H +/// \file gf/vec3h.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" #include "pxr/base/gf/half.h" +#include "pxr/base/gf/api.h" #include @@ -44,21 +48,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec3h.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec3h vec3h.h "pxr/base/gf/vec3h.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 3 half components. - * - * Represents a vector of 3 components of type \c half. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec3h +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 3 half components. +/// +/// Represents a vector of 3 components of type \c half. +/// It is intended to be fast and simple. +/// class GfVec3h { public: @@ -69,8 +66,8 @@ class GfVec3h /// Default constructor does no initialization. GfVec3h() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec3h(const GfVec3h &other) { *this = other; } @@ -86,18 +83,21 @@ class GfVec3h GfVec3h(half s0, half s1, half s2) { Set(s0, s1, s2); } - + /// Construct with pointer to values. template explicit GfVec3h(Scl const *p) { Set(p); } /// Construct from GfVec3d. + GF_API explicit GfVec3h(class GfVec3d const &other); /// Construct from GfVec3f. + GF_API explicit GfVec3h(class GfVec3f const &other); /// Implicitly convert from GfVec3i. + GF_API GfVec3h(class GfVec3i const &other); /// Create a unit vector along the X-axis. @@ -118,7 +118,7 @@ class GfVec3h result[2] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 3. static GfVec3h Axis(size_t i) { @@ -127,7 +127,7 @@ class GfVec3h result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec3h &Set(half s0, half s1, half s2) { _data[0] = s0; @@ -169,12 +169,15 @@ class GfVec3h return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec3d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec3f const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec3i const &other) const; /// Create a vec with negated elements. @@ -209,25 +212,25 @@ class GfVec3h _data[0] *= s; _data[1] *= s; _data[2] *= s; - return *this; + return *this; } GfVec3h operator*(double s) const { - return GfVec3h(*this) *= s; + return GfVec3h(*this) *= s; } friend GfVec3h operator*(double s, GfVec3h const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec3h &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec3h operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -235,7 +238,7 @@ class GfVec3h return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -243,12 +246,13 @@ class GfVec3h return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec3h GetComplement(GfVec3h const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -258,7 +262,7 @@ class GfVec3h /// Length half GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -271,7 +275,7 @@ class GfVec3h /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). half Normalize(half eps = 0.001) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. half length = GetLength(); *this /= (length > eps) ? length : eps; @@ -284,35 +288,37 @@ class GfVec3h return normalized; } - /// Orthogonalize and optionally normalize a set of basis vectors. - /// This uses an iterative method that is very stable even when the vectors - /// are far from orthogonal (close to colinear). The number of iterations - /// and thus the computation time does increase as the vectors become - /// close to colinear, however. - /// Returns a bool specifying whether the solution converged after - /// a number of iterations. If it did not converge, the returned vectors - /// will be as close as possible to orthogonal within the iteration limit. - /// Colinear vectors will be unaltered, and the method will return false. + /// Orthogonalize and optionally normalize a set of basis vectors. This + /// uses an iterative method that is very stable even when the vectors are + /// far from orthogonal (close to colinear). The number of iterations and + /// thus the computation time does increase as the vectors become close to + /// colinear, however. Returns a bool specifying whether the solution + /// converged after a number of iterations. If it did not converge, the + /// returned vectors will be as close as possible to orthogonal within the + /// iteration limit. Colinear vectors will be unaltered, and the method + /// will return false. + GF_API static bool OrthogonalizeBasis( GfVec3h *tx, GfVec3h *ty, GfVec3h *tz, const bool normalize, double eps = GF_MIN_ORTHO_TOLERANCE); - /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this - /// are mutually orthogonal. If the length L of *this is smaller than - /// \c eps, then v1 and v2 will have magnitude L/eps. As a result, - /// the function delivers a continuous result as *this shrinks in length. + /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this are + /// mutually orthogonal. If the length L of *this is smaller than \c eps, + /// then v1 and v2 will have magnitude L/eps. As a result, the function + /// delivers a continuous result as *this shrinks in length. + GF_API void BuildOrthonormalFrame(GfVec3h *v1, GfVec3h *v2, - half eps = 0.001) const; + half eps = 0.001) const; private: half _data[3]; }; -/// Output a GfVec3h +/// Output a GfVec3h. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec3h const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec3h const &); #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/vec3f.h" @@ -345,7 +351,6 @@ GfDot(GfVec3h const &v1, GfVec3h const &v2) { } - /// Returns the geometric length of \c v. inline half GfGetLength(GfVec3h const &v) @@ -363,8 +368,8 @@ GfNormalize(GfVec3h *v, half eps = 0.001) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec3h GfGetNormalized(GfVec3h const &v, half eps = 0.001) { @@ -401,11 +406,11 @@ GfIsClose(GfVec3h const &v1, GfVec3h const &v2, double tolerance) } -bool +GF_API bool GfOrthogonalizeBasis(GfVec3h *tx, GfVec3h *ty, GfVec3h *tz, bool normalize, double eps = GF_MIN_ORTHO_TOLERANCE); -void +GF_API void GfBuildOrthonormalFrame(GfVec3h const &v0, GfVec3h* v1, GfVec3h* v2, @@ -421,7 +426,8 @@ GfCross(GfVec3h const &v1, GfVec3h const &v2) v1[0] * v2[1] - v1[1] * v2[0]); } -/// Returns the cross product of \p v1 and \p v2. See also GfCross(). +/// Returns the cross product of \p v1 and \p v2. +/// \see GfCross() inline GfVec3h operator^(GfVec3h const &v1, GfVec3h const &v2) { @@ -429,7 +435,7 @@ operator^(GfVec3h const &v1, GfVec3h const &v2) } /// Spherical linear interpolation in three dimensions. -GfVec3h +GF_API GfVec3h GfSlerp(double alpha, GfVec3h const &v0, GfVec3h const &v1); diff --git a/pxr/base/lib/gf/vec3i.h b/pxr/base/lib/gf/vec3i.h index 7b7efea20e..5a7f55ba92 100644 --- a/pxr/base/lib/gf/vec3i.h +++ b/pxr/base/lib/gf/vec3i.h @@ -28,9 +28,13 @@ #ifndef GF_VEC3I_H #define GF_VEC3I_H +/// \file gf/vec3i.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -41,21 +45,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec3i.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec3i vec3i.h "pxr/base/gf/vec3i.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 3 int components. - * - * Represents a vector of 3 components of type \c int. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec3i +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 3 int components. +/// +/// Represents a vector of 3 components of type \c int. +/// It is intended to be fast and simple. +/// class GfVec3i { public: @@ -66,8 +63,8 @@ class GfVec3i /// Default constructor does no initialization. GfVec3i() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec3i(const GfVec3i &other) { *this = other; } @@ -83,7 +80,7 @@ class GfVec3i GfVec3i(int s0, int s1, int s2) { Set(s0, s1, s2); } - + /// Construct with pointer to values. template explicit GfVec3i(Scl const *p) { Set(p); } @@ -106,7 +103,7 @@ class GfVec3i result[2] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 3. static GfVec3i Axis(size_t i) { @@ -115,7 +112,7 @@ class GfVec3i result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec3i &Set(int s0, int s1, int s2) { _data[0] = s0; @@ -157,12 +154,15 @@ class GfVec3i return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec3d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec3f const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec3h const &other) const; /// Create a vec with negated elements. @@ -197,10 +197,10 @@ class GfVec3i _data[0] *= s; _data[1] *= s; _data[2] *= s; - return *this; + return *this; } GfVec3i operator*(double s) const { - return GfVec3i(*this) *= s; + return GfVec3i(*this) *= s; } friend GfVec3i operator*(double s, GfVec3i const &v) { return v * s; @@ -214,7 +214,7 @@ class GfVec3i return *this; } GfVec3i operator/(int s) const { - return GfVec3i(*this) /= s; + return GfVec3i(*this) /= s; } /// See GfDot(). @@ -222,7 +222,7 @@ class GfVec3i return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -230,12 +230,13 @@ class GfVec3i return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec3i GetComplement(GfVec3i const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -248,9 +249,9 @@ class GfVec3i int _data[3]; }; -/// Output a GfVec3i +/// Output a GfVec3i. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec3i const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec3i const &); /// Returns component-wise multiplication of vectors \p v1 and \p v2. @@ -279,6 +280,5 @@ GfDot(GfVec3i const &v1, GfVec3i const &v2) { return v1 * v2; } - #endif // GF_VEC3I_H diff --git a/pxr/base/lib/gf/vec4d.h b/pxr/base/lib/gf/vec4d.h index 74fc030e3c..461bc1d7b2 100644 --- a/pxr/base/lib/gf/vec4d.h +++ b/pxr/base/lib/gf/vec4d.h @@ -28,10 +28,14 @@ #ifndef GF_VEC4D_H #define GF_VEC4D_H +/// \file gf/vec4d.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" +#include "pxr/base/gf/api.h" #include @@ -43,21 +47,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec4d.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec4d vec4d.h "pxr/base/gf/vec4d.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 4 double components. - * - * Represents a vector of 4 components of type \c double. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec4d +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 4 double components. +/// +/// Represents a vector of 4 components of type \c double. +/// It is intended to be fast and simple. +/// class GfVec4d { public: @@ -68,8 +65,8 @@ class GfVec4d /// Default constructor does no initialization. GfVec4d() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec4d(const GfVec4d &other) { *this = other; } @@ -86,18 +83,21 @@ class GfVec4d GfVec4d(double s0, double s1, double s2, double s3) { Set(s0, s1, s2, s3); } - + /// Construct with pointer to values. template explicit GfVec4d(Scl const *p) { Set(p); } /// Implicitly convert from GfVec4f. + GF_API GfVec4d(class GfVec4f const &other); /// Implicitly convert from GfVec4h. + GF_API GfVec4d(class GfVec4h const &other); /// Implicitly convert from GfVec4i. + GF_API GfVec4d(class GfVec4i const &other); /// Create a unit vector along the X-axis. @@ -124,7 +124,7 @@ class GfVec4d result[3] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 4. static GfVec4d Axis(size_t i) { @@ -133,7 +133,7 @@ class GfVec4d result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec4d &Set(double s0, double s1, double s2, double s3) { _data[0] = s0; @@ -178,12 +178,15 @@ class GfVec4d return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec4f const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec4h const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec4i const &other) const; /// Create a vec with negated elements. @@ -221,25 +224,25 @@ class GfVec4d _data[1] *= s; _data[2] *= s; _data[3] *= s; - return *this; + return *this; } GfVec4d operator*(double s) const { - return GfVec4d(*this) *= s; + return GfVec4d(*this) *= s; } friend GfVec4d operator*(double s, GfVec4d const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec4d &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec4d operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -247,7 +250,7 @@ class GfVec4d return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2] + _data[3] * v[3]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -255,12 +258,13 @@ class GfVec4d return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec4d GetComplement(GfVec4d const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -270,7 +274,7 @@ class GfVec4d /// Length double GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -283,7 +287,7 @@ class GfVec4d /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). double Normalize(double eps = GF_MIN_VECTOR_LENGTH) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. double length = GetLength(); *this /= (length > eps) ? length : eps; @@ -301,9 +305,9 @@ class GfVec4d double _data[4]; }; -/// Output a GfVec4d +/// Output a GfVec4d. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec4d const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec4d const &); #include "pxr/base/gf/vec4f.h" #include "pxr/base/gf/vec4h.h" @@ -338,7 +342,6 @@ GfDot(GfVec4d const &v1, GfVec4d const &v2) { } - /// Returns the geometric length of \c v. inline double GfGetLength(GfVec4d const &v) @@ -356,8 +359,8 @@ GfNormalize(GfVec4d *v, double eps = GF_MIN_VECTOR_LENGTH) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec4d GfGetNormalized(GfVec4d const &v, double eps = GF_MIN_VECTOR_LENGTH) { diff --git a/pxr/base/lib/gf/vec4f.h b/pxr/base/lib/gf/vec4f.h index 3ab39c66f0..f700e5a811 100644 --- a/pxr/base/lib/gf/vec4f.h +++ b/pxr/base/lib/gf/vec4f.h @@ -28,10 +28,14 @@ #ifndef GF_VEC4F_H #define GF_VEC4F_H +/// \file gf/vec4f.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" +#include "pxr/base/gf/api.h" #include @@ -43,21 +47,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec4f.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec4f vec4f.h "pxr/base/gf/vec4f.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 4 float components. - * - * Represents a vector of 4 components of type \c float. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec4f +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 4 float components. +/// +/// Represents a vector of 4 components of type \c float. +/// It is intended to be fast and simple. +/// class GfVec4f { public: @@ -68,8 +65,8 @@ class GfVec4f /// Default constructor does no initialization. GfVec4f() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec4f(const GfVec4f &other) { *this = other; } @@ -86,18 +83,21 @@ class GfVec4f GfVec4f(float s0, float s1, float s2, float s3) { Set(s0, s1, s2, s3); } - + /// Construct with pointer to values. template explicit GfVec4f(Scl const *p) { Set(p); } /// Construct from GfVec4d. + GF_API explicit GfVec4f(class GfVec4d const &other); /// Implicitly convert from GfVec4h. + GF_API GfVec4f(class GfVec4h const &other); /// Implicitly convert from GfVec4i. + GF_API GfVec4f(class GfVec4i const &other); /// Create a unit vector along the X-axis. @@ -124,7 +124,7 @@ class GfVec4f result[3] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 4. static GfVec4f Axis(size_t i) { @@ -133,7 +133,7 @@ class GfVec4f result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec4f &Set(float s0, float s1, float s2, float s3) { _data[0] = s0; @@ -178,12 +178,15 @@ class GfVec4f return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec4d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec4h const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec4i const &other) const; /// Create a vec with negated elements. @@ -221,25 +224,25 @@ class GfVec4f _data[1] *= s; _data[2] *= s; _data[3] *= s; - return *this; + return *this; } GfVec4f operator*(double s) const { - return GfVec4f(*this) *= s; + return GfVec4f(*this) *= s; } friend GfVec4f operator*(double s, GfVec4f const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec4f &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec4f operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -247,7 +250,7 @@ class GfVec4f return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2] + _data[3] * v[3]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -255,12 +258,13 @@ class GfVec4f return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec4f GetComplement(GfVec4f const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -270,7 +274,7 @@ class GfVec4f /// Length float GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -283,7 +287,7 @@ class GfVec4f /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). float Normalize(float eps = GF_MIN_VECTOR_LENGTH) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. float length = GetLength(); *this /= (length > eps) ? length : eps; @@ -301,9 +305,9 @@ class GfVec4f float _data[4]; }; -/// Output a GfVec4f +/// Output a GfVec4f. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec4f const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec4f const &); #include "pxr/base/gf/vec4d.h" #include "pxr/base/gf/vec4h.h" @@ -338,7 +342,6 @@ GfDot(GfVec4f const &v1, GfVec4f const &v2) { } - /// Returns the geometric length of \c v. inline float GfGetLength(GfVec4f const &v) @@ -356,8 +359,8 @@ GfNormalize(GfVec4f *v, float eps = GF_MIN_VECTOR_LENGTH) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec4f GfGetNormalized(GfVec4f const &v, float eps = GF_MIN_VECTOR_LENGTH) { diff --git a/pxr/base/lib/gf/vec4h.h b/pxr/base/lib/gf/vec4h.h index 7c5eb7b7c3..fb1924eb4f 100644 --- a/pxr/base/lib/gf/vec4h.h +++ b/pxr/base/lib/gf/vec4h.h @@ -28,11 +28,15 @@ #ifndef GF_VEC4H_H #define GF_VEC4H_H +/// \file gf/vec4h.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" #include "pxr/base/gf/math.h" #include "pxr/base/gf/half.h" +#include "pxr/base/gf/api.h" #include @@ -44,21 +48,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec4h.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec4h vec4h.h "pxr/base/gf/vec4h.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 4 half components. - * - * Represents a vector of 4 components of type \c half. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec4h +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 4 half components. +/// +/// Represents a vector of 4 components of type \c half. +/// It is intended to be fast and simple. +/// class GfVec4h { public: @@ -69,8 +66,8 @@ class GfVec4h /// Default constructor does no initialization. GfVec4h() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec4h(const GfVec4h &other) { *this = other; } @@ -87,18 +84,21 @@ class GfVec4h GfVec4h(half s0, half s1, half s2, half s3) { Set(s0, s1, s2, s3); } - + /// Construct with pointer to values. template explicit GfVec4h(Scl const *p) { Set(p); } /// Construct from GfVec4d. + GF_API explicit GfVec4h(class GfVec4d const &other); /// Construct from GfVec4f. + GF_API explicit GfVec4h(class GfVec4f const &other); /// Implicitly convert from GfVec4i. + GF_API GfVec4h(class GfVec4i const &other); /// Create a unit vector along the X-axis. @@ -125,7 +125,7 @@ class GfVec4h result[3] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 4. static GfVec4h Axis(size_t i) { @@ -134,7 +134,7 @@ class GfVec4h result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec4h &Set(half s0, half s1, half s2, half s3) { _data[0] = s0; @@ -179,12 +179,15 @@ class GfVec4h return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec4d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec4f const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec4i const &other) const; /// Create a vec with negated elements. @@ -222,25 +225,25 @@ class GfVec4h _data[1] *= s; _data[2] *= s; _data[3] *= s; - return *this; + return *this; } GfVec4h operator*(double s) const { - return GfVec4h(*this) *= s; + return GfVec4h(*this) *= s; } friend GfVec4h operator*(double s, GfVec4h const &v) { return v * s; } /// Division by scalar. - // XXX: should divide by the scalar type. + // TODO should divide by the scalar type. GfVec4h &operator/=(double s) { - // XXX: This should not multiply by 1/s, it should do the division. + // TODO This should not multiply by 1/s, it should do the division. // Doing the division is more numerically stable when s is close to // zero. return *this *= (1.0 / s); } GfVec4h operator/(double s) const { - return *this * (1.0 / s); + return *this * (1.0 / s); } /// See GfDot(). @@ -248,7 +251,7 @@ class GfVec4h return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2] + _data[3] * v[3]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -256,12 +259,13 @@ class GfVec4h return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec4h GetComplement(GfVec4h const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -271,7 +275,7 @@ class GfVec4h /// Length half GetLength() const { - // XXX: should use GfSqrt. + // TODO should use GfSqrt. return sqrt(GetLengthSq()); } @@ -284,7 +288,7 @@ class GfVec4h /// By tickling the code, it no longer tries to write into /// an illegal memory address (in the code section of memory). half Normalize(half eps = 0.001) { - // XXX: this seems suspect... suggest dividing by length so long as + // TODO this seems suspect... suggest dividing by length so long as // length is not zero. half length = GetLength(); *this /= (length > eps) ? length : eps; @@ -302,9 +306,9 @@ class GfVec4h half _data[4]; }; -/// Output a GfVec4h +/// Output a GfVec4h. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec4h const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec4h const &); #include "pxr/base/gf/vec4d.h" #include "pxr/base/gf/vec4f.h" @@ -339,7 +343,6 @@ GfDot(GfVec4h const &v1, GfVec4h const &v2) { } - /// Returns the geometric length of \c v. inline half GfGetLength(GfVec4h const &v) @@ -357,8 +360,8 @@ GfNormalize(GfVec4h *v, half eps = 0.001) } /// Returns a normalized (unit-length) vector with the same direction as \p v. -/// If the length of this vector is smaller than \p eps, the vector divided -/// by \p eps is returned. +/// If the length of this vector is smaller than \p eps, the vector divided by +/// \p eps is returned. inline GfVec4h GfGetNormalized(GfVec4h const &v, half eps = 0.001) { diff --git a/pxr/base/lib/gf/vec4i.h b/pxr/base/lib/gf/vec4i.h index 15900875d2..8887a243cf 100644 --- a/pxr/base/lib/gf/vec4i.h +++ b/pxr/base/lib/gf/vec4i.h @@ -28,9 +28,13 @@ #ifndef GF_VEC4I_H #define GF_VEC4I_H +/// \file gf/vec4i.h +/// \ingroup group_gf_LinearAlgebra + #include "pxr/base/tf/diagnostic.h" #include "pxr/base/gf/limits.h" #include "pxr/base/gf/traits.h" +#include "pxr/base/gf/api.h" #include @@ -41,21 +45,14 @@ template <> struct GfIsGfVec { static const bool value = true; }; -/*! - * \file vec4i.h - * \ingroup group_gf_LinearAlgebra - */ - -/*! - * \class GfVec4i vec4i.h "pxr/base/gf/vec4i.h" - * \ingroup group_gf_LinearAlgebra - * \brief Basic type for a vector of 4 int components. - * - * Represents a vector of 4 components of type \c int. - * It is intended to be fast and simple. - * - */ - +/// \class GfVec4i +/// \ingroup group_gf_LinearAlgebra +/// +/// Basic type for a vector of 4 int components. +/// +/// Represents a vector of 4 components of type \c int. +/// It is intended to be fast and simple. +/// class GfVec4i { public: @@ -66,8 +63,8 @@ class GfVec4i /// Default constructor does no initialization. GfVec4i() {} - - // Copy constructor. XXX: Remove this, use compiler-generated. + // Copy constructor. + // TODO Remove this, use compiler-generated. GfVec4i(const GfVec4i &other) { *this = other; } @@ -84,7 +81,7 @@ class GfVec4i GfVec4i(int s0, int s1, int s2, int s3) { Set(s0, s1, s2, s3); } - + /// Construct with pointer to values. template explicit GfVec4i(Scl const *p) { Set(p); } @@ -113,7 +110,7 @@ class GfVec4i result[3] = 1; return result; } - + /// Create a unit vector along the i-th axis, zero-based. Return the zero /// vector if \p i is greater than or equal to 4. static GfVec4i Axis(size_t i) { @@ -122,7 +119,7 @@ class GfVec4i result[i] = 1; return result; } - + /// Set all elements with passed arguments. GfVec4i &Set(int s0, int s1, int s2, int s3) { _data[0] = s0; @@ -167,12 +164,15 @@ class GfVec4i return !(*this == other); } - // XXX: Add inequality for other vec types... + // TODO Add inequality for other vec types... /// Equality comparison. + GF_API bool operator==(class GfVec4d const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec4f const &other) const; /// Equality comparison. + GF_API bool operator==(class GfVec4h const &other) const; /// Create a vec with negated elements. @@ -210,10 +210,10 @@ class GfVec4i _data[1] *= s; _data[2] *= s; _data[3] *= s; - return *this; + return *this; } GfVec4i operator*(double s) const { - return GfVec4i(*this) *= s; + return GfVec4i(*this) *= s; } friend GfVec4i operator*(double s, GfVec4i const &v) { return v * s; @@ -228,7 +228,7 @@ class GfVec4i return *this; } GfVec4i operator/(int s) const { - return GfVec4i(*this) /= s; + return GfVec4i(*this) /= s; } /// See GfDot(). @@ -236,7 +236,7 @@ class GfVec4i return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2] + _data[3] * v[3]; } - /// Returns the projection of \p this onto \p v. That is: + /// Returns the projection of \p this onto \p v. That is: /// \code /// v * (*this * v) /// \endcode @@ -244,12 +244,13 @@ class GfVec4i return v * (*this * v); } - /// Returns the orthogonal complement of \p this->GetProjection(b). That is: + /// Returns the orthogonal complement of \p this->GetProjection(b). + /// That is: /// \code /// *this - this->GetProjection(b) /// \endcode GfVec4i GetComplement(GfVec4i const &b) const { - return *this - this->GetProjection(b); + return *this - this->GetProjection(b); } /// Squared length. @@ -262,9 +263,9 @@ class GfVec4i int _data[4]; }; -/// Output a GfVec4i +/// Output a GfVec4i. /// \ingroup group_gf_DebuggingOutput -std::ostream& operator<<(std::ostream &, GfVec4i const &); +GF_API std::ostream& operator<<(std::ostream &, GfVec4i const &); /// Returns component-wise multiplication of vectors \p v1 and \p v2. @@ -295,6 +296,5 @@ GfDot(GfVec4i const &v1, GfVec4i const &v2) { return v1 * v2; } - #endif // GF_VEC4I_H diff --git a/pxr/base/lib/gf/wrapBBox3d.cpp b/pxr/base/lib/gf/wrapBBox3d.cpp index 5260dd6267..884b2e0d61 100644 --- a/pxr/base/lib/gf/wrapBBox3d.cpp +++ b/pxr/base/lib/gf/wrapBBox3d.cpp @@ -21,17 +21,17 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include +#include + #include "pxr/base/gf/bbox3d.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapCamera.cpp b/pxr/base/lib/gf/wrapCamera.cpp index e486a0eb0e..76be0d4ed3 100644 --- a/pxr/base/lib/gf/wrapCamera.cpp +++ b/pxr/base/lib/gf/wrapCamera.cpp @@ -23,14 +23,13 @@ // /// /// \file gf/wrapCamera.h +#include #include "pxr/base/gf/camera.h" #include "pxr/base/gf/frustum.h" #include "pxr/base/tf/pyEnum.h" -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapColorRamp.cpp b/pxr/base/lib/gf/wrapColorRamp.cpp index 5908b455eb..fa4fdb13ee 100644 --- a/pxr/base/lib/gf/wrapColorRamp.cpp +++ b/pxr/base/lib/gf/wrapColorRamp.cpp @@ -21,12 +21,12 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include + #include "pxr/base/gf/colorRamp.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include - using namespace boost::python; static std::string diff --git a/pxr/base/lib/gf/wrapFrustum.cpp b/pxr/base/lib/gf/wrapFrustum.cpp index 3ab6691773..5bc6011225 100644 --- a/pxr/base/lib/gf/wrapFrustum.cpp +++ b/pxr/base/lib/gf/wrapFrustum.cpp @@ -21,13 +21,6 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/base/gf/frustum.h" -#include "pxr/base/gf/ray.h" - -#include "pxr/base/tf/pyEnum.h" -#include "pxr/base/tf/pyResultConversions.h" -#include "pxr/base/tf/wrapTypeHelpers.h" - #include #include #include @@ -36,6 +29,12 @@ #include #include +#include "pxr/base/gf/frustum.h" +#include "pxr/base/gf/ray.h" + +#include "pxr/base/tf/pyEnum.h" +#include "pxr/base/tf/pyResultConversions.h" +#include "pxr/base/tf/wrapTypeHelpers.h" using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapHalf.cpp b/pxr/base/lib/gf/wrapHalf.cpp index 9758174966..71b847473e 100644 --- a/pxr/base/lib/gf/wrapHalf.cpp +++ b/pxr/base/lib/gf/wrapHalf.cpp @@ -28,6 +28,8 @@ #include #include +#include + using namespace boost::python; namespace { diff --git a/pxr/base/lib/gf/wrapInterval.cpp b/pxr/base/lib/gf/wrapInterval.cpp index ae7aa48e64..903e455524 100644 --- a/pxr/base/lib/gf/wrapInterval.cpp +++ b/pxr/base/lib/gf/wrapInterval.cpp @@ -21,15 +21,16 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include + #include "pxr/base/gf/interval.h" #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapLine.cpp b/pxr/base/lib/gf/wrapLine.cpp index e8d72f6745..83b7496f91 100644 --- a/pxr/base/lib/gf/wrapLine.cpp +++ b/pxr/base/lib/gf/wrapLine.cpp @@ -21,11 +21,6 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/base/gf/line.h" - -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/wrapTypeHelpers.h" - #include #include #include @@ -33,6 +28,11 @@ #include #include +#include "pxr/base/gf/line.h" + +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/wrapTypeHelpers.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapLineSeg.cpp b/pxr/base/lib/gf/wrapLineSeg.cpp index 4895988888..d04ee1bdd5 100644 --- a/pxr/base/lib/gf/wrapLineSeg.cpp +++ b/pxr/base/lib/gf/wrapLineSeg.cpp @@ -21,11 +21,6 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/base/gf/lineSeg.h" - -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/wrapTypeHelpers.h" - #include #include #include @@ -33,6 +28,11 @@ #include #include +#include "pxr/base/gf/lineSeg.h" + +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/wrapTypeHelpers.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapMatrix.template.cpp b/pxr/base/lib/gf/wrapMatrix.template.cpp index 163445a881..ccbce52157 100644 --- a/pxr/base/lib/gf/wrapMatrix.template.cpp +++ b/pxr/base/lib/gf/wrapMatrix.template.cpp @@ -23,6 +23,15 @@ // language governing permissions and limitations under the Apache License. // #} +#include +#include +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/matrix{{ DIM }}d.h" #include "pxr/base/gf/matrix{{ DIM }}f.h" @@ -35,15 +44,6 @@ #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include -#include -#include -#include -#include - #include #include diff --git a/pxr/base/lib/gf/wrapMatrix2d.cpp b/pxr/base/lib/gf/wrapMatrix2d.cpp index 23fbeeeb94..9f70297391 100644 --- a/pxr/base/lib/gf/wrapMatrix2d.cpp +++ b/pxr/base/lib/gf/wrapMatrix2d.cpp @@ -24,16 +24,6 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapMatrix2.template.cpp file to make changes. -#include "pxr/base/gf/matrix2d.h" -#include "pxr/base/gf/matrix2f.h" - -#include "pxr/base/gf/pyBufferUtils.h" - - -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/pyContainerConversions.h" -#include "pxr/base/tf/wrapTypeHelpers.h" - #include #include #include @@ -43,6 +33,15 @@ #include #include +#include "pxr/base/gf/matrix2d.h" +#include "pxr/base/gf/matrix2f.h" + +#include "pxr/base/gf/pyBufferUtils.h" + +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/pyContainerConversions.h" +#include "pxr/base/tf/wrapTypeHelpers.h" + #include #include diff --git a/pxr/base/lib/gf/wrapMatrix2f.cpp b/pxr/base/lib/gf/wrapMatrix2f.cpp index f4706d8912..a26ad38ee9 100644 --- a/pxr/base/lib/gf/wrapMatrix2f.cpp +++ b/pxr/base/lib/gf/wrapMatrix2f.cpp @@ -23,6 +23,14 @@ // // This file is generated by a script. Do not edit directly. Edit the // wrapMatrix2.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include +#include #include "pxr/base/gf/matrix2d.h" #include "pxr/base/gf/matrix2f.h" @@ -34,15 +42,6 @@ #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include -#include -#include -#include -#include - #include #include diff --git a/pxr/base/lib/gf/wrapMatrix3d.cpp b/pxr/base/lib/gf/wrapMatrix3d.cpp index 45c110d730..063d0b1366 100644 --- a/pxr/base/lib/gf/wrapMatrix3d.cpp +++ b/pxr/base/lib/gf/wrapMatrix3d.cpp @@ -25,6 +25,15 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapMatrix3.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/matrix3d.h" #include "pxr/base/gf/matrix3f.h" @@ -36,15 +45,6 @@ #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include -#include -#include -#include -#include - #include #include diff --git a/pxr/base/lib/gf/wrapMatrix3f.cpp b/pxr/base/lib/gf/wrapMatrix3f.cpp index 7f48e2db42..e27fbf689c 100644 --- a/pxr/base/lib/gf/wrapMatrix3f.cpp +++ b/pxr/base/lib/gf/wrapMatrix3f.cpp @@ -25,6 +25,15 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapMatrix3.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/matrix3d.h" #include "pxr/base/gf/matrix3f.h" @@ -36,15 +45,6 @@ #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include -#include -#include -#include -#include - #include #include diff --git a/pxr/base/lib/gf/wrapMatrix4d.cpp b/pxr/base/lib/gf/wrapMatrix4d.cpp index 40cc34459f..45cec8c706 100644 --- a/pxr/base/lib/gf/wrapMatrix4d.cpp +++ b/pxr/base/lib/gf/wrapMatrix4d.cpp @@ -26,6 +26,15 @@ #define BOOST_PYTHON_MAX_ARITY 20 +#include +#include +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/matrix4f.h" @@ -38,15 +47,6 @@ #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include -#include -#include -#include -#include - #include #include diff --git a/pxr/base/lib/gf/wrapMatrix4f.cpp b/pxr/base/lib/gf/wrapMatrix4f.cpp index 1dc11eaca0..8216ad4829 100644 --- a/pxr/base/lib/gf/wrapMatrix4f.cpp +++ b/pxr/base/lib/gf/wrapMatrix4f.cpp @@ -26,6 +26,15 @@ #define BOOST_PYTHON_MAX_ARITY 20 +#include +#include +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/matrix4f.h" @@ -38,15 +47,6 @@ #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include -#include -#include -#include -#include - #include #include diff --git a/pxr/base/lib/gf/wrapMultiInterval.cpp b/pxr/base/lib/gf/wrapMultiInterval.cpp index a37fe30445..d1d1d1c074 100644 --- a/pxr/base/lib/gf/wrapMultiInterval.cpp +++ b/pxr/base/lib/gf/wrapMultiInterval.cpp @@ -21,15 +21,16 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include + #include "pxr/base/gf/multiInterval.h" #include "pxr/base/tf/iterator.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapPlane.cpp b/pxr/base/lib/gf/wrapPlane.cpp index 841abb33d8..ad0edddae8 100644 --- a/pxr/base/lib/gf/wrapPlane.cpp +++ b/pxr/base/lib/gf/wrapPlane.cpp @@ -21,6 +21,11 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include +#include + #include "pxr/base/gf/plane.h" #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/range3d.h" @@ -29,11 +34,6 @@ #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapQuat.template.cpp b/pxr/base/lib/gf/wrapQuat.template.cpp index 0ae7ec9818..286bb53a3a 100644 --- a/pxr/base/lib/gf/wrapQuat.template.cpp +++ b/pxr/base/lib/gf/wrapQuat.template.cpp @@ -25,15 +25,6 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapQuat.template.cpp file to make changes. -#include "pxr/base/gf/quat{{ SUFFIX }}.h" -{% for S in SCALARS if S != SCL and ALLOW_IMPLICIT_CONVERSION(S, SCL) %} -#include "pxr/base/gf/quat{{ S[0] }}.h" -{% endfor %} - -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/wrapTypeHelpers.h" -#include "pxr/base/tf/pyContainerConversions.h" - #include #include #include @@ -43,6 +34,15 @@ #include #include +#include "pxr/base/gf/quat{{ SUFFIX }}.h" +{% for S in SCALARS if S != SCL and ALLOW_IMPLICIT_CONVERSION(S, SCL) %} +#include "pxr/base/gf/quat{{ S[0] }}.h" +{% endfor %} + +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/wrapTypeHelpers.h" +#include "pxr/base/tf/pyContainerConversions.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapQuatd.cpp b/pxr/base/lib/gf/wrapQuatd.cpp index f98ea67109..b34db4e82f 100644 --- a/pxr/base/lib/gf/wrapQuatd.cpp +++ b/pxr/base/lib/gf/wrapQuatd.cpp @@ -25,14 +25,6 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapQuat.template.cpp file to make changes. -#include "pxr/base/gf/quatd.h" -#include "pxr/base/gf/quatf.h" -#include "pxr/base/gf/quath.h" - -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/wrapTypeHelpers.h" -#include "pxr/base/tf/pyContainerConversions.h" - #include #include #include @@ -42,6 +34,14 @@ #include #include +#include "pxr/base/gf/quatd.h" +#include "pxr/base/gf/quatf.h" +#include "pxr/base/gf/quath.h" + +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/wrapTypeHelpers.h" +#include "pxr/base/tf/pyContainerConversions.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapQuaternion.cpp b/pxr/base/lib/gf/wrapQuaternion.cpp index ed02420134..947bf630e5 100644 --- a/pxr/base/lib/gf/wrapQuaternion.cpp +++ b/pxr/base/lib/gf/wrapQuaternion.cpp @@ -21,12 +21,6 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/base/gf/quaternion.h" - -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/wrapTypeHelpers.h" -#include "pxr/base/tf/pyContainerConversions.h" - #include #include #include @@ -34,6 +28,12 @@ #include #include +#include "pxr/base/gf/quaternion.h" + +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/wrapTypeHelpers.h" +#include "pxr/base/tf/pyContainerConversions.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapQuatf.cpp b/pxr/base/lib/gf/wrapQuatf.cpp index ab9fa1e3b3..908ea7d966 100644 --- a/pxr/base/lib/gf/wrapQuatf.cpp +++ b/pxr/base/lib/gf/wrapQuatf.cpp @@ -25,13 +25,6 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapQuat.template.cpp file to make changes. -#include "pxr/base/gf/quatf.h" -#include "pxr/base/gf/quath.h" - -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/wrapTypeHelpers.h" -#include "pxr/base/tf/pyContainerConversions.h" - #include #include #include @@ -41,6 +34,13 @@ #include #include +#include "pxr/base/gf/quatf.h" +#include "pxr/base/gf/quath.h" + +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/wrapTypeHelpers.h" +#include "pxr/base/tf/pyContainerConversions.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapQuath.cpp b/pxr/base/lib/gf/wrapQuath.cpp index 4f697f925a..8000e099c2 100644 --- a/pxr/base/lib/gf/wrapQuath.cpp +++ b/pxr/base/lib/gf/wrapQuath.cpp @@ -25,12 +25,6 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapQuat.template.cpp file to make changes. -#include "pxr/base/gf/quath.h" - -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/wrapTypeHelpers.h" -#include "pxr/base/tf/pyContainerConversions.h" - #include #include #include @@ -40,6 +34,12 @@ #include #include +#include "pxr/base/gf/quath.h" + +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/wrapTypeHelpers.h" +#include "pxr/base/tf/pyContainerConversions.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRGBA.cpp b/pxr/base/lib/gf/wrapRGBA.cpp index 80bca56f99..380bf35f6b 100644 --- a/pxr/base/lib/gf/wrapRGBA.cpp +++ b/pxr/base/lib/gf/wrapRGBA.cpp @@ -23,6 +23,7 @@ // #include +#include "pxr/base/gf/api.h" #include "pxr/base/gf/rgba.h" #include "pxr/base/gf/matrix4d.h" @@ -141,9 +142,6 @@ struct RGBA_Pickle_Suite : boost::python::pickle_suite } }; -bool GfIsClose(const GfRGBA &v1, const GfRGBA &v2, double tolerance); - - void wrapRGBA() { typedef GfRGBA This; diff --git a/pxr/base/lib/gf/wrapRange.template.cpp b/pxr/base/lib/gf/wrapRange.template.cpp index 002d1d05bb..3a59d9f0cf 100644 --- a/pxr/base/lib/gf/wrapRange.template.cpp +++ b/pxr/base/lib/gf/wrapRange.template.cpp @@ -25,6 +25,11 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapRange.template.cpp file to make changes. +#include +#include +#include +#include + #include "pxr/base/gf/range{{ SUFFIX }}.h" {% for S in SCALARS if S != SCL %} #include "pxr/base/gf/range{{ DIM }}{{ S[0] }}.h" @@ -34,11 +39,6 @@ #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRange1d.cpp b/pxr/base/lib/gf/wrapRange1d.cpp index d4101134ee..5206ecd79e 100644 --- a/pxr/base/lib/gf/wrapRange1d.cpp +++ b/pxr/base/lib/gf/wrapRange1d.cpp @@ -25,6 +25,11 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapRange.template.cpp file to make changes. +#include +#include +#include +#include + #include "pxr/base/gf/range1d.h" #include "pxr/base/gf/range1f.h" @@ -32,11 +37,6 @@ #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRange1f.cpp b/pxr/base/lib/gf/wrapRange1f.cpp index fe594737e6..1d09768204 100644 --- a/pxr/base/lib/gf/wrapRange1f.cpp +++ b/pxr/base/lib/gf/wrapRange1f.cpp @@ -25,6 +25,11 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapRange.template.cpp file to make changes. +#include +#include +#include +#include + #include "pxr/base/gf/range1f.h" #include "pxr/base/gf/range1d.h" @@ -32,11 +37,6 @@ #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRange2d.cpp b/pxr/base/lib/gf/wrapRange2d.cpp index 23a4184b77..3a2164add3 100644 --- a/pxr/base/lib/gf/wrapRange2d.cpp +++ b/pxr/base/lib/gf/wrapRange2d.cpp @@ -25,6 +25,11 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapRange.template.cpp file to make changes. +#include +#include +#include +#include + #include "pxr/base/gf/range2d.h" #include "pxr/base/gf/range2f.h" @@ -32,11 +37,6 @@ #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRange2f.cpp b/pxr/base/lib/gf/wrapRange2f.cpp index 691b8d48f8..35e15097a6 100644 --- a/pxr/base/lib/gf/wrapRange2f.cpp +++ b/pxr/base/lib/gf/wrapRange2f.cpp @@ -25,6 +25,11 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapRange.template.cpp file to make changes. +#include +#include +#include +#include + #include "pxr/base/gf/range2f.h" #include "pxr/base/gf/range2d.h" @@ -32,11 +37,6 @@ #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRange3d.cpp b/pxr/base/lib/gf/wrapRange3d.cpp index 5ab4ba7cdb..370cca6915 100644 --- a/pxr/base/lib/gf/wrapRange3d.cpp +++ b/pxr/base/lib/gf/wrapRange3d.cpp @@ -25,6 +25,11 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapRange.template.cpp file to make changes. +#include +#include +#include +#include + #include "pxr/base/gf/range3d.h" #include "pxr/base/gf/range3f.h" @@ -32,11 +37,6 @@ #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRange3f.cpp b/pxr/base/lib/gf/wrapRange3f.cpp index 81387cfddf..533d86de5e 100644 --- a/pxr/base/lib/gf/wrapRange3f.cpp +++ b/pxr/base/lib/gf/wrapRange3f.cpp @@ -25,6 +25,11 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapRange.template.cpp file to make changes. +#include +#include +#include +#include + #include "pxr/base/gf/range3f.h" #include "pxr/base/gf/range3d.h" @@ -32,11 +37,6 @@ #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRay.cpp b/pxr/base/lib/gf/wrapRay.cpp index da3d87323d..31e0768bbe 100644 --- a/pxr/base/lib/gf/wrapRay.cpp +++ b/pxr/base/lib/gf/wrapRay.cpp @@ -21,6 +21,13 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/ray.h" #include "pxr/base/gf/line.h" #include "pxr/base/gf/lineSeg.h" @@ -30,13 +37,6 @@ #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRect2i.cpp b/pxr/base/lib/gf/wrapRect2i.cpp index 74be11118d..ec0e392ff8 100644 --- a/pxr/base/lib/gf/wrapRect2i.cpp +++ b/pxr/base/lib/gf/wrapRect2i.cpp @@ -21,17 +21,17 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include +#include + #include "pxr/base/gf/rect2i.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapRotation.cpp b/pxr/base/lib/gf/wrapRotation.cpp index 1c3b9e3e91..f4e86e37ec 100644 --- a/pxr/base/lib/gf/wrapRotation.cpp +++ b/pxr/base/lib/gf/wrapRotation.cpp @@ -21,17 +21,17 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include +#include + #include "pxr/base/gf/rotation.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapSize2.cpp b/pxr/base/lib/gf/wrapSize2.cpp index a19e6bd64b..88891b4dd2 100644 --- a/pxr/base/lib/gf/wrapSize2.cpp +++ b/pxr/base/lib/gf/wrapSize2.cpp @@ -21,17 +21,17 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include +#include + #include "pxr/base/gf/size2.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapSize3.cpp b/pxr/base/lib/gf/wrapSize3.cpp index 1af0a4e2ce..bdd07bd19d 100644 --- a/pxr/base/lib/gf/wrapSize3.cpp +++ b/pxr/base/lib/gf/wrapSize3.cpp @@ -21,17 +21,17 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include +#include + #include "pxr/base/gf/size3.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include -#include -#include -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapTransform.cpp b/pxr/base/lib/gf/wrapTransform.cpp index 325f16fb62..6b5d5dc3e8 100644 --- a/pxr/base/lib/gf/wrapTransform.cpp +++ b/pxr/base/lib/gf/wrapTransform.cpp @@ -21,6 +21,13 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/rotation.h" #include "pxr/base/gf/transform.h" @@ -29,13 +36,6 @@ #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/wrapTypeHelpers.h" -#include -#include -#include -#include -#include -#include - #include using std::string; diff --git a/pxr/base/lib/gf/wrapVec.template.cpp b/pxr/base/lib/gf/wrapVec.template.cpp index c1779fc950..66a47a59cd 100644 --- a/pxr/base/lib/gf/wrapVec.template.cpp +++ b/pxr/base/lib/gf/wrapVec.template.cpp @@ -25,6 +25,16 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + +#include + #include "pxr/base/gf/vec{{ SUFFIX }}.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -42,15 +52,7 @@ {% endfor %} {% endif %} -#include -#include -#include -#include -#include -#include -#include -#include #include diff --git a/pxr/base/lib/gf/wrapVec2d.cpp b/pxr/base/lib/gf/wrapVec2d.cpp index 19b5972849..9517194b6a 100644 --- a/pxr/base/lib/gf/wrapVec2d.cpp +++ b/pxr/base/lib/gf/wrapVec2d.cpp @@ -25,6 +25,14 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/vec2d.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,15 +48,7 @@ #include "pxr/base/gf/vec2h.h" #include "pxr/base/gf/vec2i.h" -#include -#include -#include -#include -#include -#include -#include - -#include + #include #include diff --git a/pxr/base/lib/gf/wrapVec2f.cpp b/pxr/base/lib/gf/wrapVec2f.cpp index 1cccc7674e..786944d560 100644 --- a/pxr/base/lib/gf/wrapVec2f.cpp +++ b/pxr/base/lib/gf/wrapVec2f.cpp @@ -25,6 +25,14 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,14 +48,6 @@ #include "pxr/base/gf/vec2h.h" #include "pxr/base/gf/vec2i.h" -#include -#include -#include -#include -#include -#include -#include - #include #include diff --git a/pxr/base/lib/gf/wrapVec2h.cpp b/pxr/base/lib/gf/wrapVec2h.cpp index e01d93217a..237b9b6fbc 100644 --- a/pxr/base/lib/gf/wrapVec2h.cpp +++ b/pxr/base/lib/gf/wrapVec2h.cpp @@ -25,6 +25,16 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + +#include + #include "pxr/base/gf/vec2h.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,16 +50,6 @@ #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/vec2i.h" -#include -#include -#include -#include -#include -#include -#include - -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec2i.cpp b/pxr/base/lib/gf/wrapVec2i.cpp index 9060398598..c0a70ec4b7 100644 --- a/pxr/base/lib/gf/wrapVec2i.cpp +++ b/pxr/base/lib/gf/wrapVec2i.cpp @@ -25,16 +25,6 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. -#include "pxr/base/gf/vec2i.h" - -#include "pxr/base/gf/pyBufferUtils.h" - -#include "pxr/base/tf/pyContainerConversions.h" -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/pyContainerConversions.h" -#include "pxr/base/tf/wrapTypeHelpers.h" - - #include #include #include @@ -45,6 +35,15 @@ #include +#include "pxr/base/gf/vec2i.h" + +#include "pxr/base/gf/pyBufferUtils.h" + +#include "pxr/base/tf/pyContainerConversions.h" +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/pyContainerConversions.h" +#include "pxr/base/tf/wrapTypeHelpers.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec3d.cpp b/pxr/base/lib/gf/wrapVec3d.cpp index 4ddeb2170e..41cd0ad57d 100644 --- a/pxr/base/lib/gf/wrapVec3d.cpp +++ b/pxr/base/lib/gf/wrapVec3d.cpp @@ -25,6 +25,16 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + +#include + #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,16 +50,6 @@ #include "pxr/base/gf/vec3h.h" #include "pxr/base/gf/vec3i.h" -#include -#include -#include -#include -#include -#include -#include - -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec3f.cpp b/pxr/base/lib/gf/wrapVec3f.cpp index 2ca5d1e875..2f47206d1c 100644 --- a/pxr/base/lib/gf/wrapVec3f.cpp +++ b/pxr/base/lib/gf/wrapVec3f.cpp @@ -25,6 +25,16 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + +#include + #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,16 +50,6 @@ #include "pxr/base/gf/vec3h.h" #include "pxr/base/gf/vec3i.h" -#include -#include -#include -#include -#include -#include -#include - -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec3h.cpp b/pxr/base/lib/gf/wrapVec3h.cpp index 1495440041..609f8984b9 100644 --- a/pxr/base/lib/gf/wrapVec3h.cpp +++ b/pxr/base/lib/gf/wrapVec3h.cpp @@ -25,6 +25,16 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + +#include + #include "pxr/base/gf/vec3h.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,16 +50,6 @@ #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/vec3i.h" -#include -#include -#include -#include -#include -#include -#include - -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec3i.cpp b/pxr/base/lib/gf/wrapVec3i.cpp index fbb2e22848..968731afb2 100644 --- a/pxr/base/lib/gf/wrapVec3i.cpp +++ b/pxr/base/lib/gf/wrapVec3i.cpp @@ -25,16 +25,6 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. -#include "pxr/base/gf/vec3i.h" - -#include "pxr/base/gf/pyBufferUtils.h" - -#include "pxr/base/tf/pyContainerConversions.h" -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/pyContainerConversions.h" -#include "pxr/base/tf/wrapTypeHelpers.h" - - #include #include #include @@ -45,6 +35,15 @@ #include +#include "pxr/base/gf/vec3i.h" + +#include "pxr/base/gf/pyBufferUtils.h" + +#include "pxr/base/tf/pyContainerConversions.h" +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/pyContainerConversions.h" +#include "pxr/base/tf/wrapTypeHelpers.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec4d.cpp b/pxr/base/lib/gf/wrapVec4d.cpp index 86a1077d81..4d8700faa8 100644 --- a/pxr/base/lib/gf/wrapVec4d.cpp +++ b/pxr/base/lib/gf/wrapVec4d.cpp @@ -25,6 +25,16 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + +#include + #include "pxr/base/gf/vec4d.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,16 +50,6 @@ #include "pxr/base/gf/vec4h.h" #include "pxr/base/gf/vec4i.h" -#include -#include -#include -#include -#include -#include -#include - -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec4f.cpp b/pxr/base/lib/gf/wrapVec4f.cpp index b9daa77f2a..5cbd17051c 100644 --- a/pxr/base/lib/gf/wrapVec4f.cpp +++ b/pxr/base/lib/gf/wrapVec4f.cpp @@ -25,6 +25,16 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + +#include + #include "pxr/base/gf/vec4f.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,16 +50,6 @@ #include "pxr/base/gf/vec4h.h" #include "pxr/base/gf/vec4i.h" -#include -#include -#include -#include -#include -#include -#include - -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec4h.cpp b/pxr/base/lib/gf/wrapVec4h.cpp index 0f0c2c8d67..7e3d6348a4 100644 --- a/pxr/base/lib/gf/wrapVec4h.cpp +++ b/pxr/base/lib/gf/wrapVec4h.cpp @@ -25,6 +25,16 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. +#include +#include +#include +#include +#include +#include +#include + +#include + #include "pxr/base/gf/vec4h.h" #include "pxr/base/gf/pyBufferUtils.h" @@ -40,16 +50,6 @@ #include "pxr/base/gf/vec4f.h" #include "pxr/base/gf/vec4i.h" -#include -#include -#include -#include -#include -#include -#include - -#include - #include using namespace boost::python; diff --git a/pxr/base/lib/gf/wrapVec4i.cpp b/pxr/base/lib/gf/wrapVec4i.cpp index 11b1db72d3..47a03111fa 100644 --- a/pxr/base/lib/gf/wrapVec4i.cpp +++ b/pxr/base/lib/gf/wrapVec4i.cpp @@ -25,16 +25,6 @@ // This file is generated by a script. Do not edit directly. Edit the // wrapVec.template.cpp file to make changes. -#include "pxr/base/gf/vec4i.h" - -#include "pxr/base/gf/pyBufferUtils.h" - -#include "pxr/base/tf/pyContainerConversions.h" -#include "pxr/base/tf/pyUtils.h" -#include "pxr/base/tf/pyContainerConversions.h" -#include "pxr/base/tf/wrapTypeHelpers.h" - - #include #include #include @@ -45,6 +35,15 @@ #include +#include "pxr/base/gf/vec4i.h" + +#include "pxr/base/gf/pyBufferUtils.h" + +#include "pxr/base/tf/pyContainerConversions.h" +#include "pxr/base/tf/pyUtils.h" +#include "pxr/base/tf/pyContainerConversions.h" +#include "pxr/base/tf/wrapTypeHelpers.h" + #include using namespace boost::python; diff --git a/pxr/base/lib/js/CMakeLists.txt b/pxr/base/lib/js/CMakeLists.txt index a1d51a51e6..d9c12f8b48 100644 --- a/pxr/base/lib/js/CMakeLists.txt +++ b/pxr/base/lib/js/CMakeLists.txt @@ -1,6 +1,10 @@ set(PXR_PREFIX pxr/base) set(PXR_PACKAGE js) +if(WIN32) + set(MODULE_ENTRYPOINT_CPP DllMain.cpp) +endif() + pxr_shared_library(js LIBRARIES tf @@ -14,87 +18,92 @@ pxr_shared_library(js api.h converter.h types.h -) -pxr_build_test(testJsIO - LIBRARIES - tf - js - CPPFILES - testenv/testJsIO.cpp -) -pxr_build_test(testJsConverter - LIBRARIES - tf - js - CPPFILES - testenv/testJsConverter.cpp -) -pxr_build_test(testJsUtils - LIBRARIES - tf - js CPPFILES - testenv/testJsUtils.cpp -) -pxr_install_test_dir( - SRC testenv/testJsIO - DEST testJsIO -) -pxr_install_test_dir( - SRC testenv/testJsIO_Errors - DEST testJsIO_Errors -) -pxr_install_test_dir( - SRC testenv/testJsConverter - DEST testJsConverter + ${MODULE_ENTRYPOINT_CPP} ) -pxr_register_test(testJsIO_PlugInfo - COMMAND - "${CMAKE_INSTALL_PREFIX}/tests/testJsIO plugInfo.json.in plugInfo.json" - TESTENV - testJsIO - DIFF_COMPARE - plugInfo.json -) -pxr_register_test(testJsIO_Values - COMMAND - "${CMAKE_INSTALL_PREFIX}/tests/testJsIO values.json.in values.json" - TESTENV - testJsIO - DIFF_COMPARE - values.json -) -pxr_register_test(testJsIO_Errors_BadCommaPlacement - COMMAND - "${CMAKE_INSTALL_PREFIX}/tests/testJsIO bad-commaPlacement.json -" - TESTENV - testJsIO_Errors - EXPECTED_RETURN_CODE - 2 - STDERR_REDIRECT - testJsIO_Errors-Run1-stderr.txt - DIFF_COMPARE - testJsIO_Errors-Run1-stderr.txt -) -pxr_register_test(testJsIO_Errors_MismatchedBraces - COMMAND - "${CMAKE_INSTALL_PREFIX}/tests/testJsIO bad-mismatchedBraces.json -" - TESTENV - testJsIO_Errors - EXPECTED_RETURN_CODE - 2 - STDERR_REDIRECT - testJsIO_Errors-Run2-stderr.txt - DIFF_COMPARE - testJsIO_Errors-Run2-stderr.txt -) -pxr_register_test(testJsConverter - COMMAND - "${CMAKE_INSTALL_PREFIX}/tests/testJsConverter" -) -pxr_register_test(testJsUtils - COMMAND - "${CMAKE_INSTALL_PREFIX}/tests/testJsUtils" -) +if(UNIX) + pxr_build_test(testJsIO + LIBRARIES + tf + js + CPPFILES + testenv/testJsIO.cpp + ) + pxr_build_test(testJsConverter + LIBRARIES + tf + js + CPPFILES + testenv/testJsConverter.cpp + ) + pxr_build_test(testJsUtils + LIBRARIES + tf + js + CPPFILES + testenv/testJsUtils.cpp + ) + pxr_install_test_dir( + SRC testenv/testJsIO + DEST testJsIO + ) + pxr_install_test_dir( + SRC testenv/testJsIO_Errors + DEST testJsIO_Errors + ) + pxr_install_test_dir( + SRC testenv/testJsConverter + DEST testJsConverter + ) + + pxr_register_test(testJsIO_PlugInfo + COMMAND + "${CMAKE_INSTALL_PREFIX}/tests/testJsIO plugInfo.json.in plugInfo.json" + TESTENV + testJsIO + DIFF_COMPARE + plugInfo.json + ) + pxr_register_test(testJsIO_Values + COMMAND + "${CMAKE_INSTALL_PREFIX}/tests/testJsIO values.json.in values.json" + TESTENV + testJsIO + DIFF_COMPARE + values.json + ) + pxr_register_test(testJsIO_Errors_BadCommaPlacement + COMMAND + "${CMAKE_INSTALL_PREFIX}/tests/testJsIO bad-commaPlacement.json -" + TESTENV + testJsIO_Errors + EXPECTED_RETURN_CODE + 2 + STDERR_REDIRECT + testJsIO_Errors-Run1-stderr.txt + DIFF_COMPARE + testJsIO_Errors-Run1-stderr.txt + ) + pxr_register_test(testJsIO_Errors_MismatchedBraces + COMMAND + "${CMAKE_INSTALL_PREFIX}/tests/testJsIO bad-mismatchedBraces.json -" + TESTENV + testJsIO_Errors + EXPECTED_RETURN_CODE + 2 + STDERR_REDIRECT + testJsIO_Errors-Run2-stderr.txt + DIFF_COMPARE + testJsIO_Errors-Run2-stderr.txt + ) + pxr_register_test(testJsConverter + COMMAND + "${CMAKE_INSTALL_PREFIX}/tests/testJsConverter" + ) + pxr_register_test(testJsUtils + COMMAND + "${CMAKE_INSTALL_PREFIX}/tests/testJsUtils" + ) +endif() \ No newline at end of file diff --git a/pxr/base/lib/js/DllMain.cpp b/pxr/base/lib/js/DllMain.cpp new file mode 100644 index 0000000000..6e6fd9e32a --- /dev/null +++ b/pxr/base/lib/js/DllMain.cpp @@ -0,0 +1,49 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#include +#include "pxr/base/arch/attributes.h" + +BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) +{ + UNREFERENCED_PARAMETER(module); + UNREFERENCED_PARAMETER(reserved); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + archRunConstructors(); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + archRunDestructors(); + break; + } + return TRUE; +} diff --git a/pxr/base/lib/js/api.h b/pxr/base/lib/js/api.h index 6e1e31b0b1..ca1c1f2aea 100644 --- a/pxr/base/lib/js/api.h +++ b/pxr/base/lib/js/api.h @@ -32,8 +32,12 @@ #else # if defined(JS_EXPORTS) # define JS_API ARCH_EXPORT +# define JS_API_TEMPLATE_CLASS(...) +# define JS_API_TEMPLATE_STRUCT(...) # else # define JS_API ARCH_IMPORT +# define JS_API_TEMPLATE_CLASS(...) extern template class JS_API __VA_ARGS__ +# define JS_API_TEMPLATE_STRUCT(...) extern template struct JS_API __VA_ARGS__ # endif # define JS_LOCAL ARCH_HIDDEN #endif diff --git a/pxr/base/lib/js/converter.h b/pxr/base/lib/js/converter.h index a45f67809e..a388e219de 100644 --- a/pxr/base/lib/js/converter.h +++ b/pxr/base/lib/js/converter.h @@ -21,18 +21,16 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// -/// \file js/converter.h - #ifndef JS_CONVERTER_H #define JS_CONVERTER_H +/// \file js/converter.h + #include "pxr/base/js/value.h" #include "pxr/base/tf/diagnostic.h" #include #include -// \struct Js_ValueToInt // Converts a \c JsValue \p value holding an \c int value to a \c ValueType // holding an \c int64_t. template @@ -93,9 +91,9 @@ class JsValueTypeConverter static ValueType _ToValueType(const JsValue& value) { switch (value.GetType()) { case JsValue::ObjectType: - return ValueType(_ObjectToMap(value.GetObject())); + return ValueType(_ObjectToMap(value.GetJsObject())); case JsValue::ArrayType: - return ValueType(_ArrayToVector(value.GetArray())); + return ValueType(_ArrayToVector(value.GetJsArray())); case JsValue::BoolType: return ValueType(value.GetBool()); case JsValue::StringType: diff --git a/pxr/base/lib/js/json.cpp b/pxr/base/lib/js/json.cpp index d6e728ec3f..02da806cd0 100644 --- a/pxr/base/lib/js/json.cpp +++ b/pxr/base/lib/js/json.cpp @@ -161,9 +161,9 @@ _JsValueToImplValue( { switch (value.GetType()) { case JsValue::ObjectType: - return _ToImplObjectValue(value.GetObject(), allocator); + return _ToImplObjectValue(value.GetJsObject(), allocator); case JsValue::ArrayType: - return _ToImplArrayValue(value.GetArray(), allocator); + return _ToImplArrayValue(value.GetJsArray(), allocator); case JsValue::BoolType: return rj::Value(value.GetBool()); case JsValue::StringType: @@ -233,7 +233,7 @@ JsParseString( nlpos = i; } } - error->column = eoff - nlpos; + error->column = static_cast(eoff - nlpos); error->reason = rj::GetParseError_En(result.Code()); } return JsValue(); diff --git a/pxr/base/lib/js/json.h b/pxr/base/lib/js/json.h index 3959f5b1da..e6a8b2ed4e 100644 --- a/pxr/base/lib/js/json.h +++ b/pxr/base/lib/js/json.h @@ -21,20 +21,22 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// -/// \file js/json.h #ifndef JS_JSON_H #define JS_JSON_H +/// \file js/json.h +/// Top-level entrypoints for reading and writing JSON. + #include "pxr/base/js/api.h" #include "pxr/base/js/value.h" #include #include /// \struct JsParseError +/// /// A struct containing information about a JSON parsing error. -struct JS_API JsParseError { +struct JsParseError { JsParseError() : line(0), column(0) { } unsigned int line; unsigned int column; @@ -43,21 +45,17 @@ struct JS_API JsParseError { /// Parse the contents of input stream \p istr and return a JsValue. On /// failure, this returns a null JsValue. -JS_API -JsValue JsParseStream(std::istream& istr, JsParseError* error = 0); +JS_API JsValue JsParseStream(std::istream& istr, JsParseError* error = 0); /// Parse the contents of the JSON string \p data and return it as a JsValue. /// On failure, this returns a null JsValue. -JS_API -JsValue JsParseString(const std::string& data, JsParseError* error = 0); +JS_API JsValue JsParseString(const std::string& data, JsParseError* error = 0); /// Convert the JsValue \p value to JSON and write the result to output stream /// \p ostr. -JS_API -void JsWriteToStream(const JsValue& value, std::ostream& ostr); +JS_API void JsWriteToStream(const JsValue& value, std::ostream& ostr); /// Convert the JsValue \p value to JSON and return it as a string. -JS_API -std::string JsWriteToString(const JsValue& value); +JS_API std::string JsWriteToString(const JsValue& value); #endif // JS_JSON_H diff --git a/pxr/base/lib/js/overview.dox b/pxr/base/lib/js/overview.dox index 3c7e8f4184..c57f40ecfc 100644 --- a/pxr/base/lib/js/overview.dox +++ b/pxr/base/lib/js/overview.dox @@ -1,6 +1,11 @@ /*! -\mainpage +\page js_page_front Js: JSON I/O +\if ( PIXAR_MFB_BUILD ) +\mainpage Js: JSON I/O \publicLib +\endif + +\section js_overview Overview Methods for parsing and writing JSON data from C++, and converting between arbitrary recursive container structures. @@ -11,6 +16,8 @@ performed, in order to allow the implementation to change without affecting clients. It also adheres to the coding standards of this repository, providing a more consistent interface for developers. +The top-level entrypoints are in \ref js/json.h + No Python bindings are provided by this library. Use the Python standard library 'json' module when working with json data in Python. diff --git a/pxr/base/lib/js/testenv/testJsConverter.cpp b/pxr/base/lib/js/testenv/testJsConverter.cpp index f5d085f7b5..653f45b235 100644 --- a/pxr/base/lib/js/testenv/testJsConverter.cpp +++ b/pxr/base/lib/js/testenv/testJsConverter.cpp @@ -102,7 +102,7 @@ _CheckArrayOf( assert(value.IsArrayOf()); const std::vector array = value.GetArrayOf(); - const JsArray& expArray = value.GetArray(); + const JsArray& expArray = value.GetJsArray(); indent << "array.size = " << array.size() << ", expArray.size = " << expArray.size() << std::endl; @@ -195,9 +195,9 @@ int main(int argc, char const *argv[]) assert(value.IsObject()); std::cout << "unwrapping envelope" << std::endl; - JsObject envelope = value.GetObject(); + JsObject envelope = value.GetJsObject(); assert(envelope["Object"].IsObject()); - JsObject object = envelope["Object"].GetObject(); + JsObject object = envelope["Object"].GetJsObject(); assert(not object.empty()); // Convert the top-level value to another container type. @@ -226,7 +226,7 @@ int main(int argc, char const *argv[]) indent << "checking array conversion" << std::endl; assert(object[p.first].IsArray()); assert(IsHolding<_AnyVector>(p.second)); - _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetArray()); + _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get()); @@ -245,7 +245,7 @@ int main(int argc, char const *argv[]) assert(object[p.first].IsArray()); assert(object[p.first].Is()); assert(IsHolding<_AnyVector>(p.second)); - _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetArray()); + _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get()); _CheckArrayOf(object[p.first]); @@ -254,7 +254,7 @@ int main(int argc, char const *argv[]) assert(object[p.first].IsArray()); assert(object[p.first].Is()); assert(IsHolding<_AnyVector>(p.second)); - _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetArray()); + _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get()); _CheckArrayOf(object[p.first]); @@ -263,7 +263,7 @@ int main(int argc, char const *argv[]) assert(object[p.first].IsArray()); assert(object[p.first].Is()); assert(IsHolding<_AnyVector>(p.second)); - _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetArray()); + _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get()); _CheckArrayOf(object[p.first]); @@ -272,7 +272,7 @@ int main(int argc, char const *argv[]) assert(object[p.first].IsArray()); assert(object[p.first].Is()); assert(IsHolding<_AnyVector>(p.second)); - _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetArray()); + _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get()); _CheckArrayOf(object[p.first]); @@ -281,7 +281,7 @@ int main(int argc, char const *argv[]) assert(object[p.first].IsArray()); assert(object[p.first].Is()); assert(IsHolding<_AnyVector>(p.second)); - _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetArray()); + _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get()); _CheckArrayOf(object[p.first]); diff --git a/pxr/base/lib/js/types.h b/pxr/base/lib/js/types.h index 1dbb6af3c1..dd591cb27f 100644 --- a/pxr/base/lib/js/types.h +++ b/pxr/base/lib/js/types.h @@ -21,12 +21,11 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// -/// \file js/types.h - #ifndef JS_TYPES_H #define JS_TYPES_H +/// \file js/types.h + #include #include #include diff --git a/pxr/base/lib/js/utils.h b/pxr/base/lib/js/utils.h index 48c7be6f59..9050cb2858 100644 --- a/pxr/base/lib/js/utils.h +++ b/pxr/base/lib/js/utils.h @@ -21,12 +21,11 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// -/// \file js/utils.h - #ifndef JS_UTILS_H #define JS_UTILS_H +/// \file js/utils.h + #include "pxr/base/js/api.h" #include "pxr/base/js/value.h" #include @@ -39,8 +38,8 @@ typedef boost::optional JsOptionalValue; /// such key exists, and the supplied default is not supplied, this method /// returns an uninitialized optional JsValue. Otherwise, the \p /// defaultValue is returned. -JS_API -JsOptionalValue JsFindValue( + +JS_API JsOptionalValue JsFindValue( const JsObject& object, const std::string& key, const JsOptionalValue& defaultValue = boost::none); diff --git a/pxr/base/lib/js/value.cpp b/pxr/base/lib/js/value.cpp index 409888c340..df03374d34 100644 --- a/pxr/base/lib/js/value.cpp +++ b/pxr/base/lib/js/value.cpp @@ -176,7 +176,7 @@ _CheckType( } const JsObject& -JsValue::GetObject() const +JsValue::GetJsObject() const { static TfStaticData _emptyObject; @@ -190,7 +190,7 @@ JsValue::GetObject() const } const JsArray& -JsValue::GetArray() const +JsValue::GetJsArray() const { static TfStaticData _emptyArray; diff --git a/pxr/base/lib/js/value.h b/pxr/base/lib/js/value.h index 6068fb7cdb..869ad6d852 100644 --- a/pxr/base/lib/js/value.h +++ b/pxr/base/lib/js/value.h @@ -21,12 +21,11 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// -/// \file js/value.h - #ifndef JS_VALUE_H #define JS_VALUE_H +/// \file js/value.h + #include "pxr/base/js/api.h" #include "pxr/base/js/types.h" #include @@ -36,12 +35,16 @@ #include #include +// Value API Version +// 1 (or undefined) - Initial version. +// 2 - Changed Get{Array,Object} to GetJs{Array,Object}. +#define JS_VALUE_API_VERSION 2 + /// \class JsValue /// /// A discriminated union type for JSON values. A JsValue may contain one of /// the following types: /// -/// \ul /// \li JsObject, a dictionary type /// \li JsArray, a vector type /// \li std::string @@ -50,9 +53,8 @@ /// \li uint64_t /// \li double /// \li null -/// \ul /// -class JS_API JsValue +class JsValue { public: /// Type held by this JSON value. @@ -67,73 +69,73 @@ class JS_API JsValue }; /// Constructs a null value. - JsValue(); + JS_API JsValue(); /// Constructs a value holding the given object. - JsValue(const JsObject& value); + JS_API JsValue(const JsObject& value); /// Constructs a value holding the given array. - JsValue(const JsArray& value); + JS_API JsValue(const JsArray& value); /// Constructs a value holding the given char array as a std::string. - explicit JsValue(const char* value); + JS_API explicit JsValue(const char* value); /// Constructs a value holding the given std::string. - explicit JsValue(const std::string& value); + JS_API explicit JsValue(const std::string& value); /// Constructs a value holding a bool. - explicit JsValue(bool value); + JS_API explicit JsValue(bool value); /// Constructs a value holding a signed integer. - explicit JsValue(int value); + JS_API explicit JsValue(int value); /// Constructs a value holding a 64-bit signed integer. - explicit JsValue(int64_t value); + JS_API explicit JsValue(int64_t value); /// Constructs a value holding a 64-bit unsigned integer. - explicit JsValue(uint64_t value); + JS_API explicit JsValue(uint64_t value); /// Constructs a value holding a double. - explicit JsValue(double value); + JS_API explicit JsValue(double value); /// Returns the object held by this value. If this value is not holding an /// object, this method raises a coding error and an empty object is /// returned. - const JsObject& GetObject() const; + JS_API const JsObject& GetJsObject() const; /// Returns the array held by this value. If this value is not holding an /// array, this method raises a coding error and an empty array is /// returned. - const JsArray& GetArray() const; + JS_API const JsArray& GetJsArray() const; /// Returns the string held by this value. If this value is not holding a /// string, this method raises a coding error and an empty string is /// returned. - const std::string& GetString() const; + JS_API const std::string& GetString() const; /// Returns the bool held by this value. If this value is not holding a /// bool, this method raises a coding error and false is returned. - bool GetBool() const; + JS_API bool GetBool() const; /// Returns the integer held by this value. If this value is not holding /// an int, this method raises a coding error and zero is returned. If the /// value is holding a 64-bit integer larger than the platform int may /// hold, the value is truncated. - int GetInt() const; + JS_API int GetInt() const; /// Returns the 64-bit integer held by this value. If this value is not /// holding a 64-bit integer, this method raises a coding error and zero /// is returned. - int64_t GetInt64() const; + JS_API int64_t GetInt64() const; /// Returns the 64-bit unsigned integer held by this value. If this value /// is not holding a 64-bit unsigned integer, this method raises a coding /// error and zero is returned. - uint64_t GetUInt64() const; + JS_API uint64_t GetUInt64() const; /// Returns the double held by this value. If this value is not holding a /// double, this method raises a coding error and zero is returned. - double GetReal() const; + JS_API double GetReal() const; /// Returns the value corresponding to the C++ type specified in the /// template parameter if it is holding such a value. Calling this @@ -163,31 +165,31 @@ class JS_API JsValue std::vector GetArrayOf() const; /// Returns the type of this value. - Type GetType() const; + JS_API Type GetType() const; /// Returns a display name for the type of this value. - std::string GetTypeName() const; + JS_API std::string GetTypeName() const; /// Returns true if this value is holding an object type. - bool IsObject() const; + JS_API bool IsObject() const; /// Returns true if this value is holding an array type. - bool IsArray() const; + JS_API bool IsArray() const; /// Returns true if this value is holding a string type. - bool IsString() const; + JS_API bool IsString() const; /// Returns true if this value is holding a boolean type. - bool IsBool() const; + JS_API bool IsBool() const; /// Returns true if this value is holding an integer type. - bool IsInt() const; + JS_API bool IsInt() const; /// Returns true if this value is holding a real type. - bool IsReal() const; + JS_API bool IsReal() const; /// Returns true if this value is holding a 64-bit unsigned integer. - bool IsUInt64() const; + JS_API bool IsUInt64() const; /// Returns true if this value is holding a type that corresponds /// to the C++ type specified as the template parameter. @@ -202,18 +204,18 @@ class JS_API JsValue bool IsArrayOf() const; /// Returns true if this value is null, false otherwise. - bool IsNull() const; + JS_API bool IsNull() const; /// Evaluates to true if this value is not null. - explicit operator bool() const; + JS_API explicit operator bool() const; /// Returns true of both values hold the same type and the underlying held /// values are equal. - bool operator==(const JsValue& other) const; + JS_API bool operator==(const JsValue& other) const; /// Returns true if values are of different type, or the underlying held /// values are not equal. - bool operator!=(const JsValue& other) const; + JS_API bool operator!=(const JsValue& other) const; private: template @@ -226,8 +228,8 @@ class JS_API JsValue return T(); } - const JsObject& _Get(JsObject*) const { return GetObject(); } - const JsArray& _Get(JsArray*) const { return GetArray(); } + const JsObject& _Get(JsObject*) const { return GetJsObject(); } + const JsArray& _Get(JsArray*) const { return GetJsArray(); } const std::string& _Get(std::string*) const { return GetString(); } bool _Get(bool*) const { return GetBool(); } int _Get(int*) const { return GetInt(); } @@ -258,7 +260,7 @@ class JS_API JsValue template inline std::vector JsValue::GetArrayOf() const { - const JsArray& array = GetArray(); + const JsArray& array = GetJsArray(); std::vector result(array.size()); std::transform(array.begin(), array.end(), result.begin(), [](const JsValue& v) { return v.Get(); }); @@ -271,7 +273,7 @@ inline bool JsValue::IsArrayOf() const if (not IsArray()) { return false; } - const JsArray& array = GetArray(); + const JsArray& array = GetJsArray(); return std::all_of(array.begin(), array.end(), [](const JsValue& v) { return v.Is(); }); } diff --git a/pxr/base/lib/plug/CMakeLists.txt b/pxr/base/lib/plug/CMakeLists.txt index 73cf286104..751172b7a0 100644 --- a/pxr/base/lib/plug/CMakeLists.txt +++ b/pxr/base/lib/plug/CMakeLists.txt @@ -1,6 +1,10 @@ set(PXR_PREFIX pxr/base) set(PXR_PACKAGE plug) +if(WIN32) + set(MODULE_ENTRYPOINT_CPP DllMain.cpp) +endif() + pxr_shared_library(plug LIBRARIES arch @@ -32,6 +36,7 @@ pxr_shared_library(plug api.h CPPFILES + ${MODULE_ENTRYPOINT_CPP} initConfig.cpp moduleDeps.cpp @@ -46,47 +51,48 @@ pxr_shared_library(plug __init__.py ) -pxr_test_scripts( - testPlug.py -) +if(UNIX) + pxr_test_scripts( + testPlug.py + ) -pxr_build_test_shared_lib(TestPlugDso1 - CREATE_FRAMEWORK - LIBRARIES - tf - CPPFILES - testenv/TestPlugDso1.cpp -) -pxr_build_test_shared_lib(TestPlugDso2 - LIBRARIES - tf - CPPFILES - testenv/TestPlugDso2.cpp -) -pxr_build_test_shared_lib(TestPlugDso3 - LIBRARIES - tf - CPPFILES - testenv/TestPlugDso3.cpp -) -pxr_build_test_shared_lib(TestPlugDsoEmpty - LIBRARIES - tf - CPPFILES - testenv/TestPlugDsoEmpty.cpp -) -pxr_build_test_shared_lib(TestPlugDsoIncomplete - LIBRARIES - tf - CPPFILES - testenv/TestPlugDsoIncomplete.cpp -) -pxr_build_test_shared_lib(TestPlugDsoUnloadable - LIBRARIES - tf - CPPFILES - testenv/TestPlugDsoUnloadable.cpp -) + pxr_build_test_shared_lib(TestPlugDso1 + CREATE_FRAMEWORK + LIBRARIES + tf + CPPFILES + testenv/TestPlugDso1.cpp + ) + pxr_build_test_shared_lib(TestPlugDso2 + LIBRARIES + tf + CPPFILES + testenv/TestPlugDso2.cpp + ) + pxr_build_test_shared_lib(TestPlugDso3 + LIBRARIES + tf + CPPFILES + testenv/TestPlugDso3.cpp + ) + pxr_build_test_shared_lib(TestPlugDsoEmpty + LIBRARIES + tf + CPPFILES + testenv/TestPlugDsoEmpty.cpp + ) + pxr_build_test_shared_lib(TestPlugDsoIncomplete + LIBRARIES + tf + CPPFILES + testenv/TestPlugDsoIncomplete.cpp + ) + pxr_build_test_shared_lib(TestPlugDsoUnloadable + LIBRARIES + tf + CPPFILES + testenv/TestPlugDsoUnloadable.cpp + ) # This library helps test behavior when a plugin is unloadable, # but clang by default will error out when building this due to # the references to undefined symbols. So we need to specify a @@ -98,51 +104,51 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") ) endif() -pxr_create_test_module(TestPlugModule1 - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModule2 - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModule3 - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleEmpty - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleLoaded - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleLoadedBadBase - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleUnloadable - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleUnloadable2 - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleDepBadBase - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleDepBadDep - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleDepBadDep2 - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleDepBadLoad - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleDepCycle - INSTALL_PREFIX PlugPlugins -) -pxr_create_test_module(TestPlugModuleIncomplete - INSTALL_PREFIX PlugPlugins -) - -pxr_register_test(testPlug - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testPlug" -) + pxr_create_test_module(TestPlugModule1 + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModule2 + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModule3 + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleEmpty + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleLoaded + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleLoadedBadBase + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleUnloadable + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleUnloadable2 + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleDepBadBase + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleDepBadDep + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleDepBadDep2 + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleDepBadLoad + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleDepCycle + INSTALL_PREFIX PlugPlugins + ) + pxr_create_test_module(TestPlugModuleIncomplete + INSTALL_PREFIX PlugPlugins + ) + pxr_register_test(testPlug + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testPlug" + ) +endif() \ No newline at end of file diff --git a/pxr/base/lib/plug/DllMain.cpp b/pxr/base/lib/plug/DllMain.cpp new file mode 100644 index 0000000000..6e6fd9e32a --- /dev/null +++ b/pxr/base/lib/plug/DllMain.cpp @@ -0,0 +1,49 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#include +#include "pxr/base/arch/attributes.h" + +BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) +{ + UNREFERENCED_PARAMETER(module); + UNREFERENCED_PARAMETER(reserved); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + archRunConstructors(); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + archRunDestructors(); + break; + } + return TRUE; +} diff --git a/pxr/base/lib/plug/info.cpp b/pxr/base/lib/plug/info.cpp index ec065b1772..40fb64bcf2 100644 --- a/pxr/base/lib/plug/info.cpp +++ b/pxr/base/lib/plug/info.cpp @@ -38,6 +38,8 @@ #include #include +#undef GetObject + namespace { typedef boost::function AddVisitedPathCallback; @@ -183,7 +185,7 @@ _ReadPlugInfoObject(const std::string& pathname, JsObject* result) pathname.c_str()); } else { - *result = plugInfo.GetObject(); + *result = plugInfo.GetJsObject(); } return true; } @@ -231,7 +233,7 @@ _ReadPlugInfo(_ReadContext* context, std::string pathname) pathname.c_str(), i->first.c_str()); } else { - const JsArray& plugins = i->second.GetArray(); + const JsArray& plugins = i->second.GetJsArray(); for (size_t j = 0, n = plugins.size(); j != n; ++j) { _AddPlugin(context, pathname, i->first, j, plugins[j]); } @@ -245,7 +247,7 @@ _ReadPlugInfo(_ReadContext* context, std::string pathname) pathname.c_str(), i->first.c_str()); } else { - const JsArray& includes = i->second.GetArray(); + const JsArray& includes = i->second.GetJsArray(); for (size_t j = 0, n = includes.size(); j != n; ++j) { if (not includes[j].IsString()) { TF_RUNTIME_ERROR("Plugin info file %s key '%s' " @@ -363,7 +365,7 @@ _ReadPlugInfoWithWildcards(_ReadContext* context, const std::string& pathname) } // Fail if pathname is not absolute. - if (pathname[0] != '/') { + if (TfIsRelativePath(pathname)) { TF_RUNTIME_ERROR("Plugin info file %s is not absolute", pathname.c_str()); return; @@ -387,6 +389,7 @@ _ReadPlugInfoWithWildcards(_ReadContext* context, const std::string& pathname) BOOST_FOREACH(const std::string& match, TfGlob(pathname, 0)) { context->taskArena.Run(boost::bind(_ReadPlugInfo, context, match)); } + return; } @@ -535,7 +538,7 @@ Plug_RegistrationMetadata::Plug_RegistrationMetadata( locationForErrorReporting.c_str()); return; } - const JsObject& topInfo = value.GetObject(); + const JsObject& topInfo = value.GetJsObject(); // Parse type. key = &_Tokens->TypeKey; @@ -658,7 +661,7 @@ Plug_RegistrationMetadata::Plug_RegistrationMetadata( goto error; } else { - plugInfo = i->second.GetObject(); + plugInfo = i->second.GetJsObject(); } } else { diff --git a/pxr/base/lib/plug/initConfig.cpp b/pxr/base/lib/plug/initConfig.cpp index 97e225fc9d..9ee2eea5ce 100644 --- a/pxr/base/lib/plug/initConfig.cpp +++ b/pxr/base/lib/plug/initConfig.cpp @@ -25,28 +25,26 @@ #include "pxr/base/tf/getenv.h" #include "pxr/base/tf/stringUtils.h" #include "pxr/base/arch/attributes.h" +#include "pxr/base/arch/fileSystem.h" #include namespace { const char* pathEnvVarName = BOOST_PP_STRINGIZE(PXR_PLUGINPATH_NAME); const char* buildLocation = BOOST_PP_STRINGIZE(PXR_BUILD_LOCATION); -const char* userLocation = BOOST_PP_STRINGIZE(PXR_USER_LOCATION); +const char* userLocation = BOOST_PP_STRINGIZE(C:\\ProgramData\\usd\\plugins); const char* installLocation = BOOST_PP_STRINGIZE(PXR_INSTALL_LOCATION); void _AppendPathList(std::vector* result, const std::string& paths) { - for (const auto& path: TfStringSplit(paths, ":")) { + for (const auto& path: TfStringSplit(paths, ARCH_PATH_SEP)) { if (not path.empty()) { result->push_back(path); } } } -ARCH_CONSTRUCTOR(102) -static -void -Plug_InitConfig() +ARCH_CONSTRUCTOR_DEFINE(102, Plug_InitConfig) { std::vector result; diff --git a/pxr/base/lib/plug/interfaceFactory.h b/pxr/base/lib/plug/interfaceFactory.h index 47ea705bd5..c7a4c439bc 100644 --- a/pxr/base/lib/plug/interfaceFactory.h +++ b/pxr/base/lib/plug/interfaceFactory.h @@ -21,11 +21,11 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// \file InterfaceFactory.h - #ifndef PLUG_INTERFACEFACTORY_H #define PLUG_INTERFACEFACTORY_H +/// \file plug/interfaceFactory.h + #include "pxr/base/tf/type.h" #include #include diff --git a/pxr/base/lib/plug/notice.h b/pxr/base/lib/plug/notice.h index f62d04a212..c854aece6f 100644 --- a/pxr/base/lib/plug/notice.h +++ b/pxr/base/lib/plug/notice.h @@ -36,19 +36,19 @@ class PlugNotice { public: /// Base class for all Plug notices. - class PLUG_API Base : public TfNotice + class Base : public TfNotice { public: - virtual ~Base(); + PLUG_API virtual ~Base(); }; /// Notice sent after new plugins have been registered with the Plug /// registry. - class PLUG_API DidRegisterPlugins : public Base + class DidRegisterPlugins : public Base { public: explicit DidRegisterPlugins(const PlugPluginPtrVector& newPlugins); - virtual ~DidRegisterPlugins(); + PLUG_API virtual ~DidRegisterPlugins(); const PlugPluginPtrVector& GetNewPlugins() const { return _plugins; } diff --git a/pxr/base/lib/plug/overview.dox b/pxr/base/lib/plug/overview.dox index 3364232c7f..c8b1af1bc7 100644 --- a/pxr/base/lib/plug/overview.dox +++ b/pxr/base/lib/plug/overview.dox @@ -1,6 +1,10 @@ /*! -\mainpage +\page plug_page_front Plug: Plugin Framework +\if ( PIXAR_MFB_BUILD ) +\mainpage Plug: Plugin Framework \publicLib +\endif + \section Overview Provides generic interface classes to implement a plug-in framework. The @@ -94,6 +98,7 @@ with the following structure: } ] } +\endcode The "Info" object has a key "Types" holding a single object providing metadata about the types that the plugin provides. The example above declares the type diff --git a/pxr/base/lib/plug/plugin.cpp b/pxr/base/lib/plug/plugin.cpp index a68c594844..d13c198515 100644 --- a/pxr/base/lib/plug/plugin.cpp +++ b/pxr/base/lib/plug/plugin.cpp @@ -25,7 +25,9 @@ #include "pxr/base/plug/debugCodes.h" #include "pxr/base/arch/attributes.h" +#include "pxr/base/arch/defines.h" #include "pxr/base/arch/fileSystem.h" +#include "pxr/base/arch/library.h" #include "pxr/base/arch/symbols.h" #include "pxr/base/arch/threads.h" #include "pxr/base/js/value.h" @@ -57,6 +59,8 @@ #include #include +#undef FindResource // Defined on Windows. + using std::pair; using std::string; using std::vector; @@ -251,7 +255,7 @@ PlugPlugin::GetDependencies() not depend->second.IsObject()) return JsObject(); - return depend->second.GetObject(); + return depend->second.GetJsObject(); } bool @@ -271,7 +275,7 @@ PlugPlugin::_Load() } } else { string dsoError; - _handle = TfDlopen(_path.c_str(), RTLD_NOW, &dsoError); + _handle = TfDlopen(_path.c_str(), ARCH_LIBRARY_NOW, &dsoError); if ( ! _handle ) { TF_CODING_ERROR("Load of '%s' for '%s' failed: %s", _path.c_str(), _name.c_str(), dsoError.c_str()); @@ -412,7 +416,7 @@ PlugPlugin::MakeResourcePath(const std::string& path) const } std::string -PlugPlugin::FindResource(const std::string& path, bool verify) const +PlugPlugin::FindPluginResource(const std::string& path, bool verify) const { std::string result = MakeResourcePath(path); if (verify and not TfPathExists(result)) { @@ -498,11 +502,11 @@ PlugPlugin::GetMetadataForType(const TfType &type) return JsObject(); } - const JsObject &typesDict = types.GetObject(); + const JsObject &typesDict = types.GetJsObject(); JsValue result; TfMapLookup(typesDict,type.GetTypeName(),&result); if (result.IsObject()) { - return result.GetObject(); + return result.GetJsObject(); } return JsObject(); } @@ -512,7 +516,7 @@ PlugPlugin::DeclaresType(const TfType& type, bool includeSubclasses) const { if (const JsValue* typesEntry = TfMapLookupPtr(_dict, "Types")) { if (typesEntry->IsObject()) { - const JsObject& typesDict = typesEntry->GetObject(); + const JsObject& typesDict = typesEntry->GetJsObject(); TF_FOR_ALL(it, typesDict) { const TfType typeFromPlugin = TfType::FindByName(it->first); const bool match = @@ -556,7 +560,7 @@ PlugPlugin::_DeclareAliases( TfType t, const JsObject & metadata ) if (i == metadata.end() or not i->second.IsObject()) return; - const JsObject& aliasDict = i->second.GetObject(); + const JsObject& aliasDict = i->second.GetJsObject(); TF_FOR_ALL(aliasIt, aliasDict) { @@ -579,12 +583,12 @@ PlugPlugin::_DeclareTypes() JsValue typesValue; TfMapLookup(_dict,"Types",&typesValue); if (typesValue.IsObject()) { - const JsObject& types = typesValue.GetObject(); + const JsObject& types = typesValue.GetJsObject(); // Declare TfTypes for all the types found in the plugin. TF_FOR_ALL(i, types) { if (i->second.IsObject()) { - _DeclareType(i->first, i->second.GetObject()); + _DeclareType(i->first, i->second.GetJsObject()); } } } @@ -697,19 +701,19 @@ PlugThisPlugin::~PlugThisPlugin() } std::string -PlugFindResource( +PlugFindPluginResource( const PlugPluginPtr& plugin, const std::string& path, bool verify) { - return plugin ? plugin->FindResource(path, verify) : std::string(); + return plugin ? plugin->FindPluginResource(path, verify) : std::string(); } std::string -PlugFindResource( +PlugFindPluginResource( const PlugThisPlugin& plugin, const std::string& path, bool verify) { - return PlugFindResource(plugin.Get(), path, verify); + return PlugFindPluginResource(plugin.Get(), path, verify); } diff --git a/pxr/base/lib/plug/plugin.h b/pxr/base/lib/plug/plugin.h index f403000b06..7d0586ec74 100644 --- a/pxr/base/lib/plug/plugin.h +++ b/pxr/base/lib/plug/plugin.h @@ -41,9 +41,9 @@ TF_DECLARE_WEAK_AND_REF_PTRS(PlugPlugin); class TfType; +/// \class PlugPlugin /// -/// \class PlugPlugin plugin.h pxr/base/plug/plugin.h -/// \brief Defines an interface to registered plugins. +/// Defines an interface to registered plugins. /// /// Plugins are registered using the interfaces in \c PlugRegistry. /// @@ -52,38 +52,37 @@ class TfType; /// the plugin and to retrieve information about the /// classes implemented by the plugin. /// - -class PLUG_API PlugPlugin : public TfRefBase, public TfWeakBase { +class PlugPlugin : public TfRefBase, public TfWeakBase { public: - virtual ~PlugPlugin(); + PLUG_API virtual ~PlugPlugin(); - /// \brief Loads the plugin. + /// Loads the plugin. /// This is a noop if the plugin is already loaded. - bool Load(); + PLUG_API bool Load(); /// Returns \c true if the plugin is currently loaded. Resource /// plugins always report as loaded. - bool IsLoaded() const; + PLUG_API bool IsLoaded() const; /// Returns \c true if the plugin is a python module. - bool IsPythonModule() const; + PLUG_API bool IsPythonModule() const; /// Returns \c true if the plugin is resource-only. - bool IsResource() const; + PLUG_API bool IsResource() const; /// Returns the dictionary containing meta-data for the plugin. - JsObject GetMetadata(); + PLUG_API JsObject GetMetadata(); /// Returns the metdata sub-dictionary for a particular type. - JsObject GetMetadataForType(const TfType &type); + PLUG_API JsObject GetMetadataForType(const TfType &type); /// Returns the dictionary containing the dependencies for the plugin. - JsObject GetDependencies(); + PLUG_API JsObject GetDependencies(); /// Returns true if \p type is declared by this plugin. /// If \p includeSubclasses is specified, also returns true if any /// subclasses of \p type have been declared. - bool DeclaresType(const TfType& type, bool includeSubclasses = false) const; + PLUG_API bool DeclaresType(const TfType& type, bool includeSubclasses = false) const; /// Returns the plugin's name. std::string const &GetName() const { @@ -102,13 +101,13 @@ class PLUG_API PlugPlugin : public TfRefBase, public TfWeakBase { /// Build a plugin resource path by returing a given absolute path or /// combining the plugin's resource path with a given relative path. - std::string MakeResourcePath(const std::string& path) const; + PLUG_API std::string MakeResourcePath(const std::string& path) const; /// Find a plugin resource by absolute or relative path optionally /// verifying that file exists. If verification fails an empty path /// is returned. Relative paths are relative to the plugin's resource /// path. - std::string FindResource(const std::string& path, bool verify = true) const; + PLUG_API std::string FindPluginResource(const std::string& path, bool verify = true) const; private: enum _Type { LibraryType, PythonType, ResourceType }; @@ -167,7 +166,7 @@ class PLUG_API PlugPlugin : public TfRefBase, public TfWeakBase { PLUG_LOCAL static void _DefineType( TfType t ); - class _SeenPlugins; + struct _SeenPlugins; PLUG_LOCAL bool _LoadWithDependents(_SeenPlugins * seenPlugins); @@ -179,7 +178,7 @@ class PLUG_API PlugPlugin : public TfRefBase, public TfWeakBase { std::string _path; std::string _resourcePath; JsObject _dict; - void *_handle; // the handle returned by dlopen() is a void* + void *_handle; // the handle returned by ArchOpenLibrary() is a void* std::atomic _isLoaded; _Type _type; @@ -187,9 +186,9 @@ class PLUG_API PlugPlugin : public TfRefBase, public TfWeakBase { friend class PlugThisPlugin; }; -/// /// \class PlugThisPlugin -/// \brief An object that refers to the plugin it's in. +/// +/// An object that refers to the plugin it's in. /// /// If you have a plugin that wants access to its own plugInfo metadata /// (especially its resources) then make a \b static instance of this @@ -198,10 +197,10 @@ class PLUG_API PlugPlugin : public TfRefBase, public TfWeakBase { /// in the plugin, or a member of any of those. It must not be allocated /// on the stack or the heap or \c Get() will return \c NULL. /// -class PLUG_API PlugThisPlugin : boost::noncopyable { +class PlugThisPlugin : boost::noncopyable { public: - PlugThisPlugin(); - ~PlugThisPlugin(); + PLUG_API PlugThisPlugin(); + PLUG_API ~PlugThisPlugin(); /// Returns the plugin or \c NULL if not found. const PlugPluginPtr& Get() const @@ -219,8 +218,8 @@ class PLUG_API PlugThisPlugin : boost::noncopyable { /// plugin's resource path. PLUG_API std::string -PlugFindResource(const PlugPluginPtr& plugin, - const std::string& path, bool verify = true); +PlugFindPluginResource(const PlugPluginPtr& plugin, + const std::string& path, bool verify = true); /// Find a plugin's resource by absolute or relative path optionally /// verifying that file exists. If \c plugin.Get() is \c NULL or @@ -228,7 +227,7 @@ PlugFindResource(const PlugPluginPtr& plugin, /// relative to the plugin's resource path. PLUG_API std::string -PlugFindResource(const PlugThisPlugin& plugin, - const std::string& path, bool verify = true); +PlugFindPluginResource(const PlugThisPlugin& plugin, + const std::string& path, bool verify = true); #endif // PLUG_PLUGIN_H diff --git a/pxr/base/lib/plug/registry.h b/pxr/base/lib/plug/registry.h index c032b2c8d3..da904ffa85 100644 --- a/pxr/base/lib/plug/registry.h +++ b/pxr/base/lib/plug/registry.h @@ -44,11 +44,11 @@ #include TF_DECLARE_WEAK_PTRS(PlugPlugin); -class Plug_RegistrationMetadata; +struct Plug_RegistrationMetadata; +/// \class PlugRegistry /// -/// \class PlugRegistry registry.h pxr/base/plug/registry.h -/// \brief Defines an interface for registering plugins. +/// Defines an interface for registering plugins. /// /// PlugRegistry maintains a registry of plug-ins known to the system /// and provides an interface for base classes to load any plug-ins required @@ -333,18 +333,21 @@ class Plug_RegistrationMetadata; /// \endcode /// -class PLUG_API PlugRegistry : public TfWeakBase, boost::noncopyable { +class PlugRegistry : public TfWeakBase, boost::noncopyable { public: typedef PlugRegistry This; typedef std::vector TypeVector; /// Returns the singleton \c PlugRegistry instance. + PLUG_API static PlugRegistry & GetInstance(); /// Registers all plug-ins discovered at \a pathToPlugInfo. + PLUG_API PlugPluginPtrVector RegisterPlugins(const std::string & pathToPlugInfo); /// Registers all plug-ins discovered in any of \a pathsToPlugInfo. + PLUG_API PlugPluginPtrVector RegisterPlugins(const std::vector & pathsToPlugInfo); @@ -353,6 +356,7 @@ class PLUG_API PlugRegistry : public TfWeakBase, boost::noncopyable { /// function if you expect that \c name may name a type provided by a /// plugin. Calling this function will incur plugin discovery (but not /// loading) if plugin discovery has not yet occurred. + PLUG_API static TfType FindTypeByName(std::string const &typeName); /// Retrieve the \c TfType that derives from \c base and has the given alias @@ -361,6 +365,7 @@ class PLUG_API PlugRegistry : public TfWeakBase, boost::noncopyable { /// you expect that the derived type may be provided by a plugin. Calling /// this function will incur plugin discovery (but not loading) if plugin /// discovery has not yet occurred. + PLUG_API static TfType FindDerivedTypeByName(TfType base, std::string const &typeName); @@ -380,6 +385,7 @@ class PLUG_API PlugRegistry : public TfWeakBase, boost::noncopyable { /// function if you expect that plugins may provide types derived from \a /// base. Otherwise, use \a TfType::GetDirectlyDerivedTypes. /// + PLUG_API static std::vector GetDirectlyDerivedTypes(TfType base); @@ -387,6 +393,7 @@ class PLUG_API PlugRegistry : public TfWeakBase, boost::noncopyable { /// \a base. Use this function if you expect that plugins may provide types /// derived from \a base. Otherwise, use \a TfType::GetAllDerivedTypes. /// + PLUG_API static void GetAllDerivedTypes(TfType base, std::set *result); @@ -402,27 +409,33 @@ class PLUG_API PlugRegistry : public TfWeakBase, boost::noncopyable { /// Returns the plug-in for the given type, or a /// null pointer if the is no registered plug-in. + PLUG_API PlugPluginPtr GetPluginForType(TfType t) const; /// Returns all registered plug-ins. + PLUG_API PlugPluginPtrVector GetAllPlugins() const; /// Returns the plugin that contains the given address if any, /// otherwise returns \c NULL. Naturally, this only works for /// shared library plugins. + PLUG_API PlugPluginPtr GetPluginWithAddress(void* address) const; /// Returns the plugin at the given filesystem path if any, /// otherwise returns \c NULL. + PLUG_API PlugPluginPtr GetPluginWithPath(const std::string& path) const; /// Looks for a string associated with \a type and \a key and returns it, or /// an empty string if \a type or \a key are not found. + PLUG_API std::string GetStringFromPluginMetaData(TfType type, const std::string &key) const; /// Looks for a JsValue associated with \a type and \a key and returns it, /// or a null JsValue if \a type or \a key are not found. + PLUG_API JsValue GetDataFromPluginMetaData(TfType type, const std::string &key) const; diff --git a/pxr/base/lib/plug/staticInterface.cpp b/pxr/base/lib/plug/staticInterface.cpp index 6d2ebda6f7..73467422a6 100644 --- a/pxr/base/lib/plug/staticInterface.cpp +++ b/pxr/base/lib/plug/staticInterface.cpp @@ -26,6 +26,7 @@ #include "pxr/base/plug/staticInterface.h" #include "pxr/base/plug/interfaceFactory.h" #include "pxr/base/plug/plugin.h" +#include "pxr/base/plug/info.h" #include "pxr/base/plug/registry.h" #include "pxr/base/tf/diagnostic.h" #include diff --git a/pxr/base/lib/plug/staticInterface.h b/pxr/base/lib/plug/staticInterface.h index 85e729152c..d0fcb40be9 100644 --- a/pxr/base/lib/plug/staticInterface.h +++ b/pxr/base/lib/plug/staticInterface.h @@ -21,18 +21,18 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// \file staticInterface.h - #ifndef PLUG_STATICINTERFACE_H #define PLUG_STATICINTERFACE_H +/// \file plug/staticInterface.h + #include "pxr/base/plug/api.h" #include #include #include // Base class for common stuff. -class PLUG_API Plug_StaticInterfaceBase { +class Plug_StaticInterfaceBase { public: /// Returns \c true if we've tried to initialize the interface pointer, /// even if we failed. This will not attempt to load the plugin or @@ -55,9 +55,9 @@ class PLUG_API Plug_StaticInterfaceBase { mutable void* _ptr; }; +/// \class PlugStaticInterface /// -/// \class PlugStaticInterface staticInterface.h pxr/base/plug/staticInterface.h -/// \brief Provides access to an interface into a plugin. +/// Provides access to an interface into a plugin. /// /// A plugin can provide one or more interface types through which clients /// can access the plugin's full functionality without needing to link diff --git a/pxr/base/lib/plug/testPlugBase.cpp b/pxr/base/lib/plug/testPlugBase.cpp index ff5af3ea2e..aacebfe930 100644 --- a/pxr/base/lib/plug/testPlugBase.cpp +++ b/pxr/base/lib/plug/testPlugBase.cpp @@ -22,7 +22,7 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/base/plug/testPlugBase.h" - +#include "pxr/base/plug/info.h" #include "pxr/base/plug/registry.h" #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/type.h" @@ -51,10 +51,10 @@ _TestPlugBase::Manufacture(const std::string & subclass) // XXX -- These shouldn't be in the library or used by the Python module, // let alone exported. -template class PLUG_API _TestPlugBase<1>; -template class PLUG_API _TestPlugBase<2>; -template class PLUG_API _TestPlugBase<3>; -template class PLUG_API _TestPlugBase<4>; +template class _TestPlugBase<1>; +template class _TestPlugBase<2>; +template class _TestPlugBase<3>; +template class _TestPlugBase<4>; // This derived class should be discovered as an available subclass // of _TestPlugBase1 even though it is compiled into the base library. diff --git a/pxr/base/lib/plug/testPlugBase.h b/pxr/base/lib/plug/testPlugBase.h index 2ae79ac08f..8deebd99d2 100644 --- a/pxr/base/lib/plug/testPlugBase.h +++ b/pxr/base/lib/plug/testPlugBase.h @@ -50,6 +50,7 @@ class _TestPlugBase : public TfRefBase, public TfWeakBase { return TfCreateRefPtr(new This()); } + PLUG_API static RefPtr Manufacture(const std::string & subclass); protected: diff --git a/pxr/base/lib/plug/wrapPlugin.cpp b/pxr/base/lib/plug/wrapPlugin.cpp index d48de51015..3bc282acd9 100644 --- a/pxr/base/lib/plug/wrapPlugin.cpp +++ b/pxr/base/lib/plug/wrapPlugin.cpp @@ -21,6 +21,8 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include + #include "pxr/base/plug/plugin.h" #include "pxr/base/js/converter.h" @@ -29,7 +31,6 @@ #include "pxr/base/tf/pyResultConversions.h" #include "pxr/base/tf/iterator.h" -#include #include using namespace boost::python; @@ -92,7 +93,7 @@ void wrapPlugin() arg("includeSubclasses") = false)) .def("MakeResourcePath", &This::MakeResourcePath) - .def("FindResource", &This::FindResource, + .def("FindPluginResource", &This::FindPluginResource, (arg("path"), arg("verify") = true)) ; @@ -103,3 +104,5 @@ void wrapPlugin() boost::python::to_python_converter, TfPySequenceToPython > >(); } + +TF_REFPTR_CONST_VOLATILE_GET(PlugPlugin) diff --git a/pxr/base/lib/plug/wrapRegistry.cpp b/pxr/base/lib/plug/wrapRegistry.cpp index cf05d363d7..e72a7da797 100644 --- a/pxr/base/lib/plug/wrapRegistry.cpp +++ b/pxr/base/lib/plug/wrapRegistry.cpp @@ -21,6 +21,10 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include + #include "pxr/base/plug/registry.h" #include "pxr/base/plug/plugin.h" @@ -30,10 +34,6 @@ #include "pxr/base/tf/pySingleton.h" #include "pxr/base/tf/stringUtils.h" -#include -#include -#include - #include #include #include @@ -263,4 +263,4 @@ void wrapRegistry() (arg("predicate"), arg("numThreads")=0, arg("verbose")=false)); def("ThisPlugin", _ThisPlugin); -} +} \ No newline at end of file diff --git a/pxr/base/lib/plug/wrapTestPlugBase.cpp b/pxr/base/lib/plug/wrapTestPlugBase.cpp index 344f485cc0..d8ed8a1720 100644 --- a/pxr/base/lib/plug/wrapTestPlugBase.cpp +++ b/pxr/base/lib/plug/wrapTestPlugBase.cpp @@ -21,14 +21,14 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include + #include "pxr/base/plug/testPlugBase.h" #include "pxr/base/tf/makePyConstructor.h" #include "pxr/base/tf/pyPtrHelpers.h" #include "pxr/base/tf/pyContainerConversions.h" -#include - using namespace boost::python; template @@ -55,3 +55,8 @@ void wrap_TestPlugBase() wrap_TestPlugBase<_TestPlugBase3>("_TestPlugBase3"); wrap_TestPlugBase<_TestPlugBase4>("_TestPlugBase4"); } + +TF_REFPTR_CONST_VOLATILE_GET(_TestPlugBase1) +TF_REFPTR_CONST_VOLATILE_GET(_TestPlugBase2) +TF_REFPTR_CONST_VOLATILE_GET(_TestPlugBase3) +TF_REFPTR_CONST_VOLATILE_GET(_TestPlugBase4) diff --git a/pxr/base/lib/tf/CMakeLists.txt b/pxr/base/lib/tf/CMakeLists.txt index 66629d9a7e..9cb403e09d 100644 --- a/pxr/base/lib/tf/CMakeLists.txt +++ b/pxr/base/lib/tf/CMakeLists.txt @@ -4,12 +4,19 @@ set(CMAKE_INCLUDE_CURRENT_DIR OFF) set(PXR_PACKAGE tf) set(PXR_PREFIX pxr/base) +if(WIN32) + set(WINLIBS Shlwapi.lib) + set(MODULE_ENTRYPOINT_CPP DllMain.cpp) +endif() + pxr_shared_library(tf LIBRARIES arch + ${WINLIBS} ${PYTHON_LIBRARIES} ${Boost_PYTHON_LIBRARY} ${Boost_IOSTREAMS_LIBRARY} + ${Boost_DATE_TIME_LIBRARY} ${DOUBLE_CONVERSION_LIBRARY} ${TBB_tbb_LIBRARY} ${TBB_tbbmalloc_LIBRARY} @@ -115,6 +122,7 @@ pxr_shared_library(tf wrapTypeHelpers PUBLIC_HEADERS + api.h cxxCast.h declarePtrs.h diagnosticLite.h @@ -140,6 +148,7 @@ pxr_shared_library(tf pyErrorInternal CPPFILES + ${MODULE_ENTRYPOINT_CPP} initConfig.cpp moduleDeps.cpp preprocessorUtils.cpp @@ -196,423 +205,425 @@ pxr_shared_library(tf testenv/testTfScriptModuleLoader_Unknown.py ) -pxr_build_test(testTfPyInterpreter - LIBRARIES - tf - CPPFILES - testenv/testTfPyInterpreter.cpp -) +if(UNIX) + pxr_build_test(testTfPyInterpreter + LIBRARIES + tf + CPPFILES + testenv/testTfPyInterpreter.cpp + ) -pxr_build_test(testTfPyLock - LIBRARIES - tf - ${Boost_PYTHON_LIBRARY} - CPPFILES - testenv/testTfPyLock.cpp -) + pxr_build_test(testTfPyLock + LIBRARIES + tf + ${Boost_PYTHON_LIBRARY} + CPPFILES + testenv/testTfPyLock.cpp + ) -pxr_build_test(testTfSIGFPE - LIBRARIES - tf - CPPFILES - testenv/SIGFPE.cpp -) + pxr_build_test(testTfSIGFPE + LIBRARIES + tf + CPPFILES + testenv/SIGFPE.cpp + ) -pxr_build_test(testTfSIGSEGV - LIBRARIES - tf - CPPFILES - testenv/SIGSEGV.cpp -) + pxr_build_test(testTfSIGSEGV + LIBRARIES + tf + CPPFILES + testenv/SIGSEGV.cpp + ) -pxr_build_test_shared_lib(TestTfDl - CPPFILES - testenv/TestTfDl.cpp -) + pxr_build_test_shared_lib(TestTfDl + CPPFILES + testenv/TestTfDl.cpp + ) -pxr_build_test_shared_lib(TestTfRegistryFunctionPlugin - LIBRARIES - tf - CPPFILES - testenv/TestTfRegistryFunctionPlugin.cpp -) + pxr_build_test_shared_lib(TestTfRegistryFunctionPlugin + LIBRARIES + tf + CPPFILES + testenv/TestTfRegistryFunctionPlugin.cpp + ) -pxr_build_test(testTfCast - LIBRARIES - tf - CPPFILES - testenv/testTfCast.cpp -) + pxr_build_test(testTfCast + LIBRARIES + tf + CPPFILES + testenv/testTfCast.cpp + ) -pxr_build_test(testTf - LIBRARIES - tf - CPPFILES - testenv/main.cpp - testenv/atomicOfstreamWrapper.cpp - testenv/bitUtils.cpp - testenv/debug.cpp - testenv/denseHashMap.cpp - testenv/diagnosticNotices.cpp - testenv/dl.cpp - testenv/enum.cpp - testenv/error.cpp - testenv/envSetting.cpp - testenv/fileUtils.cpp - testenv/getenv.cpp - testenv/hash.cpp - testenv/iterator.cpp - testenv/mallocTag.cpp - testenv/notice.cpp - testenv/pathUtils.cpp - testenv/patternMatcher.cpp - testenv/pointerAndBits.cpp - testenv/preprocessorUtils.cpp - testenv/probe.cpp - testenv/refPtr.cpp - testenv/registryManager.cpp - testenv/registryManagerUnload.cpp - testenv/scoped.cpp - testenv/scopeDescription.cpp - testenv/setenv.cpp - testenv/stacked.cpp - testenv/staticData.cpp - testenv/stl.cpp - testenv/stopwatch.cpp - testenv/stringUtils.cpp - testenv/staticTokens.cpp - testenv/templateString.cpp - testenv/timeStamp.cpp - testenv/token.cpp - testenv/type.cpp - testenv/typeMultipleInheritance.cpp - testenv/typeInfoMap.cpp - testenv/weakPtr.cpp -) + pxr_build_test(testTf + LIBRARIES + tf + CPPFILES + testenv/main.cpp + testenv/atomicOfstreamWrapper.cpp + testenv/bitUtils.cpp + testenv/debug.cpp + testenv/denseHashMap.cpp + testenv/diagnosticNotices.cpp + testenv/dl.cpp + testenv/enum.cpp + testenv/error.cpp + testenv/envSetting.cpp + testenv/fileUtils.cpp + testenv/getenv.cpp + testenv/hash.cpp + testenv/iterator.cpp + testenv/mallocTag.cpp + testenv/notice.cpp + testenv/pathUtils.cpp + testenv/patternMatcher.cpp + testenv/pointerAndBits.cpp + testenv/preprocessorUtils.cpp + testenv/probe.cpp + testenv/refPtr.cpp + testenv/registryManager.cpp + testenv/registryManagerUnload.cpp + testenv/scoped.cpp + testenv/scopeDescription.cpp + testenv/setenv.cpp + testenv/stacked.cpp + testenv/staticData.cpp + testenv/stl.cpp + testenv/stopwatch.cpp + testenv/stringUtils.cpp + testenv/staticTokens.cpp + testenv/templateString.cpp + testenv/timeStamp.cpp + testenv/token.cpp + testenv/type.cpp + testenv/typeMultipleInheritance.cpp + testenv/typeInfoMap.cpp + testenv/weakPtr.cpp + ) -pxr_test_scripts( - testenv/testTfCrashHandler.py - testenv/testTfFileUtils.py - testenv/testTfPathUtils.py - testenv/testTfPython.py - testenv/testTfPyDateTime.py - testenv/testTfPyNotice.py - testenv/testTfPyDiagnosticNotices.py - testenv/testTfPyOptional.py - testenv/testTfPyScopeDescription.py - testenv/testTfPyStaticTokens.py - testenv/testTfScriptModuleLoader.py - testenv/testTfStringUtils.py - testenv/testTfTemplateString.py - testenv/testTfType.py - testenv/testTf_PyContainerConversions.py -) + pxr_test_scripts( + testenv/testTfCrashHandler.py + testenv/testTfFileUtils.py + testenv/testTfPathUtils.py + testenv/testTfPython.py + testenv/testTfPyDateTime.py + testenv/testTfPyNotice.py + testenv/testTfPyDiagnosticNotices.py + testenv/testTfPyOptional.py + testenv/testTfPyScopeDescription.py + testenv/testTfPyStaticTokens.py + testenv/testTfScriptModuleLoader.py + testenv/testTfStringUtils.py + testenv/testTfTemplateString.py + testenv/testTfType.py + testenv/testTf_PyContainerConversions.py + ) -pxr_install_test_dir( - SRC testenv/baseline/TfDebug - DEST TfDebug/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/TfDebugTestEnv - DEST TfDebugTestEnv/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/TfDebugTestEnvList - DEST TfDebugTestEnvList/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/TfDiagnosticNotice_Fatal - DEST TfDiagnosticNotice_Fatal/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/TfDiagnosticNotices - DEST TfDiagnosticNotices/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/TfDiagnosticNotices_python - DEST TfDiagnosticNotices_Python/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/TfEnum - DEST TfEnum/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/TfEnvSetting - DEST TfEnvSetting/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/TfNotice - DEST TfNotice/baseline -) -pxr_install_test_dir( - SRC testenv/baseline/testTfScriptModuleLoader - DEST testTfScriptModuleLoader/baseline -) + pxr_install_test_dir( + SRC testenv/baseline/TfDebug + DEST TfDebug/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/TfDebugTestEnv + DEST TfDebugTestEnv/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/TfDebugTestEnvList + DEST TfDebugTestEnvList/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/TfDiagnosticNotice_Fatal + DEST TfDiagnosticNotice_Fatal/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/TfDiagnosticNotices + DEST TfDiagnosticNotices/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/TfDiagnosticNotices_python + DEST TfDiagnosticNotices_Python/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/TfEnum + DEST TfEnum/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/TfEnvSetting + DEST TfEnvSetting/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/TfNotice + DEST TfNotice/baseline + ) + pxr_install_test_dir( + SRC testenv/baseline/testTfScriptModuleLoader + DEST testTfScriptModuleLoader/baseline + ) -pxr_register_test(TfAtomicOfstreamWrapper - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfAtomicOfstreamWrapper" -) -pxr_register_test(TfBitUtils - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfBitUtils" -) -pxr_register_test(TfDl - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDl" -) -pxr_register_test(TfDebug - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebug" - STDOUT_REDIRECT debug.out - DIFF_COMPARE debug.out -) -pxr_register_test(TfDebugFatal_1 - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugFatal_1" - EXPECTED_RETURN_CODE 134 -) -pxr_register_test(TfDebugFatal_2 - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugFatal_2" - EXPECTED_RETURN_CODE 134 -) -pxr_register_test(TfDebugFatal_3 - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugFatal_3" - EXPECTED_RETURN_CODE 134 -) -pxr_register_test(TfDebugFatal_4 - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugFatal_4" - EXPECTED_RETURN_CODE 134 -) -pxr_register_test(TfDebugTestEnv - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugTestEnv" - ENV TF_DEBUG="FOO* FLAM_* FLAM -FOOFLIMFLAM TF_DISCOVERY_D*" - STDOUT_REDIRECT debugTestEnv.out - DIFF_COMPARE debugTestEnv.out -) -pxr_register_test(TfDebugTestEnvHelp - ENV TF_DEBUG=help - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugTestEnvHelp" -) -pxr_register_test(TfDebugTestEnvList - ENV TF_DEBUG=list - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugTestEnvList" - STDOUT_REDIRECT debugTestEnvList.out - DIFF_COMPARE debugTestEnvList.out -) -pxr_register_test(TfDenseHashMap - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDenseHashMap" -) -pxr_register_test(TfError - ENV TF_FATAL_VERIFY=0 - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfError" -) -pxr_register_test(TfErrorThreadTransport - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfErrorThreadTransport" -) -pxr_register_test(TfDiagnosticNotices - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDiagnosticNotices" - DIFF_COMPARE output.txt -) -pxr_register_test(TfDiagnosticNotice_Fatal - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDiagnosticNotice_Fatal" - EXPECTED_RETURN_CODE 134 - DIFF_COMPARE output_fatal.txt -) -pxr_register_test(TfDiagnosticNotices_Python - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyDiagnosticNotices" - DIFF_COMPARE pyDiagnosticNoticeOutput.txt -) -pxr_register_test(TfEnvSetting - ENV - TF_TEST_BOOL_ENV_SETTING=1 - TF_TEST_INT_ENV_SETTING=123 - TF_TEST_STRING_ENV_SETTING=alpha - TF_ENV_SETTING_ALERTS_ENABLED=0 - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfEnvSetting" - STDERR_REDIRECT debugTfEnvSettingStderr.txt - DIFF_COMPARE debugTfEnvSettingStderr.txt -) -pxr_register_test(TfFileUtils - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfFileUtils" -) -pxr_register_test(TfFileUtils_Python - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfFileUtils" -) -pxr_register_test(TfStringUtils_Python - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfStringUtils" -) -pxr_register_test(TfGetenv - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfGetenv" -) -pxr_register_test(TfHash - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfHash" -) -pxr_register_test(TfIterator - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfIterator" -) -pxr_register_test(TfMallocTag - ENV GLIBCXX_FORCE_NEW=1 - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfMallocTag" -) -pxr_register_test(TfRefPtr - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfRefPtr" -) -pxr_register_test(TfEnum - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfEnum" - STDOUT_REDIRECT enum.out - DIFF_COMPARE enum.out -) -pxr_register_test(TfNotice - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfNotice" - STDOUT_REDIRECT notice.out - DIFF_COMPARE notice.out -) -pxr_register_test(TfPathUtils - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfPathUtils" -) -pxr_register_test(TfPathUtils_Python - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPathUtils" -) -pxr_register_test(TfPatternMatcher - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfPatternMatcher" -) -pxr_register_test(TfPointerAndBits - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfPointerAndBits" -) -pxr_register_test(TfPreprocessorUtils - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfPreprocessorUtils" -) -pxr_register_test(TfProbe - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfProbe" -) -pxr_register_test(TfRegistryManager - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfRegistryManager" -) -pxr_register_test(TfRegistryManagerUnload - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfRegistryManagerUnload" -) -pxr_register_test(TfRegTest - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf" - EXPECTED_RETURN_CODE 2 -) -pxr_register_test(TfRegTest_TfScoped - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfScoped no args expected" - EXPECTED_RETURN_CODE 2 -) -pxr_register_test(TfRegTest_TfUndefinedTest - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfUndefinedTest" - EXPECTED_RETURN_CODE 3 -) -pxr_register_test(TfScopeDescription - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfScopeDescription" -) -pxr_register_test(TfScoped - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfScoped" -) -pxr_register_test(TfScopedVar - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfScopedVar" -) -pxr_register_test(TfSetenv - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfSetenv" -) -pxr_register_test(TfStacked - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStacked" -) -pxr_register_test(TfStaticData - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStaticData" -) -pxr_register_test(TfStaticTokens - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStaticTokens" -) -pxr_register_test(TfStl - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStl" -) -pxr_register_test(TfStopwatch - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStopwatch" -) -pxr_register_test(TfStringUtils - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStringUtils" -) -pxr_register_test(TfTemplateString - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfTemplateString" -) -pxr_register_test(testTfTemplateString - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfTemplateString" -) -pxr_register_test(TfTimeStamp - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfTimeStamp" -) -pxr_register_test(TfToken - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfToken" -) -pxr_register_test(TfType - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfType" -) -pxr_register_test(TfTypeInfoMap - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfTypeInfoMap" -) -pxr_register_test(TfType_MultipleInheritance - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfType_MultipleInheritance" -) -pxr_register_test(TfWeakPtr - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfWeakPtr" -) -pxr_register_test(TfWeakPtrConversion - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfWeakPtrConversion" -) -pxr_register_test(testTfPython - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPython" -) -pxr_register_test(testTfPyNotice - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyNotice" -) -pxr_register_test(testTfPyInterpreter - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyInterpreter" -) -pxr_register_test(testTfPyLock - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyLock" -) -pxr_register_test(testTfPyScopeDescription - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyScopeDescription" -) -pxr_register_test(testTfScriptModuleLoader - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfScriptModuleLoader" - STDOUT_REDIRECT scriptModuleLoader.out - DIFF_COMPARE scriptModuleLoader.out -) -pxr_register_test(testTfType - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfType" -) -pxr_register_test(testTfSIGSEGV - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfCrashHandler ${CMAKE_INSTALL_PREFIX}/tests/testTfSIGSEGV SIGSEGV" -) -pxr_register_test(testTfSIGFPE - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfCrashHandler ${CMAKE_INSTALL_PREFIX}/tests/testTfSIGFPE SIGFPE" -) -pxr_register_test(testTf_PyContainerConversions - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf_PyContainerConversions" -) -pxr_register_test(testTf_PyOptional - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyOptional" -) -pxr_register_test(testTf_PyDateTime - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyDateTime" -) -pxr_register_test(testTf_PyStaticTokens - PYTHON - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyStaticTokens" -) -pxr_register_test(testTfCxxCast - COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfCast" -) + pxr_register_test(TfAtomicOfstreamWrapper + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfAtomicOfstreamWrapper" + ) + pxr_register_test(TfBitUtils + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfBitUtils" + ) + pxr_register_test(TfDl + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDl" + ) + pxr_register_test(TfDebug + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebug" + STDOUT_REDIRECT debug.out + DIFF_COMPARE debug.out + ) + pxr_register_test(TfDebugFatal_1 + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugFatal_1" + EXPECTED_RETURN_CODE 134 + ) + pxr_register_test(TfDebugFatal_2 + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugFatal_2" + EXPECTED_RETURN_CODE 134 + ) + pxr_register_test(TfDebugFatal_3 + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugFatal_3" + EXPECTED_RETURN_CODE 134 + ) + pxr_register_test(TfDebugFatal_4 + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugFatal_4" + EXPECTED_RETURN_CODE 134 + ) + pxr_register_test(TfDebugTestEnv + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugTestEnv" + ENV TF_DEBUG="FOO* FLAM_* FLAM -FOOFLIMFLAM TF_DISCOVERY_D*" + STDOUT_REDIRECT debugTestEnv.out + DIFF_COMPARE debugTestEnv.out + ) + pxr_register_test(TfDebugTestEnvHelp + ENV TF_DEBUG=help + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugTestEnvHelp" + ) + pxr_register_test(TfDebugTestEnvList + ENV TF_DEBUG=list + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDebugTestEnvList" + STDOUT_REDIRECT debugTestEnvList.out + DIFF_COMPARE debugTestEnvList.out + ) + pxr_register_test(TfDenseHashMap + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDenseHashMap" + ) + pxr_register_test(TfError + ENV TF_FATAL_VERIFY=0 + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfError" + ) + pxr_register_test(TfErrorThreadTransport + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfErrorThreadTransport" + ) + pxr_register_test(TfDiagnosticNotices + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDiagnosticNotices" + DIFF_COMPARE output.txt + ) + pxr_register_test(TfDiagnosticNotice_Fatal + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfDiagnosticNotice_Fatal" + EXPECTED_RETURN_CODE 134 + DIFF_COMPARE output_fatal.txt + ) + pxr_register_test(TfDiagnosticNotices_Python + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyDiagnosticNotices" + DIFF_COMPARE pyDiagnosticNoticeOutput.txt + ) + pxr_register_test(TfEnvSetting + ENV + TF_TEST_BOOL_ENV_SETTING=1 + TF_TEST_INT_ENV_SETTING=123 + TF_TEST_STRING_ENV_SETTING=alpha + TF_ENV_SETTING_ALERTS_ENABLED=0 + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfEnvSetting" + STDERR_REDIRECT debugTfEnvSettingStderr.txt + DIFF_COMPARE debugTfEnvSettingStderr.txt + ) + pxr_register_test(TfFileUtils + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfFileUtils" + ) + pxr_register_test(TfFileUtils_Python + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfFileUtils" + ) + pxr_register_test(TfStringUtils_Python + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfStringUtils" + ) + pxr_register_test(TfGetenv + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfGetenv" + ) + pxr_register_test(TfHash + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfHash" + ) + pxr_register_test(TfIterator + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfIterator" + ) + pxr_register_test(TfMallocTag + ENV GLIBCXX_FORCE_NEW=1 + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfMallocTag" + ) + pxr_register_test(TfRefPtr + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfRefPtr" + ) + pxr_register_test(TfEnum + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfEnum" + STDOUT_REDIRECT enum.out + DIFF_COMPARE enum.out + ) + pxr_register_test(TfNotice + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfNotice" + STDOUT_REDIRECT notice.out + DIFF_COMPARE notice.out + ) + pxr_register_test(TfPathUtils + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfPathUtils" + ) + pxr_register_test(TfPathUtils_Python + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPathUtils" + ) + pxr_register_test(TfPatternMatcher + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfPatternMatcher" + ) + pxr_register_test(TfPointerAndBits + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfPointerAndBits" + ) + pxr_register_test(TfPreprocessorUtils + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfPreprocessorUtils" + ) + pxr_register_test(TfProbe + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfProbe" + ) + pxr_register_test(TfRegistryManager + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfRegistryManager" + ) + pxr_register_test(TfRegistryManagerUnload + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfRegistryManagerUnload" + ) + pxr_register_test(TfRegTest + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf" + EXPECTED_RETURN_CODE 2 + ) + pxr_register_test(TfRegTest_TfScoped + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfScoped no args expected" + EXPECTED_RETURN_CODE 2 + ) + pxr_register_test(TfRegTest_TfUndefinedTest + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfUndefinedTest" + EXPECTED_RETURN_CODE 3 + ) + pxr_register_test(TfScopeDescription + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfScopeDescription" + ) + pxr_register_test(TfScoped + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfScoped" + ) + pxr_register_test(TfScopedVar + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfScopedVar" + ) + pxr_register_test(TfSetenv + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfSetenv" + ) + pxr_register_test(TfStacked + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStacked" + ) + pxr_register_test(TfStaticData + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStaticData" + ) + pxr_register_test(TfStaticTokens + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStaticTokens" + ) + pxr_register_test(TfStl + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStl" + ) + pxr_register_test(TfStopwatch + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStopwatch" + ) + pxr_register_test(TfStringUtils + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfStringUtils" + ) + pxr_register_test(TfTemplateString + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfTemplateString" + ) + pxr_register_test(testTfTemplateString + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfTemplateString" + ) + pxr_register_test(TfTimeStamp + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfTimeStamp" + ) + pxr_register_test(TfToken + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfToken" + ) + pxr_register_test(TfType + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfType" + ) + pxr_register_test(TfTypeInfoMap + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfTypeInfoMap" + ) + pxr_register_test(TfType_MultipleInheritance + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfType_MultipleInheritance" + ) + pxr_register_test(TfWeakPtr + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfWeakPtr" + ) + pxr_register_test(TfWeakPtrConversion + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf TfWeakPtrConversion" + ) + pxr_register_test(testTfPython + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPython" + ) + pxr_register_test(testTfPyNotice + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyNotice" + ) + pxr_register_test(testTfPyInterpreter + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyInterpreter" + ) + pxr_register_test(testTfPyLock + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyLock" + ) + pxr_register_test(testTfPyScopeDescription + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyScopeDescription" + ) + pxr_register_test(testTfScriptModuleLoader + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfScriptModuleLoader" + STDOUT_REDIRECT scriptModuleLoader.out + DIFF_COMPARE scriptModuleLoader.out + ) + pxr_register_test(testTfType + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfType" + ) + pxr_register_test(testTfSIGSEGV + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfCrashHandler ${CMAKE_INSTALL_PREFIX}/tests/testTfSIGSEGV SIGSEGV" + ) + pxr_register_test(testTfSIGFPE + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfCrashHandler ${CMAKE_INSTALL_PREFIX}/tests/testTfSIGFPE SIGFPE" + ) + pxr_register_test(testTf_PyContainerConversions + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTf_PyContainerConversions" + ) + pxr_register_test(testTf_PyOptional + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyOptional" + ) + pxr_register_test(testTf_PyDateTime + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyDateTime" + ) + pxr_register_test(testTf_PyStaticTokens + PYTHON + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyStaticTokens" + ) + pxr_register_test(testTfCxxCast + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfCast" + ) +endif() \ No newline at end of file diff --git a/pxr/base/lib/tf/DllMain.cpp b/pxr/base/lib/tf/DllMain.cpp new file mode 100644 index 0000000000..ad1b46c5b3 --- /dev/null +++ b/pxr/base/lib/tf/DllMain.cpp @@ -0,0 +1,50 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#include +#include +#include "pxr/base/arch/attributes.h" + +BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) +{ + UNREFERENCED_PARAMETER(module); + UNREFERENCED_PARAMETER(reserved); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + archRunConstructors(); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + archRunDestructors(); + break; + } + return TRUE; +} diff --git a/pxr/base/lib/tf/anyWeakPtr.cpp b/pxr/base/lib/tf/anyWeakPtr.cpp index 55693e9686..d3ffaf9b72 100644 --- a/pxr/base/lib/tf/anyWeakPtr.cpp +++ b/pxr/base/lib/tf/anyWeakPtr.cpp @@ -23,6 +23,8 @@ // #include "pxr/base/tf/anyWeakPtr.h" +#include + using std::string; using std::type_info; diff --git a/pxr/base/lib/tf/anyWeakPtr.h b/pxr/base/lib/tf/anyWeakPtr.h index 077ea1d112..0429c8ac5a 100644 --- a/pxr/base/lib/tf/anyWeakPtr.h +++ b/pxr/base/lib/tf/anyWeakPtr.h @@ -24,11 +24,9 @@ #ifndef TF_ANYWEAKPTR_H #define TF_ANYWEAKPTR_H -/*! - * \file anyWeakPtr.h - * \brief Type independent WeakPtr holder class - * \ingroup group_tf_Memory - */ +/// \file tf/anyWeakPtr.h +/// \ingroup group_tf_Memory +/// Type independent WeakPtr holder class #include "pxr/base/tf/cxxCast.h" #include "pxr/base/tf/pyUtils.h" @@ -43,12 +41,10 @@ #include #include -/*! - * \class TfAnyWeakPtr - * - * \brief Provides the ability to hold an arbitrary TfWeakPtr in a - * non-type-specific manner in order to observe whether it has expired or not - */ +/// \class TfAnyWeakPtr +/// +/// Provides the ability to hold an arbitrary TfWeakPtr in a non-type-specific +/// manner in order to observe whether it has expired or not class TfAnyWeakPtr : boost::totally_ordered { struct _Data { @@ -58,7 +54,7 @@ class TfAnyWeakPtr : boost::totally_ordered public: typedef TfAnyWeakPtr This; - //! Construct an AnyWeakPtr watching \a ptr. + /// Construct an AnyWeakPtr watching \a ptr. template ::value>::type> @@ -68,17 +64,17 @@ class TfAnyWeakPtr : boost::totally_ordered new (&_ptrStorage) _PointerHolder(ptr); } - //! Construct an AnyWeakPtr not watching any \a ptr. + /// Construct an AnyWeakPtr not watching any \a ptr. TfAnyWeakPtr() { static_assert(sizeof(_EmptyHolder) <= sizeof(_Data), "Ptr is too big to fit in a TfAnyWeakPtr"); new (&_ptrStorage) _EmptyHolder; } - //! Construct and implicitly convert from TfNullPtr. + /// Construct and implicitly convert from TfNullPtr. TfAnyWeakPtr(TfNullPtrType) : TfAnyWeakPtr() {} - //! Construct and implicitly convert from std::nullptr_t. + /// Construct and implicitly convert from std::nullptr_t. TfAnyWeakPtr(std::nullptr_t) : TfAnyWeakPtr() {} TfAnyWeakPtr(TfAnyWeakPtr const &other) { @@ -97,35 +93,35 @@ class TfAnyWeakPtr : boost::totally_ordered _Get()->~_PointerHolderBase(); } - //! Return true *only* if this expiry checker is watching a weak pointer - // which has expired. - bool IsInvalid() const; + /// Return true *only* if this expiry checker is watching a weak pointer + /// which has expired. + TF_API bool IsInvalid() const; - //! Return the unique identifier of the WeakPtr this AnyWeakPtr conrtains - void const *GetUniqueIdentifier() const; + /// Return the unique identifier of the WeakPtr this AnyWeakPtr conrtains + TF_API void const *GetUniqueIdentifier() const; - //! Return the TfWeakBase object of the WeakPtr we are holding - TfWeakBase const *GetWeakBase() const; + /// Return the TfWeakBase object of the WeakPtr we are holding + TF_API TfWeakBase const *GetWeakBase() const; - //! bool operator - operator bool() const; + /// bool operator + TF_API operator bool() const; - //! operator ! - bool operator !() const; + /// operator ! + TF_API bool operator !() const; - //! equality operator - bool operator ==(const TfAnyWeakPtr &rhs) const; + /// equality operator + TF_API bool operator ==(const TfAnyWeakPtr &rhs) const; - //! comparison operator - bool operator <(const TfAnyWeakPtr &rhs) const; + /// comparison operator + TF_API bool operator <(const TfAnyWeakPtr &rhs) const; - //! returns the type_info of the underlying WeakPtr - const std::type_info & GetTypeInfo() const; + /// returns the type_info of the underlying WeakPtr + TF_API const std::type_info & GetTypeInfo() const; - //! Returns the TfType of the underlying WeakPtr. - TfType const& GetType() const; + /// Returns the TfType of the underlying WeakPtr. + TF_API TfType const& GetType() const; - //! Return a hash value for this instance. + /// Return a hash value for this instance. size_t GetHash() const { return reinterpret_cast(GetUniqueIdentifier()) >> 3; } @@ -142,11 +138,12 @@ class TfAnyWeakPtr : boost::totally_ordered template friend WeakPtr TfAnyWeakPtrDynamicCast(const TfAnyWeakPtr &anyWeak, WeakPtr*); + TF_API boost::python::api::object _GetPythonObject() const; // This is using the standard type-erasure pattern. struct _PointerHolderBase { - virtual ~_PointerHolderBase(); + TF_API virtual ~_PointerHolderBase(); virtual void Clone(_Data *target) const = 0; virtual bool IsInvalid() const = 0; virtual void const * GetUniqueIdentifier() const = 0; @@ -161,18 +158,18 @@ class TfAnyWeakPtr : boost::totally_ordered }; struct _EmptyHolder : _PointerHolderBase { - virtual ~_EmptyHolder(); - virtual void Clone(_Data *target) const; - virtual bool IsInvalid() const; - virtual void const * GetUniqueIdentifier() const; - virtual TfWeakBase const *GetWeakBase() const; - virtual operator bool() const; - virtual bool _IsConst() const; - virtual boost::python::api::object GetPythonObject() const; - virtual const std::type_info & GetTypeInfo() const; - virtual TfType const& GetType() const; - virtual const void* _GetMostDerivedPtr() const; - virtual bool _IsPolymorphic() const; + TF_API virtual ~_EmptyHolder(); + TF_API virtual void Clone(_Data *target) const; + TF_API virtual bool IsInvalid() const; + TF_API virtual void const * GetUniqueIdentifier() const; + TF_API virtual TfWeakBase const *GetWeakBase() const; + TF_API virtual operator bool() const; + TF_API virtual bool _IsConst() const; + TF_API virtual boost::python::api::object GetPythonObject() const; + TF_API virtual const std::type_info & GetTypeInfo() const; + TF_API virtual TfType const& GetType() const; + TF_API virtual const void* _GetMostDerivedPtr() const; + TF_API virtual bool _IsPolymorphic() const; }; template @@ -287,8 +284,4 @@ TfAnyWeakPtr::_PointerHolder::_IsConst() const return TfTraits::Type::isConst; } - - - - #endif diff --git a/pxr/base/lib/tf/api.h b/pxr/base/lib/tf/api.h new file mode 100644 index 0000000000..ffa0b2623f --- /dev/null +++ b/pxr/base/lib/tf/api.h @@ -0,0 +1,51 @@ +// +// Copyright 2016 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#ifndef TF_API_H +#define TF_API_H + +#include "pxr/base/arch/export.h" + +#if defined(TF_STATIC) +# define TF_API +# define TF_LOCAL +# define TF_PY_API +#else +# if defined(TF_EXPORTS) +# define TF_API ARCH_EXPORT +# define TF_API_TEMPLATE_CLASS(...) +# define TF_API_TEMPLATE_STRUCT(...) +# else +# define TF_API ARCH_IMPORT +# define TF_API_TEMPLATE_CLASS(...) extern template class TF_API __VA_ARGS__ +# define TF_API_TEMPLATE_STRUCT(...) extern template struct TF_API __VA_ARGS__ +# endif +# if defined(_BUILDING_PYD) +# define TF_PY_API __declspec(dllexport) +# else +# define TF_PY_API +# endif +# define TF_LOCAL TF_HIDDEN +#endif + +#endif \ No newline at end of file diff --git a/pxr/base/lib/tf/atomicOfstreamWrapper.cpp b/pxr/base/lib/tf/atomicOfstreamWrapper.cpp index ee03d49138..b021ad8312 100644 --- a/pxr/base/lib/tf/atomicOfstreamWrapper.cpp +++ b/pxr/base/lib/tf/atomicOfstreamWrapper.cpp @@ -26,6 +26,8 @@ #include "pxr/base/tf/atomicOfstreamWrapper.h" +#include "pxr/base/arch/defines.h" +#include "pxr/base/arch/errno.h" #include "pxr/base/arch/fileSystem.h" #include "pxr/base/tf/diagnostic.h" @@ -37,6 +39,12 @@ #include #include +#if defined(ARCH_OS_WINDOWS) +#include +#include +#include +#endif + using std::string; TfAtomicOfstreamWrapper::TfAtomicOfstreamWrapper( @@ -88,12 +96,17 @@ TfAtomicOfstreamWrapper::Open( } _filePath = realFilePath; - +#if defined(ARCH_OS_WINDOWS) + // XXX: This is not fully ported, also notice the non-platform agnostic "/" + // in the code below. + string dirPath = TfStringGetBeforeSuffix(realFilePath, '\\'); +#else // Check destination directory permissions. The destination directory must // exist and be writable so we can write the temporary file and rename the // temporary to the destination name. string dirPath = TfStringGetBeforeSuffix(realFilePath, '/'); - if (access(dirPath.c_str(), W_OK) != 0) { + + if (ArchFileAccess(dirPath.c_str(), W_OK) != 0) { if (reason) { *reason = TfStringPrintf( "Insufficient permissions to write to destination " @@ -107,7 +120,7 @@ TfAtomicOfstreamWrapper::Open( // into this path successfully even if we can't write to the file, but // we retain the policy that if the user couldn't open the file for // writing, they can't write to the file via this buffer object. - if (access(realFilePath.c_str(), W_OK) != 0) { + if (ArchFileAccess(realFilePath.c_str(), W_OK) != 0) { if (errno != ENOENT) { if (reason) { *reason = TfStringPrintf( @@ -119,7 +132,7 @@ TfAtomicOfstreamWrapper::Open( } } } - +#endif string tmpFilePrefix = TfStringGetBeforeSuffix(TfGetBaseName(realFilePath)); int tmpFd = ArchMakeTmpFile(dirPath, tmpFilePrefix, &_tmpFilePath); if (tmpFd == -1) { @@ -127,14 +140,14 @@ TfAtomicOfstreamWrapper::Open( *reason = TfStringPrintf( "Unable to open temporary file '%s' for writing: %s", _tmpFilePath.c_str(), - strerror(errno)); + ArchStrerror(errno).c_str()); } return false; } // Close the temp file descriptor returned by Arch, and open this buffer // with the same file name. - close(tmpFd); + ArchCloseFile(tmpFd); _stream.open(_tmpFilePath.c_str(), std::fstream::out|std::fstream::binary|std::fstream::trunc); @@ -165,6 +178,23 @@ TfAtomicOfstreamWrapper::Commit( // before calling rename. _stream.close(); +#if defined(ARCH_OS_WINDOWS) + + bool success = MoveFileEx(_tmpFilePath.c_str(), + _filePath.c_str(), + MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != FALSE; + + if (!success) { + + TF_RUNTIME_ERROR("Failed to move temporary file %s to file %s.", + _tmpFilePath.c_str(), + _filePath.c_str()); + return false; + } + + return true; + +#else // The default file mode for new files is user r/w and group r/w, subject // to the process umask. If the file already exists, renaming the // temporary file results in temporary file permissions, which doesn't @@ -178,7 +208,7 @@ TfAtomicOfstreamWrapper::Commit( if (chmod(_tmpFilePath.c_str(), fileMode) != 0) { // CODE_COVERAGE_OFF TF_WARN("Unable to set permissions for temporary file '%s': %s", - _tmpFilePath.c_str(), strerror(errno)); + _tmpFilePath.c_str(), ArchStrerror(errno).c_str()); // CODE_COVERAGE_ON } @@ -189,12 +219,13 @@ TfAtomicOfstreamWrapper::Commit( "Unable to rename '%s' to '%s': %s", _tmpFilePath.c_str(), _filePath.c_str(), - strerror(errno)); + ArchStrerror(errno).c_str()); } success = false; } return success; +#endif } bool @@ -213,13 +244,14 @@ TfAtomicOfstreamWrapper::Cancel( _stream.close(); bool success = true; - if (unlink(_tmpFilePath.c_str()) != 0) { + + if (ArchUnlinkFile(_tmpFilePath.c_str()) != 0) { if (errno != ENOENT) { if (reason) { - *reason = TfStringPrintf( - "Unable to remove temporary file '%s': %s", - _tmpFilePath.c_str(), - strerror(errno)); + *reason = TfStringPrintf( + "Unable to remove temporary file '%s': %s", + _tmpFilePath.c_str(), + ArchStrerror(errno).c_str()); } success = false; } diff --git a/pxr/base/lib/tf/atomicOfstreamWrapper.h b/pxr/base/lib/tf/atomicOfstreamWrapper.h index eecf1acebb..c2e7b58b10 100644 --- a/pxr/base/lib/tf/atomicOfstreamWrapper.h +++ b/pxr/base/lib/tf/atomicOfstreamWrapper.h @@ -21,12 +21,14 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// -/// \file Tf/AtomicOfstreamWrapper.h - #ifndef TF_ATOMIC_OSTREAM_WRAPPER_H #define TF_ATOMIC_OSTREAM_WRAPPER_H +/// \file tf/atomicOfstreamWrapper.h +/// Atomic file writer with ofstream interface. + +#include "pxr/base/tf/api.h" + #include #include #include @@ -75,10 +77,10 @@ class TfAtomicOfstreamWrapper : boost::noncopyable { public: /// Constructor. - explicit TfAtomicOfstreamWrapper(const std::string& filePath); + TF_API explicit TfAtomicOfstreamWrapper(const std::string& filePath); /// Destructor. Calls Cancel(). - ~TfAtomicOfstreamWrapper(); + TF_API ~TfAtomicOfstreamWrapper(); /// Opens the temporary file for writing. If the destination directory /// does not exist, it is created. If the destination directory exists but @@ -86,17 +88,17 @@ class TfAtomicOfstreamWrapper : boost::noncopyable /// temporary file cannot be opened for writing in the destination /// directory, this method returns false and \p reason is set to the /// reason for failure. - bool Open(std::string* reason = 0); + TF_API bool Open(std::string* reason = 0); /// Synchronizes the temporary file contents to disk, and renames the /// temporary file into the file path passed to Open. If the file path /// passed to the constructor names an existing file, the file, the file /// is atomically replaced with the temporary file. If the rename fails, /// false is returned and \p reason is set to the reason for failure. - bool Commit(std::string* reason = 0); + TF_API bool Commit(std::string* reason = 0); /// Closes the temporary file and removes it from disk, if it exists. - bool Cancel(std::string* reason = 0); + TF_API bool Cancel(std::string* reason = 0); /// Returns the stream. If this is called before a call to Open, the /// returned file stream is not yet initialized. If called after Commit or diff --git a/pxr/base/lib/tf/bitUtils.h b/pxr/base/lib/tf/bitUtils.h index 5a742a48f7..41297984f1 100644 --- a/pxr/base/lib/tf/bitUtils.h +++ b/pxr/base/lib/tf/bitUtils.h @@ -24,22 +24,19 @@ #ifndef TF_BIT_UTILS_H #define TF_BIT_UTILS_H -/*! - * \file BitUtils.h - */ +/// \file tf/bitUtils.h +/// \ingroup group_tf_BasicMath #include #include -/*! - * \hideinitializer -// \ingroup group_tf_BasicMath - * \brief Compute the number of bits required to store the given number of - * values. - * - * Note that the computed result for a number smaller or equal to zero is - * undefined. The input number can be any compile-time constant. - */ +/// Compute the number of bits required to store the given number of values. +/// +/// Note that the computed result for a number smaller or equal to zero is +/// undefined. The input number can be any compile-time constant. +/// +/// \ingroup group_tf_BasicMath +/// \hideinitializer #define TF_BITS_FOR_VALUES(n) \ Tf_NumBits::type::value @@ -63,19 +60,17 @@ struct Tf_NumBits typedef boost::mpl::integral_c type; }; -/*! - * \hideinitializer -// \ingroup group_tf_BasicMath - * \brief Compute the number of bits required to store the given number of - * (signed) enum values. - * - * Note: This is intended to be used when storing enum values in a bitfield - * without casting the enum type to an unsigned integer. (At least GCC - * consideres enums to be signed and hence wastes one bit when all enumerants - * are non-negative). - */ +/// Compute the number of bits required to store the given number of (signed) +/// enum values. +/// +/// \note This is intended to be used when storing enum values in a bitfield +/// without casting the enum type to an unsigned integer. (At least GCC +/// consideres enums to be signed and hence wastes one bit when all enumerants +/// are non-negative). +/// +/// \ingroup group_tf_BasicMath +/// \hideinitializer #define TF_BITS_FOR_ENUM_VALUES(n) \ (TF_BITS_FOR_VALUES(n) + 1) - #endif /* TF_BIT_UTILS_H */ diff --git a/pxr/base/lib/tf/callContext.h b/pxr/base/lib/tf/callContext.h index 55d33ed54c..074c29991f 100644 --- a/pxr/base/lib/tf/callContext.h +++ b/pxr/base/lib/tf/callContext.h @@ -24,22 +24,27 @@ #ifndef TF_CALL_CONTEXT_H #define TF_CALL_CONTEXT_H +/// \file tf/callContext.h +/// Functions for recording call locations. +/// +/// Many macros want to record the location in which they are invoked. In +/// fact, this is the most useful feature that function-like macros have over +/// regular functions. This code provides a standard way to collect and pass +/// that contextual information around. There are two parts. First is a +/// small structure which holds the contextual information. Next is a macro +/// which will produce a temporary structure containing the local contextual +/// information. The intended usage is in a macro. + #include "pxr/base/arch/functionLite.h" +#include "pxr/base/tf/api.h" #include -// Many macros want to record the location in which they are invoked. In fact, -// this is the most useful feature that function-like macros have over regular -// functions. This code provides a standard way to collect and pass that -// contextual information around. There are two parts. First is a small -// structure which holds the contextual information. Next is a macro which will -// produce a temporary structure containing the local contextual information. -// The intended usage is in a macro. - #if !defined(BUILD_COMPONENT_SRC_PREFIX) #error -DBUILD_COMPONENT_SRC_PREFIX was not specified. #endif +/// \hideinitializer #define TF_CALL_CONTEXT \ TfCallContext(BUILD_COMPONENT_SRC_PREFIX __FILE__, __ARCH_FUNCTION__, __LINE__, __ARCH_PRETTY_FUNCTION__) @@ -92,7 +97,7 @@ class TfCallContext mutable bool _hidden; }; -TfCallContext +TF_API TfCallContext Tf_PythonCallContext(char const *fileName, char const *moduleName, char const *functionName, diff --git a/pxr/base/lib/tf/copyOnWritePtr.h b/pxr/base/lib/tf/copyOnWritePtr.h index 064068a011..091b55cbfe 100644 --- a/pxr/base/lib/tf/copyOnWritePtr.h +++ b/pxr/base/lib/tf/copyOnWritePtr.h @@ -24,6 +24,57 @@ #ifndef TF_COPY_ON_WRITE_PTR #define TF_COPY_ON_WRITE_PTR +/// \file tf/copyOnWritePtr.h +/// Provides a simple mechanism for implementing copy-on-write internally +/// shared objects. +/// +/// A smart pointer that points to a shared data object. Const accesses +/// simply dereference like regular pointers. Non-const accesses will +/// "detach" from a shared data object if more than one client is sharing it. +/// This lets us create implicitly shared copy-on-write classes easily. Here +/// is a complete comparison example showing how to make a class implicitly +/// shared. +/// +/// \code +/// class Unshared { +/// public: +/// Unshared() {} +/// string const &GetString() const { return _str; } +/// void SetString(string str) { _str = str; } +/// private: +/// string _str; +/// }; +/// \endcode +/// +/// To make this class use implicit sharing, simply make a private helper +/// struct which stores the data members, then store a CopyOnWritePtr to this +/// struct in the class. +/// +/// \code +/// class Shared { +/// public: +/// Shared() : _data(new _Data) {} +/// string const &GetString() const { return _data->_str; } +/// void SetString(string str) { _data->_str = str; } +/// private: +/// struct _Data { string _str; }; +/// TfCopyOnWritePtr<_Data> _data; +/// }; +/// \endcode +/// +/// For larger classes this can be a performance win, as well as simplify +/// notation since objects can be passed around by value without incurring +/// massive copying hits. For instance, Qt's QPixmap class uses this +/// technique so users may pass QPixmaps around as if they are value types but +/// no copies occur until a QPixmap's content is changed. +/// +/// Copy-on-write pointers are reference counted so there is no need to +/// explicity delete the memory pointed to in the above example. +/// +/// Note that default-constructed copy-on-write pointers are null, and may be +/// checked for null, but do not need to be checked for null. Copy-on-write +/// pointers will allocate on demand if necessary. + #include "pxr/base/tf/refBase.h" #include "pxr/base/tf/refPtr.h" @@ -32,59 +83,6 @@ #include #include - - - -//! \brief Provides a simple mechanism for implementing copy-on-write -// internally shared objects. -// -// A smart pointer that points to a shared data object. Const accesses simply -// dereference like regular pointers. Non-const accesses will "detach" from a -// shared data object if more than one client is sharing it. This lets us -// create implicitly shared copy-on-write classes easily. Here is a complete -// comparison example showing how to make a class implicitly shared. -// -// \code -// class Unshared { -// public: -// Unshared() {} -// string const &GetString() const { return _str; } -// void SetString(string str) { _str = str; } -// private: -// string _str; -// }; -// \endcode -// -// To make this class use implicit sharing, simply make a private helper -// struct which stores the data members, then store a CopyOnWritePtr to -// this struct in the class. -// -// \code -// class Shared { -// public: -// Shared() : _data(new _Data) {} -// string const &GetString() const { return _data->_str; } -// void SetString(string str) { _data->_str = str; } -// private: -// struct _Data { string _str; }; -// TfCopyOnWritePtr<_Data> _data; -// }; -// \endcode -// -// For larger classes this can be a performance win, as well as simplify -// notation since objects can be passed around by value without -// incurring massive copying hits. For instance, Qt's QPixmap class -// uses this technique so users may pass QPixmaps around as if they are -// value types but no copies occur until a QPixmap's content is changed. -// -// Copy-on-write pointers are reference counted so there is no need to -// explicity delete the memory pointed to in the above example. -// -// Note that default-constructed copy-on-write pointers are null, and may be -// checked for null, but do not need to be checked for null. Copy-on-write -// pointers will allocate on demand if necessary. -// - // General case -- use shared_ptr. template struct Tf_CowSharedPtrHelper { @@ -116,7 +114,8 @@ struct Tf_CowRefPtrHelper { } }; - +/// \class TfCopyOnWritePtr +/// template class TfCopyOnWritePtr : boost::equality_comparable > { @@ -126,89 +125,89 @@ class TfCopyOnWritePtr : boost::equality_comparable > public: - //! \brief Data type + /// Data type typedef T Data; - //! \brief Pointer to data type + /// Pointer to data type typedef T *Pointer; - //! \brief Const pointer to data type + /// Const pointer to data type typedef T const *ConstPointer; - //! \brief Internally held pointer type. + /// Internally held pointer type. typedef typename _Helper::PtrType PtrType; typedef TfCopyOnWritePtr This; - //! \brief Default constructor leaves pointer NULL. + /// Default constructor leaves pointer NULL. TfCopyOnWritePtr() {} - //! \brief Construct with a copy of \a data. + /// Construct with a copy of \a data. explicit TfCopyOnWritePtr(Data const &data) : _ptr(_Helper::New(&data)) {} - //! \brief Copy construct a copy on write pointer with ptr. + /// Copy construct a copy on write pointer with ptr. explicit TfCopyOnWritePtr(PtrType const &ptr) : _ptr(ptr) {} - //! \brief Destructor + /// Destructor ~TfCopyOnWritePtr() {} operator bool() const { return static_cast(_ptr); } - //! \brief Returns true if the pointer is NULL. + /// Returns true if the pointer is NULL. bool operator !() const { return !_ptr; } - //! \brief Returns true if \a this and \a other point at the same object. + /// Returns true if \a this and \a other point at the same object. bool operator ==(const This &other) const { return _ptr == other._ptr; } - //! \brief Const get -- does not copy. + /// Const get -- does not copy. Pointer get() const { _AllocateIfNull(); return get_pointer(_ptr); } - //! \brief Non-const get -- causes a copy of not \a IsUnique(). + /// Non-const get -- causes a copy of not \a IsUnique(). Pointer get() { _Detach(); return get_pointer(_ptr); } - //! \brief Replace what's pointed to by this pointer with a copy of \a + /// Replace what's pointed to by this pointer with a copy of \a // data. void Reset(Data const &data) { _ptr = _Helper::New(&data); } - //! \brief Set this pointer to NULL. + /// Set this pointer to NULL. void Reset() { _Helper::Reset(_ptr); } - //! \brief Non-const dereference -- causes a copy if not \a IsUnique(). + /// Non-const dereference -- causes a copy if not \a IsUnique(). Data &operator *() { return *get(); } - //! \brief Const dereference -- never copies. + /// Const dereference -- never copies. const Data &operator *() const { return *get(); } - //! \brief Non-const indirection -- causes a copy if not \a IsUnique(). + /// Non-const indirection -- causes a copy if not \a IsUnique(). Pointer operator ->() { return get(); } - //! \brief Const indirection -- never copies. + /// Const indirection -- never copies. Pointer operator ->() const { return get(); } - //! \brief Returns true if this pointer is unique, that is, if this is the + /// Returns true if this pointer is unique, that is, if this is the //only pointer pointing to this data. This means that operations that would //ordinarily force a copy will not. bool IsUnique() const { @@ -232,11 +231,6 @@ class TfCopyOnWritePtr : boost::equality_comparable > } mutable PtrType _ptr; - }; - - - - #endif // TF_COPY_ON_WRITE_PTR diff --git a/pxr/base/lib/tf/cxxCast.h b/pxr/base/lib/tf/cxxCast.h index 8d695d2715..f5e4db851a 100644 --- a/pxr/base/lib/tf/cxxCast.h +++ b/pxr/base/lib/tf/cxxCast.h @@ -24,10 +24,14 @@ #ifndef TF_CXXCAST_H #define TF_CXXCAST_H +/// \file tf/cxxCast.h +/// C++ Cast Utilities. + #ifndef __cplusplus #error This include file can only be included in C++ programs. #endif +#include #include template @@ -43,20 +47,18 @@ using Tf_CopyVolatile = template using Tf_CopyCV = Tf_CopyConst>; -/*! - * \brief Return a pointer to the most-derived object. - * - * A dynamic_cast to \c void* is legal only for pointers to polymorphic - * objects. This function returns the original pointer for non-polymorphic - * types, and a pointer to the most-derived type of the object. - * Said differently, given a pointer of static type \c B*, and given that - * the object really points to an object of type \c D*, this function - * returns the address of the object considered as a \c D*; however, for - * non-polymorphic objects, the actual type of an object is taken to be \c B, - * since one cannot prove that that the type is actually different. - * - * Note: this function is public, but should be used sparingly (or not all). - */ +/// Return a pointer to the most-derived object. +/// +/// A \c dynamic_cast to \c void* is legal only for pointers to polymorphic +/// objects. This function returns the original pointer for non-polymorphic +/// types, and a pointer to the most-derived type of the object. +/// Said differently, given a pointer of static type \c B*, and given that +/// the object really points to an object of type \c D*, this function +/// returns the address of the object considered as a \c D*; however, for +/// non-polymorphic objects, the actual type of an object is taken to be \c B, +/// since one cannot prove that that the type is actually different. +/// +/// \warning This function is public, but should be used sparingly (or not all). template inline typename std::enable_if< std::is_polymorphic::value, Tf_CopyCV*>::type diff --git a/pxr/base/lib/tf/debug.cpp b/pxr/base/lib/tf/debug.cpp index 073b3c6110..99757d53e5 100644 --- a/pxr/base/lib/tf/debug.cpp +++ b/pxr/base/lib/tf/debug.cpp @@ -44,6 +44,7 @@ #include #include #include +#include using boost::function; using boost::bind; @@ -512,7 +513,7 @@ TfDebug::TimedScopeHelper::~TimedScopeHelper() } } -template class TfDebug::TimedScopeHelper; +template struct TfDebug::TimedScopeHelper; /* * Scan the environment variable TF_DEBUG for debug symbols. diff --git a/pxr/base/lib/tf/debug.h b/pxr/base/lib/tf/debug.h index 5c50fad273..d9749bc11e 100644 --- a/pxr/base/lib/tf/debug.h +++ b/pxr/base/lib/tf/debug.h @@ -24,12 +24,11 @@ #ifndef TF_DEBUG_H #define TF_DEBUG_H -/*! - * \file debug.h - * \brief Conditional debugging output class and macros. - * \ingroup group_tf_DebuggingOutput - */ +/// \file tf/debug.h +/// \ingroup group_tf_DebuggingOutput +/// Conditional debugging output class and macros. +#include "pxr/base/tf/api.h" #include "pxr/base/tf/tf.h" #include "pxr/base/tf/enum.h" #include "pxr/base/tf/preprocessorUtilsLite.h" @@ -45,221 +44,196 @@ class Tf_DebugSymbolRegistry; -/*! - * \class TfDebug Debug.h "pxr/base/tf/debug.h" - * \ingroup group_tf_DebuggingOutput - * \brief Enum-based debugging messages. - * - * The \c TfDebug class encapsulates a simple enum-based conditional - * debugging message system. It is meant as a tool for developers, - * and \e NOT as a means of issuing diagnostic messages to end-users. - * (This is not strictly true. The TfDebug class is extremely useful - * and has many properties that make its use attractive for issuing - * messages to end-users. However, for this purpose, please use the - * TF_INFO macro which more clearly indicates its intent.) - * - * The features of \c TfDebug are: - * \li Debugging messages/calls for an entire enum group can be - * compiled out-of-existence. - * \li The cost of checking if a specific message should be printed - * at runtime (assuming the enum group of the message has not been - * compile-time disabled) is a single inline array lookup, - * with a compile-time index into a global array. - * \li Parent/child relationships can be defined so that groups of messages - * can be hierarchically enabled or disabled. - * - * The use of the facility is simple: - * - * \code - * // header file - * #include "pxr/base/tf/debug.h" - * TF_DEBUG_CODES(MY_E1, MY_E2, MY_E3); - * - * // source file - * TF_DEBUG(MY_E2).Msg("something about e2\n"); - * - * TF_DEBUG(MY_E3).Msg("val = %d\n", value); - * - * \endcode - * - * The code in the header file declares the debug symbols to use. Under - * the hood, this creates an enum with the values given in the argument to - * TF_DEBUG_CODES, along with a first and last sentinel values and passes - * that to TF_DEBUG_RANGE. If you'd like to be more explicit (e.g., because - * you need the enum type name, or need to be able to turn off the facility - * at compile time), you could use the following, equivalent, form: - * - * \code - * // header file - * #include "pxr/base/tf/debug.h" - * enum MyDebugCodes { MY_FIRST, MY_E1, MY_E2, MY_E3, MY_LAST }; - * TF_DEBUG_RANGE(MyDebugCodes, MY_FIRST, MY_LAST, true); - * - * // source file - * TF_DEBUG(MY_E2).Msg("something about e2\n"); - * - * TF_DEBUG(MY_E3).Msg("val = %d\n", value); - * - * \endcode - * - * - * In the source file, the indicated debugging messages are printed - * only if the debugging symbols are enabled. Effectively, the construct - * \code - * TF_DEBUG(MY_E1).Msg(msgExpr) - * \endcode - * is translated to - * \code - * if (symbol-MY_E1-is-enabled) - * output(msgExpr) - * \endcode - * - * The implications are that \c msgExpr is only evaluated if symbol \c MY_E1 - * symbol is enabled. Further, if the last argument (which must be - * a compile-time constant) to the \c TF_DEBUG_RANGE() macro is \c false, - * then the test is known to fail at compile time; in this case, the - * compiler will even eliminate outputting the code to execute \c msgExpr. - * This scheme allows the costs of debugging code to be controlled at a - * fine level of detail. - * - * Most commonly debug symbols are inactive by default, but can be turned - * on either by an environment variable \c TF_DEBUG, or interactively once - * a program has started by a script interpreter. Both of these are - * accomplished as follows: - * - * \code - * // source file xyz/debugCodes.cpp - * - * #include "proj/my/debugCodes.h" - * #include "pxr/base/tf/debug.h" - * #include "pxr/base/tf/registryManager.h" - * - * TF_REGISTRY_FUNCTION(TfDebug, MyDebugCodes) { - * TF_DEBUG_ENVIRONMENT_SYMBOL(MY_E1, "loading of blah-blah files"); - * TF_DEBUG_ENVIRONMENT_SYMBOL(MY_E2, "parsing of mdl code"); - * // etc. - * } - * \endcode - * - * Once this is done - * Symbols are enabled as follows: - * \code - * TfDebug::DisableAll(); // disable everything - * - * TfDebug::Enable(MY_E1); // enable just MY_E1 - * - * \endcode - */ - +/// \addtogroup group_tf_DebuggingOutput +///@{ + +/// \class TfDebug +/// +/// Enum-based debugging messages. +/// +/// The \c TfDebug class encapsulates a simple enum-based conditional +/// debugging message system. It is meant as a tool for developers, and +/// \e NOT as a means of issuing diagnostic messages to end-users. (This is +/// not strictly true. The TfDebug class is extremely useful and has many +/// properties that make its use attractive for issuing messages to end-users. +/// However, for this purpose, please use the \c TF_INFO macro which more +/// clearly indicates its intent.) +/// +/// The features of \c TfDebug are: +/// \li Debugging messages/calls for an entire enum group can be +/// compiled out-of-existence. +/// \li The cost of checking if a specific message should be printed +/// at runtime (assuming the enum group of the message has not been +/// compile-time disabled) is a single inline array lookup, +/// with a compile-time index into a global array. +/// \li Parent/child relationships can be defined so that groups of messages +/// can be hierarchically enabled or disabled. +/// +/// The use of the facility is simple: +/// \code +/// // header file +/// #include "pxr/base/tf/debug.h" +/// TF_DEBUG_CODES(MY_E1, MY_E2, MY_E3); +/// +/// // source file +/// TF_DEBUG(MY_E2).Msg("something about e2\n"); +/// +/// TF_DEBUG(MY_E3).Msg("val = %d\n", value); +/// \endcode +/// +/// The code in the header file declares the debug symbols to use. Under +/// the hood, this creates an enum with the values given in the argument to +/// TF_DEBUG_CODES, along with a first and last sentinel values and passes +/// that to TF_DEBUG_RANGE. If you'd like to be more explicit (e.g., because +/// you need the enum type name, or need to be able to turn off the facility +/// at compile time), you could use the following, equivalent, form: +/// +/// \code +/// // header file +/// #include "pxr/base/tf/debug.h" +/// enum MyDebugCodes { MY_FIRST, MY_E1, MY_E2, MY_E3, MY_LAST }; +/// TF_DEBUG_RANGE(MyDebugCodes, MY_FIRST, MY_LAST, true); +/// +/// // source file +/// TF_DEBUG(MY_E2).Msg("something about e2\n"); +/// +/// TF_DEBUG(MY_E3).Msg("val = %d\n", value); +/// \endcode +/// +/// In the source file, the indicated debugging messages are printed +/// only if the debugging symbols are enabled. Effectively, the construct +/// \code +/// TF_DEBUG(MY_E1).Msg(msgExpr) +/// \endcode +/// is translated to +/// \code +/// if (symbol-MY_E1-is-enabled) +/// output(msgExpr) +/// \endcode +/// +/// The implications are that \c msgExpr is only evaluated if symbol \c MY_E1 +/// symbol is enabled. Further, if the last argument (which must be +/// a compile-time constant) to the \c TF_DEBUG_RANGE() macro is \c false, +/// then the test is known to fail at compile time; in this case, the +/// compiler will even eliminate outputting the code to execute \c msgExpr. +/// This scheme allows the costs of debugging code to be controlled at a +/// fine level of detail. +/// +/// Most commonly debug symbols are inactive by default, but can be turned +/// on either by an environment variable \c TF_DEBUG, or interactively once +/// a program has started by a script interpreter. Both of these are +/// accomplished as follows: +/// \code +/// // source file xyz/debugCodes.cpp +/// +/// #include "proj/my/debugCodes.h" +/// #include "pxr/base/tf/debug.h" +/// #include "pxr/base/tf/registryManager.h" +/// +/// TF_REGISTRY_FUNCTION(TfDebug, MyDebugCodes) { +/// TF_DEBUG_ENVIRONMENT_SYMBOL(MY_E1, "loading of blah-blah files"); +/// TF_DEBUG_ENVIRONMENT_SYMBOL(MY_E2, "parsing of mdl code"); +/// // etc. +/// } +/// \endcode +/// +/// Once this is done, symbols are enabled as follows: +/// \code +/// TfDebug::DisableAll(); // disable everything +/// +/// TfDebug::Enable(MY_E1); // enable just MY_E1 +/// \endcode +/// class TfDebug { public: - /*! - * \brief Mark debugging as enabled for enum value \c val, and any - * descendents of \c val as defined by \c DefineParentChild(). - * - * The default state for all debugging symbols is disabled. - * Note that the template parameter is deduced from \c val: - * \code - * TfDebug::Enable(MY_E3); - * \endcode - */ - + /// Mark debugging as enabled for enum value \c val, and any descendents + /// of \c val as defined by \c DefineParentChild(). + /// + /// The default state for all debugging symbols is disabled. Note that the + /// template parameter is deduced from \c val: + /// \code + /// TfDebug::Enable(MY_E3); + /// \endcode template static void Enable(T val) { _SetNodes(&_GetNode(val), 1, true); } - /*! - * \brief Mark debugging as disabled for enum value \c val, and any - * descendents of \c val as defined by \c DefineParentChild(). - */ + /// Mark debugging as disabled for enum value \c val, and any descendents + /// of \c val as defined by \c DefineParentChild(). template static void Disable(T val) { _SetNodes(&_GetNode(val), 1, false); } - /*! - * \brief Mark debugging as enabled for all enum values of type \c T. - * - * Note that the template parameter must be explicitly supplied: - * \code - * TfDebug::EnableAll() - * \endcode - */ - + /// Mark debugging as enabled for all enum values of type \c T. + /// + /// Note that the template parameter must be explicitly supplied: + /// \code + /// TfDebug::EnableAll() + /// \endcode template static void EnableAll() { _SetNodes(&_Data::nodes[0], _Traits::n, true); } - //! Mark debugging as disabled for all enum values of type \c T. + /// Mark debugging as disabled for all enum values of type \c T. template static void DisableAll() { _SetNodes(&_Data::nodes[0], _Traits::n, false); } - /*! - * \brief Define a parent/child relationship. - * - * Enum value \c child is marked as a child of \c parent; this means - * that enabling or disabling \c parent enable or disables not only - * parent, but, recursively, all descendents of \c parent as well. - * - * To avoid cycles, \c child cannot have been made a parent at the time - * of this call. - */ + /// Define a parent/child relationship. + /// + /// Enum value \c child is marked as a child of \c parent; this means that + /// enabling or disabling \c parent enable or disables not only parent, + /// but, recursively, all descendents of \c parent as well. + /// + /// To avoid cycles, \c child cannot have been made a parent at the time + /// of this call. template static void DefineParentChild(T1 parent, T2 child) { _SetParentChild(&_GetNode(parent), &_GetNode(child)); } - /*! - * \brief True if debugging is enabled for the enum value \c val. - * - * Note that not only must the specific enum value \c val be - * marked as enabled, but the enum type \c T must be globally enabled; - * this is controlled by the last argument to the \c TF_DEBUG_RANGE() - * must have been \c true. - */ - + /// True if debugging is enabled for the enum value \c val. + /// + /// Note that not only must the specific enum value \c val be marked as + /// enabled, but the enum type \c T must be globally enabled; this is + /// controlled by the last argument to the \c TF_DEBUG_RANGE() must have + /// been \c true. template static bool IsEnabled(T val) { return _Traits::compileTimeEnabled && _GetNode(val).enabled; } - /*! - * \brief True if debugging can be activated at run-time, whether - * or not it is currently enabled. - */ + /// True if debugging can be activated at run-time, whether or not it is + /// currently enabled. template static bool IsCompileTimeEnabled() { return _Traits::compileTimeEnabled; } - /*! - * \brief Return the number of debugging symbols of this type. - * - * Returns the number of different enums in the range specified - * by \c TF_DEBUG_RANGE(). - */ + /// Return the number of debugging symbols of this type. + /// + /// Returns the number of different enums in the range specified by \c + /// TF_DEBUG_RANGE(). template static size_t GetDebugRangeCount() { return _Traits::n; } - /*! - * \brief Return the index-th debug symbol of this type. - * - * If \p index-th is out of range (i.e. greater than or equal - * to \c GetDebugRangeCount()) the last symbol is returned. - * - * The above two functions can be used to print out the names - * of all debug symbols, if they have been registered via \c TF_ADD_ENUM_NAME(): - * \code - * for (size_t i = 0; i < TfDebug::GetDebugRangeCount(); i++) - * cout << TfEnum::GetName(TfDebug::GetDebugSymbol(i)) << "\n"; - * \endcode - */ + /// Return the index-th debug symbol of this type. + /// + /// If \p index-th is out of range (i.e. greater than or equal to + /// \c GetDebugRangeCount()) the last symbol is returned. + /// + /// The above two functions can be used to print out the names of all + /// debug symbols, if they have been registered via \c TF_ADD_ENUM_NAME(): + /// \code + /// for (size_t i = 0; i < TfDebug::GetDebugRangeCount(); i++) + /// cout << TfEnum::GetName(TfDebug::GetDebugSymbol(i)) << "\n"; + /// \endcode template static T GetDebugSymbol(size_t index) { if (index >= _Traits::n) @@ -270,8 +244,8 @@ class TfDebug { #if !defined(doxygen) struct Helper { - static void Msg(const std::string& msg); - static void Msg(const char* msg, ...) ARCH_PRINTF_FUNCTION(1,2); + static TF_API void Msg(const std::string& msg); + static TF_API void Msg(const char* msg, ...) ARCH_PRINTF_FUNCTION(1,2); }; #endif @@ -306,60 +280,52 @@ class TfDebug { TfStopwatch stopwatch; }; - /*! - * \brief Set registered debug symbols matching \p pattern to \p value. - * - * All registered debug symbols matching \p pattern are set to \p value. - * The only matching is an exact match with \p pattern, or if \p pattern ends - * with an '*' as is otherwise a prefix of a debug symbols. The names of all - * debug symbols set by this call are returned as a vector. - */ - static std::vector SetDebugSymbolsByName(const std::string& pattern, - bool value); - - /*! - * \brief True if the specified debug symbol is set. - */ + /// Set registered debug symbols matching \p pattern to \p value. + /// + /// All registered debug symbols matching \p pattern are set to \p value. + /// The only matching is an exact match with \p pattern, or if \p pattern + /// ends with an '*' as is otherwise a prefix of a debug symbols. The + /// names of all debug symbols set by this call are returned as a vector. + TF_API + static std::vector SetDebugSymbolsByName( + const std::string& pattern, bool value); + + /// True if the specified debug symbol is set. + TF_API static bool IsDebugSymbolNameEnabled(const std::string& name); - /*! - * \brief Get a description of all debug symbols and their purpose. - * - * A single string describing all registered debug symbols along with short - * descriptions is returned. - */ + /// Get a description of all debug symbols and their purpose. + /// + /// A single string describing all registered debug symbols along with + /// short descriptions is returned. + TF_API static std::string GetDebugSymbolDescriptions(); - /*! - * \brief Get a listing of all debug symbols. - */ + /// Get a listing of all debug symbols. + TF_API static std::vector GetDebugSymbolNames(); - /*! - * \brief Get a description for the specified debug symbol. - * - * A short description of the debug symbol is returned. This is the same - * description string that is embedded in the return value of - * GetDebugSymbolDescriptions. - */ + /// Get a description for the specified debug symbol. + /// + /// A short description of the debug symbol is returned. This is the same + /// description string that is embedded in the return value of + /// GetDebugSymbolDescriptions. + TF_API static std::string GetDebugSymbolDescription(const std::string& name); - /*! - * \brief Direct debug output to \a either stdout or stderr. - * - * Note that \a file MUST be either stdout or stderr. If not, issue an - * error and do nothing. Debug output is issued to stdout by default. If - * the environment variable TF_DEBUG_OUTPUT_FILE is set to 'stderr', then - * output is issued to stderr by default. - */ + /// Direct debug output to \a either stdout or stderr. + /// + /// Note that \a file MUST be either stdout or stderr. If not, issue an + /// error and do nothing. Debug output is issued to stdout by default. + /// If the environment variable TF_DEBUG_OUTPUT_FILE is set to 'stderr', + /// then output is issued to stderr by default. + TF_API static void SetOutputFile(FILE *file); struct _Node; - /* - * Public, to be used in TF_DEBUG_ENVIRONMENT_SYMBOL() macro, - * but not meant to be used otherwise. - */ + // Public, to be used in TF_DEBUG_ENVIRONMENT_SYMBOL() macro, + // but not meant to be used otherwise. template static _Node* _GetSymbolAddr(T val, const char* name) { _Traits::Enum_Not_Listed_In_Any_TF_DEBUG_RANGE(); @@ -370,22 +336,20 @@ class TfDebug { return &_GetNode(val); } - /* - * Public, to be used in TF_DEBUG_ENVIRONMENT_SYMBOL() macro, - * but not meant to be used otherwise. - */ + // Public, to be used in TF_DEBUG_ENVIRONMENT_SYMBOL() macro, + // but not meant to be used otherwise. + TF_API static void _RegisterDebugSymbol(TfEnum val, _Node* addr, const char* descrip); - /* - * This function is only meant for use by TfRegistryManager. - * It's relatively expensive, and not meant for large-scale use. - */ + // This function is only meant for use by TfRegistryManager. + // It's relatively expensive, and not meant for large-scale use. + TF_API static bool _CheckEnvironmentForMatch(const std::string& enumName); // Unfortunately, we need to make both _Traits and _Node, below // public because of their use in macros. - // Please treat both as a private datastructures! + // Please treat both as a private data structures! template struct _Traits { @@ -394,7 +358,7 @@ class TfDebug { enum{compileTimeEnabled = 0}; }; - // Note: this is a POD (plain old datastructure) so it is initialized + // Note: this is a POD (plain old data structure) so it is initialized // to zero statically. struct _Node { std::vector<_Node*>* children; @@ -419,6 +383,7 @@ class TfDebug { friend class Tf_DebugSymbolRegistry; + TF_API static void _ComplainAboutInvalidSymbol(const char*); static void _SetNodes(_Node* ptr, size_t nNodes, bool state); static void _SetParentChild(_Node* parent, _Node* child); @@ -435,25 +400,18 @@ struct TfDebug::TimedScopeHelper { } }; -/*! - * \hideinitializer - * \ingroup group_tf_DebuggingOutput - * \brief Define debugging symbols - * - * This is a simple macro that takes care of declaring your enum, - * providing a first and last symbol and declaring the range. - * Use it as follows: - * - * \code - * - * TF_DEBUG_CODES( - * MY_E1, - * MY_E2 - * ); - * - * \endcode - * - */ +/// Define debugging symbols. +/// +/// This is a simple macro that takes care of declaring your enum, providing a +/// first and last symbol and declaring the range. Use it as follows: +/// \code +/// TF_DEBUG_CODES( +/// MY_E1, +/// MY_E2 +/// ); +/// \endcode +/// +/// \hideinitializer #define TF_DEBUG_CODES(...) \ enum _TF_DEBUG_ENUM_NAME(__VA_ARGS__) { \ TF_PP_CAT( _TF_DEBUG_ENUM_NAME(__VA_ARGS__), __FIRST) \ @@ -475,23 +433,19 @@ struct TfDebug::TimedScopeHelper { #define _TF_DEBUG_FIRST_CODE(first, ...) \ first - -/*! - * \hideinitializer - * \ingroup group_tf_DebuggingOutput - * \brief Define the range for an enum class for debugging symbols. - * - * The parameters \c first and \c last should be constant values of enumerated - * type \c enumType; furthermore, \c first should be numerically less - * than (or equal to) \c last when compared as integers. The fourth - * parameter \c enabled should be a constant boolean value; if \c false, - * then all debugging symbols for enumerated type \c enumType are treated - * as disabled, regardless of any calls to \c TfDebug::Enable() or - * \c TfDebug::EnableAll(). Furthermore, this mode of disabling is - * discernable at compile time, rendering the \c TF_DEBUG() macro - * a literal no-op in terms of code-generation for this enumeration class. - */ - +/// Define the range for an enum class for debugging symbols. +/// +/// The parameters \c first and \c last should be constant values of +/// enumerated type \c enumType; furthermore, \c first should be numerically +/// less than (or equal to) \c last when compared as integers. The fourth +/// parameter \c enabled should be a constant boolean value; if \c false, then +/// all debugging symbols for enumerated type \c enumType are treated as +/// disabled, regardless of any calls to \c TfDebug::Enable() or +/// \c TfDebug::EnableAll(). Furthermore, this mode of disabling is +/// discernable at compile time, rendering the \c TF_DEBUG() macro a literal +/// no-op in terms of code-generation for this enumeration class. +/// +/// \hideinitializer #define TF_DEBUG_RANGE(enumType, first, last, enabled) \ template <> \ struct TfDebug::_Traits { \ @@ -501,113 +455,102 @@ struct TfDebug::TimedScopeHelper { static void Enum_Not_Listed_In_Any_TF_DEBUG_RANGE() { } \ }; -/*! - * \hideinitializer - * \ingroup group_tf_DebuggingOutput - * \brief Evaluate and print debugging message \c msg if \c enumVal - * is enabled for debugging. - * - * This macro is a newer, more convenient form of the \c TF_DEBUG() macro. - * Writing - * \code - * TF_DEBUG_MSG(enumVal, msg, ...); - * \endcode - * is equivalent to - * \code - * TF_DEBUG(enumVal).Msg(msg, ...); - * \endcode - * - * The TF_DEBUG_MSG() macro allows either an std::string argument or - * a printf-like format string followed by a variable number of arguments: - * - * \code - * TF_DEBUG_MSG(enumVal, "opening file %s\n", file.c_str()); - * - * TF_DEBUG_MSG(enumVal, "opening file " + file); - * \endcode - * - */ +/// Evaluate and print debugging message \c msg if \c enumVal is enabled for +/// debugging. +/// +/// This macro is a newer, more convenient form of the \c TF_DEBUG() macro. +/// Writing +/// \code +/// TF_DEBUG_MSG(enumVal, msg, ...); +/// \endcode +/// is equivalent to +/// \code +/// TF_DEBUG(enumVal).Msg(msg, ...); +/// \endcode +/// +/// The TF_DEBUG_MSG() macro allows either an std::string argument or +/// a printf-like format string followed by a variable number of arguments: +/// \code +/// TF_DEBUG_MSG(enumVal, "opening file %s\n", file.c_str()); +/// +/// TF_DEBUG_MSG(enumVal, "opening file " + file); +/// \endcode +/// +/// \hideinitializer #define TF_DEBUG_MSG(enumVal, ...) \ if (!TfDebug::IsEnabled(enumVal)) /* empty */ ; else TfDebug::Helper().Msg(__VA_ARGS__) -/*! - * \hideinitializer - * \ingroup group_tf_DebuggingOutput - * \brief Evaluate and print debugging message \c msg if \c enumVal - * is enabled for debugging. - * - * See also \c TF_DEBUG_MSG(). - * - * The \c TF_DEBUG() macro is used as follows: - * \code - * TF_DEBUG(enumVal).Msg("opening file %s, count = %d\n", - * file.c_str(), count); - * \endcode - * - * If \c enumVal is of enumerated type \c enumType, and \c enumType - * has been enabled for debugging (see \c TF_DEBUG_RANGE()), and - * the specific value \c enumVal has been enabled for debugging by a call - * to \c TfDebug::Enable(), then the arguments in the \c Msg() call are - * evaluated and printed. The argument to \c Msg() may either be a - * \c const \c char* and a variable number of arguments, using standard - * printf-formatting rules, or a \c std::string variable: - * \code - * TF_DEBUG(enumVal).Msg("opening file " + file + "\n"); - * \endcode - * - * Note that the arguments to \c Msg() are unevaluated when the value - * \c enumVal is not enabled for debugging, so \c Msg() must be free - * of side-effects; however, when \c enumVal is not enabled, there is - * no expense incurred in computing the arguments to \c Msg(). Note - * that if the entire enum type corresponding to \c enumVal is - * disabled (a compile-time determination) then the code for the \e - * entire \c TF_DEBUG().Msg() statement will typically not even be - * generated! - */ +/// Evaluate and print debugging message \c msg if \c enumVal is enabled for +/// debugging. +/// +/// The \c TF_DEBUG() macro is used as follows: +/// \code +/// TF_DEBUG(enumVal).Msg("opening file %s, count = %d\n", +/// file.c_str(), count); +/// \endcode +/// +/// If \c enumVal is of enumerated type \c enumType, and \c enumType +/// has been enabled for debugging (see \c TF_DEBUG_RANGE()), and +/// the specific value \c enumVal has been enabled for debugging by a call +/// to \c TfDebug::Enable(), then the arguments in the \c Msg() call are +/// evaluated and printed. The argument to \c Msg() may either be a +/// \c const \c char* and a variable number of arguments, using standard +/// printf-formatting rules, or a \c std::string variable: +/// \code +/// TF_DEBUG(enumVal).Msg("opening file " + file + "\n"); +/// \endcode +/// +/// Note that the arguments to \c Msg() are unevaluated when the value +/// \c enumVal is not enabled for debugging, so \c Msg() must be free +/// of side-effects; however, when \c enumVal is not enabled, there is +/// no expense incurred in computing the arguments to \c Msg(). Note +/// that if the entire enum type corresponding to \c enumVal is +/// disabled (a compile-time determination) then the code for the \e +/// entire \c TF_DEBUG().Msg() statement will typically not even be +/// generated! +/// +/// \sa TF_DEBUG_MSG() +/// +/// \hideinitializer #define TF_DEBUG(enumVal) \ if (!TfDebug::IsEnabled(enumVal)) /* empty */ ; else TfDebug::Helper() -/*! - * \hideinitializer - * \ingroup group_tf_DebuggingOutput - * \brief Evaluate and print diagnostic messages intended for end-users. - * - * The TF_INFO(x) macro is cosmetic; it actually just calls the TF_DEBUG - * macro (see above). This macro should be used if its output is intended - * to be seen by end-users. - */ +/// Evaluate and print diagnostic messages intended for end-users. +/// +/// The TF_INFO(x) macro is cosmetic; it actually just calls the TF_DEBUG +/// macro (see above). This macro should be used if its output is intended to +/// be seen by end-users. +/// +/// \hideinitializer #define TF_INFO(x) TF_DEBUG(x) -/*! - * \hideinitializer - * \ingroup group_tf_DebuggingOutput - * \brief Print description and time spent in scope upon beginning and - * exiting it if \p enumVal is enabled for debugging. - * - * The \c TF_DEBUG_TIMED_SCOPE() macro is used as follows: - * \code - * void Attribute::Compute() - * { - * TF_DEBUG_TIMED_SCOPE(ATTR_COMPUTE, "Computing %s", name.c_str()); - * ... - * } - * \endcode - * - * When the TF_DEBUG_TIMED_SCOPE macro is invoked, a timer is started - * and the supplied description is printed. When the enclosing scope is exited - * (in the example, when Attribute::Compute() finishes) the timer is stopped - * and the scope description and measured time are printed. This allows for - * very fine-grained timing of operations. - * - * Note that if the entire enum type corresponding to \p enumVal is - * disabled (a compile-time determination) then the presence of - * a \c TF_DEBUG_TIMED_SCOPE() macro should not produce any extra generated - * code (in an optimized build). If the enum type is enabled, but the - * particular value \p enumVal is disabled, the cost of the macro - * should be quite minimal; still, it would be best not to embed the macro - * in functions that are called in very tight loops, in final released - * code. - */ +/// Print description and time spent in scope upon beginning and exiting it if +/// \p enumVal is enabled for debugging. +/// +/// The \c TF_DEBUG_TIMED_SCOPE() macro is used as follows: +/// \code +/// void Attribute::Compute() +/// { +/// TF_DEBUG_TIMED_SCOPE(ATTR_COMPUTE, "Computing %s", name.c_str()); +/// ... +/// } +/// \endcode +/// +/// When the \c TF_DEBUG_TIMED_SCOPE macro is invoked, a timer is started and +/// the supplied description is printed. When the enclosing scope is exited +/// (in the example, when Attribute::Compute() finishes) the timer is stopped +/// and the scope description and measured time are printed. This allows for +/// very fine-grained timing of operations. +/// +/// Note that if the entire enum type corresponding to \p enumVal is disabled +/// (a compile-time determination) then the presence of a +/// \c TF_DEBUG_TIMED_SCOPE() macro should not produce any extra generated +/// code (in an optimized build). If the enum type is enabled, but the +/// particular value \p enumVal is disabled, the cost of the macro should be +/// quite minimal; still, it would be best not to embed the macro in functions +/// that are called in very tight loops, in final released code. +/// +/// \hideinitializer #define TF_DEBUG_TIMED_SCOPE(enumVal, ...) \ TfDebug::TimedScopeHelper< \ TfDebug::_Traits< \ @@ -615,26 +558,24 @@ struct TfDebug::TimedScopeHelper { TF_PP_CAT(local__TfScopeDebugSwObject, __LINE__)( \ TfDebug::IsEnabled(enumVal), __VA_ARGS__) -/*! - * \hideinitializer - * \ingroup group_tf_DebuggingOutput - * \brief Register an enum symbol for debugging. - * - * This call should be used in source files, not header files, and should - * This macro should usually appear within a \c TF_REGISTRY_FUNCTION(TfDebug,...) - * call. The first argument should be the literal name of the enum symbol, while the - * second argument should be a (short) description of what debugging will be enabled - * if the symbol is activated. The enum being registered must be one which is contained - * in some TF_DEBUG_RANGE() call. - * For example, - * \code - * TF_REGISTRY_FUNCTION(TfDebug, MyDebugCodes) { - * TF_DEBUG_ENVIRONMENT_SYMBOL(MY_E1, "loading of blah-blah files"); - * TF_DEBUG_ENVIRONMENT_SYMBOL(MY_E2, "parsing of mdl code"); - * // etc. - * } - * \endcode - */ +/// Register an enum symbol for debugging. +/// +/// This call should be used in source files, not header files, and should +/// This macro should usually appear within a +/// \c TF_REGISTRY_FUNCTION(TfDebug,...) call. The first argument should be +/// the literal name of the enum symbol, while the second argument should be a +/// (short) description of what debugging will be enabled if the symbol is +/// activated. The enum being registered must be one which is contained in +/// some TF_DEBUG_RANGE() call. For example: +/// \code +/// TF_REGISTRY_FUNCTION(TfDebug, MyDebugCodes) { +/// TF_DEBUG_ENVIRONMENT_SYMBOL(MY_E1, "loading of blah-blah files"); +/// TF_DEBUG_ENVIRONMENT_SYMBOL(MY_E2, "parsing of mdl code"); +/// // etc. +/// } +/// \endcode +/// +/// \hideinitializer #define TF_DEBUG_ENVIRONMENT_SYMBOL(VAL, descrip) \ if (TfDebug::_Traits< \ std::decay::type>::compileTimeEnabled) { \ @@ -644,4 +585,6 @@ struct TfDebug::TimedScopeHelper { descrip); \ } +///@} + #endif diff --git a/pxr/base/lib/tf/debugCodes.h b/pxr/base/lib/tf/debugCodes.h index e11cbca1c6..ebd34a235e 100644 --- a/pxr/base/lib/tf/debugCodes.h +++ b/pxr/base/lib/tf/debugCodes.h @@ -24,13 +24,13 @@ #ifndef TF_TFDEBUGCODES_H #define TF_TFDEBUGCODES_H - #include "pxr/base/tf/debug.h" -/* - * Note that this is a private header file to lib/Tf. - * If you add a new entry here, please be sure to update DebugCodes.cpp as well. - */ +// +// Note that this is a private header file to lib/tf. +// If you add a new entry here, please be sure to update DebugCodes.cpp as well. +// + TF_DEBUG_CODES( TF_DISCOVERY_TERSE, // these are special in that they don't have a diff --git a/pxr/base/lib/tf/debugNotice.h b/pxr/base/lib/tf/debugNotice.h index 1e26fef71a..436a1615e5 100644 --- a/pxr/base/lib/tf/debugNotice.h +++ b/pxr/base/lib/tf/debugNotice.h @@ -24,8 +24,12 @@ #ifndef TF_DEBUGNOTICE_H #define TF_DEBUGNOTICE_H +/// \file tf/debugNotice.h + #include "pxr/base/tf/notice.h" +/// \class TfDebugSymbolsChangedNotice +/// /// Sent when the list of available debug symbol names has changed. class TfDebugSymbolsChangedNotice : public TfNotice { @@ -34,6 +38,8 @@ class TfDebugSymbolsChangedNotice : public TfNotice virtual ~TfDebugSymbolsChangedNotice(); }; +/// \class TfDebugSymbolEnableChangedNotice +/// /// Sent when a debug symbol has been enabled or disabled. class TfDebugSymbolEnableChangedNotice : public TfNotice { diff --git a/pxr/base/lib/tf/declarePtrs.h b/pxr/base/lib/tf/declarePtrs.h index 44a874b424..c0ea2d0c50 100644 --- a/pxr/base/lib/tf/declarePtrs.h +++ b/pxr/base/lib/tf/declarePtrs.h @@ -24,24 +24,17 @@ #ifndef TF_DECLARE_PTR_H #define TF_DECLARE_PTR_H +/// \file tf/declarePtrs.h +/// Standard pointer typedefs. +/// +/// This file provides typedefs for standard pointer types. #include "pxr/base/tf/weakPtr.h" #include "pxr/base/tf/refPtr.h" #include -/*! - * \file declarePtrs.h - * \brief Standard pointer typedefs. - * - * This file provides typedefs for standard pointer types. - * - */ - - - -/*! - * \brief Templated struct used for type definition macros. - */ +/// \struct TfDeclarePtrs +/// Templated struct used for type definition macros. template struct TfDeclarePtrs { typedef TfWeakPtr< T > Ptr; typedef TfWeakPtr< const T > ConstPtr; @@ -54,50 +47,43 @@ template struct TfDeclarePtrs { typedef std::vector< ConstRefPtr > ConstRefPtrVector; }; -/*! - * \hideinitializer - * \brief Define standard weak pointer types. - * - * \param type is a class name. - * - * \c TF_DECLARE_WEAK_PTRS(Class) declares ClassPtr, ClassConstPtr, - * ClassPtrVector and ClassConstPtrVector. - */ +/// Define standard weak pointer types. +/// +/// \param type is a class name. +/// +/// \c TF_DECLARE_WEAK_PTRS(Class) declares ClassPtr, ClassConstPtr, +/// ClassPtrVector and ClassConstPtrVector. +/// +/// \hideinitializer #define TF_DECLARE_WEAK_PTRS(type) \ typedef TfDeclarePtrs< class type >::Ptr type##Ptr; \ typedef TfDeclarePtrs< class type >::ConstPtr type##ConstPtr; \ typedef TfDeclarePtrs< class type >::PtrVector type##PtrVector; \ typedef TfDeclarePtrs< class type >::ConstPtrVector type##ConstPtrVector -/*! - * \hideinitializer - * \brief Define standard ref pointer types. - * - * \param type is a class name. - * - * \c TF_DECLARE_REF_PTRS(Class) declares ClassRefPtr and ClassConstRefPtr. - */ +/// Define standard ref pointer types. +/// +/// \param type is a class name. +/// +/// \c TF_DECLARE_REF_PTRS(Class) declares ClassRefPtr and ClassConstRefPtr. +/// +/// \hideinitializer #define TF_DECLARE_REF_PTRS(type) \ typedef TfDeclarePtrs< class type >::RefPtr type##RefPtr; \ typedef TfDeclarePtrs< class type >::ConstRefPtr type##ConstRefPtr; \ typedef TfDeclarePtrs< class type >::RefPtrVector type##RefPtrVector; \ typedef TfDeclarePtrs< class type >::ConstRefPtrVector type##ConstRefPtrVector -/*! - * \hideinitializer - * \brief Define standard weak, ref, and vector pointer types. - * - * \param type is a class name. - * - * \c TF_DECLARE_WEAK_AND_REF_PTRS(Class) declares ClassPtr, ClassConstPtr, - * ClassPtrVector, ClassConstPtrVector, ClassRefPtr and ClassConstRefPtr. - */ +/// Define standard weak, ref, and vector pointer types. +/// +/// \param type is a class name. +/// +/// \c TF_DECLARE_WEAK_AND_REF_PTRS(Class) declares ClassPtr, ClassConstPtr, +/// ClassPtrVector, ClassConstPtrVector, ClassRefPtr and ClassConstRefPtr. +/// +/// \hideinitializer #define TF_DECLARE_WEAK_AND_REF_PTRS(type) \ TF_DECLARE_WEAK_PTRS(type); \ TF_DECLARE_REF_PTRS(type) - - - - #endif diff --git a/pxr/base/lib/tf/denseHashMap.h b/pxr/base/lib/tf/denseHashMap.h index 7e06f26d27..2d4cc410f2 100644 --- a/pxr/base/lib/tf/denseHashMap.h +++ b/pxr/base/lib/tf/denseHashMap.h @@ -24,8 +24,7 @@ #ifndef TF_DENSE_HASH_MAP_H #define TF_DENSE_HASH_MAP_H -/// -/// \file Tf/DenseHashMap.h +/// \file tf/denseHashMap.h #include @@ -33,11 +32,10 @@ #include #include #include +#include "pxr/base/arch/defines.h" #include "pxr/base/tf/hashmap.h" #include -/////////////////////////////////////////////////////////////////////////////// -/// /// \class TfDenseHashMap /// /// This is a space efficent container that mimics the TfHashMap API that @@ -46,9 +44,7 @@ /// When the map gets bigger than \p Threshold a TfHashMap is allocated /// that is used to accelerate lookup in the vector. /// -/// WARNING: -/// -/// Note that this differs from a TfHashMap in so far that inserting and +/// \warning This differs from a TfHashMap in so far that inserting and /// removing elements invalidate all iterators of the container. /// template < diff --git a/pxr/base/lib/tf/denseHashSet.h b/pxr/base/lib/tf/denseHashSet.h index a5bbb5960a..2242dc42df 100644 --- a/pxr/base/lib/tf/denseHashSet.h +++ b/pxr/base/lib/tf/denseHashSet.h @@ -24,8 +24,7 @@ #ifndef TF_DENSE_HASH_SET_H #define TF_DENSE_HASH_SET_H -/// -/// \file Tf/DenseHashSet.h +/// \file tf/denseHashSet.h #include @@ -33,13 +32,12 @@ #include #include #include +#include "pxr/base/arch/defines.h" #include "pxr/base/tf/hashmap.h" #include #include -/////////////////////////////////////////////////////////////////////////////// -/// /// \class TfDenseHashSet /// /// This is a space efficent container that mimics the TfHashSet API that @@ -48,9 +46,7 @@ /// When the set gets bigger than \p Threshold a TfHashMap is allocated /// that is used to accelerate lookup in the vector. /// -/// WARNING: -/// -/// Note that this differs from a TfHashSet in so far that inserting and +/// \warning This differs from a TfHashSet in so far that inserting and /// removing elements invalidate all iterators of the container. /// template < diff --git a/pxr/base/lib/tf/diagnostic.cpp b/pxr/base/lib/tf/diagnostic.cpp index 1a61915aa0..71647ff09d 100644 --- a/pxr/base/lib/tf/diagnostic.cpp +++ b/pxr/base/lib/tf/diagnostic.cpp @@ -125,7 +125,7 @@ Tf_TerminateHandler() std::set_terminate(::_BadThrowHandler); throw; } - catch (std::bad_alloc& exc) { + catch (std::bad_alloc&) { std::set_terminate(Tf_TerminateHandler); reason = "allocation failed (you've run out of memory)"; type = "bad_alloc"; @@ -162,6 +162,7 @@ std::string TfGetProgramNameForErrors() return ArchGetProgramNameForErrors(); } +#if !defined(ARCH_OS_WINDOWS) // Called when we get a fatal signal. static void _fatalSignalHandler(int signo, siginfo_t*, void* uctx) @@ -205,11 +206,12 @@ _fatalSignalHandler(int signo, siginfo_t*, void* uctx) // Simulate the exit status of being killed by signal signo _exit(128 + signo); } - +#endif void TfInstallTerminateAndCrashHandlers() { +#if !defined(ARCH_OS_WINDOWS) std::set_terminate(Tf_TerminateHandler); // Catch segvs and bus violations @@ -236,4 +238,5 @@ TfInstallTerminateAndCrashHandlers() sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); sigaction(SIGABRT, &act, NULL); -} +#endif +} \ No newline at end of file diff --git a/pxr/base/lib/tf/diagnostic.h b/pxr/base/lib/tf/diagnostic.h index e6bb82c254..6d175d9178 100644 --- a/pxr/base/lib/tf/diagnostic.h +++ b/pxr/base/lib/tf/diagnostic.h @@ -24,8 +24,20 @@ #ifndef TF_DIAGNOSTIC_H #define TF_DIAGNOSTIC_H +/// \file tf/diagnostic.h +/// \ingroup group_tf_Diagnostic +/// Low-level utilities for informing users of various internal and external +/// diagnostic conditions. +/// +/// lib/tf supports a range of error-reporting routines. +/// +/// For a more detailed explanation of when each of the facilities described +/// in this file is appropriate, (and more importantly, when they're not!) +/// see \ref page_tf_Diagnostic. + #include "pxr/base/arch/function.h" #include "pxr/base/tf/diagnosticLite.h" +#include "pxr/base/tf/api.h" #if defined(__cplusplus) || defined (doxygen) @@ -36,299 +48,267 @@ #include #include -/*! - * \file diagnostic.h - * \brief Low-level utilities for informing users of various internal and - * external diagnostic conditions. - * \ingroup group_tf_Diagnostic - * - * lib/tf supports a range of error-reporting routines. - * - * For a more detailed explanation of when each of the facilities described - * in this file is appropriate, (and more importantly, when they're not!) - * see \ref page_tf_Diagnostic. - */ - -/* - * Note: diagnosticLite.h defines the various macros, but we'll document - * them here. The following block is only for doxygen, not seen by a real - * compile. To see the actual macro definition, look in diagnosticLite.h. - */ +// Note: diagnosticLite.h defines the various macros, but we'll document +// them here. The following block is only for doxygen, not seen by a real +// compile. To see the actual macro definition, look in diagnosticLite.h. #if defined(doxygen) -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Issue an internal programming error, but continue execution. - * - * Please see \ref page_tf_TfError for more information about how to use - * TF_ERROR(). - * - * This is safe to call in secondary threads, but the error will be downgraded - * to a warning. - */ +/// \addtogroup group_tf_Diagnostic +///@{ + +/// Issue an internal programming error, but continue execution. +/// +/// Please see \ref page_tf_TfError for more information about how to use +/// TF_ERROR(). +/// +/// This is safe to call in secondary threads, but the error will be downgraded +/// to a warning. +/// +/// \hideinitializer #define TF_ERROR(...) -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Issue an internal programming error, but continue execution. - * - * This macro is a convenience. It produces a TF_ERROR() with an error code - * indicating a coding error. It takes a printf-like format specification or a - * std::string. Generally, an error handilng delegate will take action to turn - * this error into a python exception, and if it remains unhandled at the end of - * an application iteration will roll-back the undo stack to a last-known-good - * state. - * - * This is safe to call in secondary threads, but the error will be downgraded - * to a warning. - */ +/// Issue an internal programming error, but continue execution. +/// +/// This macro is a convenience. It produces a TF_ERROR() with an error code +/// indicating a coding error. It takes a printf-like format specification or a +/// std::string. Generally, an error handilng delegate will take action to turn +/// this error into a python exception, and if it remains unhandled at the end of +/// an application iteration will roll-back the undo stack to a last-known-good +/// state. +/// +/// This is safe to call in secondary threads, but the error will be downgraded +/// to a warning. +/// +/// \hideinitializer #define TF_CODING_ERROR(fmt, args) -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Issue a generic runtime error, but continue execution. - * - * This macro is a convenience. It produces a TF_ERROR() with an error code - * indicating a generic runtime error. It is preferred over TF_ERROR(0), - * but using a specific error code is preferred over this. It takes a - * printf-like format specification or a std::string. Generally, an error - * handilng delegate will take action to turn this error into a python - * exception, and if it remains unhandled at the end of an application iteration - * will roll-back the undo stack to a last-known-good state. - * - * This is safe to call in secondary threads, but the error will be downgraded - * to a warning. - */ +/// Issue a generic runtime error, but continue execution. +/// +/// This macro is a convenience. It produces a TF_ERROR() with an error code +/// indicating a generic runtime error. It is preferred over TF_ERROR(0), +/// but using a specific error code is preferred over this. It takes a +/// printf-like format specification or a std::string. Generally, an error +/// handilng delegate will take action to turn this error into a python +/// exception, and if it remains unhandled at the end of an application iteration +/// will roll-back the undo stack to a last-known-good state. +/// +/// This is safe to call in secondary threads, but the error will be downgraded +/// to a warning. +/// +/// \hideinitializer #define TF_RUNTIME_ERROR(fmt, args) -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Issue a fatal error and end the program. - * - * This macro takes a printf-like format specification or a std::string. The - * program will generally terminate upon a fatal error. - */ +/// Issue a fatal error and end the program. +/// +/// This macro takes a printf-like format specification or a std::string. The +/// program will generally terminate upon a fatal error. +/// +/// \hideinitializer #define TF_FATAL_ERROR(fmt, args) -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Issue a warning, but continue execution. - * - * This macro works with a variety of argument sets. It supports simple - * printf-like format specification or a std::string. It also supports - * specification of a diagnostic code and a piece of arbitrary information in - * the form of a TfDiagnosticInfo. The following is a full list of supported - * argument lists: - * - * \code - * TF_WARN(const char *) // plain old string - * TF_WARN(const char *, ...) // printf like formatting - * TF_WARN(std::string) // stl string - * \endcode - * - * A diagnostic code can be passed in along with the warning message. See - * \ref DiagnosticEnumConventions for an example of registering an enum type - * and it's values as diagnostic codes. - * - * \code - * TF_WARN(DIAGNOSTIC_ENUM, const char *) - * TF_WARN(DIAGNOSTIC_ENUM, const char *, ...) - * TF_WARN(DIAGNOSTIC_ENUM, std::string) - * \endcode - * - * A piece of arbitrary data can also be passed in along with the diagnostic - * code and warning message as follows: - * - * \code - * TF_WARN(info, DIAGNOSTIC_ENUM, const char *) - * TF_WARN(info, DIAGNOSTIC_ENUM, const char *, ...) - * TF_WARN(info, DIAGNOSTIC_ENUM, std::string) - * \endcode - * - * Generally, no adjustment to program state should occur as the result of this - * macro. This is in contrast with errors as mentioned above. - * - * This is safe to call in secondary threads, but the warning will be printed - * to stderr rather than being handled by the diagnostic delegate. - */ +/// Issue a warning, but continue execution. +/// +/// This macro works with a variety of argument sets. It supports simple +/// printf-like format specification or a std::string. It also supports +/// specification of a diagnostic code and a piece of arbitrary information in +/// the form of a TfDiagnosticInfo. The following is a full list of supported +/// argument lists: +/// +/// \code +/// TF_WARN(const char *) // plain old string +/// TF_WARN(const char *, ...) // printf like formatting +/// TF_WARN(std::string) // stl string +/// \endcode +/// +/// A diagnostic code can be passed in along with the warning message. See +/// \ref DiagnosticEnumConventions for an example of registering an enum type +/// and it's values as diagnostic codes. +/// +/// \code +/// TF_WARN(DIAGNOSTIC_ENUM, const char *) +/// TF_WARN(DIAGNOSTIC_ENUM, const char *, ...) +/// TF_WARN(DIAGNOSTIC_ENUM, std::string) +/// \endcode +/// +/// A piece of arbitrary data can also be passed in along with the diagnostic +/// code and warning message as follows: +/// +/// \code +/// TF_WARN(info, DIAGNOSTIC_ENUM, const char *) +/// TF_WARN(info, DIAGNOSTIC_ENUM, const char *, ...) +/// TF_WARN(info, DIAGNOSTIC_ENUM, std::string) +/// \endcode +/// +/// Generally, no adjustment to program state should occur as the result of +/// this macro. This is in contrast with errors as mentioned above. +/// +/// This is safe to call in secondary threads, but the warning will be printed +/// to \c stderr rather than being handled by the diagnostic delegate. +/// +/// \hideinitializer #define TF_WARN(...) -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Issue a status message, but continue execution. - * - * This macro works with a variety of argument sets. It supports simple - * printf-like format specification or a std::string. It also supports - * specification of a diagnostic code and a piece of arbitrary information in - * the form of a TfDiagnosticInfo. The following is a full list of supported - * argument lists: - * - * \code - * TF_STATUS(const char *) // plain old string - * TF_STATUS(const char *, ...) // printf like formatting - * TF_STATUS(std::string) // stl string - * \endcode - * - * A diagnostic code can be passed in along with the status message. See - * \ref DiagnosticEnumConventions for an example of registering an enum type - * and it's values as diagnostic codes. - * - * \code - * TF_STATUS(DIAGNOSTIC_ENUM, const char *) - * TF_STATUS(DIAGNOSTIC_ENUM, const char *, ...) - * TF_STATUS(DIAGNOSTIC_ENUM, std::string) - * \endcode - * - * A piece of arbitrary data can also be passed in along with the diagnostic - * code and status message as follows: - * - * \code - * TF_STATUS(info, DIAGNOSTIC_ENUM, const char *) - * TF_STATUS(info, DIAGNOSTIC_ENUM, const char *, ...) - * TF_STATUS(info, DIAGNOSTIC_ENUM, std::string) - * \endcode - * - * Generally, no adjustment to program state should occur as the result of this - * macro. This is in contrast with errors as mentioned above. - * - * This is safe to call in secondary threads, but the message will be printed - * to stderr rather than being handled by the diagnostic delegate. - */ +/// Issue a status message, but continue execution. +/// +/// This macro works with a variety of argument sets. It supports simple +/// printf-like format specification or a std::string. It also supports +/// specification of a diagnostic code and a piece of arbitrary information in +/// the form of a TfDiagnosticInfo. The following is a full list of supported +/// argument lists: +/// +/// \code +/// TF_STATUS(const char *) // plain old string +/// TF_STATUS(const char *, ...) // printf like formatting +/// TF_STATUS(std::string) // stl string +/// \endcode +/// +/// A diagnostic code can be passed in along with the status message. See +/// \ref DiagnosticEnumConventions for an example of registering an enum type +/// and it's values as diagnostic codes. +/// +/// \code +/// TF_STATUS(DIAGNOSTIC_ENUM, const char *) +/// TF_STATUS(DIAGNOSTIC_ENUM, const char *, ...) +/// TF_STATUS(DIAGNOSTIC_ENUM, std::string) +/// \endcode +/// +/// A piece of arbitrary data can also be passed in along with the diagnostic +/// code and status message as follows: +/// +/// \code +/// TF_STATUS(info, DIAGNOSTIC_ENUM, const char *) +/// TF_STATUS(info, DIAGNOSTIC_ENUM, const char *, ...) +/// TF_STATUS(info, DIAGNOSTIC_ENUM, std::string) +/// \endcode +/// +/// Generally, no adjustment to program state should occur as the result of +/// this macro. This is in contrast with errors as mentioned above. +/// +/// This is safe to call in secondary threads, but the message will be printed +/// to \c stderr rather than being handled by the diagnostic delegate. +/// +/// \hideinitializer #define TF_STATUS(...) - - -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Aborts if the condition \c cond is not met. - * - * \param cond is any expression convertible to bool; if the condition evaluates - * to \c false, program execution ends with this call. - * - * Note that the diagnostic message sent is the code \c cond, in the - * form of a string. Unless the condition expression is self-explanatory, - * use \c TF_FATAL_ERROR(). See \ref DiagnosticTF_FATAL_ERROR - * for further discussion. - * - * Currently, a \c TF_AXIOM() statement is not made a no-op in - * optimized builds; however, it always possible that either (a) the - * axiom statement might be removed at some point if the code is - * deemed correct or (b) in the future, some flavor of build might choose - * to make axioms be no-ops. Thus, programmers must make \e certain - * that the code in \p cond is entirely free of side effects. - */ +/// Aborts if the condition \c cond is not met. +/// +/// \param cond is any expression convertible to bool; if the condition evaluates +/// to \c false, program execution ends with this call. +/// +/// Note that the diagnostic message sent is the code \c cond, in the form of +/// a string. Unless the condition expression is self-explanatory, use +/// \c TF_FATAL_ERROR(). See \ref DiagnosticTF_FATAL_ERROR for further +/// discussion. +/// +/// Currently, a \c TF_AXIOM() statement is not made a no-op in optimized +/// builds; however, it always possible that either (a) the axiom statement +/// might be removed at some point if the code is deemed correct or (b) in the +/// future, some flavor of build might choose to make axioms be no-ops. Thus, +/// programmers must make \e certain that the code in \p cond is entirely free +/// of side effects. +/// +/// \hideinitializer #define TF_AXIOM(cond) -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief The same as TF_AXIOM, but compiled only in dev builds. - * - * \param cond is any expression convertible to bool; if the condition evaluates - * to \c false, program execution ends with this call. - * - * This macro has the same behavior as TF_AXIOM, but it is compiled only - * in dev builds. This version should only be used in code that is - * known (not just suspected!) to be performance critical. - */ +/// The same as TF_AXIOM, but compiled only in dev builds. +/// +/// \param cond is any expression convertible to bool; if the condition evaluates +/// to \c false, program execution ends with this call. +/// +/// This macro has the same behavior as TF_AXIOM, but it is compiled only +/// in dev builds. This version should only be used in code that is +/// known (not just suspected!) to be performance critical. +/// +/// \hideinitializer #define TF_DEV_AXIOM(cond) - -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Checks a condition and reports an error if it evaluates false. - * - * This can be thought of as something like a softer, recoverable TF_AXIOM. - * - * The macro expands to an expression whose value is either true or false - * depending on \c cond. If \c cond evaluates to false, issues a coding error - * indicating the failure. - * - * \param cond is any expression convertible to bool. - * - * Usage generally follows patterns like these: - * - * // Simple check. This is like a non-fatal TF_AXIOM. - * TF_VERIFY(condition); - * - * // Avoiding code that requires the condition be met. - * if (TF_VERIFY(condition)) { - * // code requiring condition be met. - * } - * - * // Executing recovery code in case the condition is not met. - * if (not TF_VERIFY(condition)) { - * // recovery code to execute since condition was not met. - * } - * - * Here are some examples: - * - * // List should be empty. If not, issue an error, clear it out and continue. - * if (not TF_VERIFY(list.empty()) { - * // The list was unexpectedly not empty. TF_VERIFY will have - * // issued a coding error with details. We clear the list and continue. - * list.clear(); - * } - * - * // Only add to string if ptr is valid. - * string result = ...; - * if (TF_VERIFY(ptr != NULL)) { - * result += ptr->Method(); - * } - * - * The macro also optionally accepts printf-style arguments to generate a - * message emitted in case the condition is not met. For example: - * - * if (not TF_VERIFY(index < size, - * "Index out of bounds (%zu >= %zu)", index, size)) { - * // Recovery code... - * } - * - * Unmet conditions generate TF_CODING_ERRORs by default, but setting the - * environment variable TF_FATAL_VERIFY to 1 will make unmet conditions - * generate TF_FATAL_ERRORs instead and abort the program. This is intended for - * testing. - * - * This is safe to call in secondary threads, but the error will be downgraded - * to a warning. - */ - +/// Checks a condition and reports an error if it evaluates false. +/// +/// This can be thought of as something like a softer, recoverable TF_AXIOM. +/// +/// The macro expands to an expression whose value is either true or false +/// depending on \c cond. If \c cond evaluates to false, issues a coding error +/// indicating the failure. +/// +/// \param cond is any expression convertible to bool. +/// +/// Usage generally follows patterns like these: +/// \code +/// // Simple check. This is like a non-fatal TF_AXIOM. +/// TF_VERIFY(condition); +/// +/// // Avoiding code that requires the condition be met. +/// if (TF_VERIFY(condition)) { +/// // code requiring condition be met. +/// } +/// +/// // Executing recovery code in case the condition is not met. +/// if (not TF_VERIFY(condition)) { +/// // recovery code to execute since condition was not met. +/// } +/// \endcode +/// +/// Here are some examples: +/// \code +/// // List should be empty. If not, issue an error, clear it out and continue. +/// if (not TF_VERIFY(list.empty()) { +/// // The list was unexpectedly not empty. TF_VERIFY will have +/// // issued a coding error with details. We clear the list and continue. +/// list.clear(); +/// } +/// +/// // Only add to string if ptr is valid. +/// string result = ...; +/// if (TF_VERIFY(ptr != NULL)) { +/// result += ptr->Method(); +/// } +/// \endcode +/// +/// The macro also optionally accepts printf-style arguments to generate a +/// message emitted in case the condition is not met. For example: +/// \code +/// if (not TF_VERIFY(index < size, +/// "Index out of bounds (%zu >= %zu)", index, size)) { +/// // Recovery code... +/// } +/// \endcode +/// +/// Unmet conditions generate TF_CODING_ERRORs by default, but setting the +/// environment variable TF_FATAL_VERIFY to 1 will make unmet conditions +/// generate TF_FATAL_ERRORs instead and abort the program. This is intended for +/// testing. +/// +/// This is safe to call in secondary threads, but the error will be downgraded +/// to a warning. +/// +/// \hideinitializer #define TF_VERIFY(cond [, format, ...]) #endif /* defined(doxygen) */ -/* - * The rest of this is seen by a regular compile (or doxygen). - */ +// +// The rest of this is seen by a regular compile (or doxygen). +// #if defined(__cplusplus) || defined(doxygen) -/*! - * \hideinitializer - * \ingroup group_tf_Diagnostic - * \brief Get the name of the current function as a \c std::string. - * - * This macro will return the name of the current function, nicely - * formatted, as an \c std::string. This is meant primarily for - * diagnostics. Code should not rely on a specific format, because it - * may change in the future or vary across architectures. For example, - * \code - * void YourClass::SomeMethod(int x) { - * cout << "Debugging info about function " << TF_FUNC_NAME() << "." << endl; - * ... - * } - * \endcode - * Should display something like: - * "Debugging info about function YourClass::SomeMethod." - */ + +/// Get the name of the current function as a \c std::string. +/// +/// This macro will return the name of the current function, nicely +/// formatted, as an \c std::string. This is meant primarily for +/// diagnostics. Code should not rely on a specific format, because it +/// may change in the future or vary across architectures. For example, +/// \code +/// void YourClass::SomeMethod(int x) { +/// cout << "Debugging info about function " << TF_FUNC_NAME() << "." << endl; +/// ... +/// } +/// \endcode +/// Should display something like: +/// "Debugging info about function YourClass::SomeMethod." +/// +/// \hideinitializer #define TF_FUNC_NAME() \ ArchGetPrettierFunctionName(__ARCH_FUNCTION__, __ARCH_PRETTY_FUNCTION__) @@ -336,8 +316,8 @@ void Tf_TerminateHandler(); #if !defined(doxygen) -// Redefine these macros from DiagnosticLite to versions that will accept either -// string or printf-like args. +// Redefine these macros from DiagnosticLite to versions that will accept +// either string or printf-like args. #ifdef TF_CODING_ERROR #undef TF_CODING_ERROR @@ -368,7 +348,6 @@ void Tf_TerminateHandler(); Tf_DiagnosticHelper(TF_CALL_CONTEXT.Hide(), \ TF_DIAGNOSTIC_WARNING_TYPE).IssueWarning - #ifdef TF_RUNTIME_ERROR #undef TF_RUNTIME_ERROR #endif // TF_RUNTIME_ERROR @@ -436,16 +415,15 @@ void Tf_TerminateHandler(); Tf_FailedVerifyHelper(TF_CALL_CONTEXT, # cond, \ Tf_DiagnosticStringPrintf(__VA_ARGS__))) - // Helpers for TF_VERIFY -bool +TF_API bool Tf_FailedVerifyHelper(TfCallContext const &context, char const *condition, std::string const &msg); // Helpers for TF_VERIFY. -std::string Tf_DiagnosticStringPrintf(); -std::string Tf_DiagnosticStringPrintf(const char *format, ...) +TF_API std::string Tf_DiagnosticStringPrintf(); +TF_API std::string Tf_DiagnosticStringPrintf(const char *format, ...) ARCH_PRINTF_FUNCTION(1, 2) ; @@ -453,22 +431,17 @@ std::string Tf_DiagnosticStringPrintf(const char *format, ...) #endif // __cplusplus || doxygen -/*! - * \brief Sets program name for reporting errors. - * \ingroup group_tf_Diagnostic - * - * This function simply calls to ArchSetProgramNameForErrors(). - */ +/// Sets program name for reporting errors. +/// +/// This function simply calls to ArchSetProgramNameForErrors(). void TfSetProgramNameForErrors(std::string const& programName); -/*! - * \brief Returns currently set program info. - * \ingroup group_tf_Diagnostic - * - * This function simply calls to ArchGetProgramNameForErrors(). - */ +/// Returns currently set program info. +/// +/// This function simply calls to ArchGetProgramNameForErrors(). std::string TfGetProgramNameForErrors(); +/// \private struct Tf_DiagnosticHelper { Tf_DiagnosticHelper(TfCallContext const &context, TfDiagnosticType type) : @@ -480,14 +453,14 @@ struct Tf_DiagnosticHelper { TfCallContext const &GetContext() const { return _context; } TfDiagnosticType GetType() const { return _type; } - void IssueError(std::string const &msg) const; - void IssueError(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); - void IssueFatalError(std::string const &msg) const; - void IssueFatalError(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); - void IssueWarning(std::string const &msg) const; - void IssueWarning(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); - void IssueStatus(std::string const &msg) const; - void IssueStatus(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void IssueError(std::string const &msg) const; + TF_API void IssueError(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void IssueFatalError(std::string const &msg) const; + TF_API void IssueFatalError(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void IssueWarning(std::string const &msg) const; + TF_API void IssueWarning(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void IssueStatus(std::string const &msg) const; + TF_API void IssueStatus(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); private: TfCallContext _context; @@ -496,13 +469,17 @@ struct Tf_DiagnosticHelper { #endif -/// (Re)install Tf's crash handler. This should not generally need to be called -/// since Tf does this itself when loaded. However, when run in 3rd party -/// environments that install their own signal handlers, possibly overriding -/// Tf's, this provides a way to reinstall them, in hopes that they'll stick. +/// (Re)install Tf's crash handler. This should not generally need to be +/// called since Tf does this itself when loaded. However, when run in 3rd +/// party environments that install their own signal handlers, possibly +/// overriding Tf's, this provides a way to reinstall them, in hopes that +/// they'll stick. /// /// This calls std::set_terminate() and installs signal handlers for SIGSEGV, /// SIGBUS, SIGFPE, and SIGABRT. +TF_API void TfInstallTerminateAndCrashHandlers(); +///@} + #endif // TF_DIAGNOSTIC_H diff --git a/pxr/base/lib/tf/diagnosticBase.h b/pxr/base/lib/tf/diagnosticBase.h index 098cb3b275..17ca267662 100644 --- a/pxr/base/lib/tf/diagnosticBase.h +++ b/pxr/base/lib/tf/diagnosticBase.h @@ -24,6 +24,7 @@ #ifndef TF_DIAGNOSTIC_BASE_H #define TF_DIAGNOSTIC_BASE_H +/// \file tf/diagnosticBase.h #include "pxr/base/tf/callContext.h" #include "pxr/base/tf/copyOnWritePtr.h" @@ -43,67 +44,60 @@ typedef boost::any TfDiagnosticInfo; class TfDiagnosticMgr; -/*! - * \class TfDiagnosticBase DiagnosticBase.h pxr/base/tf/diagnosticBase.h - * \brief Represents the base class of an object representing a diagnostic - * message. - * \ingroup group_tf_TfError - * - * This forms the base class for specific types associated with errors, - * warnings and status messages. It associates a diagnostic code (which is an - * enum value) with the message. It can also hold on to arbitrary information - * associated with the message in a TfDiagnosticInfo. - * - * See \ref page_tf_TfError in the C++ API reference for a detailed - * example. For a description of how to post an error, warning or a - * status message see \c TF_ERROR(), \c TF_WARN and \c TF_STATUS also in the - * C++ API reference. - * - */ - +/// \class TfDiagnosticBase +/// \ingroup group_tf_TfError +/// +/// Represents the base class of an object representing a diagnostic message. +/// +/// This forms the base class for specific types associated with errors, +/// warnings and status messages. It associates a diagnostic code (which is an +/// enum value) with the message. It can also hold on to arbitrary information +/// associated with the message in a TfDiagnosticInfo. +/// +/// See \ref page_tf_TfError in the C++ API reference for a detailed example. +/// For a description of how to post an error, warning or a status message see +/// \c TF_ERROR(), \c TF_WARN and \c TF_STATUS also in the C++ API reference. +/// class TfDiagnosticBase { public: - //! Return the call context where the message was issued. + /// Return the call context where the message was issued. const TfCallContext &GetContext() const { return _context; } - //! Return the source file name that the diagnostic message was posted from. + /// Return the source file name that the diagnostic message was posted from. std::string GetSourceFileName() const { return _context.GetFile(); } - //! Return the source line number that the diagnostic message was posted from. + /// Return the source line number that the diagnostic message was posted from. size_t GetSourceLineNumber() const { return _context.GetLine(); } - //! Return the commentary string describing this diagnostic message. + /// Return the commentary string describing this diagnostic message. std::string const &GetCommentary() const { return _data->_commentary; } - //! Return the source function that the diagnostic message was posted from. + /// Return the source function that the diagnostic message was posted from. std::string GetSourceFunction() const { return ArchGetPrettierFunctionName(_context.GetFunction(), _context.GetPrettyFunction()); } - /*! - * \brief Add to the commentary string describing - * this diagnostic message. - * - * Note: each string added to the commentary is separated from - * the previous one with a newline. This means that - * you the string \c s should \e not end with a newline. Thus, - * \code - * cout << e.GetCommentary() << "\n"; - * \endcode - * always prints the entire commentary string as a newline - * separated sequence of messages. - */ + /// Add to the commentary string describing this diagnostic message. + /// + /// Note: each string added to the commentary is separated from + /// the previous one with a newline. This means that + /// you the string \c s should \e not end with a newline. Thus, + /// \code + /// cout << e.GetCommentary() << "\n"; + /// \endcode + /// always prints the entire commentary string as a newline + /// separated sequence of messages. void AugmentCommentary(const std::string& s) const { if (_data->_commentary.empty()) _data->_commentary = s; @@ -113,78 +107,70 @@ class TfDiagnosticBase { } } - //! Return the diagnostic code posted. + /// Return the diagnostic code posted. TfEnum GetDiagnosticCode() const { return _data->_code; } - /*! - * \brief Return the diagnostic code posted as a string. - * - * If the enum value posted with the message has been registered - * with \c TF_ADD_ENUM_NAME(), then \c GetDiagnosticCodeAsString() will - * return the symbolic name of the enum. - * - * If the enum has not been registered, then code of the form - * \code - * TF_ERROR(PUCE).Post("is an ugly color"); - * \endcode - * will still result in \c GetDiagnosticCodeAsString() returning the string - * "PUCE"; however, code of the form - * \code - * MyErrorCode c = PUCE; - * TF_ERROR(c).Post("is still ugly"); - * \endcode - * will result in \c GetDiagnosticCodeAsString() returning the - * (uninformative) string "c". - */ + /// Return the diagnostic code posted as a string. + /// + /// If the enum value posted with the message has been registered + /// with \c TF_ADD_ENUM_NAME(), then \c GetDiagnosticCodeAsString() will + /// return the symbolic name of the enum. + /// + /// If the enum has not been registered, then code of the form + /// \code + /// TF_ERROR(PUCE).Post("is an ugly color"); + /// \endcode + /// will still result in \c GetDiagnosticCodeAsString() returning the string + /// "PUCE"; however, code of the form + /// \code + /// MyErrorCode c = PUCE; + /// TF_ERROR(c).Post("is still ugly"); + /// \endcode + /// will result in \c GetDiagnosticCodeAsString() returning the + /// (uninformative) string "c". const std::string& GetDiagnosticCodeAsString() const { return _data->_codeString; } - /*! - * \brief Return a (possibly NULL) const pointer to the info object - * associated with this message. - * - * If this message was posted without supplying an \c info argument - * to Post(), e.g. - * \code - * TF_ERROR(SOME_CODE).Post("something went wrong"); - * \endcode - * - * then \c GetInfo() returns NULL. Otherwise, when info is supplied, - * e.g. - * \code - * T myInfo = ... - * TF_ERROR(SOME_CODE).Post("something went wrong")->SetInfo(myInfo); - * \endcode - * - * then a const pointer to a copy of myInfo in the above example is - * returned by GetInfo(). If the type T doesn't match the held - * type then GetInfo() returns NULL. - */ + /// Return a (possibly NULL) const pointer to the info object associated + /// with this message. + /// + /// If this message was posted without supplying an \c info argument to + /// Post(), e.g. + /// \code + /// TF_ERROR(SOME_CODE).Post("something went wrong"); + /// \endcode + /// + /// then \c GetInfo() returns NULL. Otherwise, when info is supplied, + /// e.g. + /// \code + /// T myInfo = ... + /// TF_ERROR(SOME_CODE).Post("something went wrong")->SetInfo(myInfo); + /// \endcode + /// + /// then a const pointer to a copy of myInfo in the above example is + /// returned by GetInfo(). If the type T doesn't match the held type + /// then GetInfo() returns NULL. template const T* GetInfo() const { return boost::any_cast(&_data->_info); } - /*! - * \brief Set the info object associated with this diagnostic message. - * See \c GetInfo() for more details. - */ + /// Set the info object associated with this diagnostic message. + /// \see GetInfo() void SetInfo(TfDiagnosticInfo any) { _data->_info = any; } - /*! - * \brief Return true if the message was posted via \c PostQuietly(). - * - * Notices sent from \c PostQuietly() are indicating that an immediate - * printout of the error is not desirable, because someone higher up on - * the stack may actually handle this error. This is rare, but it does - * happen on occasion. - */ + /// Return true if the message was posted via \c PostQuietly(). + /// + /// Notices sent from \c PostQuietly() are indicating that an immediate + /// printout of the error is not desirable, because someone higher up on + /// the stack may actually handle this error. This is rare, but it does + /// happen on occasion. bool GetQuiet() const { return _data->_quiet; } diff --git a/pxr/base/lib/tf/diagnosticHelper.h b/pxr/base/lib/tf/diagnosticHelper.h index a6c9366105..b061b29722 100644 --- a/pxr/base/lib/tf/diagnosticHelper.h +++ b/pxr/base/lib/tf/diagnosticHelper.h @@ -24,6 +24,7 @@ #ifndef TF_DIAGNOSTIC_HELPER_H #define TF_DIAGNOSTIC_HELPER_H +#include "pxr/base/tf/api.h" #include "pxr/base/tf/stringUtils.h" #include "pxr/base/arch/attributes.h" @@ -36,53 +37,53 @@ class TfCallContext; class TfEnum; class TfError; -bool +TF_API bool Tf_PostErrorHelper( const TfCallContext &context, const TfEnum &code, const std::string &msg); -bool +TF_API bool Tf_PostErrorHelper( const TfCallContext &context, const TfEnum &code, const char *fmt, ...) ARCH_PRINTF_FUNCTION(3, 4); -bool +TF_API bool Tf_PostErrorHelper( const TfCallContext &context, const TfDiagnosticInfo &info, const TfEnum &code, const std::string &msg); -bool +TF_API bool Tf_PostErrorHelper( const TfCallContext &context, const TfDiagnosticInfo &info, const TfEnum &code, const char *fmt, ...) ARCH_PRINTF_FUNCTION(4, 5); -bool +TF_API bool Tf_PostQuietlyErrorHelper( const TfCallContext &context, const TfEnum &code, const TfDiagnosticInfo &info, const std::string &msg); -bool +TF_API bool Tf_PostQuietlyErrorHelper( const TfCallContext &context, const TfEnum &code, const TfDiagnosticInfo &info, const char *fmt, ...) ARCH_PRINTF_FUNCTION(4, 5); -bool +TF_API bool Tf_PostQuietlyErrorHelper( const TfCallContext &context, const TfEnum &code, const std::string &msg); -bool +TF_API bool Tf_PostQuietlyErrorHelper( const TfCallContext &context, const TfEnum &code, @@ -90,76 +91,75 @@ Tf_PostQuietlyErrorHelper( // Helper functions for posting a warning with TF_WARN. -void +TF_API void Tf_PostWarningHelper(const TfCallContext &context, const std::string &msg); -void +TF_API void Tf_PostWarningHelper(const TfCallContext &context, const char *fmt, ...) ARCH_PRINTF_FUNCTION(2, 3); -void +TF_API void Tf_PostWarningHelper( const TfCallContext &context, const TfEnum &code, const std::string &msg); -void +TF_API void Tf_PostWarningHelper( const TfCallContext &context, const TfEnum &code, const char *fmt, ...) ARCH_PRINTF_FUNCTION(3, 4); -void +TF_API void Tf_PostWarningHelper( const TfCallContext &context, const TfDiagnosticInfo &info, const TfEnum &code, const std::string &msg); -void +TF_API void Tf_PostWarningHelper( const TfCallContext &context, const TfDiagnosticInfo &info, const TfEnum &code, const char *fmt, ...) ARCH_PRINTF_FUNCTION(4, 5); -void +TF_API void Tf_PostStatusHelper( const TfCallContext &context, const char *fmt, ...) ARCH_PRINTF_FUNCTION(2, 3); -void +TF_API void Tf_PostStatusHelper( const TfCallContext &context, const std::string &msg); -void +TF_API void Tf_PostStatusHelper( const TfCallContext &context, const TfEnum &code, const std::string &msg); -void +TF_API void Tf_PostStatusHelper( const TfCallContext &context, const TfEnum &code, const char *fmt, ...) ARCH_PRINTF_FUNCTION(3, 4); -void +TF_API void Tf_PostStatusHelper( const TfCallContext &context, const TfDiagnosticInfo &info, const TfEnum &code, const std::string &msg); -void +TF_API void Tf_PostStatusHelper( const TfCallContext &context, const TfDiagnosticInfo &info, const TfEnum &code, const char *fmt, ...) ARCH_PRINTF_FUNCTION(4, 5); - #endif // TF_DIAGNOSTIC_HELPER_H diff --git a/pxr/base/lib/tf/diagnosticLite.h b/pxr/base/lib/tf/diagnosticLite.h index f4bad22d7a..befd72ab25 100644 --- a/pxr/base/lib/tf/diagnosticLite.h +++ b/pxr/base/lib/tf/diagnosticLite.h @@ -24,9 +24,31 @@ #ifndef TF_DIAGNOSTICLITE_H #define TF_DIAGNOSTICLITE_H +/// \file tf/diagnosticLite.h +/// Stripped down version of \c diagnostic.h that doesn't define \c std::string. +/// +/// This file provides the same functionality as \c diagnostic.h, except that +/// all strings must be passed as plain \c const \c char*, and not by +/// \c std::string, and the macro \c TF_FUNCTION_NAME() is only defined by +/// \c diagnostic.h +/// +/// In particular, this header file does not include the C++ header file +/// \c < \c string \c >, making inclusion of this file a very light-weight +/// addition. Include this file, as opposed to pxr/base/tf/diagnostic.h in +/// header files that need to remain as light-weight as possible. +/// +/// These macros are safe to use in multiple threads, but errors will be +/// converted to warnings because our error handling mechanisms are not thread +/// safe. + #include "pxr/base/arch/attributes.h" +#include "pxr/base/tf/api.h" +#include "pxr/base/arch/hints.h" +#include "pxr/base/tf/callContext.h" +#include -//! Enum describing various diagnostic conditions. +/// \enum TfDiagnosticType +/// Enum describing various diagnostic conditions. enum TfDiagnosticType { TF_DIAGNOSTIC_INVALID_TYPE = 0, TF_DIAGNOSTIC_CODING_ERROR_TYPE, @@ -39,29 +61,6 @@ enum TfDiagnosticType { TF_APPLICATION_EXIT_TYPE, }; -#include "pxr/base/arch/hints.h" -#include "pxr/base/tf/callContext.h" -#include - -/*! - * \file diagnosticLite.h - * \brief Stripped down version of pxr/base/tf/diagnostic.h that doesn't define - * \c std::string - * - * This file provides the same functionality as pxr/base/tf/diagnostic.h, - * except that all strings must be passed as plain \c const \c char*, and - * not by \c std::string, and the macro \c TF_FUNCTION_NAME() is only defined - * by pxr/base/tf/diagnostic.h - * - * In particular, this header file does not include the C++ header file \c < \c - * string \c >, making inclusion of this file a very light-weight addition. - * Include this file, as opposed to pxr/base/tf/diagnostic.h in header files that - * need to remain as light-weight as possible. - * - * These macros are safe to use in multiple threads, but errors will be - * converted to warnings because our error handling mechanisms are not - * thread safe. - */ #if !defined(doxygen) @@ -119,8 +118,6 @@ enum TfDiagnosticType { TF_AXIOM(cond); \ } while (0) - - struct Tf_DiagnosticLiteHelper { Tf_DiagnosticLiteHelper(TfCallContext const &context, TfDiagnosticType type) @@ -129,10 +126,10 @@ struct Tf_DiagnosticLiteHelper { { } - void IssueError(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); - void IssueFatalError(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); - void IssueWarning(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); - void IssueStatus(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void IssueError(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void IssueFatalError(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void IssueWarning(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void IssueStatus(char const *fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); private: TfCallContext _context; diff --git a/pxr/base/lib/tf/diagnosticMgr.cpp b/pxr/base/lib/tf/diagnosticMgr.cpp index 3947dc4c4c..e5732fcb55 100644 --- a/pxr/base/lib/tf/diagnosticMgr.cpp +++ b/pxr/base/lib/tf/diagnosticMgr.cpp @@ -86,6 +86,7 @@ static void Tf_UnhandledAbort() { +#if !defined(ARCH_OS_WINDOWS) // Remove signal handler. struct sigaction act; act.sa_handler = SIG_DFL; @@ -93,6 +94,7 @@ Tf_UnhandledAbort() sigemptyset(&act.sa_mask); sigaction(SIGABRT, &act, NULL); abort(); +#endif } TF_INSTANTIATE_SINGLETON(TfDiagnosticMgr); @@ -325,7 +327,7 @@ void TfDiagnosticMgr::PostFatal(TfCallContext const &context, // Abort, but avoid the signal handler, since we've already logged the // session info in TfLogStackTrace. - Tf_UnhandledAbort(); + Tf_UnhandledAbort(); } } diff --git a/pxr/base/lib/tf/diagnosticMgr.h b/pxr/base/lib/tf/diagnosticMgr.h index 788a41d421..11c05f3168 100644 --- a/pxr/base/lib/tf/diagnosticMgr.h +++ b/pxr/base/lib/tf/diagnosticMgr.h @@ -24,6 +24,7 @@ #ifndef TF_DIAGNOSTIC_MGR_H #define TF_DIAGNOSTIC_MGR_H +/// \file tf/diagnosticMgr.h #include "pxr/base/tf/callContext.h" #include "pxr/base/tf/copyOnWritePtr.h" @@ -36,12 +37,17 @@ #include "pxr/base/tf/warning.h" #include "pxr/base/tf/weakPtr.h" #include "pxr/base/tf/enum.h" +#include "pxr/base/tf/api.h" +#include "pxr/base/arch/pragmas.h" #include "pxr/base/arch/inttypes.h" #include "pxr/base/arch/attributes.h" #include "pxr/base/arch/functionLite.h" + +ARCH_PRAGMA_SHIFT_TO_64_BITS #include +ARCH_PRAGMA_RESTORE #include #include @@ -59,11 +65,10 @@ class TfError; class TfErrorMark; template class TfSingleton; -/*! - * \class TfDiagnosticMgr - * \brief Singleton class through which all errors and diagnostics pass. - * \ingroup group_tf_Diagnostic - */ +/// \class TfDiagnosticMgr +/// \ingroup group_tf_Diagnostic +/// +/// Singleton class through which all errors and diagnostics pass. class TfDiagnosticMgr: public TfWeakBase { public: @@ -71,167 +76,162 @@ class TfDiagnosticMgr: public TfWeakBase { typedef std::list ErrorList; - /*! - * \brief Synonym for standard STL iterator to traverse the error list. - * - * The error list for a thread is an STL list. The \c ErrorIterator type is - * an STL iterator and can be used without restriction in any way that it is - * legal to use an STL iterator. - * - * Given an iterator, one accesses the error in the standard - * STL fashion: - * \code - * TfErrorMark m; - * - * ... ; - * if (!m.IsClean()) { - * TfErrorMark::Iterator i; - * for (i = m.GetBegin(); i != m.GetEnd(); ++i) { - * cout << "file = " << i->GetSourceFileName() - * << "line = " << i->GetSourceLineNumber() << "\n"; - * } - * \endcode - */ + /// Synonym for standard STL iterator to traverse the error list. + /// + /// The error list for a thread is an STL list. The \c ErrorIterator type + /// is an STL iterator and can be used without restriction in any way that + /// it is legal to use an STL iterator. + /// + /// Given an iterator, one accesses the error in the standard STL fashion: + /// \code + /// TfErrorMark m; + /// + /// ... ; + /// if (!m.IsClean()) { + /// TfErrorMark::Iterator i; + /// for (i = m.GetBegin(); i != m.GetEnd(); ++i) { + /// cout << "file = " << i->GetSourceFileName() + /// << "line = " << i->GetSourceLineNumber() << "\n"; + /// } + /// \endcode typedef ErrorList::iterator ErrorIterator; - /*! - * \brief Returns the name of the given diagnostic code. - */ + /// Returns the name of the given diagnostic code. + TF_API static std::string GetCodeName(const TfEnum &code); - /*! \class Delegate - * \brief One may set a delegate with the \c TfDiagnosticMgr which will be - * called to respond to errors and diagnostics. - */ + /// \class Delegate + /// One may set a delegate with the \c TfDiagnosticMgr which will be + /// called to respond to errors and diagnostics. class Delegate : public TfWeakBase { public: virtual ~Delegate() = 0; - //! \brief Called when a \c TfError is posted. + /// Called when a \c TfError is posted. virtual void IssueError(TfError const &err) = 0; - //! \brief Called when a \c TF_FATAL_ERROR is issued (or a failed - // \c TF_AXIOM). + /// Called when a \c TF_FATAL_ERROR is issued (or a failed + /// \c TF_AXIOM). virtual void IssueFatalError(TfCallContext const &context, std::string const &msg) = 0; - //! \brief Called when a \c TF_STATUS() is issued. - virtual void IssueStatus(TfStatus const &status) = 0; - //! \brief Called when a \c TF_WARNING() is issued. + /// Called when a \c TF_STATUS() is issued. + virtual void IssueStatus(TfStatus const &status) = 0; + /// Called when a \c TF_WARNING() is issued. virtual void IssueWarning(TfWarning const &warning) = 0; protected: - //! \brief Abort the program, but avoid the session logging mechanism. - // This is intended to be used for fatal error cases where any - // information has already been logged. + /// Abort the program, but avoid the session logging mechanism. This + /// is intended to be used for fatal error cases where any information + /// has already been logged. void _UnhandledAbort() const; }; typedef TfWeakPtr DelegateWeakPtr; - //! \brief Return the singleton instance. - static This &GetInstance() { + /// Return the singleton instance. + TF_API static This &GetInstance() { return TfSingleton::GetInstance(); } - /*! \brief Set the delegate to \a delegate. - * - * \a delegate will be called when diagnostics and errors are invoked. - * Note that only one delegate may be registered in an application. Any - * subsequent registrations will be ignored. - * - * XXX: For now, we overwrite the delegate, since some tests need their - * own delegates, yet are dependant on libDid, which creates a global delegate. - * This is bug 3237. - * SetDelegate will still print a warning when overwriting the delegate. - */ + /// Set the delegate to \a delegate. + /// + /// \a delegate will be called when diagnostics and errors are invoked. + /// Note that only one delegate may be registered in an application. Any + /// subsequent registrations will be ignored. + TF_API void SetDelegate(DelegateWeakPtr const &delegate); - /*! \brief Set whether errors, warnings and status messages should be - * printed out to the terminal. - */ + /// Set whether errors, warnings and status messages should be printed out + /// to the terminal. + TF_API void SetQuiet(bool quiet) { _quiet = quiet; } - /*! - * \brief Return an iterator to the beginning of this thread's error list. - */ + /// Return an iterator to the beginning of this thread's error list. ErrorIterator GetErrorBegin() { return _errorList.local().begin(); } - /*! - * \brief Return an iterator to the end of this thread's error list. - */ + /// Return an iterator to the end of this thread's error list. ErrorIterator GetErrorEnd() { return _errorList.local().end(); } - /* - * Deprecated. Do not use. Use EraseRange() instead. - */ + /// Remove error specified by iterator \p i. + /// \deprecated Use TfErrorMark insetad. ErrorIterator EraseError(ErrorIterator i); - /*! - * \brief Remove all the errors in [first, last) from this thread's error - * stream. This should generally not be invoked directly. Use TfErrorMark - * instead. - */ + /// Remove all the errors in [first, last) from this thread's error + /// stream. This should generally not be invoked directly. Use TfErrorMark + /// instead. + TF_API ErrorIterator EraseRange(ErrorIterator first, ErrorIterator last); - // Append an error to the list of active errors. This is generally not - // meant to be called by user code. It is public so that the system which - // translates tf errors to and from python exceptions can manage errors. + /// Append an error to the list of active errors. This is generally not + /// meant to be called by user code. It is public so that the system + /// which translates tf errors to and from python exceptions can manage + /// errors. + TF_API void AppendError(TfError const &e); - // If called in a main thread, this method will create a TfError, - // append it to the error list, and pass it to the delegate. - // - // If called in a non-main thread, this method will print the - // error to stderr and will not add it to the error list or pass - // it to the delegate. + /// If called in a main thread, this method will create a TfError, append + /// it to the error list, and pass it to the delegate. + /// + /// If called in a non-main thread, this method will print the error to + /// stderr and will not add it to the error list or pass it to the + /// delegate. + TF_API void PostError(TfEnum errorCode, const char* errorCodeString, TfCallContext const &context, const std::string& commentary, TfDiagnosticInfo info, bool quiet); - // If called in a main thread, this method will create a TfError, - // append it to the error list, and pass it to the delegate. - // - // If called in a non-main thread, this method will print the - // error to stderr and will not add it to the error list or pass - // it to the delegate. + /// If called in a main thread, this method will create a TfError, append + /// it to the error list, and pass it to the delegate. + /// + /// If called in a non-main thread, this method will print the error to + /// stderr and will not add it to the error list or pass it to the + /// delegate. + TF_API void PostError(const TfDiagnosticBase& diagnostic); - // If called in a non-main thread, this method will print the warning msg - // rather than passing it to the delegate. + /// If called in a non-main thread, this method will print the warning msg + /// rather than passing it to the delegate. + TF_API void PostWarning(TfEnum warningCode, const char *warningCodeString, TfCallContext const &context, std::string const &commentary, TfDiagnosticInfo info, bool quiet) const; - // If called in a non-main thread, this method will print the warning msg - // rather than passing it to the delegate. + /// If called in a non-main thread, this method will print the warning msg + /// rather than passing it to the delegate. + TF_API void PostWarning(const TfDiagnosticBase& diagnostic) const; - // If called in a non-main thread, this method will print the status msg - // rather than passing it to the delegate. + /// If called in a non-main thread, this method will print the status msg + /// rather than passing it to the delegate. + TF_API void PostStatus(TfEnum statusCode, const char *statusCodeString, TfCallContext const &context, std::string const &commentary, TfDiagnosticInfo info, bool quiet) const; - // If called in a non-main thread, this method will print the status msg - // rather than passing it to the delegate. + /// If called in a non-main thread, this method will print the status msg + /// rather than passing it to the delegate. + TF_API void PostStatus(const TfDiagnosticBase& diagnostic) const; - // If called in a non-main thread, this method will print the error msg - // and handle the fatal error itself rather than passing it to the delegate. + /// If called in a non-main thread, this method will print the error msg + /// and handle the fatal error itself rather than passing it to the + /// delegate. + TF_API void PostFatal(TfCallContext const &context, TfEnum statusCode, std::string const &msg) const; - // Return true if an instance of TfErrorMark exists in the curren thread of - // exection, false otherwise. - bool HasActiveErrorMark() { return _errorMarkCounts.local(); } + /// Return true if an instance of TfErrorMark exists in the curren thread + /// of exection, false otherwise. + bool HasActiveErrorMark() { return _errorMarkCounts.local() > 0; } #if !defined(doxygen) - /* - * Public, but *only* meant to be used by the TF_ERROR() macro. - */ + // + // Public, but *only* meant to be used by the TF_ERROR() macro. + // + /// \private class ErrorHelper { public: ErrorHelper(TfCallContext const &context, TfEnum errorCode, @@ -241,18 +241,23 @@ class TfDiagnosticMgr: public TfWeakBase { { } + TF_API ErrorIterator Post(const char* fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API ErrorIterator PostQuietly(const char* fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API ErrorIterator Post(const std::string& msg) const; + TF_API ErrorIterator PostWithInfo( const std::string& msg, TfDiagnosticInfo info = TfDiagnosticInfo()) const; + TF_API ErrorIterator PostQuietly(const std::string& msg, TfDiagnosticInfo info = TfDiagnosticInfo()) const; @@ -262,7 +267,6 @@ class TfDiagnosticMgr: public TfWeakBase { const char *_errorCodeString; }; - struct WarningHelper { WarningHelper(TfCallContext const &context, TfEnum warningCode, const char *warningCodeString) @@ -271,18 +275,23 @@ class TfDiagnosticMgr: public TfWeakBase { { } + TF_API void Post(const char* fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void PostQuietly(const char* fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void Post(const std::string &str) const; + TF_API void PostWithInfo( const std::string& msg, TfDiagnosticInfo info = TfDiagnosticInfo()) const; + TF_API void PostQuietly(const std::string& msg) const; private: @@ -299,18 +308,23 @@ class TfDiagnosticMgr: public TfWeakBase { { } + TF_API void Post(const char* fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void PostQuietly(const char* fmt, ...) const ARCH_PRINTF_FUNCTION(2,3); + TF_API void Post(const std::string &str) const; + TF_API void PostWithInfo( const std::string& msg, TfDiagnosticInfo info = TfDiagnosticInfo()) const; + TF_API void PostQuietly(const std::string& msg) const; private: @@ -333,7 +347,6 @@ class TfDiagnosticMgr: public TfWeakBase { TfCallContext _context; TfEnum _statusCode; }; - #endif @@ -401,4 +414,6 @@ class TfDiagnosticMgr: public TfWeakBase { friend class TfErrorMark; }; +TF_API_TEMPLATE_CLASS(TfSingleton); + #endif // TF_DIAGNOSTIC_MGR_H diff --git a/pxr/base/lib/tf/diagnosticNotice.h b/pxr/base/lib/tf/diagnosticNotice.h index 2475f12165..f063522ed1 100644 --- a/pxr/base/lib/tf/diagnosticNotice.h +++ b/pxr/base/lib/tf/diagnosticNotice.h @@ -21,11 +21,11 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -/// \file tf/DiagnosticNotice.h -/// #ifndef TF_DIAGNOSTIC_NOTICE_H #define TF_DIAGNOSTIC_NOTICE_H +/// \file tf/diagnosticNotice.h + #include "pxr/base/tf/notice.h" #include "pxr/base/tf/diagnosticBase.h" @@ -35,25 +35,30 @@ class TfDiagnosticBase; #include -/*! \class TfDiagnosticNotice - * \brief This is a wrapper class containing the actual notices - * that TfDiagnosticMgr sends. - */ +/// \class TfDiagnosticNotice +/// +/// This is a wrapper class containing the actual notices that TfDiagnosticMgr +/// sends. class TfDiagnosticNotice { public: - //! Return if warnings/error are echoed to stderr. + /// Return if warnings/error are echoed to stderr. + TF_API static bool GetStderrOutputState(); - //! Set stderr output state, returning the previous state. + /// Set stderr output state, returning the previous state. + TF_API static bool SetStderrOutputState(bool state); - /// \brief Base notification class for TfDiagnosticMgr. + /// Base notification class for TfDiagnosticMgr. class Base : public TfNotice { public: + TF_API Base(); + TF_API TfDiagnosticBase const& GetDiagnosticData() const; + TF_API ~Base(); bool IsFatal() const { @@ -75,10 +80,12 @@ class TfDiagnosticNotice { TfDiagnosticBase const* _data; }; - /// \brief Notification sent when an error is issued. + /// Notification sent when an error is issued. class IssuedError: public Base { public: + TF_API IssuedError(const TfError &error); + TF_API virtual ~IssuedError(); const TfError &GetError() const { return _error; } @@ -87,10 +94,12 @@ class TfDiagnosticNotice { const TfError &_error; }; - /// \brief Notification sent when a warning is issued. + /// Notification sent when a warning is issued. class IssuedWarning : public Base { public: + TF_API IssuedWarning(const TfWarning &warning); + TF_API virtual ~IssuedWarning(); const TfWarning &GetWarning() const { return _warning; } @@ -99,10 +108,12 @@ class TfDiagnosticNotice { const TfWarning &_warning; }; - /// \brief Notification sent when a status message is issued. + /// Notification sent when a status message is issued. class IssuedStatus : public Base { public: + TF_API IssuedStatus(const TfStatus &status); + TF_API virtual ~IssuedStatus(); const TfStatus &GetStatus() const { return _status; } @@ -111,12 +122,15 @@ class TfDiagnosticNotice { const TfStatus &_status; }; - /// \brief Notification sent when a fatal error is encountered. + /// Notification sent when a fatal error is encountered. class IssuedFatalError : public Base { public: + TF_API IssuedFatalError(const std::string &msg, const TfCallContext &context); + TF_API virtual ~IssuedFatalError(); + TF_API void SetData(TfDiagnosticBase const&); const std::string &GetMessage() const { return _msg; } diff --git a/pxr/base/lib/tf/diagnosticOverview.dox b/pxr/base/lib/tf/diagnosticOverview.dox index ab303454f6..40c8a84450 100644 --- a/pxr/base/lib/tf/diagnosticOverview.dox +++ b/pxr/base/lib/tf/diagnosticOverview.dox @@ -17,28 +17,40 @@ Describes the use of low-level programming macros to issue coding errors, runtim If you are already familiar with the TF library diagnostic facilities, here is a quick guide to picking the correct facility: - - If it is a coding bug: - - If you can work around the bug, do so, but use TF_CODING_ERROR() to inform users that the bug exists and to let the system back out changes to authored data if necessary. - - If you can't get past the bug, use TF_FATAL_ERROR() to clearly describe what's wrong. (If the bug doesn't cross API lines, or in regression tests, TF_AXIOM() is also acceptable. See \ref DiagnosticTF_FATAL_ERROR to make the distinction clear.) - - If it is not a coding bug: Use one of TF_RUNTIME_ERROR(), TF_ERROR(), TF_WARN(), TF_STATUS() to communicate what went wrong. Use TF_FATAL_ERROR() only if there is no reasonable way for the program to continue onward. +
      +
    • If it is a coding bug: +
        +
      • If you can work around the bug, do so, but use TF_CODING_ERROR() to + inform users that the bug exists and to let the system back out changes to + authored data if necessary.
      • +
      • If you can't get past the bug, use TF_FATAL_ERROR() to clearly describe + what's wrong. (If the bug doesn't cross API lines, or in regression tests, + TF_AXIOM() is also acceptable. See \ref DiagnosticTF_FATAL_ERROR to make + the distinction clear.)
      • +
      +
    • If it is not a coding bug: Use one of TF_RUNTIME_ERROR(), TF_ERROR(), + TF_WARN(), TF_STATUS() to communicate what went wrong. Use TF_FATAL_ERROR() + only if there is no reasonable way for the program to continue onward.
    • +
    \section DiagnosticIntendedUse Intended Use The intended use of the diagnostic facilities in the Tf Library is for documenting and communicating various abnormal conditions that can occur in your code. The facilities in the Tf Library, while effective, are fairly low-level. If your application or library has access to higher-level and more structured diagnostic facilities, you are urged to make use of them; if not, you should use the facilities in the Tf Library. Although these facilities are fairly simple, they are also highly configurable. The diagnostic facilities in the Tf Library are appropriate for the following tasks: - - Communicating coding errors (for example, unsatisfied program invariants) - - Communicating serious runtime errors whose cause is external (for example, a needed server can't be found, a vital configuration file is missing) - - Informing the user of problems that are not handled by other parts of the program. + +\li Communicating coding errors (for example, unsatisfied program invariants) +\li Communicating serious runtime errors whose cause is external (for example, a needed server can't be found, a vital configuration file is missing) +\li Informing the user of problems that are not handled by other parts of the program. To communicate errors, warnings, and status messages, the Tf Library first attempts to call a delegate which may be installed by a higher-level library. If there is no delegate installed, default actions include printing errors and warnings to \c stderr, printing status messages to \c stdout, printing stack traces, and terminating the program on fatal errors. The following list describes usage scenarios for the diagnostsic facilities in the Tf Libarary: - \li For non-fatal coding errors (for example, something you didn't expect, non-fatal violation of an API requirement), use TF_CODING_ERROR(). - \li For fatal coding errors (for example, an unexpected, unrecoverable coding error, violation of an API requirement which cannot be handled), use TF_FATAL_ERROR() or TF_AXIOM(). - \li For fatal external errors (for example, you wanted to execute "/bin/cat", but it doesn't exist, the database server won't respond) use TF_FATAL_ERROR(). - \li For non-fatal user errors or conditions (for example, a mesh has bad topology, but there is no facility for fixing it, a color is out of range, etc.) use TF_RUNTIME_ERROR() or to be more specific, TF_ERROR(). - \li For warnings (conditions which might possibly be an error, but are not always so) use TF_WARN(). - \li For anything else (not fatal, never an error, but useful to know) use TF_STATUS(). +\li For non-fatal coding errors (for example, something you didn't expect, non-fatal violation of an API requirement), use TF_CODING_ERROR(). +\li For fatal coding errors (for example, an unexpected, unrecoverable coding error, violation of an API requirement which cannot be handled), use TF_FATAL_ERROR() or TF_AXIOM(). +\li For fatal external errors (for example, you wanted to execute "/bin/cat", but it doesn't exist, the database server won't respond) use TF_FATAL_ERROR(). +\li For non-fatal user errors or conditions (for example, a mesh has bad topology, but there is no facility for fixing it, a color is out of range, etc.) use TF_RUNTIME_ERROR() or to be more specific, TF_ERROR(). +\li For warnings (conditions which might possibly be an error, but are not always so) use TF_WARN(). +\li For anything else (not fatal, never an error, but useful to know) use TF_STATUS(). \section DiagnosticTF_FATAL_ERROR Fatal Errors diff --git a/pxr/base/lib/tf/dl.cpp b/pxr/base/lib/tf/dl.cpp index 779f4ee164..33d49d8773 100644 --- a/pxr/base/lib/tf/dl.cpp +++ b/pxr/base/lib/tf/dl.cpp @@ -21,6 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/library.h" #include "pxr/base/tf/dl.h" #include "pxr/base/tf/debugCodes.h" #include "pxr/base/tf/registryManager.h" @@ -57,18 +58,18 @@ TfDlopen( filename.c_str(), flag); // Clear any existing error. - (void*)dlerror(); + (void*)ArchLibraryError(); // try to dlopen the dynamic library bool state = ::_opening; ::_opening = true; - void* handle = dlopen(filename.c_str(), flag); + void* handle = ArchOpenLibrary(filename.c_str(), flag); ::_opening = state; TF_DEBUG(TF_DLOPEN).Msg("TfDlopen: [opened] '%s' (handle=%p)\n", filename.c_str(), handle); - const char *err = dlerror(); + const char *err = ArchLibraryError(); if (err) { if (error) { *error = err; @@ -102,7 +103,8 @@ TfDlclose(void* handle) TF_DEBUG(TF_DLCLOSE).Msg("TfDlclose: handle = %p\n", handle); - int status = dlclose(handle); + int status = ArchLibraryClose(handle); + ::_closing = state; return status; diff --git a/pxr/base/lib/tf/dl.h b/pxr/base/lib/tf/dl.h index 8a67dc7ae9..3e4584f8e0 100644 --- a/pxr/base/lib/tf/dl.h +++ b/pxr/base/lib/tf/dl.h @@ -24,50 +24,48 @@ #ifndef TF_DL_H #define TF_DL_H +/// \file tf/dl.h +/// \ingroup group_tf_SystemsExt +/// Interface for opening code libraries. +#include "pxr/base/arch/defines.h" +#include "pxr/base/tf/api.h" -#include #include -/*! - * \file dl.h - * \ingroup group_tf_SystemsExt - * \brief Interface for opening code libraries. - */ - +/// \addtogroup group_tf_SystemsExt +///@{ - -/*! - * \brief Call dlopen() and notify lib/tf that a new module has been loaded. - * \ingroup group_tf_SystemsExt - * - * This is a wrapper around dlopen(), in the sense that this function - * simply calls dlopen(\p name, \p flag). It will additionally load - * script bindings if scripting is initialized and loading is requested. - * - * If \p error is not NULL, it will be set to the return value of - * a dlerror() call after the dlopen(), or cleared if that value is NULL. - * It is not reliable to get the error string by calling dlerror() - * after \c TfDlopen(). - * - * If you set the environment variable TF_DLOPEN_DEBUG then debug output - * will be sent to stdout on each invocation of this function. - */ - -void* TfDlopen(const std::string &filename, int flag, - std::string *error = NULL, bool loadScriptBindings = true); +/// Call \c dlopen() and notify \c lib/tf that a new module has been loaded. +/// +/// This is a wrapper around ArchOpenLibrary(), in the sense that this function +/// simply calls \c dlopen(\p name, \p flag). It will additionally load script +/// bindings if scripting is initialized and loading is requested. +/// +/// If \p error is not \c NULL, it will be set to the return value of a +/// \c dlerror() call after the \c ArchOpenLibrary(), or cleared if that value +// is \c NULL. It is not reliable to get the error string by calling +/// \c dlerror() after \c TfDlopen(). +/// +/// If you set the environment variable \c TF_DLOPEN_DEBUG then debug output +/// will be sent to \c stdout on each invocation of this function. +TF_API +void* TfDlopen(const std::string &filename, + int flag, + std::string *error = NULL, + bool loadScriptBindings = true); /*! * \brief Call dlclose(). * \ingroup group_tf_SystemsExt */ - +TF_API int TfDlclose(void* handle); +/// \private bool Tf_DlOpenIsActive(); +/// \private bool Tf_DlCloseIsActive(); - - - +///@} #endif diff --git a/pxr/base/lib/tf/enum.h b/pxr/base/lib/tf/enum.h index 2a605fe41d..d55a35fe31 100644 --- a/pxr/base/lib/tf/enum.h +++ b/pxr/base/lib/tf/enum.h @@ -24,9 +24,14 @@ #ifndef TF_ENUM_H #define TF_ENUM_H +/// \file tf/enum.h +/// \ingroup group_tf_RuntimeTyping + +#include "pxr/base/arch/defines.h" #include "pxr/base/arch/demangle.h" #include "pxr/base/tf/preprocessorUtils.h" #include "pxr/base/tf/safeTypeCompare.h" +#include "pxr/base/tf/api.h" #include #include @@ -34,119 +39,111 @@ #include #include +#include #include #include #include #include -/*! - * \file enum.h - * \ingroup group_tf_RuntimeTyping - */ - -/*! - * \class TfEnum Enum.h pxr/base/tf/enum.h - * - * \ingroup group_tf_RuntimeTyping - * - * \brief An enum class that records both enum type and enum value. - * - * \section cppcode_runtimeTyping Run-Time Typing - * - * A \c TfEnum can hold an enum variable of any enum type, while still - * being able to distinguish between various enum types. - * Here is an example: - * - * \code - * enum Monsters { SULLEY = 0, MIKE, ROZ }; - * enum Fish { NEMO = 0, FATHER, DORY }; - * - * TfEnum t1 = MIKE, - * t2 = NEMO; - * - * t1 == MIKE; // yields true - * t2 == NEMO; // yields true - * t1 == t2; // yields false - * t1 == SULLEY; // yields false - * - * t1.IsA(); // yields true - * t1.IsA(); // yields false - * \endcode - * - * Even though \c NEMO and \c SULLEY both are represented with integral - * value zero, \c t1 and \c t2 compare false. A \c TfEnum can be passed - * by value, assigned, etc. just like a regular \c Enum variable. - * A \c TfEnum can also hold a plain integer, which will compare false against - * any other enum variable. - * - * \section cppcode_enumvals Associating Names with Enumerated Values - * - * The \c TfEnum class can also be used to represent enumerated values - * as strings. This can be useful for storing enum values in files for - * later retrieval. - * - * Use the \c TF_ADD_ENUM_NAME() macro to set up and enable strings - * for the values of an enum. Once this is done, several static - * \c TfEnum methods may be used to look up names corresponding to enum - * values and vice-versa. - * - * For example, see \c TfRegistryManager to understand the use of - * the \c TF_REGISTRY_FUNCTION() macro below: - * - * \section cppcode_enumRegMacro Enum Registration Macro - * - * \code - * // header file - * // Declare an enumerated type with some values - * enum Season { - * SPRING, - * SUMMER = 3, // It's ok to have initializers - * AUTUMN, - * WINTER - * }; - * - * // source file - * #include "pxr/base/tf/registryManager.h" - * TF_REGISTRY_FUNCTION(TfEnum, Season) { - * // Register the names for the values: - * TF_ADD_ENUM_NAME(SPRING); - * TF_ADD_ENUM_NAME(SUMMER); - * TF_ADD_ENUM_NAME(AUTUMN); - * TF_ADD_ENUM_NAME(WINTER); - * } - * - * // another source file: - * - * // Look up the name for a value: - * string name1 = TfEnum::GetName(SUMMER); // Returns "SUMMER" - * string name2 = TfEnum::GetFullName(SUMMER); // Returns "Season::SUMMER" - * - * // Look up the value for a name: - * bool found; - * Season s1 = TfEnum::GetValueFromName("AUTUMN", &found); - * // Returns 4, sets found to true - * Season s2 = TfEnum::GetValueFromName("MONDAY", &found); - * // Returns -1, sets found to false - * - * // Look up a fully-qualified name. Since this is not a templated - * // function, it has to return a generic value type, so we use - * // TfEnum. - * TfEnum s3 = TfEnum::GetValueFromFullName("Season::WINTER", &found); - * // Returns 5, sets found to \c true - * \endcode - * - */ - +/// \class TfEnum +/// \ingroup group_tf_RuntimeTyping +/// +/// An enum class that records both enum type and enum value. +/// +/// \section cppcode_runtimeTyping Run-Time Typing +/// +/// A \c TfEnum can hold an enum variable of any enum type, while still +/// being able to distinguish between various enum types. +/// Here is an example: +/// +/// \code +/// enum Monsters { SULLEY = 0, MIKE, ROZ }; +/// enum Fish { NEMO = 0, FATHER, DORY }; +/// +/// TfEnum t1 = MIKE, +/// t2 = NEMO; +/// +/// t1 == MIKE; // yields true +/// t2 == NEMO; // yields true +/// t1 == t2; // yields false +/// t1 == SULLEY; // yields false +/// +/// t1.IsA(); // yields true +/// t1.IsA(); // yields false +/// \endcode +/// +/// Even though \c NEMO and \c SULLEY both are represented with integral +/// value zero, \c t1 and \c t2 compare false. A \c TfEnum can be passed +/// by value, assigned, etc. just like a regular \c Enum variable. +/// A \c TfEnum can also hold a plain integer, which will compare false against +/// any other enum variable. +/// +/// \section cppcode_enumvals Associating Names with Enumerated Values +/// +/// The \c TfEnum class can also be used to represent enumerated values +/// as strings. This can be useful for storing enum values in files for +/// later retrieval. +/// +/// Use the \c TF_ADD_ENUM_NAME() macro to set up and enable strings +/// for the values of an enum. Once this is done, several static +/// \c TfEnum methods may be used to look up names corresponding to enum +/// values and vice-versa. +/// +/// For example, see \c TfRegistryManager to understand the use of +/// the \c TF_REGISTRY_FUNCTION() macro below: +/// +/// \section cppcode_enumRegMacro Enum Registration Macro +/// +/// \code +/// // header file +/// // Declare an enumerated type with some values +/// enum Season { +/// SPRING, +/// SUMMER = 3, // It's ok to have initializers +/// AUTUMN, +/// WINTER +/// }; +/// +/// // source file +/// #include "pxr/base/tf/registryManager.h" +/// TF_REGISTRY_FUNCTION(TfEnum, Season) { +/// // Register the names for the values: +/// TF_ADD_ENUM_NAME(SPRING); +/// TF_ADD_ENUM_NAME(SUMMER); +/// TF_ADD_ENUM_NAME(AUTUMN); +/// TF_ADD_ENUM_NAME(WINTER); +/// } +/// +/// // another source file: +/// +/// // Look up the name for a value: +/// string name1 = TfEnum::GetName(SUMMER); // Returns "SUMMER" +/// string name2 = TfEnum::GetFullName(SUMMER); // Returns "Season::SUMMER" +/// +/// // Look up the value for a name: +/// bool found; +/// Season s1 = TfEnum::GetValueFromName("AUTUMN", &found); +/// // Returns 4, sets found to true +/// Season s2 = TfEnum::GetValueFromName("MONDAY", &found); +/// // Returns -1, sets found to false +/// +/// // Look up a fully-qualified name. Since this is not a templated +/// // function, it has to return a generic value type, so we use +/// // TfEnum. +/// TfEnum s3 = TfEnum::GetValueFromFullName("Season::WINTER", &found); +/// // Returns 5, sets found to \c true +/// \endcode +/// class TfEnum : boost::totally_ordered { public: - //! Default constructor assigns integer value zero. + /// Default constructor assigns integer value zero. TfEnum() : _typeInfo(&typeid(int)), _value(0) { } - //! Initializes value to enum variable \c value of enum type \c T. + /// Initializes value to enum variable \c value of enum type \c T. template TfEnum(T value, typename boost::enable_if >::type *dummy = 0) @@ -154,99 +151,92 @@ class TfEnum : boost::totally_ordered { } - /*! - * \brief Initializes value to integral value \p value with enum type \c ti. - * - * Note: this is only for use in extreme circumstances; there is no way - * for an implemenation to guarantee that \p ti is really an enum type, - * and/or that \p value is a valid value for that enum type. - */ + /// Initializes value to integral value \p value with enum type \c ti. + /// + /// \warning This is only for use in extreme circumstances; there is no + /// way for an implemenation to guarantee that \p ti is really an enum + /// type, and/or that \p value is a valid value for that enum type. TfEnum(const std::type_info& ti, int value) : _typeInfo(&ti), _value(value) { } - //! True if \c *this and \c t have both the same type and value. + /// True if \c *this and \c t have both the same type and value. bool operator==(const TfEnum& t) const { return t._value == _value and TfSafeTypeCompare(*t._typeInfo, *_typeInfo); } - /*! Less than comparison. Enum values belonging to the same type are - * ordered according to their numeric value. Enum values belonging to - * different types are ordered in a consistent but arbitrary way which may - * vary between program runs. - */ + /// Less than comparison. Enum values belonging to the same type are + /// ordered according to their numeric value. Enum values belonging to + /// different types are ordered in a consistent but arbitrary way which + /// may vary between program runs. bool operator<(const TfEnum& t) const { return _typeInfo->before(*t._typeInfo) or (not t._typeInfo->before(*_typeInfo) and _value < t._value); } - //! True if \c *this has been assigned with \c value. + /// True if \c *this has been assigned with \c value. template typename boost::enable_if, bool>::type operator==(T value) const { - return int(value) == _value and IsA(); + return int(value) == _value && IsA(); } - //! False if \c *this has been assigned with \c value. + /// False if \c *this has been assigned with \c value. template typename boost::enable_if, bool>::type operator!=(T value) const { - return int(value) != _value or not IsA(); + return int(value) != _value || !IsA(); } - //! Compare a literal enum value \a val of enum type \a T with TfEnum \a e. + /// Compare a literal enum value \a val of enum type \a T with TfEnum \a e. template friend typename boost::enable_if, bool>::type operator==(T val, TfEnum const &e) { return e == val; } - //! Compare a literal enum value \a val of enum type \a T with TfEnum \a e. + /// Compare a literal enum value \a val of enum type \a T with TfEnum \a e. template friend typename boost::enable_if, bool>::type operator!=(T val, TfEnum const &e) { return e != val; } - //! True if \c *this has been assigned any enumerated value of type \c T. + /// True if \c *this has been assigned any enumerated value of type \c T. template bool IsA() const { return TfSafeTypeCompare(*_typeInfo, typeid(T)); } - /*! - * \brief True if \c *this has been assigned any enumerated value of - * type \c T with \c typeid(T)==t. - */ + /// True if \c *this has been assigned any enumerated value of type + /// \c T with \c typeid(T)==t. bool IsA(const std::type_info& t) const { return TfSafeTypeCompare(*_typeInfo, t); } - //! Returns the type of the enum value, as an \c std::type_info. + /// Returns the type of the enum value, as an \c std::type_info. const std::type_info& GetType() const { return *_typeInfo; } - //! Returns the integral value of the enum value. + /// Returns the integral value of the enum value. const int& GetValueAsInt() const { return _value; } - /*! - * \brief Returns the enum value for the enum type \c T. - * - * NOTE: this function can cause your program to abort if not used - * properly. - * - * If it is possible that the enum value is not of type \c T, first use - * \c IsA() to test whether the enum value is of type \c T before calling - * \c GetValue(). - * - * Note that if \c IsA() succeeds, then \c GetValue() will also - * succeed. - */ + /// Returns the enum value for the enum type \c T. + /// + /// \warning This function can cause your program to abort if not used + /// properly. + /// + /// If it is possible that the enum value is not of type \c T, first use + /// \c IsA() to test whether the enum value is of type \c T before calling + /// \c GetValue(). + /// + /// Note that if \c IsA() succeeds, then \c GetValue() will also + /// succeed. template T GetValue() const { if (!IsA()) @@ -260,146 +250,120 @@ class TfEnum : boost::totally_ordered return T(_value); } - /*! - * \name Retrieving Corresponding Names and Enumerated Values - * The methods in this group can be used to retrieve corresponding - * names and values. The correspondences are set up with the \c - * TF_ADD_ENUM_NAME() macro. - */ - //@{ - - /*! - * \brief Returns the name associated with an enumerated value. - * - * If there is no such name registered, an empty string is - * returned. - */ - static std::string GetName(TfEnum val); - - /*! - * \brief Returns the fully-qualified name for an enumerated value. - * - * This returns a fully-qualified enumerated value name (e.g., - * \c "Season::WINTER") associated with the given value. If there is - * no such name registered, an empty string is returned. - */ - static std::string GetFullName(TfEnum val); - - /*! - * \brief Returns the display name for an enumerated value. - * - * This returns a user interface-suitable string for the given - * enumerated value. - */ - static std::string GetDisplayName(TfEnum val); - - /*! - * \brief Returns a vector of all the names associated with an enum type. - * - * This returns a vector of all the names associated with the enum that - * contains the type \p val. The names are not fully qualified. For - * example, \c TfEnum::GetAllNames(WINTER) would return a vector - * containing "SPRING", "SUMMER", "AUTUMN", and "WINTER". - * - * If there are no such names registered, an empty vector is - * returned. - */ + /// \name Retrieving Corresponding Names and Enumerated Values + /// + /// The methods in this group can be used to retrieve corresponding names + /// and values. The correspondences are set up with the + /// \c TF_ADD_ENUM_NAME() macro. + /// + ///@{ + + /// Returns the name associated with an enumerated value. + /// + /// If there is no such name registered, an empty string is returned. + TF_API static std::string GetName(TfEnum val); + + /// Returns the fully-qualified name for an enumerated value. + /// + /// This returns a fully-qualified enumerated value name (e.g., + /// \c "Season::WINTER") associated with the given value. If there is no + /// such name registered, an empty string is returned. + TF_API static std::string GetFullName(TfEnum val); + + /// Returns the display name for an enumerated value. + /// + /// This returns a user interface-suitable string for the given enumerated + /// value. + TF_API static std::string GetDisplayName(TfEnum val); + + /// Returns a vector of all the names associated with an enum type. + /// + /// This returns a vector of all the names associated with the enum that + /// contains the type \p val. The names are not fully qualified. For + /// example, \c TfEnum::GetAllNames(WINTER) would return a vector + /// containing "SPRING", "SUMMER", "AUTUMN", and "WINTER". + /// + /// If there are no such names registered, an empty vector is returned. static std::vector GetAllNames(TfEnum val) { return GetAllNames(val.GetType()); } - //! \overload - static std::vector GetAllNames(const std::type_info &ti); - - /*! - * \brief Returns a vector of all the names associated with an enum type. - * - * This returns a vector of all the names associated with the enum - * type \c T. The names are not fully qualified. For - * example, \c TfEnum::GetAllNames() would return a vector - * containing "SPRING", "SUMMER", "AUTUMN", and "WINTER". - * - * If there are no such names registered, an empty vector is - * returned. - */ + /// \overload + TF_API static std::vector GetAllNames(const std::type_info &ti); + + /// Returns a vector of all the names associated with an enum type. + /// + /// This returns a vector of all the names associated with the enum + /// type \c T. The names are not fully qualified. For + /// example, \c TfEnum::GetAllNames() would return a vector + /// containing "SPRING", "SUMMER", "AUTUMN", and "WINTER". + /// + /// If there are no such names registered, an empty vector is returned. template static std::vector GetAllNames() { return GetAllNames(typeid(T)); } - /*! - * \brief Returns the typeid for a given enum type name. - * - * This returns a pointer to the type_info associated with - * the enum that has the type name \c typeName. If no such - * enum is registered, returns NULL. - */ + /// Returns the typeid for a given enum type name. + /// + /// This returns a pointer to the type_info associated with the enum that + /// has the type name \c typeName. If no such enum is registered, returns + /// NULL. + TF_API static const std::type_info *GetTypeFromName(const std::string& typeName); - /*! - * \brief Returns the enumerated value for a name. - * - * If there is no such name registered, this returns -1. Since -1 - * can sometimes be a valid value, the \p foundIt flag pointer, if - * not \c NULL, is set to \c true if the name was found and \c - * false otherwise. - */ + /// Returns the enumerated value for a name. + /// + /// If there is no such name registered, this returns -1. Since -1 can + /// sometimes be a valid value, the \p foundIt flag pointer, if not \c + /// NULL, is set to \c true if the name was found and \c false otherwise. template static T GetValueFromName(const std::string &name, bool *foundIt = NULL) { TfEnum e = GetValueFromName(typeid(T), name, foundIt); return T(e.GetValueAsInt()); } - /*! - * \brief Returns the enumerated value for a name. - * - * This is a template-independent version of \c GetValueFromName(). - * - */ + /// Returns the enumerated value for a name. + /// + /// This is a template-independent version of \c GetValueFromName(). + TF_API static TfEnum GetValueFromName(const std::type_info& ti, const std::string &name, bool *foundIt = NULL); - /*! - * \brief Returns the enumerated value for a fully-qualified name. - * - * This takes a fully-qualified enumerated value name (e.g., - * \c "Season::WINTER") and returns the associated value. If there is - * no such name, this returns -1. Since -1 can sometimes be a - * valid value, the \p foundIt flag pointer, if not \c NULL, is - * set to \c true if the name was found and \c false - * otherwise. Also, since this is not a templated function, it has - * to return a generic value type, so we use \c TfEnum. - */ - static TfEnum GetValueFromFullName(const std::string &fullname, - bool *foundIt = NULL); - - /*! - * \brief Returns true if \p typeName is a known enum type. - * - * If any enum whose demangled type name is \p typeName has been - * added via \c TF_ADD_ENUM_NAME(), this function returns true. - */ + /// Returns the enumerated value for a fully-qualified name. + /// + /// This takes a fully-qualified enumerated value name (e.g., + /// \c "Season::WINTER") and returns the associated value. If there is + /// no such name, this returns -1. Since -1 can sometimes be a + /// valid value, the \p foundIt flag pointer, if not \c NULL, is + /// set to \c true if the name was found and \c false + /// otherwise. Also, since this is not a templated function, it has + /// to return a generic value type, so we use \c TfEnum. + TF_API + static TfEnum GetValueFromFullName(const std::string &fullname, + bool *foundIt = NULL); + + /// Returns true if \p typeName is a known enum type. + /// + /// If any enum whose demangled type name is \p typeName has been + /// added via \c TF_ADD_ENUM_NAME(), this function returns true. + TF_API static bool IsKnownEnumType(const std::string& typeName); - //@} + ///@} - /*! - * \brief Associates a name with an enumerated value. - * - * This method is called by the \c TF_ADD_ENUM_NAME() macro, - * and should NOT be called directly. - * - * Instead, call AddName(), which does exactly the same thing. - */ + /// Associates a name with an enumerated value. + /// + /// \warning This method is called by the \c TF_ADD_ENUM_NAME() macro, and + /// should NOT be called directly. Instead, call AddName(), which does + /// exactly the same thing. + TF_API static void _AddName(TfEnum val, const std::string &valName, const std::string &displayName=""); - /*! - * \brief Associates a name with an enumerated value. - * - * See _AddName(). - */ + /// Associates a name with an enumerated value. + /// \see _AddName(). static void AddName(TfEnum val, const std::string &valName, const std::string &displayName="") { @@ -423,7 +387,7 @@ class TfEnum : boost::totally_ordered // Internal constructor for size_t values. explicit TfEnum(size_t value) - : _typeInfo(&typeid(size_t)), _value(value) + : _typeInfo(&typeid(size_t)), _value(static_cast(value)) { } @@ -434,40 +398,35 @@ class TfEnum : boost::totally_ordered }; -//! \brief Output a TfEnum value. -// \ingroup group_tf_DebuggingOutput -std::ostream& operator<<(std::ostream& out, const TfEnum & e); - - -/*! - * \hideinitializer - * \ingroup group_tf_RuntimeTyping - * \brief Macro used to associate a name with an enumerated value. - * - * \c TF_ADD_ENUM_NAME() registers a name for an enumerated value so - * that the association can be accessed in calls to \c - * TfEnum::GetValueFromName(), \c TfEnum::GetValueFromFullName(), \c - * TfEnum::GetName(), and \c TfEnum::GetFullName(). It's first - * argument, \p VAL, - * is the symbolic name of the enumerated value or a \c TfEnum - * instance constructed from it. The name defined for the value is - * created by putting double quotes around the VAL argument. - * - * An optional second argument, \p DISPLAY, is a name to be used - * for display purposes (i.e. in a user interface). The display name - * can contain characters like spaces and punctuation, and does not - * need to be a unique string. If this argument is not specified, - * the display name will be derived from \p VAL. - * - * Only the names for which TF_ADD_ENUM_NAME() is called will be - * accessible with the name/value methods; you can hide values from - * this mechanism by not adding them. - * - * Please note that the best way to call \c TF_ADD_ENUM_NAME() - * is using the \c TfRegistryManager macro \c TF_REGISTRY_FUNCTION(). - */ - -// cpp magic for an optional second argument +/// Output a TfEnum value. +/// \ingroup group_tf_DebuggingOutput +TF_API std::ostream& operator<<(std::ostream& out, const TfEnum & e); + +/// Macro used to associate a name with an enumerated value. +/// +/// \c TF_ADD_ENUM_NAME() registers a name for an enumerated value so that the +/// association can be accessed in calls to \c TfEnum::GetValueFromName(), +/// \c TfEnum::GetValueFromFullName(), \c TfEnum::GetName(), and +/// \c TfEnum::GetFullName(). It's first argument, \p VAL, is the symbolic +/// name of the enumerated value or a \c TfEnum instance constructed from it. +/// The name defined for the value is created by putting double quotes around +/// the \p VAL argument. +/// +/// An optional second argument, \p DISPLAY, is a name to be used for display +/// purposes (i.e. in a user interface). The display name can contain +/// characters like spaces and punctuation, and does not need to be a unique +/// string. If this argument is not specified, the display name will be +/// derived from \p VAL. +/// +/// Only the names for which \c TF_ADD_ENUM_NAME() is called will be +/// accessible with the name/value methods; you can hide values from this +/// mechanism by not adding them. +/// +/// Please note that the best way to call \c TF_ADD_ENUM_NAME() is using the +/// \c TfRegistryManager macro \c TF_REGISTRY_FUNCTION(). +/// +/// \ingroup group_tf_RuntimeTyping +/// \hideinitializer #define TF_ADD_ENUM_NAME(VAL, ...) \ TfEnum::_AddName(VAL, \ BOOST_PP_STRINGIZE(VAL) \ diff --git a/pxr/base/lib/tf/envSetting.cpp b/pxr/base/lib/tf/envSetting.cpp index 5df2898509..d86331c963 100644 --- a/pxr/base/lib/tf/envSetting.cpp +++ b/pxr/base/lib/tf/envSetting.cpp @@ -21,6 +21,10 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include +#include "pxr/base/arch/env.h" +#include "pxr/base/tf/api.h" #include "pxr/base/tf/envSetting.h" #include "pxr/base/tf/registryManager.h" #include "pxr/base/tf/stl.h" @@ -31,8 +35,8 @@ #include "pxr/base/tf/instantiateSingleton.h" #include "pxr/base/tf/getenv.h" #include "pxr/base/tf/pyUtils.h" -#include -#include +#include "pxr/base/arch/fileSystem.h" +#include using std::string; @@ -44,7 +48,8 @@ class Tf_EnvSettingRegistry : boost::noncopyable { Tf_EnvSettingRegistry() { string fileName = TfGetenv("PIXAR_TF_ENV_SETTING_FILE", ""); - if (FILE* fp = fopen(fileName.c_str(), "r")) { + FILE* fp; + if (fp = ArchOpenFile(fileName.c_str(), "r")) { char buffer[1024]; bool syncPython = TfPyIsInitialized(); int lineNo = 0; @@ -64,9 +69,9 @@ class Tf_EnvSettingRegistry : boost::noncopyable { string key = TfStringTrim(string(buffer, eqPtr)); string value = TfStringTrim(string(eqPtr+1)); if (!key.empty()) { - setenv(key.c_str(), value.c_str(), 0 /* overwrite */); + ArchSetEnv(key.c_str(), value.c_str(), 0 /* overwrite */); if (syncPython) { - if (TfSafeString(getenv(key.c_str())) == value) + if (TfSafeString(ArchGetEnv(key.c_str())) == value) TfPySetenv(key, value); } } @@ -240,23 +245,25 @@ void Tf_InitializeEnvSetting(TfEnvSetting *setting) } // Explicitly instantiate for the supported types: bool, int, and string. -template void Tf_InitializeEnvSetting(TfEnvSetting *); -template void Tf_InitializeEnvSetting(TfEnvSetting *); -template void Tf_InitializeEnvSetting(TfEnvSetting *); +template void TF_API Tf_InitializeEnvSetting(TfEnvSetting *); +template void TF_API Tf_InitializeEnvSetting(TfEnvSetting *); +template void TF_API Tf_InitializeEnvSetting(TfEnvSetting *); +TF_API boost::python::object Tf_GetEnvSettingByName(string const& name) { return Tf_EnvSettingRegistry::GetInstance().LookupByName(name); } +TF_API boost::python::object Tf_GetEnvSettingDictionary() { return Tf_EnvSettingRegistry::GetInstance().GetAllEntries(); } -void Tf_InitEnvSettings() +void TF_API Tf_InitEnvSettings() { // Cause the registry to be created. Crucially, this subscribes to // Tf_EnvSettingRegistry, ensuring that all env settings are defined diff --git a/pxr/base/lib/tf/envSetting.h b/pxr/base/lib/tf/envSetting.h index 7fd15f5e4d..7e081ccabd 100644 --- a/pxr/base/lib/tf/envSetting.h +++ b/pxr/base/lib/tf/envSetting.h @@ -24,104 +24,120 @@ #ifndef TF_ENVSETTING_H #define TF_ENVSETTING_H +/// \file tf/envSetting.h +/// Environment setting variable. +/// +/// A \c TfEnvSetting is used to access an environment variable that +/// controls program execution according to the value set in the environment. +/// Currently, the legal types for T are bool, int, and string. +/// +/// The TfEnvSetting facility is used to enable new features in the code that +/// are still in "experimental" mode, and warn the user and/or QA that they +/// are pushing the edge of the envelope by setting a non-standard value for +/// these variables. Accordingly, the \c TfEnvSetting construct should be +/// used as sparingly as possible in code. +/// +/// In contrast, a variable that allows the user to customize program +/// execution but is not an in-development code path should simply use +/// TfGetenv() to access the variable. An example would be supplying a +/// variable to override a default font or fontsize, for users who don't like +/// the default program choice (and when there is no other way to set the +/// preference). +/// +/// Here is how to use the TfEnvSetting facility. +/// +/// 1. First, define your variable in a single .cpp file: +/// +/// \code +/// #include "pxr/base/tf/envSetting.h" +/// +/// TF_DEFINE_ENV_SETTING(TDS_FILE_VERSION, 12, +/// "Default file format to use"); +/// \endcode +/// +/// The first argument is the name of your variable; it is also the name for +/// the variable you can set in your shell to set the value at runtime. The +/// second argument is the default value. To create a bool variable, pass +/// either true or false. To create a string variable, pass an explicit +/// string(), i.e. +/// +/// \code +/// TF_DEFINE_ENV_SETTING(TDS_FILE_SUFFIX, string(".tid"), +/// "Default file-name suffix"); +/// \endcode +/// +/// 2. If you need to access this variable outside the .cpp file that defines +/// the variable, put the following in a common header file: +/// +/// \code +/// extern TfEnvSetting TDS_FILE_VERSION; +/// extern TfEnvSetting TDS_FILE_SUFFIX; +/// \endcode +/// +/// 3. At runtime, access your variable using TfGetEnvSetting(). For example: +/// +/// \code +/// int version = TfGetEnvSetting(TDS_FILE_VERSION); +/// string const& suffix =TfGetEnvSetting(TDS_FILE_SUFFIX); +/// \endcode +/// +/// You can also access a variable's value from Python: +/// +/// \code{.py} +/// from import import Tf +/// suffix = Tf.GetEnvSetting("TDS_FILE_SUFFIX") +/// \endcode +/// +/// \c Tf.GetEnvSetting() returns the value for the TfEnvSetting variable, or +/// None if no such variable is defined in the currently loaded C++ code. +/// +/// If a user's environment has a value for a TfEnvSetting variable that +/// differs from the default, when the program starts or the module defining +/// the TfEnvSetting variable is loaded, a warning messages is printed. +/// +/// From Python you can also access all currently defined TfEnvSetting +/// variables: +/// +/// \code{.py} +/// settingsDict = Tf.GetEnvSettingsDictionary() +/// \endcode +/// +/// The keys of the returned dictionary are the names of the environment +/// variables; the values are tuples (defaultValue, description) corresponding +/// to the second and third arguments in the TF_DEFINE_ENV_SETTING() macro. +/// +/// Additionally, at program startup time (or when lib/tf is first loaded), +/// the environment variable PIXAR_TF_ENV_SETTING_FILE is examined. If this +/// variable indicates a file that can be read, then the file is parsed, and +/// should contain lines of the form key=value. For each line read, the +/// environment variable key is set to value. For example: +/// +/// \code{.sh} +/// $ setenv PIXAR_TF_ENV_SETTING_FILE /usr/anim//admin/env-settings +/// +/// $ cat /usr/anim//admin/env-settings +/// TDS_DEF_VERSION=30 +/// TDS_BLAH= +/// TDS_LONG_STRING=i am some long string with spaces +/// \endcode +/// +/// Blank lines in the file and lines where the first character is '#' are +/// ignored. If the file itself cannot be read, no error is printed; however, +/// if the file is malformed, errors are printed to stderr. + #include "pxr/base/arch/attributes.h" #include "pxr/base/arch/hints.h" #include "pxr/base/tf/registryManager.h" #include #include - -/*! - * \class TfEnvSetting - * \brief Environment setting variable. - * - * A \c TfEnvSetting is used to access an environment variable that - * controls program execution according to the value set in the environment. - * Currently, the legal types for T are bool, int, and string. - * - * The TfEnvSetting facility is used to enable new features in the code that are - * still in "experimental" mode, and warn the user and/or QA that they are - * pushing the edge of the envelope by setting a non-standard value for these - * variables. Accordingly, the \c TfEnvSetting construct should be used as - * sparingly as possible in code. - * - * In contrast, a variable that allows the user to customize program execution - * but is not an in-development code path should simply use TfGetenv() to access - * the variable. An example would be supplying a variable to override a default - * font or fontsize, for users who don't like the default program choice (and - * when there is no other way to set the preference). - * - * Here is how to use the TfEnvSetting facility. - * - * 1. First, define your variable in a single .cpp file: - * - * #include "pxr/base/tf/envSetting.h" - * - * TF_DEFINE_ENV_SETTING(TDS_FILE_VERSION, 12, - * "Default file format to use"); - * - * The first argument is the name of your variable; it is also the name for the - * variable you can set in your shell to set the value at runtime. The second - * argument is the default value. To create a bool variable, pass either true - * or false. To create a string variable, pass an explicit string(), i.e. - * - * TF_DEFINE_ENV_SETTING(TDS_FILE_SUFFIX, string(".tid"), - * "Default file-name suffix"); - * - * 2. If you need to access this variable outside the .cpp file that defines - * the variable, put the following in a common header file: - * - * extern TfEnvSetting TDS_FILE_VERSION; - * extern TfEnvSetting TDS_FILE_SUFFIX; - * - * 3. At runtime, access your variable using TfGetEnvSetting(). For example: - * - * int version = TfGetEnvSetting(TDS_FILE_VERSION); - * string const& suffix =TfGetEnvSetting(TDS_FILE_SUFFIX); - * - * You can also access a variable's value from Python: - * - * from import import Tf - * suffix = Tf.GetEnvSetting("TDS_FILE_SUFFIX") - * - * Tf.GetEnvSetting() returns the value for the TfEnvSetting variable, or None - * if no such variable is defined in the currently loaded C++ code. - * - * If a user's environment has a value for a TfEnvSetting variable that differs - * from the default, when the program starts or the module defining the - * TfEnvSetting variable is loaded, a warning messages is printed. - * - * From Python you can also access all currently defined TfEnvSetting variables: - * - * settingsDict = Tf.GetEnvSettingsDictionary() - * - * The keys of the returned dictionary are the names of the environment - * variables; the values are tuples (defaultValue, description) corresponding to - * the second and third arguments in the TF_DEFINE_ENV_SETTING() macro. - * - * Additionally, at program startup time (or when lib/tf is first loaded), the - * environment variable PIXAR_TF_ENV_SETTING_FILE is examined. If this variable - * indicates a file that can be read, then the file is parsed, and should - * contain lines of the form key=value. For each line read, the environment - * variable key is set to value. For example: - * - * $ setenv PIXAR_TF_ENV_SETTING_FILE /usr/anim//admin/env-settings - * - * $ cat /usr/anim//admin/env-settings - * TDS_DEF_VERSION=30 - * TDS_BLAH= - * TDS_LONG_STRING=i am some long string with spaces - * - * Blank lines in the file and lines where the first character is '#' are - * ignored. If the file itself cannot be read, no error is printed; however, if - * the file is malformed, errors are printed to stderr. - */ +#include // POD, statically initialized. // -// We store the atomic_value separately and refer to it via pointer -// because we cannot use aggregate-initialization on a struct holding -// an atomic, but we can value-initialize a single std::atomic. +// We store the atomic_value separately and refer to it via pointer because we +// cannot use aggregate-initialization on a struct holding an atomic, but we +// can value-initialize a single std::atomic. template struct TfEnvSetting { @@ -130,6 +146,7 @@ struct TfEnvSetting char const * const _name; char const * const _description; }; + // Specialize for string, default is stored as char const * (pointing to a // literal). template <> @@ -144,6 +161,8 @@ struct TfEnvSetting template void Tf_InitializeEnvSetting(TfEnvSetting *); +/// Returns the value of the specified env setting, registered using +/// \c TF_DEFINE_ENV_SETTING. template inline T const & TfGetEnvSetting(TfEnvSetting& setting) { @@ -165,6 +184,11 @@ bool Tf_ChooseEnvSettingType(bool); int Tf_ChooseEnvSettingType(int); std::string Tf_ChooseEnvSettingType(char const *); +/// Define an env setting named \p envVar with default value \p defValue and a +/// descriptive string \p description. +/// \hideinitializer +class Tf_EnvSettingRegistry; + #define TF_DEFINE_ENV_SETTING(envVar, defValue, description) \ std::atomic< decltype(Tf_ChooseEnvSettingType(defValue))*> \ envVar##_value = {nullptr}; \ diff --git a/pxr/base/lib/tf/error.h b/pxr/base/lib/tf/error.h index 7af80e302e..af6e1189c4 100644 --- a/pxr/base/lib/tf/error.h +++ b/pxr/base/lib/tf/error.h @@ -24,33 +24,34 @@ #ifndef TF_ERROR_H #define TF_ERROR_H +/// \file tf/error.h + #include "pxr/base/tf/diagnosticBase.h" class TfDiagnosticMgr; -/*! - * \class TfError Error.h pxr/base/tf/error.h - * \brief Represents an object that contains error information. - * \ingroup group_tf_Diagnostic - * - * See \ref page_tf_Diagnostic in the C++ API reference for a detailed - * description of the error issuing API. For a example of how to post an - * error, see \c TF_ERROR(), also in the C++ API reference. - * - * In the Python API, you can raise several different types of errors, - * including coding errors (Tf.RaiseCodingError), run time errors - * (Tf.RaiseRuntimeError), fatal errors (Tf.Fatal). - * - */ +/// \class TfError +/// \ingroup group_tf_Diagnostic +/// +/// Represents an object that contains error information. +/// +/// See \ref page_tf_Diagnostic in the C++ API reference for a detailed +/// description of the error issuing API. For a example of how to post an +/// error, see \c TF_ERROR(), also in the C++ API reference. +/// +/// In the Python API, you can raise several different types of errors, +/// including coding errors (Tf.RaiseCodingError), run time errors +/// (Tf.RaiseRuntimeError), fatal errors (Tf.Fatal). +/// class TfError: public TfDiagnosticBase { public: - //! \brief Return the error code posted. + /// Return the error code posted. TfEnum GetErrorCode() const { return GetDiagnosticCode(); } - //! \brief Return the diagnostic code posted as a string. + /// Return the diagnostic code posted as a string. const std::string& GetErrorCodeAsString() const { return GetDiagnosticCodeAsString(); } diff --git a/pxr/base/lib/tf/errorMark.cpp b/pxr/base/lib/tf/errorMark.cpp index 03ce9793f3..a58e0b1f98 100644 --- a/pxr/base/lib/tf/errorMark.cpp +++ b/pxr/base/lib/tf/errorMark.cpp @@ -36,6 +36,7 @@ #include #include #include +#include using std::string; using std::vector; diff --git a/pxr/base/lib/tf/errorMark.h b/pxr/base/lib/tf/errorMark.h index 4102617171..2a63b08302 100644 --- a/pxr/base/lib/tf/errorMark.h +++ b/pxr/base/lib/tf/errorMark.h @@ -24,92 +24,85 @@ #ifndef TF_ERROR_MARK #define TF_ERROR_MARK +/// \file tf/errorMark.h + #include "pxr/base/tf/diagnosticMgr.h" #include "pxr/base/tf/errorTransport.h" +#include "pxr/base/tf/api.h" #include -/*! - * \class TfErrorMark - * \brief Class used to record the end of the error-list. - * \ingroup group_tf_TfError - * - * See \ref page_tf_TfError for a detailed description. - * - * A \c TfErrorMark is used as follows: - * \code - * TfErrorMark m; - * - * m.SetMark(); // (A) - * ... ; - * ... ; - * // (B) - * if (!m.IsClean()) { - * // errors occurred between (A) and (B) - * } - * \endcode - * - * Another common pattern is - * \code - * TfErrorMark m; - * if (TF_HAS_ERRORS(m, expr)) { - * // handle errors; - * } - * \endcode - */ -class TfErrorMark : boost::noncopyable +/// \class TfErrorMark +/// \ingroup group_tf_TfError +/// +/// Class used to record the end of the error-list. +/// +/// See \ref page_tf_TfError for a detailed description. +/// +/// A \c TfErrorMark is used as follows: +/// \code +/// TfErrorMark m; +/// +/// m.SetMark(); // (A) +/// ... ; +/// ... ; +/// // (B) +/// if (!m.IsClean()) { +/// // errors occurred between (A) and (B) +/// } +/// \endcode +/// +/// Another common pattern is +/// \code +/// TfErrorMark m; +/// if (TF_HAS_ERRORS(m, expr)) { +/// // handle errors; +/// } +/// \endcode +/// +class TF_API TfErrorMark : boost::noncopyable { public: typedef TfDiagnosticMgr::ErrorIterator Iterator; - /*! - * \brief Default constructor. - * - * The default constructor automatically calls \c SetMark() at - * the point of declaration. - */ + /// Default constructor. + /// + /// The default constructor automatically calls \c SetMark() at the point + /// of declaration. TfErrorMark(); - /*! - * \brief Destroy this ErrorMark. - * - * If this is the last ErrorMark on this thread of execution and there are - * pending errors, this will report them via the diagnostic delegate (if one - * is instanlled) otherwise by printing to stderr. - */ + /// Destroy this ErrorMark. + /// + /// If this is the last ErrorMark on this thread of execution and there + /// are pending errors, this will report them via the diagnostic delegate + /// (if one is instanlled) otherwise by printing to stderr. ~TfErrorMark(); - /*! - * \brief Record future errors. - * - * \c SetMark() arranges to record future errors in \c *this. - */ + /// Record future errors. + /// + /// \c SetMark() arranges to record future errors in \c *this. inline void SetMark() { _mark = TfDiagnosticMgr::GetInstance()._nextSerial; } - /*! - * \brief Return true if no new errors were posted in this thread since the - * last call to \c SetMark(), false otherwise. - * - * When no threads are issuing errors the cost of this function is an atomic - * integer read and comparison. Otherwise thread-specific data is accessed - * to make the determination. Thus, this function is fast when diagnostics - * are not being issued. - */ + /// Return true if no new errors were posted in this thread since the last + /// call to \c SetMark(), false otherwise. + /// + /// When no threads are issuing errors the cost of this function is an + /// atomic integer read and comparison. Otherwise thread-specific data is + /// accessed to make the determination. Thus, this function is fast when + /// diagnostics are not being issued. inline bool IsClean() const { TfDiagnosticMgr &mgr = TfDiagnosticMgr::GetInstance(); return _mark >= mgr._nextSerial or _IsCleanImpl(mgr); } - /*! - * \brief Remove all errors in this mark from the error system. Return true - * if any errors were cleared, false if there were no errors in this mark. - * - * Clear all errors contained in this mark from the error system. - * Subsequently, these errors will be considered handled. - */ + /// Remove all errors in this mark from the error system. Return true if + /// any errors were cleared, false if there were no errors in this mark. + /// + /// Clear all errors contained in this mark from the error system. + /// Subsequently, these errors will be considered handled. inline bool Clear() const { TfDiagnosticMgr &mgr = TfDiagnosticMgr::GetInstance(); auto b = GetBegin(), e = mgr.GetErrorEnd(); @@ -120,60 +113,52 @@ class TfErrorMark : boost::noncopyable return false; } - /*! - * \brief Remove all errors in this mark fom the error system and return - * them in a TfErrorTransport. - * - * This can be used to transfer errors from one thread to another. See - * TfErrorTransport for more information. As with Clear(), all the removed - * errors are considered handled for this thread. See also TransportTo(). - */ + /// Remove all errors in this mark fom the error system and return them in + /// a TfErrorTransport. + /// + /// This can be used to transfer errors from one thread to another. See + /// TfErrorTransport for more information. As with Clear(), all the + /// removed errors are considered handled for this thread. See also + /// TransportTo(). inline TfErrorTransport Transport() const { TfDiagnosticMgr &mgr = TfDiagnosticMgr::GetInstance(); return TfErrorTransport(mgr._errorList.local(), GetBegin(), mgr.GetErrorEnd()); } - /*! - * \brief Remove all errors in this mark fom the error system and return - * them in a TfErrorTransport. - * - * This is a variant of Transport(). Instead of returning a new - * TfErrorTransport object it fills an existing one. - */ + /// Remove all errors in this mark fom the error system and return them in + /// a TfErrorTransport. + /// + /// This is a variant of Transport(). Instead of returning a new + /// TfErrorTransport object it fills an existing one. inline void TransportTo(TfErrorTransport &dest) const { Transport().swap(dest); } - /*! - * \brief Return an iterator to the first error added to the error list - * after \c SetMark(). - * - * If there are no errors on the error list that were not already - * present when \c SetMark() was called, the iterator returned - * is equal to the iterator returned by \c TfDiagnosticMgr::GetErrorEnd(). - * Otherwise, the iterator points to the earliest error added to the - * list since \c SetMark() was called. - * - * This function takes O(n) time where n is the number of errors - * from the end of the list to the mark i.e. \c GetMark() walks - * the list from the end until it finds the mark and then returns - * an iterator to that spot. - * - * If \c nErrors is non-NULL, then \c *nErrors is set to the number - * of errors between the returned iterator and the end of the list. - */ + /// Return an iterator to the first error added to the error list after + /// \c SetMark(). + /// + /// If there are no errors on the error list that were not already present + /// when \c SetMark() was called, the iterator returned is equal to the + /// iterator returned by \c TfDiagnosticMgr::GetErrorEnd(). Otherwise, the + /// iterator points to the earliest error added to the list since + /// \c SetMark() was called. + /// + /// This function takes O(n) time where n is the number of errors from the + /// end of the list to the mark i.e. \c GetMark() walks the list from the + /// end until it finds the mark and then returns an iterator to that spot. + /// + /// If \c nErrors is non-NULL, then \c *nErrors is set to the number of + /// errors between the returned iterator and the end of the list. Iterator GetBegin(size_t *nErrors = 0) const { return TfDiagnosticMgr::GetInstance()._GetErrorMarkBegin(_mark, nErrors); } - /*! - * \brief Return an iterator past the last error in the error system. - * - * This iterator is always equivalend to the iterator returned by \c - * TfDiagnosticMgr::GetErrorEnd(). - */ + /// Return an iterator past the last error in the error system. + /// + /// This iterator is always equivalend to the iterator returned by \c + /// TfDiagnosticMgr::GetErrorEnd(). Iterator GetEnd() const { return TfDiagnosticMgr::GetInstance().GetErrorEnd(); } @@ -191,33 +176,32 @@ class TfErrorMark : boost::noncopyable }; -/*! - * \ingroup group_tf_TfError - * \hideinitializer - * \brief Convenience macro to check if errors occurred. - * - * This macro is equivalent to - * \code - * (marker.SetMark(), (expr), !marker.IsClean()) - * \endcode - * - * which enables it to be used as an expression: - * \code - * if (TF_HAS_ERRORS(m, expr)) - * // cope! - * \endcode - */ +/// Convenience macro to check if errors occurred. +/// +/// This macro is equivalent to +/// \code +/// (marker.SetMark(), (expr), !marker.IsClean()) +/// \endcode +/// +/// which enables it to be used as an expression: +/// \code +/// if (TF_HAS_ERRORS(m, expr)) +/// // cope! +/// \endcode +/// +/// \ingroup group_tf_TfError +/// \hideinitializer #define TF_HAS_ERRORS(marker, expr) \ (marker.SetMark(), (expr), !marker.IsClean()) -/*! - * \ingroup group_tf_TfError - * \brief Report current TfErrorMark instances and the stack traces that created - * them to stdout for debugging purposes. - * - * To call this function, set _enableTfErrorMarkStackTraces in errorMark.cpp and - * enable the TF_ERROR_MARK_TRACKING TfDebug code. - */ +/// Report current TfErrorMark instances and the stack traces that created +/// them to stdout for debugging purposes. +/// +/// To call this function, set _enableTfErrorMarkStackTraces in errorMark.cpp +/// and enable the TF_ERROR_MARK_TRACKING TfDebug code. +/// +/// \ingroup group_tf_TfError +TF_API void TfReportActiveErrorMarks(); #endif // TF_ERROR_MARK diff --git a/pxr/base/lib/tf/errorTransport.h b/pxr/base/lib/tf/errorTransport.h index 6093b715d0..5eee535105 100644 --- a/pxr/base/lib/tf/errorTransport.h +++ b/pxr/base/lib/tf/errorTransport.h @@ -24,49 +24,44 @@ #ifndef TF_ERROR_TRANSPORT #define TF_ERROR_TRANSPORT +/// \file tf/errorTransport.h + #include "pxr/base/tf/diagnosticMgr.h" #include "pxr/base/arch/hints.h" +#include "pxr/base/tf/api.h" -/*! - * \class TfErrorTransport - * \brief A facility for transporting errors from thread to thread. - * - * Typical use is to create a TfErrorMark in the thread that is the error source - * (e.g. the child thread), then call TfErrorMark::Transport() or - * TfErrorMark::TransportTo() to lift generated errors out into a - * TfErrorTransport object. Later the thread that wants to sink those errors - * (e.g. the parent thread) invokes TfErrorTransport::Post() to post all - * contained errors to its own thread's error list. - */ -struct TfErrorTransport +/// \class TfErrorTransport +/// +/// A facility for transporting errors from thread to thread. +/// +/// Typical use is to create a TfErrorMark in the thread that is the error +/// source (e.g. the child thread), then call TfErrorMark::Transport() or +/// TfErrorMark::TransportTo() to lift generated errors out into a +/// TfErrorTransport object. Later the thread that wants to sink those errors +/// (e.g. the parent thread) invokes TfErrorTransport::Post() to post all +/// contained errors to its own thread's error list. +class TfErrorTransport { +public: typedef TfDiagnosticMgr::ErrorList ErrorList; - /*! - * \brief Construct an empty TfErrorTransport. - */ + /// Construct an empty TfErrorTransport. TfErrorTransport() {} - /*! - * \brief Post all contained errors to the current thread's error list, - * leaving this TfErrorTransport empty. - */ + /// Post all contained errors to the current thread's error list, leaving + /// this TfErrorTransport empty. void Post() { if (ARCH_UNLIKELY(not IsEmpty())) _PostImpl(); } - /*! - * \brief Return true if this TfErrorTransport contains no errors, false - * otherwise. - */ + /// Return true if this TfErrorTransport contains no errors, false + /// otherwise. bool IsEmpty() const { return _errorList.empty(); } - /*! - * \brief Swap this TfErrorTransport's content with \p other. This provides - * a lightweight way to move the contents of one TfErrorTransport to - * another. - */ + /// Swap this TfErrorTransport's content with \p other. This provides a + /// lightweight way to move the contents of one TfErrorTransport to + /// another. void swap(TfErrorTransport &other) { _errorList.swap(other._errorList); } @@ -80,7 +75,7 @@ struct TfErrorTransport _errorList.splice(_errorList.begin(), src, first, last); } - void _PostImpl(); + void TF_API _PostImpl(); ErrorList _errorList; }; diff --git a/pxr/base/lib/tf/executeAtStartup.h b/pxr/base/lib/tf/executeAtStartup.h index 62579e7821..f29de3768d 100644 --- a/pxr/base/lib/tf/executeAtStartup.h +++ b/pxr/base/lib/tf/executeAtStartup.h @@ -32,85 +32,74 @@ #define TF_EXECUTEATSTARTUP_H +/// \file tf/executeAtStartup.h +/// \ingroup group_tf_Initialization +/// Construct for executing arbitrary code at program start time. - -/*! - * \file executeAtStartup.h - * \brief Construct for executing arbitrary code at program start time. - * \ingroup group_tf_Initialization - */ - -/*! - * \hideinitializer - * \brief Construct for executing arbitrary code at program start time. - * \ingroup group_tf_Initialization - * - * This macro has been deprecated. Almost all need for this functionality - * has been subsumed by \c TfRegistryManager; most typically, if you - * were using this function to call \c TF_ADD_ENUM_NAME(), see \c TfEnum - * for the proper way to do this. - * - * If you think you still need to use this function, please ask for some - * consultation first, and then use it only if no other solution meets - * your needs. - * -*/ - -/* no! - * It is often convenient to populate data registries by writing code - * that automatically executes at program start time, without being - * directly invoked. This is useful because it allows the mere linking - * in of libraries to advertise their facilities. To aid in this - * pattern, the following macro allows code to be executed - * automatically at program start time. - * - * Here is an example of use: - * - * \code - * #include "pxr/base/tf/executeAtStartup.h" - * - * class MyWidget { - * ... - * }; - * - * TF_EXECUTE_AT_STARTUP() - * { - * cout << "Debugging msg: executing MyWidget stuff...\n"; - * UicRegisterWidget("some info", "more stuf"); - * } - * - * MyWidget::MyWidget() - * { - * ... - * } - * \endcode - * - * When the program begins, the code within the body of the \c - * TF_EXECUTE_AT_STARTUP() construct will be executed. For code that - * is linked into the program, program start time is (hopefully!) - * sometime before main. Program start time for a dynamically loaded - * DSO however is when the DSO is actually opened by the running - * program. - * - * The \c TF_EXECUTE_AT_STARTUP() macro can be used once per .cpp - * file. Attempts to use this macro twice in the same .cpp file - * result in a compile error. Do \e NOT use this macro in a header - * file. - * - * \c TF_EXECUTE_AT_STARTUP() is meant to look like a function - * definition, except that no return type is specified. Any code that - * is legal to put in a function can occur in the body (i.e. between - * the braces). - * - * \note - * This facility should only be used for anonymous - * execution, i.e. for cases when, outside the given file, no one is - * necessarily aware that the code exists. If there is a way to directly - * invoke the startup-code, and this facility is being used merely to - * have it automatically happen before main(), you should not be using - * this construct. See \ref page_tf_Initialization for further discussion. - */ - +/// Construct for executing arbitrary code at program start time. +/// +/// It is often convenient to populate data registries by writing code +/// that automatically executes at program start time, without being +/// directly invoked. This is useful because it allows the mere linking +/// in of libraries to advertise their facilities. To aid in this +/// pattern, the following macro allows code to be executed +/// automatically at program start time. +/// +/// Here is an example of use: +/// +/// \code +/// #include "pxr/base/tf/executeAtStartup.h" +/// +/// class MyWidget { +/// ... +/// }; +/// +/// TF_EXECUTE_AT_STARTUP() +/// { +/// cout << "Debugging msg: executing MyWidget stuff...\n"; +/// UicRegisterWidget("some info", "more stuf"); +/// } +/// +/// MyWidget::MyWidget() +/// { +/// ... +/// } +/// \endcode +/// +/// When the program begins, the code within the body of the \c +/// TF_EXECUTE_AT_STARTUP() construct will be executed. For code that +/// is linked into the program, program start time is (hopefully!) +/// sometime before main. Program start time for a dynamically loaded +/// DSO however is when the DSO is actually opened by the running +/// program. +/// +/// The \c TF_EXECUTE_AT_STARTUP() macro can be used once per .cpp +/// file. Attempts to use this macro twice in the same .cpp file +/// result in a compile error. Do \e NOT use this macro in a header +/// file. +/// +/// \c TF_EXECUTE_AT_STARTUP() is meant to look like a function +/// definition, except that no return type is specified. Any code that +/// is legal to put in a function can occur in the body (i.e. between +/// the braces). +/// +/// \note +/// This facility should only be used for anonymous +/// execution, i.e. for cases when, outside the given file, no one is +/// necessarily aware that the code exists. If there is a way to directly +/// invoke the startup-code, and this facility is being used merely to +/// have it automatically happen before main(), you should not be using +/// this construct. See \ref page_tf_Initialization for further discussion. +/// +/// \deprecated This macro has been deprecated. Almost all need for this +/// functionality has been subsumed by \c TfRegistryManager; most typically, if +/// you were using this function to call \c TF_ADD_ENUM_NAME(), see \c TfEnum +/// for the proper way to do this. If you think you still need to use this +/// function, please ask for some consultation first, and then use it only if +/// no other solution meets your needs. +/// +/// \ingroup group_tf_Initialization +/// \hideinitializer #define TF_EXECUTE_AT_STARTUP() \ static void Tf_ExecuteAtStartupFunction(int); \ static int Tf_ExecuteAtStartupObject = \ diff --git a/pxr/base/lib/tf/executeAtUnload.h b/pxr/base/lib/tf/executeAtUnload.h index 0e3c2fb517..34b358657f 100644 --- a/pxr/base/lib/tf/executeAtUnload.h +++ b/pxr/base/lib/tf/executeAtUnload.h @@ -26,27 +26,20 @@ * Complain if we see this header twice through. */ -/*! - * \file executeAtUnload.h - * \ingroup group_tf_Initialization - */ - #ifdef TF_EXECUTEATUNLOAD_H #error This file should only be included once in any given source (.cpp) file. #endif #define TF_EXECUTEATUNLOAD_H +/// \file tf/executeAtUnload.h +/// \ingroup group_tf_Initialization +/// Construct for executing arbitrary code on TfDlClose. #include "pxr/base/tf/dl.h" - - -/* - * All this structure does is execute a function at destruction time, - * if destruction occurs in the call-chain of TfDlclose(). - */ - +// All this structure does is execute a function at destruction time, +// if destruction occurs in the call-chain of TfDlclose(). class Tf_DestructorObject { public: Tf_DestructorObject(void (*functionPtr)()) @@ -62,60 +55,54 @@ class Tf_DestructorObject { void (*_functionPtr)(); }; -/*! - * \hideinitializer - * \brief Construct for executing arbitrary code at program start time. - * \ingroup group_tf_Initialization - * - * It is sometimes important for dynamically loaded modules - * (i.e. plugins) to execute "clean up" code upon unload. This macro - * allows one to specify code to be executed each time a dynamically - * loaded module is unloaded. In particular, if the module is reloaded - * and then again unloaded, the clean-up code is again run. - * - * Note that "unload time" differs from "exit time". The clean-up code is not - * run when the program exits, because modules are not unloaded on exit. - * - * Finally, this facility assumes that the dynamically loaded module was unloaded - * by a call to \c TfDlclose(), rather than directly by a call to \c dlclose(). - * - * Here is an example of use: - * - * \code - * #include "pxr/base/tf/executeAtUnload.h" - * #include "pxr/base/tf/instantiateSingleton.h" - * - * class FileCache { - * ... - * }; - * TF_INSTANTIATE_SINGLETON(FileCache); - * - * TF_EXECUTE_AT_UNLOAD() - * { - * TfSingleton::DeleteInstance(); - * } - * - * \endcode - * - * If a singleton intance of \c FileCache was ever created, then at module - * unload time, it will be destroyed. - * - * The \c TF_EXECUTE_AT_UNLOAD() macro can be used once per .cpp file. - * Attempts to use this macro twice in the same .cpp file result in a - * compile error. Do \e NOT use this macro in a header file. - * - * \c TF_EXECUTE_AT_UNLOAD() is meant to look like a function - * definition, except that no return type is specified. Any code that - * is legal to put in a function can occur in the body (i.e. between - * the braces). - */ - +/// Construct for executing arbitrary code on \c TfDlClose. +/// +/// It is sometimes important for dynamically loaded modules (i.e. plugins) to +/// execute "clean up" code upon unload. This macro allows one to specify +/// code to be executed each time a dynamically loaded module is unloaded. In +/// particular, if the module is reloaded and then again unloaded, the +/// clean-up code is again run. +/// +/// Note that "unload time" differs from "exit time". The clean-up code is +/// not run when the program exits, because modules are not unloaded on exit. +/// +/// Finally, this facility assumes that the dynamically loaded module was +/// unloaded by a call to \c TfDlclose(), rather than directly by a call to \c +/// dlclose(). +/// +/// Here is an example of use: +/// +/// \code +/// #include "pxr/base/tf/executeAtUnload.h" +/// #include "pxr/base/tf/instantiateSingleton.h" +/// +/// class FileCache { +/// ... +/// }; +/// TF_INSTANTIATE_SINGLETON(FileCache); +/// +/// TF_EXECUTE_AT_UNLOAD() +/// { +/// TfSingleton::DeleteInstance(); +/// } +/// \endcode +/// +/// If a singleton intance of \c FileCache was ever created, then at module +/// unload time, it will be destroyed. +/// +/// The \c TF_EXECUTE_AT_UNLOAD() macro can be used once per .cpp file. +/// Attempts to use this macro twice in the same .cpp file result in a compile +/// error. Do \e NOT use this macro in a header file. +/// +/// \c TF_EXECUTE_AT_UNLOAD() is meant to look like a function definition, +/// except that no return type is specified. Any code that is legal to put in +/// a function can occur in the body (i.e. between the braces). +/// +/// \ingroup group_tf_Initialization +/// \hideinitializer #define TF_EXECUTE_AT_UNLOAD() \ static void Tf__LocalUnloadFunction(); \ static Tf_DestructorObject \ tf__localUnloadFunctionObject(Tf__LocalUnloadFunction); \ static void Tf__LocalUnloadFunction() - - - diff --git a/pxr/base/lib/tf/expiryNotifier.h b/pxr/base/lib/tf/expiryNotifier.h index 3c76b018f3..b833794193 100644 --- a/pxr/base/lib/tf/expiryNotifier.h +++ b/pxr/base/lib/tf/expiryNotifier.h @@ -24,42 +24,43 @@ #ifndef TF_EXPIRYNOTIFIER_H #define TF_EXPIRYNOTIFIER_H -#include "pxr/base/arch/hints.h" +/// \file tf/expiryNotifier.h -/*! - * \brief Set the extra notifier function. - * - * Objects derived from \c TfWeakBase can request that extra notification be - * performed when they expire. Objects that do not request extra - * notification do not suffer any performance penalty when they expire, - * while objects that request the notification will have the extra notifier - * function run on them, with the address returned by \c - * TfWeakPtr::GetUniqueIdentifier() passed to the notifier function. - * - * An object requests extra notification be performed by calling \c - * wp.RequestExtraNotification() where \c wp is a \c TfWeakPtr pointing to - * the object in question. - * - * This functions sets the extra notifier function to \p func. At present, - * this notifier is intended to be used only by the scripting system to - * inform the system that a particular object has expired and scripting - * resources devoted to that object can be discarded. Accordingly, if \p - * func is non-NULL and a previous non-NULL notifier function has been set, - * a fatal error is issued. - */ +#include "pxr/base/arch/hints.h" +#include "pxr/base/tf/api.h" +/// \class Tf_ExpiryNotifier +/// +/// Set the extra notifier function. +/// +/// Objects derived from \c TfWeakBase can request that extra notification be +/// performed when they expire. Objects that do not request extra +/// notification do not suffer any performance penalty when they expire, while +/// objects that request the notification will have the extra notifier +/// function run on them, with the address returned by \c +/// TfWeakPtr::GetUniqueIdentifier() passed to the notifier function. +/// +/// An object requests extra notification be performed by calling \c +/// wp.RequestExtraNotification() where \c wp is a \c TfWeakPtr pointing to +/// the object in question. +/// +/// This functions sets the extra notifier function to \p func. At present, +/// this notifier is intended to be used only by the scripting system to +/// inform the system that a particular object has expired and scripting +/// resources devoted to that object can be discarded. Accordingly, if +/// \p func is non-NULL and a previous non-NULL notifier function has been +/// set, a fatal error is issued. class Tf_ExpiryNotifier { public: - static void Invoke(void const *p); - static void SetNotifier(void (*func)(void const *)); + TF_API static void Invoke(void const *p); + TF_API static void SetNotifier(void (*func)(void const *)); - static void Invoke2(void const *p); - static void SetNotifier2(void (*func)(void const *)); + TF_API static void Invoke2(void const *p); + TF_API static void SetNotifier2(void (*func)(void const *)); private: static void (*_func)(void const *); static void (*_func2)(void const *); }; - #endif diff --git a/pxr/base/lib/tf/fileUtils.cpp b/pxr/base/lib/tf/fileUtils.cpp index 12aa83f692..e7d9cf8974 100644 --- a/pxr/base/lib/tf/fileUtils.cpp +++ b/pxr/base/lib/tf/fileUtils.cpp @@ -27,8 +27,10 @@ #include "pxr/base/tf/staticData.h" #include "pxr/base/tf/stringUtils.h" #include "pxr/base/tf/iterator.h" +#include "pxr/base/arch/defines.h" #include "pxr/base/arch/fileSystem.h" #include "pxr/base/arch/systemInfo.h" +#include "pxr/base/arch/errno.h" #include #include @@ -42,15 +44,22 @@ #include #include #include -#include #include #include +#include +#if !defined(ARCH_OS_WINDOWS) +#include #include #include #include -#include #include - +#else +#include +#include +#include +#include +#include +#endif using std::set; using std::string; using std::vector; @@ -67,9 +76,16 @@ Tf_Stat(string const& path, bool resolveSymlinks, struct stat* st = 0) st = &unused; } +#if defined(ARCH_OS_WINDOWS) + if (resolveSymlinks) { + printf("Tf_IsStat: symlink resolving not yet implemented for windows\n"); + } + return stat(path.c_str(), st) == 0; +#else int result = resolveSymlinks ? stat(path.c_str(), st) : lstat(path.c_str(), st); - return result == 0; + return result == 0; +#endif } bool @@ -81,30 +97,46 @@ TfPathExists(string const& path, bool resolveSymlinks) bool TfIsDir(string const& path, bool resolveSymlinks) { +#if defined (ARCH_OS_WINDOWS) + DWORD attribs = GetFileAttributes(path.c_str()); + + return (attribs != INVALID_FILE_ATTRIBUTES && + (attribs & FILE_ATTRIBUTE_DIRECTORY)); +#else struct stat st; if (Tf_Stat(path, resolveSymlinks, &st)) { return S_ISDIR(st.st_mode); } return false; +#endif } bool TfIsFile(string const& path, bool resolveSymlinks) { +#if defined (ARCH_OS_WINDOWS) + DWORD attribs = GetFileAttributes(path.c_str()); + + return (attribs != INVALID_FILE_ATTRIBUTES && + !(attribs & FILE_ATTRIBUTE_DIRECTORY)); +#else struct stat st; if (Tf_Stat(path, resolveSymlinks, &st)) { return S_ISREG(st.st_mode); } return false; +#endif } bool TfIsLink(string const& path) { +#if !defined(ARCH_OS_WINDOWS) struct stat st; if (Tf_Stat(path, /* resolveSymlinks */ false, &st)) { return S_ISLNK(st.st_mode); } +#endif return false; } @@ -123,7 +155,9 @@ TfIsDirEmpty(string const& path) { if (not TfIsDir(path)) return false; - +#if defined(ARCH_OS_WINDOWS) + return PathIsDirectoryEmpty(path.c_str()) == TRUE; +#else if (DIR *dirp = opendir(path.c_str())) { struct dirent *dent; @@ -140,18 +174,25 @@ TfIsDirEmpty(string const& path) return true; } return false; +#endif } bool TfSymlink(string const& src, string const& dst) { +#if defined(ARCH_OS_WINDOWS) + return ::CreateSymbolicLink(src.c_str(), dst.c_str(), + TfIsDir(src) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) + ? true : false; +#else return (symlink(src.c_str(), dst.c_str()) != -1); +#endif } bool TfDeleteFile(std::string const& path) { - if (unlink(path.c_str()) != 0) { + if (ArchUnlinkFile(path.c_str()) != 0) { TF_RUNTIME_ERROR("Failed to delete '%s'", path.c_str()); return false; } @@ -161,16 +202,24 @@ TfDeleteFile(std::string const& path) bool TfMakeDir(string const& path, int mode) { +#if defined(ARCH_OS_WINDOWS) + return CreateDirectory(path.c_str(), nullptr) == TRUE; +#else // Default mode is 0777 if (mode == -1) mode = S_IRWXU|S_IRWXG|S_IRWXO; return (mkdir(path.c_str(), mode) != -1); +#endif } static bool Tf_MakeDirsRec(string const& path, int mode) { +#if defined(ARCH_OS_WINDOWS) + printf("Tf_MakeDirsRec not yet implemented for Windows.\n"); + return false; +#else string head = TfStringTrimRight(TfGetPathName(path), "/"); if (head.empty()) { @@ -199,6 +248,7 @@ Tf_MakeDirsRec(string const& path, int mode) } return TfIsDir(path) ? true : TfMakeDir(path, mode); +#endif } bool @@ -218,6 +268,46 @@ TfReadDir( vector* symlinknames, string *errMsg) { +#if defined(ARCH_OS_WINDOWS) + char szPath[MAX_PATH]; + WIN32_FIND_DATA fdFile; + HANDLE hFind = NULL; + + PathCombine(szPath, dirPath.c_str(), "*.*"); + + if((hFind = FindFirstFile(szPath, &fdFile)) == INVALID_HANDLE_VALUE) + { + if (errMsg) { + *errMsg = TfStringPrintf("Path not found: %s", szPath); + } + return false; + } + else + { + do + { + if(strcmp(fdFile.cFileName, ".") != 0 + && strcmp(fdFile.cFileName, "..") != 0) + { + if(fdFile.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY) + { + if (dirnames) + dirnames->push_back(fdFile.cFileName); + } + else + { + if (filenames) + filenames->push_back(fdFile.cFileName); + } + } + } + while (FindNextFile(hFind, &fdFile)); + + FindClose(hFind); + + return true; + } +#else DIR *dir; struct dirent entry; struct dirent *result; @@ -225,7 +315,7 @@ TfReadDir( if ((dir = opendir(dirPath.c_str())) == NULL) { if (errMsg) { - *errMsg = TfStringPrintf("opendir failed: %s", strerror(errno)); + *errMsg = TfStringPrintf("opendir failed: %s", ArchStrerror(errno).c_str()); } return false; } @@ -276,7 +366,7 @@ TfReadDir( } closedir(dir); - +#endif return true; } @@ -334,6 +424,10 @@ Tf_WalkDirsRec( if (not TF_VERIFY(linkTargets)) return false; +#if defined(ARCH_OS_WINDOWS) + printf("Tf_WalkDirsRec not yet implemented on Windows.\n"); + return false; +#else vector dirnames, filenames, symlinknames; Tf_ReadDir(dirpath, onError, &dirnames, &filenames, &symlinknames); @@ -375,6 +469,7 @@ Tf_WalkDirsRec( return false; return true; +#endif } void @@ -410,24 +505,30 @@ Tf_RmTree(string const& dirpath, vector::const_iterator it; for (it = filenames.begin(); it != filenames.end(); ++it) { string path = dirpath + "/" + *it; - if (unlink(path.c_str()) != 0) { + if (ArchUnlinkFile(path.c_str()) != 0) { // CODE_COVERAGE_OFF this could happen if the file is removed by // another process before we get there, or a file exists but is // not writable by us, or the parent directory is not writable by // us. - if (onError) - onError(dirpath, TfStringPrintf("unlink failed for '%s': %s", - path.c_str(), strerror(errno))); + if (onError) { + onError(dirpath, TfStringPrintf("unlink failed for '%s': %s", + path.c_str(), ArchStrerror(errno).c_str())); + } // CODE_COVERAGE_ON } } - if (rmdir(dirpath.c_str()) != 0) { +#if defined(ARCH_OS_WINDOWS) + if (RemoveDirectory(dirpath.c_str()) == TRUE) { +#else + if (rmdir(dirpath.c_str()) != 0) { +#endif // CODE_COVERAGE_OFF this could happen for all the same reasons the // unlink above could fail. - if (onError) - onError(dirpath, TfStringPrintf("rmdir failed for '%s': %s", - dirpath.c_str(), strerror(errno))); + if (onError) { + onError(dirpath, TfStringPrintf("rmdir failed for '%s': %s", + dirpath.c_str(), ArchStrerror(errno).c_str())); + } // CODE_COVERAGE_ON } @@ -476,10 +577,11 @@ TfListDir(string const& path, bool recursive) return result; } -bool +TF_API bool TfTouchFile(string const &fileName, bool create) { if (create) { +#if !defined(ARCH_OS_WINDOWS) // Attempt to create the file so it is readable and writable by user, // group and other. int fd = open(fileName.c_str(), @@ -488,9 +590,29 @@ TfTouchFile(string const &fileName, bool create) if (fd == -1) return false; close(fd); +#else + HANDLE fileHandle = ::CreateFile(fileName.c_str(), + GENERIC_WRITE, // open for write + 0, // not for sharing + NULL, // default security + CREATE_ALWAYS, // overwrite existing + FILE_ATTRIBUTE_NORMAL, //normal file + NULL); // no template + + if (fileHandle == INVALID_HANDLE_VALUE) { + return false; + } + + // Close the file + ::CloseHandle(fileHandle); +#endif } // Passing NULL to the 'times' argument sets both the atime and mtime to // the current time, with millisecond precision. +#if defined(ARCH_OS_WINDOWS) + return _utime(fileName.c_str(), /* times */ NULL) == 0; +#else return utimes(fileName.c_str(), /* times */ NULL) == 0; +#endif } diff --git a/pxr/base/lib/tf/fileUtils.h b/pxr/base/lib/tf/fileUtils.h index 6b3aaa02a9..81fc97873e 100644 --- a/pxr/base/lib/tf/fileUtils.h +++ b/pxr/base/lib/tf/fileUtils.h @@ -21,213 +21,201 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef TF_FINDFILE_H -#define TF_FINDFILE_H - -/*! - * \file fileUtils.h - * \ingroup group_tf_File - * \brief Definitions of basic file utilities in tf. - */ +#ifndef TF_FILEUTILS_H +#define TF_FILEUTILS_H +/// \file tf/fileUtils.h +/// \ingroup group_tf_File +/// Definitions of basic file utilities in tf. +#include "pxr/base/tf/api.h" #include #include #include -/*! \brief Returns true if the path exists. - * - * If \p resolveSymlinks is false (default), the path is checked using - * lstat(). if \p resolveSymlinks is true, the path is checked using stat(), - * which resolves all symbolic links in the path. - */ +/// Returns true if the path exists. +/// +/// If \p resolveSymlinks is false (default), the path is checked using +/// lstat(). if \p resolveSymlinks is true, the path is checked using stat(), +/// which resolves all symbolic links in the path. +TF_API bool TfPathExists(std::string const& path, bool resolveSymlinks = false); -/*! \brief Returns true if the path exists and is a directory. - * - * If \p resolveSymlinks is false (default), the path is checked using - * lstat(). if \p resolveSymlinks is true, the path is checked using stat(), - * which resolves all symbolic links in the path. - */ +/// Returns true if the path exists and is a directory. +/// +/// If \p resolveSymlinks is false (default), the path is checked using +/// lstat(). if \p resolveSymlinks is true, the path is checked using stat(), +/// which resolves all symbolic links in the path. +TF_API bool TfIsDir(std::string const& path, bool resolveSymlinks = false); -/*! \brief Returns true if the path exists and is a file. - * - * If \p resolveSymlinks is false (default), the path is checked using - * lstat(). if \p resolveSymlinks is true, the path is checked using stat(), - * which resolves all symbolic links in the path. - */ +/// Returns true if the path exists and is a file. +/// +/// If \p resolveSymlinks is false (default), the path is checked using +/// lstat(). if \p resolveSymlinks is true, the path is checked using stat(), +/// which resolves all symbolic links in the path. +TF_API bool TfIsFile(std::string const& path, bool resolveSymlinks = false); -/*! \brief Returns true if the path exists and is a symbolic link. - */ +/// Returns true if the path exists and is a symbolic link. +TF_API bool TfIsLink(std::string const& path); -/*! \brief Returns true if the file or directory at \p path is writable. - * - * For this function to return true, the file must exist and be writable by - * the effective user, effective group, or all users. This function - * dereferences symbolic links, returning whether or not the resolved file or - * directory path is writable. If the file or directory does not exist, this - * function returns false. - */ +/// Returns true if the file or directory at \p path is writable. +/// +/// For this function to return true, the file must exist and be writable by +/// the effective user, effective group, or all users. This function +/// dereferences symbolic links, returning whether or not the resolved file or +/// directory path is writable. If the file or directory does not exist, this +/// function returns false. +TF_API bool TfIsWritable(std::string const& path); -/*! \brief Returns true if the path is an empty directory. - */ +/// Returns true if the path is an empty directory. +TF_API bool TfIsDirEmpty(std::string const& path); -/*! \brief Creates a symbolic link from \p src to \p dst. - */ +/// Creates a symbolic link from \p src to \p dst. bool TfSymlink(std::string const& src, std::string const& dst); -/*! \brief Deletes a file at path. - */ +/// Deletes a file at path. +TF_API bool TfDeleteFile(std::string const& path); -/*! \brief Creates a directory. - * - * If the directory cannot be created, this function returns false. If no - * mode is specified, the default mode is 0777. If the specified path - * already exists, or an error occurs while creating the directory, this - * method returns false. - */ +/// Creates a directory. +/// +/// If the directory cannot be created, this function returns false. If no +/// mode is specified, the default mode is 0777. If the specified path already +/// exists, or an error occurs while creating the directory, this method +/// returns false. +TF_API bool TfMakeDir(std::string const& path, int mode=-1); -/*! \brief Creates a directory hierarchy. - * - * If any element of the path cannot be created, this function will - * return false. The specified mode will be used to create all new - * directories. If no mode is specified, the default mode of \c TfMakeDir is - * used. - */ +/// Creates a directory hierarchy. +/// +/// If any element of the path cannot be created, this function will return +/// false. The specified mode will be used to create all new directories. If +/// no mode is specified, the default mode of \c TfMakeDir is used. +TF_API bool TfMakeDirs(std::string const& path, int mode=-1); -/*! \brief Function type for TfWalkDirs. - * - * This function is called once for each directory visited by TfWalkDirs. The - * first parameter is the directory path; if the topmost directory passed to - * TfWalkDirs is relative, this path will also be relative. The second - * parameter is a vector of subdirectory names, relative to the directory - * path. This parameter is a pointer, allowing the subdirectory list to be - * modified, thus controlling which directories are visited. Note that - * modifying the subdirectory vector has no effect when TfWalkDirs is called - * with \c topDown set to \c false. The final paramter is a vector of file - * names found in the directory path. The returned value determines whether - * the walk should be terminated (\c false), or continue (\c true). - */ +/// Function type for TfWalkDirs. +/// +/// This function is called once for each directory visited by TfWalkDirs. +/// The first parameter is the directory path; if the topmost directory passed +/// to TfWalkDirs is relative, this path will also be relative. The second +/// parameter is a vector of subdirectory names, relative to the directory +/// path. This parameter is a pointer, allowing the subdirectory list to be +/// modified, thus controlling which directories are visited. Note that +/// modifying the subdirectory vector has no effect when TfWalkDirs is called +/// with \c topDown set to \c false. The final paramter is a vector of file +/// names found in the directory path. The returned value determines whether +/// the walk should be terminated (\c false), or continue (\c true). typedef boost::function *, std::vector const&)> TfWalkFunction; -/*! \brief TfRmTree error handler function. - * - * The first parameter is the path which caused the error (file or directory), - * and the second parameter is an error message indicating why the error - * occurred. - */ +/// TfRmTree error handler function. +/// +/// The first parameter is the path which caused the error (file or directory), +/// and the second parameter is an error message indicating why the error +/// occurred. typedef boost::function TfWalkErrorHandler; -/*! \brief error handler to use when you want to ignore errors - * - * When calling TfWalkDirs/ChmodTree/RmTree and you want to ignore - * errors, you can pass in this public error handler which will - * ignore all the errors. - */ -void -TfWalkIgnoreErrorHandler(std::string const& path, std::string const& msg); - -/*! \brief Directory tree walker. - * - * This function attempts to be as compatible as possible with Python's - * os.walk() function. - * - * For each directory in the tree rooted at \p top (including \p top itself, - * but excluding '.' and '..'), the boost::function \p fn is called with - * three arguments: \c dirpath, \c dirnames, and \c filenames. - * - * \c dirpath is a string, the path to the directory. \c dirnames is a list - * of the names of the subdirectories in \c dirpath (excluding '.' and '..'). - * \c filenames is a list of the names of the non-directory files in - * \c dirpath. Note that the names in the sets are just names, with no path - * components. To get a full path (which begins with \p top) to a file or - * directory in \c dirpath, use \c TfStringCatPaths(dirpath, name). - * - * If optional argument \p topDown is true, or not specified, \p fn is called - * for a directory before any subdirectories. If topdown is false, \p fn is - * called for a directory after all subdirectories. Additionally, when - * \p topDown is true, the walk function can modify the \c dirnames set in - * place. This can be used to prune the search, or to impose a specific - * visitation order. Modifying \c dirnames when \p topDown is false has no - * effect, since the directories in \c dirnames have already been visited - * by the time they are passed to \p fn. - * - * The value returned by the error handler function \p onError determines what - * further action will be taken if an error is encountered. If \c true is - * returned, the walk will continue; if \c false, the walk will not continue. - * - * If \p followLinks is false, symbolic links to directories encountered - * during the walk are passed to the walk function in the \c filenames vector. - * If \p followLinks is true, symbolic links to directories are passed to the - * walk function in the \p dirnames vector, and the walk will recurse into - * these directories. - * - * If \p top is a symbolic link to a directory, it is followed regardless of - * the value of \p followLinks. Calling TfWalkDirs with a file argument - * returns immediately without calling \p fn. - */ +/// error handler to use when you want to ignore errors +/// +/// When calling TfWalkDirs/ChmodTree/RmTree and you want to ignore errors, +/// you can pass in this public error handler which will ignore all the +/// errors. +void TfWalkIgnoreErrorHandler(std::string const& path, std::string const& msg); + +/// Directory tree walker. +/// +/// This function attempts to be as compatible as possible with Python's +/// os.walk() function. +/// +/// For each directory in the tree rooted at \p top (including \p top itself, +/// but excluding '.' and '..'), the boost::function \p fn is called with +/// three arguments: \c dirpath, \c dirnames, and \c filenames. +/// +/// \c dirpath is a string, the path to the directory. \c dirnames is a list +/// of the names of the subdirectories in \c dirpath (excluding '.' and '..'). +/// \c filenames is a list of the names of the non-directory files in +/// \c dirpath. Note that the names in the sets are just names, with no path +/// components. To get a full path (which begins with \p top) to a file or +/// directory in \c dirpath, use \c TfStringCatPaths(dirpath, name). +/// +/// If optional argument \p topDown is true, or not specified, \p fn is called +/// for a directory before any subdirectories. If topdown is false, \p fn is +/// called for a directory after all subdirectories. Additionally, when +/// \p topDown is true, the walk function can modify the \c dirnames set in +/// place. This can be used to prune the search, or to impose a specific +/// visitation order. Modifying \c dirnames when \p topDown is false has no +/// effect, since the directories in \c dirnames have already been visited +/// by the time they are passed to \p fn. +/// +/// The value returned by the error handler function \p onError determines what +/// further action will be taken if an error is encountered. If \c true is +/// returned, the walk will continue; if \c false, the walk will not continue. +/// +/// If \p followLinks is false, symbolic links to directories encountered +/// during the walk are passed to the walk function in the \c filenames vector. +/// If \p followLinks is true, symbolic links to directories are passed to the +/// walk function in the \p dirnames vector, and the walk will recurse into +/// these directories. +/// +/// If \p top is a symbolic link to a directory, it is followed regardless of +/// the value of \p followLinks. Calling TfWalkDirs with a file argument +/// returns immediately without calling \p fn. void TfWalkDirs(std::string const& top, TfWalkFunction fn, bool topDown=true, TfWalkErrorHandler onError = 0, bool followLinks = false); -/*! \brief Recursively delete a directory tree rooted at \p path. - * - * Tf runtime errors are raised if any errors are encountered while chmod'ing - * the specified \p path. Pass in TfWalkIgnoreErrorHandler() to ignore errors. - * Alternately, sending in a custom TfWalkErrorHandler will - * call this handler when errors occur. This handler receives the path which - * caused the error, and a message indicating why the error occurred. - */ +/// Recursively delete a directory tree rooted at \p path. +/// +/// Tf runtime errors are raised if any errors are encountered while chmod'ing +/// the specified \p path. Pass in TfWalkIgnoreErrorHandler() to ignore errors. +/// Alternately, sending in a custom TfWalkErrorHandler will +/// call this handler when errors occur. This handler receives the path which +/// caused the error, and a message indicating why the error occurred. void TfRmTree(std::string const& path, TfWalkErrorHandler onError = 0); -/*! \brief Return a list containing files and directories in \p path. - * - * A trailing path separator character is appended to directories returned - * in the listing. If \p recursive is true, the directory listing will - * include all subdirectory structure of \p path. - */ +/// Return a list containing files and directories in \p path. +/// +/// A trailing path separator character is appended to directories returned +/// in the listing. If \p recursive is true, the directory listing will +/// include all subdirectory structure of \p path. +TF_API std::vector TfListDir(std::string const& path, bool recursive = false); -/*! \brief Read the contents of \p dirPath and append the names of the contained - * directories, files, and symlinks to \p dirnames, \p filenames, and - * \p symlinknames, respectively. - * - * Return true if \p dirPath 's contents were read successfully. Otherwise - * return false and set \p errMsg with a description of the error if \p errMsg - * is not NULL. - * - * It is safe to pass NULL for any of \p dirnames, \p filenames, and \p - * symlinknames. In that case those elements are not reported - */ -bool +/// Read the contents of \p dirPath and append the names of the contained +/// directories, files, and symlinks to \p dirnames, \p filenames, and +/// \p symlinknames, respectively. +/// +/// Return true if \p dirPath 's contents were read successfully. Otherwise +/// return false and set \p errMsg with a description of the error if \p errMsg +/// is not NULL. +/// +/// It is safe to pass NULL for any of \p dirnames, \p filenames, and +/// \p symlinknames. In that case those elements are not reported +TF_API bool TfReadDir(std::string const &dirPath, std::vector *dirnames, std::vector *filenames, std::vector *symlinknames, std::string *errMsg = NULL); -/*! \brief Touch \p fileName, updating access and modification time to 'now'. - * - * A simple touch-like functionality. Simple in a sense that it does not offer - * as many options as the same-name unix touch command, but otherwise is identical - * to the default touch behavior. - * If \p create is true, an empty file gets created, otherwise the touch - * call fails if the file does not already exist. - */ -bool TfTouchFile(std::string const &fileName, bool create=true); +/// Touch \p fileName, updating access and modification time to 'now'. +/// +/// A simple touch-like functionality. Simple in a sense that it does not +/// offer as many options as the same-name unix touch command, but otherwise +/// is identical to the default touch behavior. If \p create is true, an empty +/// file gets created, otherwise the touch call fails if the file does not +/// already exist. +TF_API bool TfTouchFile(std::string const &fileName, bool create=true); #endif diff --git a/pxr/base/lib/tf/flyweight.h b/pxr/base/lib/tf/flyweight.h index 0dbdbe8e49..7880478cf5 100644 --- a/pxr/base/lib/tf/flyweight.h +++ b/pxr/base/lib/tf/flyweight.h @@ -24,6 +24,8 @@ #ifndef TF_FLYWEIGHT_H #define TF_FLYWEIGHT_H +/// \file tf/flyweight.h +/// An implementation of the "flyweight pattern". #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/mallocTag.h" @@ -116,10 +118,9 @@ struct Tf_FlyweightData : public Tf_FlyweightDataBase { // poolName. If successful, \a data is installed and the returned value is the // same as \a data. If unsuccessful, the returned value is a pointer to the // existing data. -Tf_FlyweightDataBase * +TF_API Tf_FlyweightDataBase * Tf_TrySetFlyweightData(std::string const &poolName, Tf_FlyweightDataBase *data); -/// /// \class TfFlyweight /// /// An implementation of the "flyweight pattern": @@ -127,32 +128,31 @@ Tf_TrySetFlyweightData(std::string const &poolName, Tf_FlyweightDataBase *data); /// /// This class maintains object instances in a shared pool so that two or more /// objects that compare equal share the same instance in the pool. This can -/// help reduce memory usage if there are many equivalent object instances in a -/// program. There is overhead associated with these savings. The primary -/// overhead is in constructing a flyweight object. This requires searching the -/// pool to determine if there exists an equivalent object, and possibly +/// help reduce memory usage if there are many equivalent object instances in +/// a program. There is overhead associated with these savings. The primary +/// overhead is in constructing a flyweight object. This requires searching +/// the pool to determine if there exists an equivalent object, and possibly /// inserting one if there is not. Minor overhead exists in accessing a /// flyweight object. This incurs an extra indirection. /// -/// TfFlyweight objects are thread-safe assuming the held -/// value type provides the basic thread safety guarantee (see below). Thread -/// safety at the TfFlyweight level is accomplished by guarding the global -/// object pool with a mutex lock. The lock is only taken when constructing and -/// assigning TfFlyweights from value types. The lock is not taken for -/// constructing and assigning TfFlyweights with other TfFlyweights. Note that -/// the common case of default construction is special-cased not to require -/// locking (except on first construction). +/// TfFlyweight objects are thread-safe assuming the held value type provides +/// the basic thread safety guarantee (see below). Thread safety at the +/// TfFlyweight level is accomplished by guarding the global object pool with +/// a mutex lock. The lock is only taken when constructing and assigning +/// TfFlyweights from value types. The lock is not taken for constructing and +/// assigning TfFlyweights with other TfFlyweights. Note that the common case +/// of default construction is special-cased not to require locking (except on +/// first construction). /// /// To use TfFlyweight with some value type concurrently in different threads, /// that value type must support basic thread safety. Specifically, it must /// safely allow multiple concurrent const accesses, but can assume that -/// non-const accesses are serialized by another party. The basic rule to keep -/// in mind is that if there are any 'mutable' member variables in \e type, then -/// those members are potentially mutable shared state in const contexts. -/// Modifications of those member variables inside const methods must be made -/// thread-safe by mutual exclusion or other means. Modifying those variables -/// in non-const methods need not be guarded. -/// +/// non-const accesses are serialized by another party. The basic rule to +/// keep in mind is that if there are any 'mutable' member variables in \e +/// type, then those members are potentially mutable shared state in const +/// contexts. Modifications of those member variables inside const methods +/// must be made thread-safe by mutual exclusion or other means. Modifying +/// those variables in non-const methods need not be guarded. template < class Type , class HashFn @@ -457,7 +457,6 @@ class TfFlyweight : _ElementPairPtr _ptr; }; - /// A functor that gives a total order for flyweight objects. Note that the /// specific order that the functor produces is arbitrary, and may differ from /// run to run of the program. It does not depend on the underlying values at diff --git a/pxr/base/lib/tf/getenv.cpp b/pxr/base/lib/tf/getenv.cpp index 787f1ded86..18d984568c 100644 --- a/pxr/base/lib/tf/getenv.cpp +++ b/pxr/base/lib/tf/getenv.cpp @@ -21,23 +21,24 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/defines.h" +#include "pxr/base/arch/pragmas.h" +#include "pxr/base/arch/env.h" #include "pxr/base/tf/getenv.h" #include "pxr/base/tf/stringUtils.h" #include #include #include #include -#include +#include +#include using std::string; - - - string TfGetenv(const string& envName, const string& defaultValue) { - const char* value = getenv(envName.c_str()); + const char* value = ArchGetEnv(envName.c_str()); if (!value || value[0] == '\0') return defaultValue; @@ -48,7 +49,7 @@ TfGetenv(const string& envName, const string& defaultValue) int TfGetenvInt(const string& envName, int defaultValue) { - const char* value = getenv(envName.c_str()); + const char* value = ArchGetEnv(envName.c_str()); if (!value || value[0] == '\0') return defaultValue; @@ -59,22 +60,26 @@ TfGetenvInt(const string& envName, int defaultValue) bool TfGetenvBool(const string& envName, bool defaultValue) { - const char* value = getenv(envName.c_str()); + const char* value = ArchGetEnv(envName.c_str()); if (!value || value[0] == '\0') return defaultValue; - else { - return strcasecmp(value, "true") == 0 or - strcasecmp(value, "yes") == 0 or - strcasecmp(value, "on") == 0 or - strcmp(value, "1") == 0; - } + else + { + for (char *iter = (char*)value; *iter != '\0'; ++iter) + *iter = tolower(*iter); + + return strcmp(value, "true") == 0 or + strcmp(value, "yes") == 0 or + strcmp(value, "on") == 0 or + strcmp(value, "1") == 0; + } } double TfGetenvDouble(const string& envName, double defaultValue) { - const char* value = getenv(envName.c_str()); + const char* value = ArchGetEnv(envName.c_str()); if (!value || value[0] == '\0') return defaultValue; diff --git a/pxr/base/lib/tf/getenv.h b/pxr/base/lib/tf/getenv.h index 42b41f9fea..cd85d6b8da 100644 --- a/pxr/base/lib/tf/getenv.h +++ b/pxr/base/lib/tf/getenv.h @@ -24,72 +24,53 @@ #ifndef TF_GETENV_H #define TF_GETENV_H -/*! - * \file getenv.h - * \brief Functions for accessing environment variables - * \ingroup group_tf_SystemsExt - */ - - -#include - - - - -/*! - * \brief Return an environment variable as a string. - * \ingroup group_tf_SystemsExt - * - * Return the value of the environment variable \c envName - * as a string. If the variable is unset, or is the empty string, - * then \c defaultValue is returned. - */ - +/// \file tf/getenv.h +/// \ingroup group_tf_SystemsExt +/// Functions for accessing environment variables. + +#include + +/// \addtogroup group_tf_SystemsExt +///@{ +#include "pxr/base/tf/api.h" + +/// Return an environment variable as a string. +/// +/// Return the value of the environment variable \c envName +/// as a string. If the variable is unset, or is the empty string, +/// then \c defaultValue is returned. +TF_API std::string TfGetenv(const std::string& envName, const std::string& defaultValue = ""); -/*! - * \brief Return an environment variable as an integer. - * \ingroup group_tf_SystemsExt - * - * Return the value of the environment variable \c envName - * as an integer. If the variable is unset, or is the empty string, - * then \c defaultValue is returned. Otherwise, the function uses - * atoi() to convert the string to an integer: the implication being that - * if the string is not a valid integer, you get back whatever value atoi() - * comes up with. - */ - +/// Return an environment variable as an integer. +/// +/// Return the value of the environment variable \c envName as an integer. If +/// the variable is unset, or is the empty string, then \c defaultValue is +/// returned. Otherwise, the function uses atoi() to convert the string to an +/// integer: the implication being that if the string is not a valid integer, +/// you get back whatever value atoi() comes up with. int TfGetenvInt(const std::string& envName, int defaultValue); -/*! - * \brief Return an environment variable as a boolean. - * \ingroup group_tf_SystemsExt - * - * Return the value of the environment variable \c envName - * as a boolean. If the variable is unset, or is the empty string, - * then \c defaultValue is returned. A value of \c true - * is returned if the environment variable is any of - * "true", "yes", "on" or "1"; the match is not case sensitive. - * All other values yield a return value of \c false. - */ - -bool TfGetenvBool(const std::string&, bool defaultValue); - -/*! - * \brief Return an environment variable as a double. - * \ingroup group_tf_SystemsExt - * - * Return the value of the environment variable \c envName as a double. If the - * variable is unset, or is the empty string, then \c defaultValue is returned. - * Otherwise, the function uses TfStringToDouble() to convert the string to a - * double: the implication being that if the string is not a valid double, you - * get back whatever value TfStringToDouble() comes up with. - */ - +/// Return an environment variable as a boolean. +/// +/// Return the value of the environment variable \c envName as a boolean. If +/// the variable is unset, or is the empty string, then \c defaultValue is +/// returned. A value of \c true is returned if the environment variable is +/// any of "true", "yes", "on" or "1"; the match is not case sensitive. All +/// other values yield a return value of \c false. +TF_API bool TfGetenvBool(const std::string&, bool defaultValue); + +/// Return an environment variable as a double. +/// +/// Return the value of the environment variable \c envName as a double. If +/// the variable is unset, or is the empty string, then \c defaultValue is +/// returned. Otherwise, the function uses TfStringToDouble() to convert the +/// string to a double: the implication being that if the string is not a +/// valid double, you get back whatever value TfStringToDouble() comes up +/// with. double TfGetenvDouble(const std::string& envName, double defaultValue); - - +///@} #endif diff --git a/pxr/base/lib/tf/hash.cpp b/pxr/base/lib/tf/hash.cpp index 4069a87f7e..98b2e7c389 100644 --- a/pxr/base/lib/tf/hash.cpp +++ b/pxr/base/lib/tf/hash.cpp @@ -25,6 +25,7 @@ //#include "pxr/base/tf/anyWeakPtr.h" #include "pxr/base/tf/enum.h" #include "pxr/base/tf/stringUtils.h" +#include "pxr/base/tf/token.h" #include "pxr/base/tf/type.h" #include @@ -40,6 +41,12 @@ TfHash::operator()(const TfType& t) const return (*this)(t._info); } +size_t +TfHash::operator()(const TfToken& t) const +{ + return t.Hash(); +} + size_t TfHashCharPtr::operator()(const char* ptr) const { diff --git a/pxr/base/lib/tf/hash.h b/pxr/base/lib/tf/hash.h index c4b3fa88b8..2d38b141fe 100644 --- a/pxr/base/lib/tf/hash.h +++ b/pxr/base/lib/tf/hash.h @@ -24,62 +24,25 @@ #ifndef TF_HASH_H #define TF_HASH_H +/// \file tf/hash.h +/// \ingroup group_tf_String + #include "pxr/base/tf/tf.h" #include "pxr/base/tf/timeStamp.h" +#include "pxr/base/tf/api.h" +#include "pxr/base/arch/defines.h" #include "pxr/base/arch/hash.h" - #include #include #include - -/*! - * \file hash.h - * \ingroup group_tf_String - */ +#include class TfAnyWeakPtr; class TfEnum; +class TfToken; class TfType; -/*! - * \class TfHash Hash.h pxr/base/tf/hash.h - * \ingroup group_tf_String - * \brief Provides hash function on STL string types and other types. - * - * The \c TfHash class is a functor as defined by the STL standard: - * currently, it is defined for: - * \li std::string - * \li TfRefPtr - * \li TfWeakPtr - * \li TfEnum - * \li TfTimeStamp - * \li const void* - * \li int - * - * The \c TfHash class can be used to implement a - * \c TfHashMap with \c string keys as follows: - * \code - * TfHashMap m; - * m["abc"] = 1; - * \endcode - * - * \c TfHash()(const char*) is disallowed to avoid confusion of whether - * the pointer or the string is being hashed. If you want to hash a - * C-string use \c TfHashCString and if you want to hash a \c char* use - * \c TfHashCharPtr. - * - * One can also declare, for any types \c S and \c T, - * \code - * TfHashMap, T, TfHash> m1; - * TfHashMap, T, TfHash> m2; - * TfHashMap m3; - * TfHashMap m4; - * TfHashMap m5; - * TfHashMap m6; - * \endcode - */ - template class TfWeakPtr; template class TfRefPtr; class TfRefBase; @@ -87,21 +50,57 @@ class TfRefBase; template