mirror of
https://github.com/overte-org/overte.git
synced 2025-06-07 08:33:03 +02:00
187 lines
6.7 KiB
C++
187 lines
6.7 KiB
C++
//
|
|
// Created by Bradley Austin Davis on 2016/05/16
|
|
// Copyright 2014 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
|
|
//
|
|
|
|
#include "TestFbx.h"
|
|
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
#include <QtCore/QFile>
|
|
|
|
#include <FBXSerializer.h>
|
|
|
|
struct MyVertex {
|
|
vec3 position;
|
|
vec2 texCoords;
|
|
vec3 normal;
|
|
uint32_t color;
|
|
|
|
static gpu::Stream::FormatPointer getVertexFormat() {
|
|
static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
|
static const gpu::Element TEXTURE_ELEMENT { gpu::VEC2, gpu::FLOAT, gpu::UV };
|
|
static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
|
static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA };
|
|
gpu::Stream::FormatPointer vertexFormat { std::make_shared<gpu::Stream::Format>() };
|
|
vertexFormat->setAttribute(gpu::Stream::POSITION, 0, POSITION_ELEMENT, offsetof(MyVertex, position));
|
|
vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, TEXTURE_ELEMENT, offsetof(MyVertex, texCoords));
|
|
vertexFormat->setAttribute(gpu::Stream::COLOR, 0, COLOR_ELEMENT, offsetof(MyVertex, color));
|
|
vertexFormat->setAttribute(gpu::Stream::NORMAL, 0, NORMAL_ELEMENT, offsetof(MyVertex, normal));
|
|
return vertexFormat;
|
|
}
|
|
|
|
};
|
|
|
|
struct Part {
|
|
size_t baseVertex;
|
|
size_t baseIndex;
|
|
size_t materialId;
|
|
};
|
|
|
|
struct DrawElementsIndirectCommand {
|
|
uint count { 0 };
|
|
uint instanceCount { 1 };
|
|
uint firstIndex { 0 };
|
|
uint baseVertex { 0 };
|
|
uint baseInstance { 0 };
|
|
};
|
|
|
|
|
|
class FileDownloader : public QObject {
|
|
Q_OBJECT
|
|
public:
|
|
explicit FileDownloader(QUrl imageUrl, QObject *parent = 0) : QObject(parent) {
|
|
connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileDownloaded(QNetworkReply*)));
|
|
QNetworkRequest request(imageUrl);
|
|
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
|
m_WebCtrl.get(request);
|
|
}
|
|
|
|
virtual ~FileDownloader() {}
|
|
|
|
const QByteArray& downloadedData() const {
|
|
return m_DownloadedData;
|
|
}
|
|
|
|
signals:
|
|
void downloaded();
|
|
|
|
private slots:
|
|
void fileDownloaded(QNetworkReply* pReply) {
|
|
m_DownloadedData = pReply->readAll();
|
|
pReply->deleteLater();
|
|
emit downloaded();
|
|
}
|
|
|
|
private:
|
|
QNetworkAccessManager m_WebCtrl;
|
|
QByteArray m_DownloadedData;
|
|
};
|
|
|
|
|
|
static const QUrl TEST_ASSET = QString("https://s3.amazonaws.com/DreamingContent/assets/models/tardis/console.fbx");
|
|
static const mat4 TEST_ASSET_TRANSFORM = glm::translate(mat4(), vec3(0, -1.5f, 0)) * glm::scale(mat4(), vec3(0.01f));
|
|
//static const QUrl TEST_ASSET = QString("https://s3.amazonaws.com/DreamingContent/assets/simple/SimpleMilitary/Models/Vehicles/tank_02_c.fbx");
|
|
//static const mat4 TEST_ASSET_TRANSFORM = glm::translate(mat4(), vec3(0, -0.5f, 0)) * glm::scale(mat4(), vec3(0.1f));
|
|
|
|
TestFbx::TestFbx(const render::ShapePlumberPointer& shapePlumber) : _shapePlumber(shapePlumber) {
|
|
FileDownloader* downloader = new FileDownloader(TEST_ASSET, qApp);
|
|
QObject::connect(downloader, &FileDownloader::downloaded, [this, downloader] {
|
|
parseFbx(downloader->downloadedData());
|
|
});
|
|
}
|
|
|
|
bool TestFbx::isReady() const {
|
|
return _partCount != 0;
|
|
}
|
|
|
|
void TestFbx::parseFbx(const QByteArray& fbxData) {
|
|
QVariantHash mapping;
|
|
HFMModel::Pointer hfmModel = FBXSerializer().read(fbxData, mapping);
|
|
size_t totalVertexCount = 0;
|
|
size_t totalIndexCount = 0;
|
|
size_t totalPartCount = 0;
|
|
size_t highestIndex = 0;
|
|
for (const auto& mesh : hfmModel->meshes) {
|
|
size_t vertexCount = mesh.vertices.size();
|
|
totalVertexCount += mesh.vertices.size();
|
|
highestIndex = std::max(highestIndex, vertexCount);
|
|
totalPartCount += mesh.parts.size();
|
|
for (const auto& part : mesh.parts) {
|
|
totalIndexCount += part.quadTrianglesIndices.size();
|
|
totalIndexCount += part.triangleIndices.size();
|
|
}
|
|
}
|
|
size_t baseVertex = 0;
|
|
std::vector<MyVertex> vertices;
|
|
vertices.reserve(totalVertexCount);
|
|
std::vector<uint16_t> indices;
|
|
indices.reserve(totalIndexCount);
|
|
std::vector<DrawElementsIndirectCommand> parts;
|
|
parts.reserve(totalPartCount);
|
|
_partCount = totalPartCount;
|
|
for (const auto& mesh : hfmModel->meshes) {
|
|
baseVertex = vertices.size();
|
|
|
|
vec3 color;
|
|
for (const auto& part : mesh.parts) {
|
|
DrawElementsIndirectCommand partIndirect;
|
|
partIndirect.baseVertex = (uint)baseVertex;
|
|
partIndirect.firstIndex = (uint)indices.size();
|
|
partIndirect.baseInstance = (uint)parts.size();
|
|
_partTransforms.push_back(mesh.modelTransform);
|
|
auto material = hfmModel->materials[part.materialID];
|
|
color = material.diffuseColor;
|
|
for (auto index : part.quadTrianglesIndices) {
|
|
indices.push_back(index);
|
|
}
|
|
for (auto index : part.triangleIndices) {
|
|
indices.push_back(index);
|
|
}
|
|
size_t triangles = (indices.size() - partIndirect.firstIndex);
|
|
Q_ASSERT(0 == (triangles % 3));
|
|
//triangles /= 3;
|
|
partIndirect.count = (uint)triangles;
|
|
parts.push_back(partIndirect);
|
|
}
|
|
|
|
size_t vertexCount = mesh.vertices.size();
|
|
for (size_t i = 0; i < vertexCount; ++i) {
|
|
MyVertex vertex;
|
|
vertex.position = mesh.vertices[(int)i];
|
|
vec3 n = mesh.normals[(int)i];
|
|
vertex.normal = n;
|
|
vertex.texCoords = mesh.texCoords[(int)i];
|
|
vertex.color = toCompactColor(vec4(color, 1));
|
|
vertices.push_back(vertex);
|
|
}
|
|
}
|
|
|
|
_vertexBuffer->append(vertices);
|
|
_indexBuffer->append(indices);
|
|
_indirectBuffer->append(parts);
|
|
}
|
|
|
|
void TestFbx::renderTest(size_t testId, RenderArgs* args) {
|
|
gpu::Batch& batch = *(args->_batch);
|
|
//pipeline->pipeline
|
|
if (_partCount) {
|
|
for (size_t i = 0; i < _partCount; ++i) {
|
|
batch.setModelTransform(TEST_ASSET_TRANSFORM * _partTransforms[i]);
|
|
batch.setupNamedCalls(__FUNCTION__, [this](gpu::Batch& batch, gpu::Batch::NamedBatchData&) {
|
|
RenderArgs args; args._batch = &batch;
|
|
_shapePlumber->pickPipeline(&args, render::ShapeKey());
|
|
batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(MyVertex));
|
|
batch.setIndexBuffer(gpu::UINT16, _indexBuffer, 0);
|
|
batch.setInputFormat(MyVertex::getVertexFormat());
|
|
batch.setIndirectBuffer(_indirectBuffer, 0);
|
|
batch.multiDrawIndexedIndirect((uint)_partCount, gpu::TRIANGLES);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
#include "TestFbx.moc"
|