Updated Sketchfab exported filter

This commit is contained in:
Paolo Cignoni 2016-12-21 11:26:27 +01:00
parent 71fd3f081d
commit 6ea0112cfe
5 changed files with 5013 additions and 37 deletions

View File

@ -34,34 +34,83 @@
#include <QScriptEngine>
#include "filter_sketchfab.h"
#include "miniz.c"
#include <wrap/io_trimesh/export_ply.h>
using namespace std;
using namespace vcg;
void Uploader();
int saveMeshZip(string fileName, string internalName, string zipName) {
qDebug("Trying to add %s to %s", fileName.c_str(), zipName.c_str());
mz_zip_archive zip_archive;
memset(&zip_archive, 0, sizeof (zip_archive)); //Saving memory for the zip archive
if (!mz_zip_writer_init_file(&zip_archive, zipName.c_str(), 65537)) {
qDebug("Failed creating zip archive");
mz_zip_writer_end(&zip_archive);
return 0;
}
const char *pTestComment = "test comment";
//MZ_BEST_COMPRESSION = 9
if (!mz_zip_writer_add_file(&zip_archive, internalName.c_str(), fileName.c_str(), pTestComment, strlen(pTestComment), MZ_UBER_COMPRESSION)) {
qDebug("failed adding %s to %s", fileName.c_str(), zipName.c_str());
mz_zip_writer_end(&zip_archive);
return 0;
}
mz_zip_writer_finalize_archive(&zip_archive);
qDebug("Compressed %i",zip_archive.m_archive_size);
return 1;
}
// Core Function doing the actual mesh processing.
bool FilterSketchFabPlugin::applyFilter( const QString& filterName, MeshDocument& md, EnvWrap& env, vcg::CallBackPos * cb )
{
if (filterName == "Export to SketchFab")
{
qDebug("Export to SketchFab start ");
this->fcb=cb;
QString APIToken=env.evalString(Env::convertToAMLScriptValidName("MeshLab::Plugins::sketchFabKeyCode"));
this->fcb(1,"Compressing Mesh");
qDebug("APIToken = '%s' ",qPrintable(APIToken));
if(APIToken.isEmpty())
Matrix44m rot; rot.SetRotateDeg(-90,Point3m(1,0,0));
Matrix44m rotI; rot.SetRotateDeg(90,Point3m(1,0,0));
if(APIToken.isEmpty() || APIToken=="0000000")
{
this->errorMessage = QString("Please set APIToken");
this->errorMessage = QString("Please set in the MeshLab preferences your private API Token string that you can find on the<a href=\"https://sketchfab.com/settings/password\">Sketchfab Password Settings.");
return false;
}
this->apiToken = APIToken;
this->name = env.evalString("title");
this->description = env.evalString("description");
this->tags = env.evalString("tags");
QString tmpObjFileName = QDir::tempPath() + "/xxxx.ply";
QString tmpZipFileName = QDir::tempPath() + "/xxxx.zip";
int mask=0;
if(md.mm()->hasDataMask(MeshModel::MM_VERTCOLOR)) mask+=tri::io::Mask::IOM_VERTCOLOR;
tri::UpdatePosition<CMeshO>::Matrix(md.mm()->cm,rot);
vcg::tri::io::ExporterPLY<CMeshO>::Save(md.mm()->cm,qPrintable(tmpObjFileName),mask,true);
tri::UpdatePosition<CMeshO>::Matrix(md.mm()->cm,rotI);
qDebug("Saved %20s",qPrintable(tmpObjFileName));
qDebug("Compressed %20s",qPrintable(tmpZipFileName));
saveMeshZip(qPrintable(tmpObjFileName),"xxxx.ply",qPrintable(tmpZipFileName));
this->zipFileName = tmpZipFileName;
qDebug("Model Title %s %s %s\n",qPrintable(this->name),qPrintable(this->description),qPrintable(this->tags));
qDebug("Starting Upload");
this->fcb(10,"Starting Upload");
bool ret = this->upload();
if(!ret){
qDebug("Upload FAILED");
return false;
}
this->Log("Upload Completed\n");
this->Log("<a href=\"%s\">%s</a>\n",qPrintable(this->sketchfabModelUrl),qPrintable(this->sketchfabModelUrl));
return true;
}
return false;
@ -70,11 +119,14 @@ bool FilterSketchFabPlugin::applyFilter( const QString& filterName, MeshDocument
void FilterSketchFabPlugin::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
qDebug("Upload progress %i on %i",int(bytesSent),int(bytesTotal));
char buf[1024]; sprintf(buf,"Upload progress %i on %i",int(bytesSent),int(bytesTotal));
if(bytesTotal) this->fcb(100*int(bytesSent)/int(bytesTotal),buf);
}
void FilterSketchFabPlugin::finished()
{
qDebug("FilterSketchFabPlugin::finished()");
uploadCompleteFlag = true;
}
@ -85,28 +137,30 @@ QHttpPart part_parameter(QString key, QString value) {
return part;
}
bool FilterSketchFabPlugin::upload()
{
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
// upload parameters data
multiPart->append(part_parameter("token", "f7252b3a4f784323a7554923b48cccda"));
multiPart->append(part_parameter("name", "oh bunny bunny"));
multiPart->append(part_parameter("description", "Test of the api with a simple model"));
multiPart->append(part_parameter("tags", "bunnyhedron"));
multiPart->append(part_parameter("private", "1"));
multiPart->append(part_parameter("isPublished", "0"));
multiPart->append(part_parameter("token", this->apiToken));
multiPart->append(part_parameter("name", this->name));
multiPart->append(part_parameter("description", this->description));
multiPart->append(part_parameter("tags", this->tags));
multiPart->append(part_parameter("private", "0"));
multiPart->append(part_parameter("isPublished", "1"));
multiPart->append(part_parameter("source", "meshlab-exporter"));
// upload file data
QHttpPart modelPart;
modelPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"modelFile\"; filename=\""+this->zipFileName+"\""));
modelPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
modelPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"modelFile\"; filename=\"./bunny5k_bin.ply\""));
QFile *file = new QFile("/Users/cignoni/devel/meshlab/src/plugins_experimental/filter_sketchfab/bunny5k_bin.ply");
QFile *zipfileToUpload = new QFile(this->zipFileName);
file->open(QIODevice::ReadOnly);
modelPart.setBodyDevice(file);
file->setParent(multiPart);
zipfileToUpload->open(QIODevice::ReadOnly);
modelPart.setBodyDevice(zipfileToUpload);
zipfileToUpload->setParent(multiPart);
multiPart->append(modelPart);
QUrl url("https://api.sketchfab.com/v2/models");
@ -115,10 +169,10 @@ bool FilterSketchFabPlugin::upload()
QNetworkAccessManager manager;
QNetworkReply *reply = manager.post(request, multiPart);
multiPart->setParent(reply);
qDebug() << "Transmitting" << file->size() << "bytes file.";
qDebug() << "Transmitting" << zipfileToUpload->size() << "bytes file.";
QObject::connect(reply, SIGNAL(finished()), this, SLOT(finished()));
QObject::connect(reply, SIGNAL(uploadProgress(qint64,qint64)),this,SLOT(uploadProgress));
QObject::connect(reply, SIGNAL(uploadProgress(qint64,qint64)),this,SLOT(uploadProgress(qint64,qint64)));
uploadCompleteFlag=false;
while(!uploadCompleteFlag)
{
@ -141,12 +195,12 @@ bool FilterSketchFabPlugin::upload()
QString uid = sc.property("uid").toString();
if(uid.isEmpty()) return false;
qDebug() << "Model uploaded with id" << uid;
this->sketchfabModelUrl="https://sketchfab.com/models/"+uid;
return true;
}
/* *********** PER GUIDO ****************
* Ovviamente mi aspetto anche che uno debba aggiungere la propria funzione di inizializzazione una volta per tutte come per le altre globali...
*
*
void FilterSketchFabPlugin::initGlobalParameterSet(QAction *action, RichParameterSet &parset)
{

View File

@ -43,7 +43,13 @@ public slots:
void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
private:
inline QString SketchFabKeyCode() const { return "MeshLab::Filter::SketchFabKeyCode" ; }
QString apiToken;
QString description;
QString name;
QString tags;
QString zipFileName;
QString sketchfabModelUrl;
vcg::CallBackPos * fcb;
};
#endif

View File

@ -1,7 +1,7 @@
include (../../shared.pri)
HEADERS += filter_sketchfab.h
SOURCES += filter_sketchfab.cpp
SOURCES += filter_sketchfab.cpp $$VCGDIR//wrap/ply/plylib.cpp
TARGET = filter_sketchfab
#PRE_TARGETDEPS += filter_sketchfab.xml
macx:QMAKE_POST_LINK = "cp "$$_PRO_FILE_PWD_/$$TARGET".xml ../../distrib/plugins/"$$TARGET".xml"

View File

@ -1,32 +1,32 @@
<MESHLAB_FILTER_INTERFACE mfiVersion="2.0">
<PLUGIN pluginName="FilterSketchFab" pluginAuthor="Paolo Cignoni" pluginEmail="paolo.cignoni@isti.cnr.it">
<FILTER filterName="Export to SketchFab" filterFunction="exportToSketchFab" filterClass="Measure" filterPre="MM_NONE" filterPost="MM_NONE" filterArity="SingleMesh" filterRasterArity="NoRaster" filterIsInterruptible="false">
<FILTER_HELP><![CDATA[Upload a model on SketchFab.]]></FILTER_HELP>
<FILTER_HELP><![CDATA[Upload a model on SketchFab. It requires that you have an account and that you set your private API token in the preferences of MeshLab.]]></FILTER_HELP>
<FILTER_JSCODE><![CDATA[]]></FILTER_JSCODE>
<PARAM parType="String" parName="APIToken" parDefault="" parIsImportant="true">
<PARAM_HELP><![CDATA[Insert here the API Token string that you can find on the<a href="https://sketchfab.com/settings/password">Password Settings</a> SketchFab page. ]]></PARAM_HELP>
<STRING_GUI guiLabel="SketchFab API Token" />
</PARAM>
<PARAM parType="String" parName="title" parDefault="" parIsImportant="true">
<PARAM_HELP><![CDATA[Mandatory. ]]></PARAM_HELP>
<PARAM parType="String" parName="title" parDefault="MeshLabModel" parIsImportant="true">
<PARAM_HELP><![CDATA[Mandatory.]]></PARAM_HELP>
<STRING_GUI guiLabel="Title" />
</PARAM>
<PARAM parType="String" parName="description" parDefault="" parIsImportant="true">
<PARAM_HELP><![CDATA[Mandatory. ]]></PARAM_HELP>
<PARAM parType="String" parName="description" parDefault="a model generated with meshlab" parIsImportant="true">
<PARAM_HELP><![CDATA[Mandatory. A short description of the models ]]></PARAM_HELP>
<STRING_GUI guiLabel="description" />
</PARAM>
<PARAM parType="String" parName="tags" parDefault="" parIsImportant="true">
<PARAM_HELP><![CDATA[Mandatory. ]]></PARAM_HELP>
<PARAM parType="String" parName="tags" parDefault="scan" parIsImportant="true">
<PARAM_HELP><![CDATA[Mandatory. Typical tags usually used by MeshLab users: scan, photogrammetry ]]></PARAM_HELP>
<STRING_GUI guiLabel="Tags" />
</PARAM>
<PARAM parName="private" parIsImportant="true" parType="Boolean" parDefault="false">
<PARAM_HELP><![CDATA[ If true ]]></PARAM_HELP>
<PARAM parName="private" parIsImportant="false" parType="Boolean" parDefault="false">
<PARAM_HELP><![CDATA[ This parameter can be true only for PRO account. ]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Private"/>
</PARAM>
<PARAM parName="isPublished" parIsImportant="true" parType="Boolean" parDefault="false">
<PARAM_HELP><![CDATA[ If true the model will be published immediately ]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Publish"/>
</PARAM>
<PARAM parName="autoRotate" parIsImportant="false" parType="Boolean" parDefault="true">
<PARAM_HELP><![CDATA[ If true the model rotated by 90 degree on the X axis to maintain similar default orientation.]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Auto Rotate"/>
</PARAM>
</FILTER>
</PLUGIN>
</MESHLAB_FILTER_INTERFACE>

File diff suppressed because it is too large Load Diff