Model loading and texturing

This commit is contained in:
Dane Johnson
2021-01-18 18:25:47 -06:00
parent 66bf7776c7
commit 155b572aca
1283 changed files with 533814 additions and 42 deletions

1488
thirdparty/assimp/code/Irr/IRRLoader.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

296
thirdparty/assimp/code/Irr/IRRLoader.h vendored Normal file
View File

@@ -0,0 +1,296 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file IRRLoader.h
* @brief Declaration of the .irrMesh (Irrlight Engine Mesh Format)
* importer class.
*/
#ifndef AI_IRRLOADER_H_INCLUDED
#define AI_IRRLOADER_H_INCLUDED
#include "Irr/IRRShared.h"
#include "Common/Importer.h"
#include <assimp/SceneCombiner.h>
#include <assimp/StringUtils.h>
#include <assimp/anim.h>
namespace Assimp {
// ---------------------------------------------------------------------------
/** Irr importer class.
*
* Irr is the native scene file format of the Irrlight engine and its editor
* irrEdit. As IrrEdit itself is capable of importing quite many file formats,
* it might be a good file format for data exchange.
*/
class IRRImporter : public BaseImporter, public IrrlichtBase {
public:
IRRImporter();
~IRRImporter();
// -------------------------------------------------------------------
/** 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;
protected:
const aiImporterDesc* GetInfo () const;
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
void SetupProperties(const Importer* pImp);
private:
/** Data structure for a scenegraph node animator
*/
struct Animator {
// Type of the animator
enum AT {
UNKNOWN = 0x0,
ROTATION = 0x1,
FLY_CIRCLE = 0x2,
FLY_STRAIGHT = 0x3,
FOLLOW_SPLINE = 0x4,
OTHER = 0x5
} type;
explicit Animator(AT t = UNKNOWN)
: type (t)
, speed ( ai_real( 0.001 ) )
, direction ( ai_real( 0.0 ), ai_real( 1.0 ), ai_real( 0.0 ) )
, circleRadius ( ai_real( 1.0) )
, tightness ( ai_real( 0.5 ) )
, loop (true)
, timeForWay (100)
{
}
// common parameters
ai_real speed;
aiVector3D direction;
// FLY_CIRCLE
aiVector3D circleCenter;
ai_real circleRadius;
// FOLLOW_SPLINE
ai_real tightness;
std::vector<aiVectorKey> splineKeys;
// ROTATION (angles given in direction)
// FLY STRAIGHT
// circleCenter = start, direction = end
bool loop;
int timeForWay;
};
/** Data structure for a scenegraph node in an IRR file
*/
struct Node
{
// Type of the node
enum ET
{
LIGHT,
CUBE,
MESH,
SKYBOX,
DUMMY,
CAMERA,
TERRAIN,
SPHERE,
ANIMMESH
} type;
explicit Node(ET t)
: type (t)
, scaling (1.0,1.0,1.0) // assume uniform scaling by default
, parent()
, framesPerSecond (0.0)
, id()
, sphereRadius (1.0)
, spherePolyCountX (100)
, spherePolyCountY (100)
{
// Generate a default name for the node
char buffer[128];
static int cnt;
ai_snprintf(buffer, 128, "IrrNode_%i",cnt++);
name = std::string(buffer);
// reserve space for up to 5 materials
materials.reserve(5);
// reserve space for up to 5 children
children.reserve(5);
}
// Transformation of the node
aiVector3D position, rotation, scaling;
// Name of the node
std::string name;
// List of all child nodes
std::vector<Node*> children;
// Parent node
Node* parent;
// Animated meshes: frames per second
// 0.f if not specified
ai_real framesPerSecond;
// Meshes: path to the mesh to be loaded
std::string meshPath;
unsigned int id;
// Meshes: List of materials to be assigned
// along with their corresponding material flags
std::vector< std::pair<aiMaterial*, unsigned int> > materials;
// Spheres: radius of the sphere to be generates
ai_real sphereRadius;
// Spheres: Number of polygons in the x,y direction
unsigned int spherePolyCountX,spherePolyCountY;
// List of all animators assigned to the node
std::list<Animator> animators;
};
/** Data structure for a vertex in an IRR skybox
*/
struct SkyboxVertex
{
SkyboxVertex()
{}
//! Construction from single vertex components
SkyboxVertex(ai_real px, ai_real py, ai_real pz,
ai_real nx, ai_real ny, ai_real nz,
ai_real uvx, ai_real uvy)
: position (px,py,pz)
, normal (nx,ny,nz)
, uv (uvx,uvy,0.0)
{}
aiVector3D position, normal, uv;
};
// -------------------------------------------------------------------
/** Fill the scenegraph recursively
*/
void GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
BatchLoader& batch,
std::vector<aiMesh*>& meshes,
std::vector<aiNodeAnim*>& anims,
std::vector<AttachmentInfo>& attach,
std::vector<aiMaterial*>& materials,
unsigned int& defaultMatIdx);
// -------------------------------------------------------------------
/** Generate a mesh that consists of just a single quad
*/
aiMesh* BuildSingleQuadMesh(const SkyboxVertex& v1,
const SkyboxVertex& v2,
const SkyboxVertex& v3,
const SkyboxVertex& v4);
// -------------------------------------------------------------------
/** Build a skybox
*
* @param meshes Receives 6 output meshes
* @param materials The last 6 materials are assigned to the newly
* created meshes. The names of the materials are adjusted.
*/
void BuildSkybox(std::vector<aiMesh*>& meshes,
std::vector<aiMaterial*> materials);
// -------------------------------------------------------------------
/** Copy a material for a mesh to the output material list
*
* @param materials Receives an output material
* @param inmaterials List of input materials
* @param defMatIdx Default material index - UINT_MAX if not present
* @param mesh Mesh to work on
*/
void CopyMaterial(std::vector<aiMaterial*>& materials,
std::vector< std::pair<aiMaterial*, unsigned int> >& inmaterials,
unsigned int& defMatIdx,
aiMesh* mesh);
// -------------------------------------------------------------------
/** Compute animations for a specific node
*
* @param root Node to be processed
* @param anims The list of output animations
*/
void ComputeAnimations(Node* root, aiNode* real,
std::vector<aiNodeAnim*>& anims);
private:
/** Configuration option: desired output FPS */
double fps;
/** Configuration option: speed flag was set? */
bool configSpeedFlag;
};
} // end of namespace Assimp
#endif // AI_IRRIMPORTER_H_INC

