commit
484eb99920
|
@ -0,0 +1,2 @@
|
||||||
|
patreon: assimp
|
||||||
|
ko_fi: kimkulling
|
|
@ -173,7 +173,6 @@ SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VER
|
||||||
SET (ASSIMP_SOVERSION 5)
|
SET (ASSIMP_SOVERSION 5)
|
||||||
|
|
||||||
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
|
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
|
||||||
|
|
||||||
if(NOT HUNTER_ENABLED)
|
if(NOT HUNTER_ENABLED)
|
||||||
# Enable C++11 support globally
|
# Enable C++11 support globally
|
||||||
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
|
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
|
||||||
|
@ -254,6 +253,7 @@ ELSEIF(MSVC)
|
||||||
IF(MSVC12)
|
IF(MSVC12)
|
||||||
ADD_COMPILE_OPTIONS(/wd4351)
|
ADD_COMPILE_OPTIONS(/wd4351)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2")
|
||||||
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
|
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
|
||||||
IF(NOT HUNTER_ENABLED)
|
IF(NOT HUNTER_ENABLED)
|
||||||
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
|
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
|
||||||
|
@ -341,7 +341,7 @@ SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING
|
||||||
|
|
||||||
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
|
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
|
||||||
|
|
||||||
IF (is_multi_config OR (CMAKE_BUILD_TYPE STREQUAL "Debug"))
|
IF (INJECT_DEBUG_POSTFIX AND (is_multi_config OR CMAKE_BUILD_TYPE STREQUAL "Debug"))
|
||||||
SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools")
|
SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools")
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools")
|
SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools")
|
||||||
|
|
|
@ -14,7 +14,6 @@ matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
|
||||||
image:
|
image:
|
||||||
- Visual Studio 2013
|
|
||||||
- Visual Studio 2015
|
- Visual Studio 2015
|
||||||
- Visual Studio 2017
|
- Visual Studio 2017
|
||||||
|
|
||||||
|
@ -27,7 +26,6 @@ configuration: Release
|
||||||
install:
|
install:
|
||||||
- set PATH=C:\Ruby24-x64\bin;%PATH%
|
- set PATH=C:\Ruby24-x64\bin;%PATH%
|
||||||
- set CMAKE_DEFINES -DASSIMP_WERROR=ON
|
- set CMAKE_DEFINES -DASSIMP_WERROR=ON
|
||||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" set CMAKE_GENERATOR_NAME=Visual Studio 12 2013
|
|
||||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
|
||||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
|
||||||
- if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
|
- if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
|
||||||
|
|
|
@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/importerdesc.h>
|
#include <assimp/importerdesc.h>
|
||||||
#include <assimp/StringComparison.h>
|
#include <assimp/StringComparison.h>
|
||||||
#include <assimp/StringUtils.h>
|
#include <assimp/StringUtils.h>
|
||||||
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -58,11 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "D3MFOpcPackage.h"
|
#include "D3MFOpcPackage.h"
|
||||||
#ifdef ASSIMP_USE_HUNTER
|
|
||||||
# include <minizip/unzip.h>
|
|
||||||
#else
|
|
||||||
# include <unzip.h>
|
|
||||||
#endif
|
|
||||||
#include <assimp/irrXMLWrapper.h>
|
#include <assimp/irrXMLWrapper.h>
|
||||||
#include "3MFXmlTags.h"
|
#include "3MFXmlTags.h"
|
||||||
#include <assimp/fast_atof.h>
|
#include <assimp/fast_atof.h>
|
||||||
|
@ -453,7 +449,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
|
||||||
if ( nullptr == pIOHandler ) {
|
if ( nullptr == pIOHandler ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( !D3MF::D3MFOpcPackage::isZipArchive( pIOHandler, filename ) ) {
|
if ( !ZipArchiveIOSystem::isZipArchive( pIOHandler, filename ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename );
|
D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename );
|
||||||
|
|
|
@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/IOSystem.hpp>
|
#include <assimp/IOSystem.hpp>
|
||||||
#include <assimp/DefaultLogger.hpp>
|
#include <assimp/DefaultLogger.hpp>
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -56,344 +57,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#ifdef ASSIMP_USE_HUNTER
|
|
||||||
# include <minizip/unzip.h>
|
|
||||||
#else
|
|
||||||
# include <unzip.h>
|
|
||||||
#endif
|
|
||||||
#include "3MFXmlTags.h"
|
#include "3MFXmlTags.h"
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
namespace D3MF {
|
namespace D3MF {
|
||||||
|
|
||||||
class IOSystem2Unzip {
|
|
||||||
public:
|
|
||||||
static voidpf open(voidpf opaque, const char* filename, int mode);
|
|
||||||
static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
|
|
||||||
static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
|
|
||||||
static long tell(voidpf opaque, voidpf stream);
|
|
||||||
static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
|
|
||||||
static int close(voidpf opaque, voidpf stream);
|
|
||||||
static int testerror(voidpf opaque, voidpf stream);
|
|
||||||
static zlib_filefunc_def get(IOSystem* pIOHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
|
|
||||||
IOSystem* io_system = reinterpret_cast<IOSystem*>(opaque);
|
|
||||||
|
|
||||||
const char* mode_fopen = NULL;
|
|
||||||
if((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) {
|
|
||||||
mode_fopen = "rb";
|
|
||||||
} else {
|
|
||||||
if(mode & ZLIB_FILEFUNC_MODE_EXISTING) {
|
|
||||||
mode_fopen = "r+b";
|
|
||||||
} else {
|
|
||||||
if(mode & ZLIB_FILEFUNC_MODE_CREATE) {
|
|
||||||
mode_fopen = "wb";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (voidpf) io_system->Open(filename, mode_fopen);
|
|
||||||
}
|
|
||||||
|
|
||||||
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
return static_cast<uLong>(io_stream->Read(buf, 1, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
return static_cast<uLong>(io_stream->Write(buf, 1, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
return static_cast<long>(io_stream->Tell());
|
|
||||||
}
|
|
||||||
|
|
||||||
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
aiOrigin assimp_origin;
|
|
||||||
switch (origin) {
|
|
||||||
default:
|
|
||||||
case ZLIB_FILEFUNC_SEEK_CUR:
|
|
||||||
assimp_origin = aiOrigin_CUR;
|
|
||||||
break;
|
|
||||||
case ZLIB_FILEFUNC_SEEK_END:
|
|
||||||
assimp_origin = aiOrigin_END;
|
|
||||||
break;
|
|
||||||
case ZLIB_FILEFUNC_SEEK_SET:
|
|
||||||
assimp_origin = aiOrigin_SET;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
|
|
||||||
IOSystem* io_system = (IOSystem*) opaque;
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
io_system->Close(io_stream);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
|
|
||||||
zlib_filefunc_def mapping;
|
|
||||||
|
|
||||||
#ifdef ASSIMP_USE_HUNTER
|
|
||||||
mapping.zopen_file = (open_file_func)open;
|
|
||||||
mapping.zread_file = (read_file_func)read;
|
|
||||||
mapping.zwrite_file = (write_file_func)write;
|
|
||||||
mapping.ztell_file = (tell_file_func)tell;
|
|
||||||
mapping.zseek_file = (seek_file_func)seek;
|
|
||||||
mapping.zclose_file = (close_file_func)close;
|
|
||||||
mapping.zerror_file = (error_file_func)testerror;
|
|
||||||
#else
|
|
||||||
mapping.zopen_file = open;
|
|
||||||
mapping.zread_file = read;
|
|
||||||
mapping.zwrite_file = write;
|
|
||||||
mapping.ztell_file = tell;
|
|
||||||
mapping.zseek_file = seek;
|
|
||||||
mapping.zclose_file = close;
|
|
||||||
mapping.zerror_file = testerror;
|
|
||||||
#endif
|
|
||||||
mapping.opaque = reinterpret_cast<voidpf>(pIOHandler);
|
|
||||||
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ZipFile : public IOStream {
|
|
||||||
friend class D3MFZipArchive;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ZipFile(size_t size);
|
|
||||||
virtual ~ZipFile();
|
|
||||||
size_t Read(void* pvBuffer, size_t pSize, size_t pCount );
|
|
||||||
size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/);
|
|
||||||
size_t FileSize() const;
|
|
||||||
aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/);
|
|
||||||
size_t Tell() const;
|
|
||||||
void Flush();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void *m_Buffer;
|
|
||||||
size_t m_Size;
|
|
||||||
};
|
|
||||||
|
|
||||||
ZipFile::ZipFile(size_t size)
|
|
||||||
: m_Buffer( nullptr )
|
|
||||||
, m_Size(size) {
|
|
||||||
ai_assert(m_Size != 0);
|
|
||||||
m_Buffer = ::malloc(m_Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZipFile::~ZipFile() {
|
|
||||||
::free(m_Buffer);
|
|
||||||
m_Buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) {
|
|
||||||
const size_t size = pSize * pCount;
|
|
||||||
ai_assert(size <= m_Size);
|
|
||||||
|
|
||||||
std::memcpy(pvBuffer, m_Buffer, size);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZipFile::Write(const void* pvBuffer, size_t size, size_t pCount ) {
|
|
||||||
const size_t size_to_write( size * pCount );
|
|
||||||
if ( 0 == size_to_write ) {
|
|
||||||
return 0U;
|
|
||||||
}
|
|
||||||
return 0U;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZipFile::FileSize() const {
|
|
||||||
return m_Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
aiReturn ZipFile::Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) {
|
|
||||||
return aiReturn_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZipFile::Tell() const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZipFile::Flush() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
class D3MFZipArchive : public IOSystem {
|
|
||||||
public:
|
|
||||||
static const unsigned int FileNameSize = 256;
|
|
||||||
|
|
||||||
D3MFZipArchive(IOSystem* pIOHandler, const std::string & rFile);
|
|
||||||
~D3MFZipArchive();
|
|
||||||
bool Exists(const char* pFile) const;
|
|
||||||
char getOsSeparator() const;
|
|
||||||
IOStream* Open(const char* pFile, const char* pMode = "rb");
|
|
||||||
void Close(IOStream* pFile);
|
|
||||||
bool isOpen() const;
|
|
||||||
void getFileList(std::vector<std::string> &rFileList);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool mapArchive();
|
|
||||||
|
|
||||||
private:
|
|
||||||
unzFile m_ZipFileHandle;
|
|
||||||
std::map<std::string, ZipFile*> m_ArchiveMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Constructor.
|
|
||||||
D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile)
|
|
||||||
: m_ZipFileHandle( nullptr )
|
|
||||||
, m_ArchiveMap() {
|
|
||||||
if (! rFile.empty()) {
|
|
||||||
zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
|
|
||||||
|
|
||||||
m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
|
|
||||||
if(m_ZipFileHandle != nullptr ) {
|
|
||||||
mapArchive();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Destructor.
|
|
||||||
D3MFZipArchive::~D3MFZipArchive() {
|
|
||||||
for(auto &file : m_ArchiveMap) {
|
|
||||||
delete file.second;
|
|
||||||
}
|
|
||||||
m_ArchiveMap.clear();
|
|
||||||
|
|
||||||
if(m_ZipFileHandle != nullptr) {
|
|
||||||
unzClose(m_ZipFileHandle);
|
|
||||||
m_ZipFileHandle = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Returns true, if the archive is already open.
|
|
||||||
bool D3MFZipArchive::isOpen() const {
|
|
||||||
return (m_ZipFileHandle != nullptr );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Returns true, if the filename is part of the archive.
|
|
||||||
bool D3MFZipArchive::Exists(const char* pFile) const {
|
|
||||||
ai_assert(pFile != nullptr );
|
|
||||||
|
|
||||||
if ( pFile == nullptr ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string filename(pFile);
|
|
||||||
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(filename);
|
|
||||||
bool exist( false );
|
|
||||||
if(it != m_ArchiveMap.end()) {
|
|
||||||
exist = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return exist;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Returns the separator delimiter.
|
|
||||||
char D3MFZipArchive::getOsSeparator() const {
|
|
||||||
#ifndef _WIN32
|
|
||||||
return '/';
|
|
||||||
#else
|
|
||||||
return '\\';
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Opens a file, which is part of the archive.
|
|
||||||
IOStream *D3MFZipArchive::Open(const char* pFile, const char* /*pMode*/) {
|
|
||||||
ai_assert(pFile != NULL);
|
|
||||||
|
|
||||||
IOStream* result = NULL;
|
|
||||||
|
|
||||||
std::map<std::string, ZipFile*>::iterator it = m_ArchiveMap.find(pFile);
|
|
||||||
|
|
||||||
if(it != m_ArchiveMap.end()) {
|
|
||||||
result = static_cast<IOStream*>(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Close a filestream.
|
|
||||||
void D3MFZipArchive::Close(IOStream *pFile) {
|
|
||||||
(void)(pFile);
|
|
||||||
ai_assert(pFile != NULL);
|
|
||||||
|
|
||||||
// We don't do anything in case the file would be opened again in the future
|
|
||||||
}
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Returns the file-list of the archive.
|
|
||||||
void D3MFZipArchive::getFileList(std::vector<std::string> &rFileList) {
|
|
||||||
rFileList.clear();
|
|
||||||
|
|
||||||
for(const auto &file : m_ArchiveMap) {
|
|
||||||
rFileList.push_back(file.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Maps the archive content.
|
|
||||||
bool D3MFZipArchive::mapArchive() {
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
if(m_ZipFileHandle != NULL) {
|
|
||||||
if(m_ArchiveMap.empty()) {
|
|
||||||
// At first ensure file is already open
|
|
||||||
if(unzGoToFirstFile(m_ZipFileHandle) == UNZ_OK) {
|
|
||||||
// Loop over all files
|
|
||||||
do {
|
|
||||||
char filename[FileNameSize];
|
|
||||||
unz_file_info fileInfo;
|
|
||||||
|
|
||||||
if(unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, NULL, 0, NULL, 0) == UNZ_OK) {
|
|
||||||
// The file has EXACTLY the size of uncompressed_size. In C
|
|
||||||
// you need to mark the last character with '\0', so add
|
|
||||||
// another character
|
|
||||||
if(fileInfo.uncompressed_size != 0 && unzOpenCurrentFile(m_ZipFileHandle) == UNZ_OK) {
|
|
||||||
std::pair<std::map<std::string, ZipFile*>::iterator, bool> result = m_ArchiveMap.insert(std::make_pair(filename, new ZipFile(fileInfo.uncompressed_size)));
|
|
||||||
|
|
||||||
if(unzReadCurrentFile(m_ZipFileHandle, result.first->second->m_Buffer, fileInfo.uncompressed_size) == (long int) fileInfo.uncompressed_size) {
|
|
||||||
if(unzCloseCurrentFile(m_ZipFileHandle) == UNZ_OK) {
|
|
||||||
// Nothing to do anymore...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while(unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
|
typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
|
||||||
|
@ -453,7 +121,7 @@ public:
|
||||||
D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
|
D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
|
||||||
: mRootStream(nullptr)
|
: mRootStream(nullptr)
|
||||||
, mZipArchive() {
|
, mZipArchive() {
|
||||||
mZipArchive.reset( new D3MF::D3MFZipArchive( pIOHandler, rFile ) );
|
mZipArchive.reset( new ZipArchiveIOSystem( pIOHandler, rFile ) );
|
||||||
if(!mZipArchive->isOpen()) {
|
if(!mZipArchive->isOpen()) {
|
||||||
throw DeadlyImportError("Failed to open file " + rFile+ ".");
|
throw DeadlyImportError("Failed to open file " + rFile+ ".");
|
||||||
}
|
}
|
||||||
|
@ -481,14 +149,14 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
|
||||||
|
|
||||||
ASSIMP_LOG_DEBUG(rootFile);
|
ASSIMP_LOG_DEBUG(rootFile);
|
||||||
|
|
||||||
|
mZipArchive->Close(fileStream);
|
||||||
|
|
||||||
mRootStream = mZipArchive->Open(rootFile.c_str());
|
mRootStream = mZipArchive->Open(rootFile.c_str());
|
||||||
ai_assert( mRootStream != nullptr );
|
ai_assert( mRootStream != nullptr );
|
||||||
if ( nullptr == mRootStream ) {
|
if ( nullptr == mRootStream ) {
|
||||||
throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile );
|
throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile );
|
||||||
}
|
}
|
||||||
|
|
||||||
mZipArchive->Close( fileStream );
|
|
||||||
|
|
||||||
} else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
|
} else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
|
||||||
ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES",file);
|
ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES",file);
|
||||||
} else {
|
} else {
|
||||||
|
@ -499,7 +167,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
D3MFOpcPackage::~D3MFOpcPackage() {
|
D3MFOpcPackage::~D3MFOpcPackage() {
|
||||||
// empty
|
mZipArchive->Close(mRootStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
IOStream* D3MFOpcPackage::RootStream() const {
|
IOStream* D3MFOpcPackage::RootStream() const {
|
||||||
|
@ -516,15 +184,6 @@ bool D3MFOpcPackage::validate() {
|
||||||
return mZipArchive->Exists( ModelRef.c_str() );
|
return mZipArchive->Exists( ModelRef.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3MFOpcPackage::isZipArchive( IOSystem* pIOHandler, const std::string& rFile ) {
|
|
||||||
D3MF::D3MFZipArchive ar( pIOHandler, rFile );
|
|
||||||
if ( !ar.isOpen() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
|
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
|
||||||
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
|
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
|
||||||
std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
|
std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
|
||||||
|
|
|
@ -49,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/irrXMLWrapper.h>
|
#include <assimp/irrXMLWrapper.h>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
class ZipArchiveIOSystem;
|
||||||
|
|
||||||
namespace D3MF {
|
namespace D3MF {
|
||||||
|
|
||||||
using XmlReader = irr::io::IrrXMLReader ;
|
using XmlReader = irr::io::IrrXMLReader ;
|
||||||
|
@ -60,22 +62,19 @@ struct OpcPackageRelationship {
|
||||||
std::string target;
|
std::string target;
|
||||||
};
|
};
|
||||||
|
|
||||||
class D3MFZipArchive;
|
|
||||||
|
|
||||||
class D3MFOpcPackage {
|
class D3MFOpcPackage {
|
||||||
public:
|
public:
|
||||||
D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile );
|
D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile );
|
||||||
~D3MFOpcPackage();
|
~D3MFOpcPackage();
|
||||||
IOStream* RootStream() const;
|
IOStream* RootStream() const;
|
||||||
bool validate();
|
bool validate();
|
||||||
static bool isZipArchive( IOSystem* pIOHandler, const std::string& rFile );
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string ReadPackageRootRelationship(IOStream* stream);
|
std::string ReadPackageRootRelationship(IOStream* stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IOStream* mRootStream;
|
IOStream* mRootStream;
|
||||||
std::unique_ptr<D3MFZipArchive> mZipArchive;
|
std::unique_ptr<ZipArchiveIOSystem> mZipArchive;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace D3MF
|
} // Namespace D3MF
|
||||||
|
|
|
@ -34,15 +34,6 @@ namespace Assimp {
|
||||||
|
|
||||||
void ExportAssimp2Json(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*);
|
void ExportAssimp2Json(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*);
|
||||||
|
|
||||||
Exporter::ExportFormatEntry Assimp2Json_desc = Assimp::Exporter::ExportFormatEntry(
|
|
||||||
"json",
|
|
||||||
"Plain JSON representation of the Assimp scene data structure",
|
|
||||||
"json",
|
|
||||||
&ExportAssimp2Json,
|
|
||||||
0u
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// small utility class to simplify serializing the aiScene to Json
|
// small utility class to simplify serializing the aiScene to Json
|
||||||
class JSONWriter {
|
class JSONWriter {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -104,6 +104,7 @@ SET( PUBLIC_HEADERS
|
||||||
${HEADER_PATH}/Exporter.hpp
|
${HEADER_PATH}/Exporter.hpp
|
||||||
${HEADER_PATH}/DefaultIOStream.h
|
${HEADER_PATH}/DefaultIOStream.h
|
||||||
${HEADER_PATH}/DefaultIOSystem.h
|
${HEADER_PATH}/DefaultIOSystem.h
|
||||||
|
${HEADER_PATH}/ZipArchiveIOSystem.h
|
||||||
${HEADER_PATH}/SceneCombiner.h
|
${HEADER_PATH}/SceneCombiner.h
|
||||||
${HEADER_PATH}/fast_atof.h
|
${HEADER_PATH}/fast_atof.h
|
||||||
${HEADER_PATH}/qnan.h
|
${HEADER_PATH}/qnan.h
|
||||||
|
@ -172,6 +173,7 @@ SET( Common_SRCS
|
||||||
Common/DefaultProgressHandler.h
|
Common/DefaultProgressHandler.h
|
||||||
Common/DefaultIOStream.cpp
|
Common/DefaultIOStream.cpp
|
||||||
Common/DefaultIOSystem.cpp
|
Common/DefaultIOSystem.cpp
|
||||||
|
Common/ZipArchiveIOSystem.cpp
|
||||||
Common/PolyTools.h
|
Common/PolyTools.h
|
||||||
Common/Importer.cpp
|
Common/Importer.cpp
|
||||||
Common/IFF.h
|
Common/IFF.h
|
||||||
|
@ -688,8 +690,6 @@ ADD_ASSIMP_IMPORTER( Q3BSP
|
||||||
Q3BSP/Q3BSPFileParser.cpp
|
Q3BSP/Q3BSPFileParser.cpp
|
||||||
Q3BSP/Q3BSPFileImporter.h
|
Q3BSP/Q3BSPFileImporter.h
|
||||||
Q3BSP/Q3BSPFileImporter.cpp
|
Q3BSP/Q3BSPFileImporter.cpp
|
||||||
Q3BSP/Q3BSPZipArchive.h
|
|
||||||
Q3BSP/Q3BSPZipArchive.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_ASSIMP_IMPORTER( RAW
|
ADD_ASSIMP_IMPORTER( RAW
|
||||||
|
@ -810,7 +810,7 @@ ADD_ASSIMP_IMPORTER( MMD
|
||||||
MMD/MMDVmdParser.h
|
MMD/MMDVmdParser.h
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_ASSIMP_EXPORTER( Assjson
|
ADD_ASSIMP_EXPORTER( ASSJSON
|
||||||
Assjson/cencode.c
|
Assjson/cencode.c
|
||||||
Assjson/cencode.h
|
Assjson/cencode.h
|
||||||
Assjson/json_exporter.cpp
|
Assjson/json_exporter.cpp
|
||||||
|
|
|
@ -580,15 +580,11 @@ struct Image
|
||||||
{
|
{
|
||||||
std::string mFileName;
|
std::string mFileName;
|
||||||
|
|
||||||
/** If image file name is zero, embedded image data
|
/** Embedded image data */
|
||||||
*/
|
|
||||||
std::vector<uint8_t> mImageData;
|
std::vector<uint8_t> mImageData;
|
||||||
|
|
||||||
/** If image file name is zero, file format of
|
/** File format hint ofembedded image data */
|
||||||
* embedded image data.
|
|
||||||
*/
|
|
||||||
std::string mEmbeddedFormat;
|
std::string mEmbeddedFormat;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An animation channel. */
|
/** An animation channel. */
|
||||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2019, assimp team
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -43,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
/** @file Implementation of the Collada loader */
|
/** @file Implementation of the Collada loader */
|
||||||
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
|
||||||
|
|
||||||
#include "ColladaLoader.h"
|
#include "ColladaLoader.h"
|
||||||
|
@ -60,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/ParsingUtils.h>
|
#include <assimp/ParsingUtils.h>
|
||||||
#include <assimp/SkeletonMeshBuilder.h>
|
#include <assimp/SkeletonMeshBuilder.h>
|
||||||
#include <assimp/CreateAnimMesh.h>
|
#include <assimp/CreateAnimMesh.h>
|
||||||
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
|
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
@ -67,7 +65,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
using namespace Assimp;
|
namespace Assimp {
|
||||||
|
|
||||||
using namespace Assimp::Formatter;
|
using namespace Assimp::Formatter;
|
||||||
|
|
||||||
static const aiImporterDesc desc = {
|
static const aiImporterDesc desc = {
|
||||||
|
@ -75,12 +74,12 @@ static const aiImporterDesc desc = {
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"http://collada.org",
|
"http://collada.org",
|
||||||
aiImporterFlags_SupportTextFlavour,
|
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
|
||||||
1,
|
1,
|
||||||
3,
|
3,
|
||||||
1,
|
1,
|
||||||
5,
|
5,
|
||||||
"dae"
|
"dae zae"
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -112,11 +111,22 @@ ColladaLoader::~ColladaLoader() {
|
||||||
// Returns whether the class can handle the format of the given file.
|
// Returns whether the class can handle the format of the given file.
|
||||||
bool ColladaLoader::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
|
bool ColladaLoader::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
|
||||||
// check file extension
|
// check file extension
|
||||||
std::string extension = GetExtension(pFile);
|
const std::string extension = GetExtension(pFile);
|
||||||
|
|
||||||
if (extension == "dae") {
|
bool readSig = checkSig && (pIOHandler != nullptr);
|
||||||
|
|
||||||
|
if (!readSig) {
|
||||||
|
if (extension == "dae" || extension == "zae") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readSig) {
|
||||||
|
// Look for a DAE file inside, but don't extract it
|
||||||
|
ZipArchiveIOSystem zip_archive(pIOHandler, pFile);
|
||||||
|
if (zip_archive.isOpen())
|
||||||
|
return !ColladaParser::ReadZaeManifest(zip_archive).empty();
|
||||||
|
}
|
||||||
|
|
||||||
// XML - too generic, we need to open the file and search for typical keywords
|
// XML - too generic, we need to open the file and search for typical keywords
|
||||||
if (extension == "xml" || !extension.length() || checkSig) {
|
if (extension == "xml" || !extension.length() || checkSig) {
|
||||||
|
@ -166,12 +176,14 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
||||||
// parse the input file
|
// parse the input file
|
||||||
ColladaParser parser(pIOHandler, pFile);
|
ColladaParser parser(pIOHandler, pFile);
|
||||||
|
|
||||||
if( !parser.mRootNode)
|
|
||||||
|
if( !parser.mRootNode) {
|
||||||
throw DeadlyImportError( "Collada: File came out empty. Something is wrong here.");
|
throw DeadlyImportError( "Collada: File came out empty. Something is wrong here.");
|
||||||
|
}
|
||||||
|
|
||||||
// reserve some storage to avoid unnecessary reallocs
|
// reserve some storage to avoid unnecessary reallocs
|
||||||
newMats.reserve(parser.mMaterialLibrary.size()*2);
|
newMats.reserve(parser.mMaterialLibrary.size()*2u);
|
||||||
mMeshes.reserve(parser.mMeshLibrary.size()*2);
|
mMeshes.reserve(parser.mMeshLibrary.size()*2u);
|
||||||
|
|
||||||
mCameras.reserve(parser.mCameraLibrary.size());
|
mCameras.reserve(parser.mCameraLibrary.size());
|
||||||
mLights.reserve(parser.mLightLibrary.size());
|
mLights.reserve(parser.mLightLibrary.size());
|
||||||
|
@ -186,33 +198,34 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
||||||
FillMaterials(parser, pScene);
|
FillMaterials(parser, pScene);
|
||||||
|
|
||||||
// Apply unit-size scale calculation
|
// Apply unit-size scale calculation
|
||||||
|
|
||||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
|
pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
|
||||||
0, parser.mUnitSize, 0, 0,
|
0, parser.mUnitSize, 0, 0,
|
||||||
0, 0, parser.mUnitSize, 0,
|
0, 0, parser.mUnitSize, 0,
|
||||||
0, 0, 0, 1);
|
0, 0, 0, 1);
|
||||||
if( !ignoreUpDirection ) {
|
if( !ignoreUpDirection ) {
|
||||||
// Convert to Y_UP, if different orientation
|
// Convert to Y_UP, if different orientation
|
||||||
if( parser.mUpDirection == ColladaParser::UP_X)
|
if( parser.mUpDirection == ColladaParser::UP_X) {
|
||||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||||
0, -1, 0, 0,
|
0, -1, 0, 0,
|
||||||
1, 0, 0, 0,
|
1, 0, 0, 0,
|
||||||
0, 0, 1, 0,
|
0, 0, 1, 0,
|
||||||
0, 0, 0, 1);
|
0, 0, 0, 1);
|
||||||
else if( parser.mUpDirection == ColladaParser::UP_Z)
|
} else if( parser.mUpDirection == ColladaParser::UP_Z) {
|
||||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||||
1, 0, 0, 0,
|
1, 0, 0, 0,
|
||||||
0, 0, 1, 0,
|
0, 0, 1, 0,
|
||||||
0, -1, 0, 0,
|
0, -1, 0, 0,
|
||||||
0, 0, 0, 1);
|
0, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Store scene metadata
|
// Store scene metadata
|
||||||
if (!parser.mAssetMetaData.empty()) {
|
if (!parser.mAssetMetaData.empty()) {
|
||||||
const size_t numMeta(parser.mAssetMetaData.size());
|
const size_t numMeta(parser.mAssetMetaData.size());
|
||||||
pScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
|
pScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it, ++i)
|
for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it, ++i) {
|
||||||
{
|
|
||||||
pScene->mMetaData->Set(static_cast<unsigned int>(i), (*it).first, (*it).second);
|
pScene->mMetaData->Set(static_cast<unsigned int>(i), (*it).first, (*it).second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,6 +236,9 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
||||||
// store all materials
|
// store all materials
|
||||||
StoreSceneMaterials(pScene);
|
StoreSceneMaterials(pScene);
|
||||||
|
|
||||||
|
// store all textures
|
||||||
|
StoreSceneTextures(pScene);
|
||||||
|
|
||||||
// store all lights
|
// store all lights
|
||||||
StoreSceneLights(pScene);
|
StoreSceneLights(pScene);
|
||||||
|
|
||||||
|
@ -232,9 +248,8 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
||||||
// store all animations
|
// store all animations
|
||||||
StoreAnimations(pScene, parser);
|
StoreAnimations(pScene, parser);
|
||||||
|
|
||||||
|
|
||||||
// If no meshes have been loaded, it's probably just an animated skeleton.
|
// If no meshes have been loaded, it's probably just an animated skeleton.
|
||||||
if (!pScene->mNumMeshes) {
|
if ( 0u == pScene->mNumMeshes) {
|
||||||
|
|
||||||
if (!noSkeletonMesh) {
|
if (!noSkeletonMesh) {
|
||||||
SkeletonMeshBuilder hero(pScene);
|
SkeletonMeshBuilder hero(pScene);
|
||||||
|
@ -302,13 +317,12 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
|
||||||
// FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
|
// FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
|
||||||
// need to check for both name and ID to catch all. To avoid breaking valid files,
|
// need to check for both name and ID to catch all. To avoid breaking valid files,
|
||||||
// the workaround is only enabled when the first attempt to resolve the node has failed.
|
// the workaround is only enabled when the first attempt to resolve the node has failed.
|
||||||
if (!nd) {
|
if (nullptr == nd) {
|
||||||
nd = FindNode(pParser.mRootNode, nodeInst.mNode);
|
nd = FindNode(pParser.mRootNode, nodeInst.mNode);
|
||||||
}
|
}
|
||||||
if (!nd)
|
if (nullptr == nd) {
|
||||||
ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
|
ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
|
||||||
|
} else {
|
||||||
else {
|
|
||||||
// attach this node to the list of children
|
// attach this node to the list of children
|
||||||
resolved.push_back(nd);
|
resolved.push_back(nd);
|
||||||
}
|
}
|
||||||
|
@ -318,6 +332,7 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Resolve UV channels
|
// Resolve UV channels
|
||||||
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
|
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
|
||||||
|
|
||||||
const Collada::SemanticMappingTable& table) {
|
const Collada::SemanticMappingTable& table) {
|
||||||
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
|
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
|
||||||
if (it != table.mMap.end()) {
|
if (it != table.mMap.end()) {
|
||||||
|
@ -357,7 +372,8 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
|
||||||
if (out->mType == aiLightSource_AMBIENT) {
|
if (out->mType == aiLightSource_AMBIENT) {
|
||||||
out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0);
|
out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0);
|
||||||
out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
|
out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// collada doesn't differentiate between these color types
|
// collada doesn't differentiate between these color types
|
||||||
out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity;
|
out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity;
|
||||||
out->mColorAmbient = aiColor3D(0, 0, 0);
|
out->mColorAmbient = aiColor3D(0, 0, 0);
|
||||||
|
@ -375,12 +391,14 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
|
||||||
// epsilon chosen to be 0.1
|
// epsilon chosen to be 0.1
|
||||||
out->mAngleOuterCone = std::acos(std::pow(0.1f, 1.f / srcLight->mFalloffExponent)) +
|
out->mAngleOuterCone = std::acos(std::pow(0.1f, 1.f / srcLight->mFalloffExponent)) +
|
||||||
out->mAngleInnerCone;
|
out->mAngleInnerCone;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD(srcLight->mPenumbraAngle);
|
out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD(srcLight->mPenumbraAngle);
|
||||||
if (out->mAngleOuterCone < out->mAngleInnerCone)
|
if (out->mAngleOuterCone < out->mAngleInnerCone)
|
||||||
std::swap(out->mAngleInnerCone, out->mAngleOuterCone);
|
std::swap(out->mAngleInnerCone, out->mAngleOuterCone);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
out->mAngleOuterCone = AI_DEG_TO_RAD(srcLight->mOuterAngle);
|
out->mAngleOuterCone = AI_DEG_TO_RAD(srcLight->mOuterAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -431,8 +449,8 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
|
||||||
out->mAspect = std::tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
|
out->mAspect = std::tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
|
||||||
std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov));
|
std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
|
} else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
|
||||||
out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(std::atan(srcCamera->mAspect *
|
out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(std::atan(srcCamera->mAspect *
|
||||||
std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
|
std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
|
||||||
}
|
}
|
||||||
|
@ -470,11 +488,13 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !srcMesh) {
|
|
||||||
|
if( nullptr == srcMesh) {
|
||||||
ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
|
ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// ID found in the mesh library -> direct reference to an unskinned mesh
|
// ID found in the mesh library -> direct reference to an unskinned mesh
|
||||||
srcMesh = srcMeshIt->second;
|
srcMesh = srcMeshIt->second;
|
||||||
}
|
}
|
||||||
|
@ -495,7 +515,8 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
||||||
if (meshMatIt != mid.mMaterials.end()) {
|
if (meshMatIt != mid.mMaterials.end()) {
|
||||||
table = &meshMatIt->second;
|
table = &meshMatIt->second;
|
||||||
meshMaterial = table->mMatName;
|
meshMaterial = table->mMatName;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ASSIMP_LOG_WARN_F("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
|
ASSIMP_LOG_WARN_F("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
|
||||||
mid.mMeshOrController, ">.");
|
mid.mMeshOrController, ">.");
|
||||||
if (!mid.mMaterials.empty()) {
|
if (!mid.mMaterials.empty()) {
|
||||||
|
@ -531,7 +552,8 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
||||||
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find(index);
|
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find(index);
|
||||||
if (dstMeshIt != mMeshIndexByID.end()) {
|
if (dstMeshIt != mMeshIndexByID.end()) {
|
||||||
newMeshRefs.push_back(dstMeshIt->second);
|
newMeshRefs.push_back(dstMeshIt->second);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// else we have to add the mesh to the collection and store its newly assigned index at the node
|
// else we have to add the mesh to the collection and store its newly assigned index at the node
|
||||||
aiMesh* dstMesh = CreateMesh(pParser, srcMesh, submesh, srcController, vertexStart, faceStart);
|
aiMesh* dstMesh = CreateMesh(pParser, srcMesh, submesh, srcController, vertexStart, faceStart);
|
||||||
|
|
||||||
|
@ -770,12 +792,14 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex];
|
IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex];
|
||||||
size_t pairCount = pSrcController->mWeightCounts[orgIndex];
|
size_t pairCount = pSrcController->mWeightCounts[orgIndex];
|
||||||
|
|
||||||
for( size_t b = 0; b < pairCount; ++b, ++iit)
|
|
||||||
{
|
|
||||||
size_t jointIndex = iit->first;
|
|
||||||
size_t vertexIndex = iit->second;
|
|
||||||
|
|
||||||
ai_real weight = ReadFloat( weightsAcc, weights, vertexIndex, 0);
|
for( size_t b = 0; b < pairCount; ++b, ++iit) {
|
||||||
|
const size_t jointIndex = iit->first;
|
||||||
|
const size_t vertexIndex = iit->second;
|
||||||
|
ai_real weight = 1.0f;
|
||||||
|
if (!weights.mValues.empty()) {
|
||||||
|
weight = ReadFloat(weightsAcc, weights, vertexIndex, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// one day I gonna kill that XSI Collada exporter
|
// one day I gonna kill that XSI Collada exporter
|
||||||
if (weight > 0.0f)
|
if (weight > 0.0f)
|
||||||
|
@ -790,19 +814,21 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
|
|
||||||
// count the number of bones which influence vertices of the current submesh
|
// count the number of bones which influence vertices of the current submesh
|
||||||
size_t numRemainingBones = 0;
|
size_t numRemainingBones = 0;
|
||||||
for( std::vector<std::vector<aiVertexWeight> >::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it)
|
for( std::vector<std::vector<aiVertexWeight> >::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it) {
|
||||||
if( it->size() > 0)
|
if( it->size() > 0) {
|
||||||
numRemainingBones++;
|
++numRemainingBones;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create bone array and copy bone weights one by one
|
// create bone array and copy bone weights one by one
|
||||||
dstMesh->mNumBones = static_cast<unsigned int>(numRemainingBones);
|
dstMesh->mNumBones = static_cast<unsigned int>(numRemainingBones);
|
||||||
dstMesh->mBones = new aiBone*[numRemainingBones];
|
dstMesh->mBones = new aiBone*[numRemainingBones];
|
||||||
size_t boneCount = 0;
|
size_t boneCount = 0;
|
||||||
for( size_t a = 0; a < numBones; ++a)
|
for( size_t a = 0; a < numBones; ++a) {
|
||||||
{
|
|
||||||
// omit bones without weights
|
// omit bones without weights
|
||||||
if( dstBones[a].size() == 0)
|
if( dstBones[a].empty() ) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// create bone with its weights
|
// create bone with its weights
|
||||||
aiBone* bone = new aiBone;
|
aiBone* bone = new aiBone;
|
||||||
|
@ -848,14 +874,16 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
// and replace the bone's name by the node's name so that the user can use the standard
|
// and replace the bone's name by the node's name so that the user can use the standard
|
||||||
// find-by-name method to associate nodes with bones.
|
// find-by-name method to associate nodes with bones.
|
||||||
const Collada::Node* bnode = FindNode( pParser.mRootNode, bone->mName.data);
|
const Collada::Node* bnode = FindNode( pParser.mRootNode, bone->mName.data);
|
||||||
if( !bnode)
|
if( !bnode) {
|
||||||
bnode = FindNodeBySID( pParser.mRootNode, bone->mName.data);
|
bnode = FindNodeBySID( pParser.mRootNode, bone->mName.data);
|
||||||
|
}
|
||||||
|
|
||||||
// assign the name that we would have assigned for the source node
|
// assign the name that we would have assigned for the source node
|
||||||
if( bnode)
|
if( bnode) {
|
||||||
bone->mName.Set( FindNameForNode( bnode));
|
bone->mName.Set( FindNameForNode( bnode));
|
||||||
else
|
} else {
|
||||||
ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." );
|
ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." );
|
||||||
|
}
|
||||||
|
|
||||||
// and insert bone
|
// and insert bone
|
||||||
dstMesh->mBones[boneCount++] = bone;
|
dstMesh->mBones[boneCount++] = bone;
|
||||||
|
@ -867,89 +895,80 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Stores all meshes in the given scene
|
// Stores all meshes in the given scene
|
||||||
void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
|
void ColladaLoader::StoreSceneMeshes( aiScene* pScene) {
|
||||||
{
|
|
||||||
pScene->mNumMeshes = static_cast<unsigned int>(mMeshes.size());
|
pScene->mNumMeshes = static_cast<unsigned int>(mMeshes.size());
|
||||||
if( mMeshes.size() > 0)
|
if( mMeshes.empty() ) {
|
||||||
{
|
return;
|
||||||
|
}
|
||||||
pScene->mMeshes = new aiMesh*[mMeshes.size()];
|
pScene->mMeshes = new aiMesh*[mMeshes.size()];
|
||||||
std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
|
std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
|
||||||
mMeshes.clear();
|
mMeshes.clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Stores all cameras in the given scene
|
// Stores all cameras in the given scene
|
||||||
void ColladaLoader::StoreSceneCameras( aiScene* pScene)
|
void ColladaLoader::StoreSceneCameras( aiScene* pScene) {
|
||||||
{
|
|
||||||
pScene->mNumCameras = static_cast<unsigned int>(mCameras.size());
|
pScene->mNumCameras = static_cast<unsigned int>(mCameras.size());
|
||||||
if( mCameras.size() > 0)
|
if( mCameras.empty() ) {
|
||||||
{
|
return;
|
||||||
|
}
|
||||||
pScene->mCameras = new aiCamera*[mCameras.size()];
|
pScene->mCameras = new aiCamera*[mCameras.size()];
|
||||||
std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras);
|
std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras);
|
||||||
mCameras.clear();
|
mCameras.clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Stores all lights in the given scene
|
// Stores all lights in the given scene
|
||||||
void ColladaLoader::StoreSceneLights( aiScene* pScene)
|
void ColladaLoader::StoreSceneLights( aiScene* pScene) {
|
||||||
{
|
|
||||||
pScene->mNumLights = static_cast<unsigned int>(mLights.size());
|
pScene->mNumLights = static_cast<unsigned int>(mLights.size());
|
||||||
if( mLights.size() > 0)
|
if( mLights.empty() ) {
|
||||||
{
|
return;
|
||||||
|
}
|
||||||
pScene->mLights = new aiLight*[mLights.size()];
|
pScene->mLights = new aiLight*[mLights.size()];
|
||||||
std::copy( mLights.begin(), mLights.end(), pScene->mLights);
|
std::copy( mLights.begin(), mLights.end(), pScene->mLights);
|
||||||
mLights.clear();
|
mLights.clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Stores all textures in the given scene
|
// Stores all textures in the given scene
|
||||||
void ColladaLoader::StoreSceneTextures( aiScene* pScene)
|
void ColladaLoader::StoreSceneTextures( aiScene* pScene) {
|
||||||
{
|
|
||||||
pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
|
pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
|
||||||
if( mTextures.size() > 0)
|
if( mTextures.empty() ) {
|
||||||
{
|
return;
|
||||||
|
}
|
||||||
pScene->mTextures = new aiTexture*[mTextures.size()];
|
pScene->mTextures = new aiTexture*[mTextures.size()];
|
||||||
std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures);
|
std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures);
|
||||||
mTextures.clear();
|
mTextures.clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Stores all materials in the given scene
|
// Stores all materials in the given scene
|
||||||
void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
|
void ColladaLoader::StoreSceneMaterials( aiScene* pScene) {
|
||||||
{
|
|
||||||
pScene->mNumMaterials = static_cast<unsigned int>(newMats.size());
|
pScene->mNumMaterials = static_cast<unsigned int>(newMats.size());
|
||||||
|
if (newMats.empty() ) {
|
||||||
if (newMats.size() > 0) {
|
return;
|
||||||
pScene->mMaterials = new aiMaterial*[newMats.size()];
|
|
||||||
for (unsigned int i = 0; i < newMats.size();++i)
|
|
||||||
pScene->mMaterials[i] = newMats[i].second;
|
|
||||||
|
|
||||||
newMats.clear();
|
|
||||||
}
|
}
|
||||||
|
pScene->mMaterials = new aiMaterial*[newMats.size()];
|
||||||
|
for (unsigned int i = 0; i < newMats.size();++i) {
|
||||||
|
pScene->mMaterials[i] = newMats[i].second;
|
||||||
|
}
|
||||||
|
newMats.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Stores all animations
|
// Stores all animations
|
||||||
void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser)
|
void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser) {
|
||||||
{
|
|
||||||
// recursively collect all animations from the collada scene
|
// recursively collect all animations from the collada scene
|
||||||
StoreAnimations(pScene, pParser, &pParser.mAnims, "");
|
StoreAnimations(pScene, pParser, &pParser.mAnims, "");
|
||||||
|
|
||||||
// catch special case: many animations with the same length, each affecting only a single node.
|
// catch special case: many animations with the same length, each affecting only a single node.
|
||||||
// we need to unite all those single-node-anims to a proper combined animation
|
// we need to unite all those single-node-anims to a proper combined animation
|
||||||
for( size_t a = 0; a < mAnims.size(); ++a)
|
for( size_t a = 0; a < mAnims.size(); ++a) {
|
||||||
{
|
|
||||||
aiAnimation* templateAnim = mAnims[a];
|
aiAnimation* templateAnim = mAnims[a];
|
||||||
if( templateAnim->mNumChannels == 1)
|
if( templateAnim->mNumChannels == 1) {
|
||||||
{
|
|
||||||
// search for other single-channel-anims with the same duration
|
// search for other single-channel-anims with the same duration
|
||||||
std::vector<size_t> collectedAnimIndices;
|
std::vector<size_t> collectedAnimIndices;
|
||||||
for( size_t b = a+1; b < mAnims.size(); ++b)
|
for( size_t b = a+1; b < mAnims.size(); ++b) {
|
||||||
{
|
|
||||||
aiAnimation* other = mAnims[b];
|
aiAnimation* other = mAnims[b];
|
||||||
if (other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration &&
|
if (other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration &&
|
||||||
other->mTicksPerSecond == templateAnim->mTicksPerSecond)
|
other->mTicksPerSecond == templateAnim->mTicksPerSecond)
|
||||||
|
@ -1056,7 +1075,8 @@ void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, floa
|
||||||
{
|
{
|
||||||
values[i].mKeys.push_back(k);
|
values[i].mKeys.push_back(k);
|
||||||
return;
|
return;
|
||||||
} else if (time > values[i].mTime && time < values[i+1].mTime)
|
}
|
||||||
|
else if (time > values[i].mTime && time < values[i + 1].mTime)
|
||||||
{
|
{
|
||||||
MorphTimeValues val;
|
MorphTimeValues val;
|
||||||
val.mTime = time;
|
val.mTime = time;
|
||||||
|
@ -1158,7 +1178,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
entry.mSubElement = 2;
|
entry.mSubElement = 2;
|
||||||
else
|
else
|
||||||
ASSIMP_LOG_WARN_F("Unknown anim subelement <", subElement, ">. Ignoring");
|
ASSIMP_LOG_WARN_F("Unknown anim subelement <", subElement, ">. Ignoring");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// no subelement following, transformId is remaining string
|
// no subelement following, transformId is remaining string
|
||||||
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1);
|
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1);
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1237,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
{
|
{
|
||||||
entry.mTargetId = entry.mTransformId;
|
entry.mTargetId = entry.mTransformId;
|
||||||
entry.mTransformId = "";
|
entry.mTransformId = "";
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1385,7 +1407,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
}
|
}
|
||||||
|
|
||||||
anims.push_back(dstAnim);
|
anims.push_back(dstAnim);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ASSIMP_LOG_WARN("Collada loader: found empty animation channel, ignored. Please check your exporter.");
|
ASSIMP_LOG_WARN("Collada loader: found empty animation channel, ignored. Please check your exporter.");
|
||||||
}
|
}
|
||||||
|
@ -1623,7 +1646,8 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
|
||||||
effect.mTransparent.a = 1.f;
|
effect.mTransparent.a = 1.f;
|
||||||
|
|
||||||
mat.AddProperty(&effect.mTransparent, 1, AI_MATKEY_COLOR_TRANSPARENT);
|
mat.AddProperty(&effect.mTransparent, 1, AI_MATKEY_COLOR_TRANSPARENT);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
effect.mTransparency *= effect.mTransparent.a;
|
effect.mTransparency *= effect.mTransparent.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1743,14 +1767,19 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this is an embedded texture image setup an aiTexture for it
|
// if this is an embedded texture image setup an aiTexture for it
|
||||||
if (imIt->second.mFileName.empty())
|
if (!imIt->second.mImageData.empty())
|
||||||
{
|
{
|
||||||
if (imIt->second.mImageData.empty()) {
|
|
||||||
throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
|
|
||||||
}
|
|
||||||
|
|
||||||
aiTexture* tex = new aiTexture();
|
aiTexture* tex = new aiTexture();
|
||||||
|
|
||||||
|
// Store embedded texture name reference
|
||||||
|
tex->mFilename.Set(imIt->second.mFileName.c_str());
|
||||||
|
result.Set(imIt->second.mFileName);
|
||||||
|
|
||||||
|
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
|
||||||
|
// result.data[0] = '*';
|
||||||
|
// result.length = 1 + ASSIMP_itoa10(result.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
|
||||||
|
|
||||||
|
|
||||||
// setup format hint
|
// setup format hint
|
||||||
if (imIt->second.mEmbeddedFormat.length() > 3) {
|
if (imIt->second.mEmbeddedFormat.length() > 3) {
|
||||||
ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
|
ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
|
||||||
|
@ -1763,20 +1792,15 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
|
||||||
tex->pcData = (aiTexel*)new char[tex->mWidth];
|
tex->pcData = (aiTexel*)new char[tex->mWidth];
|
||||||
memcpy(tex->pcData, &imIt->second.mImageData[0], tex->mWidth);
|
memcpy(tex->pcData, &imIt->second.mImageData[0], tex->mWidth);
|
||||||
|
|
||||||
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
|
|
||||||
// In FBX files textures are now stored internally by Assimp with their filename included
|
|
||||||
// Now Assimp can lookup through the loaded textures after all data is processed
|
|
||||||
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
|
|
||||||
// This may occur on this case too, it has to be studied
|
|
||||||
// setup texture reference string
|
|
||||||
result.data[0] = '*';
|
|
||||||
result.length = 1 + ASSIMP_itoa10(result.data+1,static_cast<unsigned int>(MAXLEN-1),static_cast<int32_t>(mTextures.size()));
|
|
||||||
|
|
||||||
// and add this texture to the list
|
// and add this texture to the list
|
||||||
mTextures.push_back(tex);
|
mTextures.push_back(tex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (imIt->second.mFileName.empty()) {
|
||||||
|
throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
|
||||||
|
}
|
||||||
|
|
||||||
result.Set(imIt->second.mFileName);
|
result.Set(imIt->second.mFileName);
|
||||||
ConvertPath(result);
|
ConvertPath(result);
|
||||||
}
|
}
|
||||||
|
@ -1821,7 +1845,8 @@ void ColladaLoader::ConvertPath (aiString& ss)
|
||||||
size_t nbr = strtoul16(mychar);
|
size_t nbr = strtoul16(mychar);
|
||||||
it += 3;
|
it += 3;
|
||||||
*out++ = (char)(nbr & 0xFF);
|
*out++ = (char)(nbr & 0xFF);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
*out++ = *it++;
|
*out++ = *it++;
|
||||||
}
|
}
|
||||||
|
@ -1880,19 +1905,23 @@ const Collada::Node* ColladaLoader::FindNode( const Collada::Node* pNode, const
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Finds a node in the collada scene by the given SID
|
// Finds a node in the collada scene by the given SID
|
||||||
const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const
|
const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const {
|
||||||
{
|
if (nullptr == pNode) {
|
||||||
if( pNode->mSID == pSID)
|
return nullptr;
|
||||||
return pNode;
|
|
||||||
|
|
||||||
for( size_t a = 0; a < pNode->mChildren.size(); ++a)
|
|
||||||
{
|
|
||||||
const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID);
|
|
||||||
if( node)
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
if (pNode->mSID == pSID) {
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( size_t a = 0; a < pNode->mChildren.size(); ++a) {
|
||||||
|
const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID);
|
||||||
|
if (node) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1905,7 +1934,8 @@ std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
|
||||||
{
|
{
|
||||||
if (!pNode->mName.empty()) {
|
if (!pNode->mName.empty()) {
|
||||||
return pNode->mName;
|
return pNode->mName;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return format() << "$ColladaAutoName$_" << mNodeNameCounter++;
|
return format() << "$ColladaAutoName$_" << mNodeNameCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1926,4 +1956,6 @@ std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // Namespace Assimp
|
||||||
|
|
||||||
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER
|
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER
|
||||||
|
|
|
@ -94,20 +94,20 @@ public:
|
||||||
public:
|
public:
|
||||||
/** Returns whether the class can handle the format of the given file.
|
/** Returns whether the class can handle the format of the given file.
|
||||||
* See BaseImporter::CanRead() for details. */
|
* See BaseImporter::CanRead() for details. */
|
||||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
|
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Return importer meta information.
|
/** Return importer meta information.
|
||||||
* See #BaseImporter::GetInfo for the details
|
* See #BaseImporter::GetInfo for the details
|
||||||
*/
|
*/
|
||||||
const aiImporterDesc* GetInfo () const;
|
const aiImporterDesc* GetInfo () const override;
|
||||||
|
|
||||||
void SetupProperties(const Importer* pImp);
|
void SetupProperties(const Importer* pImp) override;
|
||||||
|
|
||||||
/** Imports the given file into the given scene structure.
|
/** Imports the given file into the given scene structure.
|
||||||
* See BaseImporter::InternReadFile() for details
|
* See BaseImporter::InternReadFile() for details
|
||||||
*/
|
*/
|
||||||
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
|
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
|
||||||
|
|
||||||
/** Recursively constructs a scene node for the given parser node and returns it. */
|
/** Recursively constructs a scene node for the given parser node and returns it. */
|
||||||
aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
|
aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
|
||||||
|
|
|
@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/IOSystem.hpp>
|
#include <assimp/IOSystem.hpp>
|
||||||
#include <assimp/light.h>
|
#include <assimp/light.h>
|
||||||
#include <assimp/TinyFormatter.h>
|
#include <assimp/TinyFormatter.h>
|
||||||
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -90,21 +91,49 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
|
||||||
throw DeadlyImportError("IOSystem is NULL.");
|
throw DeadlyImportError("IOSystem is NULL.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// open the file
|
std::unique_ptr<IOStream> daefile;
|
||||||
std::unique_ptr<IOStream> file( pIOHandler->Open(pFile ) );
|
std::unique_ptr<ZipArchiveIOSystem> zip_archive;
|
||||||
if (file.get() == nullptr) {
|
|
||||||
throw DeadlyImportError( "Failed to open file " + pFile + "." );
|
// Determine type
|
||||||
|
std::string extension = BaseImporter::GetExtension(pFile);
|
||||||
|
if (extension != "dae") {
|
||||||
|
zip_archive.reset(new ZipArchiveIOSystem(pIOHandler, pFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zip_archive && zip_archive->isOpen()) {
|
||||||
|
std::string dae_filename = ReadZaeManifest(*zip_archive);
|
||||||
|
|
||||||
|
if (dae_filename.empty()) {
|
||||||
|
ThrowException(std::string("Invalid ZAE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
daefile.reset(zip_archive->Open(dae_filename.c_str()));
|
||||||
|
if (daefile == nullptr) {
|
||||||
|
ThrowException(std::string("Invalid ZAE manifest: '") + std::string(dae_filename) + std::string("' is missing"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// attempt to open the file directly
|
||||||
|
daefile.reset(pIOHandler->Open(pFile));
|
||||||
|
if (daefile.get() == nullptr) {
|
||||||
|
throw DeadlyImportError("Failed to open file '" + pFile + "'.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a XML reader for it
|
// generate a XML reader for it
|
||||||
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
|
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(daefile.get()));
|
||||||
mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
|
mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
|
||||||
if (!mReader) {
|
if (!mReader) {
|
||||||
ThrowException("Collada: Unable to open file.");
|
ThrowException("Unable to read file, malformed XML");
|
||||||
}
|
}
|
||||||
|
|
||||||
// start reading
|
// start reading
|
||||||
ReadContents();
|
ReadContents();
|
||||||
|
|
||||||
|
// read embedded textures
|
||||||
|
if (zip_archive && zip_archive->isOpen()) {
|
||||||
|
ReadEmbeddedTextures(*zip_archive);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -118,6 +147,49 @@ ColladaParser::~ColladaParser()
|
||||||
delete it->second;
|
delete it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Read a ZAE manifest and return the filename to attempt to open
|
||||||
|
std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
|
||||||
|
// Open the manifest
|
||||||
|
std::unique_ptr<IOStream> manifestfile(zip_archive.Open("manifest.xml"));
|
||||||
|
if (manifestfile == nullptr)
|
||||||
|
{
|
||||||
|
// No manifest, hope there is only one .DAE inside
|
||||||
|
std::vector<std::string> file_list;
|
||||||
|
zip_archive.getFileListExtension(file_list, "dae");
|
||||||
|
|
||||||
|
if (file_list.empty())
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
return file_list.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(manifestfile.get()));
|
||||||
|
std::unique_ptr<irr::io::IrrXMLReader> manifest_reader(irr::io::createIrrXMLReader(mIOWrapper.get()));
|
||||||
|
|
||||||
|
while (manifest_reader->read())
|
||||||
|
{
|
||||||
|
// find the manifest "dae_root" element
|
||||||
|
if (manifest_reader->getNodeType() == irr::io::EXN_ELEMENT)
|
||||||
|
{
|
||||||
|
if (::strcmp(manifest_reader->getNodeName(), "dae_root") == 0)
|
||||||
|
{
|
||||||
|
if (!manifest_reader->read())
|
||||||
|
return std::string();
|
||||||
|
if (manifest_reader->getNodeType() != irr::io::EXN_TEXT && manifest_reader->getNodeType() != irr::io::EXN_CDATA)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
const char* filepath = manifest_reader->getNodeData();
|
||||||
|
if (filepath == nullptr)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
return std::string(filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Read bool from text contents of current element
|
// Read bool from text contents of current element
|
||||||
bool ColladaParser::ReadBoolFromTextContent()
|
bool ColladaParser::ReadBoolFromTextContent()
|
||||||
|
@ -165,12 +237,14 @@ void ColladaParser::ReadContents()
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadStructure();
|
ReadStructure();
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ASSIMP_LOG_DEBUG_F("Ignoring global element <", mReader->getNodeName(), ">.");
|
ASSIMP_LOG_DEBUG_F("Ignoring global element <", mReader->getNodeName(), ">.");
|
||||||
SkipElement();
|
SkipElement();
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// skip everything else silently
|
// skip everything else silently
|
||||||
}
|
}
|
||||||
|
@ -506,7 +580,8 @@ void ColladaParser::ReadAnimationLibrary()
|
||||||
{
|
{
|
||||||
// delegate the reading. Depending on the inner elements it will be a container or a anim channel
|
// delegate the reading. Depending on the inner elements it will be a container or a anim channel
|
||||||
ReadAnimation(&mAnims);
|
ReadAnimation(&mAnims);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -722,7 +797,8 @@ void ColladaParser::ReadControllerLibrary()
|
||||||
|
|
||||||
// read on from there
|
// read on from there
|
||||||
ReadController(mControllerLibrary[id]);
|
ReadController(mControllerLibrary[id]);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -816,7 +892,8 @@ void ColladaParser::ReadController( Collada::Controller& pController)
|
||||||
pController.mMorphWeight = source + 1;
|
pController.mMorphWeight = source + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
}
|
||||||
|
else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
||||||
if (strcmp(mReader->getNodeName(), "targets") == 0)
|
if (strcmp(mReader->getNodeName(), "targets") == 0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
|
@ -1008,7 +1085,8 @@ void ColladaParser::ReadImageLibrary()
|
||||||
|
|
||||||
// read on from there
|
// read on from there
|
||||||
ReadImage(mImageLibrary[id]);
|
ReadImage(mImageLibrary[id]);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1158,7 +1236,8 @@ void ColladaParser::ReadMaterialLibrary()
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadMaterial(mMaterialLibrary[id]);
|
ReadMaterial(mMaterialLibrary[id]);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1193,7 +1272,8 @@ void ColladaParser::ReadLightLibrary()
|
||||||
// create an entry and store it in the library under its ID
|
// create an entry and store it in the library under its ID
|
||||||
ReadLight(mLightLibrary[id] = Light());
|
ReadLight(mLightLibrary[id] = Light());
|
||||||
|
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1232,7 +1312,8 @@ void ColladaParser::ReadCameraLibrary()
|
||||||
|
|
||||||
ReadCamera(cam);
|
ReadCamera(cam);
|
||||||
|
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1268,7 +1349,8 @@ void ColladaParser::ReadMaterial( Collada::Material& pMaterial)
|
||||||
pMaterial.mEffect = url + 1;
|
pMaterial.mEffect = url + 1;
|
||||||
|
|
||||||
SkipElement();
|
SkipElement();
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1439,7 +1521,8 @@ void ColladaParser::ReadEffectLibrary()
|
||||||
mEffectLibrary[id] = Effect();
|
mEffectLibrary[id] = Effect();
|
||||||
// read on from there
|
// read on from there
|
||||||
ReadEffect(mEffectLibrary[id]);
|
ReadEffect(mEffectLibrary[id]);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1779,7 +1862,8 @@ void ColladaParser::ReadEffectFloat( ai_real& pFloat)
|
||||||
SkipSpacesAndLineEnd(&content);
|
SkipSpacesAndLineEnd(&content);
|
||||||
|
|
||||||
TestClosing("float");
|
TestClosing("float");
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1834,7 +1918,8 @@ void ColladaParser::ReadEffectParam( Collada::EffectParam& pParam)
|
||||||
pParam.mType = Param_Sampler;
|
pParam.mType = Param_Sampler;
|
||||||
pParam.mReference = url;
|
pParam.mReference = url;
|
||||||
SkipElement("sampler2D");
|
SkipElement("sampler2D");
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore unknown element
|
// ignore unknown element
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1879,7 +1964,8 @@ void ColladaParser::ReadGeometryLibrary()
|
||||||
|
|
||||||
// read on from there
|
// read on from there
|
||||||
ReadGeometry(mesh);
|
ReadGeometry(mesh);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1910,7 +1996,8 @@ void ColladaParser::ReadGeometry( Collada::Mesh* pMesh)
|
||||||
{
|
{
|
||||||
// read on from there
|
// read on from there
|
||||||
ReadMesh(pMesh);
|
ReadMesh(pMesh);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1952,7 +2039,8 @@ void ColladaParser::ReadMesh( Mesh* pMesh)
|
||||||
{
|
{
|
||||||
// read per-index mesh data and faces setup
|
// read per-index mesh data and faces setup
|
||||||
ReadIndexData(pMesh);
|
ReadIndexData(pMesh);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the restf
|
// ignore the restf
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -1968,7 +2056,8 @@ void ColladaParser::ReadMesh( Mesh* pMesh)
|
||||||
{
|
{
|
||||||
// end of <mesh> element - we're done here
|
// end of <mesh> element - we're done here
|
||||||
break;
|
break;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// everything else should be punished
|
// everything else should be punished
|
||||||
ThrowException("Expected end of <mesh> element.");
|
ThrowException("Expected end of <mesh> element.");
|
||||||
|
@ -1999,7 +2088,8 @@ void ColladaParser::ReadSource()
|
||||||
else if (IsElement("accessor"))
|
else if (IsElement("accessor"))
|
||||||
{
|
{
|
||||||
ReadAccessor(sourceID);
|
ReadAccessor(sourceID);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -2015,7 +2105,8 @@ void ColladaParser::ReadSource()
|
||||||
else if (strcmp(mReader->getNodeName(), "technique_common") == 0)
|
else if (strcmp(mReader->getNodeName(), "technique_common") == 0)
|
||||||
{
|
{
|
||||||
// end of another meaningless element - read over it
|
// end of another meaningless element - read over it
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// everything else should be punished
|
// everything else should be punished
|
||||||
ThrowException("Expected end of <source> element.");
|
ThrowException("Expected end of <source> element.");
|
||||||
|
@ -2064,7 +2155,8 @@ void ColladaParser::ReadDataArray()
|
||||||
|
|
||||||
SkipSpacesAndLineEnd(&content);
|
SkipSpacesAndLineEnd(&content);
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
data.mValues.reserve(count);
|
data.mValues.reserve(count);
|
||||||
|
|
||||||
|
@ -2176,7 +2268,8 @@ void ColladaParser::ReadAccessor( const std::string& pID)
|
||||||
|
|
||||||
// skip remaining stuff of this element, if any
|
// skip remaining stuff of this element, if any
|
||||||
SkipElement();
|
SkipElement();
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <accessor>");
|
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <accessor>");
|
||||||
}
|
}
|
||||||
|
@ -2206,7 +2299,8 @@ void ColladaParser::ReadVertexData( Mesh* pMesh)
|
||||||
if (IsElement("input"))
|
if (IsElement("input"))
|
||||||
{
|
{
|
||||||
ReadInputChannel(pMesh->mPerVertexData);
|
ReadInputChannel(pMesh->mPerVertexData);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <vertices>");
|
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <vertices>");
|
||||||
}
|
}
|
||||||
|
@ -2304,9 +2398,11 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
|
||||||
else if (IsElement("extra"))
|
else if (IsElement("extra"))
|
||||||
{
|
{
|
||||||
SkipElement("extra");
|
SkipElement("extra");
|
||||||
} else if ( IsElement("ph")) {
|
}
|
||||||
|
else if (IsElement("ph")) {
|
||||||
SkipElement("ph");
|
SkipElement("ph");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">");
|
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2436,10 +2532,12 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
|
||||||
// HACK: We just fix this number since SketchUp 15.3.331 writes the wrong 'count' for 'lines'
|
// HACK: We just fix this number since SketchUp 15.3.331 writes the wrong 'count' for 'lines'
|
||||||
ReportWarning("Expected different index count in <p> element, %zu instead of %zu.", indices.size(), expectedPointCount * numOffsets);
|
ReportWarning("Expected different index count in <p> element, %zu instead of %zu.", indices.size(), expectedPointCount * numOffsets);
|
||||||
pNumPrimitives = (indices.size() / numOffsets) / 2;
|
pNumPrimitives = (indices.size() / numOffsets) / 2;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
ThrowException("Expected different index count in <p> element.");
|
ThrowException("Expected different index count in <p> element.");
|
||||||
|
|
||||||
} else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
|
}
|
||||||
|
else if (expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
|
||||||
ThrowException("Expected different index count in <p> element.");
|
ThrowException("Expected different index count in <p> element.");
|
||||||
|
|
||||||
// find the data for all sources
|
// find the data for all sources
|
||||||
|
@ -2660,7 +2758,8 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
||||||
pMesh->mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
pMesh->mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||||
if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */
|
if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */
|
||||||
pMesh->mNumUVComponents[pInput.mIndex] = 3;
|
pMesh->mNumUVComponents[pInput.mIndex] = 3;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
|
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
|
||||||
}
|
}
|
||||||
|
@ -2680,7 +2779,8 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
||||||
result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
|
result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
|
||||||
}
|
}
|
||||||
pMesh->mColors[pInput.mIndex].push_back(result);
|
pMesh->mColors[pInput.mIndex].push_back(result);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
|
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
|
||||||
}
|
}
|
||||||
|
@ -2723,7 +2823,8 @@ void ColladaParser::ReadSceneLibrary()
|
||||||
mNodeLibrary[node->mID] = node;
|
mNodeLibrary[node->mID] = node;
|
||||||
|
|
||||||
ReadSceneNode(node);
|
ReadSceneNode(node);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ignore the rest
|
// ignore the rest
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
@ -2955,6 +3056,26 @@ void ColladaParser::ReadMaterialVertexInputBinding( Collada::SemanticMappingTabl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Assimp::ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem& zip_archive)
|
||||||
|
{
|
||||||
|
// Attempt to load any undefined Collada::Image in ImageLibrary
|
||||||
|
for (ImageLibrary::iterator it = mImageLibrary.begin(); it != mImageLibrary.end(); ++it) {
|
||||||
|
Collada::Image &image = (*it).second;
|
||||||
|
|
||||||
|
if (image.mImageData.empty()) {
|
||||||
|
std::unique_ptr<IOStream> image_file(zip_archive.Open(image.mFileName.c_str()));
|
||||||
|
if (image_file) {
|
||||||
|
image.mImageData.resize(image_file->FileSize());
|
||||||
|
image_file->Read(image.mImageData.data(), image_file->FileSize(), 1);
|
||||||
|
image.mEmbeddedFormat = BaseImporter::GetExtension(image.mFileName);
|
||||||
|
if (image.mEmbeddedFormat == "jpeg") {
|
||||||
|
image.mEmbeddedFormat = "jpg";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads a mesh reference in a node and adds it to the node's mesh list
|
// Reads a mesh reference in a node and adds it to the node's mesh list
|
||||||
void ColladaParser::ReadNodeGeometry(Node* pNode)
|
void ColladaParser::ReadNodeGeometry(Node* pNode)
|
||||||
|
@ -3036,7 +3157,8 @@ void ColladaParser::ReadScene()
|
||||||
if (sit == mNodeLibrary.end())
|
if (sit == mNodeLibrary.end())
|
||||||
ThrowException("Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
|
ThrowException("Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
|
||||||
mRootNode = sit->second;
|
mRootNode = sit->second;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
SkipElement();
|
SkipElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
|
class ZipArchiveIOSystem;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
/** Parser helper class for the Collada loader.
|
/** Parser helper class for the Collada loader.
|
||||||
|
@ -75,6 +76,9 @@ namespace Assimp
|
||||||
/** Destructor */
|
/** Destructor */
|
||||||
~ColladaParser();
|
~ColladaParser();
|
||||||
|
|
||||||
|
/** Attempts to read the ZAE manifest and returns the DAE to open */
|
||||||
|
static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive);
|
||||||
|
|
||||||
/** Reads the contents of the file */
|
/** Reads the contents of the file */
|
||||||
void ReadContents();
|
void ReadContents();
|
||||||
|
|
||||||
|
@ -235,6 +239,9 @@ namespace Assimp
|
||||||
// Processes bind_vertex_input and bind elements
|
// Processes bind_vertex_input and bind elements
|
||||||
void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
|
void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
|
||||||
|
|
||||||
|
/** Reads embedded textures from a ZAE archive*/
|
||||||
|
void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Aborts the file reading with an exception */
|
/** Aborts the file reading with an exception */
|
||||||
AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
|
AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
|
||||||
|
|
|
@ -163,11 +163,11 @@ Exporter::ExportFormatEntry gExporters[] =
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
|
||||||
Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0 ),
|
Exporter::ExportFormatEntry( "assbin", "Assimp Binary File", "assbin" , &ExportSceneAssbin, 0 ),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
|
||||||
Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0 ),
|
Exporter::ExportFormatEntry( "assxml", "Assimp XML Document", "assxml" , &ExportSceneAssxml, 0 ),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
|
||||||
|
@ -184,7 +184,7 @@ Exporter::ExportFormatEntry gExporters[] =
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
|
||||||
Exporter::ExportFormatEntry("json", "Plain JSON representation of the Assimp scene data structure", "json", &ExportAssimp2Json, 0)
|
Exporter::ExportFormatEntry( "assjson", "Assimp JSON Document", "json", &ExportAssimp2Json, 0)
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,539 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file ZipArchiveIOSystem.cpp
|
||||||
|
* @brief Zip File I/O implementation for #Importer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
|
#include <assimp/BaseImporter.h>
|
||||||
|
|
||||||
|
#include <assimp/ai_assert.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#ifdef ASSIMP_USE_HUNTER
|
||||||
|
# include <minizip/unzip.h>
|
||||||
|
#else
|
||||||
|
# include <unzip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// Wraps an existing Assimp::IOSystem for unzip
|
||||||
|
class IOSystem2Unzip {
|
||||||
|
public:
|
||||||
|
static voidpf open(voidpf opaque, const char* filename, int mode);
|
||||||
|
static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
|
||||||
|
static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
|
||||||
|
static long tell(voidpf opaque, voidpf stream);
|
||||||
|
static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
|
||||||
|
static int close(voidpf opaque, voidpf stream);
|
||||||
|
static int testerror(voidpf opaque, voidpf stream);
|
||||||
|
static zlib_filefunc_def get(IOSystem* pIOHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
|
||||||
|
IOSystem* io_system = reinterpret_cast<IOSystem*>(opaque);
|
||||||
|
|
||||||
|
const char* mode_fopen = nullptr;
|
||||||
|
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) {
|
||||||
|
mode_fopen = "rb";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (mode & ZLIB_FILEFUNC_MODE_EXISTING) {
|
||||||
|
mode_fopen = "r+b";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
|
||||||
|
mode_fopen = "wb";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (voidpf)io_system->Open(filename, mode_fopen);
|
||||||
|
}
|
||||||
|
|
||||||
|
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
|
||||||
|
IOStream* io_stream = (IOStream*)stream;
|
||||||
|
|
||||||
|
return static_cast<uLong>(io_stream->Read(buf, 1, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
|
||||||
|
IOStream* io_stream = (IOStream*)stream;
|
||||||
|
|
||||||
|
return static_cast<uLong>(io_stream->Write(buf, 1, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
|
||||||
|
IOStream* io_stream = (IOStream*)stream;
|
||||||
|
|
||||||
|
return static_cast<long>(io_stream->Tell());
|
||||||
|
}
|
||||||
|
|
||||||
|
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
|
||||||
|
IOStream* io_stream = (IOStream*)stream;
|
||||||
|
|
||||||
|
aiOrigin assimp_origin;
|
||||||
|
switch (origin) {
|
||||||
|
default:
|
||||||
|
case ZLIB_FILEFUNC_SEEK_CUR:
|
||||||
|
assimp_origin = aiOrigin_CUR;
|
||||||
|
break;
|
||||||
|
case ZLIB_FILEFUNC_SEEK_END:
|
||||||
|
assimp_origin = aiOrigin_END;
|
||||||
|
break;
|
||||||
|
case ZLIB_FILEFUNC_SEEK_SET:
|
||||||
|
assimp_origin = aiOrigin_SET;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
|
||||||
|
IOSystem* io_system = (IOSystem*)opaque;
|
||||||
|
IOStream* io_stream = (IOStream*)stream;
|
||||||
|
|
||||||
|
io_system->Close(io_stream);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
|
||||||
|
zlib_filefunc_def mapping;
|
||||||
|
|
||||||
|
#ifdef ASSIMP_USE_HUNTER
|
||||||
|
mapping.zopen_file = (open_file_func)open;
|
||||||
|
mapping.zread_file = (read_file_func)read;
|
||||||
|
mapping.zwrite_file = (write_file_func)write;
|
||||||
|
mapping.ztell_file = (tell_file_func)tell;
|
||||||
|
mapping.zseek_file = (seek_file_func)seek;
|
||||||
|
mapping.zclose_file = (close_file_func)close;
|
||||||
|
mapping.zerror_file = (error_file_func)testerror;
|
||||||
|
#else
|
||||||
|
mapping.zopen_file = open;
|
||||||
|
mapping.zread_file = read;
|
||||||
|
mapping.zwrite_file = write;
|
||||||
|
mapping.ztell_file = tell;
|
||||||
|
mapping.zseek_file = seek;
|
||||||
|
mapping.zclose_file = close;
|
||||||
|
mapping.zerror_file = testerror;
|
||||||
|
#endif
|
||||||
|
mapping.opaque = reinterpret_cast<voidpf>(pIOHandler);
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// A read-only file inside a ZIP
|
||||||
|
|
||||||
|
class ZipFile : public IOStream {
|
||||||
|
friend class ZipFileInfo;
|
||||||
|
explicit ZipFile(size_t size);
|
||||||
|
public:
|
||||||
|
virtual ~ZipFile();
|
||||||
|
|
||||||
|
// IOStream interface
|
||||||
|
size_t Read(void* pvBuffer, size_t pSize, size_t pCount) override;
|
||||||
|
size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override { return 0; }
|
||||||
|
size_t FileSize() const override;
|
||||||
|
aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override;
|
||||||
|
size_t Tell() const override;
|
||||||
|
void Flush() override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_Size = 0;
|
||||||
|
size_t m_SeekPtr = 0;
|
||||||
|
std::unique_ptr<uint8_t[]> m_Buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// Info about a read-only file inside a ZIP
|
||||||
|
class ZipFileInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ZipFileInfo(unzFile zip_handle, size_t size);
|
||||||
|
|
||||||
|
// Allocate and Extract data from the ZIP
|
||||||
|
ZipFile * Extract(unzFile zip_handle) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_Size = 0;
|
||||||
|
unz_file_pos_s m_ZipFilePos;
|
||||||
|
};
|
||||||
|
|
||||||
|
ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size)
|
||||||
|
: m_Size(size) {
|
||||||
|
ai_assert(m_Size != 0);
|
||||||
|
// Workaround for MSVC 2013 - C2797
|
||||||
|
m_ZipFilePos.num_of_file = 0;
|
||||||
|
m_ZipFilePos.pos_in_zip_directory = 0;
|
||||||
|
unzGetFilePos(zip_handle, &(m_ZipFilePos));
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile * ZipFileInfo::Extract(unzFile zip_handle) const {
|
||||||
|
// Find in the ZIP. This cannot fail
|
||||||
|
unz_file_pos_s *filepos = const_cast<unz_file_pos_s*>(&(m_ZipFilePos));
|
||||||
|
if (unzGoToFilePos(zip_handle, filepos) != UNZ_OK)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (unzOpenCurrentFile(zip_handle) != UNZ_OK)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
ZipFile *zip_file = new ZipFile(m_Size);
|
||||||
|
|
||||||
|
if (unzReadCurrentFile(zip_handle, zip_file->m_Buffer.get(), static_cast<unsigned int>(m_Size)) != static_cast<int>(m_Size))
|
||||||
|
{
|
||||||
|
// Failed, release the memory
|
||||||
|
delete zip_file;
|
||||||
|
zip_file = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ai_assert(unzCloseCurrentFile(zip_handle) == UNZ_OK);
|
||||||
|
return zip_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile::ZipFile(size_t size)
|
||||||
|
: m_Size(size) {
|
||||||
|
ai_assert(m_Size != 0);
|
||||||
|
m_Buffer = std::unique_ptr<uint8_t[]>(new uint8_t[m_Size]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile::~ZipFile() {
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) {
|
||||||
|
// Should be impossible
|
||||||
|
ai_assert(m_Buffer != nullptr);
|
||||||
|
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
|
||||||
|
|
||||||
|
// Clip down to file size
|
||||||
|
size_t byteSize = pSize * pCount;
|
||||||
|
if ((byteSize + m_SeekPtr) > m_Size)
|
||||||
|
{
|
||||||
|
pCount = (m_Size - m_SeekPtr) / pSize;
|
||||||
|
byteSize = pSize * pCount;
|
||||||
|
if (byteSize == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize);
|
||||||
|
|
||||||
|
m_SeekPtr += byteSize;
|
||||||
|
|
||||||
|
return pCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZipFile::FileSize() const {
|
||||||
|
return m_Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) {
|
||||||
|
switch (pOrigin)
|
||||||
|
{
|
||||||
|
case aiOrigin_SET: {
|
||||||
|
if (pOffset > m_Size) return aiReturn_FAILURE;
|
||||||
|
m_SeekPtr = pOffset;
|
||||||
|
return aiReturn_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
case aiOrigin_CUR: {
|
||||||
|
if ((pOffset + m_SeekPtr) > m_Size) return aiReturn_FAILURE;
|
||||||
|
m_SeekPtr += pOffset;
|
||||||
|
return aiReturn_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
case aiOrigin_END: {
|
||||||
|
if (pOffset > m_Size) return aiReturn_FAILURE;
|
||||||
|
m_SeekPtr = m_Size - pOffset;
|
||||||
|
return aiReturn_SUCCESS;
|
||||||
|
}
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aiReturn_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZipFile::Tell() const {
|
||||||
|
return m_SeekPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// pImpl of the Zip Archive IO
|
||||||
|
class ZipArchiveIOSystem::Implement {
|
||||||
|
public:
|
||||||
|
static const unsigned int FileNameSize = 256;
|
||||||
|
|
||||||
|
Implement(IOSystem* pIOHandler, const char* pFilename, const char* pMode);
|
||||||
|
~Implement();
|
||||||
|
|
||||||
|
bool isOpen() const;
|
||||||
|
void getFileList(std::vector<std::string>& rFileList);
|
||||||
|
void getFileListExtension(std::vector<std::string>& rFileList, const std::string& extension);
|
||||||
|
bool Exists(std::string& filename);
|
||||||
|
IOStream* OpenFile(std::string& filename);
|
||||||
|
|
||||||
|
static void SimplifyFilename(std::string& filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MapArchive();
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::map<std::string, ZipFileInfo> ZipFileInfoMap;
|
||||||
|
|
||||||
|
unzFile m_ZipFileHandle = nullptr;
|
||||||
|
ZipFileInfoMap m_ArchiveMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
ZipArchiveIOSystem::Implement::Implement(IOSystem* pIOHandler, const char* pFilename, const char* pMode) {
|
||||||
|
ai_assert(strcmp(pMode, "r") == 0);
|
||||||
|
ai_assert(pFilename != nullptr);
|
||||||
|
if (pFilename[0] == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
|
||||||
|
m_ZipFileHandle = unzOpen2(pFilename, &mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipArchiveIOSystem::Implement::~Implement() {
|
||||||
|
m_ArchiveMap.clear();
|
||||||
|
|
||||||
|
if (m_ZipFileHandle != nullptr) {
|
||||||
|
unzClose(m_ZipFileHandle);
|
||||||
|
m_ZipFileHandle = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZipArchiveIOSystem::Implement::MapArchive() {
|
||||||
|
if (m_ZipFileHandle == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_ArchiveMap.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// At first ensure file is already open
|
||||||
|
if (unzGoToFirstFile(m_ZipFileHandle) != UNZ_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Loop over all files
|
||||||
|
do {
|
||||||
|
char filename[FileNameSize];
|
||||||
|
unz_file_info fileInfo;
|
||||||
|
|
||||||
|
if (unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, nullptr, 0, nullptr, 0) == UNZ_OK) {
|
||||||
|
if (fileInfo.uncompressed_size != 0) {
|
||||||
|
std::string filename_string(filename, fileInfo.size_filename);
|
||||||
|
SimplifyFilename(filename_string);
|
||||||
|
m_ArchiveMap.emplace(filename_string, ZipFileInfo(m_ZipFileHandle, fileInfo.uncompressed_size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipArchiveIOSystem::Implement::isOpen() const {
|
||||||
|
return (m_ZipFileHandle != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZipArchiveIOSystem::Implement::getFileList(std::vector<std::string>& rFileList) {
|
||||||
|
MapArchive();
|
||||||
|
rFileList.clear();
|
||||||
|
|
||||||
|
for (const auto &file : m_ArchiveMap) {
|
||||||
|
rFileList.push_back(file.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector<std::string>& rFileList, const std::string& extension) {
|
||||||
|
MapArchive();
|
||||||
|
rFileList.clear();
|
||||||
|
|
||||||
|
for (const auto &file : m_ArchiveMap) {
|
||||||
|
if (extension == BaseImporter::GetExtension(file.first))
|
||||||
|
rFileList.push_back(file.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipArchiveIOSystem::Implement::Exists(std::string& filename) {
|
||||||
|
MapArchive();
|
||||||
|
|
||||||
|
ZipFileInfoMap::const_iterator it = m_ArchiveMap.find(filename);
|
||||||
|
return (it != m_ArchiveMap.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
IOStream * ZipArchiveIOSystem::Implement::OpenFile(std::string& filename) {
|
||||||
|
MapArchive();
|
||||||
|
|
||||||
|
SimplifyFilename(filename);
|
||||||
|
|
||||||
|
// Find in the map
|
||||||
|
ZipFileInfoMap::const_iterator zip_it = m_ArchiveMap.find(filename);
|
||||||
|
if (zip_it == m_ArchiveMap.cend())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const ZipFileInfo &zip_file = (*zip_it).second;
|
||||||
|
return zip_file.Extract(m_ZipFileHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ReplaceAll(std::string& data, const std::string& before, const std::string& after) {
|
||||||
|
size_t pos = data.find(before);
|
||||||
|
while (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
data.replace(pos, before.size(), after);
|
||||||
|
pos = data.find(before, pos + after.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ReplaceAllChar(std::string& data, const char before, const char after) {
|
||||||
|
size_t pos = data.find(before);
|
||||||
|
while (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
data[pos] = after;
|
||||||
|
pos = data.find(before, pos + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZipArchiveIOSystem::Implement::SimplifyFilename(std::string& filename)
|
||||||
|
{
|
||||||
|
ReplaceAllChar(filename, '\\', '/');
|
||||||
|
|
||||||
|
// Remove all . and / from the beginning of the path
|
||||||
|
size_t pos = filename.find_first_not_of("./");
|
||||||
|
if (pos != 0)
|
||||||
|
filename.erase(0, pos);
|
||||||
|
|
||||||
|
// Simplify "my/folder/../file.png" constructions, if any
|
||||||
|
static const std::string relative("/../");
|
||||||
|
const size_t relsize = relative.size() - 1;
|
||||||
|
pos = filename.find(relative);
|
||||||
|
while (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
// Previous slash
|
||||||
|
size_t prevpos = filename.rfind('/', pos - 1);
|
||||||
|
if (prevpos == pos)
|
||||||
|
filename.erase(0, pos + relative.size());
|
||||||
|
else
|
||||||
|
filename.erase(prevpos, pos + relsize - prevpos);
|
||||||
|
|
||||||
|
pos = filename.find(relative);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem* pIOHandler, const char* pFilename, const char* pMode)
|
||||||
|
: pImpl(new Implement(pIOHandler, pFilename, pMode)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// The ZipArchiveIO
|
||||||
|
ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem* pIOHandler, const std::string& rFilename, const char* pMode)
|
||||||
|
: pImpl(new Implement(pIOHandler, rFilename.c_str(), pMode))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipArchiveIOSystem::~ZipArchiveIOSystem() {
|
||||||
|
delete pImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipArchiveIOSystem::Exists(const char* pFilename) const {
|
||||||
|
ai_assert(pFilename != nullptr);
|
||||||
|
|
||||||
|
if (pFilename == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string filename(pFilename);
|
||||||
|
return pImpl->Exists(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is always '/' in a ZIP
|
||||||
|
char ZipArchiveIOSystem::getOsSeparator() const {
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only supports Reading
|
||||||
|
IOStream * ZipArchiveIOSystem::Open(const char* pFilename, const char* pMode) {
|
||||||
|
ai_assert(pFilename != nullptr);
|
||||||
|
|
||||||
|
for (size_t i = 0; pMode[i] != 0; ++i)
|
||||||
|
{
|
||||||
|
ai_assert(pMode[i] != 'w');
|
||||||
|
if (pMode[i] == 'w')
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string filename(pFilename);
|
||||||
|
return pImpl->OpenFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZipArchiveIOSystem::Close(IOStream* pFile) {
|
||||||
|
delete pFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipArchiveIOSystem::isOpen() const {
|
||||||
|
return (pImpl->isOpen());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZipArchiveIOSystem::getFileList(std::vector<std::string>& rFileList) const {
|
||||||
|
return pImpl->getFileList(rFileList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZipArchiveIOSystem::getFileListExtension(std::vector<std::string>& rFileList, const std::string& extension) const {
|
||||||
|
return pImpl->getFileListExtension(rFileList, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipArchiveIOSystem::isZipArchive(IOSystem* pIOHandler, const char* pFilename) {
|
||||||
|
Implement tmp(pIOHandler, pFilename, "r");
|
||||||
|
return tmp.isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipArchiveIOSystem::isZipArchive(IOSystem* pIOHandler, const std::string& rFilename) {
|
||||||
|
return isZipArchive(pIOHandler, rFilename.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
@ -90,7 +91,6 @@ namespace Assimp {
|
||||||
, anim_fps()
|
, anim_fps()
|
||||||
, out(out)
|
, out(out)
|
||||||
, doc(doc)
|
, doc(doc)
|
||||||
, mRemoveEmptyBones( removeEmptyBones )
|
|
||||||
, mCurrentUnit(FbxUnit::cm) {
|
, mCurrentUnit(FbxUnit::cm) {
|
||||||
// animations need to be converted first since this will
|
// animations need to be converted first since this will
|
||||||
// populate the node_anim_chain_bits map, which is needed
|
// populate the node_anim_chain_bits map, which is needed
|
||||||
|
@ -685,30 +685,37 @@ namespace Assimp {
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
aiMatrix4x4 chain[TransformationComp_MAXIMUM];
|
aiMatrix4x4 chain[TransformationComp_MAXIMUM];
|
||||||
|
|
||||||
|
ai_assert(TransformationComp_MAXIMUM < 32);
|
||||||
|
std::uint32_t chainBits = 0;
|
||||||
|
// A node won't need a node chain if it only has these.
|
||||||
|
const std::uint32_t chainMaskSimple = (1 << TransformationComp_Translation) + (1 << TransformationComp_Scaling) + (1 << TransformationComp_Rotation);
|
||||||
|
// A node will need a node chain if it has any of these.
|
||||||
|
const std::uint32_t chainMaskComplex = ((1 << (TransformationComp_MAXIMUM)) - 1) - chainMaskSimple;
|
||||||
|
|
||||||
std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4());
|
std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4());
|
||||||
|
|
||||||
// generate transformation matrices for all the different transformation components
|
// generate transformation matrices for all the different transformation components
|
||||||
const float zero_epsilon = 1e-6f;
|
const float zero_epsilon = 1e-6f;
|
||||||
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
||||||
bool is_complex = false;
|
|
||||||
|
|
||||||
const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
|
const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
|
||||||
if (ok && PreRotation.SquareLength() > zero_epsilon) {
|
if (ok && PreRotation.SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_PreRotation);
|
||||||
|
|
||||||
GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[TransformationComp_PreRotation]);
|
GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[TransformationComp_PreRotation]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiVector3D& PostRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
|
const aiVector3D& PostRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
|
||||||
if (ok && PostRotation.SquareLength() > zero_epsilon) {
|
if (ok && PostRotation.SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_PostRotation);
|
||||||
|
|
||||||
GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[TransformationComp_PostRotation]);
|
GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[TransformationComp_PostRotation]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiVector3D& RotationPivot = PropertyGet<aiVector3D>(props, "RotationPivot", ok);
|
const aiVector3D& RotationPivot = PropertyGet<aiVector3D>(props, "RotationPivot", ok);
|
||||||
if (ok && RotationPivot.SquareLength() > zero_epsilon) {
|
if (ok && RotationPivot.SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_RotationPivot) | (1 << TransformationComp_RotationPivotInverse);
|
||||||
|
|
||||||
aiMatrix4x4::Translation(RotationPivot, chain[TransformationComp_RotationPivot]);
|
aiMatrix4x4::Translation(RotationPivot, chain[TransformationComp_RotationPivot]);
|
||||||
aiMatrix4x4::Translation(-RotationPivot, chain[TransformationComp_RotationPivotInverse]);
|
aiMatrix4x4::Translation(-RotationPivot, chain[TransformationComp_RotationPivotInverse]);
|
||||||
|
@ -716,21 +723,21 @@ namespace Assimp {
|
||||||
|
|
||||||
const aiVector3D& RotationOffset = PropertyGet<aiVector3D>(props, "RotationOffset", ok);
|
const aiVector3D& RotationOffset = PropertyGet<aiVector3D>(props, "RotationOffset", ok);
|
||||||
if (ok && RotationOffset.SquareLength() > zero_epsilon) {
|
if (ok && RotationOffset.SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_RotationOffset);
|
||||||
|
|
||||||
aiMatrix4x4::Translation(RotationOffset, chain[TransformationComp_RotationOffset]);
|
aiMatrix4x4::Translation(RotationOffset, chain[TransformationComp_RotationOffset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiVector3D& ScalingOffset = PropertyGet<aiVector3D>(props, "ScalingOffset", ok);
|
const aiVector3D& ScalingOffset = PropertyGet<aiVector3D>(props, "ScalingOffset", ok);
|
||||||
if (ok && ScalingOffset.SquareLength() > zero_epsilon) {
|
if (ok && ScalingOffset.SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_ScalingOffset);
|
||||||
|
|
||||||
aiMatrix4x4::Translation(ScalingOffset, chain[TransformationComp_ScalingOffset]);
|
aiMatrix4x4::Translation(ScalingOffset, chain[TransformationComp_ScalingOffset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiVector3D& ScalingPivot = PropertyGet<aiVector3D>(props, "ScalingPivot", ok);
|
const aiVector3D& ScalingPivot = PropertyGet<aiVector3D>(props, "ScalingPivot", ok);
|
||||||
if (ok && ScalingPivot.SquareLength() > zero_epsilon) {
|
if (ok && ScalingPivot.SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_ScalingPivot) | (1 << TransformationComp_ScalingPivotInverse);
|
||||||
|
|
||||||
aiMatrix4x4::Translation(ScalingPivot, chain[TransformationComp_ScalingPivot]);
|
aiMatrix4x4::Translation(ScalingPivot, chain[TransformationComp_ScalingPivot]);
|
||||||
aiMatrix4x4::Translation(-ScalingPivot, chain[TransformationComp_ScalingPivotInverse]);
|
aiMatrix4x4::Translation(-ScalingPivot, chain[TransformationComp_ScalingPivotInverse]);
|
||||||
|
@ -738,22 +745,28 @@ namespace Assimp {
|
||||||
|
|
||||||
const aiVector3D& Translation = PropertyGet<aiVector3D>(props, "Lcl Translation", ok);
|
const aiVector3D& Translation = PropertyGet<aiVector3D>(props, "Lcl Translation", ok);
|
||||||
if (ok && Translation.SquareLength() > zero_epsilon) {
|
if (ok && Translation.SquareLength() > zero_epsilon) {
|
||||||
|
chainBits = chainBits | (1 << TransformationComp_Translation);
|
||||||
|
|
||||||
aiMatrix4x4::Translation(Translation, chain[TransformationComp_Translation]);
|
aiMatrix4x4::Translation(Translation, chain[TransformationComp_Translation]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiVector3D& Scaling = PropertyGet<aiVector3D>(props, "Lcl Scaling", ok);
|
const aiVector3D& Scaling = PropertyGet<aiVector3D>(props, "Lcl Scaling", ok);
|
||||||
if (ok && (Scaling - all_ones).SquareLength() > zero_epsilon) {
|
if (ok && (Scaling - all_ones).SquareLength() > zero_epsilon) {
|
||||||
|
chainBits = chainBits | (1 << TransformationComp_Scaling);
|
||||||
|
|
||||||
aiMatrix4x4::Scaling(Scaling, chain[TransformationComp_Scaling]);
|
aiMatrix4x4::Scaling(Scaling, chain[TransformationComp_Scaling]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiVector3D& Rotation = PropertyGet<aiVector3D>(props, "Lcl Rotation", ok);
|
const aiVector3D& Rotation = PropertyGet<aiVector3D>(props, "Lcl Rotation", ok);
|
||||||
if (ok && Rotation.SquareLength() > zero_epsilon) {
|
if (ok && Rotation.SquareLength() > zero_epsilon) {
|
||||||
|
chainBits = chainBits | (1 << TransformationComp_Rotation);
|
||||||
|
|
||||||
GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]);
|
GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok);
|
const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok);
|
||||||
if (ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon) {
|
if (ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_GeometricScaling);
|
||||||
aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]);
|
aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]);
|
||||||
aiVector3D GeometricScalingInverse = GeometricScaling;
|
aiVector3D GeometricScalingInverse = GeometricScaling;
|
||||||
bool canscale = true;
|
bool canscale = true;
|
||||||
|
@ -768,13 +781,14 @@ namespace Assimp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (canscale) {
|
if (canscale) {
|
||||||
|
chainBits = chainBits | (1 << TransformationComp_GeometricScalingInverse);
|
||||||
aiMatrix4x4::Scaling(GeometricScalingInverse, chain[TransformationComp_GeometricScalingInverse]);
|
aiMatrix4x4::Scaling(GeometricScalingInverse, chain[TransformationComp_GeometricScalingInverse]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>(props, "GeometricRotation", ok);
|
const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>(props, "GeometricRotation", ok);
|
||||||
if (ok && GeometricRotation.SquareLength() > zero_epsilon) {
|
if (ok && GeometricRotation.SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_GeometricRotation) | (1 << TransformationComp_GeometricRotationInverse);
|
||||||
GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]);
|
GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]);
|
||||||
GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotationInverse]);
|
GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotationInverse]);
|
||||||
chain[TransformationComp_GeometricRotationInverse].Inverse();
|
chain[TransformationComp_GeometricRotationInverse].Inverse();
|
||||||
|
@ -782,7 +796,7 @@ namespace Assimp {
|
||||||
|
|
||||||
const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>(props, "GeometricTranslation", ok);
|
const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>(props, "GeometricTranslation", ok);
|
||||||
if (ok && GeometricTranslation.SquareLength() > zero_epsilon) {
|
if (ok && GeometricTranslation.SquareLength() > zero_epsilon) {
|
||||||
is_complex = true;
|
chainBits = chainBits | (1 << TransformationComp_GeometricTranslation) | (1 << TransformationComp_GeometricTranslationInverse);
|
||||||
aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]);
|
aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]);
|
||||||
aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]);
|
aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]);
|
||||||
}
|
}
|
||||||
|
@ -790,12 +804,12 @@ namespace Assimp {
|
||||||
// is_complex needs to be consistent with NeedsComplexTransformationChain()
|
// is_complex needs to be consistent with NeedsComplexTransformationChain()
|
||||||
// or the interplay between this code and the animation converter would
|
// or the interplay between this code and the animation converter would
|
||||||
// not be guaranteed.
|
// not be guaranteed.
|
||||||
ai_assert(NeedsComplexTransformationChain(model) == is_complex);
|
ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0));
|
||||||
|
|
||||||
// now, if we have more than just Translation, Scaling and Rotation,
|
// now, if we have more than just Translation, Scaling and Rotation,
|
||||||
// we need to generate a full node chain to accommodate for assimp's
|
// we need to generate a full node chain to accommodate for assimp's
|
||||||
// lack to express pivots and offsets.
|
// lack to express pivots and offsets.
|
||||||
if (is_complex && doc.Settings().preservePivots) {
|
if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) {
|
||||||
FBXImporter::LogInfo("generating full transformation chain for node: " + name);
|
FBXImporter::LogInfo("generating full transformation chain for node: " + name);
|
||||||
|
|
||||||
// query the anim_chain_bits dictionary to find out which chain elements
|
// query the anim_chain_bits dictionary to find out which chain elements
|
||||||
|
@ -808,7 +822,7 @@ namespace Assimp {
|
||||||
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) {
|
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) {
|
||||||
const TransformationComp comp = static_cast<TransformationComp>(i);
|
const TransformationComp comp = static_cast<TransformationComp>(i);
|
||||||
|
|
||||||
if (chain[i].IsIdentity() && (anim_chain_bitmask & bit) == 0) {
|
if ((chainBits & bit) == 0 && (anim_chain_bitmask & bit) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1462,14 +1476,8 @@ namespace Assimp {
|
||||||
|
|
||||||
const WeightIndexArray& indices = cluster->GetIndices();
|
const WeightIndexArray& indices = cluster->GetIndices();
|
||||||
|
|
||||||
if (indices.empty() && mRemoveEmptyBones ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MatIndexArray& mats = geo.GetMaterialIndices();
|
const MatIndexArray& mats = geo.GetMaterialIndices();
|
||||||
|
|
||||||
bool ok = false;
|
|
||||||
|
|
||||||
const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
|
const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
count_out_indices.clear();
|
count_out_indices.clear();
|
||||||
|
@ -1510,7 +1518,6 @@ namespace Assimp {
|
||||||
}
|
}
|
||||||
|
|
||||||
++count_out_indices.back();
|
++count_out_indices.back();
|
||||||
ok = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1518,12 +1525,10 @@ namespace Assimp {
|
||||||
// if we found at least one, generate the output bones
|
// if we found at least one, generate the output bones
|
||||||
// XXX this could be heavily simplified by collecting the bone
|
// XXX this could be heavily simplified by collecting the bone
|
||||||
// data in a single step.
|
// data in a single step.
|
||||||
if (ok && mRemoveEmptyBones) {
|
|
||||||
ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
|
ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
|
||||||
count_out_indices, node_global_transform);
|
count_out_indices, node_global_transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (std::exception&) {
|
catch (std::exception&) {
|
||||||
std::for_each(bones.begin(), bones.end(), Util::delete_fun<aiBone>());
|
std::for_each(bones.begin(), bones.end(), Util::delete_fun<aiBone>());
|
||||||
throw;
|
throw;
|
||||||
|
|
|
@ -470,9 +470,6 @@ private:
|
||||||
|
|
||||||
aiScene* const out;
|
aiScene* const out;
|
||||||
const FBX::Document& doc;
|
const FBX::Document& doc;
|
||||||
|
|
||||||
bool mRemoveEmptyBones;
|
|
||||||
|
|
||||||
FbxUnit mCurrentUnit;
|
FbxUnit mCurrentUnit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -90,14 +90,6 @@ const Object* LazyObject::Get(bool dieOnError)
|
||||||
return object.get();
|
return object.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this is the root object, we return a dummy since there
|
|
||||||
// is no root object int he fbx file - it is just referenced
|
|
||||||
// with id 0.
|
|
||||||
if(id == 0L) {
|
|
||||||
object.reset(new Object(id, element, "Model::RootNode"));
|
|
||||||
return object.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Token& key = element.KeyToken();
|
const Token& key = element.KeyToken();
|
||||||
const TokenList& tokens = element.Tokens();
|
const TokenList& tokens = element.Tokens();
|
||||||
|
|
||||||
|
|
|
@ -1219,6 +1219,16 @@ void FBXExporter::WriteObjects ()
|
||||||
layer.AddChild(le);
|
layer.AddChild(le);
|
||||||
layer.Dump(outstream, binary, indent);
|
layer.Dump(outstream, binary, indent);
|
||||||
|
|
||||||
|
for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr)
|
||||||
|
{
|
||||||
|
FBX::Node layerExtra("Layer", int32_t(1));
|
||||||
|
layerExtra.AddChild("Version", int32_t(100));
|
||||||
|
FBX::Node leExtra("LayerElement");
|
||||||
|
leExtra.AddChild("Type", "LayerElementUV");
|
||||||
|
leExtra.AddChild("TypedIndex", int32_t(lr));
|
||||||
|
layerExtra.AddChild(leExtra);
|
||||||
|
layerExtra.Dump(outstream, binary, indent);
|
||||||
|
}
|
||||||
// finish the node record
|
// finish the node record
|
||||||
indent = 1;
|
indent = 1;
|
||||||
n.End(outstream, binary, indent, true);
|
n.End(outstream, binary, indent, true);
|
||||||
|
@ -1617,6 +1627,17 @@ void FBXExporter::WriteObjects ()
|
||||||
// at the same time we can build a list of all the skeleton nodes,
|
// at the same time we can build a list of all the skeleton nodes,
|
||||||
// which will be used later to mark them as type "limbNode".
|
// which will be used later to mark them as type "limbNode".
|
||||||
std::unordered_set<const aiNode*> limbnodes;
|
std::unordered_set<const aiNode*> limbnodes;
|
||||||
|
|
||||||
|
//actual bone nodes in fbx, without parenting-up
|
||||||
|
std::unordered_set<std::string> setAllBoneNamesInScene;
|
||||||
|
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
|
||||||
|
{
|
||||||
|
aiMesh* pMesh = mScene->mMeshes[m];
|
||||||
|
for(unsigned int b = 0; b < pMesh->mNumBones; ++ b)
|
||||||
|
setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
|
||||||
|
}
|
||||||
|
aiMatrix4x4 mxTransIdentity;
|
||||||
|
|
||||||
// and a map of nodes by bone name, as finding them is annoying.
|
// and a map of nodes by bone name, as finding them is annoying.
|
||||||
std::map<std::string,aiNode*> node_by_bone;
|
std::map<std::string,aiNode*> node_by_bone;
|
||||||
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
|
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
|
||||||
|
@ -1660,6 +1681,11 @@ void FBXExporter::WriteObjects ()
|
||||||
if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
|
if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
//not a bone in scene && no effect in transform
|
||||||
|
if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end()
|
||||||
|
&& parent->mTransformation == mxTransIdentity) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// otherwise check if this is the root of the skeleton
|
// otherwise check if this is the root of the skeleton
|
||||||
bool end = false;
|
bool end = false;
|
||||||
// is the mesh part of this node?
|
// is the mesh part of this node?
|
||||||
|
@ -1680,8 +1706,7 @@ void FBXExporter::WriteObjects ()
|
||||||
}
|
}
|
||||||
if (end) { break; }
|
if (end) { break; }
|
||||||
}
|
}
|
||||||
limbnodes.insert(parent);
|
|
||||||
skeleton.insert(parent);
|
|
||||||
// if it was the skeleton root we can finish here
|
// if it was the skeleton root we can finish here
|
||||||
if (end) { break; }
|
if (end) { break; }
|
||||||
}
|
}
|
||||||
|
@ -1822,41 +1847,10 @@ void FBXExporter::WriteObjects ()
|
||||||
inverse_bone_xform.Inverse();
|
inverse_bone_xform.Inverse();
|
||||||
aiMatrix4x4 tr = inverse_bone_xform * mesh_xform;
|
aiMatrix4x4 tr = inverse_bone_xform * mesh_xform;
|
||||||
|
|
||||||
// this should be the same as the bone's mOffsetMatrix.
|
|
||||||
// if it's not the same, the skeleton isn't in the bind pose.
|
|
||||||
const float epsilon = 1e-4f; // some error is to be expected
|
|
||||||
bool bone_xform_okay = true;
|
|
||||||
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
|
|
||||||
not_in_bind_pose.insert(b);
|
|
||||||
bone_xform_okay = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we have a bone we should use the mOffsetMatrix,
|
|
||||||
// otherwise try to just use the calculated transform.
|
|
||||||
if (b) {
|
|
||||||
sdnode.AddChild("Transform", b->mOffsetMatrix);
|
|
||||||
} else {
|
|
||||||
sdnode.AddChild("Transform", tr);
|
sdnode.AddChild("Transform", tr);
|
||||||
}
|
|
||||||
// note: it doesn't matter if we mix these,
|
|
||||||
// because if they disagree we'll throw an exception later.
|
|
||||||
// it could be that the skeleton is not in the bone pose
|
|
||||||
// but all bones are still defined,
|
|
||||||
// in which case this would use the mOffsetMatrix for everything
|
|
||||||
// and a correct skeleton would still be output.
|
|
||||||
|
|
||||||
// transformlink should be the position of the bone in world space.
|
|
||||||
// if the bone is in the bind pose (or nonexistent),
|
|
||||||
// we can just use the matrix we already calculated
|
|
||||||
if (bone_xform_okay) {
|
|
||||||
sdnode.AddChild("TransformLink", bone_xform);
|
sdnode.AddChild("TransformLink", bone_xform);
|
||||||
// otherwise we can only work it out using the mesh position.
|
|
||||||
} else {
|
|
||||||
aiMatrix4x4 trl = b->mOffsetMatrix;
|
|
||||||
trl.Inverse();
|
|
||||||
trl *= mesh_xform;
|
|
||||||
sdnode.AddChild("TransformLink", trl);
|
|
||||||
}
|
|
||||||
// note: this means we ALWAYS rely on the mesh node transform
|
// note: this means we ALWAYS rely on the mesh node transform
|
||||||
// being unchanged from the time the skeleton was bound.
|
// being unchanged from the time the skeleton was bound.
|
||||||
// there's not really any way around this at the moment.
|
// there's not really any way around this at the moment.
|
||||||
|
|
|
@ -189,9 +189,13 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
||||||
if (settings.convertToMeters) {
|
if (settings.convertToMeters) {
|
||||||
unit = FbxUnit::m;
|
unit = FbxUnit::m;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert the FBX DOM to aiScene
|
// convert the FBX DOM to aiScene
|
||||||
ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones, unit);
|
ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones, unit);
|
||||||
|
|
||||||
|
// units is relative to CM :) we need it in meters for assimp
|
||||||
|
SetFileScale( doc.GlobalSettings().UnitScaleFactor() * 0.01f);
|
||||||
|
|
||||||
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
|
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
|
||||||
}
|
}
|
||||||
catch(std::exception&) {
|
catch(std::exception&) {
|
||||||
|
|
|
@ -115,7 +115,6 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
||||||
|
|
||||||
if(tempVerts.empty()) {
|
if(tempVerts.empty()) {
|
||||||
FBXImporter::LogWarn("encountered mesh with no vertices");
|
FBXImporter::LogWarn("encountered mesh with no vertices");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> tempFaces;
|
std::vector<int> tempFaces;
|
||||||
|
@ -123,7 +122,6 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
||||||
|
|
||||||
if(tempFaces.empty()) {
|
if(tempFaces.empty()) {
|
||||||
FBXImporter::LogWarn("encountered mesh with no faces");
|
FBXImporter::LogWarn("encountered mesh with no faces");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices.reserve(tempFaces.size());
|
m_vertices.reserve(tempFaces.size());
|
||||||
|
@ -612,7 +610,10 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
|
||||||
const std::string& ReferenceInformationType)
|
const std::string& ReferenceInformationType)
|
||||||
{
|
{
|
||||||
const size_t face_count = m_faces.size();
|
const size_t face_count = m_faces.size();
|
||||||
ai_assert(face_count);
|
if( 0 == face_count )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// materials are handled separately. First of all, they are assigned per-face
|
// materials are handled separately. First of all, they are assigned per-face
|
||||||
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
|
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
|
||||||
|
@ -624,16 +625,14 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
|
||||||
if (materials_out.empty()) {
|
if (materials_out.empty()) {
|
||||||
FBXImporter::LogError(Formatter::format("expected material index, ignoring"));
|
FBXImporter::LogError(Formatter::format("expected material index, ignoring"));
|
||||||
return;
|
return;
|
||||||
}
|
} else if (materials_out.size() > 1) {
|
||||||
else if (materials_out.size() > 1) {
|
|
||||||
FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one"));
|
FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one"));
|
||||||
materials_out.clear();
|
materials_out.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
materials_out.resize(m_vertices.size());
|
materials_out.resize(m_vertices.size());
|
||||||
std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0));
|
std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0));
|
||||||
}
|
} else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
|
||||||
else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
|
|
||||||
materials_out.resize(face_count);
|
materials_out.resize(face_count);
|
||||||
|
|
||||||
if(materials_out.size() != face_count) {
|
if(materials_out.size() != face_count) {
|
||||||
|
@ -642,18 +641,16 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
|
FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
|
||||||
<< MappingInformationType << "," << ReferenceInformationType);
|
<< MappingInformationType << "," << ReferenceInformationType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
||||||
: Geometry(id, element, name, doc)
|
: Geometry(id, element, name, doc) {
|
||||||
{
|
|
||||||
const Scope *sc = element.Compound();
|
const Scope *sc = element.Compound();
|
||||||
if (!sc) {
|
if (nullptr == sc) {
|
||||||
DOMError("failed to read Geometry object (class: Shape), no data scope found");
|
DOMError("failed to read Geometry object (class: Shape), no data scope found");
|
||||||
}
|
}
|
||||||
const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);
|
const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);
|
||||||
|
|
|
@ -118,7 +118,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
|
||||||
size_t lastFilePos( 0 );
|
size_t lastFilePos( 0 );
|
||||||
|
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
while ( streamBuffer.getNextDataLine( buffer, '\0' ) ) {
|
while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
|
||||||
m_DataIt = buffer.begin();
|
m_DataIt = buffer.begin();
|
||||||
m_DataItEnd = buffer.end();
|
m_DataItEnd = buffer.end();
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||||
// project tangent and bitangent into the plane formed by the vertex' normal
|
// project tangent and bitangent into the plane formed by the vertex' normal
|
||||||
aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
|
aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
|
||||||
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
|
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
|
||||||
localTangent.Normalize(); localBitangent.Normalize();
|
localTangent.NormalizeSafe(); localBitangent.NormalizeSafe();
|
||||||
|
|
||||||
// reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
|
// reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
|
||||||
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
|
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
|
||||||
|
@ -220,10 +220,10 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||||
if (invalid_tangent != invalid_bitangent) {
|
if (invalid_tangent != invalid_bitangent) {
|
||||||
if (invalid_tangent) {
|
if (invalid_tangent) {
|
||||||
localTangent = meshNorm[p] ^ localBitangent;
|
localTangent = meshNorm[p] ^ localBitangent;
|
||||||
localTangent.Normalize();
|
localTangent.NormalizeSafe();
|
||||||
} else {
|
} else {
|
||||||
localBitangent = localTangent ^ meshNorm[p];
|
localBitangent = localTangent ^ meshNorm[p];
|
||||||
localBitangent.Normalize();
|
localBitangent.NormalizeSafe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -431,31 +431,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||||
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
|
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
|
||||||
memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight));
|
memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
|
||||||
/* NOTE:
|
|
||||||
*
|
|
||||||
* In the algorithm above we're assuming that there are no vertices
|
|
||||||
* with a different bone weight setup at the same position. That wouldn't
|
|
||||||
* make sense, but it is not absolutely impossible. SkeletonMeshBuilder
|
|
||||||
* for example generates such input data if two skeleton points
|
|
||||||
* share the same position. Again this doesn't make sense but is
|
|
||||||
* reality for some model formats (MD5 for example uses these special
|
|
||||||
* nodes as attachment tags for its weapons).
|
|
||||||
*
|
|
||||||
* Then it is possible that a bone has no weights anymore .... as a quick
|
|
||||||
* workaround, we're just removing these bones. If they're animated,
|
|
||||||
* model geometry might be modified but at least there's no risk of a crash.
|
|
||||||
*/
|
|
||||||
delete bone;
|
|
||||||
--pMesh->mNumBones;
|
|
||||||
for (unsigned int n = a; n < pMesh->mNumBones; ++n) {
|
|
||||||
pMesh->mBones[n] = pMesh->mBones[n+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
--a;
|
|
||||||
ASSIMP_LOG_WARN("Removing bone -> no weights remaining");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return pMesh->mNumVertices;
|
return pMesh->mNumVertices;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,19 +39,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#ifndef ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS
|
|
||||||
|
|
||||||
#include "ScaleProcess.h"
|
#include "ScaleProcess.h"
|
||||||
|
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
|
#include <assimp/BaseImporter.h>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
ScaleProcess::ScaleProcess()
|
ScaleProcess::ScaleProcess()
|
||||||
: BaseProcess()
|
: BaseProcess()
|
||||||
, mScale( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT ) {
|
, mScale( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT ) {
|
||||||
// empty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ScaleProcess::~ScaleProcess() {
|
ScaleProcess::~ScaleProcess() {
|
||||||
|
@ -71,10 +69,26 @@ bool ScaleProcess::IsActive( unsigned int pFlags ) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleProcess::SetupProperties( const Importer* pImp ) {
|
void ScaleProcess::SetupProperties( const Importer* pImp ) {
|
||||||
mScale = pImp->GetPropertyFloat( AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 0 );
|
// User scaling
|
||||||
|
mScale = pImp->GetPropertyFloat( AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 1.0f );
|
||||||
|
|
||||||
|
// File scaling * Application Scaling
|
||||||
|
float importerScale = pImp->GetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, 1.0f );
|
||||||
|
|
||||||
|
// apply scale to the scale
|
||||||
|
// helps prevent bugs with backward compatibility for anyone using normal scaling.
|
||||||
|
mScale *= importerScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleProcess::Execute( aiScene* pScene ) {
|
void ScaleProcess::Execute( aiScene* pScene ) {
|
||||||
|
if(mScale == 1.0f) {
|
||||||
|
return; // nothing to scale
|
||||||
|
}
|
||||||
|
|
||||||
|
ai_assert( mScale != 0 );
|
||||||
|
ai_assert( nullptr != pScene );
|
||||||
|
ai_assert( nullptr != pScene->mRootNode );
|
||||||
|
|
||||||
if ( nullptr == pScene ) {
|
if ( nullptr == pScene ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -83,21 +97,112 @@ void ScaleProcess::Execute( aiScene* pScene ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process animations and update position transform to new unit system
|
||||||
|
for( unsigned int animationID = 0; animationID < pScene->mNumAnimations; animationID++ )
|
||||||
|
{
|
||||||
|
aiAnimation* animation = pScene->mAnimations[animationID];
|
||||||
|
|
||||||
|
for( unsigned int animationChannel = 0; animationChannel < animation->mNumChannels; animationChannel++)
|
||||||
|
{
|
||||||
|
aiNodeAnim* anim = animation->mChannels[animationChannel];
|
||||||
|
|
||||||
|
for( unsigned int posKey = 0; posKey < anim->mNumPositionKeys; posKey++)
|
||||||
|
{
|
||||||
|
aiVectorKey& vectorKey = anim->mPositionKeys[posKey];
|
||||||
|
vectorKey.mValue *= mScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( unsigned int meshID = 0; meshID < pScene->mNumMeshes; meshID++)
|
||||||
|
{
|
||||||
|
aiMesh *mesh = pScene->mMeshes[meshID];
|
||||||
|
|
||||||
|
// Reconstruct mesh vertexes to the new unit system
|
||||||
|
for( unsigned int vertexID = 0; vertexID < mesh->mNumVertices; vertexID++)
|
||||||
|
{
|
||||||
|
aiVector3D& vertex = mesh->mVertices[vertexID];
|
||||||
|
vertex *= mScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// bone placement / scaling
|
||||||
|
for( unsigned int boneID = 0; boneID < mesh->mNumBones; boneID++)
|
||||||
|
{
|
||||||
|
// Reconstruct matrix by transform rather than by scale
|
||||||
|
// This prevent scale values being changed which can
|
||||||
|
// be meaningful in some cases
|
||||||
|
// like when you want the modeller to see 1:1 compatibility.
|
||||||
|
aiBone* bone = mesh->mBones[boneID];
|
||||||
|
|
||||||
|
aiVector3D pos, scale;
|
||||||
|
aiQuaternion rotation;
|
||||||
|
|
||||||
|
bone->mOffsetMatrix.Decompose( scale, rotation, pos);
|
||||||
|
|
||||||
|
aiMatrix4x4 translation;
|
||||||
|
aiMatrix4x4::Translation( pos * mScale, translation );
|
||||||
|
|
||||||
|
aiMatrix4x4 scaling;
|
||||||
|
aiMatrix4x4::Scaling( aiVector3D(scale), scaling );
|
||||||
|
|
||||||
|
aiMatrix4x4 RotMatrix = aiMatrix4x4 (rotation.GetMatrix());
|
||||||
|
|
||||||
|
bone->mOffsetMatrix = translation * RotMatrix * scaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// animation mesh processing
|
||||||
|
// convert by position rather than scale.
|
||||||
|
for( unsigned int animMeshID = 0; animMeshID < mesh->mNumAnimMeshes; animMeshID++)
|
||||||
|
{
|
||||||
|
aiAnimMesh * animMesh = mesh->mAnimMeshes[animMeshID];
|
||||||
|
|
||||||
|
for( unsigned int vertexID = 0; vertexID < animMesh->mNumVertices; vertexID++)
|
||||||
|
{
|
||||||
|
aiVector3D& vertex = animMesh->mVertices[vertexID];
|
||||||
|
vertex *= mScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
traverseNodes( pScene->mRootNode );
|
traverseNodes( pScene->mRootNode );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleProcess::traverseNodes( aiNode *node ) {
|
void ScaleProcess::traverseNodes( aiNode *node, unsigned int nested_node_id ) {
|
||||||
applyScaling( node );
|
applyScaling( node );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < node->mNumChildren; i++)
|
||||||
|
{
|
||||||
|
// recurse into the tree until we are done!
|
||||||
|
traverseNodes( node->mChildren[i], nested_node_id+1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleProcess::applyScaling( aiNode *currentNode ) {
|
void ScaleProcess::applyScaling( aiNode *currentNode ) {
|
||||||
if ( nullptr != currentNode ) {
|
if ( nullptr != currentNode ) {
|
||||||
currentNode->mTransformation.a1 = currentNode->mTransformation.a1 * mScale;
|
// Reconstruct matrix by transform rather than by scale
|
||||||
currentNode->mTransformation.b2 = currentNode->mTransformation.b2 * mScale;
|
// This prevent scale values being changed which can
|
||||||
currentNode->mTransformation.c3 = currentNode->mTransformation.c3 * mScale;
|
// be meaningful in some cases
|
||||||
|
// like when you want the modeller to
|
||||||
|
// see 1:1 compatibility.
|
||||||
|
|
||||||
|
aiVector3D pos, scale;
|
||||||
|
aiQuaternion rotation;
|
||||||
|
currentNode->mTransformation.Decompose( scale, rotation, pos);
|
||||||
|
|
||||||
|
aiMatrix4x4 translation;
|
||||||
|
aiMatrix4x4::Translation( pos * mScale, translation );
|
||||||
|
|
||||||
|
aiMatrix4x4 scaling;
|
||||||
|
|
||||||
|
// note: we do not use mScale here, this is on purpose.
|
||||||
|
aiMatrix4x4::Scaling( scale, scaling );
|
||||||
|
|
||||||
|
aiMatrix4x4 RotMatrix = aiMatrix4x4 (rotation.GetMatrix());
|
||||||
|
|
||||||
|
currentNode->mTransformation = translation * RotMatrix * scaling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace Assimp
|
} // Namespace Assimp
|
||||||
|
|
||||||
#endif // !! ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS
|
|
||||||
|
|
|
@ -39,7 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#ifndef SCALE_PROCESS_H_
|
||||||
|
#define SCALE_PROCESS_H_
|
||||||
|
|
||||||
#include "Common/BaseProcess.h"
|
#include "Common/BaseProcess.h"
|
||||||
|
|
||||||
|
@ -53,6 +54,11 @@ namespace Assimp {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** ScaleProcess: Class to rescale the whole model.
|
/** ScaleProcess: Class to rescale the whole model.
|
||||||
|
* Now rescales animations, bones, and blend shapes properly.
|
||||||
|
* Please note this will not write to 'scale' transform it will rewrite mesh
|
||||||
|
* and matrixes so that your scale values
|
||||||
|
* from your model package are preserved, so this is completely intentional
|
||||||
|
* bugs should be reported as soon as they are found.
|
||||||
*/
|
*/
|
||||||
class ASSIMP_API ScaleProcess : public BaseProcess {
|
class ASSIMP_API ScaleProcess : public BaseProcess {
|
||||||
public:
|
public:
|
||||||
|
@ -78,7 +84,7 @@ public:
|
||||||
virtual void Execute( aiScene* pScene );
|
virtual void Execute( aiScene* pScene );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void traverseNodes( aiNode *currentNode );
|
void traverseNodes( aiNode *currentNode, unsigned int nested_node_id = 0 );
|
||||||
void applyScaling( aiNode *currentNode );
|
void applyScaling( aiNode *currentNode );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -86,3 +92,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace Assimp
|
} // Namespace Assimp
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SCALE_PROCESS_H_
|
|
@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
|
||||||
|
|
||||||
#include "Q3BSPFileImporter.h"
|
#include "Q3BSPFileImporter.h"
|
||||||
#include "Q3BSPZipArchive.h"
|
|
||||||
#include "Q3BSPFileParser.h"
|
#include "Q3BSPFileParser.h"
|
||||||
#include "Q3BSPFileData.h"
|
#include "Q3BSPFileData.h"
|
||||||
|
|
||||||
|
@ -60,6 +59,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
#include <assimp/DefaultIOSystem.h>
|
#include <assimp/DefaultIOSystem.h>
|
||||||
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
#include <assimp/importerdesc.h>
|
#include <assimp/importerdesc.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -181,7 +181,7 @@ const aiImporterDesc* Q3BSPFileImporter::GetInfo () const {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Import method.
|
// Import method.
|
||||||
void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* scene, IOSystem* ioHandler) {
|
void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* scene, IOSystem* ioHandler) {
|
||||||
Q3BSPZipArchive Archive( ioHandler, rFile );
|
ZipArchiveIOSystem Archive( ioHandler, rFile );
|
||||||
if ( !Archive.isOpen() ) {
|
if ( !Archive.isOpen() ) {
|
||||||
throw DeadlyImportError( "Failed to open file " + rFile + "." );
|
throw DeadlyImportError( "Failed to open file " + rFile + "." );
|
||||||
}
|
}
|
||||||
|
@ -223,10 +223,10 @@ void Q3BSPFileImporter::separateMapName( const std::string &importName, std::str
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Returns the first map in the map archive.
|
// Returns the first map in the map archive.
|
||||||
bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &bspArchive, std::string &mapName ) {
|
bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, std::string &mapName ) {
|
||||||
mapName = "";
|
mapName = "";
|
||||||
std::vector<std::string> fileList;
|
std::vector<std::string> fileList;
|
||||||
bspArchive.getFileList( fileList );
|
bspArchive.getFileListExtension( fileList, "bsp" );
|
||||||
if (fileList.empty()) {
|
if (fileList.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &bspArchive, std:
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Creates the assimp specific data.
|
// Creates the assimp specific data.
|
||||||
void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
|
void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
|
||||||
Q3BSPZipArchive *pArchive ) {
|
ZipArchiveIOSystem *pArchive ) {
|
||||||
if (nullptr == pModel || nullptr == pScene) {
|
if (nullptr == pModel || nullptr == pScene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,7 @@ void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel,
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Creates all referenced materials.
|
// Creates all referenced materials.
|
||||||
void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
|
void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
|
||||||
Q3BSPZipArchive *pArchive ) {
|
ZipArchiveIOSystem *pArchive ) {
|
||||||
if ( m_MaterialLookupMap.empty() ) {
|
if ( m_MaterialLookupMap.empty() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -564,7 +564,7 @@ aiFace *Q3BSPFileImporter::getNextFace( aiMesh *mesh, unsigned int &faceIdx ) {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Imports a texture file.
|
// Imports a texture file.
|
||||||
bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model,
|
bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model,
|
||||||
Q3BSP::Q3BSPZipArchive *archive, aiScene*,
|
ZipArchiveIOSystem *archive, aiScene*,
|
||||||
aiMaterial *pMatHelper, int textureId ) {
|
aiMaterial *pMatHelper, int textureId ) {
|
||||||
if (nullptr == archive || nullptr == pMatHelper ) {
|
if (nullptr == archive || nullptr == pMatHelper ) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -669,7 +669,7 @@ bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Will search for a supported extension.
|
// Will search for a supported extension.
|
||||||
bool Q3BSPFileImporter::expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename,
|
bool Q3BSPFileImporter::expandFile(ZipArchiveIOSystem *pArchive, const std::string &rFilename,
|
||||||
const std::vector<std::string> &rExtList, std::string &rFile,
|
const std::vector<std::string> &rExtList, std::string &rFile,
|
||||||
std::string &rExt )
|
std::string &rExt )
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,9 +54,9 @@ struct aiMaterial;
|
||||||
struct aiTexture;
|
struct aiTexture;
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
class ZipArchiveIOSystem;
|
||||||
|
|
||||||
namespace Q3BSP {
|
namespace Q3BSP {
|
||||||
class Q3BSPZipArchive;
|
|
||||||
struct Q3BSPModel;
|
struct Q3BSPModel;
|
||||||
struct sQ3BSPFace;
|
struct sQ3BSPFace;
|
||||||
}
|
}
|
||||||
|
@ -85,24 +85,24 @@ protected:
|
||||||
const aiImporterDesc* GetInfo () const;
|
const aiImporterDesc* GetInfo () const;
|
||||||
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
|
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
|
||||||
void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName );
|
void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName );
|
||||||
bool findFirstMapInArchive( Q3BSP::Q3BSPZipArchive &rArchive, std::string &rMapName );
|
bool findFirstMapInArchive(ZipArchiveIOSystem &rArchive, std::string &rMapName );
|
||||||
void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive );
|
void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, ZipArchiveIOSystem *pArchive );
|
||||||
void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent );
|
void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent );
|
||||||
aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx,
|
aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx,
|
||||||
std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh **pMesh );
|
std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh **pMesh );
|
||||||
void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx,
|
void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx,
|
||||||
unsigned int &rVertIdx );
|
unsigned int &rVertIdx );
|
||||||
void createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive );
|
void createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, ZipArchiveIOSystem *pArchive );
|
||||||
size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
|
size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
|
||||||
size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
|
size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
|
||||||
size_t countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
|
size_t countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
|
||||||
void createMaterialMap( const Q3BSP::Q3BSPModel *pModel);
|
void createMaterialMap( const Q3BSP::Q3BSPModel *pModel);
|
||||||
aiFace *getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx );
|
aiFace *getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx );
|
||||||
bool importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, Q3BSP::Q3BSPZipArchive *pArchive, aiScene* pScene,
|
bool importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, ZipArchiveIOSystem *pArchive, aiScene* pScene,
|
||||||
aiMaterial *pMatHelper, int textureId );
|
aiMaterial *pMatHelper, int textureId );
|
||||||
bool importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiMaterial *pMatHelper, int lightmapId );
|
bool importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiMaterial *pMatHelper, int lightmapId );
|
||||||
bool importEntities( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene );
|
bool importEntities( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene );
|
||||||
bool expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename, const std::vector<std::string> &rExtList,
|
bool expandFile(ZipArchiveIOSystem *pArchive, const std::string &rFilename, const std::vector<std::string> &rExtList,
|
||||||
std::string &rFile, std::string &rExt );
|
std::string &rFile, std::string &rExt );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -45,9 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "Q3BSPFileParser.h"
|
#include "Q3BSPFileParser.h"
|
||||||
#include "Q3BSPFileData.h"
|
#include "Q3BSPFileData.h"
|
||||||
#include "Q3BSPZipArchive.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <assimp/DefaultIOSystem.h>
|
#include <assimp/DefaultIOSystem.h>
|
||||||
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
@ -55,7 +55,7 @@ namespace Assimp {
|
||||||
using namespace Q3BSP;
|
using namespace Q3BSP;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Q3BSPFileParser::Q3BSPFileParser( const std::string &mapName, Q3BSPZipArchive *pZipArchive ) :
|
Q3BSPFileParser::Q3BSPFileParser( const std::string &mapName, ZipArchiveIOSystem *pZipArchive ) :
|
||||||
m_sOffset( 0 ),
|
m_sOffset( 0 ),
|
||||||
m_Data(),
|
m_Data(),
|
||||||
m_pModel(nullptr),
|
m_pModel(nullptr),
|
||||||
|
@ -101,6 +101,7 @@ bool Q3BSPFileParser::readData( const std::string &rMapName ) {
|
||||||
const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size );
|
const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size );
|
||||||
if ( readSize != size ) {
|
if ( readSize != size ) {
|
||||||
m_Data.clear();
|
m_Data.clear();
|
||||||
|
m_pZipArchive->Close(pMapFile);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_pZipArchive->Close( pMapFile );
|
m_pZipArchive->Close( pMapFile );
|
||||||
|
|
|
@ -48,13 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
|
class ZipArchiveIOSystem;
|
||||||
|
|
||||||
namespace Q3BSP
|
namespace Q3BSP
|
||||||
{
|
{
|
||||||
|
|
||||||
class Q3BSPZipArchive;
|
|
||||||
struct Q3BSPModel;
|
struct Q3BSPModel;
|
||||||
class ZipFile;
|
class ZipFile;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
@ -62,7 +61,7 @@ class ZipFile;
|
||||||
class Q3BSPFileParser
|
class Q3BSPFileParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Q3BSPFileParser( const std::string &rMapName, Q3BSP::Q3BSPZipArchive *pZipArchive );
|
Q3BSPFileParser( const std::string &rMapName, ZipArchiveIOSystem *pZipArchive );
|
||||||
~Q3BSPFileParser();
|
~Q3BSPFileParser();
|
||||||
Q3BSP::Q3BSPModel *getModel() const;
|
Q3BSP::Q3BSPModel *getModel() const;
|
||||||
|
|
||||||
|
@ -83,7 +82,7 @@ private:
|
||||||
size_t m_sOffset;
|
size_t m_sOffset;
|
||||||
std::vector<char> m_Data;
|
std::vector<char> m_Data;
|
||||||
Q3BSP::Q3BSPModel *m_pModel;
|
Q3BSP::Q3BSPModel *m_pModel;
|
||||||
Q3BSP::Q3BSPZipArchive *m_pZipArchive;
|
ZipArchiveIOSystem *m_pZipArchive;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace Assimp
|
} // Namespace Assimp
|
||||||
|
|
|
@ -1,325 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2019, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
|
|
||||||
|
|
||||||
#include "Q3BSPZipArchive.h"
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <assimp/ai_assert.h>
|
|
||||||
|
|
||||||
namespace Assimp {
|
|
||||||
namespace Q3BSP {
|
|
||||||
|
|
||||||
voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
|
|
||||||
IOSystem* io_system = (IOSystem*) opaque;
|
|
||||||
|
|
||||||
const char* mode_fopen = NULL;
|
|
||||||
if((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) {
|
|
||||||
mode_fopen = "rb";
|
|
||||||
} else {
|
|
||||||
if(mode & ZLIB_FILEFUNC_MODE_EXISTING) {
|
|
||||||
mode_fopen = "r+b";
|
|
||||||
} else {
|
|
||||||
if(mode & ZLIB_FILEFUNC_MODE_CREATE) {
|
|
||||||
mode_fopen = "wb";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (voidpf) io_system->Open(filename, mode_fopen);
|
|
||||||
}
|
|
||||||
|
|
||||||
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
return static_cast<uLong>(io_stream->Read(buf, 1, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
return static_cast<uLong>(io_stream->Write(buf, 1, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
return static_cast<long>(io_stream->Tell());
|
|
||||||
}
|
|
||||||
|
|
||||||
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
aiOrigin assimp_origin;
|
|
||||||
switch (origin) {
|
|
||||||
default:
|
|
||||||
case ZLIB_FILEFUNC_SEEK_CUR:
|
|
||||||
assimp_origin = aiOrigin_CUR;
|
|
||||||
break;
|
|
||||||
case ZLIB_FILEFUNC_SEEK_END:
|
|
||||||
assimp_origin = aiOrigin_END;
|
|
||||||
break;
|
|
||||||
case ZLIB_FILEFUNC_SEEK_SET:
|
|
||||||
assimp_origin = aiOrigin_SET;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
|
|
||||||
IOSystem* io_system = (IOSystem*) opaque;
|
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
|
||||||
|
|
||||||
io_system->Close(io_stream);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
|
|
||||||
zlib_filefunc_def mapping;
|
|
||||||
|
|
||||||
#ifdef ASSIMP_USE_HUNTER
|
|
||||||
mapping.zopen_file = (open_file_func)open;
|
|
||||||
mapping.zread_file = (read_file_func)read;
|
|
||||||
mapping.zwrite_file = (write_file_func)write;
|
|
||||||
mapping.ztell_file = (tell_file_func)tell;
|
|
||||||
mapping.zseek_file = (seek_file_func)seek;
|
|
||||||
mapping.zclose_file = (close_file_func)close;
|
|
||||||
mapping.zerror_file = (error_file_func)testerror;
|
|
||||||
#else
|
|
||||||
mapping.zopen_file = open;
|
|
||||||
mapping.zread_file = read;
|
|
||||||
mapping.zwrite_file = write;
|
|
||||||
mapping.ztell_file = tell;
|
|
||||||
mapping.zseek_file = seek;
|
|
||||||
mapping.zclose_file = close;
|
|
||||||
mapping.zerror_file = testerror;
|
|
||||||
#endif
|
|
||||||
mapping.opaque = (voidpf) pIOHandler;
|
|
||||||
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZipFile::ZipFile(size_t size) : m_Size(size) {
|
|
||||||
ai_assert(m_Size != 0);
|
|
||||||
|
|
||||||
m_Buffer = malloc(m_Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZipFile::~ZipFile() {
|
|
||||||
free(m_Buffer);
|
|
||||||
m_Buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) {
|
|
||||||
const size_t size = pSize * pCount;
|
|
||||||
assert(size <= m_Size);
|
|
||||||
|
|
||||||
std::memcpy(pvBuffer, m_Buffer, size);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZipFile::Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZipFile::FileSize() const {
|
|
||||||
return m_Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
aiReturn ZipFile::Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) {
|
|
||||||
return aiReturn_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZipFile::Tell() const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZipFile::Flush() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Constructor.
|
|
||||||
Q3BSPZipArchive::Q3BSPZipArchive(IOSystem* pIOHandler, const std::string& rFile) : m_ZipFileHandle(NULL), m_ArchiveMap() {
|
|
||||||
if (! rFile.empty()) {
|
|
||||||
zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
|
|
||||||
|
|
||||||
m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
|
|
||||||
|
|
||||||
if(m_ZipFileHandle != nullptr) {
|
|
||||||
mapArchive();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Destructor.
|
|
||||||
Q3BSPZipArchive::~Q3BSPZipArchive() {
|
|
||||||
for(auto &file : m_ArchiveMap) {
|
|
||||||
delete file.second;
|
|
||||||
}
|
|
||||||
m_ArchiveMap.clear();
|
|
||||||
|
|
||||||
if(m_ZipFileHandle != nullptr) {
|
|
||||||
unzClose(m_ZipFileHandle);
|
|
||||||
m_ZipFileHandle = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Returns true, if the archive is already open.
|
|
||||||
bool Q3BSPZipArchive::isOpen() const {
|
|
||||||
return (m_ZipFileHandle != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Returns true, if the filename is part of the archive.
|
|
||||||
bool Q3BSPZipArchive::Exists(const char* pFile) const {
|
|
||||||
bool exist = false;
|
|
||||||
if (pFile != nullptr) {
|
|
||||||
std::string rFile(pFile);
|
|
||||||
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
|
|
||||||
|
|
||||||
if(it != m_ArchiveMap.end()) {
|
|
||||||
exist = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return exist;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Returns the separator delimiter.
|
|
||||||
char Q3BSPZipArchive::getOsSeparator() const {
|
|
||||||
#ifndef _WIN32
|
|
||||||
return '/';
|
|
||||||
#else
|
|
||||||
return '\\';
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Opens a file, which is part of the archive.
|
|
||||||
IOStream *Q3BSPZipArchive::Open(const char* pFile, const char* /*pMode*/) {
|
|
||||||
ai_assert(pFile != nullptr);
|
|
||||||
|
|
||||||
IOStream* result = nullptr;
|
|
||||||
|
|
||||||
std::map<std::string, ZipFile*>::iterator it = m_ArchiveMap.find(pFile);
|
|
||||||
|
|
||||||
if(it != m_ArchiveMap.end()) {
|
|
||||||
result = (IOStream*) it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Close a filestream.
|
|
||||||
void Q3BSPZipArchive::Close(IOStream *pFile) {
|
|
||||||
(void)(pFile);
|
|
||||||
ai_assert(pFile != nullptr);
|
|
||||||
|
|
||||||
// We don't do anything in case the file would be opened again in the future
|
|
||||||
}
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Returns the file-list of the archive.
|
|
||||||
void Q3BSPZipArchive::getFileList(std::vector<std::string> &rFileList) {
|
|
||||||
rFileList.clear();
|
|
||||||
|
|
||||||
for(auto &file : m_ArchiveMap) {
|
|
||||||
rFileList.push_back(file.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Maps the archive content.
|
|
||||||
bool Q3BSPZipArchive::mapArchive() {
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
if(m_ZipFileHandle != nullptr) {
|
|
||||||
if(m_ArchiveMap.empty()) {
|
|
||||||
// At first ensure file is already open
|
|
||||||
if(unzGoToFirstFile(m_ZipFileHandle) == UNZ_OK) {
|
|
||||||
// Loop over all files
|
|
||||||
do {
|
|
||||||
char filename[FileNameSize];
|
|
||||||
unz_file_info fileInfo;
|
|
||||||
|
|
||||||
if(unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, NULL, 0, NULL, 0) == UNZ_OK) {
|
|
||||||
// The file has EXACTLY the size of uncompressed_size. In C
|
|
||||||
// you need to mark the last character with '\0', so add
|
|
||||||
// another character
|
|
||||||
if(fileInfo.uncompressed_size != 0 && unzOpenCurrentFile(m_ZipFileHandle) == UNZ_OK) {
|
|
||||||
std::pair<std::map<std::string, ZipFile*>::iterator, bool> result = m_ArchiveMap.insert(std::make_pair(filename, new ZipFile(fileInfo.uncompressed_size)));
|
|
||||||
|
|
||||||
if(unzReadCurrentFile(m_ZipFileHandle, result.first->second->m_Buffer, fileInfo.uncompressed_size) == (long int) fileInfo.uncompressed_size) {
|
|
||||||
if(unzCloseCurrentFile(m_ZipFileHandle) == UNZ_OK) {
|
|
||||||
// Nothing to do anymore...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while(unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
} // Namespace Q3BSP
|
|
||||||
} // Namespace Assimp
|
|
||||||
|
|
||||||
#endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER
|
|
|
@ -1,135 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2019, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#ifndef AI_Q3BSP_ZIPARCHIVE_H_INC
|
|
||||||
#define AI_Q3BSP_ZIPARCHIVE_H_INC
|
|
||||||
|
|
||||||
#ifdef ASSIMP_USE_HUNTER
|
|
||||||
# include <minizip/unzip.h>
|
|
||||||
#else
|
|
||||||
# include <unzip.h>
|
|
||||||
#endif
|
|
||||||
#include <assimp/IOStream.hpp>
|
|
||||||
#include <assimp/IOSystem.hpp>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
namespace Assimp {
|
|
||||||
namespace Q3BSP {
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
/// \class IOSystem2Unzip
|
|
||||||
/// \ingroup Assimp::Q3BSP
|
|
||||||
///
|
|
||||||
/// \brief
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
class IOSystem2Unzip {
|
|
||||||
public:
|
|
||||||
static voidpf open(voidpf opaque, const char* filename, int mode);
|
|
||||||
static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
|
|
||||||
static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
|
|
||||||
static long tell(voidpf opaque, voidpf stream);
|
|
||||||
static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
|
|
||||||
static int close(voidpf opaque, voidpf stream);
|
|
||||||
static int testerror(voidpf opaque, voidpf stream);
|
|
||||||
static zlib_filefunc_def get(IOSystem* pIOHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
/// \class ZipFile
|
|
||||||
/// \ingroup Assimp::Q3BSP
|
|
||||||
///
|
|
||||||
/// \brief
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
class ZipFile : public IOStream {
|
|
||||||
friend class Q3BSPZipArchive;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ZipFile(size_t size);
|
|
||||||
~ZipFile();
|
|
||||||
size_t Read(void* pvBuffer, size_t pSize, size_t pCount );
|
|
||||||
size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/);
|
|
||||||
size_t FileSize() const;
|
|
||||||
aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/);
|
|
||||||
size_t Tell() const;
|
|
||||||
void Flush();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* m_Buffer;
|
|
||||||
size_t m_Size;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
/// \class Q3BSPZipArchive
|
|
||||||
/// \ingroup Assimp::Q3BSP
|
|
||||||
///
|
|
||||||
/// \brief IMplements a zip archive like the WinZip archives. Will be also used to import data
|
|
||||||
/// from a P3K archive ( Quake level format ).
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
class Q3BSPZipArchive : public Assimp::IOSystem {
|
|
||||||
public:
|
|
||||||
static const unsigned int FileNameSize = 256;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Q3BSPZipArchive(IOSystem* pIOHandler, const std::string & rFile);
|
|
||||||
~Q3BSPZipArchive();
|
|
||||||
bool Exists(const char* pFile) const;
|
|
||||||
char getOsSeparator() const;
|
|
||||||
IOStream* Open(const char* pFile, const char* pMode = "rb");
|
|
||||||
void Close(IOStream* pFile);
|
|
||||||
bool isOpen() const;
|
|
||||||
void getFileList(std::vector<std::string> &rFileList);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool mapArchive();
|
|
||||||
|
|
||||||
private:
|
|
||||||
unzFile m_ZipFileHandle;
|
|
||||||
std::map<std::string, ZipFile*> m_ArchiveMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
} // Namespace Q3BSP
|
|
||||||
} // Namespace Assimp
|
|
||||||
|
|
||||||
#endif // AI_Q3BSP_ZIPARCHIVE_H_INC
|
|
|
@ -225,7 +225,7 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
||||||
}
|
}
|
||||||
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
|
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||||
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
|
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
|
||||||
clrDiffuse = aiColor4D( ai_real(1.0), ai_real(1.0), ai_real(1.0), ai_real(1.0));
|
clrDiffuse = aiColor4D( ai_real(0.05), ai_real(0.05), ai_real(0.05), ai_real(1.0));
|
||||||
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
|
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
|
||||||
|
|
||||||
pScene->mNumMaterials = 1;
|
pScene->mNumMaterials = 1;
|
||||||
|
|
|
@ -127,7 +127,8 @@ inline void CompressVertex(const aiVector3D& v, uint32_t& out)
|
||||||
n.X = (int32_t)v.x;
|
n.X = (int32_t)v.x;
|
||||||
n.Y = (int32_t)v.y;
|
n.Y = (int32_t)v.y;
|
||||||
n.Z = (int32_t)v.z;
|
n.Z = (int32_t)v.z;
|
||||||
out = t;
|
::memcpy( &out, &t, sizeof(int32_t));
|
||||||
|
//out = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// UNREAL vertex decompression
|
// UNREAL vertex decompression
|
||||||
|
|
|
@ -80,7 +80,13 @@ const aiImporterDesc X3DImporter::Description = {
|
||||||
//const std::regex X3DImporter::pattern_nws(R"([^, \t\r\n]+)");
|
//const std::regex X3DImporter::pattern_nws(R"([^, \t\r\n]+)");
|
||||||
//const std::regex X3DImporter::pattern_true(R"(^\s*(?:true|1)\s*$)", std::regex::icase);
|
//const std::regex X3DImporter::pattern_true(R"(^\s*(?:true|1)\s*$)", std::regex::icase);
|
||||||
|
|
||||||
struct WordIterator: public std::iterator<std::input_iterator_tag, const char*> {
|
struct WordIterator {
|
||||||
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
using value_type = const char*;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
|
||||||
static const char *whitespace;
|
static const char *whitespace;
|
||||||
const char *start_, *end_;
|
const char *start_, *end_;
|
||||||
WordIterator(const char *start, const char *end): start_(start), end_(end) {
|
WordIterator(const char *start, const char *end): start_(start), end_(end) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
* glTF Extensions Support:
|
* glTF Extensions Support:
|
||||||
* KHR_materials_pbrSpecularGlossiness full
|
* KHR_materials_pbrSpecularGlossiness full
|
||||||
* KHR_materials_unlit full
|
* KHR_materials_unlit full
|
||||||
|
* KHR_lights_punctual full
|
||||||
*/
|
*/
|
||||||
#ifndef GLTF2ASSET_H_INC
|
#ifndef GLTF2ASSET_H_INC
|
||||||
#define GLTF2ASSET_H_INC
|
#define GLTF2ASSET_H_INC
|
||||||
|
@ -668,6 +669,28 @@ namespace glTF2
|
||||||
void Read(Value& obj, Asset& r);
|
void Read(Value& obj, Asset& r);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! A light (from KHR_lights_punctual extension)
|
||||||
|
struct Light : public Object
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Directional,
|
||||||
|
Point,
|
||||||
|
Spot
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
vec3 color;
|
||||||
|
float intensity;
|
||||||
|
Nullable<float> range;
|
||||||
|
|
||||||
|
float innerConeAngle;
|
||||||
|
float outerConeAngle;
|
||||||
|
|
||||||
|
Light() {}
|
||||||
|
void Read(Value& obj, Asset& r);
|
||||||
|
};
|
||||||
|
|
||||||
//! Image data used to create a texture.
|
//! Image data used to create a texture.
|
||||||
struct Image : public Object
|
struct Image : public Object
|
||||||
|
@ -819,6 +842,7 @@ namespace glTF2
|
||||||
Nullable<vec3> scale;
|
Nullable<vec3> scale;
|
||||||
|
|
||||||
Ref<Camera> camera;
|
Ref<Camera> camera;
|
||||||
|
Ref<Light> light;
|
||||||
|
|
||||||
std::vector< Ref<Node> > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
|
std::vector< Ref<Node> > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
|
||||||
Ref<Skin> skin; //!< The ID of the skin referenced by this node.
|
Ref<Skin> skin; //!< The ID of the skin referenced by this node.
|
||||||
|
@ -1050,6 +1074,7 @@ namespace glTF2
|
||||||
{
|
{
|
||||||
bool KHR_materials_pbrSpecularGlossiness;
|
bool KHR_materials_pbrSpecularGlossiness;
|
||||||
bool KHR_materials_unlit;
|
bool KHR_materials_unlit;
|
||||||
|
bool KHR_lights_punctual;
|
||||||
|
|
||||||
} extensionsUsed;
|
} extensionsUsed;
|
||||||
|
|
||||||
|
@ -1063,6 +1088,7 @@ namespace glTF2
|
||||||
LazyDict<Buffer> buffers;
|
LazyDict<Buffer> buffers;
|
||||||
LazyDict<BufferView> bufferViews;
|
LazyDict<BufferView> bufferViews;
|
||||||
LazyDict<Camera> cameras;
|
LazyDict<Camera> cameras;
|
||||||
|
LazyDict<Light> lights;
|
||||||
LazyDict<Image> images;
|
LazyDict<Image> images;
|
||||||
LazyDict<Material> materials;
|
LazyDict<Material> materials;
|
||||||
LazyDict<Mesh> meshes;
|
LazyDict<Mesh> meshes;
|
||||||
|
@ -1083,6 +1109,7 @@ namespace glTF2
|
||||||
, buffers (*this, "buffers")
|
, buffers (*this, "buffers")
|
||||||
, bufferViews (*this, "bufferViews")
|
, bufferViews (*this, "bufferViews")
|
||||||
, cameras (*this, "cameras")
|
, cameras (*this, "cameras")
|
||||||
|
, lights (*this, "lights", "KHR_lights_punctual")
|
||||||
, images (*this, "images")
|
, images (*this, "images")
|
||||||
, materials (*this, "materials")
|
, materials (*this, "materials")
|
||||||
, meshes (*this, "meshes")
|
, meshes (*this, "meshes")
|
||||||
|
|
|
@ -1067,6 +1067,39 @@ inline void Camera::Read(Value& obj, Asset& /*r*/)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Light::Read(Value& obj, Asset& /*r*/)
|
||||||
|
{
|
||||||
|
#ifndef M_PI
|
||||||
|
const float M_PI = 3.14159265358979323846f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string type_string;
|
||||||
|
ReadMember(obj, "type", type_string);
|
||||||
|
if (type_string == "directional")
|
||||||
|
type = Light::Directional;
|
||||||
|
else if (type_string == "point")
|
||||||
|
type = Light::Point;
|
||||||
|
else
|
||||||
|
type = Light::Spot;
|
||||||
|
|
||||||
|
name = MemberOrDefault(obj, "name", "");
|
||||||
|
|
||||||
|
SetVector(color, vec3{ 1.0f, 1.0f, 1.0f });
|
||||||
|
ReadMember(obj, "color", color);
|
||||||
|
|
||||||
|
intensity = MemberOrDefault(obj, "intensity", 1.0f);
|
||||||
|
|
||||||
|
ReadMember(obj, "range", range);
|
||||||
|
|
||||||
|
if (type == Light::Spot)
|
||||||
|
{
|
||||||
|
Value* spot = FindObject(obj, "spot");
|
||||||
|
if (!spot) throw DeadlyImportError("GLTF: Light missing its spot parameters");
|
||||||
|
innerConeAngle = MemberOrDefault(*spot, "innerConeAngle", 0.0f);
|
||||||
|
outerConeAngle = MemberOrDefault(*spot, "outerConeAngle", M_PI / 4.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void Node::Read(Value& obj, Asset& r)
|
inline void Node::Read(Value& obj, Asset& r)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1110,6 +1143,19 @@ inline void Node::Read(Value& obj, Asset& r)
|
||||||
if (this->camera)
|
if (this->camera)
|
||||||
this->camera->id = this->id;
|
this->camera->id = this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Value* extensions = FindObject(obj, "extensions")) {
|
||||||
|
if (r.extensionsUsed.KHR_lights_punctual) {
|
||||||
|
|
||||||
|
if (Value* ext = FindObject(*extensions, "KHR_lights_punctual")) {
|
||||||
|
if (Value* light = FindUInt(*ext, "light")) {
|
||||||
|
this->light = r.lights.Retrieve(light->GetUint());
|
||||||
|
if (this->light)
|
||||||
|
this->light->id = this->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Scene::Read(Value& obj, Asset& r)
|
inline void Scene::Read(Value& obj, Asset& r)
|
||||||
|
@ -1421,6 +1467,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc)
|
||||||
|
|
||||||
CHECK_EXT(KHR_materials_pbrSpecularGlossiness);
|
CHECK_EXT(KHR_materials_pbrSpecularGlossiness);
|
||||||
CHECK_EXT(KHR_materials_unlit);
|
CHECK_EXT(KHR_materials_unlit);
|
||||||
|
CHECK_EXT(KHR_lights_punctual);
|
||||||
|
|
||||||
#undef CHECK_EXT
|
#undef CHECK_EXT
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,11 @@ namespace glTF2 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Write(Value& /*obj*/, Light& /*c*/, AssetWriter& /*w*/)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
inline void Write(Value& obj, Image& img, AssetWriter& w)
|
inline void Write(Value& obj, Image& img, AssetWriter& w)
|
||||||
{
|
{
|
||||||
if (img.bufferView) {
|
if (img.bufferView) {
|
||||||
|
|
|
@ -140,10 +140,10 @@ static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
|
static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
|
||||||
//{
|
{
|
||||||
// out.r = v[0]; out.g = v[1]; out.b = v[2];
|
out.r = v[0]; out.g = v[1]; out.b = v[2];
|
||||||
//}
|
}
|
||||||
|
|
||||||
static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
|
static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
|
||||||
{
|
{
|
||||||
|
@ -710,6 +710,69 @@ void glTF2Importer::ImportCameras(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void glTF2Importer::ImportLights(glTF2::Asset& r)
|
||||||
|
{
|
||||||
|
if (!r.lights.Size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mScene->mNumLights = r.lights.Size();
|
||||||
|
mScene->mLights = new aiLight*[r.lights.Size()];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < r.lights.Size(); ++i) {
|
||||||
|
Light& light = r.lights[i];
|
||||||
|
|
||||||
|
aiLight* ail = mScene->mLights[i] = new aiLight();
|
||||||
|
|
||||||
|
switch (light.type)
|
||||||
|
{
|
||||||
|
case Light::Directional:
|
||||||
|
ail->mType = aiLightSource_DIRECTIONAL; break;
|
||||||
|
case Light::Point:
|
||||||
|
ail->mType = aiLightSource_POINT; break;
|
||||||
|
case Light::Spot:
|
||||||
|
ail->mType = aiLightSource_SPOT; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ail->mType != aiLightSource_POINT)
|
||||||
|
{
|
||||||
|
ail->mDirection = aiVector3D(0.0f, 0.0f, -1.0f);
|
||||||
|
ail->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 colorWithIntensity = { light.color[0] * light.intensity, light.color[1] * light.intensity, light.color[2] * light.intensity };
|
||||||
|
CopyValue(colorWithIntensity, ail->mColorAmbient);
|
||||||
|
CopyValue(colorWithIntensity, ail->mColorDiffuse);
|
||||||
|
CopyValue(colorWithIntensity, ail->mColorSpecular);
|
||||||
|
|
||||||
|
if (ail->mType == aiLightSource_DIRECTIONAL)
|
||||||
|
{
|
||||||
|
ail->mAttenuationConstant = 1.0;
|
||||||
|
ail->mAttenuationLinear = 0.0;
|
||||||
|
ail->mAttenuationQuadratic = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//in PBR attenuation is calculated using inverse square law which can be expressed
|
||||||
|
//using assimps equation: 1/(att0 + att1 * d + att2 * d*d) with the following parameters
|
||||||
|
//this is correct equation for the case when range (see
|
||||||
|
//https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual)
|
||||||
|
//is not present. When range is not present it is assumed that it is infinite and so numerator is 1.
|
||||||
|
//When range is present then numerator might be any value in range [0,1] and then assimps equation
|
||||||
|
//will not suffice. In this case range is added into metadata in ImportNode function
|
||||||
|
//and its up to implementation to read it when it wants to
|
||||||
|
ail->mAttenuationConstant = 0.0;
|
||||||
|
ail->mAttenuationLinear = 0.0;
|
||||||
|
ail->mAttenuationQuadratic = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ail->mType == aiLightSource_SPOT)
|
||||||
|
{
|
||||||
|
ail->mAngleInnerCone = light.innerConeAngle;
|
||||||
|
ail->mAngleOuterCone = light.outerConeAngle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void GetNodeTransform(aiMatrix4x4& matrix, const glTF2::Node& node) {
|
static void GetNodeTransform(aiMatrix4x4& matrix, const glTF2::Node& node) {
|
||||||
if (node.matrix.isPresent) {
|
if (node.matrix.isPresent) {
|
||||||
CopyValue(node.matrix.value, matrix);
|
CopyValue(node.matrix.value, matrix);
|
||||||
|
@ -881,6 +944,18 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
|
||||||
pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
|
pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.light) {
|
||||||
|
pScene->mLights[node.light.GetIndex()]->mName = ainode->mName;
|
||||||
|
|
||||||
|
//range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
|
||||||
|
//it is added to meta data of parent node, because there is no other place to put it
|
||||||
|
if (node.light->range.isPresent)
|
||||||
|
{
|
||||||
|
ainode->mMetaData = aiMetadata::Alloc(1);
|
||||||
|
ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ainode;
|
return ainode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,6 +1225,7 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO
|
||||||
ImportMeshes(asset);
|
ImportMeshes(asset);
|
||||||
|
|
||||||
ImportCameras(asset);
|
ImportCameras(asset);
|
||||||
|
ImportLights(asset);
|
||||||
|
|
||||||
ImportNodes(asset);
|
ImportNodes(asset);
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,8 @@ BEGIN
|
||||||
VALUE "FileDescription", "Open Asset Import Library"
|
VALUE "FileDescription", "Open Asset Import Library"
|
||||||
VALUE "FileVersion", VER_FILEVERSION
|
VALUE "FileVersion", VER_FILEVERSION
|
||||||
VALUE "InternalName", "assimp "
|
VALUE "InternalName", "assimp "
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2006-2010"
|
VALUE "LegalCopyright", "Copyright (C) 2006-2019"
|
||||||
VALUE "OriginalFilename", "assimpNN.dll"
|
VALUE "OriginalFilename", VER_ORIGINAL_FILENAME_STR
|
||||||
VALUE "ProductName", "Open Asset Import Library"
|
VALUE "ProductName", "Open Asset Import Library"
|
||||||
VALUE "ProductVersion", VER_FILEVERSION_STR
|
VALUE "ProductVersion", VER_FILEVERSION_STR
|
||||||
,0
|
,0
|
||||||
|
|
|
@ -48,8 +48,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <map>
|
||||||
#include <assimp/types.h>
|
#include <assimp/types.h>
|
||||||
#include <assimp/ProgressHandler.hpp>
|
#include <assimp/ProgressHandler.hpp>
|
||||||
|
#include <assimp/ai_assert.h>
|
||||||
|
|
||||||
struct aiScene;
|
struct aiScene;
|
||||||
struct aiImporterDesc;
|
struct aiImporterDesc;
|
||||||
|
@ -161,6 +163,60 @@ public:
|
||||||
* some loader features. Importers must provide this information. */
|
* some loader features. Importers must provide this information. */
|
||||||
virtual const aiImporterDesc* GetInfo() const = 0;
|
virtual const aiImporterDesc* GetInfo() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will be called only by scale process when scaling is requested.
|
||||||
|
*/
|
||||||
|
virtual void SetFileScale(double scale)
|
||||||
|
{
|
||||||
|
fileScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual double GetFileScale() const
|
||||||
|
{
|
||||||
|
return fileScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ImporterUnits {
|
||||||
|
M,
|
||||||
|
MM,
|
||||||
|
CM,
|
||||||
|
INCHES,
|
||||||
|
FEET
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assimp Importer
|
||||||
|
* unit conversions available
|
||||||
|
* if you need another measurment unit add it below.
|
||||||
|
* it's currently defined in assimp that we prefer meters.
|
||||||
|
* */
|
||||||
|
std::map<ImporterUnits, double> importerUnits = {
|
||||||
|
{ImporterUnits::M, 1},
|
||||||
|
{ImporterUnits::CM, 0.01},
|
||||||
|
{ImporterUnits::MM, 0.001},
|
||||||
|
{ImporterUnits::INCHES, 0.0254},
|
||||||
|
{ImporterUnits::FEET, 0.3048}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void SetApplicationUnits( const ImporterUnits& unit )
|
||||||
|
{
|
||||||
|
importerScale = importerUnits[unit];
|
||||||
|
applicationUnits = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const ImporterUnits& GetApplicationUnits()
|
||||||
|
{
|
||||||
|
return applicationUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns scale used by application called by ScaleProcess */
|
||||||
|
double GetImporterScale() const
|
||||||
|
{
|
||||||
|
ai_assert(importerScale != 0);
|
||||||
|
ai_assert(fileScale != 0);
|
||||||
|
return importerScale * fileScale;
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Called by #Importer::GetExtensionList for each loaded importer.
|
/** Called by #Importer::GetExtensionList for each loaded importer.
|
||||||
* Take the extension list contained in the structure returned by
|
* Take the extension list contained in the structure returned by
|
||||||
|
@ -169,6 +225,10 @@ public:
|
||||||
void GetExtensionList(std::set<std::string>& extensions);
|
void GetExtensionList(std::set<std::string>& extensions);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
ImporterUnits applicationUnits = ImporterUnits::M;
|
||||||
|
double importerScale = 1.0;
|
||||||
|
double fileScale = 1.0;
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Imports the given file into the given scene structure. The
|
/** Imports the given file into the given scene structure. The
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the following
|
||||||
|
conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file ZipArchiveIOSystem.h
|
||||||
|
* @brief Implementation of IOSystem to read a ZIP file from another IOSystem
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AI_ZIPARCHIVEIOSYSTEM_H_INC
|
||||||
|
#define AI_ZIPARCHIVEIOSYSTEM_H_INC
|
||||||
|
|
||||||
|
#include <assimp/IOStream.hpp>
|
||||||
|
#include <assimp/IOSystem.hpp>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
class ZipArchiveIOSystem : public IOSystem {
|
||||||
|
public:
|
||||||
|
//! Open a Zip using the proffered IOSystem
|
||||||
|
ZipArchiveIOSystem(IOSystem* pIOHandler, const char *pFilename, const char* pMode = "r");
|
||||||
|
ZipArchiveIOSystem(IOSystem* pIOHandler, const std::string& rFilename, const char* pMode = "r");
|
||||||
|
virtual ~ZipArchiveIOSystem();
|
||||||
|
bool Exists(const char* pFilename) const override;
|
||||||
|
char getOsSeparator() const override;
|
||||||
|
IOStream* Open(const char* pFilename, const char* pMode = "rb") override;
|
||||||
|
void Close(IOStream* pFile) override;
|
||||||
|
|
||||||
|
// Specific to ZIP
|
||||||
|
//! The file was opened and is a ZIP
|
||||||
|
bool isOpen() const;
|
||||||
|
|
||||||
|
//! Get the list of all files with their simplified paths
|
||||||
|
//! Intended for use within Assimp library boundaries
|
||||||
|
void getFileList(std::vector<std::string>& rFileList) const;
|
||||||
|
|
||||||
|
//! Get the list of all files with extension (must be lowercase)
|
||||||
|
//! Intended for use within Assimp library boundaries
|
||||||
|
void getFileListExtension(std::vector<std::string>& rFileList, const std::string& extension) const;
|
||||||
|
|
||||||
|
static bool isZipArchive(IOSystem* pIOHandler, const char *pFilename);
|
||||||
|
static bool isZipArchive(IOSystem* pIOHandler, const std::string& rFilename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Implement;
|
||||||
|
Implement *pImpl = nullptr;
|
||||||
|
};
|
||||||
|
} // Namespace Assimp
|
||||||
|
|
||||||
|
#endif // AI_ZIPARCHIVEIOSYSTEM_H_INC
|
|
@ -142,7 +142,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
/** @brief Specifies the maximum angle that may be between two vertex tangents
|
/** @brief Specifies the maximum angle that may be between two vertex tangents
|
||||||
* that their tangents and bi-tangents are smoothed.
|
* that their tangents and bi-tangents are smoothed.
|
||||||
*
|
*
|
||||||
* This applies to the CalcTangentSpace-Step. TFvhe angle is specified
|
* This applies to the CalcTangentSpace-Step. The angle is specified
|
||||||
* in degrees. The maximum value is 175.
|
* in degrees. The maximum value is 175.
|
||||||
* Property type: float. Default value: 45 degrees
|
* Property type: float. Default value: 45 degrees
|
||||||
*/
|
*/
|
||||||
|
@ -999,6 +999,13 @@ enum aiComponent
|
||||||
# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
|
# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
|
||||||
#endif // !! AI_DEBONE_THRESHOLD
|
#endif // !! AI_DEBONE_THRESHOLD
|
||||||
|
|
||||||
|
#define AI_CONFIG_APP_SCALE_KEY "APP_SCALE_FACTOR"
|
||||||
|
|
||||||
|
#if (!defined AI_CONFIG_APP_SCALE_KEY)
|
||||||
|
# define AI_CONFIG_APP_SCALE_KEY 1.0
|
||||||
|
#endif // AI_CONFIG_APP_SCALE_KEY
|
||||||
|
|
||||||
|
|
||||||
// ---------- All the Build/Compile-time defines ------------
|
// ---------- All the Build/Compile-time defines ------------
|
||||||
|
|
||||||
/** @brief Specifies if double precision is supported inside assimp
|
/** @brief Specifies if double precision is supported inside assimp
|
||||||
|
|
|
@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
# include <cstdlib>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,16 @@
|
||||||
#define STR(x) STR_HELP(x)
|
#define STR(x) STR_HELP(x)
|
||||||
|
|
||||||
#define VER_FILEVERSION VER_MAJOR,VER_MINOR,VER_PATCH,VER_BUILD
|
#define VER_FILEVERSION VER_MAJOR,VER_MINOR,VER_PATCH,VER_BUILD
|
||||||
|
#if (GitVersion == 0)
|
||||||
#define VER_FILEVERSION_STR STR(VER_MAJOR) "." STR(VER_MINOR) "." STR(VER_PATCH) "." STR(VER_BUILD)
|
#define VER_FILEVERSION_STR STR(VER_MAJOR) "." STR(VER_MINOR) "." STR(VER_PATCH) "." STR(VER_BUILD)
|
||||||
|
#else
|
||||||
|
#define VER_FILEVERSION_STR STR(VER_MAJOR) "." STR(VER_MINOR) "." STR(VER_PATCH) "." STR(VER_BUILD) " (Commit @GIT_COMMIT_HASH@)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define VER_ORIGINAL_FILENAME_STR "assimp@LIBRARY_SUFFIX@.dll"
|
||||||
|
#else
|
||||||
|
#define VER_ORIGINAL_FILENAME_STR "assimp@LIBRARY_SUFFIX@@CMAKE_DEBUG_POSTFIX@.dll"
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
#endif // ASSIMP_REVISION_H_INC
|
#endif // ASSIMP_REVISION_H_INC
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Ignore Unit Test Output files
|
||||||
|
|
||||||
|
*_out.*
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,855 @@
|
||||||
|
; FBX 7.5.0 project file
|
||||||
|
; ----------------------------------------------------
|
||||||
|
|
||||||
|
FBXHeaderExtension: {
|
||||||
|
FBXHeaderVersion: 1003
|
||||||
|
FBXVersion: 7500
|
||||||
|
CreationTimeStamp: {
|
||||||
|
Version: 1000
|
||||||
|
Year: 2019
|
||||||
|
Month: 5
|
||||||
|
Day: 14
|
||||||
|
Hour: 17
|
||||||
|
Minute: 27
|
||||||
|
Second: 42
|
||||||
|
Millisecond: 70
|
||||||
|
}
|
||||||
|
Creator: "FBX SDK/FBX Plugins version 2018.1.1"
|
||||||
|
SceneInfo: "SceneInfo::GlobalInfo", "UserData" {
|
||||||
|
Type: "UserData"
|
||||||
|
Version: 100
|
||||||
|
MetaData: {
|
||||||
|
Version: 100
|
||||||
|
Title: ""
|
||||||
|
Subject: ""
|
||||||
|
Author: ""
|
||||||
|
Keywords: ""
|
||||||
|
Revision: ""
|
||||||
|
Comment: ""
|
||||||
|
}
|
||||||
|
Properties70: {
|
||||||
|
P: "DocumentUrl", "KString", "Url", "", "U:\Some\Absolute\Path\cubes_with_mirroring_and_pivot.fbx"
|
||||||
|
P: "SrcDocumentUrl", "KString", "Url", "", "U:\Some\Absolute\Path\cubes_with_mirroring_and_pivot.fbx"
|
||||||
|
P: "Original", "Compound", "", ""
|
||||||
|
P: "Original|ApplicationVendor", "KString", "", "", "Autodesk"
|
||||||
|
P: "Original|ApplicationName", "KString", "", "", "Maya"
|
||||||
|
P: "Original|ApplicationVersion", "KString", "", "", "201800"
|
||||||
|
P: "Original|DateTime_GMT", "DateTime", "", "", "14/05/2019 16:27:42.070"
|
||||||
|
P: "Original|FileName", "KString", "", "", "U:\Some\Absolute\Path\cubes_with_mirroring_and_pivot.fbx"
|
||||||
|
P: "LastSaved", "Compound", "", ""
|
||||||
|
P: "LastSaved|ApplicationVendor", "KString", "", "", "Autodesk"
|
||||||
|
P: "LastSaved|ApplicationName", "KString", "", "", "Maya"
|
||||||
|
P: "LastSaved|ApplicationVersion", "KString", "", "", "201800"
|
||||||
|
P: "LastSaved|DateTime_GMT", "DateTime", "", "", "14/05/2019 16:27:42.070"
|
||||||
|
P: "Original|ApplicationActiveProject", "KString", "", "", "U:\Some\Absolute\Path"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalSettings: {
|
||||||
|
Version: 1000
|
||||||
|
Properties70: {
|
||||||
|
P: "UpAxis", "int", "Integer", "",1
|
||||||
|
P: "UpAxisSign", "int", "Integer", "",1
|
||||||
|
P: "FrontAxis", "int", "Integer", "",2
|
||||||
|
P: "FrontAxisSign", "int", "Integer", "",1
|
||||||
|
P: "CoordAxis", "int", "Integer", "",0
|
||||||
|
P: "CoordAxisSign", "int", "Integer", "",1
|
||||||
|
P: "OriginalUpAxis", "int", "Integer", "",1
|
||||||
|
P: "OriginalUpAxisSign", "int", "Integer", "",1
|
||||||
|
P: "UnitScaleFactor", "double", "Number", "",100
|
||||||
|
P: "OriginalUnitScaleFactor", "double", "Number", "",1
|
||||||
|
P: "AmbientColor", "ColorRGB", "Color", "",0,0,0
|
||||||
|
P: "DefaultCamera", "KString", "", "", "Producer Perspective"
|
||||||
|
P: "TimeMode", "enum", "", "",11
|
||||||
|
P: "TimeProtocol", "enum", "", "",2
|
||||||
|
P: "SnapOnFrameMode", "enum", "", "",0
|
||||||
|
P: "TimeSpanStart", "KTime", "Time", "",1924423250
|
||||||
|
P: "TimeSpanStop", "KTime", "Time", "",384884650000
|
||||||
|
P: "CustomFrameRate", "double", "Number", "",-1
|
||||||
|
P: "TimeMarker", "Compound", "", ""
|
||||||
|
P: "CurrentTimeMarker", "int", "Integer", "",-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; Documents Description
|
||||||
|
;------------------------------------------------------------------
|
||||||
|
|
||||||
|
Documents: {
|
||||||
|
Count: 1
|
||||||
|
Document: 1827132552544, "", "Scene" {
|
||||||
|
Properties70: {
|
||||||
|
P: "SourceObject", "object", "", ""
|
||||||
|
P: "ActiveAnimStackName", "KString", "", "", "Take 001"
|
||||||
|
}
|
||||||
|
RootNode: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; Document References
|
||||||
|
;------------------------------------------------------------------
|
||||||
|
|
||||||
|
References: {
|
||||||
|
}
|
||||||
|
|
||||||
|
; Object definitions
|
||||||
|
;------------------------------------------------------------------
|
||||||
|
|
||||||
|
Definitions: {
|
||||||
|
Version: 100
|
||||||
|
Count: 13
|
||||||
|
ObjectType: "GlobalSettings" {
|
||||||
|
Count: 1
|
||||||
|
}
|
||||||
|
ObjectType: "AnimationStack" {
|
||||||
|
Count: 1
|
||||||
|
PropertyTemplate: "FbxAnimStack" {
|
||||||
|
Properties70: {
|
||||||
|
P: "Description", "KString", "", "", ""
|
||||||
|
P: "LocalStart", "KTime", "Time", "",0
|
||||||
|
P: "LocalStop", "KTime", "Time", "",0
|
||||||
|
P: "ReferenceStart", "KTime", "Time", "",0
|
||||||
|
P: "ReferenceStop", "KTime", "Time", "",0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObjectType: "AnimationLayer" {
|
||||||
|
Count: 1
|
||||||
|
PropertyTemplate: "FbxAnimLayer" {
|
||||||
|
Properties70: {
|
||||||
|
P: "Weight", "Number", "", "A",100
|
||||||
|
P: "Mute", "bool", "", "",0
|
||||||
|
P: "Solo", "bool", "", "",0
|
||||||
|
P: "Lock", "bool", "", "",0
|
||||||
|
P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8
|
||||||
|
P: "BlendMode", "enum", "", "",0
|
||||||
|
P: "RotationAccumulationMode", "enum", "", "",0
|
||||||
|
P: "ScaleAccumulationMode", "enum", "", "",0
|
||||||
|
P: "BlendModeBypass", "ULongLong", "", "",0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObjectType: "Geometry" {
|
||||||
|
Count: 4
|
||||||
|
PropertyTemplate: "FbxMesh" {
|
||||||
|
Properties70: {
|
||||||
|
P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8
|
||||||
|
P: "BBoxMin", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "BBoxMax", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "Primary Visibility", "bool", "", "",1
|
||||||
|
P: "Casts Shadows", "bool", "", "",1
|
||||||
|
P: "Receive Shadows", "bool", "", "",1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObjectType: "Material" {
|
||||||
|
Count: 2
|
||||||
|
PropertyTemplate: "FbxSurfaceLambert" {
|
||||||
|
Properties70: {
|
||||||
|
P: "ShadingModel", "KString", "", "", "Lambert"
|
||||||
|
P: "MultiLayer", "bool", "", "",0
|
||||||
|
P: "EmissiveColor", "Color", "", "A",0,0,0
|
||||||
|
P: "EmissiveFactor", "Number", "", "A",1
|
||||||
|
P: "AmbientColor", "Color", "", "A",0.2,0.2,0.2
|
||||||
|
P: "AmbientFactor", "Number", "", "A",1
|
||||||
|
P: "DiffuseColor", "Color", "", "A",0.8,0.8,0.8
|
||||||
|
P: "DiffuseFactor", "Number", "", "A",1
|
||||||
|
P: "Bump", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "NormalMap", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "BumpFactor", "double", "Number", "",1
|
||||||
|
P: "TransparentColor", "Color", "", "A",0,0,0
|
||||||
|
P: "TransparencyFactor", "Number", "", "A",0
|
||||||
|
P: "DisplacementColor", "ColorRGB", "Color", "",0,0,0
|
||||||
|
P: "DisplacementFactor", "double", "Number", "",1
|
||||||
|
P: "VectorDisplacementColor", "ColorRGB", "Color", "",0,0,0
|
||||||
|
P: "VectorDisplacementFactor", "double", "Number", "",1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObjectType: "Model" {
|
||||||
|
Count: 4
|
||||||
|
PropertyTemplate: "FbxNode" {
|
||||||
|
Properties70: {
|
||||||
|
P: "QuaternionInterpolate", "enum", "", "",0
|
||||||
|
P: "RotationOffset", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "RotationPivot", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "ScalingOffset", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "ScalingPivot", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "TranslationActive", "bool", "", "",0
|
||||||
|
P: "TranslationMin", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "TranslationMax", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "TranslationMinX", "bool", "", "",0
|
||||||
|
P: "TranslationMinY", "bool", "", "",0
|
||||||
|
P: "TranslationMinZ", "bool", "", "",0
|
||||||
|
P: "TranslationMaxX", "bool", "", "",0
|
||||||
|
P: "TranslationMaxY", "bool", "", "",0
|
||||||
|
P: "TranslationMaxZ", "bool", "", "",0
|
||||||
|
P: "RotationOrder", "enum", "", "",0
|
||||||
|
P: "RotationSpaceForLimitOnly", "bool", "", "",0
|
||||||
|
P: "RotationStiffnessX", "double", "Number", "",0
|
||||||
|
P: "RotationStiffnessY", "double", "Number", "",0
|
||||||
|
P: "RotationStiffnessZ", "double", "Number", "",0
|
||||||
|
P: "AxisLen", "double", "Number", "",10
|
||||||
|
P: "PreRotation", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "PostRotation", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "RotationActive", "bool", "", "",0
|
||||||
|
P: "RotationMin", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "RotationMax", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "RotationMinX", "bool", "", "",0
|
||||||
|
P: "RotationMinY", "bool", "", "",0
|
||||||
|
P: "RotationMinZ", "bool", "", "",0
|
||||||
|
P: "RotationMaxX", "bool", "", "",0
|
||||||
|
P: "RotationMaxY", "bool", "", "",0
|
||||||
|
P: "RotationMaxZ", "bool", "", "",0
|
||||||
|
P: "InheritType", "enum", "", "",0
|
||||||
|
P: "ScalingActive", "bool", "", "",0
|
||||||
|
P: "ScalingMin", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "ScalingMax", "Vector3D", "Vector", "",1,1,1
|
||||||
|
P: "ScalingMinX", "bool", "", "",0
|
||||||
|
P: "ScalingMinY", "bool", "", "",0
|
||||||
|
P: "ScalingMinZ", "bool", "", "",0
|
||||||
|
P: "ScalingMaxX", "bool", "", "",0
|
||||||
|
P: "ScalingMaxY", "bool", "", "",0
|
||||||
|
P: "ScalingMaxZ", "bool", "", "",0
|
||||||
|
P: "GeometricTranslation", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "GeometricRotation", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "GeometricScaling", "Vector3D", "Vector", "",1,1,1
|
||||||
|
P: "MinDampRangeX", "double", "Number", "",0
|
||||||
|
P: "MinDampRangeY", "double", "Number", "",0
|
||||||
|
P: "MinDampRangeZ", "double", "Number", "",0
|
||||||
|
P: "MaxDampRangeX", "double", "Number", "",0
|
||||||
|
P: "MaxDampRangeY", "double", "Number", "",0
|
||||||
|
P: "MaxDampRangeZ", "double", "Number", "",0
|
||||||
|
P: "MinDampStrengthX", "double", "Number", "",0
|
||||||
|
P: "MinDampStrengthY", "double", "Number", "",0
|
||||||
|
P: "MinDampStrengthZ", "double", "Number", "",0
|
||||||
|
P: "MaxDampStrengthX", "double", "Number", "",0
|
||||||
|
P: "MaxDampStrengthY", "double", "Number", "",0
|
||||||
|
P: "MaxDampStrengthZ", "double", "Number", "",0
|
||||||
|
P: "PreferedAngleX", "double", "Number", "",0
|
||||||
|
P: "PreferedAngleY", "double", "Number", "",0
|
||||||
|
P: "PreferedAngleZ", "double", "Number", "",0
|
||||||
|
P: "LookAtProperty", "object", "", ""
|
||||||
|
P: "UpVectorProperty", "object", "", ""
|
||||||
|
P: "Show", "bool", "", "",1
|
||||||
|
P: "NegativePercentShapeSupport", "bool", "", "",1
|
||||||
|
P: "DefaultAttributeIndex", "int", "Integer", "",-1
|
||||||
|
P: "Freeze", "bool", "", "",0
|
||||||
|
P: "LODBox", "bool", "", "",0
|
||||||
|
P: "Lcl Translation", "Lcl Translation", "", "A",0,0,0
|
||||||
|
P: "Lcl Rotation", "Lcl Rotation", "", "A",0,0,0
|
||||||
|
P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1
|
||||||
|
P: "Visibility", "Visibility", "", "A",1
|
||||||
|
P: "Visibility Inheritance", "Visibility Inheritance", "", "",1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; Object properties
|
||||||
|
;------------------------------------------------------------------
|
||||||
|
|
||||||
|
Objects: {
|
||||||
|
Geometry: 1827080157856, "Geometry::", "Mesh" {
|
||||||
|
Vertices: *24 {
|
||||||
|
a: -0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,-0.5
|
||||||
|
}
|
||||||
|
PolygonVertexIndex: *24 {
|
||||||
|
a: 0,1,3,-3,2,3,5,-5,4,5,7,-7,6,7,1,-1,1,7,5,-4,6,0,2,-5
|
||||||
|
}
|
||||||
|
Edges: *12 {
|
||||||
|
a: 0,1,2,3,5,6,7,9,10,11,13,15
|
||||||
|
}
|
||||||
|
GeometryVersion: 124
|
||||||
|
LayerElementNormal: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Normals: *72 {
|
||||||
|
a: 0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0
|
||||||
|
}
|
||||||
|
NormalsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementBinormal: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Binormals: *72 {
|
||||||
|
a: 0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,-0,1,0,-0,1,0,0,1,-0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0
|
||||||
|
}
|
||||||
|
BinormalsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LayerElementTangent: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Tangents: *72 {
|
||||||
|
a: 1,-0,-0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,0,0,-1,0,0,-1,0,-0,-1,0,0,-1,0,-0,1,0,-0,1,0,-0,1,0,-0,1
|
||||||
|
}
|
||||||
|
TangentsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementUV: 0 {
|
||||||
|
Version: 101
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "IndexToDirect"
|
||||||
|
UV: *28 {
|
||||||
|
a: 0.375,0,0.625,0,0.375,0.25,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.625,1,0.875,0,0.875,0.25,0.125,0,0.125,0.25
|
||||||
|
}
|
||||||
|
UVIndex: *24 {
|
||||||
|
a: 0,1,3,2,2,3,5,4,4,5,7,6,6,7,9,8,1,10,11,3,12,0,2,13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementSmoothing: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "ByEdge"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Smoothing: *12 {
|
||||||
|
a: 0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementMaterial: 0 {
|
||||||
|
Version: 101
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "AllSame"
|
||||||
|
ReferenceInformationType: "IndexToDirect"
|
||||||
|
Materials: *1 {
|
||||||
|
a: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Layer: 0 {
|
||||||
|
Version: 100
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementNormal"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementBinormal"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementTangent"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementMaterial"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementSmoothing"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementUV"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Geometry: 1827080155296, "Geometry::", "Mesh" {
|
||||||
|
Vertices: *24 {
|
||||||
|
a: -0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,-0.5
|
||||||
|
}
|
||||||
|
PolygonVertexIndex: *24 {
|
||||||
|
a: 0,1,3,-3,2,3,5,-5,4,5,7,-7,6,7,1,-1,1,7,5,-4,6,0,2,-5
|
||||||
|
}
|
||||||
|
Edges: *12 {
|
||||||
|
a: 0,1,2,3,5,6,7,9,10,11,13,15
|
||||||
|
}
|
||||||
|
GeometryVersion: 124
|
||||||
|
LayerElementNormal: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Normals: *72 {
|
||||||
|
a: 0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0
|
||||||
|
}
|
||||||
|
NormalsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementBinormal: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Binormals: *72 {
|
||||||
|
a: 0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,-0,1,0,-0,1,0,0,1,-0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0
|
||||||
|
}
|
||||||
|
BinormalsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LayerElementTangent: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Tangents: *72 {
|
||||||
|
a: 1,-0,-0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,0,0,-1,0,0,-1,0,-0,-1,0,0,-1,0,-0,1,0,-0,1,0,-0,1,0,-0,1
|
||||||
|
}
|
||||||
|
TangentsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementUV: 0 {
|
||||||
|
Version: 101
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "IndexToDirect"
|
||||||
|
UV: *28 {
|
||||||
|
a: 0.375,0,0.625,0,0.375,0.25,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.625,1,0.875,0,0.875,0.25,0.125,0,0.125,0.25
|
||||||
|
}
|
||||||
|
UVIndex: *24 {
|
||||||
|
a: 0,1,3,2,2,3,5,4,4,5,7,6,6,7,9,8,1,10,11,3,12,0,2,13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementSmoothing: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "ByEdge"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Smoothing: *12 {
|
||||||
|
a: 0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementMaterial: 0 {
|
||||||
|
Version: 101
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "AllSame"
|
||||||
|
ReferenceInformationType: "IndexToDirect"
|
||||||
|
Materials: *1 {
|
||||||
|
a: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Layer: 0 {
|
||||||
|
Version: 100
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementNormal"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementBinormal"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementTangent"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementMaterial"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementSmoothing"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementUV"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Geometry: 1827080156320, "Geometry::", "Mesh" {
|
||||||
|
Vertices: *24 {
|
||||||
|
a: -0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,-0.5
|
||||||
|
}
|
||||||
|
PolygonVertexIndex: *24 {
|
||||||
|
a: 0,1,3,-3,2,3,5,-5,4,5,7,-7,6,7,1,-1,1,7,5,-4,6,0,2,-5
|
||||||
|
}
|
||||||
|
Edges: *12 {
|
||||||
|
a: 0,1,2,3,5,6,7,9,10,11,13,15
|
||||||
|
}
|
||||||
|
GeometryVersion: 124
|
||||||
|
LayerElementNormal: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Normals: *72 {
|
||||||
|
a: 0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0
|
||||||
|
}
|
||||||
|
NormalsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementBinormal: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Binormals: *72 {
|
||||||
|
a: 0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,-0,1,0,-0,1,0,0,1,-0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0
|
||||||
|
}
|
||||||
|
BinormalsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LayerElementTangent: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Tangents: *72 {
|
||||||
|
a: 1,-0,-0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,0,0,-1,0,0,-1,0,-0,-1,0,0,-1,0,-0,1,0,-0,1,0,-0,1,0,-0,1
|
||||||
|
}
|
||||||
|
TangentsW: *24 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementUV: 0 {
|
||||||
|
Version: 101
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "IndexToDirect"
|
||||||
|
UV: *28 {
|
||||||
|
a: 0.375,0,0.625,0,0.375,0.25,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.625,1,0.875,0,0.875,0.25,0.125,0,0.125,0.25
|
||||||
|
}
|
||||||
|
UVIndex: *24 {
|
||||||
|
a: 0,1,3,2,2,3,5,4,4,5,7,6,6,7,9,8,1,10,11,3,12,0,2,13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementSmoothing: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "ByEdge"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Smoothing: *12 {
|
||||||
|
a: 0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementMaterial: 0 {
|
||||||
|
Version: 101
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "AllSame"
|
||||||
|
ReferenceInformationType: "IndexToDirect"
|
||||||
|
Materials: *1 {
|
||||||
|
a: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Layer: 0 {
|
||||||
|
Version: 100
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementNormal"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementBinormal"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementTangent"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementMaterial"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementSmoothing"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementUV"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Geometry: 1827080139424, "Geometry::", "Mesh" {
|
||||||
|
Vertices: *588 {
|
||||||
|
a: -0.499999970197678,-0.5,0.5,0.500000059604645,-0.5,0.5,-0.499999970197678,0.5,0.5,0.500000059604645,0.5,0.5,-0.499999970197678,0.5,-0.49999988079071,0.500000059604645,0.5,-0.49999988079071,-0.499999970197678,-0.5,-0.49999988079071,0.500000059604645,-0.5,-0.49999988079071,0,0,0.5,0,-0.5,0.5,0.500000059604645,0,0.5,0,0.5,0.5,-0.499999970197678,0,0.5,0,0.5,1.19209289550781e-07,0.500000059604645,0.5,1.19209289550781e-07,0,0.5,-0.49999988079071,-0.499999970197678,0.5,1.19209289550781e-07,0,0,-0.49999988079071,0.500000059604645,0,-0.49999988079071,0,-0.5,-0.49999988079071,-0.499999970197678,0,-0.49999988079071,0,-0.5,1.19209289550781e-07,0.500000059604645,-0.5,1.19209289550781e-07,-0.499999970197678,-0.5,1.19209289550781e-07,0.500000059604645,0,1.19209289550781e-07,-0.499999970197678,0,1.19209289550781e-07,-0.25,-0.25,0.5,-0.499999970197678,-0.25,0.5,-0.25,-0.5,0.5,0,-0.25,0.5,-0.25,0,0.5,-0.25,0.5,0.25,-0.499999970197678,0.5,0.25,-0.25,0.5,0.5,0,0.5,0.25,-0.25,0.5,1.19209289550781e-07,-0.25,0.25,-0.49999988079071,-0.499999970197678,0.25,-0.49999988079071,-0.25,0.5,-0.49999988079071,0,0.25,-0.49999988079071,-0.25,0,-0.49999988079071,-0.25,-0.5,-0.24999988079071,-0.499999970197678,-0.5,-0.24999988079071,-0.25,-0.5,-0.49999988079071,0,-0.5,-0.24999988079071,-0.25,-0.5,1.19209289550781e-07,0.500000059604645,-0.25,0.25,0.500000059604645,-0.25,0.5,0.500000059604645,-0.5,0.25,0.500000059604645,-0.25,1.19209289550781e-07,0.500000059604645,0,0.25,-0.499999970197678,-0.25,-0.24999988079071,-0.499999970197678,-0.25,-0.49999988079071,-0.499999970197678,-0.25,1.19209289550781e-07,-0.499999970197678,0,-0.24999988079071,0.250000059604645,-0.25,0.5,0.250000059604645,-0.5,0.5,0.250000059604645,0,0.5,0.250000059604645,0.25,0.5,0.500000059604645,0.25,0.5,0.250000059604645,0.5,0.5,0,0.25,0.5,-0.25,0.25,0.5,-0.499999970197678,0.25,0.5,0.250000059604645,0.5,0.25,0.500000059604645,0.5,0.25,0.250000059604645,0.5,1.19209289550781e-07,0.250000059604645,0.5,-0.24999988079071,0.500000059604645,0.5,-0.24999988079071,0.250000059604645,0.5,-0.49999988079071,
|
||||||
|
0,0.5,-0.24999988079071,-0.25,0.5,-0.24999988079071,-0.499999970197678,0.5,-0.24999988079071,0.250000059604645,0.25,-0.49999988079071,0.500000059604645,0.25,-0.49999988079071,0.250000059604645,0,-0.49999988079071,0.250000059604645,-0.25,-0.49999988079071,0.500000059604645,-0.25,-0.49999988079071,0.250000059604645,-0.5,-0.49999988079071,0,-0.25,-0.49999988079071,-0.25,-0.25,-0.49999988079071,0.250000059604645,-0.5,-0.24999988079071,0.500000059604645,-0.5,-0.24999988079071,0.250000059604645,-0.5,1.19209289550781e-07,0.250000059604645,-0.5,0.25,0,-0.5,0.25,-0.25,-0.5,0.25,-0.499999970197678,-0.5,0.25,0.500000059604645,-0.25,-0.24999988079071,0.500000059604645,0,-0.24999988079071,0.500000059604645,0.25,-0.24999988079071,0.500000059604645,0.25,1.19209289550781e-07,0.500000059604645,0.25,0.25,-0.499999970197678,-0.25,0.25,-0.499999970197678,0,0.25,-0.499999970197678,0.25,0.25,-0.499999970197678,0.25,1.19209289550781e-07,-0.499999970197678,0.25,-0.24999988079071,-0.594913899898529,0,0.594913899898529,-0.152911216020584,0,0.714658200740814,-0.594913899898529,-0.152911216020584,0.594913899898529,-0.152911216020584,-0.152911216020584,0.714658200740814,-0.594913899898529,0.594913899898529,7.29137497046395e-08,-0.152911216020584,0.714658200740814,7.29137497046395e-08,-0.594913899898529,0.594913899898529,0.152911216020584,-0.152911216020584,0.714658200740814,0.152911216020584,-0.594913899898529,0,-0.594913899898529,-0.152911216020584,0,-0.714658200740814,-0.594913899898529,0.152911216020584,-0.594913899898529,-0.152911216020584,0.152911216020584,-0.714658200740814,-0.594913899898529,-0.594913899898529,7.29137497046395e-08,-0.152911216020584,-0.714658200740814,7.29137497046395e-08,-0.594913899898529,-0.594913899898529,-0.152911216020584,-0.152911216020584,-0.714658200740814,-0.152911216020584,0.594913899898529,0,0.594913899898529,0.714658200740814,0,0.152911216020584,0.594913899898529,-0.152911216020584,0.594913899898529,0.714658200740814,-0.152911216020584,0.152911216020584,-0.714658200740814,0,-0.152911216020584,-0.594913899898529,-0.152911216020584,-0.594913899898529,
|
||||||
|
-0.714658200740814,-0.152911216020584,-0.152911216020584,8.62321627254444e-17,-0.594913899898529,0.594913899898529,8.62321627254444e-17,-0.152911216020584,0.714658200740814,0.152911230921745,-0.594913899898529,0.594913899898529,0.152911230921745,-0.152911216020584,0.714658200740814,0.152911230921745,0,0.714658200740814,0.594913899898529,0.152911216020584,0.594913899898529,0.152911230921745,0.152911216020584,0.714658200740814,8.62321627254444e-17,0.594913899898529,0.594913899898529,8.62321627254444e-17,0.152911216020584,0.714658200740814,-0.152911216020584,0.594913899898529,0.594913899898529,-0.152911216020584,0.152911216020584,0.714658200740814,8.62321627254444e-17,0.714658200740814,0.152911216020584,0.152911230921745,0.594913899898529,0.594913899898529,0.152911230921745,0.714658200740814,0.152911216020584,0.594913899898529,0.594913899898529,7.29137497046395e-08,0.152911230921745,0.714658200740814,7.29137497046395e-08,0.594913899898529,0.594913899898529,-0.152911216020584,0.152911230921745,0.714658200740814,-0.152911216020584,8.62321627254444e-17,0.594913899898529,-0.594913899898529,8.62321627254444e-17,0.714658200740814,-0.152911216020584,-0.152911216020584,0.594913899898529,-0.594913899898529,-0.152911216020584,0.714658200740814,-0.152911216020584,8.62321627254444e-17,0.152911216020584,-0.714658200740814,0.152911230921745,0.594913899898529,-0.594913899898529,0.152911230921745,0.152911216020584,-0.714658200740814,0.594913899898529,0,-0.594913899898529,0.152911230921745,0,-0.714658200740814,0.594913899898529,-0.152911216020584,-0.594913899898529,0.152911230921745,-0.152911216020584,-0.714658200740814,8.62321627254444e-17,-0.594913899898529,-0.594913899898529,8.62321627254444e-17,-0.152911216020584,-0.714658200740814,-0.152911216020584,-0.594913899898529,-0.594913899898529,-0.152911216020584,-0.152911216020584,-0.714658200740814,8.62321627254444e-17,-0.714658200740814,-0.152911216020584,0.152911230921745,-0.594913899898529,-0.594913899898529,0.152911230921745,-0.714658200740814,-0.152911216020584,0.594913899898529,-0.594913899898529,7.29137497046395e-08,
|
||||||
|
0.152911230921745,-0.714658200740814,7.29137497046395e-08,0.594913899898529,-0.594913899898529,0.152911216020584,0.152911230921745,-0.714658200740814,0.152911216020584,8.62321627254444e-17,-0.714658200740814,0.152911216020584,-0.152911216020584,-0.594913899898529,0.594913899898529,-0.152911216020584,-0.714658200740814,0.152911216020584,0.714658200740814,-0.152911216020584,7.29137497046395e-08,0.594913899898529,-0.594913899898529,-0.152911216020584,0.714658200740814,-0.152911216020584,-0.152911216020584,0.714658200740814,0,-0.152911216020584,0.594913899898529,0.152911216020584,-0.594913899898529,0.714658200740814,0.152911216020584,-0.152911216020584,0.714658200740814,0.152911216020584,7.29137497046395e-08,0.594913899898529,0.594913899898529,0.152911216020584,0.714658200740814,0.152911216020584,0.152911216020584,-0.714658200740814,-0.152911216020584,7.29137497046395e-08,-0.594913899898529,-0.594913899898529,0.152911216020584,-0.714658200740814,-0.152911216020584,0.152911216020584,-0.714658200740814,0,0.152911216020584,-0.594913899898529,0.152911216020584,0.594913899898529,-0.714658200740814,0.152911216020584,0.152911216020584,-0.714658200740814,0.152911216020584,7.29137497046395e-08,-0.594913899898529,0.594913899898529,-0.152911216020584,-0.714658200740814,0.152911216020584,-0.152911216020584,-0.541863918304443,-0.541864037513733,0.541863918304443,8.62321627254444e-17,0,0.714658200740814,-0.541863918304443,0.541863918304443,0.541863918304443,8.62321627254444e-17,0.714658200740814,7.29137497046395e-08,-0.541863918304443,0.541863918304443,-0.541863799095154,8.62321627254444e-17,0,-0.714658200740814,-0.541863918304443,-0.541864037513733,-0.541863799095154,8.62321627254444e-17,-0.714658200740814,7.29137497046395e-08,0.541863977909088,-0.541864037513733,0.541863918304443,0.714658200740814,0,7.29137497046395e-08,-0.714658200740814,0,7.29137497046395e-08,0.541863977909088,0.541863918304443,0.541863918304443,0.541863977909088,0.541863918304443,-0.541863799095154,0.541863977909088,-0.541864037513733,-0.541863799095154
|
||||||
|
}
|
||||||
|
PolygonVertexIndex: *768 {
|
||||||
|
a: 99,98,100,-102,103,102,104,-106,107,106,108,-110,111,110,112,-114,115,114,116,-118,118,106,119,-121,122,121,123,-125,125,114,126,-128,129,128,130,-132,132,128,133,-135,136,135,137,-139,140,139,141,-143,143,139,144,-146,147,146,148,-150,151,150,152,-154,154,150,155,-157,158,157,159,-161,161,121,162,-164,164,157,165,-167,167,146,168,-170,170,135,171,-173,173,110,174,-176,176,98,177,-179,179,102,180,-182,100,182,162,-102,162,121,122,-102,122,183,99,-102,104,184,130,-106,130,128,132,-106,132,185,103,-106,108,186,141,-110,141,139,143,-110,143,187,107,-110,112,188,152,-114,152,150,154,-114,154,189,111,-114,116,190,159,-118,159,157,164,-118,164,191,115,-118,119,188,112,-121,112,110,173,-121,173,192,118,-121,123,190,116,-125,116,114,125,-125,125,183,122,-125,126,193,133,-128,133,128,129,-128,129,183,125,-128,130,184,177,-132,177,98,99,-132,99,183,129,-132,133,193,171,-135,171,135,136,-135,136,185,132,-135,137,194,144,-139,144,139,140,-139,140,185,136,-139,141,186,180,-143,180,102,103,-143,103,185,140,-143,144,194,168,-146,168,146,147,-146,147,187,143,-146,148,195,155,-150,155,150,151,-150,151,187,147,-150,152,188,119,-154,119,106,107,-154,107,187,151,-154,155,195,165,-157,165,157,158,-157,158,189,154,-157,159,190,123,-161,123,121,161,-161,161,189,158,-161,162,182,174,-164,174,110,111,-164,111,189,161,-164,165,195,148,-167,148,146,167,-167,167,191,164,-167,168,194,137,-170,137,135,170,-170,170,191,167,-170,171,193,126,-173,126,114,115,-173,115,191,170,-173,174,182,100,-176,100,98,176,-176,176,192,173,-176,177,184,104,-179,104,102,179,-179,179,192,176,-179,180,186,108,-182,108,106,118,-182,118,192,179,-182,30,26,27,-13,35,31,32,-17,40,36,37,-21,45,41,42,-24,50,46,47,-11,54,51,52,-21,29,55,56,-10,57,58,59,-11,61,62,33,-12,34,64,60,-12,66,67,68,-15,70,71,38,-16,39,73,69,-16,75,76,77,-19,79,80,43,-20,44,81,78,-20,83,84,48,-23,85,86,28,-10,49,88,82,-23,89,90,74,-19,91,92,65,-15,53,93,87,-24,94,95,63,-13,96,97,72,-17,27,26,28,-1,28,26,29,-10,29,26,30,-9,32,31,33,-3,33,31,34,-12,34,31,35,-14,37,36,38,-5,38,36,39,
|
||||||
|
-16,39,36,40,-18,42,41,43,-7,43,41,44,-20,44,41,45,-22,47,46,48,-2,48,46,49,-23,49,46,50,-25,52,51,42,-7,42,51,53,-24,53,51,54,-26,56,55,47,-2,47,55,57,-11,57,55,29,-9,59,58,60,-4,60,58,61,-12,61,58,57,-9,33,62,63,-3,63,62,30,-13,30,62,61,-9,60,64,65,-4,65,64,66,-15,66,64,34,-14,68,67,69,-6,69,67,70,-16,70,67,66,-14,38,71,72,-5,72,71,35,-17,35,71,70,-14,69,73,74,-6,74,73,75,-19,75,73,39,-18,77,76,78,-8,78,76,79,-20,79,76,75,-18,43,80,52,-7,52,80,40,-21,40,80,79,-18,78,81,82,-8,82,81,83,-23,83,81,44,-22,48,84,56,-2,56,84,85,-10,85,84,83,-22,28,86,87,-1,87,86,45,-24,45,86,85,-22,82,88,77,-8,77,88,89,-19,89,88,49,-25,74,90,68,-6,68,90,91,-15,91,90,89,-25,65,92,59,-4,59,92,50,-11,50,92,91,-25,87,93,27,-1,27,93,94,-13,94,93,53,-26,63,95,32,-3,32,95,96,-17,96,95,94,-26,72,97,37,-5,37,97,54,-21,54,97,96,-26
|
||||||
|
}
|
||||||
|
Edges: *384 {
|
||||||
|
a: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,102,104,105,108,109,110,114,116,117,120,121,122,126,128,129,132,133,134,138,140,141,144,145,146,150,152,153,156,158,162,164,165,168,170,174,176,180,181,182,186,188,193,194,198,205,206,210,212,216,217,218,222,224,229,230,234,241,242,246,248,252,253,254,258,260,266,270,277,278,282,284,290,294,296,301,302,306,314,318,320,326,330,332,338,342,350,354,356,362,366,368,374,378,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,481,482,483,485,490,491,493,494,495,497,502,503,505,506,507,509,514,515,517,518,519,521,526,527,529,530,531,533,538,539,541,543,545,550,551,553,555,557,563,565,566,567,569,575,577,578,581,589,590,593,599,601,602,603,605,611,613,614,617,625,626,629,635,637,638,639,641,647,649,653,661,662,665,671,673,677,683,685,686,689,697,701,707,709,713,719,721,725,733,737,743,745,749,755,757,761
|
||||||
|
}
|
||||||
|
GeometryVersion: 124
|
||||||
|
LayerElementNormal: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Normals: *2304 {
|
||||||
|
a: -0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487185955048,0.965206921100616,0,-0.261487185955048,0.965206921100616,0,-0.261487185955048,0.965206921100616,0,-0.261487185955048,0.965206921100616,0,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487156152725,-0.965206921100616,0,-0.261487156152725,-0.965206921100616,0,-0.261487156152725,-0.965206921100616,0,-0.261487156152725,-0.965206921100616,0,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,0,-0.261487156152725,0.965206921100616,0,-0.261487156152725,0.965206921100616,0,-0.261487156152725,0.965206921100616,0,-0.261487156152725,0.965206921100616,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.965206921100616,0.261487156152725,0,0.965206921100616,0.261487156152725,0,0.965206921100616,0.261487156152725,0,0.965206921100616,0.261487156152725,0.261487156152725,0.965206921100616,0,0.261487156152725,0.965206921100616,0,0.261487156152725,0.965206921100616,0,0.261487156152725,0.965206921100616,0,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.261487156152725,-0.965206921100616,0,0.261487156152725,-0.965206921100616,0,0.261487156152725,-0.965206921100616,0,0.261487156152725,-0.965206921100616,0.261487126350403,0,-0.965206980705261,
|
||||||
|
0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.965206921100616,-0.261487156152725,0,-0.965206921100616,-0.261487156152725,0,-0.965206921100616,-0.261487156152725,0,-0.965206921100616,-0.261487156152725,0.261487185955048,-0.965206921100616,0,0.261487185955048,-0.965206921100616,0,0.261487185955048,-0.965206921100616,0,0.261487185955048,-0.965206921100616,0,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0.261487126350403,0.965206980705261,-0.261487066745758,0,0.965206980705261,-0.261487066745758,0,0.965206980705261,-0.261487066745758,0,0.965206980705261,-0.261487066745758,0,0.965206980705261,0,-0.261487185955048,0.965206980705261,0,-0.261487185955048,0.965206980705261,0,-0.261487185955048,0.965206980705261,0,-0.261487185955048,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0.261487066745758,0,-0.965206980705261,0.261487066745758,0,-0.965206980705261,0.261487066745758,0,-0.965206980705261,0.261487066745758,0,-0.211917281150818,-0.211917445063591,0.954034626483917,0,0,1,-0.211917281150818,-0.21191743016243,0.954034626483917,-0.211917266249657,-0.211917445063591,0.954034626483917,0,-0.261487185955048,0.965206980705261,0,-0.261487185955048,0.965206980705261,0,-0.261487185955048,0.965206980705261,0,-0.261487185955048,0.965206980705261,0,0,1,0,0,1,0,0,1,0,0,1,-0.211917445063591,0.954034626483917,0.211917281150818,
|
||||||
|
0,1,0,-0.211917445063591,0.954034626483917,0.211917281150818,-0.211917445063591,0.954034626483917,0.211917266249657,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,1,0,0,1,0,0,1,0,0,1,0,-0.211917594075203,0.211917579174042,-0.954034507274628,0,0,-1,-0.211917594075203,0.211917579174042,-0.954034507274628,-0.211917594075203,0.211917564272881,-0.954034507274628,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0.211917325854301,-0.954034626483917,-0.211917325854301,0,-1,0,-0.211917325854301,-0.954034686088562,-0.211917325854301,-0.211917355656624,-0.954034686088562,-0.211917355656624,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0.954034626483917,-0.211917251348495,0.21191731095314,1,0,0,0.954034626483917,-0.211917251348495,0.211917340755463,0.954034745693207,-0.211917266249657,0.211917325854301,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,1,0,0,1,0,0,1,0,0,1,0,0,-0.954034686088562,-0.211917355656624,-0.211917459964752,-1,0,0,-0.954034626483917,-0.211917325854301,-0.211917445063591,-0.954034686088562,-0.211917355656624,-0.211917474865913,-0.965206980705261,-0.261487066745758,0,-0.965206980705261,-0.261487066745758,0,-0.965206980705261,-0.261487066745758,0,-0.965206980705261,-0.261487066745758,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0.211917281150818,-0.211917400360107,0.954034626483917,0,0,1,0.211917266249657,-0.211917415261269,0.954034626483917,0.211917266249657,-0.211917415261269,0.954034626483917,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,0.261487126350403,0,0.965206980705261,
|
||||||
|
0,0,1,0,0,1,0,0,1,0,0,1,0.211917296051979,0.211917415261269,0.954034626483917,0,0,1,0.211917296051979,0.211917415261269,0.954034626483917,0.211917281150818,0.211917415261269,0.954034626483917,0,0.261487156152725,0.965206921100616,0,0.261487156152725,0.965206921100616,0,0.261487156152725,0.965206921100616,0,0.261487156152725,0.965206921100616,0,0,1,0,0,1,0,0,1,0,0,1,-0.211917281150818,0.211917445063591,0.954034626483917,0,0,1,-0.211917281150818,0.211917445063591,0.954034626483917,-0.211917266249657,0.211917445063591,0.954034626483917,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,-0.261487126350403,0,0.965206980705261,0,0,1,0,0,1,0,0,1,0,0,1,0.211917445063591,0.954034626483917,0.211917445063591,0,1,0,0.211917415261269,0.954034566879272,0.211917415261269,0.211917445063591,0.954034626483917,0.211917445063591,0.261487185955048,0.965206921100616,0,0.261487185955048,0.965206921100616,0,0.261487185955048,0.965206921100616,0,0.261487185955048,0.965206921100616,0,0,1,0,0,1,0,0,1,0,0,1,0,0.211917445063591,0.954034626483917,-0.211917489767075,0,1,0,0.21191743016243,0.954034566879272,-0.211917489767075,0.211917445063591,0.954034566879272,-0.211917474865913,0,0.965206921100616,-0.261487156152725,0,0.965206921100616,-0.261487156152725,0,0.965206921100616,-0.261487156152725,0,0.965206921100616,-0.261487156152725,0,1,0,0,1,0,0,1,0,0,1,0,-0.211917459964752,0.954034686088562,-0.211917340755463,0,1,0,-0.211917445063591,0.954034626483917,-0.21191731095314,-0.211917489767075,0.954034686088562,-0.211917355656624,-0.261487156152725,0.965206921100616,0,-0.261487156152725,0.965206921100616,0,-0.261487156152725,0.965206921100616,0,-0.261487156152725,0.965206921100616,0,0,1,0,0,1,0,0,1,0,0,1,0,0.211917608976364,0.211917579174042,-0.954034507274628,0,0,-1,0.211917608976364,0.211917564272881,-0.954034566879272,0.211917594075203,0.211917579174042,-0.954034507274628,0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,
|
||||||
|
0.261487126350403,0,-0.965206980705261,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0.211917579174042,-0.211917534470558,-0.954034507274628,0,0,-1,0.211917594075203,-0.211917549371719,-0.954034507274628,0.211917594075203,-0.211917519569397,-0.954034507274628,0,-0.261487156152725,-0.965206921100616,0,-0.261487156152725,-0.965206921100616,0,-0.261487156152725,-0.965206921100616,0,-0.261487156152725,-0.965206921100616,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0.211917594075203,-0.211917549371719,-0.954034507274628,0,0,-1,-0.211917579174042,-0.211917534470558,-0.954034566879272,-0.211917594075203,-0.211917519569397,-0.954034507274628,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,-0.261487126350403,0,-0.965206980705261,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0.211917340755463,-0.954034686088562,-0.211917519569397,0,-1,0,0.211917325854301,-0.954034626483917,-0.211917489767075,0.211917325854301,-0.954034686088562,-0.211917489767075,0.261487156152725,-0.965206921100616,0,0.261487156152725,-0.965206921100616,0,0.261487156152725,-0.965206921100616,0,0.261487156152725,-0.965206921100616,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0.211917281150818,-0.954034626483917,0.211917445063591,0,-1,0,0.211917296051979,-0.954034626483917,0.211917445063591,0.211917266249657,-0.954034626483917,0.211917445063591,0,-0.965206921100616,0.261487156152725,0,-0.965206921100616,0.261487156152725,0,-0.965206921100616,0.261487156152725,0,-0.965206921100616,0.261487156152725,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-0.211917296051979,-0.954034626483917,0.211917296051979,0,-1,0,-0.211917296051979,-0.954034626483917,0.211917296051979,-0.211917281150818,-0.954034686088562,0.211917281150818,-0.261487185955048,-0.965206921100616,0,-0.261487185955048,-0.965206921100616,0,-0.261487185955048,-0.965206921100616,0,-0.261487185955048,-0.965206921100616,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0.954034626483917,-0.211917325854301,-0.211917400360107,1,0,0,0.954034686088562,-0.211917340755463,-0.211917400360107,0.954034686088562,-0.211917355656624,-0.21191743016243,0.965206980705261,0,-0.261487185955048,
|
||||||
|
0.965206980705261,0,-0.261487185955048,0.965206980705261,0,-0.261487185955048,0.965206980705261,0,-0.261487185955048,1,0,0,1,0,0,1,0,0,1,0,0,0.954034686088562,0.211917370557785,-0.211917489767075,1,0,0,0.954034686088562,0.211917355656624,-0.211917445063591,0.954034626483917,0.211917355656624,-0.211917445063591,0.965206980705261,0.261487066745758,0,0.965206980705261,0.261487066745758,0,0.965206980705261,0.261487066745758,0,0.965206980705261,0.261487066745758,0,1,0,0,1,0,0,1,0,0,1,0,0,0.954034626483917,0.211917296051979,0.211917385458946,1,0,0,0.954034626483917,0.211917296051979,0.211917385458946,0.954034626483917,0.211917266249657,0.211917355656624,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,0.965206980705261,0,0.261487185955048,1,0,0,1,0,0,1,0,0,1,0,0,-0.954034626483917,-0.211917251348495,0.211917400360107,-1,0,0,-0.954034626483917,-0.211917266249657,0.211917400360107,-0.954034626483917,-0.211917251348495,0.211917400360107,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-0.965206980705261,0,0.261487185955048,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-0.954034626483917,0.211917281150818,0.211917445063591,-1,0,0,-0.954034626483917,0.211917281150818,0.211917445063591,-0.954034626483917,0.211917266249657,0.211917445063591,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-0.965206980705261,0.261487126350403,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-0.954034566879272,0.211917355656624,-0.211917519569397,-1,0,0,-0.954034686088562,0.211917370557785,-0.211917534470558,-0.954034626483917,0.211917355656624,-0.211917504668236,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,-0.965206980705261,0,-0.261487185955048,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,
|
||||||
|
1,0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,
|
||||||
|
-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0
|
||||||
|
}
|
||||||
|
NormalsW: *768 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementBinormal: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Binormals: *2304 {
|
||||||
|
a: 0,1,0,0,1,0,0,1,0,0,1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,-0,1,0,-0,1,0,-0,1,0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0.965207040309906,0.261487185955048,0,0.965207040309906,0.261487185955048,0,0.965207040309906,0.261487185955048,0,0.965207040309906,0.261487185955048,-0,1,0,-0,1,0,-0,1,0,-0,1,0,0,0.965206980705261,-0.261487185955048,0,0.965206980705261,-0.261487185955048,0,0.965206980705261,-0.261487185955048,0,0.965206980705261,-0.261487185955048,0,0.261487185955048,-0.965207040309906,0,0.261487185955048,-0.965207040309906,0,0.261487185955048,-0.965207040309906,0,0.261487185955048,-0.965207040309906,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-0.261487126350403,-0.965206980705261,0,-0.261487126350403,-0.965206980705261,0,-0.261487126350403,-0.965206980705261,0,-0.261487126350403,-0.965206980705261,0,-0.965207040309906,-0.261487185955048,0,-0.965207040309906,-0.261487185955048,0,-0.965207040309906,-0.261487185955048,0,-0.965207040309906,-0.261487185955048,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-0.965206980705261,0.261487185955048,0,-0.965206980705261,0.261487185955048,0,-0.965206980705261,0.261487185955048,0,-0.965206980705261,0.261487185955048,0,-0.261487185955048,0.965207040309906,0,-0.261487185955048,0.965207040309906,0,-0.261487185955048,0.965207040309906,0,-0.261487185955048,0.965207040309906,0,0,1,0,0,1,0,0,1,0,0,1,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0.261487066745758,0.965206980705261,0,0.261487066745758,0.965206980705261,0,0.261487066745758,0.965206980705261,0,0.261487066745758,0.965206980705261,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,0,1,0,0,1,0,0,1,0,
|
||||||
|
0,1,0,0.261487066745758,0.965206980705261,0,0.261487066745758,0.965206980705261,0,0.261487066745758,0.965206980705261,0,0.261487066745758,0.965206980705261,0,-0.0554696954786777,0.977241098880768,0.204750895500183,0.0677256807684898,0.997704029083252,-0,0.0995207726955414,0.966452240943909,0.236782029271126,0.022095151245594,0.974918127059937,0.221464186906815,0,0.965206980705261,0.261487185955048,0,0.965206980705261,0.261487185955048,0,0.965206980705261,0.261487185955048,0,0.965206980705261,0.261487185955048,0,1,-0,0,1,-0,0,1,-0,0,1,-0,-0.0554696545004845,0.204750746488571,-0.977241158485413,0.0677258297801018,0,-0.997703969478607,0.0995210781693459,0.23678195476532,-0.966452240943909,0.0220953319221735,0.221464082598686,-0.974918246269226,0,0.261487126350403,-0.965206980705261,0,0.261487126350403,-0.965206980705261,0,0.261487126350403,-0.965206980705261,0,0.261487126350403,-0.965206980705261,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0.055469736456871,-0.977241158485413,-0.204751059412956,0.0677258297801018,-0.997703969478607,0,0.0995209664106369,-0.966452121734619,-0.236782252788544,0.0220952294766903,-0.974918127059937,-0.221464350819588,0,-0.965206980705261,-0.261487185955048,0,-0.965206980705261,-0.261487185955048,0,-0.965206980705261,-0.261487185955048,0,-0.965206980705261,-0.261487185955048,0,-1,-0,0,-1,-0,0,-1,-0,0,-1,-0,-0.0554696694016457,-0.204750820994377,0.977241218090057,0.0677259787917137,0,0.997703969478607,0.0995214134454727,-0.236782014369965,0.966452121734619,0.0220954976975918,-0.221464157104492,0.974918186664581,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,0,1,0,0,1,0,0,1,0,0,1,0.204750746488571,0.977241218090057,0.0554696507751942,0,0.997704029083252,-0.0677256807684898,0.236781880259514,0.966452300548553,-0.0995208472013474,0.221463993191719,0.974918186664581,-0.0220952127128839,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,
|
||||||
|
-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0.204750791192055,0.977241098880768,-0.0554696619510651,0,0.997704029083252,0.0677257031202316,-0.236781939864159,0.966452240943909,0.099520817399025,-0.221464112401009,0.974918246269226,0.022095188498497,-0.261487066745758,0.965206980705261,0,-0.261487066745758,0.965206980705261,0,-0.261487066745758,0.965206980705261,0,-0.261487066745758,0.965206980705261,0,0,1,0,0,1,0,0,1,0,0,1,0,-0.099520780146122,0.966452240943909,0.236781999468803,-0.0677256733179092,0.997704029083252,0,0.0554696880280972,0.977241098880768,0.204750865697861,-0.022095151245594,0.974918127059937,0.221464157104492,-0,1,0,-0,1,0,-0,1,0,-0,1,0,0,1,-0,0,1,-0,0,1,-0,0,1,-0,-0.0554696880280972,0.977241098880768,-0.204750865697861,0.0677258223295212,0.997703969478607,-0,0.0995210558176041,0.966452181339264,-0.236782059073448,0.0220952890813351,0.974918246269226,-0.221464201807976,0,0.965207040309906,-0.261487185955048,0,0.965207040309906,-0.261487185955048,0,0.965207040309906,-0.261487185955048,0,0.965207040309906,-0.261487185955048,0,1,-0,0,1,-0,0,1,-0,0,1,-0,-0.0995210707187653,0.966452240943909,-0.236782118678093,-0.0677258297801018,0.997703969478607,0,0.0554696954786777,0.977241098880768,-0.204750895500183,-0.0220952928066254,0.974918186664581,-0.221464231610298,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,-0,0,1,-0,0,1,-0,-0.0995210558176041,0.236782118678093,-0.966452240943909,-0.0677258223295212,0,-0.997703969478607,0.0554696917533875,0.204750880599022,-0.977241098880768,-0.0220952853560448,0.221464216709137,-0.974918127059937,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0.0554697066545486,-0.204750955104828,-0.977241158485413,0.0677259713411331,0,-0.997703969478607,0.0995213314890862,-0.236782237887383,-0.966452181339264,0.0220954213291407,-0.221464306116104,-0.974918186664581,0,-0.261487185955048,-0.965207040309906,0,-0.261487185955048,-0.965207040309906,0,-0.261487185955048,-0.965207040309906,0,-0.261487185955048,-0.965207040309906,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0.0995213687419891,-0.236782059073448,-0.966452181339264,
|
||||||
|
-0.0677259787917137,0,-0.997703969478607,0.0554696545004845,-0.204750776290894,-0.977241158485413,-0.0220954604446888,-0.221464172005653,-0.974918246269226,0,0,-1,0,0,-1,-0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0.0995209515094757,-0.966452121734619,-0.236782252788544,-0.0677258223295212,-0.997703969478607,-0,0.0554697290062904,-0.977241098880768,-0.204751014709473,-0.0220952183008194,-0.974918127059937,-0.221464365720749,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0,0,-1,-0,0,-1,-0,0,-1,-0,-0.0554697290062904,-0.977241158485413,0.204751014709473,0.0677256733179092,-0.997704029083252,0,0.099520668387413,-0.966452181339264,0.236782178282738,0.022095087915659,-0.974918127059937,0.221464276313782,0,-0.965207040309906,0.261487185955048,0,-0.965207040309906,0.261487185955048,0,-0.965207040309906,0.261487185955048,0,-0.965207040309906,0.261487185955048,0,-1,0,0,-1,0,0,-1,-0,0,-1,0,-0.0995206907391548,-0.966452181339264,0.236782178282738,-0.0677256807684898,-0.997704029083252,-0,0.0554697178304195,-0.977241098880768,0.20475098490715,-0.0220951028168201,-0.974918127059937,0.221464276313782,0,-1,-0,0,-1,-0,-0,-1,0,0,-1,-0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-0.0995213836431503,-0.23678220808506,0.966452121734619,-0.0677259713411331,0,0.997703969478607,0.0554697066545486,-0.204750940203667,0.977241098880768,-0.0220954623073339,-0.221464291214943,0.974918186664581,-0,0,1,-0,0,1,-0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0.0554696954786777,0.204750895500183,0.977241098880768,0.0677258223295212,0,0.997703969478607,0.0995211154222488,0.236782103776932,0.966452181339264,0.0220953226089478,0.221464246511459,0.974918186664581,0,0.261487185955048,0.965207040309906,0,0.261487185955048,0.965207040309906,0,0.261487185955048,0.965207040309906,0,0.261487185955048,0.965207040309906,0,0,1,0,0,1,0,0,1,0,0,1,-0.0995211601257324,0.23678195476532,0.966452181339264,-0.0677258297801018,0,0.997703969478607,0.0554696619510651,0.204750776290894,0.977241218090057,-0.022095363587141,0.221464082598686,0.974918246269226,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0.236781939864159,0.966452240943909,0.0995208621025085,
|
||||||
|
-0,0.997704029083252,0.0677257031202316,0.204750806093216,0.977241158485413,-0.0554696656763554,0.221464112401009,0.974918186664581,0.0220951996743679,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0.204750806093216,0.977241098880768,0.0554696694016457,0,0.997703969478607,-0.0677258521318436,-0.236782044172287,0.966452240943909,-0.0995211452245712,-0.221464172005653,0.974918246269226,-0.0220953542739153,-0.261487066745758,0.965206980705261,0,-0.261487066745758,0.965206980705261,0,-0.261487066745758,0.965206980705261,0,-0.261487066745758,0.965206980705261,0,0,1,-0,-0,1,0,-0,1,0,-0,1,0,-0.236781984567642,0.966452300548553,0.09952113032341,-0,0.997703969478607,0.0677258297801018,-0.204750761389732,0.977241158485413,-0.0554696582257748,-0.221464067697525,0.974918246269226,0.022095350548625,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,0,1,-0,-0,1,0,-0.236781880259514,0.966452360153198,-0.0995208248496056,0,0.997704029083252,-0.0677256807684898,-0.20475073158741,0.977241158485413,0.0554696470499039,-0.221464022994041,0.974918246269226,-0.0220951903611422,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0.204750746488571,0.977241158485413,-0.0554696545004845,0,0.997703969478607,0.0677258297801018,0.23678195476532,0.966452240943909,0.0995210781693459,0.221464082598686,0.974918246269226,0.0220953319221735,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0,1,0,0,1,0,0,1,0,0,1,0,0.236782059073448,0.966452240943909,-0.0995211154222488,0,0.997703969478607,-0.0677258521318436,0.204750806093216,0.977241098880768,0.0554696656763554,0.221464142203331,0.974918186664581,-0.0220953188836575,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-1,0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,0,-0,-1,0,-0,-1,
|
||||||
|
0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-1,-0,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,
|
||||||
|
-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0
|
||||||
|
}
|
||||||
|
BinormalsW: *768 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LayerElementTangent: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Tangents: *2304 {
|
||||||
|
a: 0.965206980705261,-0,0.261487126350403,0.965206980705261,-0,0.261487126350403,0.965206980705261,-0,0.261487126350403,0.965206980705261,-0,0.261487126350403,0.965207040309906,0.26148721575737,0,0.965207040309906,0.26148721575737,0,0.965207040309906,0.26148721575737,0,0.965207040309906,0.26148721575737,0,0.965206980705261,-0,-0.261487126350403,0.965206980705261,-0,-0.261487126350403,0.965206980705261,-0,-0.261487126350403,0.965206980705261,-0,-0.261487126350403,0.965206980705261,-0.261487156152725,-0,0.965206980705261,-0.261487156152725,-0,0.965206980705261,-0.261487156152725,-0,0.965206980705261,-0.261487156152725,-0,0.26148721575737,0,-0.965207040309906,0.26148721575737,0,-0.965207040309906,0.26148721575737,0,-0.965207040309906,0.26148721575737,0,-0.965207040309906,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,0.965207040309906,1,0,-0,1,0,-0,1,0,-0,1,0,-0,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,0,1,-0,0,1,-0,-0,1,-0,0,0.965206980705261,-0.261487156152725,0,0.965206980705261,-0.261487156152725,0,0.965206980705261,-0.261487156152725,0,0.965206980705261,-0.261487156152725,0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,1,0,0,1,0,0,1,-0,0,1,0,0,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0.965207040309906,0.26148721575737,-0,0.965207040309906,0.26148721575737,-0,0.965207040309906,0.26148721575737,-0,0.965207040309906,0.26148721575737,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,-0,0,-1,-0,0,-1,-0,0,-1,-0,0,-1,-0.26148721575737,-0,-0.965207040309906,-0.26148721575737,-0,-0.965207040309906,-0.26148721575737,-0,-0.965207040309906,-0.26148721575737,-0,-0.965207040309906,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0.26148721575737,-0,0.965207040309906,
|
||||||
|
0.26148721575737,-0,0.965207040309906,0.26148721575737,-0,0.965207040309906,0.26148721575737,-0,0.965207040309906,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0.97571212053299,0.00952975451946259,0.218849271535873,0.997704029083252,-0.0677256807684898,0,0.972207129001617,-0.145124465227127,0.183717742562294,0.977037787437439,-0.0680116266012192,0.201919630169868,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,0.97571212053299,0.218849420547485,-0.0095297135412693,0.997703969478607,0,0.0677258297801018,0.972207069396973,0.183717846870422,0.145124778151512,0.977037727832794,0.20191977918148,0.0680118054151535,1,-0,0,1,-0,0,1,-0,0,1,-0,0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,0.975712060928345,-0.00952968932688236,-0.21884959936142,0.997703969478607,0.0677258297801018,0,0.972207009792328,0.145124763250351,-0.183717966079712,0.977037727832794,0.0680118054151535,-0.201919928193092,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,0.97571212053299,-0.218849316239357,0.00952973961830139,0.997703969478607,0,-0.0677259787917137,0.972207069396973,-0.183717638254166,-0.145125105977058,0.977037727832794,-0.201919630169868,-0.068011961877346,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,0.218849301338196,0.00952973961830139,-0.97571212053299,0,-0.0677256807684898,-0.997704029083252,0.1837178170681,-0.145124509930611,-0.972207069396973,0.201919689774513,-0.0680116564035416,-0.977037787437439,-0,0,-1,-0,0,-1,-0,0,-1,-0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0.218849420547485,0.0095297172665596,0.97571212053299,0,-0.0677257031202316,0.997704029083252,-0.183717906475067,-0.145124524831772,0.972207069396973,-0.201919823884964,-0.068011686205864,0.977037727832794,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0.972207129001617,0.145124465227127,-0.183717742562294,0.997704029083252,0.0677256733179092,0,0.97571212053299,-0.00952975824475288,-0.218849256634712,0.977037787437439,0.0680116191506386,-0.201919630169868,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,
|
||||||
|
1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,0.97571212053299,0.00952975172549486,-0.218849286437035,0.997703969478607,-0.0677258223295212,0,0.972207069396973,-0.14512474834919,-0.183717682957649,0.977037847042084,-0.0680117681622505,-0.20191964507103,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,0,1,-0,0,1,-0,-0,1,-0,0,0.972207069396973,0.14512474834919,0.183717668056488,0.997703969478607,0.0677258297801018,0,0.97571212053299,-0.00952975451946259,0.218849271535873,0.977037847042084,0.0680117756128311,0.201919630169868,0.965206980705261,-0,0.261487126350403,0.965206980705261,-0,0.261487126350403,0.965206980705261,-0,0.261487126350403,0.965206980705261,-0,0.261487126350403,1,-0,-0,1,-0,0,1,-0,0,1,-0,0,0.972207069396973,-0.183717831969261,-0.145124778151512,0.997703969478607,0,-0.0677258223295212,0.97571212053299,-0.218849420547485,0.00952972378581762,0.977037727832794,-0.20191977918148,-0.0680117979645729,0.965207040309906,-0.26148721575737,-0,0.965207040309906,-0.26148721575737,-0,0.965207040309906,-0.26148721575737,-0,0.965207040309906,-0.26148721575737,-0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,0.97571212053299,-0.218849420547485,-0.0095297247171402,0.997703969478607,0,0.0677259713411331,0.972207009792328,-0.183717742562294,0.145125061273575,0.977037727832794,-0.201919749379158,0.0680119395256042,1,-0,0,1,-0,0,1,-0,0,1,-0,0,1,0,0,1,0,0,1,-0,-0,1,0,0,0.972207009792328,0.183717772364616,-0.145125061273575,0.997703969478607,0,-0.0677259787917137,0.97571212053299,0.218849420547485,0.00952971447259188,0.977037727832794,0.20191977918148,-0.0680119544267654,0.965206980705261,0.261487156152725,0,0.965206980705261,0.261487156152725,0,0.965206980705261,0.261487156152725,-0,0.965206980705261,0.261487156152725,0,1,-0,0,1,0,0,1,0,0,1,0,0,0.972207009792328,-0.14512474834919,0.183717995882034,0.997703969478607,-0.0677258223295212,0,0.975712060928345,0.00952969118952751,0.218849584460258,0.977037727832794,-0.0680117979645729,0.201919928193092,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,0.965206980705261,0,0.261487126350403,
|
||||||
|
1,-0,0,1,-0,0,1,-0,0,1,-0,0,0.975712060928345,-0.00952969212085009,0.218849584460258,0.997704029083252,0.0677256733179092,0,0.972207069396973,0.145124465227127,0.183718055486679,0.977037727832794,0.0680116564035416,0.201919972896576,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,0.972207069396973,-0.145124480128288,-0.183718040585518,0.997704029083252,-0.0677256807684898,0,0.975712060928345,0.00952969398349524,-0.218849569559097,0.977037727832794,-0.0680116713047028,-0.201919972896576,0.965206980705261,0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,0.965206980705261,-0,-0.261487126350403,0.965206980705261,0,-0.261487126350403,1,0,0,1,0,0,1,0,0,1,0,0,0.972207069396973,0.183717623353004,0.145125105977058,0.997703969478607,0,0.0677259713411331,0.97571212053299,0.218849316239357,-0.00952974893152714,0.977037847042084,0.201919630169868,0.0680119544267654,0.965206980705261,0.261487156152725,0,0.965206980705261,0.261487156152725,0,0.965206980705261,0.261487156152725,0,0.965206980705261,0.261487156152725,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,0.97571212053299,0.218849271535873,0.00952975638210773,0.997703969478607,0,-0.0677258223295212,0.972207069396973,0.183717668056488,-0.145124807953835,0.977037847042084,0.201919630169868,-0.0680118054151535,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,0.972207069396973,-0.183717682957649,0.145124822854996,0.997703969478607,0,0.0677258297801018,0.97571212053299,-0.218849286437035,-0.00952974427491426,0.977037847042084,-0.201919630169868,0.0680118054151535,0.965207040309906,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,-0.183717846870422,0.145124554634094,-0.972207069396973,0,0.0677257031202316,-0.997704029083252,-0.218849360942841,-0.0095297284424305,-0.97571212053299,-0.20191977918148,0.068011686205864,-0.977037727832794,-0.26148721575737,-0,-0.965207040309906,-0.26148721575737,-0,-0.965207040309906,-0.26148721575737,-0,-0.965207040309906,-0.26148721575737,-0,-0.965207040309906,
|
||||||
|
0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0.218849450349808,0.00952971167862415,-0.97571212053299,0,-0.0677258521318436,-0.997703969478607,-0.1837178170681,-0.145124852657318,-0.972207069396973,-0.201919764280319,-0.0680118426680565,-0.977037727832794,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-0,-1,0,0,-1,0,0,-1,0,0,-1,0.183717772364616,0.145124807953835,-0.972207069396973,0,0.0677258297801018,-0.997703969478607,0.218849375844002,-0.00952972657978535,-0.97571212053299,0.201919689774513,0.0680118054151535,-0.977037727832794,0.26148721575737,0,-0.965207040309906,0.26148721575737,0,-0.965207040309906,0.26148721575737,0,-0.965207040309906,0.26148721575737,0,-0.965207040309906,0,0,-1,0,0,-1,0,-0,-1,0,0,-1,0.183717876672745,0.145124495029449,0.972207069396973,0,0.0677256807684898,0.997704029083252,0.218849375844002,-0.00952972192317247,0.97571212053299,0.20191977918148,0.0680116564035416,0.977037727832794,0.26148721575737,-0,0.965207040309906,0.26148721575737,-0,0.965207040309906,0.26148721575737,-0,0.965207040309906,0.26148721575737,-0,0.965207040309906,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0.218849420547485,0.0095297135412693,0.97571212053299,0,-0.0677258297801018,0.997703969478607,0.183717846870422,-0.145124778151512,0.972207069396973,0.20191977918148,-0.0680118054151535,0.977037727832794,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,-0.183717906475067,0.145124837756157,0.972207009792328,0,0.0677258521318436,0.997703969478607,-0.21884948015213,-0.00952970236539841,0.97571212053299,-0.201919838786125,0.0680118277668953,0.977037727832794,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,0.965207040309906,-0.26148721575737,0,0.965207040309906,0,-0,1,0,-0,1,0,-0,1,0,-0,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,0,1,0,0,1,0,0,1,-0,-0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,
|
||||||
|
1,0,0,1,0,0,1,-0,0,1,-0,0,1,-0,-0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,-0,0,1,-0,-0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,-0,0,1,-0,-0,1,-0,0,1,-0,-0,1,0,0,1,0,0,1,0,0,1,-0,0,1,-0,0,1,-0,-0,1,-0,0,1,-0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,
|
||||||
|
0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1
|
||||||
|
}
|
||||||
|
TangentsW: *768 {
|
||||||
|
a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementUV: 0 {
|
||||||
|
Version: 101
|
||||||
|
Name: "map1"
|
||||||
|
MappingInformationType: "ByPolygonVertex"
|
||||||
|
ReferenceInformationType: "IndexToDirect"
|
||||||
|
UV: *542 {
|
||||||
|
a: 0.375,0,0.625,0,0.375,0.25,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.625,1,0.875,0,0.875,0.25,0.125,0,0.125,0.25,0.5,0.125,0.5,0,0.5,1,0.625,0.125,0.5,0.25,0.375,0.125,0.5,0.375,0.625,0.375,0.75,0.25,0.5,0.5,0.375,0.375,0.25,0.25,0.5,0.625,0.625,0.625,0.875,0.125,0.5,0.75,0.375,0.625,0.125,0.125,0.5,0.875,0.625,0.875,0.75,0,0.5,1,0.375,0.875,0.25,0,0.75,0.125,0.75,0,0.875,0.125,0.75,0.25,0.25,0.125,0.25,0,0.25,0.25,0.125,0.125,0.4375,0.0625,0.375,0.0625,0.4375,0,0.4375,1,0.5,0.0625,0.4375,0.125,0.4375,0.3125,0.375,0.3125,0.3125,0.25,0.4375,0.25,0.5,0.3125,0.4375,0.375,0.4375,0.5625,0.375,0.5625,0.125,0.1875,0.4375,0.5,0.5,0.5625,0.4375,0.625,0.4375,0.8125,0.375,0.8125,0.1875,0,0.4375,0.75,0.5,0.8125,0.4375,0.875,0.6875,0.0625,0.625,0.0625,0.625,0.9375,0.6875,0,0.75,0.0625,0.6875,0.125,0.1875,0.0625,0.375,0.6875,0.125,0.0625,0.1875,0,0.25,0.0625,0.1875,0.125,0.5625,0.0625,0.5625,0,0.5625,1,0.5625,0.125,0.5625,0.1875,0.625,0.1875,0.5625,0.25,0.5,0.1875,0.4375,0.1875,0.375,0.1875,0.5625,0.3125,0.625,0.3125,0.6875,0.25,0.5625,0.375,0.5625,0.4375,0.625,0.4375,0.8125,0.25,0.5625,0.5,0.5,0.4375,0.4375,0.4375,0.375,0.4375,0.1875,0.25,0.5625,0.5625,0.625,0.5625,0.875,0.1875,0.5625,0.625,0.5625,0.6875,0.625,0.6875,0.875,0.0625,0.5625,0.75,0.5,0.6875,0.4375,0.6875,0.375,0.6875,0.5625,0.8125,0.625,0.8125,0.8125,0,0.5625,0.875,0.5625,0.9375,0.625,0.9375,0.5625,1,0.5,0.9375,0.4375,0.9375,0.4375,1,0.375,0.9375,0.3125,0,0.8125,0.0625,0.8125,0,0.875,0.0625,0.8125,0.125,0.8125,0.1875,0.875,0.1875,0.8125,0.25,0.75,0.1875,0.6875,0.1875,0.6875,0.25,0.3125,0.0625,0.3125,0,0.3125,0.125,0.3125,0.1875,0.3125,0.25,0.25,0.1875,0.1875,0.1875,0.1875,0.25,0.125,0.1875,0.4375,0.125,0.375,0.125,0.375,0.0625,0.4375,0.0625,0.4375,0.375,0.375,0.375,0.375,0.3125,0.4375,0.3125,0.4375,0.625,0.375,0.625,0.375,0.5625,0.4375,0.5625,0.4375,0.875,0.375,0.875,0.375,0.8125,0.4375,0.8125,0.6875,0.125,0.625,0.125,0.625,0.0625,0.6875,0.0625,0.1875,0.125,0.125,0.125,0.125,0.0625,0.1875,0.0625,0.5,0.0625,0.5,0,0.5625,0,
|
||||||
|
0.5625,0.0625,0.5625,0.125,0.625,0.1875,0.5625,0.1875,0.5,0.1875,0.5,0.25,0.4375,0.25,0.4375,0.1875,0.5,0.3125,0.5625,0.25,0.5625,0.3125,0.5625,0.375,0.625,0.375,0.625,0.4375,0.5625,0.4375,0.5,0.4375,0.5,0.5,0.4375,0.5,0.4375,0.4375,0.5,0.5625,0.5625,0.5,0.5625,0.5625,0.5625,0.625,0.625,0.625,0.625,0.6875,0.5625,0.6875,0.5,0.6875,0.5,0.75,0.4375,0.75,0.4375,0.6875,0.5,0.8125,0.5625,0.75,0.5625,0.8125,0.5625,0.875,0.625,0.875,0.625,0.9375,0.5625,0.9375,0.5,0.9375,0.5,1,0.4375,1,0.4375,0.9375,0.75,0.0625,0.75,0,0.8125,0,0.8125,0.0625,0.8125,0.125,0.875,0.125,0.875,0.1875,0.8125,0.1875,0.75,0.1875,0.75,0.25,0.6875,0.25,0.6875,0.1875,0.25,0.0625,0.25,0,0.3125,0,0.3125,0.0625,0.3125,0.125,0.375,0.1875,0.3125,0.1875,0.25,0.1875,0.25,0.25,0.1875,0.25,0.1875,0.1875,0.375,0,0.4375,0,0.5,0.125,0.375,0.25,0.5,0.375,0.375,0.5,0.5,0.625,0.375,0.75,0.5,0.875,0.625,0,0.6875,0,0.75,0.125,0.125,0,0.1875,0,0.25,0.125,0.625,0.25,0.625,0.3125,0.625,0.5,0.375,0.4375,0.625,0.5625,0.625,0.75,0.375,0.6875,0.625,0.8125,0.625,1,0.5625,1,0.375,1,0.375,0.9375,0.875,0,0.875,0.0625,0.875,0.25,0.8125,0.25,0.3125,0.25,0.125,0.25,0.125,0.1875
|
||||||
|
}
|
||||||
|
UVIndex: *768 {
|
||||||
|
a: 51,19,47,46,57,24,53,52,63,30,59,58,69,36,65,64,75,17,71,70,81,45,78,76,50,15,83,82,85,17,87,86,89,18,55,90,56,18,88,92,95,21,97,96,100,23,61,101,62,23,99,104,107,27,109,108,112,29,67,113,68,29,111,115,118,33,120,119,122,35,124,123,74,39,128,127,130,40,132,131,134,41,136,135,80,43,138,137,139,19,91,140,142,44,144,143,47,0,48,46,48,15,50,46,50,14,51,46,53,2,55,52,55,18,56,52,56,20,57,52,59,4,61,58,61,23,62,58,62,26,63,58,65,6,67,64,67,29,68,64,68,32,69,64,71,1,73,70,73,39,74,70,74,38,75,70,78,12,79,76,79,43,80,76,80,42,81,76,83,1,71,82,71,17,85,82,85,14,50,82,87,3,88,86,88,18,89,86,89,14,85,86,55,2,91,90,91,19,51,90,51,14,89,90,88,3,93,92,93,21,95,92,95,20,56,92,97,5,99,96,99,23,100,96,100,20,95,96,61,4,102,101,102,24,57,101,57,20,100,101,99,5,105,104,105,27,107,104,107,26,62,104,109,7,111,108,111,29,112,108,112,26,107,108,67,6,114,113,114,30,63,113,63,26,112,113,111,7,116,115,116,33,118,115,118,32,68,115,120,9,121,119,121,35,122,119,122,32,118,119,124,8,125,123,125,36,69,123,69,32,122,123,128,10,129,127,129,40,130,127,130,38,74,127,132,11,133,131,133,41,134,131,134,38,130,131,136,3,87,135,87,17,75,135,75,38,134,135,138,0,47,137,47,19,139,137,139,42,80,137,91,2,141,140,141,44,142,140,142,42,139,140,144,13,145,143,145,45,81,143,81,42,142,143,146,149,148,147,150,153,152,151,154,157,156,155,158,161,160,159,162,165,164,163,166,169,168,167,170,173,172,171,174,176,175,163,177,180,179,178,181,183,182,178,184,187,186,185,188,191,190,189,192,194,193,189,195,198,197,196,199,202,201,200,203,205,204,200,206,209,208,207,210,213,212,211,214,217,216,215,218,221,220,219,222,225,224,223,226,229,228,227,230,232,231,147,233,236,235,234,148,149,238,237,238,149,170,171,170,149,146,239,152,153,179,240,179,153,181,178,181,153,150,241,156,157,190,242,190,157,192,189,192,157,154,243,160,161,201,244,201,161,203,200,203,161,158,245,164,165,247,246,247,165,214,215,214,165,162,248,168,169,250,249,250,169,226,227,226,169,166,251,172,173,164,246,164,173,174,163,174,173,170,239,175,176,182,252,182,176,177,178,177,176,174,239,
|
||||||
|
179,180,231,240,231,180,146,147,146,180,177,239,182,183,253,252,253,183,184,185,184,183,181,241,186,187,193,254,193,187,188,189,188,187,184,241,190,191,255,242,255,191,150,151,150,191,188,241,193,194,256,254,256,194,195,196,195,194,192,243,197,198,204,257,204,198,199,200,199,198,195,243,201,202,258,244,258,202,154,155,154,202,199,243,204,205,259,257,259,205,206,207,206,205,203,245,208,209,261,260,261,209,210,211,210,209,206,245,212,213,263,262,263,213,158,159,158,213,210,245,216,217,265,264,265,217,218,219,218,217,214,248,220,221,267,266,267,221,222,223,222,221,218,248,224,225,175,252,175,225,162,163,162,225,222,248,228,229,148,237,148,229,230,147,230,229,226,251,231,232,268,240,268,232,233,234,233,232,230,251,235,236,270,269,270,236,166,167,166,236,233,251
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementSmoothing: 0 {
|
||||||
|
Version: 102
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "ByEdge"
|
||||||
|
ReferenceInformationType: "Direct"
|
||||||
|
Smoothing: *384 {
|
||||||
|
a: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LayerElementMaterial: 0 {
|
||||||
|
Version: 101
|
||||||
|
Name: ""
|
||||||
|
MappingInformationType: "AllSame"
|
||||||
|
ReferenceInformationType: "IndexToDirect"
|
||||||
|
Materials: *1 {
|
||||||
|
a: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Layer: 0 {
|
||||||
|
Version: 100
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementNormal"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementBinormal"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementTangent"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementMaterial"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementSmoothing"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
LayerElement: {
|
||||||
|
Type: "LayerElementUV"
|
||||||
|
TypedIndex: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Model: 1827098352032, "Model::Cube2", "Mesh" {
|
||||||
|
Version: 232
|
||||||
|
Properties70: {
|
||||||
|
P: "RotationActive", "bool", "", "",1
|
||||||
|
P: "InheritType", "enum", "", "",1
|
||||||
|
P: "ScalingMax", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "DefaultAttributeIndex", "int", "Integer", "",0
|
||||||
|
P: "Lcl Translation", "Lcl Translation", "", "A",-0.0104023897647858,0.00998288810253143,-0.0104375958442688
|
||||||
|
P: "Lcl Scaling", "Lcl Scaling", "", "A",0.1,-0.1,0.1
|
||||||
|
P: "currentUVSet", "KString", "", "U", "map1"
|
||||||
|
}
|
||||||
|
Shading: T
|
||||||
|
Culling: "CullingOff"
|
||||||
|
}
|
||||||
|
Model: 1827098379872, "Model::Cube1", "Mesh" {
|
||||||
|
Version: 232
|
||||||
|
Properties70: {
|
||||||
|
P: "RotationActive", "bool", "", "",1
|
||||||
|
P: "InheritType", "enum", "", "",1
|
||||||
|
P: "ScalingMax", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "DefaultAttributeIndex", "int", "Integer", "",0
|
||||||
|
P: "Lcl Translation", "Lcl Translation", "", "A",1.04023897647858,-0.998288810253143,1.04375958442688
|
||||||
|
P: "currentUVSet", "KString", "", "U", "map1"
|
||||||
|
}
|
||||||
|
Shading: T
|
||||||
|
Culling: "CullingOff"
|
||||||
|
}
|
||||||
|
Model: 1827098382192, "Model::Cube3", "Mesh" {
|
||||||
|
Version: 232
|
||||||
|
Properties70: {
|
||||||
|
P: "RotationActive", "bool", "", "",1
|
||||||
|
P: "InheritType", "enum", "", "",1
|
||||||
|
P: "ScalingMax", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "DefaultAttributeIndex", "int", "Integer", "",0
|
||||||
|
P: "Lcl Translation", "Lcl Translation", "", "A",-0.0106711769104004,0.00998288810253143,0.0939023494720459
|
||||||
|
P: "Lcl Scaling", "Lcl Scaling", "", "A",0.1,0.1,0.1
|
||||||
|
P: "currentUVSet", "KString", "", "U", "map1"
|
||||||
|
}
|
||||||
|
Shading: T
|
||||||
|
Culling: "CullingOff"
|
||||||
|
}
|
||||||
|
Model: 1827098384512, "Model::Cube1", "Mesh" {
|
||||||
|
Version: 232
|
||||||
|
Properties70: {
|
||||||
|
P: "RotationPivot", "Vector3D", "Vector", "",0.0,0.0019,0.0
|
||||||
|
P: "ScalingOffset", "Vector3D", "Vector", "",0.0,0.0019,0.0
|
||||||
|
P: "ScalingPivot", "Vector3D", "Vector", "",0.0,0.0019,0.0
|
||||||
|
P: "RotationActive", "bool", "", "",1
|
||||||
|
P: "InheritType", "enum", "", "",1
|
||||||
|
P: "ScalingMax", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "DefaultAttributeIndex", "int", "Integer", "",0
|
||||||
|
P: "Lcl Translation", "Lcl Translation", "", "A",0.0,0.0019,0.0
|
||||||
|
P: "Lcl Scaling", "Lcl Scaling", "", "A",1.0,1.0019,1.0
|
||||||
|
P: "currentUVSet", "KString", "", "U", "map1"
|
||||||
|
}
|
||||||
|
Shading: T
|
||||||
|
Culling: "CullingOff"
|
||||||
|
}
|
||||||
|
Material: 1827074508720, "Material::Mat_Green", "" {
|
||||||
|
Version: 102
|
||||||
|
ShadingModel: "lambert"
|
||||||
|
MultiLayer: 0
|
||||||
|
Properties70: {
|
||||||
|
P: "AmbientColor", "Color", "", "A",0,0,0
|
||||||
|
P: "DiffuseColor", "Color", "", "A",0,1,0
|
||||||
|
P: "DiffuseFactor", "Number", "", "A",0.800000011920929
|
||||||
|
P: "TransparencyFactor", "Number", "", "A",1
|
||||||
|
P: "Emissive", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "Ambient", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "Diffuse", "Vector3D", "Vector", "",0,0.800000011920929,0
|
||||||
|
P: "Opacity", "double", "Number", "",1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Material: 1827074501920, "Material::Mat_Red", "" {
|
||||||
|
Version: 102
|
||||||
|
ShadingModel: "lambert"
|
||||||
|
MultiLayer: 0
|
||||||
|
Properties70: {
|
||||||
|
P: "AmbientColor", "Color", "", "A",0,0,0
|
||||||
|
P: "DiffuseColor", "Color", "", "A",1,0,0
|
||||||
|
P: "DiffuseFactor", "Number", "", "A",0.800000011920929
|
||||||
|
P: "TransparencyFactor", "Number", "", "A",1
|
||||||
|
P: "Emissive", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "Ambient", "Vector3D", "Vector", "",0,0,0
|
||||||
|
P: "Diffuse", "Vector3D", "Vector", "",0.800000011920929,0,0
|
||||||
|
P: "Opacity", "double", "Number", "",1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnimationStack: 1825586153728, "AnimStack::Take 001", "" {
|
||||||
|
Properties70: {
|
||||||
|
P: "LocalStart", "KTime", "Time", "",1924423250
|
||||||
|
P: "LocalStop", "KTime", "Time", "",230930790000
|
||||||
|
P: "ReferenceStart", "KTime", "Time", "",1924423250
|
||||||
|
P: "ReferenceStop", "KTime", "Time", "",230930790000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnimationLayer: 1827070038960, "AnimLayer::BaseLayer", "" {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; Object connections
|
||||||
|
;------------------------------------------------------------------
|
||||||
|
|
||||||
|
Connections: {
|
||||||
|
|
||||||
|
;Model::Cube2, Model::RootNode
|
||||||
|
C: "OO",1827098352032,0
|
||||||
|
|
||||||
|
;Model::Cube3, Model::RootNode
|
||||||
|
C: "OO",1827098382192,0
|
||||||
|
|
||||||
|
;AnimLayer::BaseLayer, AnimStack::Take 001
|
||||||
|
C: "OO",1827070038960,1825586153728
|
||||||
|
|
||||||
|
;Geometry::, Model::Cube2
|
||||||
|
C: "OO",1827080157856,1827098352032
|
||||||
|
|
||||||
|
;Material::Mat_Green, Model::Cube2
|
||||||
|
C: "OO",1827074508720,1827098352032
|
||||||
|
|
||||||
|
;Model::Cube1, Model::Cube2
|
||||||
|
C: "OO",1827098379872,1827098352032
|
||||||
|
|
||||||
|
;Geometry::, Model::Cube1
|
||||||
|
C: "OO",1827080155296,1827098379872
|
||||||
|
|
||||||
|
;Material::Mat_Green, Model::Cube1
|
||||||
|
C: "OO",1827074508720,1827098379872
|
||||||
|
|
||||||
|
;Geometry::, Model::Cube3
|
||||||
|
C: "OO",1827080156320,1827098382192
|
||||||
|
|
||||||
|
;Material::Mat_Red, Model::Cube3
|
||||||
|
C: "OO",1827074501920,1827098382192
|
||||||
|
|
||||||
|
;Model::Cube1, Model::Cube3
|
||||||
|
C: "OO",1827098384512,1827098382192
|
||||||
|
|
||||||
|
;Geometry::, Model::Cube1
|
||||||
|
C: "OO",1827080139424,1827098384512
|
||||||
|
|
||||||
|
;Material::Mat_Red, Model::Cube1
|
||||||
|
C: "OO",1827074501920,1827098384512
|
||||||
|
}
|
||||||
|
;Takes section
|
||||||
|
;----------------------------------------------------
|
||||||
|
|
||||||
|
Takes: {
|
||||||
|
Current: "Take 001"
|
||||||
|
Take: "Take 001" {
|
||||||
|
FileName: "Take_001.tak"
|
||||||
|
LocalTime: 1924423250,230930790000
|
||||||
|
ReferenceTime: 1924423250,230930790000
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
ply
|
|
||||||
format ascii 1.0
|
|
||||||
comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.993695325)
|
|
||||||
element vertex 8
|
|
||||||
property float x
|
|
||||||
property float y
|
|
||||||
property float z
|
|
||||||
element face 6
|
|
||||||
property list uchar int vertex_index
|
|
||||||
end_header
|
|
||||||
0 0 0
|
|
||||||
0 0 1
|
|
||||||
0 1 1
|
|
||||||
0 1 0
|
|
||||||
1 0 0
|
|
||||||
1 0 1
|
|
||||||
1 1 1
|
|
||||||
1 1 0
|
|
||||||
4 0 1 2 3
|
|
||||||
4 7 6 5 4
|
|
||||||
4 0 4 5 1
|
|
||||||
4 1 5 6 2
|
|
||||||
4 2 6 7 3
|
|
||||||
4 3 7 4 0
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
Exporter exporter;
|
Exporter exporter;
|
||||||
aiReturn res = exporter.Export(scene, "json", "./spider_test.json");
|
aiReturn res = exporter.Export(scene, "assjson", "./spider_test.json");
|
||||||
return aiReturn_SUCCESS == res;
|
return aiReturn_SUCCESS == res;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,3 +71,32 @@ TEST_F(ExporterTest, ProgressHandlerTest) {
|
||||||
TestProgressHandler *ph(new TestProgressHandler);
|
TestProgressHandler *ph(new TestProgressHandler);
|
||||||
exporter.SetProgressHandler(ph);
|
exporter.SetProgressHandler(ph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure all the registered exporters have useful descriptions
|
||||||
|
TEST_F(ExporterTest, ExporterIdTest) {
|
||||||
|
Exporter exporter;
|
||||||
|
size_t exportFormatCount = exporter.GetExportFormatCount();
|
||||||
|
EXPECT_NE(0u, exportFormatCount) << "No registered exporters";
|
||||||
|
typedef std::map<std::string, const aiExportFormatDesc*> ExportIdMap;
|
||||||
|
ExportIdMap exporterMap;
|
||||||
|
for (size_t i = 0; i < exportFormatCount; ++i)
|
||||||
|
{
|
||||||
|
// Check that the exporter description exists and makes sense
|
||||||
|
const aiExportFormatDesc* desc = exporter.GetExportFormatDescription(i);
|
||||||
|
ASSERT_NE(nullptr, desc) << "Missing aiExportFormatDesc at index " << i;
|
||||||
|
EXPECT_NE(nullptr, desc->id) << "Null exporter ID at index " << i;
|
||||||
|
EXPECT_STRNE("", desc->id) << "Empty exporter ID at index " << i;
|
||||||
|
EXPECT_NE(nullptr, desc->description) << "Null exporter description at index " << i;
|
||||||
|
EXPECT_STRNE("", desc->description) << "Empty exporter description at index " << i;
|
||||||
|
EXPECT_NE(nullptr, desc->fileExtension) << "Null exporter file extension at index " << i;
|
||||||
|
EXPECT_STRNE("", desc->fileExtension) << "Empty exporter file extension at index " << i;
|
||||||
|
|
||||||
|
// Check the ID is unique
|
||||||
|
std::string key(desc->id);
|
||||||
|
std::pair<ExportIdMap::iterator, bool> result = exporterMap.emplace(key, desc);
|
||||||
|
EXPECT_TRUE(result.second) << "Duplicate exported id: '" << key << "' " << desc->description << " *." << desc->fileExtension << " at index " << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const aiExportFormatDesc* desc = exporter.GetExportFormatDescription(exportFormatCount);
|
||||||
|
EXPECT_EQ(nullptr, desc) << "More exporters than claimed";
|
||||||
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ public:
|
||||||
scene->mMeshes[ 0 ]->mFaces[ 0 ].mIndices[ 1 ] = 1;
|
scene->mMeshes[ 0 ]->mFaces[ 0 ].mIndices[ 1 ] = 1;
|
||||||
scene->mMeshes[ 0 ]->mFaces[ 0 ].mIndices[ 2 ] = 2;
|
scene->mMeshes[ 0 ]->mFaces[ 0 ].mIndices[ 2 ] = 2;
|
||||||
|
|
||||||
scene->mRootNode = new aiNode;
|
scene->mRootNode = new aiNode();
|
||||||
scene->mRootNode->mNumMeshes = 1;
|
scene->mRootNode->mNumMeshes = 1;
|
||||||
scene->mRootNode->mMeshes = new unsigned int[1]{ 0 };
|
scene->mRootNode->mMeshes = new unsigned int[1]{ 0 };
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ public:
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
|
||||||
|
|
||||||
Exporter exporter;
|
Exporter exporter;
|
||||||
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "assbin", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_test.assbin" ) );
|
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "assbin", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.assbin" ) );
|
||||||
const aiScene *newScene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider_test.assbin", aiProcess_ValidateDataStructure );
|
const aiScene *newScene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.assbin", aiProcess_ValidateDataStructure );
|
||||||
|
|
||||||
return newScene != nullptr;
|
return newScene != nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2019, assimp team
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -73,11 +71,6 @@ TEST_F(BlenderWorkTest,work_279) {
|
||||||
ASSERT_TRUE(pTest->HasMaterials());
|
ASSERT_TRUE(pTest->HasMaterials());
|
||||||
ASSERT_TRUE(pTest->HasMeshes());
|
ASSERT_TRUE(pTest->HasMeshes());
|
||||||
ASSERT_TRUE(pTest->mMeshes[0]->mNumVertices > 0);
|
ASSERT_TRUE(pTest->mMeshes[0]->mNumVertices > 0);
|
||||||
ASSERT_EQ(44, pTest->mMeshes[0]->mNumFaces);
|
ASSERT_EQ(44u, pTest->mMeshes[0]->mNumFaces);
|
||||||
EXPECT_EQ(1, pTest->mNumMaterials);
|
EXPECT_EQ(1u, pTest->mNumMaterials);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,3 +60,16 @@ public:
|
||||||
TEST_F(utColladaImportExport, importBlenFromFileTest) {
|
TEST_F(utColladaImportExport, importBlenFromFileTest) {
|
||||||
EXPECT_TRUE(importerTest());
|
EXPECT_TRUE(importerTest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class utColladaZaeImportExport : public AbstractImportExportBase {
|
||||||
|
public:
|
||||||
|
virtual bool importerTest() {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure);
|
||||||
|
return nullptr != scene;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(utColladaZaeImportExport, importBlenFromFileTest) {
|
||||||
|
EXPECT_TRUE(importerTest());
|
||||||
|
}
|
||||||
|
|
|
@ -70,10 +70,10 @@ TEST_F( utFBXImporterExporter, importBareBoxWithoutColorsAndTextureCoords ) {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/box.fbx", aiProcess_ValidateDataStructure );
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/box.fbx", aiProcess_ValidateDataStructure );
|
||||||
EXPECT_NE( nullptr, scene );
|
EXPECT_NE( nullptr, scene );
|
||||||
EXPECT_EQ(scene->mNumMeshes, 1);
|
EXPECT_EQ(scene->mNumMeshes, 1u);
|
||||||
aiMesh* mesh = scene->mMeshes[0];
|
aiMesh* mesh = scene->mMeshes[0];
|
||||||
EXPECT_EQ(mesh->mNumFaces, 12);
|
EXPECT_EQ(mesh->mNumFaces, 12u);
|
||||||
EXPECT_EQ(mesh->mNumVertices, 36);
|
EXPECT_EQ(mesh->mNumVertices, 36u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
|
TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
|
||||||
|
@ -85,13 +85,13 @@ TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
|
||||||
const auto root = scene->mRootNode;
|
const auto root = scene->mRootNode;
|
||||||
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
|
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
|
||||||
ASSERT_TRUE(root->mChildren);
|
ASSERT_TRUE(root->mChildren);
|
||||||
ASSERT_EQ(root->mNumChildren, 2);
|
ASSERT_EQ(root->mNumChildren, 2u);
|
||||||
|
|
||||||
const auto child0 = root->mChildren[0];
|
const auto child0 = root->mChildren[0];
|
||||||
ASSERT_TRUE(child0);
|
ASSERT_TRUE(child0);
|
||||||
ASSERT_STREQ(child0->mName.C_Str(), "RootNode001");
|
ASSERT_STREQ(child0->mName.C_Str(), "RootNode001");
|
||||||
ASSERT_TRUE(child0->mChildren);
|
ASSERT_TRUE(child0->mChildren);
|
||||||
ASSERT_EQ(child0->mNumChildren, 1);
|
ASSERT_EQ(child0->mNumChildren, 1u);
|
||||||
|
|
||||||
const auto child00 = child0->mChildren[0];
|
const auto child00 = child0->mChildren[0];
|
||||||
ASSERT_TRUE(child00);
|
ASSERT_TRUE(child00);
|
||||||
|
@ -101,7 +101,7 @@ TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
|
||||||
ASSERT_TRUE(child1);
|
ASSERT_TRUE(child1);
|
||||||
ASSERT_STREQ(child1->mName.C_Str(), "RootNode002");
|
ASSERT_STREQ(child1->mName.C_Str(), "RootNode002");
|
||||||
ASSERT_TRUE(child1->mChildren);
|
ASSERT_TRUE(child1->mChildren);
|
||||||
ASSERT_EQ(child1->mNumChildren, 1);
|
ASSERT_EQ(child1->mNumChildren, 1u);
|
||||||
|
|
||||||
const auto child10 = child1->mChildren[0];
|
const auto child10 = child1->mChildren[0];
|
||||||
ASSERT_TRUE(child10);
|
ASSERT_TRUE(child10);
|
||||||
|
@ -117,13 +117,13 @@ TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) {
|
||||||
const auto root = scene->mRootNode;
|
const auto root = scene->mRootNode;
|
||||||
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
|
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
|
||||||
ASSERT_TRUE(root->mChildren);
|
ASSERT_TRUE(root->mChildren);
|
||||||
ASSERT_EQ(root->mNumChildren, 2);
|
ASSERT_EQ(root->mNumChildren, 2u);
|
||||||
|
|
||||||
const auto child0 = root->mChildren[0];
|
const auto child0 = root->mChildren[0];
|
||||||
ASSERT_TRUE(child0);
|
ASSERT_TRUE(child0);
|
||||||
ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
|
ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
|
||||||
ASSERT_TRUE(child0->mChildren);
|
ASSERT_TRUE(child0->mChildren);
|
||||||
ASSERT_EQ(child0->mNumChildren, 1);
|
ASSERT_EQ(child0->mNumChildren, 1u);
|
||||||
|
|
||||||
const auto child00 = child0->mChildren[0];
|
const auto child00 = child0->mChildren[0];
|
||||||
ASSERT_TRUE(child00);
|
ASSERT_TRUE(child00);
|
||||||
|
@ -133,7 +133,7 @@ TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) {
|
||||||
ASSERT_TRUE(child1);
|
ASSERT_TRUE(child1);
|
||||||
ASSERT_STREQ(child1->mName.C_Str(), "Cube3");
|
ASSERT_STREQ(child1->mName.C_Str(), "Cube3");
|
||||||
ASSERT_TRUE(child1->mChildren);
|
ASSERT_TRUE(child1->mChildren);
|
||||||
ASSERT_EQ(child1->mNumChildren, 1);
|
ASSERT_EQ(child1->mNumChildren, 1u);
|
||||||
|
|
||||||
const auto child10 = child1->mChildren[0];
|
const auto child10 = child1->mChildren[0];
|
||||||
ASSERT_TRUE(child10);
|
ASSERT_TRUE(child10);
|
||||||
|
@ -149,13 +149,13 @@ TEST_F(utFBXImporterExporter, importCubesComplexTransform) {
|
||||||
const auto root = scene->mRootNode;
|
const auto root = scene->mRootNode;
|
||||||
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
|
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
|
||||||
ASSERT_TRUE(root->mChildren);
|
ASSERT_TRUE(root->mChildren);
|
||||||
ASSERT_EQ(root->mNumChildren, 2);
|
ASSERT_EQ(root->mNumChildren, 2u);
|
||||||
|
|
||||||
const auto child0 = root->mChildren[0];
|
const auto child0 = root->mChildren[0];
|
||||||
ASSERT_TRUE(child0);
|
ASSERT_TRUE(child0);
|
||||||
ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
|
ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
|
||||||
ASSERT_TRUE(child0->mChildren);
|
ASSERT_TRUE(child0->mChildren);
|
||||||
ASSERT_EQ(child0->mNumChildren, 1);
|
ASSERT_EQ(child0->mNumChildren, 1u);
|
||||||
|
|
||||||
const auto child00 = child0->mChildren[0];
|
const auto child00 = child0->mChildren[0];
|
||||||
ASSERT_TRUE(child00);
|
ASSERT_TRUE(child00);
|
||||||
|
@ -177,35 +177,44 @@ TEST_F(utFBXImporterExporter, importCubesComplexTransform) {
|
||||||
"Cube1001_$AssimpFbx$_ScalingPivotInverse",
|
"Cube1001_$AssimpFbx$_ScalingPivotInverse",
|
||||||
"Cube1001"
|
"Cube1001"
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < chain_length; ++i)
|
for (size_t i = 0; i < chain_length; ++i) {
|
||||||
{
|
|
||||||
ASSERT_TRUE(parent->mChildren);
|
ASSERT_TRUE(parent->mChildren);
|
||||||
ASSERT_EQ(parent->mNumChildren, 1);
|
ASSERT_EQ(parent->mNumChildren, 1u);
|
||||||
auto node = parent->mChildren[0];
|
auto node = parent->mChildren[0];
|
||||||
ASSERT_TRUE(node);
|
ASSERT_TRUE(node);
|
||||||
ASSERT_STREQ(node->mName.C_Str(), chainStr[i]);
|
ASSERT_STREQ(node->mName.C_Str(), chainStr[i]);
|
||||||
parent = node;
|
parent = node;
|
||||||
}
|
}
|
||||||
ASSERT_EQ(0, parent->mNumChildren) << "Leaf node";
|
ASSERT_EQ(0u, parent->mNumChildren) << "Leaf node";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(utFBXImporterExporter, importCloseToIdentityTransforms) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
// This was asserting in FBXConverter.cpp because the transforms appeared to be the identity by one test, but not by another.
|
||||||
|
// This asset should now load successfully.
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/close_to_identity_transforms.fbx", aiProcess_ValidateDataStructure);
|
||||||
|
ASSERT_TRUE(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( utFBXImporterExporter, importPhongMaterial ) {
|
TEST_F( utFBXImporterExporter, importPhongMaterial ) {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/phong_cube.fbx", aiProcess_ValidateDataStructure );
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/phong_cube.fbx", aiProcess_ValidateDataStructure );
|
||||||
EXPECT_NE( nullptr, scene );
|
EXPECT_NE( nullptr, scene );
|
||||||
EXPECT_EQ( (unsigned int)1, scene->mNumMaterials );
|
EXPECT_EQ( 1u, scene->mNumMaterials );
|
||||||
const aiMaterial *mat = scene->mMaterials[0];
|
const aiMaterial *mat = scene->mMaterials[0];
|
||||||
EXPECT_NE( nullptr, mat );
|
EXPECT_NE( nullptr, mat );
|
||||||
float f; aiColor3D c;
|
float f;
|
||||||
|
aiColor3D c;
|
||||||
|
|
||||||
// phong_cube.fbx has all properties defined
|
// phong_cube.fbx has all properties defined
|
||||||
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_DIFFUSE, c), aiReturn_SUCCESS );
|
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_DIFFUSE, c), aiReturn_SUCCESS );
|
||||||
EXPECT_EQ( c, aiColor3D(0.5, 0.25, 0.25) );
|
EXPECT_EQ( c, aiColor3D(0.5, 0.25, 0.25) );
|
||||||
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_SPECULAR, c), aiReturn_SUCCESS );
|
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_SPECULAR, c), aiReturn_SUCCESS );
|
||||||
EXPECT_EQ( c, aiColor3D(0.25, 0.25, 0.5) );
|
EXPECT_EQ( c, aiColor3D(0.25, 0.25, 0.5) );
|
||||||
EXPECT_EQ( mat->Get(AI_MATKEY_SHININESS_STRENGTH, f), aiReturn_SUCCESS );
|
EXPECT_EQ( mat->Get(AI_MATKEY_SHININESS_STRENGTH, f), aiReturn_SUCCESS );
|
||||||
EXPECT_EQ( f, 0.5 );
|
EXPECT_EQ( f, 0.5f );
|
||||||
EXPECT_EQ( mat->Get(AI_MATKEY_SHININESS, f), aiReturn_SUCCESS );
|
EXPECT_EQ( mat->Get(AI_MATKEY_SHININESS, f), aiReturn_SUCCESS );
|
||||||
EXPECT_EQ( f, 10.0 );
|
EXPECT_EQ( f, 10.0f );
|
||||||
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_AMBIENT, c), aiReturn_SUCCESS );
|
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_AMBIENT, c), aiReturn_SUCCESS );
|
||||||
EXPECT_EQ( c, aiColor3D(0.125, 0.25, 0.25) );
|
EXPECT_EQ( c, aiColor3D(0.125, 0.25, 0.25) );
|
||||||
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_EMISSIVE, c), aiReturn_SUCCESS );
|
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_EMISSIVE, c), aiReturn_SUCCESS );
|
||||||
|
@ -213,7 +222,7 @@ TEST_F( utFBXImporterExporter, importPhongMaterial ) {
|
||||||
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_TRANSPARENT, c), aiReturn_SUCCESS );
|
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_TRANSPARENT, c), aiReturn_SUCCESS );
|
||||||
EXPECT_EQ( c, aiColor3D(0.75, 0.5, 0.25) );
|
EXPECT_EQ( c, aiColor3D(0.75, 0.5, 0.25) );
|
||||||
EXPECT_EQ( mat->Get(AI_MATKEY_OPACITY, f), aiReturn_SUCCESS );
|
EXPECT_EQ( mat->Get(AI_MATKEY_OPACITY, f), aiReturn_SUCCESS );
|
||||||
EXPECT_EQ( f, 0.5 );
|
EXPECT_EQ( f, 0.5f );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(utFBXImporterExporter, importUnitScaleFactor) {
|
TEST_F(utFBXImporterExporter, importUnitScaleFactor) {
|
||||||
|
@ -234,7 +243,7 @@ TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) {
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
|
|
||||||
EXPECT_EQ(1, scene->mNumMaterials);
|
EXPECT_EQ(1u, scene->mNumMaterials);
|
||||||
aiMaterial *mat = scene->mMaterials[0];
|
aiMaterial *mat = scene->mMaterials[0];
|
||||||
ASSERT_NE(nullptr, mat);
|
ASSERT_NE(nullptr, mat);
|
||||||
|
|
||||||
|
@ -243,7 +252,7 @@ TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) {
|
||||||
EXPECT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes));
|
EXPECT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes));
|
||||||
ASSERT_STREQ(path.C_Str(), "..\\..\\..\\Desktop\\uv_test.png");
|
ASSERT_STREQ(path.C_Str(), "..\\..\\..\\Desktop\\uv_test.png");
|
||||||
|
|
||||||
ASSERT_EQ(1, scene->mNumTextures);
|
ASSERT_EQ(1u, scene->mNumTextures);
|
||||||
ASSERT_TRUE(scene->mTextures[0]->pcData);
|
ASSERT_TRUE(scene->mTextures[0]->pcData);
|
||||||
ASSERT_EQ(439176u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression splits data by 512Kb, it should be two parts for this texture";
|
ASSERT_EQ(439176u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression splits data by 512Kb, it should be two parts for this texture";
|
||||||
}
|
}
|
||||||
|
@ -254,7 +263,7 @@ TEST_F(utFBXImporterExporter, importEmbeddedFragmentedAsciiTest) {
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box_embedded_texture_fragmented.fbx", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box_embedded_texture_fragmented.fbx", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
|
|
||||||
EXPECT_EQ(1, scene->mNumMaterials);
|
EXPECT_EQ(1u, scene->mNumMaterials);
|
||||||
aiMaterial *mat = scene->mMaterials[0];
|
aiMaterial *mat = scene->mMaterials[0];
|
||||||
ASSERT_NE(nullptr, mat);
|
ASSERT_NE(nullptr, mat);
|
||||||
|
|
||||||
|
@ -263,7 +272,7 @@ TEST_F(utFBXImporterExporter, importEmbeddedFragmentedAsciiTest) {
|
||||||
ASSERT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes));
|
ASSERT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes));
|
||||||
ASSERT_STREQ(path.C_Str(), "paper.png");
|
ASSERT_STREQ(path.C_Str(), "paper.png");
|
||||||
|
|
||||||
ASSERT_EQ(1, scene->mNumTextures);
|
ASSERT_EQ(1u, scene->mNumTextures);
|
||||||
ASSERT_TRUE(scene->mTextures[0]->pcData);
|
ASSERT_TRUE(scene->mTextures[0]->pcData);
|
||||||
ASSERT_EQ(968029u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression splits data by 512Kb, it should be two parts for this texture";
|
ASSERT_EQ(968029u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression splits data by 512Kb, it should be two parts for this texture";
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ TEST_F( utIssues, OpacityBugWhenExporting_727 ) {
|
||||||
if ( newScene->mNumMaterials > 0 ) {
|
if ( newScene->mNumMaterials > 0 ) {
|
||||||
std::cout << "Desc = " << desc->description << "\n";
|
std::cout << "Desc = " << desc->description << "\n";
|
||||||
EXPECT_EQ( AI_SUCCESS, newScene->mMaterials[ 0 ]->Get( AI_MATKEY_OPACITY, newOpacity ) );
|
EXPECT_EQ( AI_SUCCESS, newScene->mMaterials[ 0 ]->Get( AI_MATKEY_OPACITY, newOpacity ) );
|
||||||
EXPECT_EQ( opacity, newOpacity );
|
EXPECT_FLOAT_EQ( opacity, newOpacity );
|
||||||
}
|
}
|
||||||
delete scene;
|
delete scene;
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,8 +205,8 @@ protected:
|
||||||
::Assimp::Exporter exporter;
|
::Assimp::Exporter exporter;
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
|
||||||
EXPECT_NE( nullptr, scene );
|
EXPECT_NE( nullptr, scene );
|
||||||
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_test.obj" ) );
|
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.obj" ) );
|
||||||
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "objnomtl", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_nomtl_test.obj" ) );
|
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "objnomtl", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_nomtl_out.obj" ) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ TEST_F( utObjImportExport, issue809_vertex_color_Test ) {
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
::Assimp::Exporter exporter;
|
::Assimp::Exporter exporter;
|
||||||
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/test.obj" ) );
|
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/test_out.obj" ) );
|
||||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,3 +448,37 @@ TEST_F(utObjImportExport, import_without_linend) {
|
||||||
const aiScene *scene = myImporter.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/box_without_lineending.obj", 0);
|
const aiScene *scene = myImporter.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/box_without_lineending.obj", 0);
|
||||||
ASSERT_NE(nullptr, scene);
|
ASSERT_NE(nullptr, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(utObjImportExport, import_with_line_continuations) {
|
||||||
|
static const char *ObjModel =
|
||||||
|
"v -0.5 -0.5 0.5\n"
|
||||||
|
"v -0.5 \\\n"
|
||||||
|
" -0.5 -0.5\n"
|
||||||
|
"v -0.5 \\\n"
|
||||||
|
" 0.5 \\\n"
|
||||||
|
" -0.5\n"
|
||||||
|
"f 1 2 3\n";
|
||||||
|
|
||||||
|
Assimp::Importer myImporter;
|
||||||
|
const aiScene *scene = myImporter.ReadFileFromMemory(ObjModel, strlen(ObjModel), 0);
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
|
||||||
|
EXPECT_EQ(scene->mNumMeshes, 1U);
|
||||||
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 3U);
|
||||||
|
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 1U);
|
||||||
|
|
||||||
|
auto vertices = scene->mMeshes[0]->mVertices;
|
||||||
|
const float threshold = 0.0001f;
|
||||||
|
|
||||||
|
EXPECT_NEAR(vertices[0].x, -0.5f, threshold);
|
||||||
|
EXPECT_NEAR(vertices[0].y, -0.5f, threshold);
|
||||||
|
EXPECT_NEAR(vertices[0].z, 0.5f, threshold);
|
||||||
|
|
||||||
|
EXPECT_NEAR(vertices[1].x, -0.5f, threshold);
|
||||||
|
EXPECT_NEAR(vertices[1].y, -0.5f, threshold);
|
||||||
|
EXPECT_NEAR(vertices[1].z, -0.5f, threshold);
|
||||||
|
|
||||||
|
EXPECT_NEAR(vertices[2].x, -0.5f, threshold);
|
||||||
|
EXPECT_NEAR(vertices[2].y, 0.5f, threshold);
|
||||||
|
EXPECT_NEAR(vertices[2].z, -0.5f, threshold);
|
||||||
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ public:
|
||||||
Exporter exporter;
|
Exporter exporter;
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_test.ply"));
|
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_out.ply"));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,18 +69,5 @@ TEST_F( utScaleProcess, accessScaleTest ) {
|
||||||
EXPECT_FLOAT_EQ( 2.0f, process.getScale() );
|
EXPECT_FLOAT_EQ( 2.0f, process.getScale() );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( utScaleProcess, rescaleModelTest ) {
|
|
||||||
float opacity;
|
|
||||||
aiScene *testScene = TestModelFacttory::createDefaultTestModel( opacity );
|
|
||||||
ai_real v1 = testScene->mRootNode->mTransformation.a1;
|
|
||||||
ScaleProcess process;
|
|
||||||
process.setScale( 10.0f );
|
|
||||||
process.Execute( testScene );
|
|
||||||
ai_real v2 = testScene->mRootNode->mTransformation.a1;
|
|
||||||
const ai_real scale = v2 / v1;
|
|
||||||
EXPECT_FLOAT_EQ( scale, 10.0f );
|
|
||||||
TestModelFacttory::releaseDefaultTestModel( &testScene );
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Namespace UnitTest
|
} // Namespace UnitTest
|
||||||
} // Namespace Assimp
|
} // Namespace Assimp
|
||||||
|
|
|
@ -183,8 +183,7 @@ TEST_F(SortByPTypeProcessTest, SortByPTypeStep) {
|
||||||
unsigned int idx = 0;
|
unsigned int idx = 0;
|
||||||
for (unsigned int m = 0,real = 0; m< 10;++m) {
|
for (unsigned int m = 0,real = 0; m< 10;++m) {
|
||||||
for (unsigned int n = 0; n < 4;++n) {
|
for (unsigned int n = 0; n < 4;++n) {
|
||||||
if ((idx = num[m][n]))
|
if ((idx = num[m][n])) {
|
||||||
{
|
|
||||||
EXPECT_TRUE(real < mScene->mNumMeshes);
|
EXPECT_TRUE(real < mScene->mNumMeshes);
|
||||||
|
|
||||||
aiMesh* mesh = mScene->mMeshes[real];
|
aiMesh* mesh = mScene->mMeshes[real];
|
||||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2019, assimp team
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -55,17 +53,23 @@ class utglTF2ImportExport : public AbstractImportExportBase {
|
||||||
public:
|
public:
|
||||||
virtual bool importerTest() {
|
virtual bool importerTest() {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf",
|
||||||
|
aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE( scene, nullptr );
|
EXPECT_NE( scene, nullptr );
|
||||||
if ( !scene ) return false;
|
if (!scene) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
EXPECT_TRUE( scene->HasMaterials() );
|
EXPECT_TRUE( scene->HasMaterials() );
|
||||||
if ( !scene->HasMaterials() ) return false;
|
if (!scene->HasMaterials()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const aiMaterial *material = scene->mMaterials[0];
|
const aiMaterial *material = scene->mMaterials[0];
|
||||||
|
|
||||||
aiString path;
|
aiString path;
|
||||||
aiTextureMapMode modes[2];
|
aiTextureMapMode modes[2];
|
||||||
EXPECT_EQ( aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes) );
|
EXPECT_EQ( aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr,
|
||||||
|
nullptr, nullptr, modes) );
|
||||||
EXPECT_STREQ( path.C_Str(), "CesiumLogoFlat.png" );
|
EXPECT_STREQ( path.C_Str(), "CesiumLogoFlat.png" );
|
||||||
EXPECT_EQ( modes[0], aiTextureMapMode_Mirror );
|
EXPECT_EQ( modes[0], aiTextureMapMode_Mirror );
|
||||||
EXPECT_EQ( modes[1], aiTextureMapMode_Clamp );
|
EXPECT_EQ( modes[1], aiTextureMapMode_Clamp );
|
||||||
|
@ -75,7 +79,8 @@ public:
|
||||||
|
|
||||||
virtual bool binaryImporterTest() {
|
virtual bool binaryImporterTest() {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb",
|
||||||
|
aiProcess_ValidateDataStructure);
|
||||||
return nullptr != scene;
|
return nullptr != scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +88,8 @@ public:
|
||||||
virtual bool exporterTest() {
|
virtual bool exporterTest() {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
Assimp::Exporter exporter;
|
Assimp::Exporter exporter;
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure );
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf",
|
||||||
|
aiProcess_ValidateDataStructure );
|
||||||
EXPECT_NE( nullptr, scene );
|
EXPECT_NE( nullptr, scene );
|
||||||
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) );
|
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) );
|
||||||
|
|
||||||
|
@ -105,7 +111,8 @@ TEST_F( utglTF2ImportExport, importBinaryglTF2FromFileTest ) {
|
||||||
TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
|
TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
Assimp::Exporter exporter;
|
Assimp::Exporter exporter;
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf",
|
||||||
|
aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.obj"));
|
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.obj"));
|
||||||
}
|
}
|
||||||
|
@ -113,7 +120,8 @@ TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
|
||||||
TEST_F(utglTF2ImportExport, importglTF2EmbeddedAndExportToOBJ) {
|
TEST_F(utglTF2ImportExport, importglTF2EmbeddedAndExportToOBJ) {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
Assimp::Exporter exporter;
|
Assimp::Exporter exporter;
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf",
|
||||||
|
aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj"));
|
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj"));
|
||||||
}
|
}
|
||||||
|
@ -124,10 +132,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePointsWithoutIndices) {
|
||||||
//Points without indices
|
//Points without indices
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_00.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_00.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
{
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1);
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,12 +144,11 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLinesWithoutIndices) {
|
||||||
//Lines without indices
|
//Lines without indices
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_01.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_01.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 8);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 8u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
{
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i*2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i*2);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i*2u + 1u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i*2 + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,15 +157,14 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLinesLoopWithoutIndices) {
|
||||||
//Lines loop without indices
|
//Lines loop without indices
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_02.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_02.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
|
|
||||||
std::array<int, 5> l1 = {{ 0, 1, 2, 3, 0 }};
|
std::array<unsigned int, 5> l1 = {{ 0u, 1u, 2u, 3u, 0u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
{
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2);
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], l1[i + 1]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], l1[i + 1u]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,14 +173,13 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLinesStripWithoutIndices) {
|
||||||
//Lines strip without indices
|
//Lines strip without indices
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_03.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_03.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 5);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 5u);
|
||||||
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
{
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2);
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i + 1);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i + 1u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,19 +188,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesStripWithoutIndices
|
||||||
//Triangles strip without indices
|
//Triangles strip without indices
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_04.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_04.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<int, 3> f1 = {{ 0, 1, 2 }};
|
std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
|
||||||
for (int i = 0; i < 3; ++i)
|
for (unsigned int i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int, 3> f2 = {{ 2, 1, 3 }};
|
std::array<unsigned int, 3> f2 = {{ 2u, 1u, 3u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,19 +208,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFanWithoutIndices)
|
||||||
//Triangles fan without indices
|
//Triangles fan without indices
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_05.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_05.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<int, 3> f1 = {{ 0, 1, 2 }};
|
std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int, 3> f2 = {{ 0, 2, 3 }};
|
std::array<unsigned int, 3> f2 = {{ 0u, 2u, 3u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,19 +228,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesWithoutIndices) {
|
||||||
//Triangles without indices
|
//Triangles without indices
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_06.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_06.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 6);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 6u);
|
||||||
std::array<int, 3> f1 = {{ 0, 1, 2 }};
|
std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int, 3> f2 = {{ 3, 4, 5 }};
|
std::array<unsigned int, 3> f2 = {{ 3u, 4u, 5u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,10 +248,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePoints) {
|
||||||
//Line loop
|
//Line loop
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_07.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_07.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
{
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1);
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,9 +260,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLines) {
|
||||||
//Lines
|
//Lines
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_08.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_08.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }};
|
std::array<unsigned int, 5> l1 = {{ 0u, 3u, 2u, 1u, 0u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
||||||
|
@ -278,9 +275,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineLoop) {
|
||||||
//Line loop
|
//Line loop
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_09.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_09.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }};
|
std::array<unsigned int, 5> l1 = {{ 0, 3u, 2u, 1u, 0u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
||||||
|
@ -293,11 +290,10 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineStrip) {
|
||||||
//Lines Strip
|
//Lines Strip
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_10.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_10.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }};
|
std::array<unsigned int, 5> l1 = {{ 0u, 3u, 2u, 1u, 0u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], l1[i + 1]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], l1[i + 1]);
|
||||||
}
|
}
|
||||||
|
@ -308,19 +304,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesStrip) {
|
||||||
//Triangles strip
|
//Triangles strip
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_11.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_11.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<int, 3> f1 = {{ 0, 3, 1 }};
|
std::array<unsigned int, 3> f1 = {{ 0u, 3u, 1u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int, 3> f2 = {{ 1, 3, 2 }};
|
std::array<unsigned int, 3> f2 = {{ 1u, 3u, 2u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,19 +324,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFan) {
|
||||||
//Triangles fan
|
//Triangles fan
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_12.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_12.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2);
|
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
||||||
std::array<int, 3> f1 = {{ 0, 3, 2 }};
|
std::array<unsigned int, 3> f1 = {{ 0u, 3u, 2u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u );
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int, 3> f2 = {{ 0, 2, 1 }};
|
std::array<unsigned int, 3> f2 = {{ 0u, 2u, 1u }};
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u );
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +370,8 @@ TEST_F(utglTF2ImportExport, importglTF2FromMemory) {
|
||||||
|
|
||||||
TEST_F( utglTF2ImportExport, bug_import_simple_skin ) {
|
TEST_F( utglTF2ImportExport, bug_import_simple_skin ) {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/simple_skin.gltf", aiProcess_ValidateDataStructure );
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/simple_skin.gltf",
|
||||||
|
aiProcess_ValidateDataStructure );
|
||||||
EXPECT_NE( nullptr, scene );
|
EXPECT_NE( nullptr, scene );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -384,6 +384,7 @@ int ProcessStandardArguments(
|
||||||
// -om --optimize-meshes
|
// -om --optimize-meshes
|
||||||
// -db --debone
|
// -db --debone
|
||||||
// -sbc --split-by-bone-count
|
// -sbc --split-by-bone-count
|
||||||
|
// -gs --global-scale
|
||||||
//
|
//
|
||||||
// -c<file> --config-file=<file>
|
// -c<file> --config-file=<file>
|
||||||
|
|
||||||
|
@ -472,6 +473,9 @@ int ProcessStandardArguments(
|
||||||
else if (!strcmp(param, "-embtex") || ! strcmp(param, "--embed-textures")) {
|
else if (!strcmp(param, "-embtex") || ! strcmp(param, "--embed-textures")) {
|
||||||
fill.ppFlags |= aiProcess_EmbedTextures;
|
fill.ppFlags |= aiProcess_EmbedTextures;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(param, "-gs") || ! strcmp(param, "--global-scale")) {
|
||||||
|
fill.ppFlags |= aiProcess_GlobalScale;
|
||||||
|
}
|
||||||
else if (! strncmp( param, "-c",2) || ! strncmp( param, "--config=",9)) {
|
else if (! strncmp( param, "-c",2) || ! strncmp( param, "--config=",9)) {
|
||||||
const unsigned int ofs = (params[i][1] == '-' ? 9 : 2);
|
const unsigned int ofs = (params[i][1] == '-' ? 9 : 2);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue