Rollup to upstream/master

pull/3336/head
RichardTea 2020-07-01 16:28:00 +01:00
commit 9e27fb3b89
415 changed files with 15504 additions and 33064 deletions

View File

@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

6
.gitignore vendored
View File

@ -79,6 +79,12 @@ test/gtest/src/gtest-stamp/Debug/
tools/assimp_view/assimp_viewer.vcxproj.user tools/assimp_view/assimp_viewer.vcxproj.user
*.pyc *.pyc
### Rust ###
# Generated by Cargo; will have compiled files and executables
port/assimp_rs/target/
# Backup files generated by rustfmt
port/assimp_rs/**/*.rs.bk
# Unix editor backups # Unix editor backups
*~ *~
test/gtest/src/gtest-stamp/gtest-gitinfo.txt test/gtest/src/gtest-stamp/gtest-gitinfo.txt

107
Readme.md
View File

@ -25,107 +25,12 @@ Additionally, assimp features various __mesh post processing tools__: normals an
This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases). This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
Monthly donations via Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
<br>
One-off donations via PayPal:
<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
<br>
Please check our Wiki as well: https://github.com/assimp/assimp/wiki Please check our Wiki as well: https://github.com/assimp/assimp/wiki
If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
#### Supported file formats #### #### Supported file formats ####
You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
__Importers__:
- 3D
- [3DS](https://en.wikipedia.org/wiki/.3ds)
- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format)
- AC
- [AC3D](https://en.wikipedia.org/wiki/AC3D)
- ACC
- AMJ
- ASE
- ASK
- B3D
- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format))
- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy)
- CMS
- COB
- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA)
- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF)
- ENFF
- [FBX](https://en.wikipedia.org/wiki/FBX)
- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB
- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0):
At the moment for glTF2.0 the following extensions are supported:
+ KHR_lights_punctual ( 5.0 )
+ KHR_materials_pbrSpecularGlossiness ( 5.0 )
+ KHR_materials_unlit ( 5.0 )
+ KHR_texture_transform ( 5.1 under test )
- HMB
- IFC-STEP
- IRR / IRRMESH
- [LWO](https://en.wikipedia.org/wiki/LightWave_3D)
- LWS
- LXO
- [M3D](https://bztsrc.gitlab.io/model3d)
- MD2
- MD3
- MD5
- MDC
- MDL
- MESH / MESH.XML
- MOT
- MS3D
- NDO
- NFF
- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format))
- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange)
- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format))
- PMX
- PRJ
- Q3O
- Q3S
- RAW
- SCN
- SIB
- SMD
- [STP](https://en.wikipedia.org/wiki/ISO_10303-21)
- [STL](https://en.wikipedia.org/wiki/STL_(file_format))
- TER
- UC
- VTA
- X
- [X3D](https://en.wikipedia.org/wiki/X3D)
- XGL
- ZGL
Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) IMporting geometry + node hierarchy are currently supported
__Exporters__:
- DAE (Collada)
- STL
- OBJ
- PLY
- X
- 3DS
- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN
- STEP
- glTF 1.0 (partial)
- glTF 2.0 (partial)
- 3MF ( experimental )
- FBX ( experimental )
### Building ### ### Building ###
Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do. Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
@ -196,6 +101,16 @@ Become a financial contributor and help us sustain our community. [[Contribute](
<a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a> <a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a>
Monthly donations via Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
<br>
One-off donations via PayPal:
<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
<br>
#### Organizations #### Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)] Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)]

View File

@ -73,6 +73,9 @@ else()
else() else()
set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
endif() endif()
# Import target "assimp::assimp" for configuration "Debug"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(assimp::assimp PROPERTIES set_target_properties(assimp::assimp PROPERTIES
IMPORTED_SONAME_DEBUG "${sharedLibraryName}" IMPORTED_SONAME_DEBUG "${sharedLibraryName}"
IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}"
@ -81,6 +84,9 @@ else()
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" )
else() else()
set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@") set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
# Import target "assimp::assimp" for configuration "Debug"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(assimp::assimp PROPERTIES set_target_properties(assimp::assimp PROPERTIES
IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}" IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
) )

View File

@ -73,6 +73,9 @@ else()
else() else()
set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
endif() endif()
# Import target "assimp::assimp" for configuration "Release"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(assimp::assimp PROPERTIES set_target_properties(assimp::assimp PROPERTIES
IMPORTED_SONAME_RELEASE "${sharedLibraryName}" IMPORTED_SONAME_RELEASE "${sharedLibraryName}"
IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}"
@ -81,6 +84,9 @@ else()
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" )
else() else()
set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@") set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
# Import target "assimp::assimp" for configuration "Release"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(assimp::assimp PROPERTIES set_target_properties(assimp::assimp PROPERTIES
IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}" IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
) )

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

@ -539,7 +539,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
ai_assert(nullptr != anim); ai_assert(nullptr != anim);
if (pcIn->aCameraRollKeys.size() > 1) { if (pcIn->aCameraRollKeys.size() > 1) {
ASSIMP_LOG_DEBUG("3DS: Converting camera roll track ..."); ASSIMP_LOG_VERBOSE_DEBUG("3DS: Converting camera roll track ...");
// Camera roll keys - in fact they're just rotations // Camera roll keys - in fact they're just rotations
// around the camera's z axis. The angles are given // around the camera's z axis. The angles are given
@ -558,7 +558,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
#if 0 #if 0
if (pcIn->aTargetPositionKeys.size() > 1) if (pcIn->aTargetPositionKeys.size() > 1)
{ {
ASSIMP_LOG_DEBUG("3DS: Converting target track ..."); ASSIMP_LOG_VERBOSE_DEBUG("3DS: Converting target track ...");
// Camera or spot light - need to convert the separate // Camera or spot light - need to convert the separate
// target position channel to our representation // target position channel to our representation

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,12 +462,10 @@ 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)),
@ -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 {
@ -71,22 +71,18 @@ 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);
} }
} }
@ -118,9 +114,8 @@ 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 + ".");
@ -131,12 +126,15 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
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] == '/') {
@ -147,7 +145,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
} }
} }
ASSIMP_LOG_DEBUG(rootFile); ASSIMP_LOG_VERBOSE_DEBUG(rootFile);
mZipArchive->Close(fileStream); mZipArchive->Close(fileStream);
@ -162,7 +160,6 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
} else { } else {
ASSIMP_LOG_WARN_F("Ignored file of unknown type: ", file); ASSIMP_LOG_WARN_F("Ignored file of unknown type: ", file);
} }
} }
} }

View File

@ -207,7 +207,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1); light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
obj.name = std::string(light->mName.data); obj.name = std::string(light->mName.data);
ASSIMP_LOG_DEBUG("AC3D: Light source encountered"); ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered");
obj.type = Object::Light; obj.type = Object::Light;
} else if (!ASSIMP_strincmp(buffer, "group", 5)) { } else if (!ASSIMP_strincmp(buffer, "group", 5)) {
obj.type = Object::Group; obj.type = Object::Group;
@ -294,7 +294,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
// example writes no surf chunks // example writes no surf chunks
if (!Q3DWorkAround) { if (!Q3DWorkAround) {
ASSIMP_LOG_WARN("AC3D: SURF token was expected"); ASSIMP_LOG_WARN("AC3D: SURF token was expected");
ASSIMP_LOG_DEBUG("Continuing with Quick3D Workaround enabled"); ASSIMP_LOG_VERBOSE_DEBUG("Continuing with Quick3D Workaround enabled");
} }
--buffer; // make sure the line is processed a second time --buffer; // make sure the line is processed a second time
// break; --- see fix notes above // break; --- see fix notes above
@ -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

@ -1,4 +1,4 @@
/* /*
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
/* /*
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
/* /*
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
/* /*
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------

View File

@ -614,7 +614,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
node->mNumChildren++; node->mNumChildren++;
// What we did is so great, it is at least worth a debug message // What we did is so great, it is at least worth a debug message
ASSIMP_LOG_DEBUG("ASE: Generating separate target node (" + snode->mName + ")"); ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (" + snode->mName + ")");
} }
} }

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
@ -66,16 +65,15 @@ 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
} }
@ -93,18 +91,15 @@ 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,10 +116,8 @@ 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;
@ -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
} }
@ -196,12 +189,13 @@ struct Animation {
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
} }
@ -246,10 +240,8 @@ struct BaseNode {
} 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,13 +281,8 @@ 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()
, mBoneVertices()
, mBones()
, iMaterialIndex(Face::DEFAULT_MATINDEX)
, bSkip (false) {
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) { 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;
}; };
@ -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.
@ -428,9 +404,7 @@ public:
//! 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();
@ -646,7 +620,6 @@ private:
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;
@ -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];
@ -493,37 +493,30 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) { for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) {
aiMatrix4x4 temp; aiMatrix4x4 temp;
aiMatrix3x3 rotMatrix; aiMatrix3x3 rotMatrix;
for (BVHLoader::ChannelType channel = Channel_RotationX; channel <= Channel_RotationZ; channel = (BVHLoader::ChannelType)(channel + 1)) { for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++ channelIdx) {
//Find channel in node switch (node.mChannels[channelIdx]) {
std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
if (mapIter == channelMap.end())
throw DeadlyImportError("Missing rotation channel in node " + nodeName);
else {
int channelIdx = mapIter->second;
// translate ZXY euler angels into a quaternion
const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
// Compute rotation transformations in the right order
switch (channel) {
case Channel_RotationX: case Channel_RotationX:
aiMatrix4x4::RotationX(angle, temp); {
rotMatrix *= aiMatrix3x3(temp); const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp);
}
break; break;
case Channel_RotationY: case Channel_RotationY:
aiMatrix4x4::RotationY(angle, temp); {
rotMatrix *= aiMatrix3x3(temp); const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp);
}
break; break;
case Channel_RotationZ: case Channel_RotationZ:
aiMatrix4x4::RotationZ(angle, temp); {
rotMatrix *= aiMatrix3x3(temp); const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp);
}
break; break;
default: default:
break; break;
} }
} }
}
rotkey->mTime = double(fr); rotkey->mTime = double(fr);
rotkey->mValue = aiQuaternion(rotMatrix); rotkey->mValue = aiQuaternion(rotMatrix);
++rotkey; ++rotkey;

View File

@ -353,7 +353,7 @@ void SectionParser ::Next() {
} }
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #ifdef ASSIMP_BUILD_BLENDER_DEBUG
ASSIMP_LOG_DEBUG(current.id); ASSIMP_LOG_VERBOSE_DEBUG(current.id);
#endif #endif
} }

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

@ -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,
@ -70,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];
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -239,11 +238,13 @@ bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
try { try {
f = &(*this)[name]; f = &(*this)[name];
#ifdef _DEBUG
// sanity check, should never happen if the genblenddna script is right // sanity check, should never happen if the genblenddna script is right
if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) { if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
throw Error((Formatter::format(),"Field `",name,"` of structure `", throw Error((Formatter::format(),"Field `",name,"` of structure `",
this->name,"` ought to be a pointer AND an array")); this->name,"` ought to be a pointer AND an array"));
} }
#endif // _DEBUG
db.reader->IncPtr(f->offset); db.reader->IncPtr(f->offset);

View File

@ -45,27 +45,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Blender3D importer class. * @brief Implementation of the Blender3D importer class.
*/ */
//#define ASSIMP_BUILD_NO_COMPRESSED_BLEND //#define ASSIMP_BUILD_NO_COMPRESSED_BLEND
// Uncomment this to disable support for (gzip)compressed .BLEND files // Uncomment this to disable support for (gzip)compressed .BLEND files
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#include "BlenderIntermediate.h"
#include "BlenderModifier.h"
#include "BlenderBMesh.h" #include "BlenderBMesh.h"
#include "BlenderCustomData.h" #include "BlenderCustomData.h"
#include "BlenderIntermediate.h"
#include "BlenderModifier.h"
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
#include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/StringComparison.h>
#include <assimp/StreamReader.h>
#include <assimp/MemoryIOWrapper.h> #include <assimp/MemoryIOWrapper.h>
#include <assimp/StreamReader.h>
#include <assimp/StringComparison.h>
#include <cctype> #include <cctype>
// zlib is needed for compressed blend files // zlib is needed for compressed blend files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
@ -76,12 +74,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
namespace Assimp { namespace Assimp {
template<> const char* LogFunctions<BlenderImporter>::Prefix() template <>
{ const char *LogFunctions<BlenderImporter>::Prefix() {
static auto prefix = "BLEND: "; static auto prefix = "BLEND: ";
return prefix; return prefix;
} }
} } // namespace Assimp
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Blender; using namespace Assimp::Blender;
@ -100,18 +98,16 @@ static const aiImporterDesc blenderDesc = {
"blend" "blend"
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BlenderImporter::BlenderImporter() BlenderImporter::BlenderImporter() :
: modifier_cache(new BlenderModifierShowcase()) { modifier_cache(new BlenderModifierShowcase()) {
// empty // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
BlenderImporter::~BlenderImporter() BlenderImporter::~BlenderImporter() {
{
delete modifier_cache; delete modifier_cache;
} }
@ -120,8 +116,7 @@ static const char* TokensForSearch[] = { "blender" };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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 BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
{
const std::string &extension = GetExtension(pFile); const std::string &extension = GetExtension(pFile);
if (extension == "blend") { if (extension == "blend") {
return true; return true;
@ -136,36 +131,30 @@ bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, b
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// List all extensions handled by this loader // List all extensions handled by this loader
void BlenderImporter::GetExtensionList(std::set<std::string>& app) void BlenderImporter::GetExtensionList(std::set<std::string> &app) {
{
app.insert("blend"); app.insert("blend");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Loader registry entry // Loader registry entry
const aiImporterDesc* BlenderImporter::GetInfo () const const aiImporterDesc *BlenderImporter::GetInfo() const {
{
return &blenderDesc; return &blenderDesc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader // Setup configuration properties for the loader
void BlenderImporter::SetupProperties(const Importer* /*pImp*/) void BlenderImporter::SetupProperties(const Importer * /*pImp*/) {
{
// nothing to be done for the moment // nothing to be done for the moment
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void BlenderImporter::InternReadFile(const std::string &pFile, void BlenderImporter::InternReadFile(const std::string &pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene *pScene, IOSystem *pIOHandler) {
{
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
std::vector<Bytef> uncompressed; std::vector<Bytef> uncompressed;
#endif #endif
FileDatabase file; FileDatabase file;
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb")); std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
if (!stream) { if (!stream) {
@ -227,8 +216,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
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);
@ -252,8 +240,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
LogInfo((format(), "Blender version is ", magic[0], ".", magic + 1, LogInfo((format(), "Blender version is ", magic[0], ".", magic + 1,
" (64bit: ", file.i64bit ? "true" : "false", " (64bit: ", file.i64bit ? "true" : "false",
", little endian: ",file.little?"true":"false",")" ", little endian: ", file.little ? "true" : "false", ")"));
));
ParseBlendFile(file, stream); ParseBlendFile(file, stream);
@ -264,14 +251,14 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::ParseBlendFile(FileDatabase& out, std::shared_ptr<IOStream> stream) void BlenderImporter::ParseBlendFile(FileDatabase &out, std::shared_ptr<IOStream> stream) {
{
out.reader = std::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream, out.little)); out.reader = std::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream, out.little));
DNAParser dna_reader(out); DNAParser dna_reader(out);
const DNA* dna = NULL; const DNA *dna = nullptr;
out.entries.reserve(128); { // even small BLEND files tend to consist of many file blocks out.entries.reserve(128);
{ // even small BLEND files tend to consist of many file blocks
SectionParser parser(*out.reader.get(), out.i64bit); SectionParser parser(*out.reader.get(), out.i64bit);
// first parse the file in search for the DNA and insert all other sections into the database // first parse the file in search for the DNA and insert all other sections into the database
@ -280,8 +267,7 @@ void BlenderImporter::ParseBlendFile(FileDatabase& out, std::shared_ptr<IOStream
if (head.id == "ENDB") { if (head.id == "ENDB") {
break; // only valid end of the file break; // only valid end of the file
} } else if (head.id == "DNA1") {
else if (head.id == "DNA1") {
dna_reader.Parse(); dna_reader.Parse();
dna = &dna_reader.GetDNA(); dna = &dna_reader.GetDNA();
continue; continue;
@ -298,9 +284,8 @@ void BlenderImporter::ParseBlendFile(FileDatabase& out, std::shared_ptr<IOStream
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file) void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) {
{ const FileBlockHead *block = nullptr;
const FileBlockHead* block = NULL;
std::map<std::string, size_t>::const_iterator it = file.dna.indices.find("Scene"); std::map<std::string, size_t>::const_iterator it = file.dna.indices.find("Scene");
if (it == file.dna.indices.end()) { if (it == file.dna.indices.end()) {
ThrowException("There is no `Scene` structure record"); ThrowException("There is no `Scene` structure record");
@ -332,14 +317,12 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
"(Stats) Fields read: ", file.stats().fields_read, "(Stats) Fields read: ", file.stats().fields_read,
", pointers resolved: ", file.stats().pointers_resolved, ", pointers resolved: ", file.stats().pointers_resolved,
", cache hits: ", file.stats().cache_hits, ", cache hits: ", file.stats().cache_hits,
", cached objects: " ,file.stats().cached_objects ", cached objects: ", file.stats().cached_objects);
);
#endif #endif
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileDatabase& file) void BlenderImporter::ConvertBlendFile(aiScene *out, const Scene &in, const FileDatabase &file) {
{
ConversionData conv(file); ConversionData conv(file);
// FIXME it must be possible to take the hierarchy directly from // FIXME it must be possible to take the hierarchy directly from
@ -418,9 +401,10 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const MTex* tex, const Image* img, ConversionData& conv_data) void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const MTex *tex, const Image *img, ConversionData &conv_data) {
{ (void)mat;
(void)mat; (void)tex; (void)conv_data; (void)tex;
(void)conv_data;
aiString name; aiString name;
// check if the file contents are bundled with the BLEND file // check if the file contents are bundled with the BLEND file
@ -466,13 +450,11 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
else if (map_type & MTex::MapType_NORM) { else if (map_type & MTex::MapType_NORM) {
if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) { if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) {
texture_type = aiTextureType_NORMALS; texture_type = aiTextureType_NORMALS;
} } else {
else {
texture_type = aiTextureType_HEIGHT; texture_type = aiTextureType_HEIGHT;
} }
out->AddProperty(&tex->norfac, 1, AI_MATKEY_BUMPSCALING); out->AddProperty(&tex->norfac, 1, AI_MATKEY_BUMPSCALING);
} } else if (map_type & MTex::MapType_COLSPEC)
else if (map_type & MTex::MapType_COLSPEC)
texture_type = aiTextureType_SPECULAR; texture_type = aiTextureType_SPECULAR;
else if (map_type & MTex::MapType_COLMIR) else if (map_type & MTex::MapType_COLMIR)
texture_type = aiTextureType_REFLECTION; texture_type = aiTextureType_REFLECTION;
@ -493,26 +475,23 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
out->AddProperty(&name, AI_MATKEY_TEXTURE(texture_type, out->AddProperty(&name, AI_MATKEY_TEXTURE(texture_type,
conv_data.next_texture[texture_type]++)); conv_data.next_texture[texture_type]++));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::AddSentinelTexture(aiMaterial* out, const Material* mat, const MTex* tex, ConversionData& conv_data) void BlenderImporter::AddSentinelTexture(aiMaterial *out, const Material *mat, const MTex *tex, ConversionData &conv_data) {
{ (void)mat;
(void)mat; (void)tex; (void)conv_data; (void)tex;
(void)conv_data;
aiString name; aiString name;
name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++, name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++,
GetTextureTypeDisplayString(tex->tex->type) GetTextureTypeDisplayString(tex->tex->type));
);
out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE( out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(
conv_data.next_texture[aiTextureType_DIFFUSE]++) conv_data.next_texture[aiTextureType_DIFFUSE]++));
);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::ResolveTexture(aiMaterial* out, const Material* mat, const MTex* tex, ConversionData& conv_data) void BlenderImporter::ResolveTexture(aiMaterial *out, const Material *mat, const MTex *tex, ConversionData &conv_data) {
{
const Tex *rtex = tex->tex.get(); const Tex *rtex = tex->tex.get();
if (!rtex || !rtex->type) { if (!rtex || !rtex->type) {
return; return;
@ -521,8 +500,7 @@ void BlenderImporter::ResolveTexture(aiMaterial* out, const Material* mat, const
// We can't support most of the texture types because they're mostly procedural. // We can't support most of the texture types because they're mostly procedural.
// These are substituted by a dummy texture. // These are substituted by a dummy texture.
const char *dispnam = ""; const char *dispnam = "";
switch( rtex->type ) switch (rtex->type) {
{
// these are listed in blender's UI // these are listed in blender's UI
case Tex::Type_CLOUDS: case Tex::Type_CLOUDS:
case Tex::Type_WOOD: case Tex::Type_WOOD:
@ -559,8 +537,7 @@ void BlenderImporter::ResolveTexture(aiMaterial* out, const Material* mat, const
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData& conv_data) void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData &conv_data) {
{
// add a default material if necessary // add a default material if necessary
unsigned int index = static_cast<unsigned int>(-1); unsigned int index = static_cast<unsigned int>(-1);
for (aiMesh *mesh : conv_data.meshes.get()) { for (aiMesh *mesh : conv_data.meshes.get()) {
@ -593,8 +570,7 @@ void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData& conv_data)
} }
} }
void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source) void BlenderImporter::AddBlendParams(aiMaterial *result, const Material *source) {
{
aiColor3D diffuseColor(source->r, source->g, source->b); aiColor3D diffuseColor(source->r, source->g, source->b);
result->AddProperty(&diffuseColor, 1, "$mat.blend.diffuse.color", 0, 0); result->AddProperty(&diffuseColor, 1, "$mat.blend.diffuse.color", 0, 0);
@ -607,7 +583,6 @@ void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source)
int diffuseRamp = 0; int diffuseRamp = 0;
result->AddProperty(&diffuseRamp, 1, "$mat.blend.diffuse.ramp", 0, 0); result->AddProperty(&diffuseRamp, 1, "$mat.blend.diffuse.ramp", 0, 0);
aiColor3D specularColor(source->specr, source->specg, source->specb); aiColor3D specularColor(source->specr, source->specg, source->specb);
result->AddProperty(&specularColor, 1, "$mat.blend.specular.color", 0, 0); result->AddProperty(&specularColor, 1, "$mat.blend.specular.color", 0, 0);
@ -623,7 +598,6 @@ void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source)
int specularHardness = source->har; int specularHardness = source->har;
result->AddProperty(&specularHardness, 1, "$mat.blend.specular.hardness", 0, 0); result->AddProperty(&specularHardness, 1, "$mat.blend.specular.hardness", 0, 0);
int transparencyUse = source->mode & MA_TRANSPARENCY ? 1 : 0; int transparencyUse = source->mode & MA_TRANSPARENCY ? 1 : 0;
result->AddProperty(&transparencyUse, 1, "$mat.blend.transparency.use", 0, 0); result->AddProperty(&transparencyUse, 1, "$mat.blend.transparency.use", 0, 0);
@ -666,7 +640,6 @@ void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source)
int transparencyGlossSamples = source->samp_gloss_tra; int transparencyGlossSamples = source->samp_gloss_tra;
result->AddProperty(&transparencyGlossSamples, 1, "$mat.blend.transparency.glossSamples", 0, 0); result->AddProperty(&transparencyGlossSamples, 1, "$mat.blend.transparency.glossSamples", 0, 0);
int mirrorUse = source->mode & MA_RAYMIRROR ? 1 : 0; int mirrorUse = source->mode & MA_RAYMIRROR ? 1 : 0;
result->AddProperty(&mirrorUse, 1, "$mat.blend.mirror.use", 0, 0); result->AddProperty(&mirrorUse, 1, "$mat.blend.mirror.use", 0, 0);
@ -704,8 +677,7 @@ void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source)
result->AddProperty(&mirrorGlossAnisotropic, 1, "$mat.blend.mirror.glossAnisotropic", 0, 0); result->AddProperty(&mirrorGlossAnisotropic, 1, "$mat.blend.mirror.glossAnisotropic", 0, 0);
} }
void BlenderImporter::BuildMaterials(ConversionData& conv_data) void BlenderImporter::BuildMaterials(ConversionData &conv_data) {
{
conv_data.materials->reserve(conv_data.materials_raw.size()); conv_data.materials->reserve(conv_data.materials_raw.size());
BuildDefaultMaterial(conv_data); BuildDefaultMaterial(conv_data);
@ -773,34 +745,28 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::CheckActualType(const ElemBase* dt, const char* check) void BlenderImporter::CheckActualType(const ElemBase *dt, const char *check) {
{
ai_assert(dt); ai_assert(dt);
if (strcmp(dt->dna_type, check)) { if (strcmp(dt->dna_type, check)) {
ThrowException((format(), ThrowException((format(),
"Expected object at ", std::hex, dt, " to be of type `", check, "Expected object at ", std::hex, dt, " to be of type `", check,
"`, but it claims to be a `",dt->dna_type,"`instead" "`, but it claims to be a `", dt->dna_type, "`instead"));
));
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::NotSupportedObjectType(const Object* obj, const char* type) void BlenderImporter::NotSupportedObjectType(const Object *obj, const char *type) {
{
LogWarn((format(), "Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping")); LogWarn((format(), "Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping"));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/, const Mesh *mesh, void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/, const Mesh *mesh,
ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp ConversionData &conv_data, TempArray<std::vector, aiMesh> &temp) {
)
{
// TODO: Resolve various problems with BMesh triangulation before re-enabling. // TODO: Resolve various problems with BMesh triangulation before re-enabling.
// See issues #400, #373, #318 #315 and #132. // See issues #400, #373, #318 #315 and #132.
#if defined(TODO_FIX_BMESH_CONVERSION) #if defined(TODO_FIX_BMESH_CONVERSION)
BlenderBMeshConverter BMeshConverter(mesh); BlenderBMeshConverter BMeshConverter(mesh);
if ( BMeshConverter.ContainsBMesh( ) ) if (BMeshConverter.ContainsBMesh()) {
{
mesh = BMeshConverter.TriangulateBMesh(); mesh = BMeshConverter.TriangulateBMesh();
} }
#endif #endif
@ -874,18 +840,16 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
std::shared_ptr<Material> mat = mesh->mat[it.first]; std::shared_ptr<Material> mat = mesh->mat[it.first];
const std::deque<std::shared_ptr<Material>>::iterator has = std::find( const std::deque<std::shared_ptr<Material>>::iterator has = std::find(
conv_data.materials_raw.begin(), conv_data.materials_raw.begin(),
conv_data.materials_raw.end(),mat conv_data.materials_raw.end(), mat);
);
if (has != conv_data.materials_raw.end()) { if (has != conv_data.materials_raw.end()) {
out->mMaterialIndex = static_cast<unsigned int>(std::distance(conv_data.materials_raw.begin(), has)); out->mMaterialIndex = static_cast<unsigned int>(std::distance(conv_data.materials_raw.begin(), has));
} } else {
else {
out->mMaterialIndex = static_cast<unsigned int>(conv_data.materials_raw.size()); out->mMaterialIndex = static_cast<unsigned int>(conv_data.materials_raw.size());
conv_data.materials_raw.push_back(mat); conv_data.materials_raw.push_back(mat);
} }
} } else
else out->mMaterialIndex = static_cast<unsigned int>( -1 ); out->mMaterialIndex = static_cast<unsigned int>(-1);
} }
for (int i = 0; i < mesh->totface; ++i) { for (int i = 0; i < mesh->totface; ++i) {
@ -966,8 +930,8 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
++vn; ++vn;
out->mPrimitiveTypes |= aiPrimitiveType_POLYGON; out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
} } else
else out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
// } // }
// } // }
@ -990,8 +954,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
// which are assigned by the genblenddna.py script and // which are assigned by the genblenddna.py script and
// cannot be changed without breaking the entire // cannot be changed without breaking the entire
// import process. // import process.
for (int j = 0;j < mf.totloop; ++j) for (int j = 0; j < mf.totloop; ++j) {
{
const MLoop &loop = mesh->mloop[mf.loopstart + j]; const MLoop &loop = mesh->mloop[mf.loopstart + j];
if (loop.v >= mesh->totvert) { if (loop.v >= mesh->totvert) {
@ -1010,14 +973,10 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
++vo; ++vo;
++vn; ++vn;
} }
if (mf.totloop == 3) if (mf.totloop == 3) {
{
out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
} } else {
else
{
out->mPrimitiveTypes |= aiPrimitiveType_POLYGON; out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
} }
} }
@ -1056,13 +1015,13 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)"); ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
} }
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) { for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
ai_assert((*it)->mNumVertices && (*it)->mNumFaces); ai_assert(0 != (*it)->mNumVertices);
ai_assert(0 != (*it)->mNumFaces);
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex); const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
if (itMatTexUvMapping == matTexUvMappings.end()) { if (itMatTexUvMapping == matTexUvMappings.end()) {
// default behaviour like before // default behaviour like before
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices]; (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
} } else {
else {
// create texture coords for every mapped tex // create texture coords for every mapped tex
for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) { for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) {
(*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices]; (*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices];
@ -1125,7 +1084,8 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ThrowException("Number of faces is larger than the corresponding UV face array (#2)"); ThrowException("Number of faces is larger than the corresponding UV face array (#2)");
} }
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) { for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
ai_assert((*it)->mNumVertices && (*it)->mNumFaces); ai_assert(0 != (*it)->mNumVertices);
ai_assert(0 != (*it)->mNumFaces);
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices]; (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
(*it)->mNumFaces = (*it)->mNumVertices = 0; (*it)->mNumFaces = (*it)->mNumVertices = 0;
@ -1151,7 +1111,8 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ThrowException("Number of faces is larger than the corresponding color face array"); ThrowException("Number of faces is larger than the corresponding color face array");
} }
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) { for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
ai_assert((*it)->mNumVertices && (*it)->mNumFaces); ai_assert(0 != (*it)->mNumVertices);
ai_assert(0 != (*it)->mNumFaces);
(*it)->mColors[0] = new aiColor4D[(*it)->mNumVertices]; (*it)->mColors[0] = new aiColor4D[(*it)->mNumVertices];
(*it)->mNumFaces = (*it)->mNumVertices = 0; (*it)->mNumFaces = (*it)->mNumVertices = 0;
@ -1171,7 +1132,8 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
vo->b = col->b; vo->b = col->b;
vo->a = col->a; vo->a = col->a;
} }
for (unsigned int n = f.mNumIndices; n < 4; ++n); for (unsigned int n = f.mNumIndices; n < 4; ++n)
;
} }
for (int i = 0; i < mesh->totpoly; ++i) { for (int i = 0; i < mesh->totpoly; ++i) {
@ -1188,17 +1150,14 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
vo->b = ai_real(col.b) * scaleZeroToOne; vo->b = ai_real(col.b) * scaleZeroToOne;
vo->a = ai_real(col.a) * scaleZeroToOne; vo->a = ai_real(col.a) * scaleZeroToOne;
} }
} }
} }
return; return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* cam, ConversionData& /*conv_data*/) aiCamera *BlenderImporter::ConvertCamera(const Scene & /*in*/, const Object *obj, const Camera *cam, ConversionData & /*conv_data*/) {
{
std::unique_ptr<aiCamera> out(new aiCamera()); std::unique_ptr<aiCamera> out(new aiCamera());
out->mName = obj->id.name + 2; out->mName = obj->id.name + 2;
out->mPosition = aiVector3D(0.f, 0.f, 0.f); out->mPosition = aiVector3D(0.f, 0.f, 0.f);
@ -1214,13 +1173,11 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/) aiLight *BlenderImporter::ConvertLight(const Scene & /*in*/, const Object *obj, const Lamp *lamp, ConversionData & /*conv_data*/) {
{
std::unique_ptr<aiLight> out(new aiLight()); std::unique_ptr<aiLight> out(new aiLight());
out->mName = obj->id.name + 2; out->mName = obj->id.name + 2;
switch (lamp->type) switch (lamp->type) {
{
case Lamp::Type_Local: case Lamp::Type_Local:
out->mType = aiLightSource_POINT; out->mType = aiLightSource_POINT;
break; break;
@ -1247,8 +1204,7 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
if (lamp->area_shape == 0) { if (lamp->area_shape == 0) {
out->mSize = aiVector2D(lamp->area_size, lamp->area_size); out->mSize = aiVector2D(lamp->area_size, lamp->area_size);
} } else {
else {
out->mSize = aiVector2D(lamp->area_size, lamp->area_sizey); out->mSize = aiVector2D(lamp->area_size, lamp->area_sizey);
} }
@ -1268,14 +1224,11 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
// If default values are supplied, compute the coefficients from light's max distance // If default values are supplied, compute the coefficients from light's max distance
// Read this: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/ // Read this: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
// //
if (lamp->constant_coefficient == 1.0f && lamp->linear_coefficient == 0.0f && lamp->quadratic_coefficient == 0.0f && lamp->dist > 0.0f) if (lamp->constant_coefficient == 1.0f && lamp->linear_coefficient == 0.0f && lamp->quadratic_coefficient == 0.0f && lamp->dist > 0.0f) {
{
out->mAttenuationConstant = 1.0f; out->mAttenuationConstant = 1.0f;
out->mAttenuationLinear = 2.0f / lamp->dist; out->mAttenuationLinear = 2.0f / lamp->dist;
out->mAttenuationQuadratic = 1.0f / (lamp->dist * lamp->dist); out->mAttenuationQuadratic = 1.0f / (lamp->dist * lamp->dist);
} } else {
else
{
out->mAttenuationConstant = lamp->constant_coefficient; out->mAttenuationConstant = lamp->constant_coefficient;
out->mAttenuationLinear = lamp->linear_coefficient; out->mAttenuationLinear = lamp->linear_coefficient;
out->mAttenuationQuadratic = lamp->quadratic_coefficient; out->mAttenuationQuadratic = lamp->quadratic_coefficient;
@ -1285,8 +1238,7 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform) aiNode *BlenderImporter::ConvertNode(const Scene &in, const Object *obj, ConversionData &conv_data, const aiMatrix4x4 &parentTransform) {
{
std::deque<const Object *> children; std::deque<const Object *> children;
for (ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end();) { for (ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end();) {
const Object *object = *it; const Object *object = *it;
@ -1301,12 +1253,10 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
std::unique_ptr<aiNode> node(new aiNode(obj->id.name + 2)); // skip over the name prefix 'OB' std::unique_ptr<aiNode> node(new aiNode(obj->id.name + 2)); // skip over the name prefix 'OB'
if (obj->data) { if (obj->data) {
switch (obj->type) switch (obj->type) {
{
case Object ::Type_EMPTY: case Object ::Type_EMPTY:
break; // do nothing break; // do nothing
// supported object types // supported object types
case Object ::Type_MESH: { case Object ::Type_MESH: {
const size_t old = conv_data.meshes->size(); const size_t old = conv_data.meshes->size();
@ -1319,27 +1269,24 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
for (unsigned int i = 0; i < node->mNumMeshes; ++i) { for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
node->mMeshes[i] = static_cast<unsigned int>(i + old); node->mMeshes[i] = static_cast<unsigned int>(i + old);
} }
}} }
break; } break;
case Object ::Type_LAMP: { case Object ::Type_LAMP: {
CheckActualType(obj->data.get(), "Lamp"); CheckActualType(obj->data.get(), "Lamp");
aiLight* mesh = ConvertLight(in,obj,static_cast<const Lamp*>( aiLight *mesh = ConvertLight(in, obj, static_cast<const Lamp *>(obj->data.get()), conv_data);
obj->data.get()),conv_data);
if (mesh) { if (mesh) {
conv_data.lights->push_back(mesh); conv_data.lights->push_back(mesh);
}} }
break; } break;
case Object ::Type_CAMERA: { case Object ::Type_CAMERA: {
CheckActualType(obj->data.get(), "Camera"); CheckActualType(obj->data.get(), "Camera");
aiCamera* mesh = ConvertCamera(in,obj,static_cast<const Camera*>( aiCamera *mesh = ConvertCamera(in, obj, static_cast<const Camera *>(obj->data.get()), conv_data);
obj->data.get()),conv_data);
if (mesh) { if (mesh) {
conv_data.cameras->push_back(mesh); conv_data.cameras->push_back(mesh);
}} }
break; } break;
// unsupported object types / log, but do not break // unsupported object types / log, but do not break
case Object ::Type_CURVE: case Object ::Type_CURVE:

View File

@ -290,7 +290,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
} }
std::unique_ptr<const Material> defmat; std::unique_ptr<const Material> defmat;
if (!min) { if (!min) {
ASSIMP_LOG_DEBUG(format() << "Could not resolve material index " ASSIMP_LOG_VERBOSE_DEBUG(format() << "Could not resolve material index "
<< reflist.first << " - creating default material for this slot"); << reflist.first << " - creating default material for this slot");
defmat.reset(min = new Material()); defmat.reset(min = new Material());
@ -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

@ -44,8 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
#include "ColladaExporter.h" #include "ColladaExporter.h"
#include <assimp/Bitmap.h> #include <assimp/Bitmap.h>
#include <assimp/ColladaMetaData.h>
#include <assimp/DefaultIOSystem.h> #include <assimp/DefaultIOSystem.h>
#include <assimp/Exceptional.h>
#include <assimp/MathFunctions.h> #include <assimp/MathFunctions.h>
#include <assimp/SceneCombiner.h> #include <assimp/SceneCombiner.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
@ -56,15 +59,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/Exceptional.h>
#include <ctime> #include <ctime>
#include <iostream>
#include <memory> #include <memory>
#include <set>
#include <vector>
using namespace Assimp;
namespace Assimp { namespace Assimp {
@ -91,8 +87,6 @@ void ExportSceneCollada(const char *pFile, IOSystem *pIOSystem, const aiScene *p
outfile->Write(iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()), 1); outfile->Write(iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()), 1);
} }
} // end of namespace Assimp
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Encodes a string into a valid XML ID using the xsd:ID schema qualifications. // Encodes a string into a valid XML ID using the xsd:ID schema qualifications.
static const std::string XMLIDEncode(const std::string &name) { static const std::string XMLIDEncode(const std::string &name) {
@ -115,7 +109,7 @@ static const std::string XMLIDEncode(const std::string &name) {
if (strchr(XML_ID_CHARS, *it) != nullptr) { if (strchr(XML_ID_CHARS, *it) != nullptr) {
idEncoded << *it; idEncoded << *it;
} else { } else {
// Select placeholder character based on invalid character to prevent name collisions // Select placeholder character based on invalid character to reduce ID collisions
idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT]; idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT];
} }
} }
@ -123,20 +117,37 @@ static const std::string XMLIDEncode(const std::string &name) {
return idEncoded.str(); return idEncoded.str();
} }
// ------------------------------------------------------------------------------------------------
// Helper functions to create unique ids
inline bool IsUniqueId(const std::unordered_set<std::string> &idSet, const std::string &idStr) {
return (idSet.find(idStr) == idSet.end());
}
inline std::string MakeUniqueId(const std::unordered_set<std::string> &idSet, const std::string &idPrefix, const std::string &postfix) {
std::string result(idPrefix + postfix);
if (!IsUniqueId(idSet, result)) {
// Select a number to append
size_t idnum = 1;
do {
result = idPrefix + '_' + to_string(idnum) + postfix;
++idnum;
} while (!IsUniqueId(idSet, result));
}
return result;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor for a specific scene to export // Constructor for a specific scene to export
ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file) : ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file) :
mIOSystem(pIOSystem), mPath(path), mFile(file) { mIOSystem(pIOSystem),
mPath(path),
mFile(file),
mScene(pScene),
endstr("\n") {
// make sure that all formatting happens using the standard, C locale and not the user's current locale // make sure that all formatting happens using the standard, C locale and not the user's current locale
mOutput.imbue(std::locale("C")); mOutput.imbue(std::locale("C"));
mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
mScene = pScene;
mSceneOwned = false;
// set up strings
endstr = "\n";
// start writing the file // start writing the file
WriteFile(); WriteFile();
} }
@ -144,9 +155,6 @@ ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, con
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor // Destructor
ColladaExporter::~ColladaExporter() { ColladaExporter::~ColladaExporter() {
if (mSceneOwned) {
delete mScene;
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -161,6 +169,9 @@ void ColladaExporter::WriteFile() {
WriteTextures(); WriteTextures();
WriteHeader(); WriteHeader();
// Add node names to the unique id database first so they are most likely to use their names as unique ids
CreateNodeIds(mScene->mRootNode);
WriteCamerasLibrary(); WriteCamerasLibrary();
WriteLightsLibrary(); WriteLightsLibrary();
WriteMaterials(); WriteMaterials();
@ -172,10 +183,11 @@ void ColladaExporter::WriteFile() {
// customized, Writes the animation library // customized, Writes the animation library
WriteAnimationsLibrary(); WriteAnimationsLibrary();
// useless Collada fu at the end, just in case we haven't had enough indirections, yet. // instantiate the scene(s)
// For Assimp there will only ever be one
mOutput << startstr << "<scene>" << endstr; mOutput << startstr << "<scene>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<instance_visual_scene url=\"#" + XMLIDEncode(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr; mOutput << startstr << "<instance_visual_scene url=\"#" + mSceneId + "\" />" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</scene>" << endstr; mOutput << startstr << "</scene>" << endstr;
PopTag(); PopTag();
@ -201,7 +213,7 @@ void ColladaExporter::WriteHeader() {
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));
aiVector3D scaling; aiVector3D scaling;
@ -210,13 +222,13 @@ void ColladaExporter::WriteHeader() {
mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position); mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position);
rotation.Normalize(); rotation.Normalize();
bool add_root_node = false; mAdd_root_node = false;
ai_real scale = 1.0; ai_real scale = 1.0;
if (std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { if (std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) {
scale = (ai_real)((((double)scaling.x) + ((double)scaling.y) + ((double)scaling.z)) / 3.0); scale = (ai_real)((((double)scaling.x) + ((double)scaling.y) + ((double)scaling.z)) / 3.0);
} else { } else {
add_root_node = true; mAdd_root_node = true;
} }
std::string up_axis = "Y_UP"; std::string up_axis = "Y_UP";
@ -227,33 +239,19 @@ void ColladaExporter::WriteHeader() {
} else if (rotation.Equal(z_rot, epsilon)) { } else if (rotation.Equal(z_rot, epsilon)) {
up_axis = "Z_UP"; up_axis = "Z_UP";
} else { } else {
add_root_node = true; mAdd_root_node = true;
} }
if (!position.Equal(aiVector3D(0, 0, 0))) { if (!position.Equal(aiVector3D(0, 0, 0))) {
add_root_node = true; mAdd_root_node = true;
} }
if (mScene->mRootNode->mNumChildren == 0) { // Assimp root nodes can have meshes, Collada Scenes cannot
add_root_node = true; if (mScene->mRootNode->mNumChildren == 0 || mScene->mRootNode->mMeshes != 0) {
mAdd_root_node = true;
} }
if (add_root_node) { if (mAdd_root_node) {
aiScene *scene;
SceneCombiner::CopyScene(&scene, mScene);
aiNode *root = new aiNode("Scene");
root->mNumChildren = 1;
root->mChildren = new aiNode *[root->mNumChildren];
root->mChildren[0] = scene->mRootNode;
scene->mRootNode->mParent = root;
scene->mRootNode = root;
mScene = scene;
mSceneOwned = true;
up_axis = "Y_UP"; up_axis = "Y_UP";
scale = 1.0; scale = 1.0;
} }
@ -352,7 +350,7 @@ void ColladaExporter::WriteTextures() {
std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char *)texture->achFormatHint); std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char *)texture->achFormatHint);
std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb")); std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb"));
if (outfile == NULL) { if (outfile == nullptr) {
throw DeadlyExportError("could not open output texture file: " + mPath + name); throw DeadlyExportError("could not open output texture file: " + mPath + name);
} }
@ -388,10 +386,10 @@ void ColladaExporter::WriteCamerasLibrary() {
void ColladaExporter::WriteCamera(size_t pIndex) { void ColladaExporter::WriteCamera(size_t pIndex) {
const aiCamera *cam = mScene->mCameras[pIndex]; const aiCamera *cam = mScene->mCameras[pIndex];
const std::string cameraName = XMLEscape(cam->mName.C_Str()); const std::string cameraId = GetObjectUniqueId(AiObjectType::Camera, pIndex);
const std::string cameraId = XMLIDEncode(cam->mName.C_Str()); const std::string cameraName = GetObjectName(AiObjectType::Camera, pIndex);
mOutput << startstr << "<camera id=\"" << cameraId << "-camera\" name=\"" << cameraName << "\" >" << endstr; mOutput << startstr << "<camera id=\"" << cameraId << "\" name=\"" << cameraName << "\" >" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<optics>" << endstr; mOutput << startstr << "<optics>" << endstr;
PushTag(); PushTag();
@ -441,10 +439,10 @@ void ColladaExporter::WriteLightsLibrary() {
void ColladaExporter::WriteLight(size_t pIndex) { void ColladaExporter::WriteLight(size_t pIndex) {
const aiLight *light = mScene->mLights[pIndex]; const aiLight *light = mScene->mLights[pIndex];
const std::string lightName = XMLEscape(light->mName.C_Str()); const std::string lightId = GetObjectUniqueId(AiObjectType::Light, pIndex);
const std::string lightId = XMLIDEncode(light->mName.C_Str()); const std::string lightName = GetObjectName(AiObjectType::Light, pIndex);
mOutput << startstr << "<light id=\"" << lightId << "-light\" name=\"" mOutput << startstr << "<light id=\"" << lightId << "\" name=\""
<< lightName << "\" >" << endstr; << lightName << "\" >" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<technique_common>" << endstr; mOutput << startstr << "<technique_common>" << endstr;
@ -561,12 +559,11 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a single surface entry from the given material keys // Reads a single surface entry from the given material keys
void ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial *pSrcMat, bool ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial &pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex) {
aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex) { if (pSrcMat.GetTextureCount(pTexture) > 0) {
if (pSrcMat->GetTextureCount(pTexture) > 0) {
aiString texfile; aiString texfile;
unsigned int uvChannel = 0; unsigned int uvChannel = 0;
pSrcMat->GetTexture(pTexture, 0, &texfile, NULL, &uvChannel); pSrcMat.GetTexture(pTexture, 0, &texfile, nullptr, &uvChannel);
std::string index_str(texfile.C_Str()); std::string index_str(texfile.C_Str());
@ -596,8 +593,9 @@ void ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial *
poSurface.exist = true; poSurface.exist = true;
} else { } else {
if (pKey) if (pKey)
poSurface.exist = pSrcMat->Get(pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS; poSurface.exist = pSrcMat.Get(pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS;
} }
return poSurface.exist;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -608,9 +606,9 @@ static bool isalnum_C(char c) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Writes an image entry for the given surface // Writes an image entry for the given surface
void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string &pNameAdd) { void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string &imageId) {
if (!pSurface.texture.empty()) { if (!pSurface.texture.empty()) {
mOutput << startstr << "<image id=\"" << XMLIDEncode(pNameAdd) << "\">" << endstr; mOutput << startstr << "<image id=\"" << imageId << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<init_from>"; mOutput << startstr << "<init_from>";
@ -631,14 +629,14 @@ void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Writes a color-or-texture entry into an effect definition // Writes a color-or-texture entry into an effect definition
void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pImageName) { void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &imageId) {
if (pSurface.exist) { if (pSurface.exist) {
mOutput << startstr << "<" << pTypeName << ">" << endstr; mOutput << startstr << "<" << pTypeName << ">" << endstr;
PushTag(); PushTag();
if (pSurface.texture.empty()) { if (pSurface.texture.empty()) {
mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "</color>" << endstr; mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "</color>" << endstr;
} else { } else {
mOutput << startstr << "<texture texture=\"" << XMLIDEncode(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr; mOutput << startstr << "<texture texture=\"" << imageId << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
} }
PopTag(); PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr; mOutput << startstr << "</" << pTypeName << ">" << endstr;
@ -647,24 +645,24 @@ void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Writes the two parameters necessary for referencing a texture in an effect entry // Writes the two parameters necessary for referencing a texture in an effect entry
void ColladaExporter::WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pMatName) { void ColladaExporter::WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &materialId) {
// if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
if (!pSurface.texture.empty()) { if (!pSurface.texture.empty()) {
mOutput << startstr << "<newparam sid=\"" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface\">" << endstr; mOutput << startstr << "<newparam sid=\"" << materialId << "-" << pTypeName << "-surface\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<surface type=\"2D\">" << endstr; mOutput << startstr << "<surface type=\"2D\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<init_from>" << XMLIDEncode(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr; mOutput << startstr << "<init_from>" << materialId << "-" << pTypeName << "-image</init_from>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</surface>" << endstr; mOutput << startstr << "</surface>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</newparam>" << endstr; mOutput << startstr << "</newparam>" << endstr;
mOutput << startstr << "<newparam sid=\"" << XMLIDEncode(pMatName) << "-" << pTypeName << "-sampler\">" << endstr; mOutput << startstr << "<newparam sid=\"" << materialId << "-" << pTypeName << "-sampler\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<sampler2D>" << endstr; mOutput << startstr << "<sampler2D>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<source>" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface</source>" << endstr; mOutput << startstr << "<source>" << materialId << "-" << pTypeName << "-surface</source>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</sampler2D>" << endstr; mOutput << startstr << "</sampler2D>" << endstr;
PopTag(); PopTag();
@ -687,80 +685,63 @@ void ColladaExporter::WriteFloatEntry(const Property &pProperty, const std::stri
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Writes the material setup // Writes the material setup
void ColladaExporter::WriteMaterials() { void ColladaExporter::WriteMaterials() {
std::vector<Material> materials;
materials.resize(mScene->mNumMaterials); materials.resize(mScene->mNumMaterials);
/// collect all materials from the scene /// collect all materials from the scene
size_t numTextures = 0; size_t numTextures = 0;
for (size_t a = 0; a < mScene->mNumMaterials; ++a) { for (size_t a = 0; a < mScene->mNumMaterials; ++a) {
const aiMaterial *mat = mScene->mMaterials[a]; Material &material = materials[a];
material.id = GetObjectUniqueId(AiObjectType::Material, a);
aiString name; material.name = GetObjectName(AiObjectType::Material, a);
if (mat->Get(AI_MATKEY_NAME, name) != aiReturn_SUCCESS) {
name = "mat";
materials[a].name = std::string("m") + to_string(a) + name.C_Str();
} else {
// try to use the material's name if no other material has already taken it, else append #
std::string testName = name.C_Str();
size_t materialCountWithThisName = 0;
for (size_t i = 0; i < a; i++) {
if (materials[i].name == testName) {
materialCountWithThisName++;
}
}
if (materialCountWithThisName == 0) {
materials[a].name = name.C_Str();
} else {
materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName);
}
}
const aiMaterial &mat = *(mScene->mMaterials[a]);
aiShadingMode shading = aiShadingMode_Flat; aiShadingMode shading = aiShadingMode_Flat;
materials[a].shading_model = "phong"; material.shading_model = "phong";
if (mat->Get(AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { if (mat.Get(AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) {
if (shading == aiShadingMode_Phong) { if (shading == aiShadingMode_Phong) {
materials[a].shading_model = "phong"; material.shading_model = "phong";
} else if (shading == aiShadingMode_Blinn) { } else if (shading == aiShadingMode_Blinn) {
materials[a].shading_model = "blinn"; material.shading_model = "blinn";
} else if (shading == aiShadingMode_NoShading) { } else if (shading == aiShadingMode_NoShading) {
materials[a].shading_model = "constant"; material.shading_model = "constant";
} else if (shading == aiShadingMode_Gouraud) { } else if (shading == aiShadingMode_Gouraud) {
materials[a].shading_model = "lambert"; material.shading_model = "lambert";
} }
} }
ReadMaterialSurface(materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); if (ReadMaterialSurface(material.ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT))
if (!materials[a].ambient.texture.empty()) numTextures++; ++numTextures;
ReadMaterialSurface(materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); if (ReadMaterialSurface(material.diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE))
if (!materials[a].diffuse.texture.empty()) numTextures++; ++numTextures;
ReadMaterialSurface(materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); if (ReadMaterialSurface(material.specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR))
if (!materials[a].specular.texture.empty()) numTextures++; ++numTextures;
ReadMaterialSurface(materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); if (ReadMaterialSurface(material.emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE))
if (!materials[a].emissive.texture.empty()) numTextures++; ++numTextures;
ReadMaterialSurface(materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); if (ReadMaterialSurface(material.reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE))
if (!materials[a].reflective.texture.empty()) numTextures++; ++numTextures;
ReadMaterialSurface(materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); if (ReadMaterialSurface(material.transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT))
if (!materials[a].transparent.texture.empty()) numTextures++; ++numTextures;
ReadMaterialSurface(materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); if (ReadMaterialSurface(material.normal, mat, aiTextureType_NORMALS, nullptr, 0, 0))
if (!materials[a].normal.texture.empty()) numTextures++; ++numTextures;
materials[a].shininess.exist = mat->Get(AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; material.shininess.exist = mat.Get(AI_MATKEY_SHININESS, material.shininess.value) == aiReturn_SUCCESS;
materials[a].transparency.exist = mat->Get(AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; material.transparency.exist = mat.Get(AI_MATKEY_OPACITY, material.transparency.value) == aiReturn_SUCCESS;
materials[a].index_refraction.exist = mat->Get(AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; material.index_refraction.exist = mat.Get(AI_MATKEY_REFRACTI, material.index_refraction.value) == aiReturn_SUCCESS;
} }
// output textures if present // output textures if present
if (numTextures > 0) { if (numTextures > 0) {
mOutput << startstr << "<library_images>" << endstr; mOutput << startstr << "<library_images>" << endstr;
PushTag(); PushTag();
for (std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) { for (const Material &mat : materials) {
const Material &mat = *it; WriteImageEntry(mat.ambient, mat.id + "-ambient-image");
WriteImageEntry(mat.ambient, mat.name + "-ambient-image"); WriteImageEntry(mat.diffuse, mat.id + "-diffuse-image");
WriteImageEntry(mat.diffuse, mat.name + "-diffuse-image"); WriteImageEntry(mat.specular, mat.id + "-specular-image");
WriteImageEntry(mat.specular, mat.name + "-specular-image"); WriteImageEntry(mat.emissive, mat.id + "-emission-image");
WriteImageEntry(mat.emissive, mat.name + "-emission-image"); WriteImageEntry(mat.reflective, mat.id + "-reflective-image");
WriteImageEntry(mat.reflective, mat.name + "-reflective-image"); WriteImageEntry(mat.transparent, mat.id + "-transparent-image");
WriteImageEntry(mat.transparent, mat.name + "-transparent-image"); WriteImageEntry(mat.normal, mat.id + "-normal-image");
WriteImageEntry(mat.normal, mat.name + "-normal-image");
} }
PopTag(); PopTag();
mOutput << startstr << "</library_images>" << endstr; mOutput << startstr << "</library_images>" << endstr;
@ -770,40 +751,39 @@ void ColladaExporter::WriteMaterials() {
if (!materials.empty()) { if (!materials.empty()) {
mOutput << startstr << "<library_effects>" << endstr; mOutput << startstr << "<library_effects>" << endstr;
PushTag(); PushTag();
for (std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) { for (const Material &mat : materials) {
const Material &mat = *it;
// this is so ridiculous it must be right // this is so ridiculous it must be right
mOutput << startstr << "<effect id=\"" << XMLIDEncode(mat.name) << "-fx\" name=\"" << XMLEscape(mat.name) << "\">" << endstr; mOutput << startstr << "<effect id=\"" << mat.id << "-fx\" name=\"" << mat.name << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<profile_COMMON>" << endstr; mOutput << startstr << "<profile_COMMON>" << endstr;
PushTag(); PushTag();
// write sampler- and surface params for the texture entries // write sampler- and surface params for the texture entries
WriteTextureParamEntry(mat.emissive, "emission", mat.name); WriteTextureParamEntry(mat.emissive, "emission", mat.id);
WriteTextureParamEntry(mat.ambient, "ambient", mat.name); WriteTextureParamEntry(mat.ambient, "ambient", mat.id);
WriteTextureParamEntry(mat.diffuse, "diffuse", mat.name); WriteTextureParamEntry(mat.diffuse, "diffuse", mat.id);
WriteTextureParamEntry(mat.specular, "specular", mat.name); WriteTextureParamEntry(mat.specular, "specular", mat.id);
WriteTextureParamEntry(mat.reflective, "reflective", mat.name); WriteTextureParamEntry(mat.reflective, "reflective", mat.id);
WriteTextureParamEntry(mat.transparent, "transparent", mat.name); WriteTextureParamEntry(mat.transparent, "transparent", mat.id);
WriteTextureParamEntry(mat.normal, "normal", mat.name); WriteTextureParamEntry(mat.normal, "normal", mat.id);
mOutput << startstr << "<technique sid=\"standard\">" << endstr; mOutput << startstr << "<technique sid=\"standard\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<" << mat.shading_model << ">" << endstr; mOutput << startstr << "<" << mat.shading_model << ">" << endstr;
PushTag(); PushTag();
WriteTextureColorEntry(mat.emissive, "emission", mat.name + "-emission-sampler"); WriteTextureColorEntry(mat.emissive, "emission", mat.id + "-emission-sampler");
WriteTextureColorEntry(mat.ambient, "ambient", mat.name + "-ambient-sampler"); WriteTextureColorEntry(mat.ambient, "ambient", mat.id + "-ambient-sampler");
WriteTextureColorEntry(mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); WriteTextureColorEntry(mat.diffuse, "diffuse", mat.id + "-diffuse-sampler");
WriteTextureColorEntry(mat.specular, "specular", mat.name + "-specular-sampler"); WriteTextureColorEntry(mat.specular, "specular", mat.id + "-specular-sampler");
WriteFloatEntry(mat.shininess, "shininess"); WriteFloatEntry(mat.shininess, "shininess");
WriteTextureColorEntry(mat.reflective, "reflective", mat.name + "-reflective-sampler"); WriteTextureColorEntry(mat.reflective, "reflective", mat.id + "-reflective-sampler");
WriteTextureColorEntry(mat.transparent, "transparent", mat.name + "-transparent-sampler"); WriteTextureColorEntry(mat.transparent, "transparent", mat.id + "-transparent-sampler");
WriteFloatEntry(mat.transparency, "transparency"); WriteFloatEntry(mat.transparency, "transparency");
WriteFloatEntry(mat.index_refraction, "index_of_refraction"); WriteFloatEntry(mat.index_refraction, "index_of_refraction");
if (!mat.normal.texture.empty()) { if (!mat.normal.texture.empty()) {
WriteTextureColorEntry(mat.normal, "bump", mat.name + "-normal-sampler"); WriteTextureColorEntry(mat.normal, "bump", mat.id + "-normal-sampler");
} }
PopTag(); PopTag();
@ -823,9 +803,9 @@ void ColladaExporter::WriteMaterials() {
PushTag(); PushTag();
for (std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) { for (std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
const Material &mat = *it; const Material &mat = *it;
mOutput << startstr << "<material id=\"" << XMLIDEncode(mat.name) << "\" name=\"" << XMLEscape(mat.name) << "\">" << endstr; mOutput << startstr << "<material id=\"" << mat.id << "\" name=\"" << mat.name << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<instance_effect url=\"#" << XMLIDEncode(mat.name) << "-fx\"/>" << endstr; mOutput << startstr << "<instance_effect url=\"#" << mat.id << "-fx\"/>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</material>" << endstr; mOutput << startstr << "</material>" << endstr;
} }
@ -852,20 +832,18 @@ void ColladaExporter::WriteControllerLibrary() {
// Writes a skin controller of the given mesh // Writes a skin controller of the given mesh
void ColladaExporter::WriteController(size_t pIndex) { void ColladaExporter::WriteController(size_t pIndex) {
const aiMesh *mesh = mScene->mMeshes[pIndex]; const aiMesh *mesh = mScene->mMeshes[pIndex];
const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); // Is there a skin controller?
const std::string idstrEscaped = XMLIDEncode(idstr); if (mesh->mNumBones == 0 || mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
return; return;
if (mesh->mNumBones == 0) const std::string idstr = GetObjectUniqueId(AiObjectType::Mesh, pIndex);
return; const std::string namestr = GetObjectName(AiObjectType::Mesh, pIndex);
mOutput << startstr << "<controller id=\"" << idstrEscaped << "-skin\" "; mOutput << startstr << "<controller id=\"" << idstr << "-skin\" ";
mOutput << "name=\"skinCluster" << pIndex << "\">" << endstr; mOutput << "name=\"skinCluster" << pIndex << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<skin source=\"#" << idstrEscaped << "\">" << endstr; mOutput << startstr << "<skin source=\"#" << idstr << "\">" << endstr;
PushTag(); PushTag();
// bind pose matrix // bind pose matrix
@ -882,20 +860,20 @@ void ColladaExporter::WriteController(size_t pIndex) {
PopTag(); PopTag();
mOutput << startstr << "</bind_shape_matrix>" << endstr; mOutput << startstr << "</bind_shape_matrix>" << endstr;
mOutput << startstr << "<source id=\"" << idstrEscaped << "-skin-joints\" name=\"" << idstrEscaped << "-skin-joints\">" << endstr; mOutput << startstr << "<source id=\"" << idstr << "-skin-joints\" name=\"" << namestr << "-skin-joints\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<Name_array id=\"" << idstrEscaped << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\">"; mOutput << startstr << "<Name_array id=\"" << idstr << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\">";
for (size_t i = 0; i < mesh->mNumBones; ++i) for (size_t i = 0; i < mesh->mNumBones; ++i)
mOutput << XMLIDEncode(mesh->mBones[i]->mName.C_Str()) << " "; mOutput << GetBoneUniqueId(mesh->mBones[i]) << ' ';
mOutput << "</Name_array>" << endstr; mOutput << "</Name_array>" << endstr;
mOutput << startstr << "<technique_common>" << endstr; mOutput << startstr << "<technique_common>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<accessor source=\"#" << idstrEscaped << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\" stride=\"" << 1 << "\">" << endstr; mOutput << startstr << "<accessor source=\"#" << idstr << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\" stride=\"" << 1 << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<param name=\"JOINT\" type=\"Name\"></param>" << endstr; mOutput << startstr << "<param name=\"JOINT\" type=\"Name\"></param>" << endstr;
@ -932,8 +910,8 @@ void ColladaExporter::WriteController(size_t pIndex) {
mOutput << startstr << "<joints>" << endstr; mOutput << startstr << "<joints>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstrEscaped << "-skin-joints\"></input>" << endstr; mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstr << "-skin-joints\"></input>" << endstr;
mOutput << startstr << "<input semantic=\"INV_BIND_MATRIX\" source=\"#" << idstrEscaped << "-skin-bind_poses\"></input>" << endstr; mOutput << startstr << "<input semantic=\"INV_BIND_MATRIX\" source=\"#" << idstr << "-skin-bind_poses\"></input>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</joints>" << endstr; mOutput << startstr << "</joints>" << endstr;
@ -941,8 +919,8 @@ void ColladaExporter::WriteController(size_t pIndex) {
mOutput << startstr << "<vertex_weights count=\"" << mesh->mNumVertices << "\">" << endstr; mOutput << startstr << "<vertex_weights count=\"" << mesh->mNumVertices << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstrEscaped << "-skin-joints\" offset=\"0\"></input>" << endstr; mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstr << "-skin-joints\" offset=\"0\"></input>" << endstr;
mOutput << startstr << "<input semantic=\"WEIGHT\" source=\"#" << idstrEscaped << "-skin-weights\" offset=\"1\"></input>" << endstr; mOutput << startstr << "<input semantic=\"WEIGHT\" source=\"#" << idstr << "-skin-weights\" offset=\"1\"></input>" << endstr;
mOutput << startstr << "<vcount>"; mOutput << startstr << "<vcount>";
@ -1017,9 +995,8 @@ void ColladaExporter::WriteGeometryLibrary() {
// Writes the given mesh // Writes the given mesh
void ColladaExporter::WriteGeometry(size_t pIndex) { void ColladaExporter::WriteGeometry(size_t pIndex) {
const aiMesh *mesh = mScene->mMeshes[pIndex]; const aiMesh *mesh = mScene->mMeshes[pIndex];
const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); const std::string geometryId = GetObjectUniqueId(AiObjectType::Mesh, pIndex);
const std::string geometryName = XMLEscape(idstr); const std::string geometryName = GetObjectName(AiObjectType::Mesh, pIndex);
const std::string geometryId = XMLIDEncode(idstr);
if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
return; return;
@ -1032,15 +1009,15 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
PushTag(); PushTag();
// Positions // Positions
WriteFloatArray(idstr + "-positions", FloatType_Vector, (ai_real *)mesh->mVertices, mesh->mNumVertices); WriteFloatArray(geometryId + "-positions", FloatType_Vector, (ai_real *)mesh->mVertices, mesh->mNumVertices);
// Normals, if any // Normals, if any
if (mesh->HasNormals()) if (mesh->HasNormals())
WriteFloatArray(idstr + "-normals", FloatType_Vector, (ai_real *)mesh->mNormals, mesh->mNumVertices); WriteFloatArray(geometryId + "-normals", FloatType_Vector, (ai_real *)mesh->mNormals, mesh->mNumVertices);
// texture coords // texture coords
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) { if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) {
WriteFloatArray(idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, WriteFloatArray(geometryId + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
(ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices); (ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices);
} }
} }
@ -1048,7 +1025,7 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
// vertex colors // vertex colors
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (mesh->HasVertexColors(static_cast<unsigned int>(a))) if (mesh->HasVertexColors(static_cast<unsigned int>(a)))
WriteFloatArray(idstr + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices); WriteFloatArray(geometryId + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices);
} }
// assemble vertex structure // assemble vertex structure
@ -1248,17 +1225,29 @@ void ColladaExporter::WriteFloatArray(const std::string &pIdString, FloatDataTyp
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Writes the scene library // Writes the scene library
void ColladaExporter::WriteSceneLibrary() { void ColladaExporter::WriteSceneLibrary() {
const std::string sceneName = XMLEscape(mScene->mRootNode->mName.C_Str()); // Determine if we are using the aiScene root or our own
const std::string sceneId = XMLIDEncode(mScene->mRootNode->mName.C_Str()); std::string sceneName("Scene");
if (mAdd_root_node) {
mSceneId = MakeUniqueId(mUniqueIds, sceneName, std::string());
mUniqueIds.insert(mSceneId);
} else {
mSceneId = GetNodeUniqueId(mScene->mRootNode);
sceneName = GetNodeName(mScene->mRootNode);
}
mOutput << startstr << "<library_visual_scenes>" << endstr; mOutput << startstr << "<library_visual_scenes>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<visual_scene id=\"" + sceneId + "\" name=\"" + sceneName + "\">" << endstr; mOutput << startstr << "<visual_scene id=\"" + mSceneId + "\" name=\"" + sceneName + "\">" << endstr;
PushTag(); PushTag();
// start recursive write at the root node if (mAdd_root_node) {
// Export the root node
WriteNode(mScene->mRootNode);
} else {
// Have already exported the root node
for (size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a) for (size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a)
WriteNode(mScene, mScene->mRootNode->mChildren[a]); WriteNode(mScene->mRootNode->mChildren[a]);
}
PopTag(); PopTag();
mOutput << startstr << "</visual_scene>" << endstr; mOutput << startstr << "</visual_scene>" << endstr;
@ -1272,20 +1261,10 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0) if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0)
return; return;
const std::string animation_name_escaped = XMLEscape(anim->mName.C_Str()); const std::string animationNameEscaped = GetObjectName(AiObjectType::Animation, pIndex);
std::string idstr = anim->mName.C_Str(); const std::string idstrEscaped = GetObjectUniqueId(AiObjectType::Animation, pIndex);
std::string ending = std::string("AnimId") + to_string(pIndex);
if (idstr.length() >= ending.length()) {
if (0 != idstr.compare(idstr.length() - ending.length(), ending.length(), ending)) {
idstr = idstr + ending;
}
} else {
idstr = idstr + ending;
}
const std::string idstrEscaped = XMLIDEncode(idstr); mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animationNameEscaped + "\">" << endstr;
mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
PushTag(); PushTag();
std::string cur_node_idstr; std::string cur_node_idstr;
@ -1435,20 +1414,21 @@ void ColladaExporter::WriteAnimationsLibrary() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Helper to find a bone by name in the scene // Helper to find a bone by name in the scene
aiBone *findBone(const aiScene *scene, const char *name) { aiBone *findBone(const aiScene *scene, const aiString &name) {
for (size_t m = 0; m < scene->mNumMeshes; m++) { for (size_t m = 0; m < scene->mNumMeshes; m++) {
aiMesh *mesh = scene->mMeshes[m]; aiMesh *mesh = scene->mMeshes[m];
for (size_t b = 0; b < mesh->mNumBones; b++) { for (size_t b = 0; b < mesh->mNumBones; b++) {
aiBone *bone = mesh->mBones[b]; aiBone *bone = mesh->mBones[b];
if (0 == strcmp(name, bone->mName.C_Str())) { if (name == bone->mName) {
return bone; return bone;
} }
} }
} }
return NULL; return nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Helper to find the node associated with a bone in the scene
const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) { const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) {
if (aNode && bone && aNode->mName == bone->mName) { if (aNode && bone && aNode->mName == bone->mName) {
return aNode; return aNode;
@ -1457,15 +1437,17 @@ const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) {
if (aNode && bone) { if (aNode && bone) {
for (unsigned int i = 0; i < aNode->mNumChildren; ++i) { for (unsigned int i = 0; i < aNode->mNumChildren; ++i) {
aiNode *aChild = aNode->mChildren[i]; aiNode *aChild = aNode->mChildren[i];
const aiNode *foundFromChild = 0; const aiNode *foundFromChild = nullptr;
if (aChild) { if (aChild) {
foundFromChild = findBoneNode(aChild, bone); foundFromChild = findBoneNode(aChild, bone);
if (foundFromChild) return foundFromChild; if (foundFromChild) {
return foundFromChild;
}
} }
} }
} }
return NULL; return nullptr;
} }
const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) { const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
@ -1476,7 +1458,7 @@ const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
const aiNode *node = findBoneNode(scene->mRootNode, bone); const aiNode *node = findBoneNode(scene->mRootNode, bone);
if (node) { if (node) {
while (node->mParent && findBone(scene, node->mParent->mName.C_Str()) != 0) { while (node->mParent && findBone(scene, node->mParent->mName) != nullptr) {
node = node->mParent; node = node->mParent;
} }
topParentBoneNodes.insert(node); topParentBoneNodes.insert(node);
@ -1496,44 +1478,35 @@ const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
} }
} }
return NULL; return nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursively writes the given node // Recursively writes the given node
void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { void ColladaExporter::WriteNode(const aiNode *pNode) {
// the node must have a name
if (pNode->mName.length == 0) {
std::stringstream ss;
ss << "Node_" << pNode;
pNode->mName.Set(ss.str());
}
// If the node is associated with a bone, it is a joint node (JOINT) // If the node is associated with a bone, it is a joint node (JOINT)
// otherwise it is a normal node (NODE) // otherwise it is a normal node (NODE)
// Assimp-specific: nodes with no name cannot be associated with bones
const char *node_type; const char *node_type;
bool is_joint, is_skeleton_root = false; bool is_joint, is_skeleton_root = false;
if (nullptr == findBone(pScene, pNode->mName.C_Str())) { if (pNode->mName.length == 0 || nullptr == findBone(mScene, pNode->mName)) {
node_type = "NODE"; node_type = "NODE";
is_joint = false; is_joint = false;
} else { } else {
node_type = "JOINT"; node_type = "JOINT";
is_joint = true; is_joint = true;
if (!pNode->mParent || nullptr == findBone(pScene, pNode->mParent->mName.C_Str())) { if (!pNode->mParent || nullptr == findBone(mScene, pNode->mParent->mName)) {
is_skeleton_root = true; is_skeleton_root = true;
} }
} }
const std::string node_id = XMLIDEncode(pNode->mName.data); const std::string node_id = GetNodeUniqueId(pNode);
const std::string node_name = XMLEscape(pNode->mName.data); const std::string node_name = GetNodeName(pNode);
mOutput << startstr << "<node "; mOutput << startstr << "<node ";
if (is_skeleton_root) { if (is_skeleton_root) {
mOutput << "id=\"" << node_id << "\" " << (is_joint ? "sid=\"" + node_id + "\"" : ""); // For now, only support one skeleton in a scene. mFoundSkeletonRootNodeID = node_id; // For now, only support one skeleton in a scene.
mFoundSkeletonRootNodeID = node_id;
} else {
mOutput << "id=\"" << node_id << "\" " << (is_joint ? "sid=\"" + node_id + "\"" : "");
} }
mOutput << "id=\"" << node_id << "\" " << (is_joint ? "sid=\"" + node_id + "\" " : "");
mOutput << "name=\"" << node_name mOutput << "name=\"" << node_name
<< "\" type=\"" << node_type << "\" type=\"" << node_type
<< "\">" << endstr; << "\">" << endstr;
@ -1573,14 +1546,14 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
//check if it is a camera node //check if it is a camera node
for (size_t i = 0; i < mScene->mNumCameras; i++) { for (size_t i = 0; i < mScene->mNumCameras; i++) {
if (mScene->mCameras[i]->mName == pNode->mName) { if (mScene->mCameras[i]->mName == pNode->mName) {
mOutput << startstr << "<instance_camera url=\"#" << node_id << "-camera\"/>" << endstr; mOutput << startstr << "<instance_camera url=\"#" << GetObjectUniqueId(AiObjectType::Camera, i) << "\"/>" << endstr;
break; break;
} }
} }
//check if it is a light node //check if it is a light node
for (size_t i = 0; i < mScene->mNumLights; i++) { for (size_t i = 0; i < mScene->mNumLights; i++) {
if (mScene->mLights[i]->mName == pNode->mName) { if (mScene->mLights[i]->mName == pNode->mName) {
mOutput << startstr << "<instance_light url=\"#" << node_id << "-light\"/>" << endstr; mOutput << startstr << "<instance_light url=\"#" << GetObjectUniqueId(AiObjectType::Light, i) << "\"/>" << endstr;
break; break;
} }
} }
@ -1593,22 +1566,22 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
continue; continue;
const std::string meshName = mesh->mName.length == 0 ? GetMeshId(pNode->mMeshes[a]) : mesh->mName.C_Str(); const std::string meshId = GetObjectUniqueId(AiObjectType::Mesh, pNode->mMeshes[a]);
if (mesh->mNumBones == 0) { if (mesh->mNumBones == 0) {
mOutput << startstr << "<instance_geometry url=\"#" << XMLIDEncode(meshName) << "\">" << endstr; mOutput << startstr << "<instance_geometry url=\"#" << meshId << "\">" << endstr;
PushTag(); PushTag();
} else { } else {
mOutput << startstr mOutput << startstr
<< "<instance_controller url=\"#" << XMLIDEncode(meshName) << "-skin\">" << "<instance_controller url=\"#" << meshId << "-skin\">"
<< endstr; << endstr;
PushTag(); PushTag();
// note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node. // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node.
// use the first bone to find skeleton root // use the first bone to find skeleton root
const aiNode *skeletonRootBoneNode = findSkeletonRootNode(pScene, mesh); const aiNode *skeletonRootBoneNode = findSkeletonRootNode(mScene, mesh);
if (skeletonRootBoneNode) { if (skeletonRootBoneNode) {
mFoundSkeletonRootNodeID = XMLIDEncode(skeletonRootBoneNode->mName.C_Str()); mFoundSkeletonRootNodeID = GetNodeUniqueId(skeletonRootBoneNode);
} }
mOutput << startstr << "<skeleton>#" << mFoundSkeletonRootNodeID << "</skeleton>" << endstr; mOutput << startstr << "<skeleton>#" << mFoundSkeletonRootNodeID << "</skeleton>" << endstr;
} }
@ -1616,7 +1589,7 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
PushTag(); PushTag();
mOutput << startstr << "<technique_common>" << endstr; mOutput << startstr << "<technique_common>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLIDEncode(materials[mesh->mMaterialIndex].name) << "\">" << endstr; mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << GetObjectUniqueId(AiObjectType::Material, mesh->mMaterialIndex) << "\">" << endstr;
PushTag(); PushTag();
for (size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa) { for (size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa) {
if (mesh->HasTextureCoords(static_cast<unsigned int>(aa))) if (mesh->HasTextureCoords(static_cast<unsigned int>(aa)))
@ -1641,11 +1614,135 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
// recurse into subnodes // recurse into subnodes
for (size_t a = 0; a < pNode->mNumChildren; ++a) for (size_t a = 0; a < pNode->mNumChildren; ++a)
WriteNode(pScene, pNode->mChildren[a]); WriteNode(pNode->mChildren[a]);
PopTag(); PopTag();
mOutput << startstr << "</node>" << endstr; mOutput << startstr << "</node>" << endstr;
} }
void ColladaExporter::CreateNodeIds(const aiNode *node) {
GetNodeUniqueId(node);
for (size_t a = 0; a < node->mNumChildren; ++a)
CreateNodeIds(node->mChildren[a]);
}
std::string ColladaExporter::GetNodeUniqueId(const aiNode *node) {
// Use the pointer as the key. This is safe because the scene is immutable.
auto idIt = mNodeIdMap.find(node);
if (idIt != mNodeIdMap.cend())
return idIt->second;
// Prefer the requested Collada Id if extant
std::string idStr;
aiString origId;
if (node->mMetaData && node->mMetaData->Get(AI_METADATA_COLLADA_ID, origId)) {
idStr = origId.C_Str();
} else {
idStr = node->mName.C_Str();
}
// Make sure the requested id is valid
if (idStr.empty())
idStr = "node";
else
idStr = XMLIDEncode(idStr);
// Ensure it's unique
idStr = MakeUniqueId(mUniqueIds, idStr, std::string());
mUniqueIds.insert(idStr);
mNodeIdMap.insert(std::make_pair(node, idStr));
return idStr;
}
std::string ColladaExporter::GetNodeName(const aiNode *node) {
return XMLEscape(node->mName.C_Str());
}
std::string ColladaExporter::GetBoneUniqueId(const aiBone *bone) {
// Find the Node that is this Bone
const aiNode *boneNode = findBoneNode(mScene->mRootNode, bone);
if (boneNode == nullptr)
return std::string();
return GetNodeUniqueId(boneNode);
}
std::string ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t pIndex) {
auto idIt = GetObjectIdMap(type).find(pIndex);
if (idIt != GetObjectIdMap(type).cend())
return idIt->second;
// Not seen this object before, create and add
NameIdPair result = AddObjectIndexToMaps(type, pIndex);
return result.second;
}
std::string ColladaExporter::GetObjectName(AiObjectType type, size_t pIndex) {
auto objectName = GetObjectNameMap(type).find(pIndex);
if (objectName != GetObjectNameMap(type).cend())
return objectName->second;
// Not seen this object before, create and add
NameIdPair result = AddObjectIndexToMaps(type, pIndex);
return result.first;
}
// Determine unique id and add the name and id to the maps
// @param type object type
// @param index object index
// @param name in/out. Caller to set the original name if known.
// @param idStr in/out. Caller to set the preferred id if known.
ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType type, size_t index) {
std::string name;
std::string idStr;
std::string idPostfix;
// Get the name and id postfix
switch (type) {
case AiObjectType::Mesh: name = mScene->mMeshes[index]->mName.C_Str(); break;
case AiObjectType::Material: name = mScene->mMaterials[index]->GetName().C_Str(); break;
case AiObjectType::Animation: name = mScene->mAnimations[index]->mName.C_Str(); break;
case AiObjectType::Light:
name = mScene->mLights[index]->mName.C_Str();
idPostfix = "-light";
break;
case AiObjectType::Camera:
name = mScene->mCameras[index]->mName.C_Str();
idPostfix = "-camera";
break;
case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
}
if (name.empty()) {
// Default ids if empty name
switch (type) {
case AiObjectType::Mesh: idStr = std::string("mesh_"); break;
case AiObjectType::Material: idStr = std::string("material_"); break; // This one should never happen
case AiObjectType::Animation: idStr = std::string("animation_"); break;
case AiObjectType::Light: idStr = std::string("light_"); break;
case AiObjectType::Camera: idStr = std::string("camera_"); break;
case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
}
idStr.append(to_string(index));
} else {
idStr = XMLIDEncode(name);
}
if (!name.empty())
name = XMLEscape(name);
idStr = MakeUniqueId(mUniqueIds, idStr, idPostfix);
// Add to maps
mUniqueIds.insert(idStr);
GetObjectIdMap(type).insert(std::make_pair(index, idStr));
GetObjectNameMap(type).insert(std::make_pair(index, name));
return std::make_pair(name, idStr);
}
} // end of namespace Assimp
#endif #endif
#endif #endif

View File

@ -48,25 +48,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <assimp/mesh.h>
#include <assimp/light.h>
#include <assimp/Exporter.hpp>
#include <sstream>
#include <vector>
#include <map>
#include <assimp/StringUtils.h> #include <array>
#include <map>
#include <sstream>
#include <unordered_set>
#include <vector>
struct aiScene; struct aiScene;
struct aiNode; struct aiNode;
struct aiLight;
struct aiBone;
namespace Assimp namespace Assimp {
{
class IOSystem;
/// Helper class to export a given scene to a Collada file. Just for my personal /// Helper class to export a given scene to a Collada file. Just for my personal
/// comfort when implementing it. /// comfort when implementing it.
class ColladaExporter class ColladaExporter {
{
public: public:
/// Constructor for a specific scene to export /// Constructor for a specific scene to export
ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file); ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file);
@ -117,7 +117,13 @@ protected:
//enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight }; //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight };
// customized to add animation related type // customized to add animation related type
enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight, FloatType_Time }; enum FloatDataType { FloatType_Vector,
FloatType_TexCoord2,
FloatType_TexCoord3,
FloatType_Color,
FloatType_Mat4x4,
FloatType_Weight,
FloatType_Time };
/// Writes a float array of the given type /// Writes a float array of the given type
void WriteFloatArray(const std::string &pIdString, FloatDataType pType, const ai_real *pData, size_t pElementCount); void WriteFloatArray(const std::string &pIdString, FloatDataType pType, const ai_real *pData, size_t pElementCount);
@ -131,7 +137,7 @@ protected:
std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call. std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call.
/// Recursively writes the given node /// Recursively writes the given node
void WriteNode( const aiScene* scene, aiNode* pNode); void WriteNode(const aiNode *pNode);
/// Enters a new xml element, which increases the indentation /// Enters a new xml element, which increases the indentation
void PushTag() { startstr.append(" "); } void PushTag() { startstr.append(" "); }
@ -141,10 +147,40 @@ protected:
startstr.erase(startstr.length() - 2); startstr.erase(startstr.length() - 2);
} }
/// Creates a mesh ID for the given mesh void CreateNodeIds(const aiNode *node);
std::string GetMeshId( size_t pIndex) const {
return std::string( "meshId" ) + to_string(pIndex); /// Get or Create a unique Node ID string for the given Node
} std::string GetNodeUniqueId(const aiNode *node);
std::string GetNodeName(const aiNode *node);
std::string GetBoneUniqueId(const aiBone *bone);
enum class AiObjectType {
Mesh,
Material,
Animation,
Light,
Camera,
Count,
};
/// Get or Create a unique ID string for the given scene object index
std::string GetObjectUniqueId(AiObjectType type, size_t pIndex);
/// Get or Create a name string for the given scene object index
std::string GetObjectName(AiObjectType type, size_t pIndex);
typedef std::map<size_t, std::string> IndexIdMap;
typedef std::pair<std::string, std::string> NameIdPair;
NameIdPair AddObjectIndexToMaps(AiObjectType type, size_t pIndex);
// Helpers
inline IndexIdMap &GetObjectIdMap(AiObjectType type) { return mObjectIdMap[static_cast<size_t>(type)]; }
inline IndexIdMap &GetObjectNameMap(AiObjectType type) { return mObjectNameMap[static_cast<size_t>(type)]; }
private:
std::unordered_set<std::string> mUniqueIds; // Cache of used unique ids
std::map<const void *, std::string> mNodeIdMap; // Cache of encoded node and bone ids
std::array<IndexIdMap, static_cast<size_t>(AiObjectType::Count)> mObjectIdMap; // Cache of encoded unique IDs
std::array<IndexIdMap, static_cast<size_t>(AiObjectType::Count)> mObjectNameMap; // Cache of encoded names
public: public:
/// Stringstream to write all output into /// Stringstream to write all output into
@ -160,37 +196,38 @@ public:
const std::string mFile; const std::string mFile;
/// The scene to be written /// The scene to be written
const aiScene* mScene; const aiScene *const mScene;
bool mSceneOwned; std::string mSceneId;
bool mAdd_root_node = false;
/// current line start string, contains the current indentation for simple stream insertion /// current line start string, contains the current indentation for simple stream insertion
std::string startstr; std::string startstr;
/// current line end string for simple stream insertion /// current line end string for simple stream insertion
std::string endstr; const std::string endstr;
// pair of color and texture - texture precedences color // pair of color and texture - texture precedences color
struct Surface struct Surface {
{
bool exist; bool exist;
aiColor4D color; aiColor4D color;
std::string texture; std::string texture;
size_t channel; size_t channel;
Surface() { exist = false; channel = 0; } Surface() {
exist = false;
channel = 0;
}
}; };
struct Property struct Property {
{
bool exist; bool exist;
ai_real value; ai_real value;
Property() Property() :
: exist(false) exist(false),
, value(0.0) value(0.0) {}
{}
}; };
// summarize a material in an convenient way. // summarize a material in an convenient way.
struct Material struct Material {
{ std::string id;
std::string name; std::string name;
std::string shading_model; std::string shading_model;
Surface ambient, diffuse, specular, emissive, reflective, transparent, normal; Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
@ -199,24 +236,22 @@ public:
Material() {} Material() {}
}; };
std::vector<Material> materials;
std::map<unsigned int, std::string> textures; std::map<unsigned int, std::string> textures;
public: public:
/// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions
/// Reads a single surface entry from the given material keys /// Reads a single surface entry from the given material keys
void ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex); bool ReadMaterialSurface(Surface &poSurface, const aiMaterial &pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex);
/// Writes an image entry for the given surface /// Writes an image entry for the given surface
void WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd); void WriteImageEntry(const Surface &pSurface, const std::string &imageId);
/// Writes the two parameters necessary for referencing a texture in an effect entry /// Writes the two parameters necessary for referencing a texture in an effect entry
void WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName); void WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &materialId);
/// Writes a color-or-texture entry into an effect definition /// Writes a color-or-texture entry into an effect definition
void WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName); void WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &imageId);
/// Writes a scalar property /// Writes a scalar property
void WriteFloatEntry(const Property &pProperty, const std::string &pTypeName); void WriteFloatEntry(const Property &pProperty, const std::string &pTypeName);
}; };
} } // namespace Assimp
#endif // !! AI_COLLADAEXPORTER_H_INC #endif // !! AI_COLLADAEXPORTER_H_INC

View File

@ -43,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ColladaHelper.h" #include "ColladaHelper.h"
#include <assimp/commonMetaData.h>
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/commonMetaData.h>
namespace Assimp { namespace Assimp {
namespace Collada { namespace Collada {
@ -63,39 +63,32 @@ const MetaKeyPairVector &GetColladaAssimpMetaKeys() {
const MetaKeyPairVector MakeColladaAssimpMetaKeysCamelCase() { const MetaKeyPairVector MakeColladaAssimpMetaKeysCamelCase() {
MetaKeyPairVector result = MakeColladaAssimpMetaKeys(); MetaKeyPairVector result = MakeColladaAssimpMetaKeys();
for (auto &val : result) for (auto &val : result) {
{
ToCamelCase(val.first); ToCamelCase(val.first);
} }
return result; return result;
}; };
const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase() const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase() {
{
static const MetaKeyPairVector result = MakeColladaAssimpMetaKeysCamelCase(); static const MetaKeyPairVector result = MakeColladaAssimpMetaKeysCamelCase();
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert underscore_separated to CamelCase: "authoring_tool" becomes "AuthoringTool" // Convert underscore_separated to CamelCase: "authoring_tool" becomes "AuthoringTool"
void ToCamelCase(std::string &text) void ToCamelCase(std::string &text) {
{
if (text.empty()) if (text.empty())
return; return;
// Capitalise first character // Capitalise first character
auto it = text.begin(); auto it = text.begin();
(*it) = ToUpper(*it); (*it) = ToUpper(*it);
++it; ++it;
for (/*started above*/ ; it != text.end(); /*iterated below*/) for (/*started above*/; it != text.end(); /*iterated below*/) {
{ if ((*it) == '_') {
if ((*it) == '_')
{
it = text.erase(it); it = text.erase(it);
if (it != text.end()) if (it != text.end())
(*it) = ToUpper(*it); (*it) = ToUpper(*it);
} } else {
else
{
// Make lower case // Make lower case
(*it) = ToLower(*it); (*it) = ToLower(*it);
++it; ++it;

View File

@ -45,13 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_COLLADAHELPER_H_INC #ifndef AI_COLLADAHELPER_H_INC
#define AI_COLLADAHELPER_H_INC #define AI_COLLADAHELPER_H_INC
#include <map>
#include <vector>
#include <set>
#include <stdint.h>
#include <assimp/light.h> #include <assimp/light.h>
#include <assimp/mesh.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <assimp/mesh.h>
#include <stdint.h>
#include <map>
#include <set>
#include <vector>
struct aiMaterial; struct aiMaterial;
@ -59,17 +59,14 @@ namespace Assimp {
namespace Collada { namespace Collada {
/** Collada file versions which evolved during the years ... */ /** Collada file versions which evolved during the years ... */
enum FormatVersion enum FormatVersion {
{
FV_1_5_n, FV_1_5_n,
FV_1_4_n, FV_1_4_n,
FV_1_3_n FV_1_3_n
}; };
/** Transformation types that can be applied to a node */ /** Transformation types that can be applied to a node */
enum TransformType enum TransformType {
{
TF_LOOKAT, TF_LOOKAT,
TF_ROTATE, TF_ROTATE,
TF_TRANSLATE, TF_TRANSLATE,
@ -79,8 +76,7 @@ enum TransformType
}; };
/** Different types of input data to a vertex or face */ /** Different types of input data to a vertex or face */
enum InputType enum InputType {
{
IT_Invalid, IT_Invalid,
IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data. IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
IT_Position, IT_Position,
@ -92,15 +88,13 @@ enum InputType
}; };
/** Supported controller types */ /** Supported controller types */
enum ControllerType enum ControllerType {
{
Skin, Skin,
Morph Morph
}; };
/** Supported morph methods */ /** Supported morph methods */
enum MorphMethod enum MorphMethod {
{
Normalized, Normalized,
Relative Relative
}; };
@ -118,24 +112,21 @@ const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase();
void ToCamelCase(std::string &text); void ToCamelCase(std::string &text);
/** Contains all data for one of the different transformation types */ /** Contains all data for one of the different transformation types */
struct Transform struct Transform {
{
std::string mID; ///< SID of the transform step, by which anim channels address their target node std::string mID; ///< SID of the transform step, by which anim channels address their target node
TransformType mType; TransformType mType;
ai_real f[16]; ///< Interpretation of data depends on the type of the transformation ai_real f[16]; ///< Interpretation of data depends on the type of the transformation
}; };
/** A collada camera. */ /** A collada camera. */
struct Camera struct Camera {
{ Camera() :
Camera() mOrtho(false),
: mOrtho (false) mHorFov(10e10f),
, mHorFov (10e10f) mVerFov(10e10f),
, mVerFov (10e10f) mAspect(10e10f),
, mAspect (10e10f) mZNear(0.1f),
, mZNear (0.1f) mZFar(1000.f) {}
, mZFar (1000.f)
{}
// Name of camera // Name of camera
std::string mName; std::string mName;
@ -159,19 +150,17 @@ struct Camera
#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
/** A collada light source. */ /** A collada light source. */
struct Light struct Light {
{ Light() :
Light() mType(aiLightSource_UNDEFINED),
: mType (aiLightSource_UNDEFINED) mAttConstant(1.f),
, mAttConstant (1.f) mAttLinear(0.f),
, mAttLinear (0.f) mAttQuadratic(0.f),
, mAttQuadratic (0.f) mFalloffAngle(180.f),
, mFalloffAngle (180.f) mFalloffExponent(0.f),
, mFalloffExponent (0.f) mPenumbraAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET),
, mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) mOuterAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET),
, mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) mIntensity(1.f) {}
, mIntensity (1.f)
{}
//! Type of the light source aiLightSourceType + ambient //! Type of the light source aiLightSourceType + ambient
unsigned int mType; unsigned int mType;
@ -198,12 +187,10 @@ struct Light
}; };
/** Short vertex index description */ /** Short vertex index description */
struct InputSemanticMapEntry struct InputSemanticMapEntry {
{ InputSemanticMapEntry() :
InputSemanticMapEntry() mSet(0),
: mSet(0) mType(IT_Invalid) {}
, mType(IT_Invalid)
{}
//! Index of set, optional //! Index of set, optional
unsigned int mSet; unsigned int mSet;
@ -213,8 +200,7 @@ struct InputSemanticMapEntry
}; };
/** Table to map from effect to vertex input semantics */ /** Table to map from effect to vertex input semantics */
struct SemanticMappingTable struct SemanticMappingTable {
{
//! Name of material //! Name of material
std::string mMatName; std::string mMatName;
@ -230,8 +216,7 @@ struct SemanticMappingTable
/** A reference to a mesh inside a node, including materials assigned to the various subgroups. /** A reference to a mesh inside a node, including materials assigned to the various subgroups.
* The ID refers to either a mesh or a controller which specifies the mesh * The ID refers to either a mesh or a controller which specifies the mesh
*/ */
struct MeshInstance struct MeshInstance {
{
///< ID of the mesh or controller to be instanced ///< ID of the mesh or controller to be instanced
std::string mMeshOrController; std::string mMeshOrController;
@ -240,29 +225,25 @@ struct MeshInstance
}; };
/** A reference to a camera inside a node*/ /** A reference to a camera inside a node*/
struct CameraInstance struct CameraInstance {
{
///< ID of the camera ///< ID of the camera
std::string mCamera; std::string mCamera;
}; };
/** A reference to a light inside a node*/ /** A reference to a light inside a node*/
struct LightInstance struct LightInstance {
{
///< ID of the camera ///< ID of the camera
std::string mLight; std::string mLight;
}; };
/** A reference to a node inside a node*/ /** A reference to a node inside a node*/
struct NodeInstance struct NodeInstance {
{
///< ID of the node ///< ID of the node
std::string mNode; std::string mNode;
}; };
/** A node in a scene hierarchy */ /** A node in a scene hierarchy */
struct Node struct Node {
{
std::string mName; std::string mName;
std::string mID; std::string mID;
std::string mSID; std::string mSID;
@ -288,8 +269,8 @@ struct Node
std::string mPrimaryCamera; std::string mPrimaryCamera;
//! Constructor. Begin with a zero parent //! Constructor. Begin with a zero parent
Node() Node() :
: mParent( nullptr ){ mParent(nullptr) {
// empty // empty
} }
@ -301,16 +282,14 @@ struct Node
}; };
/** Data source array: either floats or strings */ /** Data source array: either floats or strings */
struct Data struct Data {
{
bool mIsStringArray; bool mIsStringArray;
std::vector<ai_real> mValues; std::vector<ai_real> mValues;
std::vector<std::string> mStrings; std::vector<std::string> mStrings;
}; };
/** Accessor to a data array */ /** Accessor to a data array */
struct Accessor struct Accessor {
{
size_t mCount; // in number of objects size_t mCount; // in number of objects
size_t mSize; // size of an object, in elements (floats or strings, mostly 1) size_t mSize; // size of an object, in elements (floats or strings, mostly 1)
size_t mOffset; // in number of values size_t mOffset; // in number of values
@ -319,49 +298,54 @@ 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; mOffset = 0; mStride = 0; mData = NULL; mSize = 0;
mOffset = 0;
mStride = 0;
mData = nullptr;
mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0; mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
} }
}; };
/** A single face in a mesh */ /** A single face in a mesh */
struct Face struct Face {
{
std::vector<size_t> mIndices; std::vector<size_t> mIndices;
}; };
/** An input channel for mesh data, referring to a single accessor */ /** An input channel for mesh data, referring to a single accessor */
struct InputChannel struct InputChannel {
{
InputType mType; // Type of the data InputType mType; // Type of the data
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() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; } InputChannel() {
mType = IT_Invalid;
mIndex = 0;
mOffset = 0;
mResolved = nullptr;
}
}; };
/** Subset of a mesh with a certain material */ /** Subset of a mesh with a certain material */
struct SubMesh struct SubMesh {
{
std::string mMaterial; ///< subgroup identifier std::string mMaterial; ///< subgroup identifier
size_t mNumFaces; ///< number of faces in this submesh size_t mNumFaces; ///< number of faces in this submesh
}; };
/** Contains data for a single mesh */ /** Contains data for a single mesh */
struct Mesh struct Mesh {
{ Mesh(const std::string &id) :
Mesh() mId(id) {
{
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i)
mNumUVComponents[i] = 2; mNumUVComponents[i] = 2;
} }
const std::string mId;
std::string mName; std::string mName;
// just to check if there's some sophisticated addressing involved... // just to check if there's some sophisticated addressing involved...
@ -394,8 +378,7 @@ struct Mesh
}; };
/** Which type of primitives the ReadPrimitives() function is going to read */ /** Which type of primitives the ReadPrimitives() function is going to read */
enum PrimitiveType enum PrimitiveType {
{
Prim_Invalid, Prim_Invalid,
Prim_Lines, Prim_Lines,
Prim_LineStrip, Prim_LineStrip,
@ -407,8 +390,7 @@ enum PrimitiveType
}; };
/** A skeleton controller to deform a mesh with the use of joints */ /** A skeleton controller to deform a mesh with the use of joints */
struct Controller struct Controller {
{
// controller type // controller type
ControllerType mType; ControllerType mType;
@ -443,29 +425,25 @@ struct Controller
}; };
/** A collada material. Pretty much the only member is a reference to an effect. */ /** A collada material. Pretty much the only member is a reference to an effect. */
struct Material struct Material {
{
std::string mName; std::string mName;
std::string mEffect; std::string mEffect;
}; };
/** Type of the effect param */ /** Type of the effect param */
enum ParamType enum ParamType {
{
Param_Sampler, Param_Sampler,
Param_Surface Param_Surface
}; };
/** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */ /** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
struct EffectParam struct EffectParam {
{
ParamType mType; ParamType mType;
std::string mReference; // to which other thing the param is referring to. std::string mReference; // to which other thing the param is referring to.
}; };
/** Shading type supported by the standard effect spec of Collada */ /** Shading type supported by the standard effect spec of Collada */
enum ShadeType enum ShadeType {
{
Shade_Invalid, Shade_Invalid,
Shade_Constant, Shade_Constant,
Shade_Lambert, Shade_Lambert,
@ -474,18 +452,16 @@ enum ShadeType
}; };
/** Represents a texture sampler in collada */ /** Represents a texture sampler in collada */
struct Sampler struct Sampler {
{ Sampler() :
Sampler() mWrapU(true),
: mWrapU (true) mWrapV(true),
, mWrapV (true) mMirrorU(),
, mMirrorU () mMirrorV(),
, mMirrorV () mOp(aiTextureOp_Multiply),
, mOp (aiTextureOp_Multiply) mUVId(UINT_MAX),
, mUVId (UINT_MAX) mWeighting(1.f),
, mWeighting (1.f) mMixWithPrevious(1.f) {}
, mMixWithPrevious (1.f)
{}
/** Name of image reference /** Name of image reference
*/ */
@ -537,8 +513,7 @@ struct Sampler
/** A collada effect. Can contain about anything according to the Collada spec, /** A collada effect. Can contain about anything according to the Collada spec,
but we limit our version to a reasonable subset. */ but we limit our version to a reasonable subset. */
struct Effect struct Effect {
{
// Shading mode // Shading mode
ShadeType mShadeType; ShadeType mShadeType;
@ -566,30 +541,28 @@ struct Effect
// Double-sided? // Double-sided?
bool mDoubleSided, mWireframe, mFaceted; bool mDoubleSided, mWireframe, mFaceted;
Effect() Effect() :
: mShadeType (Shade_Phong) mShadeType(Shade_Phong),
, mEmissive ( 0, 0, 0, 1) mEmissive(0, 0, 0, 1),
, mAmbient ( 0.1f, 0.1f, 0.1f, 1) mAmbient(0.1f, 0.1f, 0.1f, 1),
, mDiffuse ( 0.6f, 0.6f, 0.6f, 1) mDiffuse(0.6f, 0.6f, 0.6f, 1),
, mSpecular ( 0.4f, 0.4f, 0.4f, 1) mSpecular(0.4f, 0.4f, 0.4f, 1),
, mTransparent ( 0, 0, 0, 1) mTransparent(0, 0, 0, 1),
, mShininess (10.0f) mShininess(10.0f),
, mRefractIndex (1.f) mRefractIndex(1.f),
, mReflectivity (0.f) mReflectivity(0.f),
, mTransparency (1.f) mTransparency(1.f),
, mHasTransparency (false) mHasTransparency(false),
, mRGBTransparency(false) mRGBTransparency(false),
, mInvertTransparency(false) mInvertTransparency(false),
, mDoubleSided (false) mDoubleSided(false),
, mWireframe (false) mWireframe(false),
, mFaceted (false) mFaceted(false) {
{
} }
}; };
/** An image, meaning texture */ /** An image, meaning texture */
struct Image struct Image {
{
std::string mFileName; std::string mFileName;
/** Embedded image data */ /** Embedded image data */
@ -600,8 +573,7 @@ struct Image
}; };
/** An animation channel. */ /** An animation channel. */
struct AnimationChannel struct AnimationChannel {
{
/** URL of the data to animate. Could be about anything, but we support only the /** URL of the data to animate. Could be about anything, but we support only the
* "NodeID/TransformID.SubElement" notation * "NodeID/TransformID.SubElement" notation
*/ */
@ -620,8 +592,7 @@ struct AnimationChannel
}; };
/** An animation. Container for 0-x animation channels or 0-x animations */ /** An animation. Container for 0-x animation channels or 0-x animations */
struct Animation struct Animation {
{
/** Anim name */ /** Anim name */
std::string mName; std::string mName;
@ -632,19 +603,16 @@ struct Animation
std::vector<Animation *> mSubAnims; std::vector<Animation *> mSubAnims;
/** Destructor */ /** Destructor */
~Animation() ~Animation() {
{
for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
delete *it; delete *it;
} }
/** Collect all channels in the animation hierarchy into a single channel list. */ /** Collect all channels in the animation hierarchy into a single channel list. */
void CollectChannelsRecursively(std::vector<AnimationChannel> &channels) void CollectChannelsRecursively(std::vector<AnimationChannel> &channels) {
{
channels.insert(channels.end(), mChannels.begin(), mChannels.end()); channels.insert(channels.end(), mChannels.begin(), mChannels.end());
for (std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) {
{
Animation *pAnim = (*it); Animation *pAnim = (*it);
pAnim->CollectChannelsRecursively(channels); pAnim->CollectChannelsRecursively(channels);
@ -652,18 +620,15 @@ struct Animation
} }
/** Combine all single-channel animations' channel into the same (parent) animation channel list. */ /** Combine all single-channel animations' channel into the same (parent) animation channel list. */
void CombineSingleChannelAnimations() void CombineSingleChannelAnimations() {
{
CombineSingleChannelAnimationsRecursively(this); CombineSingleChannelAnimationsRecursively(this);
} }
void CombineSingleChannelAnimationsRecursively(Animation *pParent) void CombineSingleChannelAnimationsRecursively(Animation *pParent) {
{
std::set<std::string> childrenTargets; std::set<std::string> childrenTargets;
bool childrenAnimationsHaveDifferentChannels = true; bool childrenAnimationsHaveDifferentChannels = true;
for (std::vector<Animation*>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
{
Animation *anim = *it; Animation *anim = *it;
CombineSingleChannelAnimationsRecursively(anim); CombineSingleChannelAnimationsRecursively(anim);
@ -678,10 +643,8 @@ struct Animation
} }
// We only want to combine animations if they have different channels // We only want to combine animations if they have different channels
if (childrenAnimationsHaveDifferentChannels) if (childrenAnimationsHaveDifferentChannels) {
{ for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
for (std::vector<Animation*>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();)
{
Animation *anim = *it; Animation *anim = *it;
pParent->mChannels.push_back(anim->mChannels[0]); pParent->mChannels.push_back(anim->mChannels[0]);
@ -696,8 +659,7 @@ struct Animation
}; };
/** Description of a collada animation channel which has been determined to affect the current node */ /** Description of a collada animation channel which has been determined to affect the current node */
struct ChannelEntry struct ChannelEntry {
{
const Collada::AnimationChannel *mChannel; ///> the source channel const Collada::AnimationChannel *mChannel; ///> the source channel
std::string mTargetId; std::string mTargetId;
std::string mTransformId; // the ID of the transformation step of the node which is influenced std::string mTransformId; // the ID of the transformation step of the node which is influenced
@ -710,15 +672,14 @@ struct ChannelEntry
const Collada::Accessor *mValueAccessor; ///> Collada accessor to the key value values const Collada::Accessor *mValueAccessor; ///> Collada accessor to the key value values
const Collada::Data *mValueData; ///> Source datat array for the key value values const Collada::Data *mValueData; ///> Source datat array for the key value values
ChannelEntry() ChannelEntry() :
: mChannel() mChannel(),
, mTransformIndex() mTransformIndex(),
, mSubElement() mSubElement(),
, mTimeAccessor() mTimeAccessor(),
, mTimeData() mTimeData(),
, mValueAccessor() mValueAccessor(),
, mValueData() mValueData() {}
{}
}; };
} // end of namespace Collada } // end of namespace Collada

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -47,13 +47,12 @@
#ifndef AI_COLLADAPARSER_H_INC #ifndef AI_COLLADAPARSER_H_INC
#define AI_COLLADAPARSER_H_INC #define AI_COLLADAPARSER_H_INC
#include <assimp/irrXMLWrapper.h>
#include "ColladaHelper.h" #include "ColladaHelper.h"
#include <assimp/ai_assert.h>
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>
#include <assimp/ai_assert.h>
#include <assimp/irrXMLWrapper.h>
namespace Assimp namespace Assimp {
{
class ZipArchiveIOSystem; class ZipArchiveIOSystem;
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
@ -62,8 +61,7 @@ namespace Assimp
* Does all the XML reading and builds internal data structures from it, * Does all the XML reading and builds internal data structures from it,
* but leaves the resolving of all the references to the loader. * but leaves the resolving of all the references to the loader.
*/ */
class ColladaParser class ColladaParser {
{
friend class ColladaLoader; friend class ColladaLoader;
/** Converts a path read from a collada file to the usual representation */ /** Converts a path read from a collada file to the usual representation */
@ -176,10 +174,10 @@ namespace Assimp
void ReadGeometryLibrary(); void ReadGeometryLibrary();
/** Reads a geometry from the geometry library. */ /** Reads a geometry from the geometry library. */
void ReadGeometry( Collada::Mesh* pMesh); void ReadGeometry(Collada::Mesh &pMesh);
/** Reads a mesh from the geometry library */ /** Reads a mesh from the geometry library */
void ReadMesh( Collada::Mesh* pMesh); void ReadMesh(Collada::Mesh &pMesh);
/** Reads a source element - a combination of raw data and an accessor defining /** Reads a source element - a combination of raw data and an accessor defining
* things that should not be redefinable. Yes, that's another rant. * things that should not be redefinable. Yes, that's another rant.
@ -197,29 +195,29 @@ namespace Assimp
void ReadAccessor(const std::string &pID); void ReadAccessor(const std::string &pID);
/** Reads input declarations of per-vertex mesh data into the given mesh */ /** Reads input declarations of per-vertex mesh data into the given mesh */
void ReadVertexData( Collada::Mesh* pMesh); void ReadVertexData(Collada::Mesh &pMesh);
/** Reads input declarations of per-index mesh data into the given mesh */ /** Reads input declarations of per-index mesh data into the given mesh */
void ReadIndexData( Collada::Mesh* pMesh); void ReadIndexData(Collada::Mesh &pMesh);
/** Reads a single input channel element and stores it in the given array, if valid */ /** Reads a single input channel element and stores it in the given array, if valid */
void ReadInputChannel(std::vector<Collada::InputChannel> &poChannels); void ReadInputChannel(std::vector<Collada::InputChannel> &poChannels);
/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */ /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, size_t ReadPrimitives(Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
size_t pNumPrimitives, const std::vector<size_t> &pVCount, Collada::PrimitiveType pPrimType); size_t pNumPrimitives, const std::vector<size_t> &pVCount, Collada::PrimitiveType pPrimType);
/** Copies the data for a single primitive into the mesh, based on the InputChannels */ /** Copies the data for a single primitive into the mesh, based on the InputChannels */
void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
size_t currentPrimitive, const std::vector<size_t> &indices); size_t currentPrimitive, const std::vector<size_t> &indices);
/** Reads one triangle of a tristrip into the mesh */ /** Reads one triangle of a tristrip into the mesh */
void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh, void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh &pMesh,
std::vector<Collada::InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices); std::vector<Collada::InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices);
/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh &pMesh);
/** Reads the library of node hierarchies and scene parts */ /** Reads the library of node hierarchies and scene parts */
void ReadSceneLibrary(); void ReadSceneLibrary();
@ -274,7 +272,7 @@ namespace Assimp
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();
@ -291,7 +289,8 @@ namespace Assimp
Collada::InputType GetTypeForSemantic(const std::string &pSemantic); Collada::InputType GetTypeForSemantic(const std::string &pSemantic);
/** Finds the item in the given library by its reference, throws if not found */ /** Finds the item in the given library by its reference, throws if not found */
template <typename Type> const Type& ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const; template <typename Type>
const Type &ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const;
protected: protected:
/** Filename, for a verbose error message */ /** Filename, for a verbose error message */
@ -360,7 +359,9 @@ namespace Assimp
ai_real mUnitSize; ai_real mUnitSize;
/** Which is the up vector */ /** Which is the up vector */
enum { UP_X, UP_Y, UP_Z } mUpDirection; enum { UP_X,
UP_Y,
UP_Z } mUpDirection;
/** Asset metadata (global for scene) */ /** Asset metadata (global for scene) */
StringMetaData mAssetMetaData; StringMetaData mAssetMetaData;
@ -371,8 +372,7 @@ namespace Assimp
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Check for element match // Check for element match
inline bool ColladaParser::IsElement( const char* pName) const inline bool ColladaParser::IsElement(const char *pName) const {
{
ai_assert(mReader->getNodeType() == irr::io::EXN_ELEMENT); ai_assert(mReader->getNodeType() == irr::io::EXN_ELEMENT);
return ::strcmp(mReader->getNodeName(), pName) == 0; return ::strcmp(mReader->getNodeName(), pName) == 0;
} }
@ -380,8 +380,7 @@ namespace Assimp
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Finds the item in the given library by its reference, throws if not found // Finds the item in the given library by its reference, throws if not found
template <typename Type> template <typename Type>
const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const const Type &ColladaParser::ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const {
{
typename std::map<std::string, Type>::const_iterator it = pLibrary.find(pURL); typename std::map<std::string, Type>::const_iterator it = pLibrary.find(pURL);
if (it == pLibrary.end()) if (it == pLibrary.end())
ThrowException(Formatter::format() << "Unable to resolve library reference \"" << pURL << "\"."); ThrowException(Formatter::format() << "Unable to resolve library reference \"" << pURL << "\".");

View File

@ -135,7 +135,7 @@ public:
for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++); for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
splitter++; splitter++;
ASSIMP_LOG_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); ASSIMP_LOG_VERBOSE_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
} }
} catch(std::logic_error&) { } catch(std::logic_error&) {
ai_assert(!splitter); ai_assert(!splitter);

View File

@ -241,7 +241,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) {
} }
} }
ASSIMP_LOG_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
} }
if (! output.blocks.size() ) { if (! output.blocks.size() ) {
@ -473,7 +473,7 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) {
++reader; ++reader;
} }
ASSIMP_LOG_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" ); ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -549,7 +549,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
++reader; ++reader;
} }
ASSIMP_LOG_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), ASSIMP_LOG_VERBOSE_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(),
" inserted blocks in ENTITIES" ); " inserted blocks in ENTITIES" );
} }

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,9 +58,8 @@ 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");
@ -89,19 +88,15 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::s
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
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()
, doc(doc)
{
const Scope &sc = GetRequiredScope(element); const Scope &sc = GetRequiredScope(element);
// find target node // find target node
@ -136,8 +131,6 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
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;
@ -155,14 +148,12 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
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");
@ -175,13 +166,13 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const
} }
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,10 +185,8 @@ 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
@ -205,15 +194,13 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
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
@ -259,9 +246,8 @@ 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
@ -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

@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h> #include <stdint.h>
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include <assimp/ByteSwapper.h> #include <assimp/ByteSwapper.h>
#include <assimp/DefaultLogger.hpp>
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
@ -427,6 +428,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length) void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
{ {
ai_assert(input); ai_assert(input);
ASSIMP_LOG_DEBUG("Tokenizing binary FBX file");
if(length < 0x1b) { if(length < 0x1b) {
TokenizeError("file is too short",0); TokenizeError("file is too short",0);
@ -451,6 +453,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
/*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length);
/*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length);
const uint32_t version = ReadWord(input, cursor, input + length); const uint32_t version = ReadWord(input, cursor, input + length);
ASSIMP_LOG_DEBUG_F("FBX version: ", version);
const bool is64bits = version >= 7500; const bool is64bits = version >= 7500;
const char *end = input + length; const char *end = input + length;
while (cursor < end ) { while (cursor < end ) {

View File

@ -105,7 +105,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
// The idea here is to traverse all objects to find these Textures and convert them, // The idea here is to traverse all objects to find these Textures and convert them,
// so later during material conversion it will find converted texture in the textures_converted array. // so later during material conversion it will find converted texture in the textures_converted array.
if (doc.Settings().readTextures) { if (doc.Settings().readTextures) {
ConvertOrphantEmbeddedTextures(); ConvertOrphanedEmbeddedTextures();
} }
ConvertRootNode(); ConvertRootNode();
@ -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.
@ -1163,7 +1158,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices(); const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals(); const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices(); const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); //losing channel name if using shapeGeometry->Name()
animMesh->mName.Set(FixAnimMeshName(blendShapeChannel->Name()));
for (size_t j = 0; j < curIndices.size(); j++) { for (size_t j = 0; j < curIndices.size(); j++) {
const unsigned int curIndex = curIndices.at(j); const unsigned int curIndex = curIndices.at(j);
aiVector3D vertex = curVertices.at(j); aiVector3D vertex = curVertices.at(j);
@ -1289,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()];
@ -1542,10 +1539,10 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
aiBone *bone = nullptr; aiBone *bone = nullptr;
if (bone_map.count(deformer_name)) { if (bone_map.count(deformer_name)) {
ASSIMP_LOG_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); ASSIMP_LOG_VERBOSE_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name);
bone = bone_map[deformer_name]; bone = bone_map[deformer_name];
} else { } else {
ASSIMP_LOG_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); ASSIMP_LOG_VERBOSE_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name);
bone = new aiBone(); bone = new aiBone();
bone->mName = bone_name; bone->mName = bone_name;
@ -1999,19 +1996,19 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_
TrySetTextureProperties(out_mat, _textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
// Maya PBR // Maya PBR
TrySetTextureProperties(out_mat, _textures, "Maya|baseColor|file", aiTextureType_BASE_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|baseColor", aiTextureType_BASE_COLOR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|normalCamera|file", aiTextureType_NORMAL_CAMERA, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|normalCamera", aiTextureType_NORMAL_CAMERA, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor|file", aiTextureType_EMISSION_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|metalness|file", aiTextureType_METALNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
// Maya stingray // Maya stingray
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map|file", aiTextureType_BASE_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_normal_map|file", aiTextureType_NORMAL_CAMERA, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_normal_map", aiTextureType_NORMAL_CAMERA, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_emissive_map", aiTextureType_EMISSION_COLOR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_metallic_map", aiTextureType_METALNESS, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_ao_map", aiTextureType_AMBIENT_OCCLUSION, mesh);
// 3DSMax PBR // 3DSMax PBR
TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|base_color_map", aiTextureType_BASE_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|base_color_map", aiTextureType_BASE_COLOR, mesh);
@ -2719,7 +2716,7 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
if (doc.Settings().optimizeEmptyAnimationCurves && if (doc.Settings().optimizeEmptyAnimationCurves &&
IsRedundantAnimationData(target, comp, (chain[i]->second))) { IsRedundantAnimationData(target, comp, (chain[i]->second))) {
FBXImporter::LogDebug("dropping redundant animation channel for node " + target.Name()); FBXImporter::LogVerboseDebug("dropping redundant animation channel for node " + target.Name());
continue; continue;
} }
@ -3164,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());
@ -3315,6 +3313,7 @@ void FBXConverter::InterpolateKeys(aiQuatKey *valOut, const KeyTimeList &keys, c
// http://www.3dkingdoms.com/weekly/weekly.php?a=36 // http://www.3dkingdoms.com/weekly/weekly.php?a=36
if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) { if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) {
quat.Conjugate(); quat.Conjugate();
quat.w = -quat.w;
} }
lastq = quat; lastq = quat;
@ -3466,7 +3465,7 @@ void FBXConverter::TransferDataToScene() {
} }
} }
void FBXConverter::ConvertOrphantEmbeddedTextures() { void FBXConverter::ConvertOrphanedEmbeddedTextures() {
// in C++14 it could be: // in C++14 it could be:
// for (auto&& [id, object] : objects) // for (auto&& [id, object] : objects)
for (auto &&id_and_object : doc.Objects()) { for (auto &&id_and_object : doc.Objects()) {

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,
@ -412,7 +412,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// FBX file could have embedded textures not connected to anything // FBX file could have embedded textures not connected to anything
void ConvertOrphantEmbeddedTextures(); void ConvertOrphanedEmbeddedTextures();
private: private:
// 0: not assigned yet, others: index is value - 1 // 0: not assigned yet, others: index is value - 1

View File

@ -55,6 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXDocumentUtil.h" #include "FBXDocumentUtil.h"
#include "FBXProperties.h" #include "FBXProperties.h"
#include <assimp/DefaultLogger.hpp>
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <map> #include <map>
@ -219,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()) {
@ -264,6 +266,8 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
: settings(settings) : settings(settings)
, parser(parser) , parser(parser)
{ {
ASSIMP_LOG_DEBUG("Creating FBX Document");
// Cannot use array default initialization syntax because vc8 fails on it // Cannot use array default initialization syntax because vc8 fails on it
for (auto &timeStamp : creationTimeStamp) { for (auto &timeStamp : creationTimeStamp) {
timeStamp = 0; timeStamp = 0;
@ -308,6 +312,7 @@ void Document::ReadHeader() {
const Scope& shead = *ehead->Compound(); const Scope& shead = *ehead->Compound();
fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0)); fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
ASSIMP_LOG_DEBUG_F("FBX Version: ", fbxVersion);
// While we may have some success with newer files, we don't support // While we may have some success with newer files, we don't support
// the older 6.n fbx format // the older 6.n fbx format
@ -462,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

@ -146,6 +146,8 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
ThrowException("Could not open file for reading"); ThrowException("Could not open file for reading");
} }
ASSIMP_LOG_DEBUG("Reading FBX file");
// read entire file into memory - no streaming for this, fbx // read entire file into memory - no streaming for this, fbx
// files can grow large, but the assimp output data structure // files can grow large, but the assimp output data structure
// then becomes very large, too. Assimp doesn't support // then becomes very large, too. Assimp doesn't support

View File

@ -383,7 +383,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
} catch (const runtime_error& runtimeError) } catch (const runtime_error& runtimeError)
{ {
//we don't need the content data for contents that has already been loaded //we don't need the content data for contents that has already been loaded
ASSIMP_LOG_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ", ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
runtimeError.what()); runtimeError.what());
} }
} }

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

@ -59,6 +59,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/ByteSwapper.h> #include <assimp/ByteSwapper.h>
#include <assimp/DefaultLogger.hpp>
#include <iostream> #include <iostream>
@ -76,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) {
@ -180,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");
} }
@ -195,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;
} }
@ -220,6 +221,7 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
, cursor(tokens.begin()) , cursor(tokens.begin())
, is_binary(is_binary) , is_binary(is_binary)
{ {
ASSIMP_LOG_DEBUG("Parsing FBX tokens");
root.reset(new Scope(*this,true)); root.reset(new Scope(*this,true));
} }
@ -234,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++;
} }
@ -256,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";
@ -294,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";
@ -340,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";
@ -383,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";
@ -419,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";
@ -456,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";
@ -1209,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

@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXTokenizer.h" #include "FBXTokenizer.h"
#include "FBXUtil.h" #include "FBXUtil.h"
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include <assimp/DefaultLogger.hpp>
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
@ -126,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;
} }
} }
@ -135,6 +136,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*
void Tokenize(TokenList& output_tokens, const char* input) void Tokenize(TokenList& output_tokens, const char* input)
{ {
ai_assert(input); ai_assert(input);
ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file");
// line and column numbers numbers are one-based // line and column numbers numbers are one-based
unsigned int line = 1; unsigned int line = 1;
@ -144,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,22 +71,19 @@ 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;
@ -107,23 +101,22 @@ bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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
@ -141,27 +134,22 @@ void HMPImporter::InternReadFile( const std::string& pFile,
// 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];
@ -180,16 +168,13 @@ void HMPImporter::InternReadFile( const std::string& pFile,
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)");
} }
@ -202,18 +187,15 @@ void HMPImporter::ValidateHeader_HMP457( )
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);
@ -243,15 +225,15 @@ void HMPImporter::InternReadFile_HMP5( )
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;
} }
} }
@ -272,8 +254,7 @@ 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);
@ -304,10 +285,8 @@ void HMPImporter::InternReadFile_HMP7( )
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;
@ -321,7 +300,9 @@ void HMPImporter::InternReadFile_HMP7( )
pcNorOut->z = 1.0f; pcNorOut->z = 1.0f;
pcNorOut->Normalize(); pcNorOut->Normalize();
++pcVertOut;++pcNorOut;++src; ++pcVertOut;
++pcNorOut;
++src;
} }
} }
@ -342,23 +323,19 @@ 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();
@ -385,8 +362,7 @@ void HMPImporter::CreateMaterial(const unsigned char* 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
@ -401,7 +377,7 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
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
@ -416,14 +392,12 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
*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 * width + x];
*pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x]; *pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x];
*pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x + 1]; *pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x + 1];
*pcNorOut++ = pcMesh->mNormals[y * width + x + 1]; *pcNorOut++ = pcMesh->mNormals[y * width + x + 1];
if (pcMesh->mTextureCoords[0]) if (pcMesh->mTextureCoords[0]) {
{
*pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x]; *pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x]; *pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x + 1]; *pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x + 1];
@ -440,8 +414,7 @@ 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;
} }
@ -449,8 +422,7 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
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);
@ -458,18 +430,18 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szC
// 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();
@ -479,11 +451,13 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szC
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);
@ -500,10 +474,10 @@ 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];

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) {
@ -221,7 +221,7 @@ void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs,
result.mVerts.pop_back(); result.mVerts.pop_back();
} }
} }
IFCImporter::LogDebug("generating CSG geometry by plane clipping (IfcBooleanClippingResult)"); IFCImporter::LogVerboseDebug("generating CSG geometry by plane clipping (IfcBooleanClippingResult)");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -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) {
@ -658,14 +658,14 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
} }
} }
} }
IFCImporter::LogDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)"); IFCImporter::LogVerboseDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
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
@ -706,7 +706,7 @@ void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedArea
vit += pcount; vit += pcount;
} }
IFCImporter::LogDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)"); IFCImporter::LogVerboseDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -223,7 +223,7 @@ public:
} }
if ( (std::string)curveSegment.Transition != "CONTINUOUS" ) { if ( (std::string)curveSegment.Transition != "CONTINUOUS" ) {
IFCImporter::LogDebug("ignoring transition code on composite curve segment, only continuous transitions are supported"); IFCImporter::LogVerboseDebug("ignoring transition code on composite curve segment, only continuous transitions are supported");
} }
curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) ); curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) );
@ -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);
@ -319,7 +319,7 @@ void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, Tem
ConvertAxisPlacement(trafo, solid.Position); ConvertAxisPlacement(trafo, solid.Position);
result.Transform(trafo); result.Transform(trafo);
IFCImporter::LogDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)"); IFCImporter::LogVerboseDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -457,7 +457,7 @@ void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh&
} }
} }
IFCImporter::LogDebug("generate mesh procedurally by sweeping a disk along a curve (IfcSweptDiskSolid)"); IFCImporter::LogVerboseDebug("generate mesh procedurally by sweeping a disk along a curve (IfcSweptDiskSolid)");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -660,7 +660,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp"); IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
} }
IFCImporter::LogDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)"); IFCImporter::LogVerboseDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)");
// If this is an opening element, store both the extruded mesh and the 2D profile mesh // If this is an opening element, store both the extruded mesh and the 2D profile mesh
// it was created from. Return an empty mesh to the caller. // it was created from. Return an empty mesh to the caller.

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
@ -641,14 +641,14 @@ aiNode *ProcessSpatialStructure(aiNode *parent, const Schema_2x3::IfcProduct &el
bool skipGeometry = false; bool skipGeometry = false;
if (conv.settings.skipSpaceRepresentations) { if (conv.settings.skipSpaceRepresentations) {
if (el.ToPtr<Schema_2x3::IfcSpace>()) { if (el.ToPtr<Schema_2x3::IfcSpace>()) {
IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings"); IFCImporter::LogVerboseDebug("skipping IfcSpace entity due to importer settings");
skipGeometry = true; skipGeometry = true;
} }
} }
if (conv.settings.skipAnnotations) { if (conv.settings.skipAnnotations) {
if (el.ToPtr<Schema_2x3::IfcAnnotation>()) { if (el.ToPtr<Schema_2x3::IfcAnnotation>()) {
IFCImporter::LogDebug("skipping IfcAnnotation entity due to importer settings"); IFCImporter::LogVerboseDebug("skipping IfcAnnotation entity due to importer settings");
return nullptr; return nullptr;
} }
} }
@ -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;
} }
@ -856,7 +856,7 @@ void ProcessSpatialStructures(ConversionData &conv) {
if (!prod) { if (!prod) {
continue; continue;
} }
IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : "")); IFCImporter::LogVerboseDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : ""));
// the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT
const STEP::DB::RefMap &refs = conv.db.GetRefs(); const STEP::DB::RefMap &refs = conv.db.GetRefs();
@ -868,9 +868,9 @@ void ProcessSpatialStructures(ConversionData &conv) {
// comparing pointer values is not sufficient, we would need to cast them to the same type first // comparing pointer values is not sufficient, we would need to cast them to the same type first
// as there is multiple inheritance in the game. // as there is multiple inheritance in the game.
if (def.GetID() == prod->GetID()) { if (def.GetID() == prod->GetID()) {
IFCImporter::LogDebug("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

@ -1359,7 +1359,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
break; break;
} }
else { else {
IFCImporter::LogDebug("merging overlapping openings"); IFCImporter::LogVerboseDebug("merging overlapping openings");
ExtractVerticesFromClipper(poly[0].outer, temp_contour, false); ExtractVerticesFromClipper(poly[0].outer, temp_contour, false);
// Generate the union of the bounding boxes // Generate the union of the bounding boxes

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());
@ -162,7 +162,7 @@ void TempMesh::RemoveDegenerates()
} }
if(drop) { if(drop) {
IFCImporter::LogDebug("removing degenerate faces"); IFCImporter::LogVerboseDebug("removing degenerate faces");
} }
} }
@ -437,7 +437,7 @@ void TempMesh::RemoveAdjacentDuplicates() {
base += cnt; base += cnt;
} }
if(drop) { if(drop) {
IFCImporter::LogDebug("removing duplicate vertices"); IFCImporter::LogVerboseDebug("removing duplicate vertices");
} }
} }

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); }

View File

@ -45,26 +45,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Irr importer class * @brief Implementation of the Irr importer class
*/ */
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER #ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
#include "AssetLib/Irr/IRRLoader.h" #include "AssetLib/Irr/IRRLoader.h"
#include "Common/Importer.h" #include "Common/Importer.h"
#include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h>
#include <assimp/GenericProperty.h> #include <assimp/GenericProperty.h>
#include <assimp/MathFunctions.h>
#include <assimp/ParsingUtils.h>
#include <assimp/SceneCombiner.h> #include <assimp/SceneCombiner.h>
#include <assimp/StandardShapes.h> #include <assimp/StandardShapes.h>
#include <assimp/MathFunctions.h> #include <assimp/fast_atof.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/mesh.h>
#include <assimp/material.h>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
#include <assimp/postprocess.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/material.h>
#include <assimp/mesh.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <memory> #include <memory>
@ -87,9 +85,8 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
IRRImporter::IRRImporter() IRRImporter::IRRImporter() :
: fps() fps(), configSpeedFlag() {
, configSpeedFlag(){
// empty // empty
} }
@ -121,14 +118,12 @@ bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiImporterDesc* IRRImporter::GetInfo () const const aiImporterDesc *IRRImporter::GetInfo() const {
{
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void IRRImporter::SetupProperties(const Importer* pImp) void IRRImporter::SetupProperties(const Importer *pImp) {
{
// read the output frame rate of all node animation channels // read the output frame rate of all node animation channels
fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS, 100); fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS, 100);
if (fps < 10.) { if (fps < 10.) {
@ -145,8 +140,7 @@ void IRRImporter::SetupProperties(const Importer* pImp)
aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1, aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1,
const SkyboxVertex &v2, const SkyboxVertex &v2,
const SkyboxVertex &v3, const SkyboxVertex &v3,
const SkyboxVertex& v4) const SkyboxVertex &v4) {
{
// allocate and prepare the mesh // allocate and prepare the mesh
aiMesh *out = new aiMesh(); aiMesh *out = new aiMesh();
@ -188,8 +182,7 @@ aiMesh* IRRImporter::BuildSingleQuadMesh(const SkyboxVertex& v1,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void IRRImporter::BuildSkybox(std::vector<aiMesh*>& meshes, std::vector<aiMaterial*> materials) void IRRImporter::BuildSkybox(std::vector<aiMesh *> &meshes, std::vector<aiMaterial *> materials) {
{
// Update the material of the skybox - replace the name and disable shading for skyboxes. // Update the material of the skybox - replace the name and disable shading for skyboxes.
for (unsigned int i = 0; i < 6; ++i) { for (unsigned int i = 0; i < 6; ++i) {
aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i))); aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i)));
@ -261,12 +254,10 @@ void IRRImporter::BuildSkybox(std::vector<aiMesh*>& meshes, std::vector<aiMateri
void IRRImporter::CopyMaterial(std::vector<aiMaterial *> &materials, void IRRImporter::CopyMaterial(std::vector<aiMaterial *> &materials,
std::vector<std::pair<aiMaterial *, unsigned int>> &inmaterials, std::vector<std::pair<aiMaterial *, unsigned int>> &inmaterials,
unsigned int &defMatIdx, unsigned int &defMatIdx,
aiMesh* mesh) aiMesh *mesh) {
{
if (inmaterials.empty()) { if (inmaterials.empty()) {
// Do we have a default material? If not we need to create one // Do we have a default material? If not we need to create one
if (UINT_MAX == defMatIdx) if (UINT_MAX == defMatIdx) {
{
defMatIdx = (unsigned int)materials.size(); defMatIdx = (unsigned int)materials.size();
//TODO: add this materials to someone? //TODO: add this materials to someone?
/*aiMaterial* mat = new aiMaterial(); /*aiMaterial* mat = new aiMaterial();
@ -280,8 +271,7 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
} }
mesh->mMaterialIndex = defMatIdx; mesh->mMaterialIndex = defMatIdx;
return; return;
} } else if (inmaterials.size() > 1) {
else if (inmaterials.size() > 1) {
ASSIMP_LOG_INFO("IRR: Skipping additional materials"); ASSIMP_LOG_INFO("IRR: Skipping additional materials");
} }
@ -289,26 +279,27 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
materials.push_back(inmaterials[0].first); materials.push_back(inmaterials[0].first);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline inline int ClampSpline(int idx, int size) {
int ClampSpline(int idx, int size) {
return (idx < 0 ? size + idx : (idx >= size ? idx - size : idx)); return (idx < 0 ? size + idx : (idx >= size ? idx - size : idx));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline void FindSuitableMultiple(int& angle) inline void FindSuitableMultiple(int &angle) {
{ if (angle < 3)
if (angle < 3) angle = 3; angle = 3;
else if (angle < 10) angle = 10; else if (angle < 10)
else if (angle < 20) angle = 20; angle = 10;
else if (angle < 30) angle = 30; else if (angle < 20)
angle = 20;
else if (angle < 30)
angle = 30;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNodeAnim*>& anims) void IRRImporter::ComputeAnimations(Node *root, aiNode *real, std::vector<aiNodeAnim *> &anims) {
{ ai_assert(nullptr != root);
ai_assert(nullptr != root && nullptr != real); ai_assert(nullptr != real);
// XXX totally WIP - doesn't produce proper results, need to evaluate // XXX totally WIP - doesn't produce proper results, need to evaluate
// whether there's any use for Irrlicht's proprietary scene format // whether there's any use for Irrlicht's proprietary scene format
@ -337,8 +328,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
unsigned int cur = 0; unsigned int cur = 0;
for (std::list<Animator>::iterator it = root->animators.begin(); for (std::list<Animator>::iterator it = root->animators.begin();
it != root->animators.end(); ++it) it != root->animators.end(); ++it) {
{
if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) continue; if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) continue;
Animator &in = *it; Animator &in = *it;
@ -368,13 +358,12 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
// the transformation matrix of the dummy node is the identity // the transformation matrix of the dummy node is the identity
real->mParent = dummy; real->mParent = dummy;
} } else
else anim->mNodeName.Set(root->name); anim->mNodeName.Set(root->name);
++cur; ++cur;
switch (in.type) { switch (in.type) {
case Animator::ROTATION: case Animator::ROTATION: {
{
// ----------------------------------------------------- // -----------------------------------------------------
// find out how long a full rotation will take // find out how long a full rotation will take
// This is the least common multiple of 360.f and all // This is the least common multiple of 360.f and all
@ -392,8 +381,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
angles[1] %= 360; angles[1] %= 360;
angles[2] %= 360; angles[2] %= 360;
if ( (angles[0]*angles[1]) != 0 && (angles[1]*angles[2]) != 0 ) if ((angles[0] * angles[1]) != 0 && (angles[1] * angles[2]) != 0) {
{
FindSuitableMultiple(angles[0]); FindSuitableMultiple(angles[0]);
FindSuitableMultiple(angles[1]); FindSuitableMultiple(angles[1]);
FindSuitableMultiple(angles[2]); FindSuitableMultiple(angles[2]);
@ -436,8 +424,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
// begin with a zero angle // begin with a zero angle
aiVector3D angle; aiVector3D angle;
for (unsigned int i = 0; i < anim->mNumRotationKeys;++i) for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
{
// build the quaternion for the given euler angles // build the quaternion for the given euler angles
aiQuatKey &q = anim->mRotationKeys[i]; aiQuatKey &q = anim->mRotationKeys[i];
@ -450,11 +437,9 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
// This animation is repeated and repeated ... // This animation is repeated and repeated ...
anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
} } break;
break;
case Animator::FLY_CIRCLE: case Animator::FLY_CIRCLE: {
{
// ----------------------------------------------------- // -----------------------------------------------------
// Find out how much time we'll need to perform a // Find out how much time we'll need to perform a
// full circle. // full circle.
@ -469,8 +454,8 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
aiVector3D vecU, vecV; aiVector3D vecU, vecV;
if (in.direction.y) { if (in.direction.y) {
vecV = aiVector3D(50, 0, 0) ^ in.direction; vecV = aiVector3D(50, 0, 0) ^ in.direction;
} } else
else vecV = aiVector3D(0,50,00) ^ in.direction; vecV = aiVector3D(0, 50, 00) ^ in.direction;
vecV.Normalize(); vecV.Normalize();
vecU = (vecV ^ in.direction).Normalize(); vecU = (vecV ^ in.direction).Normalize();
@ -485,11 +470,9 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
// This animation is repeated and repeated ... // This animation is repeated and repeated ...
anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
} } break;
break;
case Animator::FLY_STRAIGHT: case Animator::FLY_STRAIGHT: {
{
anim->mPostState = anim->mPreState = (in.loop ? aiAnimBehaviour_REPEAT : aiAnimBehaviour_CONSTANT); anim->mPostState = anim->mPreState = (in.loop ? aiAnimBehaviour_REPEAT : aiAnimBehaviour_CONSTANT);
const double seconds = in.timeForWay / 1000.; const double seconds = in.timeForWay / 1000.;
const double tdelta = 1000. / fps; const double tdelta = 1000. / fps;
@ -509,11 +492,9 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
key.mTime = i * tdelta; key.mTime = i * tdelta;
key.mValue = in.circleCenter + diff * ai_real(timeFactor * key.mTime); key.mValue = in.circleCenter + diff * ai_real(timeFactor * key.mTime);
} }
} } break;
break;
case Animator::FOLLOW_SPLINE: case Animator::FOLLOW_SPLINE: {
{
// repeat outside the defined time range // repeat outside the defined time range
anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
const int size = (int)in.splineKeys.size(); const int size = (int)in.splineKeys.size();
@ -524,8 +505,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
delete anim; delete anim;
anim = nullptr; anim = nullptr;
break; break;
} } else if (size == 1) {
else if (size == 1) {
// We have just one point in the spline so we don't need the full calculation // We have just one point in the spline so we don't need the full calculation
anim->mNumPositionKeys = 1; anim->mNumPositionKeys = 1;
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
@ -539,8 +519,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
anim->mNumPositionKeys = (unsigned int)(ticksPerFull * fps); anim->mNumPositionKeys = (unsigned int)(ticksPerFull * fps);
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) {
{
aiVectorKey &key = anim->mPositionKeys[i]; aiVectorKey &key = anim->mPositionKeys[i];
const ai_real dt = (i * in.speed * ai_real(0.001)); const ai_real dt = (i * in.speed * ai_real(0.001));
@ -573,8 +552,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
key.mValue = t2; key.mValue = t2;
key.mTime = (double)i; key.mTime = (double)i;
} }
} } break;
break;
default: default:
// UNKNOWN , OTHER // UNKNOWN , OTHER
break; break;
@ -588,8 +566,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// This function is maybe more generic than we'd need it here // This function is maybe more generic than we'd need it here
void SetupMapping (aiMaterial* mat, aiTextureMapping mode, const aiVector3D& axis = aiVector3D(0.f,0.f,-1.f)) void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis = aiVector3D(0.f, 0.f, -1.f)) {
{
// Check whether there are texture properties defined - setup // Check whether there are texture properties defined - setup
// the desired texture mapping mode for all of them and ignore // the desired texture mapping mode for all of them and ignore
// all UV settings we might encounter. WE HAVE NO UVS! // all UV settings we might encounter. WE HAVE NO UVS!
@ -597,8 +574,7 @@ void SetupMapping (aiMaterial* mat, aiTextureMapping mode, const aiVector3D& axi
std::vector<aiMaterialProperty *> p; std::vector<aiMaterialProperty *> p;
p.reserve(mat->mNumProperties + 1); p.reserve(mat->mNumProperties + 1);
for (unsigned int i = 0; i < mat->mNumProperties;++i) for (unsigned int i = 0; i < mat->mNumProperties; ++i) {
{
aiMaterialProperty *prop = mat->mProperties[i]; aiMaterialProperty *prop = mat->mProperties[i];
if (!::strcmp(prop->mKey.data, "$tex.file")) { if (!::strcmp(prop->mKey.data, "$tex.file")) {
// Setup the mapping key // Setup the mapping key
@ -628,11 +604,10 @@ void SetupMapping (aiMaterial* mat, aiTextureMapping mode, const aiVector3D& axi
*((aiVector3D *)m->mData) = axis; *((aiVector3D *)m->mData) = axis;
p.push_back(m); p.push_back(m);
} }
} } else if (!::strcmp(prop->mKey.data, "$tex.uvwsrc")) {
else if (! ::strcmp( prop->mKey.data, "$tex.uvwsrc")) {
delete mat->mProperties[i]; delete mat->mProperties[i];
} } else
else p.push_back(prop); p.push_back(prop);
} }
if (p.empty()) return; if (p.empty()) return;
@ -655,17 +630,14 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
std::vector<aiNodeAnim *> &anims, std::vector<aiNodeAnim *> &anims,
std::vector<AttachmentInfo> &attach, std::vector<AttachmentInfo> &attach,
std::vector<aiMaterial *> &materials, std::vector<aiMaterial *> &materials,
unsigned int& defMatIdx) unsigned int &defMatIdx) {
{
unsigned int oldMeshSize = (unsigned int)meshes.size(); unsigned int oldMeshSize = (unsigned int)meshes.size();
//unsigned int meshTrafoAssign = 0; //unsigned int meshTrafoAssign = 0;
// Now determine the type of the node // Now determine the type of the node
switch (root->type) switch (root->type) {
{
case Node::ANIMMESH: case Node::ANIMMESH:
case Node::MESH: case Node::MESH: {
{
if (!root->meshPath.length()) if (!root->meshPath.length())
break; break;
@ -705,7 +677,6 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// Process material flags // Process material flags
aiMesh *mesh = localScene->mMeshes[i]; aiMesh *mesh = localScene->mMeshes[i];
// If "trans_vertex_alpha" mode is enabled, search all vertex colors // If "trans_vertex_alpha" mode is enabled, search all vertex colors
// and check whether they have a common alpha value. This is quite // and check whether they have a common alpha value. This is quite
// often the case so we can simply extract it to a shared oacity // often the case so we can simply extract it to a shared oacity
@ -713,8 +684,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
std::pair<aiMaterial *, unsigned int> &src = root->materials[mesh->mMaterialIndex]; std::pair<aiMaterial *, unsigned int> &src = root->materials[mesh->mMaterialIndex];
aiMaterial *mat = (aiMaterial *)src.first; aiMaterial *mat = (aiMaterial *)src.first;
if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha) if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha) {
{
bool bdo = true; bool bdo = true;
for (unsigned int a = 1; a < mesh->mNumVertices; ++a) { for (unsigned int a = 1; a < mesh->mNumVertices; ++a) {
@ -742,14 +712,12 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
int idx = 1; int idx = 1;
if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap)) { if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap)) {
mat->AddProperty(&idx, 1, AI_MATKEY_UVWSRC_DIFFUSE(0)); mat->AddProperty(&idx, 1, AI_MATKEY_UVWSRC_DIFFUSE(0));
} } else if (src.second & AI_IRRMESH_MAT_normalmap_solid) {
else if (src.second & AI_IRRMESH_MAT_normalmap_solid) {
mat->AddProperty(&idx, 1, AI_MATKEY_UVWSRC_NORMALS(0)); mat->AddProperty(&idx, 1, AI_MATKEY_UVWSRC_NORMALS(0));
} }
} }
} }
} } break;
break;
case Node::LIGHT: case Node::LIGHT:
case Node::CAMERA: case Node::CAMERA:
@ -757,18 +725,19 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// We're already finished with lights and cameras // We're already finished with lights and cameras
break; break;
case Node::SPHERE: {
case Node::SPHERE:
{
// Generate the sphere model. Our input parameter to // Generate the sphere model. Our input parameter to
// the sphere generation algorithm is the number of // the sphere generation algorithm is the number of
// subdivisions of each triangle - but here we have // subdivisions of each triangle - but here we have
// the number of poylgons on a specific axis. Just // the number of poylgons on a specific axis. Just
// use some hardcoded limits to approximate this ... // use some hardcoded limits to approximate this ...
unsigned int mul = root->spherePolyCountX * root->spherePolyCountY; unsigned int mul = root->spherePolyCountX * root->spherePolyCountY;
if (mul < 100)mul = 2; if (mul < 100)
else if (mul < 300)mul = 3; mul = 2;
else mul = 4; else if (mul < 300)
mul = 3;
else
mul = 4;
meshes.push_back(StandardShapes::MakeMesh(mul, meshes.push_back(StandardShapes::MakeMesh(mul,
&StandardShapes::MakeSphere)); &StandardShapes::MakeSphere));
@ -782,11 +751,9 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// Now adjust this output material - if there is a first texture // Now adjust this output material - if there is a first texture
// set, setup spherical UV mapping around the Y axis. // set, setup spherical UV mapping around the Y axis.
SetupMapping((aiMaterial *)materials.back(), aiTextureMapping_SPHERE); SetupMapping((aiMaterial *)materials.back(), aiTextureMapping_SPHERE);
} } break;
break;
case Node::CUBE: case Node::CUBE: {
{
// Generate an unit cube first // Generate an unit cube first
meshes.push_back(StandardShapes::MakeMesh( meshes.push_back(StandardShapes::MakeMesh(
&StandardShapes::MakeHexahedron)); &StandardShapes::MakeHexahedron));
@ -800,12 +767,9 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// Now adjust this output material - if there is a first texture // Now adjust this output material - if there is a first texture
// set, setup cubic UV mapping // set, setup cubic UV mapping
SetupMapping((aiMaterial *)materials.back(), aiTextureMapping_BOX); SetupMapping((aiMaterial *)materials.back(), aiTextureMapping_BOX);
} } break;
break;
case Node::SKYBOX: {
case Node::SKYBOX:
{
// A skybox is defined by six materials // A skybox is defined by six materials
if (root->materials.size() < 6) { if (root->materials.size() < 6) {
ASSIMP_LOG_ERROR("IRR: There should be six materials for a skybox"); ASSIMP_LOG_ERROR("IRR: There should be six materials for a skybox");
@ -827,15 +791,12 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
root->name = "IRR.SkyBox_" + root->name; root->name = "IRR.SkyBox_" + root->name;
ASSIMP_LOG_INFO("IRR: Loading skybox, this will " ASSIMP_LOG_INFO("IRR: Loading skybox, this will "
"require special handling to be displayed correctly"); "require special handling to be displayed correctly");
} } break;
break;
case Node::TERRAIN: case Node::TERRAIN: {
{
// to support terrains, we'd need to have a texture decoder // to support terrains, we'd need to have a texture decoder
ASSIMP_LOG_ERROR("IRR: Unsupported node - TERRAIN"); ASSIMP_LOG_ERROR("IRR: Unsupported node - TERRAIN");
} } break;
break;
default: default:
// DUMMY // DUMMY
break; break;
@ -901,8 +862,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void IRRImporter::InternReadFile(const std::string &pFile, void IRRImporter::InternReadFile(const std::string &pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene *pScene, IOSystem *pIOHandler) {
{
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
@ -972,51 +932,41 @@ void IRRImporter::InternReadFile( const std::string& pFile,
if (!ASSIMP_stricmp(sz, "mesh") || !ASSIMP_stricmp(sz, "octTree")) { if (!ASSIMP_stricmp(sz, "mesh") || !ASSIMP_stricmp(sz, "octTree")) {
// OctTree's and meshes are treated equally // OctTree's and meshes are treated equally
nd = new Node(Node::MESH); nd = new Node(Node::MESH);
} } else if (!ASSIMP_stricmp(sz, "cube")) {
else if (!ASSIMP_stricmp(sz,"cube")) {
nd = new Node(Node::CUBE); nd = new Node(Node::CUBE);
++guessedMeshCnt; ++guessedMeshCnt;
// meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron)); // meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
} } else if (!ASSIMP_stricmp(sz, "skybox")) {
else if (!ASSIMP_stricmp(sz,"skybox")) {
nd = new Node(Node::SKYBOX); nd = new Node(Node::SKYBOX);
guessedMeshCnt += 6; guessedMeshCnt += 6;
} } else if (!ASSIMP_stricmp(sz, "camera")) {
else if (!ASSIMP_stricmp(sz,"camera")) {
nd = new Node(Node::CAMERA); nd = new Node(Node::CAMERA);
// Setup a temporary name for the camera // Setup a temporary name for the camera
aiCamera *cam = new aiCamera(); aiCamera *cam = new aiCamera();
cam->mName.Set(nd->name); cam->mName.Set(nd->name);
cameras.push_back(cam); cameras.push_back(cam);
} } else if (!ASSIMP_stricmp(sz, "light")) {
else if (!ASSIMP_stricmp(sz,"light")) {
nd = new Node(Node::LIGHT); nd = new Node(Node::LIGHT);
// Setup a temporary name for the light // Setup a temporary name for the light
aiLight *cam = new aiLight(); aiLight *cam = new aiLight();
cam->mName.Set(nd->name); cam->mName.Set(nd->name);
lights.push_back(cam); lights.push_back(cam);
} } else if (!ASSIMP_stricmp(sz, "sphere")) {
else if (!ASSIMP_stricmp(sz,"sphere")) {
nd = new Node(Node::SPHERE); nd = new Node(Node::SPHERE);
++guessedMeshCnt; ++guessedMeshCnt;
} } else if (!ASSIMP_stricmp(sz, "animatedMesh")) {
else if (!ASSIMP_stricmp(sz,"animatedMesh")) {
nd = new Node(Node::ANIMMESH); nd = new Node(Node::ANIMMESH);
} } else if (!ASSIMP_stricmp(sz, "empty")) {
else if (!ASSIMP_stricmp(sz,"empty")) {
nd = new Node(Node::DUMMY); nd = new Node(Node::DUMMY);
} } else if (!ASSIMP_stricmp(sz, "terrain")) {
else if (!ASSIMP_stricmp(sz,"terrain")) {
nd = new Node(Node::TERRAIN); nd = new Node(Node::TERRAIN);
} } else if (!ASSIMP_stricmp(sz, "billBoard")) {
else if (!ASSIMP_stricmp(sz,"billBoard")) {
// We don't support billboards, so ignore them // We don't support billboards, so ignore them
ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp"); ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
nd = new Node(Node::DUMMY); nd = new Node(Node::DUMMY);
} } else {
else {
ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(sz)); ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(sz));
/* We skip the contents of nodes we don't know. /* We skip the contents of nodes we don't know.
@ -1031,14 +981,11 @@ void IRRImporter::InternReadFile( const std::string& pFile,
curNode = nd; curNode = nd;
nd->parent = curParent; nd->parent = curParent;
curParent->children.push_back(nd); curParent->children.push_back(nd);
} } else if (!ASSIMP_stricmp(reader->getNodeName(), "materials")) {
else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) {
inMaterials = true; inMaterials = true;
} } else if (!ASSIMP_stricmp(reader->getNodeName(), "animators")) {
else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) {
inAnimator = true; inAnimator = true;
} } else if (!ASSIMP_stricmp(reader->getNodeName(), "attributes")) {
else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes")) {
/* We should have a valid node here /* We should have a valid node here
* FIX: no ... the scene root node is also contained in an attributes block * FIX: no ... the scene root node is also contained in an attributes block
*/ */
@ -1063,8 +1010,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
++guessedMatCnt; ++guessedMatCnt;
continue; continue;
} } else if (inAnimator) {
else if (inAnimator) {
/* This is an animation path - add a new animator /* This is an animation path - add a new animator
* to the list. * to the list.
*/ */
@ -1087,8 +1033,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") { if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") {
// We store the rotation euler angles in 'direction' // We store the rotation euler angles in 'direction'
curAnim->direction = prop.value; curAnim->direction = prop.value;
} } else if (curAnim->type == Animator::FOLLOW_SPLINE) {
else if (curAnim->type == Animator::FOLLOW_SPLINE) {
// Check whether the vector follows the PointN naming scheme, // Check whether the vector follows the PointN naming scheme,
// here N is the ONE-based index of the point // here N is the ONE-based index of the point
if (prop.name.length() >= 6 && prop.name.substr(0, 5) == "Point") { if (prop.name.length() >= 6 && prop.name.substr(0, 5) == "Point") {
@ -1100,63 +1045,51 @@ void IRRImporter::InternReadFile( const std::string& pFile,
key.mValue = prop.value; key.mValue = prop.value;
key.mTime = strtoul10(&prop.name[5]); key.mTime = strtoul10(&prop.name[5]);
} }
} } else if (curAnim->type == Animator::FLY_CIRCLE) {
else if (curAnim->type == Animator::FLY_CIRCLE) {
if (prop.name == "Center") { if (prop.name == "Center") {
curAnim->circleCenter = prop.value; curAnim->circleCenter = prop.value;
} } else if (prop.name == "Direction") {
else if (prop.name == "Direction") {
curAnim->direction = prop.value; curAnim->direction = prop.value;
// From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1 // From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1
if (curAnim->direction == aiVector3D()) { if (curAnim->direction == aiVector3D()) {
curAnim->direction = aiVector3D(0.f, 1.f, 0.f); curAnim->direction = aiVector3D(0.f, 1.f, 0.f);
} else
curAnim->direction.Normalize();
} }
else curAnim->direction.Normalize(); } else if (curAnim->type == Animator::FLY_STRAIGHT) {
}
}
else if (curAnim->type == Animator::FLY_STRAIGHT) {
if (prop.name == "Start") { if (prop.name == "Start") {
// We reuse the field here // We reuse the field here
curAnim->circleCenter = prop.value; curAnim->circleCenter = prop.value;
} } else if (prop.name == "End") {
else if (prop.name == "End") {
// We reuse the field here // We reuse the field here
curAnim->direction = prop.value; curAnim->direction = prop.value;
} }
} }
} } else {
else {
if (prop.name == "Position") { if (prop.name == "Position") {
curNode->position = prop.value; curNode->position = prop.value;
} } else if (prop.name == "Rotation") {
else if (prop.name == "Rotation") {
curNode->rotation = prop.value; curNode->rotation = prop.value;
} } else if (prop.name == "Scale") {
else if (prop.name == "Scale") {
curNode->scaling = prop.value; curNode->scaling = prop.value;
} } else if (Node::CAMERA == curNode->type) {
else if (Node::CAMERA == curNode->type)
{
aiCamera *cam = cameras.back(); aiCamera *cam = cameras.back();
if (prop.name == "Target") { if (prop.name == "Target") {
cam->mLookAt = prop.value; cam->mLookAt = prop.value;
} } else if (prop.name == "UpVector") {
else if (prop.name == "UpVector") {
cam->mUp = prop.value; cam->mUp = prop.value;
} }
} }
} }
} } else if (!ASSIMP_stricmp(reader->getNodeName(), "bool")) {
else if (!ASSIMP_stricmp(reader->getNodeName(),"bool")) {
BoolProperty prop; BoolProperty prop;
ReadBoolProperty(prop); ReadBoolProperty(prop);
if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") { if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") {
curAnim->loop = prop.value; curAnim->loop = prop.value;
} }
} } else if (!ASSIMP_stricmp(reader->getNodeName(), "float")) {
else if (!ASSIMP_stricmp(reader->getNodeName(),"float")) {
FloatProperty prop; FloatProperty prop;
ReadFloatProperty(prop); ReadFloatProperty(prop);
@ -1164,59 +1097,47 @@ void IRRImporter::InternReadFile( const std::string& pFile,
// The speed property exists for several animators // The speed property exists for several animators
if (prop.name == "Speed") { if (prop.name == "Speed") {
curAnim->speed = prop.value; curAnim->speed = prop.value;
} } else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius") {
else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius") {
curAnim->circleRadius = prop.value; curAnim->circleRadius = prop.value;
} } else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness") {
else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness") {
curAnim->tightness = prop.value; curAnim->tightness = prop.value;
} }
} } else {
else {
if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) { if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) {
curNode->framesPerSecond = prop.value; curNode->framesPerSecond = prop.value;
} } else if (Node::CAMERA == curNode->type) {
else if (Node::CAMERA == curNode->type) {
/* This is the vertical, not the horizontal FOV. /* This is the vertical, not the horizontal FOV.
* We need to compute the right FOV from the * We need to compute the right FOV from the
* screen aspect which we don't know yet. * screen aspect which we don't know yet.
*/ */
if (prop.name == "Fovy") { if (prop.name == "Fovy") {
cameras.back()->mHorizontalFOV = prop.value; cameras.back()->mHorizontalFOV = prop.value;
} } else if (prop.name == "Aspect") {
else if (prop.name == "Aspect") {
cameras.back()->mAspect = prop.value; cameras.back()->mAspect = prop.value;
} } else if (prop.name == "ZNear") {
else if (prop.name == "ZNear") {
cameras.back()->mClipPlaneNear = prop.value; cameras.back()->mClipPlaneNear = prop.value;
} } else if (prop.name == "ZFar") {
else if (prop.name == "ZFar") {
cameras.back()->mClipPlaneFar = prop.value; cameras.back()->mClipPlaneFar = prop.value;
} }
} } else if (Node::LIGHT == curNode->type) {
else if (Node::LIGHT == curNode->type) {
/* Additional light information /* Additional light information
*/ */
if (prop.name == "Attenuation") { if (prop.name == "Attenuation") {
lights.back()->mAttenuationLinear = prop.value; lights.back()->mAttenuationLinear = prop.value;
} } else if (prop.name == "OuterCone") {
else if (prop.name == "OuterCone") {
lights.back()->mAngleOuterCone = AI_DEG_TO_RAD(prop.value); lights.back()->mAngleOuterCone = AI_DEG_TO_RAD(prop.value);
} } else if (prop.name == "InnerCone") {
else if (prop.name == "InnerCone") {
lights.back()->mAngleInnerCone = AI_DEG_TO_RAD(prop.value); lights.back()->mAngleInnerCone = AI_DEG_TO_RAD(prop.value);
} }
} }
// radius of the sphere to be generated - // radius of the sphere to be generated -
// or alternatively, size of the cube // or alternatively, size of the cube
else if ((Node::SPHERE == curNode->type && prop.name == "Radius") else if ((Node::SPHERE == curNode->type && prop.name == "Radius") || (Node::CUBE == curNode->type && prop.name == "Size")) {
|| (Node::CUBE == curNode->type && prop.name == "Size" )) {
curNode->sphereRadius = prop.value; curNode->sphereRadius = prop.value;
} }
} }
} } else if (!ASSIMP_stricmp(reader->getNodeName(), "int")) {
else if (!ASSIMP_stricmp(reader->getNodeName(),"int")) {
IntProperty prop; IntProperty prop;
ReadIntProperty(prop); ReadIntProperty(prop);
@ -1224,21 +1145,18 @@ void IRRImporter::InternReadFile( const std::string& pFile,
if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay") { if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay") {
curAnim->timeForWay = prop.value; curAnim->timeForWay = prop.value;
} }
} } else {
else {
// sphere polgon numbers in each direction // sphere polgon numbers in each direction
if (Node::SPHERE == curNode->type) { if (Node::SPHERE == curNode->type) {
if (prop.name == "PolyCountX") { if (prop.name == "PolyCountX") {
curNode->spherePolyCountX = prop.value; curNode->spherePolyCountX = prop.value;
} } else if (prop.name == "PolyCountY") {
else if (prop.name == "PolyCountY") {
curNode->spherePolyCountY = prop.value; curNode->spherePolyCountY = prop.value;
} }
} }
} }
} } else if (!ASSIMP_stricmp(reader->getNodeName(), "string") || !ASSIMP_stricmp(reader->getNodeName(), "enum")) {
else if (!ASSIMP_stricmp(reader->getNodeName(),"string") ||!ASSIMP_stricmp(reader->getNodeName(),"enum")) {
StringProperty prop; StringProperty prop;
ReadStringProperty(prop); ReadStringProperty(prop);
if (prop.value.length()) { if (prop.value.length()) {
@ -1251,21 +1169,17 @@ void IRRImporter::InternReadFile( const std::string& pFile,
*/ */
if (Node::CAMERA == curNode->type) { if (Node::CAMERA == curNode->type) {
cameras.back()->mName.Set(prop.value); cameras.back()->mName.Set(prop.value);
} } else if (Node::LIGHT == curNode->type) {
else if (Node::LIGHT == curNode->type) {
lights.back()->mName.Set(prop.value); lights.back()->mName.Set(prop.value);
} }
} } else if (Node::LIGHT == curNode->type && "LightType" == prop.name) {
else if (Node::LIGHT == curNode->type && "LightType" == prop.name)
{
if (prop.value == "Spot") if (prop.value == "Spot")
lights.back()->mType = aiLightSource_SPOT; lights.back()->mType = aiLightSource_SPOT;
else if (prop.value == "Point") else if (prop.value == "Point")
lights.back()->mType = aiLightSource_POINT; lights.back()->mType = aiLightSource_POINT;
else if (prop.value == "Directional") else if (prop.value == "Directional")
lights.back()->mType = aiLightSource_DIRECTIONAL; lights.back()->mType = aiLightSource_DIRECTIONAL;
else else {
{
// We won't pass the validation with aiLightSourceType_UNDEFINED, // We won't pass the validation with aiLightSourceType_UNDEFINED,
// so we remove the light and replace it with a silly dummy node // so we remove the light and replace it with a silly dummy node
delete lights.back(); delete lights.back();
@ -1274,10 +1188,8 @@ void IRRImporter::InternReadFile( const std::string& pFile,
ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value); ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value);
} }
} } else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
else if ((prop.name == "Mesh" && Node::MESH == curNode->type) || Node::ANIMMESH == curNode->type) {
Node::ANIMMESH == curNode->type)
{
/* This is the file name of the mesh - either /* This is the file name of the mesh - either
* animated or not. We need to make sure we setup * animated or not. We need to make sure we setup
* the correct post-processing settings here. * the correct post-processing settings here.
@ -1303,39 +1215,29 @@ void IRRImporter::InternReadFile( const std::string& pFile,
const std::string extension = GetExtension(prop.value); const std::string extension = GetExtension(prop.value);
if ("irr" == extension) { if ("irr" == extension) {
ASSIMP_LOG_ERROR("IRR: Can't load another IRR file recursively"); ASSIMP_LOG_ERROR("IRR: Can't load another IRR file recursively");
} } else {
else
{
curNode->id = batch.AddLoadRequest(prop.value, pp, &map); curNode->id = batch.AddLoadRequest(prop.value, pp, &map);
curNode->meshPath = prop.value; curNode->meshPath = prop.value;
} }
} } else if (inAnimator && prop.name == "Type") {
else if (inAnimator && prop.name == "Type")
{
// type of the animator // type of the animator
if (prop.value == "rotation") { if (prop.value == "rotation") {
curAnim->type = Animator::ROTATION; curAnim->type = Animator::ROTATION;
} } else if (prop.value == "flyCircle") {
else if (prop.value == "flyCircle") {
curAnim->type = Animator::FLY_CIRCLE; curAnim->type = Animator::FLY_CIRCLE;
} } else if (prop.value == "flyStraight") {
else if (prop.value == "flyStraight") {
curAnim->type = Animator::FLY_CIRCLE; curAnim->type = Animator::FLY_CIRCLE;
} } else if (prop.value == "followSpline") {
else if (prop.value == "followSpline") {
curAnim->type = Animator::FOLLOW_SPLINE; curAnim->type = Animator::FOLLOW_SPLINE;
} } else {
else { ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: " + prop.value);
ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: "
+ prop.value);
curAnim->type = Animator::UNKNOWN; curAnim->type = Animator::UNKNOWN;
} }
} }
} }
} }
} } else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(), "attributes")) {
else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),"attributes")) {
break; break;
} }
} }
@ -1352,16 +1254,15 @@ void IRRImporter::InternReadFile( const std::string& pFile,
if (!curParent) { if (!curParent) {
curParent = root; curParent = root;
ASSIMP_LOG_ERROR("IRR: Too many closing <node> elements"); ASSIMP_LOG_ERROR("IRR: Too many closing <node> elements");
} } else
else curParent = curParent->parent; curParent = curParent->parent;
} } else
else curNode = nullptr; curNode = nullptr;
} }
// clear all flags // clear all flags
else if (!ASSIMP_stricmp(reader->getNodeName(), "materials")) { else if (!ASSIMP_stricmp(reader->getNodeName(), "materials")) {
inMaterials = false; inMaterials = false;
} } else if (!ASSIMP_stricmp(reader->getNodeName(), "animators")) {
else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) {
inAnimator = false; inAnimator = false;
} }
break; break;
@ -1424,8 +1325,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
GenerateGraph(root, tempScene->mRootNode, tempScene, GenerateGraph(root, tempScene->mRootNode, tempScene,
batch, meshes, anims, attach, materials, defMatIdx); batch, meshes, anims, attach, materials, defMatIdx);
if (!anims.empty()) if (!anims.empty()) {
{
tempScene->mNumAnimations = 1; tempScene->mNumAnimations = 1;
tempScene->mAnimations = new aiAnimation *[tempScene->mNumAnimations]; tempScene->mAnimations = new aiAnimation *[tempScene->mNumAnimations];
aiAnimation *an = tempScene->mAnimations[0] = new aiAnimation(); aiAnimation *an = tempScene->mAnimations[0] = new aiAnimation();
@ -1448,8 +1348,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
// copy all meshes to the temporary scene // copy all meshes to the temporary scene
tempScene->mNumMeshes = (unsigned int)meshes.size(); tempScene->mNumMeshes = (unsigned int)meshes.size();
tempScene->mMeshes = new aiMesh *[tempScene->mNumMeshes]; tempScene->mMeshes = new aiMesh *[tempScene->mNumMeshes];
::memcpy(tempScene->mMeshes,&meshes[0],tempScene->mNumMeshes* ::memcpy(tempScene->mMeshes, &meshes[0], tempScene->mNumMeshes * sizeof(void *));
sizeof(void*));
} }
/* Copy all materials to the output array /* Copy all materials to the output array
@ -1457,8 +1356,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
if (!materials.empty()) { if (!materials.empty()) {
tempScene->mNumMaterials = (unsigned int)materials.size(); tempScene->mNumMaterials = (unsigned int)materials.size();
tempScene->mMaterials = new aiMaterial *[tempScene->mNumMaterials]; tempScene->mMaterials = new aiMaterial *[tempScene->mNumMaterials];
::memcpy(tempScene->mMaterials,&materials[0],sizeof(void*)* ::memcpy(tempScene->mMaterials, &materials[0], sizeof(void *) * tempScene->mNumMaterials);
tempScene->mNumMaterials);
} }
/* Now merge all sub scenes and attach them to the correct /* Now merge all sub scenes and attach them to the correct
@ -1466,8 +1364,8 @@ void IRRImporter::InternReadFile( const std::string& pFile,
*/ */
SceneCombiner::MergeScenes(&pScene, tempScene, attach, SceneCombiner::MergeScenes(&pScene, tempScene, attach,
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? ( AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0)); AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) :
0));
/* If we have no meshes | no materials now set the INCOMPLETE /* If we have no meshes | no materials now set the INCOMPLETE
* scene flag. This is necessary if we failed to load all * scene flag. This is necessary if we failed to load all

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

@ -422,7 +422,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
// So we use a separate implementation. // So we use a separate implementation.
ComputeNormals(mesh, smoothingGroups, _mSurfaces[j]); ComputeNormals(mesh, smoothingGroups, _mSurfaces[j]);
} else { } else {
ASSIMP_LOG_DEBUG("LWO2: No need to compute normals, they're already there"); ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there");
} }
++p; ++p;
} }
@ -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;
@ -154,7 +154,7 @@ bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTex
static_assert(sizeof(aiUVTransform) / sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5"); static_assert(sizeof(aiUVTransform) / sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5");
pcMat->AddProperty(&trafo, 1, AI_MATKEY_UVTRANSFORM(type, cur)); pcMat->AddProperty(&trafo, 1, AI_MATKEY_UVTRANSFORM(type, cur));
} }
ASSIMP_LOG_DEBUG("LWO2: Setting up non-UV mapping"); ASSIMP_LOG_VERBOSE_DEBUG("LWO2: Setting up non-UV mapping");
} }
// The older LWOB format does not use indirect references to clips. // The older LWOB format does not use indirect references to clips.
@ -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

@ -101,7 +101,7 @@ void LWS::Element::Parse(const char *&buffer) {
SkipSpaces(&buffer); SkipSpaces(&buffer);
if (children.back().tokens[0] == "Plugin") { if (children.back().tokens[0] == "Plugin") {
ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data"); ASSIMP_LOG_VERBOSE_DEBUG("LWS: Skipping over plugin-specific data");
// strange stuff inside Plugin/Endplugin blocks. Needn't // strange stuff inside Plugin/Endplugin blocks. Needn't
// follow LWS syntax, so we skip over it // follow LWS syntax, so we skip over it
@ -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

@ -5071,7 +5071,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
ptr += sprintf(ptr, "\r\n"); ptr += sprintf(ptr, "\r\n");
} }
/* mathematical shapes face */ /* mathematical shapes face */
if (model->numshape && model->numshape && !(flags & M3D_EXP_NOFACE)) { if (model->numshape !(flags & M3D_EXP_NOFACE)) {
for (j = 0; j < model->numshape; j++) { for (j = 0; j < model->numshape; j++) {
sn = _m3d_safestr(model->shape[j].name, 0); sn = _m3d_safestr(model->shape[j].name, 0);
if (!sn) { if (!sn) {

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

View File

@ -50,21 +50,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* http://www.heppler.com/shader/shader/ * http://www.heppler.com/shader/shader/
*/ */
#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER #ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
#include "AssetLib/MD3/MD3Loader.h" #include "AssetLib/MD3/MD3Loader.h"
#include "Common/Importer.h" #include "Common/Importer.h"
#include <assimp/SceneCombiner.h>
#include <assimp/GenericProperty.h> #include <assimp/GenericProperty.h>
#include <assimp/RemoveComments.h>
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/RemoveComments.h>
#include <assimp/IOSystem.hpp> #include <assimp/SceneCombiner.h>
#include <assimp/importerdesc.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <cctype> #include <cctype>
#include <memory> #include <memory>
@ -86,8 +85,7 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert a Q3 shader blend function to the appropriate enum value // Convert a Q3 shader blend function to the appropriate enum value
Q3Shader::BlendFunc StringToBlendFunc(const std::string& m) Q3Shader::BlendFunc StringToBlendFunc(const std::string &m) {
{
if (m == "GL_ONE") { if (m == "GL_ONE") {
return Q3Shader::BLEND_GL_ONE; return Q3Shader::BLEND_GL_ONE;
} }
@ -109,8 +107,7 @@ Q3Shader::BlendFunc StringToBlendFunc(const std::string& m)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Load a Quake 3 shader // Load a Quake 3 shader
bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* io) bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem *io) {
{
std::unique_ptr<IOStream> file(io->Open(pFile, "rt")); std::unique_ptr<IOStream> file(io->Open(pFile, "rt"));
if (!file.get()) if (!file.get())
return false; // if we can't access the file, don't worry and return return false; // if we can't access the file, don't worry and return
@ -127,8 +124,8 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
CommentRemover::RemoveLineComments("//", &_buff[0]); CommentRemover::RemoveLineComments("//", &_buff[0]);
const char *buff = &_buff[0]; const char *buff = &_buff[0];
Q3Shader::ShaderDataBlock* curData = NULL; Q3Shader::ShaderDataBlock *curData = nullptr;
Q3Shader::ShaderMapBlock* curMap = NULL; Q3Shader::ShaderMapBlock *curMap = nullptr;
// read line per line // read line per line
for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) { for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) {
@ -161,16 +158,13 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
if (blend_src == "add") { if (blend_src == "add") {
curMap->blend_src = Q3Shader::BLEND_GL_ONE; curMap->blend_src = Q3Shader::BLEND_GL_ONE;
curMap->blend_dest = Q3Shader::BLEND_GL_ONE; curMap->blend_dest = Q3Shader::BLEND_GL_ONE;
} } else if (blend_src == "filter") {
else if (blend_src == "filter") {
curMap->blend_src = Q3Shader::BLEND_GL_DST_COLOR; curMap->blend_src = Q3Shader::BLEND_GL_DST_COLOR;
curMap->blend_dest = Q3Shader::BLEND_GL_ZERO; curMap->blend_dest = Q3Shader::BLEND_GL_ZERO;
} } else if (blend_src == "blend") {
else if (blend_src == "blend") {
curMap->blend_src = Q3Shader::BLEND_GL_SRC_ALPHA; curMap->blend_src = Q3Shader::BLEND_GL_SRC_ALPHA;
curMap->blend_dest = Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA; curMap->blend_dest = Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA;
} } else {
else {
curMap->blend_src = StringToBlendFunc(blend_src); curMap->blend_src = StringToBlendFunc(blend_src);
curMap->blend_dest = StringToBlendFunc(GetNextToken(buff)); curMap->blend_dest = StringToBlendFunc(GetNextToken(buff));
} }
@ -180,26 +174,22 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
const std::string at = GetNextToken(buff); const std::string at = GetNextToken(buff);
if (at == "GT0") { if (at == "GT0") {
curMap->alpha_test = Q3Shader::AT_GT0; curMap->alpha_test = Q3Shader::AT_GT0;
} } else if (at == "LT128") {
else if (at == "LT128") {
curMap->alpha_test = Q3Shader::AT_LT128; curMap->alpha_test = Q3Shader::AT_LT128;
} } else if (at == "GE128") {
else if (at == "GE128") {
curMap->alpha_test = Q3Shader::AT_GE128; curMap->alpha_test = Q3Shader::AT_GE128;
} }
} } else if (*buff == '}') {
else if (*buff == '}') {
++buff; ++buff;
// close this map section // close this map section
curMap = NULL; curMap = nullptr;
break; break;
} }
} }
} } else if (*buff == '}') {
else if (*buff == '}') {
++buff; ++buff;
curData = NULL; curData = nullptr;
break; break;
} }
@ -231,8 +221,7 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Load a Quake 3 skin // Load a Quake 3 skin
bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io) bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io) {
{
std::unique_ptr<IOStream> file(io->Open(pFile, "rt")); std::unique_ptr<IOStream> file(io->Open(pFile, "rt"));
if (!file.get()) if (!file.get())
return false; // if we can't access the file, don't worry and return return false; // if we can't access the file, don't worry and return
@ -241,7 +230,8 @@ bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
// read file in memory // read file in memory
const size_t s = file->FileSize(); const size_t s = file->FileSize();
std::vector<char> _buff(s+1);const char* buff = &_buff[0]; std::vector<char> _buff(s + 1);
const char *buff = &_buff[0];
file->Read(&_buff[0], s, 1); file->Read(&_buff[0], s, 1);
_buff[s] = 0; _buff[s] = 0;
@ -270,9 +260,8 @@ bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert Q3Shader to material // Convert Q3Shader to material
void Q3Shader::ConvertShaderToMaterial(aiMaterial* out, const ShaderDataBlock& shader) void Q3Shader::ConvertShaderToMaterial(aiMaterial *out, const ShaderDataBlock &shader) {
{ ai_assert(nullptr != out);
ai_assert(NULL != out);
/* IMPORTANT: This is not a real conversion. Actually we're just guessing and /* IMPORTANT: This is not a real conversion. Actually we're just guessing and
* hacking around to build an aiMaterial that looks nearly equal to the * hacking around to build an aiMaterial that looks nearly equal to the
@ -309,7 +298,8 @@ void Q3Shader::ConvertShaderToMaterial(aiMaterial* out, const ShaderDataBlock& s
// Textures with alpha funcs // Textures with alpha funcs
// - aiTextureFlags_UseAlpha is set (otherwise aiTextureFlags_NoAlpha is explicitly set) // - aiTextureFlags_UseAlpha is set (otherwise aiTextureFlags_NoAlpha is explicitly set)
aiString s((*it).name); aiString s((*it).name);
aiTextureType type; unsigned int index; aiTextureType type;
unsigned int index;
if ((*it).blend_src == Q3Shader::BLEND_GL_ONE && (*it).blend_dest == Q3Shader::BLEND_GL_ONE) { if ((*it).blend_src == Q3Shader::BLEND_GL_ONE && (*it).blend_dest == Q3Shader::BLEND_GL_ONE) {
if (it == shader.maps.begin()) { if (it == shader.maps.begin()) {
@ -318,17 +308,14 @@ void Q3Shader::ConvertShaderToMaterial(aiMaterial* out, const ShaderDataBlock& s
index = cur_diffuse++; index = cur_diffuse++;
type = aiTextureType_DIFFUSE; type = aiTextureType_DIFFUSE;
} } else {
else {
index = cur_emissive++; index = cur_emissive++;
type = aiTextureType_EMISSIVE; type = aiTextureType_EMISSIVE;
} }
} } else if ((*it).blend_src == Q3Shader::BLEND_GL_DST_COLOR && (*it).blend_dest == Q3Shader::BLEND_GL_ZERO) {
else if ((*it).blend_src == Q3Shader::BLEND_GL_DST_COLOR && (*it).blend_dest == Q3Shader::BLEND_GL_ZERO) {
index = cur_lm++; index = cur_lm++;
type = aiTextureType_LIGHTMAP; type = aiTextureType_LIGHTMAP;
} } else {
else {
const int blend = aiBlendMode_Default; const int blend = aiBlendMode_Default;
out->AddProperty(&blend, 1, AI_MATKEY_BLEND_FUNC); out->AddProperty(&blend, 1, AI_MATKEY_BLEND_FUNC);
@ -353,26 +340,16 @@ void Q3Shader::ConvertShaderToMaterial(aiMaterial* out, const ShaderDataBlock& s
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
MD3Importer::MD3Importer() MD3Importer::MD3Importer() :
: configFrameID (0) configFrameID(0), configHandleMP(true), configSpeedFlag(), pcHeader(), mBuffer(), fileSize(), mScene(), mIOHandler() {}
, configHandleMP (true)
, configSpeedFlag()
, pcHeader()
, mBuffer()
, fileSize()
, mScene()
, mIOHandler()
{}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
MD3Importer::~MD3Importer() MD3Importer::~MD3Importer() {}
{}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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 MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const bool MD3Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
{
const std::string extension = GetExtension(pFile); const std::string extension = GetExtension(pFile);
if (extension == "md3") if (extension == "md3")
return true; return true;
@ -387,8 +364,7 @@ bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateHeaderOffsets() void MD3Importer::ValidateHeaderOffsets() {
{
// Check magic number // Check magic number
if (pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE && if (pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE) pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
@ -420,8 +396,7 @@ void MD3Importer::ValidateHeaderOffsets()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf) void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface *pcSurf) {
{
// Calculate the relative offset of the surface // Calculate the relative offset of the surface
const int32_t ofs = int32_t((const unsigned char *)pcSurf - this->mBuffer); const int32_t ofs = int32_t((const unsigned char *)pcSurf - this->mBuffer);
@ -460,8 +435,7 @@ const aiImporterDesc* MD3Importer::GetInfo () const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup configuration properties // Setup configuration properties
void MD3Importer::SetupProperties(const Importer* pImp) void MD3Importer::SetupProperties(const Importer *pImp) {
{
// The // The
// AI_CONFIG_IMPORT_MD3_KEYFRAME option overrides the // AI_CONFIG_IMPORT_MD3_KEYFRAME option overrides the
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
@ -485,8 +459,7 @@ void MD3Importer::SetupProperties(const Importer* pImp)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Try to read the skin for a MD3 file // Try to read the skin for a MD3 file
void MD3Importer::ReadSkin(Q3Shader::SkinData& fill) const void MD3Importer::ReadSkin(Q3Shader::SkinData &fill) const {
{
// skip any postfixes (e.g. lower_1.md3) // skip any postfixes (e.g. lower_1.md3)
std::string::size_type s = filename.find_last_of('_'); std::string::size_type s = filename.find_last_of('_');
if (s == std::string::npos) { if (s == std::string::npos) {
@ -503,8 +476,7 @@ void MD3Importer::ReadSkin(Q3Shader::SkinData& fill) const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Try to read the shader for a MD3 file // Try to read the shader for a MD3 file
void MD3Importer::ReadShader(Q3Shader::ShaderData& fill) const void MD3Importer::ReadShader(Q3Shader::ShaderData &fill) const {
{
// Determine Q3 model name from given path // Determine Q3 model name from given path
const std::string::size_type s = path.find_last_of("\\/", path.length() - 2); const std::string::size_type s = path.find_last_of("\\/", path.length() - 2);
const std::string model_file = path.substr(s + 1, path.length() - (s + 2)); const std::string model_file = path.substr(s + 1, path.length() - (s + 2));
@ -514,8 +486,7 @@ void MD3Importer::ReadShader(Q3Shader::ShaderData& fill) const
if (!Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + model_file + ".shader", mIOHandler)) { if (!Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + model_file + ".shader", mIOHandler)) {
Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + filename + ".shader", mIOHandler); Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + filename + ".shader", mIOHandler);
} }
} } else {
else {
// If the given string specifies a file, load this file. // If the given string specifies a file, load this file.
// Otherwise it's a directory. // Otherwise it's a directory.
const std::string::size_type st = configShaderFile.find_last_of('.'); const std::string::size_type st = configShaderFile.find_last_of('.');
@ -524,8 +495,7 @@ void MD3Importer::ReadShader(Q3Shader::ShaderData& fill) const
if (!Q3Shader::LoadShader(fill, configShaderFile + model_file + ".shader", mIOHandler)) { if (!Q3Shader::LoadShader(fill, configShaderFile + model_file + ".shader", mIOHandler)) {
Q3Shader::LoadShader(fill, configShaderFile + filename + ".shader", mIOHandler); Q3Shader::LoadShader(fill, configShaderFile + filename + ".shader", mIOHandler);
} }
} } else {
else {
Q3Shader::LoadShader(fill, configShaderFile, mIOHandler); Q3Shader::LoadShader(fill, configShaderFile, mIOHandler);
} }
} }
@ -533,8 +503,7 @@ void MD3Importer::ReadShader(Q3Shader::ShaderData& fill) const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Tiny helper to remove a single node from its parent' list // Tiny helper to remove a single node from its parent' list
void RemoveSingleNodeFromList(aiNode* nd) void RemoveSingleNodeFromList(aiNode *nd) {
{
if (!nd || nd->mNumChildren || !nd->mParent) return; if (!nd || nd->mNumChildren || !nd->mParent) return;
aiNode *par = nd->mParent; aiNode *par = nd->mParent;
for (unsigned int i = 0; i < par->mNumChildren; ++i) { for (unsigned int i = 0; i < par->mNumChildren; ++i) {
@ -551,8 +520,7 @@ void RemoveSingleNodeFromList(aiNode* nd)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Read a multi-part Q3 player model // Read a multi-part Q3 player model
bool MD3Importer::ReadMultipartFile() bool MD3Importer::ReadMultipartFile() {
{
// check whether the file name contains a common postfix, e.g lower_2.md3 // check whether the file name contains a common postfix, e.g lower_2.md3
std::string::size_type s = filename.find_last_of('_'), t = filename.find_last_of('.'); std::string::size_type s = filename.find_last_of('_'), t = filename.find_last_of('.');
@ -569,9 +537,9 @@ bool MD3Importer::ReadMultipartFile()
const std::string upper = path + "upper" + suffix + ".md3"; const std::string upper = path + "upper" + suffix + ".md3";
const std::string head = path + "head" + suffix + ".md3"; const std::string head = path + "head" + suffix + ".md3";
aiScene* scene_upper = NULL; aiScene *scene_upper = nullptr;
aiScene* scene_lower = NULL; aiScene *scene_lower = nullptr;
aiScene* scene_head = NULL; aiScene *scene_head = nullptr;
std::string failure; std::string failure;
aiNode *tag_torso, *tag_head; aiNode *tag_torso, *tag_head;
@ -681,8 +649,7 @@ error_cleanup:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert a MD3 path to a proper value // Convert a MD3 path to a proper value
void MD3Importer::ConvertPath(const char* texture_name, const char* header_name, std::string& out) const void MD3Importer::ConvertPath(const char *texture_name, const char *header_name, std::string &out) const {
{
// If the MD3's internal path itself and the given path are using // If the MD3's internal path itself and the given path are using
// the same directory, remove it completely to get right output paths. // the same directory, remove it completely to get right output paths.
const char *end1 = ::strrchr(header_name, '\\'); const char *end1 = ::strrchr(header_name, '\\');
@ -706,8 +673,8 @@ void MD3Importer::ConvertPath(const char* texture_name, const char* header_name,
out = end2 + 1; out = end2 + 1;
return; return;
} }
} } else
else len2 = std::min (len1, (size_t)(end2 - texture_name )); len2 = std::min(len1, (size_t)(end2 - texture_name));
if (!ASSIMP_strincmp(texture_name, header_name, static_cast<unsigned int>(len2))) { if (!ASSIMP_strincmp(texture_name, header_name, static_cast<unsigned int>(len2))) {
// Use the file name only // Use the file name only
out = end2 + 1; out = end2 + 1;
@ -747,8 +714,9 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
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 MD3 file " + pFile + "."); throw DeadlyImportError("Failed to open MD3 file " + pFile + ".");
}
// Check whether the md3 file is large enough to contain the header // Check whether the md3 file is large enough to contain the header
fileSize = (unsigned int)file->FileSize(); fileSize = (unsigned int)file->FileSize();
@ -852,24 +820,19 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
ValidateSurfaceHeaderOffsets(pcSurfaces); ValidateSurfaceHeaderOffsets(pcSurfaces);
// Navigate to the vertex list of the surface // Navigate to the vertex list of the surface
BE_NCONST MD3::Vertex* pcVertices = (BE_NCONST MD3::Vertex*) BE_NCONST MD3::Vertex *pcVertices = (BE_NCONST MD3::Vertex *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
// Navigate to the triangle list of the surface // Navigate to the triangle list of the surface
BE_NCONST MD3::Triangle* pcTriangles = (BE_NCONST MD3::Triangle*) BE_NCONST MD3::Triangle *pcTriangles = (BE_NCONST MD3::Triangle *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
// Navigate to the texture coordinate list of the surface // Navigate to the texture coordinate list of the surface
BE_NCONST MD3::TexCoord* pcUVs = (BE_NCONST MD3::TexCoord*) BE_NCONST MD3::TexCoord *pcUVs = (BE_NCONST MD3::TexCoord *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_ST);
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST);
// Navigate to the shader list of the surface // Navigate to the shader list of the surface
BE_NCONST MD3::Shader* pcShaders = (BE_NCONST MD3::Shader*) BE_NCONST MD3::Shader *pcShaders = (BE_NCONST MD3::Shader *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_SHADERS);
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
// If the submesh is empty ignore it // If the submesh is empty ignore it
if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES) if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES) {
{
pcSurfaces = (BE_NCONST MD3::Surface *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_END); pcSurfaces = (BE_NCONST MD3::Surface *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_END);
pScene->mNumMeshes--; pScene->mNumMeshes--;
continue; continue;
@ -880,7 +843,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
aiMesh *pcMesh = pScene->mMeshes[iNum]; aiMesh *pcMesh = pScene->mMeshes[iNum];
std::string _texture_name; std::string _texture_name;
const char* texture_name = NULL; const char *texture_name = nullptr;
// Check whether we have a texture record for this surface in the .skin file // Check whether we have a texture record for this surface in the .skin file
std::list<Q3Shader::SkinData::TextureEntry>::iterator it = std::find( std::list<Q3Shader::SkinData::TextureEntry>::iterator it = std::find(
@ -888,7 +851,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
if (it != skins.textures.end()) { if (it != skins.textures.end()) {
texture_name = &*(_texture_name = (*it).second).begin(); texture_name = &*(_texture_name = (*it).second).begin();
ASSIMP_LOG_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME); ASSIMP_LOG_VERBOSE_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME);
(*it).resolved = true; // mark entry as resolved (*it).resolved = true; // mark entry as resolved
} }
@ -902,7 +865,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
ConvertPath(texture_name, header_name, convertedPath); ConvertPath(texture_name, header_name, convertedPath);
} }
const Q3Shader::ShaderDataBlock* shader = NULL; const Q3Shader::ShaderDataBlock *shader = nullptr;
// Now search the current shader for a record with this name ( // Now search the current shader for a record with this name (
// excluding texture file extension) // excluding texture file extension)
@ -1089,8 +1052,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f,
0.f, -1.f, 0.f, 0.f, 0.f, -1.f, 0.f, 0.f,
0.f,0.f,0.f,1.f 0.f, 0.f, 0.f, 1.f);
);
} }
#endif // !! ASSIMP_BUILD_NO_MD3_IMPORTER #endif // !! ASSIMP_BUILD_NO_MD3_IMPORTER

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,8 +480,9 @@ 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) {
@ -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;
@ -93,8 +92,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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);
@ -102,8 +100,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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);
@ -111,8 +108,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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)) {
@ -128,21 +124,22 @@ 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))
buffer++;
out.mName = std::string(sz, (uintptr_t)(buffer - sz)); out.mName = std::string(sz, (uintptr_t)(buffer - sz));
SkipSpaces(); SkipSpaces();
@ -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
} }
@ -169,18 +165,19 @@ bool MD5Parser::ParseSection(Section& out)
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;
} }
@ -193,7 +190,8 @@ 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() \
if (!SkipSpaces(&sz)) \
MD5Parser::ReportWarning("Unexpected end of line", elem.iLineNumber); 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)
@ -215,7 +213,8 @@ bool MD5Parser::ParseSection(Section& out)
#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)) \
++sz; \
const char *szEnd = sz; \ const char *szEnd = sz; \
if (bQuota) { \ if (bQuota) { \
szStart++; \ szStart++; \
@ -231,28 +230,27 @@ bool MD5Parser::ParseSection(Section& out)
// 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) \
++sz; \
const char *szStart = ++sz; \ const char *szStart = ++sz; \
while('\"'!=*sz)++sz; \ while ('\"' != *sz) \
++sz; \
const char *szEnd = (sz++); \ const char *szEnd = (sz++); \
out.length = (ai_uint32)(szEnd - szStart); \ out.length = (ai_uint32)(szEnd - szStart); \
::memcpy(out.data, szStart, out.length); \ ::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());
@ -268,8 +266,7 @@ MD5MeshParser::MD5MeshParser(SectionList& mSections)
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();
@ -358,8 +355,7 @@ 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;
@ -388,8 +384,7 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
// 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;
@ -400,8 +395,7 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
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;
@ -420,15 +414,14 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
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);
@ -436,11 +429,9 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
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") {
else if((*iter).mName == "frameRate") {
fast_atoreal_move<float>((*iter).mGlobalValue.c_str(), fFrameRate); fast_atoreal_move<float>((*iter).mGlobalValue.c_str(), fFrameRate);
} }
} }
@ -449,27 +440,22 @@ 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;
@ -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

@ -829,7 +829,7 @@ void HL1MDLLoader::read_meshes() {
} }
} else { } else {
for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) { for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) {
if (i & 1) { if (faceIdx & 1) {
// Preserve winding order. // Preserve winding order.
mesh_faces.push_back(HL1MeshFace{ mesh_faces.push_back(HL1MeshFace{
tricmds[faceIdx + 1], tricmds[faceIdx + 1],

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;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -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

@ -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

@ -253,7 +253,6 @@ static bool isDataDefinitionEnd(const char *tmp) {
if (*tmp == '\\') { if (*tmp == '\\') {
tmp++; tmp++;
if (IsLineEnd(*tmp)) { if (IsLineEnd(*tmp)) {
tmp++;
return true; return true;
} }
} }
@ -495,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);
} }
@ -754,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();
@ -767,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);
} }
} }
@ -776,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;
@ -793,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.");

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