mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 19:29:47 +02:00
obj file is now produced in /tmp
This commit is contained in:
parent
5131d1edf2
commit
bb3155ee61
6 changed files with 194 additions and 77 deletions
|
@ -1167,6 +1167,14 @@ void RenderablePolyVoxEntityItem::recomputeMesh() {
|
||||||
vertexBufferPtr->getSize() ,
|
vertexBufferPtr->getSize() ,
|
||||||
sizeof(PolyVox::PositionMaterialNormal),
|
sizeof(PolyVox::PositionMaterialNormal),
|
||||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)));
|
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)));
|
||||||
|
|
||||||
|
std::vector<model::Mesh::Part> parts;
|
||||||
|
parts.emplace_back(model::Mesh::Part(0, // startIndex
|
||||||
|
vecIndices.size(), // numIndices
|
||||||
|
0, // baseVertex
|
||||||
|
model::Mesh::TRIANGLES)); // topology
|
||||||
|
mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part),
|
||||||
|
(gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL));
|
||||||
entity->setMesh(mesh);
|
entity->setMesh(mesh);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// FBXReader.h
|
// OBJWriter.cpp
|
||||||
// libraries/fbx/src/
|
// libraries/fbx/src/
|
||||||
//
|
//
|
||||||
// Created by Seth Alves on 2017-1-27.
|
// Created by Seth Alves on 2017-1-27.
|
||||||
|
@ -9,63 +9,126 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include "model/Geometry.h"
|
||||||
#include "OBJWriter.h"
|
#include "OBJWriter.h"
|
||||||
|
|
||||||
|
|
||||||
bool writeOBJ(QString outFileName, QVector<model::Mesh>) {
|
|
||||||
//bool writeOBJ(QString outFileName, FBXGeometry& geometry, bool outputCentimeters, int whichMeshPart) {
|
|
||||||
// QFile file(outFileName);
|
|
||||||
// if (!file.open(QIODevice::WriteOnly)) {
|
|
||||||
// qWarning() << "unable to write to" << outFileName;
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// QTextStream out(&file);
|
static QString formatFloat(double n) {
|
||||||
// if (outputCentimeters) {
|
// limit precision to 6, but don't output trailing zeros.
|
||||||
// out << "# This file uses centimeters as units\n\n";
|
QString s = QString::number(n, 'f', 6);
|
||||||
// }
|
while (s.endsWith("0")) {
|
||||||
|
s.remove(s.size() - 1, 1);
|
||||||
|
}
|
||||||
|
if (s.endsWith(".")) {
|
||||||
|
s.remove(s.size() - 1, 1);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
// unsigned int nth = 0;
|
|
||||||
|
|
||||||
// // vertex indexes in obj files span the entire file
|
|
||||||
// // vertex indexes in a mesh span just that mesh
|
|
||||||
|
|
||||||
// int vertexIndexOffset = 0;
|
bool writeOBJToTextStream(QTextStream& out, std::vector<MeshPointer> meshes) {
|
||||||
|
qDebug() << "writeOBJToTextStream mesh count is" << meshes.size();
|
||||||
|
|
||||||
// foreach (const FBXMesh& mesh, geometry.meshes) {
|
// each mesh's vertices are numbered from zero. We're combining all their vertices into one list here,
|
||||||
// bool verticesHaveBeenOutput = false;
|
// so keep track of the start index for each mesh.
|
||||||
// foreach (const FBXMeshPart &meshPart, mesh.parts) {
|
QList<int> meshVertexStartOffset;
|
||||||
// if (whichMeshPart >= 0 && nth != (unsigned int) whichMeshPart) {
|
int currentVertexStartOffset = 0;
|
||||||
// nth++;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!verticesHaveBeenOutput) {
|
// write out all vertices
|
||||||
// for (int i = 0; i < mesh.vertices.size(); i++) {
|
foreach (const MeshPointer& mesh, meshes) {
|
||||||
// glm::vec4 v = mesh.modelTransform * glm::vec4(mesh.vertices[i], 1.0f);
|
meshVertexStartOffset.append(currentVertexStartOffset);
|
||||||
// out << "v ";
|
const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer();
|
||||||
// out << formatFloat(v[0]) << " ";
|
int vertexCount = 0;
|
||||||
// out << formatFloat(v[1]) << " ";
|
gpu::BufferView::Iterator<const glm::vec3> vertexItr = vertexBuffer.cbegin<const glm::vec3>();
|
||||||
// out << formatFloat(v[2]) << "\n";
|
while (vertexItr != vertexBuffer.cend<const glm::vec3>()) {
|
||||||
// }
|
glm::vec3 v = *vertexItr;
|
||||||
// verticesHaveBeenOutput = true;
|
out << "v ";
|
||||||
// }
|
out << formatFloat(v[0]) << " ";
|
||||||
|
out << formatFloat(v[1]) << " ";
|
||||||
|
out << formatFloat(v[2]) << "\n";
|
||||||
|
vertexItr++;
|
||||||
|
vertexCount++;
|
||||||
|
}
|
||||||
|
currentVertexStartOffset += vertexCount;
|
||||||
|
}
|
||||||
|
out << "\n";
|
||||||
|
|
||||||
// out << "g hull-" << nth++ << "\n";
|
// write out faces
|
||||||
// int triangleCount = meshPart.triangleIndices.size() / 3;
|
int nth = 0;
|
||||||
// for (int i = 0; i < triangleCount; i++) {
|
foreach (const MeshPointer& mesh, meshes) {
|
||||||
// out << "f ";
|
currentVertexStartOffset = meshVertexStartOffset.takeFirst();
|
||||||
// out << vertexIndexOffset + meshPart.triangleIndices[i*3] + 1 << " ";
|
|
||||||
// out << vertexIndexOffset + meshPart.triangleIndices[i*3+1] + 1 << " ";
|
|
||||||
// out << vertexIndexOffset + meshPart.triangleIndices[i*3+2] + 1 << "\n";
|
|
||||||
// }
|
|
||||||
// out << "\n";
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (verticesHaveBeenOutput) {
|
const gpu::BufferView& partBuffer = mesh->getPartBuffer();
|
||||||
// vertexIndexOffset += mesh.vertices.size();
|
const gpu::BufferView& indexBuffer = mesh->getIndexBuffer();
|
||||||
// }
|
// const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer();
|
||||||
// }
|
|
||||||
|
int partCount = mesh->getNumParts();
|
||||||
|
qDebug() << "writeOBJToTextStream part count is" << partCount;
|
||||||
|
for (int partIndex = 0; partIndex < partCount; partIndex++) {
|
||||||
|
const model::Mesh::Part& part = partBuffer.get<model::Mesh::Part>(partIndex);
|
||||||
|
|
||||||
|
out << "g part-" << nth++ << "\n";
|
||||||
|
|
||||||
|
// model::Mesh::TRIANGLES
|
||||||
|
// XXX handle other formats
|
||||||
|
gpu::BufferView::Iterator<const uint32_t> indexItr = indexBuffer.cbegin<uint32_t>();
|
||||||
|
indexItr += part._startIndex;
|
||||||
|
|
||||||
|
int indexCount = 0;
|
||||||
|
while (indexItr != indexBuffer.cend<uint32_t>() && indexItr != part._numIndices) {
|
||||||
|
uint32_t index0 = *indexItr;
|
||||||
|
indexItr++;
|
||||||
|
indexCount++;
|
||||||
|
if (indexItr == indexBuffer.cend<uint32_t>() || indexItr == part._numIndices) {
|
||||||
|
qDebug() << "OBJWriter -- index buffer length isn't multiple of 3";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uint32_t index1 = *indexItr;
|
||||||
|
indexItr++;
|
||||||
|
indexCount++;
|
||||||
|
if (indexItr == indexBuffer.cend<uint32_t>() || indexItr == part._numIndices) {
|
||||||
|
qDebug() << "OBJWriter -- index buffer length isn't multiple of 3";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uint32_t index2 = *indexItr;
|
||||||
|
indexItr++;
|
||||||
|
indexCount++;
|
||||||
|
|
||||||
|
out << "f ";
|
||||||
|
out << currentVertexStartOffset + index0 + 1 << " ";
|
||||||
|
out << currentVertexStartOffset + index1 + 1 << " ";
|
||||||
|
out << currentVertexStartOffset + index2 + 1 << "\n";
|
||||||
|
}
|
||||||
|
out << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool writeOBJToFile(QString path, MeshPointer mesh) {
|
||||||
|
if (QFileInfo(path).exists() && !QFile::remove(path)) {
|
||||||
|
qDebug() << "OBJ writer failed, file exists:" << path; // XXX qCDebug
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(path);
|
||||||
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
|
qDebug() << "OBJ writer failed to open output file:" << path; // XXX qCDebug
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream outStream(&file);
|
||||||
|
|
||||||
|
bool success;
|
||||||
|
std::vector<MeshPointer> meshes { mesh };
|
||||||
|
success = writeOBJToTextStream(outStream, meshes);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,26 @@
|
||||||
|
//
|
||||||
|
// OBJWriter.h
|
||||||
|
// libraries/fbx/src/
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2017-1-27.
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_objwriter_h
|
||||||
|
#define hifi_objwriter_h
|
||||||
|
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <model/Geometry.h>
|
#include <model/Geometry.h>
|
||||||
|
|
||||||
bool writeOBJ(QString outFileName, QVector<model::Mesh>);
|
using MeshPointer = std::shared_ptr<model::Mesh>;
|
||||||
|
|
||||||
|
bool writeOBJToTextStream(QTextStream& out, std::vector<MeshPointer> meshes);
|
||||||
|
bool writeOBJToFile(QString path, MeshPointer mesh);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // hifi_objwriter_h
|
||||||
|
|
39
libraries/script-engine/src/MeshProxy.h
Normal file
39
libraries/script-engine/src/MeshProxy.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// MeshProxy.h
|
||||||
|
// libraries/script-engine/src
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2017-1-27.
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_MeshProxy_h
|
||||||
|
#define hifi_MeshProxy_h
|
||||||
|
|
||||||
|
#include <model/Geometry.h>
|
||||||
|
|
||||||
|
using MeshPointer = std::shared_ptr<model::Mesh>;
|
||||||
|
|
||||||
|
class MeshProxy : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MeshProxy(MeshPointer mesh) : _mesh(mesh) {}
|
||||||
|
~MeshProxy() {}
|
||||||
|
|
||||||
|
MeshPointer getMeshPointer() const { return _mesh; }
|
||||||
|
|
||||||
|
Q_INVOKABLE int getNumVertices() const { return _mesh->getNumVertices(); }
|
||||||
|
Q_INVOKABLE glm::vec3 getPos3(int index) const { return _mesh->getPos3(index); }
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MeshPointer _mesh;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(MeshProxy*);
|
||||||
|
|
||||||
|
#endif // hifi_MeshProxy_h
|
|
@ -12,18 +12,12 @@
|
||||||
#include <QScriptEngine>
|
#include <QScriptEngine>
|
||||||
#include <QtScript/QScriptValue>
|
#include <QtScript/QScriptValue>
|
||||||
#include "ModelScriptingInterface.h"
|
#include "ModelScriptingInterface.h"
|
||||||
|
#include "OBJWriter.h"
|
||||||
|
|
||||||
|
|
||||||
ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) {
|
ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MeshProxy::MeshProxy(MeshPointer mesh) : _mesh(mesh) {
|
|
||||||
}
|
|
||||||
|
|
||||||
MeshProxy::~MeshProxy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) {
|
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) {
|
||||||
return engine->newQObject(in, QScriptEngine::QtOwnership,
|
return engine->newQObject(in, QScriptEngine::QtOwnership,
|
||||||
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
|
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
|
||||||
|
@ -32,3 +26,13 @@ QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) {
|
||||||
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) {
|
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) {
|
||||||
out = qobject_cast<MeshProxy*>(value.toQObject());
|
out = qobject_cast<MeshProxy*>(value.toQObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ModelScriptingInterface::meshToOBJ(MeshProxy* const &in) {
|
||||||
|
bool success;
|
||||||
|
QString filename = "/tmp/okokok.obj";
|
||||||
|
success = writeOBJToFile(filename, in->getMeshPointer());
|
||||||
|
if (!success) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <QScriptValue>
|
#include <QScriptValue>
|
||||||
#include <OBJWriter.h>
|
#include <OBJWriter.h>
|
||||||
#include <model/Geometry.h>
|
#include <model/Geometry.h>
|
||||||
|
#include "MeshProxy.h"
|
||||||
|
|
||||||
using MeshPointer = std::shared_ptr<model::Mesh>;
|
using MeshPointer = std::shared_ptr<model::Mesh>;
|
||||||
|
|
||||||
|
@ -25,30 +26,12 @@ class ModelScriptingInterface : public QObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ModelScriptingInterface(QObject* parent);
|
ModelScriptingInterface(QObject* parent);
|
||||||
|
|
||||||
|
Q_INVOKABLE QString meshToOBJ(MeshProxy* const &in);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MeshProxy : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MeshProxy(MeshPointer mesh);
|
|
||||||
// MeshProxy(const MeshProxy& meshProxy) { _mesh = meshProxy.getMeshPointer(); }
|
|
||||||
~MeshProxy();
|
|
||||||
|
|
||||||
MeshPointer getMeshPointer() const { return _mesh; }
|
|
||||||
|
|
||||||
Q_INVOKABLE int getNumVertices() const { return _mesh->getNumVertices(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
MeshPointer _mesh;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(MeshProxy*);
|
|
||||||
|
|
||||||
|
|
||||||
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in);
|
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in);
|
||||||
// QScriptValue meshToScriptValue(QScriptEngine* engine, const MeshPointer& in);
|
|
||||||
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out);
|
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out);
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_ModelScriptingInterface_h
|
#endif // hifi_ModelScriptingInterface_h
|
||||||
|
|
Loading…
Reference in a new issue