-
Notifications
You must be signed in to change notification settings - Fork 0
/
VertexAttributes.h
156 lines (131 loc) · 4.36 KB
/
VertexAttributes.h
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
// This file is part of FbxReader.
//
// FbxReader is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// FbxReader is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with FbxReader. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#ifndef VERTEXATTRIBUTES_H
#define VERTEXATTRIBUTES_H
#include <fbxsdk.h>
#include <vector>
#include <string>
#include <cassert>
template<typename T>
struct VertexAttribute
{
std::vector<T> data;
std::vector<unsigned int> indices;
//Vertex attributes are optimized using an index array to indirectly access the unique entries in the data array
const T& GetRefAt(unsigned int vertexIndex)
{
return data.at(indices.at(vertexIndex));
}
//Get attributes from the specified layer element
void ExtractData(FbxMesh* pMesh, FbxLayerElementTemplate<T>* pLayerElement)
{
if(!pLayerElement)
return;
if(!data.empty())
data.clear();
if(!pMesh->IsTriangleMesh())
throw std::exception( (std::string("Mesh ") + pMesh->GetName() + " contains N-gons. Only triangle meshes are supported.").c_str() );
//Gather necessary data to loop over all vertices and retrieve the attributes
const auto mappingMode = pLayerElement->GetMappingMode();
const auto referenceMode = pLayerElement->GetReferenceMode();
const unsigned int nrOfTriangles = pMesh->GetPolygonCount();
int index=0;
//For every vertex in every triangle
for(unsigned int iTri=0; iTri<nrOfTriangles; ++iTri){
for(unsigned int iVert=0; iVert<3; ++iVert){
switch(mappingMode){
//Attributes are stored per control point
case FbxLayerElement::eByControlPoint:
switch(referenceMode){
//Direct access
case FbxLayerElement::eDirect:
index = pMesh->GetPolygonVertex(iTri,iVert);
break;
//Indirect access
case FbxLayerElement::eIndexToDirect:
index = pLayerElement->GetIndexArray().GetAt( pMesh->GetPolygonVertex(iTri,iVert) );
break;
default:
throw std::exception("Invalid reference mode");
}
break;
//Attributes are stored per polygon vertex
case FbxLayerElement::eByPolygonVertex:
switch(referenceMode){
//Direct access
case FbxLayerElement::eDirect:
index = 3*iTri + iVert;
break;
//Indirect access
case FbxLayerElement::eIndexToDirect:
index = pLayerElement->GetIndexArray().GetAt( 3*iTri + iVert );
break;
default:
throw std::exception("Invalid reference mode");
}
break;
default:
throw std::exception("Invalid mapping mode");
}
//Get the attribute from the direct array
data.push_back( pLayerElement->GetDirectArray().GetAt(index) );
}
}
}
//Optimize the data by eliminating duplicates and using an index array
void Optimize(void)
{
if(data.empty()) //Nothing to optimize
return;
const unsigned int nrOfIndices = data.size();
std::vector<T> uniqueData;
//Ignore previous indices
indices.clear();
indices.resize(nrOfIndices);
for(unsigned int i=0; i<nrOfIndices; ++i){
auto it = find(uniqueData.begin(), uniqueData.end(), data[i]);
//Current data is not a duplicate => add it to uniqueData
if(it == uniqueData.end()){
uniqueData.push_back(data[i]);
it = uniqueData.end() - 1;
}
//Store index to this element in our index array
indices[i] = it - uniqueData.begin();
}
//Replace current data with unique data
data = std::move(uniqueData);
}
};
struct Mesh
{
Mesh(FbxMesh* _pMesh);
Mesh(void);
//Get the name from the mesh node
std::string GetName(void);
//Store vertex attributes for later use
void ExtractData(void);
//Optimize stored vertex attributes
void Optimize(void);
VertexAttribute<FbxVector4> Positions;
VertexAttribute<FbxVector2> TexCoords;
VertexAttribute<FbxVector4> Normals;
VertexAttribute<FbxVector4> Tangents;
VertexAttribute<FbxVector4> Binormals;
VertexAttribute<FbxColor> Colors;
private:
FbxMesh* pMesh;
};
#endif