Add macOS support to C4D importer (#5516)

The latest Cineware SDK explicitly asserts macOS support in its
documentation, but Assimp's C4D importer only works with Windows MSVC
targets. Let's improve its portability by refactoring importer code to
not depend on MSVC-only data types and quirks, and add support for linking
against the universal macOS static libraries provided in the Cineware
SDK.

Note that the C4D importer still cannot support Linux platforms because
Maxon does not provide the necessary precompiled Cineware libraries for
that platform. Windows MinGW targets are also out of the question as the
MinGW toolchain uses compiled libraries in a different format.

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
pull/5505/head^2
Alejandro González 2024-04-07 00:25:46 +02:00 committed by GitHub
parent 52c2b6896a
commit 790aad4b62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 15 deletions

View File

@ -563,9 +563,9 @@ SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
) )
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
IF ( MSVC )
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes") SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
IF (WIN32)
# pick the correct prebuilt library # pick the correct prebuilt library
IF(MSVC143) IF(MSVC143)
SET(C4D_LIB_POSTFIX "_2022") SET(C4D_LIB_POSTFIX "_2022")
@ -583,7 +583,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
SET(C4D_LIB_POSTFIX "_2010") SET(C4D_LIB_POSTFIX "_2010")
ELSE() ELSE()
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"C4D is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3" "C4D for Windows is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3"
) )
ENDIF() ENDIF()
@ -601,9 +601,20 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
# winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because
# it can be used to communicate with a running Cinema 4D instance # it can be used to communicate with a running Cinema 4D instance
SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib) SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
ELSEIF (APPLE)
SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/osx")
SET(C4D_DEBUG_LIBRARIES
"${C4D_LIB_BASE_PATH}/debug/libcinewarelib.a"
"${C4D_LIB_BASE_PATH}/debug/libjpeglib.a"
)
SET(C4D_RELEASE_LIBRARIES
"${C4D_LIB_BASE_PATH}/release/libcinewarelib.a"
"${C4D_LIB_BASE_PATH}/release/libjpeglib.a"
)
ELSE () ELSE ()
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware" "C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware"
) )
ENDIF () ENDIF ()
ELSE () ELSE ()

View File

@ -46,10 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// no #ifdefing here, Cinema4D support is carried out in a branch of assimp // no #ifdefing here, Cinema4D support is carried out in a branch of assimp
// where it is turned on in the CMake settings. // where it is turned on in the CMake settings.
#ifndef _MSC_VER
# error C4D support is currently MSVC only
#endif
#include "C4DImporter.h" #include "C4DImporter.h"
#include <memory> #include <memory>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
@ -111,7 +107,7 @@ C4DImporter::C4DImporter() = default;
C4DImporter::~C4DImporter() = default; C4DImporter::~C4DImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const { bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
const std::string& extension = GetExtension(pFile); const std::string& extension = GetExtension(pFile);
if (extension == "c4d") { if (extension == "c4d") {
return true; return true;
@ -305,7 +301,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
// based on Cineware sample code // based on Cineware sample code
while (object) { while (object) {
const LONG type = object->GetType(); const Int32 type = object->GetType();
const Matrix& ml = object->GetMl(); const Matrix& ml = object->GetMl();
aiNode* const nd = new aiNode(); aiNode* const nd = new aiNode();
@ -368,8 +364,8 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object); PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
ai_assert(polyObject != nullptr); ai_assert(polyObject != nullptr);
const LONG pointCount = polyObject->GetPointCount(); const Int32 pointCount = polyObject->GetPointCount();
const LONG polyCount = polyObject->GetPolygonCount(); const Int32 polyCount = polyObject->GetPolygonCount();
if(!polyObject || !pointCount) { if(!polyObject || !pointCount) {
LogWarn("ignoring mesh with zero vertices or faces"); LogWarn("ignoring mesh with zero vertices or faces");
return nullptr; return nullptr;
@ -391,7 +387,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
unsigned int vcount = 0; unsigned int vcount = 0;
// first count vertices // first count vertices
for (LONG i = 0; i < polyCount; i++) for (Int32 i = 0; i < polyCount; i++)
{ {
vcount += 3; vcount += 3;
@ -434,7 +430,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
} }
// copy vertices and extra channels over and populate faces // copy vertices and extra channels over and populate faces
for (LONG i = 0; i < polyCount; ++i, ++face) { for (Int32 i = 0; i < polyCount; ++i, ++face) {
ai_assert(polys[i].a < pointCount && polys[i].a >= 0); ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
const Vector& pointA = points[polys[i].a]; const Vector& pointA = points[polys[i].a];
verts->x = pointA.x; verts->x = pointA.x;
@ -511,7 +507,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
if (tangents_src) { if (tangents_src) {
for(unsigned int k = 0; k < face->mNumIndices; ++k) { for(unsigned int k = 0; k < face->mNumIndices; ++k) {
LONG l; Int32 l;
switch(k) { switch(k) {
case 0: case 0:
l = polys[i].a; l = polys[i].a;

View File

@ -78,6 +78,8 @@ namespace Assimp {
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> { class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
public: public:
C4DImporter();
~C4DImporter() override;
bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override; bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
protected: protected: