Smooth normal based on angle
Currently, if the angle of two faces are less than 60 degrees, the normal is not averaged. This feature greatly boost the realistic look of the model.master
parent
096c107775
commit
6f471e7678
|
@ -254,6 +254,9 @@ HEADERS += src/material.h
|
||||||
SOURCES += src/fbxfile.cpp
|
SOURCES += src/fbxfile.cpp
|
||||||
HEADERS += src/fbxfile.h
|
HEADERS += src/fbxfile.h
|
||||||
|
|
||||||
|
SOURCES += src/anglesmooth.cpp
|
||||||
|
HEADERS += src/anglesmooth.h
|
||||||
|
|
||||||
SOURCES += src/main.cpp
|
SOURCES += src/main.cpp
|
||||||
|
|
||||||
HEADERS += src/version.h
|
HEADERS += src/version.h
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include <cmath>
|
||||||
|
#include <map>
|
||||||
|
#include "dust3dutil.h"
|
||||||
|
#include "anglesmooth.h"
|
||||||
|
|
||||||
|
void angleSmooth(const std::vector<QVector3D> &vertices,
|
||||||
|
const std::vector<std::tuple<size_t, size_t, size_t>> &triangles,
|
||||||
|
const std::vector<QVector3D> &triangleNormals,
|
||||||
|
float thresholdAngleDegrees, std::vector<QVector3D> &triangleVertexNormals)
|
||||||
|
{
|
||||||
|
std::vector<std::vector<std::pair<size_t, size_t>>> triangleVertexNormalsMapByIndicies(vertices.size());
|
||||||
|
std::vector<QVector3D> angleAreaWeightedNormals;
|
||||||
|
for (size_t triangleIndex = 0; triangleIndex < triangles.size(); ++triangleIndex) {
|
||||||
|
const auto &sourceTriangle = triangles[triangleIndex];
|
||||||
|
size_t indicies[] = {std::get<0>(sourceTriangle),
|
||||||
|
std::get<1>(sourceTriangle),
|
||||||
|
std::get<2>(sourceTriangle)};
|
||||||
|
const auto &v1 = vertices[indicies[0]];
|
||||||
|
const auto &v2 = vertices[indicies[1]];
|
||||||
|
const auto &v3 = vertices[indicies[2]];
|
||||||
|
float area = areaOfTriangle(v1, v2, v3);
|
||||||
|
float angles[] = {radianBetweenVectors(v2-v1, v3-v1),
|
||||||
|
radianBetweenVectors(v1-v2, v3-v2),
|
||||||
|
radianBetweenVectors(v1-v3, v2-v3)};
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
triangleVertexNormalsMapByIndicies[indicies[i]].push_back({triangleIndex, angleAreaWeightedNormals.size()});
|
||||||
|
angleAreaWeightedNormals.push_back(triangleNormals[triangleIndex] * area * angles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
triangleVertexNormals = angleAreaWeightedNormals;
|
||||||
|
std::map<std::pair<size_t, size_t>, float> degreesBetweenFacesMap;
|
||||||
|
for (size_t vertexIndex = 0; vertexIndex < vertices.size(); ++vertexIndex) {
|
||||||
|
const auto &triangleVertices = triangleVertexNormalsMapByIndicies[vertexIndex];
|
||||||
|
for (const auto &triangleVertex: triangleVertices) {
|
||||||
|
for (const auto &otherTriangleVertex: triangleVertices) {
|
||||||
|
if (triangleVertex.first == otherTriangleVertex.first)
|
||||||
|
continue;
|
||||||
|
float degrees = 0;
|
||||||
|
auto findDegreesResult = degreesBetweenFacesMap.find({triangleVertex.first, otherTriangleVertex.first});
|
||||||
|
if (findDegreesResult == degreesBetweenFacesMap.end()) {
|
||||||
|
degrees = angleBetweenVectors(triangleNormals[triangleVertex.first], triangleNormals[otherTriangleVertex.first]);
|
||||||
|
degreesBetweenFacesMap.insert({{triangleVertex.first, otherTriangleVertex.first}, degrees});
|
||||||
|
degreesBetweenFacesMap.insert({{otherTriangleVertex.first, triangleVertex.first}, degrees});
|
||||||
|
} else {
|
||||||
|
degrees = findDegreesResult->second;
|
||||||
|
}
|
||||||
|
if (degrees > thresholdAngleDegrees) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
triangleVertexNormals[triangleVertex.second] += angleAreaWeightedNormals[otherTriangleVertex.second];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto &item: triangleVertexNormals)
|
||||||
|
item.normalize();
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef ANGLE_SMOOTH_H
|
||||||
|
#define ANGLE_SMOOTH_H
|
||||||
|
#include <QVector3D>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
void angleSmooth(const std::vector<QVector3D> &vertices,
|
||||||
|
const std::vector<std::tuple<size_t, size_t, size_t>> &triangles,
|
||||||
|
const std::vector<QVector3D> &triangleNormals,
|
||||||
|
float thresholdAngleDegrees, std::vector<QVector3D> &triangleVertexNormals);
|
||||||
|
|
||||||
|
#endif
|
|
@ -74,3 +74,19 @@ QQuaternion quaternionOvershootSlerp(const QQuaternion &q0, const QQuaternion &q
|
||||||
return QQuaternion::slerp(q0, q1, t);
|
return QQuaternion::slerp(q0, q1, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float radianBetweenVectors(const QVector3D &first, const QVector3D &second)
|
||||||
|
{
|
||||||
|
return std::acos(QVector3D::dotProduct(first.normalized(), second.normalized()));
|
||||||
|
};
|
||||||
|
|
||||||
|
float angleBetweenVectors(const QVector3D &first, const QVector3D &second)
|
||||||
|
{
|
||||||
|
return radianBetweenVectors(first, second) * 180.0 / M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
float areaOfTriangle(const QVector3D &a, const QVector3D &b, const QVector3D &c)
|
||||||
|
{
|
||||||
|
auto ab = b - a;
|
||||||
|
auto ac = c - a;
|
||||||
|
return 0.5 * QVector3D::crossProduct(ab, ac).length();
|
||||||
|
};
|
||||||
|
|
|
@ -19,5 +19,8 @@ float angleInRangle360BetweenTwoVectors(QVector3D a, QVector3D b, QVector3D plan
|
||||||
QVector3D projectLineOnPlane(QVector3D line, QVector3D planeNormal);
|
QVector3D projectLineOnPlane(QVector3D line, QVector3D planeNormal);
|
||||||
QString unifiedWindowTitle(const QString &text);
|
QString unifiedWindowTitle(const QString &text);
|
||||||
QQuaternion quaternionOvershootSlerp(const QQuaternion &q0, const QQuaternion &q1, float t);
|
QQuaternion quaternionOvershootSlerp(const QQuaternion &q0, const QQuaternion &q1, float t);
|
||||||
|
float radianBetweenVectors(const QVector3D &first, const QVector3D &second);
|
||||||
|
float angleBetweenVectors(const QVector3D &first, const QVector3D &second);
|
||||||
|
float areaOfTriangle(const QVector3D &a, const QVector3D &b, const QVector3D &c);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1476,11 +1476,12 @@ FbxFileWriter::FbxFileWriter(MeshResultContext &resultContext,
|
||||||
layerElementNormal.addProperty((int32_t)0);
|
layerElementNormal.addProperty((int32_t)0);
|
||||||
layerElementNormal.addPropertyNode("Version", (int32_t)101);
|
layerElementNormal.addPropertyNode("Version", (int32_t)101);
|
||||||
layerElementNormal.addPropertyNode("Name", "");
|
layerElementNormal.addPropertyNode("Name", "");
|
||||||
layerElementNormal.addPropertyNode("MappingInformationType", "ByVertice");
|
layerElementNormal.addPropertyNode("MappingInformationType", "ByPolygonVertex");
|
||||||
layerElementNormal.addPropertyNode("ReferenceInformationType", "Direct");
|
layerElementNormal.addPropertyNode("ReferenceInformationType", "Direct");
|
||||||
std::vector<double> normals;
|
std::vector<double> normals;
|
||||||
for (decltype(resultContext.vertices.size()) i = 0; i < resultContext.vertices.size(); ++i) {
|
const auto &triangleVertexNormals = resultContext.interpolatedTriangleVertexNormals();
|
||||||
const auto &n = resultContext.interpolatedVertexNormals()[i];
|
for (decltype(triangleVertexNormals.size()) i = 0; i < triangleVertexNormals.size(); ++i) {
|
||||||
|
const auto &n = triangleVertexNormals[i];
|
||||||
normals.push_back((double)n.x());
|
normals.push_back((double)n.x());
|
||||||
normals.push_back((double)n.y());
|
normals.push_back((double)n.y());
|
||||||
normals.push_back((double)n.z());
|
normals.push_back((double)n.z());
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "positionmap.h"
|
#include "positionmap.h"
|
||||||
#include "ds3file.h"
|
#include "ds3file.h"
|
||||||
|
#include "anglesmooth.h"
|
||||||
|
|
||||||
#define MAX_VERTICES_PER_FACE 100
|
#define MAX_VERTICES_PER_FACE 100
|
||||||
|
|
||||||
|
@ -104,21 +105,15 @@ MeshLoader::MeshLoader(void *meshlite, int meshId, int triangulatedMeshId, QColo
|
||||||
GLfloat *triangleNormals = new GLfloat[triangleCount * 3];
|
GLfloat *triangleNormals = new GLfloat[triangleCount * 3];
|
||||||
int loadedTriangleNormalItemCount = meshlite_get_triangle_normal_array(meshlite, triangleMesh, triangleNormals, triangleCount * 3);
|
int loadedTriangleNormalItemCount = meshlite_get_triangle_normal_array(meshlite, triangleMesh, triangleNormals, triangleCount * 3);
|
||||||
|
|
||||||
auto angleBetweenVectors = [](const QVector3D &first, const QVector3D &second) {
|
|
||||||
return std::acos(QVector3D::dotProduct(first.normalized(), second.normalized()));
|
|
||||||
};
|
|
||||||
|
|
||||||
auto areaOfTriangle = [](const QVector3D &a, const QVector3D &b, const QVector3D &c) {
|
|
||||||
auto ab = b - a;
|
|
||||||
auto ac = c - a;
|
|
||||||
return 0.5 * QVector3D::crossProduct(ab, ac).length();
|
|
||||||
};
|
|
||||||
|
|
||||||
float modelR = defaultColor.redF();
|
float modelR = defaultColor.redF();
|
||||||
float modelG = defaultColor.greenF();
|
float modelG = defaultColor.greenF();
|
||||||
float modelB = defaultColor.blueF();
|
float modelB = defaultColor.blueF();
|
||||||
m_triangleVertexCount = triangleCount * 3;
|
m_triangleVertexCount = triangleCount * 3;
|
||||||
m_triangleVertices = new Vertex[m_triangleVertexCount * 3];
|
m_triangleVertices = new Vertex[m_triangleVertexCount * 3];
|
||||||
|
const std::vector<QVector3D> &inputVerticesForSmoothAngle = m_triangulatedVertices;
|
||||||
|
std::vector<std::tuple<size_t, size_t, size_t>> inputTrianglesForSmoothAngle;
|
||||||
|
std::vector<QVector3D> inputNormalsForSmoothAngle;
|
||||||
|
float thresholdAngleDegrees = 60;
|
||||||
for (int i = 0; i < triangleCount; i++) {
|
for (int i = 0; i < triangleCount; i++) {
|
||||||
int firstIndex = i * 3;
|
int firstIndex = i * 3;
|
||||||
float useColorR = modelR;
|
float useColorR = modelR;
|
||||||
|
@ -140,21 +135,14 @@ MeshLoader::MeshLoader(void *meshlite, int meshId, int triangulatedMeshId, QColo
|
||||||
float area = 1.0;
|
float area = 1.0;
|
||||||
float angles[3] = {1.0, 1.0, 1.0};
|
float angles[3] = {1.0, 1.0, 1.0};
|
||||||
if (smoothNormal) {
|
if (smoothNormal) {
|
||||||
for (int j = 0; j < 3; j++) {
|
inputTrianglesForSmoothAngle.push_back({
|
||||||
assert(firstIndex + j < loadedTriangleVertexIndexItemCount);
|
triangleIndices[firstIndex + 0],
|
||||||
int posIndex = triangleIndices[firstIndex + j] * 3;
|
triangleIndices[firstIndex + 1],
|
||||||
assert(posIndex < loadedTriangleVertexPositionItemCount);
|
triangleIndices[firstIndex + 2]
|
||||||
positions[j] = QVector3D(triangleVertexPositions[posIndex + 0],
|
});
|
||||||
triangleVertexPositions[posIndex + 1],
|
inputNormalsForSmoothAngle.push_back(QVector3D(triangleNormals[firstIndex + 0],
|
||||||
triangleVertexPositions[posIndex + 2]);
|
triangleNormals[firstIndex + 1],
|
||||||
}
|
triangleNormals[firstIndex + 2]));
|
||||||
const auto &v1 = positions[0];
|
|
||||||
const auto &v2 = positions[1];
|
|
||||||
const auto &v3 = positions[2];
|
|
||||||
area = areaOfTriangle(v1, v2, v3);
|
|
||||||
angles[0] = angleBetweenVectors(v2-v1, v3-v1);
|
|
||||||
angles[1] = angleBetweenVectors(v1-v2, v3-v2);
|
|
||||||
angles[2] = angleBetweenVectors(v1-v3, v2-v3);
|
|
||||||
}
|
}
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
assert(firstIndex + j < loadedTriangleVertexIndexItemCount);
|
assert(firstIndex + j < loadedTriangleVertexIndexItemCount);
|
||||||
|
@ -169,34 +157,26 @@ MeshLoader::MeshLoader(void *meshlite, int meshId, int triangulatedMeshId, QColo
|
||||||
v->normX = triangleNormals[firstIndex + 0];
|
v->normX = triangleNormals[firstIndex + 0];
|
||||||
v->normY = triangleNormals[firstIndex + 1];
|
v->normY = triangleNormals[firstIndex + 1];
|
||||||
v->normZ = triangleNormals[firstIndex + 2];
|
v->normZ = triangleNormals[firstIndex + 2];
|
||||||
if (smoothNormal) {
|
|
||||||
auto factor = area * angles[j];
|
|
||||||
triangleVertexSmoothNormals[posIndex + 0] += v->normX * factor;
|
|
||||||
triangleVertexSmoothNormals[posIndex + 1] += v->normY * factor;
|
|
||||||
triangleVertexSmoothNormals[posIndex + 2] += v->normZ * factor;
|
|
||||||
}
|
|
||||||
v->colorR = useColorR;
|
v->colorR = useColorR;
|
||||||
v->colorG = useColorG;
|
v->colorG = useColorG;
|
||||||
v->colorB = useColorB;
|
v->colorB = useColorB;
|
||||||
v->metalness = useMetalness;
|
v->metalness = useMetalness;
|
||||||
v->roughness = useRoughness;
|
v->roughness = useRoughness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_triangulatedFaces.push_back(triangulatedFace);
|
m_triangulatedFaces.push_back(triangulatedFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smoothNormal) {
|
if (smoothNormal) {
|
||||||
|
std::vector<QVector3D> resultNormals;
|
||||||
|
angleSmooth(inputVerticesForSmoothAngle, inputTrianglesForSmoothAngle, inputNormalsForSmoothAngle,
|
||||||
|
thresholdAngleDegrees, resultNormals);
|
||||||
|
size_t normalIndex = 0;
|
||||||
for (int i = 0; i < triangleCount; i++) {
|
for (int i = 0; i < triangleCount; i++) {
|
||||||
int firstIndex = i * 3;
|
int firstIndex = i * 3;
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
assert(firstIndex + j < loadedTriangleVertexIndexItemCount);
|
assert(firstIndex + j < loadedTriangleVertexIndexItemCount);
|
||||||
int posIndex = triangleIndices[firstIndex + j] * 3;
|
|
||||||
Vertex *v = &m_triangleVertices[firstIndex + j];
|
Vertex *v = &m_triangleVertices[firstIndex + j];
|
||||||
QVector3D normal(triangleVertexSmoothNormals[posIndex + 0],
|
const auto &normal = resultNormals[normalIndex++];
|
||||||
triangleVertexSmoothNormals[posIndex + 1],
|
|
||||||
triangleVertexSmoothNormals[posIndex + 2]);
|
|
||||||
normal.normalize();
|
|
||||||
v->normX = normal.x();
|
v->normX = normal.x();
|
||||||
v->normY = normal.y();
|
v->normY = normal.y();
|
||||||
v->normZ = normal.z();
|
v->normZ = normal.z();
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "meshresultcontext.h"
|
#include "meshresultcontext.h"
|
||||||
#include "positionmap.h"
|
#include "positionmap.h"
|
||||||
|
#include "anglesmooth.h"
|
||||||
|
|
||||||
struct HalfColorEdge
|
struct HalfColorEdge
|
||||||
{
|
{
|
||||||
|
@ -32,7 +33,7 @@ MeshResultContext::MeshResultContext() :
|
||||||
m_bmeshNodeMapResolved(false),
|
m_bmeshNodeMapResolved(false),
|
||||||
m_resultPartsResolved(false),
|
m_resultPartsResolved(false),
|
||||||
m_resultTriangleUvsResolved(false),
|
m_resultTriangleUvsResolved(false),
|
||||||
m_vertexNormalsInterpolated(false),
|
m_triangleVertexNormalsInterpolated(false),
|
||||||
m_triangleTangentsResolved(false)
|
m_triangleTangentsResolved(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -318,6 +319,7 @@ void MeshResultContext::calculateResultParts(std::map<QUuid, ResultPart> &parts)
|
||||||
{
|
{
|
||||||
std::map<std::pair<QUuid, int>, int> oldVertexToNewMap;
|
std::map<std::pair<QUuid, int>, int> oldVertexToNewMap;
|
||||||
for (auto x = 0u; x < triangles.size(); x++) {
|
for (auto x = 0u; x < triangles.size(); x++) {
|
||||||
|
size_t normalIndex = x * 3;
|
||||||
const auto &triangle = triangles[x];
|
const auto &triangle = triangles[x];
|
||||||
const auto &sourceNode = triangleSourceNodes()[x];
|
const auto &sourceNode = triangleSourceNodes()[x];
|
||||||
auto it = parts.find(sourceNode.first);
|
auto it = parts.find(sourceNode.first);
|
||||||
|
@ -330,13 +332,14 @@ void MeshResultContext::calculateResultParts(std::map<QUuid, ResultPart> &parts)
|
||||||
ResultTriangle newTriangle;
|
ResultTriangle newTriangle;
|
||||||
newTriangle.normal = triangle.normal;
|
newTriangle.normal = triangle.normal;
|
||||||
for (auto i = 0u; i < 3; i++) {
|
for (auto i = 0u; i < 3; i++) {
|
||||||
|
const auto &normal = interpolatedTriangleVertexNormals()[normalIndex++];
|
||||||
auto key = std::make_pair(sourceNode.first, triangle.indicies[i]);
|
auto key = std::make_pair(sourceNode.first, triangle.indicies[i]);
|
||||||
const auto &it = oldVertexToNewMap.find(key);
|
const auto &it = oldVertexToNewMap.find(key);
|
||||||
bool isNewVertex = it == oldVertexToNewMap.end();
|
bool isNewVertex = it == oldVertexToNewMap.end();
|
||||||
bool isSeamVertex = m_seamVertices.end() != m_seamVertices.find(triangle.indicies[i]);
|
bool isSeamVertex = m_seamVertices.end() != m_seamVertices.find(triangle.indicies[i]);
|
||||||
if (isNewVertex || isSeamVertex) {
|
if (isNewVertex || isSeamVertex) {
|
||||||
int newIndex = resultPart.vertices.size();
|
int newIndex = resultPart.vertices.size();
|
||||||
resultPart.interpolatedVertexNormals.push_back(interpolatedVertexNormals()[triangle.indicies[i]]);
|
resultPart.interpolatedVertexNormals.push_back(normal);
|
||||||
resultPart.verticesOldIndicies.push_back(triangle.indicies[i]);
|
resultPart.verticesOldIndicies.push_back(triangle.indicies[i]);
|
||||||
resultPart.vertices.push_back(vertices[triangle.indicies[i]]);
|
resultPart.vertices.push_back(vertices[triangle.indicies[i]]);
|
||||||
ResultVertexUv vertexUv;
|
ResultVertexUv vertexUv;
|
||||||
|
@ -417,44 +420,28 @@ void MeshResultContext::calculateResultTriangleUvs(std::vector<ResultTriangleUv>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshResultContext::interpolateVertexNormals(std::vector<QVector3D> &resultNormals)
|
void MeshResultContext::interpolateTriangleVertexNormals(std::vector<QVector3D> &resultNormals)
|
||||||
{
|
{
|
||||||
resultNormals.resize(vertices.size());
|
std::vector<QVector3D> inputVerticies;
|
||||||
|
std::vector<std::tuple<size_t, size_t, size_t>> inputTriangles;
|
||||||
auto angleBetweenVectors = [](const QVector3D &first, const QVector3D &second) {
|
std::vector<QVector3D> inputNormals;
|
||||||
return std::acos(QVector3D::dotProduct(first.normalized(), second.normalized()));
|
float thresholdAngleDegrees = 60;
|
||||||
};
|
for (const auto &vertex: vertices)
|
||||||
|
inputVerticies.push_back(vertex.position);
|
||||||
auto areaOfTriangle = [](const QVector3D &a, const QVector3D &b, const QVector3D &c) {
|
for (const auto &triangle: triangles) {
|
||||||
auto ab = b - a;
|
inputTriangles.push_back({triangle.indicies[0], triangle.indicies[1], triangle.indicies[2]});
|
||||||
auto ac = c - a;
|
inputNormals.push_back(triangle.normal);
|
||||||
return 0.5 * QVector3D::crossProduct(ab, ac).length();
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t triangleIndex = 0; triangleIndex < triangles.size(); triangleIndex++) {
|
|
||||||
const auto &sourceTriangle = triangles[triangleIndex];
|
|
||||||
const auto &v1 = vertices[sourceTriangle.indicies[0]].position;
|
|
||||||
const auto &v2 = vertices[sourceTriangle.indicies[1]].position;
|
|
||||||
const auto &v3 = vertices[sourceTriangle.indicies[2]].position;
|
|
||||||
float area = areaOfTriangle(v1, v2, v3);
|
|
||||||
float angles[] = {angleBetweenVectors(v2-v1, v3-v1),
|
|
||||||
angleBetweenVectors(v1-v2, v3-v2),
|
|
||||||
angleBetweenVectors(v1-v3, v2-v3)};
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
resultNormals[sourceTriangle.indicies[i]] += sourceTriangle.normal * area * angles[i];
|
|
||||||
}
|
}
|
||||||
|
angleSmooth(inputVerticies, inputTriangles, inputNormals, thresholdAngleDegrees, resultNormals);
|
||||||
for (auto &item: resultNormals)
|
|
||||||
item.normalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<QVector3D> &MeshResultContext::interpolatedVertexNormals()
|
const std::vector<QVector3D> &MeshResultContext::interpolatedTriangleVertexNormals()
|
||||||
{
|
{
|
||||||
if (!m_vertexNormalsInterpolated) {
|
if (!m_triangleVertexNormalsInterpolated) {
|
||||||
m_vertexNormalsInterpolated = true;
|
m_triangleVertexNormalsInterpolated = true;
|
||||||
interpolateVertexNormals(m_interpolatedVertexNormals);
|
interpolateTriangleVertexNormals(m_interpolatedTriangleVertexNormals);
|
||||||
}
|
}
|
||||||
return m_interpolatedVertexNormals;
|
return m_interpolatedTriangleVertexNormals;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<QVector3D> &MeshResultContext::triangleTangents()
|
const std::vector<QVector3D> &MeshResultContext::triangleTangents()
|
||||||
|
|
|
@ -80,7 +80,7 @@ public:
|
||||||
const std::map<QUuid, ResultPart> &parts();
|
const std::map<QUuid, ResultPart> &parts();
|
||||||
const std::vector<ResultTriangleUv> &triangleUvs();
|
const std::vector<ResultTriangleUv> &triangleUvs();
|
||||||
const std::map<int, std::pair<QUuid, QUuid>> &vertexSourceMap();
|
const std::map<int, std::pair<QUuid, QUuid>> &vertexSourceMap();
|
||||||
const std::vector<QVector3D> &interpolatedVertexNormals();
|
const std::vector<QVector3D> &interpolatedTriangleVertexNormals();
|
||||||
const std::vector<QVector3D> &triangleTangents();
|
const std::vector<QVector3D> &triangleTangents();
|
||||||
private:
|
private:
|
||||||
bool m_triangleSourceResolved;
|
bool m_triangleSourceResolved;
|
||||||
|
@ -89,7 +89,7 @@ private:
|
||||||
bool m_bmeshNodeMapResolved;
|
bool m_bmeshNodeMapResolved;
|
||||||
bool m_resultPartsResolved;
|
bool m_resultPartsResolved;
|
||||||
bool m_resultTriangleUvsResolved;
|
bool m_resultTriangleUvsResolved;
|
||||||
bool m_vertexNormalsInterpolated;
|
bool m_triangleVertexNormalsInterpolated;
|
||||||
bool m_triangleTangentsResolved;
|
bool m_triangleTangentsResolved;
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<QUuid, QUuid>> m_triangleSourceNodes;
|
std::vector<std::pair<QUuid, QUuid>> m_triangleSourceNodes;
|
||||||
|
@ -101,7 +101,7 @@ private:
|
||||||
std::set<int> m_seamVertices;
|
std::set<int> m_seamVertices;
|
||||||
std::map<int, std::pair<QUuid, QUuid>> m_vertexSourceMap;
|
std::map<int, std::pair<QUuid, QUuid>> m_vertexSourceMap;
|
||||||
std::map<int, int> m_rearrangedVerticesToOldIndexMap;
|
std::map<int, int> m_rearrangedVerticesToOldIndexMap;
|
||||||
std::vector<QVector3D> m_interpolatedVertexNormals;
|
std::vector<QVector3D> m_interpolatedTriangleVertexNormals;
|
||||||
std::vector<QVector3D> m_triangleTangents;
|
std::vector<QVector3D> m_triangleTangents;
|
||||||
private:
|
private:
|
||||||
void calculateTriangleSourceNodes(std::vector<std::pair<QUuid, QUuid>> &triangleSourceNodes, std::map<int, std::pair<QUuid, QUuid>> &vertexSourceMap);
|
void calculateTriangleSourceNodes(std::vector<std::pair<QUuid, QUuid>> &triangleSourceNodes, std::map<int, std::pair<QUuid, QUuid>> &vertexSourceMap);
|
||||||
|
@ -111,7 +111,7 @@ private:
|
||||||
void calculateBmeshNodeMap(std::map<std::pair<QUuid, QUuid>, BmeshNode *> &bmeshNodeMap);
|
void calculateBmeshNodeMap(std::map<std::pair<QUuid, QUuid>, BmeshNode *> &bmeshNodeMap);
|
||||||
void calculateResultParts(std::map<QUuid, ResultPart> &parts);
|
void calculateResultParts(std::map<QUuid, ResultPart> &parts);
|
||||||
void calculateResultTriangleUvs(std::vector<ResultTriangleUv> &uvs, std::set<int> &seamVertices);
|
void calculateResultTriangleUvs(std::vector<ResultTriangleUv> &uvs, std::set<int> &seamVertices);
|
||||||
void interpolateVertexNormals(std::vector<QVector3D> &resultNormals);
|
void interpolateTriangleVertexNormals(std::vector<QVector3D> &resultNormals);
|
||||||
void calculateTriangleTangents(std::vector<QVector3D> &tangents);
|
void calculateTriangleTangents(std::vector<QVector3D> &tangents);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue