diff --git a/tesseract_common/CMakeLists.txt b/tesseract_common/CMakeLists.txt index 3f20ca3717e..40a0b59cf29 100644 --- a/tesseract_common/CMakeLists.txt +++ b/tesseract_common/CMakeLists.txt @@ -16,6 +16,7 @@ find_package(Boost REQUIRED COMPONENTS system filesystem serialization) find_package(Eigen3 REQUIRED) find_package(TinyXML2 REQUIRED) find_package(yaml-cpp REQUIRED) +find_package(FreeImage REQUIRED) find_package(console_bridge REQUIRED) if(NOT TARGET console_bridge::console_bridge) @@ -47,12 +48,18 @@ add_library( src/allowed_collision_matrix.cpp src/any_poly.cpp src/collision_margin_data.cpp + src/color.cpp src/joint_state.cpp src/manipulator_info.cpp + src/material.cpp src/kinematic_limits.cpp src/eigen_serialization.cpp + src/image.cpp src/utils.cpp src/resource_locator.cpp + src/shader_param.cpp + src/shader_params.cpp + src/shader_type.cpp src/types.cpp) target_link_libraries( ${PROJECT_NAME} @@ -64,6 +71,7 @@ target_link_libraries( Boost::filesystem Boost::serialization console_bridge::console_bridge + ${FreeImage_LIBRARIES} yaml-cpp) target_compile_options(${PROJECT_NAME} PUBLIC ${TESSERACT_COMPILE_OPTIONS_PUBLIC}) target_compile_definitions(${PROJECT_NAME} PUBLIC ${TESSERACT_COMPILE_DEFINITIONS}) @@ -77,6 +85,8 @@ target_code_coverage( ENABLE ${TESSERACT_ENABLE_CODE_COVERAGE}) target_include_directories(${PROJECT_NAME} PUBLIC "$" "$") +target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC + ${FreeImage_INCLUDE_DIRS}) configure_package(NAMESPACE tesseract TARGETS ${PROJECT_NAME}) @@ -91,6 +101,8 @@ install( install( FILES "${CMAKE_CURRENT_LIST_DIR}/cmake/tesseract_macros.cmake" + "${CMAKE_CURRENT_LIST_DIR}/cmake/FindFreeImage.cmake" + "${CMAKE_CURRENT_LIST_DIR}/cmake/FindPkgMacros.cmake" "${CMAKE_CURRENT_LIST_DIR}/cmake/FindTinyXML2.cmake" "${CMAKE_CURRENT_LIST_DIR}/cmake/Findtcmalloc.cmake" "${CMAKE_CURRENT_LIST_DIR}/cmake/Findtcmalloc_minimal.cmake" diff --git a/tesseract_common/cmake/FindFreeImage.cmake b/tesseract_common/cmake/FindFreeImage.cmake new file mode 100644 index 00000000000..e9a5414b6ab --- /dev/null +++ b/tesseract_common/cmake/FindFreeImage.cmake @@ -0,0 +1,48 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +# - Try to find FreeImage +# Once done, this will define +# +# FreeImage_FOUND - system has FreeImage +# FreeImage_INCLUDE_DIRS - the FreeImage include directories +# FreeImage_LIBRARIES - link these to use FreeImage + +include(FindPkgMacros) +findpkg_begin(FreeImage) + +# Get path, convert backslashes as ${ENV_${var}} +getenv_path(FREEIMAGE_HOME) + +# construct search paths +set(FreeImage_PREFIX_PATH ${FREEIMAGE_HOME} ${ENV_FREEIMAGE_HOME}) +create_search_paths(FreeImage "") +# redo search if prefix path changed +clear_if_changed(FreeImage_PREFIX_PATH + FreeImage_LIBRARY_FWK + FreeImage_LIBRARY_REL + FreeImage_LIBRARY_DBG + FreeImage_INCLUDE_DIR +) + +set(FreeImage_LIBRARY_NAMES freeimage freeimageLib FreeImage FreeImageLib) +get_debug_names(FreeImage_LIBRARY_NAMES) + +use_pkgconfig(FreeImage_PKGC freeimage) + +findpkg_framework(FreeImage) + +find_path(FreeImage_INCLUDE_DIR NAMES FreeImage.h HINTS ${FreeImage_INC_SEARCH_PATH} ${FreeImage_PKGC_INCLUDE_DIRS}) + +find_library(FreeImage_LIBRARY_REL NAMES ${FreeImage_LIBRARY_NAMES} HINTS ${FreeImage_LIB_SEARCH_PATH} ${FreeImage_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" Release RelWithDebInfo MinSizeRel) +find_library(FreeImage_LIBRARY_DBG NAMES ${FreeImage_LIBRARY_NAMES_DBG} HINTS ${FreeImage_LIB_SEARCH_PATH} ${FreeImage_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" Debug) + +make_library_set(FreeImage_LIBRARY) + +findpkg_finish(FreeImage) diff --git a/tesseract_common/cmake/FindPkgMacros.cmake b/tesseract_common/cmake/FindPkgMacros.cmake new file mode 100644 index 00000000000..7f39aea924e --- /dev/null +++ b/tesseract_common/cmake/FindPkgMacros.cmake @@ -0,0 +1,165 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +################################################################## +# Provides some common functionality for the FindPackage modules +################################################################## + +# Begin processing of package +macro(findpkg_begin PREFIX) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Looking for ${PREFIX}...") + endif () +endmacro(findpkg_begin) + +# Display a status message unless FIND_QUIETLY is set +macro(pkg_message PREFIX) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS ${ARGN}) + endif () +endmacro(pkg_message) + +# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes +macro(getenv_path VAR) + set(ENV_${VAR} $ENV{${VAR}}) + # replace won't work if var is blank + if (ENV_${VAR}) + string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) + endif () +endmacro(getenv_path) + +# Construct search paths for includes and libraries from a PREFIX_PATH +macro(create_search_paths PREFIX PATH_SUFFIX) + foreach(dir ${${PREFIX}_PREFIX_PATH}) + set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH} + ${dir}/include ${dir}/Include ${dir}/include/${PREFIX}${PATH_SUFFIX} ${dir}/Headers) + set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} + ${dir}/lib ${dir}/Lib ${dir}/lib/${PREFIX}${PATH_SUFFIX} ${dir}/Libs) + set(${PREFIX}_BIN_SEARCH_PATH ${${PREFIX}_BIN_SEARCH_PATH} + ${dir}/bin) + endforeach(dir) + if(ANDROID) + set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} ${OGRE_DEPENDENCIES_DIR}/lib/${ANDROID_ABI}) + endif() + set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH}) +endmacro(create_search_paths) + +# clear cache variables if a certain variable changed +macro(clear_if_changed TESTVAR) + # test against internal check variable + # HACK: Apparently, adding a variable to the cache cleans up the list + # a bit. We need to also remove any empty strings from the list, but + # at the same time ensure that we are actually dealing with a list. + list(APPEND ${TESTVAR} "") + list(REMOVE_ITEM ${TESTVAR} "") + if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}") + message(STATUS "${TESTVAR} changed.") + foreach(var ${ARGN}) + set(${var} "NOTFOUND" CACHE STRING "x" FORCE) + endforeach(var) + endif () + set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE) +endmacro(clear_if_changed) + +# Try to get some hints from pkg-config, if available +macro(use_pkgconfig PREFIX PKGNAME) + if(NOT ANDROID) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(${PREFIX} ${PKGNAME}) + endif () + endif() +endmacro (use_pkgconfig) + +# Couple a set of release AND debug libraries (or frameworks) +macro(make_library_set PREFIX) + if (${PREFIX}_FWK) + set(${PREFIX} ${${PREFIX}_FWK}) + elseif (${PREFIX}_REL AND ${PREFIX}_DBG) + set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG}) + elseif (${PREFIX}_REL) + set(${PREFIX} ${${PREFIX}_REL}) + elseif (${PREFIX}_DBG) + set(${PREFIX} ${${PREFIX}_DBG}) + endif () +endmacro(make_library_set) + +# Generate debug names from given release names +macro(get_debug_names PREFIX) + foreach(i ${${PREFIX}}) + set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i}) + endforeach(i) +endmacro(get_debug_names) + +# Add the parent dir from DIR to VAR +macro(add_parent_dir VAR DIR) + get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE) + set(${VAR} ${${VAR}} ${${DIR}_TEMP}) +endmacro(add_parent_dir) + +# Do the final processing for the package find. +macro(findpkg_finish PREFIX) + # skip if already processed during this run + if (NOT ${PREFIX}_FOUND) + if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) + set(${PREFIX}_FOUND TRUE) + set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) + set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}") + endif () + else () + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Could not locate ${PREFIX}") + endif () + if (${PREFIX}_FIND_REQUIRED) + message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.") + endif () + endif () + + mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK) + endif () +endmacro(findpkg_finish) + + +# Slightly customised framework finder +macro(findpkg_framework fwk) + if(APPLE) + set(${fwk}_FRAMEWORK_PATH + ${${fwk}_FRAMEWORK_SEARCH_PATH} + ${CMAKE_FRAMEWORK_PATH} + ~/Library/Frameworks + /Library/Frameworks + /System/Library/Frameworks + /Network/Library/Frameworks + ${CMAKE_CURRENT_SOURCE_DIR}/lib/macosx/Release + ${CMAKE_CURRENT_SOURCE_DIR}/lib/macosx/Debug + ) + # These could be arrays of paths, add each individually to the search paths + foreach(i ${OGRE_PREFIX_PATH}) + set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/macosx/Release ${i}/lib/macosx/Debug) + endforeach(i) + + foreach(i ${OGRE_PREFIX_BUILD}) + set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/macosx/Release ${i}/lib/macosx/Debug) + endforeach(i) + + foreach(dir ${${fwk}_FRAMEWORK_PATH}) + set(fwkpath ${dir}/${fwk}.framework) + if(EXISTS ${fwkpath}) + set(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES} + ${fwkpath}/Headers ${fwkpath}/PrivateHeaders) + set(${fwk}_FRAMEWORK_PATH ${dir}) + if (NOT ${fwk}_LIBRARY_FWK) + set(${fwk}_LIBRARY_FWK "-framework ${fwk}") + endif () + endif(EXISTS ${fwkpath}) + endforeach(dir) + endif(APPLE) +endmacro(findpkg_framework) diff --git a/tesseract_common/include/tesseract_common/color.h b/tesseract_common/include/tesseract_common/color.h new file mode 100644 index 00000000000..c0e874647aa --- /dev/null +++ b/tesseract_common/include/tesseract_common/color.h @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef TESSERACT_COMMON_COLOR_H +#define TESSERACT_COMMON_COLOR_H + +#include +#include +#include + +#include + +namespace tesseract_common +{ +// +/// \class Color color.h +/// \brief Defines a color using a red (R), green (G), blue (B), and alpha +/// (A) component. Each color component is in the range [0..1]. +/// +/// ## Example +/// +/// \snippet examples/color_example.cc complete +class Color +{ +public: + /// \brief (1, 1, 1) + static const Color& White; + /// \brief (0, 0, 0) + static const Color& Black; + /// \brief (1, 0, 0) + static const Color& Red; + /// \brief (0, 1, 0) + static const Color& Green; + /// \brief (0, 0, 1) + static const Color& Blue; + /// \brief (1, 1, 0) + static const Color& Yellow; + /// \brief (1, 0, 1) + static const Color& Magenta; + /// \brief (0, 1, 1) + static const Color& Cyan; + + /// \typedef RGBA + /// \brief A RGBA packed value as an unsigned int + /// Each 8 bits corresponds to a channel. + /// + /// \code + /// RGBA a = 0xFF0000FF; // (1, 0, 0, 1) for RGBA, i.e. red. + /// \endcode + using RGBA = unsigned int; + + /// \typedef BGRA + /// \brief A BGRA packed value as an unsigned int + /// Each 8 bits corresponds to a channel. + /// + /// \code + /// BGRA a = 0xFF0000FF; // (0, 0, 1, 1) for RGBA, i.e. blue. + /// \endcode + using BGRA = unsigned int; + + /// \typedef ARGB + /// \brief A ARGB packed value as an unsigned int + /// Each 8 bits corresponds to a channel. + /// + /// \code + /// ARGB a = 0xFF0000FF; // (0, 0, 1, 1) for RGBA, i.e. blue. + /// \endcode + using ARGB = unsigned int; + + /// \typedef ABGR + /// \brief A ABGR packed value as an unsigned int + /// Each 8 bits corresponds to a channel. + /// + /// \code + /// ABGR a = 0xFF0000FF; // (1, 0, 0, 1) for RGBA, i.e. red. + /// \endcode + using ABGR = unsigned int; + + /// \brief Constructor + Color() = default; + + /// \brief Constructor + /// \param[in] r Red value (range 0 to 1) + /// \param[in] g Green value (range 0 to 1) + /// \param[in] b Blue value (range 0 to 1) + /// \param[in] a Alpha value (0=transparent, 1=opaque) + constexpr Color(float r, float g, float b, float a = 1.0) : r_(r), g_(g), b_(b), a_(a) { this->Clamp(); } + + /// \brief Copy Constructor + /// \param[in] clr Color to copy + Color(const Color& clr) = default; + + /// \brief Destructor + ~Color() = default; + + /// \brief Reset the color to default values to red=0, green=0, + /// blue=0, alpha=1. + void reset(); + + /// \brief Set the contents of the vector + /// \param[in] r Red value (range 0 to 1) + /// \param[in] g Green value (range 0 to 1) + /// \param[in] b Blue value (range 0 to 1) + /// \param[in] a Alpha value (0=transparent, 1=opaque) + void set(float r = 1, float g = 1, float b = 1, float a = 1); + + /// \brief Get the color in HSV colorspace + /// \return HSV values in a Vector3f format. A vector3f containing + /// {NAN_F, NAN_F, NAN_F} is returned on error. + Eigen::Vector3f getHSV() const; + + /// \brief Set a color based on HSV values + /// \param[in] h Hue(0..360) + /// \param[in] s Saturation(0..1) + /// \param[in] v Value(0..1) + void setFromHSV(float h, float s, float v); + + /// \brief Get the color in YUV colorspace + /// \return the YUV color + Eigen::Vector3f getYUV() const; + + /// \brief Set from yuv + /// \param[in] y value + /// \param[in] u value + /// \param[in] v value + void setFromYUV(float y, float u, float v); + + /// \brief Equal operator + /// \param[in] pt Color to copy + /// \return Reference to this color + Color& operator=(const Color& pt) = default; + + /// \brief Array index operator + /// \param[in] index Color component index(0=red, 1=green, 2=blue, + /// 3=alpha) + /// \return r, g, b, or a when index is 0, 1, 2 or 3. A NAN_F value is + /// returned if the index is invalid + float operator[](const unsigned int index); + + /// \brief Array index operator, const version + /// \param[in] index Color component index(0=red, 1=green, 2=blue, + /// 3=alpha) + /// \return r, g, b, or a when index is 0, 1, 2 or 3. A NAN_F value is + /// returned if the index is invalid + float operator[](const unsigned int index) const; + + /// \brief Get as uint32 RGBA packed value + /// \return the color + RGBA asRGBA() const; + + /// \brief Get as uint32 BGRA packed value + /// \return the color + BGRA asBGRA() const; + + /// \brief Get as uint32 ARGB packed value + /// \return the color + ARGB asARGB() const; + + /// \brief Get as uint32 ABGR packed value + /// \return the color + ABGR asABGR() const; + + /// \brief Set from uint32 RGBA packed value + /// \param[in] v the new color + void setFromRGBA(RGBA v); + + /// \brief Set from uint32 BGRA packed value + /// \param[in] v the new color + void setFromBGRA(BGRA v); + + /// \brief Set from uint32 ARGB packed value + /// \param[in] v the new color + void setFromARGB(ARGB v); + + /// \brief Set from uint32 ABGR packed value + /// \param[in] v the new color + void setFromABGR(ABGR v); + + /// \brief Addition operator (this + pt) + /// \param[in] pt Color to add + /// \return The resulting color + Color operator+(const Color& pt) const; + + /// \brief Add v to all color components + /// \param[in] v Value to add to each color component + /// \return The resulting color + Color operator+(float v) const; + + /// \brief Addition equal operator + /// \param[in] pt Color to add + /// \return The resulting color + const Color& operator+=(const Color& pt); + + /// \brief Subtraction operator + /// \param[in] pt The color to substract + /// \return The resulting color + Color operator-(const Color& pt) const; + + /// \brief Subtract v from all color components + /// \param[in] v Value to subtract + /// \return The resulting color + Color operator-(float v) const; + + /// \brief Subtraction equal operator + /// \param[in] pt Color to subtract + /// \return The resulting color + const Color& operator-=(const Color& pt); + + /// \brief Division operator + /// \param[in] pt Color to divide by + /// \return The resulting color + const Color operator/(const Color& pt) const; + + /// \brief Divide all color component by v + /// \param[in] v The value to divide by + /// \return The resulting color + const Color operator/(float v) const; + + /// \brief Division equal operator + /// \param[in] pt Color to divide by + /// \return The resulting color + const Color& operator/=(const Color& pt); + + /// \brief Multiplication operator + /// \param[in] pt The color to muliply by + /// \return The resulting color + const Color operator*(const Color& pt) const; + + /// \brief Multiply all color components by v + /// \param[in] v The value to multiply by + /// \return The resulting color + const Color operator*(float v) const; + + /// \brief Multiplication equal operator + /// \param[in] pt The color to muliply by + /// \return The resulting color + const Color& operator*=(const Color& pt); + + /// \brief Equality operator + /// \param[in] pt The color to check for equality + /// \return True if the this color equals pt + bool operator==(const Color& pt) const; + + /// \brief Inequality operator + /// \param[in] pt The color to check for inequality + /// \return True if the this color does not equal pt + bool operator!=(const Color& pt) const; + + /// \brief Stream insertion operator + /// \param[in] out the output stream + /// \param[in] color the color + /// \return the output stream + friend std::ostream& operator<<(std::ostream& out, const Color& color) + { + for (auto i : { 0, 1, 2, 3 }) + { + if (i > 0) + out << " "; + + // appendToStream(out, color[i]); + } + return out; + } + + /// \brief Stream insertion operator + /// \param[in] in the input stream. If the input stream does not include + /// an alpha value, a default alpha value of 1.0 will be used. + /// \param[in] pt + friend std::istream& operator>>(std::istream& in, Color& pt) + { + // Skip white spaces + in.setf(std::ios_base::skipws); + in >> pt.r_ >> pt.g_ >> pt.b_; + // Since alpha is optional, check if it's there before parsing + while (in.good() && std::isspace(in.peek())) + { + in.get(); + } + if (in.good()) + { + in >> pt.a_; + } + else if (!in.fail()) + { + pt.a_ = 1.0; + } + return in; + } + + /// \brief Get the red value + /// \return The red value + float getR() const; + + /// \brief Get the green value + /// \return The green value + float getG() const; + + /// \brief Get the blue value + /// \return The blue value + float getB() const; + + /// \brief Get the alpha value + /// \return The alpha value + float getA() const; + + /// \brief Get a mutable reference to the red value + /// \return The red value + float& getR(); + + /// \brief Get a mutable reference to the green value + /// \return The green value + float& getG(); + + /// \brief Get a mutable reference to the blue value + /// \return The blue value + float& getB(); + + /// \brief Get a mutable reference to the alpha value + /// \return The alpha value + float& getA(); + + /// \brief Set the red value + /// \param[in] r New red value + void setR(float r); + + /// \brief Set the green value + /// \param[in] g New green value + void setG(float g); + + /// \brief Set the blue value + /// \param[in] b New blue value + void setB(float b); + + /// \brief Set the alpha value + /// \param[in] a New alpha value + void setA(float a); + +private: + /// \brief Red value + float r_ = 0; + + /// \brief Green value + float g_ = 0; + + /// \brief Blue value + float b_ = 0; + + /// \brief Alpha value + float a_ = 1; + + /// \brief Clamp the color values to valid ranges + constexpr void Clamp() + { + // These comparisons are carefully written to handle NaNs correctly. + if (!(r_ >= 0)) + r_ = 0; + + if (!(g_ >= 0)) + g_ = 0; + + if (!(b_ >= 0)) + b_ = 0; + + if (!(a_ >= 0)) + a_ = 0; + + if (r_ > 1) + r_ = r_ / 255.0f; + + if (g_ > 1) + g_ = g_ / 255.0f; + + if (b_ > 1) + b_ = b_ / 255.0f; + + if (a_ > 1) + a_ = 1; + } +}; +} // namespace tesseract_common +#endif // TESSERACT_COMMON_COLOR_H diff --git a/tesseract_common/include/tesseract_common/image.h b/tesseract_common/include/tesseract_common/image.h new file mode 100644 index 00000000000..4e2421c7955 --- /dev/null +++ b/tesseract_common/include/tesseract_common/image.h @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef TESSERACT_COMMON_IMAGE_H +#define TESSERACT_COMMON_IMAGE_H + +#include +#include +#include +#include +#include +#include +#include + +namespace tesseract_common +{ +/// \brief String names for the pixel formats. +/// \sa Image::PixelFormat. +static std::string PixelFormatNames[] = { "UNKNOWN_PIXEL_FORMAT", + "L_INT8", + "L_INT16", + "RGB_INT8", + "RGBA_INT8", + "BGRA_INT8", + "RGB_INT16", + "RGB_INT32", + "BGR_INT8", + "BGR_INT16", + "BGR_INT32", + "R_FLOAT16", + "RGB_FLOAT16", + "R_FLOAT32", + "RGB_FLOAT32", + "BAYER_RGGB8", + "BAYER_BGGR8", + "BAYER_GBRG8", + "BAYER_GRBG8" }; + +class ImagePrivate; + +/// \class Image Image.hh gz/common/common.hh +/// \brief Encapsulates an image +class Image +{ +public: + using Ptr = std::shared_ptr; + using ConstPtr = std::shared_ptr; + + /// \brief Pixel formats enumeration + enum PixelFormatType + { + UNKNOWN_PIXEL_FORMAT = 0, + L_INT8, + L_INT16, + RGB_INT8, + RGBA_INT8, + BGRA_INT8, + RGB_INT16, + RGB_INT32, + BGR_INT8, + BGR_INT16, + BGR_INT32, + R_FLOAT16, + RGB_FLOAT16, + R_FLOAT32, + RGB_FLOAT32, + BAYER_RGGB8, + BAYER_BGGR8, + BAYER_GBRG8, + BAYER_GRBG8, + COMPRESSED_PNG, + PIXEL_FORMAT_COUNT + }; + + /// \brief Convert a string to a Image::PixelFormat. + /// \param[in] _format Pixel format string. \sa Image::PixelFormatNames + /// \return Image::PixelFormat + static Image::PixelFormatType convertPixelFormat(const std::string& format); + + /// \brief Constructor + /// \param[in] _filename the path to the image + explicit Image(const std::string& filename = ""); + + /// \brief Destructor + virtual ~Image(); + + /// \brief Load an image. Return 0 on success + /// \param[in] _filename the path to the image file + /// \return 0 when the operation succeeds to open a file or -1 when fails. + int load(const std::string& filename); + + /// \brief Save the image in PNG format + /// \param[in] _filename The name of the saved image + void savePNG(const std::string& filename); + + /// \brief Save the image in PNG format + /// \param[in] _filename The name of the saved image + void savePNGToBuffer(std::vector& buffer); + + /// \brief Set the image from raw data + /// \param[in] _data Pointer to the raw image data + /// \param[in] _width Width in pixels + /// \param[in] _height Height in pixels + /// \param[in] _format Pixel format of the provided data + void setFromData(const unsigned char* data, unsigned int width, unsigned int height, Image::PixelFormatType format); + + /// \brief Set the image from compressed (i.e. png) data + /// \param[in] _data Pointer to the raw image data + /// \param[in] _size Size of the buffer + /// \param[in] _format Pixel format of the provided data + void setFromCompressedData(unsigned char* data, unsigned int size, Image::PixelFormatType format); + + /// \brief Get the image as a data array + /// \return The image data + std::vector getData() const; + + /// \brief Get only the RGB data from the image. This will drop the + /// alpha channel if one is present. + /// \return The image RGB data + std::vector getRGBData() const; + + /// \brief Get the RGBA data from the image. This will add an alpha + /// channel if one is not present. + /// \return The image RGBA data + std::vector getRGBAData() const; + + /// \brief Get the width + /// \return The image width + unsigned int width() const; + + /// \brief Get the height + /// \return The image height + unsigned int height() const; + + /// \brief Get the size of one pixel in bits + /// \return The BPP of the image + unsigned int getBPP() const; + + // \brief Get the size of a row of pixel + /// \return The pitch of the image + int getPitch() const; + + /// \brief Get the full filename of the image + /// \return The filename used to load the image + std::string getFilename() const; + + /// \brief Get the pixel format + /// \return PixelFormat + PixelFormatType getPixelFormat() const; + + /// \brief Get a pixel color value + /// \param[in] _x Column location in the image + /// \param[in] _y Row location in the image + /// \return The color of the given pixel + Color getPixel(unsigned int x, unsigned int y) const; + + /// \brief Get the average color + /// \return The average color + Color getAvgColor() const; + + /// \brief Get the max color + /// \return The max color + Color getMaxColor() const; + + /// \brief Rescale the image + /// \param[in] _width New image width + /// \param[in] _height New image height + void rescale(int width, int height); + + /// \brief Returns whether this is a valid image + /// \return true if image has a bitmap + bool valid() const; + + /// \brief Convert a single channel image data buffer into an RGB image. + /// During the conversion, the input image data are normalized to 8 bit + /// values i.e. [0, 255]. Optionally, specify min and max values to use + /// when normalizing the input image data. For example, if min and max + /// are set to 1 and 10, a data value 2 will be normalized to: + /// (2 - 1) / (10 - 1) * 255. + /// \param[in] _data input image data buffer + /// \param[in] _width image width + /// \param[in] _height image height + /// \param[out] _output Output RGB image + /// \param[in] _min Minimum value to be used when normalizing the input + /// image data to RGB. + /// \param[in] _max Maximum value to be used when normalizing the input + /// image data to RGB. + /// \param[in] _flip True to flip the values after normalization, i.e. + /// lower values are converted to brigher pixels. + template + static void convertToRGBImage(const void* _data, + unsigned int _width, + unsigned int _height, + Image& _output, + T _min = std::numeric_limits::max(), + T _max = std::numeric_limits::lowest(), + bool _flip = false) + { + unsigned int samples = _width * _height; + unsigned int bufferSize = samples * sizeof(T); + + auto buffer = std::vector(samples); + memcpy(buffer.data(), _data, bufferSize); + + auto outputRgbBuffer = std::vector(samples * 3); + + // use min and max values found in the data if not specified + T min = std::numeric_limits::max(); + T max = std::numeric_limits::lowest(); + if (_min > max) + { + for (unsigned int i = 0; i < samples; ++i) + { + auto v = buffer[i]; + // ignore inf values when computing min/max + // cast to float when calling isinf to avoid compile error on + // windows + if (v > max && !std::isinf(static_cast(v))) + max = v; + if (v < min && !std::isinf(static_cast(v))) + min = v; + } + } + min = almostEqualRelativeAndAbs(_min, std::numeric_limits::max()) ? min : _min; + max = almostEqualRelativeAndAbs(_max, std::numeric_limits::lowest()) ? max : _max; + + // convert to rgb image + // color is grayscale, i.e. r == b == g + double range = static_cast(max - min); + if (almostEqualRelativeAndAbs(range, 0.0)) + range = 1.0; + unsigned int idx = 0; + for (unsigned int j = 0; j < _height; ++j) + { + for (unsigned int i = 0; i < _width; ++i) + { + auto v = buffer[idx++]; + double t = static_cast(v - min) / range; + if (_flip) + t = 1.0 - t; + uint8_t r = static_cast(255 * t); + unsigned int outIdx = j * _width * 3 + i * 3; + outputRgbBuffer[outIdx] = r; + outputRgbBuffer[outIdx + 1] = r; + outputRgbBuffer[outIdx + 2] = r; + } + } + _output.setFromData(outputRgbBuffer.data(), _width, _height, RGB_INT8); + } + +private: + /// \brief Private data pointer + std::unique_ptr data_; +}; +} // namespace tesseract_common +#endif // TESSERACT_COMMON_IMAGE_H diff --git a/tesseract_common/include/tesseract_common/material.h b/tesseract_common/include/tesseract_common/material.h new file mode 100644 index 00000000000..0bc0fd5529d --- /dev/null +++ b/tesseract_common/include/tesseract_common/material.h @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2015 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef TESSERACT_COMMON_MATERIAL_H +#define TESSERACT_COMMON_MATERIAL_H + +#include +#include + +#include +#include +#include +#include +#include + +namespace tesseract_common +{ +// +/// \brief Default pbr material properties +// static const common::Pbr kDefaultPbr; + +enum class MaterialType +{ + /// \brief Classic shading, i.e. variants of Phong + MT_CLASSIC = 0, + + /// \brief Physically Based Shading + MT_PBS = 1 +}; + +class Material +{ +public: + using Ptr = std::shared_ptr; + using ConstPtr = std::shared_ptr; + + Material(std::string name); + + virtual ~Material(); + + // Documentation inherited + virtual std::unique_ptr clone(const std::string& name = "") const; + + // Documentation inherited + virtual std::string getName() const; + + // Documentation inherited + virtual void setAmbient(double r, double g, double b, double a = 1.0); + + // Documentation inherited + virtual void setAmbient(const Color& color); + + // Documentation inherited + virtual void setDiffuse(double r, double g, double b, double a = 1.0); + + // Documentation inherited + virtual void setDiffuse(const Color& color); + + // Documentation inherited + virtual void setSpecular(double r, double g, double b, double a = 1.0); + + // Documentation inherited + virtual void setSpecular(const Color& color); + + // Documentation inherited + virtual void setEmissive(double r, double g, double b, double a = 1.0); + + // Documentation inherited + virtual void setEmissive(const Color& color); + + // Documentation inherited + virtual void setTransparency(double transparency); + + // Documentation inherited + virtual void setAlphaFromTexture(bool enabled, double alpha = 0.5, bool two_sided = true); + + // Documentation inherited + virtual void setShininess(double shininess); + + // Documentation inherited + virtual void setReflectivity(double reflectivity); + + // Documentation inherited + virtual void setCastShadows(bool cast_shadows); + + // Documentation inherited + virtual void setReceiveShadows(bool receive_shadows); + + // Documentation inherited + virtual void setReflectionEnabled(bool enabled); + + // Documentation inherited + virtual void setLightingEnabled(bool enabled); + + // Documentation inherited. + virtual void setDepthCheckEnabled(bool enabled); + + // Documentation inherited. + virtual void setDepthWriteEnabled(bool enabled); + + // Documentation inherited + virtual Color getAmbient() const; + + // Documentation inherited + virtual Color getDiffuse() const; + + // Documentation inherited + virtual Color getSpecular() const; + + // Documentation inherited + virtual Color getEmissive() const; + + // Documentation inherited + virtual double getTransparency() const; + + // Documentation inherited + virtual double getReflectivity() const; + + // Documentation inherited + virtual double getShininess() const; + + // Documentation inherited + virtual bool castShadows() const; + + // Documentation inherited + virtual bool receiveShadows() const; + + // Documentation inherited + virtual bool lightingEnabled() const; + + // Documentation inherited + virtual bool depthCheckEnabled() const; + + // Documentation inherited + virtual bool depthWriteEnabled() const; + + // Documentation inherited + virtual bool reflectionEnabled() const; + + // Documentation inherited + virtual bool hasTexture() const; + + // Documentation inherited + virtual std::string getTexture() const; + + // Documentation inherited + virtual void setTexture(const std::string& texture, const Image::ConstPtr& img); + + // Documentation inherited + virtual Image::ConstPtr getTextureData() const; + + // Documentation inherited + virtual void clearTexture(); + + // Documentation inherited + virtual bool hasNormalMap() const; + + // Documentation inherited + virtual std::string getNormalMap() const; + + // Documentation inherited + virtual Image::ConstPtr getNormalMapData() const; + + // Documentation inherited + virtual void setNormalMap(const std::string& normal_map, const Image::ConstPtr& img); + + // Documentation inherited + virtual void clearNormalMap(); + + // Documentation inherited + virtual bool hasRoughnessMap() const; + + // Documentation inherited + virtual std::string getRoughnessMap() const; + + // Documentation inherited + virtual Image::ConstPtr getRoughnessMapData() const; + + // Documentation inherited + virtual void setRoughnessMap(const std::string& roughness_map, const Image::ConstPtr& img); + + // Documentation inherited + virtual void clearRoughnessMap(); + + // Documentation inherited + virtual bool hasMetalnessMap() const; + + // Documentation inherited + virtual std::string getMetalnessMap() const; + + // Documentation inherited + virtual Image::ConstPtr getMetalnessMapData() const; + + // Documentation inherited + virtual void setMetalnessMap(const std::string& metalness_map, const Image::ConstPtr& img); + + // Documentation inherited + virtual void clearMetalnessMap(); + + // Documentation inherited + virtual bool hasEnvironmentMap() const; + + // Documentation inherited + virtual std::string getEnvironmentMap() const; + + // Documentation inherited + virtual Image::ConstPtr getEnvironmentMapData() const; + + // Documentation inherited + virtual void setEnvironmentMap(const std::string& environment_map, const Image::ConstPtr& img); + + // Documentation inherited + virtual void clearEnvironmentMap(); + + // Documentation inherited + virtual bool hasEmissiveMap() const; + + // Documentation inherited + virtual std::string getEmissiveMap() const; + + // Documentation inherited + virtual Image::ConstPtr getEmissiveMapData() const; + + // Documentation inherited + virtual void setEmissiveMap(const std::string& emissive_map, const Image::ConstPtr& img); + + // Documentation inherited + virtual void clearEmissiveMap(); + + // Documentation inherited + virtual bool hasLightMap() const; + + // Documentation inherited + virtual std::string getLightMap() const; + + // Documentation inherited + virtual unsigned int getLightMapTexCoordSet() const; + + // Documentation inherited + virtual void setLightMap(const std::string& light_map, const Image::ConstPtr& img, unsigned int uv_set = 0u); + + // Documentation inherited + virtual Image::ConstPtr getLightMapData() const; + + // Documentation inherited + virtual void clearLightMap(); + + // Documentation inherited + virtual void setRenderOrder(float render_order); + + // Documentation inherited + virtual float getRenderOrder() const; + + // Documentation inherited + virtual void setRoughness(float roughness); + + // Documentation inherited + virtual float getRoughness() const; + + // Documentation inherited + virtual void setMetalness(float metalness); + + // Documentation inherited + virtual float getMetalness() const; + + // Documentation inherited + virtual MaterialType getType() const; + + // Documentation inherited + virtual void setShaderType(ShaderType type); + + // Documentation inherited + virtual ShaderType getShaderType() const; + + // Documentation inherited. + // \sa Material::SetDepthMaterial() + virtual void setDepthMaterial(double far, double near); + + // Documentation inherited. + // \sa Material::VertexShader() const + virtual std::string getVertexShader() const; + + // Documentation inherited. + // \sa Material::VertexShaderParams() + virtual ShaderParams::Ptr getVertexShaderParams(); + + // Documentation inherited. + // \sa Material::SetVertexShader(const std::string &) + virtual void setVertexShader(const std::string& path); + + // Documentation inherited. + // \sa Material::FragmentShader() const + virtual std::string getFragmentShader() const; + + // Documentation inherited. + // \sa Material::FragmentShaderParams() + virtual ShaderParams::Ptr getFragmentShaderParams(); + + // Documentation inherited. + // \sa Material::SetFragmentShader(const std::string &) + virtual void setFragmentShader(const std::string& path); + + // Documentation inherited. + virtual void copyFrom(Material::ConstPtr material); + + // Documentation inherited. + virtual void copyFrom(const Material& material); + + // Documentation inherited + bool textureAlphaEnabled() const; + + // Documentation inherited + double getAlphaThreshold() const; + + // Documentation inherited + bool twoSidedEnabled() const; + +protected: + virtual void reset(); + + /// \brief Material name + std::string name_; + + /// \brief Ambient color + Color ambient_; + + /// \brief Diffuse color + Color diffuse_; + + /// \brief Specular color + Color specular_; + + /// \brief Emissive color + Color emissive_; + + /// \brief Transparent. 1: fully transparent, 0: opaque + double transparency_{ 0.0 }; + + /// \brief Enable alpha channel based texture transparency + bool texture_alpha_enabled_{ false }; + + /// \brief Threshold for alpha channel rejection + double alpha_threshold_{ 0.5 }; + + /// \brief Enable two sided rendering + bool two_sided_enabled_{ false }; + + /// \brief Material render order + double render_order_{ 0.0 }; + + /// \brief Shininess factor + double shininess_{ 0.0 }; + + /// \brief Reflectivity + double reflectivity_{ 0.0 }; + + /// \brief Flag to indicate if dynamic lighting is enabled + bool lighting_enabled_{ false }; + + /// \brief Flag to indicate if depth buffer checking is enabled + bool depth_check_enabled_{ true }; + + /// \brief Flag to indicate if depth buffer writing is enabled + bool depth_write_enabled_{ true }; + + /// \brief Flag to indicate if reflection is enabled + bool reflection_enabled_{ false }; + + /// \brief True if material receives shadows + bool receive_shadows_{ true }; + + /// \brief Set to true to enable object with this material to cast shadows + bool cast_shadows_{ true }; +}; + +} // namespace tesseract_common +#endif // TESSERACT_COMMON_MATERIAL_H diff --git a/tesseract_common/include/tesseract_common/shader_param.h b/tesseract_common/include/tesseract_common/shader_param.h new file mode 100644 index 00000000000..53eea0bb74a --- /dev/null +++ b/tesseract_common/include/tesseract_common/shader_param.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef TESSERACT_COMMON_SHADER_PARAM_H +#define TESSERACT_COMMON_SHADER_PARAM_H + +#include +#include +#include +#include + +namespace tesseract_common +{ +// +/// \brief forward declaration +class ShaderParamPrivate; + +/// \brief a variant type that holds params that can be passed to a shader +class ShaderParam +{ +public: + using Ptr = std::shared_ptr; + using ConstPtr = std::shared_ptr; + + enum ParamType : uint16_t + { + /// \brief Type none + PARAM_NONE = 0, + + /// \brief Float type parameter + PARAM_FLOAT = 1, + + /// \brief Integer type parameter + PARAM_INT = 2, + + /// \brief Float Buffer type parameter + PARAM_FLOAT_BUFFER = 3, + + /// \brief Int Buffer type parameter + PARAM_INT_BUFFER = 4, + + /// \brief texture type parameter + PARAM_TEXTURE = 5, + + /// \brief cube map type parameter + PARAM_TEXTURE_CUBE = 6, + }; + + /// \brief constructor + ShaderParam(); + + /// \brief copy constructor + /// \param[in] _other Another ShaderParam + ShaderParam(const ShaderParam& _other); + + /// \brief destructor + ~ShaderParam(); + + /// \brief Get the type of this parameter + /// \return Type of this parameter + ParamType Type() const; + + /// \brief Get the element count of this parameter's buffer + /// \return Count of elements in this parameter's buffer + uint32_t Count() const; + + /// \brief Set from another ShaderParam + /// \param[in] _other Another ShaderParam + /// \return Reference to this ShaderParam + ShaderParam& operator=(const ShaderParam& _other); + + /// \brief Set this to be a float parameter + /// \param[in] _value Value to set this parameter to + void operator=(const float _value); + + /// \brief Set this to be an integer parameter + /// \param[in] _value Value to set this parameter to + void operator=(const int _value); + + /// \brief Set this to be a texture parameter + /// \param[in] _value Value to set this parameter to + /// \param[in] _type Type of texture + /// \param[in] _uvSetIndex Texture coordinate set index + void SetTexture(const std::string& _value, + ShaderParam::ParamType _type = ShaderParam::ParamType::PARAM_TEXTURE, + uint32_t _uvSetIndex = 0u); + + /// \brief Set this to be a buffer parameter + /// \param[in] _count Number of 32-bit elements in the buffer + void InitializeBuffer(uint32_t _count); + + /// \brief Copy a buffer to this parameter + /// \param[in] _floatBuffer Source buffer to copy from + void UpdateBuffer(float* _floatBuffer); + + /// \brief Copy a buffer to this parameter + /// \param[in] _intBuffer Source buffer to copy from + void UpdateBuffer(int* _intBuffer); + + /// \brief Get the value of this parameter if it is a float + /// \param[out] _value variable the value will be copied to + /// \return true if the parameter is the expected type + bool Value(float* _value) const; + + /// \brief Get the value of this parameter if it is an int + /// \param[out] _value variable the value will be copied to + /// \return true if the parameter is the expected type + bool Value(int* _value) const; + + /// \brief Get the value of this parameter if it is a texture + /// \param[out] _value variable the value will be copied to + /// \param[out] _uvSetIndex Texture coordinate set index + /// \return true if the parameter filled + bool Value(std::string& _value, uint32_t& _uvSetIndex) const; + + /// \brief Get the value of this parameter if it is a buffer + /// \param[out] _buffer variable the value will be copied to + /// \return true if the parameter is the expected type + bool Buffer(std::shared_ptr& _buffer) const; + + /// \brief private implementation +private: + std::unique_ptr dataPtr; +}; +} // namespace tesseract_common + +#endif // TESSERACT_COMMON_SHADER_PARAM_H diff --git a/tesseract_common/include/tesseract_common/shader_params.h b/tesseract_common/include/tesseract_common/shader_params.h new file mode 100644 index 00000000000..1a86ef2041f --- /dev/null +++ b/tesseract_common/include/tesseract_common/shader_params.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef TESSERACT_COMMON_SHADER_PARAMS_H +#define TESSERACT_COMMON_SHADER_PARAMS_H + +#include +#include +#include + +#include + +namespace tesseract_common +{ +// +/// \brief forward declaration +class ShaderParamsPrivate; + +/// \brief a map that holds params to be passed to a shader +class ShaderParams +{ +public: + using Ptr = std::shared_ptr; + using ConstPtr = std::shared_ptr; + + /// \brief forward declaration + class IteratorPrivate; + + /// \brief Iterator for looping through params + /// \remarks implements a forward-iterator + class Iterator + { + /// \brief Default constructor + public: + Iterator(); + + /// \brief Special constructor used by ShaderParams implementation + /// \param[in] _dataPtr Pointer to private data. + explicit Iterator(std::unique_ptr _dataPtr); + + /// \brief Copy constructor + /// \param[in] _iter Another iterator + Iterator(const Iterator& _iter); + + /// \brief Copy assignment + /// \param[in] _iter Another iterator + /// \return this + Iterator& operator=(const Iterator& _iter); + + /// \brief Destructor + ~Iterator(); + + /// \brief Equality operator + /// \param[in] _iter Another iterator + /// \return True if input interator equal to this one, false otherwise. + bool operator==(const Iterator& _iter); + + /// \brief Inequality operator + /// \param[in] _iter Another iterator + /// \return True if input interator is equal to this one, + /// false otherwise + bool operator!=(const Iterator& _iter); + + /// \brief Dereference operator + const std::pair& operator*(); + + /// \brief Arrow dereference operator + const std::pair* operator->(); + + /// \brief prefix increment + Iterator& operator++(); + + /// \brief postfix increment + Iterator operator++(int); + + private: + std::unique_ptr dataPtr; + }; + + /// \brief constructor + ShaderParams(); + + /// \brief destructor + ~ShaderParams(); + + /// \brief Access a param with a given name + /// \param[in] _name Identifier for the parameter + /// \returns parameter reference + ShaderParam& operator[](const std::string& _name); + + /// \brief Access a param with a given name + /// \param[in] _name Identifier for the parameter + /// \returns const parameter reference + const ShaderParam& operator[](const std::string& _name) const; + + /// \brief Iterator to first parameter + /// \remarks Necessary for range-base for loop support + /// \return Iterator pointing to first parameter. + Iterator begin() const; + + /// \brief Iterator to one past last param + /// \remarks Necessary for range-base for loop support + /// \return Iterator pointing to one past last parameter. + Iterator end() const; + + /// \brief Have the params changed? + /// \internal + /// \returns true if the parameters have changed + bool IsDirty() const; + + /// \brief Resets the dirty flag + /// \internal + void ClearDirty(); + + /// \brief private implementation +private: + std::unique_ptr dataPtr; +}; +} // namespace tesseract_common + +#endif // TESSERACT_COMMON_SHADER_PARAMS_H diff --git a/tesseract_common/include/tesseract_common/shader_type.h b/tesseract_common/include/tesseract_common/shader_type.h new file mode 100644 index 00000000000..7eb365a28bf --- /dev/null +++ b/tesseract_common/include/tesseract_common/shader_type.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef TESSERACT_COMMON_SHADER_TYPE_H +#define TESSERACT_COMMON_SHADER_TYPE_H + +#include + +namespace tesseract_common +{ +/// \enum ShaderType ShaderType.hh gz/rendering/ShaderType.hh +/// \brief Available types of shaders. Note that not all rendering-engines +/// will be able to use each type. They will instead default to the closest +/// alternative. +enum class ShaderType +{ + /// \brief Unknown or errant type + ST_UNKNOWN = 0, + + /// \brief Per pixel lighting shader + ST_PIXEL = 1, + + /// \brief Per vertex lighting shader + ST_VERTEX = 2, + + /// \brief Object-space normal map shader + ST_NORM_OBJ = 3, + + /// \brief Tangent-space normal map shader + ST_NORM_TAN = 4, + + /// \brief Total number of shader types + ST_COUNT = 5, +}; + +/// \class ShaderUtil ShaderType.hh gz/rendering/ShaderType.hh +/// \brief Provides supporting functions for ShaderType enum +class ShaderUtil +{ +public: + /// \brief Determine if given type is valid ShaderType enum + /// \param[in] type Enum value to be evaluated + /// \return True if the given type is valid + static bool isValid(ShaderType type); + + /// \brief Sanitize given type. If the given value is invalid, + /// ST_UNKNOWN will be returned, otherwise input will be returned + /// unchanged. + /// \param[in] type Shader type to be sanitized + /// \return The santized shader type + static ShaderType sanitize(ShaderType type); + + /// \brief Get human-readable name for shader type value. + /// \param[in] type Shader type enum value + /// \return The type name + static std::string getName(ShaderType type); + + /// \brief Get enum value by human-readable name. The given string should + /// match watch is returned by GetName. If an invalid name is given, + /// ST_UNKNOWN will be returned. + /// \param[in] name Name of the shader type to be retrieved + /// \return The specified ShaderType enum value + static ShaderType getEnum(const std::string& name); + + /// \brief Array of human-readable names for each ShaderType +private: + static const char* names[static_cast(ShaderType::ST_COUNT)]; +}; +} // namespace tesseract_common + +#endif // TESSERACT_COMMON_SHADER_TYPE_H diff --git a/tesseract_common/src/color.cpp b/tesseract_common/src/color.cpp new file mode 100644 index 00000000000..d06379139b6 --- /dev/null +++ b/tesseract_common/src/color.cpp @@ -0,0 +1,503 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include + +#include +#include + +namespace +{ +// Use constexpr storage for the Color constants, to avoid the C++ static +// initialization order fiasco. +constexpr tesseract_common::Color gWhite = tesseract_common::Color(1, 1, 1, 1); +constexpr tesseract_common::Color gBlack = tesseract_common::Color(0, 0, 0, 1); +constexpr tesseract_common::Color gRed = tesseract_common::Color(1, 0, 0, 1); +constexpr tesseract_common::Color gGreen = tesseract_common::Color(0, 1, 0, 1); +constexpr tesseract_common::Color gBlue = tesseract_common::Color(0, 0, 1, 1); +constexpr tesseract_common::Color gYellow = tesseract_common::Color(1, 1, 0, 1); +constexpr tesseract_common::Color gMagenta = tesseract_common::Color(1, 0, 1, 1); +constexpr tesseract_common::Color gCyan = tesseract_common::Color(0, 1, 1, 1); + +} // namespace + +namespace tesseract_common +{ +const Color& Color::White = gWhite; +const Color& Color::Black = gBlack; +const Color& Color::Red = gRed; +const Color& Color::Green = gGreen; +const Color& Color::Blue = gBlue; +const Color& Color::Yellow = gYellow; +const Color& Color::Magenta = gMagenta; +const Color& Color::Cyan = gCyan; + +////////////////////////////////////////////////// +void Color::reset() +{ + this->r_ = this->g_ = this->b_ = 0; + this->a_ = 1; +} + +////////////////////////////////////////////////// +void Color::set(float r, float g, float b, float a) +{ + this->r_ = r; + this->g_ = g; + this->b_ = b; + this->a_ = a; + + this->Clamp(); +} + +////////////////////////////////////////////////// +void Color::setFromHSV(float h, float s, float v) +{ + int i; + float f, p, q, t; + + h = static_cast(static_cast(h < 0 ? 0 : h) % 360); + + if (almostEqualRelativeAndAbs(s, 0.0f)) + { + // acromatic (grey) + this->r_ = this->g_ = this->b_ = v; + return; + } + + // sector 0 - 5 + h /= 60; + + i = static_cast(floor(h)); + + f = h - i; + + p = v * (1 - s); + q = v * (1 - s * f); + t = v * (1 - s * (1 - f)); + + switch (i) + { + case 0: + this->r_ = v; + this->g_ = t; + this->b_ = p; + break; + case 1: + this->r_ = q; + this->g_ = v; + this->b_ = p; + break; + case 2: + this->r_ = p; + this->g_ = v; + this->b_ = t; + break; + case 3: + this->r_ = p; + this->g_ = q; + this->b_ = v; + break; + case 4: + this->r_ = t; + this->g_ = p; + this->b_ = v; + break; + case 5: + default: + this->r_ = v; + this->g_ = p; + this->b_ = q; + break; + } + + this->Clamp(); +} + +////////////////////////////////////////////////// +Eigen::Vector3f Color::getHSV() const +{ + Eigen::Vector3f hsv; + + float min = std::min(this->r_, std::min(this->g_, this->b_)); + float max = std::max(this->r_, std::max(this->g_, this->b_)); + float delta = max - min; + + hsv.y() = delta / max; + hsv.z() = max; + + if (almostEqualRelativeAndAbs(delta, 0.0f)) + { + hsv.x() = 0.0; + hsv.y() = 0.0; + } + else if (almostEqualRelativeAndAbs(this->r_, min)) + hsv.x() = 3 - ((this->g_ - this->b_) / delta); + else if (almostEqualRelativeAndAbs(this->g_, min)) + hsv.x() = 5 - ((this->b_ - this->r_) / delta); + else + hsv.x() = 1 - ((this->r_ - this->g_) / delta); + + hsv.x() *= 60.0; + return hsv; +} + +////////////////////////////////////////////////// +Eigen::Vector3f Color::getYUV() const +{ + Eigen::Vector3f yuv; + + yuv.x() = 0.299f * this->r_ + 0.587f * this->g_ + 0.114f * this->b_; + yuv.y() = -0.1679f * this->r_ - 0.332f * this->g_ + 0.5f * this->b_ + 0.5f; + yuv.z() = 0.5f * this->r_ - 0.4189f * this->g_ - 0.08105f * this->b_ + 0.5f; + + yuv.x() = yuv.x() < 0 ? 0 : yuv.x(); + yuv.x() = yuv.x() > 255 ? 255.0f : yuv.x(); + + yuv.y() = yuv.y() < 0 ? 0 : yuv.y(); + yuv.y() = yuv.y() > 255 ? 255.0f : yuv.y(); + + yuv.z() = yuv.z() < 0 ? 0 : yuv.z(); + yuv.z() = yuv.z() > 255 ? 255.0f : yuv.z(); + + return yuv; +} + +////////////////////////////////////////////////// +void Color::setFromYUV(float y, float u, float v) +{ + this->r_ = y + 1.140f * v; + this->g_ = y - 0.395f * u - 0.581f * v; + this->b_ = y + 2.032f * u; + this->Clamp(); +} + +////////////////////////////////////////////////// +float Color::operator[](const unsigned int index) { return (*static_cast(this))[index]; } + +////////////////////////////////////////////////// +float Color::operator[](const unsigned int _index) const +{ + switch (_index) + { + case 0: + return this->r_; + case 1: + return this->g_; + case 2: + return this->b_; + case 3: + return this->a_; + default: + break; + } + + return std::numeric_limits::quiet_NaN(); +} + +////////////////////////////////////////////////// +Color::RGBA Color::asRGBA() const +{ + uint8_t val8; + unsigned int val32; + + // Convert to 32bit pattern + // (RGBA = 8888) + + val8 = static_cast(this->r_ * 255); + val32 = val8 << 24; + + val8 = static_cast(this->g_ * 255); + val32 += val8 << 16; + + val8 = static_cast(this->b_ * 255); + val32 += val8 << 8; + + val8 = static_cast(this->a_ * 255); + val32 += val8; + + return val32; +} + +////////////////////////////////////////////////// +Color::BGRA Color::asBGRA() const +{ + uint8_t val8; + unsigned int val32 = 0; + + // Convert to 32bit pattern + // (BGRA = 8888) + + val8 = static_cast(this->b_ * 255); + val32 = val8 << 24; + + val8 = static_cast(this->g_ * 255); + val32 += val8 << 16; + + val8 = static_cast(this->r_ * 255); + val32 += val8 << 8; + + val8 = static_cast(this->a_ * 255); + val32 += val8; + + return val32; +} + +////////////////////////////////////////////////// +Color::ARGB Color::asARGB() const +{ + uint8_t val8; + unsigned int val32 = 0; + + // Convert to 32bit pattern + // (ARGB = 8888) + + val8 = static_cast(this->a_ * 255); + val32 = val8 << 24; + + val8 = static_cast(this->r_ * 255); + val32 += val8 << 16; + + val8 = static_cast(this->g_ * 255); + val32 += val8 << 8; + + val8 = static_cast(this->b_ * 255); + val32 += val8; + + return val32; +} + +////////////////////////////////////////////////// +Color::ABGR Color::asABGR() const +{ + uint8_t val8; + unsigned int val32 = 0; + + // Convert to 32bit pattern + // (ABGR = 8888) + + val8 = static_cast(this->a_ * 255); + val32 = val8 << 24; + + val8 = static_cast(this->b_ * 255); + val32 += val8 << 16; + + val8 = static_cast(this->g_ * 255); + val32 += val8 << 8; + + val8 = static_cast(this->r_ * 255); + val32 += val8; + + return val32; +} + +////////////////////////////////////////////////// +void Color::setFromRGBA(RGBA v) +{ + unsigned int val32 = v; + + // Convert from 32bit pattern + // (RGBA = 8888) + + this->r_ = ((val32 >> 24) & 0xFF) / 255.0f; + this->g_ = ((val32 >> 16) & 0xFF) / 255.0f; + this->b_ = ((val32 >> 8) & 0xFF) / 255.0f; + this->a_ = (val32 & 0xFF) / 255.0f; +} + +////////////////////////////////////////////////// +void Color::setFromBGRA(BGRA v) +{ + unsigned int val32 = v; + + // Convert from 32bit pattern + // (BGRA = 8888) + + this->b_ = ((val32 >> 24) & 0xFF) / 255.0f; + this->g_ = ((val32 >> 16) & 0xFF) / 255.0f; + this->r_ = ((val32 >> 8) & 0xFF) / 255.0f; + this->a_ = (val32 & 0xFF) / 255.0f; +} + +////////////////////////////////////////////////// +void Color::setFromARGB(ARGB v) +{ + unsigned int val32 = v; + + // Convert from 32bit pattern + // (ARGB = 8888) + + this->a_ = ((val32 >> 24) & 0xFF) / 255.0f; + this->r_ = ((val32 >> 16) & 0xFF) / 255.0f; + this->g_ = ((val32 >> 8) & 0xFF) / 255.0f; + this->b_ = (val32 & 0xFF) / 255.0f; +} + +////////////////////////////////////////////////// +void Color::setFromABGR(ABGR v) +{ + unsigned int val32 = v; + + // Convert from 32bit pattern + // (ABGR = 8888) + + this->a_ = ((val32 >> 24) & 0xFF) / 255.0f; + this->b_ = ((val32 >> 16) & 0xFF) / 255.0f; + this->g_ = ((val32 >> 8) & 0xFF) / 255.0f; + this->r_ = (val32 & 0xFF) / 255.0f; +} + +////////////////////////////////////////////////// +Color Color::operator+(const Color& pt) const +{ + return Color(this->r_ + pt.r_, this->g_ + pt.g_, this->b_ + pt.b_, this->a_ + pt.a_); +} + +////////////////////////////////////////////////// +Color Color::operator+(float v) const { return Color(this->r_ + v, this->g_ + v, this->b_ + v, this->a_ + v); } + +////////////////////////////////////////////////// +const Color& Color::operator+=(const Color& pt) +{ + this->r_ += pt.r_; + this->g_ += pt.g_; + this->b_ += pt.b_; + this->a_ += pt.a_; + + this->Clamp(); + + return *this; +} + +////////////////////////////////////////////////// +Color Color::operator-(const Color& pt) const +{ + return Color(this->r_ - pt.r_, this->g_ - pt.g_, this->b_ - pt.b_, this->a_ - pt.a_); +} + +////////////////////////////////////////////////// +Color Color::operator-(float v) const { return Color(this->r_ - v, this->g_ - v, this->b_ - v, this->a_ - v); } + +////////////////////////////////////////////////// +const Color& Color::operator-=(const Color& pt) +{ + this->r_ -= pt.r_; + this->g_ -= pt.g_; + this->b_ -= pt.b_; + this->a_ -= pt.a_; + + this->Clamp(); + + return *this; +} + +////////////////////////////////////////////////// +const Color Color::operator/(float pt) const +{ + return Color(this->r_ / pt, this->g_ / pt, this->b_ / pt, this->a_ / pt); +} + +////////////////////////////////////////////////// +const Color Color::operator/(const Color& _pt) const +{ + return Color(this->r_ / _pt.r_, this->g_ / _pt.g_, this->b_ / _pt.b_, this->a_ / _pt.a_); +} + +////////////////////////////////////////////////// +const Color& Color::operator/=(const Color& pt) +{ + this->r_ /= pt.r_; + this->g_ /= pt.g_; + this->b_ /= pt.b_; + this->a_ /= pt.a_; + + this->Clamp(); + + return *this; +} + +////////////////////////////////////////////////// +const Color Color::operator*(float pt) const +{ + return Color(this->r_ * pt, this->g_ * pt, this->b_ * pt, this->a_ * pt); +} + +////////////////////////////////////////////////// +const Color Color::operator*(const Color& _pt) const +{ + return Color(this->r_ * _pt.r_, this->g_ * _pt.g_, this->b_ * _pt.b_, this->a_ * _pt.a_); +} + +////////////////////////////////////////////////// +const Color& Color::operator*=(const Color& pt) +{ + this->r_ *= pt.r_; + this->g_ *= pt.g_; + this->b_ *= pt.b_; + this->a_ *= pt.a_; + + this->Clamp(); + + return *this; +} + +////////////////////////////////////////////////// +bool Color::operator==(const Color& pt) const +{ + return almostEqualRelativeAndAbs(this->r_, pt.r_) && almostEqualRelativeAndAbs(this->g_, pt.g_) && + almostEqualRelativeAndAbs(this->b_, pt.b_) && almostEqualRelativeAndAbs(this->a_, pt.a_); +} + +////////////////////////////////////////////////// +bool Color::operator!=(const Color& pt) const { return !(*this == pt); } + +////////////////////////////////////////////////// +float Color::getR() const { return this->r_; } + +////////////////////////////////////////////////// +float Color::getG() const { return this->g_; } + +////////////////////////////////////////////////// +float Color::getB() const { return this->b_; } + +////////////////////////////////////////////////// +float Color::getA() const { return this->a_; } + +////////////////////////////////////////////////// +float& Color::getR() { return this->r_; } + +////////////////////////////////////////////////// +float& Color::getG() { return this->g_; } + +////////////////////////////////////////////////// +float& Color::getB() { return this->b_; } + +////////////////////////////////////////////////// +float& Color::getA() { return this->a_; } + +////////////////////////////////////////////////// +void Color::setR(float r) { this->r_ = r; } + +////////////////////////////////////////////////// +void Color::setG(float g) { this->g_ = g; } + +////////////////////////////////////////////////// +void Color::setB(float b) { this->b_ = b; } + +////////////////////////////////////////////////// +void Color::setA(float a) { this->a_ = a; } +} // namespace tesseract_common diff --git a/tesseract_common/src/image.cpp b/tesseract_common/src/image.cpp new file mode 100644 index 00000000000..547afe5b347 --- /dev/null +++ b/tesseract_common/src/image.cpp @@ -0,0 +1,681 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifdef BOOL +#undef BOOL +#endif +#include + +#include +#include + +#include + +#include +#include + +static int count = 0; + +namespace tesseract_common +{ +/// \brief Private data class +class ImagePrivate +{ +public: + /// \brief bitmap data + FIBITMAP* bitmap; + + /// \brief path name of the image file + std::string fullName; + + /// \brief Implementation of GetData + /// \deprecated remove once the Data functions using raw pointers + /// are removed, in favor of returning vectors of bytes + void dataImpl(unsigned char** data, unsigned int& count, FIBITMAP* img) const; + + /// \brief Implementation of Data, returns vector of bytes + std::vector dataImpl(FIBITMAP* img) const; + + /// \brief Returns true if SwapRedBlue can and should be called + /// If it returns false, it may not be safe to call SwapRedBlue + /// (it could lead to memory corruption!). See CanSwapRedBlue + /// \return True if we should call SwapRedBlue + bool shouldSwapRedBlue() const; + + /// \brief Returns true if SwapRedBlue is safe to be called + /// \return False if it is NOT safe to call SwapRedBlue + bool canSwapRedBlue() const; + + /// \brief Swap red and blue pixels + /// \param[in] _width Width of the image + /// \param[in] _height Height of the image + /// \return bitmap data with red and blue pixels swapped + FIBITMAP* swapRedBlue(unsigned int width, unsigned int height) const; + + /// \brief Get pixel value at specified index. + /// \param[in] _dib Pointer to Freeimage bitmap + /// \param[in] _x Pixel index in horizontal direction + /// \param[in] _y Pixel index in vertical direction + /// \param[out] _color Pixel value at specified index + /// \return TRUE value if the pixel index was found and the color + /// value set, FALSE otherwise. + BOOL getPixelIndex(FIBITMAP* dib, unsigned x, unsigned y, Color& color) const; +}; + +////////////////////////////////////////////////// +Image::Image(const std::string& filename) : data_(std::make_unique()) +{ + if (count == 0) + FreeImage_Initialise(); + + count++; + + this->data_->bitmap = nullptr; + if (!filename.empty()) + { + if (!filename.empty()) + this->load(filename); + else + CONSOLE_BRIDGE_logError("Unable to find image[%s]", filename); + } +} + +////////////////////////////////////////////////// +Image::~Image() +{ + count--; + + if (this->data_->bitmap) + FreeImage_Unload(this->data_->bitmap); + this->data_->bitmap = NULL; + + if (count == 0) + FreeImage_DeInitialise(); +} + +////////////////////////////////////////////////// +int Image::load(const std::string& filename) +{ + this->data_->fullName = filename; + if (tesseract_common::fs::exists((this->data_->fullName))) + { + FREE_IMAGE_FORMAT fifmt = FreeImage_GetFIFFromFilename(this->data_->fullName.c_str()); + + if (this->data_->bitmap) + FreeImage_Unload(this->data_->bitmap); + this->data_->bitmap = NULL; + + if (fifmt == FIF_PNG) + { + this->data_->bitmap = FreeImage_Load(fifmt, this->data_->fullName.c_str(), PNG_DEFAULT); + } + else if (fifmt == FIF_JPEG) + { + this->data_->bitmap = FreeImage_Load(fifmt, this->data_->fullName.c_str(), JPEG_DEFAULT); + } + else if (fifmt == FIF_BMP) + { + this->data_->bitmap = FreeImage_Load(fifmt, this->data_->fullName.c_str(), BMP_DEFAULT); + } + else + { + CONSOLE_BRIDGE_logError("Unknown image format[%s]", this->data_->fullName); + return -1; + } + + return 0; + } + + CONSOLE_BRIDGE_logError("Unable to open image file[%s]", this->data_->fullName); + return -1; +} + +////////////////////////////////////////////////// +void Image::savePNG(const std::string& filename) +{ + FreeImage_Save(FIF_PNG, this->data_->bitmap, filename.c_str(), PNG_DEFAULT); +} + +////////////////////////////////////////////////// +void Image::savePNGToBuffer(std::vector& buffer) +{ + FIMEMORY* hmem = FreeImage_OpenMemory(); + FreeImage_SaveToMemory(FIF_PNG, this->data_->bitmap, hmem); + unsigned char* memBuffer = nullptr; +#ifndef _WIN32 + unsigned int sizeInBytes = 0; +#else + DWORD sizeInBytes = 0; +#endif + FreeImage_AcquireMemory(hmem, &memBuffer, &sizeInBytes); + buffer.resize(sizeInBytes); + std::memcpy(buffer.data(), memBuffer, sizeInBytes); + FreeImage_CloseMemory(hmem); +} + +////////////////////////////////////////////////// +void Image::setFromData(const unsigned char* data, + unsigned int width, + unsigned int height, + Image::PixelFormatType format) +{ + if (this->data_->bitmap) + FreeImage_Unload(this->data_->bitmap); + this->data_->bitmap = NULL; + + // int redmask = FI_RGBA_RED_MASK; + int redmask = 0x0000ff; + + // int greenmask = FI_RGBA_GREEN_MASK; + int greenmask = 0x00ff00; + + // int bluemask = FI_RGBA_BLUE_MASK; + int bluemask = 0xff0000; + + unsigned int bpp; + int scanlineBytes; + + if (format == L_INT8) + { + bpp = 8; + scanlineBytes = width; + } + else if (format == RGB_INT8) + { + bpp = 24; + redmask = 0xff0000; + greenmask = 0x00ff00; + bluemask = 0x0000ff; + scanlineBytes = width * 3; + } + else if (format == RGBA_INT8) + { + bpp = 32; + redmask = 0xff000000; + greenmask = 0x00ff0000; + bluemask = 0x0000ff00; + scanlineBytes = width * 4; + } + else if (format == BGR_INT8) + { + bpp = 24; + redmask = 0x0000ff; + greenmask = 0x00ff00; + bluemask = 0xff0000; + scanlineBytes = width * 3; + } + else + { + CONSOLE_BRIDGE_logError("Unable to handle format[%s]", format); + return; + } + + this->data_->bitmap = FreeImage_ConvertFromRawBits( + const_cast(data), width, height, scanlineBytes, bpp, redmask, greenmask, bluemask, true); + + if (this->data_->shouldSwapRedBlue()) + { + FIBITMAP* toDelete = this->data_->bitmap; + this->data_->bitmap = this->data_->swapRedBlue(this->width(), this->height()); + FreeImage_Unload(toDelete); + } +} + +////////////////////////////////////////////////// +void Image::setFromCompressedData(unsigned char* data, unsigned int size, Image::PixelFormatType format) +{ + if (this->data_->bitmap) + FreeImage_Unload(this->data_->bitmap); + this->data_->bitmap = nullptr; + + if (format == COMPRESSED_PNG) + { + FIMEMORY* fiMem = FreeImage_OpenMemory(data, size); + this->data_->bitmap = FreeImage_LoadFromMemory(FIF_PNG, fiMem); + FreeImage_CloseMemory(fiMem); + } + else + { + CONSOLE_BRIDGE_logError("Unable to handle format[%s]", format); + return; + } +} + +////////////////////////////////////////////////// +int Image::getPitch() const { return FreeImage_GetLine(this->data_->bitmap); } + +////////////////////////////////////////////////// +std::vector Image::getRGBData() const +{ + std::vector data; + + FIBITMAP* tmp = this->data_->bitmap; + FIBITMAP* tmp2 = nullptr; + if (this->data_->shouldSwapRedBlue()) + { + tmp = this->data_->swapRedBlue(this->width(), this->height()); + tmp2 = tmp; + } + tmp = FreeImage_ConvertTo24Bits(tmp); + data = this->data_->dataImpl(tmp); + FreeImage_Unload(tmp); + if (tmp2) + FreeImage_Unload(tmp2); + + return data; +} + +////////////////////////////////////////////////// +std::vector Image::getRGBAData() const +{ + std::vector data; + + FIBITMAP* tmp = this->data_->bitmap; + FIBITMAP* tmp2 = nullptr; + if (this->data_->shouldSwapRedBlue()) + { + tmp = this->data_->swapRedBlue(this->width(), this->height()); + tmp2 = tmp; + } + tmp = FreeImage_ConvertTo32Bits(tmp); + data = this->data_->dataImpl(tmp); + FreeImage_Unload(tmp); + if (tmp2) + FreeImage_Unload(tmp2); + + return data; +} + +////////////////////////////////////////////////// +std::vector Image::getData() const +{ + std::vector data; + if (this->data_->shouldSwapRedBlue()) + { + FIBITMAP* tmp = this->data_->swapRedBlue(this->width(), this->height()); + data = this->data_->dataImpl(tmp); + FreeImage_Unload(tmp); + } + else + { + data = this->data_->dataImpl(this->data_->bitmap); + } + return data; +} + +////////////////////////////////////////////////// +std::vector ImagePrivate::dataImpl(FIBITMAP* img) const +{ + int redmask = FI_RGBA_RED_MASK; + // int bluemask = 0x00ff0000; + + int greenmask = FI_RGBA_GREEN_MASK; + // int greenmask = 0x0000ff00; + + int bluemask = FI_RGBA_BLUE_MASK; + // int redmask = 0x000000ff; + + int scanWidth = FreeImage_GetLine(img); + + std::vector data(scanWidth * FreeImage_GetHeight(img)); + + FreeImage_ConvertToRawBits( + reinterpret_cast(&data[0]), img, scanWidth, FreeImage_GetBPP(img), redmask, greenmask, bluemask, true); + + return data; +} + +////////////////////////////////////////////////// +void ImagePrivate::dataImpl(unsigned char** data, unsigned int& count, FIBITMAP* img) const +{ + int redmask = FI_RGBA_RED_MASK; + // int bluemask = 0x00ff0000; + + int greenmask = FI_RGBA_GREEN_MASK; + // int greenmask = 0x0000ff00; + + int bluemask = FI_RGBA_BLUE_MASK; + // int redmask = 0x000000ff; + + int scanWidth = FreeImage_GetLine(img); + + if (*data) + delete[] * data; + + count = scanWidth * FreeImage_GetHeight(img); + *data = new unsigned char[count]; + + FreeImage_ConvertToRawBits( + reinterpret_cast(*data), img, scanWidth, FreeImage_GetBPP(img), redmask, greenmask, bluemask, true); + +#ifdef FREEIMAGE_COLORORDER + // cppcheck-suppress ConfigurationNotChecked + if (FREEIMAGE_COLORORDER != FREEIMAGE_COLORORDER_RGB) + { +#else +#ifdef FREEIMAGE_BIGENDIAN + if (false) + { +#else + { +#endif +#endif + // FIXME: why shift by 2 pixels? + // this breaks heighmaps by wrapping artificially + // int i = 0; + // for (unsigned int y = 0; y < this->Height(); ++y) + // { + // for (unsigned int x = 0; x < this->Width(); ++x) + // { + // std::swap((*_data)[i], (*_data)[i+2]); + // unsigned int d = FreeImage_GetBPP(this->data_->bitmap)/8; + // i += d; + // } + // } + } +} + +////////////////////////////////////////////////// +unsigned int Image::width() const +{ + if (!this->valid()) + return 0; + + return FreeImage_GetWidth(this->data_->bitmap); +} + +////////////////////////////////////////////////// +unsigned int Image::height() const +{ + if (!this->valid()) + return 0; + + return FreeImage_GetHeight(this->data_->bitmap); +} + +////////////////////////////////////////////////// +unsigned int Image::getBPP() const +{ + if (!this->valid()) + return 0; + + return FreeImage_GetBPP(this->data_->bitmap); +} + +////////////////////////////////////////////////// +Color Image::getPixel(unsigned int x, unsigned int y) const +{ + Color clr; + + if (!this->valid()) + return clr; + + FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(this->data_->bitmap); + + if (type == FIC_RGB || type == FIC_RGBALPHA) + { + RGBQUAD firgb; + + if (FreeImage_GetPixelColor(this->data_->bitmap, x, y, &firgb) == FALSE) + { + CONSOLE_BRIDGE_logError("Image: Coordinates out of range[%f, %f]", x, y); + return clr; + } + clr.set(firgb.rgbRed, firgb.rgbGreen, firgb.rgbBlue); + } + else + { + if (this->data_->getPixelIndex(this->data_->bitmap, x, y, clr) == FALSE) + { + CONSOLE_BRIDGE_logError("Image: Coordinates out of range[%f, %f]", x, y); + return clr; + } + } + + return clr; +} + +////////////////////////////////////////////////// +Color Image::getAvgColor() const +{ + unsigned int x, y; + double rsum, gsum, bsum; + Color pixel; + + rsum = gsum = bsum = 0.0; + for (y = 0; y < this->height(); ++y) + { + for (x = 0; x < this->width(); ++x) + { + pixel = this->getPixel(x, y); + rsum += pixel.getR(); + gsum += pixel.getG(); + bsum += pixel.getB(); + } + } + + rsum /= (this->width() * this->height()); + gsum /= (this->width() * this->height()); + bsum /= (this->width() * this->height()); + + return Color(rsum, gsum, bsum); +} + +////////////////////////////////////////////////// +Color Image::getMaxColor() const +{ + unsigned int x, y; + Color clr; + Color maxClr; + + maxClr.set(0, 0, 0, 0); + + if (!this->valid()) + return clr; + + FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(this->data_->bitmap); + + if (type == FIC_RGB || type == FIC_RGBALPHA) + { + RGBQUAD firgb; + + for (y = 0; y < this->height(); y++) + { + for (x = 0; x < this->width(); x++) + { + clr.set(0, 0, 0, 0); + + if (FALSE == FreeImage_GetPixelColor(this->data_->bitmap, x, y, &firgb)) + { + CONSOLE_BRIDGE_logError("Image: Coordinates out of range[%f, %f]", x, y); + continue; + } + clr.set(firgb.rgbRed, firgb.rgbGreen, firgb.rgbBlue); + + if (clr.getR() + clr.getG() + clr.getB() > maxClr.getR() + maxClr.getG() + maxClr.getB()) + { + maxClr = clr; + } + } + } + } + else + { + for (y = 0; y < this->height(); y++) + { + for (x = 0; x < this->width(); x++) + { + clr.set(0, 0, 0, 0); + + if (this->data_->getPixelIndex(this->data_->bitmap, x, y, clr) == FALSE) + + { + CONSOLE_BRIDGE_logError("Image: Coordinates out of range[%f, %f]", x, y); + continue; + } + + if (clr.getR() + clr.getG() + clr.getB() > maxClr.getR() + maxClr.getG() + maxClr.getB()) + { + maxClr = clr; + } + } + } + } + + return maxClr; +} + +////////////////////////////////////////////////// +BOOL ImagePrivate::getPixelIndex(FIBITMAP* _dib, unsigned _x, unsigned _y, Color& _color) const +{ + if (!_dib) + return FALSE; + + FREE_IMAGE_TYPE imageType = FreeImage_GetImageType(_dib); + // 8 bit images + if (imageType == FIT_BITMAP) + { + BYTE byteValue; + // FreeImage_GetPixelIndex should also work with 1 and 4 bit images + if (FreeImage_GetPixelIndex(_dib, _x, _y, &byteValue) == FALSE) + { + return FALSE; + } + + unsigned int bpp = FreeImage_GetBPP(_dib); + // convert to float value between 0-1 + float value = byteValue / static_cast(((1 << (bpp)) - 1)); + _color.set(value, value, value); + } + // 16 bit images + else if (imageType == FIT_UINT16) + { + if ((_x < FreeImage_GetWidth(_dib)) && (_y < FreeImage_GetHeight(_dib))) + { + WORD* bits = reinterpret_cast(FreeImage_GetScanLine(_dib, _y)); + uint16_t word = static_cast(bits[_x]); + // convert to float value between 0-1 + float value = word / static_cast(std::numeric_limits::max()); + _color.set(value, value, value); + } + else + { + return FALSE; + } + } + return TRUE; +} + +////////////////////////////////////////////////// +void Image::rescale(int width, int height) +{ + this->data_->bitmap = FreeImage_Rescale(this->data_->bitmap, width, height, FILTER_LANCZOS3); +} + +////////////////////////////////////////////////// +bool Image::valid() const { return this->data_->bitmap != nullptr; } + +////////////////////////////////////////////////// +std::string Image::getFilename() const { return this->data_->fullName; } + +////////////////////////////////////////////////// +Image::PixelFormatType Image::getPixelFormat() const +{ + Image::PixelFormatType fmt = UNKNOWN_PIXEL_FORMAT; + FREE_IMAGE_TYPE type = FreeImage_GetImageType(this->data_->bitmap); + + unsigned int redMask = FreeImage_GetRedMask(this->data_->bitmap); + unsigned int bpp = this->getBPP(); + + if (type == FIT_BITMAP) + { + if (bpp == 8) + fmt = L_INT8; + else if (bpp == 16) + fmt = L_INT16; + else if (bpp == 24) + redMask == 0xff0000 ? fmt = RGB_INT8 : fmt = BGR_INT8; + else if (bpp == 32) + { + redMask == 0xff0000 || redMask == 0xff000000 ? fmt = RGBA_INT8 : fmt = BGRA_INT8; + } + } + else if (type == FIT_RGB16) + fmt = RGB_INT16; + else if (type == FIT_RGBF) + fmt = RGB_FLOAT32; + else if (type == FIT_UINT16 || type == FIT_INT16) + fmt = L_INT16; + + return fmt; +} + +///////////////////////////////////////////////// +Image::PixelFormatType Image::convertPixelFormat(const std::string& format) +{ + // Handle old format strings + if (format == "L8" || format == "L_INT8") + return L_INT8; + else if (format == "R8G8B8" || format == "RGB_INT8") + return RGB_INT8; + + // Handle BAYER_BGGR8 since it is after PIXEL_FORMAT_COUNT in the enum + if (format == "BAYER_BGGR8") + { + return BAYER_BGGR8; + } + + for (unsigned int i = 0; i < PIXEL_FORMAT_COUNT; ++i) + if (PixelFormatNames[i] == format) + return static_cast(i); + + return UNKNOWN_PIXEL_FORMAT; +} + +////////////////////////////////////////////////// +bool ImagePrivate::shouldSwapRedBlue() const +{ + return canSwapRedBlue() && FREEIMAGE_COLORORDER != FREEIMAGE_COLORORDER_RGB; +} + +////////////////////////////////////////////////// +bool ImagePrivate::canSwapRedBlue() const +{ + const unsigned bpp = FreeImage_GetBPP(this->bitmap); + return bpp == 24u || bpp == 32u; +} + +////////////////////////////////////////////////// +FIBITMAP* ImagePrivate::swapRedBlue(unsigned int width, unsigned int height) const +{ + FIBITMAP* copy = FreeImage_Copy(this->bitmap, 0, 0, width, height); + + const unsigned bytesperpixel = FreeImage_GetBPP(this->bitmap) / 8; + const unsigned pitch = FreeImage_GetPitch(this->bitmap); + const unsigned lineSize = FreeImage_GetLine(this->bitmap); + + BYTE* line = FreeImage_GetBits(copy); + for (unsigned y = 0; y < height; ++y, line += pitch) + { + for (BYTE* pixel = line; pixel < line + lineSize; pixel += bytesperpixel) + { + std::swap(pixel[0], pixel[2]); + } + } + + return copy; +} +} // namespace tesseract_common diff --git a/tesseract_common/src/material.cpp b/tesseract_common/src/material.cpp new file mode 100644 index 00000000000..4f1e4232c13 --- /dev/null +++ b/tesseract_common/src/material.cpp @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2015 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +namespace tesseract_common +{ +////////////////////////////////////////////////// +Material::Material(std::string name) : name_(std::move(name)) {} + +////////////////////////////////////////////////// +Material::~Material() {} + +////////////////////////////////////////////////// +std::string Material::getName() const { return name_; } + +////////////////////////////////////////////////// +void Material::setAmbient(double r, double g, double b, double a) { setAmbient(Color(r, g, b, a)); } + +////////////////////////////////////////////////// +void Material::setAmbient(const Color& color) { ambient_ = color; } + +////////////////////////////////////////////////// +void Material::setDiffuse(double r, double g, double b, double a) { setDiffuse(Color(r, g, b, a)); } + +////////////////////////////////////////////////// +void Material::setDiffuse(const Color& color) { diffuse_ = color; } + +////////////////////////////////////////////////// +void Material::setSpecular(double r, double g, double b, double a) { setSpecular(Color(r, g, b, a)); } + +////////////////////////////////////////////////// +void Material::setSpecular(const Color& color) { specular_ = color; } + +////////////////////////////////////////////////// +void Material::setEmissive(double r, double g, double b, double a) { setEmissive(Color(r, g, b, a)); } + +////////////////////////////////////////////////// +void Material::setEmissive(const Color& color) { emissive_ = color; } + +////////////////////////////////////////////////// +void Material::setShininess(double shininess) { shininess_ = shininess; } + +////////////////////////////////////////////////// +void Material::setTransparency(double transparency) { transparency_ = transparency; } + +////////////////////////////////////////////////// +void Material::setAlphaFromTexture(bool enabled, double alpha, bool two_sided) +{ + texture_alpha_enabled_ = enabled; + alpha_threshold_ = alpha; + two_sided_enabled_ = two_sided; +} + +////////////////////////////////////////////////// +bool Material::textureAlphaEnabled() const { return texture_alpha_enabled_; } + +////////////////////////////////////////////////// +double Material::getAlphaThreshold() const { return alpha_threshold_; } + +////////////////////////////////////////////////// +bool Material::twoSidedEnabled() const { return two_sided_enabled_; } + +////////////////////////////////////////////////// +void Material::setReflectivity(double reflectivity) { reflectivity_ = reflectivity; } + +////////////////////////////////////////////////// +void Material::setReflectionEnabled(bool enabled) { reflection_enabled_ = enabled; } + +////////////////////////////////////////////////// +void Material::setLightingEnabled(bool enabled) { lighting_enabled_ = enabled; } + +////////////////////////////////////////////////// +void Material::setDepthCheckEnabled(bool enabled) { depth_check_enabled_ = enabled; } + +////////////////////////////////////////////////// +void Material::setDepthWriteEnabled(bool enabled) { depth_write_enabled_ = enabled; } + +////////////////////////////////////////////////// +void Material::setCastShadows(bool cast_shadows) { cast_shadows_ = cast_shadows; } + +////////////////////////////////////////////////// +void Material::setReceiveShadows(bool receive_shadows) { receive_shadows_ = receive_shadows; } + +////////////////////////////////////////////////// +void Material::setRenderOrder(float render_order) { render_order_ = render_order; } + +////////////////////////////////////////////////// +Color Material::getAmbient() const { return ambient_; } + +////////////////////////////////////////////////// +Color Material::getDiffuse() const { return diffuse_; } + +////////////////////////////////////////////////// +Color Material::getSpecular() const { return specular_; } + +////////////////////////////////////////////////// +Color Material::getEmissive() const { return emissive_; } + +////////////////////////////////////////////////// +double Material::getShininess() const { return shininess_; } + +////////////////////////////////////////////////// +double Material::getTransparency() const { return transparency_; } + +////////////////////////////////////////////////// +float Material::getRenderOrder() const { return render_order_; } + +////////////////////////////////////////////////// +double Material::getReflectivity() const { return reflectivity_; } + +////////////////////////////////////////////////// +bool Material::castShadows() const { return cast_shadows_; } + +////////////////////////////////////////////////// +bool Material::receiveShadows() const { return receive_shadows_; } + +////////////////////////////////////////////////// +bool Material::lightingEnabled() const { return lighting_enabled_; } + +////////////////////////////////////////////////// +bool Material::depthCheckEnabled() const { return depth_check_enabled_; } + +////////////////////////////////////////////////// +bool Material::depthWriteEnabled() const { return depth_write_enabled_; } + +////////////////////////////////////////////////// +bool Material::reflectionEnabled() const { return reflection_enabled_; } + +////////////////////////////////////////////////// +MaterialType Material::getType() const { return MaterialType::MT_CLASSIC; } + +////////////////////////////////////////////////// +void Material::setShaderType(ShaderType /*type*/) +{ + // no op +} + +////////////////////////////////////////////////// +enum ShaderType Material::getShaderType() const { return ShaderType::ST_PIXEL; } + +////////////////////////////////////////////////// +std::string Material::getVertexShader() const { return {}; } + +////////////////////////////////////////////////// +ShaderParams::Ptr Material::getVertexShaderParams() { return nullptr; } + +////////////////////////////////////////////////// +void Material::setVertexShader(const std::string& /*path*/) +{ + // no op +} + +////////////////////////////////////////////////// +std::string Material::getFragmentShader() const { return {}; } + +////////////////////////////////////////////////// +ShaderParams::Ptr Material::getFragmentShaderParams() { return nullptr; } + +////////////////////////////////////////////////// +void Material::setFragmentShader(const std::string& /*path*/) +{ + // no op +} + +////////////////////////////////////////////////// +bool Material::hasTexture() const { return false; } + +////////////////////////////////////////////////// +std::string Material::getTexture() const { return {}; } + +////////////////////////////////////////////////// +void Material::setTexture(const std::string& texture, const Image::ConstPtr& img) +{ + // no op +} + +////////////////////////////////////////////////// +Image::ConstPtr Material::getTextureData() const { return {}; } + +////////////////////////////////////////////////// +void Material::clearTexture() +{ + // no op +} + +////////////////////////////////////////////////// +bool Material::hasNormalMap() const { return false; } + +////////////////////////////////////////////////// +std::string Material::getNormalMap() const { return {}; } + +////////////////////////////////////////////////// +Image::ConstPtr Material::getNormalMapData() const { return {}; } + +////////////////////////////////////////////////// +void Material::setNormalMap(const std::string& normal_map, const Image::ConstPtr& img) +{ + // no op +} + +////////////////////////////////////////////////// +void Material::clearNormalMap() +{ + // no op +} + +////////////////////////////////////////////////// +bool Material::hasRoughnessMap() const { return false; } + +////////////////////////////////////////////////// +std::string Material::getRoughnessMap() const { return {}; } + +////////////////////////////////////////////////// +Image::ConstPtr Material::getRoughnessMapData() const { return {}; } + +////////////////////////////////////////////////// +void Material::setRoughnessMap(const std::string& roughness_map, const Image::ConstPtr& img) +{ + // no op +} + +////////////////////////////////////////////////// +void Material::clearRoughnessMap() +{ + // no op +} + +////////////////////////////////////////////////// +bool Material::hasMetalnessMap() const { return false; } + +////////////////////////////////////////////////// +std::string Material::getMetalnessMap() const { return {}; } + +////////////////////////////////////////////////// +Image::ConstPtr Material::getMetalnessMapData() const { return {}; } + +////////////////////////////////////////////////// +void Material::setMetalnessMap(const std::string& metalness_map, const Image::ConstPtr& img) +{ + // no op +} + +////////////////////////////////////////////////// +void Material::clearMetalnessMap() +{ + // no op +} + +////////////////////////////////////////////////// +bool Material::hasEnvironmentMap() const { return false; } + +////////////////////////////////////////////////// +std::string Material::getEnvironmentMap() const { return {}; } + +////////////////////////////////////////////////// +Image::ConstPtr Material::getEnvironmentMapData() const { return {}; } + +////////////////////////////////////////////////// +void Material::setEnvironmentMap(const std::string& environment_map, const Image::ConstPtr& img) +{ + // no op +} + +////////////////////////////////////////////////// +void Material::clearEnvironmentMap() +{ + // no op +} + +////////////////////////////////////////////////// +bool Material::hasEmissiveMap() const { return false; } + +////////////////////////////////////////////////// +std::string Material::getEmissiveMap() const { return {}; } + +////////////////////////////////////////////////// +Image::ConstPtr Material::getEmissiveMapData() const { return {}; } + +////////////////////////////////////////////////// +void Material::setEmissiveMap(const std::string& emissive_map, const Image::ConstPtr& img) +{ + // no op +} + +////////////////////////////////////////////////// +void Material::clearEmissiveMap() +{ + // no op +} + +////////////////////////////////////////////////// +bool Material::hasLightMap() const { return false; } + +////////////////////////////////////////////////// +std::string Material::getLightMap() const { return {}; } + +////////////////////////////////////////////////// +unsigned int Material::getLightMapTexCoordSet() const { return 0u; } + +////////////////////////////////////////////////// +void Material::setLightMap(const std::string& light_map, const Image::ConstPtr& img, unsigned int uv_set) +{ + // no op +} + +////////////////////////////////////////////////// +Image::ConstPtr Material::getLightMapData() const { return {}; } + +////////////////////////////////////////////////// +void Material::clearLightMap() +{ + // no op +} + +////////////////////////////////////////////////// +void Material::setRoughness(float roughness) +{ + // no op +} + +////////////////////////////////////////////////// +float Material::getRoughness() const { return 0.0f; } + +////////////////////////////////////////////////// +void Material::setMetalness(float metalness) +{ + // no op +} + +////////////////////////////////////////////////// +float Material::getMetalness() const { return 0.0f; } + +////////////////////////////////////////////////// +std::unique_ptr Material::clone(const std::string& name) const +{ + // auto baseShared = this->shared_from_this(); + + // auto thisShared = + // std::dynamic_pointer_cast(baseShared); + + // MaterialPtr material = T::Scene()->CreateMaterial(_name); + // material->CopyFrom(thisShared); + // return material; +} + +////////////////////////////////////////////////// +void Material::copyFrom(ConstPtr material) +{ + // this->SetLightingEnabled(_material->LightingEnabled()); + // this->SetAmbient(_material->Ambient()); + // this->SetDiffuse(_material->Diffuse()); + // this->SetSpecular(_material->Specular()); + // this->SetEmissive(_material->Emissive()); + // this->SetRenderOrder(_material->RenderOrder()); + // this->SetShininess(_material->Shininess()); + // this->SetAlphaFromTexture(_material->TextureAlphaEnabled(), + // _material->AlphaThreshold(), _material->TwoSidedEnabled()); + // // override transparency / blend setting after setting alpha from texture + // this->SetTransparency(_material->Transparency()); + // // override depth check / depth write after setting transparency + // this->SetDepthCheckEnabled(_material->DepthCheckEnabled()); + // this->SetDepthWriteEnabled(_material->DepthWriteEnabled()); + // this->SetReflectivity(_material->Reflectivity()); + // this->SetCastShadows(_material->CastShadows()); + // this->SetReceiveShadows(_material->ReceiveShadows()); + // this->SetReflectionEnabled(_material->ReflectionEnabled()); + // this->SetTexture(_material->Texture(), _material->TextureData()); + // this->SetNormalMap(_material->NormalMap(), _material->NormalMapData()); + // this->SetRoughnessMap(_material->RoughnessMap(), + // _material->RoughnessMapData()); + // this->SetMetalnessMap(_material->MetalnessMap(), + // _material->MetalnessMapData()); + // this->SetRoughness(_material->Roughness()); + // this->SetMetalness(_material->Metalness()); + // this->SetEnvironmentMap(_material->EnvironmentMap(), + // _material->EnvironmentMapData()); + // this->SetEmissiveMap(_material->EmissiveMap(), + // _material->EmissiveMapData()); + // this->SetLightMap(_material->LightMap(), _material->LightMapData(), + // _material->LightMapTexCoordSet()); + // this->SetShaderType(_material->ShaderType()); + // this->SetVertexShader(_material->VertexShader()); + // this->SetFragmentShader(_material->FragmentShader()); +} + +////////////////////////////////////////////////// +void Material::copyFrom(const Material& material) +{ + // this->SetLightingEnabled(_material.Lighting()); + // this->SetAmbient(_material.Ambient()); + // this->SetDiffuse(_material.Diffuse()); + // this->SetSpecular(_material.Specular()); + // this->SetEmissive(_material.Emissive()); + // this->SetShininess(_material.Shininess()); + // this->SetTransparency(_material.Transparency()); + // this->SetAlphaFromTexture(_material.TextureAlphaEnabled(), + // _material.AlphaThreshold(), _material.TwoSidedEnabled()); + // this->SetRenderOrder(_material.RenderOrder()); + // // TODO(anyone): update common::Material + // this->SetReflectivity(0); + // this->SetTexture(_material.TextureImage(), _material.TextureData()); + // // TODO(anyone): update common::Material + // this->SetCastShadows(true); + // // TODO(anyone): update common::Material + // this->SetReceiveShadows(true); + // // TODO(anyone): update common::Material + // this->SetReflectionEnabled(true); + // // TODO(anyone): update common::Material + // this->ClearNormalMap(); + // // TODO(anyone): update common::Material + // this->SetShaderType(ST_PIXEL); + + // const common::Pbr *pbrMat = _material.PbrMaterial(); + // if (!pbrMat) + // pbrMat = &kDefaultPbr; + // this->SetNormalMap(pbrMat->NormalMap(), pbrMat->NormalMapData()); + // this->SetRoughnessMap(pbrMat->RoughnessMap(), pbrMat->RoughnessMapData()); + // this->SetMetalnessMap(pbrMat->MetalnessMap(), pbrMat->MetalnessMapData()); + // this->SetRoughness(pbrMat->Roughness()); + // this->SetMetalness(pbrMat->Metalness()); + // // TODO(anyone): update when pbrMat has EnvironmentMapData API + // this->SetEnvironmentMap(pbrMat->EnvironmentMap(), nullptr); + // this->SetEmissiveMap(pbrMat->EmissiveMap(), pbrMat->EmissiveMapData()); + // this->SetLightMap(pbrMat->LightMap(), pbrMat->LightMapData(), + // pbrMat->LightMapTexCoordSet()); +} + +////////////////////////////////////////////////// +void Material::setDepthMaterial(double /*far*/, double /*near*/) +{ + // do nothing +} + +////////////////////////////////////////////////// +void Material::reset() +{ + setLightingEnabled(true); + setDepthCheckEnabled(true); + setDepthWriteEnabled(true); + setAmbient(0.3, 0.3, 0.3); + setDiffuse(1.0, 1.0, 1.0); + setSpecular(0.2, 0.2, 0.2); + setEmissive(0, 0, 0); + setRenderOrder(0); + setShininess(1.5); + setTransparency(0); + setReflectivity(0); + setCastShadows(true); + setReceiveShadows(true); + setReflectionEnabled(true); + clearTexture(); + clearNormalMap(); + clearRoughnessMap(); + clearMetalnessMap(); + clearEmissiveMap(); + clearLightMap(); + // setRoughness(kDefaultPbr.Roughness()); + // setMetalness(kDefaultPbr.Metalness()); + setShaderType(ShaderType::ST_PIXEL); +} +} // namespace tesseract_common diff --git a/tesseract_common/src/shader_param.cpp b/tesseract_common/src/shader_param.cpp new file mode 100644 index 00000000000..aabce7348ed --- /dev/null +++ b/tesseract_common/src/shader_param.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +namespace tesseract_common +{ +class ShaderParamPrivate +{ + /// \brief Type of parameter held +public: + ShaderParam::ParamType type = ShaderParam::PARAM_NONE; + + /// \brief Union for the type held in this param +public: + union + { + float vFloat; + int vInt; + } paramValue; + + /// \brief buffer of parameter held + // Currently only 32-bit elements will be supported for buffers +public: + std::shared_ptr buffer; + + /// \brief Count of elements in buffer of parameter held +public: + uint32_t count = 0u; + + /// \brief Path to texture +public: + std::string texture; + + /// \brief Texture coord set index +public: + uint32_t uvSetIndex = 0u; +}; + +////////////////////////////////////////////////// +ShaderParam::ShaderParam() : dataPtr(new ShaderParamPrivate) +{ + this->dataPtr->count = 0u; + this->dataPtr->buffer.reset(); +} + +////////////////////////////////////////////////// +ShaderParam::ShaderParam(const ShaderParam& _other) : dataPtr(new ShaderParamPrivate) +{ + // Avoid incorrect cppcheck error about dataPtr being assigned in constructor + ShaderParamPrivate& dp = *(this->dataPtr); + dp = *(_other.dataPtr); +} + +////////////////////////////////////////////////// +ShaderParam::~ShaderParam() { this->dataPtr->buffer.reset(); } + +////////////////////////////////////////////////// +ShaderParam::ParamType ShaderParam::Type() const { return this->dataPtr->type; } + +////////////////////////////////////////////////// +uint32_t ShaderParam::Count() const { return this->dataPtr->count; } + +////////////////////////////////////////////////// +ShaderParam& ShaderParam::operator=(const ShaderParam& _other) +{ + *(this->dataPtr) = *(_other.dataPtr); + return *this; +} + +////////////////////////////////////////////////// +void ShaderParam::operator=(const float _value) +{ + this->dataPtr->type = PARAM_FLOAT; + this->dataPtr->paramValue.vFloat = _value; +} + +////////////////////////////////////////////////// +void ShaderParam::operator=(const int _value) +{ + this->dataPtr->type = PARAM_INT; + this->dataPtr->paramValue.vInt = _value; +} + +////////////////////////////////////////////////// +void ShaderParam::SetTexture(const std::string& _value, ShaderParam::ParamType _type, unsigned int _uvSetIndex) +{ + this->dataPtr->type = _type; + this->dataPtr->texture = _value; + this->dataPtr->uvSetIndex = _uvSetIndex; +} + +////////////////////////////////////////////////// +void ShaderParam::InitializeBuffer(uint32_t _count) +{ + this->dataPtr->count = _count; + this->dataPtr->buffer.reset(new float[_count], std::default_delete()); +} + +////////////////////////////////////////////////// +void ShaderParam::UpdateBuffer(float* _floatBuffer) +{ + this->dataPtr->type = PARAM_FLOAT_BUFFER; + memcpy(this->dataPtr->buffer.get(), _floatBuffer, 4 * this->dataPtr->count); +} + +////////////////////////////////////////////////// +void ShaderParam::UpdateBuffer(int* _intBuffer) +{ + this->dataPtr->type = PARAM_INT_BUFFER; + memcpy(this->dataPtr->buffer.get(), _intBuffer, 4 * this->dataPtr->count); +} + +////////////////////////////////////////////////// +bool ShaderParam::Value(float* _value) const +{ + if (PARAM_FLOAT == this->dataPtr->type) + { + *_value = this->dataPtr->paramValue.vFloat; + return true; + } + return false; +} + +////////////////////////////////////////////////// +bool ShaderParam::Value(int* _value) const +{ + if (PARAM_INT == this->dataPtr->type) + { + *_value = this->dataPtr->paramValue.vInt; + return true; + } + return false; +} + +////////////////////////////////////////////////// +bool ShaderParam::Buffer(std::shared_ptr& _buffer) const +{ + if (PARAM_FLOAT_BUFFER == this->dataPtr->type || PARAM_INT_BUFFER == this->dataPtr->type) + { + _buffer = this->dataPtr->buffer; + return true; + } + return false; +} + +////////////////////////////////////////////////// +bool ShaderParam::Value(std::string& _value, uint32_t& _uvSetIndex) const +{ + _value = this->dataPtr->texture; + _uvSetIndex = this->dataPtr->uvSetIndex; + return false; +} +} // namespace tesseract_common diff --git a/tesseract_common/src/shader_params.cpp b/tesseract_common/src/shader_params.cpp new file mode 100644 index 00000000000..0b96cd0fce6 --- /dev/null +++ b/tesseract_common/src/shader_params.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +namespace tesseract_common +{ +class ShaderParamsPrivate +{ + /// \brief collection of parameters +public: + std::unordered_map parameters; + + /// \brief true if the parameters have been modified since last cleared +public: + bool isDirty = false; +}; + +class ShaderParams::IteratorPrivate +{ + /// \brief Iterator from the map in ShaderParamsPrivate +public: + std::unordered_map::const_iterator iter; +}; + +////////////////////////////////////////////////// +ShaderParams::Iterator::Iterator() : dataPtr(new ShaderParams::IteratorPrivate) {} + +////////////////////////////////////////////////// +ShaderParams::Iterator::Iterator(std::unique_ptr _dataPtr) : dataPtr(std::move(_dataPtr)) {} + +////////////////////////////////////////////////// +ShaderParams::Iterator::Iterator(const ShaderParams::Iterator& _iter) : dataPtr(new ShaderParams::IteratorPrivate) +{ + this->dataPtr->iter = _iter.dataPtr->iter; +} + +////////////////////////////////////////////////// +ShaderParams::Iterator& ShaderParams::Iterator::operator=(const ShaderParams::Iterator& _iter) +{ + this->dataPtr->iter = _iter.dataPtr->iter; + return *this; +} + +////////////////////////////////////////////////// +ShaderParams::Iterator::~Iterator() {} + +////////////////////////////////////////////////// +bool ShaderParams::Iterator::operator==(const ShaderParams::Iterator& _iter) +{ + return this->dataPtr->iter == _iter.dataPtr->iter; +} + +////////////////////////////////////////////////// +bool ShaderParams::Iterator::operator!=(const ShaderParams::Iterator& _iter) +{ + return this->dataPtr->iter != _iter.dataPtr->iter; +} + +////////////////////////////////////////////////// +const std::pair& ShaderParams::Iterator::operator*() { return *(this->dataPtr->iter); } + +////////////////////////////////////////////////// +const std::pair* ShaderParams::Iterator::operator->() +{ + return &*(this->dataPtr->iter); +} + +////////////////////////////////////////////////// +ShaderParams::Iterator& ShaderParams::Iterator::operator++() +{ + ++(this->dataPtr->iter); + return *this; +} + +////////////////////////////////////////////////// +ShaderParams::Iterator ShaderParams::Iterator::operator++(int) // NOLINT(readability/casting) +{ + ShaderParams::Iterator copy(*this); + ++(this->dataPtr->iter); + return copy; +} + +////////////////////////////////////////////////// +ShaderParams::ShaderParams() : dataPtr(new ShaderParamsPrivate) {} + +////////////////////////////////////////////////// +ShaderParams::~ShaderParams() {} + +////////////////////////////////////////////////// +ShaderParam& ShaderParams::operator[](const std::string& _name) +{ + this->dataPtr->isDirty = true; + return this->dataPtr->parameters[_name]; +} + +////////////////////////////////////////////////// +const ShaderParam& ShaderParams::operator[](const std::string& _name) const +{ + return this->dataPtr->parameters.at(_name); +} + +////////////////////////////////////////////////// +ShaderParams::Iterator ShaderParams::begin() const +{ + auto iterPrivatePtr = std::make_unique(); + iterPrivatePtr->iter = this->dataPtr->parameters.begin(); + return ShaderParams::Iterator(std::move(iterPrivatePtr)); +} + +////////////////////////////////////////////////// +ShaderParams::Iterator ShaderParams::end() const +{ + auto iterPrivatePtr = std::make_unique(); + iterPrivatePtr->iter = this->dataPtr->parameters.end(); + return ShaderParams::Iterator(std::move(iterPrivatePtr)); +} + +////////////////////////////////////////////////// +bool ShaderParams::IsDirty() const { return this->dataPtr->isDirty; } + +////////////////////////////////////////////////// +void ShaderParams::ClearDirty() { this->dataPtr->isDirty = false; } +} // namespace tesseract_common diff --git a/tesseract_common/src/shader_type.cpp b/tesseract_common/src/shader_type.cpp new file mode 100644 index 00000000000..252b68c5f16 --- /dev/null +++ b/tesseract_common/src/shader_type.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +namespace tesseract_common +{ +////////////////////////////////////////////////// +const char* ShaderUtil::names[static_cast(ShaderType::ST_COUNT)] = { + "UNKNOWN", "pixel", "vertex", "normal_map_object_space", "normal_map_tangent_space", +}; + +////////////////////////////////////////////////// +bool ShaderUtil::isValid(ShaderType type) +{ + return static_cast(type) > 0 && + static_cast(type) < static_cast(ShaderType::ST_COUNT); +} + +////////////////////////////////////////////////// +ShaderType ShaderUtil::sanitize(ShaderType type) +{ + // check if value within enum bounds + if (!ShaderUtil::isValid(type)) + { + CONSOLE_BRIDGE_logError("Invalid ShaderType value: %d", static_cast(type)); + return ShaderType::ST_UNKNOWN; + } + + return type; +} + +////////////////////////////////////////////////// +std::string ShaderUtil::getName(ShaderType type) +{ + type = ShaderUtil::sanitize(type); + return ShaderUtil::names[static_cast(type)]; +} + +////////////////////////////////////////////////// +ShaderType ShaderUtil::getEnum(const std::string& name) +{ + // search over all enum elements + for (unsigned int i = 0; i < static_cast(ShaderType::ST_COUNT); ++i) + { + ShaderType format = static_cast(i); + + // check if names match + if (ShaderUtil::getName(format) == name) + { + return format; + } + } + + // no match found + return ShaderType::ST_UNKNOWN; +} +} // namespace tesseract_common