Skip to content

Commit

Permalink
Merge pull request #55 from gtker/master
Browse files Browse the repository at this point in the history
Replace Boost with Pybind11 + Add checking if BVH/maps built + Add C API docs
  • Loading branch information
namreeb authored Sep 5, 2023
2 parents 7855f3e + b6c5c62 commit 3d094ee
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 132 deletions.
14 changes: 3 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
- name: Checkout submodules
run: git submodule update --init --recursive

- name: Install python and boost
- name: Install python
run: |
sudo apt-get -y update
sudo apt-get install python3 python3-dev libboost-python-dev
sudo apt-get install python3 python3-dev
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
Expand Down Expand Up @@ -59,16 +59,8 @@ jobs:
python-version: '3.9'
architecture: 'x64'

- name: Build Boost
run: |
Invoke-WebRequest https://boostorg.jfrog.io/artifactory/main/release/1.78.0/source/boost_1_78_0.zip -OutFile boost.zip
Expand-Archive -Path boost.zip -DestinationPath .
cd boost_1_78_0
.\bootstrap
.\b2 --with-python link=static threading=multi runtime-link=shared architecture=x86 address-model=64 stage
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBOOST_ROOT=${{github.workspace}}/boost_1_78_0 -DBOOST_LIBRARYDIR=${{github.workspace}}/boost_1_78_0/stage/lib
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}

- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "stormlib"]
path = stormlib
url = https://github.com/ladislav-zezula/StormLib.git
[submodule "pybind11"]
path = pybind11
url = https://github.com/pybind/pybind11
80 changes: 3 additions & 77 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,87 +21,13 @@ if (CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-multichar")
endif()

unset(Python3_FOUND CACHE)
unset(PYTHON_COMPONENT CACHE)

# github python setup action will set this environment variable
if(DEFINED ENV{pythonLocation})
set(Python3_ROOT_DIR $ENV{pythonLocation})
set(Python3_FIND_REGISTRY NEVER)
endif()

option(NAMIGATOR_BUILD_PYTHON "Build Python bindings if Python2/3 is present." TRUE)
option(NAMIGATOR_INSTALL_TESTS "Install tests." TRUE)

if(NAMIGATOR_BUILD_PYTHON)
# First try finding python 3 development files
find_package(Python3 COMPONENTS Development)

if (Python3_FOUND)
set(PYTHON_COMPONENT "python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}")
set(PYTHON_LIBRARIES "${Python3_LIBRARIES}")
set(PYTHON_INCLUDE_DIRS "${Python3_INCLUDE_DIRS}")
else()
message(STATUS "Could not find python3. Attemping to find python2.")
find_package(Python2 COMPONENTS Development)
if (Python2_FOUND)
set(PYTHON_COMPONENT "python${Python2_VERSION_MAJOR}${Python2_VERSION_MINOR}")
set(PYTHON_LIBRARIES "${Python2_LIBRARIES}")
set(PYTHON_INCLUDE_DIRS "${Python2_INCLUDE_DIRS}")
else()
message(STATUS "Could not find python2 either.")
endif()
endif()
endif() # NAMIGATOR_BUILD_PYTHON

# Enable debug output from FindBoost
#set(Boost_DEBUG ON)
#set(Boost_DETAILED_FAILURE_MSG ON)

if (PYTHON_COMPONENT)
# There currently seems to be a bug with the Linux distro of boost binaries
# where some symbols are not built with position independent code (-fPIC).
# So rather than requiring our users to build boost themselves, we can just
# disable static linking of Boost libraries for now.
if (MSVC)
set(Boost_USE_STATIC_LIBS ON)
else()
set(Boost_USE_STATIC_LIBS OFF)
endif()

set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_FIND_QUIETLY ON)

find_package(Boost COMPONENTS "${PYTHON_COMPONENT}")

# If we found python 3 and boost rejected it, try again with python 2
if (NOT Boost_FOUND AND Python3_FOUND)
message(STATUS "Boost rejected ${PYTHON_COMPONENT}. Trying with python2.")
find_package(Python2 COMPONENTS Development)

if (Python2_FOUND)
message(STATUS "Python2 found. Checking for support from boost.")
set(PYTHON_COMPONENT "python${Python2_VERSION_MAJOR}${Python2_VERSION_MINOR}")
set(PYTHON_LIBRARIES "${Python2_LIBRARIES}")
set(PYTHON_INCLUDE_DIRS "${Python2_INCLUDE_DIRS}")
find_package(Boost COMPONENTS "${PYTHON_COMPONENT}")
else()
message(STATUS "Could not find python2 either.")
endif()

# Failed? Give up
if (NOT Boost_FOUND)
message(STATUS "Giving up on finding boost and python match")
unset(PYTHON_COMPONENT)
unset(PYTHON_LIBRARIES)
unset(PYTHON_INCLUDE_DIRS)
endif()
endif()
endif()

if (NAMIGATOR_BUILD_PYTHON AND NOT PYTHON_COMPONENT)
message(WARNING "No boost-compatible python was found. Python bindings for ${CMAKE_PROJECT_NAME} will not be compiled")
add_subdirectory(pybind11)
else()
message(WARNING "Python bindings for ${CMAKE_PROJECT_NAME} will not be compiled")
endif()

# GCC 7 requires an extra lib for this, but MSVC does not
Expand Down
18 changes: 5 additions & 13 deletions MapBuilder/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ set(EXECUTABLE_NAME MapBuilder)
set(LIBRARY_NAME libmapbuild)
set(PYTHON_NAME mapbuild)

set(SRC BVHConstructor.cpp GameObjectBVHBuilder.cpp MeshBuilder.cpp RecastContext.cpp Worker.cpp MapBuilder_c_bindings.cpp)
set(SRC BVHConstructor.cpp GameObjectBVHBuilder.cpp MeshBuilder.cpp RecastContext.cpp Worker.cpp MapBuilder_c_bindings.cpp FileExist.cpp)

add_library(${LIBRARY_NAME} ${SRC})
target_include_directories(${LIBRARY_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../")
Expand All @@ -15,18 +15,10 @@ target_link_libraries(${EXECUTABLE_NAME} ${LIBRARY_NAME})

install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)

if (PYTHON_COMPONENT)
if (Python3_FOUND)
Python3_add_library(${PYTHON_NAME} ${SRC} python.cpp)
elseif (Python2_FOUND)
Python2_add_library(${PYTHON_NAME} ${SRC} python.cpp)
else()
message(FATAL_ERROR "Python component defined but neither python2 nor python3 were found")
endif()

target_compile_definitions(${PYTHON_NAME} PUBLIC PYTHON BOOST_PYTHON_STATIC_LIB)
target_include_directories(${PYTHON_NAME} PUBLIC ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
target_link_libraries(${PYTHON_NAME} PRIVATE parser utility RecastNavigation::Recast RecastNavigation::Detour storm ${Boost_LIBRARIES})
if (NAMIGATOR_BUILD_PYTHON)
pybind11_add_module(${PYTHON_NAME} ${SRC} python.cpp)

target_link_libraries(${PYTHON_NAME} PRIVATE parser utility RecastNavigation::Recast RecastNavigation::Detour storm)

install(TARGETS ${PYTHON_NAME} DESTINATION lib)
endif()
17 changes: 17 additions & 0 deletions MapBuilder/FileExist.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "FileExist.hpp"

#include <filesystem>

namespace file_exist {

bool bvh_files_exist(const std::string& outputPath) {
// bvh.idx is created at the very end of building game objects
return std::filesystem::exists(outputPath + "/BVH/bvh.idx");
}

bool map_files_exist(const std::string& outputPath, const std::string& mapName) {
// mapName.map is created in MeshBuilder::SaveMap which should be after successful creation
return std::filesystem::exists(outputPath + "/" + mapName + ".map");
}

} // namespace file_exist
9 changes: 9 additions & 0 deletions MapBuilder/FileExist.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <string>

namespace file_exist {

bool bvh_files_exist(const std::string& outputPath);

bool map_files_exist(const std::string& outputPath, const std::string& mapName);

} // namespace file_exist
39 changes: 39 additions & 0 deletions MapBuilder/MapBuilder_c_bindings.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "mapbuilder_c_bindings.h"

#include "FileExist.hpp"
#include "GameObjectBVHBuilder.hpp"
#include "MeshBuilder.hpp"
#include "Worker.hpp"
Expand Down Expand Up @@ -134,5 +135,43 @@ MapBuildResultType mapbuild_build_map(const char* const data_path,
return static_cast<MapBuildResultType>(Result::SUCCESS);
}

MapBuildResultType mapbuild_bvh_files_exist(const char* const output_path,
uint8_t* const exists) {
std::string outputPath = output_path;

try {
if (file_exist::bvh_files_exist(outputPath)) {
*exists = 1;
} else {
*exists = 0;
}
}
catch (...) {
return static_cast<MapBuildResultType>(Result::UNKNOWN_EXCEPTION);
}

return static_cast<MapBuildResultType>(Result::SUCCESS);
}

MapBuildResultType mapbuild_map_files_exist(const char* const output_path,
const char* const map_name,
uint8_t* const exists) {

std::string outputPath = output_path;
std::string mapName = map_name;

try {
if (file_exist::map_files_exist(outputPath, mapName)) {
*exists = 1;
} else {
*exists = 0;
}
}
catch (...) {
return static_cast<MapBuildResultType>(Result::UNKNOWN_EXCEPTION);
}

return static_cast<MapBuildResultType>(Result::SUCCESS);
}

}
46 changes: 45 additions & 1 deletion MapBuilder/mapbuilder_c_bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,59 @@ extern "C" {

typedef uint8_t MapBuildResultType;

/*
Build gameobjects as bounded volume hierachy (BVH).
`data_path` is the `Data` directory containing `MPQ` files of a client.
`output_path` is the location where generated data will be placed.
`threads` is the amount of concurrent jobs that will be used to build the data.
`amount_of_bvhs_built` returns the amount of gameobjects built.
This MUST be done before building the maps with `mapbuild_build_map`.
*/
MapBuildResultType mapbuild_build_bvh(const char* const data_path,
const char* const output_path,
uint32_t threads,
uint32_t* const amount_of_bvhs_built);

/*
Builds a single map.
`data_path` is the `Data` directory containing `MPQ` files of a client.
`output_path` is the location where generated data will be placed.
`threads` is the amount of concurrent jobs that will be used to build the data.
`map_name` is the name of the map folder inside the MPQ. For example `Azeroth` for Eastern Kingdoms.
`gameobject_csv` is the path to a CSV file containing a list of dynamically loaded objects.
This feature is unlikely to work.
*/
MapBuildResultType mapbuild_build_map(const char* const data_path,
const char* const output_path,
const char* const map_name,
const char* const gameobject_csv,
uint32_t threads);

}
/*
Tests if gameobjects have been built in `output_path`.
`exists` will be `0` if the gameobject files haven't been built, and `1` if they have.
*/
MapBuildResultType mapbuild_bvh_files_exist(const char* const output_path,
uint8_t* const exists);

/*
Tests if the map with `map_name` has already been built in `output_path`.
`exists` will be `0` if the map hasn't been built, and `1` if it has.
*/
MapBuildResultType mapbuild_map_files_exist(const char* const output_path,
const char* const map_name,
uint8_t* const exists);

}
21 changes: 16 additions & 5 deletions MapBuilder/python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
#include "MeshBuilder.hpp"
#include "Worker.hpp"
#include "parser/MpqManager.hpp"
#include "FileExist.hpp"