View File

@@ -0,0 +1,536 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the IrrMesh importer class */
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
#include "IRRMeshLoader.h"
#include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h>
#include <memory>
#include <assimp/IOSystem.hpp>
#include <assimp/mesh.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/material.h>
#include <assimp/scene.h>
#include <assimp/importerdesc.h>
#include <assimp/Macros.h>
using namespace Assimp;
using namespace irr;
using namespace irr::io;
static const aiImporterDesc desc = {
"Irrlicht Mesh Reader",
"",
"",
"http://irrlicht.sourceforge.net/",
aiImporterFlags_SupportTextFlavour,
0,
0,
0,
0,
"xml irrmesh"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
IRRMeshImporter::IRRMeshImporter()
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
IRRMeshImporter::~IRRMeshImporter()
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool IRRMeshImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
/* NOTE: A simple check for the file extension is not enough
* here. Irrmesh and irr are easy, but xml is too generic
* and could be collada, too. So we need to open the file and
* search for typical tokens.
*/
const std::string extension = GetExtension(pFile);
if (extension == "irrmesh")return true;
else if (extension == "xml" || checkSig)
{
/* If CanRead() is called to check whether the loader
* supports a specific file extension in general we
* must return true here.
*/
if (!pIOHandler)return true;
const char* tokens[] = {"irrmesh"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
// Get a list of all file extensions which are handled by this class
const aiImporterDesc* IRRMeshImporter::GetInfo () const
{
return &desc;
}
static void releaseMaterial( aiMaterial **mat ) {
if(*mat!= nullptr) {
delete *mat;
*mat = nullptr;
}
}
static void releaseMesh( aiMesh **mesh ) {
if (*mesh != nullptr){
delete *mesh;
*mesh = nullptr;
}
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void IRRMeshImporter::InternReadFile( 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 IRRMESH file " + pFile + "");
// Construct the irrXML parser
CIrrXML_IOStreamReader st(file.get());
reader = createIrrXMLReader((IFileReadCallBack*) &st);
// final data
std::vector<aiMaterial*> materials;
std::vector<aiMesh*> meshes;
materials.reserve (5);
meshes.reserve(5);
// temporary data - current mesh buffer
aiMaterial* curMat = nullptr;
aiMesh* curMesh = nullptr;
unsigned int curMatFlags = 0;
std::vector<aiVector3D> curVertices,curNormals,curTangents,curBitangents;
std::vector<aiColor4D> curColors;
std::vector<aiVector3D> curUVs,curUV2s;
// some temporary variables
int textMeaning = 0;
int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents
bool useColors = false;
// Parse the XML file
while (reader->read()) {
switch (reader->getNodeType()) {
case EXN_ELEMENT:
if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) {
// end of previous buffer. A material and a mesh should be there
if ( !curMat || !curMesh) {
ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material");
releaseMaterial( &curMat );
releaseMesh( &curMesh );
} else {
materials.push_back(curMat);
meshes.push_back(curMesh);
}
curMat = nullptr;
curMesh = nullptr;
curVertices.clear();
curColors.clear();
curNormals.clear();
curUV2s.clear();
curUVs.clear();
curTangents.clear();
curBitangents.clear();
}
if (!ASSIMP_stricmp(reader->getNodeName(),"material")) {
if (curMat) {
ASSIMP_LOG_WARN("IRRMESH: Only one material description per buffer, please");
releaseMaterial( &curMat );
}
curMat = ParseMaterial(curMatFlags);
}
/* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices"))
{
int num = reader->getAttributeValueAsInt("vertexCount");
if (!num) {
// This is possible ... remove the mesh from the list and skip further reading
ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero vertices");
releaseMaterial( &curMat );
releaseMesh( &curMesh );
textMeaning = 0;
continue;
}
curVertices.reserve(num);
curNormals.reserve(num);
curColors.reserve(num);
curUVs.reserve(num);
// Determine the file format
const char* t = reader->getAttributeValueSafe("type");
if (!ASSIMP_stricmp("2tcoords", t)) {
curUV2s.reserve (num);
vertexFormat = 1;
if (curMatFlags & AI_IRRMESH_EXTRA_2ND_TEXTURE) {
// *********************************************************
// We have a second texture! So use this UV channel
// for it. The 2nd texture can be either a normal
// texture (solid_2layer or lightmap_xxx) or a normal
// map (normal_..., parallax_...)
// *********************************************************
int idx = 1;
aiMaterial* mat = ( aiMaterial* ) curMat;
if (curMatFlags & AI_IRRMESH_MAT_lightmap){
mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_LIGHTMAP(0));
}
else if (curMatFlags & AI_IRRMESH_MAT_normalmap_solid){
mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0));
}
else if (curMatFlags & AI_IRRMESH_MAT_solid_2layer) {
mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
}
}
}
else if (!ASSIMP_stricmp("tangents", t)) {
curTangents.reserve (num);
curBitangents.reserve (num);
vertexFormat = 2;
}
else if (ASSIMP_stricmp("standard", t)) {
releaseMaterial( &curMat );
ASSIMP_LOG_WARN("IRRMESH: Unknown vertex format");
}
else vertexFormat = 0;
textMeaning = 1;
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) {
if (curVertices.empty() && curMat) {
releaseMaterial( &curMat );
throw DeadlyImportError("IRRMESH: indices must come after vertices");
}
textMeaning = 2;
// start a new mesh
curMesh = new aiMesh();
// allocate storage for all faces
curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount");
if (!curMesh->mNumVertices) {
// This is possible ... remove the mesh from the list and skip further reading
ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero indices");
// mesh - away
releaseMesh( &curMesh );
// material - away
releaseMaterial( &curMat );
textMeaning = 0;
continue;
}
if (curMesh->mNumVertices % 3) {
ASSIMP_LOG_WARN("IRRMESH: Number if indices isn't divisible by 3");
}
curMesh->mNumFaces = curMesh->mNumVertices / 3;
curMesh->mFaces = new aiFace[curMesh->mNumFaces];
// setup some members
curMesh->mMaterialIndex = (unsigned int)materials.size();
curMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
// allocate storage for all vertices
curMesh->mVertices = new aiVector3D[curMesh->mNumVertices];
if (curNormals.size() == curVertices.size()) {
curMesh->mNormals = new aiVector3D[curMesh->mNumVertices];
}
if (curTangents.size() == curVertices.size()) {
curMesh->mTangents = new aiVector3D[curMesh->mNumVertices];
}
if (curBitangents.size() == curVertices.size()) {
curMesh->mBitangents = new aiVector3D[curMesh->mNumVertices];
}
if (curColors.size() == curVertices.size() && useColors) {
curMesh->mColors[0] = new aiColor4D[curMesh->mNumVertices];
}
if (curUVs.size() == curVertices.size()) {
curMesh->mTextureCoords[0] = new aiVector3D[curMesh->mNumVertices];
}
if (curUV2s.size() == curVertices.size()) {
curMesh->mTextureCoords[1] = new aiVector3D[curMesh->mNumVertices];
}
}
break;
case EXN_TEXT:
{
const char* sz = reader->getNodeData();
if (textMeaning == 1) {
textMeaning = 0;
// read vertices
do {
SkipSpacesAndLineEnd(&sz);
aiVector3D temp;aiColor4D c;
// Read the vertex position
sz = fast_atoreal_move<float>(sz,(float&)temp.x);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.y);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.z);
SkipSpaces(&sz);
curVertices.push_back(temp);
// Read the vertex normals
sz = fast_atoreal_move<float>(sz,(float&)temp.x);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.y);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.z);
SkipSpaces(&sz);
curNormals.push_back(temp);
// read the vertex colors
uint32_t clr = strtoul16(sz,&sz);
ColorFromARGBPacked(clr,c);
if (!curColors.empty() && c != *(curColors.end()-1))
useColors = true;
curColors.push_back(c);
SkipSpaces(&sz);
// read the first UV coordinate set
sz = fast_atoreal_move<float>(sz,(float&)temp.x);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.y);
SkipSpaces(&sz);
temp.z = 0.f;
temp.y = 1.f - temp.y; // DX to OGL
curUVs.push_back(temp);
// read the (optional) second UV coordinate set
if (vertexFormat == 1) {
sz = fast_atoreal_move<float>(sz,(float&)temp.x);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.y);
temp.y = 1.f - temp.y; // DX to OGL
curUV2s.push_back(temp);
}
// read optional tangent and bitangent vectors
else if (vertexFormat == 2) {
// tangents
sz = fast_atoreal_move<float>(sz,(float&)temp.x);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.z);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.y);
SkipSpaces(&sz);
temp.y *= -1.0f;
curTangents.push_back(temp);
// bitangents
sz = fast_atoreal_move<float>(sz,(float&)temp.x);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.z);
SkipSpaces(&sz);
sz = fast_atoreal_move<float>(sz,(float&)temp.y);
SkipSpaces(&sz);
temp.y *= -1.0f;
curBitangents.push_back(temp);
}
}
/* IMPORTANT: We assume that each vertex is specified in one
line. So we can skip the rest of the line - unknown vertex
elements are ignored.
*/
while (SkipLine(&sz));
}
else if (textMeaning == 2) {
textMeaning = 0;
// read indices
aiFace* curFace = curMesh->mFaces;
aiFace* const faceEnd = curMesh->mFaces + curMesh->mNumFaces;
aiVector3D* pcV = curMesh->mVertices;
aiVector3D* pcN = curMesh->mNormals;
aiVector3D* pcT = curMesh->mTangents;
aiVector3D* pcB = curMesh->mBitangents;
aiColor4D* pcC0 = curMesh->mColors[0];
aiVector3D* pcT0 = curMesh->mTextureCoords[0];
aiVector3D* pcT1 = curMesh->mTextureCoords[1];
unsigned int curIdx = 0;
unsigned int total = 0;
while(SkipSpacesAndLineEnd(&sz)) {
if (curFace >= faceEnd) {
ASSIMP_LOG_ERROR("IRRMESH: Too many indices");
break;
}
if (!curIdx) {
curFace->mNumIndices = 3;
curFace->mIndices = new unsigned int[3];
}
unsigned int idx = strtoul10(sz,&sz);
if (idx >= curVertices.size()) {
ASSIMP_LOG_ERROR("IRRMESH: Index out of range");
idx = 0;
}
curFace->mIndices[curIdx] = total++;
*pcV++ = curVertices[idx];
if (pcN)*pcN++ = curNormals[idx];
if (pcT)*pcT++ = curTangents[idx];
if (pcB)*pcB++ = curBitangents[idx];
if (pcC0)*pcC0++ = curColors[idx];
if (pcT0)*pcT0++ = curUVs[idx];
if (pcT1)*pcT1++ = curUV2s[idx];
if (++curIdx == 3) {
++curFace;
curIdx = 0;
}
}
if (curFace != faceEnd)
ASSIMP_LOG_ERROR("IRRMESH: Not enough indices");
// Finish processing the mesh - do some small material workarounds
if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) {
// Take the opacity value of the current material
// from the common vertex color alpha
aiMaterial* mat = (aiMaterial*)curMat;
mat->AddProperty(&curColors[0].a,1,AI_MATKEY_OPACITY);
}
}}
break;
default:
// GCC complains here ...
break;
};
}
// End of the last buffer. A material and a mesh should be there
if (curMat || curMesh) {
if ( !curMat || !curMesh) {
ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material");
releaseMaterial( &curMat );
releaseMesh( &curMesh );
}
else {
materials.push_back(curMat);
meshes.push_back(curMesh);
}
}
if (materials.empty())
throw DeadlyImportError("IRRMESH: Unable to read a mesh from this file");
// now generate the output scene
pScene->mNumMeshes = (unsigned int)meshes.size();
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
pScene->mMeshes[i] = meshes[i];
// clean this value ...
pScene->mMeshes[i]->mNumUVComponents[3] = 0;
}
pScene->mNumMaterials = (unsigned int)materials.size();
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
::memcpy(pScene->mMaterials,&materials[0],sizeof(void*)*pScene->mNumMaterials);
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<IRRMesh>");
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
pScene->mRootNode->mMeshes[i] = i;
// clean up and return
delete reader;
AI_DEBUG_INVALIDATE_PTR(reader);
}
#endif // !! ASSIMP_BUILD_NO_IRRMESH_IMPORTER

View File

@@ -0,0 +1,101 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file IRRMeshLoader.h
* @brief Declaration of the .irrMesh (Irrlight Engine Mesh Format)
* importer class.
*/
#ifndef AI_IRRMESHLOADER_H_INCLUDED
#define AI_IRRMESHLOADER_H_INCLUDED
#include <assimp/BaseImporter.h>
#include "IRRShared.h"
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
namespace Assimp {
// ---------------------------------------------------------------------------
/** IrrMesh importer class.
*
* IrrMesh is the native file format of the Irrlight engine and its editor
* irrEdit. As IrrEdit itself is capable of importing quite many file formats,
* it might be a good file format for data exchange.
*/
class IRRMeshImporter : public BaseImporter, public IrrlichtBase
{
public:
IRRMeshImporter();
~IRRMeshImporter();
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;
protected:
// -------------------------------------------------------------------
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details
*/
const aiImporterDesc* GetInfo () const;
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
};
} // end of namespace Assimp
#endif // ASSIMP_BUILD_NO_IRRMESH_IMPORTER
#endif // AI_IRRMESHIMPORTER_H_INC

501
thirdparty/assimp/code/Irr/IRRShared.cpp vendored Normal file
View File

@@ -0,0 +1,501 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file IRRShared.cpp
* @brief Shared utilities for the IRR and IRRMESH loaders
*/
//This section should be excluded only if both the Irrlicht AND the Irrlicht Mesh importers were omitted.
#if !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))
#include "IRRShared.h"
#include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/material.h>
using namespace Assimp;
using namespace irr;
using namespace irr::io;
// Transformation matrix to convert from Assimp to IRR space
const aiMatrix4x4 Assimp::AI_TO_IRR_MATRIX = aiMatrix4x4 (
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
// ------------------------------------------------------------------------------------------------
// read a property in hexadecimal format (i.e. ffffffff)
void IrrlichtBase::ReadHexProperty (HexProperty& out)
{
for (int i = 0; i < reader->getAttributeCount();++i)
{
if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
{
out.name = std::string( reader->getAttributeValue(i) );
}
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
{
// parse the hexadecimal value
out.value = strtoul16(reader->getAttributeValue(i));
}
}
}
// ------------------------------------------------------------------------------------------------
// read a decimal property
void IrrlichtBase::ReadIntProperty (IntProperty& out)
{
for (int i = 0; i < reader->getAttributeCount();++i)
{
if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
{
out.name = std::string( reader->getAttributeValue(i) );
}
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
{
// parse the ecimal value
out.value = strtol10(reader->getAttributeValue(i));
}
}
}
// ------------------------------------------------------------------------------------------------
// read a string property
void IrrlichtBase::ReadStringProperty (StringProperty& out)
{
for (int i = 0; i < reader->getAttributeCount();++i)
{
if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
{
out.name = std::string( reader->getAttributeValue(i) );
}
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
{
// simple copy the string
out.value = std::string (reader->getAttributeValue(i));
}
}
}
// ------------------------------------------------------------------------------------------------
// read a boolean property
void IrrlichtBase::ReadBoolProperty (BoolProperty& out)
{
for (int i = 0; i < reader->getAttributeCount();++i)
{
if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
{
out.name = std::string( reader->getAttributeValue(i) );
}
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
{
// true or false, case insensitive
out.value = (ASSIMP_stricmp( reader->getAttributeValue(i),
"true") ? false : true);
}
}
}
// ------------------------------------------------------------------------------------------------
// read a float property
void IrrlichtBase::ReadFloatProperty (FloatProperty& out)
{
for (int i = 0; i < reader->getAttributeCount();++i)
{
if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
{
out.name = std::string( reader->getAttributeValue(i) );
}
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
{
// just parse the float
out.value = fast_atof( reader->getAttributeValue(i) );
}
}
}
// ------------------------------------------------------------------------------------------------
// read a vector property
void IrrlichtBase::ReadVectorProperty (VectorProperty& out)
{
for (int i = 0; i < reader->getAttributeCount();++i)
{
if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
{
out.name = std::string( reader->getAttributeValue(i) );
}
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
{
// three floats, separated with commas
const char* ptr = reader->getAttributeValue(i);
SkipSpaces(&ptr);
ptr = fast_atoreal_move<float>( ptr,(float&)out.value.x );
SkipSpaces(&ptr);
if (',' != *ptr)
{
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
}
else SkipSpaces(ptr+1,&ptr);
ptr = fast_atoreal_move<float>( ptr,(float&)out.value.y );
SkipSpaces(&ptr);
if (',' != *ptr)
{
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
}
else SkipSpaces(ptr+1,&ptr);
ptr = fast_atoreal_move<float>( ptr,(float&)out.value.z );
}
}
}
// ------------------------------------------------------------------------------------------------
// Convert a string to a proper aiMappingMode
int ConvertMappingMode(const std::string& mode)
{
if (mode == "texture_clamp_repeat")
{
return aiTextureMapMode_Wrap;
}
else if (mode == "texture_clamp_mirror")
return aiTextureMapMode_Mirror;
return aiTextureMapMode_Clamp;
}
// ------------------------------------------------------------------------------------------------
// Parse a material from the XML file
aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
{
aiMaterial* mat = new aiMaterial();
aiColor4D clr;
aiString s;
matFlags = 0; // zero output flags
int cnt = 0; // number of used texture channels
unsigned int nd = 0;
// Continue reading from the file
while (reader->read())
{
switch (reader->getNodeType())
{
case EXN_ELEMENT:
// Hex properties
if (!ASSIMP_stricmp(reader->getNodeName(),"color"))
{
HexProperty prop;
ReadHexProperty(prop);
if (prop.name == "Diffuse")
{
ColorFromARGBPacked(prop.value,clr);
mat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
}
else if (prop.name == "Ambient")
{
ColorFromARGBPacked(prop.value,clr);
mat->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
}
else if (prop.name == "Specular")
{
ColorFromARGBPacked(prop.value,clr);
mat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
}
// NOTE: The 'emissive' property causes problems. It is
// often != 0, even if there is obviously no light
// emitted by the described surface. In fact I think
// IRRLICHT ignores this property, too.
#if 0
else if (prop.name == "Emissive")
{
ColorFromARGBPacked(prop.value,clr);
mat->AddProperty(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
}
#endif
}
// Float properties
else if (!ASSIMP_stricmp(reader->getNodeName(),"float"))
{
FloatProperty prop;
ReadFloatProperty(prop);
if (prop.name == "Shininess")
{
mat->AddProperty(&prop.value,1,AI_MATKEY_SHININESS);
}
}
// Bool properties
else if (!ASSIMP_stricmp(reader->getNodeName(),"bool"))
{
BoolProperty prop;
ReadBoolProperty(prop);
if (prop.name == "Wireframe")
{
int val = (prop.value ? true : false);
mat->AddProperty(&val,1,AI_MATKEY_ENABLE_WIREFRAME);
}
else if (prop.name == "GouraudShading")
{
int val = (prop.value ? aiShadingMode_Gouraud
: aiShadingMode_NoShading);
mat->AddProperty(&val,1,AI_MATKEY_SHADING_MODEL);
}
else if (prop.name == "BackfaceCulling")
{
int val = (!prop.value);
mat->AddProperty(&val,1,AI_MATKEY_TWOSIDED);
}
}
// String properties - textures and texture related properties
else if (!ASSIMP_stricmp(reader->getNodeName(),"texture") ||
!ASSIMP_stricmp(reader->getNodeName(),"enum"))
{
StringProperty prop;
ReadStringProperty(prop);
if (prop.value.length())
{
// material type (shader)
if (prop.name == "Type")
{
if (prop.value == "solid")
{
// default material ...
}
else if (prop.value == "trans_vertex_alpha")
{
matFlags = AI_IRRMESH_MAT_trans_vertex_alpha;
}
else if (prop.value == "lightmap")
{
matFlags = AI_IRRMESH_MAT_lightmap;
}
else if (prop.value == "solid_2layer")
{
matFlags = AI_IRRMESH_MAT_solid_2layer;
}
else if (prop.value == "lightmap_m2")
{
matFlags = AI_IRRMESH_MAT_lightmap_m2;
}
else if (prop.value == "lightmap_m4")
{
matFlags = AI_IRRMESH_MAT_lightmap_m4;
}
else if (prop.value == "lightmap_light")
{
matFlags = AI_IRRMESH_MAT_lightmap_light;
}
else if (prop.value == "lightmap_light_m2")
{
matFlags = AI_IRRMESH_MAT_lightmap_light_m2;
}
else if (prop.value == "lightmap_light_m4")
{
matFlags = AI_IRRMESH_MAT_lightmap_light_m4;
}
else if (prop.value == "lightmap_add")
{
matFlags = AI_IRRMESH_MAT_lightmap_add;
}
// Normal and parallax maps are treated equally
else if (prop.value == "normalmap_solid" ||
prop.value == "parallaxmap_solid")
{
matFlags = AI_IRRMESH_MAT_normalmap_solid;
}
else if (prop.value == "normalmap_trans_vertex_alpha" ||
prop.value == "parallaxmap_trans_vertex_alpha")
{
matFlags = AI_IRRMESH_MAT_normalmap_tva;
}
else if (prop.value == "normalmap_trans_add" ||
prop.value == "parallaxmap_trans_add")
{
matFlags = AI_IRRMESH_MAT_normalmap_ta;
}
else {
ASSIMP_LOG_WARN("IRRMat: Unrecognized material type: " + prop.value);
}
}
// Up to 4 texture channels are supported
if (prop.name == "Texture1")
{
// Always accept the primary texture channel
++cnt;
s.Set(prop.value);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else if (prop.name == "Texture2" && cnt == 1)
{
// 2-layer material lightmapped?
if (matFlags & AI_IRRMESH_MAT_lightmap) {
++cnt;
s.Set(prop.value);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_LIGHTMAP(0));
// set the corresponding material flag
matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
}
// alternatively: normal or parallax mapping
else if (matFlags & AI_IRRMESH_MAT_normalmap_solid) {
++cnt;
s.Set(prop.value);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_NORMALS(0));
// set the corresponding material flag
matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
} else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {// or just as second diffuse texture
++cnt;
s.Set(prop.value);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(1));
++nd;
// set the corresponding material flag
matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
} else {
ASSIMP_LOG_WARN("IRRmat: Skipping second texture");
}
} else if (prop.name == "Texture3" && cnt == 2) {
// Irrlicht does not seem to use these channels.
++cnt;
s.Set(prop.value);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+1));
} else if (prop.name == "Texture4" && cnt == 3) {
// Irrlicht does not seem to use these channels.
++cnt;
s.Set(prop.value);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+2));
}
// Texture mapping options
if (prop.name == "TextureWrap1" && cnt >= 1)
{
int map = ConvertMappingMode(prop.value);
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
}
else if (prop.name == "TextureWrap2" && cnt >= 2)
{
int map = ConvertMappingMode(prop.value);
if (matFlags & AI_IRRMESH_MAT_lightmap) {
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_LIGHTMAP(0));
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_LIGHTMAP(0));
}
else if (matFlags & (AI_IRRMESH_MAT_normalmap_solid)) {
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_NORMALS(0));
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_NORMALS(0));
}
else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(1));
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(1));
}
}
else if (prop.name == "TextureWrap3" && cnt >= 3)
{
int map = ConvertMappingMode(prop.value);
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(nd+1));
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(nd+1));
}
else if (prop.name == "TextureWrap4" && cnt >= 4)
{
int map = ConvertMappingMode(prop.value);
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(nd+2));
mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(nd+2));
}
}
}
break;
case EXN_ELEMENT_END:
/* Assume there are no further nested nodes in <material> elements
*/
if (/* IRRMESH */ !ASSIMP_stricmp(reader->getNodeName(),"material") ||
/* IRR */ !ASSIMP_stricmp(reader->getNodeName(),"attributes"))
{
// Now process lightmapping flags
// We should have at least one textur to do that ..
if (cnt && matFlags & AI_IRRMESH_MAT_lightmap)
{
float f = 1.f;
unsigned int unmasked = matFlags&~AI_IRRMESH_MAT_lightmap;
// Additive lightmap?
int op = (unmasked & AI_IRRMESH_MAT_lightmap_add
? aiTextureOp_Add : aiTextureOp_Multiply);
// Handle Irrlicht's lightmapping scaling factor
if (unmasked & AI_IRRMESH_MAT_lightmap_m2 ||
unmasked & AI_IRRMESH_MAT_lightmap_light_m2)
{
f = 2.f;
}
else if (unmasked & AI_IRRMESH_MAT_lightmap_m4 ||
unmasked & AI_IRRMESH_MAT_lightmap_light_m4)
{
f = 4.f;
}
mat->AddProperty( &f, 1, AI_MATKEY_TEXBLEND_LIGHTMAP(0));
mat->AddProperty( &op,1, AI_MATKEY_TEXOP_LIGHTMAP(0));
}
return mat;
}
default:
// GCC complains here ...
break;
}
}
ASSIMP_LOG_ERROR("IRRMESH: Unexpected end of file. Material is not complete");
return mat;
}
#endif // !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))

