2015-05-19 03:48:29 +00:00
|
|
|
/*
|
|
|
|
Open Asset Import Library (assimp)
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
|
2019-01-30 08:41:39 +00:00
|
|
|
Copyright (c) 2006-2019, assimp team
|
2018-01-28 18:42:05 +00:00
|
|
|
|
2017-05-09 17:57:36 +00:00
|
|
|
|
2015-05-19 03:48:29 +00:00
|
|
|
All rights reserved.
|
|
|
|
|
2015-05-19 03:52:10 +00:00
|
|
|
Redistribution and use of this software in source and binary forms,
|
|
|
|
with or without modification, are permitted provided that the
|
2015-05-19 03:48:29 +00:00
|
|
|
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.
|
|
|
|
|
2015-05-19 03:52:10 +00:00
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
2015-05-19 03:48:29 +00:00
|
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
2015-05-19 03:52:10 +00:00
|
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
2015-05-19 03:48:29 +00:00
|
|
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
2015-05-19 03:52:10 +00:00
|
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
2015-05-19 03:48:29 +00:00
|
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
2015-05-19 03:52:10 +00:00
|
|
|
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
|
2015-05-19 03:48:29 +00:00
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
|
|
|
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
|
|
|
|
|
|
|
#include "ObjExporter.h"
|
2018-01-06 00:18:33 +00:00
|
|
|
#include <assimp/Exceptional.h>
|
|
|
|
#include <assimp/StringComparison.h>
|
2015-07-09 23:21:10 +00:00
|
|
|
#include <assimp/version.h>
|
|
|
|
#include <assimp/IOSystem.hpp>
|
|
|
|
#include <assimp/Exporter.hpp>
|
|
|
|
#include <assimp/material.h>
|
|
|
|
#include <assimp/scene.h>
|
2016-04-05 21:23:53 +00:00
|
|
|
#include <memory>
|
2015-05-19 03:48:29 +00:00
|
|
|
|
|
|
|
using namespace Assimp;
|
2017-02-04 13:51:23 +00:00
|
|
|
|
|
|
|
namespace Assimp {
|
2015-05-19 03:48:29 +00:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
// Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
|
2017-11-02 10:13:52 +00:00
|
|
|
void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
|
2015-05-19 03:57:13 +00:00
|
|
|
// invoke the exporter
|
|
|
|
ObjExporter exporter(pFile, pScene);
|
|
|
|
|
2017-10-09 13:47:17 +00:00
|
|
|
if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
|
|
|
|
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
// we're still here - export successfully completed. Write both the main OBJ file and the material script
|
|
|
|
{
|
2016-04-05 21:23:53 +00:00
|
|
|
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
|
2015-05-19 03:57:13 +00:00
|
|
|
if(outfile == NULL) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
{
|
2016-04-05 21:23:53 +00:00
|
|
|
std::unique_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
|
2015-05-19 03:57:13 +00:00
|
|
|
if(outfile == NULL) {
|
|
|
|
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);
|
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2017-10-26 15:59:09 +00:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
// Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp
|
|
|
|
void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) {
|
|
|
|
// invoke the exporter
|
|
|
|
ObjExporter exporter(pFile, pScene, true);
|
|
|
|
|
|
|
|
if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
|
|
|
|
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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"));
|
|
|
|
if(outfile == NULL) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:48:29 +00:00
|
|
|
} // end of namespace Assimp
|
|
|
|
|
|
|
|
static const std::string MaterialExt = ".mtl";
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2017-10-26 15:59:09 +00:00
|
|
|
ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl)
|
2015-05-19 03:48:29 +00:00
|
|
|
: filename(_filename)
|
|
|
|
, pScene(pScene)
|
2017-02-04 13:51:23 +00:00
|
|
|
, vn()
|
|
|
|
, vt()
|
2018-04-30 14:27:34 +00:00
|
|
|
, vp()
|
|
|
|
, useVc(false)
|
2017-09-30 07:37:34 +00:00
|
|
|
, mVnMap()
|
|
|
|
, mVtMap()
|
2018-04-30 14:27:34 +00:00
|
|
|
, mVpMap()
|
2017-09-30 07:37:34 +00:00
|
|
|
, mMeshes()
|
2017-05-26 07:18:23 +00:00
|
|
|
, endl("\n") {
|
2015-05-19 03:57:13 +00:00
|
|
|
// make sure that all formatting happens using the standard, C locale and not the user's current locale
|
|
|
|
const std::locale& l = std::locale("C");
|
|
|
|
mOutput.imbue(l);
|
2019-06-20 17:11:11 +00:00
|
|
|
mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
|
2015-05-19 03:57:13 +00:00
|
|
|
mOutputMat.imbue(l);
|
2019-06-20 17:11:11 +00:00
|
|
|
mOutputMat.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
|
2015-05-19 03:48:29 +00:00
|
|
|
|
2017-10-26 15:59:09 +00:00
|
|
|
WriteGeometryFile(noMtl);
|
2018-03-20 22:38:08 +00:00
|
|
|
if ( !noMtl ) {
|
2017-10-26 15:59:09 +00:00
|
|
|
WriteMaterialFile();
|
2018-03-20 22:38:08 +00:00
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2017-02-04 17:32:04 +00:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
ObjExporter::~ObjExporter() {
|
2018-03-20 22:38:08 +00:00
|
|
|
// empty
|
2017-02-04 17:32:04 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:48:29 +00:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
2018-03-20 22:38:08 +00:00
|
|
|
std::string ObjExporter::GetMaterialLibName() {
|
2015-05-19 03:57:13 +00:00
|
|
|
// within the Obj file, we use just the relative file name with the path stripped
|
|
|
|
const std::string& s = GetMaterialLibFileName();
|
|
|
|
std::string::size_type il = s.find_last_of("/\\");
|
|
|
|
if (il != std::string::npos) {
|
|
|
|
return s.substr(il + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2017-05-17 08:13:07 +00:00
|
|
|
std::string ObjExporter::GetMaterialLibFileName() {
|
2017-11-09 22:19:26 +00:00
|
|
|
// Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl
|
2017-05-16 19:56:49 +00:00
|
|
|
size_t lastdot = filename.find_last_of('.');
|
2018-03-20 22:38:08 +00:00
|
|
|
if ( lastdot != std::string::npos ) {
|
|
|
|
return filename.substr( 0, lastdot ) + MaterialExt;
|
|
|
|
}
|
2017-05-16 13:55:40 +00:00
|
|
|
|
2015-05-19 03:48:29 +00:00
|
|
|
return filename + MaterialExt;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2017-09-30 07:37:34 +00:00
|
|
|
void ObjExporter::WriteHeader(std::ostringstream& out) {
|
2015-05-19 03:57:13 +00:00
|
|
|
out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl;
|
2017-09-30 07:37:34 +00:00
|
|
|
out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
|
|
|
|
<< aiGetVersionRevision() << ")" << endl << endl;
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2018-03-20 22:38:08 +00:00
|
|
|
std::string ObjExporter::GetMaterialName(unsigned int index) {
|
2015-05-19 03:57:13 +00:00
|
|
|
const aiMaterial* const mat = pScene->mMaterials[index];
|
2017-09-30 07:37:34 +00:00
|
|
|
if ( nullptr == mat ) {
|
|
|
|
static const std::string EmptyStr;
|
|
|
|
return EmptyStr;
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
aiString s;
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) {
|
|
|
|
return std::string(s.data,s.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
char number[ sizeof(unsigned int) * 3 + 1 ];
|
|
|
|
ASSIMP_itoa10(number,index);
|
|
|
|
return "$Material_" + std::string(number);
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2018-03-20 22:38:08 +00:00
|
|
|
void ObjExporter::WriteMaterialFile() {
|
2015-05-19 03:57:13 +00:00
|
|
|
WriteHeader(mOutputMat);
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
|
|
|
|
const aiMaterial* const mat = pScene->mMaterials[i];
|
|
|
|
|
|
|
|
int illum = 1;
|
|
|
|
mOutputMat << "newmtl " << GetMaterialName(i) << endl;
|
|
|
|
|
|
|
|
aiColor4D c;
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
|
|
|
|
mOutputMat << "Kd " << c.r << " " << c.g << " " << c.b << endl;
|
|
|
|
}
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
|
|
|
|
mOutputMat << "Ka " << c.r << " " << c.g << " " << c.b << endl;
|
|
|
|
}
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
|
|
|
|
mOutputMat << "Ks " << c.r << " " << c.g << " " << c.b << endl;
|
|
|
|
}
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
|
|
|
|
mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
|
|
|
|
}
|
2017-01-13 01:11:17 +00:00
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_TRANSPARENT,c)) {
|
|
|
|
mOutputMat << "Tf " << c.r << " " << c.g << " " << c.b << endl;
|
|
|
|
}
|
2017-11-02 10:13:52 +00:00
|
|
|
|
2016-07-16 02:14:36 +00:00
|
|
|
ai_real o;
|
2015-05-19 03:57:13 +00:00
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) {
|
|
|
|
mOutputMat << "d " << o << endl;
|
|
|
|
}
|
2017-01-13 01:11:17 +00:00
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_REFRACTI,o)) {
|
|
|
|
mOutputMat << "Ni " << o << endl;
|
|
|
|
}
|
2015-05-19 03:57:13 +00:00
|
|
|
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) {
|
|
|
|
mOutputMat << "Ns " << o << endl;
|
|
|
|
illum = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
mOutputMat << "illum " << illum << endl;
|
|
|
|
|
|
|
|
aiString s;
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
|
|
|
|
mOutputMat << "map_Kd " << s.data << endl;
|
|
|
|
}
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
|
|
|
|
mOutputMat << "map_Ka " << s.data << endl;
|
|
|
|
}
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
|
|
|
|
mOutputMat << "map_Ks " << s.data << endl;
|
|
|
|
}
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
|
|
|
|
mOutputMat << "map_Ns " << s.data << endl;
|
|
|
|
}
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_OPACITY(0),s)) {
|
|
|
|
mOutputMat << "map_d " << s.data << endl;
|
|
|
|
}
|
|
|
|
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
|
|
|
|
// implementations seem to vary here, so write both variants
|
|
|
|
mOutputMat << "bump " << s.data << endl;
|
|
|
|
mOutputMat << "map_bump " << s.data << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
mOutputMat << endl;
|
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2017-10-26 15:59:09 +00:00
|
|
|
void ObjExporter::WriteGeometryFile(bool noMtl) {
|
2015-05-19 03:57:13 +00:00
|
|
|
WriteHeader(mOutput);
|
2017-10-26 15:59:09 +00:00
|
|
|
if (!noMtl)
|
|
|
|
mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
|
2015-05-19 03:57:13 +00:00
|
|
|
|
|
|
|
// collect mesh geometry
|
|
|
|
aiMatrix4x4 mBase;
|
|
|
|
AddNode(pScene->mRootNode, mBase);
|
|
|
|
|
2017-02-04 13:51:23 +00:00
|
|
|
// write vertex positions with colors, if any
|
2018-04-30 14:27:34 +00:00
|
|
|
mVpMap.getKeys( vp );
|
|
|
|
if ( !useVc ) {
|
2017-02-04 13:51:23 +00:00
|
|
|
mOutput << "# " << vp.size() << " vertex positions" << endl;
|
2018-04-30 14:27:34 +00:00
|
|
|
for ( const vertexData& v : vp ) {
|
|
|
|
mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << endl;
|
2017-02-04 13:51:23 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mOutput << "# " << vp.size() << " vertex positions and colors" << endl;
|
2018-04-30 14:27:34 +00:00
|
|
|
for ( const vertexData& v : vp ) {
|
|
|
|
mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << " " << v.vc.r << " " << v.vc.g << " " << v.vc.b << endl;
|
2017-02-04 13:51:23 +00:00
|
|
|
}
|
2015-05-19 03:57:13 +00:00
|
|
|
}
|
|
|
|
mOutput << endl;
|
|
|
|
|
|
|
|
// write uv coordinates
|
2018-04-30 14:27:34 +00:00
|
|
|
mVtMap.getKeys(vt);
|
2015-05-19 03:57:13 +00:00
|
|
|
mOutput << "# " << vt.size() << " UV coordinates" << endl;
|
2016-04-05 20:53:54 +00:00
|
|
|
for(const aiVector3D& v : vt) {
|
2015-05-19 03:57:13 +00:00
|
|
|
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
|
|
|
|
}
|
|
|
|
mOutput << endl;
|
|
|
|
|
|
|
|
// write vertex normals
|
2018-04-30 14:27:34 +00:00
|
|
|
mVnMap.getKeys(vn);
|
2015-05-19 03:57:13 +00:00
|
|
|
mOutput << "# " << vn.size() << " vertex normals" << endl;
|
2016-04-05 20:53:54 +00:00
|
|
|
for(const aiVector3D& v : vn) {
|
2015-05-19 03:57:13 +00:00
|
|
|
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
|
|
|
|
}
|
|
|
|
mOutput << endl;
|
|
|
|
|
|
|
|
// now write all mesh instances
|
2017-09-30 07:37:34 +00:00
|
|
|
for(const MeshInstance& m : mMeshes) {
|
2015-05-19 03:57:13 +00:00
|
|
|
mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
|
|
|
|
if (!m.name.empty()) {
|
|
|
|
mOutput << "g " << m.name << endl;
|
|
|
|
}
|
2018-03-20 22:38:08 +00:00
|
|
|
if ( !noMtl ) {
|
2017-10-26 15:59:09 +00:00
|
|
|
mOutput << "usemtl " << m.matname << endl;
|
2018-03-20 22:38:08 +00:00
|
|
|
}
|
2015-05-19 03:57:13 +00:00
|
|
|
|
2016-04-05 20:53:54 +00:00
|
|
|
for(const Face& f : m.faces) {
|
2015-05-19 03:57:13 +00:00
|
|
|
mOutput << f.kind << ' ';
|
2016-04-05 20:53:54 +00:00
|
|
|
for(const FaceVertex& fv : f.indices) {
|
2015-05-19 03:57:13 +00:00
|
|
|
mOutput << ' ' << fv.vp;
|
|
|
|
|
|
|
|
if (f.kind != 'p') {
|
|
|
|
if (fv.vt || f.kind == 'f') {
|
|
|
|
mOutput << '/';
|
|
|
|
}
|
|
|
|
if (fv.vt) {
|
|
|
|
mOutput << fv.vt;
|
|
|
|
}
|
|
|
|
if (f.kind == 'f' && fv.vn) {
|
|
|
|
mOutput << '/' << fv.vn;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mOutput << endl;
|
|
|
|
}
|
|
|
|
mOutput << endl;
|
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2017-02-04 13:51:23 +00:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
|
2018-03-20 22:38:08 +00:00
|
|
|
mMeshes.push_back(MeshInstance() );
|
2017-09-30 07:37:34 +00:00
|
|
|
MeshInstance& mesh = mMeshes.back();
|
2015-05-19 03:57:13 +00:00
|
|
|
|
2018-04-30 14:27:34 +00:00
|
|
|
if ( nullptr != m->mColors[ 0 ] ) {
|
|
|
|
useVc = true;
|
|
|
|
}
|
|
|
|
|
2017-11-05 15:35:22 +00:00
|
|
|
mesh.name = std::string( name.data, name.length );
|
2015-05-19 03:57:13 +00:00
|
|
|
mesh.matname = GetMaterialName(m->mMaterialIndex);
|
|
|
|
|
|
|
|
mesh.faces.resize(m->mNumFaces);
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < m->mNumFaces; ++i) {
|
|
|
|
const aiFace& f = m->mFaces[i];
|
|
|
|
|
|
|
|
Face& face = mesh.faces[i];
|
|
|
|
switch (f.mNumIndices) {
|
|
|
|
case 1:
|
|
|
|
face.kind = 'p';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
face.kind = 'l';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
face.kind = 'f';
|
|
|
|
}
|
|
|
|
face.indices.resize(f.mNumIndices);
|
|
|
|
|
|
|
|
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
|
|
|
|
const unsigned int idx = f.mIndices[a];
|
|
|
|
|
|
|
|
aiVector3D vert = mat * m->mVertices[idx];
|
2018-04-30 14:27:34 +00:00
|
|
|
|
|
|
|
if ( nullptr != m->mColors[ 0 ] ) {
|
|
|
|
aiColor4D col4 = m->mColors[ 0 ][ idx ];
|
|
|
|
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)});
|
|
|
|
} else {
|
|
|
|
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)});
|
|
|
|
}
|
2015-05-19 03:57:13 +00:00
|
|
|
|
|
|
|
if (m->mNormals) {
|
|
|
|
aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
|
2017-09-30 07:37:34 +00:00
|
|
|
face.indices[a].vn = mVnMap.getIndex(norm);
|
2017-02-04 13:51:23 +00:00
|
|
|
} else {
|
2015-05-19 03:57:13 +00:00
|
|
|
face.indices[a].vn = 0;
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:51:23 +00:00
|
|
|
if ( m->mTextureCoords[ 0 ] ) {
|
2017-09-30 07:37:34 +00:00
|
|
|
face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]);
|
2017-02-04 13:51:23 +00:00
|
|
|
} else {
|
2015-05-19 03:57:13 +00:00
|
|
|
face.indices[a].vt = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2018-03-20 22:38:08 +00:00
|
|
|
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) {
|
2015-05-19 03:57:13 +00:00
|
|
|
const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
|
2015-05-19 03:48:29 +00:00
|
|
|
|
2018-04-11 15:04:49 +00:00
|
|
|
aiMesh *cm( nullptr );
|
2015-05-19 03:57:13 +00:00
|
|
|
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
|
2018-04-11 15:04:49 +00:00
|
|
|
cm = pScene->mMeshes[nd->mMeshes[i]];
|
|
|
|
if (nullptr != cm) {
|
|
|
|
AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
|
|
|
|
} else {
|
|
|
|
AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
|
|
|
|
}
|
2015-05-19 03:57:13 +00:00
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
|
|
|
|
AddNode(nd->mChildren[i], mAbs);
|
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#endif // ASSIMP_BUILD_NO_OBJ_EXPORTER
|
|
|
|
#endif // ASSIMP_BUILD_NO_EXPORT
|