Overte C++ Documentation
HFM.h
1 //
2 // HFM.h
3 // libraries/hfm/src
4 //
5 // Created by Sabrina Shanman on 2018/11/02.
6 // Copyright 2018 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_HFM_h_
13 #define hifi_HFM_h_
14 
15 #include <QMetaType>
16 #include <QSet>
17 #include <QVector>
18 
19 #include <glm/glm.hpp>
20 #include <glm/gtc/quaternion.hpp>
21 
22 #include <Extents.h>
23 #include <Transform.h>
24 
25 #include <gpu/Texture.h>
26 #include <graphics/Geometry.h>
27 #include <graphics/Material.h>
28 
29 #include <image/ColorChannel.h>
30 
31 #if defined(Q_OS_ANDROID)
32 #define HFM_PACK_NORMALS 0
33 #else
34 #define HFM_PACK_NORMALS 1
35 #endif
36 
37 #if HFM_PACK_NORMALS
38 using NormalType = glm::uint32;
39 #define HFM_NORMAL_ELEMENT gpu::Element::VEC4F_NORMALIZED_XYZ10W2
40 #else
41 using NormalType = glm::vec3;
42 #define HFM_NORMAL_ELEMENT gpu::Element::VEC3F_XYZ
43 #endif
44 
45 #define HFM_PACK_COLORS 1
46 
47 #if HFM_PACK_COLORS
48 using ColorType = glm::uint32;
49 #define HFM_COLOR_ELEMENT gpu::Element::COLOR_RGBA_32
50 #else
51 using ColorType = glm::vec3;
52 #define HFM_COLOR_ELEMENT gpu::Element::VEC3F_XYZ
53 #endif
54 
55 const int MAX_NUM_PIXELS_FOR_FBX_TEXTURE = 8192 * 8192;
56 
57 
58 using ShapeVertices = std::vector<glm::vec3>;
59 // The version of the Draco mesh binary data itself. See also: FBX_DRACO_MESH_VERSION in FBX.h
60 static const int DRACO_MESH_VERSION = 3;
61 
62 static const int DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES = 1000;
63 static const int DRACO_ATTRIBUTE_MATERIAL_ID = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES;
64 static const int DRACO_ATTRIBUTE_TEX_COORD_1 = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES + 1;
65 static const int DRACO_ATTRIBUTE_ORIGINAL_INDEX = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES + 2;
66 
67 // High Fidelity Model namespace
68 namespace hfm {
69 
71 class Blendshape {
72 public:
73  QVector<int> indices;
74  QVector<glm::vec3> vertices;
75  QVector<glm::vec3> normals;
76  QVector<glm::vec3> tangents;
77 };
78 
79 struct JointShapeInfo {
80  // same units and frame as Joint.translation
81  glm::vec3 avgPoint;
82  std::vector<float> dots;
83  std::vector<glm::vec3> points;
84  std::vector<glm::vec3> debugLines;
85 };
86 
88 class Joint {
89 public:
90  JointShapeInfo shapeInfo;
91  int parentIndex;
92  float distanceToParent;
93 
94  // http://download.autodesk.com/us/fbx/20112/FBX_SDK_HELP/SDKRef/a00209.html
95 
96  glm::vec3 translation; // T
97  glm::mat4 preTransform; // Roff * Rp
98  glm::quat preRotation; // Rpre
99  glm::quat rotation; // R
100  glm::quat postRotation; // Rpost
101  glm::mat4 postTransform; // Rp-1 * Soff * Sp * S * Sp-1
102 
103  // World = ParentWorld * T * (Roff * Rp) * Rpre * R * Rpost * (Rp-1 * Soff * Sp * S * Sp-1)
104 
105  glm::mat4 transform;
106  glm::vec3 rotationMin; // radians
107  glm::vec3 rotationMax; // radians
108  glm::quat inverseDefaultRotation;
109  glm::quat inverseBindRotation;
110  glm::mat4 bindTransform;
111  QString name;
112  bool isSkeletonJoint;
113  bool bindTransformFoundInCluster;
114 
115  // geometric offset is applied in local space but does NOT affect children.
116  bool hasGeometricOffset;
117  glm::vec3 geometricTranslation;
118  glm::quat geometricRotation;
119  glm::vec3 geometricScaling;
120 };
121 
122 
124 class Cluster {
125 public:
126 
127  int jointIndex;
128  glm::mat4 inverseBindMatrix;
129  Transform inverseBindTransform;
130 };
131 
133 class Texture {
134 public:
135 
136  QString id;
137  QString name;
138  QByteArray filename;
139  QByteArray content;
140  image::ColorChannel sourceChannel { image::ColorChannel::NONE };
141 
142  Transform transform;
143  int maxNumPixels { MAX_NUM_PIXELS_FOR_FBX_TEXTURE };
144  int texcoordSet;
145  QString texcoordSetName;
146 
147  bool isBumpmap { false };
148 
149  Sampler sampler;
150 
151  bool isNull() const { return name.isEmpty() && filename.isEmpty() && content.isEmpty(); }
152 };
153 
155 class MeshPart {
156 public:
157 
158  QVector<int> quadIndices; // original indices from the FBX mesh
159  QVector<int> quadTrianglesIndices; // original indices from the FBX mesh of the quad converted as triangles
160  QVector<int> triangleIndices; // original indices from the FBX mesh
161 
162  QString materialID;
163 };
164 
165 class Material {
166 public:
167  Material() {};
168  Material(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor,
169  float shininess, float opacity) :
170  diffuseColor(diffuseColor),
171  specularColor(specularColor),
172  emissiveColor(emissiveColor),
173  shininess(shininess),
174  opacity(opacity) {}
175 
176  void getTextureNames(QSet<QString>& textureList) const;
177  void setMaxNumPixelsPerTexture(int maxNumPixels);
178 
179  glm::vec3 diffuseColor { 1.0f };
180  float diffuseFactor { 1.0f };
181  glm::vec3 specularColor { 0.02f };
182  float specularFactor { 1.0f };
183 
184  glm::vec3 emissiveColor { 0.0f };
185  float emissiveFactor { 0.0f };
186 
187  float shininess { 23.0f };
188  float opacity { 1.0f };
189 
190  float metallic { 0.0f };
191  float roughness { 1.0f };
192  float emissiveIntensity { 1.0f };
193  float ambientFactor { 1.0f };
194 
195  float bumpMultiplier { 1.0f }; // TODO: to be implemented
196 
197  graphics::MaterialKey::OpacityMapMode alphaMode { graphics::MaterialKey::OPACITY_MAP_BLEND };
198  float alphaCutoff { 0.5f };
199 
200  QString materialID;
201  QString name;
202  QString shadingModel;
203  graphics::MaterialPointer _material;
204 
205  Texture normalTexture;
206  Texture albedoTexture;
207  Texture opacityTexture;
208  Texture glossTexture;
209  Texture roughnessTexture;
210  Texture specularTexture;
211  Texture metallicTexture;
212  Texture emissiveTexture;
213  Texture occlusionTexture;
214  Texture scatteringTexture;
215  Texture lightmapTexture;
216  glm::vec2 lightmapParams { 0.0f, 1.0f };
217 
218 
219  bool isPBSMaterial { false };
220  // THe use XXXMap are not really used to drive which map are going or not, debug only
221  bool useNormalMap { false };
222  bool useAlbedoMap { false };
223  bool useOpacityMap { false };
224  bool useRoughnessMap { false };
225  bool useSpecularMap { false };
226  bool useMetallicMap { false };
227  bool useEmissiveMap { false };
228  bool useOcclusionMap { false };
229 
230 
231  bool isMToonMaterial { false };
232  Texture shadeTexture;
233  Texture shadingShiftTexture;
234  Texture matcapTexture;
235  Texture rimTexture;
236  Texture uvAnimationTexture;
237 
238  bool needTangentSpace() const;
239 };
240 
242 class Mesh {
243 public:
244 
245  QVector<MeshPart> parts;
246 
247  QVector<glm::vec3> vertices;
248  QVector<glm::vec3> normals;
249  QVector<glm::vec3> tangents;
250  QVector<glm::vec3> colors;
251  QVector<glm::vec2> texCoords;
252  QVector<glm::vec2> texCoords1;
253  QVector<uint16_t> clusterIndices;
254  QVector<uint16_t> clusterWeights;
255  QVector<int32_t> originalIndices;
256 
257  QVector<Cluster> clusters;
258 
259  Extents meshExtents;
260  glm::mat4 modelTransform;
261 
262  QVector<Blendshape> blendshapes;
263 
264  unsigned int meshIndex; // the order the meshes appeared in the object file
265 
266  graphics::MeshPointer _mesh;
267  bool wasCompressed { false };
268 };
269 
272 public:
273  QVector<glm::quat> rotations;
274  QVector<glm::vec3> translations;
275 };
276 
278 class Light {
279 public:
280  QString name;
281  Transform transform;
282  float intensity;
283  float fogValue;
284  glm::vec3 color;
285 
286  Light() :
287  name(),
288  transform(),
289  intensity(1.0f),
290  fogValue(0.0f),
291  color(1.0f)
292  {}
293 };
294 
295 class FlowData {
296 public:
297  FlowData() {};
298  QVariantMap _physicsConfig;
299  QVariantMap _collisionsConfig;
300  bool shouldInitFlow() const { return _physicsConfig.size() > 0; }
301  bool shouldInitCollisions() const { return _collisionsConfig.size() > 0; }
302 };
303 
305 class Model {
306 public:
307  using Pointer = std::shared_ptr<Model>;
308  using ConstPointer = std::shared_ptr<const Model>;
309 
310  QString originalURL;
311  QString author;
312  QString applicationName;
313 
314  QVector<Joint> joints;
315  QHash<QString, int> jointIndices;
316  bool hasSkeletonJoints;
317 
318  QVector<Mesh> meshes;
319  QVector<QString> scripts;
320 
321  QHash<QString, Material> materials;
322 
323  glm::mat4 offset; // This includes offset, rotation, and scale as specified by the FST file
324 
325  glm::vec3 neckPivot;
326 
327  Extents bindExtents;
328  Extents meshExtents;
329 
330  QVector<AnimationFrame> animationFrames;
331 
332  int getJointIndex(const QString& name) const { return jointIndices.value(name) - 1; }
333  QStringList getJointNames() const;
334 
335  bool hasBlendedMeshes() const;
336 
338  Extents getUnscaledMeshExtents() const;
339  const Extents& getMeshExtents() const { return meshExtents; }
340 
341  bool convexHullContains(const glm::vec3& point) const;
342 
343  QHash<int, QString> meshIndicesToModelNames;
344 
346  QString getModelNameOfMesh(int meshIndex) const;
347  void computeKdops();
348 
349  QList<QString> blendshapeChannelNames;
350 
351  QMap<int, glm::quat> jointRotationOffsets;
352  std::vector<ShapeVertices> shapeVertices;
353  FlowData flowData;
354 
355  void debugDump();
356 
366 
374  int loadErrorCount = 0;
375 
376 };
377 
378 };
379 
380 class ExtractedMesh {
381 public:
382  hfm::Mesh mesh;
383  QMultiHash<int, int> newIndices;
384  QVector<QHash<int, int> > blendshapeIndexMaps;
385  QVector<QPair<int, int> > partMaterialTextures;
386  QHash<QString, size_t> texcoordSetMap;
387 };
388 
390 typedef hfm::JointShapeInfo HFMJointShapeInfo;
391 typedef hfm::Joint HFMJoint;
392 typedef hfm::Cluster HFMCluster;
393 typedef hfm::Texture HFMTexture;
394 typedef hfm::MeshPart HFMMeshPart;
395 typedef hfm::Material HFMMaterial;
396 typedef hfm::Mesh HFMMesh;
398 typedef hfm::Light HFMLight;
399 typedef hfm::Model HFMModel;
400 typedef hfm::FlowData FlowData;
401 
402 Q_DECLARE_METATYPE(HFMAnimationFrame)
403 Q_DECLARE_METATYPE(QVector<HFMAnimationFrame>)
404 Q_DECLARE_METATYPE(HFMModel)
405 Q_DECLARE_METATYPE(HFMModel::Pointer)
406 
407 #endif // hifi_HFM_h_
A simple object wrapper for an OpenGL texture.
Definition: material-networking/src/material-networking/TextureCache.h:39
A single animation frame.
Definition: HFM.h:271
A single blendshape.
Definition: HFM.h:71
A single binding to a joint.
Definition: HFM.h:124
A single joint (transformation node).
Definition: HFM.h:88
A light.
Definition: HFM.h:278
A single mesh (with optional blendshapes).
Definition: HFM.h:242
A single part of a mesh (with the same material).
Definition: HFM.h:155
The runtime model format.
Definition: HFM.h:305
Extents getUnscaledMeshExtents() const
Returns the unscaled extents of the model's mesh.
Definition: HFM.cpp:113
int loadWarningCount
Get the number of warnings that were generated when loading this model.
Definition: HFM.h:365
int loadErrorCount
Get the number of errors that were generated when loading this model.
Definition: HFM.h:374
QString applicationName
the name of the application that generated the model
Definition: HFM.h:312
QHash< QString, int > jointIndices
1-based, so as to more easily detect missing indices
Definition: HFM.h:315
QString getModelNameOfMesh(int meshIndex) const
given a meshIndex this will return the name of the model that mesh belongs to if known
Definition: HFM.cpp:175
A texture map.
Definition: HFM.h:133