Skip to content
Snippets Groups Projects
Commit ee6dee40 authored by Nicolas Pope's avatar Nicolas Pope
Browse files

Basic C++ and Python SDK

parent 4f6b664e
No related branches found
No related tags found
No related merge requests found
Showing
with 965 additions and 0 deletions
[submodule "ext/nanogui"] [submodule "ext/nanogui"]
path = ext/nanogui path = ext/nanogui
url = https://github.com/wjakob/nanogui.git url = https://github.com/wjakob/nanogui.git
[submodule "SDK/C++/public/ext/pybind11"]
path = SDK/C++/public/ext/pybind11
url = https://github.com/pybind/pybind11.git
...@@ -3,6 +3,7 @@ include (CheckIncludeFile) ...@@ -3,6 +3,7 @@ include (CheckIncludeFile)
include (CheckIncludeFileCXX) include (CheckIncludeFileCXX)
include (CheckFunctionExists) include (CheckFunctionExists)
include(CheckLanguage) include(CheckLanguage)
include(ExternalProject)
if (WIN32) if (WIN32)
set(CMAKE_GENERATOR_TOOLSET "host=x64") set(CMAKE_GENERATOR_TOOLSET "host=x64")
...@@ -476,6 +477,7 @@ if (WITH_SDK) ...@@ -476,6 +477,7 @@ if (WITH_SDK)
if (NOT WIN32) if (NOT WIN32)
add_subdirectory(SDK/C) add_subdirectory(SDK/C)
endif() endif()
add_subdirectory(SDK/C++)
endif() endif()
if (HAVE_AVFORMAT) if (HAVE_AVFORMAT)
......
add_library(voltu SHARED
private/system.cpp
private/feed_impl.cpp
private/room_impl.cpp
private/frame_impl.cpp
private/image_impl.cpp
private/observer_impl.cpp
private/pointcloud_impl.cpp
)
target_include_directories(voltu
PUBLIC public/include
PRIVATE src)
target_link_libraries(voltu ftlcommon ftldata ftlctrl ftlrgbd ftlstreams ftlrender Threads::Threads ${OpenCV_LIBS} openvr ftlnet nanogui ${NANOGUI_EXTRA_LIBS} ceres nvidia-ml)
ExternalProject_Add(
voltu_sdk
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/public"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/sdk"
INSTALL_COMMAND ""
BUILD_ALWAYS true
CMAKE_ARGS -DOpenCV_DIR=${OpenCV_DIR}
)
#include "feed_impl.hpp"
using voltu::internal::FeedImpl;
FeedImpl::FeedImpl(ftl::stream::Feed* feed, uint32_t fsid)
: feed_(feed)
{
fsids_.insert(fsid);
}
FeedImpl::~FeedImpl()
{
remove();
}
std::string FeedImpl::getURI()
{
return feed_->getURI(*fsids_.begin());
}
void FeedImpl::remove()
{
}
#pragma once
#include <voltu/feed.hpp>
#include <ftl/streams/feed.hpp>
#include <unordered_set>
namespace voltu
{
namespace internal
{
class FeedImpl : public voltu::Feed
{
public:
FeedImpl(ftl::stream::Feed*, uint32_t fsid);
~FeedImpl();
std::string getURI() override;
void remove() override;
private:
ftl::stream::Feed *feed_;
std::unordered_set<uint32_t> fsids_;
};
}
}
#include "frame_impl.hpp"
#include "image_impl.hpp"
#include <ftl/rgbd/frame.hpp>
#include <voltu/types/errors.hpp>
using voltu::internal::FrameImpl;
FrameImpl::FrameImpl()
{
}
FrameImpl::~FrameImpl()
{
}
std::list<voltu::ImagePtr> FrameImpl::getImageSet(voltu::Channel c)
{
std::list<voltu::ImagePtr> result;
ftl::codecs::Channel channel = ftl::codecs::Channel::Colour;
switch (c)
{
case voltu::Channel::kColour : channel = ftl::codecs::Channel::Colour; break;
case voltu::Channel::kDepth : channel = ftl::codecs::Channel::Depth; break;
default: throw voltu::exceptions::BadImageChannel();
}
for (const auto &fs : framesets_)
{
for (const auto &f : fs->frames)
{
if (f.hasChannel(channel))
{
auto img = std::make_shared<voltu::internal::ImageImpl>(
f.cast<ftl::rgbd::Frame>(), channel
);
result.push_back(img);
}
}
}
return result;
}
voltu::PointCloudPtr FrameImpl::getPointCloud(voltu::PointCloudFormat cloudfmt, voltu::PointFormat pointfmt)
{
return nullptr;
}
void FrameImpl::pushFrameSet(const std::shared_ptr<ftl::data::FrameSet> &fs)
{
framesets_.push_back(fs);
}
int64_t FrameImpl::getTimestamp()
{
return 0;
}
#pragma once
#include <voltu/types/frame.hpp>
#include <voltu/types/image.hpp>
#include <voltu/types/channel.hpp>
#include <ftl/data/new_frameset.hpp>
namespace voltu
{
namespace internal
{
class FrameImpl : public voltu::Frame
{
public:
FrameImpl();
~FrameImpl();
std::list<voltu::ImagePtr> getImageSet(voltu::Channel) override;
voltu::PointCloudPtr getPointCloud(voltu::PointCloudFormat cloudfmt, voltu::PointFormat pointfmt) override;
int64_t getTimestamp() override;
void pushFrameSet(const std::shared_ptr<ftl::data::FrameSet> &fs);
inline const std::list<std::shared_ptr<ftl::data::FrameSet>> &getInternalFrameSets() const { return framesets_; }
private:
std::list<std::shared_ptr<ftl::data::FrameSet>> framesets_;
};
}
}
#include "image_impl.hpp"
using voltu::internal::ImageImpl;
ImageImpl::ImageImpl(const ftl::rgbd::Frame& f, ftl::codecs::Channel c)
: frame_(f), channel_(c)
{
}
ImageImpl::~ImageImpl()
{
}
voltu::ImageData ImageImpl::getHost()
{
cv::Mat m = frame_.get<cv::Mat>(channel_);
voltu::ImageData r;
r.data = m.data;
r.width = m.cols;
r.height = m.rows;
r.pitch = m.step;
if (m.type() == CV_8UC4)
{
r.format = voltu::ImageFormat::kBGRA8;
}
else if (m.type() == CV_32F)
{
r.format = voltu::ImageFormat::kFloat32;
}
return r;
}
voltu::ImageData ImageImpl::getDevice()
{
cv::cuda::GpuMat m = frame_.get<cv::cuda::GpuMat>(channel_);
voltu::ImageData r;
r.data = m.data;
r.width = m.cols;
r.height = m.rows;
r.pitch = m.step;
if (m.type() == CV_8UC4)
{
r.format = voltu::ImageFormat::kBGRA8;
}
else if (m.type() == CV_32F)
{
r.format = voltu::ImageFormat::kFloat32;
}
return r;
}
bool ImageImpl::isDevice()
{
return true;
}
voltu::Channel ImageImpl::getChannel()
{
switch (channel_)
{
case ftl::codecs::Channel::Colour : return voltu::Channel::kColour;
case ftl::codecs::Channel::Depth : return voltu::Channel::kDepth;
default: return voltu::Channel::kInvalid;
}
}
std::string ImageImpl::getName()
{
return std::to_string(frame_.frameset()) + std::string("-") + std::to_string(frame_.source());
}
voltu::Intrinsics ImageImpl::getIntrinsics()
{
auto raw = frame_.getLeft();
voltu::Intrinsics result;
result.width = raw.width;
result.height = raw.height;
result.principle_x = raw.cx;
result.principle_y = raw.cy;
result.focal_x = raw.fx;
result.focal_y = raw.fy;
return result;
}
voltu::StereoIntrinsics ImageImpl::getStereoIntrinsics()
{
auto raw = frame_.getLeft();
voltu::StereoIntrinsics result;
result.width = raw.width;
result.height = raw.height;
result.principle_x = raw.cx;
result.principle_y = raw.cy;
result.focal_x = raw.fx;
result.focal_y = raw.fy;
result.min_depth = raw.minDepth;
result.max_depth = raw.maxDepth;
result.baseline = raw.baseline;
return result;
}
Eigen::Matrix4d ImageImpl::getPose()
{
return frame_.getPose();
}
int64_t ImageImpl::getTimestamp()
{
return frame_.timestamp();
}
int ImageImpl::getCameraNumber()
{
return frame_.source();
}
uint32_t ImageImpl::getUniqueId()
{
return frame_.id().id;
}
#pragma once
#include <voltu/types/image.hpp>
#include <ftl/rgbd/frame.hpp>
namespace voltu
{
namespace internal
{
class ImageImpl : public voltu::Image
{
public:
ImageImpl(const ftl::rgbd::Frame&, ftl::codecs::Channel c);
~ImageImpl();
voltu::ImageData getHost() override;
voltu::ImageData getDevice() override;
bool isDevice() override;
voltu::Channel getChannel() override;
std::string getName() override;
voltu::Intrinsics getIntrinsics() override;
voltu::StereoIntrinsics getStereoIntrinsics() override;
Eigen::Matrix4d getPose() override;
int64_t getTimestamp() override;
//virtual voltu::RoomId getRoomId() override;
int getCameraNumber() override;
uint32_t getUniqueId() override;
private:
const ftl::rgbd::Frame &frame_;
ftl::codecs::Channel channel_;
};
}
}
#include "observer_impl.hpp"
#include "frame_impl.hpp"
#include <voltu/types/errors.hpp>
#include <ftl/render/CUDARender.hpp>
#include <ftl/rgbd/frame.hpp>
using voltu::internal::ObserverImpl;
using ftl::rgbd::Capability;
ObserverImpl::ObserverImpl(ftl::Configurable *base)
{
pool_ = new ftl::data::Pool(2,5);
rend_ = ftl::create<ftl::render::CUDARender>(base, "camN");
intrinsics_.fx = 700.0f;
intrinsics_.fy = 700.0f;
intrinsics_.width = 1280;
intrinsics_.height = 720;
intrinsics_.cx = -1280.0f/2.0f;
intrinsics_.cy = -720.0f/2.0f;
intrinsics_.minDepth = 0.1f;
intrinsics_.maxDepth = 12.0f;
pose_.setIdentity();
calibration_uptodate_.clear();
}
ObserverImpl::~ObserverImpl()
{
}
void ObserverImpl::setResolution(uint32_t w, uint32_t h)
{
if (w < 100 || w > 10000 || h < 100 || h > 10000)
{
throw voltu::exceptions::BadParameterValue();
}
intrinsics_.width = w;
intrinsics_.height = h;
intrinsics_.cx = -int(w)/2;
intrinsics_.cy = -int(h)/2;
calibration_uptodate_.clear();
}
void ObserverImpl::setFocalLength(uint32_t f)
{
if (f < 100 || f > 10000)
{
throw voltu::exceptions::BadParameterValue();
}
intrinsics_.fx = f;
intrinsics_.fy = f;
calibration_uptodate_.clear();
}
void ObserverImpl::setStereo(bool)
{
}
bool ObserverImpl::waitCompletion(int timeout)
{
if (frame_complete_) return true;
frame_complete_ = true;
try
{
rend_->render();
rend_->end();
}
catch(const std::exception& e)
{
throw voltu::exceptions::InternalRenderError();
}
cudaSafeCall(cudaStreamSynchronize(frameset_->frames[0].stream()));
return true;
}
void ObserverImpl::submit(const voltu::FramePtr& frame)
{
if (frame_complete_)
{
frame_complete_ = false;
frameset_ = _makeFrameSet();
ftl::rgbd::Frame &rgbdframe = frameset_->frames[0].cast<ftl::rgbd::Frame>();
if (!rgbdframe.has(ftl::codecs::Channel::Calibration) || calibration_uptodate_.test_and_set())
{
rgbdframe.setLeft() = intrinsics_;
auto &cap = rgbdframe.create<std::unordered_set<Capability>>(ftl::codecs::Channel::Capabilities);
cap.clear();
cap.emplace(Capability::VIDEO);
cap.emplace(Capability::MOVABLE);
cap.emplace(Capability::ADJUSTABLE);
cap.emplace(Capability::VIRTUAL);
cap.emplace(Capability::LIVE);
if (rend_->value("projection", 0) == int(ftl::rgbd::Projection::EQUIRECTANGULAR)) cap.emplace(Capability::EQUI_RECT);
auto &meta = rgbdframe.create<std::map<std::string,std::string>>(ftl::codecs::Channel::MetaData);
meta["name"] = std::string("Virtual Camera"); //host_->value("name", host_->getID());
//meta["id"] = host_->getID();
meta["uri"] = std::string("device:render");
meta["device"] = std::string("CUDA Render");
}
//if (!rgbdframe.has(ftl::codecs::Channel::Pose))
//{
rgbdframe.setPose() = pose_.cast<double>();
//}
int width = rgbdframe.getLeft().width;
int height = rgbdframe.getLeft().height;
// FIXME: Create opengl buffers here and map to cuda?
auto &colour = rgbdframe.create<cv::cuda::GpuMat>(ftl::codecs::Channel::Colour);
colour.create(height, width, CV_8UC4);
rgbdframe.create<cv::cuda::GpuMat>(ftl::codecs::Channel::Depth).create(height, width, CV_32F);
rgbdframe.createTexture<float>(ftl::codecs::Channel::Depth);
rend_->begin(rgbdframe, ftl::codecs::Channel::Colour);
}
auto *fimp = dynamic_cast<voltu::internal::FrameImpl*>(frame.get());
if (!fimp)
{
throw voltu::exceptions::InvalidFrameObject();
}
const auto &sets = fimp->getInternalFrameSets();
for (const auto &fs : sets)
{
Eigen::Matrix4d pose;
pose.setIdentity();
try
{
rend_->submit(fs.get(), ftl::codecs::Channels<0>(ftl::codecs::Channel::Colour), pose);
}
catch (...)
{
throw voltu::exceptions::InternalRenderError();
}
}
}
void ObserverImpl::setPose(const Eigen::Matrix4f &p)
{
pose_ = p;
}
voltu::FramePtr ObserverImpl::getFrame()
{
waitCompletion(0);
auto f = std::make_shared<voltu::internal::FrameImpl>();
f->pushFrameSet(frameset_);
return f;
}
voltu::PropertyPtr ObserverImpl::property(voltu::ObserverProperty)
{
throw voltu::exceptions::InvalidProperty();
}
std::shared_ptr<ftl::data::FrameSet> ObserverImpl::_makeFrameSet()
{
int64_t timestamp = ftl::timer::get_time();
auto newf = std::make_shared<ftl::data::FrameSet>(pool_, ftl::data::FrameID(id_,255), timestamp);
for (size_t i=0; i<size_; ++i) {
newf->frames.push_back(std::move(pool_->allocate(ftl::data::FrameID(id_, i), timestamp)));
}
newf->mask = 0xFF;
newf->clearFlags();
newf->store();
return newf;
}
#pragma once
#include <voltu/observer.hpp>
#include <ftl/render/renderer.hpp>
#include <ftl/data/framepool.hpp>
#include <ftl/data/new_frameset.hpp>
#include <ftl/rgbd/camera.hpp>
#include <Eigen/Eigen>
namespace voltu
{
namespace internal
{
class ObserverImpl : public voltu::Observer
{
public:
explicit ObserverImpl(ftl::Configurable *base);
~ObserverImpl();
void setResolution(uint32_t w, uint32_t h) override;
void setFocalLength(uint32_t f) override;
void setStereo(bool) override;
bool waitCompletion(int timeout) override;
void submit(const voltu::FramePtr&) override;
void setPose(const Eigen::Matrix4f &) override;
voltu::FramePtr getFrame() override;
voltu::PropertyPtr property(voltu::ObserverProperty) override;
private:
ftl::render::FSRenderer *rend_;
ftl::data::Pool *pool_;
int id_;
size_t size_ = 1;
std::shared_ptr<ftl::data::FrameSet> frameset_;
bool frame_complete_ = true;
ftl::rgbd::Camera intrinsics_;
Eigen::Matrix4f pose_;
std::atomic_flag calibration_uptodate_;
std::shared_ptr<ftl::data::FrameSet> _makeFrameSet();
};
}
}
#include "pointcloud_impl.hpp"
using voltu::internal::PointCloudUnstructured;
using voltu::PointCloudData;
PointCloudData PointCloudUnstructured::getHost()
{
// TODO: Generate point cloud on GPU
return {};
}
PointCloudData PointCloudUnstructured::getDevice()
{
// TODO: Generate point cloud on GPU
return {};
}
#pragma once
#include <voltu/types/pointcloud.hpp>
namespace voltu
{
namespace internal
{
class PointCloudUnstructured : public voltu::PointCloud
{
public:
voltu::PointCloudData getHost() override;
voltu::PointCloudData getDevice() override;
private:
};
}
}
#include <voltu/room.hpp>
#include "room_impl.hpp"
#include "frame_impl.hpp"
#include <voltu/types/errors.hpp>
using voltu::internal::RoomImpl;
RoomImpl::RoomImpl(ftl::stream::Feed* feed)
: feed_(feed)
{
}
bool RoomImpl::waitNextFrame(int64_t timeout)
{
if (!filter_)
{
filter_ = feed_->filter(fsids_, {ftl::codecs::Channel::Colour, ftl::codecs::Channel::Depth});
filter_->on([this](const std::shared_ptr<ftl::data::FrameSet> &fs)
{
UNIQUE_LOCK(mutex_, lk);
last_seen_ = std::max(last_seen_, fs->timestamp());
cv_.notify_all();
return true;
});
}
std::unique_lock<std::mutex> lk(mutex_);
if (last_read_ >= last_seen_)
{
if (timeout > 0)
{
cv_.wait_for(lk, std::chrono::seconds(timeout), [this] {
return last_read_ < last_seen_;
});
return last_read_ < last_seen_;
}
else if (timeout == 0)
{
return false;
}
else
{
cv_.wait(lk, [this] {
return last_read_ < last_seen_;
});
}
}
return true;
}
voltu::FramePtr RoomImpl::getFrame()
{
auto f = std::make_shared<voltu::internal::FrameImpl>();
std::unique_lock<std::mutex> lk(mutex_);
int count = 0;
for (auto fsid : fsids_)
{
auto fs = feed_->getFrameSet(fsid);
if (!fs) continue;
f->pushFrameSet(fs);
last_read_ = std::max(last_read_, fs->timestamp());
++count;
}
if (count == 0) throw voltu::exceptions::NoFrame();
return f;
}
std::string RoomImpl::getName()
{
return "";
}
void RoomImpl::addFrameSet(uint32_t fsid)
{
fsids_.insert(fsid);
}
bool RoomImpl::active()
{
return ftl::running;
}
#pragma once
#include <ftl/streams/feed.hpp>
#include <ftl/threads.hpp>
#include <condition_variable>
namespace voltu
{
namespace internal
{
class RoomImpl : public voltu::Room
{
public:
explicit RoomImpl(ftl::stream::Feed*);
bool waitNextFrame(int64_t) override;
voltu::FramePtr getFrame() override;
std::string getName() override;
bool active() override;
void addFrameSet(uint32_t fsid);
private:
ftl::stream::Feed* feed_;
std::unordered_set<uint32_t> fsids_;
ftl::stream::Feed::Filter* filter_=nullptr;
MUTEX mutex_;
std::condition_variable cv_;
int64_t last_seen_ = -1;
int64_t last_read_ = -1;
};
}
}
#include "system_impl.hpp"
#include "feed_impl.hpp"
#include "room_impl.hpp"
#include "observer_impl.hpp"
#include <voltu/voltu.hpp>
#include <voltu/types/errors.hpp>
#include <ftl/timer.hpp>
#include <iostream>
using voltu::internal::SystemImpl;
static bool g_isinit = false;
#if defined(WIN32)
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
#else
#define EXTERN_DLL_EXPORT extern "C"
#endif
EXTERN_DLL_EXPORT voltu::System* voltu_initialise()
{
if (!g_isinit)
{
return new SystemImpl();
}
else
{
throw voltu::exceptions::AlreadyInit();
}
return nullptr;
}
SystemImpl::SystemImpl()
{
int argc = 1;
char arg1[] = {'v','o','l','t','u',0};
char* argv[] = {arg1,0};
root_ = ftl::configure(argc, argv, "sdk");
net_ = ftl::create<ftl::net::Universe>(root_, "net");
feed_ = ftl::create<ftl::stream::Feed>(root_, "system", net_);
net_->start();
ftl::timer::start(false);
}
SystemImpl::~SystemImpl()
{
ftl::timer::stop(true);
ftl::pool.stop(true);
}
voltu::Version SystemImpl::getVersion() const
{
voltu::Version v;
v.major = VOLTU_VERSION_MAJOR;
v.minor = VOLTU_VERSION_MINOR;
v.patch = VOLTU_VERSION_PATCH;
return v;
}
voltu::FeedPtr SystemImpl::open(const std::string& uri)
{
try
{
uint32_t fsid = feed_->add(uri);
return std::make_shared<voltu::internal::FeedImpl>(feed_, fsid);
}
catch(const std::exception &e)
{
throw voltu::exceptions::BadSourceURI();
}
};
std::list<voltu::RoomId> SystemImpl::listRooms()
{
auto fsids = feed_->listFrameSets();
std::list<voltu::RoomId> res;
for (unsigned int fsid : fsids) res.push_front(static_cast<voltu::RoomId>(fsid));
return res;
}
voltu::RoomPtr SystemImpl::getRoom(voltu::RoomId id)
{
auto s = std::make_shared<voltu::internal::RoomImpl>(feed_);
s->addFrameSet(id);
return s;
}
voltu::ObserverPtr SystemImpl::createObserver()
{
return std::make_shared<voltu::internal::ObserverImpl>(root_);
}
#pragma once
#include <voltu/system.hpp>
#include <ftl/streams/feed.hpp>
#include <ftl/net/universe.hpp>
namespace voltu
{
namespace internal
{
class SystemImpl : public voltu::System
{
public:
SystemImpl();
~SystemImpl();
voltu::Version getVersion() const override;
voltu::RoomPtr createRoom() override { return nullptr; };
voltu::ObserverPtr createObserver() override;
voltu::FeedPtr open(const std::string&) override;
std::list<voltu::RoomId> listRooms() override;
voltu::RoomPtr getRoom(voltu::RoomId) override;
private:
ftl::Configurable* root_;
ftl::stream::Feed* feed_;
ftl::net::Universe* net_;
};
} // namespace internal
} // namespace voltu
cmake_minimum_required (VERSION 3.16.0)
project (voltu_sdk VERSION 0.0.1)
include(GNUInstallDirs)
option(WITH_OPENCV "Build with OpenCV wrapper" ON)
option(WITH_PYTHON "Build Python module" OFF)
find_package( Eigen3 REQUIRED NO_MODULE )
find_package( Threads REQUIRED )
if (WITH_OPENCV)
find_package( OpenCV REQUIRED )
endif()
if(WIN32)
add_definitions(-DWIN32)
set(CMAKE_GENERATOR_TOOLSET "host=x64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2 /MP4 /std:c++14 /wd4996")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DFTL_DEBUG /Wall")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2")
set(OS_LIBS "")
else()
add_definitions(-DUNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -march=native -mfpmath=sse -Wall -Werror=unused-result -Werror=return-type -pthread")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
set(OS_LIBS "dl")
endif()
set(VOLTU_SRCS
voltu.cpp
)
set(OPTIONAL_DEPENDENCIES)
if (WITH_OPENCV)
list(APPEND OPTIONAL_DEPENDENCIES ${OpenCV_LIBS})
list(APPEND VOLTU_SRCS voltu_cv.cpp)
set(CMAKE_REQUIRED_INCLUDES ${OpenCV_INCLUDE_DIRS})
endif()
add_library(voltu_sdk STATIC ${VOLTU_SRCS})
target_include_directories(voltu_sdk
PUBLIC include)
target_link_libraries(voltu_sdk ${OS_LIBS} Threads::Threads ${OPTIONAL_DEPENDENCIES} Eigen3::Eigen)
add_executable(voltu_basic_test
samples/basic_test/main.cpp
)
target_link_libraries(voltu_basic_test voltu_sdk)
add_executable(voltu_basic_file
samples/basic_file/main.cpp
)
target_link_libraries(voltu_basic_file voltu_sdk)
add_executable(voltu_basic_virtual_cam
samples/basic_virtual_cam/main.cpp
)
target_link_libraries(voltu_basic_virtual_cam voltu_sdk)
if (WITH_PYTHON)
add_subdirectory(ext/pybind11)
add_subdirectory(python)
endif()
Subproject commit 06a54018c8a9fd9a7be5f5b56414b5da9259f637
#pragma once
#ifndef PY_API
/// include function or method in Python API
#define PY_API
#endif
#ifndef PY_NO_SHARED_PTR
/// Ownership is not passed with std::shared_ptr<>
#define PY_NO_SHARED_PTR
#endif
#ifndef PY_RV_LIFETIME_PARENT
/// Lifetime of the return value is tied to the lifetime of a parent object
#define PY_RV_LIFETIME_PARENT
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment