ArchitectureColoredPainting/ArchitectureColoredPainting/Model.cpp

387 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "Model.h"
#include <QOpenGLTexture>
#include <QOpenGLContext>
#include <QTextCodec>
#include <iostream>
#include "PaintingMesh.h"
#include <QtMath>
#include "BvhTree.h"
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
: context(context)
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
, shaderProgram(shaderProgram)
, directory(path)
{
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return;
}
qDebug() << directory.absolutePath() << "Loaded Successfully";
qDebug() << "NumMeshes: " << scene->mNumMeshes;
qDebug() << "NumMaterials: " << scene->mNumMaterials;
qDebug() << "NumTextures: " << scene->mNumTextures;
directory.cdUp();
processNode(scene->mRootNode, scene);
}
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper)
: context(context)
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
, shaderProgram(shaderProgram)
, paintingProgram(paintingProgram)
, shadowProgram(shadowProgram)
, paintingHelper(paintingHelper)
, directory(path)
{
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return;
}
qDebug() << directory.absolutePath() << "Loaded Successfully";
qDebug() << "NumMeshes: " << scene->mNumMeshes;
qDebug() << "NumMaterials: " << scene->mNumMaterials;
qDebug() << "NumTextures: " << scene->mNumTextures;
directory.cdUp();
processNode(scene->mRootNode, scene);
}
Model::~Model() //<2F><><EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD>
{
for (auto& it : textures_loaded) {
it->texture.destroy();
delete it;
}
for (auto& it : meshes) {
delete it;
}
}
void Model::draw() {
//shaderProgram->bind();
for (Drawable* mesh : meshes) {
mesh->draw();
}
}
void Model::drawShadow() {
//shaderProgram->bind();
for (Drawable* mesh : meshes) {
mesh->drawShadow();
}
}
void Model::destroy()
{
context->doneCurrent();
delete this;
}
Model* Model::createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
{
return new Model(path, context, shaderProgram);
}
void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
{
// <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĻ<D0B5><C4BB><EFBFBD>
for (unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene, mat4));
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӽڵ<D3BD><DAB5>ظ<EFBFBD><D8B8><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>
for (unsigned int i = 0; i < node->mNumChildren; i++)
{
processNode(node->mChildren[i], scene, mat4 * node->mChildren[i]->mTransformation);
}
}
Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
aiString str;
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str);
if (paintingProgram != nullptr && std::strcmp(str.C_Str(), "17876391417123941155.jpg") == 0)
{
qDebug() << str.C_Str() << "Replaced";
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
PaintingMesh* m_mesh = new PaintingMesh(glFunc, paintingProgram, shadowProgram, model);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
PaintingVertex vertex;
vertex.Position = QVector3D(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (mesh->mNormals)
vertex.Normal = QVector3D(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (mesh->mTextureCoords[0])
vertex.TexCoords = QVector2D(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
if (mesh->mTangents)
vertex.Tangent = QVector3D(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z);
if (mesh->mBitangents)
vertex.Bitangent = QVector3D(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z);;
m_mesh->vertices.push_back(vertex);
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (unsigned int j = 0; j < face.mNumIndices; j++) {
m_mesh->indices.push_back(face.mIndices[j]);
}
}
BvhTree bvhTree;
std::vector<QVector4D> initBound;
for (int i = 0; i < 30000; i++)
{
float x = (float)rand() / RAND_MAX * 2 - 1;
float y = (float)rand() / RAND_MAX * 2 - 1;
float z = 0.01 + x;//(float)rand() / RAND_MAX * (0.1) + x;
float w = 0.01 + y;//(float)rand() / RAND_MAX * (0.1) + y;
initBound.push_back(QVector4D(x, y, z, w));
}
/* initBound.push_back(QVector4D(-0.8, -0.8, -0.7, -0.7));
initBound.push_back(QVector4D(-0.8, 0.7, -0.7, 0.8));
initBound.push_back(QVector4D(0.7, -0.8, 0.8, -0.7));
initBound.push_back(QVector4D(0.7, 0.7, 0.8, 0.8));*/
bvhTree.buildBvhTree(initBound.data(), initBound.size());
std::vector<GLuint> children;
std::vector<QVector4D> bounds;
bvhTree.getBvhArray(children, bounds);
std::vector<GLuint> bvhChildren = {
//root
1,2,
3,4, 5,6,
7,0, 7,GLuint(30. / 360 * 65536 + 1 * 65536) /*<2A>Ҷ<EFBFBD><D2B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>ת<EFBFBD>ǶȺ<C7B6>zIndex*/, 8,0, 7,0,
//elememt0
1,2,
5 + 0/*contour<75><72><EFBFBD><EFBFBD>*/,5 + 12/*style<6C><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>elementData<74><61>λ<EFBFBD><CEBB>*/, 3,4,
5 + 2,5 + 12, 5 + 1,5 + 12,
//elememt1
1 + 0/*line<6E><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>element<6E>еڼ<D0B5><DABC><EFBFBD>*/,1 + 25
};
std::vector<QVector4D> bvhBounds = {
//root
QVector4D(-1,-1,1,1),
QVector4D(-0.9,-0.9,-0.1,0.9), QVector4D(0.1, -0.9,0.9,0.9),
QVector4D(-0.8,-0.8,-0.2,-0.1), QVector4D(-0.7,0.2,-0.2,0.7), QVector4D(0.2,-0.8,0.8,-0.1), QVector4D(0.2,0.1,0.8,0.8),
//elememt0
QVector4D(-1,-1,1,1),
QVector4D(-1,-0.5,1,1), QVector4D(-1,-1,1,0.5),
QVector4D(-1,-1,1,-0.5), QVector4D(-1,-0.5,1,0.5),
//elememt1
QVector4D(-1,0,1,1),
};
std::vector<GLuint> elementOffset = {
//element0
7, //elementBvhRoot
5, //elementBvhLength
0, //pointsOffset
0, //linesOffset
28, //contoursOffset
//element1
12, //elementBvhRoot
1, //elementBvhLength
19, //pointsOffset
40, //linesOffset
44 //contoursOffset
};
std::vector<GLuint> elementIndex = {
//element0
//lines, ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ױ<EFBFBD><D7B1><EFBFBD><EFBFBD><EFBFBD>, ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
4,2,2,0,
0,0,1,1,
1,1,4,4,
1,1,5,5,
4,4,5,5,
1,1,3,3,
3,3,5,5,
//contours, ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
0,1,2,
2,3,4,
3,5,6,
//element2
//lines
0,1,2
};
std::vector<GLfloat> elementData = {
//element0
//points
-1,0.5, -1,-0.5, 0,1, 0,-1, 1,0.5, 1,-0.5,
//fillStyle
//fill
0,
//fillType
0, //<2F><>ɫ
//fillColorMetallicRoughness
1,1,0, 0,0.8,
//element1
//points
-1,0.5, 0,1, 1,0.5,
//strokeStyle
//stroke
1,
//strokeWidth
0.02,
//strokeEndType
0, //Բ<><D4B2>
//strokeFillType
0, //<2F><>ɫ
//strokeFillColorMetallicRoughness
0,1,0, 0,0.8
};
//m_mesh->paintingIndex = paintingHelper->addPainting(bounds.size(), std::vector<GLuint>(children.begin()+2, children.end()), bounds,
// elementOffset, elementIndex, elementData);
m_mesh->paintingIndex = paintingHelper->addPainting(7, bvhChildren, bvhBounds,
elementOffset, elementIndex, elementData);
m_mesh->setupMesh();
return m_mesh;
}
else
{
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Mesh* m_mesh = new Mesh(glFunc, shaderProgram, shadowProgram, model);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
Vertex vertex;
QVector3D vector; //<2F><>assimp<6D><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ΪQtOpenGL֧<4C>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>
// λ<><CEBB>
vector.setX(mesh->mVertices[i].x);
vector.setY(mesh->mVertices[i].y);
vector.setZ(mesh->mVertices[i].z);
vertex.Position = vector;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (mesh->mNormals) {
vector.setX(mesh->mNormals[i].x);
vector.setY(mesh->mNormals[i].y);
vector.setZ(mesh->mNormals[i].z);
vertex.Normal = vector;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
{
QVector2D vec;
//һ<><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>԰<EFBFBD><D4B0><EFBFBD>8<EFBFBD><38><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EAA1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǽ<EFBFBD><C7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><C7B2><EFBFBD>
//ʹ<><CAB9>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(0)<29><>
vec.setX(mesh->mTextureCoords[0][i].x);
vec.setY(mesh->mTextureCoords[0][i].y);
vertex.TexCoords = vec;
}
else {
vertex.TexCoords = QVector2D(0, 0);
}
if (mesh->mTangents) {
// tangent
vector.setX(mesh->mTangents[i].x);
vector.setY(mesh->mTangents[i].y);
vector.setZ(mesh->mTangents[i].z);
vertex.Tangent = vector;
}
if (mesh->mBitangents) {
vector.setX(mesh->mBitangents[i].x);
vector.setY(mesh->mBitangents[i].y);
vector.setZ(mesh->mBitangents[i].z);
vertex.Bitangent = vector;
}
// bitangent
m_mesh->vertices.push_back(vertex);
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (unsigned int j = 0; j < face.mNumIndices; j++) {
m_mesh->indices.push_back(face.mIndices[j]);
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
QVector<Texture*> diffuseMaps = loadMaterialTextures(material, aiTextureType_BASE_COLOR, "texture_basecolor");
for (auto& it : diffuseMaps)
m_mesh->textures.push_back(it);
QVector<Texture*> metalnessMaps = loadMaterialTextures(material, aiTextureType_METALNESS, "texture_metallic_roughness");
for (auto& it : metalnessMaps)
m_mesh->textures.push_back(it);
QVector<Texture*> normalMaps = loadMaterialTextures(material, aiTextureType_NORMALS, "texture_normal");
for (auto& it : normalMaps)
m_mesh->textures.push_back(it);
m_mesh->setupMesh();
return m_mesh;
}
}
QVector<Texture*> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName)
{
QVector<Texture*> textures;
for (unsigned int i = 0; i < mat->GetTextureCount(type); i++)
{
//qDebug() << typeName;
aiString str;
mat->GetTexture(type, i, &str);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD>ع<EFBFBD><D8B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool skip = false;
for (unsigned int j = 0; j < textures_loaded.size(); j++)
{
if (std::strcmp(textures_loaded[j]->path.toStdString().c_str(), str.C_Str()) == 0)
{
textures.push_back(textures_loaded[j]);
skip = true; //<2F><><EFBFBD>Ż<EFBFBD><C5BB><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬfilepath<74><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>
break;
}
}
if (!skip)
{ // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʻ<EFBFBD>û<EFBFBD>м<EFBFBD><D0BC>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Texture* texture = new Texture;
QImage data(directory.filePath(str.C_Str()));
if (!data.isNull()) {
texture->texture.setData(data);
texture->type = typeName;
texture->path = str.C_Str();
textures.push_back(texture);
textures_loaded.push_back(texture); // store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
}
else {
qDebug() << "δ<EFBFBD>ܳɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" << directory.filePath(str.C_Str());
}
}
}
return textures;
}