Merge pull request #11028 from sethalves/script-getmeshes-for-models

Script getmeshes for models
This commit is contained in:
Andrew Meadows 2017-07-24 23:01:53 -07:00 committed by GitHub
commit a21da8613c
14 changed files with 187 additions and 24 deletions

View file

@ -23,6 +23,7 @@
#include <PerfStat.h>
#include <render/Scene.h>
#include <DependencyManager.h>
#include <shared/QtHelpers.h>
#include "EntityTreeRenderer.h"
#include "EntitiesRendererLogging.h"
@ -1282,3 +1283,11 @@ void RenderableModelEntityItem::mapJoints(const QStringList& modelJointNames) {
}
}
}
bool RenderableModelEntityItem::getMeshes(MeshProxyList& result) {
if (!_model || !_model->isLoaded()) {
return false;
}
BLOCKING_INVOKE_METHOD(_model.get(), "getMeshes", Q_RETURN_ARG(MeshProxyList, result));
return !result.isEmpty();
}

View file

@ -116,6 +116,8 @@ public:
return _animation;
}
bool getMeshes(MeshProxyList& result) override;
private:
QVariantMap parseTexturesToMap(QString textures);
void remapTextures();

View file

@ -1663,6 +1663,7 @@ bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) {
// the mesh will be in voxel-space. transform it into object-space
meshProxy = new SimpleMeshProxy(
_mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
[=](glm::vec3 color){ return color; },
[=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); },
[&](uint32_t index){ return index; }));
result << meshProxy;

View file

@ -1736,9 +1736,7 @@ glm::mat4 EntityScriptingInterface::getEntityTransform(const QUuid& entityID) {
if (entity) {
glm::mat4 translation = glm::translate(entity->getPosition());
glm::mat4 rotation = glm::mat4_cast(entity->getRotation());
glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT -
entity->getRegistrationPoint());
result = translation * rotation * registration;
result = translation * rotation;
}
});
}
@ -1753,9 +1751,7 @@ glm::mat4 EntityScriptingInterface::getEntityLocalTransform(const QUuid& entityI
if (entity) {
glm::mat4 translation = glm::translate(entity->getLocalPosition());
glm::mat4 rotation = glm::mat4_cast(entity->getLocalOrientation());
glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT -
entity->getRegistrationPoint());
result = translation * rotation * registration;
result = translation * rotation;
}
});
}

View file

@ -118,7 +118,7 @@ glm::vec3 OBJTokenizer::getVec3() {
auto z = getFloat();
auto v = glm::vec3(x, y, z);
while (isNextTokenFloat()) {
// the spec(s) get(s) vague here. might be w, might be a color... chop it off.
// ignore any following floats
nextToken();
}
return v;
@ -139,7 +139,7 @@ bool OBJTokenizer::getVertex(glm::vec3& vertex, glm::vec3& vertexColor) {
// only a single value) that it's a vertex color.
r = getFloat();
if (isNextTokenFloat()) {
// Safe to assume the following values are the green/blue components.
// Safe to assume the following values are the green/blue components.
g = getFloat();
b = getFloat();
@ -351,6 +351,8 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi
bool result = true;
int originalFaceCountForDebugging = 0;
QString currentGroup;
bool anyVertexColor { false };
int vertexCount { 0 };
setMeshPartDefaults(meshPart, QString("dontknow") + QString::number(mesh.parts.count()));
@ -412,14 +414,25 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi
#endif
}
} else if (token == "v") {
glm::vec3 vertex, vertexColor;
glm::vec3 vertex;
glm::vec3 vertexColor { glm::vec3(1.0f) };
bool hasVertexColor = tokenizer.getVertex(vertex, vertexColor);
vertices.append(vertex);
if(hasVertexColor) {
// if any vertex has color, they all need to.
if (hasVertexColor && !anyVertexColor) {
// we've had a gap of zero or more vertices without color, followed
// by one that has color. catch up:
for (int i = 0; i < vertexCount; i++) {
vertexColors.append(glm::vec3(1.0f));
}
anyVertexColor = true;
}
if (anyVertexColor) {
vertexColors.append(vertexColor);
}
vertexCount++;
} else if (token == "vn") {
normals.append(tokenizer.getVec3());
} else if (token == "vt") {

View file

@ -40,8 +40,6 @@ static QString formatFloat(double n) {
}
bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h
// each mesh's vertices are numbered from zero. We're combining all their vertices into one list here,
// so keep track of the start index for each mesh.
QList<int> meshVertexStartOffset;
@ -49,10 +47,15 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
int currentVertexStartOffset = 0;
int currentNormalStartOffset = 0;
// write out vertices
// write out vertices (and maybe colors)
foreach (const MeshPointer& mesh, meshes) {
meshVertexStartOffset.append(currentVertexStartOffset);
const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer();
const gpu::BufferView& colorsBufferView = mesh->getAttributeBuffer(gpu::Stream::COLOR);
gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements();
gpu::BufferView::Index colorIndex = 0;
int vertexCount = 0;
gpu::BufferView::Iterator<const glm::vec3> vertexItr = vertexBuffer.cbegin<const glm::vec3>();
while (vertexItr != vertexBuffer.cend<const glm::vec3>()) {
@ -60,7 +63,15 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
out << "v ";
out << formatFloat(v[0]) << " ";
out << formatFloat(v[1]) << " ";
out << formatFloat(v[2]) << "\n";
out << formatFloat(v[2]);
if (colorIndex < numColors) {
glm::vec3 color = colorsBufferView.get<glm::vec3>(colorIndex);
out << " " << formatFloat(color[0]);
out << " " << formatFloat(color[1]);
out << " " << formatFloat(color[2]);
colorIndex++;
}
out << "\n";
vertexItr++;
vertexCount++;
}
@ -72,7 +83,7 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
bool haveNormals = true;
foreach (const MeshPointer& mesh, meshes) {
meshNormalStartOffset.append(currentNormalStartOffset);
const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal);
const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(gpu::Stream::InputSlot::NORMAL);
gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements();
for (gpu::BufferView::Index i = 0; i < numNormals; i++) {
glm::vec3 normal = normalsBufferView.get<glm::vec3>(i);

View file

@ -192,7 +192,7 @@ public:
BufferView(const BufferPointer& buffer, Size offset, Size size, const Element& element = DEFAULT_ELEMENT);
BufferView(const BufferPointer& buffer, Size offset, Size size, uint16 stride, const Element& element = DEFAULT_ELEMENT);
Size getNumElements() const { return (_size - _offset) / _stride; }
Size getNumElements() const { return _size / _stride; }
//Template iterator with random access on the buffer sysmem
template<typename T>

View file

@ -11,8 +11,6 @@
#include "Geometry.h"
#include <QDebug>
using namespace model;
Mesh::Mesh() :
@ -136,11 +134,13 @@ Box Mesh::evalPartsBound(int partStart, int partEnd) const {
model::MeshPointer Mesh::map(std::function<glm::vec3(glm::vec3)> vertexFunc,
std::function<glm::vec3(glm::vec3)> colorFunc,
std::function<glm::vec3(glm::vec3)> normalFunc,
std::function<uint32_t(uint32_t)> indexFunc) {
std::function<uint32_t(uint32_t)> indexFunc) const {
// vertex data
const gpu::BufferView& vertexBufferView = getVertexBuffer();
gpu::BufferView::Index numVertices = (gpu::BufferView::Index)getNumVertices();
gpu::Resource::Size vertexSize = numVertices * sizeof(glm::vec3);
unsigned char* resultVertexData = new unsigned char[vertexSize];
unsigned char* vertexDataCursor = resultVertexData;
@ -151,6 +151,21 @@ model::MeshPointer Mesh::map(std::function<glm::vec3(glm::vec3)> vertexFunc,
vertexDataCursor += sizeof(pos);
}
// color data
int attributeTypeColor = gpu::Stream::COLOR;
const gpu::BufferView& colorsBufferView = getAttributeBuffer(attributeTypeColor);
gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements();
gpu::Resource::Size colorSize = numColors * sizeof(glm::vec3);
unsigned char* resultColorData = new unsigned char[colorSize];
unsigned char* colorDataCursor = resultColorData;
for (gpu::BufferView::Index i = 0; i < numColors; i++) {
glm::vec3 color = colorFunc(colorsBufferView.get<glm::vec3>(i));
memcpy(colorDataCursor, &color, sizeof(color));
colorDataCursor += sizeof(color);
}
// normal data
int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h
const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal);
@ -187,6 +202,12 @@ model::MeshPointer Mesh::map(std::function<glm::vec3(glm::vec3)> vertexFunc,
gpu::BufferView resultVertexBufferView(resultVertexBufferPointer, vertexElement);
result->setVertexBuffer(resultVertexBufferView);
gpu::Element colorElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ);
gpu::Buffer* resultColorsBuffer = new gpu::Buffer(colorSize, resultColorData);
gpu::BufferPointer resultColorsBufferPointer(resultColorsBuffer);
gpu::BufferView resultColorsBufferView(resultColorsBufferPointer, colorElement);
result->addAttribute(attributeTypeColor, resultColorsBufferView);
gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ);
gpu::Buffer* resultNormalsBuffer = new gpu::Buffer(normalSize, resultNormalData);
gpu::BufferPointer resultNormalsBufferPointer(resultNormalsBuffer);
@ -215,6 +236,7 @@ model::MeshPointer Mesh::map(std::function<glm::vec3(glm::vec3)> vertexFunc,
void Mesh::forEach(std::function<void(glm::vec3)> vertexFunc,
std::function<void(glm::vec3)> colorFunc,
std::function<void(glm::vec3)> normalFunc,
std::function<void(uint32_t)> indexFunc) {
// vertex data
@ -224,6 +246,14 @@ void Mesh::forEach(std::function<void(glm::vec3)> vertexFunc,
vertexFunc(vertexBufferView.get<glm::vec3>(i));
}
// color data
int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h
const gpu::BufferView& colorsBufferView = getAttributeBuffer(attributeTypeColor);
gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements();
for (gpu::BufferView::Index i = 0; i < numColors; i++) {
colorFunc(colorsBufferView.get<glm::vec3>(i));
}
// normal data
int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h
const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal);

View file

@ -123,10 +123,12 @@ public:
// create a copy of this mesh after passing its vertices, normals, and indexes though the provided functions
MeshPointer map(std::function<glm::vec3(glm::vec3)> vertexFunc,
std::function<glm::vec3(glm::vec3)> colorFunc,
std::function<glm::vec3(glm::vec3)> normalFunc,
std::function<uint32_t(uint32_t)> indexFunc);
std::function<uint32_t(uint32_t)> indexFunc) const;
void forEach(std::function<void(glm::vec3)> vertexFunc,
std::function<void(glm::vec3)> colorFunc,
std::function<void(glm::vec3)> normalFunc,
std::function<void(uint32_t)> indexFunc);

View file

@ -24,6 +24,7 @@
#include <PerfStat.h>
#include <ViewFrustum.h>
#include <GLMHelpers.h>
#include <model-networking/SimpleMeshProxy.h>
#include "AbstractViewStateInterface.h"
#include "MeshPartPayload.h"
@ -462,6 +463,41 @@ bool Model::convexHullContains(glm::vec3 point) {
return false;
}
MeshProxyList Model::getMeshes() const {
MeshProxyList result;
const Geometry::Pointer& renderGeometry = getGeometry();
const Geometry::GeometryMeshes& meshes = renderGeometry->getMeshes();
if (!isLoaded()) {
return result;
}
Transform offset;
offset.setScale(_scale);
offset.postTranslate(_offset);
glm::mat4 offsetMat = offset.getMatrix();
for (std::shared_ptr<const model::Mesh> mesh : meshes) {
if (!mesh) {
continue;
}
MeshProxy* meshProxy = new SimpleMeshProxy(
mesh->map(
[=](glm::vec3 position) {
return glm::vec3(offsetMat * glm::vec4(position, 1.0f));
},
[=](glm::vec3 color) { return color; },
[=](glm::vec3 normal) {
return glm::normalize(glm::vec3(offsetMat * glm::vec4(normal, 0.0f)));
},
[&](uint32_t index) { return index; }));
result << meshProxy;
}
return result;
}
void Model::calculateTriangleSets() {
PROFILE_RANGE(render, __FUNCTION__);

View file

@ -257,6 +257,8 @@ public:
int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); }
int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); }
Q_INVOKABLE MeshProxyList getMeshes() const;
public slots:
void loadURLFinished(bool success);

View file

@ -38,16 +38,22 @@ QString ModelScriptingInterface::meshToOBJ(MeshProxyList in) {
QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) {
// figure out the size of the resulting mesh
size_t totalVertexCount { 0 };
size_t totalAttributeCount { 0 };
size_t totalColorCount { 0 };
size_t totalNormalCount { 0 };
size_t totalIndexCount { 0 };
foreach (const MeshProxy* meshProxy, in) {
MeshPointer mesh = meshProxy->getMeshPointer();
totalVertexCount += mesh->getNumVertices();
int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h
const gpu::BufferView& colorsBufferView = mesh->getAttributeBuffer(attributeTypeColor);
gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements();
totalColorCount += numColors;
int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h
const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal);
gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements();
totalAttributeCount += numNormals;
totalNormalCount += numNormals;
totalIndexCount += mesh->getNumIndices();
}
@ -57,7 +63,11 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) {
unsigned char* combinedVertexData = new unsigned char[combinedVertexSize];
unsigned char* combinedVertexDataCursor = combinedVertexData;
gpu::Resource::Size combinedNormalSize = totalAttributeCount * sizeof(glm::vec3);
gpu::Resource::Size combinedColorSize = totalColorCount * sizeof(glm::vec3);
unsigned char* combinedColorData = new unsigned char[combinedColorSize];
unsigned char* combinedColorDataCursor = combinedColorData;
gpu::Resource::Size combinedNormalSize = totalNormalCount * sizeof(glm::vec3);
unsigned char* combinedNormalData = new unsigned char[combinedNormalSize];
unsigned char* combinedNormalDataCursor = combinedNormalData;
@ -74,6 +84,10 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) {
memcpy(combinedVertexDataCursor, &position, sizeof(position));
combinedVertexDataCursor += sizeof(position);
},
[&](glm::vec3 color){
memcpy(combinedColorDataCursor, &color, sizeof(color));
combinedColorDataCursor += sizeof(color);
},
[&](glm::vec3 normal){
memcpy(combinedNormalDataCursor, &normal, sizeof(normal));
combinedNormalDataCursor += sizeof(normal);
@ -96,6 +110,13 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) {
gpu::BufferView combinedVertexBufferView(combinedVertexBufferPointer, vertexElement);
result->setVertexBuffer(combinedVertexBufferView);
int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h
gpu::Element colorElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ);
gpu::Buffer* combinedColorsBuffer = new gpu::Buffer(combinedColorSize, combinedColorData);
gpu::BufferPointer combinedColorsBufferPointer(combinedColorsBuffer);
gpu::BufferView combinedColorsBufferView(combinedColorsBufferPointer, colorElement);
result->addAttribute(attributeTypeColor, combinedColorsBufferView);
int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h
gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ);
gpu::Buffer* combinedNormalsBuffer = new gpu::Buffer(combinedNormalSize, combinedNormalData);
@ -132,12 +153,48 @@ QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshPro
}
model::MeshPointer result = mesh->map([&](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
[&](glm::vec3 color){ return color; },
[&](glm::vec3 normal){ return glm::vec3(transform * glm::vec4(normal, 0.0f)); },
[&](uint32_t index){ return index; });
MeshProxy* resultProxy = new SimpleMeshProxy(result);
return meshToScriptValue(_modelScriptEngine, resultProxy);
}
QScriptValue ModelScriptingInterface::getVertexCount(MeshProxy* meshProxy) {
if (!meshProxy) {
return QScriptValue(false);
}
MeshPointer mesh = meshProxy->getMeshPointer();
if (!mesh) {
return QScriptValue(false);
}
gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices();
return numVertices;
}
QScriptValue ModelScriptingInterface::getVertex(MeshProxy* meshProxy, int vertexIndex) {
if (!meshProxy) {
return QScriptValue(false);
}
MeshPointer mesh = meshProxy->getMeshPointer();
if (!mesh) {
return QScriptValue(false);
}
const gpu::BufferView& vertexBufferView = mesh->getVertexBuffer();
gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices();
if (vertexIndex < 0 || vertexIndex >= numVertices) {
return QScriptValue(false);
}
glm::vec3 pos = vertexBufferView.get<glm::vec3>(vertexIndex);
return vec3toScriptValue(_modelScriptEngine, pos);
}
QScriptValue ModelScriptingInterface::newMesh(const QVector<glm::vec3>& vertices,
const QVector<glm::vec3>& normals,
const QVector<MeshFace>& faces) {

View file

@ -29,6 +29,8 @@ public:
Q_INVOKABLE QScriptValue newMesh(const QVector<glm::vec3>& vertices,
const QVector<glm::vec3>& normals,
const QVector<MeshFace>& faces);
Q_INVOKABLE QScriptValue getVertexCount(MeshProxy* meshProxy);
Q_INVOKABLE QScriptValue getVertex(MeshProxy* meshProxy, int vertexIndex);
private:
QScriptEngine* _modelScriptEngine { nullptr };

View file

@ -23,6 +23,7 @@
#include <DependencyManager.h>
#include <SettingHandle.h>
#include <AssetUpload.h>
#include <StatTracker.h>
#include "ATPClientApp.h"
@ -137,6 +138,7 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) :
Setting::init();
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
DependencyManager::set<StatTracker>();
DependencyManager::set<AccountManager>([&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); });
DependencyManager::set<AddressManager>();
DependencyManager::set<NodeList>(NodeType::Agent, _listenPort);