Use GL_LINES to show wireframe

master
Jeremy HU 2022-09-24 01:54:49 +10:00
parent d512ec0f7e
commit 61869d89dd
36 changed files with 579 additions and 182 deletions

View File

@ -155,17 +155,24 @@ HEADERS += sources/mesh_generator.h
SOURCES += sources/mesh_generator.cc
HEADERS += sources/mesh_result_post_processor.h
SOURCES += sources/mesh_result_post_processor.cc
HEADERS += sources/model.h
SOURCES += sources/model.cc
HEADERS += sources/model_mesh.h
SOURCES += sources/model_mesh.cc
HEADERS += sources/model_offscreen_render.h
SOURCES += sources/model_offscreen_render.cc
HEADERS += sources/model_opengl_program.h
SOURCES += sources/model_opengl_program.cc
HEADERS += sources/model_opengl_object.h
SOURCES += sources/model_opengl_object.cc
HEADERS += sources/model_shader_vertex.h
HEADERS += sources/model_opengl_vertex.h
HEADERS += sources/model_widget.h
SOURCES += sources/model_widget.cc
HEADERS += sources/monochrome_mesh.h
SOURCES += sources/monochrome_mesh.cc
HEADERS += sources/monochrome_opengl_program.h
SOURCES += sources/monochrome_opengl_program.cc
HEADERS += sources/monochrome_opengl_object.h
SOURCES += sources/monochrome_opengl_object.cc
HEADERS += sources/monochrome_opengl_vertex.h
HEADERS += sources/part_preview_images_generator.h
SOURCES += sources/part_preview_images_generator.cc
HEADERS += sources/part_tree_widget.h

View File

@ -8,6 +8,10 @@
<file>shaders/model.frag</file>
<file>shaders/model_core.vert</file>
<file>shaders/model_core.frag</file>
<file>shaders/monochrome.vert</file>
<file>shaders/monochrome.frag</file>
<file>shaders/monochrome_core.vert</file>
<file>shaders/monochrome_core.frag</file>
<file>resources/cedar_bridge_irradiance.dds</file>
<file>resources/cedar_bridge_specular.dds</file>
<file>resources/dust3d-vertical.png</file>

View File

@ -0,0 +1,9 @@
#version 110
varying vec3 pointPosition;
varying vec3 pointColor;
varying float pointAlpha;
void main()
{
gl_FragColor = vec4(pointColor, pointAlpha);
}

View File

@ -0,0 +1,19 @@
#version 110
attribute vec4 vertex;
attribute vec3 color;
attribute float alpha;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
varying vec3 pointPosition;
varying vec3 pointColor;
varying float pointAlpha;
void main()
{
pointPosition = (modelMatrix * vertex).xyz;
pointColor = color;
pointAlpha = alpha;
gl_Position = projectionMatrix * viewMatrix * vec4(pointPosition, 1.0);
}

View File

@ -0,0 +1,8 @@
#version 330
in vec3 pointColor;
in float pointAlpha;
out vec4 fragColor;
void main()
{
fragColor = vec4(pointColor, pointAlpha);
}

View File

@ -0,0 +1,19 @@
#version 330
layout(location = 0) in vec4 vertex;
layout(location = 1) in vec3 color;
layout(location = 2) in float alpha;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
out vec3 pointPosition;
out vec3 pointColor;
out float pointAlpha;
void main()
{
pointPosition = (modelMatrix * vertex).xyz;
pointColor = color;
pointAlpha = alpha;
gl_Position = projectionMatrix * viewMatrix * vec4(pointPosition, 1.0);
}

View File

@ -729,30 +729,38 @@ void Document::fromSnapshot(const dust3d::Snapshot &snapshot)
emit uncheckAll();
}
Model *Document::takeResultMesh()
ModelMesh *Document::takeResultMesh()
{
if (nullptr == m_resultMesh)
return nullptr;
Model *resultMesh = new Model(*m_resultMesh);
ModelMesh *resultMesh = new ModelMesh(*m_resultMesh);
return resultMesh;
}
MonochromeMesh *Document::takeWireframeMesh()
{
if (nullptr == m_wireframeMesh)
return nullptr;
return new MonochromeMesh(*m_wireframeMesh);
}
bool Document::isMeshGenerationSucceed()
{
return m_isMeshGenerationSucceed;
}
Model *Document::takeResultTextureMesh()
ModelMesh *Document::takeResultTextureMesh()
{
if (nullptr == m_resultTextureMesh)
return nullptr;
Model *resultTextureMesh = new Model(*m_resultTextureMesh);
ModelMesh *resultTextureMesh = new ModelMesh(*m_resultTextureMesh);
return resultTextureMesh;
}
void Document::meshReady()
{
Model *resultMesh = m_meshGenerator->takeResultMesh();
ModelMesh *resultMesh = m_meshGenerator->takeResultMesh();
m_wireframeMesh.reset(m_meshGenerator->takeWireframeMesh());
dust3d::Object *object = m_meshGenerator->takeObject();
bool isSuccessful = m_meshGenerator->isSuccessful();
@ -772,7 +780,7 @@ void Document::meshReady()
for (auto &partId: m_meshGenerator->generatedPreviewPartIds()) {
auto part = partMap.find(partId);
if (part != partMap.end()) {
Model *resultPartPreviewMesh = m_meshGenerator->takePartPreviewMesh(partId);
ModelMesh *resultPartPreviewMesh = m_meshGenerator->takePartPreviewMesh(partId);
part->second.updatePreviewMesh(resultPartPreviewMesh);
partPreviewsChanged = true;
}
@ -1591,7 +1599,7 @@ void Document::materialPreviewsReady()
for (const auto &materialId: m_materialPreviewsGenerator->generatedPreviewMaterialIds()) {
auto material = materialMap.find(materialId);
if (material != materialMap.end()) {
Model *resultPartPreviewMesh = m_materialPreviewsGenerator->takePreview(materialId);
ModelMesh *resultPartPreviewMesh = m_materialPreviewsGenerator->takePreview(materialId);
material->second.updatePreviewMesh(resultPartPreviewMesh);
emit materialPreviewChanged(materialId);
}

View File

@ -14,7 +14,8 @@
#include <dust3d/base/snapshot.h>
#include <dust3d/base/texture_type.h>
#include <dust3d/base/combine_mode.h>
#include "model.h"
#include "model_mesh.h"
#include "monochrome_mesh.h"
#include "theme.h"
#include "skeleton_document.h"
#include "material_layer.h"
@ -44,20 +45,20 @@ public:
QString name;
bool dirty = true;
std::vector<MaterialLayer> layers;
void updatePreviewMesh(Model *previewMesh)
void updatePreviewMesh(ModelMesh *previewMesh)
{
delete m_previewMesh;
m_previewMesh = previewMesh;
}
Model *takePreviewMesh() const
ModelMesh *takePreviewMesh() const
{
if (nullptr == m_previewMesh)
return nullptr;
return new Model(*m_previewMesh);
return new ModelMesh(*m_previewMesh);
}
private:
Q_DISABLE_COPY(Material);
Model *m_previewMesh = nullptr;
ModelMesh *m_previewMesh = nullptr;
};
enum class DocumentToSnapshotFor
@ -133,8 +134,8 @@ public: // need initialize
QImage *textureAmbientOcclusionImage = nullptr;
QByteArray *textureAmbientOcclusionImageByteArray = nullptr;
bool weldEnabled = true;
float brushMetalness = Model::m_defaultMetalness;
float brushRoughness = Model::m_defaultRoughness;
float brushMetalness = ModelMesh::m_defaultMetalness;
float brushRoughness = ModelMesh::m_defaultRoughness;
public:
Document();
~Document();
@ -160,11 +161,12 @@ public:
};
void addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSource source=SnapshotSource::Paste);
const Material *findMaterial(dust3d::Uuid materialId) const;
Model *takeResultMesh();
Model *takePaintedMesh();
ModelMesh *takeResultMesh();
MonochromeMesh *takeWireframeMesh();
ModelMesh *takePaintedMesh();
bool isMeshGenerationSucceed();
Model *takeResultTextureMesh();
Model *takeResultRigWeightMesh();
ModelMesh *takeResultTextureMesh();
ModelMesh *takeResultRigWeightMesh();
void updateTurnaround(const QImage &image);
void clearTurnaround();
void updateTextureImage(QImage *image);
@ -239,7 +241,8 @@ private:
bool m_isResultMeshObsolete = false;
MeshGenerator *m_meshGenerator = nullptr;
Model *m_resultMesh = nullptr;
ModelMesh *m_resultMesh = nullptr;
std::unique_ptr<MonochromeMesh> m_wireframeMesh;
bool m_isMeshGenerationSucceed = true;
int m_batchChangeRefCount = 0;
dust3d::Object *m_currentObject = nullptr;
@ -248,7 +251,7 @@ private:
bool m_isPostProcessResultObsolete = false;
MeshResultPostProcessor *m_postProcessor = nullptr;
dust3d::Object *m_postProcessedObject = new dust3d::Object;
Model *m_resultTextureMesh = nullptr;
ModelMesh *m_resultTextureMesh = nullptr;
unsigned long long m_textureImageUpdateVersion = 0;
bool m_smoothNormal = false;
MaterialPreviewsGenerator *m_materialPreviewsGenerator = nullptr;

