Merge branch 'master' into issue-1167
commit
2acb513732
|
@ -62,6 +62,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
|
||||||
#include "JoinVerticesProcess.h"
|
#include "JoinVerticesProcess.h"
|
||||||
#include "MakeVerboseFormat.h"
|
#include "MakeVerboseFormat.h"
|
||||||
#include "ConvertToLHProcess.h"
|
#include "ConvertToLHProcess.h"
|
||||||
|
#include "PretransformVertices.h"
|
||||||
#include <assimp/Exceptional.h>
|
#include <assimp/Exceptional.h>
|
||||||
#include "ScenePrivate.h"
|
#include "ScenePrivate.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -397,6 +398,11 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool exportPointCloud(false);
|
||||||
|
if (nullptr != pProperties) {
|
||||||
|
exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
|
||||||
|
}
|
||||||
|
|
||||||
// dispatch other processes
|
// dispatch other processes
|
||||||
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
|
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
|
||||||
BaseProcess* const p = pimpl->mPostProcessingSteps[a];
|
BaseProcess* const p = pimpl->mPostProcessingSteps[a];
|
||||||
|
@ -405,7 +411,9 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
|
||||||
&& !dynamic_cast<FlipUVsProcess*>(p)
|
&& !dynamic_cast<FlipUVsProcess*>(p)
|
||||||
&& !dynamic_cast<FlipWindingOrderProcess*>(p)
|
&& !dynamic_cast<FlipWindingOrderProcess*>(p)
|
||||||
&& !dynamic_cast<MakeLeftHandedProcess*>(p)) {
|
&& !dynamic_cast<MakeLeftHandedProcess*>(p)) {
|
||||||
|
if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
p->Execute(scenecopy.get());
|
p->Execute(scenecopy.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,7 +449,6 @@ const char* Exporter::GetErrorString() const {
|
||||||
return pimpl->mError.c_str();
|
return pimpl->mError.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Exporter::FreeBlob() {
|
void Exporter::FreeBlob() {
|
||||||
delete pimpl->blob;
|
delete pimpl->blob;
|
||||||
|
@ -470,7 +477,7 @@ size_t Exporter::GetExportFormatCount() const {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
|
const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
|
||||||
if (index >= GetExportFormatCount()) {
|
if (index >= GetExportFormatCount()) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return from static storage if the requested index is built-in.
|
// Return from static storage if the requested index is built-in.
|
||||||
|
@ -495,7 +502,8 @@ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Exporter::UnregisterExporter(const char* id) {
|
void Exporter::UnregisterExporter(const char* id) {
|
||||||
for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
|
for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin();
|
||||||
|
it != pimpl->mExporters.end(); ++it) {
|
||||||
if (!strcmp((*it).mDescription.id,id)) {
|
if (!strcmp((*it).mDescription.id,id)) {
|
||||||
pimpl->mExporters.erase(it);
|
pimpl->mExporters.erase(it);
|
||||||
break;
|
break;
|
||||||
|
@ -531,8 +539,7 @@ bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Set a configuration property
|
// Set a configuration property
|
||||||
bool ExportProperties :: SetPropertyString(const char* szName, const std::string& value)
|
bool ExportProperties::SetPropertyString(const char* szName, const std::string& value) {
|
||||||
{
|
|
||||||
return SetGenericProperty<std::string>(mStringProperties, szName,value);
|
return SetGenericProperty<std::string>(mStringProperties, szName,value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -874,7 +874,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
|
||||||
|
|
||||||
const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo );
|
const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo );
|
||||||
if ( mesh ) {
|
if ( mesh ) {
|
||||||
const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform );
|
const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform, nd);
|
||||||
std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) );
|
std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -891,7 +891,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model,
|
std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model,
|
||||||
const aiMatrix4x4& node_global_transform )
|
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||||
{
|
{
|
||||||
std::vector<unsigned int> temp;
|
std::vector<unsigned int> temp;
|
||||||
|
|
||||||
|
@ -915,17 +915,17 @@ std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, cons
|
||||||
const MatIndexArray::value_type base = mindices[ 0 ];
|
const MatIndexArray::value_type base = mindices[ 0 ];
|
||||||
for( MatIndexArray::value_type index : mindices ) {
|
for( MatIndexArray::value_type index : mindices ) {
|
||||||
if ( index != base ) {
|
if ( index != base ) {
|
||||||
return ConvertMeshMultiMaterial( mesh, model, node_global_transform );
|
return ConvertMeshMultiMaterial( mesh, model, node_global_transform, nd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// faster code-path, just copy the data
|
// faster code-path, just copy the data
|
||||||
temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform ) );
|
temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform, nd) );
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
|
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
|
||||||
{
|
{
|
||||||
aiMesh* const out_mesh = new aiMesh();
|
aiMesh* const out_mesh = new aiMesh();
|
||||||
meshes.push_back( out_mesh );
|
meshes.push_back( out_mesh );
|
||||||
|
@ -940,15 +940,19 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
|
||||||
if ( name.length() ) {
|
if ( name.length() ) {
|
||||||
out_mesh->mName.Set( name );
|
out_mesh->mName.Set( name );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_mesh->mName = nd.mName;
|
||||||
|
}
|
||||||
|
|
||||||
return out_mesh;
|
return out_mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
|
unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
|
||||||
const aiMatrix4x4& node_global_transform )
|
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||||
{
|
{
|
||||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||||
aiMesh* const out_mesh = SetupEmptyMesh( mesh );
|
aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
|
||||||
|
|
||||||
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
|
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
|
||||||
const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
|
const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
|
||||||
|
@ -1072,7 +1076,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
|
std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
|
||||||
const aiMatrix4x4& node_global_transform )
|
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||||
{
|
{
|
||||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||||
ai_assert( mindices.size() );
|
ai_assert( mindices.size() );
|
||||||
|
@ -1083,7 +1087,7 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
|
||||||
for( MatIndexArray::value_type index : mindices ) {
|
for( MatIndexArray::value_type index : mindices ) {
|
||||||
if ( had.find( index ) == had.end() ) {
|
if ( had.find( index ) == had.end() ) {
|
||||||
|
|
||||||
indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform ) );
|
indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform, nd) );
|
||||||
had.insert( index );
|
had.insert( index );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1093,9 +1097,10 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
|
||||||
|
|
||||||
unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
|
unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
|
||||||
MatIndexArray::value_type index,
|
MatIndexArray::value_type index,
|
||||||
const aiMatrix4x4& node_global_transform )
|
const aiMatrix4x4& node_global_transform,
|
||||||
|
aiNode& nd)
|
||||||
{
|
{
|
||||||
aiMesh* const out_mesh = SetupEmptyMesh( mesh );
|
aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
|
||||||
|
|
||||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||||
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
|
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
|
||||||
|
|
|
@ -172,23 +172,23 @@ private:
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
|
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
|
||||||
std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
|
std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
|
||||||
const aiMatrix4x4& node_global_transform);
|
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiMesh* SetupEmptyMesh(const MeshGeometry& mesh);
|
aiMesh* SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
|
unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
|
||||||
const aiMatrix4x4& node_global_transform);
|
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
||||||
const aiMatrix4x4& node_global_transform);
|
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
||||||
MatIndexArray::value_type index,
|
MatIndexArray::value_type index,
|
||||||
const aiMatrix4x4& node_global_transform);
|
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
|
static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
|
||||||
|
|
|
@ -114,14 +114,13 @@ static const std::string MaterialExt = ".mtl";
|
||||||
ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl)
|
ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl)
|
||||||
: filename(_filename)
|
: filename(_filename)
|
||||||
, pScene(pScene)
|
, pScene(pScene)
|
||||||
, vp()
|
|
||||||
, vn()
|
, vn()
|
||||||
, vt()
|
, vt()
|
||||||
, vc()
|
, vp()
|
||||||
, mVpMap()
|
, useVc(false)
|
||||||
, mVnMap()
|
, mVnMap()
|
||||||
, mVtMap()
|
, mVtMap()
|
||||||
, mVcMap()
|
, mVpMap()
|
||||||
, mMeshes()
|
, mMeshes()
|
||||||
, endl("\n") {
|
, endl("\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
|
||||||
|
@ -268,27 +267,22 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
|
||||||
AddNode(pScene->mRootNode, mBase);
|
AddNode(pScene->mRootNode, mBase);
|
||||||
|
|
||||||
// write vertex positions with colors, if any
|
// write vertex positions with colors, if any
|
||||||
mVpMap.getVectors( vp );
|
mVpMap.getKeys( vp );
|
||||||
mVcMap.getColors( vc );
|
if ( !useVc ) {
|
||||||
if ( vc.empty() ) {
|
|
||||||
mOutput << "# " << vp.size() << " vertex positions" << endl;
|
mOutput << "# " << vp.size() << " vertex positions" << endl;
|
||||||
for ( const aiVector3D& v : vp ) {
|
for ( const vertexData& v : vp ) {
|
||||||
mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
|
mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << endl;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mOutput << "# " << vp.size() << " vertex positions and colors" << endl;
|
mOutput << "# " << vp.size() << " vertex positions and colors" << endl;
|
||||||
size_t colIdx = 0;
|
for ( const vertexData& v : vp ) {
|
||||||
for ( const aiVector3D& v : vp ) {
|
mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << " " << v.vc.r << " " << v.vc.g << " " << v.vc.b << endl;
|
||||||
if ( colIdx < vc.size() ) {
|
|
||||||
mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl;
|
|
||||||
}
|
|
||||||
++colIdx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mOutput << endl;
|
mOutput << endl;
|
||||||
|
|
||||||
// write uv coordinates
|
// write uv coordinates
|
||||||
mVtMap.getVectors(vt);
|
mVtMap.getKeys(vt);
|
||||||
mOutput << "# " << vt.size() << " UV coordinates" << endl;
|
mOutput << "# " << vt.size() << " UV coordinates" << endl;
|
||||||
for(const aiVector3D& v : vt) {
|
for(const aiVector3D& v : vt) {
|
||||||
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
|
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
|
||||||
|
@ -296,7 +290,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
|
||||||
mOutput << endl;
|
mOutput << endl;
|
||||||
|
|
||||||
// write vertex normals
|
// write vertex normals
|
||||||
mVnMap.getVectors(vn);
|
mVnMap.getKeys(vn);
|
||||||
mOutput << "# " << vn.size() << " vertex normals" << endl;
|
mOutput << "# " << vn.size() << " vertex normals" << endl;
|
||||||
for(const aiVector3D& v : vn) {
|
for(const aiVector3D& v : vn) {
|
||||||
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
|
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
|
||||||
|
@ -337,54 +331,15 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) {
|
|
||||||
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
|
|
||||||
// vertex already exists, so reference it
|
|
||||||
if(vertIt != vecMap.end()){
|
|
||||||
return vertIt->second;
|
|
||||||
}
|
|
||||||
vecMap[vec] = mNextIndex;
|
|
||||||
int ret = mNextIndex;
|
|
||||||
mNextIndex++;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs ) {
|
|
||||||
vecs.resize(vecMap.size());
|
|
||||||
for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){
|
|
||||||
vecs[it->second-1] = it->first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
int ObjExporter::colIndexMap::getIndex( const aiColor4D& col ) {
|
|
||||||
colIndexMap::dataType::iterator vertIt = colMap.find( col );
|
|
||||||
// vertex already exists, so reference it
|
|
||||||
if ( vertIt != colMap.end() ) {
|
|
||||||
return vertIt->second;
|
|
||||||
}
|
|
||||||
colMap[ col ] = mNextIndex;
|
|
||||||
int ret = mNextIndex;
|
|
||||||
mNextIndex++;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
void ObjExporter::colIndexMap::getColors( std::vector<aiColor4D> &colors ) {
|
|
||||||
colors.resize( colMap.size() );
|
|
||||||
for ( colIndexMap::dataType::iterator it = colMap.begin(); it != colMap.end(); ++it ) {
|
|
||||||
colors[ it->second - 1 ] = it->first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
|
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
|
||||||
mMeshes.push_back(MeshInstance() );
|
mMeshes.push_back(MeshInstance() );
|
||||||
MeshInstance& mesh = mMeshes.back();
|
MeshInstance& mesh = mMeshes.back();
|
||||||
|
|
||||||
|
if ( nullptr != m->mColors[ 0 ] ) {
|
||||||
|
useVc = true;
|
||||||
|
}
|
||||||
|
|
||||||
mesh.name = std::string( name.data, name.length );
|
mesh.name = std::string( name.data, name.length );
|
||||||
mesh.matname = GetMaterialName(m->mMaterialIndex);
|
mesh.matname = GetMaterialName(m->mMaterialIndex);
|
||||||
|
|
||||||
|
@ -410,7 +365,13 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
|
||||||
const unsigned int idx = f.mIndices[a];
|
const unsigned int idx = f.mIndices[a];
|
||||||
|
|
||||||
aiVector3D vert = mat * m->mVertices[idx];
|
aiVector3D vert = mat * m->mVertices[idx];
|
||||||
face.indices[a].vp = mVpMap.getIndex(vert);
|
|
||||||
|
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)});
|
||||||
|
}
|
||||||
|
|
||||||
if (m->mNormals) {
|
if (m->mNormals) {
|
||||||
aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
|
aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
|
||||||
|
@ -419,13 +380,6 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
|
||||||
face.indices[a].vn = 0;
|
face.indices[a].vn = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( nullptr != m->mColors[ 0 ] ) {
|
|
||||||
aiColor4D col4 = m->mColors[ 0 ][ idx ];
|
|
||||||
face.indices[ a ].vc = mVcMap.getIndex( col4 );
|
|
||||||
} else {
|
|
||||||
face.indices[ a ].vc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( m->mTextureCoords[ 0 ] ) {
|
if ( m->mTextureCoords[ 0 ] ) {
|
||||||
face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]);
|
face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -77,13 +77,12 @@ private:
|
||||||
FaceVertex()
|
FaceVertex()
|
||||||
: vp()
|
: vp()
|
||||||
, vn()
|
, vn()
|
||||||
, vt()
|
, vt() {
|
||||||
, vc() {
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// one-based, 0 means: 'does not exist'
|
// one-based, 0 means: 'does not exist'
|
||||||
unsigned int vp, vn, vt, vc;
|
unsigned int vp, vn, vt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Face {
|
struct Face {
|
||||||
|
@ -106,66 +105,80 @@ private:
|
||||||
private:
|
private:
|
||||||
std::string filename;
|
std::string filename;
|
||||||
const aiScene* const pScene;
|
const aiScene* const pScene;
|
||||||
std::vector<aiVector3D> vp, vn, vt;
|
|
||||||
|
struct vertexData {
|
||||||
|
aiVector3D vp;
|
||||||
|
aiColor3D vc; // OBJ does not support 4D color
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<aiVector3D> vn, vt;
|
||||||
std::vector<aiColor4D> vc;
|
std::vector<aiColor4D> vc;
|
||||||
|
std::vector<vertexData> vp;
|
||||||
|
bool useVc;
|
||||||
|
|
||||||
struct aiVectorCompare {
|
struct vertexDataCompare {
|
||||||
bool operator() (const aiVector3D& a, const aiVector3D& b) const {
|
bool operator() ( const vertexData& a, const vertexData& b ) const {
|
||||||
if(a.x < b.x) return true;
|
// position
|
||||||
if(a.x > b.x) return false;
|
if (a.vp.x < b.vp.x) return true;
|
||||||
if(a.y < b.y) return true;
|
if (a.vp.x > b.vp.x) return false;
|
||||||
if(a.y > b.y) return false;
|
if (a.vp.y < b.vp.y) return true;
|
||||||
if(a.z < b.z) return true;
|
if (a.vp.y > b.vp.y) return false;
|
||||||
|
if (a.vp.z < b.vp.z) return true;
|
||||||
|
if (a.vp.z > b.vp.z) return false;
|
||||||
|
|
||||||
|
// color
|
||||||
|
if (a.vc.r < b.vc.r) return true;
|
||||||
|
if (a.vc.r > b.vc.r) return false;
|
||||||
|
if (a.vc.g < b.vc.g) return true;
|
||||||
|
if (a.vc.g > b.vc.g) return false;
|
||||||
|
if (a.vc.b < b.vc.b) return true;
|
||||||
|
if (a.vc.b > b.vc.b) return false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct aiColor4Compare {
|
struct aiVectorCompare {
|
||||||
bool operator() ( const aiColor4D& a, const aiColor4D& b ) const {
|
bool operator() (const aiVector3D& a, const aiVector3D& b) const {
|
||||||
if ( a.r < b.r ) return true;
|
if(a.x < b.x) return true;
|
||||||
if ( a.r > b.r ) return false;
|
if(a.x > b.x) return false;
|
||||||
if ( a.g < b.g ) return true;
|
if(a.y < b.y) return true;
|
||||||
if ( a.g > b.g ) return false;
|
if(a.y > b.y) return false;
|
||||||
if ( a.b < b.b ) return true;
|
if(a.z < b.z) return true;
|
||||||
if ( a.b > b.b ) return false;
|
|
||||||
if ( a.a < b.a ) return true;
|
|
||||||
if ( a.a > b.a ) return false;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class vecIndexMap {
|
template <class T, class Compare = std::less<T>>
|
||||||
|
class indexMap {
|
||||||
int mNextIndex;
|
int mNextIndex;
|
||||||
typedef std::map<aiVector3D, int, aiVectorCompare> dataType;
|
typedef std::map<T, int, Compare> dataType;
|
||||||
dataType vecMap;
|
dataType vecMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
vecIndexMap()
|
indexMap()
|
||||||
: mNextIndex(1) {
|
: mNextIndex(1) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
int getIndex(const aiVector3D& vec);
|
int getIndex(const T& key) {
|
||||||
void getVectors( std::vector<aiVector3D>& vecs );
|
typename dataType::iterator vertIt = vecMap.find(key);
|
||||||
|
// vertex already exists, so reference it
|
||||||
|
if(vertIt != vecMap.end()){
|
||||||
|
return vertIt->second;
|
||||||
|
}
|
||||||
|
return vecMap[key] = mNextIndex++;
|
||||||
|
};
|
||||||
|
|
||||||
|
void getKeys( std::vector<T>& keys ) {
|
||||||
|
keys.resize(vecMap.size());
|
||||||
|
for(typename dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){
|
||||||
|
keys[it->second-1] = it->first;
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class colIndexMap {
|
indexMap<aiVector3D, aiVectorCompare> mVnMap, mVtMap;
|
||||||
int mNextIndex;
|
indexMap<vertexData, vertexDataCompare> mVpMap;
|
||||||
typedef std::map<aiColor4D, int, aiColor4Compare> dataType;
|
|
||||||
dataType colMap;
|
|
||||||
|
|
||||||
public:
|
|
||||||
colIndexMap()
|
|
||||||
: mNextIndex( 1 ) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
int getIndex( const aiColor4D& col );
|
|
||||||
void getColors( std::vector<aiColor4D> &colors );
|
|
||||||
};
|
|
||||||
|
|
||||||
vecIndexMap mVpMap, mVnMap, mVtMap;
|
|
||||||
colIndexMap mVcMap;
|
|
||||||
std::vector<MeshInstance> mMeshes;
|
std::vector<MeshInstance> mMeshes;
|
||||||
|
|
||||||
// this endl() doesn't flush() the stream
|
// this endl() doesn't flush() the stream
|
||||||
|
|
|
@ -60,14 +60,17 @@ using namespace Assimp;
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
PretransformVertices::PretransformVertices()
|
PretransformVertices::PretransformVertices()
|
||||||
: configKeepHierarchy (false), configNormalize(false), configTransform(false), configTransformation()
|
: configKeepHierarchy (false)
|
||||||
{
|
, configNormalize(false)
|
||||||
|
, configTransform(false)
|
||||||
|
, configTransformation()
|
||||||
|
, mConfigPointCloud( false ) {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Destructor, private as well
|
// Destructor, private as well
|
||||||
PretransformVertices::~PretransformVertices()
|
PretransformVertices::~PretransformVertices() {
|
||||||
{
|
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +92,8 @@ void PretransformVertices::SetupProperties(const Importer* pImp)
|
||||||
configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0));
|
configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0));
|
||||||
|
|
||||||
configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4());
|
configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4());
|
||||||
|
|
||||||
|
mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -502,9 +507,7 @@ void PretransformVertices::Execute( aiScene* pScene)
|
||||||
pScene->mMeshes[i]->mBones = NULL;
|
pScene->mMeshes[i]->mBones = NULL;
|
||||||
pScene->mMeshes[i]->mNumBones = 0;
|
pScene->mMeshes[i]->mNumBones = 0;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
|
|
||||||
apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
|
apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
|
||||||
std::list<unsigned int> aiVFormats;
|
std::list<unsigned int> aiVFormats;
|
||||||
|
|
||||||
|
@ -556,7 +559,8 @@ void PretransformVertices::Execute( aiScene* pScene)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no meshes are referenced in the node graph it is possible that we get no output meshes.
|
// If no meshes are referenced in the node graph it is possible that we get no output meshes.
|
||||||
if (apcOutMeshes.empty()) {
|
if (apcOutMeshes.empty()) {
|
||||||
|
|
||||||
throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes");
|
throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -61,15 +61,11 @@ namespace Assimp {
|
||||||
* and removes the whole graph. The output is a list of meshes, one for
|
* and removes the whole graph. The output is a list of meshes, one for
|
||||||
* each material.
|
* each material.
|
||||||
*/
|
*/
|
||||||
class ASSIMP_API PretransformVertices : public BaseProcess
|
class ASSIMP_API PretransformVertices : public BaseProcess {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PretransformVertices ();
|
PretransformVertices ();
|
||||||
~PretransformVertices ();
|
~PretransformVertices ();
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Check whether step is active
|
// Check whether step is active
|
||||||
bool IsActive( unsigned int pFlags) const;
|
bool IsActive( unsigned int pFlags) const;
|
||||||
|
@ -82,7 +78,6 @@ public:
|
||||||
// Setup import settings
|
// Setup import settings
|
||||||
void SetupProperties(const Importer* pImp);
|
void SetupProperties(const Importer* pImp);
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** @brief Toggle the 'keep hierarchy' option
|
/** @brief Toggle the 'keep hierarchy' option
|
||||||
* @param d hm ... difficult to guess what this means, hu!?
|
* @param d hm ... difficult to guess what this means, hu!?
|
||||||
|
@ -100,7 +95,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Count the number of nodes
|
// Count the number of nodes
|
||||||
unsigned int CountNodes( aiNode* pcNode );
|
unsigned int CountNodes( aiNode* pcNode );
|
||||||
|
@ -161,6 +155,7 @@ private:
|
||||||
bool configNormalize;
|
bool configNormalize;
|
||||||
bool configTransform;
|
bool configTransform;
|
||||||
aiMatrix4x4 configTransformation;
|
aiMatrix4x4 configTransformation;
|
||||||
|
bool mConfigPointCloud;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/mesh.h>
|
#include <assimp/mesh.h>
|
||||||
|
|
||||||
class RemoveRedundantMatsTest;
|
class RemoveRedundantMatsTest;
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -54,14 +54,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/ByteSwapper.h>
|
#include <assimp/ByteSwapper.h>
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp
|
// Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp
|
||||||
void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
|
void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties )
|
||||||
{
|
{
|
||||||
|
bool exportPointClouds = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
|
||||||
|
|
||||||
// invoke the exporter
|
// invoke the exporter
|
||||||
STLExporter exporter(pFile, pScene);
|
STLExporter exporter(pFile, pScene, exportPointClouds );
|
||||||
|
|
||||||
if (exporter.mOutput.fail()) {
|
if (exporter.mOutput.fail()) {
|
||||||
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
|
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
|
||||||
|
@ -75,10 +78,12 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
|
void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties )
|
||||||
{
|
{
|
||||||
|
bool exportPointClouds = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
|
||||||
|
|
||||||
// invoke the exporter
|
// invoke the exporter
|
||||||
STLExporter exporter(pFile, pScene, true);
|
STLExporter exporter(pFile, pScene, exportPointClouds, true);
|
||||||
|
|
||||||
if (exporter.mOutput.fail()) {
|
if (exporter.mOutput.fail()) {
|
||||||
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
|
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
|
||||||
|
@ -95,9 +100,11 @@ void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene*
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
||||||
|
static const char *SolidToken = "solid";
|
||||||
|
static const char *EndSolidToken = "endsolid";
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
STLExporter :: STLExporter(const char* _filename, const aiScene* pScene, bool binary)
|
STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool exportPointClouds, bool binary)
|
||||||
: filename(_filename)
|
: filename(_filename)
|
||||||
, endl("\n")
|
, endl("\n")
|
||||||
{
|
{
|
||||||
|
@ -118,22 +125,55 @@ STLExporter :: STLExporter(const char* _filename, const aiScene* pScene, bool bi
|
||||||
}
|
}
|
||||||
AI_SWAP4(meshnum);
|
AI_SWAP4(meshnum);
|
||||||
mOutput.write((char *)&meshnum, 4);
|
mOutput.write((char *)&meshnum, 4);
|
||||||
|
|
||||||
|
if (exportPointClouds) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||||
WriteMeshBinary(pScene->mMeshes[i]);
|
WriteMeshBinary(pScene->mMeshes[i]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const std::string& name = "AssimpScene";
|
|
||||||
|
|
||||||
mOutput << "solid " << name << endl;
|
// Exporting only point clouds
|
||||||
|
if (exportPointClouds) {
|
||||||
|
WritePointCloud("Assimp_Pointcloud", pScene );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export the assimp mesh
|
||||||
|
const std::string name = "AssimpScene";
|
||||||
|
mOutput << SolidToken << " " << name << endl;
|
||||||
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||||
WriteMesh(pScene->mMeshes[i]);
|
WriteMesh(pScene->mMeshes[ i ]);
|
||||||
}
|
}
|
||||||
mOutput << "endsolid " << name << endl;
|
mOutput << EndSolidToken << name << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void STLExporter :: WriteMesh(const aiMesh* m)
|
void STLExporter::WritePointCloud(const std::string &name, const aiScene* pScene) {
|
||||||
|
mOutput << " " << SolidToken << " " << name << endl;
|
||||||
|
aiVector3D nor;
|
||||||
|
mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl;
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||||
|
aiMesh *mesh = pScene->mMeshes[i];
|
||||||
|
if (nullptr == mesh) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
|
||||||
|
const aiVector3D& v = mesh->mVertices[a];
|
||||||
|
mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl;
|
||||||
|
mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl;
|
||||||
|
mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mOutput << EndSolidToken << " " << name << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void STLExporter::WriteMesh(const aiMesh* m)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
|
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
|
||||||
const aiFace& f = m->mFaces[i];
|
const aiFace& f = m->mFaces[i];
|
||||||
|
@ -145,7 +185,7 @@ void STLExporter :: WriteMesh(const aiMesh* m)
|
||||||
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
|
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
|
||||||
nor += m->mNormals[f.mIndices[a]];
|
nor += m->mNormals[f.mIndices[a]];
|
||||||
}
|
}
|
||||||
nor.Normalize();
|
nor.NormalizeSafe();
|
||||||
}
|
}
|
||||||
mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl;
|
mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl;
|
||||||
mOutput << " outer loop" << endl;
|
mOutput << " outer loop" << endl;
|
||||||
|
@ -159,7 +199,7 @@ void STLExporter :: WriteMesh(const aiMesh* m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void STLExporter :: WriteMeshBinary(const aiMesh* m)
|
void STLExporter::WriteMeshBinary(const aiMesh* m)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
|
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
|
||||||
const aiFace& f = m->mFaces[i];
|
const aiFace& f = m->mFaces[i];
|
||||||
|
|
|
@ -52,8 +52,7 @@ struct aiScene;
|
||||||
struct aiNode;
|
struct aiNode;
|
||||||
struct aiMesh;
|
struct aiMesh;
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp {
|
||||||
{
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
/** Helper class to export a given scene to a STL file. */
|
/** Helper class to export a given scene to a STL file. */
|
||||||
|
@ -62,15 +61,13 @@ class STLExporter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor for a specific scene to export
|
/// Constructor for a specific scene to export
|
||||||
STLExporter(const char* filename, const aiScene* pScene, bool binary = false);
|
STLExporter(const char* filename, const aiScene* pScene, bool exportPOintClouds, bool binary = false);
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// public stringstreams to write all output into
|
/// public stringstreams to write all output into
|
||||||
std::ostringstream mOutput;
|
std::ostringstream mOutput;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void WritePointCloud(const std::string &name, const aiScene* pScene);
|
||||||
void WriteMesh(const aiMesh* m);
|
void WriteMesh(const aiMesh* m);
|
||||||
void WriteMeshBinary(const aiMesh* m);
|
void WriteMeshBinary(const aiMesh* m);
|
||||||
|
|
||||||
|
|
|
@ -75,4 +75,5 @@ bool CPUSupportsSSE2() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // Namespace Assimp
|
} // Namespace Assimp
|
||||||
|
|
|
@ -115,12 +115,16 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
public:
|
* @brief The class constructor.
|
||||||
|
*/
|
||||||
Exporter();
|
Exporter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The class destructor.
|
||||||
|
*/
|
||||||
~Exporter();
|
~Exporter();
|
||||||
|
|
||||||
public:
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Supplies a custom IO handler to the exporter to use to open and
|
/** Supplies a custom IO handler to the exporter to use to open and
|
||||||
* access files.
|
* access files.
|
||||||
|
@ -172,8 +176,10 @@ public:
|
||||||
* Any IO handlers set via #SetIOHandler are ignored here.
|
* Any IO handlers set via #SetIOHandler are ignored here.
|
||||||
* @note Use aiCopyScene() to get a modifiable copy of a previously
|
* @note Use aiCopyScene() to get a modifiable copy of a previously
|
||||||
* imported scene. */
|
* imported scene. */
|
||||||
const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* = NULL);
|
const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId,
|
||||||
const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
|
unsigned int pPreprocessing = 0u, const ExportProperties* = nullptr);
|
||||||
|
const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId,
|
||||||
|
unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Convenience function to export directly to a file. Use
|
/** Convenience function to export directly to a file. Use
|
||||||
|
@ -208,8 +214,10 @@ public:
|
||||||
* @return AI_SUCCESS if everything was fine.
|
* @return AI_SUCCESS if everything was fine.
|
||||||
* @note Use aiCopyScene() to get a modifiable copy of a previously
|
* @note Use aiCopyScene() to get a modifiable copy of a previously
|
||||||
* imported scene.*/
|
* imported scene.*/
|
||||||
aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
|
aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
|
||||||
aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
|
unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr);
|
||||||
|
aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath,
|
||||||
|
unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Returns an error description of an error that occurred in #Export
|
/** Returns an error description of an error that occurred in #Export
|
||||||
|
|
|
@ -46,15 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/Importer.hpp>
|
#include <assimp/Importer.hpp>
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
#include "Hash.h"
|
#include "Hash.h"
|
||||||
#include <map>
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
template <class T>
|
template <class T>
|
||||||
inline bool SetGenericProperty(std::map< unsigned int, T >& list,
|
inline
|
||||||
const char* szName, const T& value)
|
bool SetGenericProperty(std::map< unsigned int, T >& list,
|
||||||
{
|
const char* szName, const T& value) {
|
||||||
ai_assert(NULL != szName);
|
ai_assert(nullptr != szName);
|
||||||
const uint32_t hash = SuperFastHash(szName);
|
const uint32_t hash = SuperFastHash(szName);
|
||||||
|
|
||||||
typename std::map<unsigned int, T>::iterator it = list.find(hash);
|
typename std::map<unsigned int, T>::iterator it = list.find(hash);
|
||||||
|
@ -63,20 +63,22 @@ inline bool SetGenericProperty(std::map< unsigned int, T >& list,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
(*it).second = value;
|
(*it).second = value;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
template <class T>
|
template <class T>
|
||||||
inline const T& GetGenericProperty(const std::map< unsigned int, T >& list,
|
inline
|
||||||
const char* szName, const T& errorReturn)
|
const T& GetGenericProperty(const std::map< unsigned int, T >& list,
|
||||||
{
|
const char* szName, const T& errorReturn) {
|
||||||
ai_assert(NULL != szName);
|
ai_assert(nullptr != szName);
|
||||||
const uint32_t hash = SuperFastHash(szName);
|
const uint32_t hash = SuperFastHash(szName);
|
||||||
|
|
||||||
typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
|
typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
|
||||||
if (it == list.end())
|
if (it == list.end()) {
|
||||||
return errorReturn;
|
return errorReturn;
|
||||||
|
}
|
||||||
|
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
}
|
}
|
||||||
|
@ -85,16 +87,17 @@ inline const T& GetGenericProperty(const std::map< unsigned int, T >& list,
|
||||||
// Special version for pointer types - they will be deleted when replaced with another value
|
// Special version for pointer types - they will be deleted when replaced with another value
|
||||||
// passing NULL removes the whole property
|
// passing NULL removes the whole property
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
|
inline
|
||||||
const char* szName, T* value, bool* bWasExisting = NULL)
|
void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
|
||||||
{
|
const char* szName, T* value, bool* bWasExisting = nullptr ) {
|
||||||
ai_assert(NULL != szName);
|
ai_assert(nullptr != szName);
|
||||||
const uint32_t hash = SuperFastHash(szName);
|
const uint32_t hash = SuperFastHash(szName);
|
||||||
|
|
||||||
typename std::map<unsigned int, T*>::iterator it = list.find(hash);
|
typename std::map<unsigned int, T*>::iterator it = list.find(hash);
|
||||||
if (it == list.end()) {
|
if (it == list.end()) {
|
||||||
if (bWasExisting)
|
if (bWasExisting) {
|
||||||
*bWasExisting = false;
|
*bWasExisting = false;
|
||||||
|
}
|
||||||
|
|
||||||
list.insert(std::pair<unsigned int,T*>( hash, value ));
|
list.insert(std::pair<unsigned int,T*>( hash, value ));
|
||||||
return;
|
return;
|
||||||
|
@ -106,20 +109,23 @@ inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
|
||||||
if (!value) {
|
if (!value) {
|
||||||
list.erase(it);
|
list.erase(it);
|
||||||
}
|
}
|
||||||
if (bWasExisting)
|
if (bWasExisting) {
|
||||||
*bWasExisting = true;
|
*bWasExisting = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
template <class T>
|
template <class T>
|
||||||
inline bool HasGenericProperty(const std::map< unsigned int, T >& list,
|
inline
|
||||||
const char* szName)
|
bool HasGenericProperty(const std::map< unsigned int, T >& list,
|
||||||
{
|
const char* szName) {
|
||||||
ai_assert(NULL != szName);
|
ai_assert(nullptr != szName);
|
||||||
const uint32_t hash = SuperFastHash(szName);
|
const uint32_t hash = SuperFastHash(szName);
|
||||||
|
|
||||||
typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
|
typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
|
||||||
if (it == list.end()) return false;
|
if (it == list.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,6 @@ struct aiExportFormatDesc
|
||||||
*/
|
*/
|
||||||
ASSIMP_API size_t aiGetExportFormatCount(void);
|
ASSIMP_API size_t aiGetExportFormatCount(void);
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
/** Returns a description of the nth export file format. Use #aiGetExportFormatCount()
|
/** Returns a description of the nth export file format. Use #aiGetExportFormatCount()
|
||||||
* to learn how many export formats are supported. The description must be released by
|
* to learn how many export formats are supported. The description must be released by
|
||||||
|
@ -186,7 +185,6 @@ ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene,
|
||||||
C_STRUCT aiFileIO* pIO,
|
C_STRUCT aiFileIO* pIO,
|
||||||
unsigned int pPreprocessing );
|
unsigned int pPreprocessing );
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
/** Describes a blob of exported scene data. Use #aiExportSceneToBlob() to create a blob containing an
|
/** Describes a blob of exported scene data. Use #aiExportSceneToBlob() to create a blob containing an
|
||||||
* exported scene. The memory referred by this structure is owned by Assimp.
|
* exported scene. The memory referred by this structure is owned by Assimp.
|
||||||
|
@ -245,8 +243,8 @@ private:
|
||||||
* @param pPreprocessing Please see the documentation for #aiExportScene
|
* @param pPreprocessing Please see the documentation for #aiExportScene
|
||||||
* @return the exported data or NULL in case of error
|
* @return the exported data or NULL in case of error
|
||||||
*/
|
*/
|
||||||
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const C_STRUCT aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing );
|
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const C_STRUCT aiScene* pScene, const char* pFormatId,
|
||||||
|
unsigned int pPreprocessing );
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
/** Releases the memory associated with the given exported data. Use this function to free a data blob
|
/** Releases the memory associated with the given exported data. Use this function to free a data blob
|
||||||
|
|
|
@ -953,6 +953,11 @@ enum aiComponent
|
||||||
|
|
||||||
#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
|
#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Specifies a gobal key factor for scale, float value
|
* @brief Specifies a gobal key factor for scale, float value
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
g cube
|
g cube
|
||||||
|
|
||||||
v 0.0 0.0 0.0 124 110 120
|
v 0.0 0.0 0.0 0.48627 0.43137 0.47059
|
||||||
v 0.0 0.0 1.0 24 0 121
|
v 0.0 0.0 1.0 0.09412 0.00000 0.47451
|
||||||
v 0.0 1.0 0.0 4 0 44
|
v 0.0 1.0 0.0 0.01569 0.00000 0.17255
|
||||||
v 0.0 1.0 1.0 224 0 10
|
v 0.0 1.0 1.0 0.87843 0.00000 0.03922
|
||||||
v 1.0 0.0 0.0 24 200 25
|
v 1.0 0.0 0.0 0.09412 0.78431 0.09804
|
||||||
v 1.0 0.0 1.0 124 10 56
|
v 1.0 0.0 1.0 0.48627 0.03922 0.21961
|
||||||
v 1.0 1.0 0.0 78 10 50
|
v 1.0 1.0 0.0 0.30588 0.03922 0.19608
|
||||||
v 1.0 1.0 1.0 23 0 200
|
v 1.0 1.0 1.0 0.09020 0.00000 0.78431
|
||||||
|
|
||||||
vn 0.0 0.0 1.0
|
vn 0.0 0.0 1.0
|
||||||
vn 0.0 0.0 -1.0
|
vn 0.0 0.0 -1.0
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
g cube
|
||||||
|
|
||||||
|
v 0.0 0.0 0.0 0.0 0.0 0.0
|
||||||
|
v 0.0 0.0 1.0 1.0 0.6 0.3
|
||||||
|
v 0.0 1.0 0.0 0.0 0.0 0.0
|
||||||
|
v 0.0 1.0 1.0 0.3 0.6 1.0
|
||||||
|
v 1.0 0.0 0.0 0.0 0.0 0.0
|
||||||
|
v 1.0 0.0 1.0 1.0 0.6 0.3
|
||||||
|
v 1.0 1.0 0.0 0.0 0.0 0.0
|
||||||
|
v 1.0 1.0 1.0 0.3 0.6 1.0
|
||||||
|
|
||||||
|
vn 0.0 0.0 1.0
|
||||||
|
vn 0.0 0.0 -1.0
|
||||||
|
vn 0.0 1.0 0.0
|
||||||
|
vn 0.0 -1.0 0.0
|
||||||
|
vn 1.0 0.0 0.0
|
||||||
|
vn -1.0 0.0 0.0
|
||||||
|
|
||||||
|
f 1//2 7//2 5//2
|
||||||
|
f 1//2 3//2 7//2
|
||||||
|
f 1//6 4//6 3//6
|
||||||
|
f 1//6 2//6 4//6
|
||||||
|
f 3//3 8//3 7//3
|
||||||
|
f 3//3 4//3 8//3
|
||||||
|
f 5//5 7//5 8//5
|
||||||
|
f 5//5 8//5 6//5
|
||||||
|
f 1//4 5//4 6//4
|
||||||
|
f 1//4 6//4 2//4
|
||||||
|
f 2//1 6//1 8//1
|
||||||
|
f 2//1 8//1 4//1
|
|
@ -267,6 +267,28 @@ TEST_F( utObjImportExport, issue809_vertex_color_Test ) {
|
||||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F( utObjImportExport, issue1923_vertex_color_Test ) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_with_vertexcolors_uni.obj", aiProcess_ValidateDataStructure );
|
||||||
|
EXPECT_NE( nullptr, scene );
|
||||||
|
|
||||||
|
scene = importer.GetOrphanedScene();
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
|
::Assimp::Exporter exporter;
|
||||||
|
const aiExportDataBlob* blob = exporter.ExportToBlob( scene, "obj");
|
||||||
|
EXPECT_NE( nullptr, blob );
|
||||||
|
|
||||||
|
const aiScene *sceneReImport = importer.ReadFileFromMemory( blob->data, blob->size, aiProcess_ValidateDataStructure );
|
||||||
|
EXPECT_NE( nullptr, scene );
|
||||||
|
|
||||||
|
SceneDiffer differ;
|
||||||
|
EXPECT_TRUE( differ.isEqual( scene, sceneReImport ) );
|
||||||
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
||||||
|
delete scene;
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F( utObjImportExport, issue1453_segfault ) {
|
TEST_F( utObjImportExport, issue1453_segfault ) {
|
||||||
static const std::string ObjModel =
|
static const std::string ObjModel =
|
||||||
"v 0.0 0.0 0.0\n"
|
"v 0.0 0.0 0.0\n"
|
||||||
|
|
|
@ -138,18 +138,19 @@ TEST_F( utPLYImportExport, vertexColorTest ) {
|
||||||
EXPECT_EQ(2u, first_face.mIndices[2]);
|
EXPECT_EQ(2u, first_face.mIndices[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test issue #623, PLY importer should not automatically create faces
|
// Test issue #623, PLY importer should not automatically create faces
|
||||||
TEST_F(utPLYImportExport, pointcloudTest) {
|
TEST_F(utPLYImportExport, pointcloudTest) {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
//Could not use aiProcess_ValidateDataStructure since it's missing faces.
|
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0);
|
|
||||||
EXPECT_NE(nullptr, scene);
|
|
||||||
|
|
||||||
EXPECT_EQ(1u, scene->mNumMeshes);
|
//Could not use aiProcess_ValidateDataStructure since it's missing faces.
|
||||||
EXPECT_NE(nullptr, scene->mMeshes[0]);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0);
|
||||||
EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes);
|
|
||||||
EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces);
|
EXPECT_EQ(1u, scene->mNumMeshes);
|
||||||
|
EXPECT_NE(nullptr, scene->mMeshes[0]);
|
||||||
|
EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices);
|
||||||
|
EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes);
|
||||||
|
EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *test_file =
|
static const char *test_file =
|
||||||
|
|
|
@ -47,6 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <assimp/Importer.hpp>
|
#include <assimp/Importer.hpp>
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
|
#include <assimp/Exporter.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
|
@ -68,3 +72,73 @@ TEST_F( utSTLImporterExporter, test_with_two_solids ) {
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", aiProcess_ValidateDataStructure );
|
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", aiProcess_ValidateDataStructure );
|
||||||
EXPECT_NE( nullptr, scene );
|
EXPECT_NE( nullptr, scene );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
||||||
|
TEST_F(utSTLImporterExporter, exporterTest) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
Assimp::Exporter mAiExporter;
|
||||||
|
mAiExporter.Export( scene, "stl", "spiderExport.stl" );
|
||||||
|
|
||||||
|
const aiScene *scene2 = importer.ReadFile("spiderExport.stl", aiProcess_ValidateDataStructure);
|
||||||
|
EXPECT_NE(nullptr, scene2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(utSTLImporterExporter, test_export_pointclouds) {
|
||||||
|
struct XYZ {
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<XYZ> points;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 10; ++i) {
|
||||||
|
XYZ current;
|
||||||
|
current.x = static_cast<float>(i);
|
||||||
|
current.y = static_cast<float>(i);
|
||||||
|
current.z = static_cast<float>(i);
|
||||||
|
points.push_back(current);
|
||||||
|
}
|
||||||
|
aiScene scene;
|
||||||
|
scene.mRootNode = new aiNode();
|
||||||
|
|
||||||
|
scene.mMeshes = new aiMesh*[1];
|
||||||
|
scene.mMeshes[0] = nullptr;
|
||||||
|
scene.mNumMeshes = 1;
|
||||||
|
|
||||||
|
scene.mMaterials = new aiMaterial*[1];
|
||||||
|
scene.mMaterials[0] = nullptr;
|
||||||
|
scene.mNumMaterials = 1;
|
||||||
|
|
||||||
|
scene.mMaterials[0] = new aiMaterial();
|
||||||
|
|
||||||
|
scene.mMeshes[0] = new aiMesh();
|
||||||
|
scene.mMeshes[0]->mMaterialIndex = 0;
|
||||||
|
|
||||||
|
scene.mRootNode->mMeshes = new unsigned int[1];
|
||||||
|
scene.mRootNode->mMeshes[0] = 0;
|
||||||
|
scene.mRootNode->mNumMeshes = 1;
|
||||||
|
|
||||||
|
auto pMesh = scene.mMeshes[0];
|
||||||
|
|
||||||
|
long numValidPoints = points.size();
|
||||||
|
|
||||||
|
pMesh->mVertices = new aiVector3D[numValidPoints];
|
||||||
|
pMesh->mNumVertices = numValidPoints;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (XYZ &p : points) {
|
||||||
|
pMesh->mVertices[i] = aiVector3D(p.x, p.y, p.z);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assimp::Exporter mAiExporter;
|
||||||
|
ExportProperties *properties = new ExportProperties;
|
||||||
|
properties->SetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS, true);
|
||||||
|
mAiExporter.Export(&scene, "stl", "testExport.stl", 0, properties );
|
||||||
|
|
||||||
|
delete properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue