v0.8.1.0 Release
v0.8.1.0 Release
This commit is contained in:
332
samples/ExpressionApp/MeshRenderer.cpp
Normal file
332
samples/ExpressionApp/MeshRenderer.cpp
Normal file
@@ -0,0 +1,332 @@
|
||||
/*###############################################################################
|
||||
#
|
||||
# Copyright 2021 NVIDIA Corporation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
###############################################################################*/
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WINSOCKAPI_
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#else // UNIX
|
||||
#include <dlfcn.h>
|
||||
typedef void *HMODULE;
|
||||
typedef void *HANDLE;
|
||||
typedef void *HINSTANCE;
|
||||
#endif // _WIN32 || UNIX
|
||||
|
||||
#include "MeshRenderer.h"
|
||||
#include "DirectoryIterator.h"
|
||||
#include "OpenGLMeshRenderer.h" // Eventually this will be discoverable
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define nvLoadLibrary(library) LoadLibrary(TEXT(library))
|
||||
#else // UNIX
|
||||
#define nvLoadLibrary(library) dlopen(library, RTLD_LAZY)
|
||||
#endif // _WIN32 || UNIX
|
||||
|
||||
|
||||
inline void* nvGetProcAddress(HINSTANCE handle, const char *proc) {
|
||||
if (nullptr == handle) return nullptr;
|
||||
#ifdef _WIN32
|
||||
return GetProcAddress(handle, proc);
|
||||
#else // UNIX
|
||||
return dlsym(handle, proc);
|
||||
#endif // _WIN32 || UNIX
|
||||
}
|
||||
|
||||
|
||||
inline int nvFreeLibrary(HINSTANCE handle) {
|
||||
if (nullptr == handle) return -1;
|
||||
#ifdef _WIN32
|
||||
return int(!FreeLibrary(handle)); // convert bool true to 0 int and 1 error code
|
||||
#else // UNIX
|
||||
return dlclose(handle); // 0 on success, error code otherwise
|
||||
#endif // _WIN32 || UNIX
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///// Abstract class MeshRenderer /////
|
||||
///// This merely converts from a C++ to a C object call. /////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef DEBUG_CAST // We never instantiate MeshRenderer, only ClubMeshRenderer, so we don't need a dynamic cast.
|
||||
#define static_cast dynamic_cast // But #define this to prove it
|
||||
#endif // DEBUG_CAST
|
||||
|
||||
|
||||
NvCV_Status MeshRenderer::name(const char **str) const {
|
||||
return m_dispatch.name(str);
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRenderer::info(const char **str) const {
|
||||
return m_dispatch.info(str);
|
||||
}
|
||||
|
||||
|
||||
void MeshRenderer::destroy() {
|
||||
m_dispatch.destroy(this);
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRenderer::read(const char *modelFile) {
|
||||
return m_dispatch.read(this, modelFile);
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRenderer::init(unsigned width, unsigned height, const char *windowName) {
|
||||
return m_dispatch.init(this, width, height, windowName);
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRenderer::setCamera(const float locPt[3], const float lookVec[3], const float upVec[3], float vfov) {
|
||||
return m_dispatch.setCamera(this, locPt, lookVec, upVec, vfov);
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRenderer::render(const float exprs[53], const float qrot[4], const float trans[3], NvCVImage *result) {
|
||||
return m_dispatch.render(this, exprs, qrot, trans, result);
|
||||
}
|
||||
|
||||
|
||||
MeshRenderer::Dispatch::Dispatch() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///// MeshRendererBroker /////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RendererInfo {
|
||||
public:
|
||||
std::string name, info, file;
|
||||
HMODULE module;
|
||||
MeshRenderer::Dispatch dispatch;
|
||||
RendererInfo() {
|
||||
memset(&dispatch, 0, sizeof(dispatch));
|
||||
module = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class MeshRendererBroker::Impl {
|
||||
public:
|
||||
static const char nameStr[], infoStr[], createStr[], destroyStr[], readStr[], initStr[], setCameraStr[], renderStr[];
|
||||
|
||||
std::string rendererDirectory;
|
||||
std::vector<RendererInfo> renderers;
|
||||
|
||||
NvCV_Status GetRenderers();
|
||||
NvCV_Status LoadRenderer(const char *name);
|
||||
NvCV_Status UnloadRenderer(const char *name);
|
||||
bool AlreadyHave(const char *name);
|
||||
~Impl() {
|
||||
for (RendererInfo& ri : renderers)
|
||||
(void)UnloadRenderer(ri.name.c_str());
|
||||
}
|
||||
};
|
||||
const char MeshRendererBroker::Impl::nameStr[] = "RendererName";
|
||||
const char MeshRendererBroker::Impl::infoStr[] = "RendererInfo";
|
||||
const char MeshRendererBroker::Impl::createStr[] = "RendererName";
|
||||
const char MeshRendererBroker::Impl::destroyStr[] = "RendererDestroy";
|
||||
const char MeshRendererBroker::Impl::readStr[] = "RendererReadModel";
|
||||
const char MeshRendererBroker::Impl::initStr[] = "RendererInit";
|
||||
const char MeshRendererBroker::Impl::setCameraStr[] = "RendererSetCamera";
|
||||
const char MeshRendererBroker::Impl::renderStr[] = "RendererRender";
|
||||
|
||||
|
||||
static bool HasDLLSuffix(const char *name) {
|
||||
static const char dllSuffix[] =
|
||||
#ifdef _WIN32
|
||||
".dll"
|
||||
#else // UNIX
|
||||
".so"
|
||||
#endif // _WIN32 || UNIX
|
||||
;
|
||||
constexpr unsigned suf_len = sizeof(dllSuffix) - 1; // Strings have a NULL terminator, are not part of the string
|
||||
unsigned name_len = unsigned(strlen(name));
|
||||
return name_len > suf_len && !strcmp(name + name_len - suf_len, dllSuffix);
|
||||
}
|
||||
|
||||
|
||||
bool MeshRendererBroker::Impl::AlreadyHave(const char* name) {
|
||||
for (const RendererInfo& ri : renderers)
|
||||
if (ri.name == name)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRendererBroker::Impl::GetRenderers() {
|
||||
if (rendererDirectory.empty()) // Or should we pass in the directory as an argument?
|
||||
return NVCV_ERR_INITIALIZATION; // The renderer directory was not initialized.
|
||||
DirectoryIterator dit(rendererDirectory.c_str(), DirectoryIterator::kTypeFile);
|
||||
const char *fileName;
|
||||
unsigned type;
|
||||
while (0 == dit.next(&fileName, &type)) {
|
||||
if (!HasDLLSuffix(fileName))
|
||||
continue;
|
||||
std::string path = rendererDirectory + '/' + fileName;
|
||||
HINSTANCE lib = nvLoadLibrary(path.c_str());
|
||||
if (!lib)
|
||||
continue;
|
||||
typedef NvCV_Status(*GetStringFunc)(const char** str);
|
||||
GetStringFunc getString;
|
||||
const char *name = nullptr, *info = nullptr;
|
||||
if ((nullptr != (getString = reinterpret_cast<GetStringFunc>(nvGetProcAddress(lib, nameStr)))) &&
|
||||
(NVCV_SUCCESS == (*getString)(&name)) &&
|
||||
(nullptr != (getString = reinterpret_cast<GetStringFunc>(nvGetProcAddress(lib, infoStr)))) &&
|
||||
(NVCV_SUCCESS == (*getString)(&info)) &&
|
||||
!AlreadyHave(name)
|
||||
) {
|
||||
unsigned i = unsigned(renderers.size());
|
||||
renderers.resize(i + 1);
|
||||
RendererInfo& ri = renderers[i];
|
||||
ri.name.assign(name);
|
||||
ri.info.assign(info);
|
||||
ri.file.assign(path);
|
||||
}
|
||||
nvFreeLibrary(lib);
|
||||
}
|
||||
return NVCV_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRendererBroker::Impl::LoadRenderer(const char *name) {
|
||||
for (RendererInfo& ri : renderers) {
|
||||
if (name == ri.name) {
|
||||
if (!ri.module) {
|
||||
ri.module = nvLoadLibrary(ri.file.c_str());
|
||||
// BE VERY CAREFUL WHEN CHANGING FUNCTION SIGNATURES, ESPECIALLY FOR WINDOWS!!!! THERE ARE NO CHECKS BELOW!!!!
|
||||
*((void**)&ri.dispatch.name) = nvGetProcAddress(ri.module, nameStr);
|
||||
*((void**)&ri.dispatch.info) = nvGetProcAddress(ri.module, infoStr);
|
||||
*((void**)&ri.dispatch.create) = nvGetProcAddress(ri.module, createStr);
|
||||
*((void**)&ri.dispatch.destroy) = nvGetProcAddress(ri.module, destroyStr);
|
||||
*((void**)&ri.dispatch.read) = nvGetProcAddress(ri.module, readStr);
|
||||
*((void**)&ri.dispatch.init) = nvGetProcAddress(ri.module, initStr);
|
||||
*((void**)&ri.dispatch.setCamera) = nvGetProcAddress(ri.module, setCameraStr);
|
||||
*((void**)&ri.dispatch.render) = nvGetProcAddress(ri.module, renderStr);
|
||||
}
|
||||
return NVCV_SUCCESS;
|
||||
}
|
||||
}
|
||||
return NVCV_ERR_FEATURENOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRendererBroker::Impl::UnloadRenderer(const char *name) {
|
||||
NvCV_Status err = NVCV_ERR_FEATURENOTFOUND;
|
||||
for (RendererInfo& ri : renderers) {
|
||||
if (name == ri.name) {
|
||||
err = !ri.module ? NVCV_SUCCESS : nvFreeLibrary(ri.module) ? NVCV_ERR_LIBRARY : NVCV_SUCCESS;
|
||||
ri.module = nullptr;
|
||||
memset(&ri.dispatch, 0, sizeof(ri.dispatch));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
MeshRendererBroker::MeshRendererBroker() {
|
||||
NvCV_Status err;
|
||||
m_impl = new Impl;
|
||||
|
||||
// Automatically register the OpenGL Renderer
|
||||
MeshRenderer::Dispatch disp;
|
||||
if (NVCV_SUCCESS == (err = OpenGLMeshRenderer_InitDispatch(&disp)))
|
||||
MeshRendererBroker::addRenderer(&disp);
|
||||
}
|
||||
|
||||
|
||||
MeshRendererBroker::~MeshRendererBroker() {
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRendererBroker::setRendererDirectory(const char *dir) {
|
||||
// Load more renderers from DLLs in the given directory
|
||||
m_impl->rendererDirectory = dir;
|
||||
return m_impl->GetRenderers();
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRendererBroker::getMeshRendererList(std::vector<std::string>& list) {
|
||||
list.clear();
|
||||
list.resize(m_impl->renderers.size());
|
||||
for (size_t i = 0; i < list.size(); ++i)
|
||||
list[i] = m_impl->renderers[i].name;
|
||||
return list.size() ? NVCV_SUCCESS : NVCV_ERR_FEATURENOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRendererBroker::info(const char *renderer, const char **info) {
|
||||
if (!info)
|
||||
return NVCV_ERR_PARAMETER;
|
||||
for (const RendererInfo& ri : m_impl->renderers) {
|
||||
if (ri.name == renderer) {
|
||||
*info = ri.info.c_str();
|
||||
return NVCV_SUCCESS;
|
||||
}
|
||||
}
|
||||
*info = nullptr;
|
||||
return NVCV_ERR_FEATURENOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
NvCV_Status MeshRendererBroker::create(const char *renderer, MeshRenderer **han) {
|
||||
if (!han)
|
||||
return NVCV_ERR_PARAMETER;
|
||||
for (const RendererInfo& ri : m_impl->renderers) {
|
||||
if (ri.name == renderer) {
|
||||
if (!ri.dispatch.create) {
|
||||
NvCV_Status err = m_impl->LoadRenderer(renderer);
|
||||
if (NVCV_SUCCESS != err)
|
||||
return err;
|
||||
}
|
||||
return ri.dispatch.create(han);
|
||||
}
|
||||
}
|
||||
*han = nullptr;
|
||||
return NVCV_ERR_FEATURENOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
void MeshRendererBroker::addRenderer(MeshRenderer::Dispatch *disp) {
|
||||
unsigned n = unsigned(m_impl->renderers.size());
|
||||
m_impl->renderers.resize(n + 1);
|
||||
RendererInfo& ri = m_impl->renderers[n];
|
||||
ri.dispatch = *disp;
|
||||
const char *str;
|
||||
disp->name(&str); ri.name = str;
|
||||
disp->info(&str); ri.info = str;
|
||||
}
|
||||
Reference in New Issue
Block a user