SET(PROJECT_NAME DSO)

PROJECT(${PROJECT_NAME})
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
#set(CMAKE_VERBOSE_MAKEFILE ON)


set(BUILD_TYPE Release)
#set(BUILD_TYPE RelWithDebInfo)

set(EXECUTABLE_OUTPUT_PATH bin)
set(LIBRARY_OUTPUT_PATH lib)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

# required libraries
find_package(Eigen3 REQUIRED)

# optional libraries
find_package(LibZip QUIET)
find_package(Pangolin 0.2 QUIET)
find_package(OpenCV QUIET)

# flags
if(WIN32)
  add_definitions("-DEIGEN_NO_STATIC_ASSERT")
  add_definitions("-D__SSE3__")
  add_definitions("-DNOMINMAX")

  set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /bigobj /MDd")
  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj /MDd")
  set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD")
  set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
  
  if (MSVC)
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
  endif (MSVC)
elseif(NOT PIZERO)
  add_definitions("-DENABLE_SSE")
endif()

if (LINUX32 OR LINUX64)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
endif()

# use c++11 standard
set (CMAKE_CXX_STANDARD 11)

# Sources files
set(dso_SOURCE_FILES
  ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystem.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystemOptimize.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystemOptPoint.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystemDebugStuff.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystemMarginalize.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/Residuals.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/CoarseTracker.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/CoarseInitializer.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/ImmaturePoint.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/HessianBlocks.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/PixelSelector2.cpp
  ${PROJECT_SOURCE_DIR}/src/FullSystem/IMUPreintegrator.cpp
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/EnergyFunctional.cpp
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/AccumulatedTopHessian.cpp
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/AccumulatedSCHessian.cpp
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/EnergyFunctionalStructs.cpp
  ${PROJECT_SOURCE_DIR}/src/util/settings.cpp
  ${PROJECT_SOURCE_DIR}/src/util/Undistort.cpp
  ${PROJECT_SOURCE_DIR}/src/util/globalCalib.cpp
)

set(dso_INCLUDE_FILES
  ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystem.h
  ${PROJECT_SOURCE_DIR}/src/FullSystem/Residuals.h
  ${PROJECT_SOURCE_DIR}/src/FullSystem/CoarseTracker.h
  ${PROJECT_SOURCE_DIR}/src/FullSystem/CoarseInitializer.h
  ${PROJECT_SOURCE_DIR}/src/FullSystem/ImmaturePoint.h
  ${PROJECT_SOURCE_DIR}/src/FullSystem/HessianBlocks.h
  ${PROJECT_SOURCE_DIR}/src/FullSystem/PixelSelector.h
  ${PROJECT_SOURCE_DIR}/src/FullSystem/PixelSelector2.h
  ${PROJECT_SOURCE_DIR}/src/FullSystem/IMUPreintegrator.h
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/EnergyFunctional.h
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/AccumulatedTopHessian.h
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/AccumulatedSCHessian.h
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/EnergyFunctionalStructs.h
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/MatrixAccumulators.h
  ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/RawResidualJacobian.h
  ${PROJECT_SOURCE_DIR}/src/util/DatasetReader.h
  ${PROJECT_SOURCE_DIR}/src/util/FrameShell.h
  ${PROJECT_SOURCE_DIR}/src/util/globalCalib.h
  ${PROJECT_SOURCE_DIR}/src/util/globalFuncs.h
  ${PROJECT_SOURCE_DIR}/src/util/ImageAndExposure.h
  ${PROJECT_SOURCE_DIR}/src/util/IndexThreadReduce.h
  ${PROJECT_SOURCE_DIR}/src/util/MinimalImage.h
  ${PROJECT_SOURCE_DIR}/src/util/nanoflann.h
  ${PROJECT_SOURCE_DIR}/src/util/NumType.h
  ${PROJECT_SOURCE_DIR}/src/util/settings.h
  ${PROJECT_SOURCE_DIR}/src/util/Undistort.h
  ${PROJECT_SOURCE_DIR}/src/IOWrapper/ImageDisplay.h
  ${PROJECT_SOURCE_DIR}/src/IOWrapper/ImageRW.h
  ${PROJECT_SOURCE_DIR}/src/IOWrapper/Output3DWrapper.h
  ${PROJECT_SOURCE_DIR}/src/IOWrapper/ImageDisplay.h
  ${PROJECT_SOURCE_DIR}/src/IOWrapper/OutputWrapper/SampleOutputWrapper.h
)

include_directories(
  ${PROJECT_SOURCE_DIR}/src
  ${PROJECT_SOURCE_DIR}/thirdparty/Sophus
  ${PROJECT_SOURCE_DIR}/thirdparty/sse2neon
  ${EIGEN3_INCLUDE_DIR}
) 


# decide if we have pangolin
if (Pangolin_FOUND)
	message("--- found PANGOLIN, compiling dso_pangolin library.")
	include_directories( ${Pangolin_INCLUDE_DIRS} ) 
	set(dso_pangolin_SOURCE_FILES 
	  ${PROJECT_SOURCE_DIR}/src/IOWrapper/Pangolin/KeyFrameDisplay.cpp
	  ${PROJECT_SOURCE_DIR}/src/IOWrapper/Pangolin/PangolinDSOViewer.cpp)
	set(HAS_PANGOLIN 1)
