cmake_minimum_required(VERSION 3.24)
project(raytrace LANGUAGES C CXX CUDA)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)

# ---------------------------------------------------------------------------
# Compile-time template parameters (override via cmake -D or pip --config-settings)
# ---------------------------------------------------------------------------
set(RAYTRACE_CAM_WIDTH  128  CACHE STRING "Per-camera width  (pixels)")
set(RAYTRACE_CAM_HEIGHT 128  CACHE STRING "Per-camera height (pixels)")
set(RAYTRACE_NUM_CAMERAS 4096 CACHE STRING "Maximum number of cameras")
set(RAYTRACE_NUM_PROBES  0    CACHE STRING "Collision probes per camera (0 = disable)")

# ---------------------------------------------------------------------------
# Dependencies
# ---------------------------------------------------------------------------
include(FetchContent)

# OWL (OptiX Wrapper Library)
FetchContent_Declare(
    OWL
    GIT_REPOSITORY https://github.com/NVIDIA/OWL.git
    GIT_TAG        main
    EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(OWL)

# STB (header-only image I/O, used by rl-tools raytracer)
FetchContent_Declare(
    STB
    GIT_REPOSITORY https://github.com/nothings/stb.git
    GIT_TAG        master
    EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(STB)

find_package(assimp REQUIRED)
find_package(pybind11 REQUIRED)

# ---------------------------------------------------------------------------
# rl_tools_core – interface library with just the include path
# ---------------------------------------------------------------------------
add_library(rl_tools_core INTERFACE)
target_include_directories(rl_tools_core INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR}/raytrace/rl-tools/include
)
target_compile_definitions(rl_tools_core INTERFACE
    RL_TOOLS_RENDERING_ENABLE_RAYTRACING
)

# ---------------------------------------------------------------------------
# PTX generation for OptiX device programs
# ---------------------------------------------------------------------------
embed_ptx(
    OUTPUT_TARGET raytrace_device_ptx
    PTX_LINK_LIBRARIES owl::owl rl_tools_core
    SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/raytrace/src/device.cu
)

# ---------------------------------------------------------------------------
# raytrace_impl – static CUDA library (the only TU touching OWL/rl-tools)
# ---------------------------------------------------------------------------
add_library(raytrace_impl STATIC
    raytrace/src/raytrace_impl.cu
)
target_include_directories(raytrace_impl PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/raytrace/src
    ${stb_SOURCE_DIR}
)
target_link_libraries(raytrace_impl PUBLIC
    rl_tools_core
    owl::owl
    assimp::assimp
    raytrace_device_ptx
)
target_compile_definitions(raytrace_impl PRIVATE
    RAYTRACE_CAM_WIDTH=${RAYTRACE_CAM_WIDTH}
    RAYTRACE_CAM_HEIGHT=${RAYTRACE_CAM_HEIGHT}
    RAYTRACE_NUM_CAMERAS=${RAYTRACE_NUM_CAMERAS}
    RAYTRACE_NUM_PROBES=${RAYTRACE_NUM_PROBES}
)
set_target_properties(raytrace_impl PROPERTIES
    CUDA_RESOLVE_DEVICE_SYMBOLS ON
    POSITION_INDEPENDENT_CODE ON
)

# ---------------------------------------------------------------------------
# _raytrace_core – pybind11 extension module (plain C++, no CUDA)
# ---------------------------------------------------------------------------
pybind11_add_module(_raytrace_core
    raytrace/src/bindings.cpp
)
target_include_directories(_raytrace_core PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/raytrace/src
)
target_link_libraries(_raytrace_core PRIVATE
    raytrace_impl
)
target_compile_definitions(_raytrace_core PRIVATE
    RAYTRACE_CAM_WIDTH=${RAYTRACE_CAM_WIDTH}
    RAYTRACE_CAM_HEIGHT=${RAYTRACE_CAM_HEIGHT}
    RAYTRACE_NUM_CAMERAS=${RAYTRACE_NUM_CAMERAS}
    RAYTRACE_NUM_PROBES=${RAYTRACE_NUM_PROBES}
)

# Set RPATH so the extension module finds libowl.so next to it
set_target_properties(_raytrace_core PROPERTIES
    INSTALL_RPATH "$ORIGIN"
)

install(TARGETS _raytrace_core DESTINATION raytrace)
install(TARGETS owl DESTINATION raytrace LIBRARY NAMELINK_SKIP)
