Overte C++ Documentation
OBJSerializer.h
1 //
2 // OBJSerializer.h
3 // libraries/model-serializers/src
4 //
5 // Created by Seth Alves on 3/6/15.
6 // Copyright 2015 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_OBJSerializer_h
13 #define hifi_OBJSerializer_h
14 
15 #include <QtNetwork/QNetworkReply>
16 #include <hfm/HFMSerializer.h>
17 
18 class OBJTokenizer {
19 public:
20  OBJTokenizer(QIODevice* device);
21  enum SpecialToken {
22  NO_TOKEN = -1,
23  NO_PUSHBACKED_TOKEN = -1,
24  DATUM_TOKEN = 0x100,
25  COMMENT_TOKEN = 0x101
26  };
27  int nextToken(bool allowSpaceChar = false);
28  const hifi::ByteArray& getDatum() const { return _datum; }
29  bool isNextTokenFloat();
30  const hifi::ByteArray getLineAsDatum(); // some "filenames" have spaces in them
31  void skipLine() { _device->readLine(); }
32  void pushBackToken(int token) { _pushedBackToken = token; }
33  void ungetChar(char ch) { _device->ungetChar(ch); }
34  const QString getComment() const { return _comment; }
35  glm::vec3 getVec3();
36  bool getVertex(glm::vec3& vertex, glm::vec3& vertexColor);
37  glm::vec2 getVec2();
38  float getFloat();
39 
40 private:
41  QIODevice* _device;
42  hifi::ByteArray _datum;
43  int _pushedBackToken;
44  QString _comment;
45 };
46 
47 class OBJFace { // A single face, with three or more planar vertices. But see triangulate().
48 public:
49  QVector<int> vertexIndices;
50  QVector<int> textureUVIndices;
51  QVector<int> normalIndices;
52  QString groupName; // We don't make use of hierarchical structure, but it can be preserved for debugging and future use.
53  QString materialName;
54  // Add one more set of vertex data. Answers true if successful
55  bool add(const hifi::ByteArray& vertexIndex, const hifi::ByteArray& textureIndex, const hifi::ByteArray& normalIndex,
56  const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& vertexColors);
57  // Return a set of one or more OBJFaces from this one, in which each is just a triangle.
58  // Even though HFMMeshPart can handle quads, it would be messy to try to keep track of mixed-size faces, so we treat everything as triangles.
59  QVector<OBJFace> triangulate();
60 private:
61  void addFrom(const OBJFace* face, int index);
62 };
63 
64 class OBJMaterialTextureOptions {
65 public:
66  float bumpMultiplier { 1.0f };
67 }
68 ;
69 // Materials and references to material names can come in any order, and different mesh parts can refer to the same material.
70 // Therefore it would get pretty hacky to try to use HFMMeshPart to store these as we traverse the files.
71 class OBJMaterial {
72 public:
73  float shininess;
74  float opacity;
75  glm::vec3 diffuseColor;
76  glm::vec3 specularColor;
77  glm::vec3 emissiveColor;
78  hifi::ByteArray diffuseTextureFilename;
79  hifi::ByteArray specularTextureFilename;
80  hifi::ByteArray emissiveTextureFilename;
81  hifi::ByteArray bumpTextureFilename;
82  hifi::ByteArray opacityTextureFilename;
83 
84  OBJMaterialTextureOptions bumpTextureOptions;
85  int illuminationModel;
86  bool used { false };
87  bool userSpecifiesUV { false };
88  OBJMaterial() : shininess(0.0f), opacity(1.0f), diffuseColor(0.9f), specularColor(0.9f), emissiveColor(0.0f), illuminationModel(-1) {}
89 };
90 
91 class OBJSerializer: public QObject, public HFMSerializer { // QObject so we can make network requests.
92  Q_OBJECT
93 public:
94  MediaType getMediaType() const override;
95  std::unique_ptr<hfm::Serializer::Factory> getFactory() const override;
96 
97  typedef QVector<OBJFace> FaceGroup;
98  QVector<glm::vec3> vertices;
99  QVector<glm::vec3> vertexColors;
100  QVector<glm::vec2> textureUVs;
101  QVector<glm::vec3> normals;
102  QVector<FaceGroup> faceGroups;
103  QString currentMaterialName;
104  QHash<QString, OBJMaterial> materials;
105 
106  HFMModel::Pointer read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url = hifi::URL()) override;
107 
108 private:
109  hifi::URL _url;
110 
111  QHash<hifi::ByteArray, bool> librariesSeen;
112  bool parseOBJGroup(OBJTokenizer& tokenizer, const hifi::VariantHash& mapping, HFMModel& hfmModel,
113  float& scaleGuess, bool combineParts);
114  void parseMaterialLibrary(QIODevice* device);
115  void parseTextureLine(const hifi::ByteArray& textureLine, hifi::ByteArray& filename, OBJMaterialTextureOptions& textureOptions);
116  bool isValidTexture(const hifi::ByteArray &filename); // true if the file exists. TODO?: check content-type header and that it is a supported format.
117 
118  int _partCounter { 0 };
119 };
120 
121 // What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility.
122 void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID);
123 void hfmDebugDump(const HFMModel& hfmModel);
124 
125 #endif // hifi_OBJSerializer_h
A single part of a mesh (with the same material).
Definition: HFM.h:152
The runtime model format.
Definition: HFM.h:302