View File

@ -423,7 +423,7 @@ DocumentWindow::DocumentWindow()
m_toggleColorAction = new QAction(tr("Toggle Color"), this);
connect(m_toggleColorAction, &QAction::triggered, [&]() {
m_modelRemoveColor = !m_modelRemoveColor;
Model *mesh = nullptr;
ModelMesh *mesh = nullptr;
if (m_document->isMeshGenerating() ||
m_document->isPostProcessing() ||
m_document->isTextureGenerating()) {
@ -738,6 +738,7 @@ DocumentWindow::DocumentWindow()
if (m_modelRemoveColor && resultMesh)
resultMesh->removeColor();
m_modelRenderWidget->updateMesh(resultMesh);
m_modelRenderWidget->updateWireframeMesh(m_document->takeWireframeMesh());
});
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::cursorChanged, [=]() {
@ -1027,7 +1028,7 @@ void DocumentWindow::openPathAs(const QString &path, const QString &asName)
QByteArray fileData = file.readAll();
dust3d::Ds3FileReader ds3Reader((const std::uint8_t *)fileData.data(), fileData.size());
for (int i = 0; i < ds3Reader.items().size(); ++i) {
for (int i = 0; i < (int)ds3Reader.items().size(); ++i) {
const dust3d::Ds3ReaderItem &item = ds3Reader.items()[i];
qDebug() << "[" << i << "]item.name:" << item.name << "item.type:" << item.type;
if (item.type == "asset") {
@ -1045,7 +1046,7 @@ void DocumentWindow::openPathAs(const QString &path, const QString &asName)
}
}
for (int i = 0; i < ds3Reader.items().size(); ++i) {
for (int i = 0; i < (int)ds3Reader.items().size(); ++i) {
const dust3d::Ds3ReaderItem &item = ds3Reader.items()[i];
if (item.type == "model") {
std::vector<std::uint8_t> data;
@ -1124,7 +1125,7 @@ void DocumentWindow::exportObjResult()
void DocumentWindow::exportObjToFilename(const QString &filename)
{
QApplication::setOverrideCursor(Qt::WaitCursor);
Model *resultMesh = m_document->takeResultMesh();
ModelMesh *resultMesh = m_document->takeResultMesh();
if (nullptr != resultMesh) {
resultMesh->exportAsObj(filename);
delete resultMesh;
@ -1534,13 +1535,13 @@ void DocumentWindow::updateRecentFileActions()
{
QStringList files = Preferences::instance().recentFileList();
for (int i = 0; i < files.size() && i < m_recentFileActions.size(); ++i) {
for (int i = 0; i < (int)files.size() && i < (int)m_recentFileActions.size(); ++i) {
QString text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i]));
m_recentFileActions[i]->setText(text);
m_recentFileActions[i]->setData(files[i]);
m_recentFileActions[i]->setVisible(true);
}
for (int j = files.size(); j < m_recentFileActions.size(); ++j)
for (int j = files.size(); j < (int)m_recentFileActions.size(); ++j)
m_recentFileActions[j]->setVisible(false);
m_recentFileSeparatorAction->setVisible(files.size() > 0);

View File

@ -7,7 +7,7 @@
#include <QtCore/qbuffer.h>
#include "glb_file.h"
#include "version.h"
#include "model.h"
#include "model_mesh.h"
bool GlbFileWriter::m_enableComment = false;
@ -79,8 +79,8 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["TEXCOORD_0"] = bufferViewIndex + (++attributeIndex);
int textureIndex = 0;
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["baseColorTexture"]["index"] = textureIndex++;
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["metallicFactor"] = Model::m_defaultMetalness;
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["roughnessFactor"] = Model::m_defaultRoughness;
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["metallicFactor"] = ModelMesh::m_defaultMetalness;
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["roughnessFactor"] = ModelMesh::m_defaultRoughness;
if (object.alphaEnabled)
m_json["materials"][primitiveIndex]["alphaMode"] = "BLEND";
if (normalImage) {

View File

@ -31,9 +31,9 @@ const std::set<dust3d::Uuid> &MaterialPreviewsGenerator::generatedPreviewMateria
return m_generatedMaterialIds;
}
Model *MaterialPreviewsGenerator::takePreview(dust3d::Uuid materialId)
ModelMesh *MaterialPreviewsGenerator::takePreview(dust3d::Uuid materialId)
{
Model *resultMesh = m_previews[materialId];
ModelMesh *resultMesh = m_previews[materialId];
m_previews[materialId] = nullptr;
return resultMesh;
}
@ -102,9 +102,9 @@ void MaterialPreviewsGenerator::generate()
}
}
textureGenerator->generate();
Model *texturedResultMesh = textureGenerator->takeResultMesh();
ModelMesh *texturedResultMesh = textureGenerator->takeResultMesh();
if (nullptr != texturedResultMesh) {
m_previews[material.first] = new Model(*texturedResultMesh);
m_previews[material.first] = new ModelMesh(*texturedResultMesh);
m_generatedMaterialIds.insert(material.first);
delete texturedResultMesh;
}

View File

@ -4,7 +4,7 @@
#include <QObject>
#include <map>
#include <vector>
#include "model.h"
#include "model_mesh.h"
#include "material_layer.h"
class MaterialPreviewsGenerator : public QObject
@ -15,7 +15,7 @@ public:
~MaterialPreviewsGenerator();
void addMaterial(dust3d::Uuid materialId, const std::vector<MaterialLayer> &layers);
const std::set<dust3d::Uuid> &generatedPreviewMaterialIds();
Model *takePreview(dust3d::Uuid materialId);
ModelMesh *takePreview(dust3d::Uuid materialId);
void generate();
signals:
void finished();
@ -23,7 +23,7 @@ public slots:
void process();
private:
std::vector<std::pair<dust3d::Uuid, std::vector<MaterialLayer>>> m_materials;
std::map<dust3d::Uuid, Model *> m_previews;
std::map<dust3d::Uuid, ModelMesh *> m_previews;
std::set<dust3d::Uuid> m_generatedMaterialIds;
};

View File

@ -63,7 +63,7 @@ void MaterialWidget::updatePreview(dust3d::Uuid materialId)
qDebug() << "Material not found:" << m_materialId;
return;
}
Model *previewMesh = material->takePreviewMesh();
ModelMesh *previewMesh = material->takePreviewMesh();
m_previewWidget->updateMesh(previewMesh);
}

View File

@ -17,9 +17,9 @@ MeshGenerator::~MeshGenerator()
delete m_resultMesh;
}
Model *MeshGenerator::takePartPreviewMesh(const dust3d::Uuid &partId)
ModelMesh *MeshGenerator::takePartPreviewMesh(const dust3d::Uuid &partId)
{
Model *resultMesh = m_partPreviewMeshes[partId];
ModelMesh *resultMesh = m_partPreviewMeshes[partId];
m_partPreviewMeshes[partId] = nullptr;
return resultMesh;
}
@ -31,6 +31,11 @@ QImage *MeshGenerator::takePartPreviewImage(const dust3d::Uuid &partId)
return image;
}
MonochromeMesh *MeshGenerator::takeWireframeMesh()
{
return m_wireframeMesh.release();
}
void MeshGenerator::process()
{
QElapsedTimer countTimeConsumed;
@ -39,7 +44,7 @@ void MeshGenerator::process()
generate();
if (nullptr != m_object)
m_resultMesh = new Model(*m_object);
m_resultMesh = new ModelMesh(*m_object);
for (const auto &partId: m_generatedPreviewImagePartIds) {
auto it = m_generatedPartPreviews.find(partId);
@ -51,7 +56,7 @@ void MeshGenerator::process()
auto it = m_generatedPartPreviews.find(partId);
if (it == m_generatedPartPreviews.end())
continue;
m_partPreviewMeshes[partId] = new Model(it->second.vertices,
m_partPreviewMeshes[partId] = new ModelMesh(it->second.vertices,
it->second.triangles,
it->second.vertexNormals,
it->second.color,
@ -59,14 +64,17 @@ void MeshGenerator::process()
it->second.roughness);
}
if (nullptr != m_object)
m_wireframeMesh = std::make_unique<MonochromeMesh>(*m_object);
qDebug() << "The mesh generation took" << countTimeConsumed.elapsed() << "milliseconds";
emit finished();
}
Model *MeshGenerator::takeResultMesh()
ModelMesh *MeshGenerator::takeResultMesh()
{
Model *resultMesh = m_resultMesh;
ModelMesh *resultMesh = m_resultMesh;
m_resultMesh = nullptr;
return resultMesh;
}

View File

@ -1,10 +1,12 @@
#ifndef DUST3D_APPLICATION_MESH_GENERATOR_H_
#define DUST3D_APPLICATION_MESH_GENERATOR_H_
#include <memory>
#include <QObject>
#include <QImage>
#include <dust3d/mesh/mesh_generator.h>
#include "model.h"
#include "model_mesh.h"
#include "monochrome_mesh.h"
class MeshGenerator : public QObject, public dust3d::MeshGenerator
{
@ -12,17 +14,19 @@ class MeshGenerator : public QObject, public dust3d::MeshGenerator
public:
MeshGenerator(dust3d::Snapshot *snapshot);
~MeshGenerator();
Model *takeResultMesh();
Model *takePartPreviewMesh(const dust3d::Uuid &partId);
ModelMesh *takeResultMesh();
ModelMesh *takePartPreviewMesh(const dust3d::Uuid &partId);
QImage *takePartPreviewImage(const dust3d::Uuid &partId);
MonochromeMesh *takeWireframeMesh();
public slots:
void process();
signals:
void finished();
private:
Model *m_resultMesh = nullptr;
std::map<dust3d::Uuid, Model *> m_partPreviewMeshes;
ModelMesh *m_resultMesh = nullptr;
std::map<dust3d::Uuid, ModelMesh *> m_partPreviewMeshes;
std::map<dust3d::Uuid, QImage *> m_partPreviewImages;
std::unique_ptr<MonochromeMesh> m_wireframeMesh;
};
#endif

View File

@ -2,13 +2,13 @@
#include <QTextStream>
#include <QFile>
#include <cmath>
#include "model.h"
#include "model_mesh.h"
#include "version.h"
float Model::m_defaultMetalness = 0.0;
float Model::m_defaultRoughness = 1.0;
float ModelMesh::m_defaultMetalness = 0.0;
float ModelMesh::m_defaultRoughness = 1.0;
Model::Model(const Model &mesh) :
ModelMesh::ModelMesh(const ModelMesh &mesh) :
m_triangleVertices(nullptr),
m_triangleVertexCount(0),
m_edgeVertices(nullptr),
@ -17,21 +17,21 @@ Model::Model(const Model &mesh) :
{
if (nullptr != mesh.m_triangleVertices &&
mesh.m_triangleVertexCount > 0) {
this->m_triangleVertices = new ModelShaderVertex[mesh.m_triangleVertexCount];
this->m_triangleVertices = new ModelOpenGLVertex[mesh.m_triangleVertexCount];
this->m_triangleVertexCount = mesh.m_triangleVertexCount;
for (int i = 0; i < mesh.m_triangleVertexCount; i++)
this->m_triangleVertices[i] = mesh.m_triangleVertices[i];
}
if (nullptr != mesh.m_edgeVertices &&
mesh.m_edgeVertexCount > 0) {
this->m_edgeVertices = new ModelShaderVertex[mesh.m_edgeVertexCount];
this->m_edgeVertices = new ModelOpenGLVertex[mesh.m_edgeVertexCount];
this->m_edgeVertexCount = mesh.m_edgeVertexCount;
for (int i = 0; i < mesh.m_edgeVertexCount; i++)
this->m_edgeVertices[i] = mesh.m_edgeVertices[i];
}
if (nullptr != mesh.m_toolVertices &&
mesh.m_toolVertexCount > 0) {
this->m_toolVertices = new ModelShaderVertex[mesh.m_toolVertexCount];
this->m_toolVertices = new ModelOpenGLVertex[mesh.m_toolVertexCount];
this->m_toolVertexCount = mesh.m_toolVertexCount;
for (int i = 0; i < mesh.m_toolVertexCount; i++)
this->m_toolVertices[i] = mesh.m_toolVertices[i];
@ -54,7 +54,7 @@ Model::Model(const Model &mesh) :
this->m_meshId = mesh.meshId();
}
void Model::removeColor()
void ModelMesh::removeColor()
{
delete this->m_textureImage;
this->m_textureImage = nullptr;
@ -77,7 +77,7 @@ void Model::removeColor()
}
}
Model::Model(ModelShaderVertex *triangleVertices, int vertexNum, ModelShaderVertex *edgeVertices, int edgeVertexCount) :
ModelMesh::ModelMesh(ModelOpenGLVertex *triangleVertices, int vertexNum, ModelOpenGLVertex *edgeVertices, int edgeVertexCount) :
m_triangleVertices(triangleVertices),
m_triangleVertexCount(vertexNum),
m_edgeVertices(edgeVertices),
@ -86,21 +86,21 @@ Model::Model(ModelShaderVertex *triangleVertices, int vertexNum, ModelShaderVert
{
}
Model::Model(const std::vector<dust3d::Vector3> &vertices, const std::vector<std::vector<size_t>> &triangles,
ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices, const std::vector<std::vector<size_t>> &triangles,
const std::vector<std::vector<dust3d::Vector3>> &triangleVertexNormals,
const dust3d::Color &color,
float metalness,
float roughness)
{
m_triangleVertexCount = (int)triangles.size() * 3;
m_triangleVertices = new ModelShaderVertex[m_triangleVertexCount];
m_triangleVertices = new ModelOpenGLVertex[m_triangleVertexCount];
int destIndex = 0;
for (size_t i = 0; i < triangles.size(); ++i) {
for (auto j = 0; j < 3; j++) {
int vertexIndex = (int)triangles[i][j];
const dust3d::Vector3 *srcVert = &vertices[vertexIndex];
const dust3d::Vector3 *srcNormal = &(triangleVertexNormals)[i][j];
ModelShaderVertex *dest = &m_triangleVertices[destIndex];
ModelOpenGLVertex *dest = &m_triangleVertices[destIndex];
dest->colorR = color.r();
dest->colorG = color.g();
dest->colorB = color.b();
@ -123,7 +123,7 @@ Model::Model(const std::vector<dust3d::Vector3> &vertices, const std::vector<std
}
}
Model::Model(dust3d::Object &object) :
ModelMesh::ModelMesh(dust3d::Object &object) :
m_triangleVertices(nullptr),
m_triangleVertexCount(0),
m_edgeVertices(nullptr),
@ -141,7 +141,7 @@ Model::Model(dust3d::Object &object) :
}
m_triangleVertexCount = (int)object.triangles.size() * 3;
m_triangleVertices = new ModelShaderVertex[m_triangleVertexCount];
m_triangleVertices = new ModelOpenGLVertex[m_triangleVertexCount];
int destIndex = 0;
const auto triangleVertexNormals = object.triangleVertexNormals();
const auto triangleVertexUvs = object.triangleVertexUvs();
@ -163,7 +163,7 @@ Model::Model(dust3d::Object &object) :
const dust3d::Vector3 *srcTangent = &defaultTangent;
if (triangleTangents)
srcTangent = &(*triangleTangents)[i];
ModelShaderVertex *dest = &m_triangleVertices[destIndex];
ModelOpenGLVertex *dest = &m_triangleVertices[destIndex];
dest->colorR = triangleColor->r();
dest->colorG = triangleColor->g();
dest->colorB = triangleColor->b();
@ -196,7 +196,7 @@ Model::Model(dust3d::Object &object) :
edgeCount += face.size();
}
m_edgeVertexCount = (int)edgeCount * 2;
m_edgeVertices = new ModelShaderVertex[m_edgeVertexCount];
m_edgeVertices = new ModelOpenGLVertex[m_edgeVertexCount];
size_t edgeVertexIndex = 0;
for (size_t faceIndex = 0; faceIndex < object.triangleAndQuads.size(); ++faceIndex) {
const auto &face = object.triangleAndQuads[faceIndex];
@ -204,8 +204,8 @@ Model::Model(dust3d::Object &object) :
for (size_t x = 0; x < 2; ++x) {
size_t sourceIndex = face[(i + x) % face.size()];
const dust3d::Vector3 *srcVert = &object.vertices[sourceIndex];
ModelShaderVertex *dest = &m_edgeVertices[edgeVertexIndex];
memset(dest, 0, sizeof(ModelShaderVertex));
ModelOpenGLVertex *dest = &m_edgeVertices[edgeVertexIndex];
memset(dest, 0, sizeof(ModelOpenGLVertex));
dest->colorR = 0.0;
dest->colorG = 0.0;
dest->colorB = 0.0;
@ -221,7 +221,7 @@ Model::Model(dust3d::Object &object) :
}
}
Model::Model() :
ModelMesh::ModelMesh() :
m_triangleVertices(nullptr),
m_triangleVertexCount(0),
m_edgeVertices(nullptr),
@ -230,7 +230,7 @@ Model::Model() :
{
}
Model::~Model()
ModelMesh::~ModelMesh()
{
delete[] m_triangleVertices;
m_triangleVertexCount = 0;
@ -243,112 +243,112 @@ Model::~Model()
delete m_metalnessRoughnessAmbientOcclusionImage;
}
const std::vector<dust3d::Vector3> &Model::vertices()
const std::vector<dust3d::Vector3> &ModelMesh::vertices()
{
return m_vertices;
}
const std::vector<std::vector<size_t>> &Model::faces()
const std::vector<std::vector<size_t>> &ModelMesh::faces()
{
return m_faces;
}
const std::vector<dust3d::Vector3> &Model::triangulatedVertices()
const std::vector<dust3d::Vector3> &ModelMesh::triangulatedVertices()
{
return m_triangulatedVertices;
}
ModelShaderVertex *Model::triangleVertices()
ModelOpenGLVertex *ModelMesh::triangleVertices()
{
return m_triangleVertices;
}
int Model::triangleVertexCount()
int ModelMesh::triangleVertexCount()
{
return m_triangleVertexCount;
}
ModelShaderVertex *Model::edgeVertices()
ModelOpenGLVertex *ModelMesh::edgeVertices()
{
return m_edgeVertices;
}
int Model::edgeVertexCount()
int ModelMesh::edgeVertexCount()
{
return m_edgeVertexCount;
}
ModelShaderVertex *Model::toolVertices()
ModelOpenGLVertex *ModelMesh::toolVertices()
{
return m_toolVertices;
}
int Model::toolVertexCount()
int ModelMesh::toolVertexCount()
{
return m_toolVertexCount;
}
void Model::setTextureImage(QImage *textureImage)
void ModelMesh::setTextureImage(QImage *textureImage)
{
m_textureImage = textureImage;
}
const QImage *Model::textureImage()
const QImage *ModelMesh::textureImage()
{
return m_textureImage;
}
void Model::setNormalMapImage(QImage *normalMapImage)
void ModelMesh::setNormalMapImage(QImage *normalMapImage)
{
m_normalMapImage = normalMapImage;
}
const QImage *Model::normalMapImage()
const QImage *ModelMesh::normalMapImage()
{
return m_normalMapImage;
}
const QImage *Model::metalnessRoughnessAmbientOcclusionImage()
const QImage *ModelMesh::metalnessRoughnessAmbientOcclusionImage()
{
return m_metalnessRoughnessAmbientOcclusionImage;
}
void Model::setMetalnessRoughnessAmbientOcclusionImage(QImage *image)
void ModelMesh::setMetalnessRoughnessAmbientOcclusionImage(QImage *image)
{
m_metalnessRoughnessAmbientOcclusionImage = image;
}
bool Model::hasMetalnessInImage()
bool ModelMesh::hasMetalnessInImage()
{
return m_hasMetalnessInImage;
}
void Model::setHasMetalnessInImage(bool hasInImage)
void ModelMesh::setHasMetalnessInImage(bool hasInImage)
{
m_hasMetalnessInImage = hasInImage;
}
bool Model::hasRoughnessInImage()
bool ModelMesh::hasRoughnessInImage()
{
return m_hasRoughnessInImage;
}
void Model::setHasRoughnessInImage(bool hasInImage)
void ModelMesh::setHasRoughnessInImage(bool hasInImage)
{
m_hasRoughnessInImage = hasInImage;
}
bool Model::hasAmbientOcclusionInImage()
bool ModelMesh::hasAmbientOcclusionInImage()
{
return m_hasAmbientOcclusionInImage;
}
void Model::setHasAmbientOcclusionInImage(bool hasInImage)
void ModelMesh::setHasAmbientOcclusionInImage(bool hasInImage)
{
m_hasAmbientOcclusionInImage = hasInImage;
}
void Model::exportAsObj(QTextStream *textStream)
void ModelMesh::exportAsObj(QTextStream *textStream)
{
auto &stream = *textStream;
stream << "# " << APP_NAME << " " << APP_HUMAN_VER << endl;
@ -365,7 +365,7 @@ void Model::exportAsObj(QTextStream *textStream)
}
}
void Model::exportAsObj(const QString &filename)
void ModelMesh::exportAsObj(const QString &filename)
{
QFile file(filename);
if (file.open(QIODevice::WriteOnly)) {
@ -374,7 +374,7 @@ void Model::exportAsObj(const QString &filename)
}
}
void Model::updateTool(ModelShaderVertex *toolVertices, int vertexNum)
void ModelMesh::updateTool(ModelOpenGLVertex *toolVertices, int vertexNum)
{
delete[] m_toolVertices;
m_toolVertices = nullptr;
@ -384,7 +384,7 @@ void Model::updateTool(ModelShaderVertex *toolVertices, int vertexNum)
m_toolVertexCount = vertexNum;
}
void Model::updateEdges(ModelShaderVertex *edgeVertices, int edgeVertexCount)
void ModelMesh::updateEdges(ModelOpenGLVertex *edgeVertices, int edgeVertexCount)
{
delete[] m_edgeVertices;
m_edgeVertices = nullptr;
@ -394,7 +394,7 @@ void Model::updateEdges(ModelShaderVertex *edgeVertices, int edgeVertexCount)
m_edgeVertexCount = edgeVertexCount;
}
void Model::updateTriangleVertices(ModelShaderVertex *triangleVertices, int triangleVertexCount)
void ModelMesh::updateTriangleVertices(ModelOpenGLVertex *triangleVertices, int triangleVertexCount)
{
delete[] m_triangleVertices;
m_triangleVertices = 0;
@ -404,12 +404,12 @@ void Model::updateTriangleVertices(ModelShaderVertex *triangleVertices, int tria
m_triangleVertexCount = triangleVertexCount;
}
quint64 Model::meshId() const
quint64 ModelMesh::meshId() const
{
return m_meshId;
}
void Model::setMeshId(quint64 id)
void ModelMesh::setMeshId(quint64 id)
{
m_meshId = id;
}

View File

@ -1,5 +1,5 @@
#ifndef DUST3D_APPLICATION_MODEL_H_
#define DUST3D_APPLICATION_MODEL_H_
#ifndef DUST3D_APPLICATION_MODEL_MESH_H_
#define DUST3D_APPLICATION_MODEL_MESH_H_
#include <QObject>
#include <vector>
@ -8,26 +8,26 @@
#include <dust3d/base/vector3.h>
#include <dust3d/base/color.h>
#include <dust3d/base/object.h>
#include "model_shader_vertex.h"
#include "model_opengl_vertex.h"
class Model
class ModelMesh
{
public:
Model(const std::vector<dust3d::Vector3> &vertices, const std::vector<std::vector<size_t>> &triangles,
ModelMesh(const std::vector<dust3d::Vector3> &vertices, const std::vector<std::vector<size_t>> &triangles,
const std::vector<std::vector<dust3d::Vector3>> &triangleVertexNormals,
const dust3d::Color &color=dust3d::Color::createWhite(),
float metalness=0.0,
float roughness=0.0);
Model(dust3d::Object &object);
Model(ModelShaderVertex *triangleVertices, int vertexNum, ModelShaderVertex *edgeVertices=nullptr, int edgeVertexCount=0);
Model(const Model &mesh);
Model();
~Model();
ModelShaderVertex *triangleVertices();
ModelMesh(dust3d::Object &object);
ModelMesh(ModelOpenGLVertex *triangleVertices, int vertexNum, ModelOpenGLVertex *edgeVertices=nullptr, int edgeVertexCount=0);
ModelMesh(const ModelMesh &mesh);
ModelMesh();
~ModelMesh();
ModelOpenGLVertex *triangleVertices();
int triangleVertexCount();
ModelShaderVertex *edgeVertices();
ModelOpenGLVertex *edgeVertices();
int edgeVertexCount();
ModelShaderVertex *toolVertices();
ModelOpenGLVertex *toolVertices();
int toolVertexCount();
const std::vector<dust3d::Vector3> &vertices();
const std::vector<std::vector<size_t>> &faces();
@ -48,18 +48,18 @@ public:
static float m_defaultRoughness;
void exportAsObj(const QString &filename);
void exportAsObj(QTextStream *textStream);
void updateTool(ModelShaderVertex *toolVertices, int vertexNum);
void updateEdges(ModelShaderVertex *edgeVertices, int edgeVertexCount);
void updateTriangleVertices(ModelShaderVertex *triangleVertices, int triangleVertexCount);
void updateTool(ModelOpenGLVertex *toolVertices, int vertexNum);
void updateEdges(ModelOpenGLVertex *edgeVertices, int edgeVertexCount);
void updateTriangleVertices(ModelOpenGLVertex *triangleVertices, int triangleVertexCount);
quint64 meshId() const;
void setMeshId(quint64 id);
void removeColor();
private:
ModelShaderVertex *m_triangleVertices = nullptr;
ModelOpenGLVertex *m_triangleVertices = nullptr;
int m_triangleVertexCount = 0;
ModelShaderVertex *m_edgeVertices = nullptr;
ModelOpenGLVertex *m_edgeVertices = nullptr;
int m_edgeVertexCount = 0;
ModelShaderVertex *m_toolVertices = nullptr;
ModelOpenGLVertex *m_toolVertices = nullptr;
int m_toolVertexCount = 0;
std::vector<dust3d::Vector3> m_vertices;
std::vector<std::vector<size_t>> m_faces;

View File

@ -40,7 +40,7 @@ void ModelOffscreenRender::setRenderThread(QThread *thread)
// TODO
}
void ModelOffscreenRender::updateMesh(Model *mesh)
void ModelOffscreenRender::updateMesh(ModelMesh *mesh)
{
// TODO
}

View File

@ -4,7 +4,7 @@
#include <QOffscreenSurface>
#include <QSurfaceFormat>
#include <QVector3D>
#include "model.h"
#include "model_mesh.h"
class ModelOffscreenRender: public QOffscreenSurface
{
@ -17,7 +17,7 @@ public:
void setEyePosition(const QVector3D &eyePosition);
void setMoveToPosition(const QVector3D &moveToPosition);
void setRenderThread(QThread *thread);
void updateMesh(Model *mesh);
void updateMesh(ModelMesh *mesh);
QImage toImage(const QSize &size);
};

View File

@ -3,7 +3,7 @@
#include <QOpenGLContext>
#include "model_opengl_object.h"
void ModelOpenGLObject::update(std::unique_ptr<Model> mesh)
void ModelOpenGLObject::update(std::unique_ptr<ModelMesh> mesh)
{
QMutexLocker lock(&m_meshMutex);
m_mesh = std::move(mesh);
@ -22,7 +22,7 @@ void ModelOpenGLObject::draw()
void ModelOpenGLObject::copyMeshToOpenGL()
{
std::unique_ptr<Model> mesh;
std::unique_ptr<ModelMesh> mesh;
bool meshChanged = false;
if (m_meshIsDirty) {
QMutexLocker lock(&m_meshMutex);
@ -41,7 +41,7 @@ void ModelOpenGLObject::copyMeshToOpenGL()
m_buffer.destroy();
m_buffer.create();
m_buffer.bind();
m_buffer.allocate(mesh->triangleVertices(), mesh->triangleVertexCount() * sizeof(ModelShaderVertex));
m_buffer.allocate(mesh->triangleVertices(), mesh->triangleVertexCount() * sizeof(ModelOpenGLVertex));
m_meshTriangleVertexCount = mesh->triangleVertexCount();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(0);
@ -52,14 +52,14 @@ void ModelOpenGLObject::copyMeshToOpenGL()
f->glEnableVertexAttribArray(5);
f->glEnableVertexAttribArray(6);
f->glEnableVertexAttribArray(7);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ModelShaderVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ModelShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ModelShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
f->glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(ModelShaderVertex), reinterpret_cast<void *>(9 * sizeof(GLfloat)));
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ModelShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ModelShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ModelShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ModelShaderVertex), reinterpret_cast<void *>(16 * sizeof(GLfloat)));
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
f->glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(9 * sizeof(GLfloat)));
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(16 * sizeof(GLfloat)));
m_buffer.release();
}
}

View File

@ -5,18 +5,18 @@
#include <QMutex>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include "model.h"
#include "model_mesh.h"
class ModelOpenGLObject
{
public:
void update(std::unique_ptr<Model> mesh);
void update(std::unique_ptr<ModelMesh> mesh);
void draw();
private:
void copyMeshToOpenGL();
QOpenGLVertexArrayObject m_vertexArrayObject;
QOpenGLBuffer m_buffer;
std::unique_ptr<Model> m_mesh;
std::unique_ptr<ModelMesh> m_mesh;
bool m_meshIsDirty = false;
QMutex m_meshMutex;
int m_meshTriangleVertexCount = 0;

View File

@ -1,5 +1,5 @@
#ifndef DUST3D_APPLICATION_MODEL_SHADER_VERTEX_H_
#define DUST3D_APPLICATION_MODEL_SHADER_VERTEX_H_
#ifndef DUST3D_APPLICATION_MODEL_OPENGL_VERTEX_H_
#define DUST3D_APPLICATION_MODEL_OPENGL_VERTEX_H_
#include <QOpenGLFunctions>
@ -24,7 +24,7 @@ typedef struct
GLfloat tangentY;
GLfloat tangentZ;
GLfloat alpha = 1.0;
} ModelShaderVertex;
} ModelOpenGLVertex;
#pragma pack(pop)
#endif

View File

@ -115,11 +115,11 @@ void ModelWidget::setZRotation(int angle)
void ModelWidget::cleanup()
{
if (!m_openGLProgram)
if (!m_modelOpenGLProgram)
return;
makeCurrent();
m_openGLObject.reset();
m_openGLProgram.reset();
m_modelOpenGLObject.reset();
m_modelOpenGLProgram.reset();
doneCurrent();
}
@ -163,13 +163,13 @@ std::pair<QVector3D, QVector3D> ModelWidget::screenPositionToMouseRay(const QPoi
void ModelWidget::toggleWireframe()
{
// TODO
m_isWireframeVisible = !m_isWireframeVisible;
update();
}
bool ModelWidget::isWireframeVisible()
{
// TODO
return false;
return m_isWireframeVisible;
}
void ModelWidget::enableEnvironmentLight()
@ -367,11 +367,20 @@ void ModelWidget::setMousePickRadius(float radius)
update();
}
void ModelWidget::updateMesh(Model *mesh)
void ModelWidget::updateMesh(ModelMesh *mesh)
{
if (!m_openGLObject)
m_openGLObject = std::make_unique<ModelOpenGLObject>();
m_openGLObject->update(std::unique_ptr<Model>(mesh));
if (!m_modelOpenGLObject)
m_modelOpenGLObject = std::make_unique<ModelOpenGLObject>();
m_modelOpenGLObject->update(std::unique_ptr<ModelMesh>(mesh));
emit renderParametersChanged();
update();
}
void ModelWidget::updateWireframeMesh(MonochromeMesh *mesh)
{
if (!m_wireframeOpenGLObject)
m_wireframeOpenGLObject = std::make_unique<MonochromeOpenGLObject>();
m_wireframeOpenGLObject->update(std::unique_ptr<MonochromeMesh>(mesh));
emit renderParametersChanged();
update();
}
@ -481,20 +490,48 @@ void ModelWidget::paintGL()
m_camera.setToIdentity();
m_camera.translate(m_eyePosition.x(), m_eyePosition.y(), m_eyePosition.z());
if (!m_openGLProgram) {
m_openGLProgram = std::make_unique<ModelOpenGLProgram>();
m_openGLProgram->load(format().profile() == QSurfaceFormat::CoreProfile);
if (!m_modelOpenGLProgram) {
m_modelOpenGLProgram = std::make_unique<ModelOpenGLProgram>();
m_modelOpenGLProgram->load(format().profile() == QSurfaceFormat::CoreProfile);
}
m_openGLProgram->bind();
if (m_isWireframeVisible) {
if (!m_monochromeOpenGLProgram) {
m_monochromeOpenGLProgram = std::make_unique<MonochromeOpenGLProgram>();
m_monochromeOpenGLProgram->load(format().profile() == QSurfaceFormat::CoreProfile);
}
}
m_openGLProgram->setUniformValue(m_openGLProgram->getUniformLocationByName("eyePosition"), m_eyePosition);
m_openGLProgram->setUniformValue(m_openGLProgram->getUniformLocationByName("projectionMatrix"), m_projection);
m_openGLProgram->setUniformValue(m_openGLProgram->getUniformLocationByName("modelMatrix"), m_world);
m_openGLProgram->setUniformValue(m_openGLProgram->getUniformLocationByName("viewMatrix"), m_camera);
drawModel();
if (m_isWireframeVisible)
drawWireframe();
}
void ModelWidget::drawWireframe()
{
m_monochromeOpenGLProgram->bind();
m_monochromeOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("projectionMatrix"), m_projection);
m_monochromeOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("modelMatrix"), m_world);
m_monochromeOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("viewMatrix"), m_camera);
if (m_wireframeOpenGLObject)
m_wireframeOpenGLObject->draw();
m_monochromeOpenGLProgram->release();
}
void ModelWidget::drawModel()
{
m_modelOpenGLProgram->bind();
m_modelOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("eyePosition"), m_eyePosition);
m_modelOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("projectionMatrix"), m_projection);
m_modelOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("modelMatrix"), m_world);
m_modelOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("viewMatrix"), m_camera);
if (m_isEnvironmentLightEnabled) {
if (m_openGLProgram->isCoreProfile()) {
if (m_modelOpenGLProgram->isCoreProfile()) {
if (!m_environmentIrradianceMap) {
DdsFileReader irradianceFile(":/resources/cedar_bridge_irradiance.dds");
m_environmentIrradianceMap.reset(irradianceFile.createOpenGLTexture());
@ -505,10 +542,10 @@ void ModelWidget::paintGL()
}
m_environmentIrradianceMap->bind(0);
m_openGLProgram->setUniformValue(m_openGLProgram->getUniformLocationByName("environmentIrradianceMapId"), 0);
m_modelOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("environmentIrradianceMapId"), 0);
m_environmentSpecularMap->bind(1);
m_openGLProgram->setUniformValue(m_openGLProgram->getUniformLocationByName("environmentSpecularMapId"), 1);
m_modelOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("environmentSpecularMapId"), 1);
} else {
if (!m_environmentIrradianceMaps) {
DdsFileReader irradianceFile(":/resources/cedar_bridge_irradiance.dds");
@ -529,14 +566,14 @@ void ModelWidget::paintGL()
bindPosition = 0;
for (size_t i = 0; i < m_environmentIrradianceMaps->size(); ++i)
m_openGLProgram->setUniformValue(m_openGLProgram->getUniformLocationByName("environmentIrradianceMapId[" + std::to_string(i) + "]"), (int)(bindPosition++));
m_modelOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("environmentIrradianceMapId[" + std::to_string(i) + "]"), (int)(bindPosition++));
for (size_t i = 0; i < m_environmentSpecularMaps->size(); ++i)
m_openGLProgram->setUniformValue(m_openGLProgram->getUniformLocationByName("environmentSpecularMapId[" + std::to_string(i) + "]"), (int)(bindPosition++));
m_modelOpenGLProgram->setUniformValue(m_modelOpenGLProgram->getUniformLocationByName("environmentSpecularMapId[" + std::to_string(i) + "]"), (int)(bindPosition++));
}
}
if (m_openGLObject)
m_openGLObject->draw();
if (m_modelOpenGLObject)
m_modelOpenGLObject->draw();
m_openGLProgram->release();
m_modelOpenGLProgram->release();
}

