Merge branch 'master' of https://github.com/assimp/assimp
commit
c1001c0e07
|
@ -70,8 +70,8 @@ IncludeCategories:
|
|||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentCaseLabels: false
|
||||
#IndentPPDirectives: AfterHash
|
||||
IndentWidth: 4
|
||||
# IndentWrappedFunctionNames: false
|
||||
# JavaScriptQuotes: Leave
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
name: C/C++ CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build-ubuntu:
|
||||
|
||||
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
|
||||
|
|
@ -255,8 +255,7 @@ 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)
|
||||
|
@ -583,8 +582,8 @@ ENDIF()
|
|||
ADD_SUBDIRECTORY( code/ )
|
||||
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
|
||||
# The viewer for windows only
|
||||
IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
|
||||
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
|
||||
IF ( WIN32 )
|
||||
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF )
|
||||
IF ( ASSIMP_BUILD_ASSIMP_VIEW )
|
||||
ADD_SUBDIRECTORY( tools/assimp_view/ )
|
||||
ENDIF ()
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -35,7 +35,7 @@ if(MSVC)
|
|||
endif()
|
||||
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
|
||||
|
||||
file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX)
|
||||
file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX)
|
||||
|
||||
if(ASSIMP_BUILD_SHARED_LIBS)
|
||||
set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")
|
||||
|
|
|
@ -35,7 +35,7 @@ if(MSVC)
|
|||
endif()
|
||||
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
|
||||
|
||||
file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX)
|
||||
file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX)
|
||||
|
||||
if(ASSIMP_BUILD_SHARED_LIBS)
|
||||
set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@")
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,36 +155,37 @@ AI_WONT_RETURN void B3DImporter::Fail( string str ){
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int B3DImporter::ReadByte(){
|
||||
if( _pos<_buf.size() ) {
|
||||
return _buf[_pos++];
|
||||
}
|
||||
if (_pos > _buf.size()) {
|
||||
Fail("EOF");
|
||||
}
|
||||
|
||||
Fail( "EOF" );
|
||||
return 0;
|
||||
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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace
|
|||
template<>
|
||||
size_t select_ftell<8>(FILE* file)
|
||||
{
|
||||
return ::_ftelli64(file);
|
||||
return (size_t)::_ftelli64(file);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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,
|
||||
|
@ -437,7 +434,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 +464,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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
6634
code/M3D/m3d.h
6634
code/M3D/m3d.h
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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,
|
||||
|
|
|
@ -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")
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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,17 +170,17 @@ 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;
|
||||
|
@ -187,10 +188,10 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
|
|||
|
||||
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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue