Merge branch 'master' into FindInvalidData

pull/3294/head
Kim Kulling 2020-06-25 16:41:24 +02:00 committed by GitHub
commit ba6af9ff98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
163 changed files with 10004 additions and 10525 deletions

View File

@ -0,0 +1,707 @@
/*
---------------------------------------------------------------------------
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,
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 AMFImporter.cpp
/// \brief AMF-format files importer for Assimp: main algorithm implementation.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
// Header files, Assimp.
#include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/fast_atof.h>
#include <assimp/DefaultIOSystem.h>
// Header files, stdlib.
#include <memory>
namespace Assimp
{
/// \var aiImporterDesc AMFImporter::Description
/// Conastant which hold importer description
const aiImporterDesc AMFImporter::Description = {
"Additive manufacturing file format(AMF) Importer",
"smalcom",
"",
"See documentation in source code. Chapter: Limitations.",
aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
0,
0,
0,
0,
"amf"
};
void AMFImporter::Clear()
{
mNodeElement_Cur = nullptr;
mUnit.clear();
mMaterial_Converted.clear();
mTexture_Converted.clear();
// Delete all elements
if(!mNodeElement_List.empty())
{
for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; }
mNodeElement_List.clear();
}
}
AMFImporter::~AMFImporter()
{
if(mReader != nullptr) delete mReader;
// Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
Clear();
}
/*********************************************************************************************************************************************/
/************************************************************ Functions: find set ************************************************************/
/*********************************************************************************************************************************************/
bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const
{
for(CAMFImporter_NodeElement* ne: mNodeElement_List)
{
if((ne->ID == pID) && (ne->Type == pType))
{
if(pNodeElement != nullptr) *pNodeElement = ne;
return true;
}
}// for(CAMFImporter_NodeElement* ne: mNodeElement_List)
return false;
}
bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
{
aiString node_name(pID.c_str());
for(aiNode* node: pNodeList)
{
if(node->mName == node_name)
{
if(pNode != nullptr) *pNode = node;
return true;
}
}// for(aiNode* node: pNodeList)
return false;
}
bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
{
for(const SPP_Material& mat: mMaterial_Converted)
{
if(mat.ID == pID)
{
if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat;
return true;
}
}// for(const SPP_Material& mat: mMaterial_Converted)
return false;
}
/*********************************************************************************************************************************************/
/************************************************************ Functions: throw set ***********************************************************/
/*********************************************************************************************************************************************/
void AMFImporter::Throw_CloseNotFound(const std::string& pNode)
{
throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
}
void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName)
{
throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
}
void AMFImporter::Throw_IncorrectAttrValue(const std::string& pAttrName)
{
throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value.");
}
void AMFImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription)
{
throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription);
}
void AMFImporter::Throw_ID_NotFound(const std::string& pID) const
{
throw DeadlyImportError("Not found node with name \"" + pID + "\".");
}
/*********************************************************************************************************************************************/
/************************************************************* Functions: XML set ************************************************************/
/*********************************************************************************************************************************************/
void AMFImporter::XML_CheckNode_MustHaveChildren()
{
if(mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children.");
}
void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
{
static const size_t Uns_Skip_Len = 3;
const char* Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" };
static bool skipped_before[Uns_Skip_Len] = { false, false, false };
std::string nn(mReader->getNodeName());
bool found = false;
bool close_found = false;
size_t sk_idx;
for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
{
if(nn != Uns_Skip[sk_idx]) continue;
found = true;
if(mReader->isEmptyElement())
{
close_found = true;
goto casu_cres;
}
while(mReader->read())
{
if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName()))
{
close_found = true;
goto casu_cres;
}
}
}// for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
casu_cres:
if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
if(!close_found) Throw_CloseNotFound(nn);
if(!skipped_before[sk_idx])
{
skipped_before[sk_idx] = true;
ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, ".");
}
}
bool AMFImporter::XML_SearchNode(const std::string& pNodeName)
{
while(mReader->read())
{
if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
}
return false;
}
bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
{
std::string val(mReader->getAttributeValue(pAttrIdx));
if((val == "false") || (val == "0"))
return false;
else if((val == "true") || (val == "1"))
return true;
else
throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\"");
}
float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
{
std::string val;
float tvalf;
ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
fast_atoreal_move(val.c_str(), tvalf, false);
return tvalf;
}
uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
{
return strtoul10(mReader->getAttributeValue(pAttrIdx));
}
float AMFImporter::XML_ReadNode_GetVal_AsFloat()
{
std::string val;
float tvalf;
if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt.");
if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt.");
ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val);
fast_atoreal_move(val.c_str(), tvalf, false);
return tvalf;
}
uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32()
{
if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt.");
if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt.");
return strtoul10(mReader->getNodeData());
}
void AMFImporter::XML_ReadNode_GetVal_AsString(std::string& pValue)
{
if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt.");
if(mReader->getNodeType() != irr::io::EXN_TEXT)
throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt.");
pValue = mReader->getNodeData();
}
/*********************************************************************************************************************************************/
/************************************************************ Functions: parse set ***********************************************************/
/*********************************************************************************************************************************************/
void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode)
{
mNodeElement_Cur->Child.push_back(pNode);// add new element to current element child list.
mNodeElement_Cur = pNode;// switch current element to new one.
}
void AMFImporter::ParseHelper_Node_Exit()
{
// check if we can walk up.
if(mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent;
}
void AMFImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
{
size_t instr_len;
pOutString.clear();
instr_len = strlen(pInStr);
if(!instr_len) return;
pOutString.reserve(instr_len * 3 / 2);
// check and correct floats in format ".x". Must be "x.y".
if(pInStr[0] == '.') pOutString.push_back('0');
pOutString.push_back(pInStr[0]);
for(size_t ci = 1; ci < instr_len; ci++)
{
if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t')))
{
pOutString.push_back('0');
pOutString.push_back('.');
}
else
{
pOutString.push_back(pInStr[ci]);
}
}
}
static bool ParseHelper_Decode_Base64_IsBase64(const char pChar)
{
return (isalnum(pChar) || (pChar == '+') || (pChar == '/'));
}
void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const
{
// With help from
// René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html
const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uint8_t tidx = 0;
uint8_t arr4[4], arr3[3];
// check input data
if(pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
// prepare output place
pOutputData.clear();
pOutputData.reserve(pInputBase64.size() / 4 * 3);
for(size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--)
{
if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
{
arr4[tidx++] = pInputBase64[in_idx++];
if(tidx == 4)
{
for(tidx = 0; tidx < 4; tidx++) arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]);
arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
for(tidx = 0; tidx < 3; tidx++) pOutputData.push_back(arr3[tidx]);
tidx = 0;
}// if(tidx == 4)
}// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
else
{
in_idx++;
}// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else
}
if(tidx)
{
for(uint8_t i = tidx; i < 4; i++) arr4[i] = 0;
for(uint8_t i = 0; i < 4; i++) arr4[i] = (uint8_t)(base64_chars.find(arr4[i]));
arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
for(uint8_t i = 0; i < (tidx - 1); i++) pOutputData.push_back(arr3[i]);
}
}
void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
{
irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
}
// generate a XML reader for it
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
//
// start reading
// search for root tag <amf>
if(XML_SearchNode("amf"))
ParseNode_Root();
else
throw DeadlyImportError("Root node \"amf\" not found.");
delete mReader;
// restore old XMLreader
mReader = OldReader;
}
// <amf
// unit="" - The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
// version="" - Version of file format.
// >
// </amf>
// Root XML element.
// Multi elements - No.
void AMFImporter::ParseNode_Root()
{
std::string unit, version;
CAMFImporter_NodeElement *ne( nullptr );
// Read attributes for node <amf>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue);
MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND_WSKIP;
// Check attributes
if(!mUnit.empty())
{
if((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit");
}
// create root node element.
ne = new CAMFImporter_NodeElement_Root(nullptr);
mNodeElement_Cur = ne;// set first "current" element
// and assign attribute's values
((CAMFImporter_NodeElement_Root*)ne)->Unit = unit;
((CAMFImporter_NodeElement_Root*)ne)->Version = version;
// Check for child nodes
if(!mReader->isEmptyElement())
{
MACRO_NODECHECK_LOOPBEGIN("amf");
if(XML_CheckNode_NameEqual("object")) { ParseNode_Object(); continue; }
if(XML_CheckNode_NameEqual("material")) { ParseNode_Material(); continue; }
if(XML_CheckNode_NameEqual("texture")) { ParseNode_Texture(); continue; }
if(XML_CheckNode_NameEqual("constellation")) { ParseNode_Constellation(); continue; }
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("amf");
mNodeElement_Cur = ne;// force restore "current" element
}// if(!mReader->isEmptyElement())
mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
}
// <constellation
// id="" - The Object ID of the new constellation being defined.
// >
// </constellation>
// A collection of objects or constellations with specific relative locations.
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Constellation()
{
std::string id;
CAMFImporter_NodeElement* ne( nullptr );
// Read attributes for node <constellation>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// create and if needed - define new grouping object.
ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur);
CAMFImporter_NodeElement_Constellation& als = *((CAMFImporter_NodeElement_Constellation*)ne);// alias for convenience
if(!id.empty()) als.ID = id;
// Check for child nodes
if(!mReader->isEmptyElement())
{
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("constellation");
if(XML_CheckNode_NameEqual("instance")) { ParseNode_Instance(); continue; }
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("constellation");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <instance
// objectid="" - The Object ID of the new constellation being defined.
// >
// </instance>
// A collection of objects or constellations with specific relative locations.
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Instance()
{
std::string objectid;
CAMFImporter_NodeElement* ne( nullptr );
// Read attributes for node <constellation>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// used object id must be defined, check that.
if(objectid.empty()) throw DeadlyImportError("\"objectid\" in <instance> must be defined.");
// create and define new grouping object.
ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur);
CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);// alias for convenience
als.ObjectID = objectid;
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool read_flag[6] = { false, false, false, false, false, false };
als.Delta.Set(0, 0, 0);
als.Rotation.Set(0, 0, 0);
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("instance");
MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x);
MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y);
MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z);
MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x);
MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y);
MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z);
MACRO_NODECHECK_LOOPEND("instance");
ParseHelper_Node_Exit();
// also convert degrees to radians.
als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f;
als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f;
als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f;
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <object
// id="" - A unique ObjectID for the new object being defined.
// >
// </object>
// An object definition.
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Object()
{
std::string id;
CAMFImporter_NodeElement* ne( nullptr );
// Read attributes for node <object>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// create and if needed - define new geometry object.
ne = new CAMFImporter_NodeElement_Object(mNodeElement_Cur);
CAMFImporter_NodeElement_Object& als = *((CAMFImporter_NodeElement_Object*)ne);// alias for convenience
if(!id.empty()) als.ID = id;
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool col_read = false;
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("object");
if(XML_CheckNode_NameEqual("color"))
{
// Check if color already defined for object.
if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <object>.");
// read data and set flag about it
ParseNode_Color();
col_read = true;
continue;
}
if(XML_CheckNode_NameEqual("mesh")) { ParseNode_Mesh(); continue; }
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("object");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <metadata
// type="" - The type of the attribute.
// >
// </metadata>
// Specify additional information about an entity.
// Multi elements - Yes.
// Parent element - <amf>, <object>, <volume>, <material>, <vertex>.
//
// Reserved types are:
// "Name" - The alphanumeric label of the entity, to be used by the interpreter if interacting with the user.
// "Description" - A description of the content of the entity
// "URL" - A link to an external resource relating to the entity
// "Author" - Specifies the name(s) of the author(s) of the entity
// "Company" - Specifying the company generating the entity
// "CAD" - specifies the name of the originating CAD software and version
// "Revision" - specifies the revision of the entity
// "Tolerance" - specifies the desired manufacturing tolerance of the entity in entity's unit system
// "Volume" - specifies the total volume of the entity, in the entity's unit system, to be used for verification (object and volume only)
void AMFImporter::ParseNode_Metadata()
{
std::string type, value;
CAMFImporter_NodeElement* ne( nullptr );
// read attribute
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// and value of node.
value = mReader->getNodeData();
// Create node element and assign read data.
ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur);
((CAMFImporter_NodeElement_Metadata*)ne)->Type = type;
((CAMFImporter_NodeElement_Metadata*)ne)->Value = value;
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
/*********************************************************************************************************************************************/
/******************************************************** Functions: BaseImporter set ********************************************************/
/*********************************************************************************************************************************************/
bool AMFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const
{
const std::string extension = GetExtension(pFile);
if ( extension == "amf" ) {
return true;
}
if(!extension.length() || pCheckSig)
{
const char* tokens[] = { "<amf" };
return SearchFileHeaderForToken( pIOHandler, pFile, tokens, 1 );
}
return false;
}
void AMFImporter::GetExtensionList(std::set<std::string>& pExtensionList)
{
pExtensionList.insert("amf");
}
const aiImporterDesc* AMFImporter::GetInfo () const
{
return &Description;
}
void AMFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
Clear();// delete old graph.
ParseFile(pFile, pIOHandler);
Postprocess_BuildScene(pScene);
// scene graph is ready, exit.
}
}// namespace Assimp
#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER

View File

@ -367,7 +367,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type
aiTextureMapMode_Wrap, aiTextureMapMode_Wrap aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
}; };
ai_real blend = 1.0; ai_real blend = 1.0;
if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) { if (mat.GetTexture(type, 0, &path, nullptr, nullptr, &blend, nullptr, map_mode) != AI_SUCCESS || !path.length) {
return; return;
} }

View File

@ -462,30 +462,28 @@ struct Material {
sTexAmbient(other.sTexAmbient), sTexAmbient(other.sTexAmbient),
mTwoSided(other.mTwoSided) { mTwoSided(other.mTwoSided) {
// empty // empty
} }
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) AI_NO_EXCEPT : Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
mName(std::move(other.mName)), mDiffuse(std::move(other.mDiffuse)),
mDiffuse(std::move(other.mDiffuse)), mSpecularExponent(std::move(other.mSpecularExponent)),
mSpecularExponent(std::move(other.mSpecularExponent)), mShininessStrength(std::move(other.mShininessStrength)),
mShininessStrength(std::move(other.mShininessStrength)), mSpecular(std::move(other.mSpecular)),
mSpecular(std::move(other.mSpecular)), mAmbient(std::move(other.mAmbient)),
mAmbient(std::move(other.mAmbient)), mShading(std::move(other.mShading)),
mShading(std::move(other.mShading)), mTransparency(std::move(other.mTransparency)),
mTransparency(std::move(other.mTransparency)), sTexDiffuse(std::move(other.sTexDiffuse)),
sTexDiffuse(std::move(other.sTexDiffuse)), sTexOpacity(std::move(other.sTexOpacity)),
sTexOpacity(std::move(other.sTexOpacity)), sTexSpecular(std::move(other.sTexSpecular)),
sTexSpecular(std::move(other.sTexSpecular)), sTexReflective(std::move(other.sTexReflective)),
sTexReflective(std::move(other.sTexReflective)), sTexBump(std::move(other.sTexBump)),
sTexBump(std::move(other.sTexBump)), sTexEmissive(std::move(other.sTexEmissive)),
sTexEmissive(std::move(other.sTexEmissive)), sTexShininess(std::move(other.sTexShininess)),
sTexShininess(std::move(other.sTexShininess)), mBumpHeight(std::move(other.mBumpHeight)),
mBumpHeight(std::move(other.mBumpHeight)), mEmissive(std::move(other.mEmissive)),
mEmissive(std::move(other.mEmissive)), sTexAmbient(std::move(other.sTexAmbient)),
sTexAmbient(std::move(other.sTexAmbient)), mTwoSided(std::move(other.mTwoSided)) {
mTwoSided(std::move(other.mTwoSided)) {
// empty // empty
} }
@ -615,7 +613,12 @@ struct Node {
Node() = delete; Node() = delete;
explicit Node(const std::string &name) : explicit Node(const std::string &name) :
mParent(NULL), mName(name), mInstanceNumber(0), mHierarchyPos(0), mHierarchyIndex(0), mInstanceCount(1) { mParent(nullptr),
mName(name),
mInstanceNumber(0),
mHierarchyPos(0),
mHierarchyIndex(0),
mInstanceCount(1) {
aRotationKeys.reserve(20); aRotationKeys.reserve(20);
aPositionKeys.reserve(20); aPositionKeys.reserve(20);
aScalingKeys.reserve(20); aScalingKeys.reserve(20);

View File

@ -314,19 +314,19 @@ private:
++buf; ++buf;
comp[1] = *buf; comp[1] = *buf;
++buf; ++buf;
diffuse.r = static_cast<ai_real>(strtol(comp, NULL, 16)) / ai_real(255.0); diffuse.r = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
comp[0] = *buf; comp[0] = *buf;
++buf; ++buf;
comp[1] = *buf; comp[1] = *buf;
++buf; ++buf;
diffuse.g = static_cast<ai_real>(strtol(comp, NULL, 16)) / ai_real(255.0); diffuse.g = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
comp[0] = *buf; comp[0] = *buf;
++buf; ++buf;
comp[1] = *buf; comp[1] = *buf;
++buf; ++buf;
diffuse.b = static_cast<ai_real>(strtol(comp, NULL, 16)) / ai_real(255.0); diffuse.b = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
if (7 == len) if (7 == len)
return true; return true;
@ -334,7 +334,7 @@ private:
++buf; ++buf;
comp[1] = *buf; comp[1] = *buf;
++buf; ++buf;
diffuse.a = static_cast<ai_real>(strtol(comp, NULL, 16)) / ai_real(255.0); diffuse.a = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
return true; return true;
} }

View File

@ -45,19 +45,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "D3MFOpcPackage.h" #include "D3MFOpcPackage.h"
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include <assimp/ZipArchiveIOSystem.h>
#include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOStream.hpp> #include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/ai_assert.h>
#include <assimp/ZipArchiveIOSystem.h>
#include <cstdlib> #include "3MFXmlTags.h"
#include <memory>
#include <vector>
#include <map>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include "3MFXmlTags.h" #include <cstdlib>
#include <map>
#include <memory>
#include <vector>
namespace Assimp { namespace Assimp {
@ -68,49 +68,45 @@ typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
class OpcPackageRelationshipReader { class OpcPackageRelationshipReader {
public: public:
OpcPackageRelationshipReader(XmlReader* xmlReader) { OpcPackageRelationshipReader(XmlReader *xmlReader) {
while(xmlReader->read()) { while (xmlReader->read()) {
if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT && if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) {
{
ParseRootNode(xmlReader); ParseRootNode(xmlReader);
} }
} }
} }
void ParseRootNode(XmlReader* xmlReader) void ParseRootNode(XmlReader *xmlReader) {
{
ParseAttributes(xmlReader); ParseAttributes(xmlReader);
while(xmlReader->read()) while (xmlReader->read()) {
{ if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE) {
xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE)
{
ParseChildNode(xmlReader); ParseChildNode(xmlReader);
} }
} }
} }
void ParseAttributes(XmlReader*) { void ParseAttributes(XmlReader *) {
// empty // empty
} }
bool validateRels( OpcPackageRelationshipPtr &relPtr ) { bool validateRels(OpcPackageRelationshipPtr &relPtr) {
if ( relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty() ) { if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) {
return false; return false;
} }
return true; return true;
} }
void ParseChildNode(XmlReader* xmlReader) { void ParseChildNode(XmlReader *xmlReader) {
OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship()); OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str()); relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str());
relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str()); relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str());
relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str()); relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str());
if ( validateRels( relPtr ) ) { if (validateRels(relPtr)) {
m_relationShips.push_back( relPtr ); m_relationShips.push_back(relPtr);
} }
} }
@ -118,32 +114,34 @@ public:
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
: mRootStream(nullptr) mRootStream(nullptr), mZipArchive() {
, mZipArchive() { mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
mZipArchive.reset( new ZipArchiveIOSystem( pIOHandler, rFile ) ); if (!mZipArchive->isOpen()) {
if(!mZipArchive->isOpen()) { throw DeadlyImportError("Failed to open file " + rFile + ".");
throw DeadlyImportError("Failed to open file " + rFile+ ".");
} }
std::vector<std::string> fileList; std::vector<std::string> fileList;
mZipArchive->getFileList(fileList); mZipArchive->getFileList(fileList);
for (auto& file: fileList) { for (auto &file : fileList) {
if(file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) { if (file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) {
//PkgRelationshipReader pkgRelReader(file, archive); if (!mZipArchive->Exists(file.c_str())) {
ai_assert(mZipArchive->Exists(file.c_str())); continue;
}
IOStream *fileStream = mZipArchive->Open(file.c_str()); IOStream *fileStream = mZipArchive->Open(file.c_str());
if (nullptr == fileStream) {
ai_assert(fileStream != nullptr); ai_assert(fileStream != nullptr);
continue;
}
std::string rootFile = ReadPackageRootRelationship(fileStream); std::string rootFile = ReadPackageRootRelationship(fileStream);
if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) { if (rootFile.size() > 0 && rootFile[0] == '/') {
rootFile = rootFile.substr( 1 ); rootFile = rootFile.substr(1);
if ( rootFile[ 0 ] == '/' ) { if (rootFile[0] == '/') {
// deal with zip-bug // deal with zip-bug
rootFile = rootFile.substr( 1 ); rootFile = rootFile.substr(1);
} }
} }
@ -152,17 +150,16 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
mZipArchive->Close(fileStream); mZipArchive->Close(fileStream);
mRootStream = mZipArchive->Open(rootFile.c_str()); mRootStream = mZipArchive->Open(rootFile.c_str());
ai_assert( mRootStream != nullptr ); ai_assert(mRootStream != nullptr);
if ( nullptr == mRootStream ) { if (nullptr == mRootStream) {
throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile ); throw DeadlyExportError("Cannot open root-file in archive : " + rootFile);
} }
} else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES",file); ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file);
} else { } else {
ASSIMP_LOG_WARN_F("Ignored file of unknown type: ",file); ASSIMP_LOG_WARN_F("Ignored file of unknown type: ", file);
} }
} }
} }
@ -170,32 +167,32 @@ D3MFOpcPackage::~D3MFOpcPackage() {
mZipArchive->Close(mRootStream); mZipArchive->Close(mRootStream);
} }
IOStream* D3MFOpcPackage::RootStream() const { IOStream *D3MFOpcPackage::RootStream() const {
return mRootStream; return mRootStream;
} }
static const std::string ModelRef = "3D/3dmodel.model"; static const std::string ModelRef = "3D/3dmodel.model";
bool D3MFOpcPackage::validate() { bool D3MFOpcPackage::validate() {
if ( nullptr == mRootStream || nullptr == mZipArchive ) { if (nullptr == mRootStream || nullptr == mZipArchive) {
return false; return false;
} }
return mZipArchive->Exists( ModelRef.c_str() ); return mZipArchive->Exists(ModelRef.c_str());
} }
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream)); std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get())); std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
OpcPackageRelationshipReader reader(xml.get()); OpcPackageRelationshipReader reader(xml.get());
auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr& rel){ auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) {
return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
}); });
if ( itr == reader.m_relationShips.end() ) { if (itr == reader.m_relationShips.end()) {
throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE ); throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
} }
return (*itr)->target; return (*itr)->target;

View File

@ -627,7 +627,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name); ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name);
std::vector<aiMesh *> cpy(meshes.size() - oldm, NULL); std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr);
div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true); div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true);
std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm); std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm);

View File

@ -366,7 +366,9 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *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 // Check whether we can read from the file
if (file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + "."); if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
}
// generate a XML reader for it // generate a XML reader for it
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get())); std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));

View File

@ -925,7 +925,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode &mesh) {
ASSIMP_LOG_ERROR("ASE: Found target animation channel " ASSIMP_LOG_ERROR("ASE: Found target animation channel "
"but the node is neither a camera nor a spot light"); "but the node is neither a camera nor a spot light");
anim = NULL; anim = nullptr;
} else } else
anim = &mesh.mTargetAnim; anim = &mesh.mTargetAnim;
} }
@ -1797,14 +1797,14 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLongTriple(unsigned int *apOut) { void Parser::ParseLV4MeshLongTriple(unsigned int *apOut) {
ai_assert(NULL != apOut); ai_assert(nullptr != apOut);
for (unsigned int i = 0; i < 3; ++i) for (unsigned int i = 0; i < 3; ++i)
ParseLV4MeshLong(apOut[i]); ParseLV4MeshLong(apOut[i]);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut) { void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut) {
ai_assert(NULL != apOut); ai_assert(nullptr != apOut);
// parse the index // parse the index
ParseLV4MeshLong(rIndexOut); ParseLV4MeshLong(rIndexOut);
@ -1814,7 +1814,7 @@ void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) { void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) {
ai_assert(NULL != apOut); ai_assert(nullptr != apOut);
// parse the index // parse the index
ParseLV4MeshLong(rIndexOut); ParseLV4MeshLong(rIndexOut);
@ -1824,7 +1824,7 @@ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) { void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) {
ai_assert(NULL != apOut); ai_assert(nullptr != apOut);
for (unsigned int i = 0; i < 3; ++i) for (unsigned int i = 0; i < 3; ++i)
ParseLV4MeshFloat(apOut[i]); ParseLV4MeshFloat(apOut[i]);

View File

@ -40,15 +40,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file Defines the helper data structures for importing ASE files */ /** @file Defines the helper data structures for importing ASE files */
#ifndef AI_ASEFILEHELPER_H_INC #ifndef AI_ASEFILEHELPER_H_INC
#define AI_ASEFILEHELPER_H_INC #define AI_ASEFILEHELPER_H_INC
// public ASSIMP headers // public ASSIMP headers
#include <assimp/types.h>
#include <assimp/mesh.h>
#include <assimp/anim.h> #include <assimp/anim.h>
#include <assimp/mesh.h>
#include <assimp/types.h>
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
@ -59,27 +58,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ASE is quite similar to 3ds. We can reuse some structures // ASE is quite similar to 3ds. We can reuse some structures
#include "AssetLib/3DS/3DSLoader.h" #include "AssetLib/3DS/3DSLoader.h"
namespace Assimp { namespace Assimp {
namespace ASE { namespace ASE {
using namespace D3DS; using namespace D3DS;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing an ASE material */ /** Helper structure representing an ASE material */
struct Material : public D3DS::Material struct Material : public D3DS::Material {
{
//! Default constructor has been deleted //! Default constructor has been deleted
Material() = delete; Material() = delete;
//! Constructor with explicit name //! Constructor with explicit name
explicit Material(const std::string &name) explicit Material(const std::string &name) :
: D3DS::Material(name) D3DS::Material(name),
, pcInstance(NULL) pcInstance(nullptr),
, bNeed (false) { bNeed(false) {
// empty // empty
} }
Material(const Material &other) = default; Material(const Material &other) = default;
Material &operator=(const Material &other) { Material &operator=(const Material &other) {
if (this == &other) { if (this == &other) {
@ -93,19 +91,16 @@ struct Material : public D3DS::Material
return *this; return *this;
} }
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) AI_NO_EXCEPT Material(Material &&other) AI_NO_EXCEPT
: D3DS::Material(std::move(other)) : D3DS::Material(std::move(other)),
, avSubMaterials(std::move(other.avSubMaterials)) avSubMaterials(std::move(other.avSubMaterials)),
, pcInstance(std::move(other.pcInstance)) pcInstance(std::move(other.pcInstance)),
, bNeed(std::move(other.bNeed)) bNeed(std::move(other.bNeed)) {
{
other.pcInstance = nullptr; other.pcInstance = nullptr;
} }
Material &operator=(Material &&other) AI_NO_EXCEPT {
Material &operator=( Material &&other) AI_NO_EXCEPT {
if (this == &other) { if (this == &other) {
return *this; return *this;
} }
@ -121,15 +116,13 @@ struct Material : public D3DS::Material
return *this; return *this;
} }
~Material() {} ~Material() {}
//! Contains all sub materials of this material //! Contains all sub materials of this material
std::vector<Material> avSubMaterials; std::vector<Material> avSubMaterials;
//! aiMaterial object //! aiMaterial object
aiMaterial* pcInstance; aiMaterial *pcInstance;
//! Can we remove this material? //! Can we remove this material?
bool bNeed; bool bNeed;
@ -140,8 +133,8 @@ struct Material : public D3DS::Material
struct Face : public FaceWithSmoothingGroup { struct Face : public FaceWithSmoothingGroup {
//! Default constructor. Initializes everything with 0 //! Default constructor. Initializes everything with 0
Face() AI_NO_EXCEPT Face() AI_NO_EXCEPT
: iMaterial(DEFAULT_MATINDEX) : iMaterial(DEFAULT_MATINDEX),
, iFace(0) { iFace(0) {
// empty // empty
} }
@ -172,8 +165,8 @@ struct Bone {
Bone() = delete; Bone() = delete;
//! Construction from an existing name //! Construction from an existing name
explicit Bone( const std::string& name) explicit Bone(const std::string &name) :
: mName(name) { mName(name) {
// empty // empty
} }
@ -186,33 +179,34 @@ struct Bone {
struct BoneVertex { struct BoneVertex {
//! Bone and corresponding vertex weight. //! Bone and corresponding vertex weight.
//! -1 for unrequired bones .... //! -1 for unrequired bones ....
std::vector<std::pair<int,float> > mBoneWeights; std::vector<std::pair<int, float>> mBoneWeights;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file animation */ /** Helper structure to represent an ASE file animation */
struct Animation { struct Animation {
enum Type { enum Type {
TRACK = 0x0, TRACK = 0x0,
BEZIER = 0x1, BEZIER = 0x1,
TCB = 0x2 TCB = 0x2
} mRotationType, mScalingType, mPositionType; } mRotationType,
mScalingType, mPositionType;
Animation() AI_NO_EXCEPT Animation() AI_NO_EXCEPT
: mRotationType (TRACK) : mRotationType(TRACK),
, mScalingType (TRACK) mScalingType(TRACK),
, mPositionType (TRACK) { mPositionType(TRACK) {
// empty // empty
} }
//! List of track rotation keyframes //! List of track rotation keyframes
std::vector< aiQuatKey > akeyRotations; std::vector<aiQuatKey> akeyRotations;
//! List of track position keyframes //! List of track position keyframes
std::vector< aiVectorKey > akeyPositions; std::vector<aiVectorKey> akeyPositions;
//! List of track scaling keyframes //! List of track scaling keyframes
std::vector< aiVectorKey > akeyScaling; std::vector<aiVectorKey> akeyScaling;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -220,7 +214,7 @@ struct Animation {
struct InheritanceInfo { struct InheritanceInfo {
//! Default constructor //! Default constructor
InheritanceInfo() AI_NO_EXCEPT { InheritanceInfo() AI_NO_EXCEPT {
for ( size_t i=0; i<3; ++i ) { for (size_t i = 0; i < 3; ++i) {
abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true; abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
} }
} }
@ -239,17 +233,15 @@ struct InheritanceInfo {
/** Represents an ASE file node. Base class for mesh, light and cameras */ /** Represents an ASE file node. Base class for mesh, light and cameras */
struct BaseNode { struct BaseNode {
enum Type { enum Type {
Light, Light,
Camera, Camera,
Mesh, Mesh,
Dummy Dummy
} mType; } mType;
//! Construction from an existing name //! Construction from an existing name
BaseNode(Type _mType, const std::string &name) BaseNode(Type _mType, const std::string &name) :
: mType (_mType) mType(_mType), mName(name), mProcessed(false) {
, mName (name)
, mProcessed (false) {
// Set mTargetPosition to qnan // Set mTargetPosition to qnan
const ai_real qnan = get_qnan(); const ai_real qnan = get_qnan();
mTargetPosition.x = qnan; mTargetPosition.x = qnan;
@ -289,14 +281,9 @@ struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode {
Mesh() = delete; Mesh() = delete;
//! Construction from an existing name //! Construction from an existing name
explicit Mesh(const std::string &name) explicit Mesh(const std::string &name) :
: BaseNode( BaseNode::Mesh, name ) BaseNode(BaseNode::Mesh, name), mVertexColors(), mBoneVertices(), mBones(), iMaterialIndex(Face::DEFAULT_MATINDEX), bSkip(false) {
, mVertexColors() for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) {
, mBoneVertices()
, mBones()
, iMaterialIndex(Face::DEFAULT_MATINDEX)
, bSkip (false) {
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
this->mNumUVComponents[c] = 2; this->mNumUVComponents[c] = 2;
} }
} }
@ -325,10 +312,8 @@ struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE light source */ /** Helper structure to represent an ASE light source */
struct Light : public BaseNode struct Light : public BaseNode {
{ enum LightType {
enum LightType
{
OMNI, OMNI,
TARGET, TARGET,
FREE, FREE,
@ -339,17 +324,13 @@ struct Light : public BaseNode
Light() = delete; Light() = delete;
//! Construction from an existing name //! Construction from an existing name
explicit Light(const std::string &name) explicit Light(const std::string &name) :
: BaseNode (BaseNode::Light, name) BaseNode(BaseNode::Light, name), mLightType(OMNI), mColor(1.f, 1.f, 1.f), mIntensity(1.f) // light is white by default
, mLightType (OMNI) ,
, mColor (1.f,1.f,1.f) mAngle(45.f),
, mIntensity (1.f) // light is white by default mFalloff(0.f) {
, mAngle (45.f)
, mFalloff (0.f)
{
} }
LightType mLightType; LightType mLightType;
aiColor3D mColor; aiColor3D mColor;
ai_real mIntensity; ai_real mIntensity;
@ -359,10 +340,8 @@ struct Light : public BaseNode
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE camera */ /** Helper structure to represent an ASE camera */
struct Camera : public BaseNode struct Camera : public BaseNode {
{ enum CameraType {
enum CameraType
{
FREE, FREE,
TARGET TARGET
}; };
@ -370,18 +349,16 @@ struct Camera : public BaseNode
//! Default constructor has been deleted //! Default constructor has been deleted
Camera() = delete; Camera() = delete;
//! Construction from an existing name //! Construction from an existing name
explicit Camera(const std::string &name) explicit Camera(const std::string &name) :
: BaseNode (BaseNode::Camera, name) BaseNode(BaseNode::Camera, name), mFOV(0.75f) // in radians
, mFOV (0.75f) // in radians ,
, mNear (0.1f) mNear(0.1f),
, mFar (1000.f) // could be zero mFar(1000.f) // could be zero
, mCameraType (FREE) ,
{ mCameraType(FREE) {
} }
ai_real mFOV, mNear, mFar; ai_real mFOV, mNear, mFar;
CameraType mCameraType; CameraType mCameraType;
}; };
@ -391,7 +368,7 @@ struct Camera : public BaseNode
struct Dummy : public BaseNode { struct Dummy : public BaseNode {
//! Constructor //! Constructor
Dummy() AI_NO_EXCEPT Dummy() AI_NO_EXCEPT
: BaseNode (BaseNode::Dummy, "DUMMY") { : BaseNode(BaseNode::Dummy, "DUMMY") {
// empty // empty
} }
}; };
@ -414,7 +391,6 @@ private:
} }
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Construct a parser from a given input file which is //! Construct a parser from a given input file which is
//! guaranteed to be terminated with zero. //! guaranteed to be terminated with zero.
@ -422,15 +398,13 @@ public:
//! @param fileFormatDefault Assumed file format version. If the //! @param fileFormatDefault Assumed file format version. If the
//! file format is specified in the file the new value replaces //! file format is specified in the file the new value replaces
//! the default value. //! the default value.
Parser (const char* szFile, unsigned int fileFormatDefault); Parser(const char *szFile, unsigned int fileFormatDefault);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parses the file into the parsers internal representation //! Parses the file into the parsers internal representation
void Parse(); void Parse();
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse the *SCENE block in a file //! Parse the *SCENE block in a file
void ParseLV1SceneBlock(); void ParseLV1SceneBlock();
@ -446,45 +420,45 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *<xxx>OBJECT block in a file //! Parse a *<xxx>OBJECT block in a file
//! \param mesh Node to be filled //! \param mesh Node to be filled
void ParseLV1ObjectBlock(BaseNode& mesh); void ParseLV1ObjectBlock(BaseNode &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MATERIAL blocks in a material list //! Parse a *MATERIAL blocks in a material list
//! \param mat Material structure to be filled //! \param mat Material structure to be filled
void ParseLV2MaterialBlock(Material& mat); void ParseLV2MaterialBlock(Material &mat);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *NODE_TM block in a file //! Parse a *NODE_TM block in a file
//! \param mesh Node (!) object to be filled //! \param mesh Node (!) object to be filled
void ParseLV2NodeTransformBlock(BaseNode& mesh); void ParseLV2NodeTransformBlock(BaseNode &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *TM_ANIMATION block in a file //! Parse a *TM_ANIMATION block in a file
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV2AnimationBlock(BaseNode& mesh); void ParseLV2AnimationBlock(BaseNode &mesh);
void ParseLV3PosAnimationBlock(ASE::Animation& anim); void ParseLV3PosAnimationBlock(ASE::Animation &anim);
void ParseLV3ScaleAnimationBlock(ASE::Animation& anim); void ParseLV3ScaleAnimationBlock(ASE::Animation &anim);
void ParseLV3RotAnimationBlock(ASE::Animation& anim); void ParseLV3RotAnimationBlock(ASE::Animation &anim);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH block in a file //! Parse a *MESH block in a file
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV2MeshBlock(Mesh& mesh); void ParseLV2MeshBlock(Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *LIGHT_SETTINGS block in a file //! Parse a *LIGHT_SETTINGS block in a file
//! \param light Light object to be filled //! \param light Light object to be filled
void ParseLV2LightSettingsBlock(Light& light); void ParseLV2LightSettingsBlock(Light &light);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *CAMERA_SETTINGS block in a file //! Parse a *CAMERA_SETTINGS block in a file
//! \param cam Camera object to be filled //! \param cam Camera object to be filled
void ParseLV2CameraSettingsBlock(Camera& cam); void ParseLV2CameraSettingsBlock(Camera &cam);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse the *MAP_XXXXXX blocks in a material //! Parse the *MAP_XXXXXX blocks in a material
//! \param map Texture structure to be filled //! \param map Texture structure to be filled
void ParseLV3MapBlock(Texture& map); void ParseLV3MapBlock(Texture &map);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_VERTEX_LIST block in a file //! Parse a *MESH_VERTEX_LIST block in a file
@ -493,7 +467,7 @@ private:
//! A warning is sent to the logger if the validations fails. //! A warning is sent to the logger if the validations fails.
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV3MeshVertexListBlock( void ParseLV3MeshVertexListBlock(
unsigned int iNumVertices,Mesh& mesh); unsigned int iNumVertices, Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_FACE_LIST block in a file //! Parse a *MESH_FACE_LIST block in a file
@ -502,7 +476,7 @@ private:
//! A warning is sent to the logger if the validations fails. //! A warning is sent to the logger if the validations fails.
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV3MeshFaceListBlock( void ParseLV3MeshFaceListBlock(
unsigned int iNumFaces,Mesh& mesh); unsigned int iNumFaces, Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_TVERT_LIST block in a file //! Parse a *MESH_TVERT_LIST block in a file
@ -512,7 +486,7 @@ private:
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
//! \param iChannel Output UVW channel //! \param iChannel Output UVW channel
void ParseLV3MeshTListBlock( void ParseLV3MeshTListBlock(
unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0); unsigned int iNumVertices, Mesh &mesh, unsigned int iChannel = 0);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_TFACELIST block in a file //! Parse a *MESH_TFACELIST block in a file
@ -522,7 +496,7 @@ private:
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
//! \param iChannel Output UVW channel //! \param iChannel Output UVW channel
void ParseLV3MeshTFaceListBlock( void ParseLV3MeshTFaceListBlock(
unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0); unsigned int iNumFaces, Mesh &mesh, unsigned int iChannel = 0);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse an additional mapping channel //! Parse an additional mapping channel
@ -530,7 +504,7 @@ private:
//! \param iChannel Channel index to be filled //! \param iChannel Channel index to be filled
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV3MappingChannel( void ParseLV3MappingChannel(
unsigned int iChannel, Mesh& mesh); unsigned int iChannel, Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_CVERTLIST block in a file //! Parse a *MESH_CVERTLIST block in a file
@ -539,7 +513,7 @@ private:
//! A warning is sent to the logger if the validations fails. //! A warning is sent to the logger if the validations fails.
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV3MeshCListBlock( void ParseLV3MeshCListBlock(
unsigned int iNumVertices, Mesh& mesh); unsigned int iNumVertices, Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_CFACELIST block in a file //! Parse a *MESH_CFACELIST block in a file
@ -548,70 +522,70 @@ private:
//! A warning is sent to the logger if the validations fails. //! A warning is sent to the logger if the validations fails.
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV3MeshCFaceListBlock( void ParseLV3MeshCFaceListBlock(
unsigned int iNumFaces, Mesh& mesh); unsigned int iNumFaces, Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_NORMALS block in a file //! Parse a *MESH_NORMALS block in a file
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV3MeshNormalListBlock(Mesh& mesh); void ParseLV3MeshNormalListBlock(Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_WEIGHTSblock in a file //! Parse a *MESH_WEIGHTSblock in a file
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
void ParseLV3MeshWeightsBlock(Mesh& mesh); void ParseLV3MeshWeightsBlock(Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse the bone list of a file //! Parse the bone list of a file
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
//! \param iNumBones Number of bones in the mesh //! \param iNumBones Number of bones in the mesh
void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh); void ParseLV4MeshBones(unsigned int iNumBones, Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse the bone vertices list of a file //! Parse the bone vertices list of a file
//! \param mesh Mesh object to be filled //! \param mesh Mesh object to be filled
//! \param iNumVertices Number of vertices to be parsed //! \param iNumVertices Number of vertices to be parsed
void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh); void ParseLV4MeshBonesVertices(unsigned int iNumVertices, Mesh &mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_FACE block in a file //! Parse a *MESH_FACE block in a file
//! \param out receive the face data //! \param out receive the face data
void ParseLV4MeshFace(ASE::Face& out); void ParseLV4MeshFace(ASE::Face &out);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_VERT block in a file //! Parse a *MESH_VERT block in a file
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats) //! \param apOut Output buffer (3 floats)
//! \param rIndexOut Output index //! \param rIndexOut Output index
void ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut); void ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_VERT block in a file //! Parse a *MESH_VERT block in a file
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats) //! \param apOut Output buffer (3 floats)
void ParseLV4MeshFloatTriple(ai_real* apOut); void ParseLV4MeshFloatTriple(ai_real *apOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_TFACE block in a file //! Parse a *MESH_TFACE block in a file
//! (also works for MESH_CFACE) //! (also works for MESH_CFACE)
//! \param apOut Output buffer (3 ints) //! \param apOut Output buffer (3 ints)
//! \param rIndexOut Output index //! \param rIndexOut Output index
void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut); void ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_TFACE block in a file //! Parse a *MESH_TFACE block in a file
//! (also works for MESH_CFACE) //! (also works for MESH_CFACE)
//! \param apOut Output buffer (3 ints) //! \param apOut Output buffer (3 ints)
void ParseLV4MeshLongTriple(unsigned int* apOut); void ParseLV4MeshLongTriple(unsigned int *apOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a single float element //! Parse a single float element
//! \param fOut Output float //! \param fOut Output float
void ParseLV4MeshFloat(ai_real& fOut); void ParseLV4MeshFloat(ai_real &fOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a single int element //! Parse a single int element
//! \param iOut Output integer //! \param iOut Output integer
void ParseLV4MeshLong(unsigned int& iOut); void ParseLV4MeshLong(unsigned int &iOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Skip everything to the next: '*' or '\0' //! Skip everything to the next: '*' or '\0'
@ -625,17 +599,17 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Output a warning to the logger //! Output a warning to the logger
//! \param szWarn Warn message //! \param szWarn Warn message
void LogWarning(const char* szWarn); void LogWarning(const char *szWarn);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Output a message to the logger //! Output a message to the logger
//! \param szWarn Message //! \param szWarn Message
void LogInfo(const char* szWarn); void LogInfo(const char *szWarn);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Output an error to the logger //! Output an error to the logger
//! \param szWarn Error message //! \param szWarn Error message
AI_WONT_RETURN void LogError(const char* szWarn) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void LogError(const char *szWarn) AI_WONT_RETURN_SUFFIX;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a string, enclosed in double quotation marks //! Parse a string, enclosed in double quotation marks
@ -643,12 +617,11 @@ private:
//! \param szName Name of the enclosing element -> used in error //! \param szName Name of the enclosing element -> used in error
//! messages. //! messages.
//! \return false if an error occurred //! \return false if an error occurred
bool ParseString(std::string& out,const char* szName); bool ParseString(std::string &out, const char *szName);
public: public:
//! Pointer to current data //! Pointer to current data
const char* filePtr; const char *filePtr;
//! background color to be passed to the viewer //! background color to be passed to the viewer
//! QNAN if none was found //! QNAN if none was found
@ -695,9 +668,8 @@ public:
unsigned int iFileFormat; unsigned int iFileFormat;
}; };
} // Namespace ASE } // Namespace ASE
} // Namespace ASSIMP } // namespace Assimp
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER #endif // ASSIMP_BUILD_NO_3DS_IMPORTER

View File

@ -336,7 +336,7 @@ protected:
void WriteBinaryNode(IOStream *container, const aiNode *node) { void WriteBinaryNode(IOStream *container, const aiNode *node) {
AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AINODE); AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AINODE);
unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); unsigned int nb_metadata = (node->mMetaData != nullptr ? node->mMetaData->mNumProperties : 0);
Write<aiString>(&chunk, node->mName); Write<aiString>(&chunk, node->mName);
Write<aiMatrix4x4>(&chunk, node->mTransformation); Write<aiMatrix4x4>(&chunk, node->mTransformation);
@ -744,7 +744,7 @@ public:
}; };
try { try {
time_t tt = time(NULL); time_t tt = time(nullptr);
#if _WIN32 #if _WIN32
tm *p = gmtime(&tt); tm *p = gmtime(&tt);
#else #else
@ -790,7 +790,7 @@ public:
// Up to here the data is uncompressed. For compressed files, the rest // Up to here the data is uncompressed. For compressed files, the rest
// is compressed using standard DEFLATE from zlib. // is compressed using standard DEFLATE from zlib.
if (compressed) { if (compressed) {
AssbinChunkWriter uncompressedStream(NULL, 0); AssbinChunkWriter uncompressedStream(nullptr, 0);
WriteBinaryScene(&uncompressedStream, pScene); WriteBinaryScene(&uncompressedStream, pScene);
uLongf uncompressedSize = static_cast<uLongf>(uncompressedStream.Tell()); uLongf uncompressedSize = static_cast<uLongf>(uncompressedStream.Tell());

View File

@ -604,7 +604,7 @@ void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
// Read node graph // Read node graph
//scene->mRootNode = new aiNode[1]; //scene->mRootNode = new aiNode[1];
ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)NULL); ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)nullptr);
// Read all meshes // Read all meshes
if (scene->mNumMeshes) { if (scene->mNumMeshes) {

View File

@ -189,7 +189,7 @@ static std::string encodeXML(const std::string &data) {
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Write a text model dump // Write a text model dump
static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, IOStream *io, bool shortened) { static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, IOStream *io, bool shortened) {
time_t tt = ::time(NULL); time_t tt = ::time(nullptr);
#if _WIN32 #if _WIN32
tm *p = gmtime(&tt); tm *p = gmtime(&tt);
#else #else

View File

@ -422,9 +422,9 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
anim->mNumChannels = static_cast<unsigned int>(mNodes.size()); anim->mNumChannels = static_cast<unsigned int>(mNodes.size());
anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
// FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown // FIX: set the array elements to nullptr to ensure proper deletion if an exception is thrown
for (unsigned int i = 0; i < anim->mNumChannels; ++i) for (unsigned int i = 0; i < anim->mNumChannels; ++i)
anim->mChannels[i] = NULL; anim->mChannels[i] = nullptr;
for (unsigned int a = 0; a < anim->mNumChannels; a++) { for (unsigned int a = 0; a < anim->mNumChannels; a++) {
const Node &node = mNodes[a]; const Node &node = mNodes[a];

View File

@ -230,7 +230,7 @@ public:
// -------------------------------------------------------- // --------------------------------------------------------
/** Access a field of the structure by its canonical name. The pointer version /** Access a field of the structure by its canonical name. The pointer version
* returns NULL on failure while the reference version raises an import error. */ * returns nullptr on failure while the reference version raises an import error. */
inline const Field &operator[](const std::string &ss) const; inline const Field &operator[](const std::string &ss) const;
inline const Field *Get(const std::string &ss) const; inline const Field *Get(const std::string &ss) const;
@ -359,7 +359,7 @@ private:
template <typename T> template <typename T>
T *_allocate(vector<T> &out, size_t &s) const { T *_allocate(vector<T> &out, size_t &s) const {
out.resize(s); out.resize(s);
return s ? &out.front() : NULL; return s ? &out.front() : nullptr;
} }
// -------------------------------------------------------- // --------------------------------------------------------
@ -367,14 +367,14 @@ private:
struct _defaultInitializer { struct _defaultInitializer {
template <typename T, unsigned int N> template <typename T, unsigned int N>
void operator()(T (&out)[N], const char * = NULL) { void operator()(T (&out)[N], const char * = nullptr) {
for (unsigned int i = 0; i < N; ++i) { for (unsigned int i = 0; i < N; ++i) {
out[i] = T(); out[i] = T();
} }
} }
template <typename T, unsigned int N, unsigned int M> template <typename T, unsigned int N, unsigned int M>
void operator()(T (&out)[N][M], const char * = NULL) { void operator()(T (&out)[N][M], const char * = nullptr) {
for (unsigned int i = 0; i < N; ++i) { for (unsigned int i = 0; i < N; ++i) {
for (unsigned int j = 0; j < M; ++j) { for (unsigned int j = 0; j < M; ++j) {
out[i][j] = T(); out[i][j] = T();
@ -383,7 +383,7 @@ private:
} }
template <typename T> template <typename T>
void operator()(T &out, const char * = NULL) { void operator()(T &out, const char * = nullptr) {
out = T(); out = T();
} }
}; };
@ -448,7 +448,7 @@ public:
public: public:
// -------------------------------------------------------- // --------------------------------------------------------
/** Access a structure by its canonical name, the pointer version returns NULL on failure /** Access a structure by its canonical name, the pointer version returns nullptr on failure
* while the reference version raises an error. */ * while the reference version raises an error. */
inline const Structure &operator[](const std::string &ss) const; inline const Structure &operator[](const std::string &ss) const;
inline const Structure *Get(const std::string &ss) const; inline const Structure *Get(const std::string &ss) const;

View File

@ -69,7 +69,7 @@ const Field& Structure :: operator [] (const std::string& ss) const
const Field* Structure :: Get (const std::string& ss) const const Field* Structure :: Get (const std::string& ss) const
{ {
std::map<std::string, size_t>::const_iterator it = indices.find(ss); std::map<std::string, size_t>::const_iterator it = indices.find(ss);
return it == indices.end() ? NULL : &fields[(*it).second]; return it == indices.end() ? nullptr : &fields[(*it).second];
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -322,7 +322,9 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
break; break;
default: default:
ASSIMP_LOG_ERROR("Unknown option.");
ai_assert(false); // shouldn't be here ai_assert(false); // shouldn't be here
break;
} }
mat->AddProperty(&shader, 1, AI_MATKEY_SHADING_MODEL); mat->AddProperty(&shader, 1, AI_MATKEY_SHADING_MODEL);
if (shader != aiShadingMode_Gouraud) { if (shader != aiShadingMode_Gouraud) {

View File

@ -127,7 +127,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
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 // Check whether we can read from the file
if( file.get() == NULL) { if( file.get() == nullptr) {
throw DeadlyImportError( "Failed to open CSM file " + pFile + "."); throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
} }

View File

@ -298,14 +298,14 @@ struct Accessor {
size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on. size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on.
// For example, SubOffset[0] denotes which of the values inside the object is the vector X component. // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
std::string mSource; // URL of the source array std::string mSource; // URL of the source array
mutable const Data *mData; // Pointer to the source array, if resolved. NULL else mutable const Data *mData; // Pointer to the source array, if resolved. nullptr else
Accessor() { Accessor() {
mCount = 0; mCount = 0;
mSize = 0; mSize = 0;
mOffset = 0; mOffset = 0;
mStride = 0; mStride = 0;
mData = NULL; mData = nullptr;
mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0; mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
} }
}; };
@ -321,13 +321,13 @@ struct InputChannel {
size_t mIndex; // Optional index, if multiple sets of the same data type are given size_t mIndex; // Optional index, if multiple sets of the same data type are given
size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better. size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
std::string mAccessor; // ID of the accessor where to read the actual values from. std::string mAccessor; // ID of the accessor where to read the actual values from.
mutable const Accessor *mResolved; // Pointer to the accessor, if resolved. NULL else mutable const Accessor *mResolved; // Pointer to the accessor, if resolved. nullptr else
InputChannel() { InputChannel() {
mType = IT_Invalid; mType = IT_Invalid;
mIndex = 0; mIndex = 0;
mOffset = 0; mOffset = 0;
mResolved = NULL; mResolved = nullptr;
} }
}; };

View File

@ -145,7 +145,7 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
if (extension == "xml" || !extension.length() || checkSig) { if (extension == "xml" || !extension.length() || checkSig) {
/* If CanRead() is called in order to check whether we /* If CanRead() is called in order to check whether we
* support a specific file extension in general pIOHandler * support a specific file extension in general pIOHandler
* might be NULL and it's our duty to return true here. * might be nullptr and it's our duty to return true here.
*/ */
if (!pIOHandler) { if (!pIOHandler) {
return true; return true;
@ -316,7 +316,7 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Col
for (const auto &nodeInst : pNode->mNodeInstances) { for (const auto &nodeInst : pNode->mNodeInstances) {
// find the corresponding node in the library // find the corresponding node in the library
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode); const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
const Collada::Node *nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second; const Collada::Node *nd = itt == pParser.mNodeLibrary.end() ? nullptr : (*itt).second;
// FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632 // FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
// need to check for both name and ID to catch all. To avoid breaking valid files, // need to check for both name and ID to catch all. To avoid breaking valid files,
@ -716,7 +716,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
if (targetMesh->mSubMeshes.size() > 1) { if (targetMesh->mSubMeshes.size() > 1) {
throw DeadlyImportError("Morphing target mesh must be a single"); throw DeadlyImportError("Morphing target mesh must be a single");
} }
aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0); aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), nullptr, 0, 0);
mTargetMeshes.push_back(aimesh); mTargetMeshes.push_back(aimesh);
} }
targetMeshes.push_back(aimesh); targetMeshes.push_back(aimesh);
@ -1000,7 +1000,7 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse
combinedAnim->mChannels = new aiNodeAnim *[combinedAnim->mNumChannels]; combinedAnim->mChannels = new aiNodeAnim *[combinedAnim->mNumChannels];
// add the template anim as first channel by moving its aiNodeAnim to the combined animation // add the template anim as first channel by moving its aiNodeAnim to the combined animation
combinedAnim->mChannels[0] = templateAnim->mChannels[0]; combinedAnim->mChannels[0] = templateAnim->mChannels[0];
templateAnim->mChannels[0] = NULL; templateAnim->mChannels[0] = nullptr;
delete templateAnim; delete templateAnim;
// combined animation replaces template animation in the anim array // combined animation replaces template animation in the anim array
mAnims[a] = combinedAnim; mAnims[a] = combinedAnim;
@ -1009,7 +1009,7 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse
for (size_t b = 0; b < collectedAnimIndices.size(); ++b) { for (size_t b = 0; b < collectedAnimIndices.size(); ++b) {
aiAnimation *srcAnimation = mAnims[collectedAnimIndices[b]]; aiAnimation *srcAnimation = mAnims[collectedAnimIndices[b]];
combinedAnim->mChannels[1 + b] = srcAnimation->mChannels[0]; combinedAnim->mChannels[1 + b] = srcAnimation->mChannels[0];
srcAnimation->mChannels[0] = NULL; srcAnimation->mChannels[0] = nullptr;
delete srcAnimation; delete srcAnimation;
} }
@ -1116,9 +1116,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// find the collada node corresponding to the aiNode // find the collada node corresponding to the aiNode
const Collada::Node *srcNode = FindNode(pParser.mRootNode, nodeName); const Collada::Node *srcNode = FindNode(pParser.mRootNode, nodeName);
// ai_assert( srcNode != NULL); if (!srcNode) {
if (!srcNode)
continue; continue;
}
// now check all channels if they affect the current node // now check all channels if they affect the current node
std::string targetID, subElement; std::string targetID, subElement;
@ -1132,8 +1132,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
std::string::size_type slashPos = srcChannel.mTarget.find('/'); std::string::size_type slashPos = srcChannel.mTarget.find('/');
if (slashPos == std::string::npos) { if (slashPos == std::string::npos) {
std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID); std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID);
if (targetPos == std::string::npos) if (targetPos == std::string::npos) {
continue; continue;
}
// not node transform, but something else. store as unknown animation channel for now // not node transform, but something else. store as unknown animation channel for now
entry.mChannel = &(*cit); entry.mChannel = &(*cit);
@ -1777,11 +1778,12 @@ const Collada::Node *ColladaLoader::FindNode(const Collada::Node *pNode, const s
for (size_t a = 0; a < pNode->mChildren.size(); ++a) { for (size_t a = 0; a < pNode->mChildren.size(); ++a) {
const Collada::Node *node = FindNode(pNode->mChildren[a], pName); const Collada::Node *node = FindNode(pNode->mChildren[a], pName);
if (node) if (node) {
return node; return node;
}
} }
return NULL; return nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -89,7 +89,7 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
{ {
// validate io-handler instance // validate io-handler instance
if (nullptr == pIOHandler) { if (nullptr == pIOHandler) {
throw DeadlyImportError("IOSystem is NULL."); throw DeadlyImportError("IOSystem is nullptr.");
} }
std::unique_ptr<IOStream> daefile; std::unique_ptr<IOStream> daefile;
@ -322,7 +322,7 @@ void ColladaParser::ReadStructure() {
else if (IsElement("library_cameras")) else if (IsElement("library_cameras"))
ReadCameraLibrary(); ReadCameraLibrary();
else if (IsElement("library_nodes")) else if (IsElement("library_nodes"))
ReadSceneNode(NULL); /* some hacking to reuse this piece of code */ ReadSceneNode(nullptr); /* some hacking to reuse this piece of code */
else if (IsElement("scene")) else if (IsElement("scene"))
ReadScene(); ReadScene();
else else
@ -588,7 +588,7 @@ void ColladaParser::ReadAnimation(Collada::Animation *pParent) {
typedef std::map<std::string, AnimationChannel> ChannelMap; typedef std::map<std::string, AnimationChannel> ChannelMap;
ChannelMap channels; ChannelMap channels;
// this is the anim container in case we're a container // this is the anim container in case we're a container
Animation *anim = NULL; Animation *anim = nullptr;
// optional name given as an attribute // optional name given as an attribute
std::string animName; std::string animName;
@ -1713,9 +1713,6 @@ void ColladaParser::ReadGeometryLibrary() {
int indexID = GetAttribute("id"); int indexID = GetAttribute("id");
std::string id = mReader->getAttributeValue(indexID); std::string id = mReader->getAttributeValue(indexID);
// TODO: (thom) support SIDs
// ai_assert( TestAttribute( "sid") == -1);
// create a mesh and store it in the library under its (resolved) ID // create a mesh and store it in the library under its (resolved) ID
// Skip and warn if ID is not unique // Skip and warn if ID is not unique
if (mMeshLibrary.find(id) == mMeshLibrary.cend()) { if (mMeshLibrary.find(id) == mMeshLibrary.cend()) {
@ -2329,7 +2326,7 @@ size_t ColladaParser::ReadPrimitives(Mesh &pMesh, std::vector<InputChannel> &pPe
return numPrimitives; return numPrimitives;
} }
///@note This function willn't work correctly if both PerIndex and PerVertex channels have same channels. ///@note This function won't work correctly if both PerIndex and PerVertex channels have same channels.
///For example if TEXCOORD present in both <vertices> and <polylist> tags this function will create wrong uv coordinates. ///For example if TEXCOORD present in both <vertices> and <polylist> tags this function will create wrong uv coordinates.
///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior ///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior
void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh &pMesh, std::vector<InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices) { void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh &pMesh, std::vector<InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices) {
@ -2525,8 +2522,6 @@ void ColladaParser::ReadSceneNode(Node *pNode) {
if (attrName > -1) if (attrName > -1)
child->mName = mReader->getAttributeValue(attrName); child->mName = mReader->getAttributeValue(attrName);
// TODO: (thom) support SIDs
// ai_assert( TestAttribute( "sid") == -1);
if (pNode) { if (pNode) {
pNode->mChildren.push_back(child); pNode->mChildren.push_back(child);
@ -2557,7 +2552,7 @@ void ColladaParser::ReadSceneNode(Node *pNode) {
ReadNodeTransformation(pNode, TF_SKEW); ReadNodeTransformation(pNode, TF_SKEW);
else if (IsElement("translate")) else if (IsElement("translate"))
ReadNodeTransformation(pNode, TF_TRANSLATE); ReadNodeTransformation(pNode, TF_TRANSLATE);
else if (IsElement("render") && pNode->mParent == NULL && 0 == pNode->mPrimaryCamera.length()) { else if (IsElement("render") && pNode->mParent == nullptr && 0 == pNode->mPrimaryCamera.length()) {
// ... scene evaluation or, in other words, postprocessing pipeline, // ... scene evaluation or, in other words, postprocessing pipeline,
// or, again in other words, a turing-complete description how to // or, again in other words, a turing-complete description how to
// render a Collada scene. The only thing that is interesting for // render a Collada scene. The only thing that is interesting for
@ -2915,17 +2910,19 @@ const char *ColladaParser::GetTextContent() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the text contents of an element, returns NULL if not given. Skips leading whitespace. // Reads the text contents of an element, returns nullptr if not given. Skips leading whitespace.
const char *ColladaParser::TestTextContent() { const char *ColladaParser::TestTextContent() {
// present node should be the beginning of an element // present node should be the beginning of an element
if (mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement()) if (mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement())
return NULL; return nullptr;
// read contents of the element // read contents of the element
if (!mReader->read()) if (!mReader->read()) {
return NULL; return nullptr;
if (mReader->getNodeType() != irr::io::EXN_TEXT && mReader->getNodeType() != irr::io::EXN_CDATA) }
return NULL; if (mReader->getNodeType() != irr::io::EXN_TEXT && mReader->getNodeType() != irr::io::EXN_CDATA) {
return nullptr;
}
// skip leading whitespace // skip leading whitespace
const char *text = mReader->getNodeData(); const char *text = mReader->getNodeData();

View File

@ -272,7 +272,7 @@ protected:
Skips leading whitespace. */ Skips leading whitespace. */
const char *GetTextContent(); const char *GetTextContent();
/** Reads the text contents of an element, returns NULL if not given. /** Reads the text contents of an element, returns nullptr if not given.
Skips leading whitespace. */ Skips leading whitespace. */
const char *TestTextContent(); const char *TestTextContent();

View File

@ -47,10 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#include "FBXParser.h"
#include "FBXDocument.h" #include "FBXDocument.h"
#include "FBXImporter.h"
#include "FBXDocumentUtil.h" #include "FBXDocumentUtil.h"
#include "FBXImporter.h"
#include "FBXParser.h"
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
@ -58,65 +58,60 @@ namespace FBX {
using namespace Util; using namespace Util;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/) AnimationCurve::AnimationCurve(uint64_t id, const Element &element, const std::string &name, const Document & /*doc*/) :
: Object(id, element, name) Object(id, element, name) {
{ const Scope &sc = GetRequiredScope(element);
const Scope& sc = GetRequiredScope(element); const Element &KeyTime = GetRequiredElement(sc, "KeyTime");
const Element& KeyTime = GetRequiredElement(sc,"KeyTime"); const Element &KeyValueFloat = GetRequiredElement(sc, "KeyValueFloat");
const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat");
ParseVectorDataArray(keys, KeyTime); ParseVectorDataArray(keys, KeyTime);
ParseVectorDataArray(values, KeyValueFloat); ParseVectorDataArray(values, KeyValueFloat);
if(keys.size() != values.size()) { if (keys.size() != values.size()) {
DOMError("the number of key times does not match the number of keyframe values",&KeyTime); DOMError("the number of key times does not match the number of keyframe values", &KeyTime);
} }
// check if the key times are well-ordered // check if the key times are well-ordered
if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) { if (!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
DOMError("the keyframes are not in ascending order",&KeyTime); DOMError("the keyframes are not in ascending order", &KeyTime);
} }
const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"]; const Element *KeyAttrDataFloat = sc["KeyAttrDataFloat"];
if(KeyAttrDataFloat) { if (KeyAttrDataFloat) {
ParseVectorDataArray(attributes, *KeyAttrDataFloat); ParseVectorDataArray(attributes, *KeyAttrDataFloat);
} }
const Element* KeyAttrFlags = sc["KeyAttrFlags"]; const Element *KeyAttrFlags = sc["KeyAttrFlags"];
if(KeyAttrFlags) { if (KeyAttrFlags) {
ParseVectorDataArray(flags, *KeyAttrFlags); ParseVectorDataArray(flags, *KeyAttrFlags);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurve::~AnimationCurve() AnimationCurve::~AnimationCurve() {
{
// empty // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name,
const Document& doc, const char* const * target_prop_whitelist /*= NULL*/, const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/,
size_t whitelist_size /*= 0*/) size_t whitelist_size /*= 0*/) :
: Object(id, element, name) Object(id, element, name), target(), doc(doc) {
, target() const Scope &sc = GetRequiredScope(element);
, doc(doc)
{
const Scope& sc = GetRequiredScope(element);
// find target node // find target node
const char* whitelist[] = {"Model","NodeAttribute","Deformer"}; const char *whitelist[] = { "Model", "NodeAttribute", "Deformer" };
const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3); const std::vector<const Connection *> &conns = doc.GetConnectionsBySourceSequenced(ID(), whitelist, 3);
for(const Connection* con : conns) { for (const Connection *con : conns) {
// link should go for a property // link should go for a property
if (!con->PropertyName().length()) { if (!con->PropertyName().length()) {
continue; continue;
} }
if(target_prop_whitelist) { if (target_prop_whitelist) {
const char* const s = con->PropertyName().c_str(); const char *const s = con->PropertyName().c_str();
bool ok = false; bool ok = false;
for (size_t i = 0; i < whitelist_size; ++i) { for (size_t i = 0; i < whitelist_size; ++i) {
if (!strcmp(s, target_prop_whitelist[i])) { if (!strcmp(s, target_prop_whitelist[i])) {
@ -130,16 +125,14 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
} }
} }
const Object* const ob = con->DestinationObject(); const Object *const ob = con->DestinationObject();
if(!ob) { if (!ob) {
DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element); DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring", &element);
continue; continue;
} }
// XXX support constraints as DOM class
//ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob));
target = ob; target = ob;
if(!target) { if (!target) {
continue; continue;
} }
@ -147,42 +140,40 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
break; break;
} }
if(!target) { if (!target) {
DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element); DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode", &element);
} }
props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false); props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNode::~AnimationCurveNode() AnimationCurveNode::~AnimationCurveNode() {
{
// empty // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const AnimationCurveMap& AnimationCurveNode::Curves() const const AnimationCurveMap &AnimationCurveNode::Curves() const {
{ if (curves.empty()) {
if ( curves.empty() ) {
// resolve attached animation curves // resolve attached animation curves
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurve");
for(const Connection* con : conns) { for (const Connection *con : conns) {
// link should go for a property // link should go for a property
if (!con->PropertyName().length()) { if (!con->PropertyName().length()) {
continue; continue;
} }
const Object* const ob = con->SourceObject(); const Object *const ob = con->SourceObject();
if(!ob) { if (nullptr == ob) {
DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element); DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring", &element);
continue; continue;
} }
const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob); const AnimationCurve *const anim = dynamic_cast<const AnimationCurve *>(ob);
if(!anim) { if (nullptr == anim) {
DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element); DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve", &element);
continue; continue;
} }
@ -194,53 +185,49 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc) AnimationLayer::AnimationLayer(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
: Object(id, element, name) Object(id, element, name), doc(doc) {
, doc(doc) const Scope &sc = GetRequiredScope(element);
{
const Scope& sc = GetRequiredScope(element);
// note: the props table here bears little importance and is usually absent // note: the props table here bears little importance and is usually absent
props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true); props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationLayer::~AnimationLayer() AnimationLayer::~AnimationLayer() {
{
// empty // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/,
size_t whitelist_size /*= 0*/) const size_t whitelist_size /*= 0*/) const {
{
AnimationCurveNodeList nodes; AnimationCurveNodeList nodes;
// resolve attached animation nodes // resolve attached animation nodes
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode"); const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurveNode");
nodes.reserve(conns.size()); nodes.reserve(conns.size());
for(const Connection* con : conns) { for (const Connection *con : conns) {
// link should not go to a property // link should not go to a property
if (con->PropertyName().length()) { if (con->PropertyName().length()) {
continue; continue;
} }
const Object* const ob = con->SourceObject(); const Object *const ob = con->SourceObject();
if(!ob) { if (!ob) {
DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element); DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring", &element);
continue; continue;
} }
const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob); const AnimationCurveNode *const anim = dynamic_cast<const AnimationCurveNode *>(ob);
if(!anim) { if (!anim) {
DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element); DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode", &element);
continue; continue;
} }
if(target_prop_whitelist) { if (target_prop_whitelist) {
const char* s = anim->TargetProperty().c_str(); const char *s = anim->TargetProperty().c_str();
bool ok = false; bool ok = false;
for (size_t i = 0; i < whitelist_size; ++i) { for (size_t i = 0; i < whitelist_size; ++i) {
if (!strcmp(s, target_prop_whitelist[i])) { if (!strcmp(s, target_prop_whitelist[i])) {
@ -248,7 +235,7 @@ AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whi
break; break;
} }
} }
if(!ok) { if (!ok) {
continue; continue;
} }
} }
@ -259,34 +246,33 @@ AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whi
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc) AnimationStack::AnimationStack(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
: Object(id, element, name) Object(id, element, name) {
{ const Scope &sc = GetRequiredScope(element);
const Scope& sc = GetRequiredScope(element);
// note: we don't currently use any of these properties so we shouldn't bother if it is missing // note: we don't currently use any of these properties so we shouldn't bother if it is missing
props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true); props = GetPropertyTable(doc, "AnimationStack.FbxAnimStack", element, sc, true);
// resolve attached animation layers // resolve attached animation layers
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer"); const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationLayer");
layers.reserve(conns.size()); layers.reserve(conns.size());
for(const Connection* con : conns) { for (const Connection *con : conns) {
// link should not go to a property // link should not go to a property
if (con->PropertyName().length()) { if (con->PropertyName().length()) {
continue; continue;
} }
const Object* const ob = con->SourceObject(); const Object *const ob = con->SourceObject();
if(!ob) { if (!ob) {
DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element); DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring", &element);
continue; continue;
} }
const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob); const AnimationLayer *const anim = dynamic_cast<const AnimationLayer *>(ob);
if(!anim) { if (!anim) {
DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element); DOMWarning("source object for ->AnimationStack link is not an AnimationLayer", &element);
continue; continue;
} }
layers.push_back(anim); layers.push_back(anim);
@ -294,12 +280,11 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationStack::~AnimationStack() AnimationStack::~AnimationStack() {
{
// empty // empty
} }
} //!FBX } // namespace FBX
} //!Assimp } // namespace Assimp
#endif // ASSIMP_BUILD_NO_FBX_IMPORTER #endif // ASSIMP_BUILD_NO_FBX_IMPORTER

View File

@ -804,11 +804,6 @@ bool FBXConverter::GenerateTransformationNodeChain(const Model &model, const std
aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]); aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]);
} }
// is_complex needs to be consistent with NeedsComplexTransformationChain()
// or the interplay between this code and the animation converter would
// not be guaranteed.
//ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0));
// now, if we have more than just Translation, Scaling and Rotation, // now, if we have more than just Translation, Scaling and Rotation,
// we need to generate a full node chain to accommodate for assimp's // we need to generate a full node chain to accommodate for assimp's
// lack to express pivots and offsets. // lack to express pivots and offsets.
@ -1290,7 +1285,8 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
} }
if (binormals) { if (binormals) {
ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size()); ai_assert(tangents.size() == vertices.size());
ai_assert(binormals->size() == vertices.size());
out_mesh->mTangents = new aiVector3D[vertices.size()]; out_mesh->mTangents = new aiVector3D[vertices.size()];
out_mesh->mBitangents = new aiVector3D[vertices.size()]; out_mesh->mBitangents = new aiVector3D[vertices.size()];
@ -3165,7 +3161,8 @@ FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vector<c
} }
const AnimationCurve *const curve = kv.second; const AnimationCurve *const curve = kv.second;
ai_assert(curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size()); ai_assert(curve->GetKeys().size() == curve->GetValues().size());
ai_assert(curve->GetKeys().size());
//get values within the start/stop time window //get values within the start/stop time window
std::shared_ptr<KeyTimeList> Keys(new KeyTimeList()); std::shared_ptr<KeyTimeList> Keys(new KeyTimeList());

View File

@ -220,8 +220,8 @@ private:
* each output vertex the DOM index it maps to. * each output vertex the DOM index it maps to.
*/ */
void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
aiNode *parent = NULL, unsigned int materialIndex = NO_MATERIAL_SEPARATION, aiNode *parent = nullptr, unsigned int materialIndex = NO_MATERIAL_SEPARATION,
std::vector<unsigned int> *outputVertStartIndices = NULL); std::vector<unsigned int> *outputVertStartIndices = nullptr);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl, void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,

View File

@ -221,7 +221,7 @@ const Object* LazyObject::Get(bool dieOnError)
if(!DefaultLogger::isNullLogger()) { if(!DefaultLogger::isNullLogger()) {
ASSIMP_LOG_ERROR(ex.what()); ASSIMP_LOG_ERROR(ex.what());
} }
return NULL; return nullptr;
} }
if (!object.get()) { if (!object.get()) {
@ -467,7 +467,7 @@ void Document::ReadPropertyTemplates()
const Element *Properties70 = (*innerSc)["Properties70"]; const Element *Properties70 = (*innerSc)["Properties70"];
if(Properties70) { if(Properties70) {
std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>( std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
*Properties70,std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL)) *Properties70, std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable *>(nullptr))
); );
templates[oname+"."+pname] = props; templates[oname+"."+pname] = props;

View File

@ -96,7 +96,7 @@ public:
template <typename T> template <typename T>
const T* Get(bool dieOnError = false) { const T* Get(bool dieOnError = false) {
const Object* const ob = Get(dieOnError); const Object* const ob = Get(dieOnError);
return ob ? dynamic_cast<const T*>(ob) : NULL; return ob ? dynamic_cast<const T *>(ob) : nullptr;
} }
uint64_t ID() const { uint64_t ID() const {
@ -213,7 +213,8 @@ private:
type name() const { \ type name() const { \
const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \ const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \
if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \ if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \
ai_assert(static_cast<int>(default_value) >= 0 && static_cast<int>(default_value) < AI_CONCAT(type, _MAX)); \ ai_assert(static_cast<int>(default_value) >= 0); \
ai_assert(static_cast<int>(default_value) < AI_CONCAT(type, _MAX)); \
return static_cast<type>(default_value); \ return static_cast<type>(default_value); \
} \ } \
return static_cast<type>(ival); \ return static_cast<type>(ival); \
@ -744,7 +745,7 @@ public:
wants animations for. If the curve node does not match one of these, std::range_error wants animations for. If the curve node does not match one of these, std::range_error
will be thrown. */ will be thrown. */
AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0); const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
virtual ~AnimationCurveNode(); virtual ~AnimationCurveNode();
@ -756,7 +757,7 @@ public:
const AnimationCurveMap& Curves() const; const AnimationCurveMap& Curves() const;
/** Object the curve is assigned to, this can be NULL if the /** Object the curve is assigned to, this can be nullptr if the
* target object has no DOM representation or could not * target object has no DOM representation or could not
* be read for other reasons.*/ * be read for other reasons.*/
const Object* Target() const { const Object* Target() const {
@ -968,7 +969,7 @@ public:
// note: a connection ensures that the source and dest objects exist, but // note: a connection ensures that the source and dest objects exist, but
// not that they have DOM representations, so the return value of one of // not that they have DOM representations, so the return value of one of
// these functions can still be NULL. // these functions can still be nullptr.
const Object* SourceObject() const; const Object* SourceObject() const;
const Object* DestinationObject() const; const Object* DestinationObject() const;

View File

@ -65,7 +65,7 @@ void DOMError(const std::string& message, const Token& token)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void DOMError(const std::string& message, const Element* element /*= NULL*/) void DOMError(const std::string& message, const Element* element /*= nullptr*/)
{ {
if(element) { if(element) {
DOMError(message,element->KeyToken()); DOMError(message,element->KeyToken());
@ -84,7 +84,7 @@ void DOMWarning(const std::string& message, const Token& token)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void DOMWarning(const std::string& message, const Element* element /*= NULL*/) void DOMWarning(const std::string& message, const Element* element /*= nullptr*/)
{ {
if(element) { if(element) {
DOMWarning(message,element->KeyToken()); DOMWarning(message,element->KeyToken());
@ -106,7 +106,7 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
{ {
const Element* const Properties70 = sc["Properties70"]; const Element* const Properties70 = sc["Properties70"];
std::shared_ptr<const PropertyTable> templateProps = std::shared_ptr<const PropertyTable>( std::shared_ptr<const PropertyTable> templateProps = std::shared_ptr<const PropertyTable>(
static_cast<const PropertyTable*>(NULL)); static_cast<const PropertyTable *>(nullptr));
if(templateName.length()) { if(templateName.length()) {
PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName); PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName);

View File

@ -241,7 +241,7 @@ const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const { const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
if ( in_index >= m_mapping_counts.size() ) { if ( in_index >= m_mapping_counts.size() ) {
return NULL; return nullptr;
} }
ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() ); ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );

View File

@ -61,10 +61,10 @@ public:
Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc ); Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
virtual ~Geometry(); virtual ~Geometry();
/** Get the Skin attached to this geometry or NULL */ /** Get the Skin attached to this geometry or nullptr */
const Skin* DeformerSkin() const; const Skin* DeformerSkin() const;
/** Get the BlendShape attached to this geometry or NULL */ /** Get the BlendShape attached to this geometry or nullptr */
const std::vector<const BlendShape*>& GetBlendShapes() const; const std::vector<const BlendShape*>& GetBlendShapes() const;
private: private:
@ -123,7 +123,7 @@ public:
/** Get per-face-vertex material assignments */ /** Get per-face-vertex material assignments */
const MatIndexArray& GetMaterialIndices() const; const MatIndexArray& GetMaterialIndices() const;
/** Convert from a fbx file vertex index (for example from a #Cluster weight) or NULL /** Convert from a fbx file vertex index (for example from a #Cluster weight) or nullptr
* if the vertex index is not valid. */ * if the vertex index is not valid. */
const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const; const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;

View File

@ -77,7 +77,7 @@ namespace {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void ParseError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ParseError(const std::string &message, const Element *element = nullptr) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ParseError(const std::string& message, const Element* element) AI_WONT_RETURN void ParseError(const std::string& message, const Element* element)
{ {
if(element) { if(element) {
@ -181,7 +181,7 @@ Scope::Scope(Parser& parser,bool topLevel)
} }
TokenPtr n = parser.AdvanceToNextToken(); TokenPtr n = parser.AdvanceToNextToken();
if(n == NULL) { if (n == nullptr) {
ParseError("unexpected end of file"); ParseError("unexpected end of file");
} }
@ -196,7 +196,7 @@ Scope::Scope(Parser& parser,bool topLevel)
// Element() should stop at the next Key token (or right after a Close token) // Element() should stop at the next Key token (or right after a Close token)
n = parser.CurrentToken(); n = parser.CurrentToken();
if(n == NULL) { if (n == nullptr) {
if (topLevel) { if (topLevel) {
return; return;
} }
@ -236,7 +236,7 @@ TokenPtr Parser::AdvanceToNextToken()
{ {
last = current; last = current;
if (cursor == tokens.end()) { if (cursor == tokens.end()) {
current = NULL; current = nullptr;
} else { } else {
current = *cursor++; current = *cursor++;
} }
@ -258,7 +258,7 @@ TokenPtr Parser::LastToken() const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
uint64_t ParseTokenAsID(const Token& t, const char*& err_out) uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
{ {
err_out = NULL; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
err_out = "expected TOK_DATA token"; err_out = "expected TOK_DATA token";
@ -296,7 +296,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
size_t ParseTokenAsDim(const Token& t, const char*& err_out) size_t ParseTokenAsDim(const Token& t, const char*& err_out)
{ {
// same as ID parsing, except there is a trailing asterisk // same as ID parsing, except there is a trailing asterisk
err_out = NULL; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
err_out = "expected TOK_DATA token"; err_out = "expected TOK_DATA token";
@ -342,7 +342,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
float ParseTokenAsFloat(const Token& t, const char*& err_out) float ParseTokenAsFloat(const Token& t, const char*& err_out)
{ {
err_out = NULL; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
err_out = "expected TOK_DATA token"; err_out = "expected TOK_DATA token";
@ -385,7 +385,7 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
int ParseTokenAsInt(const Token& t, const char*& err_out) int ParseTokenAsInt(const Token& t, const char*& err_out)
{ {
err_out = NULL; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
err_out = "expected TOK_DATA token"; err_out = "expected TOK_DATA token";
@ -421,7 +421,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
int64_t ParseTokenAsInt64(const Token& t, const char*& err_out) int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
{ {
err_out = NULL; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
err_out = "expected TOK_DATA token"; err_out = "expected TOK_DATA token";
@ -458,7 +458,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string ParseTokenAsString(const Token& t, const char*& err_out) std::string ParseTokenAsString(const Token& t, const char*& err_out)
{ {
err_out = NULL; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
err_out = "expected TOK_DATA token"; err_out = "expected TOK_DATA token";
@ -1211,7 +1211,7 @@ bool HasElement( const Scope& sc, const std::string& index ) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// extract a required element from a scope, abort if the element cannot be found // extract a required element from a scope, abort if the element cannot be found
const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/) const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= nullptr*/)
{ {
const Element* el = sc[index]; const Element* el = sc[index];
if(!el) { if(!el) {

View File

@ -137,7 +137,7 @@ public:
return element->second; return element->second;
} }
} }
return NULL; return nullptr;
} }
ElementCollection GetCollection(const std::string& index) const { ElementCollection GetCollection(const std::string& index) const {
@ -219,7 +219,7 @@ void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el);
bool HasElement( const Scope& sc, const std::string& index ); bool HasElement( const Scope& sc, const std::string& index );
// extract a required element from a scope, abort if the element cannot be found // extract a required element from a scope, abort if the element cannot be found
const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL); const Element &GetRequiredElement(const Scope &sc, const std::string &index, const Element *element = nullptr);
// extract required compound scope // extract required compound scope
const Scope& GetRequiredScope(const Element& el); const Scope& GetRequiredScope(const Element& el);

View File

@ -70,7 +70,7 @@ Property::~Property()
namespace { namespace {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a typed property out of a FBX element. The return value is NULL if the property cannot be read. // read a typed property out of a FBX element. The return value is nullptr if the property cannot be read.
Property* ReadTypedProperty(const Element& element) Property* ReadTypedProperty(const Element& element)
{ {
ai_assert(element.KeyToken().StringContents() == "P"); ai_assert(element.KeyToken().StringContents() == "P");
@ -112,7 +112,7 @@ Property* ReadTypedProperty(const Element& element)
else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) { else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) {
return new TypedProperty<float>(ParseTokenAsFloat(*tok[4])); return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
} }
return NULL; return nullptr;
} }
@ -197,7 +197,7 @@ const Property* PropertyTable::Get(const std::string& name) const
return templateProps->Get(name); return templateProps->Get(name);
} }
return NULL; return nullptr;
} }
} }

View File

@ -110,7 +110,7 @@ public:
const Property* Get(const std::string& name) const; const Property* Get(const std::string& name) const;
// PropertyTable's need not be coupled with FBX elements so this can be NULL // PropertyTable's need not be coupled with FBX elements so this can be nullptr
const Element* GetElement() const { const Element* GetElement() const {
return element; return element;
} }

View File

@ -127,7 +127,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*
TokenizeError("unexpected character, expected data token", line, column); TokenizeError("unexpected character, expected data token", line, column);
} }
start = end = NULL; start = end = nullptr;
} }
} }
@ -146,7 +146,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
bool in_double_quotes = false; bool in_double_quotes = false;
bool pending_data_token = false; bool pending_data_token = false;
const char* token_begin = NULL, *token_end = NULL; const char *token_begin = nullptr, *token_end = nullptr;
for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) { for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) {
const char c = *cur; const char c = *cur;

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -43,17 +41,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the MDL importer class */ /** @file Implementation of the MDL importer class */
#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER #ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
// internal headers // internal headers
#include "AssetLib/HMP/HMPLoader.h" #include "AssetLib/HMP/HMPLoader.h"
#include "AssetLib/MD2/MD2FileData.h" #include "AssetLib/MD2/MD2FileData.h"
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <memory> #include <memory>
@ -74,24 +71,21 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
HMPImporter::HMPImporter() HMPImporter::HMPImporter() {
{
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
HMPImporter::~HMPImporter() HMPImporter::~HMPImporter() {
{
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const bool HMPImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const {
{
const std::string extension = GetExtension(pFile); const std::string extension = GetExtension(pFile);
if (extension == "hmp" ) if (extension == "hmp")
return true; return true;
// if check for extension is not enough, check for the magic tokens // if check for extension is not enough, check for the magic tokens
@ -100,167 +94,155 @@ bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4; tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4;
tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5; tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5;
tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7; tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7;
return CheckMagicToken(pIOHandler,pFile,tokens,3,0); return CheckMagicToken(pIOHandler, pFile, tokens, 3, 0);
} }
return false; return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get list of all file extensions that are handled by this loader // Get list of all file extensions that are handled by this loader
const aiImporterDesc* HMPImporter::GetInfo () const const aiImporterDesc *HMPImporter::GetInfo() const {
{
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void HMPImporter::InternReadFile( const std::string& pFile, void HMPImporter::InternReadFile(const std::string &pFile,
aiScene* _pScene, IOSystem* _pIOHandler) aiScene *_pScene, IOSystem *_pIOHandler) {
{ pScene = _pScene;
pScene = _pScene;
mIOHandler = _pIOHandler; mIOHandler = _pIOHandler;
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile)); std::unique_ptr<IOStream> file(mIOHandler->Open(pFile));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == nullptr) if (file.get() == nullptr) {
throw DeadlyImportError( "Failed to open HMP file " + pFile + "."); throw DeadlyImportError("Failed to open HMP file " + pFile + ".");
}
// Check whether the HMP file is large enough to contain // Check whether the HMP file is large enough to contain
// at least the file header // at least the file header
const size_t fileSize = file->FileSize(); const size_t fileSize = file->FileSize();
if( fileSize < 50) if (fileSize < 50)
throw DeadlyImportError( "HMP File is too small."); throw DeadlyImportError("HMP File is too small.");
// Allocate storage and copy the contents of the file to a memory buffer // Allocate storage and copy the contents of the file to a memory buffer
mBuffer = new uint8_t[fileSize]; mBuffer = new uint8_t[fileSize];
file->Read( (void*)mBuffer, 1, fileSize); file->Read((void *)mBuffer, 1, fileSize);
iFileSize = (unsigned int)fileSize; iFileSize = (unsigned int)fileSize;
// Determine the file subtype and call the appropriate member function // Determine the file subtype and call the appropriate member function
const uint32_t iMagic = *((uint32_t*)this->mBuffer); const uint32_t iMagic = *((uint32_t *)this->mBuffer);
// HMP4 format // HMP4 format
if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic || if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_4 == iMagic) AI_HMP_MAGIC_NUMBER_BE_4 == iMagic) {
{
ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A4, magic word is HMP4"); ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A4, magic word is HMP4");
InternReadFile_HMP4(); InternReadFile_HMP4();
} }
// HMP5 format // HMP5 format
else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic || else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_5 == iMagic) AI_HMP_MAGIC_NUMBER_BE_5 == iMagic) {
{
ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A5, magic word is HMP5"); ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A5, magic word is HMP5");
InternReadFile_HMP5(); InternReadFile_HMP5();
} }
// HMP7 format // HMP7 format
else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic || else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_7 == iMagic) AI_HMP_MAGIC_NUMBER_BE_7 == iMagic) {
{
ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A7, magic word is HMP7"); ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A7, magic word is HMP7");
InternReadFile_HMP7(); InternReadFile_HMP7();
} } else {
else
{
// Print the magic word to the logger // Print the magic word to the logger
char szBuffer[5]; char szBuffer[5];
szBuffer[0] = ((char*)&iMagic)[0]; szBuffer[0] = ((char *)&iMagic)[0];
szBuffer[1] = ((char*)&iMagic)[1]; szBuffer[1] = ((char *)&iMagic)[1];
szBuffer[2] = ((char*)&iMagic)[2]; szBuffer[2] = ((char *)&iMagic)[2];
szBuffer[3] = ((char*)&iMagic)[3]; szBuffer[3] = ((char *)&iMagic)[3];
szBuffer[4] = '\0'; szBuffer[4] = '\0';
// We're definitely unable to load this file // We're definitely unable to load this file
throw DeadlyImportError( "Unknown HMP subformat " + pFile + throw DeadlyImportError("Unknown HMP subformat " + pFile +
". Magic word (" + szBuffer + ") is not known"); ". Magic word (" + szBuffer + ") is not known");
} }
// Set the AI_SCENE_FLAGS_TERRAIN bit // Set the AI_SCENE_FLAGS_TERRAIN bit
pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN; pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
delete[] mBuffer; delete[] mBuffer;
mBuffer= nullptr; mBuffer = nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void HMPImporter::ValidateHeader_HMP457( ) void HMPImporter::ValidateHeader_HMP457() {
{ const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer;
const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
if (120 > iFileSize) if (120 > iFileSize) {
{
throw DeadlyImportError("HMP file is too small (header size is " throw DeadlyImportError("HMP file is too small (header size is "
"120 bytes, this file is smaller)"); "120 bytes, this file is smaller)");
} }
if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y) if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y)
throw DeadlyImportError("Size of triangles in either x or y direction is zero"); throw DeadlyImportError("Size of triangles in either x or y direction is zero");
if(pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f) if (pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts / pcHeader->fnumverts_x) < 1.0f)
throw DeadlyImportError("Number of triangles in either x or y direction is zero"); throw DeadlyImportError("Number of triangles in either x or y direction is zero");
if(!pcHeader->numframes) if (!pcHeader->numframes)
throw DeadlyImportError("There are no frames. At least one should be there"); throw DeadlyImportError("There are no frames. At least one should be there");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP4( ) void HMPImporter::InternReadFile_HMP4() {
{
throw DeadlyImportError("HMP4 is currently not supported"); throw DeadlyImportError("HMP4 is currently not supported");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP5( ) void HMPImporter::InternReadFile_HMP5() {
{
// read the file header and skip everything to byte 84 // read the file header and skip everything to byte 84
const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)mBuffer; const HMP::Header_HMP5 *pcHeader = (const HMP::Header_HMP5 *)mBuffer;
const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84); const unsigned char *szCurrent = (const unsigned char *)(mBuffer + 84);
ValidateHeader_HMP457(); ValidateHeader_HMP457();
// generate an output mesh // generate an output mesh
pScene->mNumMeshes = 1; pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh*[1]; pScene->mMeshes = new aiMesh *[1];
aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); aiMesh *pcMesh = pScene->mMeshes[0] = new aiMesh();
pcMesh->mMaterialIndex = 0; pcMesh->mMaterialIndex = 0;
pcMesh->mVertices = new aiVector3D[pcHeader->numverts]; pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
pcMesh->mNormals = new aiVector3D[pcHeader->numverts]; pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x); const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
const unsigned int width = (unsigned int)pcHeader->fnumverts_x; const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
// generate/load a material for the terrain // generate/load a material for the terrain
CreateMaterial(szCurrent,&szCurrent); CreateMaterial(szCurrent, &szCurrent);
// goto offset 120, I don't know why ... // goto offset 120, I don't know why ...
// (fixme) is this the frame header? I assume yes since it starts with 2. // (fixme) is this the frame header? I assume yes since it starts with 2.
szCurrent += 36; szCurrent += 36;
SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width); SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7) * height * width);
// now load all vertices from the file // now load all vertices from the file
aiVector3D* pcVertOut = pcMesh->mVertices; aiVector3D *pcVertOut = pcMesh->mVertices;
aiVector3D* pcNorOut = pcMesh->mNormals; aiVector3D *pcNorOut = pcMesh->mNormals;
const HMP::Vertex_HMP5* src = (const HMP::Vertex_HMP5*) szCurrent; const HMP::Vertex_HMP5 *src = (const HMP::Vertex_HMP5 *)szCurrent;
for (unsigned int y = 0; y < height;++y) for (unsigned int y = 0; y < height; ++y) {
{ for (unsigned int x = 0; x < width; ++x) {
for (unsigned int x = 0; x < width;++x)
{
pcVertOut->x = x * pcHeader->ftrisize_x; pcVertOut->x = x * pcHeader->ftrisize_x;
pcVertOut->y = y * pcHeader->ftrisize_y; pcVertOut->y = y * pcHeader->ftrisize_y;
pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f; pcVertOut->z = (((float)src->z / 0xffff) - 0.5f) * pcHeader->ftrisize_x * 8.0f;
MD2::LookupNormalIndex(src->normals162index, *pcNorOut ); MD2::LookupNormalIndex(src->normals162index, *pcNorOut);
++pcVertOut;++pcNorOut;++src; ++pcVertOut;
++pcNorOut;
++src;
} }
} }
// generate texture coordinates if necessary // generate texture coordinates if necessary
if (pcHeader->numskins) if (pcHeader->numskins)
GenerateTextureCoords(width,height); GenerateTextureCoords(width, height);
// now build a list of faces // now build a list of faces
CreateOutputFaceList(width,height); CreateOutputFaceList(width, height);
// there is no nodegraph in HMP files. Simply assign the one mesh // there is no nodegraph in HMP files. Simply assign the one mesh
// (no, not the one ring) to the root node // (no, not the one ring) to the root node
@ -272,17 +254,16 @@ void HMPImporter::InternReadFile_HMP5( )
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP7( ) void HMPImporter::InternReadFile_HMP7() {
{
// read the file header and skip everything to byte 84 // read the file header and skip everything to byte 84
const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer; const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer;
const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84); const unsigned char *szCurrent = (const unsigned char *)(mBuffer + 84);
ValidateHeader_HMP457(); ValidateHeader_HMP457();
// generate an output mesh // generate an output mesh
pScene->mNumMeshes = 1; pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh*[1]; pScene->mMeshes = new aiMesh *[1];
aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); aiMesh *pcMesh = pScene->mMeshes[0] = new aiMesh();
pcMesh->mMaterialIndex = 0; pcMesh->mMaterialIndex = 0;
pcMesh->mVertices = new aiVector3D[pcHeader->numverts]; pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
@ -292,44 +273,44 @@ void HMPImporter::InternReadFile_HMP7( )
const unsigned int width = (unsigned int)pcHeader->fnumverts_x; const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
// generate/load a material for the terrain // generate/load a material for the terrain
CreateMaterial(szCurrent,&szCurrent); CreateMaterial(szCurrent, &szCurrent);
// goto offset 120, I don't know why ... // goto offset 120, I don't know why ...
// (fixme) is this the frame header? I assume yes since it starts with 2. // (fixme) is this the frame header? I assume yes since it starts with 2.
szCurrent += 36; szCurrent += 36;
SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width); SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7) * height * width);
// now load all vertices from the file // now load all vertices from the file
aiVector3D* pcVertOut = pcMesh->mVertices; aiVector3D *pcVertOut = pcMesh->mVertices;
aiVector3D* pcNorOut = pcMesh->mNormals; aiVector3D *pcNorOut = pcMesh->mNormals;
const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent; const HMP::Vertex_HMP7 *src = (const HMP::Vertex_HMP7 *)szCurrent;
for (unsigned int y = 0; y < height;++y) for (unsigned int y = 0; y < height; ++y) {
{ for (unsigned int x = 0; x < width; ++x) {
for (unsigned int x = 0; x < width;++x)
{
pcVertOut->x = x * pcHeader->ftrisize_x; pcVertOut->x = x * pcHeader->ftrisize_x;
pcVertOut->y = y * pcHeader->ftrisize_y; pcVertOut->y = y * pcHeader->ftrisize_y;
// FIXME: What exctly is the correct scaling factor to use? // FIXME: What exctly is the correct scaling factor to use?
// possibly pcHeader->scale_origin[2] in combination with a // possibly pcHeader->scale_origin[2] in combination with a
// signed interpretation of src->z? // signed interpretation of src->z?
pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f; pcVertOut->z = (((float)src->z / 0xffff) - 0.5f) * pcHeader->ftrisize_x * 8.0f;
pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0]; pcNorOut->x = ((float)src->normal_x / 0x80); // * pcHeader->scale_origin[0];
pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1]; pcNorOut->y = ((float)src->normal_y / 0x80); // * pcHeader->scale_origin[1];
pcNorOut->z = 1.0f; pcNorOut->z = 1.0f;
pcNorOut->Normalize(); pcNorOut->Normalize();
++pcVertOut;++pcNorOut;++src; ++pcVertOut;
++pcNorOut;
++src;
} }
} }
// generate texture coordinates if necessary // generate texture coordinates if necessary
if (pcHeader->numskins)GenerateTextureCoords(width,height); if (pcHeader->numskins) GenerateTextureCoords(width, height);
// now build a list of faces // now build a list of faces
CreateOutputFaceList(width,height); CreateOutputFaceList(width, height);
// there is no nodegraph in HMP files. Simply assign the one mesh // there is no nodegraph in HMP files. Simply assign the one mesh
// (no, not the One Ring) to the root node // (no, not the One Ring) to the root node
@ -341,96 +322,89 @@ void HMPImporter::InternReadFile_HMP7( )
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void HMPImporter::CreateMaterial(const unsigned char* szCurrent, void HMPImporter::CreateMaterial(const unsigned char *szCurrent,
const unsigned char** szCurrentOut) const unsigned char **szCurrentOut) {
{ aiMesh *const pcMesh = pScene->mMeshes[0];
aiMesh* const pcMesh = pScene->mMeshes[0]; const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer;
const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
// we don't need to generate texture coordinates if // we don't need to generate texture coordinates if
// we have no textures in the file ... // we have no textures in the file ...
if (pcHeader->numskins) if (pcHeader->numskins) {
{
pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts]; pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts];
pcMesh->mNumUVComponents[0] = 2; pcMesh->mNumUVComponents[0] = 2;
// now read the first skin and skip all others // now read the first skin and skip all others
ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent); ReadFirstSkin(pcHeader->numskins, szCurrent, &szCurrent);
} } else {
else
{
// generate a default material // generate a default material
const int iMode = (int)aiShadingMode_Gouraud; const int iMode = (int)aiShadingMode_Gouraud;
aiMaterial* pcHelper = new aiMaterial(); aiMaterial *pcHelper = new aiMaterial();
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
aiColor3D clr; aiColor3D clr;
clr.b = clr.g = clr.r = 0.6f; clr.b = clr.g = clr.r = 0.6f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
clr.b = clr.g = clr.r = 0.05f; clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
aiString szName; aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME); szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName,AI_MATKEY_NAME); pcHelper->AddProperty(&szName, AI_MATKEY_NAME);
// add the material to the scene // add the material to the scene
pScene->mNumMaterials = 1; pScene->mNumMaterials = 1;
pScene->mMaterials = new aiMaterial*[1]; pScene->mMaterials = new aiMaterial *[1];
pScene->mMaterials[0] = pcHelper; pScene->mMaterials[0] = pcHelper;
} }
*szCurrentOut = szCurrent; *szCurrentOut = szCurrent;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height) void HMPImporter::CreateOutputFaceList(unsigned int width, unsigned int height) {
{ aiMesh *const pcMesh = this->pScene->mMeshes[0];
aiMesh* const pcMesh = this->pScene->mMeshes[0];
// Allocate enough storage // Allocate enough storage
pcMesh->mNumFaces = (width-1) * (height-1); pcMesh->mNumFaces = (width - 1) * (height - 1);
pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
pcMesh->mNumVertices = pcMesh->mNumFaces*4; pcMesh->mNumVertices = pcMesh->mNumFaces * 4;
aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices]; aiVector3D *pcVertices = new aiVector3D[pcMesh->mNumVertices];
aiVector3D* pcNormals = new aiVector3D[pcMesh->mNumVertices]; aiVector3D *pcNormals = new aiVector3D[pcMesh->mNumVertices];
aiFace* pcFaceOut(pcMesh->mFaces); aiFace *pcFaceOut(pcMesh->mFaces);
aiVector3D* pcVertOut = pcVertices; aiVector3D *pcVertOut = pcVertices;
aiVector3D* pcNorOut = pcNormals; aiVector3D *pcNorOut = pcNormals;
aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL; aiVector3D *pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : nullptr;
aiVector3D* pcUVOut(pcUVs); aiVector3D *pcUVOut(pcUVs);
// Build the terrain square // Build the terrain square
unsigned int iCurrent = 0; unsigned int iCurrent = 0;
for (unsigned int y = 0; y < height-1;++y) { for (unsigned int y = 0; y < height - 1; ++y) {
for (unsigned int x = 0; x < width-1;++x,++pcFaceOut) { for (unsigned int x = 0; x < width - 1; ++x, ++pcFaceOut) {
pcFaceOut->mNumIndices = 4; pcFaceOut->mNumIndices = 4;
pcFaceOut->mIndices = new unsigned int[4]; pcFaceOut->mIndices = new unsigned int[4];
*pcVertOut++ = pcMesh->mVertices[y*width+x]; *pcVertOut++ = pcMesh->mVertices[y * width + x];
*pcVertOut++ = pcMesh->mVertices[(y+1)*width+x]; *pcVertOut++ = pcMesh->mVertices[(y + 1) * width + x];
*pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1]; *pcVertOut++ = pcMesh->mVertices[(y + 1) * width + x + 1];
*pcVertOut++ = pcMesh->mVertices[y*width+x+1]; *pcVertOut++ = pcMesh->mVertices[y * width + x + 1];
*pcNorOut++ = pcMesh->mNormals[y * width + x];
*pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x];
*pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x + 1];
*pcNorOut++ = pcMesh->mNormals[y * width + x + 1];
*pcNorOut++ = pcMesh->mNormals[y*width+x]; if (pcMesh->mTextureCoords[0]) {
*pcNorOut++ = pcMesh->mNormals[(y+1)*width+x]; *pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x];
*pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1]; *pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x];
*pcNorOut++ = pcMesh->mNormals[y*width+x+1]; *pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x + 1];
*pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x + 1];
if (pcMesh->mTextureCoords[0])
{
*pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1];
*pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
} }
for (unsigned int i = 0; i < 4;++i) for (unsigned int i = 0; i < 4; ++i)
pcFaceOut->mIndices[i] = iCurrent++; pcFaceOut->mIndices[i] = iCurrent++;
} }
} }
@ -440,58 +414,58 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
delete[] pcMesh->mNormals; delete[] pcMesh->mNormals;
pcMesh->mNormals = pcNormals; pcMesh->mNormals = pcNormals;
if (pcMesh->mTextureCoords[0]) if (pcMesh->mTextureCoords[0]) {
{
delete[] pcMesh->mTextureCoords[0]; delete[] pcMesh->mTextureCoords[0];
pcMesh->mTextureCoords[0] = pcUVs; pcMesh->mTextureCoords[0] = pcUVs;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor, void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char *szCursor,
const unsigned char** szCursorOut) const unsigned char **szCursorOut) {
{ ai_assert(0 != iNumSkins);
ai_assert( 0 != iNumSkins ); ai_assert(nullptr != szCursor);
ai_assert( nullptr != szCursor);
// read the type of the skin ... // read the type of the skin ...
// sometimes we need to skip 12 bytes here, I don't know why ... // sometimes we need to skip 12 bytes here, I don't know why ...
uint32_t iType = *((uint32_t*)szCursor); uint32_t iType = *((uint32_t *)szCursor);
szCursor += sizeof(uint32_t); szCursor += sizeof(uint32_t);
if (0 == iType) if (0 == iType) {
{
szCursor += sizeof(uint32_t) * 2; szCursor += sizeof(uint32_t) * 2;
iType = *((uint32_t*)szCursor); iType = *((uint32_t *)szCursor);
szCursor += sizeof(uint32_t); szCursor += sizeof(uint32_t);
if (!iType) if (!iType)
throw DeadlyImportError("Unable to read HMP7 skin chunk"); throw DeadlyImportError("Unable to read HMP7 skin chunk");
} }
// read width and height // read width and height
uint32_t iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); uint32_t iWidth = *((uint32_t *)szCursor);
uint32_t iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); szCursor += sizeof(uint32_t);
uint32_t iHeight = *((uint32_t *)szCursor);
szCursor += sizeof(uint32_t);
// allocate an output material // allocate an output material
aiMaterial* pcMat = new aiMaterial(); aiMaterial *pcMat = new aiMaterial();
// read the skin, this works exactly as for MDL7 // read the skin, this works exactly as for MDL7
ParseSkinLump_3DGS_MDL7(szCursor,&szCursor, ParseSkinLump_3DGS_MDL7(szCursor, &szCursor,
pcMat,iType,iWidth,iHeight); pcMat, iType, iWidth, iHeight);
// now we need to skip any other skins ... // now we need to skip any other skins ...
for (unsigned int i = 1; i< iNumSkins;++i) for (unsigned int i = 1; i < iNumSkins; ++i) {
{ iType = *((uint32_t *)szCursor);
iType = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); szCursor += sizeof(uint32_t);
iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); iWidth = *((uint32_t *)szCursor);
iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); szCursor += sizeof(uint32_t);
iHeight = *((uint32_t *)szCursor);
szCursor += sizeof(uint32_t);
SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,iType,iWidth,iHeight); SkipSkinLump_3DGS_MDL7(szCursor, &szCursor, iType, iWidth, iHeight);
SizeCheck(szCursor); SizeCheck(szCursor);
} }
// setup the material ... // setup the material ...
pScene->mNumMaterials = 1; pScene->mNumMaterials = 1;
pScene->mMaterials = new aiMaterial*[1]; pScene->mMaterials = new aiMaterial *[1];
pScene->mMaterials[0] = pcMat; pScene->mMaterials[0] = pcMat;
*szCursorOut = szCursor; *szCursorOut = szCursor;
@ -500,20 +474,20 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szC
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Generate proepr texture coords // Generate proepr texture coords
void HMPImporter::GenerateTextureCoords( void HMPImporter::GenerateTextureCoords(
const unsigned int width, const unsigned int height) const unsigned int width, const unsigned int height) {
{ ai_assert(nullptr != pScene->mMeshes);
ai_assert(NULL != pScene->mMeshes && NULL != pScene->mMeshes[0] && ai_assert(nullptr != pScene->mMeshes[0]);
NULL != pScene->mMeshes[0]->mTextureCoords[0]); ai_assert(nullptr != pScene->mMeshes[0]->mTextureCoords[0]);
aiVector3D* uv = pScene->mMeshes[0]->mTextureCoords[0]; aiVector3D *uv = pScene->mMeshes[0]->mTextureCoords[0];
const float fY = (1.0f / height) + (1.0f / height) / (height-1); const float fY = (1.0f / height) + (1.0f / height) / (height - 1);
const float fX = (1.0f / width) + (1.0f / width) / (width-1); const float fX = (1.0f / width) + (1.0f / width) / (width - 1);
for (unsigned int y = 0; y < height;++y) { for (unsigned int y = 0; y < height; ++y) {
for (unsigned int x = 0; x < width;++x,++uv) { for (unsigned int x = 0; x < width; ++x, ++uv) {
uv->y = fY*y; uv->y = fY * y;
uv->x = fX*x; uv->x = fX * x;
uv->z = 0.0f; uv->z = 0.0f;
} }
} }

View File

@ -131,7 +131,7 @@ void WritePolygon(std::vector<IfcVector3> &resultpoly, TempMesh &result) {
void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs, TempMesh &result, void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs, TempMesh &result,
const TempMesh &first_operand, const TempMesh &first_operand,
ConversionData & /*conv*/) { ConversionData & /*conv*/) {
ai_assert(hs != NULL); ai_assert(hs != nullptr);
const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr<Schema_2x3::IfcPlane>(); const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr<Schema_2x3::IfcPlane>();
if (!plane) { if (!plane) {
@ -366,7 +366,7 @@ bool PointInPoly(const IfcVector3 &p, const std::vector<IfcVector3> &boundary) {
void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPolygonalBoundedHalfSpace *hs, TempMesh &result, void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPolygonalBoundedHalfSpace *hs, TempMesh &result,
const TempMesh &first_operand, const TempMesh &first_operand,
ConversionData &conv) { ConversionData &conv) {
ai_assert(hs != NULL); ai_assert(hs != nullptr);
const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr<Schema_2x3::IfcPlane>(); const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr<Schema_2x3::IfcPlane>();
if (!plane) { if (!plane) {
@ -665,7 +665,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as, TempMesh &result, void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as, TempMesh &result,
const TempMesh &first_operand, const TempMesh &first_operand,
ConversionData &conv) { ConversionData &conv) {
ai_assert(as != NULL); ai_assert(as != nullptr);
// This case is handled by reduction to an instance of the quadrify() algorithm. // This case is handled by reduction to an instance of the quadrify() algorithm.
// Obviously, this won't work for arbitrarily complex cases. In fact, the first // Obviously, this won't work for arbitrarily complex cases. In fact, the first

View File

@ -389,7 +389,8 @@ public:
// -------------------------------------------------- // --------------------------------------------------
void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const { void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const {
ai_assert(InRange(a) && InRange(b)); ai_assert(InRange(a));
ai_assert(InRange(b));
return base->SampleDiscrete(out,TrimParam(a),TrimParam(b)); return base->SampleDiscrete(out,TrimParam(a),TrimParam(b));
} }
@ -446,7 +447,8 @@ public:
// -------------------------------------------------- // --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert(InRange(a) && InRange(b)); ai_assert(InRange(a));
ai_assert(InRange(b));
return static_cast<size_t>( std::ceil(b) - std::floor(a) ); return static_cast<size_t>( std::ceil(b) - std::floor(a) );
} }
@ -489,7 +491,7 @@ Curve* Curve::Convert(const IFC::Schema_2x3::IfcCurve& curve,ConversionData& con
} }
// XXX OffsetCurve2D, OffsetCurve3D not currently supported // XXX OffsetCurve2D, OffsetCurve3D not currently supported
return NULL; return nullptr;
} }
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG

View File

@ -174,7 +174,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
TempOpening& opening = fake_openings.back(); TempOpening& opening = fake_openings.back();
opening.extrusionDir = master_normal; opening.extrusionDir = master_normal;
opening.solid = NULL; opening.solid = nullptr;
opening.profileMesh = std::make_shared<TempMesh>(); opening.profileMesh = std::make_shared<TempMesh>();
opening.profileMesh->mVerts.reserve(*iit); opening.profileMesh->mVerts.reserve(*iit);

View File

@ -172,7 +172,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
if (GetExtension(pFile) == "ifczip") { if (GetExtension(pFile) == "ifczip") {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
unzFile zip = unzOpen(pFile.c_str()); unzFile zip = unzOpen(pFile.c_str());
if (zip == NULL) { if (zip == nullptr) {
ThrowException("Could not open ifczip file for reading, unzip failed"); ThrowException("Could not open ifczip file for reading, unzip failed");
} }
@ -373,7 +373,7 @@ void SetUnits(ConversionData &conv) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void SetCoordinateSpace(ConversionData &conv) { void SetCoordinateSpace(ConversionData &conv) {
const Schema_2x3::IfcRepresentationContext *fav = NULL; const Schema_2x3::IfcRepresentationContext *fav = nullptr;
for (const Schema_2x3::IfcRepresentationContext &v : conv.proj.RepresentationContexts) { for (const Schema_2x3::IfcRepresentationContext &v : conv.proj.RepresentationContexts) {
fav = &v; fav = &v;
// Model should be the most suitable type of context, hence ignore the others // Model should be the most suitable type of context, hence ignore the others
@ -790,7 +790,7 @@ aiNode *ProcessSpatialStructure(aiNode *parent, const Schema_2x3::IfcProduct &el
for (const Schema_2x3::IfcObjectDefinition &def : aggr->RelatedObjects) { for (const Schema_2x3::IfcObjectDefinition &def : aggr->RelatedObjects) {
if (const Schema_2x3::IfcProduct *const prod = def.ToPtr<Schema_2x3::IfcProduct>()) { if (const Schema_2x3::IfcProduct *const prod = def.ToPtr<Schema_2x3::IfcProduct>()) {
aiNode *const ndnew = ProcessSpatialStructure(nd_aggr.get(), *prod, conv, NULL); aiNode *const ndnew = ProcessSpatialStructure(nd_aggr.get(), *prod, conv, nullptr);
if (ndnew) { if (ndnew) {
nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew; nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew;
} }
@ -870,7 +870,7 @@ void ProcessSpatialStructures(ConversionData &conv) {
if (def.GetID() == prod->GetID()) { if (def.GetID() == prod->GetID()) {
IFCImporter::LogVerboseDebug("selecting this spatial structure as root structure"); IFCImporter::LogVerboseDebug("selecting this spatial structure as root structure");
// got it, this is one primary site. // got it, this is one primary site.
nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); nodes.push_back(ProcessSpatialStructure(nullptr, *prod, conv, nullptr));
} }
} }
} }
@ -887,7 +887,7 @@ void ProcessSpatialStructures(ConversionData &conv) {
continue; continue;
} }
nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); nodes.push_back(ProcessSpatialStructure(nullptr, *prod, conv, nullptr));
} }
nb_nodes = nodes.size(); nb_nodes = nodes.size();
@ -897,7 +897,7 @@ void ProcessSpatialStructures(ConversionData &conv) {
conv.out->mRootNode = nodes[0]; conv.out->mRootNode = nodes[0];
} else if (nb_nodes > 1) { } else if (nb_nodes > 1) {
conv.out->mRootNode = new aiNode("Root"); conv.out->mRootNode = new aiNode("Root");
conv.out->mRootNode->mParent = NULL; conv.out->mRootNode->mParent = nullptr;
conv.out->mRootNode->mNumChildren = static_cast<unsigned int>(nb_nodes); conv.out->mRootNode->mNumChildren = static_cast<unsigned int>(nb_nodes);
conv.out->mRootNode->mChildren = new aiNode *[conv.out->mRootNode->mNumChildren]; conv.out->mRootNode->mChildren = new aiNode *[conv.out->mRootNode->mNumChildren];

View File

@ -54,333 +54,333 @@ namespace {
typedef EXPRESS::ConversionSchema::SchemaEntry SchemaEntry; typedef EXPRESS::ConversionSchema::SchemaEntry SchemaEntry;
static const SchemaEntry schema_raw_2x3[] = { static const SchemaEntry schema_raw_2x3[] = {
SchemaEntry("ifcstairtypeenum",NULL ) SchemaEntry("ifcstairtypeenum",nullptr )
, SchemaEntry("ifcspacetypeenum",NULL ) , SchemaEntry("ifcspacetypeenum",nullptr )
, SchemaEntry("ifcwalltypeenum",NULL ) , SchemaEntry("ifcwalltypeenum",nullptr )
, SchemaEntry("ifcmonthinyearnumber",NULL ) , SchemaEntry("ifcmonthinyearnumber",nullptr )
, SchemaEntry("ifcheatfluxdensitymeasure",NULL ) , SchemaEntry("ifcheatfluxdensitymeasure",nullptr )
, SchemaEntry("ifckinematicviscositymeasure",NULL ) , SchemaEntry("ifckinematicviscositymeasure",nullptr )
, SchemaEntry("ifcsequenceenum",NULL ) , SchemaEntry("ifcsequenceenum",nullptr )
, SchemaEntry("ifcairtoairheatrecoverytypeenum",NULL ) , SchemaEntry("ifcairtoairheatrecoverytypeenum",nullptr )
, SchemaEntry("ifcactorselect",NULL ) , SchemaEntry("ifcactorselect",nullptr )
, SchemaEntry("ifctransformertypeenum",NULL ) , SchemaEntry("ifctransformertypeenum",nullptr )
, SchemaEntry("ifcunitaryequipmenttypeenum",NULL ) , SchemaEntry("ifcunitaryequipmenttypeenum",nullptr )
, SchemaEntry("ifcelectricflowstoragedevicetypeenum",NULL ) , SchemaEntry("ifcelectricflowstoragedevicetypeenum",nullptr )
, SchemaEntry("ifcenergysequenceenum",NULL ) , SchemaEntry("ifcenergysequenceenum",nullptr )
, SchemaEntry("ifcworkcontroltypeenum",NULL ) , SchemaEntry("ifcworkcontroltypeenum",nullptr )
, SchemaEntry("ifccurvaturemeasure",NULL ) , SchemaEntry("ifccurvaturemeasure",nullptr )
, SchemaEntry("ifcparametervalue",NULL ) , SchemaEntry("ifcparametervalue",nullptr )
, SchemaEntry("ifcappliedvalueselect",NULL ) , SchemaEntry("ifcappliedvalueselect",nullptr )
, SchemaEntry("ifcwarpingconstantmeasure",NULL ) , SchemaEntry("ifcwarpingconstantmeasure",nullptr )
, SchemaEntry("ifcarithmeticoperatorenum",NULL ) , SchemaEntry("ifcarithmeticoperatorenum",nullptr )
, SchemaEntry("ifclinearforcemeasure",NULL ) , SchemaEntry("ifclinearforcemeasure",nullptr )
, SchemaEntry("ifcwindowpanelpositionenum",NULL ) , SchemaEntry("ifcwindowpanelpositionenum",nullptr )
, SchemaEntry("ifcflowmetertypeenum",NULL ) , SchemaEntry("ifcflowmetertypeenum",nullptr )
, SchemaEntry("ifcrampflighttypeenum",NULL ) , SchemaEntry("ifcrampflighttypeenum",nullptr )
, SchemaEntry("ifcspecularhighlightselect",NULL ) , SchemaEntry("ifcspecularhighlightselect",nullptr )
, SchemaEntry("ifcactiontypeenum",NULL ) , SchemaEntry("ifcactiontypeenum",nullptr )
, SchemaEntry("ifcgeometricprojectionenum",NULL ) , SchemaEntry("ifcgeometricprojectionenum",nullptr )
, SchemaEntry("ifctimeseriesdatatypeenum",NULL ) , SchemaEntry("ifctimeseriesdatatypeenum",nullptr )
, SchemaEntry("ifcmagneticfluxmeasure",NULL ) , SchemaEntry("ifcmagneticfluxmeasure",nullptr )
, SchemaEntry("ifcobjecttypeenum",NULL ) , SchemaEntry("ifcobjecttypeenum",nullptr )
, SchemaEntry("ifcdataoriginenum",NULL ) , SchemaEntry("ifcdataoriginenum",nullptr )
, SchemaEntry("ifcmassdensitymeasure",NULL ) , SchemaEntry("ifcmassdensitymeasure",nullptr )
, SchemaEntry("ifclightfixturetypeenum",NULL ) , SchemaEntry("ifclightfixturetypeenum",nullptr )
, SchemaEntry("ifcservicelifetypeenum",NULL ) , SchemaEntry("ifcservicelifetypeenum",nullptr )
, SchemaEntry("ifcelectricvoltagemeasure",NULL ) , SchemaEntry("ifcelectricvoltagemeasure",nullptr )
, SchemaEntry("ifcheatingvaluemeasure",NULL ) , SchemaEntry("ifcheatingvaluemeasure",nullptr )
, SchemaEntry("ifcpresentabletext",NULL ) , SchemaEntry("ifcpresentabletext",nullptr )
, SchemaEntry("ifcaheadorbehind",NULL ) , SchemaEntry("ifcaheadorbehind",nullptr )
, SchemaEntry("ifcsimplevalue",NULL ) , SchemaEntry("ifcsimplevalue",nullptr )
, SchemaEntry("ifcsensortypeenum",NULL ) , SchemaEntry("ifcsensortypeenum",nullptr )
, SchemaEntry("ifcderivedunitenum",NULL ) , SchemaEntry("ifcderivedunitenum",nullptr )
, SchemaEntry("ifcsizeselect",NULL ) , SchemaEntry("ifcsizeselect",nullptr )
, SchemaEntry("ifctransportelementtypeenum",NULL ) , SchemaEntry("ifctransportelementtypeenum",nullptr )
, SchemaEntry("ifcinventorytypeenum",NULL ) , SchemaEntry("ifcinventorytypeenum",nullptr )
, SchemaEntry("ifctextdecoration",NULL ) , SchemaEntry("ifctextdecoration",nullptr )
, SchemaEntry("ifcdirectionsenseenum",NULL ) , SchemaEntry("ifcdirectionsenseenum",nullptr )
, SchemaEntry("ifcductfittingtypeenum",NULL ) , SchemaEntry("ifcductfittingtypeenum",nullptr )
, SchemaEntry("ifcdocumentstatusenum",NULL ) , SchemaEntry("ifcdocumentstatusenum",nullptr )
, SchemaEntry("ifcslabtypeenum",NULL ) , SchemaEntry("ifcslabtypeenum",nullptr )
, SchemaEntry("ifcdoorstyleconstructionenum",NULL ) , SchemaEntry("ifcdoorstyleconstructionenum",nullptr )
, SchemaEntry("ifcvolumemeasure",NULL ) , SchemaEntry("ifcvolumemeasure",nullptr )
, SchemaEntry("ifcinductancemeasure",NULL ) , SchemaEntry("ifcinductancemeasure",nullptr )
, SchemaEntry("ifccurtainwalltypeenum",NULL ) , SchemaEntry("ifccurtainwalltypeenum",nullptr )
, SchemaEntry("ifcsiunitname",NULL ) , SchemaEntry("ifcsiunitname",nullptr )
, SchemaEntry("ifcspecularexponent",NULL ) , SchemaEntry("ifcspecularexponent",nullptr )
, SchemaEntry("ifcsoundpressuremeasure",NULL ) , SchemaEntry("ifcsoundpressuremeasure",nullptr )
, SchemaEntry("ifcanalysistheorytypeenum",NULL ) , SchemaEntry("ifcanalysistheorytypeenum",nullptr )
, SchemaEntry("ifcgasterminaltypeenum",NULL ) , SchemaEntry("ifcgasterminaltypeenum",nullptr )
, SchemaEntry("ifcyearnumber",NULL ) , SchemaEntry("ifcyearnumber",nullptr )
, SchemaEntry("ifcmodulusofelasticitymeasure",NULL ) , SchemaEntry("ifcmodulusofelasticitymeasure",nullptr )
, SchemaEntry("ifcchangeactionenum",NULL ) , SchemaEntry("ifcchangeactionenum",nullptr )
, SchemaEntry("ifcdampertypeenum",NULL ) , SchemaEntry("ifcdampertypeenum",nullptr )
, SchemaEntry("ifcevaporatortypeenum",NULL ) , SchemaEntry("ifcevaporatortypeenum",nullptr )
, SchemaEntry("ifcionconcentrationmeasure",NULL ) , SchemaEntry("ifcionconcentrationmeasure",nullptr )
, SchemaEntry("ifcductsegmenttypeenum",NULL ) , SchemaEntry("ifcductsegmenttypeenum",nullptr )
, SchemaEntry("ifcprotectivedevicetypeenum",NULL ) , SchemaEntry("ifcprotectivedevicetypeenum",nullptr )
, SchemaEntry("ifcabsorbeddosemeasure",NULL ) , SchemaEntry("ifcabsorbeddosemeasure",nullptr )
, SchemaEntry("ifcmassperlengthmeasure",NULL ) , SchemaEntry("ifcmassperlengthmeasure",nullptr )
, SchemaEntry("ifctextfontname",NULL ) , SchemaEntry("ifctextfontname",nullptr )
, SchemaEntry("ifcorientationselect",NULL ) , SchemaEntry("ifcorientationselect",nullptr )
, SchemaEntry("ifcilluminancemeasure",NULL ) , SchemaEntry("ifcilluminancemeasure",nullptr )
, SchemaEntry("ifcfiresuppressionterminaltypeenum",NULL ) , SchemaEntry("ifcfiresuppressionterminaltypeenum",nullptr )
, SchemaEntry("ifcfontstyle",NULL ) , SchemaEntry("ifcfontstyle",nullptr )
, SchemaEntry("ifcmomentofinertiameasure",NULL ) , SchemaEntry("ifcmomentofinertiameasure",nullptr )
, SchemaEntry("ifcmodulusofsubgradereactionmeasure",NULL ) , SchemaEntry("ifcmodulusofsubgradereactionmeasure",nullptr )
, SchemaEntry("ifccomplexnumber",NULL ) , SchemaEntry("ifccomplexnumber",nullptr )
, SchemaEntry("ifchumidifiertypeenum",NULL ) , SchemaEntry("ifchumidifiertypeenum",nullptr )
, SchemaEntry("ifcpresentationstyleselect",NULL ) , SchemaEntry("ifcpresentationstyleselect",nullptr )
, SchemaEntry("ifcthermaltransmittancemeasure",NULL ) , SchemaEntry("ifcthermaltransmittancemeasure",nullptr )
, SchemaEntry("ifcribplatedirectionenum",NULL ) , SchemaEntry("ifcribplatedirectionenum",nullptr )
, SchemaEntry("ifcclassificationnotationselect",NULL ) , SchemaEntry("ifcclassificationnotationselect",nullptr )
, SchemaEntry("ifcminuteinhour",NULL ) , SchemaEntry("ifcminuteinhour",nullptr )
, SchemaEntry("ifcinternalorexternalenum",NULL ) , SchemaEntry("ifcinternalorexternalenum",nullptr )
, SchemaEntry("ifcrotationalfrequencymeasure",NULL ) , SchemaEntry("ifcrotationalfrequencymeasure",nullptr )
, SchemaEntry("ifcsanitaryterminaltypeenum",NULL ) , SchemaEntry("ifcsanitaryterminaltypeenum",nullptr )
, SchemaEntry("ifcsymbolstyleselect",NULL ) , SchemaEntry("ifcsymbolstyleselect",nullptr )
, SchemaEntry("ifcelementcompositionenum",NULL ) , SchemaEntry("ifcelementcompositionenum",nullptr )
, SchemaEntry("ifctextpath",NULL ) , SchemaEntry("ifctextpath",nullptr )
, SchemaEntry("ifcpowermeasure",NULL ) , SchemaEntry("ifcpowermeasure",nullptr )
, SchemaEntry("ifcsurfacestyleelementselect",NULL ) , SchemaEntry("ifcsurfacestyleelementselect",nullptr )
, SchemaEntry("ifcresourceconsumptionenum",NULL ) , SchemaEntry("ifcresourceconsumptionenum",nullptr )
, SchemaEntry("ifcelectriccapacitancemeasure",NULL ) , SchemaEntry("ifcelectriccapacitancemeasure",nullptr )
, SchemaEntry("ifclayersetdirectionenum",NULL ) , SchemaEntry("ifclayersetdirectionenum",nullptr )
, SchemaEntry("ifcrailingtypeenum",NULL ) , SchemaEntry("ifcrailingtypeenum",nullptr )
, SchemaEntry("ifcobjectiveenum",NULL ) , SchemaEntry("ifcobjectiveenum",nullptr )
, SchemaEntry("ifcdocumentselect",NULL ) , SchemaEntry("ifcdocumentselect",nullptr )
, SchemaEntry("ifcmodulusoflinearsubgradereactionmeasure",NULL ) , SchemaEntry("ifcmodulusoflinearsubgradereactionmeasure",nullptr )
, SchemaEntry("ifcthermaladmittancemeasure",NULL ) , SchemaEntry("ifcthermaladmittancemeasure",nullptr )
, SchemaEntry("ifctransitioncode",NULL ) , SchemaEntry("ifctransitioncode",nullptr )
, SchemaEntry("ifcconnectiontypeenum",NULL ) , SchemaEntry("ifcconnectiontypeenum",nullptr )
, SchemaEntry("ifcmonetarymeasure",NULL ) , SchemaEntry("ifcmonetarymeasure",nullptr )
, SchemaEntry("ifcstackterminaltypeenum",NULL ) , SchemaEntry("ifcstackterminaltypeenum",nullptr )
, SchemaEntry("ifccolour",NULL ) , SchemaEntry("ifccolour",nullptr )
, SchemaEntry("ifctext",NULL ) , SchemaEntry("ifctext",nullptr )
, SchemaEntry("ifccontextdependentmeasure",NULL ) , SchemaEntry("ifccontextdependentmeasure",nullptr )
, SchemaEntry("ifcthermalconductivitymeasure",NULL ) , SchemaEntry("ifcthermalconductivitymeasure",nullptr )
, SchemaEntry("ifcprojectedortruelengthenum",NULL ) , SchemaEntry("ifcprojectedortruelengthenum",nullptr )
, SchemaEntry("ifcpressuremeasure",NULL ) , SchemaEntry("ifcpressuremeasure",nullptr )
, SchemaEntry("ifcmoisturediffusivitymeasure",NULL ) , SchemaEntry("ifcmoisturediffusivitymeasure",nullptr )
, SchemaEntry("ifcbooleanoperator",NULL ) , SchemaEntry("ifcbooleanoperator",nullptr )
, SchemaEntry("ifcpropertysourceenum",NULL ) , SchemaEntry("ifcpropertysourceenum",nullptr )
, SchemaEntry("ifctimestamp",NULL ) , SchemaEntry("ifctimestamp",nullptr )
, SchemaEntry("ifcmaterialselect",NULL ) , SchemaEntry("ifcmaterialselect",nullptr )
, SchemaEntry("ifcgloballyuniqueid",NULL ) , SchemaEntry("ifcgloballyuniqueid",nullptr )
, SchemaEntry("ifcreflectancemethodenum",NULL ) , SchemaEntry("ifcreflectancemethodenum",nullptr )
, SchemaEntry("ifcvaporpermeabilitymeasure",NULL ) , SchemaEntry("ifcvaporpermeabilitymeasure",nullptr )
, SchemaEntry("ifctimeseriesscheduletypeenum",NULL ) , SchemaEntry("ifctimeseriesscheduletypeenum",nullptr )
, SchemaEntry("ifclinearmomentmeasure",NULL ) , SchemaEntry("ifclinearmomentmeasure",nullptr )
, SchemaEntry("ifcgeometricsetselect",NULL ) , SchemaEntry("ifcgeometricsetselect",nullptr )
, SchemaEntry("ifcsectionmodulusmeasure",NULL ) , SchemaEntry("ifcsectionmodulusmeasure",nullptr )
, SchemaEntry("ifcbsplinecurveform",NULL ) , SchemaEntry("ifcbsplinecurveform",nullptr )
, SchemaEntry("ifcdimensionextentusage",NULL ) , SchemaEntry("ifcdimensionextentusage",nullptr )
, SchemaEntry("ifcthermalexpansioncoefficientmeasure",NULL ) , SchemaEntry("ifcthermalexpansioncoefficientmeasure",nullptr )
, SchemaEntry("ifchourinday",NULL ) , SchemaEntry("ifchourinday",nullptr )
, SchemaEntry("ifclinearvelocitymeasure",NULL ) , SchemaEntry("ifclinearvelocitymeasure",nullptr )
, SchemaEntry("ifctorquemeasure",NULL ) , SchemaEntry("ifctorquemeasure",nullptr )
, SchemaEntry("ifctemperaturegradientmeasure",NULL ) , SchemaEntry("ifctemperaturegradientmeasure",nullptr )
, SchemaEntry("ifcfillstyleselect",NULL ) , SchemaEntry("ifcfillstyleselect",nullptr )
, SchemaEntry("ifcelectricchargemeasure",NULL ) , SchemaEntry("ifcelectricchargemeasure",nullptr )
, SchemaEntry("ifcheatexchangertypeenum",NULL ) , SchemaEntry("ifcheatexchangertypeenum",nullptr )
, SchemaEntry("ifcelectriccurrentenum",NULL ) , SchemaEntry("ifcelectriccurrentenum",nullptr )
, SchemaEntry("ifcdaylightsavinghour",NULL ) , SchemaEntry("ifcdaylightsavinghour",nullptr )
, SchemaEntry("ifcshell",NULL ) , SchemaEntry("ifcshell",nullptr )
, SchemaEntry("ifcdoseequivalentmeasure",NULL ) , SchemaEntry("ifcdoseequivalentmeasure",nullptr )
, SchemaEntry("ifcprojectordertypeenum",NULL ) , SchemaEntry("ifcprojectordertypeenum",nullptr )
, SchemaEntry("ifcderivedmeasurevalue",NULL ) , SchemaEntry("ifcderivedmeasurevalue",nullptr )
, SchemaEntry("ifclightdistributioncurveenum",NULL ) , SchemaEntry("ifclightdistributioncurveenum",nullptr )
, SchemaEntry("ifcwarpingmomentmeasure",NULL ) , SchemaEntry("ifcwarpingmomentmeasure",nullptr )
, SchemaEntry("ifcmembertypeenum",NULL ) , SchemaEntry("ifcmembertypeenum",nullptr )
, SchemaEntry("ifcsoundpowermeasure",NULL ) , SchemaEntry("ifcsoundpowermeasure",nullptr )
, SchemaEntry("ifctextalignment",NULL ) , SchemaEntry("ifctextalignment",nullptr )
, SchemaEntry("ifccurveoredgecurve",NULL ) , SchemaEntry("ifccurveoredgecurve",nullptr )
, SchemaEntry("ifcmassflowratemeasure",NULL ) , SchemaEntry("ifcmassflowratemeasure",nullptr )
, SchemaEntry("ifcisothermalmoisturecapacitymeasure",NULL ) , SchemaEntry("ifcisothermalmoisturecapacitymeasure",nullptr )
, SchemaEntry("ifccsgselect",NULL ) , SchemaEntry("ifccsgselect",nullptr )
, SchemaEntry("ifccoolingtowertypeenum",NULL ) , SchemaEntry("ifccoolingtowertypeenum",nullptr )
, SchemaEntry("ifcmassmeasure",NULL ) , SchemaEntry("ifcmassmeasure",nullptr )
, SchemaEntry("ifcpileconstructionenum",NULL ) , SchemaEntry("ifcpileconstructionenum",nullptr )
, SchemaEntry("ifcdoorstyleoperationenum",NULL ) , SchemaEntry("ifcdoorstyleoperationenum",nullptr )
, SchemaEntry("ifcflowdirectionenum",NULL ) , SchemaEntry("ifcflowdirectionenum",nullptr )
, SchemaEntry("ifcthermalloadsourceenum",NULL ) , SchemaEntry("ifcthermalloadsourceenum",nullptr )
, SchemaEntry("ifclengthmeasure",NULL ) , SchemaEntry("ifclengthmeasure",nullptr )
, SchemaEntry("ifcconstraintenum",NULL ) , SchemaEntry("ifcconstraintenum",nullptr )
, SchemaEntry("ifcaxis2placement",NULL ) , SchemaEntry("ifcaxis2placement",nullptr )
, SchemaEntry("ifcloadgrouptypeenum",NULL ) , SchemaEntry("ifcloadgrouptypeenum",nullptr )
, SchemaEntry("ifcvalue",NULL ) , SchemaEntry("ifcvalue",nullptr )
, SchemaEntry("ifcreinforcingbarsurfaceenum",NULL ) , SchemaEntry("ifcreinforcingbarsurfaceenum",nullptr )
, SchemaEntry("ifcprojectorderrecordtypeenum",NULL ) , SchemaEntry("ifcprojectorderrecordtypeenum",nullptr )
, SchemaEntry("ifcdatetimeselect",NULL ) , SchemaEntry("ifcdatetimeselect",nullptr )
, SchemaEntry("ifcstructuralsurfacetypeenum",NULL ) , SchemaEntry("ifcstructuralsurfacetypeenum",nullptr )
, SchemaEntry("ifcpermeablecoveringoperationenum",NULL ) , SchemaEntry("ifcpermeablecoveringoperationenum",nullptr )
, SchemaEntry("ifcfontweight",NULL ) , SchemaEntry("ifcfontweight",nullptr )
, SchemaEntry("ifcphmeasure",NULL ) , SchemaEntry("ifcphmeasure",nullptr )
, SchemaEntry("ifcdescriptivemeasure",NULL ) , SchemaEntry("ifcdescriptivemeasure",nullptr )
, SchemaEntry("ifccurvestylefontselect",NULL ) , SchemaEntry("ifccurvestylefontselect",nullptr )
, SchemaEntry("ifcunit",NULL ) , SchemaEntry("ifcunit",nullptr )
, SchemaEntry("ifchatchlinedistanceselect",NULL ) , SchemaEntry("ifchatchlinedistanceselect",nullptr )
, SchemaEntry("ifctextstyleselect",NULL ) , SchemaEntry("ifctextstyleselect",nullptr )
, SchemaEntry("ifcmetricvalueselect",NULL ) , SchemaEntry("ifcmetricvalueselect",nullptr )
, SchemaEntry("ifcvectorordirection",NULL ) , SchemaEntry("ifcvectorordirection",nullptr )
, SchemaEntry("ifcassemblyplaceenum",NULL ) , SchemaEntry("ifcassemblyplaceenum",nullptr )
, SchemaEntry("ifcairterminaltypeenum",NULL ) , SchemaEntry("ifcairterminaltypeenum",nullptr )
, SchemaEntry("ifccoveringtypeenum",NULL ) , SchemaEntry("ifccoveringtypeenum",nullptr )
, SchemaEntry("ifcplanarforcemeasure",NULL ) , SchemaEntry("ifcplanarforcemeasure",nullptr )
, SchemaEntry("ifcvalvetypeenum",NULL ) , SchemaEntry("ifcvalvetypeenum",nullptr )
, SchemaEntry("ifcalarmtypeenum",NULL ) , SchemaEntry("ifcalarmtypeenum",nullptr )
, SchemaEntry("ifcdynamicviscositymeasure",NULL ) , SchemaEntry("ifcdynamicviscositymeasure",nullptr )
, SchemaEntry("ifccurrencyenum",NULL ) , SchemaEntry("ifccurrencyenum",nullptr )
, SchemaEntry("ifcmodulusofrotationalsubgradereactionmeasure",NULL ) , SchemaEntry("ifcmodulusofrotationalsubgradereactionmeasure",nullptr )
, SchemaEntry("ifccablecarrierfittingtypeenum",NULL ) , SchemaEntry("ifccablecarrierfittingtypeenum",nullptr )
, SchemaEntry("ifcboolean",NULL ) , SchemaEntry("ifcboolean",nullptr )
, SchemaEntry("ifcactionsourcetypeenum",NULL ) , SchemaEntry("ifcactionsourcetypeenum",nullptr )
, SchemaEntry("ifcstructuralactivityassignmentselect",NULL ) , SchemaEntry("ifcstructuralactivityassignmentselect",nullptr )
, SchemaEntry("ifcdistributionchamberelementtypeenum",NULL ) , SchemaEntry("ifcdistributionchamberelementtypeenum",nullptr )
, SchemaEntry("ifcevaporativecoolertypeenum",NULL ) , SchemaEntry("ifcevaporativecoolertypeenum",nullptr )
, SchemaEntry("ifcmagneticfluxdensitymeasure",NULL ) , SchemaEntry("ifcmagneticfluxdensitymeasure",nullptr )
, SchemaEntry("ifclightdistributiondatasourceselect",NULL ) , SchemaEntry("ifclightdistributiondatasourceselect",nullptr )
, SchemaEntry("ifctubebundletypeenum",NULL ) , SchemaEntry("ifctubebundletypeenum",nullptr )
, SchemaEntry("ifcaccelerationmeasure",NULL ) , SchemaEntry("ifcaccelerationmeasure",nullptr )
, SchemaEntry("ifcboilertypeenum",NULL ) , SchemaEntry("ifcboilertypeenum",nullptr )
, SchemaEntry("ifcramptypeenum",NULL ) , SchemaEntry("ifcramptypeenum",nullptr )
, SchemaEntry("ifcluminousintensitydistributionmeasure",NULL ) , SchemaEntry("ifcluminousintensitydistributionmeasure",nullptr )
, SchemaEntry("ifctrimmingpreference",NULL ) , SchemaEntry("ifctrimmingpreference",nullptr )
, SchemaEntry("ifcspecificheatcapacitymeasure",NULL ) , SchemaEntry("ifcspecificheatcapacitymeasure",nullptr )
, SchemaEntry("ifcamountofsubstancemeasure",NULL ) , SchemaEntry("ifcamountofsubstancemeasure",nullptr )
, SchemaEntry("ifcroleenum",NULL ) , SchemaEntry("ifcroleenum",nullptr )
, SchemaEntry("ifcdocumentconfidentialityenum",NULL ) , SchemaEntry("ifcdocumentconfidentialityenum",nullptr )
, SchemaEntry("ifcfrequencymeasure",NULL ) , SchemaEntry("ifcfrequencymeasure",nullptr )
, SchemaEntry("ifcsectiontypeenum",NULL ) , SchemaEntry("ifcsectiontypeenum",nullptr )
, SchemaEntry("ifcelementassemblytypeenum",NULL ) , SchemaEntry("ifcelementassemblytypeenum",nullptr )
, SchemaEntry("ifcfootingtypeenum",NULL ) , SchemaEntry("ifcfootingtypeenum",nullptr )
, SchemaEntry("ifclayereditem",NULL ) , SchemaEntry("ifclayereditem",nullptr )
, SchemaEntry("ifccablesegmenttypeenum",NULL ) , SchemaEntry("ifccablesegmenttypeenum",nullptr )
, SchemaEntry("ifcdefinedsymbolselect",NULL ) , SchemaEntry("ifcdefinedsymbolselect",nullptr )
, SchemaEntry("ifcbuildingelementproxytypeenum",NULL ) , SchemaEntry("ifcbuildingelementproxytypeenum",nullptr )
, SchemaEntry("ifcelectricgeneratortypeenum",NULL ) , SchemaEntry("ifcelectricgeneratortypeenum",nullptr )
, SchemaEntry("ifcrotationalstiffnessmeasure",NULL ) , SchemaEntry("ifcrotationalstiffnessmeasure",nullptr )
, SchemaEntry("ifcspaceheatertypeenum",NULL ) , SchemaEntry("ifcspaceheatertypeenum",nullptr )
, SchemaEntry("ifcareameasure",NULL ) , SchemaEntry("ifcareameasure",nullptr )
, SchemaEntry("ifclabel",NULL ) , SchemaEntry("ifclabel",nullptr )
, SchemaEntry("ifccostscheduletypeenum",NULL ) , SchemaEntry("ifccostscheduletypeenum",nullptr )
, SchemaEntry("ifcswitchingdevicetypeenum",NULL ) , SchemaEntry("ifcswitchingdevicetypeenum",nullptr )
, SchemaEntry("ifcelectrictimecontroltypeenum",NULL ) , SchemaEntry("ifcelectrictimecontroltypeenum",nullptr )
, SchemaEntry("ifcfiltertypeenum",NULL ) , SchemaEntry("ifcfiltertypeenum",nullptr )
, SchemaEntry("ifcpositivelengthmeasure",NULL ) , SchemaEntry("ifcpositivelengthmeasure",nullptr )
, SchemaEntry("ifcnullstyle",NULL ) , SchemaEntry("ifcnullstyle",nullptr )
, SchemaEntry("ifcconditioncriterionselect",NULL ) , SchemaEntry("ifcconditioncriterionselect",nullptr )
, SchemaEntry("ifcshearmodulusmeasure",NULL ) , SchemaEntry("ifcshearmodulusmeasure",nullptr )
, SchemaEntry("ifcnormalisedratiomeasure",NULL ) , SchemaEntry("ifcnormalisedratiomeasure",nullptr )
, SchemaEntry("ifcdoorpaneloperationenum",NULL ) , SchemaEntry("ifcdoorpaneloperationenum",nullptr )
, SchemaEntry("ifcpointorvertexpoint",NULL ) , SchemaEntry("ifcpointorvertexpoint",nullptr )
, SchemaEntry("ifcrooftypeenum",NULL ) , SchemaEntry("ifcrooftypeenum",nullptr )
, SchemaEntry("ifccountmeasure",NULL ) , SchemaEntry("ifccountmeasure",nullptr )
, SchemaEntry("ifcelectricconductancemeasure",NULL ) , SchemaEntry("ifcelectricconductancemeasure",nullptr )
, SchemaEntry("ifcproceduretypeenum",NULL ) , SchemaEntry("ifcproceduretypeenum",nullptr )
, SchemaEntry("ifcflowinstrumenttypeenum",NULL ) , SchemaEntry("ifcflowinstrumenttypeenum",nullptr )
, SchemaEntry("ifcelectricmotortypeenum",NULL ) , SchemaEntry("ifcelectricmotortypeenum",nullptr )
, SchemaEntry("ifcsurfaceside",NULL ) , SchemaEntry("ifcsurfaceside",nullptr )
, SchemaEntry("ifcstructuralcurvetypeenum",NULL ) , SchemaEntry("ifcstructuralcurvetypeenum",nullptr )
, SchemaEntry("ifccondensertypeenum",NULL ) , SchemaEntry("ifccondensertypeenum",nullptr )
, SchemaEntry("ifclinearstiffnessmeasure",NULL ) , SchemaEntry("ifclinearstiffnessmeasure",nullptr )
, SchemaEntry("ifcunitenum",NULL ) , SchemaEntry("ifcunitenum",nullptr )
, SchemaEntry("ifcoccupanttypeenum",NULL ) , SchemaEntry("ifcoccupanttypeenum",nullptr )
, SchemaEntry("ifcthermalloadtypeenum",NULL ) , SchemaEntry("ifcthermalloadtypeenum",nullptr )
, SchemaEntry("ifcreinforcingbarroleenum",NULL ) , SchemaEntry("ifcreinforcingbarroleenum",nullptr )
, SchemaEntry("ifcbenchmarkenum",NULL ) , SchemaEntry("ifcbenchmarkenum",nullptr )
, SchemaEntry("ifcpositiveplaneanglemeasure",NULL ) , SchemaEntry("ifcpositiveplaneanglemeasure",nullptr )
, SchemaEntry("ifctexttransformation",NULL ) , SchemaEntry("ifctexttransformation",nullptr )
, SchemaEntry("ifcdraughtingcalloutelement",NULL ) , SchemaEntry("ifcdraughtingcalloutelement",nullptr )
, SchemaEntry("ifcratiomeasure",NULL ) , SchemaEntry("ifcratiomeasure",nullptr )
, SchemaEntry("ifcsolidanglemeasure",NULL ) , SchemaEntry("ifcsolidanglemeasure",nullptr )
, SchemaEntry("ifcpipesegmenttypeenum",NULL ) , SchemaEntry("ifcpipesegmenttypeenum",nullptr )
, SchemaEntry("ifccablecarriersegmenttypeenum",NULL ) , SchemaEntry("ifccablecarriersegmenttypeenum",nullptr )
, SchemaEntry("ifccolourorfactor",NULL ) , SchemaEntry("ifccolourorfactor",nullptr )
, SchemaEntry("ifcidentifier",NULL ) , SchemaEntry("ifcidentifier",nullptr )
, SchemaEntry("ifctendontypeenum",NULL ) , SchemaEntry("ifctendontypeenum",nullptr )
, SchemaEntry("ifccontrollertypeenum",NULL ) , SchemaEntry("ifccontrollertypeenum",nullptr )
, SchemaEntry("ifcradioactivitymeasure",NULL ) , SchemaEntry("ifcradioactivitymeasure",nullptr )
, SchemaEntry("ifctimemeasure",NULL ) , SchemaEntry("ifctimemeasure",nullptr )
, SchemaEntry("ifcpumptypeenum",NULL ) , SchemaEntry("ifcpumptypeenum",nullptr )
, SchemaEntry("ifcelectricheatertypeenum",NULL ) , SchemaEntry("ifcelectricheatertypeenum",nullptr )
, SchemaEntry("ifcbeamtypeenum",NULL ) , SchemaEntry("ifcbeamtypeenum",nullptr )
, SchemaEntry("ifcstateenum",NULL ) , SchemaEntry("ifcstateenum",nullptr )
, SchemaEntry("ifcsiprefix",NULL ) , SchemaEntry("ifcsiprefix",nullptr )
, SchemaEntry("ifcnumericmeasure",NULL ) , SchemaEntry("ifcnumericmeasure",nullptr )
, SchemaEntry("ifcoutlettypeenum",NULL ) , SchemaEntry("ifcoutlettypeenum",nullptr )
, SchemaEntry("ifccompoundplaneanglemeasure",NULL ) , SchemaEntry("ifccompoundplaneanglemeasure",nullptr )
, SchemaEntry("ifcservicelifefactortypeenum",NULL ) , SchemaEntry("ifcservicelifefactortypeenum",nullptr )
, SchemaEntry("ifclogicaloperatorenum",NULL ) , SchemaEntry("ifclogicaloperatorenum",nullptr )
, SchemaEntry("ifcbooleanoperand",NULL ) , SchemaEntry("ifcbooleanoperand",nullptr )
, SchemaEntry("ifcobjectreferenceselect",NULL ) , SchemaEntry("ifcobjectreferenceselect",nullptr )
, SchemaEntry("ifccooledbeamtypeenum",NULL ) , SchemaEntry("ifccooledbeamtypeenum",nullptr )
, SchemaEntry("ifcductsilencertypeenum",NULL ) , SchemaEntry("ifcductsilencertypeenum",nullptr )
, SchemaEntry("ifcsectionalareaintegralmeasure",NULL ) , SchemaEntry("ifcsectionalareaintegralmeasure",nullptr )
, SchemaEntry("ifcfontvariant",NULL ) , SchemaEntry("ifcfontvariant",nullptr )
, SchemaEntry("ifcvolumetricflowratemeasure",NULL ) , SchemaEntry("ifcvolumetricflowratemeasure",nullptr )
, SchemaEntry("ifcplatetypeenum",NULL ) , SchemaEntry("ifcplatetypeenum",nullptr )
, SchemaEntry("ifcenvironmentalimpactcategoryenum",NULL ) , SchemaEntry("ifcenvironmentalimpactcategoryenum",nullptr )
, SchemaEntry("ifcvibrationisolatortypeenum",NULL ) , SchemaEntry("ifcvibrationisolatortypeenum",nullptr )
, SchemaEntry("ifcthermodynamictemperaturemeasure",NULL ) , SchemaEntry("ifcthermodynamictemperaturemeasure",nullptr )
, SchemaEntry("ifcrotationalmassmeasure",NULL ) , SchemaEntry("ifcrotationalmassmeasure",nullptr )
, SchemaEntry("ifcsecondinminute",NULL ) , SchemaEntry("ifcsecondinminute",nullptr )
, SchemaEntry("ifcdayinmonthnumber",NULL ) , SchemaEntry("ifcdayinmonthnumber",nullptr )
, SchemaEntry("ifcdimensioncount",NULL ) , SchemaEntry("ifcdimensioncount",nullptr )
, SchemaEntry("ifcwindowstyleoperationenum",NULL ) , SchemaEntry("ifcwindowstyleoperationenum",nullptr )
, SchemaEntry("ifcthermalresistancemeasure",NULL ) , SchemaEntry("ifcthermalresistancemeasure",nullptr )
, SchemaEntry("ifcmeasurevalue",NULL ) , SchemaEntry("ifcmeasurevalue",nullptr )
, SchemaEntry("ifcwindowpaneloperationenum",NULL ) , SchemaEntry("ifcwindowpaneloperationenum",nullptr )
, SchemaEntry("ifcchillertypeenum",NULL ) , SchemaEntry("ifcchillertypeenum",nullptr )
, SchemaEntry("ifcpositiveratiomeasure",NULL ) , SchemaEntry("ifcpositiveratiomeasure",nullptr )
, SchemaEntry("ifcinteger",NULL ) , SchemaEntry("ifcinteger",nullptr )
, SchemaEntry("ifclogical",NULL ) , SchemaEntry("ifclogical",nullptr )
, SchemaEntry("ifcjunctionboxtypeenum",NULL ) , SchemaEntry("ifcjunctionboxtypeenum",nullptr )
, SchemaEntry("ifcaddresstypeenum",NULL ) , SchemaEntry("ifcaddresstypeenum",nullptr )
, SchemaEntry("ifcwasteterminaltypeenum",NULL ) , SchemaEntry("ifcwasteterminaltypeenum",nullptr )
, SchemaEntry("ifctrimmingselect",NULL ) , SchemaEntry("ifctrimmingselect",nullptr )
, SchemaEntry("ifclightemissionsourceenum",NULL ) , SchemaEntry("ifclightemissionsourceenum",nullptr )
, SchemaEntry("ifcsoundscaleenum",NULL ) , SchemaEntry("ifcsoundscaleenum",nullptr )
, SchemaEntry("ifcluminousfluxmeasure",NULL ) , SchemaEntry("ifcluminousfluxmeasure",nullptr )
, SchemaEntry("ifcelectricresistancemeasure",NULL ) , SchemaEntry("ifcelectricresistancemeasure",nullptr )
, SchemaEntry("ifcintegercountratemeasure",NULL ) , SchemaEntry("ifcintegercountratemeasure",nullptr )
, SchemaEntry("ifcphysicalorvirtualenum",NULL ) , SchemaEntry("ifcphysicalorvirtualenum",nullptr )
, SchemaEntry("ifcmolecularweightmeasure",NULL ) , SchemaEntry("ifcmolecularweightmeasure",nullptr )
, SchemaEntry("ifcprofiletypeenum",NULL ) , SchemaEntry("ifcprofiletypeenum",nullptr )
, SchemaEntry("ifcboxalignment",NULL ) , SchemaEntry("ifcboxalignment",nullptr )
, SchemaEntry("ifcglobalorlocalenum",NULL ) , SchemaEntry("ifcglobalorlocalenum",nullptr )
, SchemaEntry("ifcspecularroughness",NULL ) , SchemaEntry("ifcspecularroughness",nullptr )
, SchemaEntry("ifclamptypeenum",NULL ) , SchemaEntry("ifclamptypeenum",nullptr )
, SchemaEntry("ifcpiletypeenum",NULL ) , SchemaEntry("ifcpiletypeenum",nullptr )
, SchemaEntry("ifcelectriccurrentmeasure",NULL ) , SchemaEntry("ifcelectriccurrentmeasure",nullptr )
, SchemaEntry("ifcfantypeenum",NULL ) , SchemaEntry("ifcfantypeenum",nullptr )
, SchemaEntry("ifcsurfaceorfacesurface",NULL ) , SchemaEntry("ifcsurfaceorfacesurface",nullptr )
, SchemaEntry("ifcpipefittingtypeenum",NULL ) , SchemaEntry("ifcpipefittingtypeenum",nullptr )
, SchemaEntry("ifctanktypeenum",NULL ) , SchemaEntry("ifctanktypeenum",nullptr )
, SchemaEntry("ifccurvefontorscaledcurvefontselect",NULL ) , SchemaEntry("ifccurvefontorscaledcurvefontselect",nullptr )
, SchemaEntry("ifcwindowstyleconstructionenum",NULL ) , SchemaEntry("ifcwindowstyleconstructionenum",nullptr )
, SchemaEntry("ifcairterminalboxtypeenum",NULL ) , SchemaEntry("ifcairterminalboxtypeenum",nullptr )
, SchemaEntry("ifcstairflighttypeenum",NULL ) , SchemaEntry("ifcstairflighttypeenum",nullptr )
, SchemaEntry("ifcluminousintensitymeasure",NULL ) , SchemaEntry("ifcluminousintensitymeasure",nullptr )
, SchemaEntry("ifcmotorconnectiontypeenum",NULL ) , SchemaEntry("ifcmotorconnectiontypeenum",nullptr )
, SchemaEntry("ifcplaneanglemeasure",NULL ) , SchemaEntry("ifcplaneanglemeasure",nullptr )
, SchemaEntry("ifcactuatortypeenum",NULL ) , SchemaEntry("ifcactuatortypeenum",nullptr )
, SchemaEntry("ifccolumntypeenum",NULL ) , SchemaEntry("ifccolumntypeenum",nullptr )
, SchemaEntry("ifctextfontselect",NULL ) , SchemaEntry("ifctextfontselect",nullptr )
, SchemaEntry("ifcdoorpanelpositionenum",NULL ) , SchemaEntry("ifcdoorpanelpositionenum",nullptr )
, SchemaEntry("ifccoiltypeenum",NULL ) , SchemaEntry("ifccoiltypeenum",nullptr )
, SchemaEntry("ifcangularvelocitymeasure",NULL ) , SchemaEntry("ifcangularvelocitymeasure",nullptr )
, SchemaEntry("ifcanalysismodeltypeenum",NULL ) , SchemaEntry("ifcanalysismodeltypeenum",nullptr )
, SchemaEntry("ifclibraryselect",NULL ) , SchemaEntry("ifclibraryselect",nullptr )
, SchemaEntry("ifcforcemeasure",NULL ) , SchemaEntry("ifcforcemeasure",nullptr )
, SchemaEntry("ifcfillareastyletileshapeselect",NULL ) , SchemaEntry("ifcfillareastyletileshapeselect",nullptr )
, SchemaEntry("ifcelectricappliancetypeenum",NULL ) , SchemaEntry("ifcelectricappliancetypeenum",nullptr )
, SchemaEntry("ifcsurfacetextureenum",NULL ) , SchemaEntry("ifcsurfacetextureenum",nullptr )
, SchemaEntry("ifccharacterstyleselect",NULL ) , SchemaEntry("ifccharacterstyleselect",nullptr )
, SchemaEntry("ifcenergymeasure",NULL ) , SchemaEntry("ifcenergymeasure",nullptr )
, SchemaEntry("ifcreal",NULL ) , SchemaEntry("ifcreal",nullptr )
, SchemaEntry("ifccompressortypeenum",NULL ) , SchemaEntry("ifccompressortypeenum",nullptr )
, SchemaEntry("ifcelectricdistributionpointfunctionenum",NULL ) , SchemaEntry("ifcelectricdistributionpointfunctionenum",nullptr )
, SchemaEntry("ifcroot",&STEP::ObjectHelper<IfcRoot,4>::Construct ) , SchemaEntry("ifcroot",&STEP::ObjectHelper<IfcRoot,4>::Construct )
, SchemaEntry("ifcobjectdefinition",&STEP::ObjectHelper<IfcObjectDefinition,0>::Construct ) , SchemaEntry("ifcobjectdefinition",&STEP::ObjectHelper<IfcObjectDefinition,0>::Construct )
, SchemaEntry("ifctypeobject",&STEP::ObjectHelper<IfcTypeObject,2>::Construct ) , SchemaEntry("ifctypeobject",&STEP::ObjectHelper<IfcTypeObject,2>::Construct )

View File

@ -71,7 +71,7 @@ aiMesh* TempMesh::ToMesh()
ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(),mVertcnt.end(),size_t(0))); ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(),mVertcnt.end(),size_t(0)));
if (mVerts.empty()) { if (mVerts.empty()) {
return NULL; return nullptr;
} }
std::unique_ptr<aiMesh> mesh(new aiMesh()); std::unique_ptr<aiMesh> mesh(new aiMesh());

View File

@ -201,7 +201,7 @@ struct ConversionData
struct MeshCacheIndex { struct MeshCacheIndex {
const IFC::Schema_2x3::IfcRepresentationItem* item; unsigned int matindex; const IFC::Schema_2x3::IfcRepresentationItem* item; unsigned int matindex;
MeshCacheIndex() : item(NULL), matindex(0) { } MeshCacheIndex() : item(nullptr), matindex(0) { }
MeshCacheIndex(const IFC::Schema_2x3::IfcRepresentationItem* i, unsigned int mi) : item(i), matindex(mi) { } MeshCacheIndex(const IFC::Schema_2x3::IfcRepresentationItem* i, unsigned int mi) : item(i), matindex(mi) { }
bool operator == (const MeshCacheIndex& o) const { return item == o.item && matindex == o.matindex; } bool operator == (const MeshCacheIndex& o) const { return item == o.item && matindex == o.matindex; }
bool operator < (const MeshCacheIndex& o) const { return item < o.item || (item == o.item && matindex < o.matindex); } bool operator < (const MeshCacheIndex& o) const { return item < o.item || (item == o.item && matindex < o.matindex); }

File diff suppressed because it is too large Load Diff

View File

@ -139,8 +139,9 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile)); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) if (file.get() == nullptr) {
throw DeadlyImportError( "Failed to open IRRMESH file " + pFile + ""); throw DeadlyImportError("Failed to open IRRMESH file " + pFile + ".");
}
// Construct the irrXML parser // Construct the irrXML parser
CIrrXML_IOStreamReader st(file.get()); CIrrXML_IOStreamReader st(file.get());

View File

@ -538,11 +538,11 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey> &out,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Extract animation channel // Extract animation channel
void AnimResolver::ExtractAnimChannel(aiNodeAnim **out, unsigned int /*= 0*/) { void AnimResolver::ExtractAnimChannel(aiNodeAnim **out, unsigned int /*= 0*/) {
*out = NULL; *out = nullptr;
//FIXME: crashes if more than one component is animated at different timings, to be resolved. //FIXME: crashes if more than one component is animated at different timings, to be resolved.
// If we have no envelopes, return NULL // If we have no envelopes, return nullptr
if (envelopes.empty()) { if (envelopes.empty()) {
return; return;
} }

View File

@ -211,7 +211,7 @@ public:
// ------------------------------------------------------------------ // ------------------------------------------------------------------
/** @brief Extract a node animation channel /** @brief Extract a node animation channel
* @param out Receives a pointer to a newly allocated node anim. * @param out Receives a pointer to a newly allocated node anim.
* If there's just one keyframe defined, *out is set to NULL and * If there's just one keyframe defined, *out is set to nullptr and
* no animation channel is computed. * no animation channel is computed.
* @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
*/ */
@ -261,7 +261,7 @@ protected:
* @param envl_y Y-component envelope * @param envl_y Y-component envelope
* @param envl_z Z-component envelope * @param envl_z Z-component envelope
* @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
* @note Up to two input envelopes may be NULL * @note Up to two input envelopes may be nullptr
*/ */
void GetKeys(std::vector<aiVectorKey>& out, void GetKeys(std::vector<aiVectorKey>& out,
LWO::Envelope* envl_x, LWO::Envelope* envl_x,

View File

@ -255,7 +255,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
mSurfaces->push_back( LWO::Surface () ); mSurfaces->push_back( LWO::Surface () );
LWO::Surface& surf = mSurfaces->back(); LWO::Surface& surf = mSurfaces->back();
LWO::Texture* pTex = NULL; LWO::Texture *pTex = nullptr;
GetS0(surf.mName,size); GetS0(surf.mName,size);
bool running = true; bool running = true;

View File

@ -917,7 +917,7 @@ inline void CreateNewEntry(std::vector<T> &list, unsigned int srcIdx) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry *base, unsigned int numRead, inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry *base, unsigned int numRead,
unsigned int idx, float *data) { unsigned int idx, float *data) {
ai_assert(NULL != data); ai_assert(nullptr != data);
LWO::ReferrerList &refList = mCurLayer->mPointReferrers; LWO::ReferrerList &refList = mCurLayer->mPointReferrers;
unsigned int i; unsigned int i;

View File

@ -305,7 +305,7 @@ private:
/** Add children to a node /** Add children to a node
* @param node Node to become a father * @param node Node to become a father
* @param parent Index of the node * @param parent Index of the node
* @param apcNodes Flat list of nodes - used nodes are set to NULL. * @param apcNodes Flat list of nodes - used nodes are set to nullptr.
*/ */
void AddChildren(aiNode* node, uint16_t parent, void AddChildren(aiNode* node, uint16_t parent,
std::vector<aiNode*>& apcNodes); std::vector<aiNode*>& apcNodes);

View File

@ -79,7 +79,7 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTextureType type) { bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTextureType type) {
ai_assert(NULL != pcMat); ai_assert(nullptr != pcMat);
unsigned int cur = 0, temp = 0; unsigned int cur = 0, temp = 0;
aiString s; aiString s;
@ -603,7 +603,7 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader *head, unsi
} }
// get the destination channel // get the destination channel
TextureList *listRef = NULL; TextureList *listRef = nullptr;
switch (tex.type) { switch (tex.type) {
case AI_LWO_COLR: case AI_LWO_COLR:
listRef = &surf.mColorTextures; listRef = &surf.mColorTextures;

View File

@ -342,7 +342,7 @@ void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector<Attachm
if (src.type == LWS::NodeDesc::OBJECT) { if (src.type == LWS::NodeDesc::OBJECT) {
// If the object is from an external file, get it // If the object is from an external file, get it
aiScene *obj = NULL; aiScene *obj = nullptr;
if (src.path.length()) { if (src.path.length()) {
obj = batch.GetImport(src.id); obj = batch.GetImport(src.id);
if (!obj) { if (!obj) {
@ -359,7 +359,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) //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; obj->mRootNode->mChildren[0] = nullptr;
delete obj->mRootNode; delete obj->mRootNode;
obj->mRootNode = newRootNode; obj->mRootNode = newRootNode;
@ -600,7 +600,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
d.number = cur_object++; d.number = cur_object++;
} }
std::string path = FindLWOFile(c); std::string path = FindLWOFile(c);
d.id = batch.AddLoadRequest(path, 0, NULL); d.id = batch.AddLoadRequest(path, 0, nullptr);
d.path = path; d.path = path;
nodes.push_back(d); nodes.push_back(d);

View File

@ -84,7 +84,19 @@ public:
*/ */
struct NodeDesc { struct NodeDesc {
NodeDesc() : NodeDesc() :
type(), id(), number(0), parent(0), name(""), isPivotSet(false), lightColor(1.f, 1.f, 1.f), lightIntensity(1.f), lightType(0), lightFalloffType(0), lightConeAngle(45.f), lightEdgeAngle(), parent_resolved(NULL) {} type(),
id(),
number(0),
parent(0),
name(""),
isPivotSet(false),
lightColor(1.f, 1.f, 1.f),
lightIntensity(1.f),
lightType(0),
lightFalloffType(0),
lightConeAngle(45.f),
lightEdgeAngle(),
parent_resolved(nullptr) {}
enum { enum {

View File

@ -181,7 +181,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
} }
m3d->material[mi].name = SafeStr(name, true); m3d->material[mi].name = SafeStr(name, true);
m3d->material[mi].numprop = 0; m3d->material[mi].numprop = 0;
m3d->material[mi].prop = NULL; m3d->material[mi].prop = nullptr;
// iterate through the material property table and see what we got // iterate through the material property table and see what we got
for (k = 0; k < 15; k++) { for (k = 0; k < 15; k++) {
unsigned int j; unsigned int j;
@ -229,8 +229,8 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
} }
if (aiTxProps[k].pKey && if (aiTxProps[k].pKey &&
mat->GetTexture((aiTextureType)aiTxProps[k].type, mat->GetTexture((aiTextureType)aiTxProps[k].type,
aiTxProps[k].index, &name, NULL, NULL, NULL, aiTxProps[k].index, &name, nullptr, nullptr, nullptr,
NULL, NULL) == AI_SUCCESS) { nullptr, nullptr) == AI_SUCCESS) {
unsigned int i; unsigned int i;
for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++) for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++)
; ;
@ -259,7 +259,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
m3d->texture[i].name = fn; m3d->texture[i].name = fn;
m3d->texture[i].w = 0; m3d->texture[i].w = 0;
m3d->texture[i].h = 0; m3d->texture[i].h = 0;
m3d->texture[i].d = NULL; m3d->texture[i].d = nullptr;
} }
addProp(&m3d->material[mi], addProp(&m3d->material[mi],
m3d_propertytypes[k].id + 128, i); m3d_propertytypes[k].id + 128, i);

View File

@ -618,8 +618,10 @@ aiColor4D M3DImporter::mkColor(uint32_t c) {
void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) { void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) {
ai_assert(m != nullptr); ai_assert(m != nullptr);
ai_assert(m3d); ai_assert(m3d);
ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex); ai_assert(posid != M3D_UNDEF);
ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex); ai_assert(posid < m3d->numvertex);
ai_assert(orientid != M3D_UNDEF);
ai_assert(orientid < m3d->numvertex);
if (!m3d->numvertex || !m3d->vertex) if (!m3d->numvertex || !m3d->vertex)
return; return;
m3dv_t *p = &m3d->vertex[posid]; m3dv_t *p = &m3d->vertex[posid];

View File

@ -71,14 +71,14 @@ static const aiMatProp aiProps[] = {
{ AI_MATKEY_OPACITY }, /* m3dp_d */ { AI_MATKEY_OPACITY }, /* m3dp_d */
{ AI_MATKEY_SHADING_MODEL }, /* m3dp_il */ { AI_MATKEY_SHADING_MODEL }, /* m3dp_il */
{ NULL, 0, 0 }, /* m3dp_Pr */ { nullptr, 0, 0 }, /* m3dp_Pr */
{ AI_MATKEY_REFLECTIVITY }, /* m3dp_Pm */ { AI_MATKEY_REFLECTIVITY }, /* m3dp_Pm */
{ NULL, 0, 0 }, /* m3dp_Ps */ { nullptr, 0, 0 }, /* m3dp_Ps */
{ AI_MATKEY_REFRACTI }, /* m3dp_Ni */ { AI_MATKEY_REFRACTI }, /* m3dp_Ni */
{ NULL, 0, 0 }, /* m3dp_Nt */ { nullptr, 0, 0 }, /* m3dp_Nt */
{ NULL, 0, 0 }, { nullptr, 0, 0 },
{ NULL, 0, 0 }, { nullptr, 0, 0 },
{ NULL, 0, 0 } { nullptr, 0, 0 }
}; };
/* --- Texture Map Properties --- !!!!! must match m3d_propertytypes !!!!! */ /* --- Texture Map Properties --- !!!!! must match m3d_propertytypes !!!!! */
@ -88,19 +88,19 @@ static const aiMatProp aiTxProps[] = {
{ AI_MATKEY_TEXTURE_SPECULAR(0) }, /* m3dp_map_Ks */ { AI_MATKEY_TEXTURE_SPECULAR(0) }, /* m3dp_map_Ks */
{ AI_MATKEY_TEXTURE_SHININESS(0) }, /* m3dp_map_Ns */ { AI_MATKEY_TEXTURE_SHININESS(0) }, /* m3dp_map_Ns */
{ AI_MATKEY_TEXTURE_EMISSIVE(0) }, /* m3dp_map_Ke */ { AI_MATKEY_TEXTURE_EMISSIVE(0) }, /* m3dp_map_Ke */
{ NULL, 0, 0 }, /* m3dp_map_Tf */ { nullptr, 0, 0 }, /* m3dp_map_Tf */
{ AI_MATKEY_TEXTURE_HEIGHT(0) }, /* m3dp_bump */ { AI_MATKEY_TEXTURE_HEIGHT(0) }, /* m3dp_bump */
{ AI_MATKEY_TEXTURE_OPACITY(0) }, /* m3dp_map_d */ { AI_MATKEY_TEXTURE_OPACITY(0) }, /* m3dp_map_d */
{ AI_MATKEY_TEXTURE_NORMALS(0) }, /* m3dp_map_N */ { AI_MATKEY_TEXTURE_NORMALS(0) }, /* m3dp_map_N */
{ AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS,0) },/* m3dp_map_Pr */ { AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS,0) },/* m3dp_map_Pr */
{ AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */ { AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */
{ NULL, 0, 0 }, /* m3dp_map_Ps */ { nullptr, 0, 0 }, /* m3dp_map_Ps */
{ AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,0) }, /* m3dp_map_Ni */ { AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,0) }, /* m3dp_map_Ni */
{ NULL, 0, 0 }, /* m3dp_map_Nt */ { nullptr, 0, 0 }, /* m3dp_map_Nt */
{ NULL, 0, 0 }, { nullptr, 0, 0 },
{ NULL, 0, 0 }, { nullptr, 0, 0 },
{ NULL, 0, 0 } { nullptr, 0, 0 }
}; };
#endif // AI_M3DMATERIALS_H_INC #endif // AI_M3DMATERIALS_H_INC

View File

@ -72,7 +72,7 @@ unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
std::unique_ptr<Assimp::IOStream> pStream( std::unique_ptr<Assimp::IOStream> pStream(
(reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb")); (reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
size_t fileSize = 0; size_t fileSize = 0;
unsigned char *data = NULL; unsigned char *data = nullptr;
// sometimes pStream is nullptr in a single-threaded scenario too for some reason // sometimes pStream is nullptr in a single-threaded scenario too for some reason
// (should be an empty object returning nothing I guess) // (should be an empty object returning nothing I guess)
if (pStream) { if (pStream) {

View File

@ -221,20 +221,21 @@ void MD2Importer::InternReadFile( const std::string& pFile,
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile)); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) if (file.get() == nullptr) {
throw DeadlyImportError( "Failed to open MD2 file " + pFile + ""); throw DeadlyImportError("Failed to open MD2 file " + pFile + "");
}
// check whether the md3 file is large enough to contain // check whether the md3 file is large enough to contain
// at least the file header // at least the file header
fileSize = (unsigned int)file->FileSize(); fileSize = (unsigned int)file->FileSize();
if( fileSize < sizeof(MD2::Header)) if (fileSize < sizeof(MD2::Header)) {
throw DeadlyImportError( "MD2 File is too small"); throw DeadlyImportError("MD2 File is too small");
}
std::vector<uint8_t> mBuffer2(fileSize); std::vector<uint8_t> mBuffer2(fileSize);
file->Read(&mBuffer2[0], 1, fileSize); file->Read(&mBuffer2[0], 1, fileSize);
mBuffer = &mBuffer2[0]; mBuffer = &mBuffer2[0];
m_pcHeader = (BE_NCONST MD2::Header*)mBuffer; m_pcHeader = (BE_NCONST MD2::Header*)mBuffer;
#ifdef AI_BUILD_BIG_ENDIAN #ifdef AI_BUILD_BIG_ENDIAN

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -82,7 +80,15 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
MD5Importer::MD5Importer() : MD5Importer::MD5Importer() :
mIOHandler(nullptr), mBuffer(), fileSize(), iLineNumber(), pScene(), bHadMD5Mesh(), bHadMD5Anim(), bHadMD5Camera(), configNoAutoLoad(false) { mIOHandler(nullptr),
mBuffer(),
mFileSize(),
mLineNumber(),
mScene(),
mHadMD5Mesh(),
mHadMD5Anim(),
mHadMD5Camera(),
mCconfigNoAutoLoad(false) {
// empty // empty
} }
@ -106,6 +112,7 @@ bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
const char *tokens[] = { "MD5Version" }; const char *tokens[] = { "MD5Version" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
} }
return false; return false;
} }
@ -119,16 +126,15 @@ const aiImporterDesc *MD5Importer::GetInfo() const {
// Setup import properties // Setup import properties
void MD5Importer::SetupProperties(const Importer *pImp) { void MD5Importer::SetupProperties(const Importer *pImp) {
// AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD
configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0)); mCconfigNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void MD5Importer::InternReadFile(const std::string &pFile, void MD5Importer::InternReadFile(const std::string &pFile, aiScene *_pScene, IOSystem *pIOHandler) {
aiScene *_pScene, IOSystem *pIOHandler) {
mIOHandler = pIOHandler; mIOHandler = pIOHandler;
pScene = _pScene; mScene = _pScene;
bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false; mHadMD5Mesh = mHadMD5Anim = mHadMD5Camera = false;
// remove the file extension // remove the file extension
const std::string::size_type pos = pFile.find_last_of('.'); const std::string::size_type pos = pFile.find_last_of('.');
@ -138,7 +144,7 @@ void MD5Importer::InternReadFile(const std::string &pFile,
try { try {
if (extension == "md5camera") { if (extension == "md5camera") {
LoadMD5CameraFile(); LoadMD5CameraFile();
} else if (configNoAutoLoad || extension == "md5anim") { } else if (mCconfigNoAutoLoad || extension == "md5anim") {
// determine file extension and process just *one* file // determine file extension and process just *one* file
if (extension.length() == 0) { if (extension.length() == 0) {
throw DeadlyImportError("Failure, need file extension to determine MD5 part type"); throw DeadlyImportError("Failure, need file extension to determine MD5 part type");
@ -158,17 +164,17 @@ void MD5Importer::InternReadFile(const std::string &pFile,
} }
// make sure we have at least one file // make sure we have at least one file
if (!bHadMD5Mesh && !bHadMD5Anim && !bHadMD5Camera) { if (!mHadMD5Mesh && !mHadMD5Anim && !mHadMD5Camera) {
throw DeadlyImportError("Failed to read valid contents out of this MD5* file"); throw DeadlyImportError("Failed to read valid contents out of this MD5* file");
} }
// Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system // 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, mScene->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); 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 // the output scene wouldn't pass the validation without this flag
if (!bHadMD5Mesh) { if (!mHadMD5Mesh) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; mScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
} }
// clean the instance -- the BaseImporter instance may be reused later. // clean the instance -- the BaseImporter instance may be reused later.
@ -181,17 +187,17 @@ void MD5Importer::LoadFileIntoMemory(IOStream *file) {
// unload the previous buffer, if any // unload the previous buffer, if any
UnloadFileFromMemory(); UnloadFileFromMemory();
ai_assert(NULL != file); ai_assert(nullptr != file);
fileSize = (unsigned int)file->FileSize(); mFileSize = (unsigned int)file->FileSize();
ai_assert(fileSize); ai_assert(mFileSize);
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer
mBuffer = new char[fileSize + 1]; mBuffer = new char[mFileSize + 1];
file->Read((void *)mBuffer, 1, fileSize); file->Read((void *)mBuffer, 1, mFileSize);
iLineNumber = 1; mLineNumber = 1;
// append a terminal 0 // append a terminal 0
mBuffer[fileSize] = '\0'; mBuffer[mFileSize] = '\0';
// now remove all line comments from the file // now remove all line comments from the file
CommentRemover::RemoveLineComments("//", mBuffer, ' '); CommentRemover::RemoveLineComments("//", mBuffer, ' ');
@ -202,8 +208,8 @@ void MD5Importer::LoadFileIntoMemory(IOStream *file) {
void MD5Importer::UnloadFileFromMemory() { void MD5Importer::UnloadFileFromMemory() {
// delete the file buffer // delete the file buffer
delete[] mBuffer; delete[] mBuffer;
mBuffer = NULL; mBuffer = nullptr;
fileSize = 0; mFileSize = 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -243,7 +249,8 @@ void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursive node graph construction from a MD5MESH // 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); ai_assert(nullptr != piParent);
ai_assert(!piParent->mNumChildren);
// First find out how many children we'll have // First find out how many children we'll have
for (int i = 0; i < (int)bones.size(); ++i) { for (int i = 0; i < (int)bones.size(); ++i) {
@ -293,7 +300,8 @@ void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &b
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursive node graph construction from a MD5ANIM // 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); ai_assert(nullptr != piParent);
ai_assert(!piParent->mNumChildren);
// First find out how many children we'll have // First find out how many children we'll have
for (int i = 0; i < (int)bones.size(); ++i) { for (int i = 0; i < (int)bones.size(); ++i) {
@ -332,37 +340,37 @@ void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneLis
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Load a MD5MESH file // Load a MD5MESH file
void MD5Importer::LoadMD5MeshFile() { void MD5Importer::LoadMD5MeshFile() {
std::string pFile = mFile + "md5mesh"; std::string filename = mFile + "md5mesh";
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb")); std::unique_ptr<IOStream> file(mIOHandler->Open(filename, "rb"));
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr || !file->FileSize()) { if (file.get() == nullptr || !file->FileSize()) {
ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile); ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + filename);
return; return;
} }
bHadMD5Mesh = true; mHadMD5Mesh = true;
LoadFileIntoMemory(file.get()); LoadFileIntoMemory(file.get());
// now construct a parser and parse the file // now construct a parser and parse the file
MD5::MD5Parser parser(mBuffer, fileSize); MD5::MD5Parser parser(mBuffer, mFileSize);
// load the mesh information from it // load the mesh information from it
MD5::MD5MeshParser meshParser(parser.mSections); MD5::MD5MeshParser meshParser(parser.mSections);
// create the bone hierarchy - first the root node and dummy nodes for all meshes // create the bone hierarchy - first the root node and dummy nodes for all meshes
pScene->mRootNode = new aiNode("<MD5_Root>"); mScene->mRootNode = new aiNode("<MD5_Root>");
pScene->mRootNode->mNumChildren = 2; mScene->mRootNode->mNumChildren = 2;
pScene->mRootNode->mChildren = new aiNode *[2]; mScene->mRootNode->mChildren = new aiNode *[2];
// build the hierarchy from the MD5MESH file // build the hierarchy from the MD5MESH file
aiNode *pcNode = pScene->mRootNode->mChildren[1] = new aiNode(); aiNode *pcNode = mScene->mRootNode->mChildren[1] = new aiNode();
pcNode->mName.Set("<MD5_Hierarchy>"); pcNode->mName.Set("<MD5_Hierarchy>");
pcNode->mParent = pScene->mRootNode; pcNode->mParent = mScene->mRootNode;
AttachChilds_Mesh(-1, pcNode, meshParser.mJoints); AttachChilds_Mesh(-1, pcNode, meshParser.mJoints);
pcNode = pScene->mRootNode->mChildren[0] = new aiNode(); pcNode = mScene->mRootNode->mChildren[0] = new aiNode();
pcNode->mName.Set("<MD5_Mesh>"); pcNode->mName.Set("<MD5_Mesh>");
pcNode->mParent = pScene->mRootNode; pcNode->mParent = mScene->mRootNode;
#if 0 #if 0
if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */ if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */
@ -371,28 +379,31 @@ void MD5Importer::LoadMD5MeshFile() {
// FIX: MD5 files exported from Blender can have empty meshes // 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()) if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) {
++pScene->mNumMaterials; ++mScene->mNumMaterials;
}
} }
// generate all meshes // generate all meshes
pScene->mNumMeshes = pScene->mNumMaterials; mScene->mNumMeshes = mScene->mNumMaterials;
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; mScene->mMeshes = new aiMesh *[mScene->mNumMeshes];
pScene->mMaterials = new aiMaterial *[pScene->mNumMeshes]; mScene->mMaterials = new aiMaterial *[mScene->mNumMeshes];
// storage for node mesh indices // storage for node mesh indices
pcNode->mNumMeshes = pScene->mNumMeshes; pcNode->mNumMeshes = mScene->mNumMeshes;
pcNode->mMeshes = new unsigned int[pcNode->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; pcNode->mMeshes[m] = m;
}
unsigned int n = 0; unsigned int n = 0;
for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
MD5::MeshDesc &meshSrc = *it; MD5::MeshDesc &meshSrc = *it;
if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) {
continue; continue;
}
aiMesh *mesh = pScene->mMeshes[n] = new aiMesh(); aiMesh *mesh = mScene->mMeshes[n] = new aiMesh();
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
// generate unique vertices in our internal verbose format // generate unique vertices in our internal verbose format
@ -422,17 +433,19 @@ void MD5Importer::LoadMD5MeshFile() {
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) {
MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
/* FIX for some invalid exporters */ /* 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]; ++piCount[weightDesc.mBone];
}
} }
} }
// check how many we will need // check how many we will need
for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) {
if (piCount[p]) mesh->mNumBones++; if (piCount[p]) mesh->mNumBones++;
}
if (mesh->mNumBones) // just for safety // just for safety
{ if (mesh->mNumBones) {
mesh->mBones = new aiBone *[mesh->mNumBones]; mesh->mBones = new aiBone *[mesh->mNumBones];
for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) { for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) {
if (!piCount[q]) continue; if (!piCount[q]) continue;
@ -457,8 +470,9 @@ void MD5Importer::LoadMD5MeshFile() {
// there are models which have weights which don't sum to 1 ... // there are models which have weights which don't sum to 1 ...
ai_real fSum = 0.0; 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; fSum += meshSrc.mWeights[w].mWeight;
}
if (!fSum) { if (!fSum) {
ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0"); ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0");
continue; continue;
@ -466,11 +480,12 @@ void MD5Importer::LoadMD5MeshFile() {
// process bone weights // 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()) if (w >= meshSrc.mWeights.size()) {
throw DeadlyImportError("MD5MESH: Invalid weight index"); throw DeadlyImportError("MD5MESH: Invalid weight index");
}
MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
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) {
continue; continue;
} }
@ -504,12 +519,12 @@ void MD5Importer::LoadMD5MeshFile() {
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].mNumIndices = 3;
mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices; mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices;
meshSrc.mFaces[c].mIndices = NULL; meshSrc.mFaces[c].mIndices = nullptr;
} }
// generate a material for the mesh // generate a material for the mesh
aiMaterial *mat = new aiMaterial(); aiMaterial *mat = new aiMaterial();
pScene->mMaterials[n] = mat; mScene->mMaterials[n] = mat;
// insert the typical doom3 textures: // insert the typical doom3 textures:
// nnn_local.tga - normal map // nnn_local.tga - normal map
@ -555,10 +570,11 @@ void MD5Importer::LoadMD5AnimFile() {
ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile); ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile);
return; return;
} }
LoadFileIntoMemory(file.get()); LoadFileIntoMemory(file.get());
// parse the basic file structure // parse the basic file structure
MD5::MD5Parser parser(mBuffer, fileSize); MD5::MD5Parser parser(mBuffer, mFileSize);
// load the animation information from the parse tree // load the animation information from the parse tree
MD5::MD5AnimParser animParser(parser.mSections); MD5::MD5AnimParser animParser(parser.mSections);
@ -568,10 +584,10 @@ void MD5Importer::LoadMD5AnimFile() {
animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) { animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded"); ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded");
} else { } else {
bHadMD5Anim = true; mHadMD5Anim = true;
pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations = 1]; mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations = 1];
aiAnimation *anim = pScene->mAnimations[0] = new aiAnimation(); aiAnimation *anim = mScene->mAnimations[0] = new aiAnimation();
anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size(); anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size();
anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
for (unsigned int i = 0; i < anim->mNumChannels; ++i) { for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
@ -637,15 +653,15 @@ void MD5Importer::LoadMD5AnimFile() {
// If we didn't build the hierarchy yet (== we didn't load a MD5MESH), // If we didn't build the hierarchy yet (== we didn't load a MD5MESH),
// construct it now from the data given in the MD5ANIM. // construct it now from the data given in the MD5ANIM.
if (!pScene->mRootNode) { if (!mScene->mRootNode) {
pScene->mRootNode = new aiNode(); mScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<MD5_Hierarchy>"); mScene->mRootNode->mName.Set("<MD5_Hierarchy>");
AttachChilds_Anim(-1, pScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels); AttachChilds_Anim(-1, mScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels);
// Call SkeletonMeshBuilder to construct a mesh to represent the shape // Call SkeletonMeshBuilder to construct a mesh to represent the shape
if (pScene->mRootNode->mNumChildren) { if (mScene->mRootNode->mNumChildren) {
SkeletonMeshBuilder skeleton_maker(pScene, pScene->mRootNode->mChildren[0]); SkeletonMeshBuilder skeleton_maker(mScene, mScene->mRootNode->mChildren[0]);
} }
} }
} }
@ -661,11 +677,11 @@ void MD5Importer::LoadMD5CameraFile() {
if (!file.get() || !file->FileSize()) { if (!file.get() || !file->FileSize()) {
throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile); throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile);
} }
bHadMD5Camera = true; mHadMD5Camera = true;
LoadFileIntoMemory(file.get()); LoadFileIntoMemory(file.get());
// parse the basic file structure // parse the basic file structure
MD5::MD5Parser parser(mBuffer, fileSize); MD5::MD5Parser parser(mBuffer, mFileSize);
// load the camera animation data from the parse tree // load the camera animation data from the parse tree
MD5::MD5CameraParser cameraParser(parser.mSections); MD5::MD5CameraParser cameraParser(parser.mSections);
@ -679,14 +695,14 @@ void MD5Importer::LoadMD5CameraFile() {
// Construct output graph - a simple root with a dummy child. // Construct output graph - a simple root with a dummy child.
// The root node performs the coordinate system conversion // The root node performs the coordinate system conversion
aiNode *root = pScene->mRootNode = new aiNode("<MD5CameraRoot>"); aiNode *root = mScene->mRootNode = new aiNode("<MD5CameraRoot>");
root->mChildren = new aiNode *[root->mNumChildren = 1]; root->mChildren = new aiNode *[root->mNumChildren = 1];
root->mChildren[0] = new aiNode("<MD5Camera>"); root->mChildren[0] = new aiNode("<MD5Camera>");
root->mChildren[0]->mParent = root; root->mChildren[0]->mParent = root;
// ... but with one camera assigned to it // ... but with one camera assigned to it
pScene->mCameras = new aiCamera *[pScene->mNumCameras = 1]; mScene->mCameras = new aiCamera *[mScene->mNumCameras = 1];
aiCamera *cam = pScene->mCameras[0] = new aiCamera(); aiCamera *cam = mScene->mCameras[0] = new aiCamera();
cam->mName = "<MD5Camera>"; cam->mName = "<MD5Camera>";
// FIXME: Fov is currently set to the first frame's value // FIXME: Fov is currently set to the first frame's value
@ -703,8 +719,8 @@ void MD5Importer::LoadMD5CameraFile() {
cuts.push_back(static_cast<unsigned int>(frames.size() - 1)); cuts.push_back(static_cast<unsigned int>(frames.size() - 1));
} }
pScene->mNumAnimations = static_cast<unsigned int>(cuts.size() - 1); mScene->mNumAnimations = static_cast<unsigned int>(cuts.size() - 1);
aiAnimation **tmp = pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations]; aiAnimation **tmp = mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations];
for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) { for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) {
aiAnimation *anim = *tmp++ = new aiAnimation(); aiAnimation *anim = *tmp++ = new aiAnimation();

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -156,25 +155,25 @@ protected:
char *mBuffer; char *mBuffer;
/** Size of the file */ /** Size of the file */
unsigned int fileSize; unsigned int mFileSize;
/** Current line number. For debugging purposes */ /** Current line number. For debugging purposes */
unsigned int iLineNumber; unsigned int mLineNumber;
/** Scene to be filled */ /** Scene to be filled */
aiScene *pScene; aiScene *mScene;
/** true if a MD5MESH file has already been parsed */ /** true if a MD5MESH file has already been parsed */
bool bHadMD5Mesh; bool mHadMD5Mesh;
/** true if a MD5ANIM file has already been parsed */ /** true if a MD5ANIM file has already been parsed */
bool bHadMD5Anim; bool mHadMD5Anim;
/** true if a MD5CAMERA file has already been parsed */ /** true if a MD5CAMERA file has already been parsed */
bool bHadMD5Camera; bool mHadMD5Camera;
/** configuration option: prevent anim autoload */ /** configuration option: prevent anim autoload */
bool configNoAutoLoad; bool mCconfigNoAutoLoad;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -45,25 +45,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the MD5 parser class * @brief Implementation of the MD5 parser class
*/ */
// internal headers // internal headers
#include "AssetLib/MD5/MD5Loader.h" #include "AssetLib/MD5/MD5Loader.h"
#include "Material/MaterialSystem.h" #include "Material/MaterialSystem.h"
#include <assimp/fast_atof.h>
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/fast_atof.h>
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/DefaultLogger.hpp>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::MD5; using namespace Assimp::MD5;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Parse the segment structure fo a MD5 file // Parse the segment structure fo a MD5 file
MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize ) MD5Parser::MD5Parser(char *_buffer, unsigned int _fileSize) {
{ ai_assert(nullptr != _buffer);
ai_assert(NULL != _buffer && 0 != _fileSize); ai_assert(0 != _fileSize);
buffer = _buffer; buffer = _buffer;
fileSize = _fileSize; fileSize = _fileSize;
@ -78,48 +77,45 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
bool running = true; bool running = true;
while (running) { while (running) {
mSections.push_back(Section()); mSections.push_back(Section());
Section& sec = mSections.back(); Section &sec = mSections.back();
if(!ParseSection(sec)) { if (!ParseSection(sec)) {
break; break;
} }
} }
if ( !DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
char szBuffer[128]; // should be sufficiently large char szBuffer[128]; // should be sufficiently large
::ai_snprintf(szBuffer,128,"MD5Parser end. Parsed %i sections",(int)mSections.size()); ::ai_snprintf(szBuffer, 128, "MD5Parser end. Parsed %i sections", (int)mSections.size());
ASSIMP_LOG_DEBUG(szBuffer); ASSIMP_LOG_DEBUG(szBuffer);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Report error to the log stream // Report error to the log stream
/*static*/ AI_WONT_RETURN void MD5Parser::ReportError (const char* error, unsigned int line) /*static*/ AI_WONT_RETURN void MD5Parser::ReportError(const char *error, unsigned int line) {
{
char szBuffer[1024]; char szBuffer[1024];
::ai_snprintf(szBuffer, 1024, "[MD5] Line %u: %s",line,error); ::ai_snprintf(szBuffer, 1024, "[MD5] Line %u: %s", line, error);
throw DeadlyImportError(szBuffer); throw DeadlyImportError(szBuffer);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Report warning to the log stream // Report warning to the log stream
/*static*/ void MD5Parser::ReportWarning (const char* warn, unsigned int line) /*static*/ void MD5Parser::ReportWarning(const char *warn, unsigned int line) {
{
char szBuffer[1024]; char szBuffer[1024];
::sprintf(szBuffer,"[MD5] Line %u: %s",line,warn); ::sprintf(szBuffer, "[MD5] Line %u: %s", line, warn);
ASSIMP_LOG_WARN(szBuffer); ASSIMP_LOG_WARN(szBuffer);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Parse and validate the MD5 header // Parse and validate the MD5 header
void MD5Parser::ParseHeader() void MD5Parser::ParseHeader() {
{
// parse and validate the file version // parse and validate the file version
SkipSpaces(); SkipSpaces();
if (!TokenMatch(buffer,"MD5Version",10)) { if (!TokenMatch(buffer, "MD5Version", 10)) {
ReportError("Invalid MD5 file: MD5Version tag has not been found"); ReportError("Invalid MD5 file: MD5Version tag has not been found");
} }
SkipSpaces(); SkipSpaces();
unsigned int iVer = ::strtoul10(buffer,(const char**)&buffer); unsigned int iVer = ::strtoul10(buffer, (const char **)&buffer);
if (10 != iVer) { if (10 != iVer) {
ReportError("MD5 version tag is unknown (10 is expected)"); ReportError("MD5 version tag is unknown (10 is expected)");
} }
@ -127,23 +123,24 @@ void MD5Parser::ParseHeader()
// print the command line options to the console // print the command line options to the console
// FIX: can break the log length limit, so we need to be careful // FIX: can break the log length limit, so we need to be careful
char* sz = buffer; char *sz = buffer;
while (!IsLineEnd( *buffer++)); while (!IsLineEnd(*buffer++))
ASSIMP_LOG_INFO(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz)))); ;
ASSIMP_LOG_INFO(std::string(sz, std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer - sz))));
SkipSpacesAndLineEnd(); SkipSpacesAndLineEnd();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursive MD5 parsing function // Recursive MD5 parsing function
bool MD5Parser::ParseSection(Section& out) bool MD5Parser::ParseSection(Section &out) {
{
// store the current line number for use in error messages // store the current line number for use in error messages
out.iLineNumber = lineNumber; out.iLineNumber = lineNumber;
// first parse the name of the section // first parse the name of the section
char* sz = buffer; char *sz = buffer;
while (!IsSpaceOrNewLine( *buffer))buffer++; while (!IsSpaceOrNewLine(*buffer))
out.mName = std::string(sz,(uintptr_t)(buffer-sz)); buffer++;
out.mName = std::string(sz, (uintptr_t)(buffer - sz));
SkipSpaces(); SkipSpaces();
bool running = true; bool running = true;
@ -152,8 +149,7 @@ bool MD5Parser::ParseSection(Section& out)
// it is a normal section so read all lines // it is a normal section so read all lines
buffer++; buffer++;
bool run = true; bool run = true;
while (run) while (run) {
{
if (!SkipSpacesAndLineEnd()) { if (!SkipSpacesAndLineEnd()) {
return false; // seems this was the last section return false; // seems this was the last section
} }
@ -163,25 +159,26 @@ bool MD5Parser::ParseSection(Section& out)
} }
out.mElements.push_back(Element()); out.mElements.push_back(Element());
Element& elem = out.mElements.back(); Element &elem = out.mElements.back();
elem.iLineNumber = lineNumber; elem.iLineNumber = lineNumber;
elem.szStart = buffer; elem.szStart = buffer;
// terminate the line with zero // terminate the line with zero
while (!IsLineEnd( *buffer))buffer++; while (!IsLineEnd(*buffer))
buffer++;
if (*buffer) { if (*buffer) {
++lineNumber; ++lineNumber;
*buffer++ = '\0'; *buffer++ = '\0';
} }
} }
break; break;
} } else if (!IsSpaceOrNewLine(*buffer)) {
else if (!IsSpaceOrNewLine(*buffer)) {
// it is an element at global scope. Parse its value and go on // it is an element at global scope. Parse its value and go on
sz = buffer; sz = buffer;
while (!IsSpaceOrNewLine( *buffer++)); while (!IsSpaceOrNewLine(*buffer++))
out.mGlobalValue = std::string(sz,(uintptr_t)(buffer-sz)); ;
out.mGlobalValue = std::string(sz, (uintptr_t)(buffer - sz));
continue; continue;
} }
break; break;
@ -193,161 +190,161 @@ bool MD5Parser::ParseSection(Section& out)
// Some dirty macros just because they're so funny and easy to debug // Some dirty macros just because they're so funny and easy to debug
// skip all spaces ... handle EOL correctly // skip all spaces ... handle EOL correctly
#define AI_MD5_SKIP_SPACES() if(!SkipSpaces(&sz)) \ #define AI_MD5_SKIP_SPACES() \
MD5Parser::ReportWarning("Unexpected end of line",elem.iLineNumber); if (!SkipSpaces(&sz)) \
MD5Parser::ReportWarning("Unexpected end of line", elem.iLineNumber);
// read a triple float in brackets: (1.0 1.0 1.0) // read a triple float in brackets: (1.0 1.0 1.0)
#define AI_MD5_READ_TRIPLE(vec) \ #define AI_MD5_READ_TRIPLE(vec) \
AI_MD5_SKIP_SPACES(); \ AI_MD5_SKIP_SPACES(); \
if ('(' != *sz++) \ if ('(' != *sz++) \
MD5Parser::ReportWarning("Unexpected token: ( was expected",elem.iLineNumber); \ MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); \
AI_MD5_SKIP_SPACES(); \ AI_MD5_SKIP_SPACES(); \
sz = fast_atoreal_move<float>(sz,(float&)vec.x); \ sz = fast_atoreal_move<float>(sz, (float &)vec.x); \
AI_MD5_SKIP_SPACES(); \ AI_MD5_SKIP_SPACES(); \
sz = fast_atoreal_move<float>(sz,(float&)vec.y); \ sz = fast_atoreal_move<float>(sz, (float &)vec.y); \
AI_MD5_SKIP_SPACES(); \ AI_MD5_SKIP_SPACES(); \
sz = fast_atoreal_move<float>(sz,(float&)vec.z); \ sz = fast_atoreal_move<float>(sz, (float &)vec.z); \
AI_MD5_SKIP_SPACES(); \ AI_MD5_SKIP_SPACES(); \
if (')' != *sz++) \ if (')' != *sz++) \
MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber); MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber);
// parse a string, enclosed in quotation marks or not // parse a string, enclosed in quotation marks or not
#define AI_MD5_PARSE_STRING(out) \ #define AI_MD5_PARSE_STRING(out) \
bool bQuota = (*sz == '\"'); \ bool bQuota = (*sz == '\"'); \
const char* szStart = sz; \ const char *szStart = sz; \
while (!IsSpaceOrNewLine(*sz))++sz; \ while (!IsSpaceOrNewLine(*sz)) \
const char* szEnd = sz; \ ++sz; \
if (bQuota) { \ const char *szEnd = sz; \
szStart++; \ if (bQuota) { \
if ('\"' != *(szEnd-=1)) { \ szStart++; \
if ('\"' != *(szEnd -= 1)) { \
MD5Parser::ReportWarning("Expected closing quotation marks in string", \ MD5Parser::ReportWarning("Expected closing quotation marks in string", \
elem.iLineNumber); \ elem.iLineNumber); \
continue; \ continue; \
} \ } \
} \ } \
out.length = (size_t)(szEnd - szStart); \ out.length = (size_t)(szEnd - szStart); \
::memcpy(out.data,szStart,out.length); \ ::memcpy(out.data, szStart, out.length); \
out.data[out.length] = '\0'; out.data[out.length] = '\0';
// parse a string, enclosed in quotation marks // parse a string, enclosed in quotation marks
#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \ #define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \
while('\"'!=*sz)++sz; \ while ('\"' != *sz) \
const char* szStart = ++sz; \ ++sz; \
while('\"'!=*sz)++sz; \ const char *szStart = ++sz; \
const char* szEnd = (sz++); \ while ('\"' != *sz) \
out.length = (ai_uint32) (szEnd - szStart); \ ++sz; \
::memcpy(out.data,szStart,out.length); \ const char *szEnd = (sz++); \
out.length = (ai_uint32)(szEnd - szStart); \
::memcpy(out.data, szStart, out.length); \
out.data[out.length] = '\0'; out.data[out.length] = '\0';
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// .MD5MESH parsing function // .MD5MESH parsing function
MD5MeshParser::MD5MeshParser(SectionList& mSections) MD5MeshParser::MD5MeshParser(SectionList &mSections) {
{
ASSIMP_LOG_DEBUG("MD5MeshParser begin"); ASSIMP_LOG_DEBUG("MD5MeshParser begin");
// now parse all sections // now parse all sections
for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter){ for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) {
if ( (*iter).mName == "numMeshes") { if ((*iter).mName == "numMeshes") {
mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str())); mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
} } else if ((*iter).mName == "numJoints") {
else if ( (*iter).mName == "numJoints") {
mJoints.reserve(::strtoul10((*iter).mGlobalValue.c_str())); mJoints.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
} } else if ((*iter).mName == "joints") {
else if ((*iter).mName == "joints") {
// "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 ) // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 )
for (const auto & elem : (*iter).mElements){ for (const auto &elem : (*iter).mElements) {
mJoints.push_back(BoneDesc()); mJoints.push_back(BoneDesc());
BoneDesc& desc = mJoints.back(); BoneDesc &desc = mJoints.back();
const char* sz = elem.szStart; const char *sz = elem.szStart;
AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
// negative values, at least -1, is allowed here // negative values, at least -1, is allowed here
desc.mParentIndex = (int)strtol10(sz,&sz); desc.mParentIndex = (int)strtol10(sz, &sz);
AI_MD5_READ_TRIPLE(desc.mPositionXYZ); AI_MD5_READ_TRIPLE(desc.mPositionXYZ);
AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there
} }
} } else if ((*iter).mName == "mesh") {
else if ((*iter).mName == "mesh") {
mMeshes.push_back(MeshDesc()); mMeshes.push_back(MeshDesc());
MeshDesc& desc = mMeshes.back(); MeshDesc &desc = mMeshes.back();
for (const auto & elem : (*iter).mElements){ for (const auto &elem : (*iter).mElements) {
const char* sz = elem.szStart; const char *sz = elem.szStart;
// shader attribute // shader attribute
if (TokenMatch(sz,"shader",6)) { if (TokenMatch(sz, "shader", 6)) {
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mShader); AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mShader);
} }
// numverts attribute // numverts attribute
else if (TokenMatch(sz,"numverts",8)) { else if (TokenMatch(sz, "numverts", 8)) {
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
desc.mVertices.resize(strtoul10(sz)); desc.mVertices.resize(strtoul10(sz));
} }
// numtris attribute // numtris attribute
else if (TokenMatch(sz,"numtris",7)) { else if (TokenMatch(sz, "numtris", 7)) {
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
desc.mFaces.resize(strtoul10(sz)); desc.mFaces.resize(strtoul10(sz));
} }
// numweights attribute // numweights attribute
else if (TokenMatch(sz,"numweights",10)) { else if (TokenMatch(sz, "numweights", 10)) {
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
desc.mWeights.resize(strtoul10(sz)); desc.mWeights.resize(strtoul10(sz));
} }
// vert attribute // vert attribute
// "vert 0 ( 0.394531 0.513672 ) 0 1" // "vert 0 ( 0.394531 0.513672 ) 0 1"
else if (TokenMatch(sz,"vert",4)) { else if (TokenMatch(sz, "vert", 4)) {
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
const unsigned int idx = ::strtoul10(sz,&sz); const unsigned int idx = ::strtoul10(sz, &sz);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
if (idx >= desc.mVertices.size()) if (idx >= desc.mVertices.size())
desc.mVertices.resize(idx+1); desc.mVertices.resize(idx + 1);
VertexDesc& vert = desc.mVertices[idx]; VertexDesc &vert = desc.mVertices[idx];
if ('(' != *sz++) if ('(' != *sz++)
MD5Parser::ReportWarning("Unexpected token: ( was expected",elem.iLineNumber); MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
sz = fast_atoreal_move<float>(sz,(float&)vert.mUV.x); sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.x);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
sz = fast_atoreal_move<float>(sz,(float&)vert.mUV.y); sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.y);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
if (')' != *sz++) if (')' != *sz++)
MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber); MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
vert.mFirstWeight = ::strtoul10(sz,&sz); vert.mFirstWeight = ::strtoul10(sz, &sz);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
vert.mNumWeights = ::strtoul10(sz,&sz); vert.mNumWeights = ::strtoul10(sz, &sz);
} }
// tri attribute // tri attribute
// "tri 0 15 13 12" // "tri 0 15 13 12"
else if (TokenMatch(sz,"tri",3)) { else if (TokenMatch(sz, "tri", 3)) {
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
const unsigned int idx = strtoul10(sz,&sz); const unsigned int idx = strtoul10(sz, &sz);
if (idx >= desc.mFaces.size()) if (idx >= desc.mFaces.size())
desc.mFaces.resize(idx+1); desc.mFaces.resize(idx + 1);
aiFace& face = desc.mFaces[idx]; aiFace &face = desc.mFaces[idx];
face.mIndices = new unsigned int[face.mNumIndices = 3]; face.mIndices = new unsigned int[face.mNumIndices = 3];
for (unsigned int i = 0; i < 3;++i) { for (unsigned int i = 0; i < 3; ++i) {
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
face.mIndices[i] = strtoul10(sz,&sz); face.mIndices[i] = strtoul10(sz, &sz);
} }
} }
// weight attribute // weight attribute
// "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )" // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )"
else if (TokenMatch(sz,"weight",6)) { else if (TokenMatch(sz, "weight", 6)) {
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
const unsigned int idx = strtoul10(sz,&sz); const unsigned int idx = strtoul10(sz, &sz);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
if (idx >= desc.mWeights.size()) if (idx >= desc.mWeights.size())
desc.mWeights.resize(idx+1); desc.mWeights.resize(idx + 1);
WeightDesc& weight = desc.mWeights[idx]; WeightDesc &weight = desc.mWeights[idx];
weight.mBone = strtoul10(sz,&sz); weight.mBone = strtoul10(sz, &sz);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
sz = fast_atoreal_move<float>(sz,weight.mWeight); sz = fast_atoreal_move<float>(sz, weight.mWeight);
AI_MD5_READ_TRIPLE(weight.vOffsetPosition); AI_MD5_READ_TRIPLE(weight.vOffsetPosition);
} }
} }
@ -358,57 +355,54 @@ MD5MeshParser::MD5MeshParser(SectionList& mSections)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// .MD5ANIM parsing function // .MD5ANIM parsing function
MD5AnimParser::MD5AnimParser(SectionList& mSections) MD5AnimParser::MD5AnimParser(SectionList &mSections) {
{
ASSIMP_LOG_DEBUG("MD5AnimParser begin"); ASSIMP_LOG_DEBUG("MD5AnimParser begin");
fFrameRate = 24.0f; fFrameRate = 24.0f;
mNumAnimatedComponents = UINT_MAX; mNumAnimatedComponents = UINT_MAX;
for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) { for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) {
if ((*iter).mName == "hierarchy") { if ((*iter).mName == "hierarchy") {
// "sheath" 0 63 6 // "sheath" 0 63 6
for (const auto & elem : (*iter).mElements) { for (const auto &elem : (*iter).mElements) {
mAnimatedBones.push_back ( AnimBoneDesc () ); mAnimatedBones.push_back(AnimBoneDesc());
AnimBoneDesc& desc = mAnimatedBones.back(); AnimBoneDesc &desc = mAnimatedBones.back();
const char* sz = elem.szStart; const char *sz = elem.szStart;
AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
// parent index - negative values are allowed (at least -1) // parent index - negative values are allowed (at least -1)
desc.mParentIndex = ::strtol10(sz,&sz); desc.mParentIndex = ::strtol10(sz, &sz);
// flags (highest is 2^6-1) // flags (highest is 2^6-1)
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
if(63 < (desc.iFlags = ::strtoul10(sz,&sz))){ if (63 < (desc.iFlags = ::strtoul10(sz, &sz))) {
MD5Parser::ReportWarning("Invalid flag combination in hierarchy section",elem.iLineNumber); MD5Parser::ReportWarning("Invalid flag combination in hierarchy section", elem.iLineNumber);
} }
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
// index of the first animation keyframe component for this joint // index of the first animation keyframe component for this joint
desc.iFirstKeyIndex = ::strtoul10(sz,&sz); desc.iFirstKeyIndex = ::strtoul10(sz, &sz);
} }
} } else if ((*iter).mName == "baseframe") {
else if((*iter).mName == "baseframe") {
// ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 ) // ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 )
for (const auto & elem : (*iter).mElements) { for (const auto &elem : (*iter).mElements) {
const char* sz = elem.szStart; const char *sz = elem.szStart;
mBaseFrames.push_back ( BaseFrameDesc () ); mBaseFrames.push_back(BaseFrameDesc());
BaseFrameDesc& desc = mBaseFrames.back(); BaseFrameDesc &desc = mBaseFrames.back();
AI_MD5_READ_TRIPLE(desc.vPositionXYZ); AI_MD5_READ_TRIPLE(desc.vPositionXYZ);
AI_MD5_READ_TRIPLE(desc.vRotationQuat); AI_MD5_READ_TRIPLE(desc.vRotationQuat);
} }
} } else if ((*iter).mName == "frame") {
else if((*iter).mName == "frame") {
if (!(*iter).mGlobalValue.length()) { if (!(*iter).mGlobalValue.length()) {
MD5Parser::ReportWarning("A frame section must have a frame index",(*iter).iLineNumber); MD5Parser::ReportWarning("A frame section must have a frame index", (*iter).iLineNumber);
continue; continue;
} }
mFrames.push_back ( FrameDesc () ); mFrames.push_back(FrameDesc());
FrameDesc& desc = mFrames.back(); FrameDesc &desc = mFrames.back();
desc.iIndex = strtoul10((*iter).mGlobalValue.c_str()); desc.iIndex = strtoul10((*iter).mGlobalValue.c_str());
// we do already know how much storage we will presumably need // we do already know how much storage we will presumably need
@ -417,31 +411,28 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
} }
// now read all elements (continuous list of floats) // now read all elements (continuous list of floats)
for (const auto & elem : (*iter).mElements){ for (const auto &elem : (*iter).mElements) {
const char* sz = elem.szStart; const char *sz = elem.szStart;
while (SkipSpacesAndLineEnd(&sz)) { while (SkipSpacesAndLineEnd(&sz)) {
float f;sz = fast_atoreal_move<float>(sz,f); float f;
sz = fast_atoreal_move<float>(sz, f);
desc.mValues.push_back(f); desc.mValues.push_back(f);
} }
} }
} } else if ((*iter).mName == "numFrames") {
else if((*iter).mName == "numFrames") {
mFrames.reserve(strtoul10((*iter).mGlobalValue.c_str())); mFrames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
} } else if ((*iter).mName == "numJoints") {
else if((*iter).mName == "numJoints") {
const unsigned int num = strtoul10((*iter).mGlobalValue.c_str()); const unsigned int num = strtoul10((*iter).mGlobalValue.c_str());
mAnimatedBones.reserve(num); mAnimatedBones.reserve(num);
// try to guess the number of animated components if that element is not given // try to guess the number of animated components if that element is not given
if (UINT_MAX == mNumAnimatedComponents) { if (UINT_MAX == mNumAnimatedComponents) {
mNumAnimatedComponents = num * 6; mNumAnimatedComponents = num * 6;
} }
} } else if ((*iter).mName == "numAnimatedComponents") {
else if((*iter).mName == "numAnimatedComponents") { mAnimatedBones.reserve(strtoul10((*iter).mGlobalValue.c_str()));
mAnimatedBones.reserve( strtoul10((*iter).mGlobalValue.c_str())); } else if ((*iter).mName == "frameRate") {
} fast_atoreal_move<float>((*iter).mGlobalValue.c_str(), fFrameRate);
else if((*iter).mName == "frameRate") {
fast_atoreal_move<float>((*iter).mGlobalValue.c_str(),fFrameRate);
} }
} }
ASSIMP_LOG_DEBUG("MD5AnimParser end"); ASSIMP_LOG_DEBUG("MD5AnimParser end");
@ -449,32 +440,27 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// .MD5CAMERA parsing function // .MD5CAMERA parsing function
MD5CameraParser::MD5CameraParser(SectionList& mSections) MD5CameraParser::MD5CameraParser(SectionList &mSections) {
{
ASSIMP_LOG_DEBUG("MD5CameraParser begin"); ASSIMP_LOG_DEBUG("MD5CameraParser begin");
fFrameRate = 24.0f; fFrameRate = 24.0f;
for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) { for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) {
if ((*iter).mName == "numFrames") { if ((*iter).mName == "numFrames") {
frames.reserve(strtoul10((*iter).mGlobalValue.c_str())); frames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
} } else if ((*iter).mName == "frameRate") {
else if ((*iter).mName == "frameRate") { fFrameRate = fast_atof((*iter).mGlobalValue.c_str());
fFrameRate = fast_atof ((*iter).mGlobalValue.c_str()); } else if ((*iter).mName == "numCuts") {
}
else if ((*iter).mName == "numCuts") {
cuts.reserve(strtoul10((*iter).mGlobalValue.c_str())); cuts.reserve(strtoul10((*iter).mGlobalValue.c_str()));
} } else if ((*iter).mName == "cuts") {
else if ((*iter).mName == "cuts") { for (const auto &elem : (*iter).mElements) {
for (const auto & elem : (*iter).mElements){ cuts.push_back(strtoul10(elem.szStart) + 1);
cuts.push_back(strtoul10(elem.szStart)+1);
} }
} } else if ((*iter).mName == "camera") {
else if ((*iter).mName == "camera") { for (const auto &elem : (*iter).mElements) {
for (const auto & elem : (*iter).mElements){ const char *sz = elem.szStart;
const char* sz = elem.szStart;
frames.push_back(CameraAnimFrameDesc()); frames.push_back(CameraAnimFrameDesc());
CameraAnimFrameDesc& cur = frames.back(); CameraAnimFrameDesc &cur = frames.back();
AI_MD5_READ_TRIPLE(cur.vPositionXYZ); AI_MD5_READ_TRIPLE(cur.vPositionXYZ);
AI_MD5_READ_TRIPLE(cur.vRotationQuat); AI_MD5_READ_TRIPLE(cur.vRotationQuat);
AI_MD5_SKIP_SPACES(); AI_MD5_SKIP_SPACES();
@ -484,4 +470,3 @@ MD5CameraParser::MD5CameraParser(SectionList& mSections)
} }
ASSIMP_LOG_DEBUG("MD5CameraParser end"); ASSIMP_LOG_DEBUG("MD5CameraParser end");
} }

View File

@ -267,7 +267,7 @@ void MDCImporter::InternReadFile(
// necessary that we don't crash if an exception occurs // 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; pScene->mMeshes[i] = nullptr;
} }
// now read all surfaces // now read all surfaces
@ -347,8 +347,8 @@ void MDCImporter::InternReadFile(
#endif #endif
const MDC::CompressedVertex *pcCVerts = NULL; const MDC::CompressedVertex *pcCVerts = nullptr;
int16_t *mdcCompVert = NULL; int16_t *mdcCompVert = nullptr;
// access compressed frames for large frame numbers, but never for the first // access compressed frames for large frame numbers, but never for the first
if (this->configFrameID && pcSurface->ulNumCompFrames > 0) { if (this->configFrameID && pcSurface->ulNumCompFrames > 0) {
@ -359,7 +359,7 @@ void MDCImporter::InternReadFile(
pcSurface->ulOffsetCompVerts) + pcSurface->ulOffsetCompVerts) +
*mdcCompVert * pcSurface->ulNumVertices; *mdcCompVert * pcSurface->ulNumVertices;
} else } else
mdcCompVert = NULL; mdcCompVert = nullptr;
} }
// copy all faces // copy all faces

View File

@ -222,12 +222,14 @@ void HL1MDLLoader::load_file_into_buffer(const std::string &file_path, unsigned
std::unique_ptr<IOStream> file(io_->Open(file_path)); std::unique_ptr<IOStream> file(io_->Open(file_path));
if (file.get() == NULL) if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open MDL file " + DefaultIOSystem::fileName(file_path) + "."); throw DeadlyImportError("Failed to open MDL file " + DefaultIOSystem::fileName(file_path) + ".");
}
const size_t file_size = file->FileSize(); const size_t file_size = file->FileSize();
if (file_size < sizeof(MDLFileHeader)) if (file_size < sizeof(MDLFileHeader)) {
throw DeadlyImportError("MDL file is too small."); throw DeadlyImportError("MDL file is too small.");
}
buffer = new unsigned char[1 + file_size]; buffer = new unsigned char[1 + file_size];
file->Read((void *)buffer, 1, file_size); file->Read((void *)buffer, 1, file_size);

View File

@ -278,7 +278,7 @@ void MDLImporter::SizeCheck(const void *szPos) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Just for debugging purposes // Just for debugging purposes
void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int iLine) { void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int iLine) {
ai_assert(NULL != szFile); ai_assert(nullptr != szFile);
if (!szPos || (const unsigned char *)szPos > mBuffer + iFileSize) { if (!szPos || (const unsigned char *)szPos > mBuffer + iFileSize) {
// remove a directory if there is one // remove a directory if there is one
const char *szFilePtr = ::strrchr(szFile, '\\'); const char *szFilePtr = ::strrchr(szFile, '\\');
@ -304,7 +304,7 @@ void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Validate a quake file header // Validate a quake file header
void MDLImporter::ValidateHeader_Quake1(const MDL::Header *pcHeader) { void MDLImporter::ValidateHeader_Quake1(const MDL::Header *pcHeader) {
// some values may not be NULL // some values may not be nullptr
if (!pcHeader->num_frames) if (!pcHeader->num_frames)
throw DeadlyImportError("[Quake 1 MDL] There are no frames in the file"); throw DeadlyImportError("[Quake 1 MDL] There are no frames in the file");
@ -359,7 +359,7 @@ void FlipQuakeHeader(BE_NCONST MDL::Header *pcHeader) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Read a Quake 1 file // Read a Quake 1 file
void MDLImporter::InternReadFile_Quake1() { void MDLImporter::InternReadFile_Quake1() {
ai_assert(NULL != pScene); ai_assert(nullptr != pScene);
BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer; BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer;
@ -548,7 +548,7 @@ void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1() {
delete pScene->mTextures[0]; delete pScene->mTextures[0];
delete[] pScene->mTextures; delete[] pScene->mTextures;
pScene->mTextures = NULL; pScene->mTextures = nullptr;
pScene->mNumTextures = 0; pScene->mNumTextures = 0;
} else { } else {
clr.b = clr.a = clr.g = clr.r = 1.0f; clr.b = clr.a = clr.g = clr.r = 1.0f;
@ -572,7 +572,7 @@ void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1() {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Read a MDL 3,4,5 file // Read a MDL 3,4,5 file
void MDLImporter::InternReadFile_3DGS_MDL345() { void MDLImporter::InternReadFile_3DGS_MDL345() {
ai_assert(NULL != pScene); ai_assert(nullptr != pScene);
// the header of MDL 3/4/5 is nearly identical to the original Quake1 header // the header of MDL 3/4/5 is nearly identical to the original Quake1 header
BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer; BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer;
@ -791,7 +791,7 @@ void MDLImporter::ImportUVCoordinate_3DGS_MDL345(
aiVector3D &vOut, aiVector3D &vOut,
const MDL::TexCoord_MDL3 *pcSrc, const MDL::TexCoord_MDL3 *pcSrc,
unsigned int iIndex) { unsigned int iIndex) {
ai_assert(NULL != pcSrc); ai_assert(nullptr != pcSrc);
const MDL::Header *const pcHeader = (const MDL::Header *)this->mBuffer; const MDL::Header *const pcHeader = (const MDL::Header *)this->mBuffer;
// validate UV indices // validate UV indices
@ -860,7 +860,7 @@ void MDLImporter::CalculateUVCoordinates_MDL5() {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Validate the header of a MDL7 file // Validate the header of a MDL7 file
void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) { void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) {
ai_assert(NULL != pcHeader); ai_assert(nullptr != pcHeader);
// There are some fixed sizes ... // There are some fixed sizes ...
if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) { if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) {
@ -887,7 +887,7 @@ void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) {
void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) { void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) {
const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)this->mBuffer;
const MDL::Bone_MDL7 *pcBones = (const MDL::Bone_MDL7 *)(pcHeader + 1); const MDL::Bone_MDL7 *pcBones = (const MDL::Bone_MDL7 *)(pcHeader + 1);
ai_assert(NULL != apcOutBones); ai_assert(nullptr != apcOutBones);
// first find the bone that has NO parent, calculate the // first find the bone that has NO parent, calculate the
// animation matrix for it, then go on and search for the next parent // animation matrix for it, then go on and search for the next parent
@ -979,7 +979,7 @@ MDL::IntBone_MDL7 **MDLImporter::LoadBones_3DGS_MDL7() {
AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size && AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size &&
AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) { AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) {
ASSIMP_LOG_WARN("Unknown size of bone data structure"); ASSIMP_LOG_WARN("Unknown size of bone data structure");
return NULL; return nullptr;
} }
MDL::IntBone_MDL7 **apcBonesOut = new MDL::IntBone_MDL7 *[pcHeader->bones_num]; MDL::IntBone_MDL7 **apcBonesOut = new MDL::IntBone_MDL7 *[pcHeader->bones_num];
@ -990,7 +990,7 @@ MDL::IntBone_MDL7 **MDLImporter::LoadBones_3DGS_MDL7() {
CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut); CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut);
return apcBonesOut; return apcBonesOut;
} }
return NULL; return nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1014,7 +1014,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7 &groupInfo,
unsigned int iIndex = pcGroupTris->v_index[c]; unsigned int iIndex = pcGroupTris->v_index[c];
if (iIndex > (unsigned int)groupInfo.pcGroup->numverts) { if (iIndex > (unsigned int)groupInfo.pcGroup->numverts) {
// (we might need to read this section a second time - to process frame vertices correctly) // (we might need to read this section a second time - to process frame vertices correctly)
pcGroupTris->v_index[c] = (uint16_t) (iIndex = groupInfo.pcGroup->numverts - 1 ); pcGroupTris->v_index[c] = (uint16_t)(iIndex = groupInfo.pcGroup->numverts - 1);
ASSIMP_LOG_WARN("Index overflow in MDL7 vertex list"); ASSIMP_LOG_WARN("Index overflow in MDL7 vertex list");
} }
@ -1337,7 +1337,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7(
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Read a MDL7 file // Read a MDL7 file
void MDLImporter::InternReadFile_3DGS_MDL7() { void MDLImporter::InternReadFile_3DGS_MDL7() {
ai_assert(NULL != pScene); ai_assert(nullptr != pScene);
MDL::IntSharedData_MDL7 sharedData; MDL::IntSharedData_MDL7 sharedData;
@ -1368,7 +1368,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
// load all bones (they are shared by all groups, so // load all bones (they are shared by all groups, so
// we'll need to add them to all groups/meshes later) // we'll need to add them to all groups/meshes later)
// apcBonesOut is a list of all bones or NULL if they could not been loaded // apcBonesOut is a list of all bones or nullptr if they could not been loaded
szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size; szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
sharedData.apcOutBones = this->LoadBones_3DGS_MDL7(); sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
@ -1558,9 +1558,9 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) { if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) {
aiNode *pcOldRoot = this->pScene->mRootNode; aiNode *pcOldRoot = this->pScene->mRootNode;
pScene->mRootNode = pcOldRoot->mChildren[0]; pScene->mRootNode = pcOldRoot->mChildren[0];
pcOldRoot->mChildren[0] = NULL; pcOldRoot->mChildren[0] = nullptr;
delete pcOldRoot; delete pcOldRoot;
pScene->mRootNode->mParent = NULL; pScene->mRootNode->mParent = nullptr;
} else } else
pScene->mRootNode->mName.Set("<mesh_root>"); pScene->mRootNode->mName.Set("<mesh_root>");
@ -1665,7 +1665,8 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7(
// Attach bones to the output nodegraph // Attach bones to the output nodegraph
void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBones, void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBones,
aiNode *pcParent, uint16_t iParentIndex) { aiNode *pcParent, uint16_t iParentIndex) {
ai_assert(NULL != apcBones && NULL != pcParent); ai_assert(nullptr != apcBones);
ai_assert(nullptr != pcParent);
// get a pointer to the header ... // get a pointer to the header ...
const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)this->mBuffer;
@ -1696,7 +1697,7 @@ void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBon
// Build output animations // Build output animations
void MDLImporter::BuildOutputAnims_3DGS_MDL7( void MDLImporter::BuildOutputAnims_3DGS_MDL7(
const MDL::IntBone_MDL7 **apcBonesOut) { const MDL::IntBone_MDL7 **apcBonesOut) {
ai_assert(NULL != apcBonesOut); ai_assert(nullptr != apcBonesOut);
const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)mBuffer; const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)mBuffer;
// one animation ... // one animation ...
@ -1755,8 +1756,8 @@ void MDLImporter::BuildOutputAnims_3DGS_MDL7(
void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo, void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
const MDL::BoneTransform_MDL7 *pcBoneTransforms, const MDL::BoneTransform_MDL7 *pcBoneTransforms,
MDL::IntBone_MDL7 **apcBonesOut) { MDL::IntBone_MDL7 **apcBonesOut) {
ai_assert(NULL != pcBoneTransforms); ai_assert(nullptr != pcBoneTransforms);
ai_assert(NULL != apcBonesOut); ai_assert(nullptr != apcBonesOut);
// first .. get the transformation matrix // first .. get the transformation matrix
aiMatrix4x4 mTransform; aiMatrix4x4 mTransform;
@ -1920,7 +1921,9 @@ void MDLImporter::JoinSkins_3DGS_MDL7(
aiMaterial *pcMat1, aiMaterial *pcMat1,
aiMaterial *pcMat2, aiMaterial *pcMat2,
aiMaterial *pcMatOut) { aiMaterial *pcMatOut) {
ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut); ai_assert(nullptr != pcMat1);
ai_assert(nullptr != pcMat2);
ai_assert(nullptr != pcMatOut);
// first create a full copy of the first skin property set // first create a full copy of the first skin property set
// and assign it to the output material // and assign it to the output material

View File

@ -320,7 +320,7 @@ protected:
/** Load the bone list of a MDL7 file /** Load the bone list of a MDL7 file
* \return If the bones could be loaded successfully, a valid * \return If the bones could be loaded successfully, a valid
* array containing pointers to a temporary bone * array containing pointers to a temporary bone
* representation. NULL if the bones could not be loaded. * representation. nullptr if the bones could not be loaded.
*/ */
MDL::IntBone_MDL7** LoadBones_3DGS_MDL7(); MDL::IntBone_MDL7** LoadBones_3DGS_MDL7();

View File

@ -364,7 +364,7 @@ void MDLImporter::ParseTextureColorData(const unsigned char *szData,
void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData, void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData,
unsigned int iType, unsigned int iType,
unsigned int *piSkip) { unsigned int *piSkip) {
ai_assert(NULL != piSkip); ai_assert(nullptr != piSkip);
bool bNoRead = *piSkip == UINT_MAX; bool bNoRead = *piSkip == UINT_MAX;
// allocate a new texture object // allocate a new texture object
@ -428,7 +428,7 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData,
delete[] pc; delete[] pc;
} }
} else { } else {
pcNew->pcData = NULL; pcNew->pcData = nullptr;
delete pcNew; delete pcNew;
} }
return; return;

View File

@ -134,7 +134,7 @@ void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel, void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel,
aiScene *pScene) { aiScene *pScene) {
if (pModel == NULL) { if (pModel == nullptr) {
return; return;
} }

View File

@ -131,7 +131,7 @@ namespace pmd
stream->read((char*) &index_count, sizeof(uint32_t)); stream->read((char*) &index_count, sizeof(uint32_t));
stream->read((char*) &buffer, sizeof(char) * 20); stream->read((char*) &buffer, sizeof(char) * 20);
char* pstar = strchr(buffer, '*'); char* pstar = strchr(buffer, '*');
if (NULL == pstar) if (nullptr == pstar)
{ {
texture_filename = std::string(buffer); texture_filename = std::string(buffer);
sphere_filename.clear(); sphere_filename.clear();

View File

@ -657,7 +657,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
} }
// fixup to pass the validation if not a single animation channel is non-trivial // fixup to pass the validation if not a single animation channel is non-trivial
if (!anim->mNumChannels) { if (!anim->mNumChannels) {
anim->mChannels = NULL; anim->mChannels = nullptr;
} }
} }
} }

View File

@ -154,7 +154,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector<ShadingInfo> &output,
return; return;
} }
ShadingInfo *curShader = NULL; ShadingInfo *curShader = nullptr;
// No read the file line per line // No read the file line per line
char line[4096]; char line[4096];
@ -238,9 +238,9 @@ void NFFImporter::InternReadFile(const std::string &pFile,
bool hasCam = false; bool hasCam = false;
MeshInfo *currentMeshWithNormals = NULL; MeshInfo *currentMeshWithNormals = nullptr;
MeshInfo *currentMesh = NULL; MeshInfo *currentMesh = nullptr;
MeshInfo *currentMeshWithUVCoords = NULL; MeshInfo *currentMeshWithUVCoords = nullptr;
ShadingInfo s; // current material info ShadingInfo s; // current material info
@ -542,7 +542,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
// search the list of all shaders we have for this object whether // search the list of all shaders we have for this object whether
// there is an identical one. In this case, we append our mesh // there is an identical one. In this case, we append our mesh
// data to it. // data to it.
MeshInfo *mesh = NULL; MeshInfo *mesh = nullptr;
for (std::vector<MeshInfo>::iterator it = meshes.begin() + objStart, end = meshes.end(); for (std::vector<MeshInfo>::iterator it = meshes.begin() + objStart, end = meshes.end();
it != end; ++it) { it != end; ++it) {
if ((*it).shader == shader && (*it).matIndex == matIdx) { if ((*it).shader == shader && (*it).matIndex == matIdx) {
@ -603,11 +603,11 @@ void NFFImporter::InternReadFile(const std::string &pFile,
while (GetNextLine(buffer, line)) { while (GetNextLine(buffer, line)) {
sz = line; sz = line;
if ('p' == line[0] || TokenMatch(sz, "tpp", 3)) { if ('p' == line[0] || TokenMatch(sz, "tpp", 3)) {
MeshInfo *out = NULL; MeshInfo *out = nullptr;
// 'tpp' - texture polygon patch primitive // 'tpp' - texture polygon patch primitive
if ('t' == line[0]) { if ('t' == line[0]) {
currentMeshWithUVCoords = NULL; currentMeshWithUVCoords = nullptr;
for (auto &mesh : meshesWithUVCoords) { for (auto &mesh : meshesWithUVCoords) {
if (mesh.shader == s) { if (mesh.shader == s) {
currentMeshWithUVCoords = &mesh; currentMeshWithUVCoords = &mesh;
@ -624,7 +624,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
} }
// 'pp' - polygon patch primitive // 'pp' - polygon patch primitive
else if ('p' == line[1]) { else if ('p' == line[1]) {
currentMeshWithNormals = NULL; currentMeshWithNormals = nullptr;
for (auto &mesh : meshesWithNormals) { for (auto &mesh : meshesWithNormals) {
if (mesh.shader == s) { if (mesh.shader == s) {
currentMeshWithNormals = &mesh; currentMeshWithNormals = &mesh;
@ -642,7 +642,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
} }
// 'p' - polygon primitive // 'p' - polygon primitive
else { else {
currentMesh = NULL; currentMesh = nullptr;
for (auto &mesh : meshes) { for (auto &mesh : meshes) {
if (mesh.shader == s) { if (mesh.shader == s) {
currentMesh = &mesh; currentMesh = &mesh;
@ -969,8 +969,8 @@ void NFFImporter::InternReadFile(const std::string &pFile,
root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int)lights.size(); root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int)lights.size();
root->mNumMeshes = pScene->mNumMeshes - numNamed; root->mNumMeshes = pScene->mNumMeshes - numNamed;
aiNode **ppcChildren = NULL; aiNode **ppcChildren = nullptr;
unsigned int *pMeshes = NULL; unsigned int *pMeshes = nullptr;
if (root->mNumMeshes) if (root->mNumMeshes)
pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes]; pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes];
if (root->mNumChildren) if (root->mNumChildren)
@ -1037,7 +1037,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
mesh->mNumFaces = (unsigned int)src.faces.size(); mesh->mNumFaces = (unsigned int)src.faces.size();
// Generate sub nodes for named meshes // Generate sub nodes for named meshes
if (src.name[0] && NULL != ppcChildren) { if (src.name[0] && nullptr != ppcChildren) {
aiNode *const node = *ppcChildren = new aiNode(); aiNode *const node = *ppcChildren = new aiNode();
node->mParent = root; node->mParent = root;
node->mNumMeshes = 1; node->mNumMeshes = 1;

View File

@ -70,14 +70,14 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// we're still here - export successfully completed. Write both the main OBJ file and the material script // we're still here - export successfully completed. Write both the main OBJ file and the material script
{ {
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .obj file: " + std::string(pFile)); throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
} }
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1); outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
} }
{ {
std::unique_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt")); std::unique_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
if(outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName())); throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
} }
outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1); outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
@ -97,7 +97,7 @@ void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* p
// we're still here - export successfully completed. Write both the main OBJ file and the material script // we're still here - export successfully completed. Write both the main OBJ file and the material script
{ {
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .obj file: " + std::string(pFile)); throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
} }
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1); outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);

View File

@ -41,12 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once #pragma once
#ifndef OBJ_FILEDATA_H_INC #ifndef OBJ_FILEDATA_H_INC
# define OBJ_FILEDATA_H_INC #define OBJ_FILEDATA_H_INC
# include <assimp/mesh.h> #include <assimp/mesh.h>
# include <assimp/types.h> #include <assimp/types.h>
# include <map> #include <map>
# include <vector> #include <vector>
namespace Assimp { namespace Assimp {
namespace ObjFile { namespace ObjFile {
@ -215,7 +215,11 @@ struct Mesh {
/// Constructor /// Constructor
explicit Mesh(const std::string &name) : explicit Mesh(const std::string &name) :
m_name(name), m_pMaterial(NULL), m_uiNumIndices(0), m_uiMaterialIndex(NoMaterial), m_hasNormals(false) { m_name(name),
m_pMaterial(nullptr),
m_uiNumIndices(0),
m_uiMaterialIndex(NoMaterial),
m_hasNormals(false) {
memset(m_uiUVCoordinates, 0, sizeof(unsigned int) * AI_MAX_NUMBER_OF_TEXTURECOORDS); memset(m_uiUVCoordinates, 0, sizeof(unsigned int) * AI_MAX_NUMBER_OF_TEXTURECOORDS);
} }
@ -275,13 +279,13 @@ struct Model {
//! \brief The default class constructor //! \brief The default class constructor
Model() : Model() :
m_ModelName(""), m_ModelName(""),
m_pCurrent(NULL), m_pCurrent(nullptr),
m_pCurrentMaterial(NULL), m_pCurrentMaterial(nullptr),
m_pDefaultMaterial(NULL), m_pDefaultMaterial(nullptr),
m_pGroupFaceIDs(NULL), m_pGroupFaceIDs(nullptr),
m_strActiveGroup(""), m_strActiveGroup(""),
m_TextureCoordDim(0), m_TextureCoordDim(0),
m_pCurrentMesh(NULL) { m_pCurrentMesh(nullptr) {
// empty // empty
} }

View File

@ -252,9 +252,9 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject, aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject,
aiNode *pParent, aiScene *pScene, aiNode *pParent, aiScene *pScene,
std::vector<aiMesh *> &MeshArray) { std::vector<aiMesh *> &MeshArray) {
ai_assert(NULL != pModel); ai_assert(nullptr != pModel);
if (NULL == pObject) { if (nullptr == pObject) {
return NULL; return nullptr;
} }
// Store older mesh size to be able to computes mesh offsets for new mesh instances // Store older mesh size to be able to computes mesh offsets for new mesh instances
@ -264,7 +264,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
pNode->mName = pObject->m_strObjName; pNode->mName = pObject->m_strObjName;
// If we have a parent node, store it // If we have a parent node, store it
ai_assert(NULL != pParent); ai_assert(nullptr != pParent);
appendChildToParentNode(pParent, pNode); appendChildToParentNode(pParent, pNode);
for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) { for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
@ -308,20 +308,20 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
// Create topology data // 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 // Checking preconditions
ai_assert(NULL != pModel); ai_assert(nullptr != pModel);
if (NULL == pData) { if (nullptr == pData) {
return NULL; return nullptr;
} }
// Create faces // Create faces
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[meshIndex]; ObjFile::Mesh *pObjMesh = pModel->m_Meshes[meshIndex];
if (!pObjMesh) { if (!pObjMesh) {
return NULL; return nullptr;
} }
if (pObjMesh->m_Faces.empty()) { if (pObjMesh->m_Faces.empty()) {
return NULL; return nullptr;
} }
std::unique_ptr<aiMesh> pMesh(new aiMesh); std::unique_ptr<aiMesh> pMesh(new aiMesh);
@ -331,7 +331,7 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) { for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
ObjFile::Face *const inp = pObjMesh->m_Faces[index]; ObjFile::Face *const inp = pObjMesh->m_Faces[index];
ai_assert(NULL != inp); ai_assert(nullptr != inp);
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) { if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1); pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
@ -400,7 +400,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
aiMesh *pMesh, aiMesh *pMesh,
unsigned int numIndices) { unsigned int numIndices) {
// Checking preconditions // Checking preconditions
ai_assert(NULL != pCurrentObject); ai_assert(nullptr != pCurrentObject);
// Break, if no faces are stored in object // Break, if no faces are stored in object
if (pCurrentObject->m_Meshes.empty()) if (pCurrentObject->m_Meshes.empty())
@ -408,7 +408,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
// Get current mesh // Get current mesh
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[uiMeshIndex]; ObjFile::Mesh *pObjMesh = pModel->m_Meshes[uiMeshIndex];
if (NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1) { if (nullptr == pObjMesh || pObjMesh->m_uiNumIndices < 1) {
return; return;
} }
@ -561,7 +561,7 @@ void ObjFileImporter::addTextureMappingModeProperty(aiMaterial *mat, aiTextureTy
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates the material // Creates the material
void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pScene) { void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pScene) {
if (NULL == pScene) { if (nullptr == pScene) {
return; return;
} }
@ -717,8 +717,8 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
// Appends this node to the parent node // Appends this node to the parent node
void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) { void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) {
// Checking preconditions // Checking preconditions
ai_assert(NULL != pParent); ai_assert(nullptr != pParent);
ai_assert(NULL != pChild); ai_assert(nullptr != pChild);
// Assign parent to child // Assign parent to child
pChild->mParent = pParent; pChild->mParent = pParent;

View File

@ -200,7 +200,7 @@ void ObjFileMtlImporter::load() {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Loads a color definition // Loads a color definition
void ObjFileMtlImporter::getColorRGBA(aiColor3D *pColor) { void ObjFileMtlImporter::getColorRGBA(aiColor3D *pColor) {
ai_assert(NULL != pColor); ai_assert(nullptr != pColor);
ai_real r(0.0), g(0.0), b(0.0); ai_real r(0.0), g(0.0), b(0.0);
m_DataIt = getFloat<DataArrayIt>(m_DataIt, m_DataItEnd, r); m_DataIt = getFloat<DataArrayIt>(m_DataIt, m_DataItEnd, r);
@ -274,7 +274,7 @@ void ObjFileMtlImporter::createMaterial() {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Gets a texture name from data. // Gets a texture name from data.
void ObjFileMtlImporter::getTexture() { void ObjFileMtlImporter::getTexture() {
aiString *out(NULL); aiString *out(nullptr);
int clampIndex = -1; int clampIndex = -1;
const char *pPtr(&(*m_DataIt)); const char *pPtr(&(*m_DataIt));
@ -332,7 +332,7 @@ void ObjFileMtlImporter::getTexture() {
std::string texture; std::string texture;
m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, texture); m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, texture);
if (NULL != out) { if (nullptr != out) {
out->Set(texture); out->Set(texture);
} }
} }

View File

@ -494,19 +494,19 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
} }
// Set active material, if one set // Set active material, if one set
if (NULL != m_pModel->m_pCurrentMaterial) { if (nullptr != m_pModel->m_pCurrentMaterial) {
face->m_pMaterial = m_pModel->m_pCurrentMaterial; face->m_pMaterial = m_pModel->m_pCurrentMaterial;
} else { } else {
face->m_pMaterial = m_pModel->m_pDefaultMaterial; face->m_pMaterial = m_pModel->m_pDefaultMaterial;
} }
// Create a default object, if nothing is there // Create a default object, if nothing is there
if (NULL == m_pModel->m_pCurrent) { if (nullptr == m_pModel->m_pCurrent) {
createObject(DefaultObjName); createObject(DefaultObjName);
} }
// Assign face to mesh // Assign face to mesh
if (NULL == m_pModel->m_pCurrentMesh) { if (nullptr == m_pModel->m_pCurrentMesh) {
createMesh(DefaultObjName); createMesh(DefaultObjName);
} }
@ -753,7 +753,7 @@ void ObjFileParser::getObjectName() {
std::string strObjectName(pStart, &(*m_DataIt)); std::string strObjectName(pStart, &(*m_DataIt));
if (!strObjectName.empty()) { if (!strObjectName.empty()) {
// Reset current object // Reset current object
m_pModel->m_pCurrent = NULL; m_pModel->m_pCurrent = nullptr;
// Search for actual object // Search for actual object
for (std::vector<ObjFile::Object *>::const_iterator it = m_pModel->m_Objects.begin(); for (std::vector<ObjFile::Object *>::const_iterator it = m_pModel->m_Objects.begin();
@ -766,7 +766,7 @@ void ObjFileParser::getObjectName() {
} }
// Allocate a new object, if current one was not found before // Allocate a new object, if current one was not found before
if (NULL == m_pModel->m_pCurrent) { if (nullptr == m_pModel->m_pCurrent) {
createObject(strObjectName); createObject(strObjectName);
} }
} }
@ -775,7 +775,7 @@ void ObjFileParser::getObjectName() {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Creates a new object instance // Creates a new object instance
void ObjFileParser::createObject(const std::string &objName) { void ObjFileParser::createObject(const std::string &objName) {
ai_assert(NULL != m_pModel); ai_assert(nullptr != m_pModel);
m_pModel->m_pCurrent = new ObjFile::Object; m_pModel->m_pCurrent = new ObjFile::Object;
m_pModel->m_pCurrent->m_strObjName = objName; m_pModel->m_pCurrent->m_strObjName = objName;
@ -792,11 +792,12 @@ void ObjFileParser::createObject(const std::string &objName) {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Creates a new mesh // Creates a new mesh
void ObjFileParser::createMesh(const std::string &meshName) { void ObjFileParser::createMesh(const std::string &meshName) {
ai_assert(NULL != m_pModel); ai_assert(nullptr != m_pModel);
m_pModel->m_pCurrentMesh = new ObjFile::Mesh(meshName); m_pModel->m_pCurrentMesh = new ObjFile::Mesh(meshName);
m_pModel->m_Meshes.push_back(m_pModel->m_pCurrentMesh); m_pModel->m_Meshes.push_back(m_pModel->m_pCurrentMesh);
unsigned int meshId = static_cast<unsigned int>(m_pModel->m_Meshes.size() - 1); unsigned int meshId = static_cast<unsigned int>(m_pModel->m_Meshes.size() - 1);
if (NULL != m_pModel->m_pCurrent) { if (nullptr != m_pModel->m_pCurrent) {
m_pModel->m_pCurrent->m_Meshes.push_back(meshId); m_pModel->m_pCurrent->m_Meshes.push_back(meshId);
} else { } else {
ASSIMP_LOG_ERROR("OBJ: No object detected to attach a new mesh instance."); ASSIMP_LOG_ERROR("OBJ: No object detected to attach a new mesh instance.");

File diff suppressed because it is too large Load Diff

View File

@ -77,7 +77,7 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// we're still here - export successfully completed. Write the file. // we're still here - export successfully completed. Write the file.
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .ply file: " + std::string(pFile)); throw DeadlyExportError("could not open output .ply file: " + std::string(pFile));
} }
@ -91,7 +91,7 @@ void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene*
// we're still here - export successfully completed. Write the file. // we're still here - export successfully completed. Write the file.
std::unique_ptr<IOStream> outfile(pIOSystem->Open(pFile, "wb")); std::unique_ptr<IOStream> outfile(pIOSystem->Open(pFile, "wb"));
if (outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .ply file: " + std::string(pFile)); throw DeadlyExportError("could not open output .ply file: " + std::string(pFile));
} }

View File

@ -693,7 +693,7 @@ void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance> &avL
unsigned int aiPositions[4], unsigned int aiPositions[4],
PLY::EDataType aiTypes[4], PLY::EDataType aiTypes[4],
aiColor4D *clrOut) { aiColor4D *clrOut) {
ai_assert(NULL != clrOut); ai_assert(nullptr != clrOut);
if (0xFFFFFFFF == aiPositions[0]) if (0xFFFFFFFF == aiPositions[0])
clrOut->r = 0.0f; clrOut->r = 0.0f;
@ -736,7 +736,7 @@ void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance> &avL
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Extract a material from the PLY DOM // Extract a material from the PLY DOM
void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &defaultTexture, const bool pointsOnly) { void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &defaultTexture, const bool pointsOnly) {
ai_assert(NULL != pvOut); ai_assert(nullptr != pvOut);
// diffuse[4], specular[4], ambient[4] // diffuse[4], specular[4], ambient[4]
// rgba order // rgba order
@ -752,7 +752,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
{ EDT_Char, EDT_Char, EDT_Char, EDT_Char }, { 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::ElementInstanceList *pcList = nullptr;
unsigned int iPhong = 0xFFFFFFFF; unsigned int iPhong = 0xFFFFFFFF;
PLY::EDataType ePhong = EDT_Char; PLY::EDataType ePhong = EDT_Char;
@ -835,7 +835,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
} }
} }
// check whether we have a valid source for the material data // check whether we have a valid source for the material data
if (NULL != pcList) { if (nullptr != pcList) {
for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i) { for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i) {
aiColor4D clrOut; aiColor4D clrOut;
aiMaterial *pcHelper = new aiMaterial(); aiMaterial *pcHelper = new aiMaterial();

File diff suppressed because it is too large Load Diff

View File

@ -43,27 +43,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
#include "Q3BSPFileImporter.h" #include "Q3BSPFileImporter.h"
#include "Q3BSPFileParser.h"
#include "Q3BSPFileData.h" #include "Q3BSPFileData.h"
#include "Q3BSPFileParser.h"
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h> #include <zlib.h>
#else #else
# include "../contrib/zlib/zlib.h" #include "../contrib/zlib/zlib.h"
#endif #endif
#include <assimp/types.h> #include <assimp/DefaultIOSystem.h>
#include <assimp/StringComparison.h>
#include <assimp/ZipArchiveIOSystem.h>
#include <assimp/ai_assert.h>
#include <assimp/importerdesc.h>
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/ai_assert.h> #include <assimp/types.h>
#include <assimp/DefaultIOSystem.h>
#include <assimp/ZipArchiveIOSystem.h>
#include <assimp/importerdesc.h>
#include <vector>
#include <sstream> #include <sstream>
#include <assimp/StringComparison.h> #include <vector>
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"Quake III BSP Importer", "Quake III BSP Importer",
@ -84,7 +84,7 @@ using namespace Q3BSP;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Local function to create a material key name. // Local function to create a material key name.
static void createKey( int id1, int id2, std::string &key ) { static void createKey(int id1, int id2, std::string &key) {
std::ostringstream str; std::ostringstream str;
str << id1 << "." << id2; str << id1 << "." << id2;
key = str.str(); key = str.str();
@ -92,27 +92,27 @@ static void createKey( int id1, int id2, std::string &key ) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Local function to extract the texture ids from a material key-name. // Local function to extract the texture ids from a material key-name.
static void extractIds( const std::string &key, int &id1, int &id2 ) { static void extractIds(const std::string &key, int &id1, int &id2) {
id1 = -1; id1 = -1;
id2 = -1; id2 = -1;
if (key.empty()) { if (key.empty()) {
return; return;
} }
const std::string::size_type pos = key.find( "." ); const std::string::size_type pos = key.find(".");
if (std::string::npos == pos) { if (std::string::npos == pos) {
return; return;
} }
std::string tmp1 = key.substr( 0, pos ); std::string tmp1 = key.substr(0, pos);
std::string tmp2 = key.substr( pos + 1, key.size() - pos - 1 ); std::string tmp2 = key.substr(pos + 1, key.size() - pos - 1);
id1 = atoi( tmp1.c_str() ); id1 = atoi(tmp1.c_str());
id2 = atoi( tmp2.c_str() ); id2 = atoi(tmp2.c_str());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Local helper function to normalize filenames. // Local helper function to normalize filenames.
static void normalizePathName( const std::string &rPath, std::string &normalizedPath ) { static void normalizePathName(const std::string &rPath, std::string &normalizedPath) {
normalizedPath = ""; normalizedPath = "";
if (rPath.empty()) { if (rPath.empty()) {
return; return;
@ -125,12 +125,12 @@ static void normalizePathName( const std::string &rPath, std::string &normalized
#endif #endif
static const unsigned int numDelimiters = 2; static const unsigned int numDelimiters = 2;
const char delimiters[ numDelimiters ] = { '/', '\\' }; const char delimiters[numDelimiters] = { '/', '\\' };
normalizedPath = rPath; normalizedPath = rPath;
for (const char delimiter : delimiters) { for (const char delimiter : delimiters) {
for ( size_t j=0; j<normalizedPath.size(); ++j ) { for (size_t j = 0; j < normalizedPath.size(); ++j) {
if ( normalizedPath[j] == delimiter ) { if (normalizedPath[j] == delimiter) {
normalizedPath[ j ] = sep[ 0 ]; normalizedPath[j] = sep[0];
} }
} }
} }
@ -138,11 +138,8 @@ static void normalizePathName( const std::string &rPath, std::string &normalized
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor. // Constructor.
Q3BSPFileImporter::Q3BSPFileImporter() Q3BSPFileImporter::Q3BSPFileImporter() :
: m_pCurrentMesh( nullptr ) m_pCurrentMesh(nullptr), m_pCurrentFace(nullptr), m_MaterialLookupMap(), mTextures() {
, m_pCurrentFace(nullptr)
, m_MaterialLookupMap()
, mTextures() {
// empty // empty
} }
@ -153,9 +150,9 @@ Q3BSPFileImporter::~Q3BSPFileImporter() {
m_pCurrentFace = nullptr; m_pCurrentFace = nullptr;
// Clear face-to-material map // Clear face-to-material map
for ( FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it ) { for (FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) {
const std::string &matName = it->first; const std::string &matName = it->first;
if ( !matName.empty() ) { if (!matName.empty()) {
delete it->second; delete it->second;
} }
} }
@ -164,9 +161,9 @@ Q3BSPFileImporter::~Q3BSPFileImporter() {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns true, if the loader can read this. // Returns true, if the loader can read this.
bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const { bool Q3BSPFileImporter::CanRead(const std::string &rFile, IOSystem * /*pIOHandler*/, bool checkSig) const {
if(!checkSig) { if (!checkSig) {
return SimpleExtensionCheck( rFile, "pk3", "bsp" ); return SimpleExtensionCheck(rFile, "pk3", "bsp");
} }
return false; return false;
@ -174,69 +171,69 @@ bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandle
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Adds extensions. // Adds extensions.
const aiImporterDesc* Q3BSPFileImporter::GetInfo () const { const aiImporterDesc *Q3BSPFileImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Import method. // Import method.
void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* scene, IOSystem* ioHandler) { void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) {
ZipArchiveIOSystem Archive( ioHandler, rFile ); ZipArchiveIOSystem Archive(ioHandler, rFile);
if ( !Archive.isOpen() ) { if (!Archive.isOpen()) {
throw DeadlyImportError( "Failed to open file " + rFile + "." ); throw DeadlyImportError("Failed to open file " + rFile + ".");
} }
std::string archiveName( "" ), mapName( "" ); std::string archiveName(""), mapName("");
separateMapName( rFile, archiveName, mapName ); separateMapName(rFile, archiveName, mapName);
if ( mapName.empty() ) { if (mapName.empty()) {
if ( !findFirstMapInArchive( Archive, mapName ) ) { if (!findFirstMapInArchive(Archive, mapName)) {
return; return;
} }
} }
Q3BSPFileParser fileParser( mapName, &Archive ); Q3BSPFileParser fileParser(mapName, &Archive);
Q3BSPModel *pBSPModel = fileParser.getModel(); Q3BSPModel *pBSPModel = fileParser.getModel();
if ( nullptr != pBSPModel ) { if (nullptr != pBSPModel) {
CreateDataFromImport( pBSPModel, scene, &Archive ); CreateDataFromImport(pBSPModel, scene, &Archive);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Separates the map name from the import name. // Separates the map name from the import name.
void Q3BSPFileImporter::separateMapName( const std::string &importName, std::string &archiveName, std::string &mapName ) { void Q3BSPFileImporter::separateMapName(const std::string &importName, std::string &archiveName, std::string &mapName) {
archiveName = ""; archiveName = "";
mapName = ""; mapName = "";
if (importName.empty()) { if (importName.empty()) {
return; return;
} }
const std::string::size_type pos = importName.rfind( "," ); const std::string::size_type pos = importName.rfind(",");
if ( std::string::npos == pos ) { if (std::string::npos == pos) {
archiveName = importName; archiveName = importName;
return; return;
} }
archiveName = importName.substr( 0, pos ); archiveName = importName.substr(0, pos);
mapName = importName.substr( pos, importName.size() - pos - 1 ); mapName = importName.substr(pos, importName.size() - pos - 1);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns the first map in the map archive. // Returns the first map in the map archive.
bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, std::string &mapName ) { bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, std::string &mapName) {
mapName = ""; mapName = "";
std::vector<std::string> fileList; std::vector<std::string> fileList;
bspArchive.getFileListExtension( fileList, "bsp" ); bspArchive.getFileListExtension(fileList, "bsp");
if (fileList.empty()) { if (fileList.empty()) {
return false; return false;
} }
std::vector<std::string>::iterator it( fileList.begin() ); std::vector<std::string>::iterator it(fileList.begin());
for ( ; it != fileList.end(); ++it ) { for (; it != fileList.end(); ++it) {
const std::string::size_type pos = (*it).find( "maps/" ); const std::string::size_type pos = (*it).find("maps/");
if ( std::string::npos != pos ) { if (std::string::npos != pos) {
std::string::size_type extPos = (*it).find( ".bsp" ); std::string::size_type extPos = (*it).find(".bsp");
if ( std::string::npos != extPos ) { if (std::string::npos != extPos) {
mapName = *it; mapName = *it;
return true; return true;
} }
@ -248,122 +245,122 @@ bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, st
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates the assimp specific data. // Creates the assimp specific data.
void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, void Q3BSPFileImporter::CreateDataFromImport(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene,
ZipArchiveIOSystem *pArchive ) { ZipArchiveIOSystem *pArchive) {
if (nullptr == pModel || nullptr == pScene) { if (nullptr == pModel || nullptr == pScene) {
return; return;
} }
pScene->mRootNode = new aiNode; pScene->mRootNode = new aiNode;
if ( !pModel->m_ModelName.empty() ) { if (!pModel->m_ModelName.empty()) {
pScene->mRootNode->mName.Set( pModel->m_ModelName ); pScene->mRootNode->mName.Set(pModel->m_ModelName);
} }
// Create the face to material relation map // Create the face to material relation map
createMaterialMap( pModel ); createMaterialMap(pModel);
// Create all nodes // Create all nodes
CreateNodes( pModel, pScene, pScene->mRootNode ); CreateNodes(pModel, pScene, pScene->mRootNode);
// Create the assigned materials // Create the assigned materials
createMaterials( pModel, pScene, pArchive ); createMaterials(pModel, pScene, pArchive);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates all assimp nodes. // Creates all assimp nodes.
void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, void Q3BSPFileImporter::CreateNodes(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene,
aiNode *pParent ) { aiNode *pParent) {
if ( nullptr == pModel ) { if (nullptr == pModel) {
return; return;
} }
unsigned int matIdx( 0 ); unsigned int matIdx(0);
std::vector<aiMesh*> MeshArray; std::vector<aiMesh *> MeshArray;
std::vector<aiNode*> NodeArray; std::vector<aiNode *> NodeArray;
for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it ) { for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) {
std::vector<Q3BSP::sQ3BSPFace*> *pArray = (*it).second; std::vector<Q3BSP::sQ3BSPFace *> *pArray = (*it).second;
size_t numVerts = countData( *pArray ); size_t numVerts = countData(*pArray);
if ( 0 != numVerts ) { if (0 != numVerts) {
aiMesh *pMesh( nullptr ); aiMesh *pMesh(nullptr);
aiNode *pNode = CreateTopology( pModel, matIdx, *pArray, &pMesh ); aiNode *pNode = CreateTopology(pModel, matIdx, *pArray, &pMesh);
if ( nullptr != pNode ) { if (nullptr != pNode) {
NodeArray.push_back( pNode ); NodeArray.push_back(pNode);
MeshArray.push_back( pMesh ); MeshArray.push_back(pMesh);
} }
} }
matIdx++; matIdx++;
} }
pScene->mNumMeshes = static_cast<unsigned int>( MeshArray.size() ); pScene->mNumMeshes = static_cast<unsigned int>(MeshArray.size());
if ( pScene->mNumMeshes > 0 ) { if (pScene->mNumMeshes > 0) {
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
for ( size_t i = 0; i < MeshArray.size(); i++ ) { for (size_t i = 0; i < MeshArray.size(); i++) {
aiMesh *pMesh = MeshArray[ i ]; aiMesh *pMesh = MeshArray[i];
if ( nullptr != pMesh ) { if (nullptr != pMesh) {
pScene->mMeshes[ i ] = pMesh; pScene->mMeshes[i] = pMesh;
} }
} }
} }
pParent->mNumChildren = static_cast<unsigned int>(MeshArray.size()); pParent->mNumChildren = static_cast<unsigned int>(MeshArray.size());
pParent->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ]; pParent->mChildren = new aiNode *[pScene->mRootNode->mNumChildren];
for ( size_t i=0; i<NodeArray.size(); i++ ) { for (size_t i = 0; i < NodeArray.size(); i++) {
aiNode *pNode = NodeArray[ i ]; aiNode *pNode = NodeArray[i];
pNode->mParent = pParent; pNode->mParent = pParent;
pParent->mChildren[ i ] = pNode; pParent->mChildren[i] = pNode;
pParent->mChildren[ i ]->mMeshes[ 0 ] = static_cast<unsigned int>(i); pParent->mChildren[i]->mMeshes[0] = static_cast<unsigned int>(i);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates the topology. // Creates the topology.
aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx, aiNode *Q3BSPFileImporter::CreateTopology(const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx,
std::vector<sQ3BSPFace*> &rArray, aiMesh **pMesh ) { std::vector<sQ3BSPFace *> &rArray, aiMesh **pMesh) {
size_t numVerts = countData( rArray ); size_t numVerts = countData(rArray);
if ( 0 == numVerts ) { if (0 == numVerts) {
return nullptr; return nullptr;
} }
size_t numFaces = countFaces( rArray ); size_t numFaces = countFaces(rArray);
if ( 0 == numFaces ) { if (0 == numFaces) {
return nullptr; return nullptr;
} }
aiMesh *mesh = new aiMesh; aiMesh *mesh = new aiMesh;
size_t numTriangles = countTriangles( rArray ); size_t numTriangles = countTriangles(rArray);
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
mesh->mFaces = new aiFace[ numTriangles ]; mesh->mFaces = new aiFace[numTriangles];
mesh->mNumFaces = static_cast<unsigned int>(numTriangles); mesh->mNumFaces = static_cast<unsigned int>(numTriangles);
mesh->mNumVertices = static_cast<unsigned int>(numVerts); mesh->mNumVertices = static_cast<unsigned int>(numVerts);
mesh->mVertices = new aiVector3D[ numVerts ]; mesh->mVertices = new aiVector3D[numVerts];
mesh->mNormals = new aiVector3D[ numVerts ]; mesh->mNormals = new aiVector3D[numVerts];
mesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ]; mesh->mTextureCoords[0] = new aiVector3D[numVerts];
mesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ]; mesh->mTextureCoords[1] = new aiVector3D[numVerts];
mesh->mMaterialIndex = materialIdx; mesh->mMaterialIndex = materialIdx;
unsigned int faceIdx = 0; unsigned int faceIdx = 0;
unsigned int vertIdx = 0; unsigned int vertIdx = 0;
mesh->mNumUVComponents[ 0 ] = 2; mesh->mNumUVComponents[0] = 2;
mesh->mNumUVComponents[ 1 ] = 2; mesh->mNumUVComponents[1] = 2;
for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); ++it ) { for (std::vector<sQ3BSPFace *>::const_iterator it = rArray.begin(); it != rArray.end(); ++it) {
Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
ai_assert( NULL != pQ3BSPFace ); ai_assert(nullptr != pQ3BSPFace);
if ( nullptr == pQ3BSPFace ) { if (nullptr == pQ3BSPFace) {
continue; continue;
} }
if ( pQ3BSPFace->iNumOfFaceVerts > 0 ) { if (pQ3BSPFace->iNumOfFaceVerts > 0) {
if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh ) { if (pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh) {
createTriangleTopology( pModel, pQ3BSPFace, mesh, faceIdx, vertIdx ); createTriangleTopology(pModel, pQ3BSPFace, mesh, faceIdx, vertIdx);
} }
} }
} }
aiNode *pNode = new aiNode; aiNode *pNode = new aiNode;
pNode->mNumMeshes = 1; pNode->mNumMeshes = 1;
pNode->mMeshes = new unsigned int[ 1 ]; pNode->mMeshes = new unsigned int[1];
*pMesh = mesh; *pMesh = mesh;
return pNode; return pNode;
@ -371,27 +368,27 @@ aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsi
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates the triangle topology from a face array. // Creates the triangle topology from a face array.
void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, sQ3BSPFace *pQ3BSPFace, void Q3BSPFileImporter::createTriangleTopology(const Q3BSP::Q3BSPModel *pModel, sQ3BSPFace *pQ3BSPFace,
aiMesh* pMesh, unsigned int &faceIdx, unsigned int &vertIdx ) { aiMesh *pMesh, unsigned int &faceIdx, unsigned int &vertIdx) {
ai_assert( faceIdx < pMesh->mNumFaces ); ai_assert(faceIdx < pMesh->mNumFaces);
m_pCurrentFace = getNextFace( pMesh, faceIdx ); m_pCurrentFace = getNextFace(pMesh, faceIdx);
if ( nullptr == m_pCurrentFace ) { if (nullptr == m_pCurrentFace) {
return; return;
} }
m_pCurrentFace->mNumIndices = 3; m_pCurrentFace->mNumIndices = 3;
m_pCurrentFace->mIndices = new unsigned int[ m_pCurrentFace->mNumIndices ]; m_pCurrentFace->mIndices = new unsigned int[m_pCurrentFace->mNumIndices];
size_t idx( 0 ); size_t idx(0);
for ( size_t i = 0; i < (size_t) pQ3BSPFace->iNumOfFaceVerts; ++i ) { for (size_t i = 0; i < (size_t)pQ3BSPFace->iNumOfFaceVerts; ++i) {
const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[ pQ3BSPFace->iFaceVertexIndex + i ]; const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[pQ3BSPFace->iFaceVertexIndex + i];
if ( index >= pModel->m_Vertices.size() ) { if (index >= pModel->m_Vertices.size()) {
continue; continue;
} }
sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ]; sQ3BSPVertex *pVertex = pModel->m_Vertices[index];
if ( nullptr == pVertex ) { if (nullptr == pVertex) {
continue; continue;
} }
if (idx > 2) { if (idx > 2) {
@ -400,15 +397,15 @@ void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel,
if (nullptr != m_pCurrentFace) { if (nullptr != m_pCurrentFace) {
m_pCurrentFace->mNumIndices = 3; m_pCurrentFace->mNumIndices = 3;
m_pCurrentFace->mIndices = new unsigned int[3]; m_pCurrentFace->mIndices = new unsigned int[3];
m_pCurrentFace->mIndices[ idx ] = vertIdx; m_pCurrentFace->mIndices[idx] = vertIdx;
} }
} }
pMesh->mVertices[ vertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z ); pMesh->mVertices[vertIdx].Set(pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z);
pMesh->mNormals[ vertIdx ].Set( pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z ); pMesh->mNormals[vertIdx].Set(pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z);
pMesh->mTextureCoords[ 0 ][ vertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f ); pMesh->mTextureCoords[0][vertIdx].Set(pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f);
pMesh->mTextureCoords[ 1 ][ vertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f ); pMesh->mTextureCoords[1][vertIdx].Set(pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f);
vertIdx++; vertIdx++;
idx++; idx++;
@ -417,65 +414,61 @@ void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates all referenced materials. // Creates all referenced materials.
void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, void Q3BSPFileImporter::createMaterials(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene,
ZipArchiveIOSystem *pArchive ) { ZipArchiveIOSystem *pArchive) {
if ( m_MaterialLookupMap.empty() ) { if (m_MaterialLookupMap.empty()) {
return; return;
} }
pScene->mMaterials = new aiMaterial*[ m_MaterialLookupMap.size() ]; pScene->mMaterials = new aiMaterial *[m_MaterialLookupMap.size()];
aiString aiMatName; aiString aiMatName;
int textureId( -1 ), lightmapId( -1 ); int textureId(-1), lightmapId(-1);
for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end();
++it ) { ++it) {
const std::string matName( it->first ); const std::string matName(it->first);
if ( matName.empty() ) { if (matName.empty()) {
continue; continue;
} }
aiMatName.Set( matName ); aiMatName.Set(matName);
aiMaterial *pMatHelper = new aiMaterial; aiMaterial *pMatHelper = new aiMaterial;
pMatHelper->AddProperty( &aiMatName, AI_MATKEY_NAME ); pMatHelper->AddProperty(&aiMatName, AI_MATKEY_NAME);
extractIds( matName, textureId, lightmapId ); extractIds(matName, textureId, lightmapId);
// Adding the texture // Adding the texture
if ( -1 != textureId ) { if (-1 != textureId) {
sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ]; sQ3BSPTexture *pTexture = pModel->m_Textures[textureId];
if ( nullptr != pTexture ) { if (nullptr != pTexture) {
std::string tmp( "*" ), texName( "" ); std::string tmp("*"), texName("");
tmp += pTexture->strName; tmp += pTexture->strName;
tmp += ".jpg"; tmp += ".jpg";
normalizePathName( tmp, texName ); normalizePathName(tmp, texName);
if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) ) { if (!importTextureFromArchive(pModel, pArchive, pScene, pMatHelper, textureId)) {
ASSIMP_LOG_ERROR("Cannot import texture from archive " + texName); ASSIMP_LOG_ERROR("Cannot import texture from archive " + texName);
} }
} }
} }
if ( -1 != lightmapId ) if (-1 != lightmapId) {
{ importLightmap(pModel, pScene, pMatHelper, lightmapId);
importLightmap( pModel, pScene, pMatHelper, lightmapId );
} }
pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper; pScene->mMaterials[pScene->mNumMaterials] = pMatHelper;
pScene->mNumMaterials++; pScene->mNumMaterials++;
} }
pScene->mNumTextures = static_cast<unsigned int>(mTextures.size()); pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
pScene->mTextures = new aiTexture*[ pScene->mNumTextures ]; pScene->mTextures = new aiTexture *[pScene->mNumTextures];
std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures ); std::copy(mTextures.begin(), mTextures.end(), pScene->mTextures);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Counts the number of referenced vertices. // Counts the number of referenced vertices.
size_t Q3BSPFileImporter::countData( const std::vector<sQ3BSPFace*> &faceArray ) const { size_t Q3BSPFileImporter::countData(const std::vector<sQ3BSPFace *> &faceArray) const {
size_t numVerts( 0 ); size_t numVerts(0);
for ( std::vector<sQ3BSPFace*>::const_iterator it = faceArray.begin(); it != faceArray.end(); for (std::vector<sQ3BSPFace *>::const_iterator it = faceArray.begin(); it != faceArray.end();
++it ) ++it) {
{
sQ3BSPFace *pQ3BSPFace = *it; sQ3BSPFace *pQ3BSPFace = *it;
if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh ) if (pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh) {
{
Q3BSP::sQ3BSPFace *face = *it; Q3BSP::sQ3BSPFace *face = *it;
if (nullptr != face) { if (nullptr != face) {
numVerts += face->iNumOfFaceVerts; numVerts += face->iNumOfFaceVerts;
@ -488,15 +481,12 @@ size_t Q3BSPFileImporter::countData( const std::vector<sQ3BSPFace*> &faceArray )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Counts the faces with vertices. // Counts the faces with vertices.
size_t Q3BSPFileImporter::countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const size_t Q3BSPFileImporter::countFaces(const std::vector<Q3BSP::sQ3BSPFace *> &rArray) const {
{
size_t numFaces = 0; size_t numFaces = 0;
for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); for (std::vector<sQ3BSPFace *>::const_iterator it = rArray.begin(); it != rArray.end();
++it ) ++it) {
{
Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
if ( pQ3BSPFace->iNumOfFaceVerts > 0 ) if (pQ3BSPFace->iNumOfFaceVerts > 0) {
{
numFaces++; numFaces++;
} }
} }
@ -506,15 +496,12 @@ size_t Q3BSPFileImporter::countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rAr
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Counts the number of triangles in a Q3-face-array. // Counts the number of triangles in a Q3-face-array.
size_t Q3BSPFileImporter::countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const size_t Q3BSPFileImporter::countTriangles(const std::vector<Q3BSP::sQ3BSPFace *> &rArray) const {
{
size_t numTriangles = 0; size_t numTriangles = 0;
for ( std::vector<Q3BSP::sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); for (std::vector<Q3BSP::sQ3BSPFace *>::const_iterator it = rArray.begin(); it != rArray.end();
++it ) ++it) {
{
const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
if ( NULL != pQ3BSPFace ) if (nullptr != pQ3BSPFace) {
{
numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3; numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3;
} }
} }
@ -524,38 +511,34 @@ size_t Q3BSPFileImporter::countTriangles( const std::vector<Q3BSP::sQ3BSPFace*>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates the faces-to-material map. // Creates the faces-to-material map.
void Q3BSPFileImporter::createMaterialMap( const Q3BSP::Q3BSPModel *pModel ) { void Q3BSPFileImporter::createMaterialMap(const Q3BSP::Q3BSPModel *pModel) {
std::string key( "" ); std::string key("");
std::vector<sQ3BSPFace*> *pCurFaceArray = NULL; std::vector<sQ3BSPFace *> *pCurFaceArray = nullptr;
for ( size_t idx = 0; idx < pModel->m_Faces.size(); idx++ ) for (size_t idx = 0; idx < pModel->m_Faces.size(); idx++) {
{ Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[idx];
Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ];
const int texId = pQ3BSPFace->iTextureID; const int texId = pQ3BSPFace->iTextureID;
const int lightMapId = pQ3BSPFace->iLightmapID; const int lightMapId = pQ3BSPFace->iLightmapID;
createKey( texId, lightMapId, key ); createKey(texId, lightMapId, key);
FaceMapIt it = m_MaterialLookupMap.find( key ); FaceMapIt it = m_MaterialLookupMap.find(key);
if ( m_MaterialLookupMap.end() == it ) { if (m_MaterialLookupMap.end() == it) {
pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace*>; pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace *>;
m_MaterialLookupMap[ key ] = pCurFaceArray; m_MaterialLookupMap[key] = pCurFaceArray;
} } else {
else
{
pCurFaceArray = (*it).second; pCurFaceArray = (*it).second;
} }
ai_assert( nullptr != pCurFaceArray ); ai_assert(nullptr != pCurFaceArray);
if (nullptr != pCurFaceArray ) if (nullptr != pCurFaceArray) {
{ pCurFaceArray->push_back(pQ3BSPFace);
pCurFaceArray->push_back( pQ3BSPFace );
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns the next face. // Returns the next face.
aiFace *Q3BSPFileImporter::getNextFace( aiMesh *mesh, unsigned int &faceIdx ) { aiFace *Q3BSPFileImporter::getNextFace(aiMesh *mesh, unsigned int &faceIdx) {
aiFace *face( nullptr ); aiFace *face(nullptr);
if ( faceIdx < mesh->mNumFaces ) { if (faceIdx < mesh->mNumFaces) {
face = &mesh->mFaces[ faceIdx ]; face = &mesh->mFaces[faceIdx];
++faceIdx; ++faceIdx;
} }
@ -564,31 +547,31 @@ aiFace *Q3BSPFileImporter::getNextFace( aiMesh *mesh, unsigned int &faceIdx ) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports a texture file. // Imports a texture file.
bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model, bool Q3BSPFileImporter::importTextureFromArchive(const Q3BSP::Q3BSPModel *model,
ZipArchiveIOSystem *archive, aiScene*, ZipArchiveIOSystem *archive, aiScene *,
aiMaterial *pMatHelper, int textureId ) { aiMaterial *pMatHelper, int textureId) {
if (nullptr == archive || nullptr == pMatHelper ) { if (nullptr == archive || nullptr == pMatHelper) {
return false; return false;
} }
if ( textureId < 0 || textureId >= static_cast<int>( model->m_Textures.size() ) ) { if (textureId < 0 || textureId >= static_cast<int>(model->m_Textures.size())) {
return false; return false;
} }
bool res = true; bool res = true;
sQ3BSPTexture *pTexture = model->m_Textures[ textureId ]; sQ3BSPTexture *pTexture = model->m_Textures[textureId];
if ( !pTexture ) { if (!pTexture) {
return false; return false;
} }
std::vector<std::string> supportedExtensions; std::vector<std::string> supportedExtensions;
supportedExtensions.push_back( ".jpg" ); supportedExtensions.push_back(".jpg");
supportedExtensions.push_back( ".png" ); supportedExtensions.push_back(".png");
supportedExtensions.push_back( ".tga" ); supportedExtensions.push_back(".tga");
std::string textureName, ext; std::string textureName, ext;
if ( expandFile( archive, pTexture->strName, supportedExtensions, textureName, ext ) ) { if (expandFile(archive, pTexture->strName, supportedExtensions, textureName, ext)) {
IOStream *pTextureStream = archive->Open( textureName.c_str() ); IOStream *pTextureStream = archive->Open(textureName.c_str());
if ( pTextureStream ) { if (pTextureStream) {
size_t texSize = pTextureStream->FileSize(); size_t texSize = pTextureStream->FileSize();
aiTexture *curTexture = new aiTexture; aiTexture *curTexture = new aiTexture;
curTexture->mHeight = 0; curTexture->mHeight = 0;
@ -605,20 +588,20 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model
res = true; res = true;
aiString name; aiString name;
name.data[ 0 ] = '*'; name.data[0] = '*';
name.length = 1 + ASSIMP_itoa10( name.data + 1, static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(mTextures.size()) ); name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
archive->Close( pTextureStream ); archive->Close(pTextureStream);
pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(0));
mTextures.push_back(curTexture); mTextures.push_back(curTexture);
} else { } else {
// If it doesn't exist in the archive, it is probably just a reference to an external file. // If it doesn't exist in the archive, it is probably just a reference to an external file.
// We'll leave it up to the user to figure out which extension the file has. // We'll leave it up to the user to figure out which extension the file has.
aiString name; aiString name;
strncpy( name.data, pTexture->strName, sizeof name.data ); strncpy(name.data, pTexture->strName, sizeof name.data);
name.length = static_cast<ai_uint32>(strlen( name.data )); name.length = static_cast<ai_uint32>(strlen(name.data));
pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(0));
} }
} }
@ -627,19 +610,18 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports a light map file. // Imports a light map file.
bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, bool Q3BSPFileImporter::importLightmap(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene,
aiMaterial *pMatHelper, int lightmapId ) aiMaterial *pMatHelper, int lightmapId) {
{ if (nullptr == pModel || nullptr == pScene || nullptr == pMatHelper) {
if (nullptr == pModel || nullptr == pScene || nullptr == pMatHelper ) {
return false; return false;
} }
if ( lightmapId < 0 || lightmapId >= static_cast<int>( pModel->m_Lightmaps.size() ) ) { if (lightmapId < 0 || lightmapId >= static_cast<int>(pModel->m_Lightmaps.size())) {
return false; return false;
} }
sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[ lightmapId ]; sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[lightmapId];
if (nullptr == pLightMap ) { if (nullptr == pLightMap) {
return false; return false;
} }
@ -649,21 +631,21 @@ bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene
pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT; pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT;
pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT]; pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT];
::memcpy( pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth ); ::memcpy(pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth);
size_t p = 0; size_t p = 0;
for ( size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i ) { for (size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i) {
pTexture->pcData[ i ].r = pLightMap->bLMapData[ p++ ]; pTexture->pcData[i].r = pLightMap->bLMapData[p++];
pTexture->pcData[ i ].g = pLightMap->bLMapData[ p++ ]; pTexture->pcData[i].g = pLightMap->bLMapData[p++];
pTexture->pcData[ i ].b = pLightMap->bLMapData[ p++ ]; pTexture->pcData[i].b = pLightMap->bLMapData[p++];
pTexture->pcData[ i ].a = 0xFF; pTexture->pcData[i].a = 0xFF;
} }
aiString name; aiString name;
name.data[ 0 ] = '*'; name.data[0] = '*';
name.length = 1 + ASSIMP_itoa10( name.data + 1, static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(mTextures.size()) ); name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) ); pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_LIGHTMAP(1));
mTextures.push_back( pTexture ); mTextures.push_back(pTexture);
return true; return true;
} }
@ -671,25 +653,21 @@ bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Will search for a supported extension. // Will search for a supported extension.
bool Q3BSPFileImporter::expandFile(ZipArchiveIOSystem *pArchive, const std::string &rFilename, bool Q3BSPFileImporter::expandFile(ZipArchiveIOSystem *pArchive, const std::string &rFilename,
const std::vector<std::string> &rExtList, std::string &rFile, const std::vector<std::string> &rExtList, std::string &rFile,
std::string &rExt ) std::string &rExt) {
{ ai_assert(nullptr != pArchive);
ai_assert( NULL != pArchive ); ai_assert(!rFilename.empty());
ai_assert( !rFilename.empty() );
if ( rExtList.empty() ) if (rExtList.empty()) {
{ rFile = rFilename;
rFile = rFilename;
rExt = ""; rExt = "";
return true; return true;
} }
bool found = false; bool found = false;
for ( std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it ) for (std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it) {
{
const std::string textureName = rFilename + *it; const std::string textureName = rFilename + *it;
if ( pArchive->Exists( textureName.c_str() ) ) if (pArchive->Exists(textureName.c_str())) {
{
rExt = *it; rExt = *it;
rFile = textureName; rFile = textureName;
found = true; found = true;

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -45,17 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Q3D importer class * @brief Implementation of the Q3D importer class
*/ */
#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER #ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
// internal headers // internal headers
#include "Q3DLoader.h" #include "Q3DLoader.h"
#include <assimp/StreamReader.h> #include <assimp/StreamReader.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
using namespace Assimp; using namespace Assimp;
@ -74,68 +71,66 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
Q3DImporter::Q3DImporter() Q3DImporter::Q3DImporter() {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
Q3DImporter::~Q3DImporter() Q3DImporter::~Q3DImporter() {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool Q3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const bool Q3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
{
const std::string extension = GetExtension(pFile); const std::string extension = GetExtension(pFile);
if (extension == "q3s" || extension == "q3o") if (extension == "q3s" || extension == "q3o")
return true; return true;
else if (!extension.length() || checkSig) { else if (!extension.length() || checkSig) {
if (!pIOHandler) if (!pIOHandler)
return true; return true;
const char* tokens[] = {"quick3Do","quick3Ds"}; const char *tokens[] = { "quick3Do", "quick3Ds" };
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2); return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 2);
} }
return false; return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiImporterDesc* Q3DImporter::GetInfo () const const aiImporterDesc *Q3DImporter::GetInfo() const {
{
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void Q3DImporter::InternReadFile( const std::string& pFile, void Q3DImporter::InternReadFile(const std::string &pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene *pScene, IOSystem *pIOHandler) {
{ StreamReaderLE stream(pIOHandler->Open(pFile, "rb"));
StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
// The header is 22 bytes large // The header is 22 bytes large
if (stream.GetRemainingSize() < 22) if (stream.GetRemainingSize() < 22)
throw DeadlyImportError("File is either empty or corrupt: " + pFile); throw DeadlyImportError("File is either empty or corrupt: " + pFile);
// Check the file's signature // Check the file's signature
if (ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Do", 8 ) && if (ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Do", 8) &&
ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Ds", 8 )) ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Ds", 8)) {
{
throw DeadlyImportError("Not a Quick3D file. Signature string is: " + throw DeadlyImportError("Not a Quick3D file. Signature string is: " +
std::string((const char*)stream.GetPtr(),8)); std::string((const char *)stream.GetPtr(), 8));
} }
// Print the file format version // Print the file format version
ASSIMP_LOG_INFO_F("Quick3D File format version: ", ASSIMP_LOG_INFO_F("Quick3D File format version: ",
std::string(&((const char*)stream.GetPtr())[8],2)); std::string(&((const char *)stream.GetPtr())[8], 2));
// ... an store it // ... an store it
char major = ((const char*)stream.GetPtr())[8]; char major = ((const char *)stream.GetPtr())[8];
char minor = ((const char*)stream.GetPtr())[9]; char minor = ((const char *)stream.GetPtr())[9];
stream.IncPtr(10); stream.IncPtr(10);
unsigned int numMeshes = (unsigned int)stream.GetI4(); unsigned int numMeshes = (unsigned int)stream.GetI4();
unsigned int numMats = (unsigned int)stream.GetI4(); unsigned int numMats = (unsigned int)stream.GetI4();
unsigned int numTextures = (unsigned int)stream.GetI4(); unsigned int numTextures = (unsigned int)stream.GetI4();
std::vector<Material> materials; std::vector<Material> materials;
materials.reserve(numMats); materials.reserve(numMats);
@ -146,124 +141,109 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
// Allocate the scene root node // Allocate the scene root node
pScene->mRootNode = new aiNode(); pScene->mRootNode = new aiNode();
aiColor3D fgColor (0.6f,0.6f,0.6f); aiColor3D fgColor(0.6f, 0.6f, 0.6f);
// Now read all file chunks // Now read all file chunks
while (true) while (true) {
{ if (stream.GetRemainingSize() < 1) break;
if (stream.GetRemainingSize() < 1)break;
char c = stream.GetI1(); char c = stream.GetI1();
switch (c) switch (c) {
{
// Meshes chunk // Meshes chunk
case 'm': case 'm': {
{ for (unsigned int quak = 0; quak < numMeshes; ++quak) {
for (unsigned int quak = 0; quak < numMeshes; ++quak) meshes.push_back(Mesh());
{ Mesh &mesh = meshes.back();
meshes.push_back(Mesh());
Mesh& mesh = meshes.back();
// read all vertices // read all vertices
unsigned int numVerts = (unsigned int)stream.GetI4(); unsigned int numVerts = (unsigned int)stream.GetI4();
if (!numVerts) if (!numVerts)
throw DeadlyImportError("Quick3D: Found mesh with zero vertices"); throw DeadlyImportError("Quick3D: Found mesh with zero vertices");
std::vector<aiVector3D>& verts = mesh.verts; std::vector<aiVector3D> &verts = mesh.verts;
verts.resize(numVerts); verts.resize(numVerts);
for (unsigned int i = 0; i < numVerts;++i) for (unsigned int i = 0; i < numVerts; ++i) {
{ verts[i].x = stream.GetF4();
verts[i].x = stream.GetF4(); verts[i].y = stream.GetF4();
verts[i].y = stream.GetF4(); verts[i].z = stream.GetF4();
verts[i].z = stream.GetF4();
}
// read all faces
numVerts = (unsigned int)stream.GetI4();
if (!numVerts)
throw DeadlyImportError("Quick3D: Found mesh with zero faces");
std::vector<Face >& faces = mesh.faces;
faces.reserve(numVerts);
// number of indices
for (unsigned int i = 0; i < numVerts;++i)
{
faces.push_back(Face(stream.GetI2()) );
if (faces.back().indices.empty())
throw DeadlyImportError("Quick3D: Found face with zero indices");
}
// indices
for (unsigned int i = 0; i < numVerts;++i)
{
Face& vec = faces[i];
for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
vec.indices[a] = stream.GetI4();
}
// material indices
for (unsigned int i = 0; i < numVerts;++i)
{
faces[i].mat = (unsigned int)stream.GetI4();
}
// read all normals
numVerts = (unsigned int)stream.GetI4();
std::vector<aiVector3D>& normals = mesh.normals;
normals.resize(numVerts);
for (unsigned int i = 0; i < numVerts;++i)
{
normals[i].x = stream.GetF4();
normals[i].y = stream.GetF4();
normals[i].z = stream.GetF4();
}
numVerts = (unsigned int)stream.GetI4();
if (numTextures && numVerts)
{
// read all texture coordinates
std::vector<aiVector3D>& uv = mesh.uv;
uv.resize(numVerts);
for (unsigned int i = 0; i < numVerts;++i)
{
uv[i].x = stream.GetF4();
uv[i].y = stream.GetF4();
}
// UV indices
for (unsigned int i = 0; i < (unsigned int)faces.size();++i)
{
Face& vec = faces[i];
for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
{
vec.uvindices[a] = stream.GetI4();
if (!i && !a)
mesh.prevUVIdx = vec.uvindices[a];
else if (vec.uvindices[a] != mesh.prevUVIdx)
mesh.prevUVIdx = UINT_MAX;
}
}
}
// we don't need the rest, but we need to get to the next chunk
stream.IncPtr(36);
if (minor > '0' && major == '3')
stream.IncPtr(mesh.faces.size());
} }
// stream.IncPtr(4); // unknown value here
// read all faces
numVerts = (unsigned int)stream.GetI4();
if (!numVerts)
throw DeadlyImportError("Quick3D: Found mesh with zero faces");
std::vector<Face> &faces = mesh.faces;
faces.reserve(numVerts);
// number of indices
for (unsigned int i = 0; i < numVerts; ++i) {
faces.push_back(Face(stream.GetI2()));
if (faces.back().indices.empty())
throw DeadlyImportError("Quick3D: Found face with zero indices");
}
// indices
for (unsigned int i = 0; i < numVerts; ++i) {
Face &vec = faces[i];
for (unsigned int a = 0; a < (unsigned int)vec.indices.size(); ++a)
vec.indices[a] = stream.GetI4();
}
// material indices
for (unsigned int i = 0; i < numVerts; ++i) {
faces[i].mat = (unsigned int)stream.GetI4();
}
// read all normals
numVerts = (unsigned int)stream.GetI4();
std::vector<aiVector3D> &normals = mesh.normals;
normals.resize(numVerts);
for (unsigned int i = 0; i < numVerts; ++i) {
normals[i].x = stream.GetF4();
normals[i].y = stream.GetF4();
normals[i].z = stream.GetF4();
}
numVerts = (unsigned int)stream.GetI4();
if (numTextures && numVerts) {
// read all texture coordinates
std::vector<aiVector3D> &uv = mesh.uv;
uv.resize(numVerts);
for (unsigned int i = 0; i < numVerts; ++i) {
uv[i].x = stream.GetF4();
uv[i].y = stream.GetF4();
}
// UV indices
for (unsigned int i = 0; i < (unsigned int)faces.size(); ++i) {
Face &vec = faces[i];
for (unsigned int a = 0; a < (unsigned int)vec.indices.size(); ++a) {
vec.uvindices[a] = stream.GetI4();
if (!i && !a)
mesh.prevUVIdx = vec.uvindices[a];
else if (vec.uvindices[a] != mesh.prevUVIdx)
mesh.prevUVIdx = UINT_MAX;
}
}
}
// we don't need the rest, but we need to get to the next chunk
stream.IncPtr(36);
if (minor > '0' && major == '3')
stream.IncPtr(mesh.faces.size());
} }
break; // stream.IncPtr(4); // unknown value here
} break;
// materials chunk // materials chunk
case 'c': case 'c':
for (unsigned int i = 0; i < numMats; ++i) for (unsigned int i = 0; i < numMats; ++i) {
{
materials.push_back(Material()); materials.push_back(Material());
Material& mat = materials.back(); Material &mat = materials.back();
// read the material name // read the material name
c = stream.GetI1(); c = stream.GetI1();
@ -308,17 +288,18 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
if (!numTextures) { if (!numTextures) {
break; break;
} }
pScene->mTextures = new aiTexture*[pScene->mNumTextures]; pScene->mTextures = new aiTexture *[pScene->mNumTextures];
// to make sure we won't crash if we leave through an exception // to make sure we won't crash if we leave through an exception
::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures); ::memset(pScene->mTextures, 0, sizeof(void *) * pScene->mNumTextures);
for (unsigned int i = 0; i < pScene->mNumTextures; ++i) { for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {
aiTexture* tex = pScene->mTextures[i] = new aiTexture; aiTexture *tex = pScene->mTextures[i] = new aiTexture;
// skip the texture name // skip the texture name
while (stream.GetI1()); while (stream.GetI1())
;
// read texture width and height // read texture width and height
tex->mWidth = (unsigned int)stream.GetI4(); tex->mWidth = (unsigned int)stream.GetI4();
tex->mHeight = (unsigned int)stream.GetI4(); tex->mHeight = (unsigned int)stream.GetI4();
if (!tex->mWidth || !tex->mHeight) { if (!tex->mWidth || !tex->mHeight) {
@ -326,11 +307,10 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
} }
unsigned int mul = tex->mWidth * tex->mHeight; unsigned int mul = tex->mWidth * tex->mHeight;
aiTexel* begin = tex->pcData = new aiTexel[mul]; aiTexel *begin = tex->pcData = new aiTexel[mul];
aiTexel* const end = & begin[mul-1] +1; aiTexel *const end = &begin[mul - 1] + 1;
for (; begin != end; ++begin) {
for (;begin != end; ++begin) {
begin->r = stream.GetI1(); begin->r = stream.GetI1();
begin->g = stream.GetI1(); begin->g = stream.GetI1();
begin->b = stream.GetI1(); begin->b = stream.GetI1();
@ -341,68 +321,66 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
break; break;
// scene chunk // scene chunk
case 's': case 's': {
{ // skip position and rotation
// skip position and rotation stream.IncPtr(12);
stream.IncPtr(12);
for (unsigned int i = 0; i < 4;++i) for (unsigned int i = 0; i < 4; ++i)
for (unsigned int a = 0; a < 4;++a) for (unsigned int a = 0; a < 4; ++a)
pScene->mRootNode->mTransformation[i][a] = stream.GetF4(); pScene->mRootNode->mTransformation[i][a] = stream.GetF4();
stream.IncPtr(16); stream.IncPtr(16);
// now setup a single camera // now setup a single camera
pScene->mNumCameras = 1; pScene->mNumCameras = 1;
pScene->mCameras = new aiCamera*[1]; pScene->mCameras = new aiCamera *[1];
aiCamera* cam = pScene->mCameras[0] = new aiCamera(); aiCamera *cam = pScene->mCameras[0] = new aiCamera();
cam->mPosition.x = stream.GetF4(); cam->mPosition.x = stream.GetF4();
cam->mPosition.y = stream.GetF4(); cam->mPosition.y = stream.GetF4();
cam->mPosition.z = stream.GetF4(); cam->mPosition.z = stream.GetF4();
cam->mName.Set("Q3DCamera"); cam->mName.Set("Q3DCamera");
// skip eye rotation for the moment // skip eye rotation for the moment
stream.IncPtr(12); stream.IncPtr(12);
// read the default material color // read the default material color
fgColor .r = stream.GetF4(); fgColor.r = stream.GetF4();
fgColor .g = stream.GetF4(); fgColor.g = stream.GetF4();
fgColor .b = stream.GetF4(); fgColor.b = stream.GetF4();
// skip some unimportant properties // skip some unimportant properties
stream.IncPtr(29); stream.IncPtr(29);
// setup a single point light with no attenuation // setup a single point light with no attenuation
pScene->mNumLights = 1; pScene->mNumLights = 1;
pScene->mLights = new aiLight*[1]; pScene->mLights = new aiLight *[1];
aiLight* light = pScene->mLights[0] = new aiLight(); aiLight *light = pScene->mLights[0] = new aiLight();
light->mName.Set("Q3DLight"); light->mName.Set("Q3DLight");
light->mType = aiLightSource_POINT; light->mType = aiLightSource_POINT;
light->mAttenuationConstant = 1; light->mAttenuationConstant = 1;
light->mAttenuationLinear = 0; light->mAttenuationLinear = 0;
light->mAttenuationQuadratic = 0; light->mAttenuationQuadratic = 0;
light->mColorDiffuse.r = stream.GetF4(); light->mColorDiffuse.r = stream.GetF4();
light->mColorDiffuse.g = stream.GetF4(); light->mColorDiffuse.g = stream.GetF4();
light->mColorDiffuse.b = stream.GetF4(); light->mColorDiffuse.b = stream.GetF4();
light->mColorSpecular = light->mColorDiffuse; light->mColorSpecular = light->mColorDiffuse;
// We don't need the rest, but we need to know where this chunk ends.
unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4());
// We don't need the rest, but we need to know where this chunk ends. // skip the background file name
unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4()); while (stream.GetI1())
;
// skip the background file name // skip background texture data + the remaining fields
while (stream.GetI1()); stream.IncPtr(temp * 3 + 20); // 4 bytes of unknown data here
// skip background texture data + the remaining fields // TODO
stream.IncPtr(temp*3 + 20); // 4 bytes of unknown data here goto outer;
} break;
// TODO
goto outer;
}
break;
default: default:
throw DeadlyImportError("Quick3D: Unknown chunk"); throw DeadlyImportError("Quick3D: Unknown chunk");
@ -416,55 +394,50 @@ outer:
throw DeadlyImportError("Quick3D: No meshes loaded"); throw DeadlyImportError("Quick3D: No meshes loaded");
// If we have no materials loaded - generate a default mat // If we have no materials loaded - generate a default mat
if (materials.empty()) if (materials.empty()) {
{
ASSIMP_LOG_INFO("Quick3D: No material found, generating one"); ASSIMP_LOG_INFO("Quick3D: No material found, generating one");
materials.push_back(Material()); materials.push_back(Material());
materials.back().diffuse = fgColor ; materials.back().diffuse = fgColor;
} }
// find out which materials we'll need // find out which materials we'll need
typedef std::pair<unsigned int, unsigned int> FaceIdx; typedef std::pair<unsigned int, unsigned int> FaceIdx;
typedef std::vector< FaceIdx > FaceIdxArray; typedef std::vector<FaceIdx> FaceIdxArray;
FaceIdxArray* fidx = new FaceIdxArray[materials.size()]; FaceIdxArray *fidx = new FaceIdxArray[materials.size()];
unsigned int p = 0; unsigned int p = 0;
for (std::vector<Mesh>::iterator it = meshes.begin(), end = meshes.end(); for (std::vector<Mesh>::iterator it = meshes.begin(), end = meshes.end();
it != end; ++it,++p) it != end; ++it, ++p) {
{
unsigned int q = 0; unsigned int q = 0;
for (std::vector<Face>::iterator fit = (*it).faces.begin(), fend = (*it).faces.end(); for (std::vector<Face>::iterator fit = (*it).faces.begin(), fend = (*it).faces.end();
fit != fend; ++fit,++q) fit != fend; ++fit, ++q) {
{ if ((*fit).mat >= materials.size()) {
if ((*fit).mat >= materials.size())
{
ASSIMP_LOG_WARN("Quick3D: Material index overflow"); ASSIMP_LOG_WARN("Quick3D: Material index overflow");
(*fit).mat = 0; (*fit).mat = 0;
} }
if (fidx[(*fit).mat].empty())++pScene->mNumMeshes; if (fidx[(*fit).mat].empty()) ++pScene->mNumMeshes;
fidx[(*fit).mat].push_back( FaceIdx(p,q) ); fidx[(*fit).mat].push_back(FaceIdx(p, q));
} }
} }
pScene->mNumMaterials = pScene->mNumMeshes; pScene->mNumMaterials = pScene->mNumMeshes;
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
pScene->mMeshes = new aiMesh*[pScene->mNumMaterials]; pScene->mMeshes = new aiMesh *[pScene->mNumMaterials];
for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) {
{ if (fidx[i].empty()) continue;
if (fidx[i].empty())continue;
// Allocate a mesh and a material // Allocate a mesh and a material
aiMesh* mesh = pScene->mMeshes[real] = new aiMesh(); aiMesh *mesh = pScene->mMeshes[real] = new aiMesh();
aiMaterial* mat = new aiMaterial(); aiMaterial *mat = new aiMaterial();
pScene->mMaterials[real] = mat; pScene->mMaterials[real] = mat;
mesh->mMaterialIndex = real; mesh->mMaterialIndex = real;
// Build the output material // Build the output material
Material& srcMat = materials[i]; Material &srcMat = materials[i];
mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty(&srcMat.diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR); mat->AddProperty(&srcMat.specular, 1, AI_MATKEY_COLOR_SPECULAR);
mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT); mat->AddProperty(&srcMat.ambient, 1, AI_MATKEY_COLOR_AMBIENT);
// NOTE: Ignore transparency for the moment - it seems // NOTE: Ignore transparency for the moment - it seems
// unclear how to interpret the data // unclear how to interpret the data
@ -482,57 +455,48 @@ outer:
mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL); mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL);
if (srcMat.name.length) if (srcMat.name.length)
mat->AddProperty(&srcMat.name,AI_MATKEY_NAME); mat->AddProperty(&srcMat.name, AI_MATKEY_NAME);
// Add a texture // Add a texture
if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures) if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures) {
{
srcMat.name.data[0] = '*'; srcMat.name.data[0] = '*';
srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1],1000, srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1], 1000,
(srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real)); (srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real));
mat->AddProperty(&srcMat.name,AI_MATKEY_TEXTURE_DIFFUSE(0)); mat->AddProperty(&srcMat.name, AI_MATKEY_TEXTURE_DIFFUSE(0));
} }
mesh->mNumFaces = (unsigned int)fidx[i].size(); mesh->mNumFaces = (unsigned int)fidx[i].size();
aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; aiFace *faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
// Now build the output mesh. First find out how many // Now build the output mesh. First find out how many
// vertices we'll need // vertices we'll need
for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); for (FaceIdxArray::const_iterator it = fidx[i].begin(), end = fidx[i].end();
it != end; ++it) it != end; ++it) {
{ mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[(*it).second].indices.size();
mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[
(*it).second].indices.size();
} }
aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; aiVector3D *verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
aiVector3D* norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices]; aiVector3D *norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
aiVector3D* uv; aiVector3D *uv = nullptr;
if (real < pScene->mNumTextures) if (real < pScene->mNumTextures) {
{ uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; mesh->mNumUVComponents[0] = 2;
mesh->mNumUVComponents[0] = 2;
} }
else uv = NULL;
// Build the final array // Build the final array
unsigned int cnt = 0; unsigned int cnt = 0;
for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); for (FaceIdxArray::const_iterator it = fidx[i].begin(), end = fidx[i].end();
it != end; ++it, ++faces) it != end; ++it, ++faces) {
{ Mesh &curMesh = meshes[(*it).first];
Mesh& curMesh = meshes[(*it).first];
Face &face = curMesh.faces[(*it).second]; Face &face = curMesh.faces[(*it).second];
faces->mNumIndices = (unsigned int)face.indices.size(); faces->mNumIndices = (unsigned int)face.indices.size();
faces->mIndices = new unsigned int [faces->mNumIndices]; faces->mIndices = new unsigned int[faces->mNumIndices];
aiVector3D faceNormal; aiVector3D faceNormal;
bool fnOK = false; bool fnOK = false;
for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts) for (unsigned int n = 0; n < faces->mNumIndices; ++n, ++cnt, ++norms, ++verts) {
{ if (face.indices[n] >= curMesh.verts.size()) {
if (face.indices[n] >= curMesh.verts.size())
{
ASSIMP_LOG_WARN("Quick3D: Vertex index overflow"); ASSIMP_LOG_WARN("Quick3D: Vertex index overflow");
face.indices[n] = 0; face.indices[n] = 0;
} }
@ -540,11 +504,9 @@ outer:
// copy vertices // copy vertices
*verts = curMesh.verts[face.indices[n]]; *verts = curMesh.verts[face.indices[n]];
if (face.indices[n] >= curMesh.normals.size() && faces->mNumIndices >= 3) if (face.indices[n] >= curMesh.normals.size() && faces->mNumIndices >= 3) {
{
// we have no normal here - assign the face normal // we have no normal here - assign the face normal
if (!fnOK) if (!fnOK) {
{
const aiVector3D &pV1 = curMesh.verts[face.indices[0]]; const aiVector3D &pV1 = curMesh.verts[face.indices[0]];
const aiVector3D &pV2 = curMesh.verts[face.indices[1]]; const aiVector3D &pV2 = curMesh.verts[face.indices[1]];
const aiVector3D &pV3 = curMesh.verts[face.indices.size() - 1]; const aiVector3D &pV3 = curMesh.verts[face.indices.size() - 1];
@ -557,16 +519,12 @@ outer:
} }
// copy texture coordinates // copy texture coordinates
if (uv && curMesh.uv.size()) if (uv && curMesh.uv.size()) {
{
if (curMesh.prevUVIdx != 0xffffffff && curMesh.uv.size() >= curMesh.verts.size()) // workaround if (curMesh.prevUVIdx != 0xffffffff && curMesh.uv.size() >= curMesh.verts.size()) // workaround
{ {
*uv = curMesh.uv[face.indices[n]]; *uv = curMesh.uv[face.indices[n]];
} } else {
else if (face.uvindices[n] >= curMesh.uv.size()) {
{
if (face.uvindices[n] >= curMesh.uv.size())
{
ASSIMP_LOG_WARN("Quick3D: Texture coordinate index overflow"); ASSIMP_LOG_WARN("Quick3D: Texture coordinate index overflow");
face.uvindices[n] = 0; face.uvindices[n] = 0;
} }
@ -579,7 +537,6 @@ outer:
// setup the new vertex index // setup the new vertex index
faces->mIndices[n] = cnt; faces->mIndices[n] = cnt;
} }
} }
++real; ++real;
} }
@ -589,8 +546,8 @@ outer:
// Now we need to attach the meshes to the root node of the scene // Now we need to attach the meshes to the root node of the scene
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int [pScene->mNumMeshes]; pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) for (unsigned int i = 0; i < pScene->mNumMeshes; ++i)
pScene->mRootNode->mMeshes[i] = i; pScene->mRootNode->mMeshes[i] = i;
/*pScene->mRootNode->mTransformation *= aiMatrix4x4( /*pScene->mRootNode->mTransformation *= aiMatrix4x4(
@ -600,13 +557,12 @@ outer:
0.f, 0.f, 0.f, 1.f);*/ 0.f, 0.f, 0.f, 1.f);*/
// Add cameras and light sources to the scene root node // Add cameras and light sources to the scene root node
pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras; pScene->mRootNode->mNumChildren = pScene->mNumLights + pScene->mNumCameras;
if (pScene->mRootNode->mNumChildren) if (pScene->mRootNode->mNumChildren) {
{ pScene->mRootNode->mChildren = new aiNode *[pScene->mRootNode->mNumChildren];
pScene->mRootNode->mChildren = new aiNode* [ pScene->mRootNode->mNumChildren ];
// the light source // the light source
aiNode* nd = pScene->mRootNode->mChildren[0] = new aiNode(); aiNode *nd = pScene->mRootNode->mChildren[0] = new aiNode();
nd->mParent = pScene->mRootNode; nd->mParent = pScene->mRootNode;
nd->mName.Set("Q3DLight"); nd->mName.Set("Q3DLight");
nd->mTransformation = pScene->mRootNode->mTransformation; nd->mTransformation = pScene->mRootNode->mTransformation;

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -45,18 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the RAW importer class * @brief Implementation of the RAW importer class
*/ */
#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER #ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
// internal headers // internal headers
#include "RawLoader.h" #include "RawLoader.h"
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <memory>
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <memory>
using namespace Assimp; using namespace Assimp;
@ -75,146 +72,129 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
RAWImporter::RAWImporter() RAWImporter::RAWImporter() {
{} // empty
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
RAWImporter::~RAWImporter()
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool RAWImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
{
return SimpleExtensionCheck(pFile,"raw");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiImporterDesc* RAWImporter::GetInfo () const // Destructor, private as well
{ RAWImporter::~RAWImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool RAWImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(pFile, "raw");
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc *RAWImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void RAWImporter::InternReadFile( const std::string& pFile, void RAWImporter::InternReadFile(const std::string &pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene *pScene, IOSystem *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 // Check whether we can read from the file
if( file.get() == NULL) { if (file.get() == nullptr) {
throw DeadlyImportError( "Failed to open RAW file " + pFile + "."); throw DeadlyImportError("Failed to open RAW file " + pFile + ".");
} }
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer
// (terminate it with zero) // (terminate it with zero)
std::vector<char> mBuffer2; std::vector<char> mBuffer2;
TextFileToBuffer(file.get(),mBuffer2); TextFileToBuffer(file.get(), mBuffer2);
const char* buffer = &mBuffer2[0]; const char *buffer = &mBuffer2[0];
// list of groups loaded from the file // list of groups loaded from the file
std::vector< GroupInformation > outGroups(1,GroupInformation("<default>")); std::vector<GroupInformation> outGroups(1, GroupInformation("<default>"));
std::vector< GroupInformation >::iterator curGroup = outGroups.begin(); std::vector<GroupInformation>::iterator curGroup = outGroups.begin();
// now read all lines // now read all lines
char line[4096]; char line[4096];
while (GetNextLine(buffer,line)) while (GetNextLine(buffer, line)) {
{
// if the line starts with a non-numeric identifier, it marks // if the line starts with a non-numeric identifier, it marks
// the beginning of a new group // the beginning of a new group
const char* sz = line;SkipSpaces(&sz); const char *sz = line;
if (IsLineEnd(*sz))continue; SkipSpaces(&sz);
if (!IsNumeric(*sz)) if (IsLineEnd(*sz)) continue;
{ if (!IsNumeric(*sz)) {
const char* sz2 = sz; const char *sz2 = sz;
while (!IsSpaceOrNewLine(*sz2))++sz2; while (!IsSpaceOrNewLine(*sz2))
const unsigned int length = (unsigned int)(sz2-sz); ++sz2;
const unsigned int length = (unsigned int)(sz2 - sz);
// find an existing group with this name // find an existing group with this name
for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); for (std::vector<GroupInformation>::iterator it = outGroups.begin(), end = outGroups.end();
it != end;++it) it != end; ++it) {
{ if (length == (*it).name.length() && !::strcmp(sz, (*it).name.c_str())) {
if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str())) curGroup = it;
{ sz2 = nullptr;
curGroup = it;sz2 = NULL;
break; break;
} }
} }
if (sz2) if (sz2) {
{ outGroups.push_back(GroupInformation(std::string(sz, length)));
outGroups.push_back(GroupInformation(std::string(sz,length))); curGroup = outGroups.end() - 1;
curGroup = outGroups.end()-1;
} }
} } else {
else
{
// there can be maximally 12 floats plus an extra texture file name // there can be maximally 12 floats plus an extra texture file name
float data[12]; float data[12];
unsigned int num; unsigned int num;
for (num = 0; num < 12;++num) for (num = 0; num < 12; ++num) {
{ if (!SkipSpaces(&sz) || !IsNumeric(*sz)) break;
if(!SkipSpaces(&sz) || !IsNumeric(*sz))break; sz = fast_atoreal_move<float>(sz, data[num]);
sz = fast_atoreal_move<float>(sz,data[num]);
} }
if (num != 12 && num != 9) if (num != 12 && num != 9) {
{
ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture"); ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture");
continue; continue;
} }
MeshInformation* output = NULL; MeshInformation *output = nullptr;
const char* sz2 = sz; const char *sz2 = sz;
unsigned int length; unsigned int length;
if (!IsLineEnd(*sz)) if (!IsLineEnd(*sz)) {
{ while (!IsSpaceOrNewLine(*sz2))
while (!IsSpaceOrNewLine(*sz2))++sz2; ++sz2;
length = (unsigned int)(sz2-sz); length = (unsigned int)(sz2 - sz);
} } else if (9 == num) {
else if (9 == num)
{
sz = "%default%"; sz = "%default%";
length = 9; length = 9;
} } else {
else
{
sz = ""; sz = "";
length = 0; length = 0;
} }
// search in the list of meshes whether we have one with this texture // search in the list of meshes whether we have one with this texture
for (auto &mesh : (*curGroup).meshes) for (auto &mesh : (*curGroup).meshes) {
{ if (length == mesh.name.length() && (length ? !::strcmp(sz, mesh.name.c_str()) : true)) {
if (length == mesh.name.length() && (length ? !::strcmp(sz, mesh.name.c_str()) : true))
{
output = &mesh; output = &mesh;
break; break;
} }
} }
// if we don't have the mesh, create it // if we don't have the mesh, create it
if (!output) if (!output) {
{ (*curGroup).meshes.push_back(MeshInformation(std::string(sz, length)));
(*curGroup).meshes.push_back(MeshInformation(std::string(sz,length)));
output = &((*curGroup).meshes.back()); output = &((*curGroup).meshes.back());
} }
if (12 == num) if (12 == num) {
{ aiColor4D v(data[0], data[1], data[2], 1.0f);
aiColor4D v(data[0],data[1],data[2],1.0f);
output->colors.push_back(v); output->colors.push_back(v);
output->colors.push_back(v); output->colors.push_back(v);
output->colors.push_back(v); output->colors.push_back(v);
output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); output->vertices.push_back(aiVector3D(data[3], data[4], data[5]));
output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); output->vertices.push_back(aiVector3D(data[6], data[7], data[8]));
output->vertices.push_back(aiVector3D(data[9],data[10],data[11])); output->vertices.push_back(aiVector3D(data[9], data[10], data[11]));
} } else {
else output->vertices.push_back(aiVector3D(data[0], data[1], data[2]));
{ output->vertices.push_back(aiVector3D(data[3], data[4], data[5]));
output->vertices.push_back(aiVector3D(data[0],data[1],data[2])); output->vertices.push_back(aiVector3D(data[6], data[7], data[8]));
output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
} }
} }
} }
@ -224,105 +204,96 @@ void RAWImporter::InternReadFile( const std::string& pFile,
// count the number of valid groups // count the number of valid groups
// (meshes can't be empty) // (meshes can't be empty)
for (auto & outGroup : outGroups) for (auto &outGroup : outGroups) {
{ if (!outGroup.meshes.empty()) {
if (!outGroup.meshes.empty())
{
++pScene->mRootNode->mNumChildren; ++pScene->mRootNode->mNumChildren;
pScene->mNumMeshes += (unsigned int) outGroup.meshes.size(); pScene->mNumMeshes += (unsigned int)outGroup.meshes.size();
} }
} }
if (!pScene->mNumMeshes) if (!pScene->mNumMeshes) {
{
throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty."); throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty.");
} }
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
aiNode** cc; aiNode **cc;
if (1 == pScene->mRootNode->mNumChildren) if (1 == pScene->mRootNode->mNumChildren) {
{
cc = &pScene->mRootNode; cc = &pScene->mRootNode;
pScene->mRootNode->mNumChildren = 0; pScene->mRootNode->mNumChildren = 0;
} else { } else {
cc = new aiNode*[pScene->mRootNode->mNumChildren]; cc = new aiNode *[pScene->mRootNode->mNumChildren];
memset(cc, 0, sizeof(aiNode*) * pScene->mRootNode->mNumChildren); memset(cc, 0, sizeof(aiNode *) * pScene->mRootNode->mNumChildren);
pScene->mRootNode->mChildren = cc; pScene->mRootNode->mChildren = cc;
} }
pScene->mNumMaterials = pScene->mNumMeshes; pScene->mNumMaterials = pScene->mNumMeshes;
aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; aiMaterial **mats = pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
unsigned int meshIdx = 0; unsigned int meshIdx = 0;
for (auto & outGroup : outGroups) for (auto &outGroup : outGroups) {
{ if (outGroup.meshes.empty()) continue;
if (outGroup.meshes.empty())continue;
aiNode* node; aiNode *node;
if (pScene->mRootNode->mNumChildren) if (pScene->mRootNode->mNumChildren) {
{
node = *cc = new aiNode(); node = *cc = new aiNode();
node->mParent = pScene->mRootNode; node->mParent = pScene->mRootNode;
} } else
else node = *cc; node = *cc;
node->mName.Set(outGroup.name); node->mName.Set(outGroup.name);
// add all meshes // add all meshes
node->mNumMeshes = (unsigned int) outGroup.meshes.size(); node->mNumMeshes = (unsigned int)outGroup.meshes.size();
unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ]; unsigned int *pi = node->mMeshes = new unsigned int[node->mNumMeshes];
for (std::vector< MeshInformation >::iterator it2 = outGroup.meshes.begin(), for (std::vector<MeshInformation>::iterator it2 = outGroup.meshes.begin(),
end2 = outGroup.meshes.end(); it2 != end2; ++it2) end2 = outGroup.meshes.end();
{ it2 != end2; ++it2) {
ai_assert(!(*it2).vertices.empty()); ai_assert(!(*it2).vertices.empty());
// allocate the mesh // allocate the mesh
*pi++ = meshIdx; *pi++ = meshIdx;
aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh(); aiMesh *mesh = pScene->mMeshes[meshIdx] = new aiMesh();
mesh->mMaterialIndex = meshIdx++; mesh->mMaterialIndex = meshIdx++;
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
// allocate storage for the vertex components and copy them // allocate storage for the vertex components and copy them
mesh->mNumVertices = (unsigned int)(*it2).vertices.size(); mesh->mNumVertices = (unsigned int)(*it2).vertices.size();
mesh->mVertices = new aiVector3D[ mesh->mNumVertices ]; mesh->mVertices = new aiVector3D[mesh->mNumVertices];
::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices); ::memcpy(mesh->mVertices, &(*it2).vertices[0], sizeof(aiVector3D) * mesh->mNumVertices);
if ((*it2).colors.size()) if ((*it2).colors.size()) {
{
ai_assert((*it2).colors.size() == mesh->mNumVertices); ai_assert((*it2).colors.size() == mesh->mNumVertices);
mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ]; mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices); ::memcpy(mesh->mColors[0], &(*it2).colors[0], sizeof(aiColor4D) * mesh->mNumVertices);
} }
// generate triangles // generate triangles
ai_assert(0 == mesh->mNumVertices % 3); ai_assert(0 == mesh->mNumVertices % 3);
aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ]; aiFace *fc = mesh->mFaces = new aiFace[mesh->mNumFaces = mesh->mNumVertices / 3];
aiFace* const fcEnd = fc + mesh->mNumFaces; aiFace *const fcEnd = fc + mesh->mNumFaces;
unsigned int n = 0; unsigned int n = 0;
while (fc != fcEnd) while (fc != fcEnd) {
{ aiFace &f = *fc++;
aiFace& f = *fc++;
f.mIndices = new unsigned int[f.mNumIndices = 3]; f.mIndices = new unsigned int[f.mNumIndices = 3];
for (unsigned int m = 0; m < 3;++m) for (unsigned int m = 0; m < 3; ++m)
f.mIndices[m] = n++; f.mIndices[m] = n++;
} }
// generate a material for the mesh // generate a material for the mesh
aiMaterial* mat = new aiMaterial(); aiMaterial *mat = new aiMaterial();
aiColor4D clr(1.0f,1.0f,1.0f,1.0f); aiColor4D clr(1.0f, 1.0f, 1.0f, 1.0f);
if ("%default%" == (*it2).name) // a gray default material if ("%default%" == (*it2).name) // a gray default material
{ {
clr.r = clr.g = clr.b = 0.6f; clr.r = clr.g = clr.b = 0.6f;
} } else if ((*it2).name.length() > 0) // a texture
else if ((*it2).name.length() > 0) // a texture
{ {
aiString s; aiString s;
s.Set((*it2).name); s.Set((*it2).name);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); mat->AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
} }
mat->AddProperty<aiColor4D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty<aiColor4D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
*mats++ = mat; *mats++ = mat;
} }
} }

View File

@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Nevertheless, this implementation is reasonably complete. * Nevertheless, this implementation is reasonably complete.
*/ */
#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER #ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
// internal headers // internal headers
@ -60,15 +59,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StreamReader.h> #include <assimp/StreamReader.h>
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>
#ifdef ASSIMP_USE_HUNTER #ifdef ASSIMP_USE_HUNTER
# include <utf8/utf8.h> #include <utf8/utf8.h>
#else #else
//# include "../contrib/ConvertUTF/ConvertUTF.h" //# include "../contrib/ConvertUTF/ConvertUTF.h"
# include "../contrib/utf8cpp/source/utf8.h" #include "../contrib/utf8cpp/source/utf8.h"
#endif #endif
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <map> #include <map>
@ -86,14 +85,14 @@ static const aiImporterDesc desc = {
}; };
struct SIBChunk { struct SIBChunk {
uint32_t Tag; uint32_t Tag;
uint32_t Size; uint32_t Size;
} PACK_STRUCT; } PACK_STRUCT;
enum { enum {
POS, POS,
NRM, NRM,
UV, UV,
N N
}; };
@ -122,14 +121,14 @@ struct SIBObject {
}; };
struct SIB { struct SIB {
std::vector<aiMaterial*> mtls; std::vector<aiMaterial *> mtls;
std::vector<aiMesh*> meshes; std::vector<aiMesh *> meshes;
std::vector<aiLight*> lights; std::vector<aiLight *> lights;
std::vector<SIBObject> objs, insts; std::vector<SIBObject> objs, insts;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB) { static SIBEdge &GetEdge(SIBMesh *mesh, uint32_t posA, uint32_t posB) {
SIBPair pair = (posA < posB) ? SIBPair(posA, posB) : SIBPair(posB, posA); SIBPair pair = (posA < posB) ? SIBPair(posA, posB) : SIBPair(posB, posA);
std::map<SIBPair, uint32_t>::iterator it = mesh->edgeMap.find(pair); std::map<SIBPair, uint32_t>::iterator it = mesh->edgeMap.find(pair);
if (it != mesh->edgeMap.end()) if (it != mesh->edgeMap.end())
@ -146,10 +145,9 @@ static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Helpers for reading chunked data. // Helpers for reading chunked data.
#define TAG(A,B,C,D) ((A << 24) | (B << 16) | (C << 8) | D) #define TAG(A, B, C, D) ((A << 24) | (B << 16) | (C << 8) | D)
static SIBChunk ReadChunk(StreamReaderLE* stream) static SIBChunk ReadChunk(StreamReaderLE *stream) {
{
SIBChunk chunk; SIBChunk chunk;
chunk.Tag = stream->GetU4(); chunk.Tag = stream->GetU4();
chunk.Size = stream->GetU4(); chunk.Size = stream->GetU4();
@ -159,8 +157,7 @@ static SIBChunk ReadChunk(StreamReaderLE* stream)
return chunk; return chunk;
} }
static aiColor3D ReadColor(StreamReaderLE* stream) static aiColor3D ReadColor(StreamReaderLE *stream) {
{
float r = stream->GetF4(); float r = stream->GetF4();
float g = stream->GetF4(); float g = stream->GetF4();
float b = stream->GetF4(); float b = stream->GetF4();
@ -168,37 +165,36 @@ static aiColor3D ReadColor(StreamReaderLE* stream)
return aiColor3D(r, g, b); return aiColor3D(r, g, b);
} }
static void UnknownChunk(StreamReaderLE* /*stream*/, const SIBChunk& chunk) static void UnknownChunk(StreamReaderLE * /*stream*/, const SIBChunk &chunk) {
{
char temp[5] = { char temp[5] = {
static_cast<char>(( chunk.Tag>>24 ) & 0xff), static_cast<char>((chunk.Tag >> 24) & 0xff),
static_cast<char>(( chunk.Tag>>16 ) & 0xff), static_cast<char>((chunk.Tag >> 16) & 0xff),
static_cast<char>(( chunk.Tag>>8 ) & 0xff), static_cast<char>((chunk.Tag >> 8) & 0xff),
static_cast<char>(chunk.Tag & 0xff), '\0' static_cast<char>(chunk.Tag & 0xff), '\0'
}; };
ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '",temp,"' chunk.")); ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '", temp, "' chunk."));
} }
// Reads a UTF-16LE string and returns it at UTF-8. // Reads a UTF-16LE string and returns it at UTF-8.
static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) { static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) {
if ( nullptr == stream || 0 == numWChars ) { if (nullptr == stream || 0 == numWChars) {
static const aiString empty; static const aiString empty;
return empty; return empty;
} }
// Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8) // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8)
std::vector<unsigned char> str; std::vector<unsigned char> str;
str.reserve( numWChars * 4 + 1 ); str.reserve(numWChars * 4 + 1);
uint16_t *temp = new uint16_t[ numWChars ]; uint16_t *temp = new uint16_t[numWChars];
for ( uint32_t n = 0; n < numWChars; ++n ) { for (uint32_t n = 0; n < numWChars; ++n) {
temp[ n ] = stream->GetU2(); temp[n] = stream->GetU2();
} }
// Convert it and NUL-terminate. // Convert it and NUL-terminate.
const uint16_t *start( temp ), *end( temp + numWChars ); const uint16_t *start(temp), *end(temp + numWChars);
utf8::utf16to8( start, end, back_inserter( str ) ); utf8::utf16to8(start, end, back_inserter(str));
str[ str.size() - 1 ] = '\0'; str[str.size() - 1] = '\0';
// Return the final string. // Return the final string.
aiString result = aiString((const char *)&str[0]); aiString result = aiString((const char *)&str[0]);
@ -221,52 +217,49 @@ SIBImporter::~SIBImporter() {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const { bool SIBImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(pFile, "sib"); return SimpleExtensionCheck(pFile, "sib");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiImporterDesc* SIBImporter::GetInfo () const { const aiImporterDesc *SIBImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count) { static void ReadVerts(SIBMesh *mesh, StreamReaderLE *stream, uint32_t count) {
if ( nullptr == mesh || nullptr == stream ) { if (nullptr == mesh || nullptr == stream) {
return; return;
} }
mesh->pos.resize(count); mesh->pos.resize(count);
for ( uint32_t n=0; n<count; ++n ) { for (uint32_t n = 0; n < count; ++n) {
mesh->pos[ n ].x = stream->GetF4(); mesh->pos[n].x = stream->GetF4();
mesh->pos[ n ].y = stream->GetF4(); mesh->pos[n].y = stream->GetF4();
mesh->pos[ n ].z = stream->GetF4(); mesh->pos[n].z = stream->GetF4();
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadFaces(SIBMesh* mesh, StreamReaderLE* stream) static void ReadFaces(SIBMesh *mesh, StreamReaderLE *stream) {
{
uint32_t ptIdx = 0; uint32_t ptIdx = 0;
while (stream->GetRemainingSizeToLimit() > 0) while (stream->GetRemainingSizeToLimit() > 0) {
{
uint32_t numPoints = stream->GetU4(); uint32_t numPoints = stream->GetU4();
// Store room for the N index channels, plus the point count. // Store room for the N index channels, plus the point count.
size_t pos = mesh->idx.size() + 1; size_t pos = mesh->idx.size() + 1;
mesh->idx.resize(pos + numPoints*N); mesh->idx.resize(pos + numPoints * N);
mesh->idx[pos-1] = numPoints; mesh->idx[pos - 1] = numPoints;
uint32_t *idx = &mesh->idx[pos]; uint32_t *idx = &mesh->idx[pos];
mesh->faceStart.push_back(static_cast<uint32_t>(pos-1)); mesh->faceStart.push_back(static_cast<uint32_t>(pos - 1));
mesh->mtls.push_back(0); mesh->mtls.push_back(0);
// Read all the position data. // Read all the position data.
// UV/normals will be supplied later. // UV/normals will be supplied later.
// Positions are supplied indexed already, so we preserve that // Positions are supplied indexed already, so we preserve that
// mapping. UVs are supplied uniquely, so we allocate unique indices. // mapping. UVs are supplied uniquely, so we allocate unique indices.
for (uint32_t n=0;n<numPoints;n++,idx+=N,ptIdx++) for (uint32_t n = 0; n < numPoints; n++, idx += N, ptIdx++) {
{
uint32_t p = stream->GetU4(); uint32_t p = stream->GetU4();
if (p >= mesh->pos.size()) if (p >= mesh->pos.size())
throw DeadlyImportError("Vertex index is out of range."); throw DeadlyImportError("Vertex index is out of range.");
@ -277,17 +270,15 @@ static void ReadFaces(SIBMesh* mesh, StreamReaderLE* stream)
} }
// Allocate data channels for normals/UVs. // Allocate data channels for normals/UVs.
mesh->nrm.resize(ptIdx, aiVector3D(0,0,0)); mesh->nrm.resize(ptIdx, aiVector3D(0, 0, 0));
mesh->uv.resize(ptIdx, aiVector3D(0,0,0)); mesh->uv.resize(ptIdx, aiVector3D(0, 0, 0));
mesh->numPts = ptIdx; mesh->numPts = ptIdx;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadUVs(SIBMesh* mesh, StreamReaderLE* stream) static void ReadUVs(SIBMesh *mesh, StreamReaderLE *stream) {
{ while (stream->GetRemainingSizeToLimit() > 0) {
while (stream->GetRemainingSizeToLimit() > 0)
{
uint32_t faceIdx = stream->GetU4(); uint32_t faceIdx = stream->GetU4();
uint32_t numPoints = stream->GetU4(); uint32_t numPoints = stream->GetU4();
@ -297,8 +288,7 @@ static void ReadUVs(SIBMesh* mesh, StreamReaderLE* stream)
uint32_t pos = mesh->faceStart[faceIdx]; uint32_t pos = mesh->faceStart[faceIdx];
uint32_t *idx = &mesh->idx[pos + 1]; uint32_t *idx = &mesh->idx[pos + 1];
for (uint32_t n=0;n<numPoints;n++,idx+=N) for (uint32_t n = 0; n < numPoints; n++, idx += N) {
{
uint32_t id = idx[UV]; uint32_t id = idx[UV];
mesh->uv[id].x = stream->GetF4(); mesh->uv[id].x = stream->GetF4();
mesh->uv[id].y = stream->GetF4(); mesh->uv[id].y = stream->GetF4();
@ -307,19 +297,16 @@ static void ReadUVs(SIBMesh* mesh, StreamReaderLE* stream)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadMtls(SIBMesh* mesh, StreamReaderLE* stream) static void ReadMtls(SIBMesh *mesh, StreamReaderLE *stream) {
{
// Material assignments are stored run-length encoded. // Material assignments are stored run-length encoded.
// Also, we add 1 to each material so that we can use mtl #0 // Also, we add 1 to each material so that we can use mtl #0
// as the default material. // as the default material.
uint32_t prevFace = stream->GetU4(); uint32_t prevFace = stream->GetU4();
uint32_t prevMtl = stream->GetU4() + 1; uint32_t prevMtl = stream->GetU4() + 1;
while (stream->GetRemainingSizeToLimit() > 0) while (stream->GetRemainingSizeToLimit() > 0) {
{
uint32_t face = stream->GetU4(); uint32_t face = stream->GetU4();
uint32_t mtl = stream->GetU4() + 1; uint32_t mtl = stream->GetU4() + 1;
while (prevFace < face) while (prevFace < face) {
{
if (prevFace >= mesh->mtls.size()) if (prevFace >= mesh->mtls.size())
throw DeadlyImportError("Invalid face index."); throw DeadlyImportError("Invalid face index.");
mesh->mtls[prevFace++] = prevMtl; mesh->mtls[prevFace++] = prevMtl;
@ -334,8 +321,7 @@ static void ReadMtls(SIBMesh* mesh, StreamReaderLE* stream)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadAxis(aiMatrix4x4& axis, StreamReaderLE* stream) static void ReadAxis(aiMatrix4x4 &axis, StreamReaderLE *stream) {
{
axis.a4 = stream->GetF4(); axis.a4 = stream->GetF4();
axis.b4 = stream->GetF4(); axis.b4 = stream->GetF4();
axis.c4 = stream->GetF4(); axis.c4 = stream->GetF4();
@ -355,10 +341,8 @@ static void ReadAxis(aiMatrix4x4& axis, StreamReaderLE* stream)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadEdges(SIBMesh* mesh, StreamReaderLE* stream) static void ReadEdges(SIBMesh *mesh, StreamReaderLE *stream) {
{ while (stream->GetRemainingSizeToLimit() > 0) {
while (stream->GetRemainingSizeToLimit() > 0)
{
uint32_t posA = stream->GetU4(); uint32_t posA = stream->GetU4();
uint32_t posB = stream->GetU4(); uint32_t posB = stream->GetU4();
GetEdge(mesh, posA, posB); GetEdge(mesh, posA, posB);
@ -366,10 +350,8 @@ static void ReadEdges(SIBMesh* mesh, StreamReaderLE* stream)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadCreases(SIBMesh* mesh, StreamReaderLE* stream) static void ReadCreases(SIBMesh *mesh, StreamReaderLE *stream) {
{ while (stream->GetRemainingSizeToLimit() > 0) {
while (stream->GetRemainingSizeToLimit() > 0)
{
uint32_t edge = stream->GetU4(); uint32_t edge = stream->GetU4();
if (edge >= mesh->edges.size()) if (edge >= mesh->edges.size())
throw DeadlyImportError("SIB: Invalid edge index."); throw DeadlyImportError("SIB: Invalid edge index.");
@ -378,22 +360,19 @@ static void ReadCreases(SIBMesh* mesh, StreamReaderLE* stream)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ConnectFaces(SIBMesh* mesh) static void ConnectFaces(SIBMesh *mesh) {
{
// Find faces connected to each edge. // Find faces connected to each edge.
size_t numFaces = mesh->faceStart.size(); size_t numFaces = mesh->faceStart.size();
for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++) for (size_t faceIdx = 0; faceIdx < numFaces; faceIdx++) {
{
uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]]; uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]];
uint32_t numPoints = *idx++; uint32_t numPoints = *idx++;
uint32_t prev = idx[(numPoints-1)*N+POS]; uint32_t prev = idx[(numPoints - 1) * N + POS];
for (uint32_t i=0;i<numPoints;i++,idx+=N) for (uint32_t i = 0; i < numPoints; i++, idx += N) {
{
uint32_t next = idx[POS]; uint32_t next = idx[POS];
// Find this edge. // Find this edge.
SIBEdge& edge = GetEdge(mesh, prev, next); SIBEdge &edge = GetEdge(mesh, prev, next);
// Link this face onto it. // Link this face onto it.
// This gives potentially undesirable normals when used // This gives potentially undesirable normals when used
@ -409,45 +388,39 @@ static void ConnectFaces(SIBMesh* mesh)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static aiVector3D CalculateVertexNormal(SIBMesh* mesh, uint32_t faceIdx, uint32_t pos, static aiVector3D CalculateVertexNormal(SIBMesh *mesh, uint32_t faceIdx, uint32_t pos,
const std::vector<aiVector3D>& faceNormals) const std::vector<aiVector3D> &faceNormals) {
{
// Creased edges complicate this. We need to find the start/end range of the // Creased edges complicate this. We need to find the start/end range of the
// ring of faces that touch this position. // ring of faces that touch this position.
// We do this in two passes. The first pass is to find the end of the range, // We do this in two passes. The first pass is to find the end of the range,
// the second is to work backwards to the start and calculate the final normal. // the second is to work backwards to the start and calculate the final normal.
aiVector3D vtxNormal; aiVector3D vtxNormal;
for (int pass=0;pass<2;pass++) for (int pass = 0; pass < 2; pass++) {
{
vtxNormal = aiVector3D(0, 0, 0); vtxNormal = aiVector3D(0, 0, 0);
uint32_t startFaceIdx = faceIdx; uint32_t startFaceIdx = faceIdx;
uint32_t prevFaceIdx = faceIdx; uint32_t prevFaceIdx = faceIdx;
// Process each connected face. // Process each connected face.
while (true) while (true) {
{
// Accumulate the face normal. // Accumulate the face normal.
vtxNormal += faceNormals[faceIdx]; vtxNormal += faceNormals[faceIdx];
uint32_t nextFaceIdx = 0xffffffff; uint32_t nextFaceIdx = 0xffffffff;
// Move to the next edge sharing this position. // Move to the next edge sharing this position.
uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]]; uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]];
uint32_t numPoints = *idx++; uint32_t numPoints = *idx++;
uint32_t posA = idx[(numPoints-1)*N+POS]; uint32_t posA = idx[(numPoints - 1) * N + POS];
for (uint32_t n=0;n<numPoints;n++,idx+=N) for (uint32_t n = 0; n < numPoints; n++, idx += N) {
{
uint32_t posB = idx[POS]; uint32_t posB = idx[POS];
// Test if this edge shares our target position. // Test if this edge shares our target position.
if (posA == pos || posB == pos) if (posA == pos || posB == pos) {
{ SIBEdge &edge = GetEdge(mesh, posA, posB);
SIBEdge& edge = GetEdge(mesh, posA, posB);
// Non-manifold meshes can produce faces which share // Non-manifold meshes can produce faces which share
// positions but have no edge entry, so check it. // positions but have no edge entry, so check it.
if (edge.faceA == faceIdx || edge.faceB == faceIdx) if (edge.faceA == faceIdx || edge.faceB == faceIdx) {
{
// Move to whichever side we didn't just come from. // Move to whichever side we didn't just come from.
if (!edge.creased) { if (!edge.creased) {
if (edge.faceA != prevFaceIdx && edge.faceA != faceIdx && edge.faceA != 0xffffffff) if (edge.faceA != prevFaceIdx && edge.faceA != faceIdx && edge.faceA != 0xffffffff)
@ -479,24 +452,21 @@ static aiVector3D CalculateVertexNormal(SIBMesh* mesh, uint32_t faceIdx, uint32_
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void CalculateNormals(SIBMesh* mesh) static void CalculateNormals(SIBMesh *mesh) {
{
size_t numFaces = mesh->faceStart.size(); size_t numFaces = mesh->faceStart.size();
// Calculate face normals. // Calculate face normals.
std::vector<aiVector3D> faceNormals(numFaces); std::vector<aiVector3D> faceNormals(numFaces);
for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++) for (size_t faceIdx = 0; faceIdx < numFaces; faceIdx++) {
{ uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]];
uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]];
uint32_t numPoints = *idx++; uint32_t numPoints = *idx++;
aiVector3D faceNormal(0, 0, 0); aiVector3D faceNormal(0, 0, 0);
uint32_t *prev = &idx[(numPoints-1)*N]; uint32_t *prev = &idx[(numPoints - 1) * N];
for (uint32_t i=0;i<numPoints;i++) for (uint32_t i = 0; i < numPoints; i++) {
{ uint32_t *next = &idx[i * N];
uint32_t *next = &idx[i*N];
faceNormal += mesh->pos[prev[POS]] ^ mesh->pos[next[POS]]; faceNormal += mesh->pos[prev[POS]] ^ mesh->pos[next[POS]];
prev = next; prev = next;
@ -506,15 +476,13 @@ static void CalculateNormals(SIBMesh* mesh)
} }
// Calculate vertex normals. // Calculate vertex normals.
for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++) for (size_t faceIdx = 0; faceIdx < numFaces; faceIdx++) {
{ uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]];
uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]];
uint32_t numPoints = *idx++; uint32_t numPoints = *idx++;
for (uint32_t i=0;i<numPoints;i++) for (uint32_t i = 0; i < numPoints; i++) {
{ uint32_t pos = idx[i * N + POS];
uint32_t pos = idx[i*N+POS]; uint32_t nrm = idx[i * N + NRM];
uint32_t nrm = idx[i*N+NRM];
aiVector3D vtxNorm = CalculateVertexNormal(mesh, static_cast<uint32_t>(faceIdx), pos, faceNormals); aiVector3D vtxNorm = CalculateVertexNormal(mesh, static_cast<uint32_t>(faceIdx), pos, faceNormals);
mesh->nrm[nrm] = vtxNorm; mesh->nrm[nrm] = vtxNorm;
} }
@ -522,43 +490,39 @@ static void CalculateNormals(SIBMesh* mesh)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
struct TempMesh struct TempMesh {
{
std::vector<aiVector3D> vtx; std::vector<aiVector3D> vtx;
std::vector<aiVector3D> nrm; std::vector<aiVector3D> nrm;
std::vector<aiVector3D> uv; std::vector<aiVector3D> uv;
std::vector<aiFace> faces; std::vector<aiFace> faces;
}; };
static void ReadShape(SIB* sib, StreamReaderLE* stream) static void ReadShape(SIB *sib, StreamReaderLE *stream) {
{
SIBMesh smesh; SIBMesh smesh;
aiString name; aiString name;
while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) {
{
SIBChunk chunk = ReadChunk(stream); SIBChunk chunk = ReadChunk(stream);
unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size); unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
switch (chunk.Tag) switch (chunk.Tag) {
{ case TAG('M', 'I', 'R', 'P'): break; // mirror plane maybe?
case TAG('M','I','R','P'): break; // mirror plane maybe? case TAG('I', 'M', 'R', 'P'): break; // instance mirror? (not supported here yet)
case TAG('I','M','R','P'): break; // instance mirror? (not supported here yet) case TAG('D', 'I', 'N', 'F'): break; // display info, not needed
case TAG('D','I','N','F'): break; // display info, not needed case TAG('P', 'I', 'N', 'F'): break; // ?
case TAG('P','I','N','F'): break; // ? case TAG('V', 'M', 'I', 'R'): break; // ?
case TAG('V','M','I','R'): break; // ? case TAG('F', 'M', 'I', 'R'): break; // ?
case TAG('F','M','I','R'): break; // ? case TAG('T', 'X', 'S', 'M'): break; // ?
case TAG('T','X','S','M'): break; // ? case TAG('F', 'A', 'H', 'S'): break; // ?
case TAG('F','A','H','S'): break; // ? case TAG('V', 'R', 'T', 'S'): ReadVerts(&smesh, stream, chunk.Size / 12); break;
case TAG('V','R','T','S'): ReadVerts(&smesh, stream, chunk.Size/12); break; case TAG('F', 'A', 'C', 'S'): ReadFaces(&smesh, stream); break;
case TAG('F','A','C','S'): ReadFaces(&smesh, stream); break; case TAG('F', 'T', 'V', 'S'): ReadUVs(&smesh, stream); break;
case TAG('F','T','V','S'): ReadUVs(&smesh, stream); break; case TAG('S', 'N', 'A', 'M'): name = ReadString(stream, chunk.Size / 2); break;
case TAG('S','N','A','M'): name = ReadString(stream, chunk.Size/2); break; case TAG('F', 'A', 'M', 'A'): ReadMtls(&smesh, stream); break;
case TAG('F','A','M','A'): ReadMtls(&smesh, stream); break; case TAG('A', 'X', 'I', 'S'): ReadAxis(smesh.axis, stream); break;
case TAG('A','X','I','S'): ReadAxis(smesh.axis, stream); break; case TAG('E', 'D', 'G', 'S'): ReadEdges(&smesh, stream); break;
case TAG('E','D','G','S'): ReadEdges(&smesh, stream); break; case TAG('E', 'C', 'R', 'S'): ReadCreases(&smesh, stream); break;
case TAG('E','C','R','S'): ReadCreases(&smesh, stream); break; default: UnknownChunk(stream, chunk); break;
default: UnknownChunk(stream, chunk); break;
} }
stream->SetCurrentPos(stream->GetReadLimit()); stream->SetCurrentPos(stream->GetReadLimit());
@ -585,25 +549,22 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
std::vector<TempMesh> meshes(sib->mtls.size()); std::vector<TempMesh> meshes(sib->mtls.size());
// Un-index the source data and apply to each vertex. // Un-index the source data and apply to each vertex.
for (unsigned fi=0;fi<smesh.faceStart.size();fi++) for (unsigned fi = 0; fi < smesh.faceStart.size(); fi++) {
{
uint32_t start = smesh.faceStart[fi]; uint32_t start = smesh.faceStart[fi];
uint32_t mtl = smesh.mtls[fi]; uint32_t mtl = smesh.mtls[fi];
uint32_t *idx = &smesh.idx[start]; uint32_t *idx = &smesh.idx[start];
if (mtl >= meshes.size()) if (mtl >= meshes.size()) {
{
ASSIMP_LOG_ERROR("SIB: Face material index is invalid."); ASSIMP_LOG_ERROR("SIB: Face material index is invalid.");
mtl = 0; mtl = 0;
} }
TempMesh& dest = meshes[mtl]; TempMesh &dest = meshes[mtl];
aiFace face; aiFace face;
face.mNumIndices = *idx++; face.mNumIndices = *idx++;
face.mIndices = new unsigned[face.mNumIndices]; face.mIndices = new unsigned[face.mNumIndices];
for (unsigned pt=0;pt<face.mNumIndices;pt++,idx+=N) for (unsigned pt = 0; pt < face.mNumIndices; pt++, idx += N) {
{
size_t vtxIdx = dest.vtx.size(); size_t vtxIdx = dest.vtx.size();
face.mIndices[pt] = static_cast<unsigned int>(vtxIdx); face.mIndices[pt] = static_cast<unsigned int>(vtxIdx);
@ -611,7 +572,7 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
// we did it when creating the data. // we did it when creating the data.
aiVector3D pos = smesh.pos[idx[POS]]; aiVector3D pos = smesh.pos[idx[POS]];
aiVector3D nrm = smesh.nrm[idx[NRM]]; aiVector3D nrm = smesh.nrm[idx[NRM]];
aiVector3D uv = smesh.uv[idx[UV]]; aiVector3D uv = smesh.uv[idx[UV]];
// The verts are supplied in world-space, so let's // The verts are supplied in world-space, so let's
// transform them back into the local space of this mesh: // transform them back into the local space of this mesh:
@ -632,13 +593,12 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
// Now that we know the size of everything, // Now that we know the size of everything,
// we can build the final one-material-per-mesh data. // we can build the final one-material-per-mesh data.
for (size_t n=0;n<meshes.size();n++) for (size_t n = 0; n < meshes.size(); n++) {
{ TempMesh &src = meshes[n];
TempMesh& src = meshes[n];
if (src.faces.empty()) if (src.faces.empty())
continue; continue;
aiMesh* mesh = new aiMesh; aiMesh *mesh = new aiMesh;
mesh->mName = name; mesh->mName = name;
mesh->mNumFaces = static_cast<unsigned int>(src.faces.size()); mesh->mNumFaces = static_cast<unsigned int>(src.faces.size());
mesh->mFaces = new aiFace[mesh->mNumFaces]; mesh->mFaces = new aiFace[mesh->mNumFaces];
@ -649,14 +609,12 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
mesh->mNumUVComponents[0] = 2; mesh->mNumUVComponents[0] = 2;
mesh->mMaterialIndex = static_cast<unsigned int>(n); mesh->mMaterialIndex = static_cast<unsigned int>(n);
for (unsigned i=0;i<mesh->mNumVertices;i++) for (unsigned i = 0; i < mesh->mNumVertices; i++) {
{
mesh->mVertices[i] = src.vtx[i]; mesh->mVertices[i] = src.vtx[i];
mesh->mNormals[i] = src.nrm[i]; mesh->mNormals[i] = src.nrm[i];
mesh->mTextureCoords[0][i] = src.uv[i]; mesh->mTextureCoords[0][i] = src.uv[i];
} }
for (unsigned i=0;i<mesh->mNumFaces;i++) for (unsigned i = 0; i < mesh->mNumFaces; i++) {
{
mesh->mFaces[i] = src.faces[i]; mesh->mFaces[i] = src.faces[i];
} }
@ -668,8 +626,7 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadMaterial(SIB* sib, StreamReaderLE* stream) static void ReadMaterial(SIB *sib, StreamReaderLE *stream) {
{
aiColor3D diff = ReadColor(stream); aiColor3D diff = ReadColor(stream);
aiColor3D ambi = ReadColor(stream); aiColor3D ambi = ReadColor(stream);
aiColor3D spec = ReadColor(stream); aiColor3D spec = ReadColor(stream);
@ -677,11 +634,11 @@ static void ReadMaterial(SIB* sib, StreamReaderLE* stream)
float shiny = (float)stream->GetU4(); float shiny = (float)stream->GetU4();
uint32_t nameLen = stream->GetU4(); uint32_t nameLen = stream->GetU4();
aiString name = ReadString(stream, nameLen/2); aiString name = ReadString(stream, nameLen / 2);
uint32_t texLen = stream->GetU4(); uint32_t texLen = stream->GetU4();
aiString tex = ReadString(stream, texLen/2); aiString tex = ReadString(stream, texLen / 2);
aiMaterial* mtl = new aiMaterial(); aiMaterial *mtl = new aiMaterial();
mtl->AddProperty(&diff, 1, AI_MATKEY_COLOR_DIFFUSE); mtl->AddProperty(&diff, 1, AI_MATKEY_COLOR_DIFFUSE);
mtl->AddProperty(&ambi, 1, AI_MATKEY_COLOR_AMBIENT); mtl->AddProperty(&ambi, 1, AI_MATKEY_COLOR_AMBIENT);
mtl->AddProperty(&spec, 1, AI_MATKEY_COLOR_SPECULAR); mtl->AddProperty(&spec, 1, AI_MATKEY_COLOR_SPECULAR);
@ -697,8 +654,7 @@ static void ReadMaterial(SIB* sib, StreamReaderLE* stream)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadLightInfo(aiLight* light, StreamReaderLE* stream) static void ReadLightInfo(aiLight *light, StreamReaderLE *stream) {
{
uint32_t type = stream->GetU4(); uint32_t type = stream->GetU4();
switch (type) { switch (type) {
case 0: light->mType = aiLightSource_POINT; break; case 0: light->mType = aiLightSource_POINT; break;
@ -728,7 +684,7 @@ static void ReadLightInfo(aiLight* light, StreamReaderLE* stream)
// 99% and 1% percentiles. // 99% and 1% percentiles.
// OpenGL: I = cos(angle)^E // OpenGL: I = cos(angle)^E
// Solving: angle = acos(I^(1/E)) // Solving: angle = acos(I^(1/E))
ai_real E = ai_real( 1.0 ) / std::max(spotExponent, (ai_real)0.00001); ai_real E = ai_real(1.0) / std::max(spotExponent, (ai_real)0.00001);
ai_real inner = std::acos(std::pow((ai_real)0.99, E)); ai_real inner = std::acos(std::pow((ai_real)0.99, E));
ai_real outer = std::acos(std::pow((ai_real)0.01, E)); ai_real outer = std::acos(std::pow((ai_real)0.01, E));
@ -739,20 +695,17 @@ static void ReadLightInfo(aiLight* light, StreamReaderLE* stream)
light->mAngleOuterCone = outer; light->mAngleOuterCone = outer;
} }
static void ReadLight(SIB* sib, StreamReaderLE* stream) static void ReadLight(SIB *sib, StreamReaderLE *stream) {
{ aiLight *light = new aiLight();
aiLight* light = new aiLight();
while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) {
{
SIBChunk chunk = ReadChunk(stream); SIBChunk chunk = ReadChunk(stream);
unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size); unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
switch (chunk.Tag) switch (chunk.Tag) {
{ case TAG('L', 'N', 'F', 'O'): ReadLightInfo(light, stream); break;
case TAG('L','N','F','O'): ReadLightInfo(light, stream); break; case TAG('S', 'N', 'A', 'M'): light->mName = ReadString(stream, chunk.Size / 2); break;
case TAG('S','N','A','M'): light->mName = ReadString(stream, chunk.Size/2); break; default: UnknownChunk(stream, chunk); break;
default: UnknownChunk(stream, chunk); break;
} }
stream->SetCurrentPos(stream->GetReadLimit()); stream->SetCurrentPos(stream->GetReadLimit());
@ -763,8 +716,7 @@ static void ReadLight(SIB* sib, StreamReaderLE* stream)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadScale(aiMatrix4x4& axis, StreamReaderLE* stream) static void ReadScale(aiMatrix4x4 &axis, StreamReaderLE *stream) {
{
aiMatrix4x4 scale; aiMatrix4x4 scale;
scale.a1 = stream->GetF4(); scale.a1 = stream->GetF4();
scale.b1 = stream->GetF4(); scale.b1 = stream->GetF4();
@ -786,68 +738,61 @@ static void ReadScale(aiMatrix4x4& axis, StreamReaderLE* stream)
axis = axis * scale; axis = axis * scale;
} }
static void ReadInstance(SIB* sib, StreamReaderLE* stream) static void ReadInstance(SIB *sib, StreamReaderLE *stream) {
{
SIBObject inst; SIBObject inst;
uint32_t shapeIndex = 0; uint32_t shapeIndex = 0;
while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) {
{
SIBChunk chunk = ReadChunk(stream); SIBChunk chunk = ReadChunk(stream);
unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size); unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
switch (chunk.Tag) switch (chunk.Tag) {
{ case TAG('D', 'I', 'N', 'F'): break; // display info, not needed
case TAG('D','I','N','F'): break; // display info, not needed case TAG('P', 'I', 'N', 'F'): break; // ?
case TAG('P','I','N','F'): break; // ? case TAG('A', 'X', 'I', 'S'): ReadAxis(inst.axis, stream); break;
case TAG('A','X','I','S'): ReadAxis(inst.axis, stream); break; case TAG('I', 'N', 'S', 'I'): shapeIndex = stream->GetU4(); break;
case TAG('I','N','S','I'): shapeIndex = stream->GetU4(); break; case TAG('S', 'M', 'T', 'X'): ReadScale(inst.axis, stream); break;
case TAG('S','M','T','X'): ReadScale(inst.axis, stream); break; case TAG('S', 'N', 'A', 'M'): inst.name = ReadString(stream, chunk.Size / 2); break;
case TAG('S','N','A','M'): inst.name = ReadString(stream, chunk.Size/2); break; default: UnknownChunk(stream, chunk); break;
default: UnknownChunk(stream, chunk); break;
} }
stream->SetCurrentPos(stream->GetReadLimit()); stream->SetCurrentPos(stream->GetReadLimit());
stream->SetReadLimit(oldLimit); stream->SetReadLimit(oldLimit);
} }
if ( shapeIndex >= sib->objs.size() ) { if (shapeIndex >= sib->objs.size()) {
throw DeadlyImportError( "SIB: Invalid shape index." ); throw DeadlyImportError("SIB: Invalid shape index.");
} }
const SIBObject& src = sib->objs[shapeIndex]; const SIBObject &src = sib->objs[shapeIndex];
inst.meshIdx = src.meshIdx; inst.meshIdx = src.meshIdx;
inst.meshCount = src.meshCount; inst.meshCount = src.meshCount;
sib->insts.push_back(inst); sib->insts.push_back(inst);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void CheckVersion(StreamReaderLE* stream) static void CheckVersion(StreamReaderLE *stream) {
{
uint32_t version = stream->GetU4(); uint32_t version = stream->GetU4();
if ( version < 1 || version > 2 ) { if (version < 1 || version > 2) {
throw DeadlyImportError( "SIB: Unsupported file version." ); throw DeadlyImportError("SIB: Unsupported file version.");
} }
} }
static void ReadScene(SIB* sib, StreamReaderLE* stream) static void ReadScene(SIB *sib, StreamReaderLE *stream) {
{
// Parse each chunk in turn. // Parse each chunk in turn.
while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) {
{
SIBChunk chunk = ReadChunk(stream); SIBChunk chunk = ReadChunk(stream);
unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size); unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
switch (chunk.Tag) switch (chunk.Tag) {
{ case TAG('H', 'E', 'A', 'D'): CheckVersion(stream); break;
case TAG('H','E','A','D'): CheckVersion(stream); break; case TAG('S', 'H', 'A', 'P'): ReadShape(sib, stream); break;
case TAG('S','H','A','P'): ReadShape(sib, stream); break; case TAG('G', 'R', 'P', 'S'): break; // group assignment, we don't import this
case TAG('G','R','P','S'): break; // group assignment, we don't import this case TAG('T', 'E', 'X', 'P'): break; // ?
case TAG('T','E','X','P'): break; // ? case TAG('I', 'N', 'S', 'T'): ReadInstance(sib, stream); break;
case TAG('I','N','S','T'): ReadInstance(sib, stream); break; case TAG('M', 'A', 'T', 'R'): ReadMaterial(sib, stream); break;
case TAG('M','A','T','R'): ReadMaterial(sib, stream); break; case TAG('L', 'G', 'H', 'T'): ReadLight(sib, stream); break;
case TAG('L','G','H','T'): ReadLight(sib, stream); break; default: UnknownChunk(stream, chunk); break;
default: UnknownChunk(stream, chunk); break;
} }
stream->SetCurrentPos(stream->GetReadLimit()); stream->SetCurrentPos(stream->GetReadLimit());
@ -857,9 +802,8 @@ static void ReadScene(SIB* sib, StreamReaderLE* stream)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void SIBImporter::InternReadFile(const std::string& pFile, void SIBImporter::InternReadFile(const std::string &pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene *pScene, IOSystem *pIOHandler) {
{
StreamReaderLE stream(pIOHandler->Open(pFile, "rb")); StreamReaderLE stream(pIOHandler->Open(pFile, "rb"));
// We should have at least one chunk // We should have at least one chunk
@ -869,7 +813,7 @@ void SIBImporter::InternReadFile(const std::string& pFile,
SIB sib; SIB sib;
// Default material. // Default material.
aiMaterial* defmtl = new aiMaterial; aiMaterial *defmtl = new aiMaterial;
aiString defname = aiString(AI_DEFAULT_MATERIAL_NAME); aiString defname = aiString(AI_DEFAULT_MATERIAL_NAME);
defmtl->AddProperty(&defname, AI_MATKEY_NAME); defmtl->AddProperty(&defname, AI_MATKEY_NAME);
sib.mtls.push_back(defmtl); sib.mtls.push_back(defmtl);
@ -886,57 +830,54 @@ void SIBImporter::InternReadFile(const std::string& pFile,
pScene->mNumMaterials = static_cast<unsigned int>(sib.mtls.size()); pScene->mNumMaterials = static_cast<unsigned int>(sib.mtls.size());
pScene->mNumMeshes = static_cast<unsigned int>(sib.meshes.size()); pScene->mNumMeshes = static_cast<unsigned int>(sib.meshes.size());
pScene->mNumLights = static_cast<unsigned int>(sib.lights.size()); pScene->mNumLights = static_cast<unsigned int>(sib.lights.size());
pScene->mMaterials = pScene->mNumMaterials ? new aiMaterial*[pScene->mNumMaterials] : NULL; pScene->mMaterials = pScene->mNumMaterials ? new aiMaterial *[pScene->mNumMaterials] : nullptr;
pScene->mMeshes = pScene->mNumMeshes ? new aiMesh*[pScene->mNumMeshes] : NULL; pScene->mMeshes = pScene->mNumMeshes ? new aiMesh *[pScene->mNumMeshes] : nullptr;
pScene->mLights = pScene->mNumLights ? new aiLight*[pScene->mNumLights] : NULL; pScene->mLights = pScene->mNumLights ? new aiLight *[pScene->mNumLights] : nullptr;
if (pScene->mNumMaterials) if (pScene->mNumMaterials)
memcpy(pScene->mMaterials, &sib.mtls[0], sizeof(aiMaterial*) * pScene->mNumMaterials); memcpy(pScene->mMaterials, &sib.mtls[0], sizeof(aiMaterial *) * pScene->mNumMaterials);
if (pScene->mNumMeshes) if (pScene->mNumMeshes)
memcpy(pScene->mMeshes, &sib.meshes[0], sizeof(aiMesh*) * pScene->mNumMeshes); memcpy(pScene->mMeshes, &sib.meshes[0], sizeof(aiMesh *) * pScene->mNumMeshes);
if (pScene->mNumLights) if (pScene->mNumLights)
memcpy(pScene->mLights, &sib.lights[0], sizeof(aiLight*) * pScene->mNumLights); memcpy(pScene->mLights, &sib.lights[0], sizeof(aiLight *) * pScene->mNumLights);
// Construct the root node. // Construct the root node.
size_t childIdx = 0; size_t childIdx = 0;
aiNode *root = new aiNode(); aiNode *root = new aiNode();
root->mName.Set("<SIBRoot>"); root->mName.Set("<SIBRoot>");
root->mNumChildren = static_cast<unsigned int>(sib.objs.size() + sib.lights.size()); root->mNumChildren = static_cast<unsigned int>(sib.objs.size() + sib.lights.size());
root->mChildren = root->mNumChildren ? new aiNode*[root->mNumChildren] : NULL; root->mChildren = root->mNumChildren ? new aiNode *[root->mNumChildren] : nullptr;
pScene->mRootNode = root; pScene->mRootNode = root;
// Add nodes for each object. // Add nodes for each object.
for (size_t n=0;n<sib.objs.size();n++) for (size_t n = 0; n < sib.objs.size(); n++) {
{
ai_assert(root->mChildren); ai_assert(root->mChildren);
SIBObject& obj = sib.objs[n]; SIBObject &obj = sib.objs[n];
aiNode* node = new aiNode; aiNode *node = new aiNode;
root->mChildren[childIdx++] = node; root->mChildren[childIdx++] = node;
node->mName = obj.name; node->mName = obj.name;
node->mParent = root; node->mParent = root;
node->mTransformation = obj.axis; node->mTransformation = obj.axis;
node->mNumMeshes = static_cast<unsigned int>(obj.meshCount); node->mNumMeshes = static_cast<unsigned int>(obj.meshCount);
node->mMeshes = node->mNumMeshes ? new unsigned[node->mNumMeshes] : NULL; node->mMeshes = node->mNumMeshes ? new unsigned[node->mNumMeshes] : nullptr;
for (unsigned i=0;i<node->mNumMeshes;i++) for (unsigned i = 0; i < node->mNumMeshes; i++)
node->mMeshes[i] = static_cast<unsigned int>(obj.meshIdx + i); node->mMeshes[i] = static_cast<unsigned int>(obj.meshIdx + i);
// Mark instanced objects as being so. // Mark instanced objects as being so.
if (n >= firstInst) if (n >= firstInst) {
{ node->mMetaData = aiMetadata::Alloc(1);
node->mMetaData = aiMetadata::Alloc( 1 ); node->mMetaData->Set(0, "IsInstance", true);
node->mMetaData->Set( 0, "IsInstance", true );
} }
} }
// Add nodes for each light. // Add nodes for each light.
// (no transformation as the light is already in world space) // (no transformation as the light is already in world space)
for (size_t n=0;n<sib.lights.size();n++) for (size_t n = 0; n < sib.lights.size(); n++) {
{
ai_assert(root->mChildren); ai_assert(root->mChildren);
aiLight* light = sib.lights[n]; aiLight *light = sib.lights[n];
if ( nullptr != light ) { if (nullptr != light) {
aiNode* node = new aiNode; aiNode *node = new aiNode;
root->mChildren[ childIdx++ ] = node; root->mChildren[childIdx++] = node;
node->mName = light->mName; node->mName = light->mName;
node->mParent = root; node->mParent = root;
} }

View File

@ -577,7 +577,7 @@ void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHa
char *context1, *context2; char *context1, *context2;
tok1 = strtok_s(&buf[0], "\r\n", &context1); tok1 = strtok_s(&buf[0], "\r\n", &context1);
while (tok1 != NULL) { while (tok1 != nullptr) {
tok2 = strtok_s(tok1, " \t", &context2); tok2 = strtok_s(tok1, " \t", &context2);
if (tok2) { if (tok2) {
char *p = tok2; char *p = tok2;

View File

@ -299,7 +299,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/) std::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= nullptr*/)
{ {
const char* cur = inout; const char* cur = inout;
SkipSpaces(&cur); SkipSpaces(&cur);
@ -422,7 +422,7 @@ std::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& i
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::shared_ptr<const EXPRESS::LIST> EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/) { std::shared_ptr<const EXPRESS::LIST> EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= nullptr*/) {
const std::shared_ptr<EXPRESS::LIST> list = std::make_shared<EXPRESS::LIST>(); const std::shared_ptr<EXPRESS::LIST> list = std::make_shared<EXPRESS::LIST>();
EXPRESS::LIST::MemberList& members = list->members; EXPRESS::LIST::MemberList& members = list->members;
@ -540,9 +540,9 @@ void STEP::LazyObject::LazyInit() const {
const char* acopy = args; const char* acopy = args;
std::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,(uint64_t)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; delete[] args;
args = NULL; args = nullptr;
// if the converter fails, it should throw an exception, but it should never return NULL // if the converter fails, it should throw an exception, but it should never return nullptr
try { try {
obj = proc(db,*conv_args); obj = proc(db,*conv_args);
} }

View File

@ -72,7 +72,7 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// we're still here - export successfully completed. Write the file. // we're still here - export successfully completed. Write the file.
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .stl file: " + std::string(pFile)); throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
} }
@ -91,7 +91,7 @@ void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene*
// we're still here - export successfully completed. Write the file. // we're still here - export successfully completed. Write the file.
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wb")); std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wb"));
if(outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .stl file: " + std::string(pFile)); throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
} }

View File

@ -108,7 +108,7 @@ void ExportSceneStep(const char* pFile,IOSystem* pIOSystem, const aiScene* pScen
// we're still here - export successfully completed. Write result to the given IOSYstem // we're still here - export successfully completed. Write result to the given IOSYstem
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .stp file: " + std::string(pFile)); throw DeadlyExportError("could not open output .stp file: " + std::string(pFile));
} }
@ -204,7 +204,7 @@ void StepExporter::WriteFile()
static const unsigned int date_nb_chars = 20; static const unsigned int date_nb_chars = 20;
char date_str[date_nb_chars]; char date_str[date_nb_chars];
std::time_t date = std::time(NULL); std::time_t date = std::time(nullptr);
std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date)); std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
// write the header // write the header

View File

@ -87,12 +87,16 @@ bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, b
if (!extension.length() || checkSig) { if (!extension.length() || checkSig) {
/* If CanRead() is called in order to check whether we /* If CanRead() is called in order to check whether we
* support a specific file extension in general pIOHandler * support a specific file extension in general pIOHandler
* might be NULL and it's our duty to return true here. * might be nullptr and it's our duty to return true here.
*/ */
if (!pIOHandler) return true; if (!pIOHandler) {
return true;
}
const char *tokens[] = { "terragen" }; const char *tokens[] = { "terragen" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
} }
return false; return false;
} }
@ -116,7 +120,7 @@ void TerragenImporter::InternReadFile(const std::string &pFile,
IOStream *file = pIOHandler->Open(pFile, "rb"); IOStream *file = pIOHandler->Open(pFile, "rb");
// Check whether we can read from the file // Check whether we can read from the file
if (file == NULL) if (file == nullptr)
throw DeadlyImportError("Failed to open TERRAGEN TERRAIN file " + pFile + "."); throw DeadlyImportError("Failed to open TERRAGEN TERRAIN file " + pFile + ".");
// Construct a stream reader to read all data in the correct endianness // Construct a stream reader to read all data in the correct endianness
@ -199,7 +203,7 @@ void TerragenImporter::InternReadFile(const std::string &pFile,
aiFace *f = m->mFaces = new aiFace[m->mNumFaces = (x - 1) * (y - 1)]; aiFace *f = m->mFaces = new aiFace[m->mNumFaces = (x - 1) * (y - 1)];
aiVector3D *pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces * 4]; aiVector3D *pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces * 4];
aiVector3D *uv(NULL); aiVector3D *uv(nullptr);
float step_y(0.0f), step_x(0.0f); float step_y(0.0f), step_x(0.0f);
if (configComputeUVs) { if (configComputeUVs) {
uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices]; uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices];

View File

@ -89,7 +89,7 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce
// we're still here - export successfully completed. Write result to the given IOSYstem // we're still here - export successfully completed. Write result to the given IOSYstem
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output .x file: " + std::string(pFile)); throw DeadlyExportError("could not open output .x file: " + std::string(pFile));
} }

View File

@ -113,7 +113,7 @@ const aiImporterDesc* XFileImporter::GetInfo () const {
void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
// read file into memory // read file into memory
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile)); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
if ( file.get() == NULL ) { if ( file.get() == nullptr ) {
throw DeadlyImportError( "Failed to open file " + pFile + "." ); throw DeadlyImportError( "Failed to open file " + pFile + "." );
} }

File diff suppressed because it is too large Load Diff

View File

@ -104,7 +104,7 @@ protected:
//! reads header of data object including the opening brace. //! reads header of data object including the opening brace.
//! returns false if error happened, and writes name of object //! returns false if error happened, and writes name of object
//! if there is one //! if there is one
void readHeadOfDataObject( std::string* poName = NULL); void readHeadOfDataObject(std::string *poName = nullptr);
//! checks for closing curly brace, throws exception if not there //! checks for closing curly brace, throws exception if not there
void CheckForClosingBrace(); void CheckForClosingBrace();

View File

@ -64,8 +64,8 @@ namespace Assimp
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model." // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
// </Shape> // </Shape>
// A Shape node is unlit if either of the following is true: // A Shape node is unlit if either of the following is true:
// The shape's appearance field is NULL (default). // The shape's appearance field is nullptr (default).
// The material field in the Appearance node is NULL (default). // The material field in the Appearance node is nullptr (default).
// NOTE Geometry nodes that represent lines or points do not support lighting. // NOTE Geometry nodes that represent lines or points do not support lighting.
void X3DImporter::ParseNode_Shape_Shape() void X3DImporter::ParseNode_Shape_Shape()
{ {

View File

@ -43,18 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the XGL/ZGL importer class */ /** @file Implementation of the XGL/ZGL importer class */
#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER #ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
#include "XGLLoader.h" #include "XGLLoader.h"
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/StreamReader.h>
#include <assimp/MemoryIOWrapper.h> #include <assimp/MemoryIOWrapper.h>
#include <assimp/StreamReader.h>
#include <assimp/importerdesc.h>
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h>
#include <cctype> #include <cctype>
#include <memory> #include <memory>
@ -64,21 +63,20 @@ using namespace irr::io;
// zlib is needed for compressed XGL files // zlib is needed for compressed XGL files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
# ifdef ASSIMP_BUILD_NO_OWN_ZLIB #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h> #include <zlib.h>
# else #else
# include <contrib/zlib/zlib.h> #include <contrib/zlib/zlib.h>
# endif #endif
#endif #endif
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
template<> const char* LogFunctions<XGLImporter>::Prefix() template <>
{ const char *LogFunctions<XGLImporter>::Prefix() {
static auto prefix = "XGL: "; static auto prefix = "XGL: ";
return prefix; return prefix;
}
} }
} // namespace Assimp
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"XGL Importer", "XGL Importer",
@ -93,12 +91,10 @@ static const aiImporterDesc desc = {
"xgl zgl" "xgl zgl"
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
XGLImporter::XGLImporter() XGLImporter::XGLImporter() :
: m_reader( nullptr ) m_reader(nullptr), m_scene(nullptr) {
, m_scene( nullptr ) {
// empty // empty
} }
@ -110,8 +106,7 @@ XGLImporter::~XGLImporter() {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool XGLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
{
/* NOTE: A simple check for the file extension is not enough /* NOTE: A simple check for the file extension is not enough
* here. XGL and ZGL are ok, but xml is too generic * here. XGL and ZGL are ok, but xml is too generic
* and might be collada as well. So open the file and * and might be collada as well. So open the file and
@ -121,38 +116,35 @@ bool XGLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
if (extension == "xgl" || extension == "zgl") { if (extension == "xgl" || extension == "zgl") {
return true; return true;
} } else if (extension == "xml" || checkSig) {
else if (extension == "xml" || checkSig) { ai_assert(pIOHandler != nullptr);
ai_assert(pIOHandler != NULL);
const char* tokens[] = {"<world>","<World>","<WORLD>"}; const char *tokens[] = { "<world>", "<World>", "<WORLD>" };
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,3); return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3);
} }
return false; return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a list of all file extensions which are handled by this class // Get a list of all file extensions which are handled by this class
const aiImporterDesc* XGLImporter::GetInfo () const const aiImporterDesc *XGLImporter::GetInfo() const {
{
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void XGLImporter::InternReadFile( const std::string& pFile, void XGLImporter::InternReadFile(const std::string &pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene *pScene, IOSystem *pIOHandler) {
{
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
std::vector<Bytef> uncompressed; std::vector<Bytef> uncompressed;
#endif #endif
m_scene = pScene; m_scene = pScene;
std::shared_ptr<IOStream> stream( pIOHandler->Open( pFile, "rb")); std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
// check whether we can read from the file // check whether we can read from the file
if( stream.get() == NULL) { if (stream.get() == nullptr) {
throw DeadlyImportError( "Failed to open XGL/ZGL file " + pFile + ""); throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + "");
} }
// see if its compressed, if so uncompress it // see if its compressed, if so uncompress it
@ -166,7 +158,7 @@ void XGLImporter::InternReadFile( const std::string& pFile,
z_stream zstream; z_stream zstream;
zstream.opaque = Z_NULL; zstream.opaque = Z_NULL;
zstream.zalloc = Z_NULL; zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL; zstream.zfree = Z_NULL;
zstream.data_type = Z_BINARY; zstream.data_type = Z_BINARY;
// raw decompression without a zlib or gzip header // raw decompression without a zlib or gzip header
@ -175,14 +167,14 @@ void XGLImporter::InternReadFile( const std::string& pFile,
// skip two extra bytes, zgl files do carry a crc16 upfront (I think) // skip two extra bytes, zgl files do carry a crc16 upfront (I think)
raw_reader->IncPtr(2); raw_reader->IncPtr(2);
zstream.next_in = reinterpret_cast<Bytef*>( raw_reader->GetPtr() ); zstream.next_in = reinterpret_cast<Bytef *>(raw_reader->GetPtr());
zstream.avail_in = (uInt) raw_reader->GetRemainingSize(); zstream.avail_in = (uInt)raw_reader->GetRemainingSize();
size_t total = 0l; size_t total = 0l;
// TODO: be smarter about this, decompress directly into heap buffer // TODO: be smarter about this, decompress directly into heap buffer
// and decompress the data .... do 1k chunks in the hope that we won't kill the stack // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
#define MYBLOCK 1024 #define MYBLOCK 1024
Bytef block[MYBLOCK]; Bytef block[MYBLOCK];
int ret; int ret;
do { do {
@ -196,51 +188,49 @@ void XGLImporter::InternReadFile( const std::string& pFile,
const size_t have = MYBLOCK - zstream.avail_out; const size_t have = MYBLOCK - zstream.avail_out;
total += have; total += have;
uncompressed.resize(total); uncompressed.resize(total);
memcpy(uncompressed.data() + total - have,block,have); memcpy(uncompressed.data() + total - have, block, have);
} } while (ret != Z_STREAM_END);
while (ret != Z_STREAM_END);
// terminate zlib // terminate zlib
inflateEnd(&zstream); inflateEnd(&zstream);
// replace the input stream with a memory stream // replace the input stream with a memory stream
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(uncompressed.data()),total)); stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
#endif #endif
} }
// construct the irrXML parser // construct the irrXML parser
CIrrXML_IOStreamReader st(stream.get()); CIrrXML_IOStreamReader st(stream.get());
m_reader.reset( createIrrXMLReader( ( IFileReadCallBack* ) &st ) ); m_reader.reset(createIrrXMLReader((IFileReadCallBack *)&st));
// parse the XML file // parse the XML file
TempScope scope; TempScope scope;
while (ReadElement()) { while (ReadElement()) {
if (!ASSIMP_stricmp(m_reader->getNodeName(),"world")) { if (!ASSIMP_stricmp(m_reader->getNodeName(), "world")) {
ReadWorld(scope); ReadWorld(scope);
} }
} }
std::vector<aiMesh *> &meshes = scope.meshes_linear;
std::vector<aiMesh*>& meshes = scope.meshes_linear; std::vector<aiMaterial *> &materials = scope.materials_linear;
std::vector<aiMaterial*>& materials = scope.materials_linear; if (!meshes.size() || !materials.size()) {
if(!meshes.size() || !materials.size()) {
ThrowException("failed to extract data from XGL file, no meshes loaded"); ThrowException("failed to extract data from XGL file, no meshes loaded");
} }
// copy meshes // copy meshes
m_scene->mNumMeshes = static_cast<unsigned int>(meshes.size()); m_scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
m_scene->mMeshes = new aiMesh*[m_scene->mNumMeshes](); m_scene->mMeshes = new aiMesh *[m_scene->mNumMeshes]();
std::copy(meshes.begin(),meshes.end(),m_scene->mMeshes); std::copy(meshes.begin(), meshes.end(), m_scene->mMeshes);
// copy materials // copy materials
m_scene->mNumMaterials = static_cast<unsigned int>(materials.size()); m_scene->mNumMaterials = static_cast<unsigned int>(materials.size());
m_scene->mMaterials = new aiMaterial*[m_scene->mNumMaterials](); m_scene->mMaterials = new aiMaterial *[m_scene->mNumMaterials]();
std::copy(materials.begin(),materials.end(),m_scene->mMaterials); std::copy(materials.begin(), materials.end(), m_scene->mMaterials);
if (scope.light) { if (scope.light) {
m_scene->mNumLights = 1; m_scene->mNumLights = 1;
m_scene->mLights = new aiLight*[1]; m_scene->mLights = new aiLight *[1];
m_scene->mLights[0] = scope.light; m_scene->mLights[0] = scope.light;
scope.light->mName = m_scene->mRootNode->mName; scope.light->mName = m_scene->mRootNode->mName;
@ -250,9 +240,8 @@ void XGLImporter::InternReadFile( const std::string& pFile,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadElement() bool XGLImporter::ReadElement() {
{ while (m_reader->read()) {
while(m_reader->read()) {
if (m_reader->getNodeType() == EXN_ELEMENT) { if (m_reader->getNodeType() == EXN_ELEMENT) {
return true; return true;
} }
@ -261,13 +250,11 @@ bool XGLImporter::ReadElement()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadElementUpToClosing(const char* closetag) bool XGLImporter::ReadElementUpToClosing(const char *closetag) {
{ while (m_reader->read()) {
while(m_reader->read()) {
if (m_reader->getNodeType() == EXN_ELEMENT) { if (m_reader->getNodeType() == EXN_ELEMENT) {
return true; return true;
} } else if (m_reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(m_reader->getNodeName(), closetag)) {
else if (m_reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(m_reader->getNodeName(),closetag)) {
return false; return false;
} }
} }
@ -276,13 +263,11 @@ bool XGLImporter::ReadElementUpToClosing(const char* closetag)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool XGLImporter::SkipToText() bool XGLImporter::SkipToText() {
{ while (m_reader->read()) {
while(m_reader->read()) {
if (m_reader->getNodeType() == EXN_TEXT) { if (m_reader->getNodeType() == EXN_TEXT) {
return true; return true;
} } else if (m_reader->getNodeType() == EXN_ELEMENT || m_reader->getNodeType() == EXN_ELEMENT_END) {
else if (m_reader->getNodeType() == EXN_ELEMENT || m_reader->getNodeType() == EXN_ELEMENT_END) {
ThrowException("expected text contents but found another element (or element end)"); ThrowException("expected text contents but found another element (or element end)");
} }
} }
@ -290,9 +275,8 @@ bool XGLImporter::SkipToText()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string XGLImporter::GetElementName() std::string XGLImporter::GetElementName() {
{ const char *s = m_reader->getNodeName();
const char* s = m_reader->getNodeName();
size_t len = strlen(s); size_t len = strlen(s);
std::string ret; std::string ret;
@ -302,26 +286,23 @@ std::string XGLImporter::GetElementName()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void XGLImporter::ReadWorld(TempScope& scope) void XGLImporter::ReadWorld(TempScope &scope) {
{
while (ReadElementUpToClosing("world")) { while (ReadElementUpToClosing("world")) {
const std::string& s = GetElementName(); const std::string &s = GetElementName();
// XXX right now we'd skip <lighting> if it comes after // XXX right now we'd skip <lighting> if it comes after
// <object> or <mesh> // <object> or <mesh>
if (s == "lighting") { if (s == "lighting") {
ReadLighting(scope); ReadLighting(scope);
} } else if (s == "object" || s == "mesh" || s == "mat") {
else if (s == "object" || s == "mesh" || s == "mat") {
break; break;
} }
} }
aiNode *const nd = ReadObject(scope, true, "world");
aiNode* const nd = ReadObject(scope,true,"world"); if (!nd) {
if(!nd) {
ThrowException("failure reading <world>"); ThrowException("failure reading <world>");
} }
if(!nd->mName.length) { if (!nd->mName.length) {
nd->mName.Set("WORLD"); nd->mName.Set("WORLD");
} }
@ -329,37 +310,31 @@ void XGLImporter::ReadWorld(TempScope& scope)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void XGLImporter::ReadLighting(TempScope& scope) void XGLImporter::ReadLighting(TempScope &scope) {
{ while (ReadElementUpToClosing("lighting")) {
while (ReadElementUpToClosing("lighting")) { const std::string &s = GetElementName();
const std::string& s = GetElementName();
if (s == "directionallight") { if (s == "directionallight") {
scope.light = ReadDirectionalLight(); scope.light = ReadDirectionalLight();
} } else if (s == "ambient") {
else if (s == "ambient") {
LogWarn("ignoring <ambient> tag"); LogWarn("ignoring <ambient> tag");
} } else if (s == "spheremap") {
else if (s == "spheremap") {
LogWarn("ignoring <spheremap> tag"); LogWarn("ignoring <spheremap> tag");
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiLight* XGLImporter::ReadDirectionalLight() aiLight *XGLImporter::ReadDirectionalLight() {
{
std::unique_ptr<aiLight> l(new aiLight()); std::unique_ptr<aiLight> l(new aiLight());
l->mType = aiLightSource_DIRECTIONAL; l->mType = aiLightSource_DIRECTIONAL;
while (ReadElementUpToClosing("directionallight")) { while (ReadElementUpToClosing("directionallight")) {
const std::string& s = GetElementName(); const std::string &s = GetElementName();
if (s == "direction") { if (s == "direction") {
l->mDirection = ReadVec3(); l->mDirection = ReadVec3();
} } else if (s == "diffuse") {
else if (s == "diffuse") {
l->mColorDiffuse = ReadCol3(); l->mColorDiffuse = ReadCol3();
} } else if (s == "specular") {
else if (s == "specular") {
l->mColorSpecular = ReadCol3(); l->mColorSpecular = ReadCol3();
} }
} }
@ -367,49 +342,44 @@ aiLight* XGLImporter::ReadDirectionalLight()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* closetag) aiNode *XGLImporter::ReadObject(TempScope &scope, bool skipFirst, const char *closetag) {
{
aiNode *nd = new aiNode; aiNode *nd = new aiNode;
std::vector<aiNode*> children; std::vector<aiNode *> children;
std::vector<unsigned int> meshes; std::vector<unsigned int> meshes;
try { try {
while (skipFirst || ReadElementUpToClosing(closetag)) { while (skipFirst || ReadElementUpToClosing(closetag)) {
skipFirst = false; skipFirst = false;
const std::string& s = GetElementName(); const std::string &s = GetElementName();
if (s == "mesh") { if (s == "mesh") {
const size_t prev = scope.meshes_linear.size(); const size_t prev = scope.meshes_linear.size();
if(ReadMesh(scope)) { if (ReadMesh(scope)) {
const size_t newc = scope.meshes_linear.size(); const size_t newc = scope.meshes_linear.size();
for(size_t i = 0; i < newc-prev; ++i) { for (size_t i = 0; i < newc - prev; ++i) {
meshes.push_back(static_cast<unsigned int>(i+prev)); meshes.push_back(static_cast<unsigned int>(i + prev));
} }
} }
} } else if (s == "mat") {
else if (s == "mat") {
ReadMaterial(scope); ReadMaterial(scope);
} } else if (s == "object") {
else if (s == "object") {
children.push_back(ReadObject(scope)); children.push_back(ReadObject(scope));
} } else if (s == "objectref") {
else if (s == "objectref") {
// XXX // XXX
} } else if (s == "meshref") {
else if (s == "meshref") { const unsigned int id = static_cast<unsigned int>(ReadIndexFromText());
const unsigned int id = static_cast<unsigned int>( ReadIndexFromText() );
std::multimap<unsigned int, aiMesh*>::iterator it = scope.meshes.find(id), end = scope.meshes.end(); std::multimap<unsigned int, aiMesh *>::iterator it = scope.meshes.find(id), end = scope.meshes.end();
if (it == end) { if (it == end) {
ThrowException("<meshref> index out of range"); ThrowException("<meshref> index out of range");
} }
for(; it != end && (*it).first == id; ++it) { for (; it != end && (*it).first == id; ++it) {
// ok, this is n^2 and should get optimized one day // ok, this is n^2 and should get optimized one day
aiMesh* const m = (*it).second; aiMesh *const m = (*it).second;
unsigned int i = 0, mcount = static_cast<unsigned int>(scope.meshes_linear.size()); unsigned int i = 0, mcount = static_cast<unsigned int>(scope.meshes_linear.size());
for(; i < mcount; ++i) { for (; i < mcount; ++i) {
if (scope.meshes_linear[i] == m) { if (scope.meshes_linear[i] == m) {
meshes.push_back(i); meshes.push_back(i);
break; break;
@ -418,14 +388,13 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl
ai_assert(i < mcount); ai_assert(i < mcount);
} }
} } else if (s == "transform") {
else if (s == "transform") {
nd->mTransformation = ReadTrafo(); nd->mTransformation = ReadTrafo();
} }
} }
} catch(...) { } catch (...) {
for(aiNode* ch : children) { for (aiNode *ch : children) {
delete ch; delete ch;
} }
throw; throw;
@ -441,7 +410,7 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl
nd->mNumMeshes = static_cast<unsigned int>(meshes.size()); nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
if (nd->mNumMeshes) { if (nd->mNumMeshes) {
nd->mMeshes = new unsigned int[nd->mNumMeshes](); nd->mMeshes = new unsigned int[nd->mNumMeshes]();
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { for (unsigned int i = 0; i < nd->mNumMeshes; ++i) {
nd->mMeshes[i] = meshes[i]; nd->mMeshes[i] = meshes[i];
} }
} }
@ -449,8 +418,8 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl
// link children to parent // link children to parent
nd->mNumChildren = static_cast<unsigned int>(children.size()); nd->mNumChildren = static_cast<unsigned int>(children.size());
if (nd->mNumChildren) { if (nd->mNumChildren) {
nd->mChildren = new aiNode*[nd->mNumChildren](); nd->mChildren = new aiNode *[nd->mNumChildren]();
for(unsigned int i = 0; i < nd->mNumChildren; ++i) { for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
nd->mChildren[i] = children[i]; nd->mChildren[i] = children[i];
children[i]->mParent = nd; children[i]->mParent = nd;
} }
@ -460,25 +429,22 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiMatrix4x4 XGLImporter::ReadTrafo() aiMatrix4x4 XGLImporter::ReadTrafo() {
{
aiVector3D forward, up, right, position; aiVector3D forward, up, right, position;
float scale = 1.0f; float scale = 1.0f;
while (ReadElementUpToClosing("transform")) { while (ReadElementUpToClosing("transform")) {
const std::string& s = GetElementName(); const std::string &s = GetElementName();
if (s == "forward") { if (s == "forward") {
forward = ReadVec3(); forward = ReadVec3();
} } else if (s == "up") {
else if (s == "up") {
up = ReadVec3(); up = ReadVec3();
} } else if (s == "position") {
else if (s == "position") {
position = ReadVec3(); position = ReadVec3();
} }
if (s == "scale") { if (s == "scale") {
scale = ReadFloat(); scale = ReadFloat();
if(scale < 0.f) { if (scale < 0.f) {
// this is wrong, but we can leave the value and pass it to the caller // this is wrong, but we can leave the value and pass it to the caller
LogError("found negative scaling in <transform>, ignoring"); LogError("found negative scaling in <transform>, ignoring");
} }
@ -486,7 +452,7 @@ aiMatrix4x4 XGLImporter::ReadTrafo()
} }
aiMatrix4x4 m; aiMatrix4x4 m;
if(forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) { if (forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
LogError("A direction vector in <transform> is zero, ignoring trafo"); LogError("A direction vector in <transform> is zero, ignoring trafo");
return m; return m;
} }
@ -526,37 +492,36 @@ aiMatrix4x4 XGLImporter::ReadTrafo()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m) aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
{
std::unique_ptr<aiMesh> mesh(new aiMesh()); std::unique_ptr<aiMesh> mesh(new aiMesh());
mesh->mNumVertices = static_cast<unsigned int>(m.positions.size()); mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
mesh->mVertices = new aiVector3D[mesh->mNumVertices]; mesh->mVertices = new aiVector3D[mesh->mNumVertices];
std::copy(m.positions.begin(),m.positions.end(),mesh->mVertices); std::copy(m.positions.begin(), m.positions.end(), mesh->mVertices);
if(m.normals.size()) { if (m.normals.size()) {
mesh->mNormals = new aiVector3D[mesh->mNumVertices]; mesh->mNormals = new aiVector3D[mesh->mNumVertices];
std::copy(m.normals.begin(),m.normals.end(),mesh->mNormals); std::copy(m.normals.begin(), m.normals.end(), mesh->mNormals);
} }
if(m.uvs.size()) { if (m.uvs.size()) {
mesh->mNumUVComponents[0] = 2; mesh->mNumUVComponents[0] = 2;
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
for(unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x,m.uvs[i].y,0.f); mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x, m.uvs[i].y, 0.f);
} }
} }
mesh->mNumFaces = static_cast<unsigned int>(m.vcounts.size()); mesh->mNumFaces = static_cast<unsigned int>(m.vcounts.size());
mesh->mFaces = new aiFace[m.vcounts.size()]; mesh->mFaces = new aiFace[m.vcounts.size()];
unsigned int idx = 0; unsigned int idx = 0;
for(unsigned int i = 0; i < mesh->mNumFaces; ++i) { for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
aiFace& f = mesh->mFaces[i]; aiFace &f = mesh->mFaces[i];
f.mNumIndices = m.vcounts[i]; f.mNumIndices = m.vcounts[i];
f.mIndices = new unsigned int[f.mNumIndices]; f.mIndices = new unsigned int[f.mNumIndices];
for(unsigned int c = 0; c < f.mNumIndices; ++c) { for (unsigned int c = 0; c < f.mNumIndices; ++c) {
f.mIndices[c] = idx++; f.mIndices[c] = idx++;
} }
} }
@ -569,57 +534,49 @@ aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadMesh(TempScope& scope) bool XGLImporter::ReadMesh(TempScope &scope) {
{
TempMesh t; TempMesh t;
std::map<unsigned int, TempMaterialMesh> bymat; std::map<unsigned int, TempMaterialMesh> bymat;
const unsigned int mesh_id = ReadIDAttr(); const unsigned int mesh_id = ReadIDAttr();
while (ReadElementUpToClosing("mesh")) { while (ReadElementUpToClosing("mesh")) {
const std::string& s = GetElementName(); const std::string &s = GetElementName();
if (s == "mat") { if (s == "mat") {
ReadMaterial(scope); ReadMaterial(scope);
} } else if (s == "p") {
else if (s == "p") {
if (!m_reader->getAttributeValue("ID")) { if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <p>, ignoring"); LogWarn("no ID attribute on <p>, ignoring");
} } else {
else {
int id = m_reader->getAttributeValueAsInt("ID"); int id = m_reader->getAttributeValueAsInt("ID");
t.points[id] = ReadVec3(); t.points[id] = ReadVec3();
} }
} } else if (s == "n") {
else if (s == "n") {
if (!m_reader->getAttributeValue("ID")) { if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <n>, ignoring"); LogWarn("no ID attribute on <n>, ignoring");
} } else {
else {
int id = m_reader->getAttributeValueAsInt("ID"); int id = m_reader->getAttributeValueAsInt("ID");
t.normals[id] = ReadVec3(); t.normals[id] = ReadVec3();
} }
} } else if (s == "tc") {
else if (s == "tc") {
if (!m_reader->getAttributeValue("ID")) { if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <tc>, ignoring"); LogWarn("no ID attribute on <tc>, ignoring");
} } else {
else {
int id = m_reader->getAttributeValueAsInt("ID"); int id = m_reader->getAttributeValueAsInt("ID");
t.uvs[id] = ReadVec2(); t.uvs[id] = ReadVec2();
} }
} } else if (s == "f" || s == "l" || s == "p") {
else if (s == "f" || s == "l" || s == "p") {
const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1); const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
unsigned int mid = ~0u; unsigned int mid = ~0u;
TempFace tf[3]; TempFace tf[3];
bool has[3] = {0}; bool has[3] = { 0 };
while (ReadElementUpToClosing(s.c_str())) { while (ReadElementUpToClosing(s.c_str())) {
const std::string& elemName = GetElementName(); const std::string &elemName = GetElementName();
if (elemName == "fv1" || elemName == "lv1" || elemName == "pv1") { if (elemName == "fv1" || elemName == "lv1" || elemName == "pv1") {
ReadFaceVertex(t,tf[0]); ReadFaceVertex(t, tf[0]);
has[0] = true; has[0] = true;
} else if (elemName == "fv2" || elemName == "lv2") { } else if (elemName == "fv2" || elemName == "lv2") {
ReadFaceVertex(t, tf[1]); ReadFaceVertex(t, tf[1]);
@ -646,7 +603,7 @@ bool XGLImporter::ReadMesh(TempScope& scope)
bool nor = false; bool nor = false;
bool uv = false; bool uv = false;
for(unsigned int i = 0; i < vcount; ++i) { for (unsigned int i = 0; i < vcount; ++i) {
if (!has[i]) { if (!has[i]) {
ThrowException("missing face vertex data"); ThrowException("missing face vertex data");
} }
@ -655,24 +612,24 @@ bool XGLImporter::ReadMesh(TempScope& scope)
uv = uv || tf[i].has_uv; uv = uv || tf[i].has_uv;
} }
if (mid >= (1<<30)) { if (mid >= (1 << 30)) {
LogWarn("material indices exhausted, this may cause errors in the output"); LogWarn("material indices exhausted, this may cause errors in the output");
} }
unsigned int meshId = mid | ((nor?1:0)<<31) | ((uv?1:0)<<30); unsigned int meshId = mid | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30);
TempMaterialMesh& mesh = bymat[meshId]; TempMaterialMesh &mesh = bymat[meshId];
mesh.matid = mid; mesh.matid = mid;
for(unsigned int i = 0; i < vcount; ++i) { for (unsigned int i = 0; i < vcount; ++i) {
mesh.positions.push_back(tf[i].pos); mesh.positions.push_back(tf[i].pos);
if(nor) { if (nor) {
mesh.normals.push_back(tf[i].normal); mesh.normals.push_back(tf[i].normal);
} }
if(uv) { if (uv) {
mesh.uvs.push_back(tf[i].uv); mesh.uvs.push_back(tf[i].uv);
} }
mesh.pflags |= 1 << (vcount-1); mesh.pflags |= 1 << (vcount - 1);
} }
mesh.vcounts.push_back(vcount); mesh.vcounts.push_back(vcount);
@ -681,13 +638,13 @@ bool XGLImporter::ReadMesh(TempScope& scope)
// finally extract output meshes and add them to the scope // finally extract output meshes and add them to the scope
typedef std::pair<const unsigned int, TempMaterialMesh> pairt; typedef std::pair<const unsigned int, TempMaterialMesh> pairt;
for(const pairt& p : bymat) { for (const pairt &p : bymat) {
aiMesh* const m = ToOutputMesh(p.second); aiMesh *const m = ToOutputMesh(p.second);
scope.meshes_linear.push_back(m); scope.meshes_linear.push_back(m);
// if this is a definition, keep it on the stack // if this is a definition, keep it on the stack
if(mesh_id != ~0u) { if (mesh_id != ~0u) {
scope.meshes.insert(std::pair<unsigned int, aiMesh*>(mesh_id,m)); scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
} }
} }
@ -696,26 +653,25 @@ bool XGLImporter::ReadMesh(TempScope& scope)
} }
// ---------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------
unsigned int XGLImporter::ResolveMaterialRef(TempScope& scope) unsigned int XGLImporter::ResolveMaterialRef(TempScope &scope) {
{ const std::string &s = GetElementName();
const std::string& s = GetElementName();
if (s == "mat") { if (s == "mat") {
ReadMaterial(scope); ReadMaterial(scope);
return static_cast<unsigned int>(scope.materials_linear.size()-1); return static_cast<unsigned int>(scope.materials_linear.size() - 1);
} }
const int id = ReadIndexFromText(); const int id = ReadIndexFromText();
std::map<unsigned int, aiMaterial*>::iterator it = scope.materials.find(id), end = scope.materials.end(); std::map<unsigned int, aiMaterial *>::iterator it = scope.materials.find(id), end = scope.materials.end();
if (it == end) { if (it == end) {
ThrowException("<matref> index out of range"); ThrowException("<matref> index out of range");
} }
// ok, this is n^2 and should get optimized one day // ok, this is n^2 and should get optimized one day
aiMaterial* const m = (*it).second; aiMaterial *const m = (*it).second;
unsigned int i = 0, mcount = static_cast<unsigned int>(scope.materials_linear.size()); unsigned int i = 0, mcount = static_cast<unsigned int>(scope.materials_linear.size());
for(; i < mcount; ++i) { for (; i < mcount; ++i) {
if (scope.materials_linear[i] == m) { if (scope.materials_linear[i] == m) {
return i; return i;
} }
@ -726,35 +682,30 @@ unsigned int XGLImporter::ResolveMaterialRef(TempScope& scope)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void XGLImporter::ReadMaterial(TempScope& scope) { void XGLImporter::ReadMaterial(TempScope &scope) {
const unsigned int mat_id = ReadIDAttr(); const unsigned int mat_id = ReadIDAttr();
aiMaterial *mat(new aiMaterial ); aiMaterial *mat(new aiMaterial);
while (ReadElementUpToClosing("mat")) { while (ReadElementUpToClosing("mat")) {
const std::string& s = GetElementName(); const std::string &s = GetElementName();
if (s == "amb") { if (s == "amb") {
const aiColor3D c = ReadCol3(); const aiColor3D c = ReadCol3();
mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT); mat->AddProperty(&c, 1, AI_MATKEY_COLOR_AMBIENT);
} } else if (s == "diff") {
else if (s == "diff") {
const aiColor3D c = ReadCol3(); const aiColor3D c = ReadCol3();
mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
} } else if (s == "spec") {
else if (s == "spec") {
const aiColor3D c = ReadCol3(); const aiColor3D c = ReadCol3();
mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR); mat->AddProperty(&c, 1, AI_MATKEY_COLOR_SPECULAR);
} } else if (s == "emiss") {
else if (s == "emiss") {
const aiColor3D c = ReadCol3(); const aiColor3D c = ReadCol3();
mat->AddProperty(&c,1,AI_MATKEY_COLOR_EMISSIVE); mat->AddProperty(&c, 1, AI_MATKEY_COLOR_EMISSIVE);
} } else if (s == "alpha") {
else if (s == "alpha") {
const float f = ReadFloat(); const float f = ReadFloat();
mat->AddProperty(&f,1,AI_MATKEY_OPACITY); mat->AddProperty(&f, 1, AI_MATKEY_OPACITY);
} } else if (s == "shine") {
else if (s == "shine") {
const float f = ReadFloat(); const float f = ReadFloat();
mat->AddProperty(&f,1,AI_MATKEY_SHININESS); mat->AddProperty(&f, 1, AI_MATKEY_SHININESS);
} }
} }
@ -763,13 +714,12 @@ void XGLImporter::ReadMaterial(TempScope& scope) {
} }
// ---------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------
void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out) void XGLImporter::ReadFaceVertex(const TempMesh &t, TempFace &out) {
{ const std::string &end = GetElementName();
const std::string& end = GetElementName();
bool havep = false; bool havep = false;
while (ReadElementUpToClosing(end.c_str())) { while (ReadElementUpToClosing(end.c_str())) {
const std::string& s = GetElementName(); const std::string &s = GetElementName();
if (s == "pref") { if (s == "pref") {
const unsigned int id = ReadIndexFromText(); const unsigned int id = ReadIndexFromText();
std::map<unsigned int, aiVector3D>::const_iterator it = t.points.find(id); std::map<unsigned int, aiVector3D>::const_iterator it = t.points.find(id);
@ -779,8 +729,7 @@ void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
out.pos = (*it).second; out.pos = (*it).second;
havep = true; havep = true;
} } else if (s == "nref") {
else if (s == "nref") {
const unsigned int id = ReadIndexFromText(); const unsigned int id = ReadIndexFromText();
std::map<unsigned int, aiVector3D>::const_iterator it = t.normals.find(id); std::map<unsigned int, aiVector3D>::const_iterator it = t.normals.find(id);
if (it == t.normals.end()) { if (it == t.normals.end()) {
@ -789,8 +738,7 @@ void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
out.normal = (*it).second; out.normal = (*it).second;
out.has_normal = true; out.has_normal = true;
} } else if (s == "tcref") {
else if (s == "tcref") {
const unsigned int id = ReadIndexFromText(); const unsigned int id = ReadIndexFromText();
std::map<unsigned int, aiVector2D>::const_iterator it = t.uvs.find(id); std::map<unsigned int, aiVector2D>::const_iterator it = t.uvs.find(id);
if (it == t.uvs.end()) { if (it == t.uvs.end()) {
@ -799,14 +747,11 @@ void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
out.uv = (*it).second; out.uv = (*it).second;
out.has_uv = true; out.has_uv = true;
} } else if (s == "p") {
else if (s == "p") {
out.pos = ReadVec3(); out.pos = ReadVec3();
} } else if (s == "n") {
else if (s == "n") {
out.normal = ReadVec3(); out.normal = ReadVec3();
} } else if (s == "tc") {
else if (s == "tc") {
out.uv = ReadVec2(); out.uv = ReadVec2();
} }
} }
@ -817,11 +762,10 @@ void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
unsigned int XGLImporter::ReadIDAttr() unsigned int XGLImporter::ReadIDAttr() {
{ for (int i = 0, e = m_reader->getAttributeCount(); i < e; ++i) {
for(int i = 0, e = m_reader->getAttributeCount(); i < e; ++i) {
if(!ASSIMP_stricmp(m_reader->getAttributeName(i),"id")) { if (!ASSIMP_stricmp(m_reader->getAttributeName(i), "id")) {
return m_reader->getAttributeValueAsInt(i); return m_reader->getAttributeValueAsInt(i);
} }
} }
@ -829,21 +773,20 @@ unsigned int XGLImporter::ReadIDAttr()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
float XGLImporter::ReadFloat() float XGLImporter::ReadFloat() {
{ if (!SkipToText()) {
if(!SkipToText()) {
LogError("unexpected EOF reading float element contents"); LogError("unexpected EOF reading float element contents");
return 0.f; return 0.f;
} }
const char* s = m_reader->getNodeData(), *se; const char *s = m_reader->getNodeData(), *se;
if(!SkipSpaces(&s)) { if (!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse float"); LogError("unexpected EOL, failed to parse float");
return 0.f; return 0.f;
} }
float t; float t;
se = fast_atoreal_move(s,t); se = fast_atoreal_move(s, t);
if (se == s) { if (se == s) {
LogError("failed to read float text"); LogError("failed to read float text");
@ -854,19 +797,18 @@ float XGLImporter::ReadFloat()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
unsigned int XGLImporter::ReadIndexFromText() unsigned int XGLImporter::ReadIndexFromText() {
{ if (!SkipToText()) {
if(!SkipToText()) {
LogError("unexpected EOF reading index element contents"); LogError("unexpected EOF reading index element contents");
return ~0u; return ~0u;
} }
const char* s = m_reader->getNodeData(), *se; const char *s = m_reader->getNodeData(), *se;
if(!SkipSpaces(&s)) { if (!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse index element"); LogError("unexpected EOL, failed to parse index element");
return ~0u; return ~0u;
} }
const unsigned int t = strtoul10(s,&se); const unsigned int t = strtoul10(s, &se);
if (se == s) { if (se == s) {
LogError("failed to read index"); LogError("failed to read index");
@ -877,23 +819,22 @@ unsigned int XGLImporter::ReadIndexFromText()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiVector2D XGLImporter::ReadVec2() aiVector2D XGLImporter::ReadVec2() {
{
aiVector2D vec; aiVector2D vec;
if(!SkipToText()) { if (!SkipToText()) {
LogError("unexpected EOF reading vec2 contents"); LogError("unexpected EOF reading vec2 contents");
return vec; return vec;
} }
const char* s = m_reader->getNodeData(); const char *s = m_reader->getNodeData();
ai_real v[2]; ai_real v[2];
for(int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
if(!SkipSpaces(&s)) { if (!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse vec2"); LogError("unexpected EOL, failed to parse vec2");
return vec; return vec;
} }
v[i] = fast_atof(&s); v[i] = fast_atof(&s);
SkipSpaces(&s); SkipSpaces(&s);
@ -903,25 +844,24 @@ aiVector2D XGLImporter::ReadVec2()
} }
++s; ++s;
} }
vec.x = v[0]; vec.x = v[0];
vec.y = v[1]; vec.y = v[1];
return vec; return vec;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiVector3D XGLImporter::ReadVec3() aiVector3D XGLImporter::ReadVec3() {
{
aiVector3D vec; aiVector3D vec;
if(!SkipToText()) { if (!SkipToText()) {
LogError("unexpected EOF reading vec3 contents"); LogError("unexpected EOF reading vec3 contents");
return vec; return vec;
} }
const char* s = m_reader->getNodeData(); const char *s = m_reader->getNodeData();
for(int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
if(!SkipSpaces(&s)) { if (!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse vec3"); LogError("unexpected EOL, failed to parse vec3");
return vec; return vec;
} }
@ -939,13 +879,12 @@ aiVector3D XGLImporter::ReadVec3()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiColor3D XGLImporter::ReadCol3() aiColor3D XGLImporter::ReadCol3() {
{ const aiVector3D &v = ReadVec3();
const aiVector3D& v = ReadVec3();
if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) { if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) {
LogWarn("color values out of range, ignoring"); LogWarn("color values out of range, ignoring");
} }
return aiColor3D(v.x,v.y,v.z); return aiColor3D(v.x, v.y, v.z);
} }
#endif #endif

View File

@ -47,69 +47,59 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_XGLLOADER_H_INCLUDED #define AI_XGLLOADER_H_INCLUDED
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/irrXMLWrapper.h>
#include <assimp/LogAux.h> #include <assimp/LogAux.h>
#include <assimp/material.h> #include <assimp/irrXMLWrapper.h>
#include <assimp/Importer.hpp>
#include <assimp/mesh.h>
#include <assimp/light.h> #include <assimp/light.h>
#include <memory> #include <assimp/material.h>
#include <assimp/mesh.h>
#include <assimp/Importer.hpp>
#include <map> #include <map>
#include <memory>
struct aiNode; struct aiNode;
namespace Assimp { namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** XGL/ZGL importer. /** XGL/ZGL importer.
* *
* Spec: http://vizstream.aveva.com/release/vsplatform/XGLSpec.htm * Spec: http://vizstream.aveva.com/release/vsplatform/XGLSpec.htm
*/ */
class XGLImporter : public BaseImporter, public LogFunctions<XGLImporter> class XGLImporter : public BaseImporter, public LogFunctions<XGLImporter> {
{
public: public:
XGLImporter(); XGLImporter();
~XGLImporter(); ~XGLImporter();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */ * See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const; bool checkSig) const;
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details */ * See #BaseImporter::GetInfo for the details */
const aiImporterDesc* GetInfo () const; const aiImporterDesc *GetInfo() const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details */ * See BaseImporter::InternReadFile() for details */
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile(const std::string &pFile, aiScene *pScene,
IOSystem* pIOHandler); IOSystem *pIOHandler);
private: private:
struct TempScope {
TempScope() :
light() {}
~TempScope() {
struct TempScope for (aiMesh *m : meshes_linear) {
{
TempScope()
: light()
{}
~TempScope()
{
for(aiMesh* m : meshes_linear) {
delete m; delete m;
} }
for(aiMaterial* m : materials_linear) { for (aiMaterial *m : materials_linear) {
delete m; delete m;
} }
@ -117,45 +107,41 @@ private:
} }
void dismiss() { void dismiss() {
light = NULL; light = nullptr;
meshes_linear.clear(); meshes_linear.clear();
materials_linear.clear(); materials_linear.clear();
meshes.clear(); meshes.clear();
materials.clear(); materials.clear();
} }
std::multimap<unsigned int, aiMesh*> meshes; std::multimap<unsigned int, aiMesh *> meshes;
std::map<unsigned int, aiMaterial*> materials; std::map<unsigned int, aiMaterial *> materials;
std::vector<aiMesh*> meshes_linear; std::vector<aiMesh *> meshes_linear;
std::vector<aiMaterial*> materials_linear; std::vector<aiMaterial *> materials_linear;
aiLight* light; aiLight *light;
}; };
struct SortMeshByMaterialId { struct SortMeshByMaterialId {
SortMeshByMaterialId(const TempScope& scope) : scope(scope) {} SortMeshByMaterialId(const TempScope &scope) :
scope(scope) {}
bool operator()(unsigned int a, unsigned int b) const { bool operator()(unsigned int a, unsigned int b) const {
return scope.meshes_linear[a]->mMaterialIndex < scope.meshes_linear[b]->mMaterialIndex; return scope.meshes_linear[a]->mMaterialIndex < scope.meshes_linear[b]->mMaterialIndex;
}; };
const TempScope& scope; const TempScope &scope;
}; };
struct TempMesh struct TempMesh {
{
std::map<unsigned int, aiVector3D> points; std::map<unsigned int, aiVector3D> points;
std::map<unsigned int, aiVector3D> normals; std::map<unsigned int, aiVector3D> normals;
std::map<unsigned int, aiVector2D> uvs; std::map<unsigned int, aiVector2D> uvs;
}; };
struct TempMaterialMesh struct TempMaterialMesh {
{ TempMaterialMesh() :
TempMaterialMesh() pflags(), matid() {}
: pflags()
, matid()
{}
std::vector<aiVector3D> positions, normals; std::vector<aiVector3D> positions, normals;
std::vector<aiVector2D> uvs; std::vector<aiVector2D> uvs;
@ -165,12 +151,9 @@ private:
unsigned int matid; unsigned int matid;
}; };
struct TempFace struct TempFace {
{ TempFace() :
TempFace() has_uv(), has_normal() {}
: has_uv()
, has_normal()
{}
aiVector3D pos; aiVector3D pos;
aiVector3D normal; aiVector3D normal;
@ -180,21 +163,20 @@ private:
}; };
private: private:
void Cleanup(); void Cleanup();
std::string GetElementName(); std::string GetElementName();
bool ReadElement(); bool ReadElement();
bool ReadElementUpToClosing(const char* closetag); bool ReadElementUpToClosing(const char *closetag);
bool SkipToText(); bool SkipToText();
unsigned int ReadIDAttr(); unsigned int ReadIDAttr();
void ReadWorld(TempScope& scope); void ReadWorld(TempScope &scope);
void ReadLighting(TempScope& scope); void ReadLighting(TempScope &scope);
aiLight* ReadDirectionalLight(); aiLight *ReadDirectionalLight();
aiNode* ReadObject(TempScope& scope,bool skipFirst = false,const char* closetag = "object"); aiNode *ReadObject(TempScope &scope, bool skipFirst = false, const char *closetag = "object");
bool ReadMesh(TempScope& scope); bool ReadMesh(TempScope &scope);
void ReadMaterial(TempScope& scope); void ReadMaterial(TempScope &scope);
aiVector2D ReadVec2(); aiVector2D ReadVec2();
aiVector3D ReadVec3(); aiVector3D ReadVec3();
aiColor3D ReadCol3(); aiColor3D ReadCol3();
@ -202,13 +184,13 @@ private:
unsigned int ReadIndexFromText(); unsigned int ReadIndexFromText();
float ReadFloat(); float ReadFloat();
aiMesh* ToOutputMesh(const TempMaterialMesh& m); aiMesh *ToOutputMesh(const TempMaterialMesh &m);
void ReadFaceVertex(const TempMesh& t, TempFace& out); void ReadFaceVertex(const TempMesh &t, TempFace &out);
unsigned int ResolveMaterialRef(TempScope& scope); unsigned int ResolveMaterialRef(TempScope &scope);
private: private:
std::shared_ptr<irr::io::IrrXMLReader> m_reader; std::shared_ptr<irr::io::IrrXMLReader> m_reader;
aiScene* m_scene; aiScene *m_scene;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -48,12 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h>
#include <assimp/commonMetaData.h> #include <assimp/commonMetaData.h>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
#include <memory> #include <memory>
@ -69,8 +69,7 @@ static const aiImporterDesc desc = {
"", "",
"", "",
"", "",
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
| aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
0, 0,
0, 0,
0, 0,
@ -78,11 +77,8 @@ static const aiImporterDesc desc = {
"gltf glb" "gltf glb"
}; };
glTFImporter::glTFImporter() glTFImporter::glTFImporter() :
: BaseImporter() BaseImporter(), meshOffsets(), embeddedTexIdxs(), mScene(nullptr) {
, meshOffsets()
, embeddedTexIdxs()
, mScene( nullptr ) {
// empty // empty
} }
@ -90,11 +86,11 @@ glTFImporter::~glTFImporter() {
// empty // empty
} }
const aiImporterDesc* glTFImporter::GetInfo() const { const aiImporterDesc *glTFImporter::GetInfo() const {
return &desc; return &desc;
} }
bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool /* checkSig */) const { bool glTFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const {
const std::string &extension = GetExtension(pFile); const std::string &extension = GetExtension(pFile);
if (extension != "gltf" && extension != "glb") { if (extension != "gltf" && extension != "glb") {
@ -115,9 +111,8 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
return false; return false;
} }
inline inline void SetMaterialColorProperty(std::vector<int> &embeddedTexIdxs, Asset & /*r*/, glTF::TexProperty prop, aiMaterial *mat,
void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& /*r*/, glTF::TexProperty prop, aiMaterial* mat, aiTextureType texType, const char *pKey, unsigned int type, unsigned int idx) {
aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) {
if (prop.texture) { if (prop.texture) {
if (prop.texture->source) { if (prop.texture->source) {
aiString uri(prop.texture->source->uri); aiString uri(prop.texture->source->uri);
@ -138,22 +133,22 @@ void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& /*r*/, g
} }
} }
void glTFImporter::ImportMaterials(glTF::Asset& r) { void glTFImporter::ImportMaterials(glTF::Asset &r) {
mScene->mNumMaterials = unsigned(r.materials.Size()); mScene->mNumMaterials = unsigned(r.materials.Size());
mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials]; mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial(); aiMaterial *aimat = mScene->mMaterials[i] = new aiMaterial();
Material& mat = r.materials[i]; Material &mat = r.materials[i];
/*if (!mat.name.empty())*/ { /*if (!mat.name.empty())*/ {
aiString str(mat.id /*mat.name*/); aiString str(mat.id /*mat.name*/);
aimat->AddProperty(&str, AI_MATKEY_NAME); aimat->AddProperty(&str, AI_MATKEY_NAME);
} }
SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT ); SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE ); SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE);
SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR);
SetMaterialColorProperty(embeddedTexIdxs, r, mat.emission, aimat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); SetMaterialColorProperty(embeddedTexIdxs, r, mat.emission, aimat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE);
@ -172,29 +167,25 @@ void glTFImporter::ImportMaterials(glTF::Asset& r) {
mScene->mNumMaterials = 1; mScene->mNumMaterials = 1;
// Delete the array of length zero created above. // Delete the array of length zero created above.
delete[] mScene->mMaterials; delete[] mScene->mMaterials;
mScene->mMaterials = new aiMaterial*[1]; mScene->mMaterials = new aiMaterial *[1];
mScene->mMaterials[0] = new aiMaterial(); mScene->mMaterials[0] = new aiMaterial();
} }
} }
static inline void SetFace(aiFace &face, int a) {
static inline void SetFace(aiFace& face, int a)
{
face.mNumIndices = 1; face.mNumIndices = 1;
face.mIndices = new unsigned int[1]; face.mIndices = new unsigned int[1];
face.mIndices[0] = a; face.mIndices[0] = a;
} }
static inline void SetFace(aiFace& face, int a, int b) static inline void SetFace(aiFace &face, int a, int b) {
{
face.mNumIndices = 2; face.mNumIndices = 2;
face.mIndices = new unsigned int[2]; face.mIndices = new unsigned int[2];
face.mIndices[0] = a; face.mIndices[0] = a;
face.mIndices[1] = b; face.mIndices[1] = b;
} }
static inline void SetFace(aiFace& face, int a, int b, int c) static inline void SetFace(aiFace &face, int a, int b, int c) {
{
face.mNumIndices = 3; face.mNumIndices = 3;
face.mIndices = new unsigned int[3]; face.mIndices = new unsigned int[3];
face.mIndices[0] = a; face.mIndices[0] = a;
@ -202,9 +193,7 @@ static inline void SetFace(aiFace& face, int a, int b, int c)
face.mIndices[2] = c; face.mIndices[2] = c;
} }
#ifdef ASSIMP_BUILD_DEBUG static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsigned nVerts) {
static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts)
{
for (unsigned i = 0; i < nFaces; ++i) { for (unsigned i = 0; i < nFaces; ++i) {
for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
unsigned idx = faces[i].mIndices[j]; unsigned idx = faces[i].mIndices[j];
@ -214,105 +203,98 @@ static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsign
} }
return true; return true;
} }
#endif // ASSIMP_BUILD_DEBUG
void glTFImporter::ImportMeshes(glTF::Asset& r) void glTFImporter::ImportMeshes(glTF::Asset &r) {
{ std::vector<aiMesh *> meshes;
std::vector<aiMesh*> meshes;
unsigned int k = 0; unsigned int k = 0;
meshOffsets.clear(); meshOffsets.clear();
for (unsigned int m = 0; m < r.meshes.Size(); ++m) { for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
Mesh& mesh = r.meshes[m]; Mesh &mesh = r.meshes[m];
// Check if mesh extensions is used // Check if mesh extensions is used
if(mesh.Extension.size() > 0) if (mesh.Extension.size() > 0) {
{ for (Mesh::SExtension *cur_ext : mesh.Extension) {
for(Mesh::SExtension* cur_ext : mesh.Extension)
{
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
if(cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) if (cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) {
{ // Limitations for meshes when using Open3DGC-compression.
// Limitations for meshes when using Open3DGC-compression. // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive?
// It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive? // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can
// Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression"
// point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression" // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives.
// is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives. // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem.
// Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem. // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor
// Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor // of primitive must point to one continuous region of the buffer.
// of primitive must point to one continuous region of the buffer. if (mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed.");
if(mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed.");
Mesh::SCompression_Open3DGC* o3dgc_ext = (Mesh::SCompression_Open3DGC*)cur_ext; Mesh::SCompression_Open3DGC *o3dgc_ext = (Mesh::SCompression_Open3DGC *)cur_ext;
Ref<Buffer> buf = r.buffers.Get(o3dgc_ext->Buffer); Ref<Buffer> buf = r.buffers.Get(o3dgc_ext->Buffer);
buf->EncodedRegion_SetCurrent(mesh.id); buf->EncodedRegion_SetCurrent(mesh.id);
} } else
else
#endif #endif
{ {
throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) + throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) +
"\"), only Open3DGC is supported."); "\"), only Open3DGC is supported.");
} }
} }
}// if(mesh.Extension.size() > 0) } // if(mesh.Extension.size() > 0)
meshOffsets.push_back(k); meshOffsets.push_back(k);
k += unsigned(mesh.primitives.size()); k += unsigned(mesh.primitives.size());
for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
Mesh::Primitive& prim = mesh.primitives[p]; Mesh::Primitive &prim = mesh.primitives[p];
aiMesh* aim = new aiMesh(); aiMesh *aim = new aiMesh();
meshes.push_back(aim); meshes.push_back(aim);
aim->mName = mesh.id; aim->mName = mesh.id;
if (mesh.primitives.size() > 1) { if (mesh.primitives.size() > 1) {
ai_uint32& len = aim->mName.length; ai_uint32 &len = aim->mName.length;
aim->mName.data[len] = '-'; aim->mName.data[len] = '-';
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
} }
switch (prim.mode) { switch (prim.mode) {
case PrimitiveMode_POINTS: case PrimitiveMode_POINTS:
aim->mPrimitiveTypes |= aiPrimitiveType_POINT; aim->mPrimitiveTypes |= aiPrimitiveType_POINT;
break; break;
case PrimitiveMode_LINES: case PrimitiveMode_LINES:
case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: case PrimitiveMode_LINE_STRIP:
aim->mPrimitiveTypes |= aiPrimitiveType_LINE; aim->mPrimitiveTypes |= aiPrimitiveType_LINE;
break; break;
case PrimitiveMode_TRIANGLES: case PrimitiveMode_TRIANGLES:
case PrimitiveMode_TRIANGLE_STRIP: case PrimitiveMode_TRIANGLE_STRIP:
case PrimitiveMode_TRIANGLE_FAN: case PrimitiveMode_TRIANGLE_FAN:
aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
break; break;
} }
Mesh::Primitive::Attributes& attr = prim.attributes; Mesh::Primitive::Attributes &attr = prim.attributes;
if (attr.position.size() > 0 && attr.position[0]) { if (attr.position.size() > 0 && attr.position[0]) {
aim->mNumVertices = attr.position[0]->count; aim->mNumVertices = attr.position[0]->count;
attr.position[0]->ExtractData(aim->mVertices); attr.position[0]->ExtractData(aim->mVertices);
} }
if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals);
for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
aiVector3D* values = aim->mTextureCoords[tc]; aiVector3D *values = aim->mTextureCoords[tc];
for (unsigned int i = 0; i < aim->mNumVertices; ++i) { for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
values[i].y = 1 - values[i].y; // Flip Y coords values[i].y = 1 - values[i].y; // Flip Y coords
} }
} }
aiFace *faces = 0;
aiFace* faces = 0;
unsigned int nFaces = 0; unsigned int nFaces = 0;
if (prim.indices) { if (prim.indices) {
@ -322,76 +304,75 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
ai_assert(data.IsValid()); ai_assert(data.IsValid());
switch (prim.mode) { switch (prim.mode) {
case PrimitiveMode_POINTS: { case PrimitiveMode_POINTS: {
nFaces = count; nFaces = count;
faces = new aiFace[nFaces]; faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) { for (unsigned int i = 0; i < count; ++i) {
SetFace(faces[i], data.GetUInt(i)); SetFace(faces[i], data.GetUInt(i));
}
break;
} }
break;
case PrimitiveMode_LINES: {
nFaces = count / 2;
if (nFaces * 2 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
count = nFaces * 2;
}
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1));
}
break;
}
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1));
for (unsigned int i = 2; i < count; ++i) {
SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i));
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
if (nFaces * 3 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
count = nFaces * 3;
}
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i));
}
break;
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i));
}
break;
} }
}
else { // no indices provided so directly generate from counts
// use the already determined count as it includes checks case PrimitiveMode_LINES: {
nFaces = count / 2;
if (nFaces * 2 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
count = nFaces * 2;
}
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1));
}
break;
}
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1));
for (unsigned int i = 2; i < count; ++i) {
SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i));
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
if (nFaces * 3 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
count = nFaces * 3;
}
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i));
}
break;
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i));
}
break;
}
} else { // no indices provided so directly generate from counts
// use the already determined count as it includes checks
unsigned int count = aim->mNumVertices; unsigned int count = aim->mNumVertices;
switch (prim.mode) { switch (prim.mode) {
@ -466,7 +447,11 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
if (faces) { if (faces) {
aim->mFaces = faces; aim->mFaces = faces;
aim->mNumFaces = nFaces; aim->mNumFaces = nFaces;
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); const bool validRes = CheckValidFacesIndices(faces, nFaces, aim->mNumVertices);
if (!validRes) {
ai_assert(validRes);
ASSIMP_LOG_WARN("Invalid number of faces detected.");
}
} }
if (prim.material) { if (prim.material) {
@ -480,22 +465,22 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
} }
void glTFImporter::ImportCameras(glTF::Asset& r) { void glTFImporter::ImportCameras(glTF::Asset &r) {
if (!r.cameras.Size()) { if (!r.cameras.Size()) {
return; return;
} }
mScene->mNumCameras = r.cameras.Size(); mScene->mNumCameras = r.cameras.Size();
mScene->mCameras = new aiCamera*[r.cameras.Size()]; mScene->mCameras = new aiCamera *[r.cameras.Size()];
for (size_t i = 0; i < r.cameras.Size(); ++i) { for (size_t i = 0; i < r.cameras.Size(); ++i) {
Camera& cam = r.cameras[i]; Camera &cam = r.cameras[i];
aiCamera* aicam = mScene->mCameras[i] = new aiCamera(); aiCamera *aicam = mScene->mCameras[i] = new aiCamera();
if (cam.type == Camera::Perspective) { if (cam.type == Camera::Perspective) {
aicam->mAspect = cam.perspective.aspectRatio; aicam->mAspect = cam.perspective.aspectRatio;
aicam->mHorizontalFOV = cam.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect); aicam->mHorizontalFOV = cam.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect);
aicam->mClipPlaneFar = cam.perspective.zfar; aicam->mClipPlaneFar = cam.perspective.zfar;
aicam->mClipPlaneNear = cam.perspective.znear; aicam->mClipPlaneNear = cam.perspective.znear;
} else { } else {
aicam->mClipPlaneFar = cam.ortographic.zfar; aicam->mClipPlaneFar = cam.ortographic.zfar;
@ -509,30 +494,33 @@ void glTFImporter::ImportCameras(glTF::Asset& r) {
} }
} }
void glTFImporter::ImportLights(glTF::Asset& r) void glTFImporter::ImportLights(glTF::Asset &r) {
{
if (!r.lights.Size()) return; if (!r.lights.Size()) return;
mScene->mNumLights = r.lights.Size(); mScene->mNumLights = r.lights.Size();
mScene->mLights = new aiLight*[r.lights.Size()]; mScene->mLights = new aiLight *[r.lights.Size()];
for (size_t i = 0; i < r.lights.Size(); ++i) { for (size_t i = 0; i < r.lights.Size(); ++i) {
Light& l = r.lights[i]; Light &l = r.lights[i];
aiLight* ail = mScene->mLights[i] = new aiLight(); aiLight *ail = mScene->mLights[i] = new aiLight();
switch (l.type) { switch (l.type) {
case Light::Type_directional: case Light::Type_directional:
ail->mType = aiLightSource_DIRECTIONAL; break; ail->mType = aiLightSource_DIRECTIONAL;
break;
case Light::Type_spot: case Light::Type_spot:
ail->mType = aiLightSource_SPOT; break; ail->mType = aiLightSource_SPOT;
break;
case Light::Type_ambient: case Light::Type_ambient:
ail->mType = aiLightSource_AMBIENT; break; ail->mType = aiLightSource_AMBIENT;
break;
default: // Light::Type_point default: // Light::Type_point
ail->mType = aiLightSource_POINT; break; ail->mType = aiLightSource_POINT;
break;
} }
CopyValue(l.color, ail->mColorAmbient); CopyValue(l.color, ail->mColorAmbient);
@ -542,35 +530,32 @@ void glTFImporter::ImportLights(glTF::Asset& r)
ail->mAngleOuterCone = l.falloffAngle; ail->mAngleOuterCone = l.falloffAngle;
ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all
ail->mAttenuationConstant = l.constantAttenuation; ail->mAttenuationConstant = l.constantAttenuation;
ail->mAttenuationLinear = l.linearAttenuation; ail->mAttenuationLinear = l.linearAttenuation;
ail->mAttenuationQuadratic = l.quadraticAttenuation; ail->mAttenuationQuadratic = l.quadraticAttenuation;
} }
} }
aiNode *ImportNode(aiScene *pScene, glTF::Asset &r, std::vector<unsigned int> &meshOffsets, glTF::Ref<glTF::Node> &ptr) {
Node &node = *ptr;
aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector<unsigned int>& meshOffsets, glTF::Ref<glTF::Node>& ptr) aiNode *ainode = new aiNode(node.id);
{
Node& node = *ptr;
aiNode* ainode = new aiNode(node.id);
if (!node.children.empty()) { if (!node.children.empty()) {
ainode->mNumChildren = unsigned(node.children.size()); ainode->mNumChildren = unsigned(node.children.size());
ainode->mChildren = new aiNode*[ainode->mNumChildren]; ainode->mChildren = new aiNode *[ainode->mNumChildren];
for (unsigned int i = 0; i < ainode->mNumChildren; ++i) { for (unsigned int i = 0; i < ainode->mNumChildren; ++i) {
aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]); aiNode *child = ImportNode(pScene, r, meshOffsets, node.children[i]);
child->mParent = ainode; child->mParent = ainode;
ainode->mChildren[i] = child; ainode->mChildren[i] = child;
} }
} }
aiMatrix4x4& matrix = ainode->mTransformation; aiMatrix4x4 &matrix = ainode->mTransformation;
if (node.matrix.isPresent) { if (node.matrix.isPresent) {
CopyValue(node.matrix.value, matrix); CopyValue(node.matrix.value, matrix);
} } else {
else {
if (node.translation.isPresent) { if (node.translation.isPresent) {
aiVector3D trans; aiVector3D trans;
CopyValue(node.translation.value, trans); CopyValue(node.translation.value, trans);
@ -587,7 +572,6 @@ aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector<unsigned int>& m
matrix = s * matrix; matrix = s * matrix;
} }
if (node.rotation.isPresent) { if (node.rotation.isPresent) {
aiQuaternion rot; aiQuaternion rot;
CopyValue(node.rotation.value, rot); CopyValue(node.rotation.value, rot);
@ -625,22 +609,20 @@ aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector<unsigned int>& m
return ainode; return ainode;
} }
void glTFImporter::ImportNodes(glTF::Asset& r) void glTFImporter::ImportNodes(glTF::Asset &r) {
{
if (!r.scene) return; if (!r.scene) return;
std::vector< Ref<Node> > rootNodes = r.scene->nodes; std::vector<Ref<Node>> rootNodes = r.scene->nodes;
// The root nodes // The root nodes
unsigned int numRootNodes = unsigned(rootNodes.size()); unsigned int numRootNodes = unsigned(rootNodes.size());
if (numRootNodes == 1) { // a single root node: use it if (numRootNodes == 1) { // a single root node: use it
mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]); mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
} } else if (numRootNodes > 1) { // more than one root node: create a fake root
else if (numRootNodes > 1) { // more than one root node: create a fake root aiNode *root = new aiNode("ROOT");
aiNode* root = new aiNode("ROOT"); root->mChildren = new aiNode *[numRootNodes];
root->mChildren = new aiNode*[numRootNodes];
for (unsigned int i = 0; i < numRootNodes; ++i) { for (unsigned int i = 0; i < numRootNodes; ++i) {
aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); aiNode *node = ImportNode(mScene, r, meshOffsets, rootNodes[i]);
node->mParent = root; node->mParent = root;
root->mChildren[root->mNumChildren++] = node; root->mChildren[root->mNumChildren++] = node;
} }
@ -652,8 +634,7 @@ void glTFImporter::ImportNodes(glTF::Asset& r)
//} //}
} }
void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) void glTFImporter::ImportEmbeddedTextures(glTF::Asset &r) {
{
embeddedTexIdxs.resize(r.images.Size(), -1); embeddedTexIdxs.resize(r.images.Size(), -1);
int numEmbeddedTexs = 0; int numEmbeddedTexs = 0;
@ -665,7 +646,7 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r)
if (numEmbeddedTexs == 0) if (numEmbeddedTexs == 0)
return; return;
mScene->mTextures = new aiTexture*[numEmbeddedTexs]; mScene->mTextures = new aiTexture *[numEmbeddedTexs];
// Add the embedded textures // Add the embedded textures
for (size_t i = 0; i < r.images.Size(); ++i) { for (size_t i = 0; i < r.images.Size(); ++i) {
@ -675,18 +656,18 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r)
int idx = mScene->mNumTextures++; int idx = mScene->mNumTextures++;
embeddedTexIdxs[i] = idx; embeddedTexIdxs[i] = idx;
aiTexture* tex = mScene->mTextures[idx] = new aiTexture(); aiTexture *tex = mScene->mTextures[idx] = new aiTexture();
size_t length = img.GetDataLength(); size_t length = img.GetDataLength();
void* data = img.StealData(); void *data = img.StealData();
tex->mFilename = img.name; tex->mFilename = img.name;
tex->mWidth = static_cast<unsigned int>(length); tex->mWidth = static_cast<unsigned int>(length);
tex->mHeight = 0; tex->mHeight = 0;
tex->pcData = reinterpret_cast<aiTexel*>(data); tex->pcData = reinterpret_cast<aiTexel *>(data);
if (!img.mimeType.empty()) { if (!img.mimeType.empty()) {
const char* ext = strchr(img.mimeType.c_str(), '/') + 1; const char *ext = strchr(img.mimeType.c_str(), '/') + 1;
if (ext) { if (ext) {
if (strcmp(ext, "jpeg") == 0) ext = "jpg"; if (strcmp(ext, "jpeg") == 0) ext = "jpg";
@ -699,32 +680,26 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r)
} }
} }
void glTFImporter::ImportCommonMetadata(glTF::Asset& a) void glTFImporter::ImportCommonMetadata(glTF::Asset &a) {
{
ai_assert(mScene->mMetaData == nullptr); ai_assert(mScene->mMetaData == nullptr);
const bool hasVersion = !a.asset.version.empty(); const bool hasVersion = !a.asset.version.empty();
const bool hasGenerator = !a.asset.generator.empty(); const bool hasGenerator = !a.asset.generator.empty();
const bool hasCopyright = !a.asset.copyright.empty(); const bool hasCopyright = !a.asset.copyright.empty();
if (hasVersion || hasGenerator || hasCopyright) if (hasVersion || hasGenerator || hasCopyright) {
{
mScene->mMetaData = new aiMetadata; mScene->mMetaData = new aiMetadata;
if (hasVersion) if (hasVersion) {
{
mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version));
} }
if (hasGenerator) if (hasGenerator) {
{
mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator));
} }
if (hasCopyright) if (hasCopyright) {
{
mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright)); mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright));
} }
} }
} }
void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) void glTFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
{
// clean all member arrays // clean all member arrays
meshOffsets.clear(); meshOffsets.clear();
embeddedTexIdxs.clear(); embeddedTexIdxs.clear();
@ -735,7 +710,6 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS
glTF::Asset asset(pIOHandler); glTF::Asset asset(pIOHandler);
asset.Load(pFile, GetExtension(pFile) == "glb"); asset.Load(pFile, GetExtension(pFile) == "glb");
// //
// Copy the data out // Copy the data out
// //
@ -757,4 +731,3 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS
} }
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER

View File

@ -48,108 +48,96 @@ Assimp C export interface. See Exporter.cpp for some notes.
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
#include "CInterfaceIOWrapper.h" #include "CInterfaceIOWrapper.h"
#include <assimp/SceneCombiner.h>
#include "Common/ScenePrivate.h" #include "Common/ScenePrivate.h"
#include <assimp/SceneCombiner.h>
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
using namespace Assimp; using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API size_t aiGetExportFormatCount(void) ASSIMP_API size_t aiGetExportFormatCount(void) {
{
return Exporter().GetExportFormatCount(); return Exporter().GetExportFormatCount();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index) ASSIMP_API const aiExportFormatDesc *aiGetExportFormatDescription(size_t index) {
{
// Note: this is valid as the index always pertains to a built-in exporter, // Note: this is valid as the index always pertains to a built-in exporter,
// for which the returned structure is guaranteed to be of static storage duration. // for which the returned structure is guaranteed to be of static storage duration.
Exporter exporter; Exporter exporter;
const aiExportFormatDesc* orig( exporter.GetExportFormatDescription( index ) ); const aiExportFormatDesc *orig(exporter.GetExportFormatDescription(index));
if (NULL == orig) { if (nullptr == orig) {
return NULL; return nullptr;
} }
aiExportFormatDesc *desc = new aiExportFormatDesc; aiExportFormatDesc *desc = new aiExportFormatDesc;
desc->description = new char[ strlen( orig->description ) + 1 ](); desc->description = new char[strlen(orig->description) + 1]();
::memcpy( (char*) desc->description, orig->description, strlen( orig->description ) ); ::memcpy((char *)desc->description, orig->description, strlen(orig->description));
desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ](); desc->fileExtension = new char[strlen(orig->fileExtension) + 1]();
::memcpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) ); ::memcpy((char *)desc->fileExtension, orig->fileExtension, strlen(orig->fileExtension));
desc->id = new char[ strlen( orig->id ) + 1 ](); desc->id = new char[strlen(orig->id) + 1]();
::memcpy( ( char* ) desc->id, orig->id, strlen( orig->id ) ); ::memcpy((char *)desc->id, orig->id, strlen(orig->id));
return desc; return desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiReleaseExportFormatDescription( const aiExportFormatDesc *desc ) { ASSIMP_API void aiReleaseExportFormatDescription(const aiExportFormatDesc *desc) {
if (NULL == desc) { if (nullptr == desc) {
return; return;
} }
delete [] desc->description; delete[] desc->description;
delete [] desc->fileExtension; delete[] desc->fileExtension;
delete [] desc->id; delete[] desc->id;
delete desc; delete desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut) ASSIMP_API void aiCopyScene(const aiScene *pIn, aiScene **pOut) {
{
if (!pOut || !pIn) { if (!pOut || !pIn) {
return; return;
} }
SceneCombiner::CopyScene(pOut,pIn,true); SceneCombiner::CopyScene(pOut, pIn, true);
ScenePriv(*pOut)->mIsCopy = true; ScenePriv(*pOut)->mIsCopy = true;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn) ASSIMP_API void aiFreeScene(const C_STRUCT aiScene *pIn) {
{
// note: aiReleaseImport() is also able to delete scene copies, but in addition // note: aiReleaseImport() is also able to delete scene copies, but in addition
// it also handles scenes with import metadata. // it also handles scenes with import metadata.
delete pIn; delete pIn;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing ) ASSIMP_API aiReturn aiExportScene(const aiScene *pScene, const char *pFormatId, const char *pFileName, unsigned int pPreprocessing) {
{ return ::aiExportSceneEx(pScene, pFormatId, pFileName, nullptr, pPreprocessing);
return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing ) ASSIMP_API aiReturn aiExportSceneEx(const aiScene *pScene, const char *pFormatId, const char *pFileName, aiFileIO *pIO, unsigned int pPreprocessing) {
{
Exporter exp; Exporter exp;
if (pIO) { if (pIO) {
exp.SetIOHandler(new CIOSystemWrapper(pIO)); exp.SetIOHandler(new CIOSystemWrapper(pIO));
} }
return exp.Export(pScene,pFormatId,pFileName,pPreprocessing); return exp.Export(pScene, pFormatId, pFileName, pPreprocessing);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing ) ASSIMP_API const C_STRUCT aiExportDataBlob *aiExportSceneToBlob(const aiScene *pScene, const char *pFormatId, unsigned int pPreprocessing) {
{
Exporter exp; Exporter exp;
if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) { if (!exp.ExportToBlob(pScene, pFormatId, pPreprocessing)) {
return NULL; return nullptr;
} }
const aiExportDataBlob* blob = exp.GetOrphanedBlob(); const aiExportDataBlob *blob = exp.GetOrphanedBlob();
ai_assert(blob); ai_assert(blob);
return blob; return blob;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData ) ASSIMP_API C_STRUCT void aiReleaseExportBlob(const aiExportDataBlob *pData) {
{
delete pData; delete pData;
} }

View File

@ -116,7 +116,7 @@ char CIOSystemWrapper::getOsSeparator() const {
IOStream *CIOSystemWrapper::Open(const char *pFile, const char *pMode) { IOStream *CIOSystemWrapper::Open(const char *pFile, const char *pMode) {
aiFile *p = mFileSystem->OpenProc(mFileSystem, pFile, pMode); aiFile *p = mFileSystem->OpenProc(mFileSystem, pFile, pMode);
if (!p) { if (!p) {
return NULL; return nullptr;
} }
return new CIOStreamWrapper(p, this); return new CIOStreamWrapper(p, this);
} }

View File

@ -199,6 +199,7 @@ SET( Common_SRCS
Common/simd.h Common/simd.h
Common/simd.cpp Common/simd.cpp
Common/material.cpp Common/material.cpp
Common/AssertHandler.cpp
) )
SOURCE_GROUP(Common FILES ${Common_SRCS}) SOURCE_GROUP(Common FILES ${Common_SRCS})

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