118
thirdparty/assimp/code/Irr/IRRShared.h vendored Normal file
View File

@@ -0,0 +1,118 @@
/** @file IRRShared.h
* @brief Shared utilities for the IRR and IRRMESH loaders
*/
#ifndef INCLUDED_AI_IRRSHARED_H
#define INCLUDED_AI_IRRSHARED_H
#include <assimp/irrXMLWrapper.h>
#include <assimp/BaseImporter.h>
#include <stdint.h>
struct aiMaterial;
namespace Assimp {
/** @brief Matrix to convert from Assimp to IRR and backwards
*/
extern const aiMatrix4x4 AI_TO_IRR_MATRIX;
// Default: 0 = solid, one texture
#define AI_IRRMESH_MAT_solid_2layer 0x10000
// Transparency flags
#define AI_IRRMESH_MAT_trans_vertex_alpha 0x1
#define AI_IRRMESH_MAT_trans_add 0x2
// Lightmapping flags
#define AI_IRRMESH_MAT_lightmap 0x2
#define AI_IRRMESH_MAT_lightmap_m2 (AI_IRRMESH_MAT_lightmap|0x4)
#define AI_IRRMESH_MAT_lightmap_m4 (AI_IRRMESH_MAT_lightmap|0x8)
#define AI_IRRMESH_MAT_lightmap_light (AI_IRRMESH_MAT_lightmap|0x10)
#define AI_IRRMESH_MAT_lightmap_light_m2 (AI_IRRMESH_MAT_lightmap|0x20)
#define AI_IRRMESH_MAT_lightmap_light_m4 (AI_IRRMESH_MAT_lightmap|0x40)
#define AI_IRRMESH_MAT_lightmap_add (AI_IRRMESH_MAT_lightmap|0x80)
// Standard NormalMap (or Parallax map, they're treated equally)
#define AI_IRRMESH_MAT_normalmap_solid (0x100)
// Normal map combined with vertex alpha
#define AI_IRRMESH_MAT_normalmap_tva \
(AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_vertex_alpha)
// Normal map combined with additive transparency
#define AI_IRRMESH_MAT_normalmap_ta \
(AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_add)
// Special flag. It indicates a second texture has been found
// Its type depends ... either a normal textue or a normal map
#define AI_IRRMESH_EXTRA_2ND_TEXTURE 0x100000
// ---------------------------------------------------------------------------
/** Base class for the Irr and IrrMesh importers.
*
* Declares some irrlight-related xml parsing utilities and provides tools
* to load materials from IRR and IRRMESH files.
*/
class IrrlichtBase
{
protected:
/** @brief Data structure for a simple name-value property
*/
template <class T>
struct Property
{
std::string name;
T value;
};
typedef Property<uint32_t> HexProperty;
typedef Property<std::string> StringProperty;
typedef Property<bool> BoolProperty;
typedef Property<float> FloatProperty;
typedef Property<aiVector3D> VectorProperty;
typedef Property<int> IntProperty;
/** XML reader instance
*/
irr::io::IrrXMLReader* reader;
// -------------------------------------------------------------------
/** Parse a material description from the XML
* @return The created material
* @param matFlags Receives AI_IRRMESH_MAT_XX flags
*/
aiMaterial* ParseMaterial(unsigned int& matFlags);
// -------------------------------------------------------------------
/** Read a property of the specified type from the current XML element.
* @param out Receives output data
*/
void ReadHexProperty (HexProperty& out);
void ReadStringProperty (StringProperty& out);
void ReadBoolProperty (BoolProperty& out);
void ReadFloatProperty (FloatProperty& out);
void ReadVectorProperty (VectorProperty& out);
void ReadIntProperty (IntProperty& out);
};
// ------------------------------------------------------------------------------------------------
// Unpack a hex color, e.g. 0xdcdedfff
inline void ColorFromARGBPacked(uint32_t in, aiColor4D& clr)
{
clr.a = ((in >> 24) & 0xff) / 255.f;
clr.r = ((in >> 16) & 0xff) / 255.f;
clr.g = ((in >> 8) & 0xff) / 255.f;
clr.b = ((in ) & 0xff) / 255.f;
}
} // end namespace Assimp
#endif // !! INCLUDED_AI_IRRSHARED_H