View File

@ -10,9 +10,12 @@
#include <QVector2D>
#include <QTimer>
#include <QString>
#include "model.h"
#include "model_mesh.h"
#include "model_opengl_program.h"
#include "model_opengl_object.h"
#include "monochrome_mesh.h"
#include "monochrome_opengl_program.h"
#include "monochrome_opengl_object.h"
class ModelWidget : public QOpenGLWidget
{
@ -31,7 +34,8 @@ signals:
public:
ModelWidget(QWidget *parent = 0);
~ModelWidget();
void updateMesh(Model *mesh);
void updateMesh(ModelMesh *mesh);
void updateWireframeMesh(MonochromeMesh *mesh);
void updateColorTexture(QImage *colorTextureImage);
void toggleWireframe();
bool isWireframeVisible();
@ -82,8 +86,10 @@ private:
int m_yRot = m_defaultYRotation;
int m_zRot = m_defaultZRotation;
int m_directionOnMoveStart = 0;
std::unique_ptr<ModelOpenGLProgram> m_openGLProgram;
std::unique_ptr<ModelOpenGLObject> m_openGLObject;
std::unique_ptr<ModelOpenGLProgram> m_modelOpenGLProgram;
std::unique_ptr<ModelOpenGLObject> m_modelOpenGLObject;
std::unique_ptr<MonochromeOpenGLProgram> m_monochromeOpenGLProgram;
std::unique_ptr<MonochromeOpenGLObject> m_wireframeOpenGLObject;
bool m_moveStarted = false;
bool m_moveEnabled = true;
bool m_zoomEnabled = true;
@ -108,6 +114,7 @@ private:
bool m_enableCullFace = true;
bool m_notGraphics = false;
bool m_isEnvironmentLightEnabled = false;
bool m_isWireframeVisible = false;
std::unique_ptr<QOpenGLTexture> m_environmentIrradianceMap;
std::unique_ptr<QOpenGLTexture> m_environmentSpecularMap;
std::unique_ptr<std::vector<std::unique_ptr<QOpenGLTexture>>> m_environmentIrradianceMaps;
@ -116,6 +123,8 @@ private:
std::pair<QVector3D, QVector3D> screenPositionToMouseRay(const QPoint &screenPosition);
void updateProjectionMatrix();
void normalizeAngle(int &angle);
void drawModel();
void drawWireframe();
public:
static int m_defaultXRotation;
static int m_defaultYRotation;

View File

@ -0,0 +1,58 @@
#include <set>
#include "monochrome_mesh.h"
MonochromeMesh::MonochromeMesh(const MonochromeMesh &mesh)
{
m_lineVertices = mesh.m_lineVertices;
}
MonochromeMesh::MonochromeMesh(MonochromeMesh &&mesh)
{
m_lineVertices = std::move(mesh.m_lineVertices);
}
MonochromeMesh::MonochromeMesh(const dust3d::Object &object)
{
std::set<std::pair<size_t, size_t>> halfEdges;
for (const auto &face: object.triangleAndQuads) {
if (3 == face.size()) {
halfEdges.insert({face[0], face[1]});
halfEdges.insert({face[1], face[0]});
halfEdges.insert({face[1], face[2]});
halfEdges.insert({face[2], face[1]});
halfEdges.insert({face[2], face[0]});
halfEdges.insert({face[0], face[2]});
continue;
}
halfEdges.insert({face[0], face[1]});
halfEdges.insert({face[1], face[0]});
halfEdges.insert({face[1], face[2]});
halfEdges.insert({face[2], face[1]});
halfEdges.insert({face[2], face[3]});
halfEdges.insert({face[3], face[2]});
halfEdges.insert({face[3], face[0]});
halfEdges.insert({face[0], face[3]});
}
m_lineVertices.reserve(halfEdges.size() * 2);
for (const auto &halfEdge: halfEdges) {
// For two halfedges shared one edge, only output one line
if (halfEdge.first > halfEdge.second)
continue;
const auto &from = object.vertices[halfEdge.first];
const auto &to = object.vertices[halfEdge.second];
m_lineVertices.emplace_back(MonochromeOpenGLVertex {(GLfloat)from.x(), (GLfloat)from.y(), (GLfloat)from.z()});
m_lineVertices.emplace_back(MonochromeOpenGLVertex {(GLfloat)to.x(), (GLfloat)to.y(), (GLfloat)to.z()});
}
}
const MonochromeOpenGLVertex *MonochromeMesh::lineVertices()
{
if (m_lineVertices.empty())
return nullptr;
return &m_lineVertices[0];
}
int MonochromeMesh::lineVertexCount()
{
return (int)m_lineVertices.size();
}

View File

@ -0,0 +1,21 @@
#ifndef DUST3D_APPLICATION_MONOCHROME_MESH_H_
#define DUST3D_APPLICATION_MONOCHROME_MESH_H_
#include <memory>
#include <dust3d/base/object.h>
#include "monochrome_opengl_vertex.h"
class MonochromeMesh
{
public:
MonochromeMesh(const MonochromeMesh &mesh);
MonochromeMesh(MonochromeMesh &&mesh);
MonochromeMesh(const dust3d::Object &object);
const MonochromeOpenGLVertex *lineVertices();
int lineVertexCount();
private:
std::vector<MonochromeOpenGLVertex> m_lineVertices;
};
#endif

View File

@ -0,0 +1,55 @@
#include <dust3d/base/debug.h>
#include <QOpenGLFunctions>
#include <QOpenGLContext>
#include "monochrome_opengl_object.h"
void MonochromeOpenGLObject::update(std::unique_ptr<MonochromeMesh> mesh)
{
QMutexLocker lock(&m_meshMutex);
m_mesh = std::move(mesh);
m_meshIsDirty = true;
}
void MonochromeOpenGLObject::draw()
{
copyMeshToOpenGL();
if (0 == m_meshLineVertexCount)
return;
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
QOpenGLVertexArrayObject::Binder binder(&m_vertexArrayObject);
f->glDrawArrays(GL_LINES, 0, m_meshLineVertexCount);
}
void MonochromeOpenGLObject::copyMeshToOpenGL()
{
std::unique_ptr<MonochromeMesh> mesh;
bool meshChanged = false;
if (m_meshIsDirty) {
QMutexLocker lock(&m_meshMutex);
if (m_meshIsDirty) {
m_meshIsDirty = false;
meshChanged = true;
mesh = std::move(m_mesh);
}
}
if (!meshChanged)
return;
m_meshLineVertexCount = 0;
if (mesh) {
QOpenGLVertexArrayObject::Binder binder(&m_vertexArrayObject);
if (m_buffer.isCreated())
m_buffer.destroy();
m_buffer.create();
m_buffer.bind();
m_buffer.allocate(mesh->lineVertices(), mesh->lineVertexCount() * sizeof(MonochromeOpenGLVertex));
m_meshLineVertexCount = mesh->lineVertexCount();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glEnableVertexAttribArray(2);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MonochromeOpenGLVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MonochromeOpenGLVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(MonochromeOpenGLVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
m_buffer.release();
}
}

View File

@ -0,0 +1,25 @@
#ifndef DUST3D_APPLICATION_MONOCHROME_OPENGL_OBJECT_H_
#define DUST3D_APPLICATION_MONOCHROME_OPENGL_OBJECT_H_
#include <memory>
#include <QMutex>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include "monochrome_mesh.h"
class MonochromeOpenGLObject
{
public:
void update(std::unique_ptr<MonochromeMesh> mesh);
void draw();
private:
void copyMeshToOpenGL();
QOpenGLVertexArrayObject m_vertexArrayObject;
QOpenGLBuffer m_buffer;
std::unique_ptr<MonochromeMesh> m_mesh;
bool m_meshIsDirty = false;
QMutex m_meshMutex;
int m_meshLineVertexCount = 0;
};
#endif

View File

@ -0,0 +1,60 @@
#include <QOpenGLFunctions>
#include <QFile>
#include <dust3d/base/debug.h>
#include "monochrome_opengl_program.h"
static const QString &loadShaderSource(const QString &name)
{
static std::map<QString, QString> s_shaderSources;
auto findShader = s_shaderSources.find(name);
if (findShader != s_shaderSources.end()) {
return findShader->second;
}
QFile file(name);
file.open(QFile::ReadOnly | QFile::Text);
QTextStream stream(&file);
auto insertResult = s_shaderSources.insert({name, stream.readAll()});
return insertResult.first->second;
}
void MonochromeOpenGLProgram::addShaderFromResource(QOpenGLShader::ShaderType type, const char *resourceName)
{
if (!addShaderFromSourceCode(type, loadShaderSource(resourceName)))
dust3dDebug << "Failed to addShaderFromResource, resource:" << resourceName << ", " << log().toStdString();
}
bool MonochromeOpenGLProgram::isCoreProfile() const
{
return m_isCoreProfile;
}
void MonochromeOpenGLProgram::load(bool isCoreProfile)
{
if (m_isLoaded)
return;
m_isCoreProfile = isCoreProfile;
if (m_isCoreProfile) {
addShaderFromResource(QOpenGLShader::Vertex, ":/shaders/monochrome_core.vert");
addShaderFromResource(QOpenGLShader::Fragment, ":/shaders/monochrome_core.frag");
} else {
addShaderFromResource(QOpenGLShader::Vertex, ":/shaders/monochrome.vert");
addShaderFromResource(QOpenGLShader::Fragment, ":/shaders/monochrome.frag");
}
bindAttributeLocation("vertex", 0);
bindAttributeLocation("color", 1);
bindAttributeLocation("alpha", 2);
link();
bind();
m_isLoaded = true;
}
int MonochromeOpenGLProgram::getUniformLocationByName(const std::string &name)
{
auto findLocation = m_uniformLocationMap.find(name);
if (findLocation != m_uniformLocationMap.end())
return findLocation->second;
int location = uniformLocation(name.c_str());
m_uniformLocationMap.insert({name, location});
return location;
}

View File

@ -0,0 +1,22 @@
#ifndef DUST3D_APPLICATION_MONOCHROME_OPENGL_PROGRAM_H_
#define DUST3D_APPLICATION_MONOCHROME_OPENGL_PROGRAM_H_
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
class MonochromeOpenGLProgram: public QOpenGLShaderProgram
{
public:
void load(bool isCoreProfile=false);
int getUniformLocationByName(const std::string &name);
bool isCoreProfile() const;
private:
void addShaderFromResource(QOpenGLShader::ShaderType type, const char *resourceName);
bool m_isLoaded = false;
bool m_isCoreProfile = false;
std::map<std::string, int> m_uniformLocationMap;
};
#endif

View File

@ -0,0 +1,20 @@
#ifndef DUST3D_APPLICATION_MONOCHROME_OPENGL_VERTEX_H_
#define DUST3D_APPLICATION_MONOCHROME_OPENGL_VERTEX_H_
#include <QOpenGLFunctions>
#pragma pack(push)
#pragma pack(1)
typedef struct
{
GLfloat posX;
GLfloat posY;
GLfloat posZ;
GLfloat colorR = 1.0;
GLfloat colorG = 1.0;
GLfloat colorB = 1.0;
GLfloat alpha = 1.0;
} MonochromeOpenGLVertex;
#pragma pack(pop)
#endif

View File

@ -2,7 +2,7 @@
#include "part_preview_images_generator.h"
#include "theme.h"
void PartPreviewImagesGenerator::addPart(const dust3d::Uuid &partId, Model *previewMesh, bool isCutFace)
void PartPreviewImagesGenerator::addPart(const dust3d::Uuid &partId, ModelMesh *previewMesh, bool isCutFace)
{
m_partPreviews.insert({partId, {previewMesh, isCutFace}});
}

View File

@ -18,7 +18,7 @@ public:
struct PreviewInput
{
Model *mesh = nullptr;
ModelMesh *mesh = nullptr;
bool isCutFace = false;
};
@ -32,7 +32,7 @@ public:
delete m_offscreenRender;
}
void addPart(const dust3d::Uuid &partId, Model *previewMesh, bool isCutFace);
void addPart(const dust3d::Uuid &partId, ModelMesh *previewMesh, bool isCutFace);
void generate();
std::map<dust3d::Uuid, QImage> *takePartImages();
signals:

View File

@ -15,7 +15,7 @@
#include <dust3d/base/part_base.h>
#include <dust3d/base/combine_mode.h>
#include "theme.h"
#include "model.h"
#include "model_mesh.h"
#include "debug.h"
class SkeletonNode
@ -388,21 +388,21 @@ public:
smooth = other.smooth;
hollowThickness = other.hollowThickness;
}
void updatePreviewMesh(Model *previewMesh)
void updatePreviewMesh(ModelMesh *previewMesh)
{
delete m_previewMesh;
m_previewMesh = previewMesh;
isPreviewMeshObsolete = true;
}
Model *takePreviewMesh() const
ModelMesh *takePreviewMesh() const
{
if (nullptr == m_previewMesh)
return nullptr;
return new Model(*m_previewMesh);
return new ModelMesh(*m_previewMesh);
}
private:
Q_DISABLE_COPY(SkeletonPart);
Model *m_previewMesh = nullptr;
ModelMesh *m_previewMesh = nullptr;
};
enum class SkeletonDocumentEditMode

