Merge remote-tracking branch 'upstream/master'

pull/3194/head
RichardTea 2020-03-30 13:38:54 +01:00
commit d276044ad3
251 changed files with 24470 additions and 22438 deletions

View File

@ -70,8 +70,8 @@ IncludeCategories:
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: true
IndentPPDirectives: AfterHash
IndentCaseLabels: false
#IndentPPDirectives: AfterHash
IndentWidth: 4
# IndentWrappedFunctionNames: false
# JavaScriptQuotes: Leave

32
.github/workflows/ccpp.yml vendored 100644
View File

@ -0,0 +1,32 @@
name: C/C++ CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: configure
run: cmake CMakeLists.txt
- name: build
run: cmake --build .
- name: test
run: cd bin && ./unit
mac:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- name: configure
run: cmake CMakeLists.txt
- name: build
run: cmake --build .
- name: test
run: cd bin && ./unit

View File

@ -39,9 +39,9 @@ SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW)
CMAKE_MINIMUM_REQUIRED( VERSION 3.0 )
# Toggles the use of the hunter package manager
option(HUNTER_ENABLED "Enable Hunter package manager support" OFF)
option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.23.176.tar.gz"
@ -60,7 +60,7 @@ OPTION( BUILD_SHARED_LIBS
ON
)
OPTION( BUILD_FRAMEWORK
OPTION( ASSIMP_BUILD_FRAMEWORK
"Build package as Mac OS X Framework bundle."
OFF
)
@ -101,7 +101,7 @@ OPTION ( ASSIMP_COVERALLS
OFF
)
OPTION( ASSIMP_INSTALL
"DIsable this if you want to use assimp as a submodule."
"Disable this if you want to use assimp as a submodule."
ON
)
OPTION ( ASSIMP_ERROR_MAX
@ -120,25 +120,25 @@ OPTION ( ASSIMP_UBSAN
"Enable Undefined Behavior sanitizer."
OFF
)
OPTION ( SYSTEM_IRRXML
OPTION ( ASSIMP_SYSTEM_IRRXML
"Use system installed Irrlicht/IrrXML library."
OFF
)
OPTION ( BUILD_DOCS
OPTION ( ASSIMP_BUILD_DOCS
"Build documentation using Doxygen."
OFF
)
OPTION( INJECT_DEBUG_POSTFIX
OPTION( ASSIMP_INJECT_DEBUG_POSTFIX
"Inject debug postfix in .a/.so/.dll lib names"
ON
)
OPTION ( IGNORE_GIT_HASH
OPTION ( ASSIMP_IGNORE_GIT_HASH
"Don't call git to get the hash."
OFF
)
IF (IOS AND NOT HUNTER_ENABLED)
IF (IOS AND NOT ASSIMP_HUNTER_ENABLED)
IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release")
ENDIF ()
@ -161,7 +161,7 @@ IF(MSVC)
ENDIF()
ENDIF()
IF (BUILD_FRAMEWORK)
IF (ASSIMP_BUILD_FRAMEWORK)
SET (BUILD_SHARED_LIBS ON)
MESSAGE(STATUS "Framework bundle building enabled")
ENDIF()
@ -181,12 +181,12 @@ SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VER
SET (ASSIMP_SOVERSION 5)
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
if(NOT HUNTER_ENABLED)
if(NOT ASSIMP_HUNTER_ENABLED)
# Enable C++11 support globally
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
endif()
IF(NOT IGNORE_GIT_HASH)
IF(NOT ASSIMP_IGNORE_GIT_HASH)
# Get the current working branch
EXECUTE_PROCESS(
COMMAND git rev-parse --abbrev-ref HEAD
@ -245,7 +245,7 @@ ENDIF()
# Grouped compiler settings
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
IF(NOT HUNTER_ENABLED)
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++0x ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
ENDIF()
@ -255,15 +255,14 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
SET(LIBSTDC++_LIBRARIES -lstdc++)
ELSEIF(MSVC)
# enable multi-core compilation with MSVC
ADD_COMPILE_OPTIONS(/MP)
ADD_COMPILE_OPTIONS( /bigobj )
ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX )
# disable "elements of array '' will be default initialized" warning on MSVC2013
IF(MSVC12)
ADD_COMPILE_OPTIONS(/wd4351)
ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
IF(NOT HUNTER_ENABLED)
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
ENDIF()
@ -275,7 +274,7 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
ELSEIF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3)
message(WARNING "MinGW is old, if you experience errors, update MinGW.")
ENDIF()
IF(NOT HUNTER_ENABLED)
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
ENDIF()
@ -284,7 +283,7 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
ADD_DEFINITIONS( -U__STRICT_ANSI__ )
ENDIF()
IF ( IOS AND NOT HUNTER_ENABLED)
IF ( IOS AND NOT ASSIMP_HUNTER_ENABLED)
IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -Og")
@ -361,7 +360,7 @@ SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
IF (INJECT_DEBUG_POSTFIX AND (is_multi_config OR CMAKE_BUILD_TYPE STREQUAL "Debug"))
IF (ASSIMP_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")
ELSE()
SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools")
@ -374,7 +373,7 @@ IF (NOT TARGET uninstall)
ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
ENDIF()
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
set(INCLUDE_INSTALL_DIR "include")
@ -441,18 +440,18 @@ ELSE()
DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
ENDIF()
IF( BUILD_DOCS )
IF( ASSIMP_BUILD_DOCS )
ADD_SUBDIRECTORY(doc)
ENDIF()
# Look for system installed irrXML
IF ( SYSTEM_IRRXML )
IF ( ASSIMP_SYSTEM_IRRXML )
FIND_PACKAGE( IrrXML REQUIRED )
ENDIF()
# Search for external dependencies, and build them from source if not found
# Search for zlib
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(ZLIB)
find_package(ZLIB CONFIG REQUIRED)
@ -576,7 +575,7 @@ ELSE ()
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
ENDIF ()
IF(NOT HUNTER_ENABLED)
IF(NOT ASSIMP_HUNTER_ENABLED)
ADD_SUBDIRECTORY(contrib)
ENDIF()

View File

@ -2,6 +2,7 @@ Open Asset Import Library (assimp)
==================================
A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
### Current project status ###
![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
[![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
<a href="https://scan.coverity.com/projects/5607">

View File

@ -80,7 +80,7 @@ namespace {
{
chunk_start_pos = writer.GetCurrentPos();
writer.PutU2(chunk_type);
writer.PutU4(CHUNK_SIZE_NOT_SET);
writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET);
}
~ChunkWriter() {
@ -193,21 +193,21 @@ Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, co
CollectTrafos(scene->mRootNode, trafos);
CollectMeshes(scene->mRootNode, meshes);
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAIN);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_OBJMESH);
WriteMaterials();
WriteMeshes();
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
ChunkWriter curChunk1(writer, Discreet3DS::CHUNK_MASTER_SCALE);
writer.PutF4(1.0f);
}
}
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
WriteHierarchy(*scene->mRootNode, -1, -1);
}
}
@ -223,9 +223,9 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling
{
// 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_TRACKINFO);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
// Assimp node names are unique and distinct from all mesh-node
// names we generate; thus we can use them as-is
@ -237,7 +237,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling
int16_t hierarchy_pos = static_cast<int16_t>(seq);
if (sibling_level != -1) {
hierarchy_pos = sibling_level;
hierarchy_pos =(uint16_t) sibling_level;
}
// Write the hierarchy position
@ -262,7 +262,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling
const unsigned int mesh_idx = node.mMeshes[i];
const aiMesh& mesh = *scene->mMeshes[mesh_idx];
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKINFO);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
WriteString(GetMeshName(mesh, mesh_idx, node));
@ -279,7 +279,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling
void Discreet3DSExporter::WriteMaterials()
{
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
const aiMaterial& mat = *scene->mMaterials[i];
{
@ -290,22 +290,22 @@ void Discreet3DSExporter::WriteMaterials()
aiColor3D color;
if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
WriteColor(color);
}
@ -389,14 +389,14 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type
ChunkWriter chunk(writer, chunk_flags);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAPFILE);
WriteString(path);
}
WritePercentChunk(blend);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
uint16_t val = 0; // WRAP
if (map_mode[0] == aiTextureMapMode_Mirror) {
val = 0x2;
@ -447,7 +447,7 @@ void Discreet3DSExporter::WriteMeshes()
// Vertices in world space
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_VERTLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count);
@ -461,7 +461,7 @@ void Discreet3DSExporter::WriteMeshes()
// UV coordinates
if (mesh.HasTextureCoords(0)) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAPLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count);
@ -474,7 +474,7 @@ void Discreet3DSExporter::WriteMeshes()
// Faces (indices)
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACELIST);
ai_assert(mesh.mNumFaces <= 0xffff);
@ -513,7 +513,7 @@ void Discreet3DSExporter::WriteMeshes()
// Transformation matrix by which the mesh vertices have been pre-transformed with.
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX);
for (unsigned int r = 0; r < 4; ++r) {
for (unsigned int c = 0; c < 3; ++c) {
writer.PutF4(trafo[r][c]);
@ -526,7 +526,7 @@ void Discreet3DSExporter::WriteMeshes()
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACEMAT);
const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
WriteString(name);
@ -559,7 +559,7 @@ void Discreet3DSExporter::WriteString(const aiString& s) {
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_RGBF);
writer.PutF4(color.r);
writer.PutF4(color.g);
writer.PutF4(color.b);
@ -567,13 +567,13 @@ void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WritePercentChunk(float f) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_PERCENTF);
writer.PutF4(f);
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WritePercentChunk(double f) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTD);
ChunkWriter ccurChunkhunk(writer, Discreet3DS::CHUNK_PERCENTD);
writer.PutF8(f);
}

View File

@ -45,18 +45,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_3DSFILEHELPER_H_INC
#define AI_3DSFILEHELPER_H_INC
#include <assimp/SpatialSort.h>
#include <assimp/SmoothingGroups.h>
#include <assimp/SpatialSort.h>
#include <assimp/StringUtils.h>
#include <assimp/qnan.h>
#include <assimp/material.h>
#include <assimp/anim.h>
#include <assimp/camera.h>
#include <assimp/light.h>
#include <assimp/anim.h>
#include <assimp/material.h>
#include <assimp/qnan.h>
#include <stdio.h> //sprintf
namespace Assimp {
namespace D3DS {
namespace Assimp {
namespace D3DS {
#include <assimp/Compiler/pushpack1.h>
@ -77,15 +77,13 @@ private:
public:
//! data structure for a single chunk in a .3ds file
struct Chunk {
uint16_t Flag;
uint32_t Size;
uint16_t Flag;
uint32_t Size;
} PACK_STRUCT;
//! Used for shading field in material3ds structure
//! From AutoDesk 3ds SDK
typedef enum
{
typedef enum {
// translated to gouraud shading with wireframe active
Wire = 0x0,
@ -109,59 +107,57 @@ public:
} shadetype3ds;
// Flags for animated keys
enum
{
KEY_USE_TENS = 0x1,
KEY_USE_CONT = 0x2,
KEY_USE_BIAS = 0x4,
KEY_USE_EASE_TO = 0x8,
KEY_USE_EASE_FROM = 0x10
} ;
enum {
KEY_USE_TENS = 0x1,
KEY_USE_CONT = 0x2,
KEY_USE_BIAS = 0x4,
KEY_USE_EASE_TO = 0x8,
KEY_USE_EASE_FROM = 0x10
};
enum
{
enum {
// ********************************************************************
// Basic chunks which can be found everywhere in the file
CHUNK_VERSION = 0x0002,
CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B
CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B
CHUNK_VERSION = 0x0002,
CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B
CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B
// Linear color values (gamma = 2.2?)
CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B
CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B
CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B
CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B
CHUNK_PERCENTW = 0x0030, // int2 percentage
CHUNK_PERCENTF = 0x0031, // float4 percentage
CHUNK_PERCENTD = 0x0032, // float8 percentage
CHUNK_PERCENTW = 0x0030, // int2 percentage
CHUNK_PERCENTF = 0x0031, // float4 percentage
CHUNK_PERCENTD = 0x0032, // float8 percentage
// ********************************************************************
// Prj master chunk
CHUNK_PRJ = 0xC23D,
CHUNK_PRJ = 0xC23D,
// MDLI master chunk
CHUNK_MLI = 0x3DAA,
CHUNK_MLI = 0x3DAA,
// Primary main chunk of the .3ds file
CHUNK_MAIN = 0x4D4D,
CHUNK_MAIN = 0x4D4D,
// Mesh main chunk
CHUNK_OBJMESH = 0x3D3D,
CHUNK_OBJMESH = 0x3D3D,
// Specifies the background color of the .3ds file
// This is passed through the material system for
// viewing purposes.
CHUNK_BKGCOLOR = 0x1200,
CHUNK_BKGCOLOR = 0x1200,
// Specifies the ambient base color of the scene.
// This is added to all materials in the file
CHUNK_AMBCOLOR = 0x2100,
CHUNK_AMBCOLOR = 0x2100,
// Specifies the background image for the whole scene
// This value is passed through the material system
// to the viewer
CHUNK_BIT_MAP = 0x1100,
CHUNK_BIT_MAP_EXISTS = 0x1101,
CHUNK_BIT_MAP = 0x1100,
CHUNK_BIT_MAP_EXISTS = 0x1101,
// ********************************************************************
// Viewport related stuff. Ignored
@ -177,171 +173,222 @@ public:
// ********************************************************************
// Mesh chunks
CHUNK_OBJBLOCK = 0x4000,
CHUNK_TRIMESH = 0x4100,
CHUNK_VERTLIST = 0x4110,
CHUNK_OBJBLOCK = 0x4000,
CHUNK_TRIMESH = 0x4100,
CHUNK_VERTLIST = 0x4110,
CHUNK_VERTFLAGS = 0x4111,
CHUNK_FACELIST = 0x4120,
CHUNK_FACEMAT = 0x4130,
CHUNK_MAPLIST = 0x4140,
CHUNK_SMOOLIST = 0x4150,
CHUNK_TRMATRIX = 0x4160,
CHUNK_FACELIST = 0x4120,
CHUNK_FACEMAT = 0x4130,
CHUNK_MAPLIST = 0x4140,
CHUNK_SMOOLIST = 0x4150,
CHUNK_TRMATRIX = 0x4160,
CHUNK_MESHCOLOR = 0x4165,
CHUNK_TXTINFO = 0x4170,
CHUNK_LIGHT = 0x4600,
CHUNK_CAMERA = 0x4700,
CHUNK_TXTINFO = 0x4170,
CHUNK_LIGHT = 0x4600,
CHUNK_CAMERA = 0x4700,
CHUNK_HIERARCHY = 0x4F00,
// Specifies the global scaling factor. This is applied
// to the root node's transformation matrix
CHUNK_MASTER_SCALE = 0x0100,
CHUNK_MASTER_SCALE = 0x0100,
// ********************************************************************
// Material chunks
CHUNK_MAT_MATERIAL = 0xAFFF,
CHUNK_MAT_MATERIAL = 0xAFFF,
// asciiz containing the name of the material
CHUNK_MAT_MATNAME = 0xA000,
CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk
CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk
CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk
// asciiz containing the name of the material
CHUNK_MAT_MATNAME = 0xA000,
CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk
CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk
CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk
// Specifies the shininess of the material
// followed by percentage chunk
CHUNK_MAT_SHININESS = 0xA040,
CHUNK_MAT_SHININESS_PERCENT = 0xA041 ,
// Specifies the shininess of the material
// followed by percentage chunk
CHUNK_MAT_SHININESS = 0xA040,
CHUNK_MAT_SHININESS_PERCENT = 0xA041,
// Specifies the shading mode to be used
// followed by a short
CHUNK_MAT_SHADING = 0xA100,
// Specifies the shading mode to be used
// followed by a short
CHUNK_MAT_SHADING = 0xA100,
// NOTE: Emissive color (self illumination) seems not
// to be a color but a single value, type is unknown.
// Make the parser accept both of them.
// followed by percentage chunk (?)
CHUNK_MAT_SELF_ILLUM = 0xA080,
// NOTE: Emissive color (self illumination) seems not
// to be a color but a single value, type is unknown.
// Make the parser accept both of them.
// followed by percentage chunk (?)
CHUNK_MAT_SELF_ILLUM = 0xA080,
// Always followed by percentage chunk (?)
CHUNK_MAT_SELF_ILPCT = 0xA084,
// Always followed by percentage chunk (?)
CHUNK_MAT_SELF_ILPCT = 0xA084,
// Always followed by percentage chunk
CHUNK_MAT_TRANSPARENCY = 0xA050,
// Always followed by percentage chunk
CHUNK_MAT_TRANSPARENCY = 0xA050,
// Diffuse texture channel 0
CHUNK_MAT_TEXTURE = 0xA200,
// Diffuse texture channel 0
CHUNK_MAT_TEXTURE = 0xA200,
// Contains opacity information for each texel
CHUNK_MAT_OPACMAP = 0xA210,
// Contains opacity information for each texel
CHUNK_MAT_OPACMAP = 0xA210,
// Contains a reflection map to be used to reflect
// the environment. This is partially supported.
CHUNK_MAT_REFLMAP = 0xA220,
// Contains a reflection map to be used to reflect
// the environment. This is partially supported.
CHUNK_MAT_REFLMAP = 0xA220,
// Self Illumination map (emissive colors)
CHUNK_MAT_SELFIMAP = 0xA33d,
// Self Illumination map (emissive colors)
CHUNK_MAT_SELFIMAP = 0xA33d,
// Bumpmap. Not specified whether it is a heightmap
// or a normal map. Assme it is a heightmap since
// artist normally prefer this format.
CHUNK_MAT_BUMPMAP = 0xA230,
// Bumpmap. Not specified whether it is a heightmap
// or a normal map. Assme it is a heightmap since
// artist normally prefer this format.
CHUNK_MAT_BUMPMAP = 0xA230,
// Specular map. Seems to influence the specular color
CHUNK_MAT_SPECMAP = 0xA204,
// Specular map. Seems to influence the specular color
CHUNK_MAT_SPECMAP = 0xA204,
// Holds shininess data.
CHUNK_MAT_MAT_SHINMAP = 0xA33C,
// Holds shininess data.
CHUNK_MAT_MAT_SHINMAP = 0xA33C,
// Scaling in U/V direction.
// (need to gen separate UV coordinate set
// and do this by hand)
CHUNK_MAT_MAP_USCALE = 0xA354,
CHUNK_MAT_MAP_VSCALE = 0xA356,
// Scaling in U/V direction.
// (need to gen separate UV coordinate set
// and do this by hand)
CHUNK_MAT_MAP_USCALE = 0xA354,
CHUNK_MAT_MAP_VSCALE = 0xA356,
// Translation in U/V direction.
// (need to gen separate UV coordinate set
// and do this by hand)
CHUNK_MAT_MAP_UOFFSET = 0xA358,
CHUNK_MAT_MAP_VOFFSET = 0xA35a,
// Translation in U/V direction.
// (need to gen separate UV coordinate set
// and do this by hand)
CHUNK_MAT_MAP_UOFFSET = 0xA358,
CHUNK_MAT_MAP_VOFFSET = 0xA35a,
// UV-coordinates rotation around the z-axis
// Assumed to be in radians.
CHUNK_MAT_MAP_ANG = 0xA35C,
// UV-coordinates rotation around the z-axis
// Assumed to be in radians.
CHUNK_MAT_MAP_ANG = 0xA35C,
// Tiling flags for 3DS files
CHUNK_MAT_MAP_TILING = 0xa351,
// Tiling flags for 3DS files
CHUNK_MAT_MAP_TILING = 0xa351,
// Specifies the file name of a texture
CHUNK_MAPFILE = 0xA300,
// Specifies the file name of a texture
CHUNK_MAPFILE = 0xA300,
// Specifies whether a materail requires two-sided rendering
CHUNK_MAT_TWO_SIDE = 0xA081,
// Specifies whether a materail requires two-sided rendering
CHUNK_MAT_TWO_SIDE = 0xA081,
// ********************************************************************
// Main keyframer chunk. Contains translation/rotation/scaling data
CHUNK_KEYFRAMER = 0xB000,
CHUNK_KEYFRAMER = 0xB000,
// Supported sub chunks
CHUNK_TRACKINFO = 0xB002,
CHUNK_TRACKOBJNAME = 0xB010,
CHUNK_TRACKDUMMYOBJNAME = 0xB011,
CHUNK_TRACKPIVOT = 0xB013,
CHUNK_TRACKPOS = 0xB020,
CHUNK_TRACKROTATE = 0xB021,
CHUNK_TRACKSCALE = 0xB022,
CHUNK_TRACKINFO = 0xB002,
CHUNK_TRACKOBJNAME = 0xB010,
CHUNK_TRACKDUMMYOBJNAME = 0xB011,
CHUNK_TRACKPIVOT = 0xB013,
CHUNK_TRACKPOS = 0xB020,
CHUNK_TRACKROTATE = 0xB021,
CHUNK_TRACKSCALE = 0xB022,
// ********************************************************************
// Keyframes for various other stuff in the file
// Partially ignored
CHUNK_AMBIENTKEY = 0xB001,
CHUNK_TRACKMORPH = 0xB026,
CHUNK_TRACKHIDE = 0xB029,
CHUNK_OBJNUMBER = 0xB030,
CHUNK_TRACKCAMERA = 0xB003,
CHUNK_TRACKFOV = 0xB023,
CHUNK_TRACKROLL = 0xB024,
CHUNK_TRACKCAMTGT = 0xB004,
CHUNK_TRACKLIGHT = 0xB005,
CHUNK_TRACKLIGTGT = 0xB006,
CHUNK_TRACKSPOTL = 0xB007,
CHUNK_FRAMES = 0xB008,
CHUNK_AMBIENTKEY = 0xB001,
CHUNK_TRACKMORPH = 0xB026,
CHUNK_TRACKHIDE = 0xB029,
CHUNK_OBJNUMBER = 0xB030,
CHUNK_TRACKCAMERA = 0xB003,
CHUNK_TRACKFOV = 0xB023,
CHUNK_TRACKROLL = 0xB024,
CHUNK_TRACKCAMTGT = 0xB004,
CHUNK_TRACKLIGHT = 0xB005,
CHUNK_TRACKLIGTGT = 0xB006,
CHUNK_TRACKSPOTL = 0xB007,
CHUNK_FRAMES = 0xB008,
// ********************************************************************
// light sub-chunks
CHUNK_DL_OFF = 0x4620,
CHUNK_DL_OUTER_RANGE = 0x465A,
CHUNK_DL_INNER_RANGE = 0x4659,
CHUNK_DL_MULTIPLIER = 0x465B,
CHUNK_DL_EXCLUDE = 0x4654,
CHUNK_DL_ATTENUATE = 0x4625,
CHUNK_DL_SPOTLIGHT = 0x4610,
CHUNK_DL_OFF = 0x4620,
CHUNK_DL_OUTER_RANGE = 0x465A,
CHUNK_DL_INNER_RANGE = 0x4659,
CHUNK_DL_MULTIPLIER = 0x465B,
CHUNK_DL_EXCLUDE = 0x4654,
CHUNK_DL_ATTENUATE = 0x4625,
CHUNK_DL_SPOTLIGHT = 0x4610,
// camera sub-chunks
CHUNK_CAM_RANGES = 0x4720
CHUNK_CAM_RANGES = 0x4720
};
};
// ---------------------------------------------------------------------------
/** Helper structure representing a 3ds mesh face */
struct Face : public FaceWithSmoothingGroup
{
struct Face : public FaceWithSmoothingGroup {
};
#ifdef _WIN32
# pragma warning(disable : 4315)
#endif
// ---------------------------------------------------------------------------
/** Helper structure representing a texture */
struct Texture {
//! Default constructor
Texture() AI_NO_EXCEPT
: mOffsetU (0.0)
, mOffsetV (0.0)
, mScaleU (1.0)
, mScaleV (1.0)
, mRotation (0.0)
, mMapMode (aiTextureMapMode_Wrap)
, bPrivate()
, iUVSrc (0) {
: mTextureBlend(0.0f),
mMapName(),
mOffsetU(0.0),
mOffsetV(0.0),
mScaleU(1.0),
mScaleV(1.0),
mRotation(0.0),
mMapMode(aiTextureMapMode_Wrap),
bPrivate(),
iUVSrc(0) {
mTextureBlend = get_qnan();
}
Texture(const Texture &other) :
mTextureBlend(other.mTextureBlend),
mMapName(other.mMapName),
mOffsetU(other.mOffsetU),
mOffsetV(other.mOffsetV),
mScaleU(other.mScaleU),
mScaleV(other.mScaleV),
mRotation(other.mRotation),
mMapMode(other.mMapMode),
bPrivate(other.bPrivate),
iUVSrc(other.iUVSrc) {
// empty
}
Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)),
mMapName(std::move(other.mMapName)),
mOffsetU(std::move(other.mOffsetU)),
mOffsetV(std::move(other.mOffsetV)),
mScaleU(std::move(other.mScaleU)),
mScaleV(std::move(other.mScaleV)),
mRotation(std::move(other.mRotation)),
mMapMode(std::move(other.mMapMode)),
bPrivate(std::move(other.bPrivate)),
iUVSrc(std::move(other.iUVSrc)) {
// empty
}
Texture &operator=(Texture &&other) AI_NO_EXCEPT {
if (this == &other) {
return *this;
}
mTextureBlend = std::move(other.mTextureBlend);
mMapName = std::move(other.mMapName);
mOffsetU = std::move(other.mOffsetU);
mOffsetV = std::move(other.mOffsetV);
mScaleU = std::move(other.mScaleU);
mScaleV = std::move(other.mScaleV);
mRotation = std::move(other.mRotation);
mMapMode = std::move(other.mMapMode);
bPrivate = std::move(other.bPrivate);
iUVSrc = std::move(other.iUVSrc);
return *this;
}
//! Specifies the blend factor for the texture
ai_real mTextureBlend;
@ -367,55 +414,59 @@ struct Texture {
// ---------------------------------------------------------------------------
/** Helper structure representing a 3ds material */
struct Material
{
struct Material {
//! Default constructor has been deleted
Material() = delete;
//! Constructor with explicit name
explicit Material(const std::string &name)
: mName(name)
, mDiffuse ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
, mSpecularExponent ( ai_real( 0.0 ) )
, mShininessStrength ( ai_real( 1.0 ) )
, mShading(Discreet3DS::Gouraud)
, mTransparency ( ai_real( 1.0 ) )
, mBumpHeight ( ai_real( 1.0 ) )
, mTwoSided (false)
{
Material() :
mName(),
mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
mSpecularExponent(ai_real(0.0)),
mShininessStrength(ai_real(1.0)),
mShading(Discreet3DS::Gouraud),
mTransparency(ai_real(1.0)),
mBumpHeight(ai_real(1.0)),
mTwoSided(false) {
// empty
}
//! Constructor with explicit name
explicit Material(const std::string &name) :
mName(name),
mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
mSpecularExponent(ai_real(0.0)),
mShininessStrength(ai_real(1.0)),
mShading(Discreet3DS::Gouraud),
mTransparency(ai_real(1.0)),
mBumpHeight(ai_real(1.0)),
mTwoSided(false) {
// empty
}
Material(const Material &other) = default;
Material(const Material &other) = default;
Material &operator=(const Material &other) = default;
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) AI_NO_EXCEPT
: mName(std::move(other.mName))
, mDiffuse(std::move(other.mDiffuse))
, mSpecularExponent(std::move(other.mSpecularExponent))
, mShininessStrength(std::move(other.mShininessStrength))
, mSpecular(std::move(other.mSpecular))
, mAmbient(std::move(other.mAmbient))
, mShading(std::move(other.mShading))
, mTransparency(std::move(other.mTransparency))
, sTexDiffuse(std::move(other.sTexDiffuse))
, sTexOpacity(std::move(other.sTexOpacity))
, sTexSpecular(std::move(other.sTexSpecular))
, sTexReflective(std::move(other.sTexReflective))
, sTexBump(std::move(other.sTexBump))
, sTexEmissive(std::move(other.sTexEmissive))
, sTexShininess(std::move(other.sTexShininess))
, mBumpHeight(std::move(other.mBumpHeight))
, mEmissive(std::move(other.mEmissive))
, sTexAmbient(std::move(other.sTexAmbient))
, mTwoSided(std::move(other.mTwoSided))
{
: mName(std::move(other.mName)),
mDiffuse(std::move(other.mDiffuse)),
mSpecularExponent(std::move(other.mSpecularExponent)),
mShininessStrength(std::move(other.mShininessStrength)),
mSpecular(std::move(other.mSpecular)),
mAmbient(std::move(other.mAmbient)),
mShading(std::move(other.mShading)),
mTransparency(std::move(other.mTransparency)),
sTexDiffuse(std::move(other.sTexDiffuse)),
sTexOpacity(std::move(other.sTexOpacity)),
sTexSpecular(std::move(other.sTexSpecular)),
sTexReflective(std::move(other.sTexReflective)),
sTexBump(std::move(other.sTexBump)),
sTexEmissive(std::move(other.sTexEmissive)),
sTexShininess(std::move(other.sTexShininess)),
mBumpHeight(std::move(other.mBumpHeight)),
mEmissive(std::move(other.mEmissive)),
sTexAmbient(std::move(other.sTexAmbient)),
mTwoSided(std::move(other.mTwoSided)) {
}
Material &operator=(Material &&other) AI_NO_EXCEPT {
if (this == &other) {
return *this;
@ -444,9 +495,9 @@ struct Material
return *this;
}
virtual ~Material() {}
virtual ~Material() {
// empty
}
//! Name of the material
std::string mName;
@ -491,18 +542,15 @@ struct Material
// ---------------------------------------------------------------------------
/** Helper structure to represent a 3ds file mesh */
struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
{
struct Mesh : public MeshWithSmoothingGroups<D3DS::Face> {
//! Default constructor has been deleted
Mesh() = delete;
//! Constructor with explicit name
explicit Mesh(const std::string &name)
: mName(name)
{
explicit Mesh(const std::string &name) :
mName(name) {
}
//! Name of the mesh
std::string mName;
@ -519,62 +567,48 @@ struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
// ---------------------------------------------------------------------------
/** Float key - quite similar to aiVectorKey and aiQuatKey. Both are in the
C-API, so it would be difficult to make them a template. */
struct aiFloatKey
{
double mTime; ///< The time of this key
ai_real mValue; ///< The value of this key
struct aiFloatKey {
double mTime; ///< The time of this key
ai_real mValue; ///< The value of this key
#ifdef __cplusplus
// time is not compared
bool operator == (const aiFloatKey& o) const
{return o.mValue == this->mValue;}
bool operator==(const aiFloatKey &o) const { return o.mValue == this->mValue; }
bool operator != (const aiFloatKey& o) const
{return o.mValue != this->mValue;}
bool operator!=(const aiFloatKey &o) const { return o.mValue != this->mValue; }
// Only time is compared. This operator is defined
// for use with std::sort
bool operator < (const aiFloatKey& o) const
{return mTime < o.mTime;}
bool operator<(const aiFloatKey &o) const { return mTime < o.mTime; }
bool operator > (const aiFloatKey& o) const
{return mTime > o.mTime;}
bool operator>(const aiFloatKey &o) const { return mTime > o.mTime; }
#endif
};
// ---------------------------------------------------------------------------
/** Helper structure to represent a 3ds file node */
struct Node
{
struct Node {
Node() = delete;
explicit Node(const std::string &name)
: mParent(NULL)
, mName(name)
, mInstanceNumber(0)
, mHierarchyPos (0)
, mHierarchyIndex (0)
, mInstanceCount (1)
{
aRotationKeys.reserve (20);
aPositionKeys.reserve (20);
aScalingKeys.reserve (20);
explicit Node(const std::string &name) :
mParent(NULL), mName(name), mInstanceNumber(0), mHierarchyPos(0), mHierarchyIndex(0), mInstanceCount(1) {
aRotationKeys.reserve(20);
aPositionKeys.reserve(20);
aScalingKeys.reserve(20);
}
~Node()
{
for (unsigned int i = 0; i < mChildren.size();++i)
~Node() {
for (unsigned int i = 0; i < mChildren.size(); ++i)
delete mChildren[i];
}
//! Pointer to the parent node
Node* mParent;
Node *mParent;
//! Holds all child nodes
std::vector<Node*> mChildren;
std::vector<Node *> mChildren;
//! Name of the node
std::string mName;
@ -600,13 +634,12 @@ struct Node
//! Scaling keys loaded from the file
std::vector<aiVectorKey> aScalingKeys;
// For target lights (spot lights and directional lights):
// The position of the target
std::vector< aiVectorKey > aTargetPositionKeys;
std::vector<aiVectorKey> aTargetPositionKeys;
// For cameras: the camera roll angle
std::vector< aiFloatKey > aCameraRollKeys;
std::vector<aiFloatKey> aCameraRollKeys;
//! Pivot position loaded from the file
aiVector3D vPivot;
@ -616,8 +649,7 @@ struct Node
//! Add a child node, setup the right parent node for it
//! \param pc Node to be 'adopted'
inline Node& push_back(Node* pc)
{
inline Node &push_back(Node *pc) {
mChildren.push_back(pc);
pc->mParent = this;
return *this;
@ -625,8 +657,7 @@ struct Node
};
// ---------------------------------------------------------------------------
/** Helper structure analogue to aiScene */
struct Scene
{
struct Scene {
//! List of all materials loaded
//! NOTE: 3ds references materials globally
std::vector<Material> mMaterials;
@ -635,17 +666,16 @@ struct Scene
std::vector<Mesh> mMeshes;
//! List of all cameras loaded
std::vector<aiCamera*> mCameras;
std::vector<aiCamera *> mCameras;
//! List of all lights loaded
std::vector<aiLight*> mLights;
std::vector<aiLight *> mLights;
//! Pointer to the root node of the scene
// --- moved to main class
// Node* pcRootNode;
};
} // end of namespace D3DS
} // end of namespace Assimp

View File

@ -158,13 +158,13 @@ void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/)
void Discreet3DSImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
StreamReaderLE theStream(pIOHandler->Open(pFile,"rb"));
// We should have at least one chunk
if (stream.GetRemainingSize() < 16) {
if (theStream.GetRemainingSize() < 16) {
throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile);
}
this->stream = &stream;
this->stream = &theStream;
// Allocate our temporary 3DS representation
D3DS::Scene _scene;
@ -599,16 +599,19 @@ void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCur
// ------------------------------------------------------------------------------------------------
// Find a node with a specific name in the import hierarchy
D3DS::Node* FindNode(D3DS::Node* root, const std::string& name)
{
if (root->mName == name)
D3DS::Node* FindNode(D3DS::Node* root, const std::string& name) {
if (root->mName == name) {
return root;
for (std::vector<D3DS::Node*>::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) {
D3DS::Node* nd;
if (( nd = FindNode(*it,name)))
return nd;
}
return NULL;
for (std::vector<D3DS::Node*>::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) {
D3DS::Node *nd = FindNode(*it, name);
if (nullptr != nd) {
return nd;
}
}
return nullptr;
}
// ------------------------------------------------------------------------------------------------

View File

@ -256,13 +256,13 @@ void D3MFExporter::writeBaseMaterials() {
tmp.clear();
hexDiffuseColor = "#";
tmp = DecimalToHexa( color.r );
tmp = DecimalToHexa( (ai_real) color.r );
hexDiffuseColor += tmp;
tmp = DecimalToHexa( color.g );
tmp = DecimalToHexa((ai_real)color.g);
hexDiffuseColor += tmp;
tmp = DecimalToHexa( color.b );
tmp = DecimalToHexa((ai_real)color.b);
hexDiffuseColor += tmp;
tmp = DecimalToHexa( color.a );
tmp = DecimalToHexa((ai_real)color.a);
hexDiffuseColor += tmp;
} else {
hexDiffuseColor = "#FFFFFFFF";

File diff suppressed because it is too large Load Diff

View File

@ -68,8 +68,6 @@ public:
AC3DImporter();
~AC3DImporter();
// Represents an AC3D material
struct Material
{
@ -245,8 +243,6 @@ private:
aiMaterial& matDest);
private:
// points to the next data line
const char* buffer;
@ -268,7 +264,7 @@ private:
std::vector<aiLight*>* mLights;
// name counters
unsigned int lights, groups, polys, worlds;
unsigned int mLightsCounter, mGroupsCounter, mPolysCounter, mWorldsCounter;
};
} // end of namespace Assimp

View File

@ -465,7 +465,7 @@ std::list<unsigned int> mesh_idx;
{
auto VertexIndex_GetMinimal = [](const std::list<SComplexFace>& pFaceList, const size_t* pBiggerThan) -> size_t
{
size_t rv;
size_t rv=0;
if(pBiggerThan != nullptr)
{

View File

@ -80,7 +80,18 @@ struct Material : public D3DS::Material
}
Material(const Material &other) = default;
Material &operator=(const Material &other) = default;
Material &operator=(const Material &other) {
if (this == &other) {
return *this;
}
avSubMaterials = other.avSubMaterials;
pcInstance = other.pcInstance;
bNeed = other.bNeed;
return *this;
}
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
@ -94,12 +105,12 @@ struct Material : public D3DS::Material
}
Material &operator=(Material &&other) AI_NO_EXCEPT {
Material &operator=( Material &&other) AI_NO_EXCEPT {
if (this == &other) {
return *this;
}
D3DS::Material::operator=(std::move(other));
//D3DS::Material::operator=(std::move(other));
avSubMaterials = std::move(other.avSubMaterials);
pcInstance = std::move(other.pcInstance);

View File

@ -49,19 +49,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssbinFileWriter.h"
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/IOSystem.hpp>
namespace Assimp {
void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
void ExportSceneAssbin(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) {
DumpSceneToAssbin(
pFile,
"\0", // no command(s).
pIOSystem,
pScene,
false, // shortened?
false); // compressed?
pFile,
"\0", // no command(s).
pIOSystem,
pScene,
false, // shortened?
false); // compressed?
}
} // end of namespace Assimp

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -53,16 +51,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Assbin/AssbinLoader.h"
#include "Common/assbin_chunks.h"
#include <assimp/MemoryIOWrapper.h>
#include <assimp/mesh.h>
#include <assimp/anim.h>
#include <assimp/scene.h>
#include <assimp/importerdesc.h>
#include <assimp/mesh.h>
#include <assimp/scene.h>
#include <memory>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
#include <zlib.h>
#else
# include <contrib/zlib/zlib.h>
#include <contrib/zlib/zlib.h>
#endif
using namespace Assimp;
@ -81,94 +79,97 @@ static const aiImporterDesc desc = {
};
// -----------------------------------------------------------------------------------
const aiImporterDesc* AssbinImporter::GetInfo() const {
const aiImporterDesc *AssbinImporter::GetInfo() const {
return &desc;
}
// -----------------------------------------------------------------------------------
bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const {
IOStream * in = pIOHandler->Open(pFile);
bool AssbinImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
IOStream *in = pIOHandler->Open(pFile);
if (nullptr == in) {
return false;
}
char s[32];
in->Read( s, sizeof(char), 32 );
in->Read(s, sizeof(char), 32);
pIOHandler->Close(in);
return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
return strncmp(s, "ASSIMP.binary-dump.", 19) == 0;
}
// -----------------------------------------------------------------------------------
template <typename T>
T Read(IOStream * stream) {
T Read(IOStream *stream) {
T t;
size_t res = stream->Read( &t, sizeof(T), 1 );
if(res != 1)
size_t res = stream->Read(&t, sizeof(T), 1);
if (res != 1) {
throw DeadlyImportError("Unexpected EOF");
}
return t;
}
// -----------------------------------------------------------------------------------
template <>
aiVector3D Read<aiVector3D>(IOStream * stream) {
aiVector3D Read<aiVector3D>(IOStream *stream) {
aiVector3D v;
v.x = Read<float>(stream);
v.y = Read<float>(stream);
v.z = Read<float>(stream);
v.x = Read<ai_real>(stream);
v.y = Read<ai_real>(stream);
v.z = Read<ai_real>(stream);
return v;
}
// -----------------------------------------------------------------------------------
template <>
aiColor4D Read<aiColor4D>(IOStream * stream) {
aiColor4D Read<aiColor4D>(IOStream *stream) {
aiColor4D c;
c.r = Read<float>(stream);
c.g = Read<float>(stream);
c.b = Read<float>(stream);
c.a = Read<float>(stream);
c.r = Read<ai_real>(stream);
c.g = Read<ai_real>(stream);
c.b = Read<ai_real>(stream);
c.a = Read<ai_real>(stream);
return c;
}
// -----------------------------------------------------------------------------------
template <>
aiQuaternion Read<aiQuaternion>(IOStream * stream) {
aiQuaternion Read<aiQuaternion>(IOStream *stream) {
aiQuaternion v;
v.w = Read<float>(stream);
v.x = Read<float>(stream);
v.y = Read<float>(stream);
v.z = Read<float>(stream);
v.w = Read<ai_real>(stream);
v.x = Read<ai_real>(stream);
v.y = Read<ai_real>(stream);
v.z = Read<ai_real>(stream);
return v;
}
// -----------------------------------------------------------------------------------
template <>
aiString Read<aiString>(IOStream * stream) {
aiString Read<aiString>(IOStream *stream) {
aiString s;
stream->Read(&s.length,4,1);
if(s.length)
stream->Read(s.data,s.length,1);
stream->Read(&s.length, 4, 1);
if (s.length) {
stream->Read(s.data, s.length, 1);
}
s.data[s.length] = 0;
return s;
}
// -----------------------------------------------------------------------------------
template <>
aiVertexWeight Read<aiVertexWeight>(IOStream * stream) {
aiVertexWeight Read<aiVertexWeight>(IOStream *stream) {
aiVertexWeight w;
w.mVertexId = Read<unsigned int>(stream);
w.mWeight = Read<float>(stream);
w.mWeight = Read<ai_real>(stream);
return w;
}
// -----------------------------------------------------------------------------------
template <>
aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream) {
aiMatrix4x4 Read<aiMatrix4x4>(IOStream *stream) {
aiMatrix4x4 m;
for (unsigned int i = 0; i < 4;++i) {
for (unsigned int i2 = 0; i2 < 4;++i2) {
m[i][i2] = Read<float>(stream);
for (unsigned int i = 0; i < 4; ++i) {
for (unsigned int i2 = 0; i2 < 4; ++i2) {
m[i][i2] = Read<ai_real>(stream);
}
}
return m;
@ -176,7 +177,7 @@ aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream) {
// -----------------------------------------------------------------------------------
template <>
aiVectorKey Read<aiVectorKey>(IOStream * stream) {
aiVectorKey Read<aiVectorKey>(IOStream *stream) {
aiVectorKey v;
v.mTime = Read<double>(stream);
v.mValue = Read<aiVector3D>(stream);
@ -185,7 +186,7 @@ aiVectorKey Read<aiVectorKey>(IOStream * stream) {
// -----------------------------------------------------------------------------------
template <>
aiQuatKey Read<aiQuatKey>(IOStream * stream) {
aiQuatKey Read<aiQuatKey>(IOStream *stream) {
aiQuatKey v;
v.mTime = Read<double>(stream);
v.mValue = Read<aiQuaternion>(stream);
@ -194,27 +195,27 @@ aiQuatKey Read<aiQuatKey>(IOStream * stream) {
// -----------------------------------------------------------------------------------
template <typename T>
void ReadArray( IOStream *stream, T * out, unsigned int size) {
ai_assert( nullptr != stream );
ai_assert( nullptr != out );
void ReadArray(IOStream *stream, T *out, unsigned int size) {
ai_assert(nullptr != stream);
ai_assert(nullptr != out);
for (unsigned int i=0; i<size; i++) {
for (unsigned int i = 0; i < size; i++) {
out[i] = Read<T>(stream);
}
}
// -----------------------------------------------------------------------------------
template <typename T>
void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) {
void ReadBounds(IOStream *stream, T * /*p*/, unsigned int n) {
// not sure what to do here, the data isn't really useful.
stream->Seek( sizeof(T) * n, aiOrigin_CUR );
stream->Seek(sizeof(T) * n, aiOrigin_CUR);
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode* parent ) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODE)
void AssbinImporter::ReadBinaryNode(IOStream *stream, aiNode **onode, aiNode *parent) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
std::unique_ptr<aiNode> node(new aiNode());
@ -222,14 +223,13 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode*
node->mTransformation = Read<aiMatrix4x4>(stream);
unsigned numChildren = Read<unsigned int>(stream);
unsigned numMeshes = Read<unsigned int>(stream);
unsigned int nb_metadata = Read<unsigned int>(stream);
unsigned int nb_metadata = Read<unsigned int>(stream);
if(parent) {
if (parent) {
node->mParent = parent;
}
if (numMeshes)
{
if (numMeshes) {
node->mMeshes = new unsigned int[numMeshes];
for (unsigned int i = 0; i < numMeshes; ++i) {
node->mMeshes[i] = Read<unsigned int>(stream);
@ -238,19 +238,19 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode*
}
if (numChildren) {
node->mChildren = new aiNode*[numChildren];
node->mChildren = new aiNode *[numChildren];
for (unsigned int i = 0; i < numChildren; ++i) {
ReadBinaryNode( stream, &node->mChildren[i], node.get() );
ReadBinaryNode(stream, &node->mChildren[i], node.get());
node->mNumChildren++;
}
}
if ( nb_metadata > 0 ) {
if (nb_metadata > 0) {
node->mMetaData = aiMetadata::Alloc(nb_metadata);
for (unsigned int i = 0; i < nb_metadata; ++i) {
node->mMetaData->mKeys[i] = Read<aiString>(stream);
node->mMetaData->mValues[i].mType = (aiMetadataType) Read<uint16_t>(stream);
void* data = nullptr;
node->mMetaData->mValues[i].mType = (aiMetadataType)Read<uint16_t>(stream);
void *data = nullptr;
switch (node->mMetaData->mValues[i].mType) {
case AI_BOOL:
@ -263,7 +263,7 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode*
data = new uint64_t(Read<uint64_t>(stream));
break;
case AI_FLOAT:
data = new float(Read<float>(stream));
data = new ai_real(Read<ai_real>(stream));
break;
case AI_DOUBLE:
data = new double(Read<double>(stream));
@ -281,17 +281,17 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode*
break;
}
node->mMetaData->mValues[i].mData = data;
}
}
node->mMetaData->mValues[i].mData = data;
}
}
*onode = node.release();
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIBONE)
void AssbinImporter::ReadBinaryBone(IOStream *stream, aiBone *b) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIBONE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
b->mName = Read<aiString>(stream);
b->mNumWeights = Read<unsigned int>(stream);
@ -300,23 +300,24 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) {
// for the moment we write dumb min/max values for the bones, too.
// maybe I'll add a better, hash-like solution later
if (shortened) {
ReadBounds(stream,b->mWeights,b->mNumWeights);
ReadBounds(stream, b->mWeights, b->mNumWeights);
} else {
// else write as usual
b->mWeights = new aiVertexWeight[b->mNumWeights];
ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights);
ReadArray<aiVertexWeight>(stream, b->mWeights, b->mNumWeights);
}
}
// -----------------------------------------------------------------------------------
static bool fitsIntoUI16(unsigned int mNumVertices) {
return ( mNumVertices < (1u<<16) );
return (mNumVertices < (1u << 16));
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMESH)
void AssbinImporter::ReadBinaryMesh(IOStream *stream, aiMesh *mesh) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMESH)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
mesh->mPrimitiveTypes = Read<unsigned int>(stream);
mesh->mNumVertices = Read<unsigned int>(stream);
@ -329,48 +330,48 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
if (c & ASSBIN_MESH_HAS_POSITIONS) {
if (shortened) {
ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
} else {
ReadBounds(stream, mesh->mVertices, mesh->mNumVertices);
} else {
// else write as usual
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
ReadArray<aiVector3D>(stream, mesh->mVertices, mesh->mNumVertices);
}
}
if (c & ASSBIN_MESH_HAS_NORMALS) {
if (shortened) {
ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
} else {
ReadBounds(stream, mesh->mNormals, mesh->mNumVertices);
} else {
// else write as usual
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices);
ReadArray<aiVector3D>(stream, mesh->mNormals, mesh->mNumVertices);
}
}
if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) {
if (shortened) {
ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
} else {
ReadBounds(stream, mesh->mTangents, mesh->mNumVertices);
ReadBounds(stream, mesh->mBitangents, mesh->mNumVertices);
} else {
// else write as usual
mesh->mTangents = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
ReadArray<aiVector3D>(stream, mesh->mTangents, mesh->mNumVertices);
mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
ReadArray<aiVector3D>(stream, mesh->mBitangents, mesh->mNumVertices);
}
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS; ++n) {
if (!(c & ASSBIN_MESH_HAS_COLOR(n))) {
break;
}
if (shortened) {
ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
} else {
ReadBounds(stream, mesh->mColors[n], mesh->mNumVertices);
} else {
// else write as usual
mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
ReadArray<aiColor4D>(stream, mesh->mColors[n], mesh->mNumVertices);
}
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++n) {
if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n))) {
break;
}
@ -379,11 +380,11 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
if (shortened) {
ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
} else {
ReadBounds(stream, mesh->mTextureCoords[n], mesh->mNumVertices);
} else {
// else write as usual
mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
ReadArray<aiVector3D>(stream, mesh->mTextureCoords[n], mesh->mNumVertices);
}
}
@ -393,20 +394,20 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
// using Assimp's standard hashing function.
if (shortened) {
Read<unsigned int>(stream);
} else {
} else {
// else write as usual
// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
mesh->mFaces = new aiFace[mesh->mNumFaces];
for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
aiFace& f = mesh->mFaces[i];
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
aiFace &f = mesh->mFaces[i];
static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff");
f.mNumIndices = Read<uint16_t>(stream);
f.mIndices = new unsigned int[f.mNumIndices];
for (unsigned int a = 0; a < f.mNumIndices;++a) {
for (unsigned int a = 0; a < f.mNumIndices; ++a) {
// Check if unsigned short ( 16 bit ) are big enought for the indices
if ( fitsIntoUI16( mesh->mNumVertices ) ) {
if (fitsIntoUI16(mesh->mNumVertices)) {
f.mIndices[a] = Read<uint16_t>(stream);
} else {
f.mIndices[a] = Read<unsigned int>(stream);
@ -417,19 +418,19 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
// write bones
if (mesh->mNumBones) {
mesh->mBones = new C_STRUCT aiBone*[mesh->mNumBones];
for (unsigned int a = 0; a < mesh->mNumBones;++a) {
mesh->mBones = new C_STRUCT aiBone *[mesh->mNumBones];
for (unsigned int a = 0; a < mesh->mNumBones; ++a) {
mesh->mBones[a] = new aiBone();
ReadBinaryBone(stream,mesh->mBones[a]);
ReadBinaryBone(stream, mesh->mBones[a]);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY)
void AssbinImporter::ReadBinaryMaterialProperty(IOStream *stream, aiMaterialProperty *prop) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
prop->mKey = Read<aiString>(stream);
prop->mSemantic = Read<unsigned int>(stream);
@ -437,36 +438,34 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro
prop->mDataLength = Read<unsigned int>(stream);
prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream);
prop->mData = new char [ prop->mDataLength ];
stream->Read(prop->mData,1,prop->mDataLength);
prop->mData = new char[prop->mDataLength];
stream->Read(prop->mData, 1, prop->mDataLength);
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIAL)
void AssbinImporter::ReadBinaryMaterial(IOStream *stream, aiMaterial *mat) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIAL)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
if (mat->mNumProperties)
{
if (mat->mProperties)
{
if (mat->mNumProperties) {
if (mat->mProperties) {
delete[] mat->mProperties;
}
mat->mProperties = new aiMaterialProperty*[mat->mNumProperties];
for (unsigned int i = 0; i < mat->mNumProperties;++i) {
mat->mProperties = new aiMaterialProperty *[mat->mNumProperties];
for (unsigned int i = 0; i < mat->mNumProperties; ++i) {
mat->mProperties[i] = new aiMaterialProperty();
ReadBinaryMaterialProperty( stream, mat->mProperties[i]);
ReadBinaryMaterialProperty(stream, mat->mProperties[i]);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODEANIM)
void AssbinImporter::ReadBinaryNodeAnim(IOStream *stream, aiNodeAnim *nd) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODEANIM)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
nd->mNodeName = Read<aiString>(stream);
nd->mNumPositionKeys = Read<unsigned int>(stream);
@ -477,82 +476,82 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) {
if (nd->mNumPositionKeys) {
if (shortened) {
ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys);
ReadBounds(stream, nd->mPositionKeys, nd->mNumPositionKeys);
} // else write as usual
else {
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
ReadArray<aiVectorKey>(stream,nd->mPositionKeys,nd->mNumPositionKeys);
ReadArray<aiVectorKey>(stream, nd->mPositionKeys, nd->mNumPositionKeys);
}
}
if (nd->mNumRotationKeys) {
if (shortened) {
ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
ReadBounds(stream, nd->mRotationKeys, nd->mNumRotationKeys);
} else {
} else {
// else write as usual
nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
ReadArray<aiQuatKey>(stream, nd->mRotationKeys, nd->mNumRotationKeys);
}
}
if (nd->mNumScalingKeys) {
if (shortened) {
ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
ReadBounds(stream, nd->mScalingKeys, nd->mNumScalingKeys);
} else {
} else {
// else write as usual
nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys);
ReadArray<aiVectorKey>(stream, nd->mScalingKeys, nd->mNumScalingKeys);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIANIMATION)
void AssbinImporter::ReadBinaryAnim(IOStream *stream, aiAnimation *anim) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIANIMATION)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
anim->mName = Read<aiString> (stream);
anim->mDuration = Read<double> (stream);
anim->mTicksPerSecond = Read<double> (stream);
anim->mName = Read<aiString>(stream);
anim->mDuration = Read<double>(stream);
anim->mTicksPerSecond = Read<double>(stream);
anim->mNumChannels = Read<unsigned int>(stream);
if (anim->mNumChannels) {
anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
for (unsigned int a = 0; a < anim->mNumChannels;++a) {
anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
for (unsigned int a = 0; a < anim->mNumChannels; ++a) {
anim->mChannels[a] = new aiNodeAnim();
ReadBinaryNodeAnim(stream,anim->mChannels[a]);
ReadBinaryNodeAnim(stream, anim->mChannels[a]);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AITEXTURE)
void AssbinImporter::ReadBinaryTexture(IOStream *stream, aiTexture *tex) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AITEXTURE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
tex->mWidth = Read<unsigned int>(stream);
tex->mHeight = Read<unsigned int>(stream);
stream->Read( tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1 );
stream->Read(tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1);
if(!shortened) {
if (!shortened) {
if (!tex->mHeight) {
tex->pcData = new aiTexel[ tex->mWidth ];
stream->Read(tex->pcData,1,tex->mWidth);
tex->pcData = new aiTexel[tex->mWidth];
stream->Read(tex->pcData, 1, tex->mWidth);
} else {
tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
tex->pcData = new aiTexel[tex->mWidth * tex->mHeight];
stream->Read(tex->pcData, 1, tex->mWidth * tex->mHeight * 4);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AILIGHT)
void AssbinImporter::ReadBinaryLight(IOStream *stream, aiLight *l) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AILIGHT)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
l->mName = Read<aiString>(stream);
l->mType = (aiLightSourceType)Read<unsigned int>(stream);
@ -574,10 +573,10 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) {
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AICAMERA)
void AssbinImporter::ReadBinaryCamera(IOStream *stream, aiCamera *cam) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AICAMERA)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
cam->mName = Read<aiString>(stream);
cam->mPosition = Read<aiVector3D>(stream);
@ -590,141 +589,139 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) {
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AISCENE)
void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AISCENE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
/*uint32_t size =*/Read<uint32_t>(stream);
scene->mFlags = Read<unsigned int>(stream);
scene->mNumMeshes = Read<unsigned int>(stream);
scene->mNumMaterials = Read<unsigned int>(stream);
scene->mFlags = Read<unsigned int>(stream);
scene->mNumMeshes = Read<unsigned int>(stream);
scene->mNumMaterials = Read<unsigned int>(stream);
scene->mNumAnimations = Read<unsigned int>(stream);
scene->mNumTextures = Read<unsigned int>(stream);
scene->mNumLights = Read<unsigned int>(stream);
scene->mNumCameras = Read<unsigned int>(stream);
scene->mNumTextures = Read<unsigned int>(stream);
scene->mNumLights = Read<unsigned int>(stream);
scene->mNumCameras = Read<unsigned int>(stream);
// Read node graph
//scene->mRootNode = new aiNode[1];
ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL );
ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)NULL);
// Read all meshes
if (scene->mNumMeshes) {
scene->mMeshes = new aiMesh*[scene->mNumMeshes];
memset(scene->mMeshes, 0, scene->mNumMeshes*sizeof(aiMesh*));
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
scene->mMeshes = new aiMesh *[scene->mNumMeshes];
memset(scene->mMeshes, 0, scene->mNumMeshes * sizeof(aiMesh *));
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
scene->mMeshes[i] = new aiMesh();
ReadBinaryMesh( stream,scene->mMeshes[i]);
ReadBinaryMesh(stream, scene->mMeshes[i]);
}
}
// Read materials
if (scene->mNumMaterials) {
scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
memset(scene->mMaterials, 0, scene->mNumMaterials*sizeof(aiMaterial*));
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
memset(scene->mMaterials, 0, scene->mNumMaterials * sizeof(aiMaterial *));
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
scene->mMaterials[i] = new aiMaterial();
ReadBinaryMaterial(stream,scene->mMaterials[i]);
ReadBinaryMaterial(stream, scene->mMaterials[i]);
}
}
// Read all animations
if (scene->mNumAnimations) {
scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
memset(scene->mAnimations, 0, scene->mNumAnimations*sizeof(aiAnimation*));
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
scene->mAnimations = new aiAnimation *[scene->mNumAnimations];
memset(scene->mAnimations, 0, scene->mNumAnimations * sizeof(aiAnimation *));
for (unsigned int i = 0; i < scene->mNumAnimations; ++i) {
scene->mAnimations[i] = new aiAnimation();
ReadBinaryAnim(stream,scene->mAnimations[i]);
ReadBinaryAnim(stream, scene->mAnimations[i]);
}
}
// Read all textures
if (scene->mNumTextures) {
scene->mTextures = new aiTexture*[scene->mNumTextures];
memset(scene->mTextures, 0, scene->mNumTextures*sizeof(aiTexture*));
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
scene->mTextures = new aiTexture *[scene->mNumTextures];
memset(scene->mTextures, 0, scene->mNumTextures * sizeof(aiTexture *));
for (unsigned int i = 0; i < scene->mNumTextures; ++i) {
scene->mTextures[i] = new aiTexture();
ReadBinaryTexture(stream,scene->mTextures[i]);
ReadBinaryTexture(stream, scene->mTextures[i]);
}
}
// Read lights
if (scene->mNumLights) {
scene->mLights = new aiLight*[scene->mNumLights];
memset(scene->mLights, 0, scene->mNumLights*sizeof(aiLight*));
for (unsigned int i = 0; i < scene->mNumLights;++i) {
scene->mLights = new aiLight *[scene->mNumLights];
memset(scene->mLights, 0, scene->mNumLights * sizeof(aiLight *));
for (unsigned int i = 0; i < scene->mNumLights; ++i) {
scene->mLights[i] = new aiLight();
ReadBinaryLight(stream,scene->mLights[i]);
ReadBinaryLight(stream, scene->mLights[i]);
}
}
// Read cameras
if (scene->mNumCameras) {
scene->mCameras = new aiCamera*[scene->mNumCameras];
memset(scene->mCameras, 0, scene->mNumCameras*sizeof(aiCamera*));
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
scene->mCameras = new aiCamera *[scene->mNumCameras];
memset(scene->mCameras, 0, scene->mNumCameras * sizeof(aiCamera *));
for (unsigned int i = 0; i < scene->mNumCameras; ++i) {
scene->mCameras[i] = new aiCamera();
ReadBinaryCamera(stream,scene->mCameras[i]);
ReadBinaryCamera(stream, scene->mCameras[i]);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) {
IOStream * stream = pIOHandler->Open(pFile,"rb");
void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
IOStream *stream = pIOHandler->Open(pFile, "rb");
if (nullptr == stream) {
return;
}
// signature
stream->Seek( 44, aiOrigin_CUR );
stream->Seek(44, aiOrigin_CUR);
unsigned int versionMajor = Read<unsigned int>(stream);
unsigned int versionMinor = Read<unsigned int>(stream);
if (versionMinor != ASSBIN_VERSION_MINOR || versionMajor != ASSBIN_VERSION_MAJOR) {
throw DeadlyImportError( "Invalid version, data format not compatible!" );
throw DeadlyImportError("Invalid version, data format not compatible!");
}
/*unsigned int versionRevision =*/ Read<unsigned int>(stream);
/*unsigned int compileFlags =*/ Read<unsigned int>(stream);
/*unsigned int versionRevision =*/Read<unsigned int>(stream);
/*unsigned int compileFlags =*/Read<unsigned int>(stream);
shortened = Read<uint16_t>(stream) > 0;
compressed = Read<uint16_t>(stream) > 0;
if (shortened)
throw DeadlyImportError( "Shortened binaries are not supported!" );
throw DeadlyImportError("Shortened binaries are not supported!");
stream->Seek( 256, aiOrigin_CUR ); // original filename
stream->Seek( 128, aiOrigin_CUR ); // options
stream->Seek( 64, aiOrigin_CUR ); // padding
stream->Seek(256, aiOrigin_CUR); // original filename
stream->Seek(128, aiOrigin_CUR); // options
stream->Seek(64, aiOrigin_CUR); // padding
if (compressed) {
uLongf uncompressedSize = Read<uint32_t>(stream);
uLongf compressedSize = static_cast<uLongf>(stream->FileSize() - stream->Tell());
unsigned char * compressedData = new unsigned char[ compressedSize ];
size_t len = stream->Read( compressedData, 1, compressedSize );
unsigned char *compressedData = new unsigned char[compressedSize];
size_t len = stream->Read(compressedData, 1, compressedSize);
ai_assert(len == compressedSize);
unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
unsigned char *uncompressedData = new unsigned char[uncompressedSize];
int res = uncompress( uncompressedData, &uncompressedSize, compressedData, (uLong) len );
if(res != Z_OK)
{
delete [] uncompressedData;
delete [] compressedData;
int res = uncompress(uncompressedData, &uncompressedSize, compressedData, (uLong)len);
if (res != Z_OK) {
delete[] uncompressedData;
delete[] compressedData;
pIOHandler->Close(stream);
throw DeadlyImportError("Zlib decompression failed.");
}
MemoryIOStream io( uncompressedData, uncompressedSize );
MemoryIOStream io(uncompressedData, uncompressedSize);
ReadBinaryScene(&io,pScene);
ReadBinaryScene(&io, pScene);
delete[] uncompressedData;
delete[] compressedData;
} else {
ReadBinaryScene(stream,pScene);
ReadBinaryScene(stream, pScene);
}
pIOHandler->Close(stream);

View File

@ -8,6 +8,10 @@ For details, see http://sourceforge.net/projects/libb64
#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H
#ifdef _WIN32
#pragma warning(disable : 4127 )
#endif // _WIN32
typedef enum
{
step_A, step_B, step_C

View File

@ -91,20 +91,20 @@ public:
base64_encodestate s;
base64_init_encodestate(&s);
char* const out = new char[std::max(len * 2, static_cast<size_t>(16u))];
const int n = base64_encode_block(reinterpret_cast<const char*>(buffer), static_cast<int>(len), out, &s);
out[n + base64_encode_blockend(out + n, &s)] = '\0';
char* const cur_out = new char[std::max(len * 2, static_cast<size_t>(16u))];
const int n = base64_encode_block(reinterpret_cast<const char *>(buffer), static_cast<int>(len), cur_out, &s);
cur_out[n + base64_encode_blockend(cur_out + n, &s)] = '\0';
// base64 encoding may add newlines, but JSON strings may not contain 'real' newlines
// (only escaped ones). Remove any newlines in out.
for (char* cur = out; *cur; ++cur) {
for (char *cur = cur_out; *cur; ++cur) {
if (*cur == '\n') {
*cur = ' ';
}
}
buff << '\"' << out << "\"\n";
delete[] out;
buff << '\"' << cur_out << "\"\n";
delete[] cur_out;
}
void StartObj(bool is_element = false) {
@ -464,8 +464,8 @@ void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) {
case aiPTI_Float:
if (prop->mDataLength / sizeof(float) > 1) {
out.StartArray();
for (unsigned int i = 0; i < prop->mDataLength / sizeof(float); ++i) {
out.Element(reinterpret_cast<float*>(prop->mData)[i]);
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) {
out.Element(reinterpret_cast<float*>(prop->mData)[ii]);
}
out.EndArray();
}
@ -477,8 +477,8 @@ void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) {
case aiPTI_Integer:
if (prop->mDataLength / sizeof(int) > 1) {
out.StartArray();
for (unsigned int i = 0; i < prop->mDataLength / sizeof(int); ++i) {
out.Element(reinterpret_cast<int*>(prop->mData)[i]);
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) {
out.Element(reinterpret_cast<int*>(prop->mData)[ii]);
}
out.EndArray();
} else {

View File

@ -373,25 +373,25 @@ void WriteDump(const char* pFile, const char* cmd, const aiScene* scene, IOStrea
ioprintf(io," size=\"%i\">\n\t\t\t\t",
static_cast<int>(prop->mDataLength/sizeof(float)));
for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) {
ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float))));
for (unsigned int pp = 0; pp < prop->mDataLength/sizeof(float);++pp) {
ioprintf(io,"%f ",*((float*)(prop->mData+pp*sizeof(float))));
}
}
else if (prop->mType == aiPTI_Integer) {
ioprintf(io," size=\"%i\">\n\t\t\t\t",
static_cast<int>(prop->mDataLength/sizeof(int)));
for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) {
ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int))));
for (unsigned int pp = 0; pp < prop->mDataLength/sizeof(int);++pp) {
ioprintf(io,"%i ",*((int*)(prop->mData+pp*sizeof(int))));
}
}
else if (prop->mType == aiPTI_Buffer) {
ioprintf(io," size=\"%i\">\n\t\t\t\t",
static_cast<int>(prop->mDataLength));
for (unsigned int p = 0; p < prop->mDataLength;++p) {
ioprintf(io,"%2x ",prop->mData[p]);
if (p && 0 == p%30) {
for (unsigned int pp = 0; pp< prop->mDataLength;++pp) {
ioprintf(io,"%2x ",prop->mData[pp]);
if (pp && 0 == pp%30) {
ioprintf(io,"\n\t\t\t\t");
}
}

View File

@ -155,36 +155,37 @@ AI_WONT_RETURN void B3DImporter::Fail( string str ){
// ------------------------------------------------------------------------------------------------
int B3DImporter::ReadByte(){
if( _pos<_buf.size() ) {
return _buf[_pos++];
}
Fail( "EOF" );
return 0;
if (_pos > _buf.size()) {
Fail("EOF");
}
return _buf[_pos++];
}
// ------------------------------------------------------------------------------------------------
int B3DImporter::ReadInt(){
if( _pos+4<=_buf.size() ){
int n;
memcpy(&n, &_buf[_pos], 4);
_pos+=4;
return n;
if (_pos + 4 > _buf.size()) {
Fail("EOF");
}
Fail( "EOF" );
return 0;
int n;
memcpy(&n, &_buf[_pos], 4);
_pos+=4;
return n;
}
// ------------------------------------------------------------------------------------------------
float B3DImporter::ReadFloat(){
if( _pos+4<=_buf.size() ){
float n;
memcpy(&n, &_buf[_pos], 4);
_pos+=4;
return n;
}
Fail( "EOF" );
return 0.0f;
float B3DImporter::ReadFloat() {
if (_pos + 4 > _buf.size()) {
Fail("EOF");
}
float n;
memcpy(&n, &_buf[_pos], 4);
_pos+=4;
return n;
}
// ------------------------------------------------------------------------------------------------
@ -214,6 +215,9 @@ aiQuaternion B3DImporter::ReadQuat(){
// ------------------------------------------------------------------------------------------------
string B3DImporter::ReadString(){
if (_pos > _buf.size()) {
Fail("EOF");
}
string str;
while( _pos<_buf.size() ){
char c=(char)ReadByte();
@ -222,7 +226,6 @@ string B3DImporter::ReadString(){
}
str+=c;
}
Fail( "EOF" );
return string();
}
@ -247,7 +250,7 @@ void B3DImporter::ExitChunk(){
}
// ------------------------------------------------------------------------------------------------
unsigned B3DImporter::ChunkSize(){
size_t B3DImporter::ChunkSize(){
return _stack.back()-_pos;
}
// ------------------------------------------------------------------------------------------------
@ -355,13 +358,13 @@ void B3DImporter::ReadVRTS(){
Fail( "Bad texcoord data" );
}
int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
int n_verts=ChunkSize()/sz;
int sz = 12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
size_t n_verts = ChunkSize()/sz;
int v0=static_cast<int>(_vertices.size());
_vertices.resize( v0+n_verts );
for( int i=0;i<n_verts;++i ){
for( unsigned int i=0;i<n_verts;++i ){
Vertex &v=_vertices[v0+i];
memset( v.bones,0,sizeof(v.bones) );
@ -377,14 +380,14 @@ void B3DImporter::ReadVRTS(){
ReadQuat(); //skip v 4bytes...
}
for( int i=0;i<_tcsets;++i ){
for( int j=0;j<_tcsets;++j ){
float t[4]={0,0,0,0};
for( int j=0;j<_tcsize;++j ){
t[j]=ReadFloat();
for( int k=0;k<_tcsize;++k ){
t[k]=ReadFloat();
}
t[1]=1-t[1];
if( !i ) {
v.texcoords=aiVector3D( t[0],t[1],t[2] );
t[1] = 1 - t[1];
if( !j ) {
v.texcoords = aiVector3D( t[0],t[1],t[2] );
}
}
}
@ -408,10 +411,10 @@ void B3DImporter::ReadTRIS(int v0) {
mesh->mNumFaces = 0;
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
int n_tris = ChunkSize() / 12;
size_t n_tris = ChunkSize() / 12;
aiFace *face = mesh->mFaces = new aiFace[n_tris];
for (int i = 0; i < n_tris; ++i) {
for (unsigned int i = 0; i < n_tris; ++i) {
int i0 = ReadInt() + v0;
int i1 = ReadInt() + v0;
int i2 = ReadInt() + v0;
@ -463,7 +466,7 @@ void B3DImporter::ReadBONE(int id) {
Vertex &v = _vertices[vertex];
for (int i = 0; i < 4; ++i) {
if (!v.weights[i]) {
v.bones[i] = id;
v.bones[i] = static_cast<unsigned char>(id);
v.weights[i] = weight;
break;
}
@ -547,24 +550,24 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
vector<aiNode*> children;
while( ChunkSize() ){
string t=ReadChunk();
if( t=="MESH" ){
const string chunk = ReadChunk();
if (chunk == "MESH") {
unsigned int n= static_cast<unsigned int>(_meshes.size());
ReadMESH();
for( unsigned int i=n;i<static_cast<unsigned int>(_meshes.size());++i ){
meshes.push_back( i );
}
}else if( t=="BONE" ){
} else if (chunk == "BONE") {
ReadBONE( nodeid );
}else if( t=="ANIM" ){
} else if (chunk == "ANIM") {
ReadANIM();
}else if( t=="KEYS" ){
} else if (chunk == "KEYS") {
if( !nodeAnim ){
nodeAnim.reset(new aiNodeAnim);
nodeAnim->mNodeName=node->mName;
}
ReadKEYS( nodeAnim.get() );
}else if( t=="NODE" ){
} else if (chunk == "NODE") {
aiNode *child=ReadNODE( node );
children.push_back( child );
}
@ -613,12 +616,12 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
}
while( ChunkSize() ){
string t=ReadChunk();
if( t=="TEXS" ){
const string chunk = ReadChunk();
if (chunk == "TEXS") {
ReadTEXS();
}else if( t=="BRUS" ){
} else if (chunk == "BRUS") {
ReadBRUS();
}else if( t=="NODE" ){
} else if (chunk == "NODE") {
ReadNODE( 0 );
}
ExitChunk();
@ -656,48 +659,51 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
vector< vector<aiVertexWeight> > vweights( _nodes.size() );
for( int i=0;i<n_verts;i+=3 ){
for( int j=0;j<3;++j ){
Vertex &v=_vertices[face->mIndices[j]];
for (int vertIdx = 0; vertIdx < n_verts; vertIdx += 3) {
for (int faceIndex = 0; faceIndex < 3; ++faceIndex) {
Vertex &v = _vertices[face->mIndices[faceIndex]];
*mv++=v.vertex;
if( mn ) *mn++=v.normal;
if( mc ) *mc++=v.texcoords;
face->mIndices[j]=i+j;
face->mIndices[faceIndex] = vertIdx + faceIndex;
for( int k=0;k<4;++k ){
if( !v.weights[k] ) break;
if( !v.weights[k] )
break;
int bone=v.bones[k];
float weight=v.weights[k];
int bone = v.bones[k];
float weight = v.weights[k];
vweights[bone].push_back( aiVertexWeight(i+j,weight) );
vweights[bone].push_back(aiVertexWeight(vertIdx + faceIndex, weight));
}
}
++face;
}
vector<aiBone*> bones;
for(size_t i=0;i<vweights.size();++i ){
vector<aiVertexWeight> &weights=vweights[i];
if( !weights.size() ) continue;
for (size_t weightIndx = 0; weightIndx < vweights.size(); ++weightIndx) {
vector<aiVertexWeight> &weights = vweights[weightIndx];
if (!weights.size()) {
continue;
}
aiBone *bone=new aiBone;
aiBone *bone = new aiBone;
bones.push_back( bone );
aiNode *bnode=_nodes[i];
aiNode *bnode = _nodes[weightIndx];
bone->mName=bnode->mName;
bone->mNumWeights= static_cast<unsigned int>(weights.size());
bone->mWeights=to_array( weights );
bone->mName = bnode->mName;
bone->mNumWeights = static_cast<unsigned int>(weights.size());
bone->mWeights = to_array( weights );
aiMatrix4x4 mat=bnode->mTransformation;
aiMatrix4x4 mat = bnode->mTransformation;
while( bnode->mParent ){
bnode=bnode->mParent;
mat=bnode->mTransformation * mat;
}
bone->mOffsetMatrix=mat.Inverse();
bone->mOffsetMatrix = mat.Inverse();
}
mesh->mNumBones= static_cast<unsigned int>(bones.size());
mesh->mBones=to_array( bones );

View File

@ -82,7 +82,7 @@ private:
std::string ReadString();
std::string ReadChunk();
void ExitChunk();
unsigned ChunkSize();
size_t ChunkSize();
template<class T>
T *to_array( const std::vector<T> &v );
@ -112,10 +112,10 @@ private:
void ReadBB3D( aiScene *scene );
unsigned _pos;
size_t _pos;
// unsigned _size;
std::vector<unsigned char> _buf;
std::vector<unsigned> _stack;
std::vector<size_t> _stack;
std::vector<std::string> _textures;
std::vector<std::unique_ptr<aiMaterial> > _materials;

View File

@ -429,7 +429,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
name.length = 1+ ASSIMP_itoa10(name.data+1,static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(conv_data.textures->size()));
conv_data.textures->push_back(new aiTexture());
aiTexture* tex = conv_data.textures->back();
aiTexture* curTex = conv_data.textures->back();
// usually 'img->name' will be the original file name of the embedded textures,
// so we can extract the file extension from it.
@ -439,19 +439,19 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
--s;
}
tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
tex->achFormatHint[2] = s+3>e ? '\0' : ::tolower( s[3] );
tex->achFormatHint[3] = '\0';
curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]);
curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]);
curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]);
curTex->achFormatHint[3] = '\0';
// tex->mHeight = 0;
tex->mWidth = img->packedfile->size;
uint8_t* ch = new uint8_t[tex->mWidth];
curTex->mWidth = img->packedfile->size;
uint8_t *ch = new uint8_t[curTex->mWidth];
conv_data.db.reader->SetCurrentPos(static_cast<size_t>( img->packedfile->data->val));
conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth);
conv_data.db.reader->CopyAndAdvance(ch, curTex->mWidth);
tex->pcData = reinterpret_cast<aiTexel*>(ch);
curTex->pcData = reinterpret_cast<aiTexel *>(ch);
LogInfo("Reading embedded texture, original file was "+std::string(img->name));
} else {
@ -1078,9 +1078,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
const aiFace& f = out->mFaces[out->mNumFaces++];
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
vo->x = v->uv[i][0];
vo->y = v->uv[i][1];
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
vo->x = v->uv[j][0];
vo->y = v->uv[j][1];
}
}
@ -1098,8 +1098,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
vo->x = uv.uv[0];
vo->y = uv.uv[1];
}
}
else {
} else {
// create textureCoords for every mapped tex
for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
const MLoopUV *tm = itMatTexUvMapping->second[m];
@ -1139,9 +1138,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
const aiFace& f = out->mFaces[out->mNumFaces++];
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
vo->x = v->uv[i][0];
vo->y = v->uv[i][1];
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
vo->x = v->uv[j][0];
vo->y = v->uv[j][1];
}
}
}

View File

@ -57,52 +57,51 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
using namespace Assimp::Blender;
template <typename T> BlenderModifier* god() {
template <typename T>
BlenderModifier *god() {
return new T();
}
// add all available modifiers here
typedef BlenderModifier* (*fpCreateModifier)();
typedef BlenderModifier *(*fpCreateModifier)();
static const fpCreateModifier creators[] = {
&god<BlenderModifier_Mirror>,
&god<BlenderModifier_Subdivision>,
&god<BlenderModifier_Mirror>,
&god<BlenderModifier_Subdivision>,
NULL // sentinel
NULL // sentinel
};
// ------------------------------------------------------------------------------------------------
struct SharedModifierData : ElemBase
{
struct SharedModifierData : ElemBase {
ModifierData modifier;
};
// ------------------------------------------------------------------------------------------------
void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
{
void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_data, const Scene &in, const Object &orig_object) {
size_t cnt = 0u, ful = 0u;
// NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
// we're allowed to dereference the pointers without risking to crash. We might still be
// invoking UB btw - we're assuming that the ModifierData member of the respective modifier
// structures is at offset sizeof(vftable) with no padding.
const SharedModifierData* cur = static_cast<const SharedModifierData *> ( orig_object.modifiers.first.get() );
for (; cur; cur = static_cast<const SharedModifierData *> ( cur->modifier.next.get() ), ++ful) {
const SharedModifierData *cur = static_cast<const SharedModifierData *>(orig_object.modifiers.first.get());
for (; cur; cur = static_cast<const SharedModifierData *>(cur->modifier.next.get()), ++ful) {
ai_assert(cur->dna_type);
const Structure* s = conv_data.db.dna.Get( cur->dna_type );
const Structure *s = conv_data.db.dna.Get(cur->dna_type);
if (!s) {
ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ", cur->dna_type);
continue;
}
// this is a common trait of all XXXMirrorData structures in BlenderDNA
const Field* f = s->Get("modifier");
const Field *f = s->Get("modifier");
if (!f || f->offset != 0) {
ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
continue;
}
s = conv_data.db.dna.Get( f->type );
s = conv_data.db.dna.Get(f->type);
if (!s || s->name != "ModifierData") {
ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
continue;
@ -110,22 +109,22 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
// now, we can be sure that we should be fine to dereference *cur* as
// ModifierData (with the above note).
const ModifierData& dat = cur->modifier;
const ModifierData &dat = cur->modifier;
const fpCreateModifier* curgod = creators;
std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
const fpCreateModifier *curgod = creators;
std::vector<BlenderModifier *>::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
for (; *curgod; ++curgod, ++curmod) { // allocate modifiers on the fly
if (curmod == endmod) {
cached_modifiers->push_back((*curgod)());
endmod = cached_modifiers->end();
curmod = endmod-1;
curmod = endmod - 1;
}
BlenderModifier* const modifier = *curmod;
if(modifier->IsActive(dat)) {
modifier->DoIt(out,conv_data,*static_cast<const ElemBase *>(cur),in,orig_object);
BlenderModifier *const modifier = *curmod;
if (modifier->IsActive(dat)) {
modifier->DoIt(out, conv_data, *static_cast<const ElemBase *>(cur), in, orig_object);
cnt++;
curgod = NULL;
@ -133,7 +132,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
}
}
if (curgod) {
ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ", dat.name);
}
}
@ -141,26 +140,22 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
// object, we still can't say whether our modifier implementations were
// able to fully do their job.
if (ful) {
ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
"`, check log messages above for errors");
ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name,
"`, check log messages above for errors");
}
}
// ------------------------------------------------------------------------------------------------
bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
{
bool BlenderModifier_Mirror ::IsActive(const ModifierData &modin) {
return modin.type == ModifierData::eModifierType_Mirror;
}
// ------------------------------------------------------------------------------------------------
void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
const Scene& /*in*/,
const Object& orig_object )
{
void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const ElemBase &orig_modifier,
const Scene & /*in*/,
const Object &orig_object) {
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
const MirrorModifierData &mir = static_cast<const MirrorModifierData &>(orig_modifier);
ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
@ -169,48 +164,55 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
// take all input meshes and clone them
for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
aiMesh* mesh;
SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
aiMesh *mesh;
SceneCombiner::Copy(&mesh, conv_data.meshes[out.mMeshes[i]]);
const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
if (mir.mirror_ob) {
const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mVertices[i];
const aiVector3D center(mir.mirror_ob->obmat[3][0], mir.mirror_ob->obmat[3][1], mir.mirror_ob->obmat[3][2]);
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
aiVector3D &v = mesh->mVertices[j];
v.x = center.x + xs*(center.x - v.x);
v.y = center.y + ys*(center.y - v.y);
v.z = center.z + zs*(center.z - v.z);
v.x = center.x + xs * (center.x - v.x);
v.y = center.y + ys * (center.y - v.y);
v.z = center.z + zs * (center.z - v.z);
}
}
else {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mVertices[i];
v.x *= xs;v.y *= ys;v.z *= zs;
} else {
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
aiVector3D &v = mesh->mVertices[j];
v.x *= xs;
v.y *= ys;
v.z *= zs;
}
}
if (mesh->mNormals) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mNormals[i];
v.x *= xs;v.y *= ys;v.z *= zs;
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
aiVector3D &v = mesh->mNormals[j];
v.x *= xs;
v.y *= ys;
v.z *= zs;
}
}
if (mesh->mTangents) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mTangents[i];
v.x *= xs;v.y *= ys;v.z *= zs;
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
aiVector3D &v = mesh->mTangents[j];
v.x *= xs;
v.y *= ys;
v.z *= zs;
}
}
if (mesh->mBitangents) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mBitangents[i];
v.x *= xs;v.y *= ys;v.z *= zs;
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
aiVector3D &v = mesh->mBitangents[j];
v.x *= xs;
v.y *= ys;
v.z *= zs;
}
}
@ -218,82 +220,80 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mTextureCoords[n][i];
v.x *= us;v.y *= vs;
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
aiVector3D &v = mesh->mTextureCoords[n][j];
v.x *= us;
v.y *= vs;
}
}
// Only reverse the winding order if an odd number of axes were mirrored.
if (xs * ys * zs < 0) {
for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace& face = mesh->mFaces[i];
for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
for (unsigned int j = 0; j < mesh->mNumFaces; ++j ) {
aiFace &face = mesh->mFaces[j];
for (unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
std::swap(face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
}
}
conv_data.meshes->push_back(mesh);
}
unsigned int* nind = new unsigned int[out.mNumMeshes*2];
unsigned int *nind = new unsigned int[out.mNumMeshes * 2];
std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
[&out](unsigned int n) { return out.mNumMeshes + n; });
std::copy(out.mMeshes, out.mMeshes + out.mNumMeshes, nind);
std::transform(out.mMeshes, out.mMeshes + out.mNumMeshes, nind + out.mNumMeshes,
[&out](unsigned int n) { return out.mNumMeshes + n; });
delete[] out.mMeshes;
out.mMeshes = nind;
out.mNumMeshes *= 2;
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
orig_object.id.name,"`");
orig_object.id.name, "`");
}
// ------------------------------------------------------------------------------------------------
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
{
bool BlenderModifier_Subdivision ::IsActive(const ModifierData &modin) {
return modin.type == ModifierData::eModifierType_Subsurf;
}
// ------------------------------------------------------------------------------------------------
void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
const Scene& /*in*/,
const Object& orig_object )
{
void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data, const ElemBase &orig_modifier,
const Scene & /*in*/,
const Object &orig_object) {
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
const SubsurfModifierData &mir = static_cast<const SubsurfModifierData &>(orig_modifier);
ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
Subdivider::Algorithm algo;
switch (mir.subdivType)
{
case SubsurfModifierData::TYPE_CatmullClarke:
algo = Subdivider::CATMULL_CLARKE;
break;
switch (mir.subdivType) {
case SubsurfModifierData::TYPE_CatmullClarke:
algo = Subdivider::CATMULL_CLARKE;
break;
case SubsurfModifierData::TYPE_Simple:
ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
algo = Subdivider::CATMULL_CLARKE;
break;
case SubsurfModifierData::TYPE_Simple:
ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
algo = Subdivider::CATMULL_CLARKE;
break;
default:
ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
return;
default:
ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType);
return;
};
std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
ai_assert(subd);
if ( conv_data.meshes->empty() ) {
if (conv_data.meshes->empty()) {
return;
}
aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
aiMesh **const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
std::unique_ptr<aiMesh *[]> tempmeshes(new aiMesh *[out.mNumMeshes]());
subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
subd->Subdivide(meshes, out.mNumMeshes, tempmeshes.get(), std::max(mir.renderLevels, mir.levels), true);
std::copy(tempmeshes.get(), tempmeshes.get() + out.mNumMeshes, meshes);
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
orig_object.id.name,"`");
orig_object.id.name, "`");
}
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -861,15 +861,15 @@ if ((CMAKE_COMPILER_IS_MINGW) AND (CMAKE_BUILD_TYPE MATCHES Debug))
SET_SOURCE_FILES_PROPERTIES(Importer/StepFile/StepFileGen1.cpp PROPERTIES STATIC_LIBRARY_FLAGS -Os )
endif()
ADD_ASSIMP_IMPORTER( STEP
Step/STEPFile.h
Importer/StepFile/StepFileImporter.h
Importer/StepFile/StepFileImporter.cpp
Importer/StepFile/StepFileGen1.cpp
Importer/StepFile/StepFileGen2.cpp
Importer/StepFile/StepFileGen3.cpp
Importer/StepFile/StepReaderGen.h
)
#ADD_ASSIMP_IMPORTER( STEP
# Step/STEPFile.h
# Importer/StepFile/StepFileImporter.h
# Importer/StepFile/StepFileImporter.cpp
# Importer/StepFile/StepFileGen1.cpp
# Importer/StepFile/StepFileGen2.cpp
# Importer/StepFile/StepFileGen3.cpp
# Importer/StepFile/StepReaderGen.h
#)
if ((NOT ASSIMP_NO_EXPORT) OR (NOT ASSIMP_EXPORTERS_ENABLED STREQUAL ""))
SET( Exporter_SRCS
@ -886,7 +886,7 @@ SET( Extra_SRCS
SOURCE_GROUP( Extra FILES ${Extra_SRCS})
# irrXML
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(irrXML)
find_package(irrXML CONFIG REQUIRED)
ELSE()
@ -894,7 +894,7 @@ ELSE()
ENDIF()
# utf8
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(utf8)
find_package(utf8 CONFIG REQUIRED)
ELSE()
@ -902,7 +902,7 @@ ELSE()
ENDIF()
# polyclipping
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(polyclipping)
find_package(polyclipping CONFIG REQUIRED)
ELSE()
@ -914,7 +914,7 @@ ELSE()
ENDIF()
# poly2tri
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(poly2tri)
find_package(poly2tri CONFIG REQUIRED)
ELSE()
@ -935,7 +935,7 @@ ELSE()
ENDIF()
# minizip/unzip
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(minizip)
find_package(minizip CONFIG REQUIRED)
ELSE()
@ -950,7 +950,7 @@ ELSE()
ENDIF()
# zip (https://github.com/kuba--/zip)
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(zip)
find_package(zip CONFIG REQUIRED)
ELSE()
@ -971,7 +971,7 @@ ELSE()
ENDIF()
# openddlparser
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(openddlparser)
find_package(openddlparser CONFIG REQUIRED)
ELSE()
@ -994,7 +994,7 @@ ELSE()
ENDIF()
# Open3DGC
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
# Nothing to do, not available in Hunter yet.
ELSE()
SET ( open3dgc_SRCS
@ -1035,7 +1035,7 @@ ENDIF()
# RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file
# has implementation for different platforms: WIN32, __MACH__ and other ("else" block).
FIND_PACKAGE(RT QUIET)
IF (NOT HUNTER_ENABLED AND (RT_FOUND OR MSVC))
IF (NOT ASSIMP_HUNTER_ENABLED AND (RT_FOUND OR MSVC))
SET( ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC 1 )
ADD_DEFINITIONS( -DASSIMP_IMPORTER_GLTF_USE_OPEN3DGC=1 )
ELSE ()
@ -1045,7 +1045,7 @@ ELSE ()
ENDIF ()
# RapidJSON
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(RapidJSON)
find_package(RapidJSON CONFIG REQUIRED)
ELSE()
@ -1068,7 +1068,7 @@ if ( MSVC )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
endif ()
IF(NOT HUNTER_ENABLED)
IF(NOT ASSIMP_HUNTER_ENABLED)
if (UNZIP_FOUND)
SET (unzip_compile_SRCS "")
else ()
@ -1118,7 +1118,7 @@ SET( assimp_src
)
ADD_DEFINITIONS( -DOPENDDLPARSER_BUILD )
IF(NOT HUNTER_ENABLED)
IF(NOT ASSIMP_HUNTER_ENABLED)
INCLUDE_DIRECTORIES(
${IRRXML_INCLUDE_DIR}
../contrib/openddlparser/include
@ -1139,7 +1139,7 @@ TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
$<INSTALL_INTERFACE:include>
)
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
TARGET_LINK_LIBRARIES(assimp
PUBLIC
polyclipping::polyclipping
@ -1212,7 +1212,7 @@ SET_TARGET_PROPERTIES( assimp PROPERTIES
)
if (APPLE)
if (BUILD_FRAMEWORK)
if (ASSIMP_BUILD_FRAMEWORK)
SET_TARGET_PROPERTIES( assimp PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION C
@ -1232,7 +1232,7 @@ ENDIF()
# Build against external unzip, or add ../contrib/unzip so
# assimp can #include "unzip.h"
IF(NOT HUNTER_ENABLED)
IF(NOT ASSIMP_HUNTER_ENABLED)
if (UNZIP_FOUND)
INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
@ -1246,7 +1246,7 @@ IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
TARGET_LINK_LIBRARIES(assimp ${RT_LIBRARY})
ENDIF ()
IF(HUNTER_ENABLED)
IF(ASSIMP_HUNTER_ENABLED)
INSTALL( TARGETS assimp
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}

View File

@ -1015,8 +1015,8 @@ void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const
// XXX backface culling flag is 0x10 in flags
// hole?
bool hole;
if ((hole = (reader.GetI1() & 0x08) != 0)) {
bool hole = (reader.GetI1() & 0x08) != 0;
if ( hole ) {
// XXX Basically this should just work fine - then triangulator
// should output properly triangulated data even for polygons
// with holes. Test data specific to COB is needed to confirm it.

View File

@ -75,10 +75,10 @@ struct Face
// ------------------
/** COB chunk header information */
const unsigned int NO_SIZE = UINT_MAX;
struct ChunkInfo
{
enum {NO_SIZE=UINT_MAX};
ChunkInfo ()
: id (0)
, parent_id (0)

View File

@ -1335,32 +1335,34 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
PushTag();
std::string node_idstr;
std::string cur_node_idstr;
for (size_t a = 0; a < anim->mNumChannels; ++a) {
const aiNodeAnim * nodeAnim = anim->mChannels[a];
// sanity check
if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
if (nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys) {
continue;
}
{
node_idstr.clear();
node_idstr += nodeAnim->mNodeName.data;
node_idstr += std::string( "_matrix-input" );
cur_node_idstr.clear();
cur_node_idstr += nodeAnim->mNodeName.data;
cur_node_idstr += std::string("_matrix-input");
std::vector<ai_real> frames;
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
frames.push_back(static_cast<ai_real>(nodeAnim->mPositionKeys[i].mTime));
}
WriteFloatArray( node_idstr , FloatType_Time, (const ai_real*) frames.data(), frames.size());
WriteFloatArray(cur_node_idstr, FloatType_Time, (const ai_real *)frames.data(), frames.size());
frames.clear();
}
{
node_idstr.clear();
cur_node_idstr.clear();
node_idstr += nodeAnim->mNodeName.data;
node_idstr += std::string("_matrix-output");
cur_node_idstr += nodeAnim->mNodeName.data;
cur_node_idstr += std::string("_matrix-output");
std::vector<ai_real> keyframes;
keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
@ -1385,7 +1387,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
}
}
WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16);
WriteFloatArray(cur_node_idstr, FloatType_Mat4x4, (const ai_real *)keyframes.data(), keyframes.size() / 16);
}
{
@ -1401,16 +1403,16 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
}
}
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation");
std::string arrayId = XMLIDEncode(node_idstr) + "-array";
const std::string cur_node_idstr2 = nodeAnim->mNodeName.data + std::string("_matrix-interpolation");
std::string arrayId = XMLIDEncode(cur_node_idstr2) + "-array";
mOutput << startstr << "<source id=\"" << XMLIDEncode(node_idstr) << "\">" << endstr;
mOutput << startstr << "<source id=\"" << XMLIDEncode(cur_node_idstr2) << "\">" << endstr;
PushTag();
// source array
mOutput << startstr << "<Name_array id=\"" << arrayId << "\" count=\"" << names.size() << "\"> ";
for( size_t a = 0; a < names.size(); ++a ) {
mOutput << names[a] << " ";
for( size_t aa = 0; aa < names.size(); ++aa ) {
mOutput << names[aa] << " ";
}
mOutput << "</Name_array>" << endstr;
@ -1672,13 +1674,13 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
PushTag();
mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLIDEncode(materials[mesh->mMaterialIndex].name) << "\">" << endstr;
PushTag();
for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
for( size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa )
{
if( mesh->HasTextureCoords( static_cast<unsigned int>(a) ) )
if( mesh->HasTextureCoords( static_cast<unsigned int>(aa) ) )
// semantic as in <texture texcoord=...>
// input_semantic as in <input semantic=...>
// input_set as in <input set=...>
mOutput << startstr << "<bind_vertex_input semantic=\"CHANNEL" << a << "\" input_semantic=\"TEXCOORD\" input_set=\"" << a << "\"/>" << endstr;
mOutput << startstr << "<bind_vertex_input semantic=\"CHANNEL" << aa << "\" input_semantic=\"TEXCOORD\" input_set=\"" << aa << "\"/>" << endstr;
}
PopTag();
mOutput << startstr << "</instance_material>" << endstr;

View File

@ -714,8 +714,8 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent)
else if (IsElement("sampler"))
{
// read the ID to assign the corresponding collada channel afterwards.
int indexID = GetAttribute("id");
std::string id = mReader->getAttributeValue(indexID);
int indexId = GetAttribute("id");
std::string id = mReader->getAttributeValue(indexId);
ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
// have it read into a channel
@ -3339,13 +3339,12 @@ void ColladaParser::TestClosing(const char* pName) {
// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
int ColladaParser::GetAttribute(const char* pAttr) const {
int index = TestAttribute(pAttr);
if (index != -1) {
return index;
if (index == -1) {
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
}
// attribute not found -> throw an exception
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
return -1;
return index;
}
// ------------------------------------------------------------------------------------------------

View File

@ -693,3 +693,598 @@ ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extensi
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiVector2AreEqual(
const C_STRUCT aiVector2D* a,
const C_STRUCT aiVector2D* b) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return *a == *b;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiVector2AreEqualEpsilon(
const C_STRUCT aiVector2D* a,
const C_STRUCT aiVector2D* b,
const float epsilon) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return a->Equal(*b, epsilon);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector2Add(
C_STRUCT aiVector2D* dst,
const C_STRUCT aiVector2D* src) {
ai_assert(NULL != dst);
ai_assert(NULL != src);
*dst = *dst + *src;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector2Subtract(
C_STRUCT aiVector2D* dst,
const C_STRUCT aiVector2D* src) {
ai_assert(NULL != dst);
ai_assert(NULL != src);
*dst = *dst - *src;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector2Scale(
C_STRUCT aiVector2D* dst,
const float s) {
ai_assert(NULL != dst);
*dst *= s;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector2SymMul(
C_STRUCT aiVector2D* dst,
const C_STRUCT aiVector2D* other) {
ai_assert(NULL != dst);
ai_assert(NULL != other);
*dst = dst->SymMul(*other);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector2DivideByScalar(
C_STRUCT aiVector2D* dst,
const float s) {
ai_assert(NULL != dst);
*dst /= s;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector2DivideByVector(
C_STRUCT aiVector2D* dst,
C_STRUCT aiVector2D* v) {
ai_assert(NULL != dst);
ai_assert(NULL != v);
*dst = *dst / *v;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector2Length(
const C_STRUCT aiVector2D* v) {
ai_assert(NULL != v);
return v->Length();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector2SquareLength(
const C_STRUCT aiVector2D* v) {
ai_assert(NULL != v);
return v->SquareLength();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector2Negate(
C_STRUCT aiVector2D* dst) {
ai_assert(NULL != dst);
*dst = -(*dst);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector2DotProduct(
const C_STRUCT aiVector2D* a,
const C_STRUCT aiVector2D* b) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return (*a) * (*b);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector2Normalize(
C_STRUCT aiVector2D* v) {
ai_assert(NULL != v);
v->Normalize();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiVector3AreEqual(
const C_STRUCT aiVector3D* a,
const C_STRUCT aiVector3D* b) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return *a == *b;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiVector3AreEqualEpsilon(
const C_STRUCT aiVector3D* a,
const C_STRUCT aiVector3D* b,
const float epsilon) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return a->Equal(*b, epsilon);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiVector3LessThan(
const C_STRUCT aiVector3D* a,
const C_STRUCT aiVector3D* b) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return *a < *b;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3Add(
C_STRUCT aiVector3D* dst,
const C_STRUCT aiVector3D* src) {
ai_assert(NULL != dst);
ai_assert(NULL != src);
*dst = *dst + *src;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3Subtract(
C_STRUCT aiVector3D* dst,
const C_STRUCT aiVector3D* src) {
ai_assert(NULL != dst);
ai_assert(NULL != src);
*dst = *dst - *src;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3Scale(
C_STRUCT aiVector3D* dst,
const float s) {
ai_assert(NULL != dst);
*dst *= s;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3SymMul(
C_STRUCT aiVector3D* dst,
const C_STRUCT aiVector3D* other) {
ai_assert(NULL != dst);
ai_assert(NULL != other);
*dst = dst->SymMul(*other);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3DivideByScalar(
C_STRUCT aiVector3D* dst, const float s) {
ai_assert(NULL != dst);
*dst /= s;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3DivideByVector(
C_STRUCT aiVector3D* dst,
C_STRUCT aiVector3D* v) {
ai_assert(NULL != dst);
ai_assert(NULL != v);
*dst = *dst / *v;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector3Length(
const C_STRUCT aiVector3D* v) {
ai_assert(NULL != v);
return v->Length();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector3SquareLength(
const C_STRUCT aiVector3D* v) {
ai_assert(NULL != v);
return v->SquareLength();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3Negate(
C_STRUCT aiVector3D* dst) {
ai_assert(NULL != dst);
*dst = -(*dst);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector3DotProduct(
const C_STRUCT aiVector3D* a,
const C_STRUCT aiVector3D* b) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return (*a) * (*b);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3CrossProduct(
C_STRUCT aiVector3D* dst,
const C_STRUCT aiVector3D* a,
const C_STRUCT aiVector3D* b) {
ai_assert(NULL != dst);
ai_assert(NULL != a);
ai_assert(NULL != b);
*dst = *a ^ *b;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3Normalize(
C_STRUCT aiVector3D* v) {
ai_assert(NULL != v);
v->Normalize();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3NormalizeSafe(
C_STRUCT aiVector3D* v) {
ai_assert(NULL != v);
v->NormalizeSafe();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiVector3RotateByQuaternion(
C_STRUCT aiVector3D* v,
const C_STRUCT aiQuaternion* q) {
ai_assert(NULL != v);
ai_assert(NULL != q);
*v = q->Rotate(*v);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix3FromMatrix4(
C_STRUCT aiMatrix3x3* dst,
const C_STRUCT aiMatrix4x4* mat) {
ai_assert(NULL != dst);
ai_assert(NULL != mat);
*dst = aiMatrix3x3(*mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix3FromQuaternion(
C_STRUCT aiMatrix3x3* mat,
const C_STRUCT aiQuaternion* q) {
ai_assert(NULL != mat);
ai_assert(NULL != q);
*mat = q->GetMatrix();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiMatrix3AreEqual(
const C_STRUCT aiMatrix3x3* a,
const C_STRUCT aiMatrix3x3* b) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return *a == *b;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiMatrix3AreEqualEpsilon(
const C_STRUCT aiMatrix3x3* a,
const C_STRUCT aiMatrix3x3* b,
const float epsilon) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return a->Equal(*b, epsilon);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix3Inverse(C_STRUCT aiMatrix3x3* mat) {
ai_assert(NULL != mat);
mat->Inverse();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3* mat) {
ai_assert(NULL != mat);
return mat->Determinant();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix3RotationZ(
C_STRUCT aiMatrix3x3* mat,
const float angle) {
ai_assert(NULL != mat);
aiMatrix3x3::RotationZ(angle, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix3FromRotationAroundAxis(
C_STRUCT aiMatrix3x3* mat,
const C_STRUCT aiVector3D* axis,
const float angle) {
ai_assert(NULL != mat);
ai_assert(NULL != axis);
aiMatrix3x3::Rotation(angle, *axis, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix3Translation(
C_STRUCT aiMatrix3x3* mat,
const C_STRUCT aiVector2D* translation) {
ai_assert(NULL != mat);
ai_assert(NULL != translation);
aiMatrix3x3::Translation(*translation, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix3FromTo(
C_STRUCT aiMatrix3x3* mat,
const C_STRUCT aiVector3D* from,
const C_STRUCT aiVector3D* to) {
ai_assert(NULL != mat);
ai_assert(NULL != from);
ai_assert(NULL != to);
aiMatrix3x3::FromToMatrix(*from, *to, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4FromMatrix3(
C_STRUCT aiMatrix4x4* dst,
const C_STRUCT aiMatrix3x3* mat) {
ai_assert(NULL != dst);
ai_assert(NULL != mat);
*dst = aiMatrix4x4(*mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4FromScalingQuaternionPosition(
C_STRUCT aiMatrix4x4* mat,
const C_STRUCT aiVector3D* scaling,
const C_STRUCT aiQuaternion* rotation,
const C_STRUCT aiVector3D* position) {
ai_assert(NULL != mat);
ai_assert(NULL != scaling);
ai_assert(NULL != rotation);
ai_assert(NULL != position);
*mat = aiMatrix4x4(*scaling, *rotation, *position);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4Add(
C_STRUCT aiMatrix4x4* dst,
const C_STRUCT aiMatrix4x4* src) {
ai_assert(NULL != dst);
ai_assert(NULL != src);
*dst = *dst + *src;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiMatrix4AreEqual(
const C_STRUCT aiMatrix4x4* a,
const C_STRUCT aiMatrix4x4* b) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return *a == *b;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiMatrix4AreEqualEpsilon(
const C_STRUCT aiMatrix4x4* a,
const C_STRUCT aiMatrix4x4* b,
const float epsilon) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return a->Equal(*b, epsilon);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4Inverse(C_STRUCT aiMatrix4x4* mat) {
ai_assert(NULL != mat);
mat->Inverse();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiMatrix4Determinant(const C_STRUCT aiMatrix4x4* mat) {
ai_assert(NULL != mat);
return mat->Determinant();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiMatrix4IsIdentity(const C_STRUCT aiMatrix4x4* mat) {
ai_assert(NULL != mat);
return mat->IsIdentity();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4DecomposeIntoScalingEulerAnglesPosition(
const C_STRUCT aiMatrix4x4* mat,
C_STRUCT aiVector3D* scaling,
C_STRUCT aiVector3D* rotation,
C_STRUCT aiVector3D* position) {
ai_assert(NULL != mat);
ai_assert(NULL != scaling);
ai_assert(NULL != rotation);
ai_assert(NULL != position);
mat->Decompose(*scaling, *rotation, *position);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition(
const C_STRUCT aiMatrix4x4* mat,
C_STRUCT aiVector3D* scaling,
C_STRUCT aiVector3D* axis,
float* angle,
C_STRUCT aiVector3D* position) {
ai_assert(NULL != mat);
ai_assert(NULL != scaling);
ai_assert(NULL != axis);
ai_assert(NULL != angle);
ai_assert(NULL != position);
mat->Decompose(*scaling, *axis, *angle, *position);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4DecomposeNoScaling(
const C_STRUCT aiMatrix4x4* mat,
C_STRUCT aiQuaternion* rotation,
C_STRUCT aiVector3D* position) {
ai_assert(NULL != mat);
ai_assert(NULL != rotation);
ai_assert(NULL != position);
mat->DecomposeNoScaling(*rotation, *position);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4FromEulerAngles(
C_STRUCT aiMatrix4x4* mat,
float x, float y, float z) {
ai_assert(NULL != mat);
mat->FromEulerAnglesXYZ(x, y, z);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4RotationX(
C_STRUCT aiMatrix4x4* mat,
const float angle) {
ai_assert(NULL != mat);
aiMatrix4x4::RotationX(angle, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4RotationY(
C_STRUCT aiMatrix4x4* mat,
const float angle) {
ai_assert(NULL != mat);
aiMatrix4x4::RotationY(angle, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4RotationZ(
C_STRUCT aiMatrix4x4* mat,
const float angle) {
ai_assert(NULL != mat);
aiMatrix4x4::RotationZ(angle, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4FromRotationAroundAxis(
C_STRUCT aiMatrix4x4* mat,
const C_STRUCT aiVector3D* axis,
const float angle) {
ai_assert(NULL != mat);
ai_assert(NULL != axis);
aiMatrix4x4::Rotation(angle, *axis, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4Translation(
C_STRUCT aiMatrix4x4* mat,
const C_STRUCT aiVector3D* translation) {
ai_assert(NULL != mat);
ai_assert(NULL != translation);
aiMatrix4x4::Translation(*translation, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4Scaling(
C_STRUCT aiMatrix4x4* mat,
const C_STRUCT aiVector3D* scaling) {
ai_assert(NULL != mat);
ai_assert(NULL != scaling);
aiMatrix4x4::Scaling(*scaling, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMatrix4FromTo(
C_STRUCT aiMatrix4x4* mat,
const C_STRUCT aiVector3D* from,
const C_STRUCT aiVector3D* to) {
ai_assert(NULL != mat);
ai_assert(NULL != from);
ai_assert(NULL != to);
aiMatrix4x4::FromToMatrix(*from, *to, *mat);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiQuaternionFromEulerAngles(
C_STRUCT aiQuaternion* q,
float x, float y, float z) {
ai_assert(NULL != q);
*q = aiQuaternion(x, y, z);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiQuaternionFromAxisAngle(
C_STRUCT aiQuaternion* q,
const C_STRUCT aiVector3D* axis,
const float angle) {
ai_assert(NULL != q);
ai_assert(NULL != axis);
*q = aiQuaternion(*axis, angle);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiQuaternionFromNormalizedQuaternion(
C_STRUCT aiQuaternion* q,
const C_STRUCT aiVector3D* normalized) {
ai_assert(NULL != q);
ai_assert(NULL != normalized);
*q = aiQuaternion(*normalized);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiQuaternionAreEqual(
const C_STRUCT aiQuaternion* a,
const C_STRUCT aiQuaternion* b) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return *a == *b;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API int aiQuaternionAreEqualEpsilon(
const C_STRUCT aiQuaternion* a,
const C_STRUCT aiQuaternion* b,
const float epsilon) {
ai_assert(NULL != a);
ai_assert(NULL != b);
return a->Equal(*b, epsilon);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiQuaternionNormalize(
C_STRUCT aiQuaternion* q) {
ai_assert(NULL != q);
q->Normalize();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiQuaternionConjugate(
C_STRUCT aiQuaternion* q) {
ai_assert(NULL != q);
q->Conjugate();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiQuaternionMultiply(
C_STRUCT aiQuaternion* dst,
const C_STRUCT aiQuaternion* q) {
ai_assert(NULL != dst);
ai_assert(NULL != q);
*dst = (*dst) * (*q);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiQuaternionInterpolate(
C_STRUCT aiQuaternion* dst,
const C_STRUCT aiQuaternion* start,
const C_STRUCT aiQuaternion* end,
const float factor) {
ai_assert(NULL != dst);
ai_assert(NULL != start);
ai_assert(NULL != end);
aiQuaternion::Interpolate(*dst, *start, *end, factor);
}

View File

@ -146,7 +146,7 @@ aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSyst
}
// ------------------------------------------------------------------------------------------------
void BaseImporter::SetupProperties(const Importer* pImp)
void BaseImporter::SetupProperties(const Importer* )
{
// the default implementation does nothing
}

View File

@ -70,7 +70,7 @@ namespace
template<>
size_t select_ftell<8>(FILE* file)
{
return ::_ftelli64(file);
return (size_t)::_ftelli64(file);
}
template<>

View File

@ -44,26 +44,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StringComparison.h>
#include <assimp/DefaultIOSystem.h>
#include <assimp/DefaultIOStream.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/DefaultIOSystem.h>
#include <assimp/ai_assert.h>
#include <stdlib.h>
#include <assimp/DefaultLogger.hpp>
#ifdef __unix__
#include <sys/param.h>
#include <stdlib.h>
# include <stdlib.h>
# include <sys/param.h>
#endif
#ifdef _WIN32
#include <windows.h>
# include <windows.h>
#endif
using namespace Assimp;
#ifdef _WIN32
static std::wstring Utf8ToWide(const char* in)
{
static std::wstring Utf8ToWide(const char *in) {
int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0);
// size includes terminating null; std::wstring adds null automatically
std::wstring out(static_cast<size_t>(size) - 1, L'\0');
@ -71,8 +70,7 @@ static std::wstring Utf8ToWide(const char* in)
return out;
}
static std::string WideToUtf8(const wchar_t* in)
{
static std::string WideToUtf8(const wchar_t *in) {
int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr);
// size includes terminating null; std::string adds null automatically
std::string out(static_cast<size_t>(size) - 1, '\0');
@ -83,52 +81,51 @@ static std::string WideToUtf8(const wchar_t* in)
// ------------------------------------------------------------------------------------------------
// Tests for the existence of a file at the given path.
bool DefaultIOSystem::Exists(const char* pFile) const
{
bool DefaultIOSystem::Exists(const char *pFile) const {
#ifdef _WIN32
struct __stat64 filestat;
if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) {
return false;
}
#else
FILE* file = ::fopen(pFile, "rb");
if (!file)
FILE *file = ::fopen(pFile, "rb");
if (!file) {
return false;
}
::fclose(file);
#endif
return true;
}
// ------------------------------------------------------------------------------------------------
// Open a new file with a given path.
IOStream* DefaultIOSystem::Open(const char* strFile, const char* strMode)
{
IOStream *DefaultIOSystem::Open(const char *strFile, const char *strMode) {
ai_assert(strFile != nullptr);
ai_assert(strMode != nullptr);
FILE* file;
FILE *file;
#ifdef _WIN32
file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str());
#else
file = ::fopen(strFile, strMode);
#endif
if (!file)
if (!file) {
return nullptr;
}
return new DefaultIOStream(file, strFile);
}
// ------------------------------------------------------------------------------------------------
// Closes the given file and releases all resources associated with it.
void DefaultIOSystem::Close(IOStream* pFile)
{
void DefaultIOSystem::Close(IOStream *pFile) {
delete pFile;
}
// ------------------------------------------------------------------------------------------------
// Returns the operation specific directory separator
char DefaultIOSystem::getOsSeparator() const
{
char DefaultIOSystem::getOsSeparator() const {
#ifndef _WIN32
return '/';
#else
@ -138,25 +135,23 @@ char DefaultIOSystem::getOsSeparator() const
// ------------------------------------------------------------------------------------------------
// IOSystem default implementation (ComparePaths isn't a pure virtual function)
bool IOSystem::ComparePaths(const char* one, const char* second) const
{
bool IOSystem::ComparePaths(const char *one, const char *second) const {
return !ASSIMP_stricmp(one, second);
}
// ------------------------------------------------------------------------------------------------
// Convert a relative path into an absolute path
inline static std::string MakeAbsolutePath(const char* in)
{
inline static std::string MakeAbsolutePath(const char *in) {
ai_assert(in);
std::string out;
#ifdef _WIN32
wchar_t* ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0);
wchar_t *ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0);
if (ret) {
out = WideToUtf8(ret);
free(ret);
}
#else
char* ret = realpath(in, nullptr);
char *ret = realpath(in, nullptr);
if (ret) {
out = ret;
free(ret);
@ -173,8 +168,7 @@ inline static std::string MakeAbsolutePath(const char* in)
// ------------------------------------------------------------------------------------------------
// DefaultIOSystem's more specialized implementation
bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const
{
bool DefaultIOSystem::ComparePaths(const char *one, const char *second) const {
// chances are quite good both paths are formatted identically,
// so we can hopefully return here already
if (!ASSIMP_stricmp(one, second))
@ -187,8 +181,7 @@ bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const
}
// ------------------------------------------------------------------------------------------------
std::string DefaultIOSystem::fileName(const std::string& path)
{
std::string DefaultIOSystem::fileName(const std::string &path) {
std::string ret = path;
std::size_t last = ret.find_last_of("\\/");
if (last != std::string::npos) ret = ret.substr(last + 1);
@ -196,8 +189,7 @@ std::string DefaultIOSystem::fileName(const std::string& path)
}
// ------------------------------------------------------------------------------------------------
std::string DefaultIOSystem::completeBaseName(const std::string& path)
{
std::string DefaultIOSystem::completeBaseName(const std::string &path) {
std::string ret = fileName(path);
std::size_t pos = ret.find_last_of('.');
if (pos != std::string::npos) ret = ret.substr(0, pos);
@ -205,8 +197,7 @@ std::string DefaultIOSystem::completeBaseName(const std::string& path)
}
// ------------------------------------------------------------------------------------------------
std::string DefaultIOSystem::absolutePath(const std::string& path)
{
std::string DefaultIOSystem::absolutePath(const std::string &path) {
std::string ret = path;
std::size_t last = ret.find_last_of("\\/");
if (last != std::string::npos) ret = ret.substr(0, last);

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -76,6 +74,11 @@ Here we implement only the C++ interface (Assimp::Exporter).
namespace Assimp {
#ifdef _WIN32
# pragma warning( disable : 4800 )
#endif // _WIN32
// PostStepRegistry.cpp
void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -200,9 +198,9 @@ corresponding preprocessor flag to selectively disable formats.
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
# include "M3D/M3DImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
# include "Importer/StepFile/StepFileImporter.h"
#endif
//#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
//# include "Importer/StepFile/StepFileImporter.h"
//#endif
namespace Assimp {
@ -361,9 +359,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
out.push_back( new MMDImporter() );
#endif
#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
out.push_back(new StepFile::StepFileImporter());
#endif
//#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
// out.push_back(new StepFile::StepFileImporter());
//#endif
}
/** will delete all registered importers. */

View File

@ -53,6 +53,10 @@ using namespace Assimp;
# define CHAR_BIT 8
#endif
#ifdef _WIN32
# pragma warning(disable : 4127)
#endif // _WIN32
// ------------------------------------------------------------------------------------------------
// Constructs a spatially sorted representation from the given position array.
SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,

View File

@ -53,6 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
void mydummy() {}
#ifdef _WIN32
# pragma warning( disable : 4709 )
#endif // _WIN32
// ------------------------------------------------------------------------------------------------
/** Subdivider stub class to implement the Catmull-Clarke subdivision algorithm. The
* implementation is basing on recursive refinement. Directly evaluating the result is also

View File

@ -42,51 +42,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Actually just a dummy, used by the compiler to build the precompiled header.
#include <assimp/version.h>
#include <assimp/scene.h>
#include "ScenePrivate.h"
#include <assimp/scene.h>
#include <assimp/version.h>
#include "revision.h"
// --------------------------------------------------------------------------------
// Legal information string - don't remove this.
static const char* LEGAL_INFORMATION =
static const char *LEGAL_INFORMATION =
"Open Asset Import Library (Assimp).\n"
"A free C/C++ library to import various 3D file formats into applications\n\n"
"Open Asset Import Library (Assimp).\n"
"A free C/C++ library to import various 3D file formats into applications\n\n"
"(c) 2006-2020, assimp team\n"
"License under the terms and conditions of the 3-clause BSD license\n"
"http://assimp.org\n"
;
"(c) 2006-2020, assimp team\n"
"License under the terms and conditions of the 3-clause BSD license\n"
"http://assimp.org\n";
// ------------------------------------------------------------------------------------------------
// Get legal string
ASSIMP_API const char* aiGetLegalString () {
ASSIMP_API const char *aiGetLegalString() {
return LEGAL_INFORMATION;
}
// ------------------------------------------------------------------------------------------------
// Get Assimp patch version
ASSIMP_API unsigned int aiGetVersionPatch() {
return VER_PATCH;
return VER_PATCH;
}
// ------------------------------------------------------------------------------------------------
// Get Assimp minor version
ASSIMP_API unsigned int aiGetVersionMinor () {
ASSIMP_API unsigned int aiGetVersionMinor() {
return VER_MINOR;
}
// ------------------------------------------------------------------------------------------------
// Get Assimp major version
ASSIMP_API unsigned int aiGetVersionMajor () {
ASSIMP_API unsigned int aiGetVersionMajor() {
return VER_MAJOR;
}
// ------------------------------------------------------------------------------------------------
// Get flags used for compilation
ASSIMP_API unsigned int aiGetCompileFlags () {
ASSIMP_API unsigned int aiGetCompileFlags() {
unsigned int flags = 0;
@ -119,24 +118,9 @@ ASSIMP_API const char *aiGetBranchName() {
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API aiScene::aiScene()
: mFlags(0)
, mRootNode(nullptr)
, mNumMeshes(0)
, mMeshes(nullptr)
, mNumMaterials(0)
, mMaterials(nullptr)
, mNumAnimations(0)
, mAnimations(nullptr)
, mNumTextures(0)
, mTextures(nullptr)
, mNumLights(0)
, mLights(nullptr)
, mNumCameras(0)
, mCameras(nullptr)
, mMetaData(nullptr)
, mPrivate(new Assimp::ScenePrivateData()) {
// empty
ASSIMP_API aiScene::aiScene() :
mFlags(0), mRootNode(nullptr), mNumMeshes(0), mMeshes(nullptr), mNumMaterials(0), mMaterials(nullptr), mNumAnimations(0), mAnimations(nullptr), mNumTextures(0), mTextures(nullptr), mNumLights(0), mLights(nullptr), mNumCameras(0), mCameras(nullptr), mMetaData(nullptr), mPrivate(new Assimp::ScenePrivateData()) {
// empty
}
// ------------------------------------------------------------------------------------------------
@ -148,40 +132,39 @@ ASSIMP_API aiScene::~aiScene() {
// much better to check whether both mNumXXX and mXXX are
// valid instead of relying on just one of them.
if (mNumMeshes && mMeshes)
for( unsigned int a = 0; a < mNumMeshes; a++)
for (unsigned int a = 0; a < mNumMeshes; a++)
delete mMeshes[a];
delete [] mMeshes;
delete[] mMeshes;
if (mNumMaterials && mMaterials) {
for (unsigned int a = 0; a < mNumMaterials; ++a ) {
delete mMaterials[ a ];
for (unsigned int a = 0; a < mNumMaterials; ++a) {
delete mMaterials[a];
}
}
delete [] mMaterials;
delete[] mMaterials;
if (mNumAnimations && mAnimations)
for( unsigned int a = 0; a < mNumAnimations; a++)
for (unsigned int a = 0; a < mNumAnimations; a++)
delete mAnimations[a];
delete [] mAnimations;
delete[] mAnimations;
if (mNumTextures && mTextures)
for( unsigned int a = 0; a < mNumTextures; a++)
for (unsigned int a = 0; a < mNumTextures; a++)
delete mTextures[a];
delete [] mTextures;
delete[] mTextures;
if (mNumLights && mLights)
for( unsigned int a = 0; a < mNumLights; a++)
for (unsigned int a = 0; a < mNumLights; a++)
delete mLights[a];
delete [] mLights;
delete[] mLights;
if (mNumCameras && mCameras)
for( unsigned int a = 0; a < mNumCameras; a++)
for (unsigned int a = 0; a < mNumCameras; a++)
delete mCameras[a];
delete [] mCameras;
delete[] mCameras;
aiMetadata::Dealloc(mMetaData);
mMetaData = nullptr;
delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
}

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -44,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Zip File I/O implementation for #Importer
*/
#include <assimp/ZipArchiveIOSystem.h>
#include <assimp/BaseImporter.h>
#include <assimp/ZipArchiveIOSystem.h>
#include <assimp/ai_assert.h>
@ -53,70 +52,69 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#ifdef ASSIMP_USE_HUNTER
# include <minizip/unzip.h>
# include <minizip/unzip.h>
#else
# include <unzip.h>
# 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);
// ----------------------------------------------------------------
// 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);
};
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";
}
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 (voidpf)io_system->Open(filename, mode_fopen);
}
return static_cast<uLong>(io_stream->Read(buf, 1, size));
}
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void *buf, uLong size) {
IOStream *io_stream = (IOStream *)stream;
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
IOStream* io_stream = (IOStream*)stream;
return static_cast<uLong>(io_stream->Read(buf, 1, size));
}
return static_cast<uLong>(io_stream->Write(buf, 1, size));
}
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void *buf, uLong size) {
IOStream *io_stream = (IOStream *)stream;
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
IOStream* io_stream = (IOStream*)stream;
return static_cast<uLong>(io_stream->Write(buf, 1, size));
}
return static_cast<long>(io_stream->Tell());
}
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
IOStream *io_stream = (IOStream *)stream;
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
IOStream* io_stream = (IOStream*)stream;
return static_cast<long>(io_stream->Tell());
}
aiOrigin assimp_origin;
switch (origin) {
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;
@ -127,157 +125,153 @@ namespace Assimp {
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;
return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
}
io_system->Close(io_stream);
int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
IOSystem *io_system = (IOSystem *)opaque;
IOStream *io_stream = (IOStream *)stream;
return 0;
}
io_system->Close(io_stream);
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
return 0;
}
return 0;
}
zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
zlib_filefunc_def mapping;
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;
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;
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);
mapping.opaque = reinterpret_cast<voidpf>(pIOHandler);
return mapping;
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;
}
// ----------------------------------------------------------------
// A read-only file inside a ZIP
ai_assert(unzCloseCurrentFile(zip_handle) == UNZ_OK);
return zip_file;
}
class ZipFile : public IOStream {
friend class ZipFileInfo;
explicit ZipFile(size_t size);
public:
virtual ~ZipFile();
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]);
}
// 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 {}
ZipFile::~ZipFile() {
}
private:
size_t m_Size = 0;
size_t m_SeekPtr = 0;
std::unique_ptr<uint8_t[]> m_Buffer;
};
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);
// ----------------------------------------------------------------
// 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));
// 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;
}
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;
std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize);
if (unzOpenCurrentFile(zip_handle) != UNZ_OK)
return nullptr;
m_SeekPtr += byteSize;
ZipFile *zip_file = new ZipFile(m_Size);
return pCount;
}
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;
}
size_t ZipFile::FileSize() const {
return m_Size;
}
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)
{
aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) {
switch (pOrigin) {
case aiOrigin_SET: {
if (pOffset > m_Size) return aiReturn_FAILURE;
m_SeekPtr = pOffset;
@ -296,242 +290,237 @@ namespace Assimp {
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() {
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());
}
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 || nullptr == pMode) {
return;
}
zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
m_ZipFileHandle = unzOpen2(pFilename, &mapping);
}
ZipArchiveIOSystem::Implement::~Implement() {
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());
}
} // namespace Assimp

View File

@ -48,40 +48,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
namespace Assimp {
namespace FBX
{
const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'
}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings
const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
const int64_t SECOND = 46186158000; // FBX's kTime unit
namespace FBX {
// rotation order. We'll probably use EulerXYZ for everything
enum RotOrder {
RotOrder_EulerXYZ = 0,
RotOrder_EulerXZY,
RotOrder_EulerYZX,
RotOrder_EulerYXZ,
RotOrder_EulerZXY,
RotOrder_EulerZYX,
const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
const std::string SEPARATOR = { '\x00', '\x01' }; // for use inside strings
const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
const int64_t SECOND = 46186158000; // FBX's kTime unit
RotOrder_SphericXYZ,
// rotation order. We'll probably use EulerXYZ for everything
enum RotOrder {
RotOrder_EulerXYZ = 0,
RotOrder_EulerXZY,
RotOrder_EulerYZX,
RotOrder_EulerYXZ,
RotOrder_EulerZXY,
RotOrder_EulerZYX,
RotOrder_MAX // end-of-enum sentinel
};
RotOrder_SphericXYZ,
// transformation inheritance method. Most of the time RSrs
enum TransformInheritance {
TransformInheritance_RrSs = 0,
TransformInheritance_RSrs,
TransformInheritance_Rrs,
RotOrder_MAX // end-of-enum sentinel
};
TransformInheritance_MAX // end-of-enum sentinel
};
}
}
// transformation inheritance method. Most of the time RSrs
enum TransformInheritance {
TransformInheritance_RrSs = 0,
TransformInheritance_RSrs,
TransformInheritance_Rrs,
TransformInheritance_MAX // end-of-enum sentinel
};
} // namespace FBX
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // AI_FBXCOMMON_H_INC

File diff suppressed because it is too large Load Diff

View File

@ -189,8 +189,7 @@ private:
const aiMatrix4x4 &absolute_transform);
// ------------------------------------------------------------------------------------------------
std::vector<unsigned int> ConvertLine(const LineGeometry& line, const Model& model,
aiNode *parent, aiNode *root_node);
std::vector<unsigned int> ConvertLine(const LineGeometry& line, aiNode *root_node);
// ------------------------------------------------------------------------------------------------
aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
@ -220,17 +219,15 @@ private:
* - outputVertStartIndices is only used when a material index is specified, it gives for
* each output vertex the DOM index it maps to.
*/
void ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
aiNode *parent = NULL, aiNode *root_node = NULL,
unsigned int materialIndex = NO_MATERIAL_SEPARATION,
void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
aiNode *parent = NULL, unsigned int materialIndex = NO_MATERIAL_SEPARATION,
std::vector<unsigned int> *outputVertStartIndices = NULL);
// lookup
static const aiNode* GetNodeByName( const aiString& name, aiNode *current_node );
// ------------------------------------------------------------------------------------------------
void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
aiNode *parent, aiNode *root_node);
aiNode *parent );
// ------------------------------------------------------------------------------------------------
void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
@ -352,12 +349,10 @@ private:
aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name,
const Model& target,
NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
NodeMap::const_iterator iter_end,
const LayerMap& layer_map,
NodeMap::const_iterator iterEnd,
int64_t start, int64_t stop,
double& max_time,
double& min_time,
bool reverse_order = false);
double& maxTime,
double& minTime);
// key (time), value, mapto (component index)
typedef std::tuple<std::shared_ptr<KeyTimeList>, std::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
@ -382,20 +377,6 @@ private:
double& minTime,
Model::RotOrder order);
// ------------------------------------------------------------------------------------------------
void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
aiVectorKey* out_translation,
const KeyFrameListList& scaling,
const KeyFrameListList& translation,
const KeyFrameListList& rotation,
const KeyTimeList& times,
double& maxTime,
double& minTime,
Model::RotOrder order,
const aiVector3D& def_scale,
const aiVector3D& def_translate,
const aiVector3D& def_rotation);
// ------------------------------------------------------------------------------------------------
// euler xyz -> quat
aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order);
@ -437,7 +418,7 @@ private:
// 0: not assigned yet, others: index is value - 1
unsigned int defaultMaterialIndex;
std::vector<aiMesh*> meshes;
std::vector<aiMesh*> mMeshes;
std::vector<aiMaterial*> materials;
std::vector<aiAnimation*> animations;
std::vector<aiLight*> lights;
@ -467,9 +448,9 @@ private:
double anim_fps;
aiScene* const out;
aiScene* const mSceneOut;
const FBX::Document& doc;
bool mRemoveEmptyBones;
static void BuildBoneList(aiNode *current_node, const aiNode *root_node, const aiScene *scene,
std::vector<aiBone*>& bones);

View File

@ -428,8 +428,8 @@ void Document::ReadPropertyTemplates()
const ElementCollection otypes = sdefs.GetCollection("ObjectType");
for(ElementMap::const_iterator it = otypes.first; it != otypes.second; ++it) {
const Element& el = *(*it).second;
const Scope* sc = el.Compound();
if(!sc) {
const Scope* curSc = el.Compound();
if (!curSc) {
DOMWarning("expected nested scope in ObjectType, ignoring",&el);
continue;
}
@ -442,24 +442,24 @@ void Document::ReadPropertyTemplates()
const std::string& oname = ParseTokenAsString(*tok[0]);
const ElementCollection templs = sc->GetCollection("PropertyTemplate");
for(ElementMap::const_iterator it = templs.first; it != templs.second; ++it) {
const Element& el = *(*it).second;
const Scope* sc = el.Compound();
if(!sc) {
const ElementCollection templs = curSc->GetCollection("PropertyTemplate");
for (ElementMap::const_iterator elemIt = templs.first; elemIt != templs.second; ++elemIt) {
const Element &innerEl = *(*elemIt).second;
const Scope *innerSc = innerEl.Compound();
if (!innerSc) {
DOMWarning("expected nested scope in PropertyTemplate, ignoring",&el);
continue;
}
const TokenList& tok = el.Tokens();
if(tok.empty()) {
const TokenList &curTok = innerEl.Tokens();
if (curTok.empty()) {
DOMWarning("expected name for PropertyTemplate element, ignoring",&el);
continue;
}
const std::string& pname = ParseTokenAsString(*tok[0]);
const std::string &pname = ParseTokenAsString(*curTok[0]);
const Element* Properties70 = (*sc)["Properties70"];
const Element *Properties70 = (*innerSc)["Properties70"];
if(Properties70) {
std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
*Properties70,std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL))
@ -529,8 +529,8 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
animationStacksResolved.reserve(animationStacks.size());
for(uint64_t id : animationStacks) {
LazyObject* const lazy = GetObject(id);
const AnimationStack* stack;
if(!lazy || !(stack = lazy->Get<AnimationStack>())) {
const AnimationStack *stack = lazy->Get<AnimationStack>();
if(!lazy || nullptr == stack ) {
DOMWarning("failed to read AnimationStack object");
continue;
}

View File

@ -62,90 +62,81 @@ namespace Assimp {
// so they are specified with an 'A' suffix.
void FBX::Node::AddP70int(
const std::string& name, int32_t value
const std::string& cur_name, int32_t value
) {
FBX::Node n("P");
n.AddProperties(name, "int", "Integer", "", value);
n.AddProperties(cur_name, "int", "Integer", "", value);
AddChild(n);
}
void FBX::Node::AddP70bool(
const std::string& name, bool value
const std::string& cur_name, bool value
) {
FBX::Node n("P");
n.AddProperties(name, "bool", "", "", int32_t(value));
n.AddProperties(cur_name, "bool", "", "", int32_t(value));
AddChild(n);
}
void FBX::Node::AddP70double(
const std::string& name, double value
) {
const std::string &cur_name, double value) {
FBX::Node n("P");
n.AddProperties(name, "double", "Number", "", value);
n.AddProperties(cur_name, "double", "Number", "", value);
AddChild(n);
}
void FBX::Node::AddP70numberA(
const std::string& name, double value
) {
const std::string &cur_name, double value) {
FBX::Node n("P");
n.AddProperties(name, "Number", "", "A", value);
n.AddProperties(cur_name, "Number", "", "A", value);
AddChild(n);
}
void FBX::Node::AddP70color(
const std::string& name, double r, double g, double b
) {
const std::string &cur_name, double r, double g, double b) {
FBX::Node n("P");
n.AddProperties(name, "ColorRGB", "Color", "", r, g, b);
n.AddProperties(cur_name, "ColorRGB", "Color", "", r, g, b);
AddChild(n);
}
void FBX::Node::AddP70colorA(
const std::string& name, double r, double g, double b
) {
const std::string &cur_name, double r, double g, double b) {
FBX::Node n("P");
n.AddProperties(name, "Color", "", "A", r, g, b);
n.AddProperties(cur_name, "Color", "", "A", r, g, b);
AddChild(n);
}
void FBX::Node::AddP70vector(
const std::string& name, double x, double y, double z
) {
const std::string &cur_name, double x, double y, double z) {
FBX::Node n("P");
n.AddProperties(name, "Vector3D", "Vector", "", x, y, z);
n.AddProperties(cur_name, "Vector3D", "Vector", "", x, y, z);
AddChild(n);
}
void FBX::Node::AddP70vectorA(
const std::string& name, double x, double y, double z
) {
const std::string &cur_name, double x, double y, double z) {
FBX::Node n("P");
n.AddProperties(name, "Vector", "", "A", x, y, z);
n.AddProperties(cur_name, "Vector", "", "A", x, y, z);
AddChild(n);
}
void FBX::Node::AddP70string(
const std::string& name, const std::string& value
) {
const std::string &cur_name, const std::string &value) {
FBX::Node n("P");
n.AddProperties(name, "KString", "", "", value);
n.AddProperties(cur_name, "KString", "", "", value);
AddChild(n);
}
void FBX::Node::AddP70enum(
const std::string& name, int32_t value
) {
const std::string &cur_name, int32_t value) {
FBX::Node n("P");
n.AddProperties(name, "enum", "", "", value);
n.AddProperties(cur_name, "enum", "", "", value);
AddChild(n);
}
void FBX::Node::AddP70time(
const std::string& name, int64_t value
) {
const std::string &cur_name, int64_t value) {
FBX::Node n("P");
n.AddProperties(name, "KTime", "Time", "", value);
n.AddProperties(cur_name, "KTime", "Time", "", value);
AddChild(n);
}

View File

@ -944,7 +944,9 @@ void FBXExporter::WriteDefinitions ()
FBX::Node defs("Definitions");
defs.AddChild("Version", int32_t(100));
defs.AddChild("Count", int32_t(total_count));
for (auto &n : object_nodes) { defs.AddChild(n); }
for (auto &on : object_nodes) {
defs.AddChild(on);
}
defs.Dump(outfile, binary, 0);
}
@ -1119,10 +1121,10 @@ void FBXExporter::WriteObjects ()
for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
const aiFace &f = m->mFaces[fi];
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
const aiVector3D &n = m->mNormals[f.mIndices[pvi]];
normal_data.push_back(n.x);
normal_data.push_back(n.y);
normal_data.push_back(n.z);
const aiVector3D &curN = m->mNormals[f.mIndices[pvi]];
normal_data.push_back(curN.x);
normal_data.push_back(curN.y);
normal_data.push_back(curN.z);
}
}
FBX::Node::WritePropertyNode(
@ -1226,14 +1228,14 @@ void FBXExporter::WriteObjects ()
for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
const aiFace &f = m->mFaces[fi];
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
const aiVector3D &uv =
const aiVector3D &curUv =
m->mTextureCoords[uvi][f.mIndices[pvi]];
auto elem = index_by_uv.find(uv);
auto elem = index_by_uv.find(curUv);
if (elem == index_by_uv.end()) {
index_by_uv[uv] = index;
index_by_uv[curUv] = index;
uv_indices.push_back(index);
for (unsigned int x = 0; x < m->mNumUVComponents[uvi]; ++x) {
uv_data.push_back(uv[x]);
uv_data.push_back(curUv[x]);
}
++index;
} else {
@ -2246,7 +2248,7 @@ const std::map<std::string,std::pair<std::string,char>> transform_types = {
// write a single model node to the stream
void FBXExporter::WriteModelNode(
StreamWriterLE& outstream,
bool binary,
bool,
const aiNode* node,
int64_t node_uid,
const std::string& type,
@ -2299,16 +2301,13 @@ void FBXExporter::WriteModelNode(
err << item.first;
throw DeadlyExportError(err.str());
}
const std::string &name = elem->second.first;
const std::string &cur_name = elem->second.first;
const aiVector3D &v = item.second;
if (name.compare(0, 4, "Lcl ") == 0) {
if (cur_name.compare(0, 4, "Lcl ") == 0) {
// special handling for animatable properties
p.AddP70(
name, name, "", "A",
double(v.x), double(v.y), double(v.z)
);
p.AddP70( cur_name, cur_name, "", "A", double(v.x), double(v.y), double(v.z) );
} else {
p.AddP70vector(name, v.x, v.y, v.z);
p.AddP70vector(cur_name, v.x, v.y, v.z);
}
}
}

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -53,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXDocumentUtil.h"
#include "FBXProperties.h"
#include <assimp/ByteSwapper.h>
#include <assimp/ParsingUtils.h>
#include <algorithm> // std::transform
#include "FBXUtil.h"
@ -86,7 +86,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
std::string templateName;
// lower-case shading because Blender (for example) writes "Phong"
std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower);
std::transform(shading.begin(), shading.end(), shading.begin(), Assimp::ToLower<char>);
if(shading == "phong") {
templateName = "Material.FbxSurfacePhong";
}

View File

@ -46,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#include "FBXParser.h"
#include "FBXMeshGeometry.h"
#include "FBXDocument.h"
#include "FBXImporter.h"
#include "FBXDocumentUtil.h"
#include "FBXImporter.h"
#include "FBXMeshGeometry.h"
#include "FBXParser.h"
namespace Assimp {
namespace FBX {
@ -58,87 +58,81 @@ namespace FBX {
using namespace Util;
// ------------------------------------------------------------------------------------------------
Model::Model(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: Object(id,element,name)
, shading("Y")
{
const Scope& sc = GetRequiredScope(element);
const Element* const Shading = sc["Shading"];
const Element* const Culling = sc["Culling"];
Model::Model(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
Object(id, element, name), shading("Y") {
const Scope &sc = GetRequiredScope(element);
const Element *const Shading = sc["Shading"];
const Element *const Culling = sc["Culling"];
if(Shading) {
shading = GetRequiredToken(*Shading,0).StringContents();
if (Shading) {
shading = GetRequiredToken(*Shading, 0).StringContents();
}
if (Culling) {
culling = ParseTokenAsString(GetRequiredToken(*Culling,0));
culling = ParseTokenAsString(GetRequiredToken(*Culling, 0));
}
props = GetPropertyTable(doc,"Model.FbxNode",element,sc);
ResolveLinks(element,doc);
props = GetPropertyTable(doc, "Model.FbxNode", element, sc);
ResolveLinks(element, doc);
}
// ------------------------------------------------------------------------------------------------
Model::~Model()
{
Model::~Model() {
}
// ------------------------------------------------------------------------------------------------
void Model::ResolveLinks(const Element& element, const Document& doc)
{
const char* const arr[] = {"Geometry","Material","NodeAttribute"};
void Model::ResolveLinks(const Element&, const Document &doc) {
const char *const arr[] = { "Geometry", "Material", "NodeAttribute" };
// resolve material
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 3);
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), arr, 3);
materials.reserve(conns.size());
geometry.reserve(conns.size());
attributes.reserve(conns.size());
for(const Connection* con : conns) {
for (const Connection *con : conns) {
// material and geometry links should be Object-Object connections
if (con->PropertyName().length()) {
continue;
}
const Object* const ob = con->SourceObject();
if(!ob) {
DOMWarning("failed to read source object for incoming Model link, ignoring",&element);
const Object *const ob = con->SourceObject();
if (!ob) {
DOMWarning("failed to read source object for incoming Model link, ignoring", &element);
continue;
}
const Material* const mat = dynamic_cast<const Material*>(ob);
if(mat) {
const Material *const mat = dynamic_cast<const Material *>(ob);
if (mat) {
materials.push_back(mat);
continue;
}
const Geometry* const geo = dynamic_cast<const Geometry*>(ob);
if(geo) {
const Geometry *const geo = dynamic_cast<const Geometry *>(ob);
if (geo) {
geometry.push_back(geo);
continue;
}
const NodeAttribute* const att = dynamic_cast<const NodeAttribute*>(ob);
if(att) {
const NodeAttribute *const att = dynamic_cast<const NodeAttribute *>(ob);
if (att) {
attributes.push_back(att);
continue;
}
DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring",&element);
DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring", &element);
continue;
}
}
// ------------------------------------------------------------------------------------------------
bool Model::IsNull() const
{
const std::vector<const NodeAttribute*>& attrs = GetAttributes();
for(const NodeAttribute* att : attrs) {
bool Model::IsNull() const {
const std::vector<const NodeAttribute *> &attrs = GetAttributes();
for (const NodeAttribute *att : attrs) {
const Null* null_tag = dynamic_cast<const Null*>(att);
if(null_tag) {
const Null *null_tag = dynamic_cast<const Null *>(att);
if (null_tag) {
return true;
}
}
@ -146,8 +140,7 @@ bool Model::IsNull() const
return false;
}
} //!FBX
} //!Assimp
} // namespace FBX
} // namespace Assimp
#endif

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -49,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h>
#include <map>
#include <memory>
#include <vector>
#include <assimp/LogAux.h>
#include <assimp/fast_atof.h>
@ -126,7 +126,7 @@ public:
const Element* operator[] (const std::string& index) const {
ElementMap::const_iterator it = elements.find(index);
return it == elements.end() ? NULL : (*it).second;
return it == elements.end() ? nullptr : (*it).second;
}
const Element* FindElementCaseInsensitive(const std::string& elementName) const {

View File

@ -209,21 +209,25 @@ DirectPropertyMap PropertyTable::GetUnparsedProperties() const
DirectPropertyMap result;
// Loop through all the lazy properties (which is all the properties)
for(const LazyPropertyMap::value_type& element : lazyProps) {
for(const LazyPropertyMap::value_type& currentElement : lazyProps) {
// Skip parsed properties
if (props.end() != props.find(element.first)) continue;
if (props.end() != props.find(currentElement.first)) {
continue;
}
// Read the element's value.
// Wrap the naked pointer (since the call site is required to acquire ownership)
// std::unique_ptr from C++11 would be preferred both as a wrapper and a return value.
std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*element.second));
std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*currentElement.second));
// Element could not be read. Skip it.
if (!prop) continue;
if (!prop) {
continue;
}
// Add to result
result[element.first] = prop;
result[currentElement.first] = prop;
}
return result;

View File

@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXCompileConfig.h"
#include <assimp/ai_assert.h>
#include <assimp/defs.h>
#include <vector>
#include <string>

View File

@ -118,11 +118,11 @@ void HMPImporter::InternReadFile( const std::string& pFile,
aiScene* _pScene, IOSystem* _pIOHandler)
{
pScene = _pScene;
pIOHandler = _pIOHandler;
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
mIOHandler = _pIOHandler;
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile));
// Check whether we can read from the file
if( file.get() == NULL)
if( file.get() == nullptr)
throw DeadlyImportError( "Failed to open HMP file " + pFile + ".");
// Check whether the HMP file is large enough to contain

View File

@ -285,11 +285,11 @@ public:
out.mVerts.reserve(out.mVerts.size() + cnt);
for(const CurveEntry& entry : curves) {
const size_t cnt = out.mVerts.size();
const size_t curCnt = out.mVerts.size();
entry.first->SampleDiscrete(out);
if (!entry.second && cnt != out.mVerts.size()) {
std::reverse(out.mVerts.begin()+cnt,out.mVerts.end());
if (!entry.second && curCnt != out.mVerts.size()) {
std::reverse(out.mVerts.begin() + curCnt, out.mVerts.end());
}
}
}
@ -329,8 +329,8 @@ public:
have_param = true;
break;
}
else if (const Schema_2x3::IfcCartesianPoint* const r = sel->ResolveSelectPtr<Schema_2x3::IfcCartesianPoint>(conv.db)) {
ConvertCartesianPoint(point,*r);
else if (const Schema_2x3::IfcCartesianPoint* const curR = sel->ResolveSelectPtr<Schema_2x3::IfcCartesianPoint>(conv.db)) {
ConvertCartesianPoint(point, *curR);
have_point = true;
}
}
@ -346,8 +346,8 @@ public:
have_param = true;
break;
}
else if (const Schema_2x3::IfcCartesianPoint* const r = sel->ResolveSelectPtr<Schema_2x3::IfcCartesianPoint>(conv.db)) {
ConvertCartesianPoint(point,*r);
else if (const Schema_2x3::IfcCartesianPoint* const curR = sel->ResolveSelectPtr<Schema_2x3::IfcCartesianPoint>(conv.db)) {
ConvertCartesianPoint(point, *curR);
have_point = true;
}
}

View File

@ -101,7 +101,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
return;
}
ai_assert(std::count(inmesh.mVertcnt.begin(), inmesh.mVertcnt.end(), 0) == 0);
ai_assert(std::count(inmesh.mVertcnt.begin(), inmesh.mVertcnt.end(), 0u) == 0);
typedef std::vector<unsigned int>::const_iterator face_iter;
@ -379,7 +379,7 @@ void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh&
IfcVector3 q;
bool take_any = false;
for (unsigned int i = 0; i < 2; ++i, take_any = true) {
for (unsigned int j = 0; j < 2; ++j, take_any = true) {
if ((last_dir == 0 || take_any) && std::abs(d.x) > 1e-6) {
q.y = startvec.y;
q.z = startvec.z;

File diff suppressed because it is too large Load Diff

View File

@ -294,7 +294,7 @@ void InsertWindowContours(const ContourVector& contours,
const IfcFloat epsilon = diag/1000.f;
// walk through all contour points and find those that lie on the BB corner
size_t last_hit = -1, very_first_hit = -1;
size_t last_hit = (size_t)-1, very_first_hit = (size_t)-1;
IfcVector2 edge;
for(size_t n = 0, e=0, size = contour.size();; n=(n+1)%size, ++e) {
@ -330,7 +330,7 @@ void InsertWindowContours(const ContourVector& contours,
const size_t old = curmesh.mVerts.size();
size_t cnt = last_hit > n ? size-(last_hit-n) : n-last_hit;
for(size_t a = last_hit, e = 0; e <= cnt; a=(a+1)%size, ++e) {
for(size_t a = last_hit, ee = 0; ee <= cnt; a=(a+1)%size, ++ee) {
// hack: this is to fix cases where opening contours are self-intersecting.
// Clipper doesn't produce such polygons, but as soon as we're back in
// our brave new floating-point world, very small distances are consumed

View File

@ -45,6 +45,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "code/Step/STEPFile.h"
#ifdef _WIN32
# pragma warning( disable : 4512 )
#endif // _WIN32
namespace Assimp {
namespace IFC {
namespace Schema_2x3 {

View File

@ -362,8 +362,9 @@ void TempMesh::FixupFaceOrientation()
{
std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc);
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
for( size_t a = 0; a < nbvc - 1; ++a )
std::swap(neighbour[nbvsi + a], neighbour[nbvsi + a + 1]);
for (size_t aa = 0; aa < nbvc - 1; ++aa) {
std::swap(neighbour[nbvsi + aa], neighbour[nbvsi + aa + 1]);
}
}
// either way we're done with the neighbour. Mark it as done and continue checking from there recursively

View File

@ -50,12 +50,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/TinyFormatter.h>
#include <assimp/fast_atof.h>
#include <memory>
#include <functional>
using namespace Assimp;
namespace EXPRESS = STEP::EXPRESS;
#include <functional>
namespace EXPRESS = STEP::EXPRESS;
// ------------------------------------------------------------------------------------------------
std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = "")
@ -127,8 +126,8 @@ STEP::DB* STEP::ReadFileHeader(std::shared_ptr<IOStream> stream) {
if (list->GetSize() > 1) {
ASSIMP_LOG_WARN(AddLineNumber("multiple schemas currently not supported",line));
}
const EXPRESS::STRING* string( nullptr );
if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0].get() ))) {
const EXPRESS::STRING *string = dynamic_cast<const EXPRESS::STRING *>((*list)[0].get());
if (!list->GetSize() || nullptr == string ) {
throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line);
}
head.fileSchema = *string;
@ -539,7 +538,7 @@ void STEP::LazyObject::LazyInit() const {
}
const char* acopy = args;
std::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema());
std::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,(uint64_t)STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema());
delete[] args;
args = NULL;

View File

@ -225,7 +225,7 @@ namespace {
, SchemaEntry("presentation_representation_select",NULL )
, SchemaEntry("presentation_size_assignment_select",NULL )
, SchemaEntry("presentation_style_select",NULL )
, SchemaEntry("presented_item_select",NULL )
//, SchemaEntry("presented_item_select",NULL )
, SchemaEntry("pressure_measure",NULL )
, SchemaEntry("product_definition_or_assembly_relationship",NULL )
, SchemaEntry("product_definition_or_breakdown_element_usage",NULL )
@ -397,7 +397,7 @@ namespace {
, SchemaEntry("applied_organizational_project_assignment",&STEP::ObjectHelper<applied_organizational_project_assignment,1>::Construct )
, SchemaEntry("person_and_organization_assignment",&STEP::ObjectHelper<person_and_organization_assignment,2>::Construct )
, SchemaEntry("applied_person_and_organization_assignment",&STEP::ObjectHelper<applied_person_and_organization_assignment,1>::Construct )
, SchemaEntry("presented_item",&STEP::ObjectHelper<presented_item,0>::Construct )
//, SchemaEntry("presented_item",&STEP::ObjectHelper<presented_item,0>::Construct )
, SchemaEntry("applied_presented_item",&STEP::ObjectHelper<applied_presented_item,1>::Construct )
, SchemaEntry("security_classification_assignment",&STEP::ObjectHelper<security_classification_assignment,1>::Construct )
, SchemaEntry("applied_security_classification_assignment",&STEP::ObjectHelper<applied_security_classification_assignment,1>::Construct )
@ -1014,7 +1014,7 @@ namespace {
, SchemaEntry("presentation_size",&STEP::ObjectHelper<NotImplemented,0>::Construct )
, SchemaEntry("presentation_style_assignment",&STEP::ObjectHelper<presentation_style_assignment,1>::Construct )
, SchemaEntry("presentation_style_by_context",&STEP::ObjectHelper<presentation_style_by_context,1>::Construct )
, SchemaEntry("presented_item_representation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
//, SchemaEntry("presented_item_representation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
, SchemaEntry("pressure_measure_with_unit",&STEP::ObjectHelper<pressure_measure_with_unit,0>::Construct )
, SchemaEntry("pressure_unit",&STEP::ObjectHelper<pressure_unit,0>::Construct )
, SchemaEntry("procedural_representation",&STEP::ObjectHelper<procedural_representation,0>::Construct )
@ -1311,11 +1311,11 @@ void StepFile::GetSchema(EXPRESS::ConversionSchema& out)
namespace STEP {
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
/*template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
{
return 0;
}
*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<measure_with_unit>(const DB& db, const LIST& params, measure_with_unit* in)
{
@ -1359,8 +1359,7 @@ template <> size_t GenericFill<absorbed_dose_unit>(const DB& db, const LIST& par
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to absorbed_dose_unit"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<abstract_variable>(const DB& db, const LIST& params, abstract_variable* in)
{
template <> size_t GenericFill<abstract_variable>(const DB&, const LIST&, abstract_variable*) {
size_t base = 0;
return base;
}
@ -1680,7 +1679,7 @@ template <> size_t GenericFill<amount_of_substance_unit>(const DB& db, const LIS
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to amount_of_substance_unit"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<angle_direction_reference>(const DB& db, const LIST& params, angle_direction_reference* in)
template <> size_t GenericFill<angle_direction_reference>(const DB&, const LIST&, angle_direction_reference*)
{
size_t base = 0;
return base;

View File

@ -452,11 +452,11 @@ template <> size_t GenericFill<applied_person_and_organization_assignment>(const
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<presented_item>(const DB& db, const LIST& params, presented_item* in)
/*template <> size_t GenericFill<presented_item>(const DB& db, const LIST& params, presented_item* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<applied_presented_item>(const DB& db, const LIST& params, applied_presented_item* in)
{
@ -642,11 +642,11 @@ template <> size_t GenericFill<atomic_formula>(const DB& db, const LIST& params,
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to atomic_formula"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<attribute_assertion>(const DB& db, const LIST& params, attribute_assertion* in)
/*template <> size_t GenericFill<attribute_assertion>(const DB& db, const LIST& params, attribute_assertion* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<attribute_language_assignment>(const DB& db, const LIST& params, attribute_language_assignment* in)
{
@ -683,11 +683,11 @@ template <> size_t GenericFill<attribute_value_assignment>(const DB& db, const L
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<auxiliary_geometric_representation_item>(const DB& db, const LIST& params, auxiliary_geometric_representation_item* in)
/*template <> size_t GenericFill<auxiliary_geometric_representation_item>(const DB& db, const LIST& params, auxiliary_geometric_representation_item* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<placement>(const DB& db, const LIST& params, placement* in)
{
@ -946,7 +946,7 @@ template <> size_t GenericFill<back_chaining_rule>(const DB& db, const LIST& par
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to back_chaining_rule"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<back_chaining_rule_body>(const DB& db, const LIST& params, back_chaining_rule_body* in)
/*template <> size_t GenericFill<back_chaining_rule_body>(const DB& db, const LIST& params, back_chaining_rule_body* in)
{
size_t base = 0;
return base;
@ -956,7 +956,7 @@ template <> size_t GenericFill<colour>(const DB& db, const LIST& params, colour*
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<background_colour>(const DB& db, const LIST& params, background_colour* in)
{
@ -987,11 +987,11 @@ template <> size_t GenericFill<bezier_surface>(const DB& db, const LIST& params,
if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to bezier_surface"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<generic_expression>(const DB& db, const LIST& params, generic_expression* in)
/*template <> size_t GenericFill<generic_expression>(const DB& db, const LIST& params, generic_expression* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<binary_generic_expression>(const DB& db, const LIST& params, binary_generic_expression* in)
{
@ -1004,11 +1004,11 @@ template <> size_t GenericFill<binary_generic_expression>(const DB& db, const LI
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<binary_numeric_expression>(const DB& db, const LIST& params, binary_numeric_expression* in)
/*template <> size_t GenericFill<binary_numeric_expression>(const DB& db, const LIST& params, binary_numeric_expression* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<binary_representation_item>(const DB& db, const LIST& params, binary_representation_item* in)
{
@ -1071,11 +1071,11 @@ template <> size_t GenericFill<boolean_literal>(const DB& db, const LIST& params
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<boolean_representation_item>(const DB& db, const LIST& params, boolean_representation_item* in)
/*template <> size_t GenericFill<boolean_representation_item>(const DB& db, const LIST& params, boolean_representation_item* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<boolean_result>(const DB& db, const LIST& params, boolean_result* in)
{
@ -1128,7 +1128,7 @@ template <> size_t GenericFill<boundary_curve>(const DB& db, const LIST& params,
if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to boundary_curve"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<bounded_pcurve>(const DB& db, const LIST& params, bounded_pcurve* in)
/*template <> size_t GenericFill<bounded_pcurve>(const DB& db, const LIST& params, bounded_pcurve* in)
{
size_t base = 0;
return base;
@ -1144,7 +1144,7 @@ template <> size_t GenericFill<founded_item>(const DB& db, const LIST& params, f
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<box_domain>(const DB& db, const LIST& params, box_domain* in)
{
@ -1218,11 +1218,11 @@ template <> size_t GenericFill<breakdown_element_group_assignment>(const DB& db,
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<breakdown_element_realization>(const DB& db, const LIST& params, breakdown_element_realization* in)
/*template <> size_t GenericFill<breakdown_element_realization>(const DB& db, const LIST& params, breakdown_element_realization* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<breakdown_element_usage>(const DB& db, const LIST& params, breakdown_element_usage* in)
{
@ -1784,11 +1784,11 @@ template <> size_t GenericFill<characteristic_type>(const DB& db, const LIST& pa
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to characteristic_type"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<characterized_class>(const DB& db, const LIST& params, characterized_class* in)
/*template <> size_t GenericFill<characterized_class>(const DB& db, const LIST& params, characterized_class* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<characterized_object>(const DB& db, const LIST& params, characterized_object* in)
{
@ -1947,6 +1947,7 @@ template <> size_t GenericFill<colour_rgb>(const DB& db, const LIST& params, col
} while (0);
return base;
}
/*
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<common_datum>(const DB& db, const LIST& params, common_datum* in)
{
@ -1958,7 +1959,7 @@ template <> size_t GenericFill<comparison_expression>(const DB& db, const LIST&
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<complex_clause>(const DB& db, const LIST& params, complex_clause* in)
{
@ -2792,7 +2793,7 @@ template <> size_t GenericFill<cylindricity_tolerance>(const DB& db, const LIST&
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to cylindricity_tolerance"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<date_representation_item>(const DB& db, const LIST& params, date_representation_item* in)
/*template <> size_t GenericFill<date_representation_item>(const DB& db, const LIST& params, date_representation_item* in)
{
size_t base = 0;
return base;
@ -2802,7 +2803,7 @@ template <> size_t GenericFill<date_time_representation_item>(const DB& db, cons
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<dated_effectivity>(const DB& db, const LIST& params, dated_effectivity* in)
{

View File

@ -98,11 +98,11 @@ template <> size_t GenericFill<dimension_pair>(const DB& db, const LIST& params,
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to dimension_pair"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<dimension_text_associativity>(const DB& db, const LIST& params, dimension_text_associativity* in)
/*template <> size_t GenericFill<dimension_text_associativity>(const DB& db, const LIST& params, dimension_text_associativity* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<dimensional_location_with_path>(const DB& db, const LIST& params, dimensional_location_with_path* in)
{
@ -160,11 +160,11 @@ template <> size_t GenericFill<direction>(const DB& db, const LIST& params, dire
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<document_file>(const DB& db, const LIST& params, document_file* in)
/*template <> size_t GenericFill<document_file>(const DB& db, const LIST& params, document_file* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<document_identifier>(const DB& db, const LIST& params, document_identifier* in)
{
@ -347,11 +347,11 @@ template <> size_t GenericFill<draughting_model_item_association>(const DB& db,
if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to draughting_model_item_association"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<pre_defined_colour>(const DB& db, const LIST& params, pre_defined_colour* in)
/*template <> size_t GenericFill<pre_defined_colour>(const DB& db, const LIST& params, pre_defined_colour* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<draughting_pre_defined_colour>(const DB& db, const LIST& params, draughting_pre_defined_colour* in)
{
@ -461,11 +461,11 @@ template <> size_t GenericFill<draughting_text_literal_with_delineation>(const D
if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to draughting_text_literal_with_delineation"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<presentation_set>(const DB& db, const LIST& params, presentation_set* in)
/*template <> size_t GenericFill<presentation_set>(const DB& db, const LIST& params, presentation_set* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<drawing_revision>(const DB& db, const LIST& params, drawing_revision* in)
{
@ -592,11 +592,11 @@ template <> size_t GenericFill<edge_curve>(const DB& db, const LIST& params, edg
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<edge_loop>(const DB& db, const LIST& params, edge_loop* in)
/*template <> size_t GenericFill<edge_loop>(const DB& db, const LIST& params, edge_loop* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<electric_charge_measure_with_unit>(const DB& db, const LIST& params, electric_charge_measure_with_unit* in)
{
@ -711,11 +711,11 @@ template <> size_t GenericFill<enum_reference_prefix>(const DB& db, const LIST&
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to enum_reference_prefix"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<evaluated_characteristic>(const DB& db, const LIST& params, evaluated_characteristic* in)
/*template <> size_t GenericFill<evaluated_characteristic>(const DB& db, const LIST& params, evaluated_characteristic* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<evaluated_degenerate_pcurve>(const DB& db, const LIST& params, evaluated_degenerate_pcurve* in)
{
@ -867,11 +867,11 @@ template <> size_t GenericFill<explicit_procedural_shape_representation_relation
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to explicit_procedural_shape_representation_relationship"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<expression_conversion_based_unit>(const DB& db, const LIST& params, expression_conversion_based_unit* in)
/*template <> size_t GenericFill<expression_conversion_based_unit>(const DB& db, const LIST& params, expression_conversion_based_unit* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<extension>(const DB& db, const LIST& params, extension* in)
{
@ -903,35 +903,35 @@ template <> size_t GenericFill<external_class_library>(const DB& db, const LIST&
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to external_class_library"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_class>(const DB& db, const LIST& params, externally_defined_class* in)
/*template <> size_t GenericFill<externally_defined_class>(const DB& db, const LIST& params, externally_defined_class* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_colour>(const DB& db, const LIST& params, externally_defined_colour* in)
/*template <> size_t GenericFill<externally_defined_colour>(const DB& db, const LIST& params, externally_defined_colour* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_context_dependent_unit>(const DB& db, const LIST& params, externally_defined_context_dependent_unit* in)
/*template <> size_t GenericFill<externally_defined_context_dependent_unit>(const DB& db, const LIST& params, externally_defined_context_dependent_unit* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_conversion_based_unit>(const DB& db, const LIST& params, externally_defined_conversion_based_unit* in)
/*template <> size_t GenericFill<externally_defined_conversion_based_unit>(const DB& db, const LIST& params, externally_defined_conversion_based_unit* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_currency>(const DB& db, const LIST& params, externally_defined_currency* in)
/*template <> size_t GenericFill<externally_defined_currency>(const DB& db, const LIST& params, externally_defined_currency* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_item>(const DB& db, const LIST& params, externally_defined_item* in)
{
@ -957,7 +957,7 @@ template <> size_t GenericFill<externally_defined_curve_font>(const DB& db, cons
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to externally_defined_curve_font"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_dimension_definition>(const DB& db, const LIST& params, externally_defined_dimension_definition* in)
/*template <> size_t GenericFill<externally_defined_dimension_definition>(const DB& db, const LIST& params, externally_defined_dimension_definition* in)
{
size_t base = 0;
return base;
@ -979,7 +979,7 @@ template <> size_t GenericFill<externally_defined_marker>(const DB& db, const LI
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<picture_representation_item>(const DB& db, const LIST& params, picture_representation_item* in)
{
@ -993,7 +993,7 @@ template <> size_t GenericFill<externally_defined_picture_representation_item>(c
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to externally_defined_picture_representation_item"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_representation_item>(const DB& db, const LIST& params, externally_defined_representation_item* in)
/*template <> size_t GenericFill<externally_defined_representation_item>(const DB& db, const LIST& params, externally_defined_representation_item* in)
{
size_t base = 0;
return base;
@ -1003,7 +1003,7 @@ template <> size_t GenericFill<externally_defined_string>(const DB& db, const LI
{
size_t base = GenericFill(db, params, static_cast<externally_defined_representation_item*>(in));
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_symbol>(const DB& db, const LIST& params, externally_defined_symbol* in)
{
@ -1029,11 +1029,11 @@ template <> size_t GenericFill<externally_defined_tile>(const DB& db, const LIST
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to externally_defined_tile"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<externally_defined_tile_style>(const DB& db, const LIST& params, externally_defined_tile_style* in)
/*template <> size_t GenericFill<externally_defined_tile_style>(const DB& db, const LIST& params, externally_defined_tile_style* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<swept_area_solid>(const DB& db, const LIST& params, swept_area_solid* in)
{
@ -1358,11 +1358,11 @@ template <> size_t GenericFill<forward_chaining_rule>(const DB& db, const LIST&
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to forward_chaining_rule"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<forward_chaining_rule_premise>(const DB& db, const LIST& params, forward_chaining_rule_premise* in)
/*template <> size_t GenericFill<forward_chaining_rule_premise>(const DB& db, const LIST& params, forward_chaining_rule_premise* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<frequency_measure_with_unit>(const DB& db, const LIST& params, frequency_measure_with_unit* in)
{
@ -1454,11 +1454,11 @@ template <> size_t GenericFill<geometric_item_specific_usage>(const DB& db, cons
if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to geometric_item_specific_usage"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<geometric_model_element_relationship>(const DB& db, const LIST& params, geometric_model_element_relationship* in)
/*template <> size_t GenericFill<geometric_model_element_relationship>(const DB& db, const LIST& params, geometric_model_element_relationship* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<representation_context>(const DB& db, const LIST& params, representation_context* in)
{
@ -1633,11 +1633,11 @@ template <> size_t GenericFill<indirectly_selected_elements>(const DB& db, const
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<indirectly_selected_shape_elements>(const DB& db, const LIST& params, indirectly_selected_shape_elements* in)
/*template <> size_t GenericFill<indirectly_selected_shape_elements>(const DB& db, const LIST& params, indirectly_selected_shape_elements* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<inductance_measure_with_unit>(const DB& db, const LIST& params, inductance_measure_with_unit* in)
{
@ -1674,11 +1674,11 @@ template <> size_t GenericFill<instance_usage_context_assignment>(const DB& db,
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<instanced_feature>(const DB& db, const LIST& params, instanced_feature* in)
/*template <> size_t GenericFill<instanced_feature>(const DB& db, const LIST& params, instanced_feature* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<literal_number>(const DB& db, const LIST& params, literal_number* in)
{
@ -1698,11 +1698,11 @@ template <> size_t GenericFill<int_literal>(const DB& db, const LIST& params, in
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to int_literal"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<integer_representation_item>(const DB& db, const LIST& params, integer_representation_item* in)
/*template <> size_t GenericFill<integer_representation_item>(const DB& db, const LIST& params, integer_representation_item* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<surface_curve>(const DB& db, const LIST& params, surface_curve* in)
{
@ -1734,11 +1734,11 @@ template <> size_t GenericFill<intersection_curve>(const DB& db, const LIST& par
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to intersection_curve"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<interval_expression>(const DB& db, const LIST& params, interval_expression* in)
/*template <> size_t GenericFill<interval_expression>(const DB& db, const LIST& params, interval_expression* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<iso4217_currency>(const DB& db, const LIST& params, iso4217_currency* in)
{
@ -1746,11 +1746,11 @@ template <> size_t GenericFill<iso4217_currency>(const DB& db, const LIST& param
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to iso4217_currency"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<known_source>(const DB& db, const LIST& params, known_source* in)
/*template <> size_t GenericFill<known_source>(const DB& db, const LIST& params, known_source* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<laid_defined_transformation>(const DB& db, const LIST& params, laid_defined_transformation* in)
{
@ -1943,11 +1943,11 @@ template <> size_t GenericFill<logical_literal>(const DB& db, const LIST& params
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<logical_representation_item>(const DB& db, const LIST& params, logical_representation_item* in)
/*template <> size_t GenericFill<logical_representation_item>(const DB&, const LIST& params, logical_representation_item* )
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<loop>(const DB& db, const LIST& params, loop* in)
{
@ -2105,11 +2105,11 @@ template <> size_t GenericFill<material_property_representation>(const DB& db, c
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<measure_representation_item>(const DB& db, const LIST& params, measure_representation_item* in)
/*template <> size_t GenericFill<measure_representation_item>(const DB& db, const LIST& params, measure_representation_item* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<product_context>(const DB& db, const LIST& params, product_context* in)
{
@ -2165,11 +2165,11 @@ template <> size_t GenericFill<mechanical_design_shaded_presentation_representat
if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to mechanical_design_shaded_presentation_representation"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<min_and_major_ply_orientation_basis>(const DB& db, const LIST& params, min_and_major_ply_orientation_basis* in)
/*template <> size_t GenericFill<min_and_major_ply_orientation_basis>(const DB& db, const LIST& params, min_and_major_ply_orientation_basis* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<modified_geometric_tolerance>(const DB& db, const LIST& params, modified_geometric_tolerance* in)
{
@ -2211,11 +2211,11 @@ template <> size_t GenericFill<multi_language_attribute_assignment>(const DB& db
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<multiple_arity_boolean_expression>(const DB& db, const LIST& params, multiple_arity_boolean_expression* in)
/*template <> size_t GenericFill<multiple_arity_boolean_expression>(const DB& db, const LIST& params, multiple_arity_boolean_expression* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<multiple_arity_generic_expression>(const DB& db, const LIST& params, multiple_arity_generic_expression* in)
{
@ -2228,11 +2228,11 @@ template <> size_t GenericFill<multiple_arity_generic_expression>(const DB& db,
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<multiple_arity_numeric_expression>(const DB& db, const LIST& params, multiple_arity_numeric_expression* in)
/*template <> size_t GenericFill<multiple_arity_numeric_expression>(const DB& db, const LIST& params, multiple_arity_numeric_expression* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<next_assembly_usage_occurrence>(const DB& db, const LIST& params, next_assembly_usage_occurrence* in)
{
@ -2533,11 +2533,11 @@ template <> size_t GenericFill<parametric_representation_context>(const DB& db,
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to parametric_representation_context"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<partial_document_with_structured_text_representation_assignment>(const DB& db, const LIST& params, partial_document_with_structured_text_representation_assignment* in)
/*template <> size_t GenericFill<partial_document_with_structured_text_representation_assignment>(const DB& db, const LIST& params, partial_document_with_structured_text_representation_assignment* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<pcurve>(const DB& db, const LIST& params, pcurve* in)
{
@ -2591,11 +2591,11 @@ template <> size_t GenericFill<perpendicularity_tolerance>(const DB& db, const L
if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to perpendicularity_tolerance"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<person_and_organization_address>(const DB& db, const LIST& params, person_and_organization_address* in)
/*template <> size_t GenericFill<person_and_organization_address>(const DB& db, const LIST& params, person_and_organization_address* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<personal_address>(const DB& db, const LIST& params, personal_address* in)
{
@ -2715,11 +2715,11 @@ template <> size_t GenericFill<ply_laminate_table>(const DB& db, const LIST& par
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to ply_laminate_table"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<point_and_vector>(const DB& db, const LIST& params, point_and_vector* in)
/*template <> size_t GenericFill<point_and_vector>(const DB& db, const LIST& params, point_and_vector* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<point_on_curve>(const DB& db, const LIST& params, point_on_curve* in)
{
@ -2758,11 +2758,11 @@ template <> size_t GenericFill<point_on_surface>(const DB& db, const LIST& param
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<point_path>(const DB& db, const LIST& params, point_path* in)
/*template <> size_t GenericFill<point_path>(const DB& db, const LIST& params, point_path* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<point_replica>(const DB& db, const LIST& params, point_replica* in)
{
@ -2904,11 +2904,11 @@ template <> size_t GenericFill<pre_defined_marker>(const DB& db, const LIST& par
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to pre_defined_marker"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<pre_defined_point_marker_symbol>(const DB& db, const LIST& params, pre_defined_point_marker_symbol* in)
/*template <> size_t GenericFill<pre_defined_point_marker_symbol>(const DB& db, const LIST& params, pre_defined_point_marker_symbol* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<pre_defined_surface_condition_symbol>(const DB& db, const LIST& params, pre_defined_surface_condition_symbol* in)
{
@ -3002,7 +3002,7 @@ template <> size_t GenericFill<procedural_representation_sequence>(const DB& db,
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<procedural_shape_representation>(const DB& db, const LIST& params, procedural_shape_representation* in)
/*template <> size_t GenericFill<procedural_shape_representation>(const DB& db, const LIST& params, procedural_shape_representation* in)
{
size_t base = 0;
return base;
@ -3012,7 +3012,7 @@ template <> size_t GenericFill<procedural_shape_representation_sequence>(const D
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<product_category>(const DB& db, const LIST& params, product_category* in)
{
@ -3033,11 +3033,11 @@ template <> size_t GenericFill<product_category>(const DB& db, const LIST& param
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<product_class>(const DB& db, const LIST& params, product_class* in)
/*template <> size_t GenericFill<product_class>(const DB& db, const LIST& params, product_class* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<product_concept_context>(const DB& db, const LIST& params, product_concept_context* in)
{
@ -3131,11 +3131,11 @@ template <> size_t GenericFill<product_definition_with_associated_documents>(con
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<product_identification>(const DB& db, const LIST& params, product_identification* in)
/*template <> size_t GenericFill<product_identification>(const DB& db, const LIST& params, product_identification* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<product_material_composition_relationship>(const DB& db, const LIST& params, product_material_composition_relationship* in)
{
@ -3174,11 +3174,11 @@ template <> size_t GenericFill<product_related_product_category>(const DB& db, c
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<product_specification>(const DB& db, const LIST& params, product_specification* in)
/*template <> size_t GenericFill<product_specification>(const DB& db, const LIST& params, product_specification* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<tolerance_zone_definition>(const DB& db, const LIST& params, tolerance_zone_definition* in)
{
@ -3289,11 +3289,11 @@ template <> size_t GenericFill<radius_dimension>(const DB& db, const LIST& param
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to radius_dimension"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<range_characteristic>(const DB& db, const LIST& params, range_characteristic* in)
/*template <> size_t GenericFill<range_characteristic>(const DB& db, const LIST& params, range_characteristic* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<ratio_unit>(const DB& db, const LIST& params, ratio_unit* in)
{
@ -3318,11 +3318,11 @@ template <> size_t GenericFill<rational_b_spline_surface>(const DB& db, const LI
if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to rational_b_spline_surface"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<rational_representation_item>(const DB& db, const LIST& params, rational_representation_item* in)
/*template <> size_t GenericFill<rational_representation_item>(const DB& db, const LIST& params, rational_representation_item* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<real_literal>(const DB& db, const LIST& params, real_literal* in)
{
@ -3330,11 +3330,11 @@ template <> size_t GenericFill<real_literal>(const DB& db, const LIST& params, r
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to real_literal"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<real_representation_item>(const DB& db, const LIST& params, real_representation_item* in)
/*template <> size_t GenericFill<real_representation_item>(const DB& db, const LIST& params, real_representation_item* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<rectangular_composite_surface>(const DB& db, const LIST& params, rectangular_composite_surface* in)
{
@ -3410,11 +3410,11 @@ template <> size_t GenericFill<relative_event_occurrence>(const DB& db, const LI
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<rep_item_group>(const DB& db, const LIST& params, rep_item_group* in)
/*template <> size_t GenericFill<rep_item_group>(const DB& db, const LIST& params, rep_item_group* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<reparametrised_composite_curve_segment>(const DB& db, const LIST& params, reparametrised_composite_curve_segment* in)
{
@ -3449,11 +3449,11 @@ template <> size_t GenericFill<requirement_assigned_object>(const DB& db, const
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<requirement_assignment>(const DB& db, const LIST& params, requirement_assignment* in)
/*template <> size_t GenericFill<requirement_assignment>(const DB& db, const LIST& params, requirement_assignment* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<requirement_source>(const DB& db, const LIST& params, requirement_source* in)
{
@ -3891,7 +3891,7 @@ template <> size_t GenericFill<shell_based_wireframe_shape_representation>(const
if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to shell_based_wireframe_shape_representation"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<si_absorbed_dose_unit>(const DB& db, const LIST& params, si_absorbed_dose_unit* in)
/*template <> size_t GenericFill<si_absorbed_dose_unit>(const DB& db, const LIST& params, si_absorbed_dose_unit* in)
{
size_t base = 0;
return base;
@ -3991,7 +3991,7 @@ template <> size_t GenericFill<si_resistance_unit>(const DB& db, const LIST& par
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<si_unit>(const DB& db, const LIST& params, si_unit* in)
{
@ -4010,7 +4010,7 @@ template <> size_t GenericFill<si_unit>(const DB& db, const LIST& params, si_uni
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<simple_boolean_expression>(const DB& db, const LIST& params, simple_boolean_expression* in)
/*template <> size_t GenericFill<simple_boolean_expression>(const DB& db, const LIST& params, simple_boolean_expression* in)
{
size_t base = 0;
return base;
@ -4026,7 +4026,7 @@ template <> size_t GenericFill<slash_expression>(const DB& db, const LIST& param
{
size_t base = GenericFill(db, params, static_cast<binary_numeric_expression*>(in));
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<smeared_material_definition>(const DB& db, const LIST& params, smeared_material_definition* in)
{
@ -5450,11 +5450,11 @@ template <> size_t GenericFill<unary_generic_expression>(const DB& db, const LIS
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<unary_numeric_expression>(const DB& db, const LIST& params, unary_numeric_expression* in)
/*template <> size_t GenericFill<unary_numeric_expression>(const DB& db, const LIST& params, unary_numeric_expression* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<uncertainty_assigned_representation>(const DB& db, const LIST& params, uncertainty_assigned_representation* in)
{
@ -5508,7 +5508,7 @@ template <> size_t GenericFill<usage_association>(const DB& db, const LIST& para
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to usage_association"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<user_defined_curve_font>(const DB& db, const LIST& params, user_defined_curve_font* in)
/*template <> size_t GenericFill<user_defined_curve_font>(const DB& db, const LIST& params, user_defined_curve_font* in)
{
size_t base = 0;
return base;
@ -5524,7 +5524,7 @@ template <> size_t GenericFill<user_defined_terminator_symbol>(const DB& db, con
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<user_selected_shape_elements>(const DB& db, const LIST& params, user_selected_shape_elements* in)
{
@ -5549,11 +5549,11 @@ template <> size_t GenericFill<value_representation_item>(const DB& db, const LI
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<variable_semantics>(const DB& db, const LIST& params, variable_semantics* in)
/*template <> size_t GenericFill<variable_semantics>(const DB& db, const LIST& params, variable_semantics* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<variational_representation_item>(const DB& db, const LIST& params, variational_representation_item* in)
{
@ -5577,11 +5577,11 @@ template <> size_t GenericFill<vector>(const DB& db, const LIST& params, vector*
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<vector_style>(const DB& db, const LIST& params, vector_style* in)
/*template <> size_t GenericFill<vector_style>(const DB& db, const LIST& params, vector_style* in)
{
size_t base = 0;
return base;
}
}*/
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<velocity_measure_with_unit>(const DB& db, const LIST& params, velocity_measure_with_unit* in)
{

View File

@ -93,7 +93,7 @@ const aiImporterDesc *StepFileImporter::GetInfo() const {
static const std::string mode = "rb";
static const std::string StepFileSchema = "CONFIG_CONTROL_DESIGN";
void StepFileImporter::InternReadFile(const std::string &file, aiScene* pScene, IOSystem* pIOHandler) {
void StepFileImporter::InternReadFile(const std::string &file, aiScene*, IOSystem* pIOHandler) {
// Read file into memory
std::shared_ptr<IOStream> fileStream(pIOHandler->Open(file, mode));
if (!fileStream.get()) {

View File

@ -45,6 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "code/Step/STEPFile.h"
#ifdef _WIN32
# pragma warning( disable : 4512 )
#endif // _WIN32
namespace Assimp {
namespace StepFile {
using namespace STEP;
@ -404,7 +407,7 @@ namespace StepFile {
// C++ wrapper type for presentation_style_select
typedef SELECT presentation_style_select;
// C++ wrapper type for presented_item_select
typedef SELECT presented_item_select;
//typedef SELECT presented_item_select;
// C++ wrapper type for pressure_measure
typedef REAL pressure_measure;
// C++ wrapper type for product_definition_or_assembly_relationship
@ -545,7 +548,7 @@ namespace StepFile {
struct absorbed_dose_measure_with_unit;
struct derived_unit;
struct absorbed_dose_unit;
struct abstract_variable;
//struct abstract_variable;
struct acceleration_measure_with_unit;
struct acceleration_unit;
struct action;
@ -646,7 +649,7 @@ namespace StepFile {
struct applied_organizational_project_assignment;
struct person_and_organization_assignment;
struct applied_person_and_organization_assignment;
struct presented_item;
//struct presented_item;
struct applied_presented_item;
struct security_classification_assignment;
struct applied_security_classification_assignment;

View File

@ -185,9 +185,11 @@ void AnimResolver::UpdateAnimRangeSetup()
for (unsigned int i = 0; i < num; ++i) {
m = n+old_size*(i+1);
std::copy(n,n+old_size,m);
if ((*it).pre == LWO::PrePostBehaviour_Oscillate && (reverse = !reverse))
const bool res = ((*it).pre == LWO::PrePostBehaviour_Oscillate);
reverse = !reverse;
if (res && reverse ) {
std::reverse(m,m+old_size-1);
}
}
// update time values
@ -533,7 +535,7 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
// ------------------------------------------------------------------------------------------------
// Extract animation channel
void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0*/)
void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int /*= 0*/)
{
*out = NULL;

File diff suppressed because it is too large Load Diff

View File

@ -76,9 +76,6 @@ public:
LWOImporter();
~LWOImporter();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
@ -86,7 +83,6 @@ public:
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
@ -389,7 +385,7 @@ protected:
unsigned int fileSize;
/** Output scene */
aiScene* pScene;
aiScene* mScene;
/** Configuration option: speed flag set? */
bool configSpeedFlag;
@ -406,8 +402,8 @@ protected:
// ------------------------------------------------------------------------------------------------
inline float LWOImporter::GetF4()
{
inline
float LWOImporter::GetF4() {
float f;
::memcpy(&f, mFileBuffer, 4);
mFileBuffer += 4;

File diff suppressed because it is too large Load Diff

View File

@ -45,22 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the LWS importer class
*/
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
#include "LWS/LWSLoader.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include "Common/Importer.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h>
#include <assimp/SceneCombiner.h>
#include <assimp/GenericProperty.h>
#include <assimp/ParsingUtils.h>
#include <assimp/SceneCombiner.h>
#include <assimp/SkeletonMeshBuilder.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
#include <assimp/fast_atof.h>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <memory>
@ -81,9 +80,8 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Recursive parsing of LWS files
void LWS::Element::Parse (const char*& buffer)
{
for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) {
void LWS::Element::Parse(const char *&buffer) {
for (; SkipSpacesAndLineEnd(&buffer); SkipLine(&buffer)) {
// begin of a new element with children
bool sub = false;
@ -91,27 +89,26 @@ void LWS::Element::Parse (const char*& buffer)
++buffer;
SkipSpaces(&buffer);
sub = true;
}
else if (*buffer == '}')
} else if (*buffer == '}')
return;
children.push_back(Element());
// copy data line - read token per token
const char* cur = buffer;
while (!IsSpaceOrNewLine(*buffer)) ++buffer;
children.back().tokens[0] = std::string(cur,(size_t) (buffer-cur));
const char *cur = buffer;
while (!IsSpaceOrNewLine(*buffer))
++buffer;
children.back().tokens[0] = std::string(cur, (size_t)(buffer - cur));
SkipSpaces(&buffer);
if (children.back().tokens[0] == "Plugin")
{
if (children.back().tokens[0] == "Plugin") {
ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data");
// strange stuff inside Plugin/Endplugin blocks. Needn't
// follow LWS syntax, so we skip over it
for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) {
if (!::strncmp(buffer,"EndPlugin",9)) {
for (; SkipSpacesAndLineEnd(&buffer); SkipLine(&buffer)) {
if (!::strncmp(buffer, "EndPlugin", 9)) {
//SkipLine(&buffer);
break;
}
@ -120,8 +117,9 @@ void LWS::Element::Parse (const char*& buffer)
}
cur = buffer;
while (!IsLineEnd(*buffer)) ++buffer;
children.back().tokens[1] = std::string(cur,(size_t) (buffer-cur));
while (!IsLineEnd(*buffer))
++buffer;
children.back().tokens[1] = std::string(cur, (size_t)(buffer - cur));
// parse more elements recursively
if (sub)
@ -131,28 +129,25 @@ void LWS::Element::Parse (const char*& buffer)
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
LWSImporter::LWSImporter()
: configSpeedFlag(),
io(),
first(),
last(),
fps(),
noSkeletonMesh()
{
LWSImporter::LWSImporter() :
configSpeedFlag(),
io(),
first(),
last(),
fps(),
noSkeletonMesh() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
LWSImporter::~LWSImporter()
{
LWSImporter::~LWSImporter() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool checkSig) const
{
bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "lws" || extension == "mot")
return true;
@ -162,69 +157,67 @@ bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool c
uint32_t tokens[2];
tokens[0] = AI_MAKE_MAGIC("LWSC");
tokens[1] = AI_MAKE_MAGIC("LWMO");
return CheckMagicToken(pIOHandler,pFile,tokens,2);
return CheckMagicToken(pIOHandler, pFile, tokens, 2);
}
return false;
}
// ------------------------------------------------------------------------------------------------
// Get list of file extensions
const aiImporterDesc* LWSImporter::GetInfo () const
{
const aiImporterDesc *LWSImporter::GetInfo() const {
return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void LWSImporter::SetupProperties(const Importer* pImp)
{
void LWSImporter::SetupProperties(const Importer *pImp) {
// AI_CONFIG_FAVOUR_SPEED
configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0));
// AI_CONFIG_IMPORT_LWS_ANIM_START
first = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_START,
150392 /* magic hack */);
150392 /* magic hack */);
// AI_CONFIG_IMPORT_LWS_ANIM_END
last = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_END,
150392 /* magic hack */);
150392 /* magic hack */);
if (last < first) {
std::swap(last,first);
std::swap(last, first);
}
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0;
}
// ------------------------------------------------------------------------------------------------
// Read an envelope description
void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
{
void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
if (dad.children.empty()) {
ASSIMP_LOG_ERROR("LWS: Envelope descriptions must not be empty");
return;
}
// reserve enough storage
std::list< LWS::Element >::const_iterator it = dad.children.begin();;
std::list<LWS::Element>::const_iterator it = dad.children.begin();
;
fill.keys.reserve(strtoul10(it->tokens[1].c_str()));
for (++it; it != dad.children.end(); ++it) {
const char* c = (*it).tokens[1].c_str();
const char *c = (*it).tokens[1].c_str();
if ((*it).tokens[0] == "Key") {
fill.keys.push_back(LWO::Key());
LWO::Key& key = fill.keys.back();
LWO::Key &key = fill.keys.back();
float f;
SkipSpaces(&c);
c = fast_atoreal_move<float>(c,key.value);
c = fast_atoreal_move<float>(c, key.value);
SkipSpaces(&c);
c = fast_atoreal_move<float>(c,f);
c = fast_atoreal_move<float>(c, f);
key.time = f;
unsigned int span = strtoul10(c,&c), num = 0;
unsigned int span = strtoul10(c, &c), num = 0;
switch (span) {
case 0:
@ -251,16 +244,15 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
default:
ASSIMP_LOG_ERROR("LWS: Unknown span type");
}
for (unsigned int i = 0; i < num;++i) {
for (unsigned int i = 0; i < num; ++i) {
SkipSpaces(&c);
c = fast_atoreal_move<float>(c,key.params[i]);
c = fast_atoreal_move<float>(c, key.params[i]);
}
}
else if ((*it).tokens[0] == "Behaviors") {
} else if ((*it).tokens[0] == "Behaviors") {
SkipSpaces(&c);
fill.pre = (LWO::PrePostBehaviour) strtoul10(c,&c);
fill.pre = (LWO::PrePostBehaviour)strtoul10(c, &c);
SkipSpaces(&c);
fill.post = (LWO::PrePostBehaviour) strtoul10(c,&c);
fill.post = (LWO::PrePostBehaviour)strtoul10(c, &c);
}
}
}
@ -268,36 +260,35 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
// ------------------------------------------------------------------------------------------------
// Read animation channels in the old LightWave animation format
void LWSImporter::ReadEnvelope_Old(
std::list< LWS::Element >::const_iterator& it,
const std::list< LWS::Element >::const_iterator& end,
LWS::NodeDesc& nodes,
unsigned int /*version*/)
{
unsigned int num,sub_num;
if (++it == end)goto unexpected_end;
std::list<LWS::Element>::const_iterator &it,
const std::list<LWS::Element>::const_iterator &end,
LWS::NodeDesc &nodes,
unsigned int /*version*/) {
unsigned int num, sub_num;
if (++it == end) goto unexpected_end;
num = strtoul10((*it).tokens[0].c_str());
for (unsigned int i = 0; i < num; ++i) {
nodes.channels.push_back(LWO::Envelope());
LWO::Envelope& envl = nodes.channels.back();
LWO::Envelope &envl = nodes.channels.back();
envl.index = i;
envl.type = (LWO::EnvelopeType)(i+1);
envl.type = (LWO::EnvelopeType)(i + 1);
if (++it == end)goto unexpected_end;
if (++it == end) goto unexpected_end;
sub_num = strtoul10((*it).tokens[0].c_str());
for (unsigned int n = 0; n < sub_num;++n) {
for (unsigned int n = 0; n < sub_num; ++n) {
if (++it == end)goto unexpected_end;
if (++it == end) goto unexpected_end;
// parse value and time, skip the rest for the moment.
LWO::Key key;
const char* c = fast_atoreal_move<float>((*it).tokens[0].c_str(),key.value);
const char *c = fast_atoreal_move<float>((*it).tokens[0].c_str(), key.value);
SkipSpaces(&c);
float f;
fast_atoreal_move<float>((*it).tokens[0].c_str(),f);
fast_atoreal_move<float>((*it).tokens[0].c_str(), f);
key.time = f;
envl.keys.push_back(key);
@ -311,51 +302,49 @@ unexpected_end:
// ------------------------------------------------------------------------------------------------
// Setup a nice name for a node
void LWSImporter::SetupNodeName(aiNode* nd, LWS::NodeDesc& src)
{
void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
const unsigned int combined = src.number | ((unsigned int)src.type) << 28u;
// the name depends on the type. We break LWS's strange naming convention
// and return human-readable, but still machine-parsable and unique, strings.
if (src.type == LWS::NodeDesc::OBJECT) {
if (src.type == LWS::NodeDesc::OBJECT) {
if (src.path.length()) {
std::string::size_type s = src.path.find_last_of("\\/");
if (s == std::string::npos)
s = 0;
else ++s;
else
++s;
std::string::size_type t = src.path.substr(s).find_last_of(".");
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.path.substr(s).substr(0,t).c_str(),combined);
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
return;
}
}
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.name,combined);
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.name, combined);
}
// ------------------------------------------------------------------------------------------------
// Recursively build the scenegraph
void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<AttachmentInfo>& attach,
BatchLoader& batch,
aiCamera**& camOut,
aiLight**& lightOut,
std::vector<aiNodeAnim*>& animOut)
{
void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector<AttachmentInfo> &attach,
BatchLoader &batch,
aiCamera **&camOut,
aiLight **&lightOut,
std::vector<aiNodeAnim *> &animOut) {
// Setup a very cryptic name for the node, we want the user to be happy
SetupNodeName(nd,src);
aiNode* ndAnim = nd;
SetupNodeName(nd, src);
aiNode *ndAnim = nd;
// If the node is an object
if (src.type == LWS::NodeDesc::OBJECT) {
// If the object is from an external file, get it
aiScene* obj = NULL;
if (src.path.length() ) {
aiScene *obj = NULL;
if (src.path.length()) {
obj = batch.GetImport(src.id);
if (!obj) {
ASSIMP_LOG_ERROR("LWS: Failed to read external file " + src.path);
}
else {
} else {
if (obj->mRootNode->mNumChildren == 1) {
//If the pivot is not set for this layer, get it from the external object
@ -366,7 +355,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
}
//Remove first node from obj (the old pivot), reset transform of second node (the mesh node)
aiNode* newRootNode = obj->mRootNode->mChildren[0];
aiNode *newRootNode = obj->mRootNode->mChildren[0];
obj->mRootNode->mChildren[0] = NULL;
delete obj->mRootNode;
@ -384,7 +373,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
//Add the attachment node to it
nd->mNumChildren = 1;
nd->mChildren = new aiNode*[1];
nd->mChildren = new aiNode *[1];
nd->mChildren[0] = new aiNode();
nd->mChildren[0]->mParent = nd;
nd->mChildren[0]->mTransformation.a4 = -src.pivotPos.x;
@ -397,16 +386,16 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
//Push attachment, if the object came from an external file
if (obj) {
attach.push_back(AttachmentInfo(obj,nd));
attach.push_back(AttachmentInfo(obj, nd));
}
}
// If object is a light source - setup a corresponding ai structure
else if (src.type == LWS::NodeDesc::LIGHT) {
aiLight* lit = *lightOut++ = new aiLight();
aiLight *lit = *lightOut++ = new aiLight();
// compute final light color
lit->mColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity;
lit->mColorDiffuse = lit->mColorSpecular = src.lightColor * src.lightIntensity;
// name to attach light to node -> unique due to LWs indexing system
lit->mName = nd->mName;
@ -415,14 +404,13 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
if (src.lightType == 2) { /* spot light */
lit->mType = aiLightSource_SPOT;
lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle );
lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle );
lit->mAngleInnerCone = (float)AI_DEG_TO_RAD(src.lightConeAngle);
lit->mAngleOuterCone = lit->mAngleInnerCone + (float)AI_DEG_TO_RAD(src.lightEdgeAngle);
}
else if (src.lightType == 1) { /* directional light source */
} else if (src.lightType == 1) { /* directional light source */
lit->mType = aiLightSource_DIRECTIONAL;
}
else lit->mType = aiLightSource_POINT;
} else
lit->mType = aiLightSource_POINT;
// fixme: no proper handling of light falloffs yet
if (src.lightFalloffType == 1)
@ -435,22 +423,22 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
// If object is a camera - setup a corresponding ai structure
else if (src.type == LWS::NodeDesc::CAMERA) {
aiCamera* cam = *camOut++ = new aiCamera();
aiCamera *cam = *camOut++ = new aiCamera();
// name to attach cam to node -> unique due to LWs indexing system
cam->mName = nd->mName;
}
// Get the node transformation from the LWO key
LWO::AnimResolver resolver(src.channels,fps);
LWO::AnimResolver resolver(src.channels, fps);
resolver.ExtractBindPose(ndAnim->mTransformation);
// .. and construct animation channels
aiNodeAnim* anim = NULL;
aiNodeAnim *anim = NULL;
if (first != last) {
resolver.SetAnimationRange(first,last);
resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO);
resolver.SetAnimationRange(first, last);
resolver.ExtractAnimChannel(&anim, AI_LWO_ANIM_FLAG_SAMPLE_ANIMS | AI_LWO_ANIM_FLAG_START_AT_ZERO);
if (anim) {
anim->mNodeName = ndAnim->mName;
animOut.push_back(anim);
@ -459,27 +447,25 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
// Add children
if (!src.children.empty()) {
nd->mChildren = new aiNode*[src.children.size()];
for (std::list<LWS::NodeDesc*>::iterator it = src.children.begin(); it != src.children.end(); ++it) {
aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode();
nd->mChildren = new aiNode *[src.children.size()];
for (std::list<LWS::NodeDesc *>::iterator it = src.children.begin(); it != src.children.end(); ++it) {
aiNode *ndd = nd->mChildren[nd->mNumChildren++] = new aiNode();
ndd->mParent = nd;
BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut);
BuildGraph(ndd, **it, attach, batch, camOut, lightOut, animOut);
}
}
}
// ------------------------------------------------------------------------------------------------
// Determine the exact location of a LWO file
std::string LWSImporter::FindLWOFile(const std::string& in)
{
std::string LWSImporter::FindLWOFile(const std::string &in) {
// insert missing directory separator if necessary
std::string tmp;
if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
{
if (in.length() > 3 && in[1] == ':' && in[2] != '\\' && in[2] != '/') {
tmp = in[0] + (std::string(":\\") + in.substr(2));
}
else tmp = in;
} else
tmp = in;
if (io->Exists(tmp)) {
return in;
@ -503,35 +489,34 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
return test;
}
// return original path, maybe the IOsystem knows better
return tmp;
}
// ------------------------------------------------------------------------------------------------
// Read file into given scene data structure
void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler)
{
void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene,
IOSystem *pIOHandler) {
io = pIOHandler;
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if( file.get() == NULL) {
throw DeadlyImportError( "Failed to open LWS file " + pFile + ".");
if (file.get() == NULL) {
throw DeadlyImportError("Failed to open LWS file " + pFile + ".");
}
// Allocate storage and copy the contents of the file to a memory buffer
std::vector< char > mBuffer;
TextFileToBuffer(file.get(),mBuffer);
std::vector<char> mBuffer;
TextFileToBuffer(file.get(), mBuffer);
// Parse the file structure
LWS::Element root; const char* dummy = &mBuffer[0];
LWS::Element root;
const char *dummy = &mBuffer[0];
root.Parse(dummy);
// Construct a Batchimporter to read more files recursively
BatchLoader batch(pIOHandler);
// batch.SetBasePath(pFile);
// batch.SetBasePath(pFile);
// Construct an array to receive the flat output graph
std::list<LWS::NodeDesc> nodes;
@ -541,7 +526,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
// check magic identifier, 'LWSC'
bool motion_file = false;
std::list< LWS::Element >::const_iterator it = root.children.begin();
std::list<LWS::Element>::const_iterator it = root.children.begin();
if ((*it).tokens[0] == "LWMO")
motion_file = true;
@ -554,54 +539,54 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
unsigned int version = strtoul10((*it).tokens[0].c_str());
ASSIMP_LOG_INFO("LWS file format version is " + (*it).tokens[0]);
first = 0.;
last = 60.;
fps = 25.; /* seems to be a good default frame rate */
last = 60.;
fps = 25.; /* seems to be a good default frame rate */
// Now read all elements in a very straghtforward manner
for (; it != root.children.end(); ++it) {
const char* c = (*it).tokens[1].c_str();
const char *c = (*it).tokens[1].c_str();
// 'FirstFrame': begin of animation slice
if ((*it).tokens[0] == "FirstFrame") {
if (150392. != first /* see SetupProperties() */)
first = strtoul10(c,&c)-1.; /* we're zero-based */
if (150392. != first /* see SetupProperties() */)
first = strtoul10(c, &c) - 1.; /* we're zero-based */
}
// 'LastFrame': end of animation slice
else if ((*it).tokens[0] == "LastFrame") {
if (150392. != last /* see SetupProperties() */)
last = strtoul10(c,&c)-1.; /* we're zero-based */
if (150392. != last /* see SetupProperties() */)
last = strtoul10(c, &c) - 1.; /* we're zero-based */
}
// 'FramesPerSecond': frames per second
else if ((*it).tokens[0] == "FramesPerSecond") {
fps = strtoul10(c,&c);
fps = strtoul10(c, &c);
}
// 'LoadObjectLayer': load a layer of a specific LWO file
else if ((*it).tokens[0] == "LoadObjectLayer") {
// get layer index
const int layer = strtoul10(c,&c);
const int layer = strtoul10(c, &c);
// setup the layer to be loaded
BatchLoader::PropertyMap props;
SetGenericProperty(props.ints,AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,layer);
SetGenericProperty(props.ints, AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY, layer);
// add node to list
LWS::NodeDesc d;
d.type = LWS::NodeDesc::OBJECT;
if (version >= 4) { // handle LWSC 4 explicit ID
SkipSpaces(&c);
d.number = strtoul16(c,&c) & AI_LWS_MASK;
}
else d.number = cur_object++;
d.number = strtoul16(c, &c) & AI_LWS_MASK;
} else
d.number = cur_object++;
// and add the file to the import list
SkipSpaces(&c);
std::string path = FindLWOFile( c );
std::string path = FindLWOFile(c);
d.path = path;
d.id = batch.AddLoadRequest(path,0,&props);
d.id = batch.AddLoadRequest(path, 0, &props);
nodes.push_back(d);
num_object++;
@ -614,12 +599,12 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
d.type = LWS::NodeDesc::OBJECT;
if (version >= 4) { // handle LWSC 4 explicit ID
d.number = strtoul16(c,&c) & AI_LWS_MASK;
d.number = strtoul16(c, &c) & AI_LWS_MASK;
SkipSpaces(&c);
}
else d.number = cur_object++;
std::string path = FindLWOFile( c );
d.id = batch.AddLoadRequest(path,0,NULL);
} else
d.number = cur_object++;
std::string path = FindLWOFile(c);
d.id = batch.AddLoadRequest(path, 0, NULL);
d.path = path;
nodes.push_back(d);
@ -632,10 +617,10 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
LWS::NodeDesc d;
d.type = LWS::NodeDesc::OBJECT;
if (version >= 4) { // handle LWSC 4 explicit ID
d.number = strtoul16(c,&c) & AI_LWS_MASK;
d.number = strtoul16(c, &c) & AI_LWS_MASK;
SkipSpaces(&c);
}
else d.number = cur_object++;
} else
d.number = cur_object++;
d.name = c;
nodes.push_back(d);
@ -662,13 +647,13 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
// important: index of channel
nodes.back().channels.push_back(LWO::Envelope());
LWO::Envelope& env = nodes.back().channels.back();
LWO::Envelope &env = nodes.back().channels.back();
env.index = strtoul10(c);
// currently we can just interpret the standard channels 0...9
// (hack) assume that index-i yields the binary channel type from LWO
env.type = (LWO::EnvelopeType)(env.index+1);
env.type = (LWO::EnvelopeType)(env.index + 1);
}
// 'Envelope': a single animation channel
@ -676,18 +661,18 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().channels.empty())
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Envelope\'");
else {
ReadEnvelope((*it),nodes.back().channels.back());
ReadEnvelope((*it), nodes.back().channels.back());
}
}
// 'ObjectMotion': animation information for older lightwave formats
else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" ||
(*it).tokens[0] == "CameraMotion" ||
(*it).tokens[0] == "LightMotion")) {
else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" ||
(*it).tokens[0] == "CameraMotion" ||
(*it).tokens[0] == "LightMotion")) {
if (nodes.empty())
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'<Light|Object|Camera>Motion\'");
else {
ReadEnvelope_Old(it,root.children.end(),nodes.back(),version);
ReadEnvelope_Old(it, root.children.end(), nodes.back(), version);
}
}
// 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2
@ -695,11 +680,13 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty())
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Pre/PostBehavior'");
else {
for (std::list<LWO::Envelope>::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) {
for (std::list<LWO::Envelope>::iterator envelopeIt = nodes.back().channels.begin(); envelopeIt != nodes.back().channels.end(); ++envelopeIt) {
// two ints per envelope
LWO::Envelope& env = *it;
env.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
env.post = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
LWO::Envelope &env = *envelopeIt;
env.pre = (LWO::PrePostBehaviour)strtoul10(c, &c);
SkipSpaces(&c);
env.post = (LWO::PrePostBehaviour)strtoul10(c, &c);
SkipSpaces(&c);
}
}
}
@ -708,7 +695,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty())
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentItem\'");
else nodes.back().parent = strtoul16(c,&c);
else
nodes.back().parent = strtoul16(c, &c);
}
// 'ParentObject': deprecated one for older formats
else if (version < 3 && (*it).tokens[0] == "ParentObject") {
@ -716,7 +704,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentObject\'");
else {
nodes.back().parent = strtoul10(c,&c) | (1u << 28u);
nodes.back().parent = strtoul10(c, &c) | (1u << 28u);
}
}
// 'AddCamera': add a camera to the scenegraph
@ -727,9 +715,9 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
d.type = LWS::NodeDesc::CAMERA;
if (version >= 4) { // handle LWSC 4 explicit ID
d.number = strtoul16(c,&c) & AI_LWS_MASK;
}
else d.number = cur_camera++;
d.number = strtoul16(c, &c) & AI_LWS_MASK;
} else
d.number = cur_camera++;
nodes.push_back(d);
num_camera++;
@ -739,7 +727,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'CameraName\'");
else nodes.back().name = c;
else
nodes.back().name = c;
}
// 'AddLight': add a light to the scenegraph
else if ((*it).tokens[0] == "AddLight") {
@ -749,9 +738,9 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
d.type = LWS::NodeDesc::LIGHT;
if (version >= 4) { // handle LWSC 4 explicit ID
d.number = strtoul16(c,&c) & AI_LWS_MASK;
}
else d.number = cur_light++;
d.number = strtoul16(c, &c) & AI_LWS_MASK;
} else
d.number = cur_light++;
nodes.push_back(d);
num_light++;
@ -761,14 +750,16 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightName\'");
else nodes.back().name = c;
else
nodes.back().name = c;
}
// 'LightIntensity': set intensity of currently active light
else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) {
else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity") {
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightIntensity\'");
else fast_atoreal_move<float>(c, nodes.back().lightIntensity );
else
fast_atoreal_move<float>(c, nodes.back().lightIntensity);
}
// 'LightType': set type of currently active light
@ -776,7 +767,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightType\'");
else nodes.back().lightType = strtoul10(c);
else
nodes.back().lightType = strtoul10(c);
}
// 'LightFalloffType': set falloff type of currently active light
@ -784,7 +776,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightFalloffType\'");
else nodes.back().lightFalloffType = strtoul10(c);
else
nodes.back().lightFalloffType = strtoul10(c);
}
// 'LightConeAngle': set cone angle of currently active light
@ -792,7 +785,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightConeAngle\'");
else nodes.back().lightConeAngle = fast_atof(c);
else
nodes.back().lightConeAngle = fast_atof(c);
}
// 'LightEdgeAngle': set area where we're smoothing from min to max intensity
@ -800,7 +794,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightEdgeAngle\'");
else nodes.back().lightEdgeAngle = fast_atof(c);
else
nodes.back().lightEdgeAngle = fast_atof(c);
}
// 'LightColor': set color of currently active light
@ -809,11 +804,11 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'");
else {
c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.r );
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.r);
SkipSpaces(&c);
c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.g );
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.g);
SkipSpaces(&c);
c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.b );
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.b);
}
}
@ -822,11 +817,11 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty())
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'");
else {
c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.x );
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.x);
SkipSpaces(&c);
c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.y );
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.y);
SkipSpaces(&c);
c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.z );
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.z);
// Mark pivotPos as set
nodes.back().isPivotSet = true;
}
@ -834,79 +829,80 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
}
// resolve parenting
for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
for (std::list<LWS::NodeDesc>::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) {
// check whether there is another node which calls us a parent
for (std::list<LWS::NodeDesc>::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) {
if (dit != it && *it == (*dit).parent) {
if (dit != ndIt && *ndIt == (*dit).parent) {
if ((*dit).parent_resolved) {
// fixme: it's still possible to produce an overflow due to cross references ..
ASSIMP_LOG_ERROR("LWS: Found cross reference in scene-graph");
continue;
}
(*it).children.push_back(&*dit);
(*dit).parent_resolved = &*it;
ndIt->children.push_back(&*dit);
(*dit).parent_resolved = &*ndIt;
}
}
}
// find out how many nodes have no parent yet
unsigned int no_parent = 0;
for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
if (!(*it).parent_resolved)
++ no_parent;
for (std::list<LWS::NodeDesc>::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) {
if (!ndIt->parent_resolved) {
++no_parent;
}
}
if (!no_parent)
if (!no_parent) {
throw DeadlyImportError("LWS: Unable to find scene root node");
}
// Load all subsequent files
batch.LoadAll();
// and build the final output graph by attaching the loaded external
// files to ourselves. first build a master graph
aiScene* master = new aiScene();
aiNode* nd = master->mRootNode = new aiNode();
aiScene *master = new aiScene();
aiNode *nd = master->mRootNode = new aiNode();
// allocate storage for cameras&lights
if (num_camera) {
master->mCameras = new aiCamera*[master->mNumCameras = num_camera];
master->mCameras = new aiCamera *[master->mNumCameras = num_camera];
}
aiCamera** cams = master->mCameras;
aiCamera **cams = master->mCameras;
if (num_light) {
master->mLights = new aiLight*[master->mNumLights = num_light];
master->mLights = new aiLight *[master->mNumLights = num_light];
}
aiLight** lights = master->mLights;
aiLight **lights = master->mLights;
std::vector<AttachmentInfo> attach;
std::vector<aiNodeAnim*> anims;
std::vector<aiNodeAnim *> anims;
nd->mName.Set("<LWSRoot>");
nd->mChildren = new aiNode*[no_parent];
for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
if (!(*it).parent_resolved) {
aiNode* ro = nd->mChildren[ nd->mNumChildren++ ] = new aiNode();
nd->mChildren = new aiNode *[no_parent];
for (std::list<LWS::NodeDesc>::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) {
if (!ndIt->parent_resolved) {
aiNode *ro = nd->mChildren[nd->mNumChildren++] = new aiNode();
ro->mParent = nd;
// ... and build the scene graph. If we encounter object nodes,
// add then to our attachment table.
BuildGraph(ro,*it, attach, batch, cams, lights, anims);
BuildGraph(ro, *ndIt, attach, batch, cams, lights, anims);
}
}
// create a master animation channel for us
if (anims.size()) {
master->mAnimations = new aiAnimation*[master->mNumAnimations = 1];
aiAnimation* anim = master->mAnimations[0] = new aiAnimation();
master->mAnimations = new aiAnimation *[master->mNumAnimations = 1];
aiAnimation *anim = master->mAnimations[0] = new aiAnimation();
anim->mName.Set("LWSMasterAnim");
// LWS uses seconds as time units, but we convert to frames
anim->mTicksPerSecond = fps;
anim->mDuration = last-(first-1); /* fixme ... zero or one-based?*/
anim->mDuration = last - (first - 1); /* fixme ... zero or one-based?*/
anim->mChannels = new aiNodeAnim*[anim->mNumChannels = static_cast<unsigned int>(anims.size())];
std::copy(anims.begin(),anims.end(),anim->mChannels);
anim->mChannels = new aiNodeAnim *[anim->mNumChannels = static_cast<unsigned int>(anims.size())];
std::copy(anims.begin(), anims.end(), anim->mChannels);
}
// convert the master scene to RH
@ -918,9 +914,10 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
flipper.Execute(master);
// OK ... finally build the output graph
SceneCombiner::MergeScenes(&pScene,master,attach,
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0));
SceneCombiner::MergeScenes(&pScene, master, attach,
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) :
0));
// Check flags
if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
@ -931,7 +928,6 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
SkeletonMeshBuilder builder(pScene);
}
}
}
#endif // !! ASSIMP_BUILD_NO_LWS_IMPORTER

View File

@ -64,9 +64,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Exporter.hpp>
#include <assimp/IOSystem.hpp>
#include "M3DWrapper.h"
#include "M3DExporter.h"
#include "M3DMaterials.h"
#include "M3DWrapper.h"
// RESOURCES:
// https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md
@ -87,186 +87,187 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ------------------------------------------------------------------------------------------------
// helper to add a vertex (private to NodeWalk)
m3dv_t *AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) {
if (v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0;
if (v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0;
if (v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0;
if (v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0;
vrtx = (m3dv_t *)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t));
memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t));
*idx = *numvrtx;
(*numvrtx)++;
return vrtx;
if (v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0;
if (v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0;
if (v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0;
if (v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0;
vrtx = (m3dv_t *)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t));
memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t));
*idx = *numvrtx;
(*numvrtx)++;
return vrtx;
}
// ------------------------------------------------------------------------------------------------
// helper to add a tmap (private to NodeWalk)
m3dti_t *AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx) {
tmap = (m3dti_t *)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t));
memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t));
*idx = *numtmap;
(*numtmap)++;
return tmap;
tmap = (m3dti_t *)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t));
memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t));
*idx = *numtmap;
(*numtmap)++;
return tmap;
}
// ------------------------------------------------------------------------------------------------
// convert aiColor4D into uint32_t
uint32_t mkColor(aiColor4D *c) {
return ((uint8_t)(c->a * 255) << 24L) |
((uint8_t)(c->b * 255) << 16L) |
((uint8_t)(c->g * 255) << 8L) |
((uint8_t)(c->r * 255) << 0L);
return ((uint8_t)(c->a * 255) << 24L) |
((uint8_t)(c->b * 255) << 16L) |
((uint8_t)(c->g * 255) << 8L) |
((uint8_t)(c->r * 255) << 0L);
}
// ------------------------------------------------------------------------------------------------
// add a material property to the output
void addProp(m3dm_t *m, uint8_t type, uint32_t value) {
unsigned int i;
i = m->numprop++;
m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
if (!m->prop) {
throw DeadlyExportError("memory allocation error");
}
m->prop[i].type = type;
m->prop[i].value.num = value;
unsigned int i;
i = m->numprop++;
m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
if (!m->prop) {
throw DeadlyExportError("memory allocation error");
}
m->prop[i].type = type;
m->prop[i].value.num = value;
}
// ------------------------------------------------------------------------------------------------
// convert aiString to identifier safe C string. This is a duplication of _m3d_safestr
char *SafeStr(aiString str, bool isStrict)
{
char *s = (char *)&str.data;
char *d, *ret;
int i, len;
char *SafeStr(aiString str, bool isStrict) {
char *s = (char *)&str.data;
char *d, *ret;
int i, len;
for(len = str.length + 1; *s && (*s == ' ' || *s == '\t'); s++, len--);
if(len > 255) len = 255;
ret = (char *)M3D_MALLOC(len + 1);
if (!ret) {
throw DeadlyExportError("memory allocation error");
}
for(i = 0, d = ret; i < len && *s && *s != '\r' && *s != '\n'; s++, d++, i++) {
*d = isStrict && (*s == ' ' || *s == '\t' || *s == '/' || *s == '\\') ? '_' : (*s == '\t' ? ' ' : *s);
}
for(; d > ret && (*(d-1) == ' ' || *(d-1) == '\t'); d--);
*d = 0;
return ret;
for (len = str.length + 1; *s && (*s == ' ' || *s == '\t'); s++, len--)
;
if (len > 255) len = 255;
ret = (char *)M3D_MALLOC(len + 1);
if (!ret) {
throw DeadlyExportError("memory allocation error");
}
for (i = 0, d = ret; i < len && *s && *s != '\r' && *s != '\n'; s++, d++, i++) {
*d = isStrict && (*s == ' ' || *s == '\t' || *s == '/' || *s == '\\') ? '_' : (*s == '\t' ? ' ' : *s);
}
for (; d > ret && (*(d - 1) == ' ' || *(d - 1) == '\t'); d--)
;
*d = 0;
return ret;
}
// ------------------------------------------------------------------------------------------------
// add a material to the output
M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
unsigned int mi = M3D_NOTDEFINED;
aiColor4D c;
aiString name;
ai_real f;
char *fn;
unsigned int mi = M3D_NOTDEFINED;
aiColor4D c;
aiString name;
ai_real f;
char *fn;
if (mat && mat->Get(AI_MATKEY_NAME, name) == AI_SUCCESS && name.length &&
strcmp((char *)&name.data, AI_DEFAULT_MATERIAL_NAME)) {
// check if we have saved a material by this name. This has to be done
// because only the referenced materials should be added to the output
for (unsigned int i = 0; i < m3d->nummaterial; i++)
if (!strcmp((char *)&name.data, m3d->material[i].name)) {
mi = i;
break;
}
// if not found, add the material to the output
if (mi == M3D_NOTDEFINED) {
unsigned int k;
mi = m3d->nummaterial++;
m3d->material = (m3dm_t *)M3D_REALLOC(m3d->material, m3d->nummaterial * sizeof(m3dm_t));
if (!m3d->material) {
throw DeadlyExportError("memory allocation error");
}
m3d->material[mi].name = SafeStr(name, true);
m3d->material[mi].numprop = 0;
m3d->material[mi].prop = NULL;
// iterate through the material property table and see what we got
for (k = 0; k < 15; k++) {
unsigned int j;
if (m3d_propertytypes[k].format == m3dpf_map)
continue;
if (aiProps[k].pKey) {
switch (m3d_propertytypes[k].format) {
case m3dpf_color:
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, c) == AI_SUCCESS)
addProp(&m3d->material[mi],
m3d_propertytypes[k].id, mkColor(&c));
break;
case m3dpf_float:
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, f) == AI_SUCCESS)
addProp(&m3d->material[mi],
m3d_propertytypes[k].id,
/* not (uint32_t)f, because we don't want to convert
if (mat && mat->Get(AI_MATKEY_NAME, name) == AI_SUCCESS && name.length &&
strcmp((char *)&name.data, AI_DEFAULT_MATERIAL_NAME)) {
// check if we have saved a material by this name. This has to be done
// because only the referenced materials should be added to the output
for (unsigned int i = 0; i < m3d->nummaterial; i++)
if (!strcmp((char *)&name.data, m3d->material[i].name)) {
mi = i;
break;
}
// if not found, add the material to the output
if (mi == M3D_NOTDEFINED) {
unsigned int k;
mi = m3d->nummaterial++;
m3d->material = (m3dm_t *)M3D_REALLOC(m3d->material, m3d->nummaterial * sizeof(m3dm_t));
if (!m3d->material) {
throw DeadlyExportError("memory allocation error");
}
m3d->material[mi].name = SafeStr(name, true);
m3d->material[mi].numprop = 0;
m3d->material[mi].prop = NULL;
// iterate through the material property table and see what we got
for (k = 0; k < 15; k++) {
unsigned int j;
if (m3d_propertytypes[k].format == m3dpf_map)
continue;
if (aiProps[k].pKey) {
switch (m3d_propertytypes[k].format) {
case m3dpf_color:
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, c) == AI_SUCCESS)
addProp(&m3d->material[mi],
m3d_propertytypes[k].id, mkColor(&c));
break;
case m3dpf_float:
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, f) == AI_SUCCESS)
addProp(&m3d->material[mi],
m3d_propertytypes[k].id,
/* not (uint32_t)f, because we don't want to convert
* it, we want to see it as 32 bits of memory */
*((uint32_t *)&f));
break;
case m3dpf_uint8:
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, j) == AI_SUCCESS) {
// special conversion for illumination model property
if (m3d_propertytypes[k].id == m3dp_il) {
switch (j) {
case aiShadingMode_NoShading: j = 0; break;
case aiShadingMode_Phong: j = 2; break;
default: j = 1; break;
}
}
addProp(&m3d->material[mi],
m3d_propertytypes[k].id, j);
}
break;
default:
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, j) == AI_SUCCESS)
addProp(&m3d->material[mi],
m3d_propertytypes[k].id, j);
break;
}
}
if (aiTxProps[k].pKey &&
mat->GetTexture((aiTextureType)aiTxProps[k].type,
aiTxProps[k].index, &name, NULL, NULL, NULL,
NULL, NULL) == AI_SUCCESS) {
unsigned int i;
for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++)
;
if (j && name.data[j] == '.' &&
(name.data[j + 1] == 'p' || name.data[j + 1] == 'P') &&
(name.data[j + 1] == 'n' || name.data[j + 1] == 'N') &&
(name.data[j + 1] == 'g' || name.data[j + 1] == 'G'))
name.data[j] = 0;
// do we have this texture saved already?
fn = SafeStr(name, true);
for (j = 0, i = M3D_NOTDEFINED; j < m3d->numtexture; j++)
if (!strcmp(fn, m3d->texture[j].name)) {
i = j;
free(fn);
break;
}
if (i == M3D_NOTDEFINED) {
i = m3d->numtexture++;
m3d->texture = (m3dtx_t *)M3D_REALLOC(
m3d->texture,
m3d->numtexture * sizeof(m3dtx_t));
if (!m3d->texture) {
throw DeadlyExportError("memory allocation error");
}
// we don't need the texture itself, only its name
m3d->texture[i].name = fn;
m3d->texture[i].w = 0;
m3d->texture[i].h = 0;
m3d->texture[i].d = NULL;
}
addProp(&m3d->material[mi],
m3d_propertytypes[k].id + 128, i);
}
}
}
}
return mi;
*((uint32_t *)&f));
break;
case m3dpf_uint8:
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, j) == AI_SUCCESS) {
// special conversion for illumination model property
if (m3d_propertytypes[k].id == m3dp_il) {
switch (j) {
case aiShadingMode_NoShading: j = 0; break;
case aiShadingMode_Phong: j = 2; break;
default: j = 1; break;
}
}
addProp(&m3d->material[mi],
m3d_propertytypes[k].id, j);
}
break;
default:
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, j) == AI_SUCCESS)
addProp(&m3d->material[mi],
m3d_propertytypes[k].id, j);
break;
}
}
if (aiTxProps[k].pKey &&
mat->GetTexture((aiTextureType)aiTxProps[k].type,
aiTxProps[k].index, &name, NULL, NULL, NULL,
NULL, NULL) == AI_SUCCESS) {
unsigned int i;
for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++)
;
if (j && name.data[j] == '.' &&
(name.data[j + 1] == 'p' || name.data[j + 1] == 'P') &&
(name.data[j + 1] == 'n' || name.data[j + 1] == 'N') &&
(name.data[j + 1] == 'g' || name.data[j + 1] == 'G'))
name.data[j] = 0;
// do we have this texture saved already?
fn = SafeStr(name, true);
for (j = 0, i = M3D_NOTDEFINED; j < m3d->numtexture; j++)
if (!strcmp(fn, m3d->texture[j].name)) {
i = j;
free(fn);
break;
}
if (i == M3D_NOTDEFINED) {
i = m3d->numtexture++;
m3d->texture = (m3dtx_t *)M3D_REALLOC(
m3d->texture,
m3d->numtexture * sizeof(m3dtx_t));
if (!m3d->texture) {
throw DeadlyExportError("memory allocation error");
}
// we don't need the texture itself, only its name
m3d->texture[i].name = fn;
m3d->texture[i].w = 0;
m3d->texture[i].h = 0;
m3d->texture[i].d = NULL;
}
addProp(&m3d->material[mi],
m3d_propertytypes[k].id + 128, i);
}
}
}
}
return mi;
}
namespace Assimp {
@ -275,161 +276,161 @@ namespace Assimp {
// Worker function for exporting a scene to binary M3D.
// Prototyped and registered in Exporter.cpp
void ExportSceneM3D(
const char *pFile,
IOSystem *pIOSystem,
const aiScene *pScene,
const ExportProperties *pProperties) {
// initialize the exporter
M3DExporter exporter(pScene, pProperties);
const char *pFile,
IOSystem *pIOSystem,
const aiScene *pScene,
const ExportProperties *pProperties) {
// initialize the exporter
M3DExporter exporter(pScene, pProperties);
// perform binary export
exporter.doExport(pFile, pIOSystem, false);
// perform binary export
exporter.doExport(pFile, pIOSystem, false);
}
// ---------------------------------------------------------------------
// Worker function for exporting a scene to ASCII A3D.
// Prototyped and registered in Exporter.cpp
void ExportSceneM3DA(
const char *pFile,
IOSystem *pIOSystem,
const aiScene *pScene,
const ExportProperties *pProperties
const char *,
IOSystem*,
const aiScene*,
const ExportProperties *
) {
#ifdef M3D_ASCII
// initialize the exporter
M3DExporter exporter(pScene, pProperties);
// initialize the exporter
M3DExporter exporter(pScene, pProperties);
// perform ascii export
exporter.doExport(pFile, pIOSystem, true);
// perform ascii export
exporter.doExport(pFile, pIOSystem, true);
#else
throw DeadlyExportError("Assimp configured without M3D_ASCII support");
throw DeadlyExportError("Assimp configured without M3D_ASCII support");
#endif
}
// ------------------------------------------------------------------------------------------------
M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) :
mScene(pScene),
mProperties(pProperties),
outfile() {}
mScene(pScene),
mProperties(pProperties),
outfile() {}
// ------------------------------------------------------------------------------------------------
void M3DExporter::doExport(
const char *pFile,
IOSystem *pIOSystem,
bool toAscii) {
// TODO: convert mProperties into M3D_EXP_* flags
(void)mProperties;
const char *pFile,
IOSystem *pIOSystem,
bool toAscii) {
// TODO: convert mProperties into M3D_EXP_* flags
(void)mProperties;
// open the indicated file for writing (in binary / ASCII mode)
outfile.reset(pIOSystem->Open(pFile, toAscii ? "wt" : "wb"));
if (!outfile) {
throw DeadlyExportError("could not open output .m3d file: " + std::string(pFile));
}
// open the indicated file for writing (in binary / ASCII mode)
outfile.reset(pIOSystem->Open(pFile, toAscii ? "wt" : "wb"));
if (!outfile) {
throw DeadlyExportError("could not open output .m3d file: " + std::string(pFile));
}
M3DWrapper m3d;
if (!m3d) {
throw DeadlyExportError("memory allocation error");
}
m3d->name = SafeStr(mScene->mRootNode->mName, false);
M3DWrapper m3d;
if (!m3d) {
throw DeadlyExportError("memory allocation error");
}
m3d->name = SafeStr(mScene->mRootNode->mName, false);
// Create a model from assimp structures
aiMatrix4x4 m;
NodeWalk(m3d, mScene->mRootNode, m);
// Create a model from assimp structures
aiMatrix4x4 m;
NodeWalk(m3d, mScene->mRootNode, m);
// serialize the structures
unsigned int size;
unsigned char *output = m3d.Save(M3D_EXP_FLOAT, M3D_EXP_EXTRA | (toAscii ? M3D_EXP_ASCII : 0), size);
// serialize the structures
unsigned int size;
unsigned char *output = m3d.Save(M3D_EXP_FLOAT, M3D_EXP_EXTRA | (toAscii ? M3D_EXP_ASCII : 0), size);
if (!output || size < 8) {
throw DeadlyExportError("unable to serialize into Model 3D");
}
if (!output || size < 8) {
throw DeadlyExportError("unable to serialize into Model 3D");
}
// Write out serialized model
outfile->Write(output, size, 1);
// Write out serialized model
outfile->Write(output, size, 1);
// explicitly release file pointer,
// so we don't have to rely on class destruction.
outfile.reset();
// explicitly release file pointer,
// so we don't have to rely on class destruction.
outfile.reset();
}
// ------------------------------------------------------------------------------------------------
// recursive node walker
void M3DExporter::NodeWalk(const M3DWrapper &m3d, const aiNode *pNode, aiMatrix4x4 m) {
aiMatrix4x4 nm = m * pNode->mTransformation;
aiMatrix4x4 nm = m * pNode->mTransformation;
for (unsigned int i = 0; i < pNode->mNumMeshes; i++) {
const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]];
unsigned int mi = M3D_NOTDEFINED;
if (mScene->mMaterials) {
// get the material for this mesh
mi = addMaterial(m3d, mScene->mMaterials[mesh->mMaterialIndex]);
}
// iterate through the mesh faces
for (unsigned int j = 0; j < mesh->mNumFaces; j++) {
unsigned int n;
const aiFace *face = &(mesh->mFaces[j]);
// only triangle meshes supported for now
if (face->mNumIndices != 3) {
throw DeadlyExportError("use aiProcess_Triangulate before export");
}
// add triangle to the output
n = m3d->numface++;
m3d->face = (m3df_t *)M3D_REALLOC(m3d->face,
m3d->numface * sizeof(m3df_t));
if (!m3d->face) {
throw DeadlyExportError("memory allocation error");
}
/* set all index to -1 by default */
m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] =
m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] =
m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = M3D_UNDEF;
m3d->face[n].materialid = mi;
for (unsigned int k = 0; k < face->mNumIndices; k++) {
// get the vertex's index
unsigned int l = face->mIndices[k];
unsigned int idx;
m3dv_t vertex;
m3dti_t ti;
// multiply the position vector by the transformation matrix
aiVector3D v = mesh->mVertices[l];
v *= nm;
vertex.x = v.x;
vertex.y = v.y;
vertex.z = v.z;
vertex.w = 1.0;
vertex.color = 0;
vertex.skinid = M3D_UNDEF;
// add color if defined
if (mesh->HasVertexColors(0))
vertex.color = mkColor(&mesh->mColors[0][l]);
// save the vertex to the output
m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex,
&vertex, &idx);
m3d->face[n].vertex[k] = (M3D_INDEX)idx;
// do we have texture coordinates?
if (mesh->HasTextureCoords(0)) {
ti.u = mesh->mTextureCoords[0][l].x;
ti.v = mesh->mTextureCoords[0][l].y;
m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx);
m3d->face[n].texcoord[k] = (M3D_INDEX)idx;
}
// do we have normal vectors?
if (mesh->HasNormals()) {
vertex.x = mesh->mNormals[l].x;
vertex.y = mesh->mNormals[l].y;
vertex.z = mesh->mNormals[l].z;
vertex.color = 0;
m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx);
m3d->face[n].normal[k] = (M3D_INDEX)idx;
}
}
}
}
// repeat for the children nodes
for (unsigned int i = 0; i < pNode->mNumChildren; i++) {
NodeWalk(m3d, pNode->mChildren[i], nm);
}
for (unsigned int i = 0; i < pNode->mNumMeshes; i++) {
const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]];
unsigned int mi = M3D_NOTDEFINED;
if (mScene->mMaterials) {
// get the material for this mesh
mi = addMaterial(m3d, mScene->mMaterials[mesh->mMaterialIndex]);
}
// iterate through the mesh faces
for (unsigned int j = 0; j < mesh->mNumFaces; j++) {
unsigned int n;
const aiFace *face = &(mesh->mFaces[j]);
// only triangle meshes supported for now
if (face->mNumIndices != 3) {
throw DeadlyExportError("use aiProcess_Triangulate before export");
}
// add triangle to the output
n = m3d->numface++;
m3d->face = (m3df_t *)M3D_REALLOC(m3d->face,
m3d->numface * sizeof(m3df_t));
if (!m3d->face) {
throw DeadlyExportError("memory allocation error");
}
/* set all index to -1 by default */
m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] =
m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] =
m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = M3D_UNDEF;
m3d->face[n].materialid = mi;
for (unsigned int k = 0; k < face->mNumIndices; k++) {
// get the vertex's index
unsigned int l = face->mIndices[k];
unsigned int idx;
m3dv_t vertex;
m3dti_t ti;
// multiply the position vector by the transformation matrix
aiVector3D v = mesh->mVertices[l];
v *= nm;
vertex.x = v.x;
vertex.y = v.y;
vertex.z = v.z;
vertex.w = 1.0;
vertex.color = 0;
vertex.skinid = M3D_UNDEF;
// add color if defined
if (mesh->HasVertexColors(0))
vertex.color = mkColor(&mesh->mColors[0][l]);
// save the vertex to the output
m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex,
&vertex, &idx);
m3d->face[n].vertex[k] = (M3D_INDEX)idx;
// do we have texture coordinates?
if (mesh->HasTextureCoords(0)) {
ti.u = mesh->mTextureCoords[0][l].x;
ti.v = mesh->mTextureCoords[0][l].y;
m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx);
m3d->face[n].texcoord[k] = (M3D_INDEX)idx;
}
// do we have normal vectors?
if (mesh->HasNormals()) {
vertex.x = mesh->mNormals[l].x;
vertex.y = mesh->mNormals[l].y;
vertex.z = mesh->mNormals[l].z;
vertex.color = 0;
m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx);
m3d->face[n].normal[k] = (M3D_INDEX)idx;
}
}
}
}
// repeat for the children nodes
for (unsigned int i = 0; i < pNode->mNumChildren; i++) {
NodeWalk(m3d, pNode->mChildren[i], nm);
}
}
} // namespace Assimp

File diff suppressed because it is too large Load Diff

View File

@ -100,6 +100,10 @@ M3DWrapper::M3DWrapper() {
}
M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
if (nullptr == pIOHandler) {
ai_assert(nullptr != pIOHandler);
}
#ifdef ASSIMP_USE_M3D_READFILECB
// pass this IOHandler to the C callback in a thread-local pointer
m3dimporter_pIOHandler = pIOHandler;

File diff suppressed because it is too large Load Diff

View File

@ -45,21 +45,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the MD5 importer class
*/
#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
// internal headers
#include <assimp/RemoveComments.h>
#include "MD5Loader.h"
#include <assimp/MathFunctions.h>
#include <assimp/RemoveComments.h>
#include <assimp/SkeletonMeshBuilder.h>
#include <assimp/StringComparison.h>
#include <assimp/fast_atof.h>
#include <assimp/MathFunctions.h>
#include <assimp/SkeletonMeshBuilder.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/Importer.hpp>
#include <memory>
using namespace Assimp;
@ -67,7 +66,6 @@ using namespace Assimp;
// Minimum weight value. Weights inside [-n ... n] are ignored
#define AI_MD5_WEIGHT_EPSILON Math::getEpsilon<float>()
static const aiImporterDesc desc = {
"Doom 3 / MD5 Mesh Importer",
"",
@ -83,93 +81,78 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MD5Importer::MD5Importer()
: mIOHandler()
, mBuffer()
, fileSize()
, iLineNumber()
, pScene()
, pIOHandler()
, bHadMD5Mesh()
, bHadMD5Anim()
, bHadMD5Camera()
, configNoAutoLoad (false)
{}
MD5Importer::MD5Importer() :
mIOHandler(nullptr), mBuffer(), fileSize(), iLineNumber(), pScene(), bHadMD5Mesh(), bHadMD5Anim(), bHadMD5Camera(), configNoAutoLoad(false) {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MD5Importer::~MD5Importer()
{}
MD5Importer::~MD5Importer() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MD5Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera")
return true;
else if (!extension.length() || checkSig) {
else if (!extension.length() || checkSig) {
if (!pIOHandler) {
return true;
}
const char* tokens[] = {"MD5Version"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
const char *tokens[] = { "MD5Version" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
// Get list of all supported extensions
const aiImporterDesc* MD5Importer::GetInfo () const
{
const aiImporterDesc *MD5Importer::GetInfo() const {
return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup import properties
void MD5Importer::SetupProperties(const Importer* pImp)
{
void MD5Importer::SetupProperties(const Importer *pImp) {
// AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD
configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD,0));
configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0));
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void MD5Importer::InternReadFile( const std::string& pFile,
aiScene* _pScene, IOSystem* _pIOHandler)
{
pIOHandler = _pIOHandler;
pScene = _pScene;
void MD5Importer::InternReadFile(const std::string &pFile,
aiScene *_pScene, IOSystem *pIOHandler) {
mIOHandler = pIOHandler;
pScene = _pScene;
bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false;
// remove the file extension
const std::string::size_type pos = pFile.find_last_of('.');
mFile = (std::string::npos == pos ? pFile : pFile.substr(0,pos+1));
mFile = (std::string::npos == pos ? pFile : pFile.substr(0, pos + 1));
const std::string extension = GetExtension(pFile);
try {
if (extension == "md5camera") {
LoadMD5CameraFile();
}
else if (configNoAutoLoad || extension == "md5anim") {
} else if (configNoAutoLoad || extension == "md5anim") {
// determine file extension and process just *one* file
if (extension.length() == 0) {
throw DeadlyImportError("Failure, need file extension to determine MD5 part type");
}
if (extension == "md5anim") {
LoadMD5AnimFile();
}
else if (extension == "md5mesh") {
} else if (extension == "md5mesh") {
LoadMD5MeshFile();
}
}
else {
} else {
LoadMD5MeshFile();
LoadMD5AnimFile();
}
}
catch ( ... ) { // std::exception, Assimp::DeadlyImportError
} catch (...) { // std::exception, Assimp::DeadlyImportError
UnloadFileFromMemory();
throw;
}
@ -180,8 +163,8 @@ void MD5Importer::InternReadFile( const std::string& pFile,
}
// Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
// the output scene wouldn't pass the validation without this flag
if (!bHadMD5Mesh) {
@ -194,8 +177,7 @@ void MD5Importer::InternReadFile( const std::string& pFile,
// ------------------------------------------------------------------------------------------------
// Load a file into a memory buffer
void MD5Importer::LoadFileIntoMemory (IOStream* file)
{
void MD5Importer::LoadFileIntoMemory(IOStream *file) {
// unload the previous buffer, if any
UnloadFileFromMemory();
@ -204,21 +186,20 @@ void MD5Importer::LoadFileIntoMemory (IOStream* file)
ai_assert(fileSize);
// allocate storage and copy the contents of the file to a memory buffer
mBuffer = new char[fileSize+1];
file->Read( (void*)mBuffer, 1, fileSize);
mBuffer = new char[fileSize + 1];
file->Read((void *)mBuffer, 1, fileSize);
iLineNumber = 1;
// append a terminal 0
mBuffer[fileSize] = '\0';
// now remove all line comments from the file
CommentRemover::RemoveLineComments("//",mBuffer,' ');
CommentRemover::RemoveLineComments("//", mBuffer, ' ');
}
// ------------------------------------------------------------------------------------------------
// Unload the current memory buffer
void MD5Importer::UnloadFileFromMemory ()
{
void MD5Importer::UnloadFileFromMemory() {
// delete the file buffer
delete[] mBuffer;
mBuffer = NULL;
@ -227,57 +208,55 @@ void MD5Importer::UnloadFileFromMemory ()
// ------------------------------------------------------------------------------------------------
// Build unique vertices
void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc)
{
std::vector<bool> abHad(meshSrc.mVertices.size(),false);
void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) {
std::vector<bool> abHad(meshSrc.mVertices.size(), false);
// allocate enough storage to keep the output structures
const unsigned int iNewNum = static_cast<unsigned int>(meshSrc.mFaces.size()*3);
const unsigned int iNewNum = static_cast<unsigned int>(meshSrc.mFaces.size() * 3);
unsigned int iNewIndex = static_cast<unsigned int>(meshSrc.mVertices.size());
meshSrc.mVertices.resize(iNewNum);
// try to guess how much storage we'll need for new weights
const float fWeightsPerVert = meshSrc.mWeights.size() / (float)iNewIndex;
const unsigned int guess = (unsigned int)(fWeightsPerVert*iNewNum);
const unsigned int guess = (unsigned int)(fWeightsPerVert * iNewNum);
meshSrc.mWeights.reserve(guess + (guess >> 3)); // + 12.5% as buffer
for (FaceList::const_iterator iter = meshSrc.mFaces.begin(),iterEnd = meshSrc.mFaces.end();iter != iterEnd;++iter){
const aiFace& face = *iter;
for (unsigned int i = 0; i < 3;++i) {
for (FaceList::const_iterator iter = meshSrc.mFaces.begin(), iterEnd = meshSrc.mFaces.end(); iter != iterEnd; ++iter) {
const aiFace &face = *iter;
for (unsigned int i = 0; i < 3; ++i) {
if (face.mIndices[0] >= meshSrc.mVertices.size()) {
throw DeadlyImportError("MD5MESH: Invalid vertex index");
}
if (abHad[face.mIndices[i]]) {
if (abHad[face.mIndices[i]]) {
// generate a new vertex
meshSrc.mVertices[iNewIndex] = meshSrc.mVertices[face.mIndices[i]];
face.mIndices[i] = iNewIndex++;
}
else abHad[face.mIndices[i]] = true;
} else
abHad[face.mIndices[i]] = true;
}
// swap face order
std::swap(face.mIndices[0],face.mIndices[2]);
std::swap(face.mIndices[0], face.mIndices[2]);
}
}
// ------------------------------------------------------------------------------------------------
// Recursive node graph construction from a MD5MESH
void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bones)
{
void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) {
ai_assert(NULL != piParent && !piParent->mNumChildren);
// First find out how many children we'll have
for (int i = 0; i < (int)bones.size();++i) {
if (iParentID != i && bones[i].mParentIndex == iParentID) {
for (int i = 0; i < (int)bones.size(); ++i) {
if (iParentID != i && bones[i].mParentIndex == iParentID) {
++piParent->mNumChildren;
}
}
if (piParent->mNumChildren) {
piParent->mChildren = new aiNode*[piParent->mNumChildren];
for (int i = 0; i < (int)bones.size();++i) {
piParent->mChildren = new aiNode *[piParent->mNumChildren];
for (int i = 0; i < (int)bones.size(); ++i) {
// (avoid infinite recursion)
if (iParentID != i && bones[i].mParentIndex == iParentID) {
aiNode* pc;
if (iParentID != i && bones[i].mParentIndex == iParentID) {
aiNode *pc;
// setup a new node
*piParent->mChildren++ = pc = new aiNode();
pc->mName = aiString(bones[i].mName);
@ -285,9 +264,9 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo
// get the transformation matrix from rotation and translational components
aiQuaternion quat;
MD5::ConvertQuaternion ( bones[i].mRotationQuat, quat );
MD5::ConvertQuaternion(bones[i].mRotationQuat, quat);
bones[i].mTransform = aiMatrix4x4 ( quat.GetMatrix());
bones[i].mTransform = aiMatrix4x4(quat.GetMatrix());
bones[i].mTransform.a4 = bones[i].mPositionXYZ.x;
bones[i].mTransform.b4 = bones[i].mPositionXYZ.y;
bones[i].mTransform.c4 = bones[i].mPositionXYZ.z;
@ -298,12 +277,12 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo
// the transformations for each bone are absolute, so we need to multiply them
// with the inverse of the absolute matrix of the parent joint
if (-1 != iParentID) {
if (-1 != iParentID) {
pc->mTransformation = bones[iParentID].mInvTransform * pc->mTransformation;
}
// add children to this node, too
AttachChilds_Mesh( i, pc, bones);
AttachChilds_Mesh(i, pc, bones);
}
}
// undo offset computations
@ -313,37 +292,36 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo
// ------------------------------------------------------------------------------------------------
// Recursive node graph construction from a MD5ANIM
void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList& bones,const aiNodeAnim** node_anims)
{
void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) {
ai_assert(NULL != piParent && !piParent->mNumChildren);
// First find out how many children we'll have
for (int i = 0; i < (int)bones.size();++i) {
if (iParentID != i && bones[i].mParentIndex == iParentID) {
for (int i = 0; i < (int)bones.size(); ++i) {
if (iParentID != i && bones[i].mParentIndex == iParentID) {
++piParent->mNumChildren;
}
}
if (piParent->mNumChildren) {
piParent->mChildren = new aiNode*[piParent->mNumChildren];
for (int i = 0; i < (int)bones.size();++i) {
piParent->mChildren = new aiNode *[piParent->mNumChildren];
for (int i = 0; i < (int)bones.size(); ++i) {
// (avoid infinite recursion)
if (iParentID != i && bones[i].mParentIndex == iParentID)
{
aiNode* pc;
if (iParentID != i && bones[i].mParentIndex == iParentID) {
aiNode *pc;
// setup a new node
*piParent->mChildren++ = pc = new aiNode();
pc->mName = aiString(bones[i].mName);
pc->mParent = piParent;
// get the corresponding animation channel and its first frame
const aiNodeAnim** cur = node_anims;
while ((**cur).mNodeName != pc->mName)++cur;
const aiNodeAnim **cur = node_anims;
while ((**cur).mNodeName != pc->mName)
++cur;
aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue,pc->mTransformation);
pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix()) ;
aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue, pc->mTransformation);
pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix());
// add children to this node, too
AttachChilds_Anim( i, pc, bones,node_anims);
AttachChilds_Anim(i, pc, bones, node_anims);
}
}
// undo offset computations
@ -353,13 +331,12 @@ void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList
// ------------------------------------------------------------------------------------------------
// Load a MD5MESH file
void MD5Importer::LoadMD5MeshFile ()
{
void MD5Importer::LoadMD5MeshFile() {
std::string pFile = mFile + "md5mesh";
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if( file.get() == NULL || !file->FileSize()) {
if (file.get() == nullptr || !file->FileSize()) {
ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile);
return;
}
@ -367,7 +344,7 @@ void MD5Importer::LoadMD5MeshFile ()
LoadFileIntoMemory(file.get());
// now construct a parser and parse the file
MD5::MD5Parser parser(mBuffer,fileSize);
MD5::MD5Parser parser(mBuffer, fileSize);
// load the mesh information from it
MD5::MD5MeshParser meshParser(parser.mSections);
@ -375,13 +352,13 @@ void MD5Importer::LoadMD5MeshFile ()
// create the bone hierarchy - first the root node and dummy nodes for all meshes
pScene->mRootNode = new aiNode("<MD5_Root>");
pScene->mRootNode->mNumChildren = 2;
pScene->mRootNode->mChildren = new aiNode*[2];
pScene->mRootNode->mChildren = new aiNode *[2];
// build the hierarchy from the MD5MESH file
aiNode* pcNode = pScene->mRootNode->mChildren[1] = new aiNode();
aiNode *pcNode = pScene->mRootNode->mChildren[1] = new aiNode();
pcNode->mName.Set("<MD5_Hierarchy>");
pcNode->mParent = pScene->mRootNode;
AttachChilds_Mesh(-1,pcNode,meshParser.mJoints);
AttachChilds_Mesh(-1, pcNode, meshParser.mJoints);
pcNode = pScene->mRootNode->mChildren[0] = new aiNode();
pcNode->mName.Set("<MD5_Mesh>");
@ -393,96 +370,94 @@ void MD5Importer::LoadMD5MeshFile ()
#else
// FIX: MD5 files exported from Blender can have empty meshes
for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) {
for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
if (!(*it).mFaces.empty() && !(*it).mVertices.empty())
++pScene->mNumMaterials;
}
// generate all meshes
pScene->mNumMeshes = pScene->mNumMaterials;
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
pScene->mMaterials = new aiMaterial *[pScene->mNumMeshes];
// storage for node mesh indices
pcNode->mNumMeshes = pScene->mNumMeshes;
pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
for (unsigned int m = 0; m < pcNode->mNumMeshes;++m)
for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m)
pcNode->mMeshes[m] = m;
unsigned int n = 0;
for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) {
MD5::MeshDesc& meshSrc = *it;
for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
MD5::MeshDesc &meshSrc = *it;
if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty())
continue;
aiMesh* mesh = pScene->mMeshes[n] = new aiMesh();
aiMesh *mesh = pScene->mMeshes[n] = new aiMesh();
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
// generate unique vertices in our internal verbose format
MakeDataUnique(meshSrc);
std::string name( meshSrc.mShader.C_Str() );
std::string name(meshSrc.mShader.C_Str());
name += ".msh";
mesh->mName = name;
mesh->mNumVertices = (unsigned int) meshSrc.mVertices.size();
mesh->mNumVertices = (unsigned int)meshSrc.mVertices.size();
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
mesh->mNumUVComponents[0] = 2;
// copy texture coordinates
aiVector3D* pv = mesh->mTextureCoords[0];
for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
aiVector3D *pv = mesh->mTextureCoords[0];
for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) {
pv->x = (*iter).mUV.x;
pv->y = 1.0f-(*iter).mUV.y; // D3D to OpenGL
pv->y = 1.0f - (*iter).mUV.y; // D3D to OpenGL
pv->z = 0.0f;
}
// sort all bone weights - per bone
unsigned int* piCount = new unsigned int[meshParser.mJoints.size()];
::memset(piCount,0,sizeof(unsigned int)*meshParser.mJoints.size());
unsigned int *piCount = new unsigned int[meshParser.mJoints.size()];
::memset(piCount, 0, sizeof(unsigned int) * meshParser.mJoints.size());
for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
{
MD5::WeightDesc& weightDesc = meshSrc.mWeights[w];
for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) {
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
/* FIX for some invalid exporters */
if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON ))
if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON))
++piCount[weightDesc.mBone];
}
}
// check how many we will need
for (unsigned int p = 0; p < meshParser.mJoints.size();++p)
if (piCount[p])mesh->mNumBones++;
for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p)
if (piCount[p]) mesh->mNumBones++;
if (mesh->mNumBones) // just for safety
{
mesh->mBones = new aiBone*[mesh->mNumBones];
for (unsigned int q = 0,h = 0; q < meshParser.mJoints.size();++q)
{
if (!piCount[q])continue;
aiBone* p = mesh->mBones[h] = new aiBone();
mesh->mBones = new aiBone *[mesh->mNumBones];
for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) {
if (!piCount[q]) continue;
aiBone *p = mesh->mBones[h] = new aiBone();
p->mNumWeights = piCount[q];
p->mWeights = new aiVertexWeight[p->mNumWeights];
p->mName = aiString(meshParser.mJoints[q].mName);
p->mOffsetMatrix = meshParser.mJoints[q].mInvTransform;
// store the index for later use
MD5::BoneDesc& boneSrc = meshParser.mJoints[q];
MD5::BoneDesc &boneSrc = meshParser.mJoints[q];
boneSrc.mMap = h++;
// compute w-component of quaternion
MD5::ConvertQuaternion( boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted );
MD5::ConvertQuaternion(boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted);
}
pv = mesh->mVertices;
for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) {
// compute the final vertex position from all single weights
*pv = aiVector3D();
// there are models which have weights which don't sum to 1 ...
ai_real fSum = 0.0;
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w)
fSum += meshSrc.mWeights[w].mWeight;
if (!fSum) {
ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0");
@ -490,32 +465,32 @@ void MD5Importer::LoadMD5MeshFile ()
}
// process bone weights
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) {
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
if (w >= meshSrc.mWeights.size())
throw DeadlyImportError("MD5MESH: Invalid weight index");
MD5::WeightDesc& weightDesc = meshSrc.mWeights[w];
if ( weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
continue;
}
const ai_real fNewWeight = weightDesc.mWeight / fSum;
// transform the local position into worldspace
MD5::BoneDesc& boneSrc = meshParser.mJoints[weightDesc.mBone];
const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (weightDesc.vOffsetPosition);
MD5::BoneDesc &boneSrc = meshParser.mJoints[weightDesc.mBone];
const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate(weightDesc.vOffsetPosition);
// use the original weight to compute the vertex position
// (some MD5s seem to depend on the invalid weight values ...)
*pv += ((boneSrc.mPositionXYZ+v)* (ai_real)weightDesc.mWeight);
*pv += ((boneSrc.mPositionXYZ + v) * (ai_real)weightDesc.mWeight);
aiBone* bone = mesh->mBones[boneSrc.mMap];
*bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight);
aiBone *bone = mesh->mBones[boneSrc.mMap];
*bone->mWeights++ = aiVertexWeight((unsigned int)(pv - mesh->mVertices), fNewWeight);
}
}
// undo our nice offset tricks ...
for (unsigned int p = 0; p < mesh->mNumBones;++p) {
for (unsigned int p = 0; p < mesh->mNumBones; ++p) {
mesh->mBones[p]->mWeights -= mesh->mBones[p]->mNumWeights;
}
}
@ -526,14 +501,14 @@ void MD5Importer::LoadMD5MeshFile ()
// (however, take care that the aiFace destructor doesn't delete the mIndices array)
mesh->mNumFaces = (unsigned int)meshSrc.mFaces.size();
mesh->mFaces = new aiFace[mesh->mNumFaces];
for (unsigned int c = 0; c < mesh->mNumFaces;++c) {
for (unsigned int c = 0; c < mesh->mNumFaces; ++c) {
mesh->mFaces[c].mNumIndices = 3;
mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices;
meshSrc.mFaces[c].mIndices = NULL;
}
// generate a material for the mesh
aiMaterial* mat = new aiMaterial();
aiMaterial *mat = new aiMaterial();
pScene->mMaterials[n] = mat;
// insert the typical doom3 textures:
@ -541,28 +516,27 @@ void MD5Importer::LoadMD5MeshFile ()
// nnn_h.tga - height map
// nnn_s.tga - specular map
// nnn_d.tga - diffuse map
if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data,'.')) {
if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data, '.')) {
aiString temp(meshSrc.mShader);
temp.Append("_local.tga");
mat->AddProperty(&temp,AI_MATKEY_TEXTURE_NORMALS(0));
mat->AddProperty(&temp, AI_MATKEY_TEXTURE_NORMALS(0));
temp = aiString(meshSrc.mShader);
temp = aiString(meshSrc.mShader);
temp.Append("_s.tga");
mat->AddProperty(&temp,AI_MATKEY_TEXTURE_SPECULAR(0));
mat->AddProperty(&temp, AI_MATKEY_TEXTURE_SPECULAR(0));
temp = aiString(meshSrc.mShader);
temp = aiString(meshSrc.mShader);
temp.Append("_d.tga");
mat->AddProperty(&temp,AI_MATKEY_TEXTURE_DIFFUSE(0));
mat->AddProperty(&temp, AI_MATKEY_TEXTURE_DIFFUSE(0));
temp = aiString(meshSrc.mShader);
temp = aiString(meshSrc.mShader);
temp.Append("_h.tga");
mat->AddProperty(&temp,AI_MATKEY_TEXTURE_HEIGHT(0));
mat->AddProperty(&temp, AI_MATKEY_TEXTURE_HEIGHT(0));
// set this also as material name
mat->AddProperty(&meshSrc.mShader,AI_MATKEY_NAME);
}
else {
mat->AddProperty(&meshSrc.mShader, AI_MATKEY_NAME);
} else {
mat->AddProperty(&meshSrc.mShader, AI_MATKEY_TEXTURE_DIFFUSE(0));
}
mesh->mMaterialIndex = n++;
@ -572,39 +546,37 @@ void MD5Importer::LoadMD5MeshFile ()
// ------------------------------------------------------------------------------------------------
// Load an MD5ANIM file
void MD5Importer::LoadMD5AnimFile ()
{
void MD5Importer::LoadMD5AnimFile() {
std::string pFile = mFile + "md5anim";
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if( !file.get() || !file->FileSize()) {
if (!file.get() || !file->FileSize()) {
ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile);
return;
}
LoadFileIntoMemory(file.get());
// parse the basic file structure
MD5::MD5Parser parser(mBuffer,fileSize);
MD5::MD5Parser parser(mBuffer, fileSize);
// load the animation information from the parse tree
MD5::MD5AnimParser animParser(parser.mSections);
// generate and fill the output animation
if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() ||
animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded");
}
else {
} else {
bHadMD5Anim = true;
pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations = 1];
aiAnimation* anim = pScene->mAnimations[0] = new aiAnimation();
pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations = 1];
aiAnimation *anim = pScene->mAnimations[0] = new aiAnimation();
anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size();
anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
for (unsigned int i = 0; i < anim->mNumChannels;++i) {
aiNodeAnim* node = anim->mChannels[i] = new aiNodeAnim();
node->mNodeName = aiString( animParser.mAnimatedBones[i].mName );
anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
aiNodeAnim *node = anim->mChannels[i] = new aiNodeAnim();
node->mNodeName = aiString(animParser.mAnimatedBones[i].mName);
// allocate storage for the keyframes
node->mPositionKeys = new aiVectorKey[animParser.mFrames.size()];
@ -614,46 +586,44 @@ void MD5Importer::LoadMD5AnimFile ()
// 1 tick == 1 frame
anim->mTicksPerSecond = animParser.fFrameRate;
for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end();iter != iterEnd;++iter){
for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end(); iter != iterEnd; ++iter) {
double dTime = (double)(*iter).iIndex;
aiNodeAnim** pcAnimNode = anim->mChannels;
aiNodeAnim **pcAnimNode = anim->mChannels;
if (!(*iter).mValues.empty() || iter == animParser.mFrames.begin()) /* be sure we have at least one frame */
{
// now process all values in there ... read all joints
MD5::BaseFrameDesc* pcBaseFrame = &animParser.mBaseFrames[0];
for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end();++iter2,
++pcAnimNode,++pcBaseFrame)
{
if((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) {
MD5::BaseFrameDesc *pcBaseFrame = &animParser.mBaseFrames[0];
for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end(); ++iter2,
++pcAnimNode, ++pcBaseFrame) {
if ((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) {
// Allow for empty frames
if ((*iter2).iFlags != 0) {
throw DeadlyImportError("MD5: Keyframe index is out of range");
}
continue;
}
const float* fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex];
aiNodeAnim* pcCurAnimBone = *pcAnimNode;
const float *fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex];
aiNodeAnim *pcCurAnimBone = *pcAnimNode;
aiVectorKey* vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++];
aiQuatKey* qKey = &pcCurAnimBone->mRotationKeys [pcCurAnimBone->mNumRotationKeys++];
aiVectorKey *vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++];
aiQuatKey *qKey = &pcCurAnimBone->mRotationKeys[pcCurAnimBone->mNumRotationKeys++];
aiVector3D vTemp;
// translational component
for (unsigned int i = 0; i < 3; ++i) {
if ((*iter2).iFlags & (1u << i)) {
vKey->mValue[i] = *fpCur++;
}
else vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i];
vKey->mValue[i] = *fpCur++;
} else
vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i];
}
// orientation component
for (unsigned int i = 0; i < 3; ++i) {
if ((*iter2).iFlags & (8u << i)) {
vTemp[i] = *fpCur++;
}
else vTemp[i] = pcBaseFrame->vRotationQuat[i];
vTemp[i] = *fpCur++;
} else
vTemp[i] = pcBaseFrame->vRotationQuat[i];
}
MD5::ConvertQuaternion(vTemp, qKey->mValue);
@ -662,7 +632,7 @@ void MD5Importer::LoadMD5AnimFile ()
}
// compute the duration of the animation
anim->mDuration = std::max(dTime,anim->mDuration);
anim->mDuration = std::max(dTime, anim->mDuration);
}
// If we didn't build the hierarchy yet (== we didn't load a MD5MESH),
@ -671,11 +641,11 @@ void MD5Importer::LoadMD5AnimFile ()
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<MD5_Hierarchy>");
AttachChilds_Anim(-1,pScene->mRootNode,animParser.mAnimatedBones,(const aiNodeAnim**)anim->mChannels);
AttachChilds_Anim(-1, pScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels);
// Call SkeletonMeshBuilder to construct a mesh to represent the shape
if (pScene->mRootNode->mNumChildren) {
SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[0]);
SkeletonMeshBuilder skeleton_maker(pScene, pScene->mRootNode->mChildren[0]);
}
}
}
@ -683,20 +653,19 @@ void MD5Importer::LoadMD5AnimFile ()
// ------------------------------------------------------------------------------------------------
// Load an MD5CAMERA file
void MD5Importer::LoadMD5CameraFile ()
{
void MD5Importer::LoadMD5CameraFile() {
std::string pFile = mFile + "md5camera";
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if( !file.get() || !file->FileSize()) {
if (!file.get() || !file->FileSize()) {
throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile);
}
bHadMD5Camera = true;
LoadFileIntoMemory(file.get());
// parse the basic file structure
MD5::MD5Parser parser(mBuffer,fileSize);
MD5::MD5Parser parser(mBuffer, fileSize);
// load the camera animation data from the parse tree
MD5::MD5CameraParser cameraParser(parser.mSections);
@ -705,56 +674,55 @@ void MD5Importer::LoadMD5CameraFile ()
throw DeadlyImportError("MD5CAMERA: No frames parsed");
}
std::vector<unsigned int>& cuts = cameraParser.cuts;
std::vector<MD5::CameraAnimFrameDesc>& frames = cameraParser.frames;
std::vector<unsigned int> &cuts = cameraParser.cuts;
std::vector<MD5::CameraAnimFrameDesc> &frames = cameraParser.frames;
// Construct output graph - a simple root with a dummy child.
// The root node performs the coordinate system conversion
aiNode* root = pScene->mRootNode = new aiNode("<MD5CameraRoot>");
root->mChildren = new aiNode*[root->mNumChildren = 1];
aiNode *root = pScene->mRootNode = new aiNode("<MD5CameraRoot>");
root->mChildren = new aiNode *[root->mNumChildren = 1];
root->mChildren[0] = new aiNode("<MD5Camera>");
root->mChildren[0]->mParent = root;
// ... but with one camera assigned to it
pScene->mCameras = new aiCamera*[pScene->mNumCameras = 1];
aiCamera* cam = pScene->mCameras[0] = new aiCamera();
pScene->mCameras = new aiCamera *[pScene->mNumCameras = 1];
aiCamera *cam = pScene->mCameras[0] = new aiCamera();
cam->mName = "<MD5Camera>";
// FIXME: Fov is currently set to the first frame's value
cam->mHorizontalFOV = AI_DEG_TO_RAD( frames.front().fFOV );
cam->mHorizontalFOV = AI_DEG_TO_RAD(frames.front().fFOV);
// every cut is written to a separate aiAnimation
if (!cuts.size()) {
cuts.push_back(0);
cuts.push_back(static_cast<unsigned int>(frames.size()-1));
}
else {
cuts.insert(cuts.begin(),0);
cuts.push_back(static_cast<unsigned int>(frames.size() - 1));
} else {
cuts.insert(cuts.begin(), 0);
if (cuts.back() < frames.size()-1)
cuts.push_back(static_cast<unsigned int>(frames.size()-1));
if (cuts.back() < frames.size() - 1)
cuts.push_back(static_cast<unsigned int>(frames.size() - 1));
}
pScene->mNumAnimations = static_cast<unsigned int>(cuts.size()-1);
aiAnimation** tmp = pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations];
for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end()-1; ++it) {
pScene->mNumAnimations = static_cast<unsigned int>(cuts.size() - 1);
aiAnimation **tmp = pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations];
for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) {
aiAnimation* anim = *tmp++ = new aiAnimation();
anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u",(unsigned int)(it-cuts.begin()),(*it),*(it+1));
aiAnimation *anim = *tmp++ = new aiAnimation();
anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u", (unsigned int)(it - cuts.begin()), (*it), *(it + 1));
anim->mTicksPerSecond = cameraParser.fFrameRate;
anim->mChannels = new aiNodeAnim*[anim->mNumChannels = 1];
aiNodeAnim* nd = anim->mChannels[0] = new aiNodeAnim();
anim->mChannels = new aiNodeAnim *[anim->mNumChannels = 1];
aiNodeAnim *nd = anim->mChannels[0] = new aiNodeAnim();
nd->mNodeName.Set("<MD5Camera>");
nd->mNumPositionKeys = nd->mNumRotationKeys = *(it+1) - (*it);
nd->mNumPositionKeys = nd->mNumRotationKeys = *(it + 1) - (*it);
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
nd->mRotationKeys = new aiQuatKey [nd->mNumRotationKeys];
nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
for (unsigned int i = 0; i < nd->mNumPositionKeys; ++i) {
nd->mPositionKeys[i].mValue = frames[*it+i].vPositionXYZ;
MD5::ConvertQuaternion(frames[*it+i].vRotationQuat,nd->mRotationKeys[i].mValue);
nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it+i;
nd->mPositionKeys[i].mValue = frames[*it + i].vPositionXYZ;
MD5::ConvertQuaternion(frames[*it + i].vRotationQuat, nd->mRotationKeys[i].mValue);
nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it + i;
}
}
}

View File

@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file MD5Loader.h
* @brief Definition of the .MD5 importer class.
* http://www.modwiki.net/wiki/MD5_(file_format)
@ -48,15 +47,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MD5LOADER_H_INCLUDED
#define AI_MD5LOADER_H_INCLUDED
#include <assimp/BaseImporter.h>
#include "MD5Parser.h"
#include <assimp/BaseImporter.h>
#include <assimp/types.h>
struct aiNode;
struct aiNodeAnim;
namespace Assimp {
namespace Assimp {
class IOStream;
using namespace Assimp::MD5;
@ -64,61 +63,53 @@ using namespace Assimp::MD5;
// ---------------------------------------------------------------------------
/** Importer class for the MD5 file format
*/
class MD5Importer : public BaseImporter
{
class MD5Importer : public BaseImporter {
public:
MD5Importer();
~MD5Importer();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* 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;
protected:
// -------------------------------------------------------------------
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details
*/
const aiImporterDesc* GetInfo () const;
const aiImporterDesc *GetInfo() const;
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.
*/
void SetupProperties(const Importer* pImp);
void SetupProperties(const Importer *pImp);
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
protected:
void InternReadFile(const std::string &pFile, aiScene *pScene,
IOSystem *pIOHandler);
// -------------------------------------------------------------------
/** Load a *.MD5MESH file.
*/
void LoadMD5MeshFile ();
void LoadMD5MeshFile();
// -------------------------------------------------------------------
/** Load a *.MD5ANIM file.
*/
void LoadMD5AnimFile ();
void LoadMD5AnimFile();
// -------------------------------------------------------------------
/** Load a *.MD5CAMERA file.
*/
void LoadMD5CameraFile ();
void LoadMD5CameraFile();
// -------------------------------------------------------------------
/** Construct node hierarchy from a given MD5ANIM
@ -127,8 +118,8 @@ protected:
* @param bones Input bones
* @param node_anims Generated node animations
*/
void AttachChilds_Anim(int iParentID,aiNode* piParent,
AnimBoneList& bones,const aiNodeAnim** node_anims);
void AttachChilds_Anim(int iParentID, aiNode *piParent,
AnimBoneList &bones, const aiNodeAnim **node_anims);
// -------------------------------------------------------------------
/** Construct node hierarchy from a given MD5MESH
@ -136,13 +127,13 @@ protected:
* @param piParent Parent node to attach to
* @param bones Input bones
*/
void AttachChilds_Mesh(int iParentID,aiNode* piParent,BoneList& bones);
void AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones);
// -------------------------------------------------------------------
/** Build unique vertex buffers from a given MD5ANIM
* @param meshSrc Input data
*/
void MakeDataUnique (MD5::MeshDesc& meshSrc);
void MakeDataUnique(MD5::MeshDesc &meshSrc);
// -------------------------------------------------------------------
/** Load the contents of a specific file into memory and
@ -151,19 +142,18 @@ protected:
* mBuffer is modified to point to this buffer.
* @param pFile File stream to be read
*/
void LoadFileIntoMemory (IOStream* pFile);
void UnloadFileFromMemory ();
void LoadFileIntoMemory(IOStream *pFile);
void UnloadFileFromMemory();
/** IOSystem to be used to access files */
IOSystem* mIOHandler;
IOSystem *mIOHandler;
/** Path to the file, excluding the file extension but
with the dot */
std::string mFile;
/** Buffer to hold the loaded file */
char* mBuffer;
char *mBuffer;
/** Size of the file */
unsigned int fileSize;
@ -172,10 +162,7 @@ protected:
unsigned int iLineNumber;
/** Scene to be filled */
aiScene* pScene;
/** (Custom) I/O handler implementation */
IOSystem* pIOHandler;
aiScene *pScene;
/** true if a MD5MESH file has already been parsed */
bool bHadMD5Mesh;

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
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 MDC importer class */
#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
// internal headers
@ -51,11 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "MD3/MD3FileData.h"
#include "MDC/MDCNormalTable.h" // shouldn't be included by other units
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/Importer.hpp>
#include <memory>
@ -76,12 +73,11 @@ static const aiImporterDesc desc = {
};
// ------------------------------------------------------------------------------------------------
void MDC::BuildVertex(const Frame& frame,
const BaseVertex& bvert,
const CompressedVertex& cvert,
aiVector3D& vXYZOut,
aiVector3D& vNorOut)
{
void MDC::BuildVertex(const Frame &frame,
const BaseVertex &bvert,
const CompressedVertex &cvert,
aiVector3D &vXYZOut,
aiVector3D &vNorOut) {
// compute the position
const float xd = (cvert.xd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
const float yd = (cvert.yd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
@ -98,66 +94,65 @@ void MDC::BuildVertex(const Frame& frame,
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MDCImporter::MDCImporter()
: configFrameID(),
pcHeader(),
mBuffer(),
fileSize()
{
MDCImporter::MDCImporter() :
configFrameID(),
pcHeader(),
mBuffer(),
fileSize() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MDCImporter::~MDCImporter()
{
MDCImporter::~MDCImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MDCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "mdc")
if (extension == "mdc") {
return true;
}
// if check for extension is not enough, check for the magic tokens
if (!extension.length() || checkSig) {
uint32_t tokens[1];
tokens[0] = AI_MDC_MAGIC_NUMBER_LE;
return CheckMagicToken(pIOHandler,pFile,tokens,1);
return CheckMagicToken(pIOHandler, pFile, tokens, 1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* MDCImporter::GetInfo () const
{
const aiImporterDesc *MDCImporter::GetInfo() const {
return &desc;
}
// ------------------------------------------------------------------------------------------------
// Validate the header of the given MDC file
void MDCImporter::ValidateHeader()
{
AI_SWAP4( this->pcHeader->ulVersion );
AI_SWAP4( this->pcHeader->ulFlags );
AI_SWAP4( this->pcHeader->ulNumFrames );
AI_SWAP4( this->pcHeader->ulNumTags );
AI_SWAP4( this->pcHeader->ulNumSurfaces );
AI_SWAP4( this->pcHeader->ulNumSkins );
AI_SWAP4( this->pcHeader->ulOffsetBorderFrames );
void MDCImporter::ValidateHeader() {
AI_SWAP4(this->pcHeader->ulVersion);
AI_SWAP4(this->pcHeader->ulFlags);
AI_SWAP4(this->pcHeader->ulNumFrames);
AI_SWAP4(this->pcHeader->ulNumTags);
AI_SWAP4(this->pcHeader->ulNumSurfaces);
AI_SWAP4(this->pcHeader->ulNumSkins);
AI_SWAP4(this->pcHeader->ulOffsetBorderFrames);
if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE)
{
pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) {
char szBuffer[5];
szBuffer[0] = ((char*)&pcHeader->ulIdent)[0];
szBuffer[1] = ((char*)&pcHeader->ulIdent)[1];
szBuffer[2] = ((char*)&pcHeader->ulIdent)[2];
szBuffer[3] = ((char*)&pcHeader->ulIdent)[3];
szBuffer[0] = ((char *)&pcHeader->ulIdent)[0];
szBuffer[1] = ((char *)&pcHeader->ulIdent)[1];
szBuffer[2] = ((char *)&pcHeader->ulIdent)[2];
szBuffer[3] = ((char *)&pcHeader->ulIdent)[3];
szBuffer[4] = '\0';
throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the "
"magic word found is " + std::string( szBuffer ));
"magic word found is " +
std::string(szBuffer));
}
if (pcHeader->ulVersion != AI_MDC_VERSION) {
@ -165,10 +160,9 @@ void MDCImporter::ValidateHeader()
}
if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize ||
pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize)
{
pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize) {
throw DeadlyImportError("Some of the offset values in the MDC header are invalid "
"and point to something behind the file.");
"and point to something behind the file.");
}
if (this->configFrameID >= this->pcHeader->ulNumFrames) {
@ -178,8 +172,7 @@ void MDCImporter::ValidateHeader()
// ------------------------------------------------------------------------------------------------
// Validate the header of a given MDC file surface
void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
{
void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface *pcSurf) {
AI_SWAP4(pcSurf->ulFlags);
AI_SWAP4(pcSurf->ulNumCompFrames);
AI_SWAP4(pcSurf->ulNumBaseFrames);
@ -194,230 +187,216 @@ void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
AI_SWAP4(pcSurf->ulOffsetFrameCompFrames);
AI_SWAP4(pcSurf->ulOffsetEnd);
const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcSurf-(int8_t*)pcHeader);
const unsigned int iMax = this->fileSize - (unsigned int)((int8_t *)pcSurf - (int8_t *)pcHeader);
if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax ||
(pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) ||
pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax ||
pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax ||
pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax ||
pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax ||
(pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax))
{
if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax ||
(pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) ||
pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax ||
pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax ||
pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax ||
pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax ||
(pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax)) {
throw DeadlyImportError("Some of the offset values in the MDC surface header "
"are invalid and point somewhere behind the file.");
"are invalid and point somewhere behind the file.");
}
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void MDCImporter::SetupProperties(const Importer* pImp)
{
void MDCImporter::SetupProperties(const Importer *pImp) {
// The AI_CONFIG_IMPORT_MDC_KEYFRAME option overrides the
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
if(static_cast<unsigned int>(-1) == (configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDC_KEYFRAME,-1))){
configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
if (static_cast<unsigned int>(-1) == (configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDC_KEYFRAME, -1))) {
configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME, 0);
}
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void MDCImporter::InternReadFile(
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
// Check whether we can read from the file
if( file.get() == NULL)
throw DeadlyImportError( "Failed to open MDC file " + pFile + ".");
if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open MDC file " + pFile + ".");
}
// check whether the mdc file is large enough to contain the file header
fileSize = (unsigned int)file->FileSize();
if( fileSize < sizeof(MDC::Header))
throw DeadlyImportError( "MDC File is too small.");
fileSize = static_cast<unsigned int>(file->FileSize());
if (fileSize < sizeof(MDC::Header)) {
throw DeadlyImportError("MDC File is too small.");
}
std::vector<unsigned char> mBuffer2(fileSize);
file->Read( &mBuffer2[0], 1, fileSize);
file->Read(&mBuffer2[0], 1, fileSize);
mBuffer = &mBuffer2[0];
// validate the file header
this->pcHeader = (BE_NCONST MDC::Header*)this->mBuffer;
this->pcHeader = (BE_NCONST MDC::Header *)this->mBuffer;
this->ValidateHeader();
std::vector<std::string> aszShaders;
// get a pointer to the frame we want to read
BE_NCONST MDC::Frame* pcFrame = (BE_NCONST MDC::Frame*)(this->mBuffer+
this->pcHeader->ulOffsetBorderFrames);
BE_NCONST MDC::Frame *pcFrame = (BE_NCONST MDC::Frame *)(this->mBuffer +
this->pcHeader->ulOffsetBorderFrames);
// no need to swap the other members, we won't need them
pcFrame += configFrameID;
AI_SWAP4( pcFrame->localOrigin[0] );
AI_SWAP4( pcFrame->localOrigin[1] );
AI_SWAP4( pcFrame->localOrigin[2] );
AI_SWAP4(pcFrame->localOrigin[0]);
AI_SWAP4(pcFrame->localOrigin[1]);
AI_SWAP4(pcFrame->localOrigin[2]);
// get the number of valid surfaces
BE_NCONST MDC::Surface* pcSurface, *pcSurface2;
BE_NCONST MDC::Surface *pcSurface, *pcSurface2;
pcSurface = pcSurface2 = new (mBuffer + pcHeader->ulOffsetSurfaces) MDC::Surface;
unsigned int iNumShaders = 0;
for (unsigned int i = 0; i < pcHeader->ulNumSurfaces;++i)
{
for (unsigned int i = 0; i < pcHeader->ulNumSurfaces; ++i) {
// validate the surface header
this->ValidateSurfaceHeader(pcSurface2);
if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles)++pScene->mNumMeshes;
if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles) {
++pScene->mNumMeshes;
}
iNumShaders += pcSurface2->ulNumShaders;
pcSurface2 = new ((int8_t*)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface;
pcSurface2 = new ((int8_t *)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface;
}
aszShaders.reserve(iNumShaders);
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
// necessary that we don't crash if an exception occurs
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
pScene->mMeshes[i] = NULL;
}
// now read all surfaces
unsigned int iDefaultMatIndex = UINT_MAX;
for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces;++i)
{
if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles)continue;
aiMesh* pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces; ++i) {
if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles) continue;
aiMesh *pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
pcMesh->mNumFaces = pcSurface->ulNumTriangles;
pcMesh->mNumVertices = pcMesh->mNumFaces * 3;
// store the name of the surface for use as node name.
pcMesh->mName.Set(std::string(pcSurface->ucName
, strnlen(pcSurface->ucName, AI_MDC_MAXQPATH - 1)));
pcMesh->mName.Set(std::string(pcSurface->ucName, strnlen(pcSurface->ucName, AI_MDC_MAXQPATH - 1)));
// go to the first shader in the file. ignore the others.
if (pcSurface->ulNumShaders)
{
const MDC::Shader* pcShader = (const MDC::Shader*)((int8_t*)pcSurface + pcSurface->ulOffsetShaders);
if (pcSurface->ulNumShaders) {
const MDC::Shader *pcShader = (const MDC::Shader *)((int8_t *)pcSurface + pcSurface->ulOffsetShaders);
pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
// create a new shader
aszShaders.push_back(std::string( pcShader->ucName,
::strnlen(pcShader->ucName, sizeof(pcShader->ucName)) ));
aszShaders.push_back(std::string(pcShader->ucName,
::strnlen(pcShader->ucName, sizeof(pcShader->ucName))));
}
// need to create a default material
else if (UINT_MAX == iDefaultMatIndex)
{
else if (UINT_MAX == iDefaultMatIndex) {
pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
aszShaders.push_back(std::string());
}
// otherwise assign a reference to the default material
else pcMesh->mMaterialIndex = iDefaultMatIndex;
else
pcMesh->mMaterialIndex = iDefaultMatIndex;
// allocate output storage for the mesh
aiVector3D* pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
aiVector3D* pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
aiVector3D* pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
aiFace* pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
aiVector3D *pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
aiVector3D *pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
aiVector3D *pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
aiFace *pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
// create all vertices/faces
BE_NCONST MDC::Triangle* pcTriangle = (BE_NCONST MDC::Triangle*)
((int8_t*)pcSurface+pcSurface->ulOffsetTriangles);
BE_NCONST MDC::Triangle *pcTriangle = (BE_NCONST MDC::Triangle *)((int8_t *)pcSurface + pcSurface->ulOffsetTriangles);
BE_NCONST MDC::TexturCoord* const pcUVs = (BE_NCONST MDC::TexturCoord*)
((int8_t*)pcSurface+pcSurface->ulOffsetTexCoords);
BE_NCONST MDC::TexturCoord *const pcUVs = (BE_NCONST MDC::TexturCoord *)((int8_t *)pcSurface + pcSurface->ulOffsetTexCoords);
// get a pointer to the uncompressed vertices
int16_t iOfs = *((int16_t*) ((int8_t*) pcSurface +
pcSurface->ulOffsetFrameBaseFrames) + this->configFrameID);
int16_t iOfs = *((int16_t *)((int8_t *)pcSurface +
pcSurface->ulOffsetFrameBaseFrames) +
this->configFrameID);
AI_SWAP2(iOfs);
BE_NCONST MDC::BaseVertex* const pcVerts = (BE_NCONST MDC::BaseVertex*)
((int8_t*)pcSurface+pcSurface->ulOffsetBaseVerts) +
((int)iOfs * pcSurface->ulNumVertices * 4);
BE_NCONST MDC::BaseVertex *const pcVerts = (BE_NCONST MDC::BaseVertex *)((int8_t *)pcSurface + pcSurface->ulOffsetBaseVerts) +
((int)iOfs * pcSurface->ulNumVertices * 4);
// do the main swapping stuff ...
#if (defined AI_BUILD_BIG_ENDIAN)
// swap all triangles
for (unsigned int i = 0; i < pcSurface->ulNumTriangles;++i)
{
AI_SWAP4( pcTriangle[i].aiIndices[0] );
AI_SWAP4( pcTriangle[i].aiIndices[1] );
AI_SWAP4( pcTriangle[i].aiIndices[2] );
for (unsigned int i = 0; i < pcSurface->ulNumTriangles; ++i) {
AI_SWAP4(pcTriangle[i].aiIndices[0]);
AI_SWAP4(pcTriangle[i].aiIndices[1]);
AI_SWAP4(pcTriangle[i].aiIndices[2]);
}
// swap all vertices
for (unsigned int i = 0; i < pcSurface->ulNumVertices*pcSurface->ulNumBaseFrames;++i)
{
AI_SWAP2( pcVerts->normal );
AI_SWAP2( pcVerts->x );
AI_SWAP2( pcVerts->y );
AI_SWAP2( pcVerts->z );
for (unsigned int i = 0; i < pcSurface->ulNumVertices * pcSurface->ulNumBaseFrames; ++i) {
AI_SWAP2(pcVerts->normal);
AI_SWAP2(pcVerts->x);
AI_SWAP2(pcVerts->y);
AI_SWAP2(pcVerts->z);
}
// swap all texture coordinates
for (unsigned int i = 0; i < pcSurface->ulNumVertices;++i)
{
AI_SWAP4( pcUVs->u );
AI_SWAP4( pcUVs->v );
for (unsigned int i = 0; i < pcSurface->ulNumVertices; ++i) {
AI_SWAP4(pcUVs->u);
AI_SWAP4(pcUVs->v);
}
#endif
const MDC::CompressedVertex* pcCVerts = NULL;
int16_t* mdcCompVert = NULL;
const MDC::CompressedVertex *pcCVerts = NULL;
int16_t *mdcCompVert = NULL;
// access compressed frames for large frame numbers, but never for the first
if( this->configFrameID && pcSurface->ulNumCompFrames > 0 )
{
mdcCompVert = (int16_t*) ((int8_t*)pcSurface+pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
if (this->configFrameID && pcSurface->ulNumCompFrames > 0) {
mdcCompVert = (int16_t *)((int8_t *)pcSurface + pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
AI_SWAP2P(mdcCompVert);
if( *mdcCompVert >= 0 )
{
pcCVerts = (const MDC::CompressedVertex*)((int8_t*)pcSurface +
pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices;
}
else mdcCompVert = NULL;
if (*mdcCompVert >= 0) {
pcCVerts = (const MDC::CompressedVertex *)((int8_t *)pcSurface +
pcSurface->ulOffsetCompVerts) +
*mdcCompVert * pcSurface->ulNumVertices;
} else
mdcCompVert = NULL;
}
// copy all faces
for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles;++iFace,
++pcTriangle,++pcFaceCur)
{
const unsigned int iOutIndex = iFace*3;
for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles; ++iFace,
++pcTriangle, ++pcFaceCur) {
const unsigned int iOutIndex = iFace * 3;
pcFaceCur->mNumIndices = 3;
pcFaceCur->mIndices = new unsigned int[3];
for (unsigned int iIndex = 0; iIndex < 3;++iIndex,
++pcVertCur,++pcUVCur,++pcNorCur)
{
for (unsigned int iIndex = 0; iIndex < 3; ++iIndex,
++pcVertCur, ++pcUVCur, ++pcNorCur) {
uint32_t quak = pcTriangle->aiIndices[iIndex];
if (quak >= pcSurface->ulNumVertices)
{
if (quak >= pcSurface->ulNumVertices) {
ASSIMP_LOG_ERROR("MDC vertex index is out of range");
quak = pcSurface->ulNumVertices-1;
quak = pcSurface->ulNumVertices - 1;
}
// compressed vertices?
if (mdcCompVert)
{
MDC::BuildVertex(*pcFrame,pcVerts[quak],pcCVerts[quak],
*pcVertCur,*pcNorCur);
}
else
{
if (mdcCompVert) {
MDC::BuildVertex(*pcFrame, pcVerts[quak], pcCVerts[quak],
*pcVertCur, *pcNorCur);
} else {
// copy position
pcVertCur->x = pcVerts[quak].x * AI_MDC_BASE_SCALING;
pcVertCur->y = pcVerts[quak].y * AI_MDC_BASE_SCALING;
pcVertCur->z = pcVerts[quak].z * AI_MDC_BASE_SCALING;
// copy normals
MD3::LatLngNormalToVec3( pcVerts[quak].normal, &pcNorCur->x );
MD3::LatLngNormalToVec3(pcVerts[quak].normal, &pcNorCur->x);
// copy texture coordinates
pcUVCur->x = pcUVs[quak].u;
pcUVCur->y = ai_real( 1.0 )-pcUVs[quak].v; // DX to OGL
pcUVCur->y = ai_real(1.0) - pcUVs[quak].v; // DX to OGL
}
pcVertCur->x += pcFrame->localOrigin[0] ;
pcVertCur->y += pcFrame->localOrigin[1] ;
pcVertCur->z += pcFrame->localOrigin[2] ;
pcVertCur->x += pcFrame->localOrigin[0];
pcVertCur->y += pcFrame->localOrigin[1];
pcVertCur->z += pcFrame->localOrigin[2];
}
// swap the face order - DX to OGL
@ -426,31 +405,27 @@ void MDCImporter::InternReadFile(
pcFaceCur->mIndices[2] = iOutIndex + 0;
}
pcSurface = new ((int8_t*)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface;
pcSurface = new ((int8_t *)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface;
}
// create a flat node graph with a root node and one child for each surface
if (!pScene->mNumMeshes)
throw DeadlyImportError( "Invalid MDC file: File contains no valid mesh");
else if (1 == pScene->mNumMeshes)
{
throw DeadlyImportError("Invalid MDC file: File contains no valid mesh");
else if (1 == pScene->mNumMeshes) {
pScene->mRootNode = new aiNode();
if ( nullptr != pScene->mMeshes[0] ) {
if (nullptr != pScene->mMeshes[0]) {
pScene->mRootNode->mName = pScene->mMeshes[0]->mName;
pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int[1];
pScene->mRootNode->mMeshes[0] = 0;
}
}
else
{
} else {
pScene->mRootNode = new aiNode();
pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
pScene->mRootNode->mChildren = new aiNode *[pScene->mNumMeshes];
pScene->mRootNode->mName.Set("<root>");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{
aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
aiNode *pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
pcNode->mParent = pScene->mRootNode;
pcNode->mName = pScene->mMeshes[i]->mName;
pcNode->mNumMeshes = 1;
@ -461,13 +436,12 @@ void MDCImporter::InternReadFile(
// create materials
pScene->mNumMaterials = (unsigned int)aszShaders.size();
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
{
aiMaterial* pcMat = new aiMaterial();
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
aiMaterial *pcMat = new aiMaterial();
pScene->mMaterials[i] = pcMat;
const std::string& name = aszShaders[i];
const std::string &name = aszShaders[i];
int iMode = (int)aiShadingMode_Gouraud;
pcMat->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
@ -475,19 +449,20 @@ void MDCImporter::InternReadFile(
// add a small ambient color value - RtCW seems to have one
aiColor3D clr;
clr.b = clr.g = clr.r = 0.05f;
pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
if (name.length())clr.b = clr.g = clr.r = 1.0f;
else clr.b = clr.g = clr.r = 0.6f;
pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
pcMat->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
if (name.length())
{
clr.b = clr.g = clr.r = 1.0f;
else
clr.b = clr.g = clr.r = 0.6f;
pcMat->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
pcMat->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
if (name.length()) {
aiString path;
path.Set(name);
pcMat->AddProperty(&path,AI_MATKEY_TEXTURE_DIFFUSE(0));
pcMat->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
}
}
}

View File

@ -68,6 +68,10 @@ namespace Assimp {
namespace MDL {
namespace HalfLife {
#ifdef _WIN32
# pragma warning(disable : 4706)
#endif // _WIN32
// ------------------------------------------------------------------------------------------------
HL1MDLLoader::HL1MDLLoader(
aiScene *scene,
@ -817,25 +821,25 @@ void HL1MDLLoader::read_meshes() {
mesh_faces.reserve(num_faces);
if (is_triangle_fan) {
for (int i = 0; i < num_faces; ++i) {
for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) {
mesh_faces.push_back(HL1MeshFace{
tricmds[0],
tricmds[i + 1],
tricmds[i + 2] });
tricmds[faceIdx + 1],
tricmds[faceIdx + 2] });
}
} else {
for (int i = 0; i < num_faces; ++i) {
for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) {
if (i & 1) {
// Preserve winding order.
mesh_faces.push_back(HL1MeshFace{
tricmds[i + 1],
tricmds[i],
tricmds[i + 2] });
tricmds[faceIdx + 1],
tricmds[faceIdx],
tricmds[faceIdx + 2] });
} else {
mesh_faces.push_back(HL1MeshFace{
tricmds[i],
tricmds[i + 1],
tricmds[i + 2] });
tricmds[faceIdx],
tricmds[faceIdx + 1],
tricmds[faceIdx + 2] });
}
}
}
@ -1122,10 +1126,10 @@ void HL1MDLLoader::read_sequence_infos() {
aiNode *blend_controller_node = blend_controllers_node->mChildren[j] = new aiNode();
blend_controller_node->mParent = blend_controllers_node;
aiMetadata *md = blend_controller_node->mMetaData = aiMetadata::Alloc(3);
md->Set(0, "Start", pseqdesc->blendstart[j]);
md->Set(1, "End", pseqdesc->blendend[j]);
md->Set(2, "MotionFlags", pseqdesc->blendtype[j]);
aiMetadata *metaData = blend_controller_node->mMetaData = aiMetadata::Alloc(3);
metaData->Set(0, "Start", pseqdesc->blendstart[j]);
metaData->Set(1, "End", pseqdesc->blendend[j]);
metaData->Set(2, "MotionFlags", pseqdesc->blendtype[j]);
}
}
}
@ -1151,10 +1155,10 @@ void HL1MDLLoader::read_sequence_infos() {
aiNode *pEvent = pEventsNode->mChildren[j] = new aiNode();
pEvent->mParent = pEventsNode;
aiMetadata *md = pEvent->mMetaData = aiMetadata::Alloc(3);
md->Set(0, "Frame", pevent->frame);
md->Set(1, "ScriptEvent", pevent->event);
md->Set(2, "Options", aiString(pevent->options));
aiMetadata *metaData = pEvent->mMetaData = aiMetadata::Alloc(3);
metaData->Set(0, "Frame", pevent->frame);
metaData->Set(1, "ScriptEvent", pevent->event);
metaData->Set(2, "Options", aiString(pevent->options));
}
}

View File

@ -56,27 +56,27 @@ namespace HalfLife {
/* A class to help map model triverts to mesh triverts. */
struct HL1MeshTrivert {
HL1MeshTrivert() :
vertindex(-1),
normindex(-1),
s(0),
t(0),
localindex(-1) {
vertindex(-1),
normindex(-1),
s(0),
t(0),
localindex(-1) {
}
HL1MeshTrivert(short vertindex, short normindex, short s, short t, short localindex) :
vertindex(vertindex),
normindex(normindex),
s(s),
t(t),
localindex() {
vertindex(vertindex),
normindex(normindex),
s(s),
t(t),
localindex(localindex) {
}
HL1MeshTrivert(const Trivert &a) :
vertindex(a.vertindex),
normindex(a.normindex),
s(a.s),
t(a.t),
localindex(-1) {
vertindex(a.vertindex),
normindex(a.normindex),
s(a.s),
t(a.t),
localindex(-1) {
}
inline bool operator==(const Trivert &a) const {

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -58,7 +57,6 @@ struct aiTexture;
namespace Assimp {
using namespace MDL;
// --------------------------------------------------------------------------------------
@ -436,7 +434,7 @@ protected:
unsigned int iGSFileVersion;
/** Output I/O handler. used to load external lmp files */
IOSystem* pIOHandler;
IOSystem* mIOHandler;
/** Output scene to be filled */
aiScene* pScene;

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -43,85 +41,77 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the material part of the MDL importer class */
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
// internal headers
#include "MDLLoader.h"
#include "MDLDefaultColorMap.h"
#include <assimp/StringUtils.h>
#include <assimp/texture.h>
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include "MDLLoader.h"
#include <assimp/Defines.h>
#include <assimp/StringUtils.h>
#include <assimp/qnan.h>
#include <assimp/scene.h>
#include <assimp/texture.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <memory>
using namespace Assimp;
static aiTexel* const bad_texel = reinterpret_cast<aiTexel*>(SIZE_MAX);
static aiTexel *const bad_texel = reinterpret_cast<aiTexel *>(SIZE_MAX);
// ------------------------------------------------------------------------------------------------
// Find a suitable palette file or take the default one
void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
{
void MDLImporter::SearchPalette(const unsigned char **pszColorMap) {
// now try to find the color map in the current directory
IOStream* pcStream = pIOHandler->Open(configPalette,"rb");
IOStream *pcStream = mIOHandler->Open(configPalette, "rb");
const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
if(pcStream)
{
if (pcStream->FileSize() >= 768)
{
const unsigned char *szColorMap = (const unsigned char *)::g_aclrDefaultColorMap;
if (pcStream) {
if (pcStream->FileSize() >= 768) {
size_t len = 256 * 3;
unsigned char* colorMap = new unsigned char[len];
unsigned char *colorMap = new unsigned char[len];
szColorMap = colorMap;
pcStream->Read(colorMap, len,1);
pcStream->Read(colorMap, len, 1);
ASSIMP_LOG_INFO("Found valid colormap.lmp in directory. "
"It will be used to decode embedded textures in palletized formats.");
"It will be used to decode embedded textures in palletized formats.");
}
delete pcStream;
pcStream = NULL;
pcStream = nullptr;
}
*pszColorMap = szColorMap;
}
// ------------------------------------------------------------------------------------------------
// Free the palette again
void MDLImporter::FreePalette(const unsigned char* szColorMap)
{
if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
void MDLImporter::FreePalette(const unsigned char *szColorMap) {
if (szColorMap != (const unsigned char *)::g_aclrDefaultColorMap) {
delete[] szColorMap;
}
}
// ------------------------------------------------------------------------------------------------
// Check whether we can replace a texture with a single color
aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture)
{
ai_assert(NULL != pcTexture);
aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture *pcTexture) {
ai_assert(nullptr != pcTexture);
aiColor4D clrOut;
clrOut.r = get_qnan();
if (!pcTexture->mHeight || !pcTexture->mWidth)
return clrOut;
const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth;
const aiTexel* pcTexel = pcTexture->pcData+1;
const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels];
const unsigned int iNumPixels = pcTexture->mHeight * pcTexture->mWidth;
const aiTexel *pcTexel = pcTexture->pcData + 1;
const aiTexel *const pcTexelEnd = &pcTexture->pcData[iNumPixels];
while (pcTexel != pcTexelEnd)
{
if (*pcTexel != *(pcTexel-1))
{
pcTexel = NULL;
while (pcTexel != pcTexelEnd) {
if (*pcTexel != *(pcTexel - 1)) {
pcTexel = nullptr;
break;
}
++pcTexel;
}
if (pcTexel)
{
if (pcTexel) {
clrOut.r = pcTexture->pcData->r / 255.0f;
clrOut.g = pcTexture->pcData->g / 255.0f;
clrOut.b = pcTexture->pcData->b / 255.0f;
@ -132,28 +122,26 @@ aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture)
// ------------------------------------------------------------------------------------------------
// Read a texture from a MDL3 file
void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData)
{
const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function
void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char *szData) {
const MDL::Header *pcHeader = (const MDL::Header *)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function
VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth *
pcHeader->skinheight);
pcHeader->skinheight);
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
aiTexture *pcNew = new aiTexture();
pcNew->mWidth = pcHeader->skinwidth;
pcNew->mHeight = pcHeader->skinheight;
pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
const unsigned char* szColorMap;
const unsigned char *szColorMap;
this->SearchPalette(&szColorMap);
// copy texture data
for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
for (unsigned int i = 0; i < pcNew->mWidth * pcNew->mHeight; ++i) {
const unsigned char val = szData[i];
const unsigned char* sz = &szColorMap[val*3];
const unsigned char *sz = &szColorMap[val * 3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = *sz++;
@ -164,29 +152,26 @@ void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData)
FreePalette(szColorMap);
// store the texture
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
for (unsigned int i = 0; i <pScene->mNumTextures;++i)
aiTexture **pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture *[pScene->mNumTextures + 1];
for (unsigned int i = 0; i < pScene->mNumTextures; ++i)
pScene->mTextures[i] = pc[i];
pScene->mTextures[this->pScene->mNumTextures] = pcNew;
pScene->mNumTextures++;
delete[] pc;
return;
}
// ------------------------------------------------------------------------------------------------
// Read a texture from a MDL4 file
void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip)
{
ai_assert(NULL != piSkip);
void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char *szData,
unsigned int iType,
unsigned int *piSkip) {
ai_assert(nullptr != piSkip);
const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function
const MDL::Header *pcHeader = (const MDL::Header *)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function
if (iType == 1 || iType > 3)
{
if (iType == 1 || iType > 3) {
ASSIMP_LOG_ERROR("Unsupported texture file format");
return;
}
@ -194,35 +179,30 @@ void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
const bool bNoRead = *piSkip == UINT_MAX;
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
aiTexture *pcNew = new aiTexture();
pcNew->mWidth = pcHeader->skinwidth;
pcNew->mHeight = pcHeader->skinheight;
if (bNoRead)pcNew->pcData = bad_texel;
ParseTextureColorData(szData,iType,piSkip,pcNew);
if (bNoRead) pcNew->pcData = bad_texel;
ParseTextureColorData(szData, iType, piSkip, pcNew);
// store the texture
if (!bNoRead)
{
if (!this->pScene->mNumTextures)
{
if (!bNoRead) {
if (!this->pScene->mNumTextures) {
pScene->mNumTextures = 1;
pScene->mTextures = new aiTexture*[1];
pScene->mTextures = new aiTexture *[1];
pScene->mTextures[0] = pcNew;
}
else
{
aiTexture** pc = pScene->mTextures;
pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
} else {
aiTexture **pc = pScene->mTextures;
pScene->mTextures = new aiTexture *[pScene->mNumTextures + 1];
for (unsigned int i = 0; i < this->pScene->mNumTextures; ++i)
pScene->mTextures[i] = pc[i];
pScene->mTextures[pScene->mNumTextures] = pcNew;
pScene->mNumTextures++;
delete[] pc;
}
}
else {
pcNew->pcData = NULL;
} else {
pcNew->pcData = nullptr;
delete pcNew;
}
return;
@ -230,11 +210,10 @@ void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
// ------------------------------------------------------------------------------------------------
// Load color data of a texture and convert it to our output format
void MDLImporter::ParseTextureColorData(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip,
aiTexture* pcNew)
{
void MDLImporter::ParseTextureColorData(const unsigned char *szData,
unsigned int iType,
unsigned int *piSkip,
aiTexture *pcNew) {
const bool do_read = bad_texel != pcNew->pcData;
// allocate storage for the texture image
@ -244,17 +223,14 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
// R5G6B5 format (with or without MIPs)
// ****************************************************************
if (2 == iType || 10 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2);
if (2 == iType || 10 == iType) {
VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight * 2);
// copy texture data
unsigned int i;
if (do_read)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
if (do_read) {
for (i = 0; i < pcNew->mWidth * pcNew->mHeight; ++i) {
MDL::RGB565 val = ((MDL::RGB565 *)szData)[i];
AI_SWAP2(val);
pcNew->pcData[i].a = 0xFF;
@ -262,30 +238,27 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
pcNew->pcData[i].g = (unsigned char)val.g << 2;
pcNew->pcData[i].b = (unsigned char)val.r << 3;
}
} else {
i = pcNew->mWidth * pcNew->mHeight;
}
else i = pcNew->mWidth*pcNew->mHeight;
*piSkip = i * 2;
// apply MIP maps
if (10 == iType)
{
if (10 == iType) {
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// ARGB4 format (with or without MIPs)
// ****************************************************************
else if (3 == iType || 11 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
else if (3 == iType || 11 == iType) {
VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight * 4);
// copy texture data
unsigned int i;
if (do_read)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
if (do_read) {
for (i = 0; i < pcNew->mWidth * pcNew->mHeight; ++i) {
MDL::ARGB4 val = ((MDL::ARGB4 *)szData)[i];
AI_SWAP2(val);
pcNew->pcData[i].a = (unsigned char)val.a << 4;
@ -293,95 +266,83 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
pcNew->pcData[i].g = (unsigned char)val.g << 4;
pcNew->pcData[i].b = (unsigned char)val.b << 4;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
} else
i = pcNew->mWidth * pcNew->mHeight;
*piSkip = i * 2;
// apply MIP maps
if (11 == iType)
{
if (11 == iType) {
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// RGB8 format (with or without MIPs)
// ****************************************************************
else if (4 == iType || 12 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3);
else if (4 == iType || 12 == iType) {
VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight * 3);
// copy texture data
unsigned int i;
if (do_read)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char* _szData = &szData[i*3];
if (do_read) {
for (i = 0; i < pcNew->mWidth * pcNew->mHeight; ++i) {
const unsigned char *_szData = &szData[i * 3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].b = *_szData++;
pcNew->pcData[i].g = *_szData++;
pcNew->pcData[i].r = *_szData;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
} else
i = pcNew->mWidth * pcNew->mHeight;
// apply MIP maps
*piSkip = i * 3;
if (12 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
if (12 == iType) {
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) * 3;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// ARGB8 format (with ir without MIPs)
// ****************************************************************
else if (5 == iType || 13 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
else if (5 == iType || 13 == iType) {
VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight * 4);
// copy texture data
unsigned int i;
if (do_read)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char* _szData = &szData[i*4];
if (do_read) {
for (i = 0; i < pcNew->mWidth * pcNew->mHeight; ++i) {
const unsigned char *_szData = &szData[i * 4];
pcNew->pcData[i].b = *_szData++;
pcNew->pcData[i].g = *_szData++;
pcNew->pcData[i].r = *_szData++;
pcNew->pcData[i].a = *_szData;
}
} else {
i = pcNew->mWidth * pcNew->mHeight;
}
else i = pcNew->mWidth*pcNew->mHeight;
// apply MIP maps
*piSkip = i << 2;
if (13 == iType)
{
if (13 == iType) {
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2;
}
}
// palletized 8 bit texture. As for Quake 1
// ****************************************************************
else if (0 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight);
else if (0 == iType) {
VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight);
// copy texture data
unsigned int i;
if (do_read)
{
if (do_read) {
const unsigned char* szColorMap;
const unsigned char *szColorMap;
SearchPalette(&szColorMap);
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
for (i = 0; i < pcNew->mWidth * pcNew->mHeight; ++i) {
const unsigned char val = szData[i];
const unsigned char* sz = &szColorMap[val*3];
const unsigned char *sz = &szColorMap[val * 3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = *sz++;
@ -390,8 +351,8 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
}
this->FreePalette(szColorMap);
}
else i = pcNew->mWidth*pcNew->mHeight;
} else
i = pcNew->mWidth * pcNew->mHeight;
*piSkip = i;
// FIXME: Also support for MIP maps?
@ -400,24 +361,23 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
// ------------------------------------------------------------------------------------------------
// Get a texture from a MDL5 file
void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip)
{
void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData,
unsigned int iType,
unsigned int *piSkip) {
ai_assert(NULL != piSkip);
bool bNoRead = *piSkip == UINT_MAX;
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
aiTexture *pcNew = new aiTexture();
VALIDATE_FILE_SIZE(szData+8);
VALIDATE_FILE_SIZE(szData + 8);
// first read the size of the texture
pcNew->mWidth = *((uint32_t*)szData);
pcNew->mWidth = *((uint32_t *)szData);
AI_SWAP4(pcNew->mWidth);
szData += sizeof(uint32_t);
pcNew->mHeight = *((uint32_t*)szData);
pcNew->mHeight = *((uint32_t *)szData);
AI_SWAP4(pcNew->mHeight);
szData += sizeof(uint32_t);
@ -429,14 +389,12 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
// however, one can easily try out what MED does if you have
// a model with a DDS texture and export it to MDL5 ...
// yeah, it embedds the DDS file.
if (6 == iType)
{
if (6 == iType) {
// this is a compressed texture in DDS format
*piSkip = pcNew->mWidth;
VALIDATE_FILE_SIZE(szData + *piSkip);
if (!bNoRead)
{
if (!bNoRead) {
// place a hint and let the application know that this is a DDS file
pcNew->mHeight = 0;
pcNew->achFormatHint[0] = 'd';
@ -444,39 +402,32 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
pcNew->achFormatHint[2] = 's';
pcNew->achFormatHint[3] = '\0';
pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
::memcpy(pcNew->pcData,szData,pcNew->mWidth);
pcNew->pcData = (aiTexel *)new unsigned char[pcNew->mWidth];
::memcpy(pcNew->pcData, szData, pcNew->mWidth);
}
}
else
{
} else {
// parse the color data of the texture
ParseTextureColorData(szData,iType,piSkip,pcNew);
ParseTextureColorData(szData, iType, piSkip, pcNew);
}
*piSkip += sizeof(uint32_t) * 2;
if (!bNoRead)
{
if (!bNoRead) {
// store the texture
if (!this->pScene->mNumTextures)
{
if (!this->pScene->mNumTextures) {
pScene->mNumTextures = 1;
pScene->mTextures = new aiTexture*[1];
pScene->mTextures = new aiTexture *[1];
pScene->mTextures[0] = pcNew;
}
else
{
aiTexture** pc = pScene->mTextures;
pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
for (unsigned int i = 0; i < pScene->mNumTextures;++i)
} else {
aiTexture **pc = pScene->mTextures;
pScene->mTextures = new aiTexture *[pScene->mNumTextures + 1];
for (unsigned int i = 0; i < pScene->mNumTextures; ++i)
this->pScene->mTextures[i] = pc[i];
pScene->mTextures[pScene->mNumTextures] = pcNew;
pScene->mNumTextures++;
delete[] pc;
}
}
else {
} else {
pcNew->pcData = NULL;
delete pcNew;
}
@ -486,31 +437,26 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
// ------------------------------------------------------------------------------------------------
// Get a skin from a MDL7 file - more complex than all other subformats
void MDLImporter::ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
aiMaterial* pcMatOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight)
{
const unsigned char *szCurrent,
const unsigned char **szCurrentOut,
aiMaterial *pcMatOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight) {
std::unique_ptr<aiTexture> pcNew;
// get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF);
if (0x1 == iMasked)
{
if (0x1 == iMasked) {
// ***** REFERENCE TO ANOTHER SKIN INDEX *****
int referrer = (int)iWidth;
pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL);
}
else if (0x6 == iMasked)
{
pcMatOut->AddProperty<int>(&referrer, 1, AI_MDL7_REFERRER_MATERIAL);
} else if (0x6 == iMasked) {
// ***** EMBEDDED DDS FILE *****
if (1 != iHeight)
{
if (1 != iHeight) {
ASSIMP_LOG_WARN("Found a reference to an embedded DDS texture, "
"but texture height is not equal to 1, which is not supported by MED");
"but texture height is not equal to 1, which is not supported by MED");
}
pcNew.reset(new aiTexture());
@ -523,57 +469,47 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
pcNew->achFormatHint[2] = 's';
pcNew->achFormatHint[3] = '\0';
pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
pcNew->pcData = (aiTexel *)new unsigned char[pcNew->mWidth];
memcpy(pcNew->pcData, szCurrent, pcNew->mWidth);
szCurrent += iWidth;
}
else if (0x7 == iMasked)
{
} else if (0x7 == iMasked) {
// ***** REFERENCE TO EXTERNAL FILE *****
if (1 != iHeight)
{
if (1 != iHeight) {
ASSIMP_LOG_WARN("Found a reference to an external texture, "
"but texture height is not equal to 1, which is not supported by MED");
"but texture height is not equal to 1, which is not supported by MED");
}
aiString szFile;
const size_t iLen = strlen((const char*)szCurrent);
size_t iLen2 = iLen+1;
const size_t iLen = strlen((const char *)szCurrent);
size_t iLen2 = iLen + 1;
iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
memcpy(szFile.data,(const char*)szCurrent,iLen2);
memcpy(szFile.data, (const char *)szCurrent, iLen2);
szFile.length = (ai_uint32)iLen;
szCurrent += iLen2;
// place this as diffuse texture
pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else if (iMasked || !iType || (iType && iWidth && iHeight))
{
pcMatOut->AddProperty(&szFile, AI_MATKEY_TEXTURE_DIFFUSE(0));
} else if (iMasked || !iType || (iType && iWidth && iHeight)) {
pcNew.reset(new aiTexture());
if (!iHeight || !iWidth)
{
if (!iHeight || !iWidth) {
ASSIMP_LOG_WARN("Found embedded texture, but its width "
"an height are both 0. Is this a joke?");
"an height are both 0. Is this a joke?");
// generate an empty chess pattern
pcNew->mWidth = pcNew->mHeight = 8;
pcNew->pcData = new aiTexel[64];
for (unsigned int x = 0; x < 8;++x)
{
for (unsigned int y = 0; y < 8;++y)
{
for (unsigned int x = 0; x < 8; ++x) {
for (unsigned int y = 0; y < 8; ++y) {
const bool bSet = ((0 == x % 2 && 0 != y % 2) ||
(0 != x % 2 && 0 == y % 2));
(0 != x % 2 && 0 == y % 2));
aiTexel* pc = &pcNew->pcData[y * 8 + x];
pc->r = pc->b = pc->g = (bSet?0xFF:0);
aiTexel *pc = &pcNew->pcData[y * 8 + x];
pc->r = pc->b = pc->g = (bSet ? 0xFF : 0);
pc->a = 0xFF;
}
}
}
else
{
} else {
// it is a standard color texture. Fill in width and height
// and call the same function we used for loading MDL5 files
@ -581,7 +517,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
pcNew->mHeight = iHeight;
unsigned int iSkip = 0;
ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew.get());
ParseTextureColorData(szCurrent, iMasked, &iSkip, pcNew.get());
// skip length of texture data
szCurrent += iSkip;
@ -592,25 +528,25 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
// texture instead of material colors ... posssible they have
// been converted to MDL7 from other formats, such as MDL5
aiColor4D clrTexture;
if (pcNew)clrTexture = ReplaceTextureWithColor(pcNew.get());
else clrTexture.r = get_qnan();
if (pcNew)
clrTexture = ReplaceTextureWithColor(pcNew.get());
else
clrTexture.r = get_qnan();
// check whether a material definition is contained in the skin
if (iType & AI_MDL7_SKINTYPE_MATERIAL)
{
BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
szCurrent = (unsigned char*)(pcMatIn+1);
if (iType & AI_MDL7_SKINTYPE_MATERIAL) {
BE_NCONST MDL::Material_MDL7 *pcMatIn = (BE_NCONST MDL::Material_MDL7 *)szCurrent;
szCurrent = (unsigned char *)(pcMatIn + 1);
VALIDATE_FILE_SIZE(szCurrent);
aiColor3D clrTemp;
#define COLOR_MULTIPLY_RGB() \
if (is_not_qnan(clrTexture.r)) \
{ \
clrTemp.r *= clrTexture.r; \
clrTemp.g *= clrTexture.g; \
clrTemp.b *= clrTexture.b; \
}
#define COLOR_MULTIPLY_RGB() \
if (is_not_qnan(clrTexture.r)) { \
clrTemp.r *= clrTexture.r; \
clrTemp.g *= clrTexture.g; \
clrTemp.b *= clrTexture.b; \
}
// read diffuse color
clrTemp.r = pcMatIn->Diffuse.r;
@ -620,7 +556,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
clrTemp.b = pcMatIn->Diffuse.b;
AI_SWAP4(clrTemp.b);
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
pcMatOut->AddProperty<aiColor3D>(&clrTemp, 1, AI_MATKEY_COLOR_DIFFUSE);
// read specular color
clrTemp.r = pcMatIn->Specular.r;
@ -630,7 +566,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
clrTemp.b = pcMatIn->Specular.b;
AI_SWAP4(clrTemp.b);
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
pcMatOut->AddProperty<aiColor3D>(&clrTemp, 1, AI_MATKEY_COLOR_SPECULAR);
// read ambient color
clrTemp.r = pcMatIn->Ambient.r;
@ -640,7 +576,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
clrTemp.b = pcMatIn->Ambient.b;
AI_SWAP4(clrTemp.b);
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
pcMatOut->AddProperty<aiColor3D>(&clrTemp, 1, AI_MATKEY_COLOR_AMBIENT);
// read emissive color
clrTemp.r = pcMatIn->Emissive.r;
@ -649,7 +585,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
AI_SWAP4(clrTemp.g);
clrTemp.b = pcMatIn->Emissive.b;
AI_SWAP4(clrTemp.b);
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
pcMatOut->AddProperty<aiColor3D>(&clrTemp, 1, AI_MATKEY_COLOR_EMISSIVE);
#undef COLOR_MULITPLY_RGB
@ -661,38 +597,33 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
if (is_not_qnan(clrTexture.r)) {
clrTemp.r *= clrTexture.a;
}
pcMatOut->AddProperty<ai_real>(&clrTemp.r,1,AI_MATKEY_OPACITY);
pcMatOut->AddProperty<ai_real>(&clrTemp.r, 1, AI_MATKEY_OPACITY);
// read phong power
int iShadingMode = (int)aiShadingMode_Gouraud;
AI_SWAP4(pcMatIn->Power);
if (0.0f != pcMatIn->Power)
{
if (0.0f != pcMatIn->Power) {
iShadingMode = (int)aiShadingMode_Phong;
// pcMatIn is packed, we can't form pointers to its members
float power = pcMatIn->Power;
pcMatOut->AddProperty<float>(&power,1,AI_MATKEY_SHININESS);
pcMatOut->AddProperty<float>(&power, 1, AI_MATKEY_SHININESS);
}
pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
}
else if (is_not_qnan(clrTexture.r))
{
pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE);
pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR);
pcMatOut->AddProperty<int>(&iShadingMode, 1, AI_MATKEY_SHADING_MODEL);
} else if (is_not_qnan(clrTexture.r)) {
pcMatOut->AddProperty<aiColor4D>(&clrTexture, 1, AI_MATKEY_COLOR_DIFFUSE);
pcMatOut->AddProperty<aiColor4D>(&clrTexture, 1, AI_MATKEY_COLOR_SPECULAR);
}
// if the texture could be replaced by a single material color
// we don't need the texture anymore
if (is_not_qnan(clrTexture.r))
{
if (is_not_qnan(clrTexture.r)) {
pcNew.reset();
}
// If an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ...
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
{
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) {
VALIDATE_FILE_SIZE(szCurrent);
int32_t iMe = *((int32_t*)szCurrent);
int32_t iMe = *((int32_t *)szCurrent);
AI_SWAP4(iMe);
szCurrent += sizeof(char) * iMe + sizeof(int32_t);
VALIDATE_FILE_SIZE(szCurrent);
@ -700,32 +631,27 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
// If an embedded texture has been loaded setup the corresponding
// data structures in the aiScene instance
if (pcNew && pScene->mNumTextures <= 999)
{
if (pcNew && pScene->mNumTextures <= 999) {
// place this as diffuse texture
char szCurrent[5];
ai_snprintf(szCurrent,5,"*%i",this->pScene->mNumTextures);
char current[5];
ai_snprintf(current, 5, "*%i", this->pScene->mNumTextures);
aiString szFile;
const size_t iLen = strlen((const char*)szCurrent);
::memcpy(szFile.data,(const char*)szCurrent,iLen+1);
const size_t iLen = strlen((const char *)current);
::memcpy(szFile.data, (const char *)current, iLen + 1);
szFile.length = (ai_uint32)iLen;
pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
pcMatOut->AddProperty(&szFile, AI_MATKEY_TEXTURE_DIFFUSE(0));
// store the texture
if (!pScene->mNumTextures)
{
if (!pScene->mNumTextures) {
pScene->mNumTextures = 1;
pScene->mTextures = new aiTexture*[1];
pScene->mTextures = new aiTexture *[1];
pScene->mTextures[0] = pcNew.release();
}
else
{
aiTexture** pc = pScene->mTextures;
pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
for (unsigned int i = 0; i < pScene->mNumTextures;++i) {
} else {
aiTexture **pc = pScene->mTextures;
pScene->mTextures = new aiTexture *[pScene->mNumTextures + 1];
for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {
pScene->mTextures[i] = pc[i];
}
@ -741,28 +667,22 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
// ------------------------------------------------------------------------------------------------
// Skip a skin lump
void MDLImporter::SkipSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight)
{
const unsigned char *szCurrent,
const unsigned char **szCurrentOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight) {
// get the type of the skin
const unsigned int iMasked = (unsigned int)(iType & 0xF);
if (0x6 == iMasked)
{
if (0x6 == iMasked) {
szCurrent += iWidth;
}
if (0x7 == iMasked)
{
const size_t iLen = ::strlen((const char*)szCurrent);
szCurrent += iLen+1;
}
else if (iMasked || !iType)
{
if (iMasked || !iType || (iType && iWidth && iHeight))
{
if (0x7 == iMasked) {
const size_t iLen = std::strlen((const char *)szCurrent);
szCurrent += iLen + 1;
} else if (iMasked || !iType) {
if (iMasked || !iType || (iType && iWidth && iHeight)) {
// ParseTextureColorData(..., aiTexture::pcData == bad_texel) will simply
// return the size of the color data in bytes in iSkip
unsigned int iSkip = 0;
@ -771,10 +691,10 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
tex.pcData = bad_texel;
tex.mHeight = iHeight;
tex.mWidth = iWidth;
ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex);
ParseTextureColorData(szCurrent, iMasked, &iSkip, &tex);
// FIX: Important, otherwise the destructor will crash
tex.pcData = NULL;
tex.pcData = nullptr;
// skip length of texture data
szCurrent += iSkip;
@ -782,17 +702,15 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
}
// check whether a material definition is contained in the skin
if (iType & AI_MDL7_SKINTYPE_MATERIAL)
{
BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
szCurrent = (unsigned char*)(pcMatIn+1);
if (iType & AI_MDL7_SKINTYPE_MATERIAL) {
BE_NCONST MDL::Material_MDL7 *pcMatIn = (BE_NCONST MDL::Material_MDL7 *)szCurrent;
szCurrent = (unsigned char *)(pcMatIn + 1);
}
// if an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ...
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
{
int32_t iMe = *((int32_t*)szCurrent);
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) {
int32_t iMe = *((int32_t *)szCurrent);
AI_SWAP4(iMe);
szCurrent += sizeof(char) * iMe + sizeof(int32_t);
}
@ -801,39 +719,37 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
// ------------------------------------------------------------------------------------------------
void MDLImporter::ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
std::vector<aiMaterial*>& pcMats)
{
ai_assert(NULL != szCurrent);
ai_assert(NULL != szCurrentOut);
const unsigned char *szCurrent,
const unsigned char **szCurrentOut,
std::vector<aiMaterial *> &pcMats) {
ai_assert(nullptr != szCurrent);
ai_assert(nullptr != szCurrentOut);
*szCurrentOut = szCurrent;
BE_NCONST MDL::Skin_MDL7* pcSkin = (BE_NCONST MDL::Skin_MDL7*)szCurrent;
BE_NCONST MDL::Skin_MDL7 *pcSkin = (BE_NCONST MDL::Skin_MDL7 *)szCurrent;
AI_SWAP4(pcSkin->width);
AI_SWAP4(pcSkin->height);
szCurrent += 12;
// allocate an output material
aiMaterial* pcMatOut = new aiMaterial();
aiMaterial *pcMatOut = new aiMaterial();
pcMats.push_back(pcMatOut);
// skip length of file name
szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut,
pcSkin->typ,pcSkin->width,pcSkin->height);
ParseSkinLump_3DGS_MDL7(szCurrent, szCurrentOut, pcMatOut,
pcSkin->typ, pcSkin->width, pcSkin->height);
// place the name of the skin in the material
if (pcSkin->texture_name[0])
{
if (pcSkin->texture_name[0]) {
// the 0 termination could be there or not - we can't know
aiString szFile;
::memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
::memcpy(szFile.data, pcSkin->texture_name, sizeof(pcSkin->texture_name));
szFile.data[sizeof(pcSkin->texture_name)] = '\0';
szFile.length = (ai_uint32)::strlen(szFile.data);
pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
pcMatOut->AddProperty(&szFile, AI_MATKEY_NAME);
}
}

View File

@ -199,9 +199,9 @@ namespace vmd
stream->write((char*)&ik_count, sizeof(int));
for (int i = 0; i < ik_count; i++)
{
const VmdIkEnable& ik_enable = this->ik_enable.at(i);
stream->write(ik_enable.ik_name.c_str(), 20);
stream->write((char*)&ik_enable.enable, sizeof(uint8_t));
const VmdIkEnable& ik_enable_ref = this->ik_enable.at(i);
stream->write(ik_enable_ref.ik_name.c_str(), 20);
stream->write((char *)&ik_enable_ref.enable, sizeof(uint8_t));
}
}
};

View File

@ -261,19 +261,19 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
TempTriangle& t = triangles[i];
stream.IncPtr(2);
for (unsigned int i = 0; i < 3; ++i) {
t.indices[i] = stream.GetI2();
for (unsigned int j = 0; j < 3; ++j) {
t.indices[j] = stream.GetI2();
}
for (unsigned int i = 0; i < 3; ++i) {
ReadVector(stream,t.normals[i]);
for (unsigned int j = 0; j < 3; ++j) {
ReadVector(stream,t.normals[j]);
}
for (unsigned int i = 0; i < 3; ++i) {
stream >> (float&)(t.uv[i].x); // see note in ReadColor()
for (unsigned int j = 0; j < 3; ++j) {
stream >> (float&)(t.uv[j].x); // see note in ReadColor()
}
for (unsigned int i = 0; i < 3; ++i) {
stream >> (float&)(t.uv[i].y);
for (unsigned int j = 0; j < 3; ++j) {
stream >> (float&)(t.uv[j].y);
}
t.sg = stream.GetI1();
@ -296,8 +296,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
stream >> num;
t.triangles.resize(num);
for (unsigned int i = 0; i < num; ++i) {
t.triangles[i] = stream.GetI2();
for (unsigned int j = 0; j < num; ++j) {
t.triangles[j] = stream.GetI2();
}
t.mat = stream.GetI1();
if (t.mat == UINT_MAX) {
@ -309,8 +309,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
stream >> mat;
std::vector<TempMaterial> materials(mat);
for (unsigned int i = 0;i < mat; ++i) {
TempMaterial& t = materials[i];
for (unsigned int j = 0;j < mat; ++j) {
TempMaterial& t = materials[j];
stream.CopyAndAdvance(t.name,32);
t.name[32] = '\0';
@ -338,8 +338,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
stream >> joint;
std::vector<TempJoint> joints(joint);
for(unsigned int i = 0; i < joint; ++i) {
TempJoint& j = joints[i];
for(unsigned int ii = 0; ii < joint; ++ii) {
TempJoint& j = joints[ii];
stream.IncPtr(1);
stream.CopyAndAdvance(j.name,32);
@ -494,17 +494,17 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
typedef std::map<unsigned int,unsigned int> BoneSet;
BoneSet mybones;
for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
aiFace& f = m->mFaces[i];
if (g.triangles[i]>triangles.size()) {
for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) {
aiFace& f = m->mFaces[j];
if (g.triangles[j]>triangles.size()) {
throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
}
TempTriangle& t = triangles[g.triangles[i]];
f.mIndices = new unsigned int[f.mNumIndices=3];
for (unsigned int i = 0; i < 3; ++i,++n) {
if (t.indices[i]>vertices.size()) {
for (unsigned int k = 0; k < 3; ++k,++n) {
if (t.indices[k]>vertices.size()) {
throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
}
@ -545,11 +545,11 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
}
// .. and collect bone weights
for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
TempTriangle& t = triangles[g.triangles[i]];
for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) {
TempTriangle& t = triangles[g.triangles[j]];
for (unsigned int i = 0; i < 3; ++i,++n) {
const TempVertex& v = vertices[t.indices[i]];
for (unsigned int k = 0; k < 3; ++k,++n) {
const TempVertex& v = vertices[t.indices[k]];
for(unsigned int a = 0; a < 4; ++a) {
const unsigned int bone = v.bone_id[a];
if(bone==UINT_MAX){

View File

@ -332,8 +332,7 @@ unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
aiMaterialProperty* prop = pMat->mProperties[i];
if ( prop /* just a sanity check ... */
&& 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE )
&& prop->mSemantic == type) {
&& 0 == strcmp(prop->mKey.data, _AI_MATKEY_TEXTURE_BASE) && static_cast < aiTextureType>(prop->mSemantic) == type) {
max = std::max(max,prop->mIndex+1);
}
@ -562,7 +561,8 @@ uint32_t Assimp::ComputeMaterialHash(const aiMaterial* mat, bool includeMatName
// Exclude all properties whose first character is '?' from the hash
// See doc for aiMaterialProperty.
if ((prop = mat->mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?')) {
prop = mat->mProperties[ i ];
if ( nullptr != prop && (includeMatName || prop->mKey.data[0] != '?')) {
hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash);
hash = SuperFastHash(prop->mData,prop->mDataLength,hash);

File diff suppressed because it is too large Load Diff

View File

@ -185,8 +185,8 @@ private:
// for spheres, cones and cylinders: center point of the object
aiVector3D center, radius, dir;
char name[128];
static const size_t MaxNameLen = 128;
char name[MaxNameLen];
std::vector<aiVector3D> vertices, normals, uvs;
std::vector<unsigned int> faces;

View File

@ -86,7 +86,7 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp
void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) {
void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* ) {
// invoke the exporter
ObjExporter exporter(pFile, pScene, true);

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -42,12 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#ifndef OBJ_FILEDATA_H_INC
#define OBJ_FILEDATA_H_INC
# define OBJ_FILEDATA_H_INC
#include <vector>
#include <map>
#include <assimp/types.h>
#include <assimp/mesh.h>
# include <assimp/mesh.h>
# include <assimp/types.h>
# include <map>
# include <vector>
namespace Assimp {
namespace ObjFile {
@ -75,12 +74,8 @@ struct Face {
Material *m_pMaterial;
//! \brief Default constructor
Face( aiPrimitiveType pt = aiPrimitiveType_POLYGON)
: m_PrimitiveType( pt )
, m_vertices()
, m_normals()
, m_texturCoords()
, m_pMaterial( 0L ) {
Face(aiPrimitiveType pt = aiPrimitiveType_POLYGON) :
m_PrimitiveType(pt), m_vertices(), m_normals(), m_texturCoords(), m_pMaterial(0L) {
// empty
}
@ -105,7 +100,7 @@ struct Object {
//! Transformation matrix, stored in OpenGL format
aiMatrix4x4 m_Transformation;
//! All sub-objects referenced by this object
std::vector<Object*> m_SubObjects;
std::vector<Object *> m_SubObjects;
/// Assigned meshes
std::vector<unsigned int> m_Meshes;
@ -114,7 +109,7 @@ struct Object {
//! \brief Destructor
~Object() {
for ( std::vector<Object*>::iterator it = m_SubObjects.begin(); it != m_SubObjects.end(); ++it) {
for (std::vector<Object *>::iterator it = m_SubObjects.begin(); it != m_SubObjects.end(); ++it) {
delete *it;
}
}
@ -181,15 +176,14 @@ struct Material {
aiColor3D transparent;
//! Constructor
Material()
: diffuse ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) )
, alpha (ai_real( 1.0 ) )
, shineness ( ai_real( 0.0) )
, illumination_model (1)
, ior ( ai_real( 1.0 ) )
, transparent( ai_real( 1.0), ai_real (1.0), ai_real(1.0)) {
std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false);
Material() :
diffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
alpha(ai_real(1.0)),
shineness(ai_real(0.0)),
illumination_model(1),
ior(ai_real(1.0)),
transparent(ai_real(1.0), ai_real(1.0), ai_real(1.0)) {
std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false);
}
// Destructor
@ -205,13 +199,13 @@ struct Mesh {
/// The name for the mesh
std::string m_name;
/// Array with pointer to all stored faces
std::vector<Face*> m_Faces;
std::vector<Face *> m_Faces;
/// Assigned material
Material *m_pMaterial;
/// Number of stored indices.
unsigned int m_uiNumIndices;
/// Number of UV
unsigned int m_uiUVCoordinates[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
unsigned int m_uiUVCoordinates[AI_MAX_NUMBER_OF_TEXTURECOORDS];
/// Material index.
unsigned int m_uiMaterialIndex;
/// True, if normals are stored.
@ -220,20 +214,15 @@ struct Mesh {
bool m_hasVertexColors;
/// Constructor
explicit Mesh( const std::string &name )
: m_name( name )
, m_pMaterial(NULL)
, m_uiNumIndices(0)
, m_uiMaterialIndex( NoMaterial )
, m_hasNormals(false) {
memset(m_uiUVCoordinates, 0, sizeof( unsigned int ) * AI_MAX_NUMBER_OF_TEXTURECOORDS);
explicit Mesh(const std::string &name) :
m_name(name), m_pMaterial(NULL), m_uiNumIndices(0), m_uiMaterialIndex(NoMaterial), m_hasNormals(false) {
memset(m_uiUVCoordinates, 0, sizeof(unsigned int) * AI_MAX_NUMBER_OF_TEXTURECOORDS);
}
/// Destructor
~Mesh() {
for (std::vector<Face*>::iterator it = m_Faces.begin();
it != m_Faces.end(); ++it)
{
for (std::vector<Face *>::iterator it = m_Faces.begin();
it != m_Faces.end(); ++it) {
delete *it;
}
}
@ -244,14 +233,14 @@ struct Mesh {
//! \brief Data structure to store all obj-specific model datas
// ------------------------------------------------------------------------------------------------
struct Model {
typedef std::map<std::string, std::vector<unsigned int>* > GroupMap;
typedef std::map<std::string, std::vector<unsigned int>* >::iterator GroupMapIt;
typedef std::map<std::string, std::vector<unsigned int>* >::const_iterator ConstGroupMapIt;
typedef std::map<std::string, std::vector<unsigned int> *> GroupMap;
typedef std::map<std::string, std::vector<unsigned int> *>::iterator GroupMapIt;
typedef std::map<std::string, std::vector<unsigned int> *>::const_iterator ConstGroupMapIt;
//! Model name
std::string m_ModelName;
//! List ob assigned objects
std::vector<Object*> m_Objects;
std::vector<Object *> m_Objects;
//! Pointer to current object
ObjFile::Object *m_pCurrent;
//! Pointer to current material
@ -279,46 +268,45 @@ struct Model {
//! Current mesh instance
Mesh *m_pCurrentMesh;
//! Vector with stored meshes
std::vector<Mesh*> m_Meshes;
std::vector<Mesh *> m_Meshes;
//! Material map
std::map<std::string, Material*> m_MaterialMap;
std::map<std::string, Material *> m_MaterialMap;
//! \brief The default class constructor
Model() :
m_ModelName(""),
m_pCurrent(NULL),
m_pCurrentMaterial(NULL),
m_pDefaultMaterial(NULL),
m_pGroupFaceIDs(NULL),
m_strActiveGroup(""),
m_TextureCoordDim(0),
m_pCurrentMesh(NULL)
{
m_ModelName(""),
m_pCurrent(NULL),
m_pCurrentMaterial(NULL),
m_pDefaultMaterial(NULL),
m_pGroupFaceIDs(NULL),
m_strActiveGroup(""),
m_TextureCoordDim(0),
m_pCurrentMesh(NULL) {
// empty
}
//! \brief The class destructor
~Model() {
// Clear all stored object instances
for (std::vector<Object*>::iterator it = m_Objects.begin();
it != m_Objects.end(); ++it) {
for (std::vector<Object *>::iterator it = m_Objects.begin();
it != m_Objects.end(); ++it) {
delete *it;
}
m_Objects.clear();
// Clear all stored mesh instances
for (std::vector<Mesh*>::iterator it = m_Meshes.begin();
it != m_Meshes.end(); ++it) {
for (std::vector<Mesh *>::iterator it = m_Meshes.begin();
it != m_Meshes.end(); ++it) {
delete *it;
}
m_Meshes.clear();
for(GroupMapIt it = m_Groups.begin(); it != m_Groups.end(); ++it) {
for (GroupMapIt it = m_Groups.begin(); it != m_Groups.end(); ++it) {
delete it->second;
}
m_Groups.clear();
for ( std::map<std::string, Material*>::iterator it = m_MaterialMap.begin(); it != m_MaterialMap.end(); ++it ) {
for (std::map<std::string, Material *>::iterator it = m_MaterialMap.begin(); it != m_MaterialMap.end(); ++it) {
delete it->second;
}
}

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -44,16 +42,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
#include "ObjFileImporter.h"
#include "ObjFileParser.h"
#include "ObjFileData.h"
#include <assimp/IOStreamBuffer.h>
#include <memory>
#include "ObjFileParser.h"
#include <assimp/DefaultIOSystem.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/IOStreamBuffer.h>
#include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
#include <memory>
static const aiImporterDesc desc = {
"Wavefront Object Importer",
@ -76,10 +74,8 @@ using namespace std;
// ------------------------------------------------------------------------------------------------
// Default constructor
ObjFileImporter::ObjFileImporter()
: m_Buffer()
, m_pRootObject( nullptr )
, m_strAbsPath( std::string(1, DefaultIOSystem().getOsSeparator()) ) {}
ObjFileImporter::ObjFileImporter() :
m_Buffer(), m_pRootObject(nullptr), m_strAbsPath(std::string(1, DefaultIOSystem().getOsSeparator())) {}
// ------------------------------------------------------------------------------------------------
// Destructor.
@ -90,59 +86,59 @@ ObjFileImporter::~ObjFileImporter() {
// ------------------------------------------------------------------------------------------------
// Returns true, if file is an obj file.
bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const {
if(!checkSig) {
bool ObjFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
if (!checkSig) {
//Check File Extension
return SimpleExtensionCheck(pFile,"obj");
return SimpleExtensionCheck(pFile, "obj");
} else {
// Check file Header
static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9, 200, false, true );
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9, 200, false, true);
}
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* ObjFileImporter::GetInfo() const {
const aiImporterDesc *ObjFileImporter::GetInfo() const {
return &desc;
}
// ------------------------------------------------------------------------------------------------
// Obj-file import implementation
void ObjFileImporter::InternReadFile( const std::string &file, aiScene* pScene, IOSystem* pIOHandler) {
void ObjFileImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) {
// Read file into memory
static const std::string mode = "rb";
std::unique_ptr<IOStream> fileStream( pIOHandler->Open( file, mode));
if( !fileStream.get() ) {
throw DeadlyImportError( "Failed to open file " + file + "." );
std::unique_ptr<IOStream> fileStream(pIOHandler->Open(file, mode));
if (!fileStream.get()) {
throw DeadlyImportError("Failed to open file " + file + ".");
}
// Get the file-size and validate it, throwing an exception when fails
size_t fileSize = fileStream->FileSize();
if( fileSize < ObjMinSize ) {
throw DeadlyImportError( "OBJ-file is too small.");
if (fileSize < ObjMinSize) {
throw DeadlyImportError("OBJ-file is too small.");
}
IOStreamBuffer<char> streamedBuffer;
streamedBuffer.open( fileStream.get() );
streamedBuffer.open(fileStream.get());
// Allocate buffer and read file into it
//TextFileToBuffer( fileStream.get(),m_Buffer);
// Get the model name
std::string modelName, folderName;
std::string::size_type pos = file.find_last_of( "\\/" );
if ( pos != std::string::npos ) {
modelName = file.substr(pos+1, file.size() - pos - 1);
folderName = file.substr( 0, pos );
if ( !folderName.empty() ) {
pIOHandler->PushDirectory( folderName );
std::string modelName, folderName;
std::string::size_type pos = file.find_last_of("\\/");
if (pos != std::string::npos) {
modelName = file.substr(pos + 1, file.size() - pos - 1);
folderName = file.substr(0, pos);
if (!folderName.empty()) {
pIOHandler->PushDirectory(folderName);
}
} else {
modelName = file;
}
// parse the file into a temporary representation
ObjFileParser parser( streamedBuffer, modelName, pIOHandler, m_progress, file);
ObjFileParser parser(streamedBuffer, modelName, pIOHandler, m_progress, file);
// And create the proper return structures out of it
CreateDataFromImport(parser.GetModel(), pScene);
@ -153,21 +149,21 @@ void ObjFileImporter::InternReadFile( const std::string &file, aiScene* pScene,
m_Buffer.clear();
// Pop directory stack
if ( pIOHandler->StackSize() > 0 ) {
if (pIOHandler->StackSize() > 0) {
pIOHandler->PopDirectory();
}
}
// ------------------------------------------------------------------------------------------------
// Create the data from parsed obj-file
void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene) {
if( 0L == pModel ) {
void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene *pScene) {
if (0L == pModel) {
return;
}
// Create the root node of the scene
pScene->mRootNode = new aiNode;
if ( !pModel->m_ModelName.empty() ) {
if (!pModel->m_ModelName.empty()) {
// Set the name of the scene
pScene->mRootNode->mName.Set(pModel->m_ModelName);
} else {
@ -181,17 +177,17 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
unsigned int childCount = 0;
for (auto object : pModel->m_Objects) {
if(object) {
if (object) {
++childCount;
meshCount += (unsigned int)object->m_Meshes.size();
}
}
// Allocate space for the child nodes on the root node
pScene->mRootNode->mChildren = new aiNode*[ childCount ];
pScene->mRootNode->mChildren = new aiNode *[childCount];
// Create nodes for the whole scene
std::vector<aiMesh*> MeshArray;
std::vector<aiMesh *> MeshArray;
MeshArray.reserve(meshCount);
for (size_t index = 0; index < pModel->m_Objects.size(); ++index) {
createNodes(pModel, pModel->m_Objects[index], pScene->mRootNode, pScene, MeshArray);
@ -201,7 +197,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
// Create mesh pointer buffer for this scene
if (pScene->mNumMeshes > 0) {
pScene->mMeshes = new aiMesh*[MeshArray.size()];
pScene->mMeshes = new aiMesh *[MeshArray.size()];
for (size_t index = 0; index < MeshArray.size(); ++index) {
pScene->mMeshes[index] = MeshArray[index];
}
@ -209,34 +205,34 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
// Create all materials
createMaterials(pModel, pScene);
}else {
if (pModel->m_Vertices.empty()){
return;
}
} else {
if (pModel->m_Vertices.empty()) {
return;
}
std::unique_ptr<aiMesh> mesh( new aiMesh );
std::unique_ptr<aiMesh> mesh(new aiMesh);
mesh->mPrimitiveTypes = aiPrimitiveType_POINT;
unsigned int n = (unsigned int)pModel->m_Vertices.size();
mesh->mNumVertices = n;
mesh->mVertices = new aiVector3D[n];
memcpy(mesh->mVertices, pModel->m_Vertices.data(), n*sizeof(aiVector3D) );
memcpy(mesh->mVertices, pModel->m_Vertices.data(), n * sizeof(aiVector3D));
if ( !pModel->m_Normals.empty() ) {
if (!pModel->m_Normals.empty()) {
mesh->mNormals = new aiVector3D[n];
if (pModel->m_Normals.size() < n) {
throw DeadlyImportError("OBJ: vertex normal index out of range");
}
memcpy(mesh->mNormals, pModel->m_Normals.data(), n*sizeof(aiVector3D));
memcpy(mesh->mNormals, pModel->m_Normals.data(), n * sizeof(aiVector3D));
}
if ( !pModel->m_VertexColors.empty() ){
if (!pModel->m_VertexColors.empty()) {
mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
for (unsigned int i = 0; i < n; ++i) {
if (i < pModel->m_VertexColors.size() ) {
const aiVector3D& color = pModel->m_VertexColors[i];
if (i < pModel->m_VertexColors.size()) {
const aiVector3D &color = pModel->m_VertexColors[i];
mesh->mColors[0][i] = aiColor4D(color.x, color.y, color.z, 1.0);
}else {
} else {
throw DeadlyImportError("OBJ: vertex color index out of range");
}
}
@ -245,7 +241,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int[1];
pScene->mRootNode->mMeshes[0] = 0;
pScene->mMeshes = new aiMesh*[1];
pScene->mMeshes = new aiMesh *[1];
pScene->mNumMeshes = 1;
pScene->mMeshes[0] = mesh.release();
}
@ -253,12 +249,11 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
// ------------------------------------------------------------------------------------------------
// Creates all nodes of the model
aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject,
aiNode *pParent, aiScene* pScene,
std::vector<aiMesh*> &MeshArray )
{
ai_assert( NULL != pModel );
if( NULL == pObject ) {
aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject,
aiNode *pParent, aiScene *pScene,
std::vector<aiMesh *> &MeshArray) {
ai_assert(NULL != pModel);
if (NULL == pObject) {
return NULL;
}
@ -269,15 +264,15 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
pNode->mName = pObject->m_strObjName;
// If we have a parent node, store it
ai_assert( NULL != pParent );
appendChildToParentNode( pParent, pNode );
ai_assert(NULL != pParent);
appendChildToParentNode(pParent, pNode);
for ( size_t i=0; i< pObject->m_Meshes.size(); ++i ) {
unsigned int meshId = pObject->m_Meshes[ i ];
aiMesh *pMesh = createTopology( pModel, pObject, meshId );
if( pMesh ) {
for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
unsigned int meshId = pObject->m_Meshes[i];
aiMesh *pMesh = createTopology(pModel, pObject, meshId);
if (pMesh) {
if (pMesh->mNumFaces > 0) {
MeshArray.push_back( pMesh );
MeshArray.push_back(pMesh);
} else {
delete pMesh;
}
@ -285,22 +280,22 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
}
// Create all nodes from the sub-objects stored in the current object
if ( !pObject->m_SubObjects.empty() ) {
if (!pObject->m_SubObjects.empty()) {
size_t numChilds = pObject->m_SubObjects.size();
pNode->mNumChildren = static_cast<unsigned int>( numChilds );
pNode->mChildren = new aiNode*[ numChilds ];
pNode->mNumChildren = static_cast<unsigned int>(numChilds);
pNode->mChildren = new aiNode *[numChilds];
pNode->mNumMeshes = 1;
pNode->mMeshes = new unsigned int[ 1 ];
pNode->mMeshes = new unsigned int[1];
}
// Set mesh instances into scene- and node-instances
const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
if ( meshSizeDiff > 0 ) {
pNode->mMeshes = new unsigned int[ meshSizeDiff ];
pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
const size_t meshSizeDiff = MeshArray.size() - oldMeshSize;
if (meshSizeDiff > 0) {
pNode->mMeshes = new unsigned int[meshSizeDiff];
pNode->mNumMeshes = static_cast<unsigned int>(meshSizeDiff);
size_t index = 0;
for (size_t i = oldMeshSize; i < MeshArray.size(); ++i ) {
pNode->mMeshes[ index ] = pScene->mNumMeshes;
for (size_t i = oldMeshSize; i < MeshArray.size(); ++i) {
pNode->mMeshes[index] = pScene->mNumMeshes;
pScene->mNumMeshes++;
++index;
}
@ -311,33 +306,32 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
// ------------------------------------------------------------------------------------------------
// Create topology data
aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData, unsigned int meshIndex ) {
aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, unsigned int meshIndex) {
// Checking preconditions
ai_assert( NULL != pModel );
ai_assert(NULL != pModel);
if( NULL == pData ) {
if (NULL == pData) {
return NULL;
}
// Create faces
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ meshIndex ];
if( !pObjMesh ) {
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[meshIndex];
if (!pObjMesh) {
return NULL;
}
if( pObjMesh->m_Faces.empty() ) {
if (pObjMesh->m_Faces.empty()) {
return NULL;
}
std::unique_ptr<aiMesh> pMesh(new aiMesh);
if( !pObjMesh->m_name.empty() ) {
pMesh->mName.Set( pObjMesh->m_name );
if (!pObjMesh->m_name.empty()) {
pMesh->mName.Set(pObjMesh->m_name);
}
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
{
ObjFile::Face *const inp = pObjMesh->m_Faces[ index ];
ai_assert( NULL != inp );
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
ObjFile::Face *const inp = pObjMesh->m_Faces[index];
ai_assert(NULL != inp);
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
@ -355,40 +349,39 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
}
}
unsigned int uiIdxCount( 0u );
if ( pMesh->mNumFaces > 0 ) {
pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial ) {
unsigned int uiIdxCount(0u);
if (pMesh->mNumFaces > 0) {
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
if (pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial) {
pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
}
unsigned int outIndex( 0 );
unsigned int outIndex(0);
// Copy all data from all stored meshes
for (auto& face : pObjMesh->m_Faces) {
ObjFile::Face* const inp = face;
for (auto &face : pObjMesh->m_Faces) {
ObjFile::Face *const inp = face;
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
for(size_t i = 0; i < inp->m_vertices.size() - 1; ++i) {
aiFace& f = pMesh->mFaces[ outIndex++ ];
for (size_t i = 0; i < inp->m_vertices.size() - 1; ++i) {
aiFace &f = pMesh->mFaces[outIndex++];
uiIdxCount += f.mNumIndices = 2;
f.mIndices = new unsigned int[2];
}
continue;
}
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
for(size_t i = 0; i < inp->m_vertices.size(); ++i) {
aiFace& f = pMesh->mFaces[ outIndex++ ];
} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
for (size_t i = 0; i < inp->m_vertices.size(); ++i) {
aiFace &f = pMesh->mFaces[outIndex++];
uiIdxCount += f.mNumIndices = 1;
f.mIndices = new unsigned int[1];
}
continue;
}
aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
const unsigned int uiNumIndices = (unsigned int) face->m_vertices.size();
uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
aiFace *pFace = &pMesh->mFaces[outIndex++];
const unsigned int uiNumIndices = (unsigned int)face->m_vertices.size();
uiIdxCount += pFace->mNumIndices = (unsigned int)uiNumIndices;
if (pFace->mNumIndices > 0) {
pFace->mIndices = new unsigned int[ uiNumIndices ];
pFace->mIndices = new unsigned int[uiNumIndices];
}
}
}
@ -401,46 +394,45 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
// ------------------------------------------------------------------------------------------------
// Creates a vertex array
void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
const ObjFile::Object* pCurrentObject,
unsigned int uiMeshIndex,
aiMesh* pMesh,
unsigned int numIndices) {
void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
const ObjFile::Object *pCurrentObject,
unsigned int uiMeshIndex,
aiMesh *pMesh,
unsigned int numIndices) {
// Checking preconditions
ai_assert( NULL != pCurrentObject );
ai_assert(NULL != pCurrentObject);
// Break, if no faces are stored in object
if ( pCurrentObject->m_Meshes.empty() )
if (pCurrentObject->m_Meshes.empty())
return;
// Get current mesh
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1 ) {
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[uiMeshIndex];
if (NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1) {
return;
}
// Copy vertices of this mesh instance
pMesh->mNumVertices = numIndices;
if (pMesh->mNumVertices == 0) {
throw DeadlyImportError( "OBJ: no vertices" );
throw DeadlyImportError("OBJ: no vertices");
} else if (pMesh->mNumVertices > AI_MAX_VERTICES) {
throw DeadlyImportError( "OBJ: Too many vertices" );
throw DeadlyImportError("OBJ: Too many vertices");
}
pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
// Allocate buffer for normal vectors
if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
if (!pModel->m_Normals.empty() && pObjMesh->m_hasNormals)
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
// Allocate buffer for vertex-color vectors
if ( !pModel->m_VertexColors.empty() )
pMesh->mColors[0] = new aiColor4D[ pMesh->mNumVertices ];
if (!pModel->m_VertexColors.empty())
pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
// Allocate buffer for texture coordinates
if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
{
pMesh->mNumUVComponents[ 0 ] = pModel->m_TextureCoordDim;
pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
if (!pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0]) {
pMesh->mNumUVComponents[0] = pModel->m_TextureCoordDim;
pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices];
}
// Copy vertices, normals and textures into aiMesh instance
@ -448,60 +440,52 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
unsigned int newIndex = 0, outIndex = 0;
for (auto sourceFace : pObjMesh->m_Faces) {
// Copy all index arrays
for (size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < sourceFace->m_vertices.size(); vertexIndex++ ) {
const unsigned int vertex = sourceFace->m_vertices.at(vertexIndex );
if ( vertex >= pModel->m_Vertices.size() ) {
throw DeadlyImportError( "OBJ: vertex index out of range" );
for (size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < sourceFace->m_vertices.size(); vertexIndex++) {
const unsigned int vertex = sourceFace->m_vertices.at(vertexIndex);
if (vertex >= pModel->m_Vertices.size()) {
throw DeadlyImportError("OBJ: vertex index out of range");
}
if ( pMesh->mNumVertices <= newIndex ) {
if (pMesh->mNumVertices <= newIndex) {
throw DeadlyImportError("OBJ: bad vertex index");
}
pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
pMesh->mVertices[newIndex] = pModel->m_Vertices[vertex];
// Copy all normals
if ( normalsok && !pModel->m_Normals.empty() && vertexIndex < sourceFace->m_normals.size()) {
const unsigned int normal = sourceFace->m_normals.at(vertexIndex );
if ( normal >= pModel->m_Normals.size() )
{
if (normalsok && !pModel->m_Normals.empty() && vertexIndex < sourceFace->m_normals.size()) {
const unsigned int normal = sourceFace->m_normals.at(vertexIndex);
if (normal >= pModel->m_Normals.size()) {
normalsok = false;
}
else
{
pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
} else {
pMesh->mNormals[newIndex] = pModel->m_Normals[normal];
}
}
// Copy all vertex colors
if ( !pModel->m_VertexColors.empty())
{
const aiVector3D& color = pModel->m_VertexColors[ vertex ];
pMesh->mColors[0][ newIndex ] = aiColor4D(color.x, color.y, color.z, 1.0);
if (!pModel->m_VertexColors.empty()) {
const aiVector3D &color = pModel->m_VertexColors[vertex];
pMesh->mColors[0][newIndex] = aiColor4D(color.x, color.y, color.z, 1.0);
}
// Copy all texture coordinates
if ( uvok && !pModel->m_TextureCoord.empty() && vertexIndex < sourceFace->m_texturCoords.size())
{
const unsigned int tex = sourceFace->m_texturCoords.at(vertexIndex );
if (uvok && !pModel->m_TextureCoord.empty() && vertexIndex < sourceFace->m_texturCoords.size()) {
const unsigned int tex = sourceFace->m_texturCoords.at(vertexIndex);
if ( tex >= pModel->m_TextureCoord.size() )
{
if (tex >= pModel->m_TextureCoord.size()) {
uvok = false;
}
else
{
const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
} else {
const aiVector3D &coord3d = pModel->m_TextureCoord[tex];
pMesh->mTextureCoords[0][newIndex] = aiVector3D(coord3d.x, coord3d.y, coord3d.z);
}
}
// Get destination face
aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
aiFace *pDestFace = &pMesh->mFaces[outIndex];
const bool last = (vertexIndex == sourceFace->m_vertices.size() - 1 );
const bool last = (vertexIndex == sourceFace->m_vertices.size() - 1);
if (sourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) {
pDestFace->mIndices[ outVertexIndex ] = newIndex;
pDestFace->mIndices[outVertexIndex] = newIndex;
outVertexIndex++;
}
@ -511,18 +495,18 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
} else if (sourceFace->m_PrimitiveType == aiPrimitiveType_LINE) {
outVertexIndex = 0;
if(!last)
if (!last)
outIndex++;
if (vertexIndex) {
if(!last) {
pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
if (!last) {
pMesh->mVertices[newIndex + 1] = pMesh->mVertices[newIndex];
if (!sourceFace->m_normals.empty() && !pModel->m_Normals.empty()) {
pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
pMesh->mNormals[newIndex + 1] = pMesh->mNormals[newIndex];
}
if ( !pModel->m_TextureCoord.empty() ) {
for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
if (!pModel->m_TextureCoord.empty()) {
for (size_t i = 0; i < pMesh->GetNumUVChannels(); i++) {
pMesh->mTextureCoords[i][newIndex + 1] = pMesh->mTextureCoords[i][newIndex];
}
}
++newIndex;
@ -530,40 +514,34 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
pDestFace[-1].mIndices[1] = newIndex;
}
}
else if (last) {
} else if (last) {
outIndex++;
}
++newIndex;
}
}
if (!normalsok)
{
delete [] pMesh->mNormals;
if (!normalsok) {
delete[] pMesh->mNormals;
pMesh->mNormals = nullptr;
}
if (!uvok)
{
delete [] pMesh->mTextureCoords[0];
if (!uvok) {
delete[] pMesh->mTextureCoords[0];
pMesh->mTextureCoords[0] = nullptr;
}
}
// ------------------------------------------------------------------------------------------------
// Counts all stored meshes
void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes)
{
void ObjFileImporter::countObjects(const std::vector<ObjFile::Object *> &rObjects, int &iNumMeshes) {
iNumMeshes = 0;
if ( rObjects.empty() )
if (rObjects.empty())
return;
iNumMeshes += static_cast<unsigned int>( rObjects.size() );
for (auto object: rObjects)
{
if (!object->m_SubObjects.empty())
{
iNumMeshes += static_cast<unsigned int>(rObjects.size());
for (auto object : rObjects) {
if (!object->m_SubObjects.empty()) {
countObjects(object->m_SubObjects, iNumMeshes);
}
}
@ -571,209 +549,187 @@ void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects
// ------------------------------------------------------------------------------------------------
// Add clamp mode property to material if necessary
void ObjFileImporter::addTextureMappingModeProperty( aiMaterial* mat, aiTextureType type, int clampMode, int index) {
if ( nullptr == mat ) {
void ObjFileImporter::addTextureMappingModeProperty(aiMaterial *mat, aiTextureType type, int clampMode, int index) {
if (nullptr == mat) {
return;
}
mat->AddProperty<int>( &clampMode, 1, AI_MATKEY_MAPPINGMODE_U( type, index ) );
mat->AddProperty<int>( &clampMode, 1, AI_MATKEY_MAPPINGMODE_V( type, index ) );
mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_U(type, index));
mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_V(type, index));
}
// ------------------------------------------------------------------------------------------------
// Creates the material
void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene ) {
if ( NULL == pScene ) {
void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pScene) {
if (NULL == pScene) {
return;
}
const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
const unsigned int numMaterials = (unsigned int)pModel->m_MaterialLib.size();
pScene->mNumMaterials = 0;
if ( pModel->m_MaterialLib.empty() ) {
if (pModel->m_MaterialLib.empty()) {
ASSIMP_LOG_DEBUG("OBJ: no materials specified");
return;
}
pScene->mMaterials = new aiMaterial*[ numMaterials ];
for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
{
pScene->mMaterials = new aiMaterial *[numMaterials];
for (unsigned int matIndex = 0; matIndex < numMaterials; matIndex++) {
// Store material name
std::map<std::string, ObjFile::Material*>::const_iterator it;
it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
std::map<std::string, ObjFile::Material *>::const_iterator it;
it = pModel->m_MaterialMap.find(pModel->m_MaterialLib[matIndex]);
// No material found, use the default material
if ( pModel->m_MaterialMap.end() == it )
if (pModel->m_MaterialMap.end() == it)
continue;
aiMaterial* mat = new aiMaterial;
aiMaterial *mat = new aiMaterial;
ObjFile::Material *pCurrentMaterial = (*it).second;
mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
mat->AddProperty(&pCurrentMaterial->MaterialName, AI_MATKEY_NAME);
// convert illumination model
int sm = 0;
switch (pCurrentMaterial->illumination_model)
{
case 0:
sm = aiShadingMode_NoShading;
break;
case 1:
sm = aiShadingMode_Gouraud;
break;
case 2:
sm = aiShadingMode_Phong;
break;
default:
sm = aiShadingMode_Gouraud;
ASSIMP_LOG_ERROR("OBJ: unexpected illumination model (0-2 recognized)");
switch (pCurrentMaterial->illumination_model) {
case 0:
sm = aiShadingMode_NoShading;
break;
case 1:
sm = aiShadingMode_Gouraud;
break;
case 2:
sm = aiShadingMode_Phong;
break;
default:
sm = aiShadingMode_Gouraud;
ASSIMP_LOG_ERROR("OBJ: unexpected illumination model (0-2 recognized)");
}
mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL);
mat->AddProperty<int>(&sm, 1, AI_MATKEY_SHADING_MODEL);
// Adding material colors
mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
mat->AddProperty( &pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE );
mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY );
mat->AddProperty( &pCurrentMaterial->transparent,1,AI_MATKEY_COLOR_TRANSPARENT);
mat->AddProperty(&pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty(&pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty(&pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR);
mat->AddProperty(&pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE);
mat->AddProperty(&pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS);
mat->AddProperty(&pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY);
mat->AddProperty(&pCurrentMaterial->transparent, 1, AI_MATKEY_COLOR_TRANSPARENT);
// Adding refraction index
mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
mat->AddProperty(&pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI);
// Adding textures
const int uvwIndex = 0;
if ( 0 != pCurrentMaterial->texture.length )
{
mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_DIFFUSE(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType])
{
if (0 != pCurrentMaterial->texture.length) {
mat->AddProperty(&pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_DIFFUSE(0));
if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType]) {
addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE);
}
}
if ( 0 != pCurrentMaterial->textureAmbient.length )
{
mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_AMBIENT(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType])
{
if (0 != pCurrentMaterial->textureAmbient.length) {
mat->AddProperty(&pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_AMBIENT(0));
if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType]) {
addTextureMappingModeProperty(mat, aiTextureType_AMBIENT);
}
}
if ( 0 != pCurrentMaterial->textureEmissive.length )
{
mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_EMISSIVE(0) );
if (0 != pCurrentMaterial->textureEmissive.length) {
mat->AddProperty(&pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_EMISSIVE(0));
}
if ( 0 != pCurrentMaterial->textureSpecular.length )
{
mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_SPECULAR(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType])
{
if (0 != pCurrentMaterial->textureSpecular.length) {
mat->AddProperty(&pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_SPECULAR(0));
if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType]) {
addTextureMappingModeProperty(mat, aiTextureType_SPECULAR);
}
}
if ( 0 != pCurrentMaterial->textureBump.length )
{
mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_HEIGHT(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType])
{
if (0 != pCurrentMaterial->textureBump.length) {
mat->AddProperty(&pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_HEIGHT(0));
if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType]) {
addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
}
}
if ( 0 != pCurrentMaterial->textureNormal.length )
{
mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_NORMALS(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType])
{
if (0 != pCurrentMaterial->textureNormal.length) {
mat->AddProperty(&pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_NORMALS(0));
if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType]) {
addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
}
}
if( 0 != pCurrentMaterial->textureReflection[0].length )
{
if (0 != pCurrentMaterial->textureReflection[0].length) {
ObjFile::Material::TextureType type = 0 != pCurrentMaterial->textureReflection[1].length ?
ObjFile::Material::TextureReflectionCubeTopType :
ObjFile::Material::TextureReflectionSphereType;
ObjFile::Material::TextureReflectionCubeTopType :
ObjFile::Material::TextureReflectionSphereType;
unsigned count = type == ObjFile::Material::TextureReflectionSphereType ? 1 : 6;
for( unsigned i = 0; i < count; i++ )
{
for (unsigned i = 0; i < count; i++) {
mat->AddProperty(&pCurrentMaterial->textureReflection[i], AI_MATKEY_TEXTURE_REFLECTION(i));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_REFLECTION(i) );
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_REFLECTION(i));
if(pCurrentMaterial->clamp[type])
if (pCurrentMaterial->clamp[type])
addTextureMappingModeProperty(mat, aiTextureType_REFLECTION, 1, i);
}
}
if ( 0 != pCurrentMaterial->textureDisp.length )
{
mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_DISPLACEMENT(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType])
{
if (0 != pCurrentMaterial->textureDisp.length) {
mat->AddProperty(&pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_DISPLACEMENT(0));
if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType]) {
addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT);
}
}
if ( 0 != pCurrentMaterial->textureOpacity.length )
{
mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_OPACITY(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType])
{
if (0 != pCurrentMaterial->textureOpacity.length) {
mat->AddProperty(&pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_OPACITY(0));
if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType]) {
addTextureMappingModeProperty(mat, aiTextureType_OPACITY);
}
}
if ( 0 != pCurrentMaterial->textureSpecularity.length )
{
mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_SHININESS(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType])
{
if (0 != pCurrentMaterial->textureSpecularity.length) {
mat->AddProperty(&pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_SHININESS(0));
if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType]) {
addTextureMappingModeProperty(mat, aiTextureType_SHININESS);
}
}
// Store material property info in material array in scene
pScene->mMaterials[ pScene->mNumMaterials ] = mat;
pScene->mMaterials[pScene->mNumMaterials] = mat;
pScene->mNumMaterials++;
}
// Test number of created materials.
ai_assert( pScene->mNumMaterials == numMaterials );
ai_assert(pScene->mNumMaterials == numMaterials);
}
// ------------------------------------------------------------------------------------------------
// Appends this node to the parent node
void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
{
void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) {
// Checking preconditions
ai_assert( NULL != pParent );
ai_assert( NULL != pChild );
ai_assert(NULL != pParent);
ai_assert(NULL != pChild);
// Assign parent to child
pChild->mParent = pParent;
// Copy node instances into parent node
pParent->mNumChildren++;
pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
pParent->mChildren[pParent->mNumChildren - 1] = pChild;
}
// ------------------------------------------------------------------------------------------------
} // Namespace Assimp
} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -52,9 +51,9 @@ struct aiNode;
namespace Assimp {
namespace ObjFile {
struct Object;
struct Model;
}
struct Object;
struct Model;
} // namespace ObjFile
// ------------------------------------------------------------------------------------------------
/// \class ObjFileImporter
@ -71,38 +70,38 @@ public:
public:
/// \brief Returns whether the class can handle the format of the given file.
/// \remark 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;
private:
//! \brief Appends the supported extension.
const aiImporterDesc* GetInfo () const;
const aiImporterDesc *GetInfo() const;
//! \brief File import implementation.
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
//! \brief Create the data from imported content.
void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene);
void CreateDataFromImport(const ObjFile::Model *pModel, aiScene *pScene);
//! \brief Creates all nodes stored in imported content.
aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
aiNode *createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pData,
aiNode *pParent, aiScene *pScene, std::vector<aiMesh *> &MeshArray);
//! \brief Creates topology data like faces and meshes for the geometry.
aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
unsigned int uiMeshIndex );
aiMesh *createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData,
unsigned int uiMeshIndex);
//! \brief Creates vertices from model.
void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
unsigned int uiMeshIndex, aiMesh* pMesh, unsigned int numIndices );
void createVertexArray(const ObjFile::Model *pModel, const ObjFile::Object *pCurrentObject,
unsigned int uiMeshIndex, aiMesh *pMesh, unsigned int numIndices);
//! \brief Object counter helper method.
void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes);
void countObjects(const std::vector<ObjFile::Object *> &rObjects, int &iNumMeshes);
//! \brief Material creation.
void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
void createMaterials(const ObjFile::Model *pModel, aiScene *pScene);
/// @brief Adds special property for the used texture mapping mode of the model.
void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1, int index = 0);
void addTextureMappingModeProperty(aiMaterial *mat, aiTextureType type, int clampMode = 1, int index = 0);
//! \brief Appends a child node to a parent node and updates the data structures.
void appendChildToParentNode(aiNode *pParent, aiNode *pChild);

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -41,214 +39,177 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
#include <stdlib.h>
#include "ObjFileMtlImporter.h"
#include "ObjTools.h"
#include "ObjFileData.h"
#include <assimp/fast_atof.h>
#include "ObjTools.h"
#include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h>
#include <assimp/material.h>
#include <stdlib.h>
#include <assimp/DefaultLogger.hpp>
namespace Assimp {
namespace Assimp {
// Material specific token (case insensitive compare)
static const std::string DiffuseTexture = "map_Kd";
static const std::string AmbientTexture = "map_Ka";
static const std::string SpecularTexture = "map_Ks";
static const std::string OpacityTexture = "map_d";
static const std::string EmissiveTexture1 = "map_emissive";
static const std::string EmissiveTexture2 = "map_Ke";
static const std::string BumpTexture1 = "map_bump";
static const std::string BumpTexture2 = "bump";
static const std::string NormalTexture = "map_Kn";
static const std::string ReflectionTexture = "refl";
static const std::string DiffuseTexture = "map_Kd";
static const std::string AmbientTexture = "map_Ka";
static const std::string SpecularTexture = "map_Ks";
static const std::string OpacityTexture = "map_d";
static const std::string EmissiveTexture1 = "map_emissive";
static const std::string EmissiveTexture2 = "map_Ke";
static const std::string BumpTexture1 = "map_bump";
static const std::string BumpTexture2 = "bump";
static const std::string NormalTexture = "map_Kn";
static const std::string ReflectionTexture = "refl";
static const std::string DisplacementTexture1 = "map_disp";
static const std::string DisplacementTexture2 = "disp";
static const std::string SpecularityTexture = "map_ns";
static const std::string SpecularityTexture = "map_ns";
// texture option specific token
static const std::string BlendUOption = "-blendu";
static const std::string BlendVOption = "-blendv";
static const std::string BoostOption = "-boost";
static const std::string ModifyMapOption = "-mm";
static const std::string OffsetOption = "-o";
static const std::string ScaleOption = "-s";
static const std::string TurbulenceOption = "-t";
static const std::string ResolutionOption = "-texres";
static const std::string ClampOption = "-clamp";
static const std::string BumpOption = "-bm";
static const std::string ChannelOption = "-imfchan";
static const std::string TypeOption = "-type";
static const std::string BlendUOption = "-blendu";
static const std::string BlendVOption = "-blendv";
static const std::string BoostOption = "-boost";
static const std::string ModifyMapOption = "-mm";
static const std::string OffsetOption = "-o";
static const std::string ScaleOption = "-s";
static const std::string TurbulenceOption = "-t";
static const std::string ResolutionOption = "-texres";
static const std::string ClampOption = "-clamp";
static const std::string BumpOption = "-bm";
static const std::string ChannelOption = "-imfchan";
static const std::string TypeOption = "-type";
// -------------------------------------------------------------------
// Constructor
ObjFileMtlImporter::ObjFileMtlImporter( std::vector<char> &buffer,
const std::string &,
ObjFile::Model *pModel ) :
m_DataIt( buffer.begin() ),
m_DataItEnd( buffer.end() ),
m_pModel( pModel ),
m_uiLine( 0 )
{
ai_assert( NULL != m_pModel );
if ( NULL == m_pModel->m_pDefaultMaterial )
{
ObjFileMtlImporter::ObjFileMtlImporter(std::vector<char> &buffer,
const std::string &,
ObjFile::Model *pModel) :
m_DataIt(buffer.begin()),
m_DataItEnd(buffer.end()),
m_pModel(pModel),
m_uiLine(0),
m_buffer() {
ai_assert(nullptr != m_pModel);
m_buffer.resize(BUFFERSIZE);
std::fill(m_buffer.begin(), m_buffer.end(), '\0');
if (nullptr == m_pModel->m_pDefaultMaterial) {
m_pModel->m_pDefaultMaterial = new ObjFile::Material;
m_pModel->m_pDefaultMaterial->MaterialName.Set( "default" );
m_pModel->m_pDefaultMaterial->MaterialName.Set("default");
}
load();
}
// -------------------------------------------------------------------
// Destructor
ObjFileMtlImporter::~ObjFileMtlImporter()
{
ObjFileMtlImporter::~ObjFileMtlImporter() {
// empty
}
// -------------------------------------------------------------------
// Private copy constructor
ObjFileMtlImporter::ObjFileMtlImporter(const ObjFileMtlImporter & )
{
// empty
}
// -------------------------------------------------------------------
// Private copy constructor
ObjFileMtlImporter &ObjFileMtlImporter::operator = ( const ObjFileMtlImporter & )
{
return *this;
}
// -------------------------------------------------------------------
// Loads the material description
void ObjFileMtlImporter::load()
{
if ( m_DataIt == m_DataItEnd )
void ObjFileMtlImporter::load() {
if (m_DataIt == m_DataItEnd)
return;
while ( m_DataIt != m_DataItEnd )
{
switch (*m_DataIt)
{
case 'k':
case 'K':
{
while (m_DataIt != m_DataItEnd) {
switch (*m_DataIt) {
case 'k':
case 'K': {
++m_DataIt;
if (*m_DataIt == 'a') // Ambient color
{
++m_DataIt;
getColorRGBA( &m_pModel->m_pCurrentMaterial->ambient );
}
else if (*m_DataIt == 'd') // Diffuse color
getColorRGBA(&m_pModel->m_pCurrentMaterial->ambient);
} else if (*m_DataIt == 'd') // Diffuse color
{
++m_DataIt;
getColorRGBA( &m_pModel->m_pCurrentMaterial->diffuse );
}
else if (*m_DataIt == 's')
{
getColorRGBA(&m_pModel->m_pCurrentMaterial->diffuse);
} else if (*m_DataIt == 's') {
++m_DataIt;
getColorRGBA( &m_pModel->m_pCurrentMaterial->specular );
}
else if (*m_DataIt == 'e')
{
getColorRGBA(&m_pModel->m_pCurrentMaterial->specular);
} else if (*m_DataIt == 'e') {
++m_DataIt;
getColorRGBA( &m_pModel->m_pCurrentMaterial->emissive );
getColorRGBA(&m_pModel->m_pCurrentMaterial->emissive);
}
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
case 'T':
{
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
case 'T': {
++m_DataIt;
if (*m_DataIt == 'f') // Material transmission
{
++m_DataIt;
getColorRGBA( &m_pModel->m_pCurrentMaterial->transparent);
getColorRGBA(&m_pModel->m_pCurrentMaterial->transparent);
}
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
case 'd':
{
if( *(m_DataIt+1) == 'i' && *( m_DataIt + 2 ) == 's' && *( m_DataIt + 3 ) == 'p' ) {
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
case 'd': {
if (*(m_DataIt + 1) == 'i' && *(m_DataIt + 2) == 's' && *(m_DataIt + 3) == 'p') {
// A displacement map
getTexture();
} else {
// Alpha value
++m_DataIt;
getFloatValue( m_pModel->m_pCurrentMaterial->alpha );
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
getFloatValue(m_pModel->m_pCurrentMaterial->alpha);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
}
}
break;
} break;
case 'N':
case 'n':
{
case 'N':
case 'n': {
++m_DataIt;
switch(*m_DataIt)
{
case 's': // Specular exponent
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
break;
case 'i': // Index Of refraction
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->ior);
break;
case 'e': // New material
createMaterial();
break;
switch (*m_DataIt) {
case 's': // Specular exponent
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
break;
case 'i': // Index Of refraction
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->ior);
break;
case 'e': // New material
createMaterial();
break;
}
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
case 'm': // Texture
case 'b': // quick'n'dirty - for 'bump' sections
case 'r': // quick'n'dirty - for 'refl' sections
case 'm': // Texture
case 'b': // quick'n'dirty - for 'bump' sections
case 'r': // quick'n'dirty - for 'refl' sections
{
getTexture();
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
case 'i': // Illumination model
case 'i': // Illumination model
{
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
getIlluminationModel( m_pModel->m_pCurrentMaterial->illumination_model );
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
getIlluminationModel(m_pModel->m_pCurrentMaterial->illumination_model);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
default:
{
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
default: {
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
}
}
}
// -------------------------------------------------------------------
// Loads a color definition
void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor )
{
ai_assert( NULL != pColor );
void ObjFileMtlImporter::getColorRGBA(aiColor3D *pColor) {
ai_assert(NULL != pColor);
ai_real r( 0.0 ), g( 0.0 ), b( 0.0 );
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
ai_real r(0.0), g(0.0), b(0.0);
m_DataIt = getFloat<DataArrayIt>(m_DataIt, m_DataItEnd, r);
pColor->r = r;
// we have to check if color is default 0 with only one token
if( !IsLineEnd( *m_DataIt ) ) {
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
if (!IsLineEnd(*m_DataIt)) {
m_DataIt = getFloat<DataArrayIt>(m_DataIt, m_DataItEnd, g);
m_DataIt = getFloat<DataArrayIt>(m_DataIt, m_DataItEnd, b);
}
pColor->g = g;
pColor->b = b;
@ -256,34 +217,31 @@ void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor )
// -------------------------------------------------------------------
// Loads the kind of illumination model.
void ObjFileMtlImporter::getIlluminationModel( int &illum_model )
{
m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE );
illum_model = atoi(m_buffer);
void ObjFileMtlImporter::getIlluminationModel(int &illum_model) {
m_DataIt = CopyNextWord<DataArrayIt>(m_DataIt, m_DataItEnd, &m_buffer[0], BUFFERSIZE);
illum_model = atoi(&m_buffer[0]);
}
// -------------------------------------------------------------------
// Loads a single float value.
void ObjFileMtlImporter::getFloatValue( ai_real &value )
{
m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE );
value = (ai_real) fast_atof(m_buffer);
void ObjFileMtlImporter::getFloatValue(ai_real &value) {
m_DataIt = CopyNextWord<DataArrayIt>(m_DataIt, m_DataItEnd, &m_buffer[0], BUFFERSIZE);
value = (ai_real)fast_atof(&m_buffer[0]);
}
// -------------------------------------------------------------------
// Creates a material from loaded data.
void ObjFileMtlImporter::createMaterial()
{
void ObjFileMtlImporter::createMaterial() {
std::string line;
while( !IsLineEnd( *m_DataIt ) ) {
while (!IsLineEnd(*m_DataIt)) {
line += *m_DataIt;
++m_DataIt;
}
std::vector<std::string> token;
const unsigned int numToken = tokenize<std::string>( line, token, " \t" );
const unsigned int numToken = tokenize<std::string>(line, token, " \t");
std::string name;
if ( numToken == 1 ) {
if (numToken == 1) {
name = AI_DEFAULT_MATERIAL_NAME;
} else {
// skip newmtl and all following white spaces
@ -296,13 +254,13 @@ void ObjFileMtlImporter::createMaterial()
name = trim_whitespaces(name);
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( name );
if ( m_pModel->m_MaterialMap.end() == it) {
std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->m_MaterialMap.find(name);
if (m_pModel->m_MaterialMap.end() == it) {
// New Material created
m_pModel->m_pCurrentMaterial = new ObjFile::Material();
m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
m_pModel->m_MaterialLib.push_back( name );
m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
m_pModel->m_pCurrentMaterial->MaterialName.Set(name);
m_pModel->m_MaterialLib.push_back(name);
m_pModel->m_MaterialMap[name] = m_pModel->m_pCurrentMaterial;
if (m_pModel->m_pCurrentMesh) {
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->m_MaterialLib.size() - 1);
@ -316,52 +274,52 @@ void ObjFileMtlImporter::createMaterial()
// -------------------------------------------------------------------
// Gets a texture name from data.
void ObjFileMtlImporter::getTexture() {
aiString *out( NULL );
aiString *out(NULL);
int clampIndex = -1;
const char *pPtr( &(*m_DataIt) );
if ( !ASSIMP_strincmp( pPtr, DiffuseTexture.c_str(), static_cast<unsigned int>(DiffuseTexture.size()) ) ) {
const char *pPtr(&(*m_DataIt));
if (!ASSIMP_strincmp(pPtr, DiffuseTexture.c_str(), static_cast<unsigned int>(DiffuseTexture.size()))) {
// Diffuse texture
out = & m_pModel->m_pCurrentMaterial->texture;
out = &m_pModel->m_pCurrentMaterial->texture;
clampIndex = ObjFile::Material::TextureDiffuseType;
} else if ( !ASSIMP_strincmp( pPtr,AmbientTexture.c_str(), static_cast<unsigned int>(AmbientTexture.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, AmbientTexture.c_str(), static_cast<unsigned int>(AmbientTexture.size()))) {
// Ambient texture
out = & m_pModel->m_pCurrentMaterial->textureAmbient;
out = &m_pModel->m_pCurrentMaterial->textureAmbient;
clampIndex = ObjFile::Material::TextureAmbientType;
} else if ( !ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), static_cast<unsigned int>(SpecularTexture.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, SpecularTexture.c_str(), static_cast<unsigned int>(SpecularTexture.size()))) {
// Specular texture
out = & m_pModel->m_pCurrentMaterial->textureSpecular;
out = &m_pModel->m_pCurrentMaterial->textureSpecular;
clampIndex = ObjFile::Material::TextureSpecularType;
} else if ( !ASSIMP_strincmp( pPtr, DisplacementTexture1.c_str(), static_cast<unsigned int>(DisplacementTexture1.size()) ) ||
!ASSIMP_strincmp( pPtr, DisplacementTexture2.c_str(), static_cast<unsigned int>(DisplacementTexture2.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, DisplacementTexture1.c_str(), static_cast<unsigned int>(DisplacementTexture1.size())) ||
!ASSIMP_strincmp(pPtr, DisplacementTexture2.c_str(), static_cast<unsigned int>(DisplacementTexture2.size()))) {
// Displacement texture
out = &m_pModel->m_pCurrentMaterial->textureDisp;
clampIndex = ObjFile::Material::TextureDispType;
} else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), static_cast<unsigned int>(OpacityTexture.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, OpacityTexture.c_str(), static_cast<unsigned int>(OpacityTexture.size()))) {
// Opacity texture
out = & m_pModel->m_pCurrentMaterial->textureOpacity;
out = &m_pModel->m_pCurrentMaterial->textureOpacity;
clampIndex = ObjFile::Material::TextureOpacityType;
} else if ( !ASSIMP_strincmp( pPtr, EmissiveTexture1.c_str(), static_cast<unsigned int>(EmissiveTexture1.size()) ) ||
!ASSIMP_strincmp( pPtr, EmissiveTexture2.c_str(), static_cast<unsigned int>(EmissiveTexture2.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, EmissiveTexture1.c_str(), static_cast<unsigned int>(EmissiveTexture1.size())) ||
!ASSIMP_strincmp(pPtr, EmissiveTexture2.c_str(), static_cast<unsigned int>(EmissiveTexture2.size()))) {
// Emissive texture
out = & m_pModel->m_pCurrentMaterial->textureEmissive;
out = &m_pModel->m_pCurrentMaterial->textureEmissive;
clampIndex = ObjFile::Material::TextureEmissiveType;
} else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), static_cast<unsigned int>(BumpTexture1.size()) ) ||
!ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), static_cast<unsigned int>(BumpTexture2.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, BumpTexture1.c_str(), static_cast<unsigned int>(BumpTexture1.size())) ||
!ASSIMP_strincmp(pPtr, BumpTexture2.c_str(), static_cast<unsigned int>(BumpTexture2.size()))) {
// Bump texture
out = & m_pModel->m_pCurrentMaterial->textureBump;
out = &m_pModel->m_pCurrentMaterial->textureBump;
clampIndex = ObjFile::Material::TextureBumpType;
} else if ( !ASSIMP_strincmp( pPtr,NormalTexture.c_str(), static_cast<unsigned int>(NormalTexture.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, NormalTexture.c_str(), static_cast<unsigned int>(NormalTexture.size()))) {
// Normal map
out = & m_pModel->m_pCurrentMaterial->textureNormal;
out = &m_pModel->m_pCurrentMaterial->textureNormal;
clampIndex = ObjFile::Material::TextureNormalType;
} else if( !ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), static_cast<unsigned int>(ReflectionTexture.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, ReflectionTexture.c_str(), static_cast<unsigned int>(ReflectionTexture.size()))) {
// Reflection texture(s)
//Do nothing here
return;
} else if ( !ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(SpecularityTexture.size()) ) ) {
} else if (!ASSIMP_strincmp(pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(SpecularityTexture.size()))) {
// Specularity scaling (glossiness)
out = & m_pModel->m_pCurrentMaterial->textureSpecularity;
out = &m_pModel->m_pCurrentMaterial->textureSpecularity;
clampIndex = ObjFile::Material::TextureSpecularityType;
} else {
ASSIMP_LOG_ERROR("OBJ/MTL: Encountered unknown texture type");
@ -373,9 +331,9 @@ void ObjFileMtlImporter::getTexture() {
m_pModel->m_pCurrentMaterial->clamp[clampIndex] = clamp;
std::string texture;
m_DataIt = getName<DataArrayIt>( m_DataIt, m_DataItEnd, texture );
if ( NULL!=out ) {
out->Set( texture );
m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, texture);
if (NULL != out) {
out->Set(texture);
}
}
@ -398,90 +356,57 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
// If there is any more texture option
while (!isEndOfBuffer(m_DataIt, m_DataItEnd) && *m_DataIt == '-')
{
const char *pPtr( &(*m_DataIt) );
while (!isEndOfBuffer(m_DataIt, m_DataItEnd) && *m_DataIt == '-') {
const char *pPtr(&(*m_DataIt));
//skip option key and value
int skipToken = 1;
if (!ASSIMP_strincmp(pPtr, ClampOption.c_str(), static_cast<unsigned int>(ClampOption.size())))
{
if (!ASSIMP_strincmp(pPtr, ClampOption.c_str(), static_cast<unsigned int>(ClampOption.size()))) {
DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
char value[3];
CopyNextWord(it, m_DataItEnd, value, sizeof(value) / sizeof(*value));
if (!ASSIMP_strincmp(value, "on", 2))
{
if (!ASSIMP_strincmp(value, "on", 2)) {
clamp = true;
}
skipToken = 2;
}
else if( !ASSIMP_strincmp( pPtr, TypeOption.c_str(), static_cast<unsigned int>(TypeOption.size()) ) )
{
DataArrayIt it = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
char value[ 12 ];
CopyNextWord( it, m_DataItEnd, value, sizeof( value ) / sizeof( *value ) );
if( !ASSIMP_strincmp( value, "cube_top", 8 ) )
{
} else if (!ASSIMP_strincmp(pPtr, TypeOption.c_str(), static_cast<unsigned int>(TypeOption.size()))) {
DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
char value[12];
CopyNextWord(it, m_DataItEnd, value, sizeof(value) / sizeof(*value));
if (!ASSIMP_strincmp(value, "cube_top", 8)) {
clampIndex = ObjFile::Material::TextureReflectionCubeTopType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[0];
}
else if( !ASSIMP_strincmp( value, "cube_bottom", 11 ) )
{
} else if (!ASSIMP_strincmp(value, "cube_bottom", 11)) {
clampIndex = ObjFile::Material::TextureReflectionCubeBottomType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[1];
}
else if( !ASSIMP_strincmp( value, "cube_front", 10 ) )
{
} else if (!ASSIMP_strincmp(value, "cube_front", 10)) {
clampIndex = ObjFile::Material::TextureReflectionCubeFrontType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[2];
}
else if( !ASSIMP_strincmp( value, "cube_back", 9 ) )
{
} else if (!ASSIMP_strincmp(value, "cube_back", 9)) {
clampIndex = ObjFile::Material::TextureReflectionCubeBackType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[3];
}
else if( !ASSIMP_strincmp( value, "cube_left", 9 ) )
{
} else if (!ASSIMP_strincmp(value, "cube_left", 9)) {
clampIndex = ObjFile::Material::TextureReflectionCubeLeftType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[4];
}
else if( !ASSIMP_strincmp( value, "cube_right", 10 ) )
{
} else if (!ASSIMP_strincmp(value, "cube_right", 10)) {
clampIndex = ObjFile::Material::TextureReflectionCubeRightType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[5];
}
else if( !ASSIMP_strincmp( value, "sphere", 6 ) )
{
} else if (!ASSIMP_strincmp(value, "sphere", 6)) {
clampIndex = ObjFile::Material::TextureReflectionSphereType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[0];
}
skipToken = 2;
}
else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), static_cast<unsigned int>(BlendUOption.size()))
|| !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), static_cast<unsigned int>(BlendVOption.size()))
|| !ASSIMP_strincmp(pPtr, BoostOption.c_str(), static_cast<unsigned int>(BoostOption.size()))
|| !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), static_cast<unsigned int>(ResolutionOption.size()))
|| !ASSIMP_strincmp(pPtr, BumpOption.c_str(), static_cast<unsigned int>(BumpOption.size()))
|| !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), static_cast<unsigned int>(ChannelOption.size())))
{
} else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), static_cast<unsigned int>(BlendUOption.size())) || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), static_cast<unsigned int>(BlendVOption.size())) || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), static_cast<unsigned int>(BoostOption.size())) || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), static_cast<unsigned int>(ResolutionOption.size())) || !ASSIMP_strincmp(pPtr, BumpOption.c_str(), static_cast<unsigned int>(BumpOption.size())) || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), static_cast<unsigned int>(ChannelOption.size()))) {
skipToken = 2;
}
else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), static_cast<unsigned int>(ModifyMapOption.size())))
{
} else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), static_cast<unsigned int>(ModifyMapOption.size()))) {
skipToken = 3;
}
else if ( !ASSIMP_strincmp(pPtr, OffsetOption.c_str(), static_cast<unsigned int>(OffsetOption.size()))
|| !ASSIMP_strincmp(pPtr, ScaleOption.c_str(), static_cast<unsigned int>(ScaleOption.size()))
|| !ASSIMP_strincmp(pPtr, TurbulenceOption.c_str(), static_cast<unsigned int>(TurbulenceOption.size()))
)
{
} else if (!ASSIMP_strincmp(pPtr, OffsetOption.c_str(), static_cast<unsigned int>(OffsetOption.size())) || !ASSIMP_strincmp(pPtr, ScaleOption.c_str(), static_cast<unsigned int>(ScaleOption.size())) || !ASSIMP_strincmp(pPtr, TurbulenceOption.c_str(), static_cast<unsigned int>(TurbulenceOption.size()))) {
skipToken = 4;
}
for (int i = 0; i < skipToken; ++i)
{
for (int i = 0; i < skipToken; ++i) {
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
}
}

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -41,9 +40,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OBJFILEMTLIMPORTER_H_INC
#define OBJFILEMTLIMPORTER_H_INC
#include <vector>
#include <string>
#include <assimp/defs.h>
#include <string>
#include <vector>
struct aiColor3D;
struct aiString;
@ -51,44 +50,41 @@ struct aiString;
namespace Assimp {
namespace ObjFile {
struct Model;
struct Material;
}
struct Model;
struct Material;
} // namespace ObjFile
/**
* @class ObjFileMtlImporter
* @brief Loads the material description from a mtl file.
*/
class ObjFileMtlImporter
{
class ObjFileMtlImporter {
public:
static const size_t BUFFERSIZE = 2048;
typedef std::vector<char> DataArray;
typedef std::vector<char>::iterator DataArrayIt;
typedef std::vector<char>::const_iterator ConstDataArrayIt;
public:
//! \brief Default constructor
ObjFileMtlImporter( std::vector<char> &buffer, const std::string &strAbsPath,
ObjFile::Model *pModel );
//! \brief The class default constructor
ObjFileMtlImporter(std::vector<char> &buffer, const std::string &strAbsPath,
ObjFile::Model *pModel);
//! \brief DEstructor
//! \brief The class destructor
~ObjFileMtlImporter();
ObjFileMtlImporter(const ObjFileMtlImporter &rOther) = delete;
ObjFileMtlImporter &operator=(const ObjFileMtlImporter &rOther) = delete;
private:
/// Copy constructor, empty.
ObjFileMtlImporter(const ObjFileMtlImporter &rOther);
/// \brief Assignment operator, returns only a reference of this instance.
ObjFileMtlImporter &operator = (const ObjFileMtlImporter &rOther);
/// Load the whole material description
void load();
/// Get color data.
void getColorRGBA( aiColor3D *pColor);
void getColorRGBA(aiColor3D *pColor);
/// Get illumination model from loaded data
void getIlluminationModel( int &illum_model );
void getIlluminationModel(int &illum_model);
/// Gets a float value from data.
void getFloatValue( ai_real &value );
void getFloatValue(ai_real &value);
/// Creates a new material from loaded data.
void createMaterial();
/// Get texture name from loaded data.
@ -107,7 +103,7 @@ private:
//! Current line in file
unsigned int m_uiLine;
//! Helper buffer
char m_buffer[BUFFERSIZE];
std::vector<char> m_buffer;
};
// ------------------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -42,24 +41,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OBJ_FILEPARSER_H_INC
#define OBJ_FILEPARSER_H_INC
#include <vector>
#include <string>
#include <map>
#include <memory>
#include <assimp/IOStreamBuffer.h>
#include <assimp/mesh.h>
#include <assimp/vector2.h>
#include <assimp/vector3.h>
#include <assimp/mesh.h>
#include <assimp/IOStreamBuffer.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace Assimp {
namespace ObjFile {
struct Model;
struct Object;
struct Material;
struct Point3;
struct Point2;
}
struct Model;
struct Object;
struct Material;
struct Point3;
struct Point2;
} // namespace ObjFile
class ObjFileImporter;
class IOSystem;
@ -78,31 +77,34 @@ public:
/// @brief The default constructor.
ObjFileParser();
/// @brief Constructor with data array.
ObjFileParser(IOStreamBuffer<char> &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, std::string originalObjFileName);
ObjFileParser(IOStreamBuffer<char> &streamBuffer, const std::string &modelName, IOSystem *io, ProgressHandler *progress, const std::string &originalObjFileName);
/// @brief Destructor
~ObjFileParser();
/// @brief If you want to load in-core data.
void setBuffer( std::vector<char> &buffer );
void setBuffer(std::vector<char> &buffer);
/// @brief Model getter.
ObjFile::Model *GetModel() const;
ObjFileParser(const ObjFileParser&) = delete;
ObjFileParser &operator=(const ObjFileParser& ) = delete;
protected:
/// Parse the loaded file
void parseFile( IOStreamBuffer<char> &streamBuffer );
void parseFile(IOStreamBuffer<char> &streamBuffer);
/// Method to copy the new delimited word in the current line.
void copyNextWord(char *pBuffer, size_t length);
/// Method to copy the new line.
// void copyNextLine(char *pBuffer, size_t length);
// void copyNextLine(char *pBuffer, size_t length);
/// Get the number of components in a line.
size_t getNumComponentsInDataDefinition();
/// Stores the vector
size_t getTexCoordVector( std::vector<aiVector3D> &point3d_array );
size_t getTexCoordVector(std::vector<aiVector3D> &point3d_array);
/// Stores the following 3d vector.
void getVector3( std::vector<aiVector3D> &point3d_array );
void getVector3(std::vector<aiVector3D> &point3d_array);
/// Stores the following homogeneous vector as a 3D vector
void getHomogeneousVector3( std::vector<aiVector3D> &point3d_array );
void getHomogeneousVector3(std::vector<aiVector3D> &point3d_array);
/// Stores the following two 3d vectors on the line.
void getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b );
void getTwoVectors3(std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b);
/// Stores the following 3d vector.
void getVector2(std::vector<aiVector2D> &point2d_array);
/// Stores the following face.
@ -122,23 +124,21 @@ protected:
/// Gets the group number and resolution from file.
void getGroupNumberAndResolution();
/// Returns the index of the material. Is -1 if not material was found.
int getMaterialIndex( const std::string &strMaterialName );
int getMaterialIndex(const std::string &strMaterialName);
/// Parse object name
void getObjectName();
/// Creates a new object.
void createObject( const std::string &strObjectName );
void createObject(const std::string &strObjectName);
/// Creates a new mesh.
void createMesh( const std::string &meshName );
void createMesh(const std::string &meshName);
/// Returns true, if a new mesh instance must be created.
bool needsNewMesh( const std::string &rMaterialName );
bool needsNewMesh(const std::string &rMaterialName);
/// Error report in token
void reportErrorTokenInFace();
private:
// Copy and assignment constructor should be private
// because the class contains pointer to allocated memory
ObjFileParser(const ObjFileParser& rhs);
ObjFileParser& operator=(const ObjFileParser& rhs);
/// Default material name
static const std::string DEFAULT_MATERIAL;
@ -155,11 +155,11 @@ private:
/// Pointer to IO system instance.
IOSystem *m_pIO;
//! Pointer to progress handler
ProgressHandler* m_progress;
ProgressHandler *m_progress;
/// Path to the current model, name of the obj file where the buffer comes from
const std::string m_originalObjFileName;
};
} // Namespace Assimp
} // Namespace Assimp
#endif

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -46,8 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OBJ_TOOLS_H_INC
#define OBJ_TOOLS_H_INC
#include <assimp/fast_atof.h>
#include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h>
#include <vector>
namespace Assimp {
@ -57,17 +56,14 @@ namespace Assimp {
* @param end Iterator with end of buffer.
* @return true, if the end of the buffer is reached.
*/
template<class char_t>
inline bool isEndOfBuffer( char_t it, char_t end ) {
if ( it == end )
{
template <class char_t>
inline bool isEndOfBuffer(char_t it, char_t end) {
if (it == end) {
return true;
}
else
{
} else {
--end;
}
return ( it == end );
return (it == end);
}
/** @brief Returns next word separated by a space
@ -75,14 +71,12 @@ inline bool isEndOfBuffer( char_t it, char_t end ) {
* @param pEnd Pointer to end of buffer
* @return Pointer to next space
*/
template<class Char_T>
inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
{
while ( !isEndOfBuffer( pBuffer, pEnd ) )
{
if ( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) ) {
template <class Char_T>
inline Char_T getNextWord(Char_T pBuffer, Char_T pEnd) {
while (!isEndOfBuffer(pBuffer, pEnd)) {
if (!IsSpaceOrNewLine(*pBuffer) || IsLineEnd(*pBuffer)) {
//if ( *pBuffer != '\\' )
break;
break;
}
pBuffer++;
}
@ -94,16 +88,14 @@ inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
* @param pEnd Pointer to end of buffer
* @return Pointer to next token
*/
template<class Char_T>
inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
{
while ( !isEndOfBuffer( pBuffer, pEnd ) )
{
if( IsSpaceOrNewLine( *pBuffer ) )
template <class Char_T>
inline Char_T getNextToken(Char_T pBuffer, Char_T pEnd) {
while (!isEndOfBuffer(pBuffer, pEnd)) {
if (IsSpaceOrNewLine(*pBuffer))
break;
pBuffer++;
}
return getNextWord( pBuffer, pEnd );
return getNextWord(pBuffer, pEnd);
}
/** @brief Skips a line
@ -112,18 +104,18 @@ inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
* @param uiLine Current line number in format
* @return Current-iterator with new position
*/
template<class char_t>
inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
template <class char_t>
inline char_t skipLine(char_t it, char_t end, unsigned int &uiLine) {
while (!isEndOfBuffer(it, end) && !IsLineEnd(*it)) {
++it;
}
if ( it != end ) {
if (it != end) {
++it;
++uiLine;
}
// fix .. from time to time there are spaces at the beginning of a material line
while ( it != end && ( *it == '\t' || *it == ' ' ) ) {
while (it != end && (*it == '\t' || *it == ' ')) {
++it;
}
@ -137,20 +129,19 @@ inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
* @param name Separated name
* @return Current-iterator with new position
*/
template<class char_t>
inline char_t getName( char_t it, char_t end, std::string &name )
{
template <class char_t>
inline char_t getName(char_t it, char_t end, std::string &name) {
name = "";
if( isEndOfBuffer( it, end ) ) {
if (isEndOfBuffer(it, end)) {
return end;
}
char *pStart = &( *it );
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it )) {
char *pStart = &(*it);
while (!isEndOfBuffer(it, end) && !IsLineEnd(*it)) {
++it;
}
while(IsSpace( *it ) ) {
while (IsSpace(*it)) {
--it;
}
// Get name
@ -158,8 +149,8 @@ inline char_t getName( char_t it, char_t end, std::string &name )
while (&(*it) < pStart) {
++it;
}
std::string strName( pStart, &(*it) );
if ( strName.empty() )
std::string strName(pStart, &(*it));
if (strName.empty())
return it;
else
name = strName;
@ -174,22 +165,19 @@ inline char_t getName( char_t it, char_t end, std::string &name )
* @param name Separated name
* @return Current-iterator with new position
*/
template<class char_t>
inline char_t getNameNoSpace( char_t it, char_t end, std::string &name )
{
template <class char_t>
inline char_t getNameNoSpace(char_t it, char_t end, std::string &name) {
name = "";
if( isEndOfBuffer( it, end ) ) {
if (isEndOfBuffer(it, end)) {
return end;
}
char *pStart = &( *it );
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it )
&& !IsSpaceOrNewLine( *it ) ) {
char *pStart = &(*it);
while (!isEndOfBuffer(it, end) && !IsLineEnd(*it) && !IsSpaceOrNewLine(*it)) {
++it;
}
while( isEndOfBuffer( it, end ) || IsLineEnd( *it )
|| IsSpaceOrNewLine( *it ) ) {
while (isEndOfBuffer(it, end) || IsLineEnd(*it) || IsSpaceOrNewLine(*it)) {
--it;
}
++it;
@ -199,8 +187,8 @@ inline char_t getNameNoSpace( char_t it, char_t end, std::string &name )
while (&(*it) < pStart) {
++it;
}
std::string strName( pStart, &(*it) );
if ( strName.empty() )
std::string strName(pStart, &(*it));
if (strName.empty())
return it;
else
name = strName;
@ -215,20 +203,18 @@ inline char_t getNameNoSpace( char_t it, char_t end, std::string &name )
* @param length Buffer length
* @return Current-iterator with new position
*/
template<class char_t>
inline char_t CopyNextWord( char_t it, char_t end, char *pBuffer, size_t length )
{
template <class char_t>
inline char_t CopyNextWord(char_t it, char_t end, char *pBuffer, size_t length) {
size_t index = 0;
it = getNextWord<char_t>( it, end );
while( !IsSpaceOrNewLine( *it ) && !isEndOfBuffer( it, end ) )
{
pBuffer[index] = *it ;
it = getNextWord<char_t>(it, end);
while (!IsSpaceOrNewLine(*it) && !isEndOfBuffer(it, end)) {
pBuffer[index] = *it;
index++;
if (index == length-1)
if (index == length - 1)
break;
++it;
}
pBuffer[ index ] = '\0';
pBuffer[index] = '\0';
return it;
}
@ -238,13 +224,12 @@ inline char_t CopyNextWord( char_t it, char_t end, char *pBuffer, size_t length
* @param value Separated float value.
* @return Current-iterator with new position
*/
template<class char_t>
inline char_t getFloat( char_t it, char_t end, ai_real &value )
{
template <class char_t>
inline char_t getFloat(char_t it, char_t end, ai_real &value) {
static const size_t BUFFERSIZE = 1024;
char buffer[ BUFFERSIZE ];
it = CopyNextWord<char_t>( it, end, buffer, BUFFERSIZE );
value = (ai_real) fast_atof( buffer );
char buffer[BUFFERSIZE];
it = CopyNextWord<char_t>(it, end, buffer, BUFFERSIZE);
value = (ai_real)fast_atof(buffer);
return it;
}
@ -255,46 +240,45 @@ inline char_t getFloat( char_t it, char_t end, ai_real &value )
* @param delimiters Delimiter for tokenize.
* @return Number of found token.
*/
template<class string_type>
unsigned int tokenize( const string_type& str, std::vector<string_type>& tokens,
const string_type& delimiters )
{
template <class string_type>
unsigned int tokenize(const string_type &str, std::vector<string_type> &tokens,
const string_type &delimiters) {
// Skip delimiters at beginning.
typename string_type::size_type lastPos = str.find_first_not_of( delimiters, 0 );
typename string_type::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
typename string_type::size_type pos = str.find_first_of( delimiters, lastPos );
while ( string_type::npos != pos || string_type::npos != lastPos )
{
typename string_type::size_type pos = str.find_first_of(delimiters, lastPos);
while (string_type::npos != pos || string_type::npos != lastPos) {
// Found a token, add it to the vector.
string_type tmp = str.substr(lastPos, pos - lastPos);
if ( !tmp.empty() && ' ' != tmp[ 0 ] )
tokens.push_back( tmp );
if (!tmp.empty() && ' ' != tmp[0])
tokens.push_back(tmp);
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of( delimiters, pos );
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of( delimiters, lastPos );
pos = str.find_first_of(delimiters, lastPos);
}
return static_cast<unsigned int>( tokens.size() );
return static_cast<unsigned int>(tokens.size());
}
template <class string_type>
string_type trim_whitespaces(string_type str)
{
while (!str.empty() && IsSpace(str[0])) str.erase(0);
while (!str.empty() && IsSpace(str[str.length() - 1])) str.erase(str.length() - 1);
string_type trim_whitespaces(string_type str) {
while (!str.empty() && IsSpace(str[0]))
str.erase(0);
while (!str.empty() && IsSpace(str[str.length() - 1]))
str.erase(str.length() - 1);
return str;
}
template<class T>
bool hasLineEnd( T it, T end ) {
bool hasLineEnd( false );
while ( !isEndOfBuffer( it, end ) ) {
template <class T>
bool hasLineEnd(T it, T end) {
bool hasLineEnd(false);
while (!isEndOfBuffer(it, end)) {
it++;
if ( IsLineEnd( it ) ) {
if (IsLineEnd(it)) {
hasLineEnd = true;
break;
}

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,

View File

@ -206,8 +206,8 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
aiMaterial *material = new aiMaterial();
m_textures.clear();
aiString ts(materialName);
material->AddProperty(&ts, AI_MATKEY_NAME);
aiString matName(materialName);
material->AddProperty(&matName, AI_MATKEY_NAME);
// The stringstream will push words from a line until newline.
// It will also trim whitespace from line start and between words.
@ -279,14 +279,14 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
else if (linePart=="$colormap")
{
ss >> linePart;
aiString ts(linePart);
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
aiString cm(linePart);
material->AddProperty(&cm, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
}
else if (linePart=="$normalmap")
{
ss >> linePart;
aiString ts(linePart);
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
aiString nm(linePart);
material->AddProperty(&nm, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
}
else if (linePart=="$shininess_strength")
{

View File

@ -46,26 +46,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include <assimp/ParsingUtils.h>
#include <functional>
#include <algorithm>
#include <stdint.h>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <functional>
#include <sstream>
namespace Assimp {
namespace Ogre {
/// Returns a lower cased copy of @s.
static AI_FORCE_INLINE
std::string ToLower(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
static AI_FORCE_INLINE std::string ToLower(const std::string &s) {
std::string lower(s);
std::transform(lower.begin(), lower.end(), lower.begin(), Assimp::ToLower<char>);
return lower;
}
/// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
static AI_FORCE_INLINE
bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) {
static AI_FORCE_INLINE bool EndsWith( const std::string &s, const std::string &suffix, bool caseSensitive = true) {
if (s.empty() || suffix.empty()) {
return false;
} else if (s.length() < suffix.length()) {
@ -77,7 +76,7 @@ bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitiv
}
size_t len = suffix.length();
std::string sSuffix = s.substr(s.length()-len, len);
std::string sSuffix = s.substr(s.length() - len, len);
return (ASSIMP_stricmp(sSuffix, suffix) == 0);
}
@ -86,7 +85,8 @@ bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitiv
/// Trim from start
static AI_FORCE_INLINE
std::string &TrimLeft(std::string &s, bool newlines = true) {
std::string &
TrimLeft(std::string &s, bool newlines = true) {
if (!newlines) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
} else {
@ -97,9 +97,10 @@ std::string &TrimLeft(std::string &s, bool newlines = true) {
/// Trim from end
static AI_FORCE_INLINE
std::string &TrimRight(std::string &s, bool newlines = true) {
std::string &
TrimRight(std::string &s, bool newlines = true) {
if (!newlines) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(),s.end());
s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(), s.end());
} else {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
}
@ -108,13 +109,15 @@ std::string &TrimRight(std::string &s, bool newlines = true) {
/// Trim from both ends
static AI_FORCE_INLINE
std::string &Trim(std::string &s, bool newlines = true) {
std::string &
Trim(std::string &s, bool newlines = true) {
return TrimLeft(TrimRight(s, newlines), newlines);
}
/// Skips a line from current @ss position until a newline. Returns the skipped part.
static AI_FORCE_INLINE
std::string SkipLine(std::stringstream &ss) {
std::string
SkipLine(std::stringstream &ss) {
std::string skipped;
getline(ss, skipped);
return skipped;
@ -123,14 +126,15 @@ std::string SkipLine(std::stringstream &ss) {
/// Skips a line and reads next element from @c ss to @c nextElement.
/** @return Skipped line content until newline. */
static AI_FORCE_INLINE
std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
std::string
NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
std::string skipped = SkipLine(ss);
ss >> nextElement;
return skipped;
}
} // Ogre
} // Assimp
} // namespace Ogre
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
#endif // AI_OGREPARSINGUTILS_H_INC

View File

@ -53,140 +53,94 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Define as 1 to get verbose logging.
#define OGRE_XML_SERIALIZER_DEBUG 0
namespace Assimp
{
namespace Ogre
{
namespace Assimp {
namespace Ogre {
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error)
{
if (!error.empty())
{
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error) {
if (!error.empty()) {
throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
}
else
{
} else {
throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
}
}
template<>
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(const char *name) const
{
if (HasAttribute(name))
{
return static_cast<int32_t>(m_reader->getAttributeValueAsInt(name));
}
else
{
ThrowAttibuteError(m_reader, name);
return 0;
}
}
template<>
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(const char *name) const
{
if (HasAttribute(name))
{
/** @note This is hackish. But we are never expecting unsigned values that go outside the
int32_t range. Just monitor for negative numbers and kill the import. */
int32_t temp = ReadAttribute<int32_t>(name);
if (temp >= 0)
{
return static_cast<uint32_t>(temp);
}
else
{
ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value");
}
}
else
{
template <>
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(const char *name) const {
if (!HasAttribute(name)) {
ThrowAttibuteError(m_reader, name);
}
return 0;
return static_cast<int32_t>(m_reader->getAttributeValueAsInt(name));
}
template<>
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(const char *name) const
{
if (HasAttribute(name))
{
return static_cast<uint16_t>(ReadAttribute<uint32_t>(name));
}
else
{
template <>
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(const char *name) const {
if (!HasAttribute(name)) {
ThrowAttibuteError(m_reader, name);
}
return 0;
// @note This is hackish. But we are never expecting unsigned values that go outside the
// int32_t range. Just monitor for negative numbers and kill the import.
int32_t temp = ReadAttribute<int32_t>(name);
if (temp < 0) {
ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value");
}
return static_cast<uint32_t>(temp);
}
template<>
float OgreXmlSerializer::ReadAttribute<float>(const char *name) const
{
if (HasAttribute(name))
{
return m_reader->getAttributeValueAsFloat(name);
}
else
{
template <>
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(const char *name) const {
if (!HasAttribute(name)) {
ThrowAttibuteError(m_reader, name);
return 0;
}
return static_cast<uint16_t>(ReadAttribute<uint32_t>(name));
}
template<>
std::string OgreXmlSerializer::ReadAttribute<std::string>(const char *name) const
{
const char* value = m_reader->getAttributeValue(name);
if (value)
{
return std::string(value);
}
else
{
template <>
float OgreXmlSerializer::ReadAttribute<float>(const char *name) const {
if (!HasAttribute(name)) {
ThrowAttibuteError(m_reader, name);
return "";
}
return m_reader->getAttributeValueAsFloat(name);
}
template<>
bool OgreXmlSerializer::ReadAttribute<bool>(const char *name) const
{
template <>
std::string OgreXmlSerializer::ReadAttribute<std::string>(const char *name) const {
const char *value = m_reader->getAttributeValue(name);
if (nullptr == value) {
ThrowAttibuteError(m_reader, name);
}
return std::string(value);
}
template <>
bool OgreXmlSerializer::ReadAttribute<bool>(const char *name) const {
std::string value = Ogre::ToLower(ReadAttribute<std::string>(name));
if (ASSIMP_stricmp(value, "true") == 0)
{
if (ASSIMP_stricmp(value, "true") == 0) {
return true;
}
else if (ASSIMP_stricmp(value, "false") == 0)
{
} else if (ASSIMP_stricmp(value, "false") == 0) {
return false;
}
else
{
} else {
ThrowAttibuteError(m_reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
return false;
}
}
bool OgreXmlSerializer::HasAttribute(const char *name) const
{
bool OgreXmlSerializer::HasAttribute(const char *name) const {
return (m_reader->getAttributeValue(name) != 0);
}
std::string &OgreXmlSerializer::NextNode()
{
do
{
if (!m_reader->read())
{
std::string &OgreXmlSerializer::NextNode() {
do {
if (!m_reader->read()) {
m_currentNodeName = "";
return m_currentNodeName;
}
}
while(m_reader->getNodeType() != irr::io::EXN_ELEMENT);
} while (m_reader->getNodeType() != irr::io::EXN_ELEMENT);
CurrentNodeName(true);
#if (OGRE_XML_SERIALIZER_DEBUG == 1)
@ -195,32 +149,29 @@ std::string &OgreXmlSerializer::NextNode()
return m_currentNodeName;
}
bool OgreXmlSerializer::CurrentNodeNameEquals(const std::string &name) const
{
bool OgreXmlSerializer::CurrentNodeNameEquals(const std::string &name) const {
return (ASSIMP_stricmp(m_currentNodeName, name) == 0);
}
std::string OgreXmlSerializer::CurrentNodeName(bool forceRead)
{
std::string OgreXmlSerializer::CurrentNodeName(bool forceRead) {
if (forceRead)
m_currentNodeName = std::string(m_reader->getNodeName());
return m_currentNodeName;
}
std::string &OgreXmlSerializer::SkipCurrentNode()
{
std::string &OgreXmlSerializer::SkipCurrentNode() {
#if (OGRE_XML_SERIALIZER_DEBUG == 1)
ASSIMP_LOG_DEBUG("Skipping node <" + m_currentNodeName + ">");
#endif
for(;;) {
for (;;) {
if (!m_reader->read()) {
m_currentNodeName = "";
return m_currentNodeName;
}
if ( m_reader->getNodeType() != irr::io::EXN_ELEMENT_END ) {
if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END) {
continue;
} else if ( std::string( m_reader->getNodeName() ) == m_currentNodeName ) {
} else if (std::string(m_reader->getNodeName()) == m_currentNodeName) {
break;
}
}
@ -231,38 +182,38 @@ std::string &OgreXmlSerializer::SkipCurrentNode()
// Mesh XML constants
// <mesh>
static const char *nnMesh = "mesh";
static const char *nnSharedGeometry = "sharedgeometry";
static const char *nnSubMeshes = "submeshes";
static const char *nnSubMesh = "submesh";
static const char *nnSubMeshNames = "submeshnames";
static const char *nnSkeletonLink = "skeletonlink";
static const char *nnLOD = "levelofdetail";
static const char *nnExtremes = "extremes";
static const char *nnPoses = "poses";
static const char *nnAnimations = "animations";
static const char *nnMesh = "mesh";
static const char *nnSharedGeometry = "sharedgeometry";
static const char *nnSubMeshes = "submeshes";
static const char *nnSubMesh = "submesh";
static const char *nnSubMeshNames = "submeshnames";
static const char *nnSkeletonLink = "skeletonlink";
static const char *nnLOD = "levelofdetail";
static const char *nnExtremes = "extremes";
static const char *nnPoses = "poses";
static const char *nnAnimations = "animations";
// <submesh>
static const char *nnFaces = "faces";
static const char *nnFace = "face";
static const char *nnGeometry = "geometry";
static const char *nnTextures = "textures";
static const char *nnFaces = "faces";
static const char *nnFace = "face";
static const char *nnGeometry = "geometry";
static const char *nnTextures = "textures";
// <mesh/submesh>
static const char *nnBoneAssignments = "boneassignments";
static const char *nnBoneAssignments = "boneassignments";
// <sharedgeometry/geometry>
static const char *nnVertexBuffer = "vertexbuffer";
static const char *nnVertexBuffer = "vertexbuffer";
// <vertexbuffer>
static const char *nnVertex = "vertex";
static const char *nnPosition = "position";
static const char *nnNormal = "normal";
static const char *nnTangent = "tangent";
static const char *nnBinormal = "binormal";
static const char *nnTexCoord = "texcoord";
static const char *nnColorDiffuse = "colour_diffuse";
static const char *nnColorSpecular = "colour_specular";
static const char *nnVertex = "vertex";
static const char *nnPosition = "position";
static const char *nnNormal = "normal";
static const char *nnTangent = "tangent";
static const char *nnBinormal = "binormal";
static const char *nnTexCoord = "texcoord";
static const char *nnColorDiffuse = "colour_diffuse";
static const char *nnColorSpecular = "colour_specular";
// <boneassignments>
static const char *nnVertexBoneAssignment = "vertexboneassignment";
@ -270,30 +221,30 @@ static const char *nnVertexBoneAssignment = "vertexboneassignment";
// Skeleton XML constants
// <skeleton>
static const char *nnSkeleton = "skeleton";
static const char *nnBones = "bones";
static const char *nnBoneHierarchy = "bonehierarchy";
static const char *nnAnimationLinks = "animationlinks";
static const char *nnSkeleton = "skeleton";
static const char *nnBones = "bones";
static const char *nnBoneHierarchy = "bonehierarchy";
static const char *nnAnimationLinks = "animationlinks";
// <bones>
static const char *nnBone = "bone";
static const char *nnRotation = "rotation";
static const char *nnAxis = "axis";
static const char *nnScale = "scale";
static const char *nnBone = "bone";
static const char *nnRotation = "rotation";
static const char *nnAxis = "axis";
static const char *nnScale = "scale";
// <bonehierarchy>
static const char *nnBoneParent = "boneparent";
static const char *nnBoneParent = "boneparent";
// <animations>
static const char *nnAnimation = "animation";
static const char *nnTracks = "tracks";
static const char *nnAnimation = "animation";
static const char *nnTracks = "tracks";
// <tracks>
static const char *nnTrack = "track";
static const char *nnKeyFrames = "keyframes";
static const char *nnKeyFrame = "keyframe";
static const char *nnTranslate = "translate";
static const char *nnRotate = "rotate";
static const char *nnTrack = "track";
static const char *nnKeyFrames = "keyframes";
static const char *nnKeyFrame = "keyframe";
static const char *nnTranslate = "translate";
static const char *nnRotate = "rotate";
// Common XML constants
@ -322,34 +273,26 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
NextNode();
// Root level nodes
while(m_currentNodeName == nnSharedGeometry ||
m_currentNodeName == nnSubMeshes ||
m_currentNodeName == nnSkeletonLink ||
m_currentNodeName == nnBoneAssignments ||
m_currentNodeName == nnLOD ||
m_currentNodeName == nnSubMeshNames ||
m_currentNodeName == nnExtremes ||
m_currentNodeName == nnPoses ||
m_currentNodeName == nnAnimations)
{
if (m_currentNodeName == nnSharedGeometry)
{
while (m_currentNodeName == nnSharedGeometry ||
m_currentNodeName == nnSubMeshes ||
m_currentNodeName == nnSkeletonLink ||
m_currentNodeName == nnBoneAssignments ||
m_currentNodeName == nnLOD ||
m_currentNodeName == nnSubMeshNames ||
m_currentNodeName == nnExtremes ||
m_currentNodeName == nnPoses ||
m_currentNodeName == nnAnimations) {
if (m_currentNodeName == nnSharedGeometry) {
mesh->sharedVertexData = new VertexDataXml();
ReadGeometry(mesh->sharedVertexData);
}
else if (m_currentNodeName == nnSubMeshes)
{
} else if (m_currentNodeName == nnSubMeshes) {
NextNode();
while(m_currentNodeName == nnSubMesh) {
while (m_currentNodeName == nnSubMesh) {
ReadSubMesh(mesh);
}
}
else if (m_currentNodeName == nnBoneAssignments)
{
} else if (m_currentNodeName == nnBoneAssignments) {
ReadBoneAssignments(mesh->sharedVertexData);
}
else if (m_currentNodeName == nnSkeletonLink)
{
} else if (m_currentNodeName == nnSkeletonLink) {
mesh->skeletonRef = ReadAttribute<std::string>("name");
ASSIMP_LOG_DEBUG_F("Read skeleton link ", mesh->skeletonRef);
NextNode();
@ -360,49 +303,43 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
}
}
void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest)
{
void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest) {
dest->count = ReadAttribute<uint32_t>("vertexcount");
ASSIMP_LOG_DEBUG_F( " - Reading geometry of ", dest->count, " vertices");
ASSIMP_LOG_DEBUG_F(" - Reading geometry of ", dest->count, " vertices");
NextNode();
while(m_currentNodeName == nnVertexBuffer) {
while (m_currentNodeName == nnVertexBuffer) {
ReadGeometryVertexBuffer(dest);
}
}
void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
{
void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
bool positions = (HasAttribute("positions") && ReadAttribute<bool>("positions"));
bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals"));
bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents"));
uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute<uint32_t>("texture_coords") : 0);
bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals"));
bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents"));
uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute<uint32_t>("texture_coords") : 0);
// Not having positions is a error only if a previous vertex buffer did not have them.
if (!positions && !dest->HasPositions()) {
throw DeadlyImportError("Vertex buffer does not contain positions!");
}
if (positions)
{
if (positions) {
ASSIMP_LOG_DEBUG(" - Contains positions");
dest->positions.reserve(dest->count);
}
if (normals)
{
if (normals) {
ASSIMP_LOG_DEBUG(" - Contains normals");
dest->normals.reserve(dest->count);
}
if (tangents)
{
if (tangents) {
ASSIMP_LOG_DEBUG(" - Contains tangents");
dest->tangents.reserve(dest->count);
}
if (uvs > 0)
{
ASSIMP_LOG_DEBUG_F( " - Contains ", uvs, " texture coords");
if (uvs > 0) {
ASSIMP_LOG_DEBUG_F(" - Contains ", uvs, " texture coords");
dest->uvs.resize(uvs);
for(size_t i=0, len=dest->uvs.size(); i<len; ++i) {
for (size_t i = 0, len = dest->uvs.size(); i < len; ++i) {
dest->uvs[i].reserve(dest->count);
}
}
@ -413,49 +350,40 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
NextNode();
while(m_currentNodeName == nnVertex ||
m_currentNodeName == nnPosition ||
m_currentNodeName == nnNormal ||
m_currentNodeName == nnTangent ||
m_currentNodeName == nnBinormal ||
m_currentNodeName == nnTexCoord ||
m_currentNodeName == nnColorDiffuse ||
m_currentNodeName == nnColorSpecular)
{
while (m_currentNodeName == nnVertex ||
m_currentNodeName == nnPosition ||
m_currentNodeName == nnNormal ||
m_currentNodeName == nnTangent ||
m_currentNodeName == nnBinormal ||
m_currentNodeName == nnTexCoord ||
m_currentNodeName == nnColorDiffuse ||
m_currentNodeName == nnColorSpecular) {
if (m_currentNodeName == nnVertex) {
NextNode();
}
/// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular
if (positions && m_currentNodeName == nnPosition)
{
if (positions && m_currentNodeName == nnPosition) {
aiVector3D pos;
pos.x = ReadAttribute<float>(anX);
pos.y = ReadAttribute<float>(anY);
pos.z = ReadAttribute<float>(anZ);
dest->positions.push_back(pos);
}
else if (normals && m_currentNodeName == nnNormal)
{
} else if (normals && m_currentNodeName == nnNormal) {
aiVector3D normal;
normal.x = ReadAttribute<float>(anX);
normal.y = ReadAttribute<float>(anY);
normal.z = ReadAttribute<float>(anZ);
dest->normals.push_back(normal);
}
else if (tangents && m_currentNodeName == nnTangent)
{
} else if (tangents && m_currentNodeName == nnTangent) {
aiVector3D tangent;
tangent.x = ReadAttribute<float>(anX);
tangent.y = ReadAttribute<float>(anY);
tangent.z = ReadAttribute<float>(anZ);
dest->tangents.push_back(tangent);
}
else if (uvs > 0 && m_currentNodeName == nnTexCoord)
{
for(auto &uvs : dest->uvs)
{
} else if (uvs > 0 && m_currentNodeName == nnTexCoord) {
for (auto &curUvs : dest->uvs) {
if (m_currentNodeName != nnTexCoord) {
throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
}
@ -463,47 +391,31 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
aiVector3D uv;
uv.x = ReadAttribute<float>("u");
uv.y = (ReadAttribute<float>("v") * -1) + 1; // Flip UV from Ogre to Assimp form
uvs.push_back(uv);
curUvs.push_back(uv);
NextNode();
}
// Continue main loop as above already read next node
continue;
}
else
{
} else {
/// @todo Remove this stuff once implemented. We only want to log warnings once per element.
bool warn = true;
if (m_currentNodeName == nnBinormal)
{
if (warnBinormal)
{
if (m_currentNodeName == nnBinormal) {
if (warnBinormal) {
warnBinormal = false;
}
else
{
} else {
warn = false;
}
}
else if (m_currentNodeName == nnColorDiffuse)
{
if (warnColorDiffuse)
{
} else if (m_currentNodeName == nnColorDiffuse) {
if (warnColorDiffuse) {
warnColorDiffuse = false;
}
else
{
} else {
warn = false;
}
}
else if (m_currentNodeName == nnColorSpecular)
{
if (warnColorSpecular)
{
} else if (m_currentNodeName == nnColorSpecular) {
if (warnColorSpecular) {
warnColorSpecular = false;
}
else
{
} else {
warn = false;
}
}
@ -518,7 +430,7 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
// Sanity checks
if (dest->positions.size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count);
throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count);
}
if (normals && dest->normals.size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->normals.size() << " normals when should have read " << dest->count);
@ -526,26 +438,24 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
if (tangents && dest->tangents.size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->tangents.size() << " tangents when should have read " << dest->count);
}
for(unsigned int i=0; i<dest->uvs.size(); ++i)
{
for (unsigned int i = 0; i < dest->uvs.size(); ++i) {
if (dest->uvs[i].size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->uvs[i].size()
<< " uvs for uv index " << i << " when should have read " << dest->count);
<< " uvs for uv index " << i << " when should have read " << dest->count);
}
}
}
void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
{
static const char *anMaterial = "material";
void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
static const char *anMaterial = "material";
static const char *anUseSharedVertices = "usesharedvertices";
static const char *anCount = "count";
static const char *anV1 = "v1";
static const char *anV2 = "v2";
static const char *anV3 = "v3";
static const char *anV4 = "v4";
static const char *anCount = "count";
static const char *anV1 = "v1";
static const char *anV2 = "v2";
static const char *anV3 = "v3";
static const char *anV4 = "v4";
SubMeshXml* submesh = new SubMeshXml();
SubMeshXml *submesh = new SubMeshXml();
if (HasAttribute(anMaterial)) {
submesh->materialRef = ReadAttribute<std::string>(anMaterial);
@ -554,9 +464,9 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
submesh->usesSharedVertexData = ReadAttribute<bool>(anUseSharedVertices);
}
ASSIMP_LOG_DEBUG_F( "Reading SubMesh ", mesh->subMeshes.size());
ASSIMP_LOG_DEBUG_F( " - Material: '", submesh->materialRef, "'");
ASSIMP_LOG_DEBUG_F( " - Uses shared geometry: ", (submesh->usesSharedVertexData ? "true" : "false"));
ASSIMP_LOG_DEBUG_F("Reading SubMesh ", mesh->subMeshes.size());
ASSIMP_LOG_DEBUG_F(" - Material: '", submesh->materialRef, "'");
ASSIMP_LOG_DEBUG_F(" - Uses shared geometry: ", (submesh->usesSharedVertexData ? "true" : "false"));
// TODO: maybe we have always just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order
// of faces and geometry changed, and not if we have more than one of one
@ -565,19 +475,16 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
bool quadWarned = false;
NextNode();
while(m_currentNodeName == nnFaces ||
m_currentNodeName == nnGeometry ||
m_currentNodeName == nnTextures ||
m_currentNodeName == nnBoneAssignments)
{
if (m_currentNodeName == nnFaces)
{
while (m_currentNodeName == nnFaces ||
m_currentNodeName == nnGeometry ||
m_currentNodeName == nnTextures ||
m_currentNodeName == nnBoneAssignments) {
if (m_currentNodeName == nnFaces) {
submesh->indexData->faceCount = ReadAttribute<uint32_t>(anCount);
submesh->indexData->faces.reserve(submesh->indexData->faceCount);
NextNode();
while(m_currentNodeName == nnFace)
{
while (m_currentNodeName == nnFace) {
aiFace face;
face.mNumIndices = 3;
face.mIndices = new unsigned int[3];
@ -598,7 +505,7 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
}
if (submesh->indexData->faces.size() == submesh->indexData->faceCount) {
ASSIMP_LOG_DEBUG_F( " - Faces ", submesh->indexData->faceCount);
ASSIMP_LOG_DEBUG_F(" - Faces ", submesh->indexData->faceCount);
} else {
throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount);
}
@ -622,21 +529,19 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
mesh->subMeshes.push_back(submesh);
}
void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
{
void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) {
if (!dest) {
throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
}
static const char *anVertexIndex = "vertexindex";
static const char *anBoneIndex = "boneindex";
static const char *anWeight = "weight";
static const char *anBoneIndex = "boneindex";
static const char *anWeight = "weight";
std::set<uint32_t> influencedVertices;
NextNode();
while(m_currentNodeName == nnVertexBoneAssignment)
{
while (m_currentNodeName == nnVertexBoneAssignment) {
VertexBoneAssignment ba;
ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
ba.boneIndex = ReadAttribute<uint16_t>(anBoneIndex);
@ -652,38 +557,32 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
Some exporters won't care if the sum of all bone weights
for a single vertex equals 1 or not, so validate here. */
const float epsilon = 0.05f;
for (const uint32_t vertexIndex : influencedVertices)
{
for (const uint32_t vertexIndex : influencedVertices) {
float sum = 0.0f;
for (VertexBoneAssignmentList::const_iterator baIter=dest->boneAssignments.begin(), baEnd=dest->boneAssignments.end(); baIter != baEnd; ++baIter)
{
for (VertexBoneAssignmentList::const_iterator baIter = dest->boneAssignments.begin(), baEnd = dest->boneAssignments.end(); baIter != baEnd; ++baIter) {
if (baIter->vertexIndex == vertexIndex)
sum += baIter->weight;
}
if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
{
for (auto &boneAssign : dest->boneAssignments)
{
if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon))) {
for (auto &boneAssign : dest->boneAssignments) {
if (boneAssign.vertexIndex == vertexIndex)
boneAssign.weight /= sum;
}
}
}
ASSIMP_LOG_DEBUG_F( " - ", dest->boneAssignments.size(), " bone assignments");
ASSIMP_LOG_DEBUG_F(" - ", dest->boneAssignments.size(), " bone assignments");
}
// Skeleton
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh)
{
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh) {
if (!mesh || mesh->skeletonRef.empty())
return false;
// Highly unusual to see in read world cases but support
// XML mesh referencing a binary skeleton file.
if (EndsWith(mesh->skeletonRef, ".skeleton", false))
{
if (EndsWith(mesh->skeletonRef, ".skeleton", false)) {
if (OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh))
return true;
@ -705,8 +604,7 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me
return true;
}
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
{
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) {
if (!mesh || mesh->skeletonRef.empty())
return false;
@ -721,16 +619,13 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
return true;
}
XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename)
{
if (!EndsWith(filename, ".skeleton.xml", false))
{
XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename) {
if (!EndsWith(filename, ".skeleton.xml", false)) {
ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file.");
return XmlReaderPtr();
}
if (!pIOHandler->Exists(filename))
{
if (!pIOHandler->Exists(filename)) {
ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh.");
return XmlReaderPtr();
}
@ -748,8 +643,7 @@ XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const s
return reader;
}
void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
{
void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) {
if (NextNode() != nnSkeleton) {
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <skeleton>");
}
@ -758,18 +652,16 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
// Optional blend mode from root node
if (HasAttribute("blendmode")) {
skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative"
? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
}
NextNode();
// Root level nodes
while(m_currentNodeName == nnBones ||
m_currentNodeName == nnBoneHierarchy ||
m_currentNodeName == nnAnimations ||
m_currentNodeName == nnAnimationLinks)
{
while (m_currentNodeName == nnBones ||
m_currentNodeName == nnBoneHierarchy ||
m_currentNodeName == nnAnimations ||
m_currentNodeName == nnAnimationLinks) {
if (m_currentNodeName == nnBones)
ReadBones(skeleton);
else if (m_currentNodeName == nnBoneHierarchy)
@ -781,8 +673,7 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
}
}
void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton)
{
void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) {
if (skeleton->bones.empty()) {
throw DeadlyImportError("Cannot read <animations> for a Skeleton without bones");
}
@ -790,8 +681,7 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton)
ASSIMP_LOG_DEBUG(" - Animations");
NextNode();
while(m_currentNodeName == nnAnimation)
{
while (m_currentNodeName == nnAnimation) {
Animation *anim = new Animation(skeleton);
anim->name = ReadAttribute<std::string>("name");
anim->length = ReadAttribute<float>("length");
@ -803,15 +693,13 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton)
ReadAnimationTracks(anim);
skeleton->animations.push_back(anim);
ASSIMP_LOG_DEBUG_F( " ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)");
ASSIMP_LOG_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)");
}
}
void OgreXmlSerializer::ReadAnimationTracks(Animation *dest)
{
void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) {
NextNode();
while(m_currentNodeName == nnTrack)
{
while (m_currentNodeName == nnTrack) {
VertexAnimationTrack track;
track.type = VertexAnimationTrack::VAT_TRANSFORM;
track.boneName = ReadAttribute<std::string>("bone");
@ -826,27 +714,21 @@ void OgreXmlSerializer::ReadAnimationTracks(Animation *dest)
}
}
void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest)
{
void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest) {
const aiVector3D zeroVec(0.f, 0.f, 0.f);
NextNode();
while(m_currentNodeName == nnKeyFrame)
{
while (m_currentNodeName == nnKeyFrame) {
TransformKeyFrame keyframe;
keyframe.timePos = ReadAttribute<float>("time");
NextNode();
while(m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale)
{
if (m_currentNodeName == nnTranslate)
{
while (m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale) {
if (m_currentNodeName == nnTranslate) {
keyframe.position.x = ReadAttribute<float>(anX);
keyframe.position.y = ReadAttribute<float>(anY);
keyframe.position.z = ReadAttribute<float>(anZ);
}
else if (m_currentNodeName == nnRotate)
{
} else if (m_currentNodeName == nnRotate) {
float angle = ReadAttribute<float>("angle");
if (NextNode() != nnAxis) {
@ -857,17 +739,14 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT
axis.x = ReadAttribute<float>(anX);
axis.y = ReadAttribute<float>(anY);
axis.z = ReadAttribute<float>(anZ);
if (axis.Equal(zeroVec))
{
if (axis.Equal(zeroVec)) {
axis.x = 1.0f;
if (angle != 0) {
ASSIMP_LOG_WARN_F("Found invalid a key frame with a zero rotation axis in animation: ", anim->name);
}
}
keyframe.rotation = aiQuaternion(axis, angle);
}
else if (m_currentNodeName == nnScale)
{
} else if (m_currentNodeName == nnScale) {
keyframe.scale.x = ReadAttribute<float>(anX);
keyframe.scale.y = ReadAttribute<float>(anY);
keyframe.scale.z = ReadAttribute<float>(anZ);
@ -880,14 +759,12 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT
}
}
void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton)
{
void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) {
if (skeleton->bones.empty()) {
throw DeadlyImportError("Cannot read <bonehierarchy> for a Skeleton without bones");
}
while(NextNode() == nnBoneParent)
{
while (NextNode() == nnBoneParent) {
const std::string name = ReadAttribute<std::string>("bone");
const std::string parentName = ReadAttribute<std::string>("parent");
@ -901,46 +778,38 @@ void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton)
}
// Calculate bone matrices for root bones. Recursively calculates their children.
for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
{
for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) {
Bone *bone = skeleton->bones[i];
if (!bone->IsParented())
bone->CalculateWorldMatrixAndDefaultPose(skeleton);
}
}
static bool BoneCompare(Bone *a, Bone *b)
{
ai_assert( nullptr != a );
ai_assert( nullptr != b );
static bool BoneCompare(Bone *a, Bone *b) {
ai_assert(nullptr != a);
ai_assert(nullptr != b);
return (a->id < b->id);
}
void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
{
void OgreXmlSerializer::ReadBones(Skeleton *skeleton) {
ASSIMP_LOG_DEBUG(" - Bones");
NextNode();
while(m_currentNodeName == nnBone)
{
while (m_currentNodeName == nnBone) {
Bone *bone = new Bone();
bone->id = ReadAttribute<uint16_t>("id");
bone->name = ReadAttribute<std::string>("name");
NextNode();
while(m_currentNodeName == nnPosition ||
m_currentNodeName == nnRotation ||
m_currentNodeName == nnScale)
{
if (m_currentNodeName == nnPosition)
{
while (m_currentNodeName == nnPosition ||
m_currentNodeName == nnRotation ||
m_currentNodeName == nnScale) {
if (m_currentNodeName == nnPosition) {
bone->position.x = ReadAttribute<float>(anX);
bone->position.y = ReadAttribute<float>(anY);
bone->position.z = ReadAttribute<float>(anZ);
}
else if (m_currentNodeName == nnRotation)
{
} else if (m_currentNodeName == nnRotation) {
float angle = ReadAttribute<float>("angle");
if (NextNode() != nnAxis) {
@ -953,17 +822,12 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
axis.z = ReadAttribute<float>(anZ);
bone->rotation = aiQuaternion(axis, angle);
}
else if (m_currentNodeName == nnScale)
{
} else if (m_currentNodeName == nnScale) {
/// @todo Implement taking scale into account in matrix/pose calculations!
if (HasAttribute("factor"))
{
if (HasAttribute("factor")) {
float factor = ReadAttribute<float>("factor");
bone->scale.Set(factor, factor, factor);
}
else
{
} else {
if (HasAttribute(anX))
bone->scale.x = ReadAttribute<float>(anX);
if (HasAttribute(anY))
@ -985,10 +849,9 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
// Validate that bone indexes are not skipped.
/** @note Left this from original authors code, but not sure if this is strictly necessary
as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */
for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
{
for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) {
Bone *b = skeleton->bones[i];
ASSIMP_LOG_DEBUG_F( " ", b->id, " ", b->name);
ASSIMP_LOG_DEBUG_F(" ", b->id, " ", b->name);
if (b->id != static_cast<uint16_t>(i)) {
throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i);
@ -996,7 +859,7 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
}
}
} // Ogre
} // Assimp
} // namespace Ogre
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER

View File

@ -1212,8 +1212,8 @@ void OpenGEXImporter::resolveReferences() {
if( RefInfo::MeshRef == currentRefInfo->m_type ) {
for( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) {
const std::string &name( currentRefInfo->m_Names[ i ] );
ReferenceMap::const_iterator it( m_mesh2refMap.find( name ) );
if( m_mesh2refMap.end() != it ) {
ReferenceMap::const_iterator curIt( m_mesh2refMap.find( name ) );
if (m_mesh2refMap.end() != curIt) {
unsigned int meshIdx = static_cast<unsigned int>(m_mesh2refMap[ name ]);
node->mMeshes[ i ] = meshIdx;
}
@ -1221,8 +1221,8 @@ void OpenGEXImporter::resolveReferences() {
} else if( RefInfo::MaterialRef == currentRefInfo->m_type ) {
for ( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) {
const std::string name( currentRefInfo->m_Names[ i ] );
ReferenceMap::const_iterator it( m_material2refMap.find( name ) );
if ( m_material2refMap.end() != it ) {
ReferenceMap::const_iterator curIt(m_material2refMap.find(name));
if (m_material2refMap.end() != curIt) {
if ( nullptr != m_currentMesh ) {
unsigned int matIdx = static_cast< unsigned int >( m_material2refMap[ name ] );
if ( m_currentMesh->mMaterialIndex != 0 ) {

View File

@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -49,10 +48,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// internal headers
#include "PlyLoader.h"
#include <assimp/IOStreamBuffer.h>
#include <memory>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
#include <memory>
using namespace ::Assimp;
@ -69,29 +68,27 @@ static const aiImporterDesc desc = {
"ply"
};
// ------------------------------------------------------------------------------------------------
// Internal stuff
namespace {
// ------------------------------------------------------------------------------------------------
// Checks that property index is within range
template <class T>
inline
const T &GetProperty(const std::vector<T> &props, int idx) {
if (static_cast<size_t>(idx) >= props.size()) {
throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
}
return props[idx];
// ------------------------------------------------------------------------------------------------
// Checks that property index is within range
template <class T>
inline const T &GetProperty(const std::vector<T> &props, int idx) {
if (static_cast<size_t>(idx) >= props.size()) {
throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
}
return props[idx];
}
} // namespace
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
PLYImporter::PLYImporter()
: mBuffer(nullptr)
, pcDOM(nullptr)
, mGeneratedMesh(nullptr) {
PLYImporter::PLYImporter() :
mBuffer(nullptr),
pcDOM(nullptr),
mGeneratedMesh(nullptr) {
// empty
}
@ -103,16 +100,20 @@ PLYImporter::~PLYImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool PLYImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if ( extension == "ply" ) {
if (extension == "ply") {
return true;
} else if (!extension.length() || checkSig) {
if ( !pIOHandler ) {
}
if (!extension.length() || checkSig) {
if (!pIOHandler) {
return true;
}
static const char* tokens[] = { "ply" };
static const char *tokens[] = {
"ply"
};
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
@ -120,19 +121,19 @@ bool PLYImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool c
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* PLYImporter::GetInfo() const {
const aiImporterDesc *PLYImporter::GetInfo() const {
return &desc;
}
// ------------------------------------------------------------------------------------------------
static bool isBigEndian(const char* szMe) {
static bool isBigEndian(const char *szMe) {
ai_assert(nullptr != szMe);
// binary_little_endian
// binary_big_endian
bool isBigEndian(false);
#if (defined AI_BUILD_BIG_ENDIAN)
if ( 'l' == *szMe || 'L' == *szMe ) {
if ('l' == *szMe || 'L' == *szMe) {
isBigEndian = true;
}
#else
@ -146,7 +147,7 @@ static bool isBigEndian(const char* szMe) {
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
const std::string mode = "rb";
std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode));
if (!fileStream.get()) {
@ -154,8 +155,8 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
}
// Get the file-size
const size_t fileSize( fileStream->FileSize() );
if ( 0 == fileSize ) {
const size_t fileSize(fileStream->FileSize());
if (0 == fileSize) {
throw DeadlyImportError("File " + pFile + " is empty.");
}
@ -169,28 +170,28 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
if ((headerCheck.size() < 3) ||
(headerCheck[0] != 'P' && headerCheck[0] != 'p') ||
(headerCheck[1] != 'L' && headerCheck[1] != 'l') ||
(headerCheck[2] != 'Y' && headerCheck[2] != 'y') ) {
(headerCheck[2] != 'Y' && headerCheck[2] != 'y')) {
streamedBuffer.close();
throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there");
}
std::vector<char> mBuffer2;
streamedBuffer.getNextLine(mBuffer2);
mBuffer = (unsigned char*)&mBuffer2[0];
mBuffer = (unsigned char *)&mBuffer2[0];
char* szMe = (char*)&this->mBuffer[0];
SkipSpacesAndLineEnd(szMe, (const char**)&szMe);
char *szMe = (char *)&this->mBuffer[0];
SkipSpacesAndLineEnd(szMe, (const char **)&szMe);
// determine the format of the file data and construct the aiMesh
PLY::DOM sPlyDom;
PLY::DOM sPlyDom;
this->pcDOM = &sPlyDom;
if (TokenMatch(szMe, "format", 6)) {
if (TokenMatch(szMe, "ascii", 5)) {
SkipLine(szMe, (const char**)&szMe);
SkipLine(szMe, (const char **)&szMe);
if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) {
if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh);
delete (mGeneratedMesh);
mGeneratedMesh = nullptr;
}
@ -204,7 +205,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
// skip the line, parse the rest of the header and build the DOM
if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) {
if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh);
delete (mGeneratedMesh);
mGeneratedMesh = nullptr;
}
@ -213,7 +214,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
}
} else {
if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh);
delete (mGeneratedMesh);
mGeneratedMesh = nullptr;
}
@ -223,7 +224,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
} else {
AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh);
delete (mGeneratedMesh);
mGeneratedMesh = nullptr;
}
@ -242,24 +243,24 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
// list is containing a list of points
bool pointsOnly = mGeneratedMesh->mFaces == nullptr ? true : false;
if (pointsOnly) {
mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT;
mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT;
}
// now load a list of all materials
std::vector<aiMaterial*> avMaterials;
std::vector<aiMaterial *> avMaterials;
std::string defaultTexture;
LoadMaterial(&avMaterials, defaultTexture, pointsOnly);
// now generate the output scene object. Fill the material list
pScene->mNumMaterials = (unsigned int)avMaterials.size();
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
pScene->mMaterials[i] = avMaterials[i];
}
// fill the mesh list
pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
pScene->mMeshes[0] = mGeneratedMesh;
mGeneratedMesh = nullptr;
@ -273,7 +274,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
}
}
void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) {
void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos) {
ai_assert(nullptr != pcElement);
ai_assert(nullptr != instElement);
@ -290,8 +291,8 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char };
// now check whether which normal components are available
unsigned int _a( 0 ), cnt( 0 );
for ( std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
unsigned int _a(0), cnt(0);
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
a != pcElement->alProperties.end(); ++a, ++_a) {
if ((*a).bIsList) {
continue;
@ -358,17 +359,17 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
aiVector3D vOut;
if (0xFFFFFFFF != aiPositions[0]) {
vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]);
GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]);
}
if (0xFFFFFFFF != aiPositions[1]) {
vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]);
GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]);
}
if (0xFFFFFFFF != aiPositions[2]) {
vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]);
GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]);
}
// Normals
@ -376,19 +377,19 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
bool haveNormal = false;
if (0xFFFFFFFF != aiNormal[0]) {
nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]);
GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]);
haveNormal = true;
}
if (0xFFFFFFFF != aiNormal[1]) {
nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]);
GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]);
haveNormal = true;
}
if (0xFFFFFFFF != aiNormal[2]) {
nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]);
GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]);
haveNormal = true;
}
@ -397,19 +398,25 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
bool haveColor = false;
if (0xFFFFFFFF != aiColors[0]) {
cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[0]).avList.front(), aiColorsTypes[0]);
aiColors[0])
.avList.front(),
aiColorsTypes[0]);
haveColor = true;
}
if (0xFFFFFFFF != aiColors[1]) {
cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[1]).avList.front(), aiColorsTypes[1]);
aiColors[1])
.avList.front(),
aiColorsTypes[1]);
haveColor = true;
}
if (0xFFFFFFFF != aiColors[2]) {
cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[2]).avList.front(), aiColorsTypes[2]);
aiColors[2])
.avList.front(),
aiColorsTypes[2]);
haveColor = true;
}
@ -418,7 +425,9 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
cOut.a = 1.0;
} else {
cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[3]).avList.front(), aiColorsTypes[3]);
aiColors[3])
.avList.front(),
aiColorsTypes[3]);
haveColor = true;
}
@ -429,18 +438,18 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
bool haveTextureCoords = false;
if (0xFFFFFFFF != aiTexcoord[0]) {
tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]);
GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]);
haveTextureCoords = true;
}
if (0xFFFFFFFF != aiTexcoord[1]) {
tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]);
GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]);
haveTextureCoords = true;
}
//create aiMesh if needed
if ( nullptr == mGeneratedMesh ) {
if (nullptr == mGeneratedMesh) {
mGeneratedMesh = new aiMesh();
mGeneratedMesh->mMaterialIndex = 0;
}
@ -474,29 +483,28 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
}
}
// ------------------------------------------------------------------------------------------------
// Convert a color component to [0...1]
ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) {
switch (eType) {
case EDT_Float:
return val.fFloat;
case EDT_Double:
return (ai_real)val.fDouble;
case EDT_UChar:
return (ai_real)val.iUInt / (ai_real)0xFF;
case EDT_Char:
return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF;
case EDT_UShort:
return (ai_real)val.iUInt / (ai_real)0xFFFF;
case EDT_Short:
return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF;
case EDT_UInt:
return (ai_real)val.iUInt / (ai_real)0xFFFF;
case EDT_Int:
return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
default:
break;
case EDT_Float:
return val.fFloat;
case EDT_Double:
return (ai_real)val.fDouble;
case EDT_UChar:
return (ai_real)val.iUInt / (ai_real)0xFF;
case EDT_Char:
return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF;
case EDT_UShort:
return (ai_real)val.iUInt / (ai_real)0xFFFF;
case EDT_Short:
return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF;
case EDT_UInt:
return (ai_real)val.iUInt / (ai_real)0xFFFF;
case EDT_Int:
return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
default:
break;
}
return 0.0f;
@ -504,7 +512,7 @@ ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val,
// ------------------------------------------------------------------------------------------------
// Try to extract proper faces from the PLY DOM
void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement,
void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInstance *instElement,
unsigned int pos) {
ai_assert(nullptr != pcElement);
ai_assert(nullptr != instElement);
@ -586,16 +594,16 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
GetProperty(instElement->alProperties, iProperty).avList.begin();
GetProperty(instElement->alProperties, iProperty).avList.begin();
for (unsigned int a = 0; a < iNum; ++a, ++p) {
mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType);
}
}
// parse the material index
// cannot be handled without processing the whole file first
/*if (0xFFFFFFFF != iMaterialIndex)
// parse the material index
// cannot be handled without processing the whole file first
/*if (0xFFFFFFFF != iMaterialIndex)
{
mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo<unsigned int>(
GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
@ -606,14 +614,14 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
//should be 6 coords
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
if ((iNum / 3) == 2) // X Y coord
{
for (unsigned int a = 0; a < iNum; ++a, ++p) {
unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2];
if (vindex < mGeneratedMesh->mNumVertices) {
if (mGeneratedMesh->mTextureCoords[0] == nullptr ) {
if (mGeneratedMesh->mTextureCoords[0] == nullptr) {
mGeneratedMesh->mNumUVComponents[0] = 2;
mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
}
@ -633,11 +641,11 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
// normally we have only one triangle strip instance where
// a value of -1 indicates a restart of the strip
bool flip = false;
const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty(instElement->alProperties, iProperty).avList;
const std::vector<PLY::PropertyInstance::ValueUnion> &quak = GetProperty(instElement->alProperties, iProperty).avList;
//pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
int aiTable[2] = { -1, -1 };
for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a) {
for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a) {
const int p = PLY::PropertyInstance::ConvertTo<int>(*a, eType);
if (-1 == p) {
@ -668,7 +676,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
// every second pass swap the indices.
flip = !flip;
if ( flip ) {
if (flip) {
std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]);
}
@ -681,285 +689,254 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
// ------------------------------------------------------------------------------------------------
// Get a RGBA color in [0...1] range
void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
unsigned int aiPositions[4],
PLY::EDataType aiTypes[4],
aiColor4D* clrOut)
{
ai_assert(NULL != clrOut);
void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance> &avList,
unsigned int aiPositions[4],
PLY::EDataType aiTypes[4],
aiColor4D *clrOut) {
ai_assert(NULL != clrOut);
if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
else
{
clrOut->r = NormalizeColorValue(GetProperty(avList,
aiPositions[0]).avList.front(), aiTypes[0]);
}
if (0xFFFFFFFF == aiPositions[0])
clrOut->r = 0.0f;
else {
clrOut->r = NormalizeColorValue(GetProperty(avList,
aiPositions[0])
.avList.front(),
aiTypes[0]);
}
if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
else
{
clrOut->g = NormalizeColorValue(GetProperty(avList,
aiPositions[1]).avList.front(), aiTypes[1]);
}
if (0xFFFFFFFF == aiPositions[1])
clrOut->g = 0.0f;
else {
clrOut->g = NormalizeColorValue(GetProperty(avList,
aiPositions[1])
.avList.front(),
aiTypes[1]);
}
if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
else
{
clrOut->b = NormalizeColorValue(GetProperty(avList,
aiPositions[2]).avList.front(), aiTypes[2]);
}
if (0xFFFFFFFF == aiPositions[2])
clrOut->b = 0.0f;
else {
clrOut->b = NormalizeColorValue(GetProperty(avList,
aiPositions[2])
.avList.front(),
aiTypes[2]);
}
// assume 1.0 for the alpha channel ifit is not set
if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
else
{
clrOut->a = NormalizeColorValue(GetProperty(avList,
aiPositions[3]).avList.front(), aiTypes[3]);
}
// assume 1.0 for the alpha channel ifit is not set
if (0xFFFFFFFF == aiPositions[3])
clrOut->a = 1.0f;
else {
clrOut->a = NormalizeColorValue(GetProperty(avList,
aiPositions[3])
.avList.front(),
aiTypes[3]);
}
}
// ------------------------------------------------------------------------------------------------
// Extract a material from the PLY DOM
void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly)
{
ai_assert(NULL != pvOut);
void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &defaultTexture, const bool pointsOnly) {
ai_assert(NULL != pvOut);
// diffuse[4], specular[4], ambient[4]
// rgba order
unsigned int aaiPositions[3][4] = {
// diffuse[4], specular[4], ambient[4]
// rgba order
unsigned int aaiPositions[3][4] = {
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
};
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
};
PLY::EDataType aaiTypes[3][4] = {
{ EDT_Char, EDT_Char, EDT_Char, EDT_Char },
{ EDT_Char, EDT_Char, EDT_Char, EDT_Char },
{ EDT_Char, EDT_Char, EDT_Char, EDT_Char }
};
PLY::ElementInstanceList* pcList = NULL;
PLY::EDataType aaiTypes[3][4] = {
{ EDT_Char, EDT_Char, EDT_Char, EDT_Char },
{ EDT_Char, EDT_Char, EDT_Char, EDT_Char },
{ EDT_Char, EDT_Char, EDT_Char, EDT_Char }
};
PLY::ElementInstanceList *pcList = NULL;
unsigned int iPhong = 0xFFFFFFFF;
PLY::EDataType ePhong = EDT_Char;
unsigned int iPhong = 0xFFFFFFFF;
PLY::EDataType ePhong = EDT_Char;
unsigned int iOpacity = 0xFFFFFFFF;
PLY::EDataType eOpacity = EDT_Char;
unsigned int iOpacity = 0xFFFFFFFF;
PLY::EDataType eOpacity = EDT_Char;
// search in the DOM for a vertex entry
unsigned int _i = 0;
for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin();
i != this->pcDOM->alElements.end(); ++i, ++_i)
{
if (PLY::EEST_Material == (*i).eSemantic)
{
pcList = &this->pcDOM->alElementData[_i];
// search in the DOM for a vertex entry
unsigned int _i = 0;
for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin();
i != this->pcDOM->alElements.end(); ++i, ++_i) {
if (PLY::EEST_Material == (*i).eSemantic) {
pcList = &this->pcDOM->alElementData[_i];
// now check whether which coordinate sets are available
unsigned int _a = 0;
for (std::vector<PLY::Property>::const_iterator
a = (*i).alProperties.begin();
a != (*i).alProperties.end(); ++a, ++_a)
{
if ((*a).bIsList)continue;
// now check whether which coordinate sets are available
unsigned int _a = 0;
for (std::vector<PLY::Property>::const_iterator
a = (*i).alProperties.begin();
a != (*i).alProperties.end(); ++a, ++_a) {
if ((*a).bIsList) continue;
// pohng specularity -----------------------------------
if (PLY::EST_PhongPower == (*a).Semantic)
{
iPhong = _a;
ePhong = (*a).eType;
}
// pohng specularity -----------------------------------
if (PLY::EST_PhongPower == (*a).Semantic) {
iPhong = _a;
ePhong = (*a).eType;
}
// general opacity -----------------------------------
if (PLY::EST_Opacity == (*a).Semantic)
{
iOpacity = _a;
eOpacity = (*a).eType;
}
// general opacity -----------------------------------
if (PLY::EST_Opacity == (*a).Semantic) {
iOpacity = _a;
eOpacity = (*a).eType;
}
// diffuse color channels -----------------------------------
if (PLY::EST_DiffuseRed == (*a).Semantic)
{
aaiPositions[0][0] = _a;
aaiTypes[0][0] = (*a).eType;
// diffuse color channels -----------------------------------
if (PLY::EST_DiffuseRed == (*a).Semantic) {
aaiPositions[0][0] = _a;
aaiTypes[0][0] = (*a).eType;
} else if (PLY::EST_DiffuseGreen == (*a).Semantic) {
aaiPositions[0][1] = _a;
aaiTypes[0][1] = (*a).eType;
} else if (PLY::EST_DiffuseBlue == (*a).Semantic) {
aaiPositions[0][2] = _a;
aaiTypes[0][2] = (*a).eType;
} else if (PLY::EST_DiffuseAlpha == (*a).Semantic) {
aaiPositions[0][3] = _a;
aaiTypes[0][3] = (*a).eType;
}
// specular color channels -----------------------------------
else if (PLY::EST_SpecularRed == (*a).Semantic) {
aaiPositions[1][0] = _a;
aaiTypes[1][0] = (*a).eType;
} else if (PLY::EST_SpecularGreen == (*a).Semantic) {
aaiPositions[1][1] = _a;
aaiTypes[1][1] = (*a).eType;
} else if (PLY::EST_SpecularBlue == (*a).Semantic) {
aaiPositions[1][2] = _a;
aaiTypes[1][2] = (*a).eType;
} else if (PLY::EST_SpecularAlpha == (*a).Semantic) {
aaiPositions[1][3] = _a;
aaiTypes[1][3] = (*a).eType;
}
// ambient color channels -----------------------------------
else if (PLY::EST_AmbientRed == (*a).Semantic) {
aaiPositions[2][0] = _a;
aaiTypes[2][0] = (*a).eType;
} else if (PLY::EST_AmbientGreen == (*a).Semantic) {
aaiPositions[2][1] = _a;
aaiTypes[2][1] = (*a).eType;
} else if (PLY::EST_AmbientBlue == (*a).Semantic) {
aaiPositions[2][2] = _a;
aaiTypes[2][2] = (*a).eType;
} else if (PLY::EST_AmbientAlpha == (*a).Semantic) {
aaiPositions[2][3] = _a;
aaiTypes[2][3] = (*a).eType;
}
}
break;
} else if (PLY::EEST_TextureFile == (*i).eSemantic) {
defaultTexture = (*i).szName;
}
else if (PLY::EST_DiffuseGreen == (*a).Semantic)
{
aaiPositions[0][1] = _a;
aaiTypes[0][1] = (*a).eType;
}
else if (PLY::EST_DiffuseBlue == (*a).Semantic)
{
aaiPositions[0][2] = _a;
aaiTypes[0][2] = (*a).eType;
}
else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
{
aaiPositions[0][3] = _a;
aaiTypes[0][3] = (*a).eType;
}
// specular color channels -----------------------------------
else if (PLY::EST_SpecularRed == (*a).Semantic)
{
aaiPositions[1][0] = _a;
aaiTypes[1][0] = (*a).eType;
}
else if (PLY::EST_SpecularGreen == (*a).Semantic)
{
aaiPositions[1][1] = _a;
aaiTypes[1][1] = (*a).eType;
}
else if (PLY::EST_SpecularBlue == (*a).Semantic)
{
aaiPositions[1][2] = _a;
aaiTypes[1][2] = (*a).eType;
}
else if (PLY::EST_SpecularAlpha == (*a).Semantic)
{
aaiPositions[1][3] = _a;
aaiTypes[1][3] = (*a).eType;
}
// ambient color channels -----------------------------------
else if (PLY::EST_AmbientRed == (*a).Semantic)
{
aaiPositions[2][0] = _a;
aaiTypes[2][0] = (*a).eType;
}
else if (PLY::EST_AmbientGreen == (*a).Semantic)
{
aaiPositions[2][1] = _a;
aaiTypes[2][1] = (*a).eType;
}
else if (PLY::EST_AmbientBlue == (*a).Semantic)
{
aaiPositions[2][2] = _a;
aaiTypes[2][2] = (*a).eType;
}
else if (PLY::EST_AmbientAlpha == (*a).Semantic)
{
aaiPositions[2][3] = _a;
aaiTypes[2][3] = (*a).eType;
}
}
break;
}
else if (PLY::EEST_TextureFile == (*i).eSemantic)
{
defaultTexture = (*i).szName;
}
}
// check whether we have a valid source for the material data
if (NULL != pcList) {
for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i) {
aiColor4D clrOut;
aiMaterial* pcHelper = new aiMaterial();
// check whether we have a valid source for the material data
if (NULL != pcList) {
for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i) {
aiColor4D clrOut;
aiMaterial *pcHelper = new aiMaterial();
// build the diffuse material color
GetMaterialColor((*i).alProperties, aaiPositions[0], aaiTypes[0], &clrOut);
pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_DIFFUSE);
// build the diffuse material color
GetMaterialColor((*i).alProperties, aaiPositions[0], aaiTypes[0], &clrOut);
pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_DIFFUSE);
// build the specular material color
GetMaterialColor((*i).alProperties, aaiPositions[1], aaiTypes[1], &clrOut);
pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_SPECULAR);
// build the specular material color
GetMaterialColor((*i).alProperties, aaiPositions[1], aaiTypes[1], &clrOut);
pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_SPECULAR);
// build the ambient material color
GetMaterialColor((*i).alProperties, aaiPositions[2], aaiTypes[2], &clrOut);
pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_AMBIENT);
// build the ambient material color
GetMaterialColor((*i).alProperties, aaiPositions[2], aaiTypes[2], &clrOut);
pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_AMBIENT);
// handle phong power and shading mode
int iMode = (int)aiShadingMode_Gouraud;
if (0xFFFFFFFF != iPhong) {
ai_real fSpec = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), ePhong);
// handle phong power and shading mode
int iMode = (int)aiShadingMode_Gouraud;
if (0xFFFFFFFF != iPhong) {
ai_real fSpec = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), ePhong);
// if shininess is 0 (and the pow() calculation would therefore always
// become 1, not depending on the angle), use gouraud lighting
if (fSpec) {
// scale this with 15 ... hopefully this is correct
fSpec *= 15;
pcHelper->AddProperty<ai_real>(&fSpec, 1, AI_MATKEY_SHININESS);
// if shininess is 0 (and the pow() calculation would therefore always
// become 1, not depending on the angle), use gouraud lighting
if (fSpec) {
// scale this with 15 ... hopefully this is correct
fSpec *= 15;
pcHelper->AddProperty<ai_real>(&fSpec, 1, AI_MATKEY_SHININESS);
iMode = (int)aiShadingMode_Phong;
iMode = (int)aiShadingMode_Phong;
}
}
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
// handle opacity
if (0xFFFFFFFF != iOpacity) {
ai_real fOpacity = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), eOpacity);
pcHelper->AddProperty<ai_real>(&fOpacity, 1, AI_MATKEY_OPACITY);
}
// The face order is absolutely undefined for PLY, so we have to
// use two-sided rendering to be sure it's ok.
const int two_sided = 1;
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
//default texture
if (!defaultTexture.empty()) {
const aiString name(defaultTexture.c_str());
pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
}
if (!pointsOnly) {
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
}
//set to wireframe, so when using this material info we can switch to points rendering
if (pointsOnly) {
const int wireframe = 1;
pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
// add the newly created material instance to the list
pvOut->push_back(pcHelper);
}
}
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
} else {
// generate a default material
aiMaterial *pcHelper = new aiMaterial();
// handle opacity
if (0xFFFFFFFF != iOpacity) {
ai_real fOpacity = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), eOpacity);
pcHelper->AddProperty<ai_real>(&fOpacity, 1, AI_MATKEY_OPACITY);
}
// fill in a default material
int iMode = (int)aiShadingMode_Gouraud;
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
// The face order is absolutely undefined for PLY, so we have to
// use two-sided rendering to be sure it's ok.
const int two_sided = 1;
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
//generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color
aiColor3D clr;
clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
//default texture
if (!defaultTexture.empty())
{
const aiString name(defaultTexture.c_str());
pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
}
clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
if (!pointsOnly)
{
const int two_sided = 1;
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
}
// The face order is absolutely undefined for PLY, so we have to
// use two-sided rendering to be sure it's ok.
if (!pointsOnly) {
const int two_sided = 1;
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
}
//set to wireframe, so when using this material info we can switch to points rendering
if (pointsOnly)
{
const int wireframe = 1;
pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
//default texture
if (!defaultTexture.empty()) {
const aiString name(defaultTexture.c_str());
pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
}
// add the newly created material instance to the list
pvOut->push_back(pcHelper);
//set to wireframe, so when using this material info we can switch to points rendering
if (pointsOnly) {
const int wireframe = 1;
pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
pvOut->push_back(pcHelper);
}
}
else
{
// generate a default material
aiMaterial* pcHelper = new aiMaterial();
// fill in a default material
int iMode = (int)aiShadingMode_Gouraud;
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
//generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color
aiColor3D clr;
clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
// The face order is absolutely undefined for PLY, so we have to
// use two-sided rendering to be sure it's ok.
if (!pointsOnly)
{
const int two_sided = 1;
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
}
//default texture
if (!defaultTexture.empty())
{
const aiString name(defaultTexture.c_str());
pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
}
//set to wireframe, so when using this material info we can switch to points rendering
if (pointsOnly)
{
const int wireframe = 1;
pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
pvOut->push_back(pcHelper);
}
}
#endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -46,9 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_PLYLOADER_H_INCLUDED
#define AI_PLYLOADER_H_INCLUDED
#include "PlyParser.h"
#include <assimp/BaseImporter.h>
#include <assimp/types.h>
#include "PlyParser.h"
#include <vector>
struct aiNode;
@ -62,77 +61,72 @@ using namespace PLY;
// ---------------------------------------------------------------------------
/** Importer class to load the stanford PLY file format
*/
class PLYImporter : public BaseImporter
{
class PLYImporter : public BaseImporter {
public:
PLYImporter();
~PLYImporter();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* 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;
// -------------------------------------------------------------------
/** Extract a vertex from the DOM
*/
void LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
void LoadVertex(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos);
// -------------------------------------------------------------------
/** Extract a face from the DOM
*/
void LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
void LoadFace(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos);
protected:
// -------------------------------------------------------------------
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details
*/
const aiImporterDesc* GetInfo () const;
const aiImporterDesc *GetInfo() const;
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* 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);
protected:
// -------------------------------------------------------------------
/** Extract a material list from the DOM
*/
void LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly);
void LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &defaultTexture, const bool pointsOnly);
// -------------------------------------------------------------------
/** Static helper to parse a color from four single channels in
*/
static void GetMaterialColor(
const std::vector<PLY::PropertyInstance>& avList,
unsigned int aiPositions[4],
PLY::EDataType aiTypes[4],
aiColor4D* clrOut);
const std::vector<PLY::PropertyInstance> &avList,
unsigned int aiPositions[4],
PLY::EDataType aiTypes[4],
aiColor4D *clrOut);
// -------------------------------------------------------------------
/** Static helper to parse a color channel value. The input value
* is normalized to 0-1.
*/
static ai_real NormalizeColorValue (
PLY::PropertyInstance::ValueUnion val,
PLY::EDataType eType);
static ai_real NormalizeColorValue(
PLY::PropertyInstance::ValueUnion val,
PLY::EDataType eType);
/** Buffer to hold the loaded file */
unsigned char* mBuffer;
unsigned char *mBuffer;
/** Document object model representation extracted from the file */
PLY::DOM* pcDOM;
PLY::DOM *pcDOM;
/** Mesh generated by loader */
aiMesh* mGeneratedMesh;
aiMesh *mGeneratedMesh;
};
} // end of namespace Assimp

Some files were not shown because too many files have changed in this diff Show More