43#include <ACG/GL/GLState.hh>
48#include <OpenMesh/Core/IO/IOManager.hh>
50#include <OpenFlipper/Utils/Memory/RAMInfo.hh>
56#include <ACG/Utils/SmartPointer.hh>
60#define TYPEAUTODETECT 0
70void remove_duplicated_vertices(VHandles& _indices)
72 VHandles::iterator endIter = _indices.end();
73 for (VHandles::iterator iter = _indices.begin(); iter != endIter; ++iter)
74 endIter = std::remove(iter+1, endIter, *(iter));
76 _indices.erase(endIter,_indices.end());
89 saveFaceColorOverride_(0),
95 saveCreateTexFolder_(0),
96 savePrecisionLabel_(0),
98 saveDefaultButton_(0),
106 loadDefaultButton_(0),
107 forceTriangleMesh_(false),
108 forcePolyMesh_(false),
109 textureIndexPropFetched_(false),
122 return QString( tr(
"Alias/Wavefront ( *.obj )") );
128 return QString( tr(
"Alias/Wavefront ( *.obj )") );
136 #ifdef ENABLE_BSPLINECURVE_SUPPORT
140 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
149bool FileOBJPlugin::readMaterial(QString _filename,
OBJImporter& _importer)
167 bool insideDefintion;
168 insideDefintion =
false;
174 QFile matFile(_filename);
175 if (!matFile.open(QFile::ReadOnly))
177 emit log(
LOGERR, tr(
"readMaterial : cannot open file %1").arg(_filename));
181 QTextStream matStream(&matFile);
182 if ( matStream.status()!=QTextStream::Ok ){
183 emit log(
LOGERR, tr(
"readMaterial : cannot open stream %1").arg(_filename) );
191 while( matStream.status() == QTextStream::Ok && !matStream.atEnd() )
193 line = matStream.readLine();
194 if ( matStream.status() != QTextStream::Ok ){
195 emit log(
LOGERR, tr(
"readMaterial : Warning! Could not read file properly!"));
199 if ( line.isEmpty() )
202 QTextStream stream(&line);
206 if( ( line[0].isSpace() && line[0] != QLatin1Char(
'\t') ) || line[0] == QLatin1Char(
'#') )
208 if (insideDefintion && !matName.isEmpty() && mat.is_valid())
210 _importer.
materials()[matName.toStdString()] = mat;
215 else if (keyWrd == QLatin1String(
"newmtl"))
218 insideDefintion =
true;
221 else if (keyWrd == QLatin1String(
"Kd"))
223 f1 = getFloat(stream);
224 f2 = getFloat(stream);
225 f3 = getFloat(stream);
227 if( stream.status()==QTextStream::Ok )
228 mat.set_Kd(f1,f2,f3);
231 else if (keyWrd == QLatin1String(
"Ka"))
233 f1 = getFloat(stream);
234 f2 = getFloat(stream);
235 f3 = getFloat(stream);
237 if( stream.status()==QTextStream::Ok )
238 mat.set_Ka(f1,f2,f3);
241 else if (keyWrd == QLatin1String(
"Ks"))
243 f1 = getFloat(stream);
244 f2 = getFloat(stream);
245 f3 = getFloat(stream);
247 if( stream.status()==QTextStream::Ok )
248 mat.set_Ks(f1,f2,f3);
251 else if (keyWrd == QLatin1String(
"Ke"))
253 f1 = getFloat(stream);
254 f2 = getFloat(stream);
255 f3 = getFloat(stream);
257 if( stream.status()==QTextStream::Ok )
258 mat.set_Ke(f1,f2,f3);
262 else if (keyWrd == QLatin1String(
"illum"))
266 if(stream.status() == QTextStream::Ok)
270 else if (keyWrd == QLatin1String(
"Ns"))
272 f1 = getFloat(stream);
274 if(stream.status() == QTextStream::Ok)
278 else if (keyWrd == QLatin1String(
"Ni"))
280 f1 = getFloat(stream);
282 if(stream.status() == QTextStream::Ok)
286 else if (keyWrd == QLatin1String(
"Tr"))
288 f1 = getFloat(stream);
290 if(stream.status() == QTextStream::Ok)
294 else if (keyWrd == QLatin1String(
"d"))
297 f1 = getFloat(stream);
299 if(stream.status() == QTextStream::Ok && !mat.has_Tr())
303 else if (keyWrd == QLatin1String(
"map_"))
312 else if (keyWrd == QLatin1String(
"map_Kd") ) {
315 textureName = stream.readLine();
316 textureName = textureName.trimmed();
317 if ( ! textureName.isEmpty() )
318 mat.set_map_Kd( textureName.toStdString(), textureId++ );
321 if ( matStream.status() == QTextStream::Ok && insideDefintion && mat.is_valid() && !matName.isEmpty())
322 _importer.
materials()[matName.toStdString()] = mat;
325 emit log( tr(
"%1 materials loaded.").arg( _importer.
materials().size() ) );
332void FileOBJPlugin::createAllGroupObjects(
OBJImporter& _importer) {
334 for(
unsigned int i = 0; i < _importer.numGroups(); ++i) {
337 QString
name = _importer.groupName(i);
340 if ( _importer.isTriangleMesh( i ) ){
352 object->setPath(_importer.
path());
353 object->setName(
name);
356 }
else if (_importer.isPolyMesh( i )) {
367 object->setPath(_importer.
path());
368 object->setName(
name);
372#ifdef ENABLE_BSPLINECURVE_SUPPORT
374 else if (_importer.isCurve( i )) {
385 object->setPath(_importer.
path());
386 object->setName(
name);
392#ifdef ENABLE_BSPLINESURFACE_SUPPORT
394 else if (_importer.isSurface( i )) {
405 object->setPath(_importer.
path());
406 object->setName(
name);
413 if (OpenFlipper::Options::gui() && loadOptions_ != 0) {
415 if (!loadFaceColor_->isChecked())
416 _importer.
setOption(OBJImporter::FORCE_NOCOLOR, i);
418 if (!loadNormals_->isChecked())
419 _importer.
setOption(OBJImporter::FORCE_NONORMALS, i);
421 if (!loadTexCoords_->isChecked() || !loadTextures_->isChecked())
422 _importer.
setOption(OBJImporter::FORCE_NOTEXTURES, i);
432 QString n = fi.baseName();
434 _name = n.trimmed() +
".obj";
438template <
class MeshT>
442 if (_mesh.has_vertex_texcoords2D()) {
445 if (!_mesh.get_property_handle(oldVertexCoords,
"Original Per Vertex Texture Coords"))
446 _mesh.add_property(oldVertexCoords,
"Original Per Vertex Texture Coords");
448 for (
auto v_it : _mesh.vertices())
449 _mesh.property(oldVertexCoords, v_it) = _mesh.texcoord2D(v_it);
454 if (_mesh.has_halfedge_texcoords2D()) {
457 if (!_mesh.get_property_handle(oldHalfedgeCoords,
"Original Per Face Texture Coords"))
458 _mesh.add_property(oldHalfedgeCoords,
"Original Per Face Texture Coords");
460 for (
auto he_it : _mesh.halfedges())
461 _mesh.property(oldHalfedgeCoords, he_it) = _mesh.texcoord2D(he_it);
468void FileOBJPlugin::addTextures(
OBJImporter& _importer,
int _objectID ){
478 std::map< int,int > newMapping;
482 const std::vector<std::string> matNames = _importer.
usedMaterials( _objectID );
484 for (
unsigned int i=0; i < matNames.size(); i++){
486 Material& material = _importer.
materials()[ matNames[i] ];
490 QString textureBlock = QString( material.map_Kd().c_str());
494#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
495 QStringList options = textureBlock.split(
" ",QString::SkipEmptyParts);
497 QStringList options = textureBlock.split(
" ",Qt::SkipEmptyParts);
500 while ( options.size() > 1 ) {
501 if ( options[0] ==
"-blendu" ) {
504 }
else if ( options[0] ==
"-blendv" ) {
507 }
else if ( options[0] ==
"-cc" ) {
510 }
else if ( options[0] ==
"-clamp" ) {
513 }
else if ( options[0] ==
"-mm" ) {
517 }
else if ( options[0] ==
"-o" ) {
522 }
else if ( options[0] ==
"-s" ) {
527 }
else if ( options[0] ==
"-t" ) {
532 }
else if ( options[0] ==
"-texres" ) {
540 QString fullName = _importer.
path() + QDir::separator() + options.join(
" ");
542 QFileInfo info(fullName);
543 if ( info.exists() ) {
544 emit addMultiTexture(
"OBJ Data", info.baseName().trimmed(), fullName, object->
id(), textureId );
546 emit log(
LOGWARN, tr(
"Unable to load texture image %1").arg( QString(material.map_Kd().c_str()) ) );
547 addMultiTexture(
"OBJ Data",
"Unknown Texture image " + QString::number(textureId),
"unknown.png", object->
id(), textureId );
550 newMapping[ material.map_Kd_index() ] = textureId;
564 if (! mesh.get_property_handle(indexProperty,TEXTUREINDEX) )
567 for (
auto f_it : mesh.faces())
568 mesh.property(indexProperty, f_it) = newMapping[ mesh.property(indexProperty, f_it) ];
582 if (! mesh.get_property_handle(indexProperty,TEXTUREINDEX) )
585 for (
auto f_it : mesh.faces())
586 mesh.property(indexProperty, f_it) = newMapping[ mesh.property(indexProperty, f_it) ];
595void FileOBJPlugin::readOBJFile(QByteArray& _bufferedFile, QString _filename,
OBJImporter& _importer)
597 QString path = QFileInfo(_filename).absolutePath();
598 ptr::shared_ptr<QTextStream> streamPointer;
599 ptr::shared_ptr<QFile> sourceFile;
602 if (_bufferedFile.isNull())
604 sourceFile.reset(
new QFile(_filename) );
605 if(!sourceFile->open(QFile::ReadOnly))
607 emit log(
LOGERR, tr(
"readOBJFile : cannot open file %1").arg(_filename) );
612 streamPointer.reset(
new QTextStream(sourceFile.get()));
616 streamPointer.reset(
new QTextStream(&_bufferedFile));
618 QTextStream input(streamPointer->device());
621 QTextStream lineData;
623 if ( input.status() != QTextStream::Ok){
624 emit log(
LOGERR, tr(
"readOBJFile : cannot read file %1 is the file corrupt?").arg(_filename) );
628 QString currentFileName = QFileInfo(_filename).fileName() ;
630 ReaderMode mode =
NONE;
634 QString nextKeyWrd = QLatin1String(
"");
636#ifdef ENABLE_BSPLINECURVE_SUPPORT
637 unsigned int curveCount = 0;
640#ifdef ENABLE_BSPLINESURFACE_SUPPORT
641 unsigned int surfaceCount = 0;
646 std::vector<VertexHandle> vhandles;
647 std::vector<int> face_texcoords;
649 QString lastMaterial;
651#if defined (ENABLE_BSPLINECURVE_SUPPORT) || defined (ENABLE_BSPLINESURFACE_SUPPORT)
652 std::vector< int > cpIndices;
653 std::vector< double > knotsU,knotsV;
659 int currentVertexCount = 0;
662 int currentTextureCoordCount = 0;
665 int currentNormalCount = 0;
668 bool inGroup =
false;
670 bool firstFace =
true;
672 _importer.setPath( path );
675 _importer.setGroupName(0, currentFileName);
678 createAllGroupObjects(_importer);
680 bool bSuppNoVertCoord =
false;
681 bool bSuppTooManyTexCoord =
false;
682 bool bSuppTooManyNormal =
false;
683 bool bSuppErrorSettingTexCoord =
false;
685 while( !input.atEnd() )
687 line=input.readLine();
688 if ( input.status() == QTextStream::ReadCorruptData ){
689 emit log(
LOGERR, tr(
"readOBJFile : Warning! Could not read file properly!"));
694 line = line.trimmed();
697 if ( line.isEmpty() || line[0] == QLatin1Char(
'#') || line[0].isSpace() ) {
701 stream.setString(&line,QIODevice::ReadOnly);
705 if (nextKeyWrd == QLatin1String(
""))
709 nextKeyWrd = QLatin1String(
"");
713 if (mode == NONE && keyWrd == QLatin1String(
"mtllib"))
718 matString = stream.readLine();
720 QString matFile = path + QDir::separator() + matString.trimmed();
722 emit log( tr(
"Loading material file: %1").arg( matFile ) );
724 readMaterial( matFile, _importer );
728 else if (mode == NONE && keyWrd == QLatin1String(
"usemtl"))
733 emit log(
LOGERR, tr(
"Warning! Material '%1' not defined in material file").arg( matname ) );
734 matname=QLatin1String(
"");
738 Material& mat = _importer.
materials()[matname.toStdString()];
740 if ( mat.has_Texture() ){
743 _importer.useMaterial( matname.toStdString() );
747 lastMaterial = matname;
750 else if (mode == NONE && keyWrd == QLatin1String(
"v"))
755 currentVertexCount++;
758 else if (mode == NONE && keyWrd == QLatin1String(
"vt"))
764 currentTextureCoordCount++;
766 auto u = getFloat(stream);
767 auto v = getFloat(stream);
769 if ( stream.status() == QTextStream::Ok ){
775 emit log(
LOGERR, tr(
"Could not add TexCoord. Possible NaN or Inf?\nOnly single 2D texture coordinate per vertex allowed"));
781 else if (mode == NONE && keyWrd == QLatin1String(
"vn"))
787 currentNormalCount++;
789 auto x = getDouble(stream);
790 auto y = getDouble(stream);
791 auto z = getDouble(stream);
793 if ( stream.status() == QTextStream::Ok ){
796 emit log(
LOGERR, tr(
"Could not read normal. Possible NaN or Inf?"));
801 else if (mode == NONE && keyWrd == QLatin1String(
"deg"))
805 if ( stream.status() == QTextStream::Ok )
810 if ( stream.status() == QTextStream::Ok )
815 else if (mode == NONE && keyWrd == QLatin1String(
"g")){
820 groupName = stream.readLine();
823 currentFileName = groupName;
826 int id = _importer.groupId(groupName);
828 std::cerr <<
"Error: Group has not been added before!" << std::endl;
831 _importer.setCurrentGroup(
id);
836 if (lastMaterial !=
"" ) {
837 _importer.useMaterial(lastMaterial.toStdString());
842 else if (mode == NONE && keyWrd == QLatin1String(
"f"))
847 _importer.setCurrentGroup(0);
852 int component(0), nV(0);
856 face_texcoords.clear();
860 faceLine = stream.readLine();
861 lineData.setString(&faceLine);
864 while ( !lineData.atEnd() )
873 int found=vertex.indexOf(QLatin1String(
"/"));
879 QString vertexEntry = vertex.left(found);
880 tmp.setString( &vertexEntry );
883 if ( vertexEntry.isEmpty() ) {
885 vertex = vertex.right(vertex.length()-(found+1));
898 vertex = vertex.right(vertex.length()-(found+1));
903 tmp.setString( &vertex );
907 vertex=QLatin1String(
"");
910 if ( tmp.status() != QTextStream::Ok ) {
923 value = currentVertexCount + value + 1;
927 vhandles.push_back( value-1 );
935 value = currentTextureCoordCount + value + 1;
937 if (vhandles.empty())
939 if(!bSuppNoVertCoord) {
940 emit log (
LOGWARN, tr(
"Texture coordinates defined, but no vertex coordinates found!"));
941 bSuppNoVertCoord=
true;
945 if ((
unsigned int)(value-1) >= _importer.n_texCoords())
947 if(!bSuppTooManyTexCoord) {
948 emit log(
LOGWARN, tr(
"Too many texcoords defined, skipping the rest"));
949 bSuppTooManyTexCoord=
true;
954 if ( _importer.n_texCoords() > 0 ) {
957 face_texcoords.push_back( value-1 );
958 }
else if(bSuppErrorSettingTexCoord){
959 emit log(
LOGERR, tr(
"Error setting Texture coordinates") );
960 bSuppErrorSettingTexCoord=
true;
970 value = currentNormalCount + value + 1;
973 if (vhandles.empty())
975 if(!bSuppNoVertCoord) {
976 emit log (
LOGWARN, tr(
"Texture coordinates defined, but no vertex coordinates found!"));
977 bSuppNoVertCoord=
true;
982 if ((
unsigned int)(value-1) >= _importer.n_normals())
984 if(!bSuppTooManyNormal)
986 emit log (
LOGWARN, tr(
"Too many normals defined, skipping the rest"));
987 bSuppTooManyNormal=
true;
993 _importer.
setNormal(vhandles.back(), value-1);
1001 }
while ( !vertex.isEmpty() );
1008 remove_duplicated_vertices(vhandles);
1011 if( vhandles.size() > 2 ){
1013 if ( !face_texcoords.empty() )
1015 _importer.
addFace(vhandles, face_texcoords );
1029#ifdef ENABLE_BSPLINECURVE_SUPPORT
1031 else if ( (mode == CURVE && keyWrd == QLatin1String(
"parm")) || (mode == CURVE && keyWrd == QLatin1String(
"parm_add")) ){
1037 paramLine = stream.readLine();
1040 if ( paramLine.endsWith(QLatin1String(
"\\"))){
1041 paramLine = paramLine.left( paramLine.length()-1);
1042 nextKeyWrd = QLatin1String(
"parm_add");
1045 lineData.setString( ¶mLine );
1047 if ( keyWrd != QLatin1String(
"parm_add"))
1051 while ( !lineData.atEnd() && lineData.status()==QTextStream::Ok )
1056 knot = getDouble(lineData);
1058 if ( lineData.status() == QTextStream::Ok )
1059 knotsU.push_back( knot );
1064 else if ( (mode == NONE && keyWrd == QLatin1String(
"curv")) || (mode == CURVE && keyWrd == QLatin1String(
"curv_add")) ){
1072 if ( keyWrd == QLatin1String(
"curv") )
1074 int id = _importer.getCurveGroupId(curveCount);
1076 std::cerr <<
"Error: Group has not been added before!" << std::endl;
1079 _importer.setCurrentGroup(
id);
1086 curveLine = stream.readLine();
1089 if ( curveLine.endsWith(QLatin1String(
"\\"))){
1090 curveLine = curveLine.left(curveLine.length()-1);
1091 nextKeyWrd = QLatin1String(
"curv_add");
1094 lineData.setString( &curveLine );
1097 if ( keyWrd == QLatin1String(
"curv") ) {
1099 getDouble(lineData);
1100 getDouble(lineData);
1106 while ( !lineData.atEnd() && lineData.status()==QTextStream::Ok )
1116 index = currentVertexCount + index + 1;
1119 if ( lineData.status()==QTextStream::Ok )
1120 cpIndices.push_back( index -1 );
1125 else if (mode == CURVE && keyWrd == QLatin1String(
"end")){
1129 _importer.currentCurve()->set_degree( _importer.
degreeU() );
1130 _importer.currentCurve()->autocompute_knotvector(
false);
1133 std::vector< ACG::Vec3d > controlPolygon;
1135 for (
unsigned int i = 0; i < cpIndices.size(); ++i)
1138 _importer.currentCurve()->set_control_polygon( controlPolygon );
1140 _importer.currentCurve()->set_knots(knotsU);
1150#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1152 else if ( (mode == SURFACE && keyWrd == QLatin1String(
"parm")) || (mode == SURFACE && keyWrd == QLatin1String(
"parm_add")) ){
1158 paramLine = stream.readLine();
1161 if ( paramLine.endsWith(QLatin1String(
"\\"))){
1162 paramLine = paramLine.left(paramLine.length()-1);
1163 nextKeyWrd = QLatin1String(
"parm_add");
1166 lineData.setString( ¶mLine );
1168 if ( keyWrd == QLatin1String(
"parm_add_u"))
1169 tmp = QLatin1String(
"u");
1170 else if ( keyWrd == QLatin1String(
"parm_add_v"))
1171 tmp = QLatin1String(
"v");
1175 std::vector< double >* knots;
1178 if (tmp == QLatin1String(
"u"))
1183 if (nextKeyWrd != QLatin1String(
""))
1184 nextKeyWrd += QLatin1String(
"_") + tmp;
1187 while ( !lineData.atEnd() && lineData.status()==QTextStream::Ok )
1192 knot = getDouble(lineData);
1194 if ( lineData.status()==QTextStream::Ok ) {
1195 knots->push_back( knot );
1201 else if ( (mode == NONE && keyWrd == QLatin1String(
"surf")) || (mode == SURFACE && keyWrd == QLatin1String(
"surf_add")) ){
1209 if ( keyWrd == QLatin1String(
"surf") )
1211 int id = _importer.getSurfaceGroupId(surfaceCount);
1213 std::cerr <<
"Error: Group has not been added before!" << std::endl;
1216 _importer.setCurrentGroup(
id);
1223 surfLine = stream.readLine();
1226 if ( surfLine.endsWith(QLatin1String(
"\\"))){
1227 surfLine = surfLine.left(surfLine.length()-1);
1228 nextKeyWrd = QLatin1String(
"surf_add");
1231 lineData.setString( &surfLine );
1234 while ( !lineData.atEnd() && lineData.status()==QTextStream::Ok )
1244 index = currentVertexCount + index + 1;
1247 if ( lineData.status()==QTextStream::Ok )
1248 cpIndices.push_back( index -1 );
1253 else if (mode == SURFACE && keyWrd == QLatin1String(
"end")){
1255 if ( _importer.isSurface( _importer.
currentGroup() ) ){
1258 cpIndices.erase(cpIndices.begin());
1259 cpIndices.erase(cpIndices.begin());
1260 cpIndices.erase(cpIndices.begin());
1261 cpIndices.erase(cpIndices.begin());
1264 _importer.currentSurface()->set_degree( _importer.
degreeU(), _importer.
degreeV() );
1267 int dimU = knotsU.size() - _importer.
degreeU() - 1;
1268 int dimV = knotsV.size() - _importer.
degreeV() - 1;
1271 std::vector< ACG::Vec3d > controlPolygon;
1273 for (
int i = 0; i < dimU; ++i)
1275 controlPolygon.clear();
1277 for (
int j = 0; j < dimV; ++j){
1278 controlPolygon.push_back( (
ACG::Vec3d) _importer.
vertex( cpIndices[dimU * j + i] ) );
1281 _importer.currentSurface()->add_vector_m(controlPolygon);
1284 _importer.currentSurface()->set_knots_m(knotsU);
1285 _importer.currentSurface()->set_knots_n(knotsV);
1300 bool isType = faceCount != 0;
1302#ifdef ENABLE_BSPLINECURVE_SUPPORT
1303 isType = isType || curveCount != 0;
1306#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1307 isType = isType || surfaceCount != 0;
1312 if (!isType && currentVertexCount != 0 ) {
1315 _importer.setCurrentGroup(0);
1323 ptr::shared_ptr<QTextStream> streamPointer;
1324 ptr::shared_ptr<QFile> sourceFile;
1326 if (_bufferedFile.isNull() || _bufferedFile.isEmpty())
1329 sourceFile.reset(
new QFile(_filename));
1330 if(!sourceFile->open(QFile::ReadOnly))
1332 emit log(
LOGERR, tr(
"readOBJFile : cannot open file %1 while checking Types").arg(_filename) );
1335 streamPointer.reset(
new QTextStream(sourceFile.get()));
1339 streamPointer.reset(
new QTextStream(&_bufferedFile));
1341 QTextStream input(streamPointer->device());
1343 QTextStream lineData;
1346 if ( input.status()!=QTextStream::Ok ){
1347 emit log(
LOGERR, tr(
"readOBJFile : cannot read file %1 while checking Types (is the file corrupt?)").arg(_filename) );
1351 ReaderMode mode = NONE;
1355 QString nextKeyWrd = QLatin1String(
"");
1357#ifdef ENABLE_BSPLINECURVE_SUPPORT
1358 unsigned int curveCount = 0;
1361#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1362 unsigned int surfaceCount = 0;
1368 int PolyMeshCount = 0;
1369 int TriMeshCount = 0;
1371 OBJImporter::ObjectOptions options = OBJImporter::NONE;
1374 bool inGroup =
false;
1376 bool firstFace =
true;
1378#if defined ENABLE_BSPLINECURVE_SUPPORT || defined ENABLE_BSPLINESURFACE_SUPPORT
1379 QString currentGroupName;
1385 while( !input.atEnd())
1387 line = input.readLine();
1388 if ( input.status()!=QTextStream::Ok ){
1389 emit log(
LOGERR, tr(
"readOBJFile : Warning! Could not read file properly!"));
1394 line = line.trimmed();
1397 if ( line.isEmpty() || line[0] == QLatin1Char(
'#') || line[0].isSpace() ) {
1401 stream.setString(&line);
1405 if (nextKeyWrd == QLatin1String(
""))
1408 keyWrd = nextKeyWrd;
1409 nextKeyWrd = QLatin1String(
"");
1413 if (mode == NONE && keyWrd == QLatin1String(
"call")){
1417 include =stream.readLine();
1420 QString includeStr = include.trimmed();
1422 if ( !includeStr.isEmpty() ){
1424 if (includeStr[0] == QLatin1Char(
'.')){
1425 includeStr = includeStr.right( includeStr.length()-1 );
1427 QFileInfo fi(_filename);
1429 includeStr = fi.path() + QDir::separator() + includeStr;
1432 _includes.append( includeStr );
1439 else if (mode == NONE && keyWrd == QLatin1String(
"v"))
1444 x = getDouble(stream);
1445 y = getDouble(stream);
1446 z = getDouble(stream);
1448 if ( stream.status()==QTextStream::Ok )
1451 emit log(
LOGERR, tr(
"Could not add Vertex %1. Possible NaN or Inf?").arg(_importer.
n_vertices()));
1455 else if (mode == NONE && keyWrd == QLatin1String(
"g")){
1463 grpName = stream.readLine();
1465 if ( options & OBJImporter::TRIMESH ) TriMeshCount++;
1466 if ( options & OBJImporter::POLYMESH ) PolyMeshCount++;
1468 int id = _importer.addGroup(grpName);
1469#if defined ENABLE_BSPLINECURVE_SUPPORT || defined ENABLE_BSPLINESURFACE_SUPPORT
1471 currentGroupName = grpName;
1472 currentGroupName.remove(QLatin1String(
".obj"));
1474 _importer.setCurrentGroup(
id);
1481 options = OBJImporter::NONE;
1486 else if (mode == NONE && keyWrd == QLatin1String(
"f")){
1491 _importer.setCurrentGroup(0);
1497 int verticesPerFace = 0;
1502 faceLine = stream.readLine();
1503 lineData.setString( &faceLine );
1506 while ( !lineData.atEnd() )
1516 int found=vertex.indexOf(QLatin1String(
"/"));
1522 QString vertexEntry = vertex.left(found);
1523 tmp.setString( &vertexEntry );
1528 if ( tmp.status()!=QTextStream::Ok )
1529 emit log(
LOGERR, tr(
"readOBJFile : Error reading vertex index!"));
1534 tmp.setString( &vertex );
1537 if ( tmp.status()!=QTextStream::Ok )
1538 emit log(
LOGERR, tr(
"readOBJFile : Error reading vertex index!"));
1555 if( verticesPerFace > 3 ) {
1556 options = OBJImporter::POLYMESH;
1558 }
else if ( verticesPerFace == 3 ) {
1559 options = OBJImporter::TRIMESH;
1564#ifdef ENABLE_BSPLINECURVE_SUPPORT
1567 if ( (mode == NONE && keyWrd == QLatin1String(
"curv")) || (mode == CURVE && keyWrd == QLatin1String(
"curv_add")) ){
1575 if ( keyWrd == QLatin1String(
"curv") ) {
1579 if ( options & OBJImporter::TRIMESH ) TriMeshCount++;
1580 if ( options & OBJImporter::POLYMESH ) PolyMeshCount++;
1582 QString
name = currentGroupName;
1583 if (
name.size() == 0)
1584 name = QLatin1String(
"DefaultGroup");
1586 name.append(QString(
"_curve_%1").arg(curveCount));
1587 int id = _importer.addGroup(
name);
1589 if (_importer.numCurves() == 0) {
1590 if (currentGroupName.size() == 0)
1591 _importer.setGroupName(
id, QString(
"DefaultGroup"));
1593 _importer.setGroupName(
id, currentGroupName);
1595 if (curveCount == 1) {
1596 int first = _importer.getCurveGroupId(0);
1597 QString tmp = _importer.groupName(first);
1598 tmp.append(QString(
"_curve_0"));
1599 _importer.setGroupName(first, tmp);
1601 _importer.setGroupName(
id,
name);
1603 _importer.setCurveParentId(
id, parentId);
1604 _importer.setCurrentGroup(
id);
1605 _importer.setCurveGroupId(curveCount,
id);
1610 options = OBJImporter::CURVE;
1616 curveLine=stream.readLine();
1619 if ( curveLine.endsWith(QLatin1String(
"\\"))){
1620 curveLine = curveLine.left( curveLine.length()-1);
1621 nextKeyWrd = QLatin1String(
"curv_add");
1624 lineData.setString( &curveLine );
1627 if ( keyWrd == QLatin1String(
"curv") ) {
1629 getDouble(lineData);
1630 getDouble(lineData);
1634 while ( !lineData.atEnd() && lineData.status()==QTextStream::Ok )
1640 if ( lineData.status()==QTextStream::Ok ){
1649 else if (mode == CURVE && keyWrd == QLatin1String(
"end")){
1654 options = OBJImporter::TRIMESH;
1659#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1662 if ( (mode == NONE && keyWrd == QLatin1String(
"surf")) || (mode == SURFACE && keyWrd == QLatin1String(
"surf_add")) ){
1670 if ( keyWrd == QLatin1String(
"surf") ){
1674 if ( options & OBJImporter::TRIMESH ) TriMeshCount++;
1675 if ( options & OBJImporter::POLYMESH ) PolyMeshCount++;
1677 QString
name = currentGroupName;
1678 if (
name.size() == 0)
1679 name = QLatin1String(
"DefaultGroup");
1681 name.append(QString(
"_surface_%1").arg(surfaceCount));
1682 int id = _importer.addGroup(
name);
1684 if (_importer.numSurfaces() == 0) {
1685 if (currentGroupName.size() == 0)
1686 _importer.setGroupName(
id,
"DefaultGroup");
1688 _importer.setGroupName(
id, currentGroupName);
1690 if (surfaceCount == 1) {
1691 int first = _importer.getSurfaceGroupId(0);
1692 QString tmp = _importer.groupName(first);
1693 tmp.append(QString(
"_surface_0"));
1694 _importer.setGroupName(first, tmp);
1696 _importer.setGroupName(
id,
name);
1698 _importer.setSurfaceParentId(
id, parentId);
1699 _importer.setCurrentGroup(
id);
1700 _importer.setSurfaceGroupId(surfaceCount,
id);
1705 options = OBJImporter::SURFACE;
1711 surfLine = stream.readLine();
1714 if ( surfLine.endsWith(QLatin1String(
"\\"))){
1715 surfLine = surfLine.left(surfLine.length()-1);
1716 nextKeyWrd = QLatin1String(
"surf_add");
1719 lineData.setString( &surfLine );
1722 while ( !lineData.atEnd() && lineData.status()==QTextStream::Ok )
1728 if ( lineData.status()==QTextStream::Ok ){
1736 else if (mode == SURFACE && keyWrd == QLatin1String(
"end")){
1741 options = OBJImporter::TRIMESH;
1749 if ( options & OBJImporter::TRIMESH ) TriMeshCount++;
1750 if ( options & OBJImporter::POLYMESH ) PolyMeshCount++;
1755 if (keyWrd != QLatin1String(
"call")) {
1757 if (keyWrd == QLatin1String(
"v") && !inGroup) {
1758 _importer.setCurrentGroup(0);
1760 forceTriangleMesh_ =
false;
1761 forcePolyMesh_ =
true;
1764 for (
unsigned int i = 0; i < _importer.
n_vertices(); ++i)
1777 if (TriMeshCount == 0 && PolyMeshCount == 0)
1782 if (forceTriangleMesh_){
1787 if (forcePolyMesh_){
1794 if ( OpenFlipper::Options::gui() && triMeshHandling_ != 0 ){
1796 switch( triMeshHandling_->currentIndex() ){
1797 case TYPEAUTODETECT :
1801 QMetaObject::invokeMethod(
this,
"handleTrimeshDialog",Qt::BlockingQueuedConnection);
1802 if (trimeshOptions_ == OBJImporter::TRIMESH )
1804 else if (trimeshOptions_ == OBJImporter::POLYMESH)
1823void FileOBJPlugin::handleTrimeshDialog()
1826 QPushButton *detectButton = msgBox.addButton(tr(
"Auto-Detect"), QMessageBox::ActionRole);
1827 QPushButton *triButton = msgBox.addButton(tr(
"Open as triangle mesh"), QMessageBox::ActionRole);
1828 QPushButton *polyButton = msgBox.addButton(tr(
"Open as poly mesh"), QMessageBox::ActionRole);
1829 msgBox.setWindowTitle( tr(
"Mesh types in file") );
1830 msgBox.setText( tr(
"You are about to open a file containing one or more mesh types. \n\n Which mesh type should be used?") );
1831 msgBox.setDefaultButton( detectButton );
1835 if (msgBox.clickedButton() == triButton)
1836 trimeshOptions_ = OBJImporter::TRIMESH ;
1837 else if (msgBox.clickedButton() == polyButton)
1838 trimeshOptions_ = OBJImporter::POLYMESH ;
1848 QStringList includes;
1850 QFile sourceFile(_filename);
1851 if (!sourceFile.open(QFile::ReadOnly))
1853 emit log(
LOGERR, tr(
"readOBJFile : cannot open file %1 while checking Types").arg(_filename));
1856 QByteArray bufferedFile = QByteArray();
1859 unsigned long freeMem = Utils::Memory::queryFreeRAM();
1860 unsigned long fs = sourceFile.size() / 1024 / 1024;
1861 if (freeMem >= 2*fs)
1863 bufferedFile = sourceFile.readAll();
1867 checkTypes( bufferedFile, _filename, importer, includes );
1872 for (
int i=0; i < includes.size(); i++){
1878 objIDs.push_back(
id );
1882 if ( ! includes.empty() )
1883 importer.addGroup( QFileInfo(_filename).fileName() );
1886 if ( importer.
noOptions() && objIDs.empty() ){
1888 forceTriangleMesh_ =
false;
1889 forcePolyMesh_ =
false;
1895 readOBJFile( bufferedFile, _filename, importer );
1903 if ( importer.numGroups() > 1){
1905 bool dataControlExists =
false;
1906 pluginExists(
"datacontrol", dataControlExists );
1908 if ( dataControlExists ){
1909#if defined ENABLE_BSPLINECURVE_SUPPORT || defined ENABLE_BSPLINESURFACE_SUPPORT
1910 std::map<int, QString> groupNames;
1913#ifdef ENABLE_BSPLINECURVE_SUPPORT
1914 std::vector< std::vector<int> > curveGroups;
1915 std::vector<int> curveIds;
1916 int lastCurveParent = -2;
1919#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1920 std::vector< std::vector<int> > surfaceGroups;
1921 std::vector<int> surfaceIds;
1922 int lastSurfaceParent = -2;
1924 for(
unsigned int i = 0; i < importer.
groupCount(); i++) {
1927 if ( !importer.isNone(i) ) {
1930#ifdef ENABLE_BSPLINECURVE_SUPPORT
1931 if ( importer.isCurve(i) ) {
1933 groupNames[obj->
id()] = importer.groupName(importer.getCurveParentId(i));
1936 if (lastCurveParent == -2) {
1937 lastCurveParent = importer.getCurveParentId(i);
1938 curveIds.push_back(obj->
id());
1941 curveIds.push_back(parent->
id());
1943 std::vector<int>::iterator pos = std::find(objIDs.begin(), objIDs.end(), parent->
id());
1944 if (pos != objIDs.end())
1948 }
else if (lastCurveParent != importer.getCurveParentId(i)) {
1949 lastCurveParent = importer.getCurveParentId(i);
1950 curveGroups.push_back(curveIds);
1952 curveIds.push_back(obj->
id());
1955 curveIds.push_back(parent->
id());
1957 std::vector<int>::iterator pos = std::find(objIDs.begin(), objIDs.end(), parent->
id());
1958 if (pos != objIDs.end())
1963 curveIds.push_back(obj->
id());
1967#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1968 if ( importer.isSurface(i)) {
1970 groupNames[obj->
id()] = importer.groupName(importer.getSurfaceParentId(i));
1973 if (lastSurfaceParent == -2) {
1974 lastSurfaceParent = importer.getSurfaceParentId(i);
1975 surfaceIds.push_back(obj->
id());
1978 surfaceIds.push_back(parent->
id());
1979 std::vector<int>::iterator pos = std::find(objIDs.begin(), objIDs.end(), parent->
id());
1980 if (pos != objIDs.end())
1984 }
else if (lastSurfaceParent != importer.getSurfaceParentId(i)) {
1985 lastSurfaceParent = importer.getSurfaceParentId(i);
1986 surfaceGroups.push_back(surfaceIds);
1988 surfaceIds.push_back(obj->
id());
1991 surfaceIds.push_back(parent->
id());
1992 std::vector<int>::iterator pos = std::find(objIDs.begin(), objIDs.end(), parent->
id());
1993 if (pos != objIDs.end())
1998 surfaceIds.push_back(obj->
id());
2002 if ( (importer.isTriangleMesh(i) || importer.isPolyMesh(i) ) )
2003 objIDs.push_back( obj->
id() );
2005 std::cerr <<
"Object is NULL!" << std::endl;
2010#ifdef ENABLE_BSPLINECURVE_SUPPORT
2012 curveGroups.push_back(curveIds);
2013 std::vector< std::vector<int> >::iterator it = curveGroups.begin();
2014 for (; it != curveGroups.end(); ++it) {
2016 if (it->size() > 2) {
2017 if (groupNames[it->back()].size() == 0)
2018 RPC::callFunctionValue<int>(
"datacontrol",
"groupObjects", *it, QFileInfo(_filename).fileName());
2020 RPC::callFunctionValue<int>(
"datacontrol",
"groupObjects", *it, groupNames[it->back()]);
2025#ifdef ENABLE_BSPLINESURFACE_SUPPORT
2027 surfaceGroups.push_back(surfaceIds);
2028 std::vector< std::vector<int> >::iterator it2 = surfaceGroups.begin();
2029 for (; it2 != surfaceGroups.end(); ++it2) {
2031 if (it2->size() > 2) {
2032 if (groupNames[it2->back()].size() == 0)
2033 RPC::callFunctionValue<int>(
"datacontrol",
"groupObjects", *it2, QFileInfo(_filename).fileName());
2035 RPC::callFunctionValue<int>(
"datacontrol",
"groupObjects", *it2, groupNames[it2->back()]);
2041 if (objIDs.size() > 1)
2042 returnID = RPC::callFunctionValue<int>(
"datacontrol",
"groupObjects", objIDs, importer.groupName(0));
2047 for(
unsigned int i=0; i < importer.
groupCount(); i++){
2050 if(
object == NULL)
continue;
2055 if ( returnID == -1)
2056 returnID =
object->id();
2080#ifdef ENABLE_BSPLINECURVE_SUPPORT
2091 if ( importer.hasTexture(i) && !importer.
hasOption( i, OBJImporter::FORCE_NOTEXTURES ) ){
2094 addTextures( importer, i );
2097 emit setTextureMode(
"OBJ Data",
"indexProperty=OriginalTexIndexMapping", object->
id() );
2099 emit switchTexture(
"OBJ Data", object->
id() );
2107 emit openedFile( object->
id() );
2110 forceTriangleMesh_ =
false;
2111 forcePolyMesh_ =
false;
2124 forceTriangleMesh_ =
true;
2126 forcePolyMesh_ =
true;
2133bool FileOBJPlugin::saveObject(
int _id, QString _filename)
2137 emit log(
LOGERR, tr(
"saveObject : cannot get object id %1 for save name %2").arg(_id).arg(_filename) );
2142 std::string filename = std::string( _filename.toUtf8() );
2144 std::fstream objStream( filename.c_str(), std::ios_base::out );
2148 emit log(
LOGERR, tr(
"saveObject : cannot not open file %1").arg(_filename) );
2155 object->setFromFileName(_filename);
2156 object->setName(object->
filename());
2161 if ( writeMesh( objStream, _filename, *polyObj->
mesh(), polyObj->
id() ) ){
2163 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2169 emit log(
LOGERR, tr(
"Unable to save ") + _filename);
2176 object->setFromFileName(_filename);
2177 object->setName(object->
filename());
2182 if ( writeMesh( objStream, _filename, *triObj->
mesh(), triObj->
id() )) {
2184 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2190 emit log(
LOGERR, tr(
"Unable to save ") + _filename );
2195#ifdef ENABLE_BSPLINECURVE_SUPPORT
2198 object->setFromFileName(_filename);
2199 object->setName(object->
filename());
2204 if ( writeCurve( objStream, _filename, bscObj->
splineCurve()) ) {
2206 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2212 emit log(
LOGERR, tr(
"Unable to save ") + _filename );
2218#ifdef ENABLE_BSPLINESURFACE_SUPPORT
2221 object->setFromFileName(_filename);
2222 object->setName(object->
filename());
2227 if ( writeSurface( objStream, _filename, bssObj->
splineSurface()) ) {
2229 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2235 emit log(
LOGERR, tr(
"Unable to save ") + object->
path() + OpenFlipper::Options::dirSeparator() + object->
name());
2243 emit log(
LOGERR, tr(
"Unable to save (object is not a compatible mesh type)"));
2251void FileOBJPlugin::slotHandleCheckBoxes(
bool _checked) {
2253 if(saveCopyTextures_) {
2254 saveCreateTexFolder_->setEnabled(_checked);
2255 saveCreateTexFolder_->setChecked(_checked);
2263 if (saveOptions_ == 0){
2265 saveOptions_ =
new QWidget();
2266 QVBoxLayout* layout =
new QVBoxLayout();
2267 layout->setAlignment(Qt::AlignTop);
2269 saveFaceColor_ =
new QCheckBox(
"Save Face Colors");
2270 layout->addWidget(saveFaceColor_);
2272 saveFaceColorOverride_ =
new QCheckBox(
"Save Face Colors Error Override (Save, even if colors contain errors!)");
2273 saveFaceColorOverride_->setToolTip(
"If color values of a mesh are not initialized, OpenFlipper will detect that and stop writing materials. This option will force it to write them anyway.");
2274 layout->addWidget(saveFaceColorOverride_);
2276 saveAlpha_ =
new QCheckBox(
"Save Color Alpha");
2277 layout->addWidget(saveAlpha_);
2279 saveNormals_ =
new QCheckBox(
"Save Normals");
2280 layout->addWidget(saveNormals_);
2282 saveTexCoords_ =
new QCheckBox(
"Save Texture Coordinates");
2283 layout->addWidget(saveTexCoords_);
2285 saveTextures_ =
new QCheckBox(
"Save Textures");
2286 layout->addWidget(saveTextures_);
2288 saveCopyTextures_ =
new QCheckBox(
"Copy Texture Files");
2289 layout->addWidget(saveCopyTextures_);
2291 saveCreateTexFolder_ =
new QCheckBox(
"Create Textures Folder");
2292 layout->addWidget(saveCreateTexFolder_);
2294 savePrecisionLabel_ =
new QLabel(
"Writer Precision");
2295 layout->addWidget(savePrecisionLabel_);
2297 savePrecision_ =
new QSpinBox();
2298 savePrecision_->setMinimum(1);
2299 savePrecision_->setMaximum(std::numeric_limits<double>::max_digits10);
2300 layout->addWidget(savePrecision_);
2302 saveDefaultButton_ =
new QPushButton(
"Make Default");
2303 layout->addWidget(saveDefaultButton_);
2305 saveOptions_->setLayout(layout);
2307 connect(saveDefaultButton_, SIGNAL(clicked()),
this, SLOT(
slotSaveDefault()));
2308 connect(saveCopyTextures_, SIGNAL(toggled(
bool)),
this, SLOT(slotHandleCheckBoxes(
bool)));
2310 saveFaceColor_->setChecked( OpenFlipperSettings().value(
"FileObj/Save/FaceColor",
true).toBool() );
2311 saveFaceColorOverride_->setChecked( OpenFlipperSettings().value(
"FileObj/Save/FaceColorOverrise",
false).toBool() );
2312 saveAlpha_->setChecked( OpenFlipperSettings().value(
"FileObj/Save/Alpha",
true).toBool() );
2313 saveNormals_->setChecked( OpenFlipperSettings().value(
"FileObj/Save/Normals",
true).toBool() );
2314 saveTexCoords_->setChecked( OpenFlipperSettings().value(
"FileObj/Save/TexCoords",
true).toBool() );
2315 saveTextures_->setChecked( OpenFlipperSettings().value(
"FileObj/Save/Textures",
true).toBool() );
2316 saveCopyTextures_->setChecked( OpenFlipperSettings().value(
"FileObj/Save/CopyTextures",
true).toBool() );
2317 saveCreateTexFolder_->setChecked( OpenFlipperSettings().value(
"FileObj/Save/CreateTexFolder",
true).toBool() );
2318 savePrecision_->setValue( OpenFlipperSettings().value(
"FileObj/Save/Precision",
2319 std::numeric_limits<double>::max_digits10
2322 slotHandleCheckBoxes(saveCopyTextures_->isChecked());
2325 return saveOptions_;
2332 if (loadOptions_ == 0){
2334 loadOptions_ =
new QWidget();
2335 QVBoxLayout* layout =
new QVBoxLayout();
2336 layout->setAlignment(Qt::AlignTop);
2338 QLabel* label =
new QLabel(tr(
"If file contains meshes:"));
2340 layout->addWidget(label);
2342 triMeshHandling_ =
new QComboBox();
2343 triMeshHandling_->addItem( tr(
"Detect correct type") );
2344 triMeshHandling_->addItem( tr(
"Ask") );
2345 triMeshHandling_->addItem( tr(
"Open as PolyMesh") );
2346 triMeshHandling_->addItem( tr(
"Open as TriangleMesh") );
2348 layout->addWidget(triMeshHandling_);
2350 loadFaceColor_ =
new QCheckBox(
"Load Face Colors");
2351 layout->addWidget(loadFaceColor_);
2353 loadNormals_ =
new QCheckBox(
"Load Normals");
2354 layout->addWidget(loadNormals_);
2356 loadTexCoords_ =
new QCheckBox(
"Load Texture Coordinates");
2357 layout->addWidget(loadTexCoords_);
2359 loadTextures_ =
new QCheckBox(
"Load Textures");
2360 layout->addWidget(loadTextures_);
2362 loadDefaultButton_ =
new QPushButton(
"Make Default");
2363 layout->addWidget(loadDefaultButton_);
2365 loadOptions_->setLayout(layout);
2367 connect(loadDefaultButton_, SIGNAL(clicked()),
this, SLOT(
slotLoadDefault()));
2370 triMeshHandling_->setCurrentIndex(OpenFlipperSettings().value(
"FileObj/Load/TriMeshHandling",TYPEAUTODETECT).toInt() );
2372 loadFaceColor_->setChecked( OpenFlipperSettings().value(
"FileObj/Load/FaceColor",
true).toBool() );
2373 loadNormals_->setChecked( OpenFlipperSettings().value(
"FileObj/Load/Normals",
true).toBool() );
2374 loadTexCoords_->setChecked( OpenFlipperSettings().value(
"FileObj/Load/TexCoords",
true).toBool() );
2375 loadTextures_->setChecked( OpenFlipperSettings().value(
"FileObj/Load/Textures",
true).toBool() );
2378 return loadOptions_;
2382 OpenFlipperSettings().
setValue(
"FileObj/Load/FaceColor", loadFaceColor_->isChecked() );
2383 OpenFlipperSettings().
setValue(
"FileObj/Load/Normals", loadNormals_->isChecked() );
2384 OpenFlipperSettings().
setValue(
"FileObj/Load/TexCoords", loadTexCoords_->isChecked() );
2385 OpenFlipperSettings().
setValue(
"FileObj/Load/Textures", loadTextures_->isChecked() );
2386 OpenFlipperSettings().
setValue(
"FileObj/Load/TriMeshHandling", triMeshHandling_->currentIndex() );
2388 OpenFlipperSettings().
setValue(
"Core/File/UseLoadDefaults",
true );
2393 OpenFlipperSettings().
setValue(
"FileObj/Save/FaceColor", saveFaceColor_->isChecked() );
2394 OpenFlipperSettings().
setValue(
"FileObj/Save/FaceColorOverride", saveFaceColorOverride_->isChecked() );
2395 OpenFlipperSettings().
setValue(
"FileObj/Save/Normals", saveNormals_->isChecked() );
2396 OpenFlipperSettings().
setValue(
"FileObj/Save/TexCoords", saveTexCoords_->isChecked() );
2397 OpenFlipperSettings().
setValue(
"FileObj/Save/Textures", saveTextures_->isChecked() );
2398 OpenFlipperSettings().
setValue(
"FileObj/Save/CopyTextures", saveCopyTextures_->isChecked() );
2399 OpenFlipperSettings().
setValue(
"FileObj/Save/CreateTexFolder", saveCreateTexFolder_->isChecked() );
2400 OpenFlipperSettings().
setValue(
"FileObj/Save/Precision", savePrecision_->value() );
#define DATA_BSPLINE_CURVE
#define DATA_BSPLINE_SURFACE
const DataType DATA_GROUP(1)
Items used for Grouping.
std::vector< int > IdList
Standard Type for id Lists used for scripting.
#define DATA_TRIANGLE_MESH
ACG::SceneGraph::BSplineCurveNodeT< BSplineCurve > * splineCurveNode()
Get the scenegraph Node.
BSplineCurve * splineCurve()
return a pointer to the spline curve
BSplineSurface * splineSurface()
return a pointer to the spline curve
QString name() const
return the name of the object. The name defaults to NONAME if unset.
QString filename() const
return the filename of the object
bool dataType(DataType _type) const
QString path() const
return the path to the object ( defaults to "." if unset )
void setFromFileName(const QString &_filename)
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
void initializePlugin()
Initialize Plugin.
QWidget * saveOptionsWidget(QString)
void slotLoadDefault()
Slot called when user wants to save the given Load options as default.
void convertToOBJName(QString &_name)
Convert non-valid filenames (e.g. of groups that end with .jpg) to valid .objs.
void checkTypes(QByteArray &_bufferedFile, QString _filename, OBJImporter &_importer, QStringList &_includes)
Reader functions.
void slotSaveDefault()
Slot called when user wants to save the given Save options as default.
QString name()
Return a name for the plugin.
int loadObject(QString _filename)
Loads Object and converts it to a triangle mesh if possible.
FileOBJPlugin()
Constructor.
void backupTextureCoordinates(MeshT &_mesh)
creates a backup of the original per vertex/face texture coordinates
QWidget * loadOptionsWidget(QString)
MeshT * mesh()
return a pointer to the mesh
unsigned int groupCount()
Number of groups currently stored in the importer.
Vec3d vertex(unsigned int _index)
get vertex with given index
void addMaterial(std::string _materialName)
Add a material.
void setDegreeV(int _degree)
set degree V direction
void setVertexTexCoord(VertexHandle _vh, int _texCoordID)
set vertex texture coordinate
unsigned int n_vertices()
Global Properties.
void useVertex(int _vertex_index)
used vertices
void setObjectOptions(ObjectOptions _options)
void addFace(const VHandles &_indices)
add a face with indices _indices refering to vertices
int addTexCoord(const Vec2f &_coord)
add texture coordinates
VertexHandle addVertex(const Vec3d &_point)
add a vertex with coordinate _point
int degreeU()
get current degree
void setDegreeU(int _degree)
set degree
bool noOptions()
Return true if the importer has no options stored.
QString path()
Path of the OBJ file.
void forceMeshType(ObjectOptions _meshType)
force all meshes to be opened with specific type
int addNormal(const Vec3d &_normal)
add a normal
void setNormal(int _index, int _normalID)
set vertex normal
bool hasOption(unsigned int _id, ObjectOptions _option)
check if object with given id has given option
BaseObject * object(int _groupId)
return object for the given group
void setOption(ObjectOptionsE _option)
Set Object Option.
void setObject(BaseObject *_object, int _groupId)
add an object
MaterialList & materials()
return all loaded materials
int degreeV()
get current degree
const std::vector< std::string > usedMaterials(unsigned int _objectID)
used materials
bool hasNormals(int _objectID)
Query Object Options.
int currentGroup()
Get the id of the current group.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
void update_face_normals()
Update normal vectors for all faces.
void update_normals()
Compute normals for all primitives.
Type for a Meshobject containing a poly mesh.
Type for a MeshObject containing a triangle mesh.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
DrawMode SOLID_2DTEXTURED_FACE_SHADED
draw per halfedge textured faces
DrawMode NONE
not a valid draw mode
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
void setDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, int _viewer)
Set the draw Mode of a Viewer. .