#include <boost/python.hpp>
#include <pybind11/pybind11.h>
#include <filesystem>
#include <memory>
#include <string>
Expand Down Expand Up @@ -142,9 +143,19 @@ bool BuildADT(const std::string& dataPath, const std::string& outputPath,
return true;
}

BOOST_PYTHON_MODULE(mapbuild)
bool BVHFilesExist(const std::string& outputPath) {
return file_exist::bvh_files_exist(outputPath);
}

bool MapFilesExist(const std::string& outputPath, const std::string& mapName) {
return file_exist::map_files_exist(outputPath, mapName);
}

PYBIND11_MODULE(mapbuild, m)
{
boost::python::def("build_bvh", BuildBVH);
boost::python::def("build_map", BuildMap);
boost::python::def("build_adt", BuildADT);
m.def("build_bvh", &BuildBVH);
m.def("build_map", &BuildMap);
m.def("build_adt", &BuildADT);
m.def("map_files_exist", &MapFilesExist);
m.def("bvh_files_exist", &BVHFilesExist);
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ server.
* **stormlib** -- Used for extracting source data from its containers.
* **recastnavigation** -- Underlying computational geometry library. Used for
mesh generation, pathfinding, and more.
* **boost** -- Optional. Used in creating python modules.
* **pybind11** -- Optional. Used in creating python modules.
* **python** -- Optional. Used in creating python modules.

## Future Plans
Expand Down
14 changes: 3 additions & 11 deletions pathfind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,10 @@ target_link_libraries(${LIBRARY_NAME} PRIVATE ${FILESYSTEM_LIBRARY} utility Reca

install(TARGETS ${LIBRARY_NAME} ARCHIVE DESTINATION lib)

if (PYTHON_COMPONENT)
if (Python3_FOUND)
Python3_add_library(${PYTHON_NAME} ${SRC} python.cpp)
elseif (Python2_FOUND)
Python2_add_library(${PYTHON_NAME} ${SRC} python.cpp)
else()
message(FATAL_ERROR "Python component defined but neither python2 nor python3 were found")
endif()
if (NAMIGATOR_BUILD_PYTHON)
pybind11_add_module(${PYTHON_NAME} ${SRC} python.cpp)

target_compile_definitions(${PYTHON_NAME} PUBLIC PYTHON BOOST_PYTHON_STATIC_LIB)
target_include_directories(${PYTHON_NAME} PRIVATE ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
target_link_libraries(${PYTHON_NAME} PRIVATE ${FILESYSTEM_LIBRARY} utility RecastNavigation::Recast RecastNavigation::Detour storm ${Boost_LIBRARIES})
target_link_libraries(${PYTHON_NAME} PRIVATE ${FILESYSTEM_LIBRARY} utility RecastNavigation::Recast RecastNavigation::Detour storm)

install(TARGETS ${PYTHON_NAME} DESTINATION lib)
endif()
Loading

0 comments on commit 3d094ee

Please sign in to comment.