View File

@ -73,9 +73,9 @@ dust3d::Object *TextureGenerator::takeObject()
return object;
}
Model *TextureGenerator::takeResultMesh()
ModelMesh *TextureGenerator::takeResultMesh()
{
Model *resultMesh = m_resultMesh;
ModelMesh *resultMesh = m_resultMesh;
m_resultMesh = nullptr;
return resultMesh;
}
@ -174,7 +174,7 @@ bool TextureGenerator::hasTransparencySettings()
void TextureGenerator::generate()
{
m_resultMesh = new Model(*m_object);
m_resultMesh = new ModelMesh(*m_object);
if (nullptr == m_object->triangleVertexUvs())
return;

View File

@ -8,7 +8,7 @@
#include <QPixmap>
#include <dust3d/base/object.h>
#include <dust3d/base/snapshot.h>
#include "model.h"
#include "model_mesh.h"
class TextureGenerator : public QObject
{
@ -22,7 +22,7 @@ public:
QImage *takeResultTextureMetalnessImage();
QImage *takeResultTextureAmbientOcclusionImage();
dust3d::Object *takeObject();
Model *takeResultMesh();
ModelMesh *takeResultMesh();
bool hasTransparencySettings();
void addPartColorMap(dust3d::Uuid partId, const QImage *image, float tileScale);
void addPartNormalMap(dust3d::Uuid partId, const QImage *image, float tileScale);
@ -48,7 +48,7 @@ private:
QImage *m_resultTextureRoughnessImage = nullptr;
QImage *m_resultTextureMetalnessImage = nullptr;
QImage *m_resultTextureAmbientOcclusionImage = nullptr;
Model *m_resultMesh = nullptr;
ModelMesh *m_resultMesh = nullptr;
std::map<dust3d::Uuid, std::pair<QImage, float>> m_partColorTextureMap;
std::map<dust3d::Uuid, std::pair<QImage, float>> m_partNormalTextureMap;
std::map<dust3d::Uuid, std::pair<QImage, float>> m_partMetalnessTextureMap;