else ()
	message("--- could not find PANGOLIN, not compiling dso_pangolin library.")
	message("    this means there will be no 3D display / GUI available for dso_dataset.")
	set(dso_pangolin_SOURCE_FILES )
	set(HAS_PANGOLIN 0)
endif ()

# decide if we have openCV
if (OpenCV_FOUND)
	message("--- found OpenCV, compiling dso_opencv library.")
	include_directories( ${OpenCV_INCLUDE_DIRS} )
	set(dso_opencv_SOURCE_FILES 
	  ${PROJECT_SOURCE_DIR}/src/IOWrapper/OpenCV/ImageDisplay_OpenCV.cpp
	  ${PROJECT_SOURCE_DIR}/src/IOWrapper/OpenCV/ImageRW_OpenCV.cpp)
	set(HAS_OPENCV 1)
else ()
	message("--- could not find OpenCV, not compiling dso_opencv library.")
	message("    this means there will be no image display, and image read / load functionality.")
	set(dso_opencv_SOURCE_FILES 
	  ${PROJECT_SOURCE_DIR}/src/IOWrapper/ImageDisplay_dummy.cpp
	  ${PROJECT_SOURCE_DIR}/src/IOWrapper/ImageRW_dummy.cpp)
	set(HAS_OPENCV 0)
endif ()

# decide if we have ziplib.
if (LIBZIP_LIBRARY)
	message("--- found ziplib (${LIBZIP_VERSION}), compiling with zip capability.")
	add_definitions(-DHAS_ZIPLIB=1)
	include_directories( ${LIBZIP_INCLUDE_DIR_ZIP} ${LIBZIP_INCLUDE_DIR_ZIPCONF} ) 
else()
	message("--- not found ziplib (${LIBZIP_LIBRARY}), compiling without zip capability.")
	set(LIBZIP_LIBRARY "")
endif()


# compile main library.
add_library(${PROJECT_NAME} ${dso_SOURCE_FILES} ${dso_INCLUDE_FILES} ${dso_opencv_SOURCE_FILES} ${dso_pangolin_SOURCE_FILES})

target_include_directories(${PROJECT_NAME} PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
  $<INSTALL_INTERFACE:include/${PROJECT_NAME}>
)

include(CMakePackageConfigHelpers)

# Generate cmake configuration scripts
set(DSO_GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated)
set(DSO_VERSION_CONFIG ${DSO_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake)
set(DSO_PROJECT_CONFIG ${DSO_GENERATED_DIR}/${PROJECT_NAME}Config.cmake)
set(DSO_TARGETS_EXPORT_NAME ${PROJECT_NAME}Targets)
set(DSO_CONFIG_INSTALL_DIR lib/cmake/${PROJECT_NAME})
set(DSO_NAMESPACE "${PROJECT_NAME}::")
set(DSO_VERSION 1.0.0)

# Create a version config file
write_basic_package_version_file(${DSO_VERSION_CONFIG}
                                 VERSION ${DSO_VERSION}
                                 COMPATIBILITY SameMajorVersion)
# Create a project config file
configure_file(${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in ${DSO_PROJECT_CONFIG} @ONLY)

# Install to the specified directory
install(FILES ${DSO_VERSION_CONFIG} ${DSO_PROJECT_CONFIG}
        DESTINATION ${DSO_CONFIG_INSTALL_DIR})
install(EXPORT ${DSO_TARGETS_EXPORT_NAME}
        NAMESPACE ${DSO_NAMESPACE}
        DESTINATION ${DSO_CONFIG_INSTALL_DIR})

# Set standard installation directories
set(RUNTIME_DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
set(LIBRARY_DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
set(ARCHIVE_DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
set(INCLUDES_DESTINATION ${CMAKE_INSTALL_PREFIX}/include)

install(TARGETS ${PROJECT_NAME}
        EXPORT ${DSO_TARGETS_EXPORT_NAME}
        RUNTIME DESTINATION ${RUNTIME_DESTINATION}
        LIBRARY DESTINATION ${LIBRARY_DESTINATION}
        ARCHIVE DESTINATION ${ARCHIVE_DESTINATION})

# Install DSO headers
install(DIRECTORY src/ DESTINATION include/${PROJECT_NAME} FILES_MATCHING PATTERN "*.h")
install(DIRECTORY thirdparty/Sophus/ DESTINATION include/${PROJECT_NAME} FILES_MATCHING PATTERN "*.hpp")
install(DIRECTORY thirdparty/sse2neon/ DESTINATION include/${PROJECT_NAME} FILES_MATCHING PATTERN "*.h")

# build main executable (only if we have both OpenCV and Pangolin)
if (OpenCV_FOUND AND Pangolin_FOUND)
	message("--- compiling dso_dataset.")
	add_executable(dso_dataset ${PROJECT_SOURCE_DIR}/src/main_dso_pangolin.cpp)
    target_link_libraries(dso_dataset dso ${LIBZIP_LIBRARY} ${Pangolin_LIBRARIES} ${OpenCV_LIBS})
else()
	message("--- not building dso_dataset, since either don't have openCV or Pangolin.")
endif()