1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
// Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
#pragma once
#ifndef NV_MESH_ATLAS_H
#define NV_MESH_ATLAS_H
#include "nvcore/Array.h"
#include "nvcore/Ptr.h"
#include "nvmath/Vector.h"
#include "nvmesh/nvmesh.h"
#include "nvmesh/halfedge/Mesh.h"
namespace nv
{
namespace HalfEdge { class Mesh; }
class Chart;
class MeshCharts;
class VertexMap;
struct SegmentationSettings
{
SegmentationSettings();
float maxChartArea;
float maxBoundaryLength;
float proxyFitMetricWeight;
float roundnessMetricWeight;
float straightnessMetricWeight;
float normalSeamMetricWeight;
float textureSeamMetricWeight;
};
/// An atlas is a set of charts.
class Atlas
{
public:
Atlas();
~Atlas();
uint meshCount() const { return m_meshChartsArray.count(); }
const MeshCharts * meshAt(uint i) const { return m_meshChartsArray[i]; }
MeshCharts * meshAt(uint i) { return m_meshChartsArray[i]; }
uint chartCount() const;
const Chart * chartAt(uint i) const;
Chart * chartAt(uint i);
// Add mesh charts and takes ownership.
void addMeshCharts(MeshCharts * meshCharts);
void extractCharts(const HalfEdge::Mesh * mesh);
void computeCharts(const HalfEdge::Mesh * mesh, const SegmentationSettings & settings, const Array<uint> & unchartedMaterialArray);
// Compute a trivial seamless texture similar to ZBrush.
//bool computeSeamlessTextureAtlas(bool groupFaces = true, bool scaleTiles = false, uint w = 1024, uint h = 1024);
void parameterizeCharts();
// Pack charts in the smallest possible rectangle.
float packCharts(int quality, float texelArea, bool blockAlign, bool conservative);
void setFailed() { failed = true; }
bool hasFailed() const { return failed; }
private:
bool failed;
Array<MeshCharts *> m_meshChartsArray;
};
// Set of charts corresponding to a single mesh.
class MeshCharts
{
public:
MeshCharts(const HalfEdge::Mesh * mesh);
~MeshCharts();
uint chartCount() const { return m_chartArray.count(); }
uint vertexCount () const { return m_totalVertexCount; }
const Chart * chartAt(uint i) const { return m_chartArray[i]; }
Chart * chartAt(uint i) { return m_chartArray[i]; }
void computeVertexMap(const Array<uint> & unchartedMaterialArray);
// Extract the charts of the input mesh.
void extractCharts();
// Compute charts using a simple segmentation algorithm.
void computeCharts(const SegmentationSettings & settings, const Array<uint> & unchartedMaterialArray);
void parameterizeCharts();
uint faceChartAt(uint i) const { return m_faceChart[i]; }
uint faceIndexWithinChartAt(uint i) const { return m_faceIndex[i]; }
uint vertexCountBeforeChartAt(uint i) const { return m_chartVertexCountPrefixSum[i]; }
private:
const HalfEdge::Mesh * m_mesh;
Array<Chart *> m_chartArray;
Array<uint> m_chartVertexCountPrefixSum;
uint m_totalVertexCount;
Array<uint> m_faceChart; // the chart of every face of the input mesh.
Array<uint> m_faceIndex; // the index within the chart for every face of the input mesh.
};
/// A chart is a connected set of faces with a certain topology (usually a disk).
class Chart
{
public:
Chart();
void build(const HalfEdge::Mesh * originalMesh, const Array<uint> & faceArray);
void buildVertexMap(const HalfEdge::Mesh * originalMesh, const Array<uint> & unchartedMaterialArray);
bool closeHoles();
bool isDisk() const { return m_isDisk; }
bool isVertexMapped() const { return m_isVertexMapped; }
uint vertexCount() const { return m_chartMesh->vertexCount(); }
uint colocalVertexCount() const { return m_unifiedMesh->vertexCount(); }
uint faceCount() const { return m_faceArray.count(); }
uint faceAt(uint i) const { return m_faceArray[i]; }
const HalfEdge::Mesh * chartMesh() const { return m_chartMesh.ptr(); }
HalfEdge::Mesh * chartMesh() { return m_chartMesh.ptr(); }
const HalfEdge::Mesh * unifiedMesh() const { return m_unifiedMesh.ptr(); }
HalfEdge::Mesh * unifiedMesh() { return m_unifiedMesh.ptr(); }
//uint vertexIndex(uint i) const { return m_vertexIndexArray[i]; }
uint mapChartVertexToOriginalVertex(uint i) const { return m_chartToOriginalMap[i]; }
uint mapChartVertexToUnifiedVertex(uint i) const { return m_chartToUnifiedMap[i]; }
const Array<uint> & faceArray() const { return m_faceArray; }
void transferParameterization();
float computeSurfaceArea() const;
float computeParametricArea() const;
Vector2 computeParametricBounds() const;
float scale = 1.0f;
uint vertexMapWidth;
uint vertexMapHeight;
private:
bool closeLoop(uint start, const Array<HalfEdge::Edge *> & loop);
// Chart mesh.
AutoPtr<HalfEdge::Mesh> m_chartMesh;
AutoPtr<HalfEdge::Mesh> m_unifiedMesh;
bool m_isDisk;
bool m_isVertexMapped;
// List of faces of the original mesh that belong to this chart.
Array<uint> m_faceArray;
// Map vertices of the chart mesh to vertices of the original mesh.
Array<uint> m_chartToOriginalMap;
Array<uint> m_chartToUnifiedMap;
};
} // nv namespace
#endif // NV_MESH_ATLAS_H
|