OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/android/vr_shell/gltf_parser.h" | |
6 | |
7 #include "base/base64.h" | |
8 #include "base/logging.h" | |
9 #include "base/memory/ptr_util.h" | |
10 | |
11 namespace vr_shell { | |
12 | |
13 constexpr char kBase64Header[] = "data:application/octet-stream;base64,"; | |
14 constexpr size_t kBase64HeaderSize = 37; | |
15 | |
16 namespace gltf { | |
17 | |
18 const std::unordered_map<std::string, Type> kTypeMap = { | |
19 {"SCALAR", SCALAR}, {"VEC2", VEC2}, {"VEC3", VEC3}, {"VEC4", VEC4}, | |
20 {"MAT2", MAT2}, {"MAT3", MAT3}, {"MAT4", MAT4}, | |
21 }; | |
22 | |
23 Type GetType(const std::string& type) { | |
24 auto it = kTypeMap.find(type); | |
25 CHECK(it != kTypeMap.end()); | |
26 return it->second; | |
27 } | |
28 | |
29 Primitive::Primitive() : indices(nullptr), mode(0) {} | |
30 | |
31 Primitive::~Primitive() = default; | |
32 | |
33 Mesh::Mesh() {} | |
34 | |
35 Mesh::~Mesh() = default; | |
36 | |
37 Node::Node() {} | |
38 | |
39 Node::~Node() = default; | |
40 | |
41 Scene::Scene() {} | |
42 | |
43 Scene::~Scene() = default; | |
44 | |
45 Asset::Asset() : scene_(nullptr) {} | |
46 | |
47 Asset::~Asset() = default; | |
48 | |
49 } // namespace gltf | |
50 | |
51 GltfParser::GltfParser() {} | |
52 | |
53 GltfParser::~GltfParser() = default; | |
54 | |
55 std::unique_ptr<gltf::Asset> GltfParser::Parse( | |
56 const base::DictionaryValue& dict) { | |
57 std::string gltf_version; | |
58 CHECK(dict.GetString("asset.version", &gltf_version)); | |
59 CHECK(gltf_version == "1.0"); | |
60 | |
61 asset_ = base::MakeUnique<gltf::Asset>(); | |
62 | |
63 const base::DictionaryValue* sub_dict; | |
64 CHECK(dict.GetDictionary("buffers", &sub_dict)); | |
65 SetBuffers(*sub_dict); | |
66 CHECK(dict.GetDictionary("bufferViews", &sub_dict)); | |
67 SetBufferViews(*sub_dict); | |
68 CHECK(dict.GetDictionary("accessors", &sub_dict)); | |
69 SetAccessors(*sub_dict); | |
70 CHECK(dict.GetDictionary("meshes", &sub_dict)); | |
71 SetMeshes(*sub_dict); | |
72 CHECK(dict.GetDictionary("nodes", &sub_dict)); | |
73 SetNodes(*sub_dict); | |
74 CHECK(dict.GetDictionary("scenes", &sub_dict)); | |
75 SetScenes(*sub_dict); | |
76 std::string scene_key; | |
77 CHECK(dict.GetString("scene", &scene_key)); | |
78 auto scene_it = scene_ids_.find(scene_key); | |
79 CHECK(scene_it != scene_ids_.end()); | |
80 asset_->SetScene(asset_->GetScene(scene_it->second)); | |
81 | |
82 return std::move(asset_); | |
83 } | |
84 | |
85 void GltfParser::SetBuffers(const base::DictionaryValue& dict) { | |
86 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | |
87 const base::DictionaryValue* buffer_dict; | |
88 CHECK(it.value().GetAsDictionary(&buffer_dict)); | |
89 | |
90 std::string uri; | |
91 CHECK(buffer_dict->GetString("uri", &uri)); | |
92 // Only inline data is supported | |
mthiesse
2017/03/21 16:06:54
nit: add period.
| |
93 CHECK(uri.substr(0, kBase64HeaderSize) == kBase64Header); | |
94 | |
95 auto buffer = base::MakeUnique<gltf::Buffer>(); | |
96 CHECK(base::Base64Decode(uri.substr(kBase64HeaderSize), buffer.get())); | |
97 | |
98 int byte_length; | |
99 CHECK(buffer_dict->GetInteger("byteLength", &byte_length)); | |
mthiesse
2017/03/21 16:06:54
byteLength isn't required by the spec, add a comme
acondor_
2017/03/21 19:31:29
Actually we don't need it.
| |
100 CHECK(int{buffer->length()} == byte_length); | |
mthiesse
2017/03/21 16:06:54
static_cast<int>(buffer->length())
acondor_
2017/03/21 19:31:29
Done.
| |
101 | |
102 buffer_ids_[it.key()] = asset_->AddBuffer(std::move(buffer)); | |
103 } | |
104 } | |
105 | |
106 void GltfParser::SetBufferViews(const base::DictionaryValue& dict) { | |
107 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | |
108 const base::DictionaryValue* buffer_view_dict; | |
109 CHECK(it.value().GetAsDictionary(&buffer_view_dict)); | |
110 | |
111 auto buffer_view = base::MakeUnique<gltf::BufferView>(); | |
112 std::string buffer_key; | |
113 CHECK(buffer_view_dict->GetString("buffer", &buffer_key)); | |
114 auto buffer_it = buffer_ids_.find(buffer_key); | |
115 CHECK(buffer_it != buffer_ids_.end()); | |
116 buffer_view->buffer = asset_->GetBuffer(buffer_it->second); | |
117 CHECK( | |
118 buffer_view_dict->GetInteger("byteLength", &buffer_view->byte_length)); | |
mthiesse
2017/03/21 16:06:54
byteLength and target are not required per the spe
acondor_
2017/03/21 19:31:29
Acknowledged.
| |
119 CHECK( | |
120 buffer_view_dict->GetInteger("byteOffset", &buffer_view->byte_offset)); | |
121 CHECK(buffer_view_dict->GetInteger("target", &buffer_view->target)); | |
122 | |
123 buffer_view_ids_[it.key()] = asset_->AddBufferView(std::move(buffer_view)); | |
124 } | |
125 } | |
126 | |
127 void GltfParser::SetAccessors(const base::DictionaryValue& dict) { | |
128 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | |
129 const base::DictionaryValue* accessor_dict; | |
130 CHECK(it.value().GetAsDictionary(&accessor_dict)); | |
131 | |
132 auto accessor = base::MakeUnique<gltf::Accessor>(); | |
133 std::string buffer_view_key; | |
134 std::string type_str; | |
135 CHECK(accessor_dict->GetString("bufferView", &buffer_view_key)); | |
136 auto buffer_view_it = buffer_view_ids_.find(buffer_view_key); | |
137 CHECK(buffer_view_it != buffer_view_ids_.end()); | |
138 accessor->buffer_view = asset_->GetBufferView(buffer_view_it->second); | |
139 CHECK(accessor_dict->GetInteger("byteOffset", &accessor->byte_offset)); | |
140 CHECK(accessor_dict->GetInteger("byteStride", &accessor->byte_stride)); | |
mthiesse
2017/03/21 16:06:54
Also not required per spec, add comment?
acondor_
2017/03/21 19:31:29
Acknowledged.
| |
141 CHECK( | |
142 accessor_dict->GetInteger("componentType", &accessor->component_type)); | |
143 CHECK(accessor_dict->GetInteger("count", &accessor->count)); | |
144 CHECK(accessor_dict->GetString("type", &type_str)); | |
145 accessor->type = gltf::GetType(type_str); | |
146 | |
147 accessor_ids_[it.key()] = asset_->AddAccessor(std::move(accessor)); | |
148 } | |
149 } | |
150 | |
151 void GltfParser::SetMeshes(const base::DictionaryValue& dict) { | |
152 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | |
153 const base::DictionaryValue* mesh_dict; | |
154 CHECK(it.value().GetAsDictionary(&mesh_dict)); | |
155 | |
156 auto mesh = base::MakeUnique<gltf::Mesh>(); | |
157 const base::ListValue* list; | |
158 CHECK(mesh_dict->GetList("primitives", &list)); | |
159 for (const auto& primitive_value : *list) { | |
mthiesse
2017/03/21 16:06:54
nit: Move parsing of mesh.primitive into separate
| |
160 const base::DictionaryValue* primitive_dict; | |
mthiesse
2017/03/21 16:06:54
Add comment that we ignore the required material a
acondor_
2017/03/21 19:31:29
Done.
| |
161 CHECK(primitive_value->GetAsDictionary(&primitive_dict)); | |
162 | |
163 auto primitive = base::MakeUnique<gltf::Primitive>(); | |
164 std::string indices_key; | |
165 const base::DictionaryValue* attributes; | |
166 CHECK(primitive_dict->GetString("indices", &indices_key)); | |
mthiesse
2017/03/21 16:06:54
Add comment, not required per spec.
acondor_
2017/03/21 19:31:29
Acknowledged.
| |
167 auto accessor_it = accessor_ids_.find(indices_key); | |
168 CHECK(accessor_it != accessor_ids_.end()); | |
169 primitive->indices = asset_->GetAccessor(accessor_it->second); | |
170 CHECK(primitive_dict->GetInteger("mode", &primitive->mode)); | |
mthiesse
2017/03/21 16:06:54
Add comment, not required per spec.
acondor_
2017/03/21 19:31:29
Acknowledged.
| |
171 CHECK(primitive_dict->GetDictionary("attributes", &attributes)); | |
mthiesse
2017/03/21 16:06:54
Attributes isn't required per spec. Do we need it,
acondor_
2017/03/21 19:31:29
We can handle them. Recall that the only model we
| |
172 for (base::DictionaryValue::Iterator it2(*attributes); !it2.IsAtEnd(); | |
173 it2.Advance()) { | |
174 std::string accessor_key; | |
175 CHECK(it2.value().GetAsString(&accessor_key)); | |
176 accessor_it = accessor_ids_.find(accessor_key); | |
177 CHECK(accessor_it != accessor_ids_.end()); | |
178 primitive->attributes[it2.key()] = | |
179 asset_->GetAccessor(accessor_it->second); | |
180 } | |
181 | |
182 mesh->primitives.push_back(std::move(primitive)); | |
183 } | |
184 | |
185 mesh_ids_[it.key()] = asset_->AddMesh(std::move(mesh)); | |
186 } | |
187 } | |
188 | |
189 void GltfParser::SetNodes(const base::DictionaryValue& dict) { | |
190 std::unordered_map<std::string, gltf::Node*> nodes; | |
191 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | |
192 const base::DictionaryValue* node_dict; | |
193 CHECK(it.value().GetAsDictionary(&node_dict)); | |
194 | |
195 auto node = base::MakeUnique<gltf::Node>(); | |
196 const base::ListValue* list; | |
197 if (node_dict->GetList("meshes", &list)) { | |
198 std::string mesh_key; | |
199 for (const auto& mesh_value : *list) { | |
200 CHECK(mesh_value->GetAsString(&mesh_key)); | |
201 auto mesh_it = mesh_ids_.find(mesh_key); | |
202 CHECK(mesh_it != mesh_ids_.end()); | |
203 node->meshes.push_back(asset_->GetMesh(mesh_it->second)); | |
204 } | |
205 } | |
206 | |
207 nodes[it.key()] = node.get(); | |
208 node_ids_[it.key()] = asset_->AddNode(std::move(node)); | |
209 } | |
210 | |
211 // Processing children after all nodes have been added to the asset. | |
212 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | |
213 const base::DictionaryValue* node_dict; | |
214 it.value().GetAsDictionary(&node_dict); | |
215 | |
216 gltf::Node* node = nodes[it.key()]; | |
217 const base::ListValue* list; | |
218 if (node_dict->GetList("children", &list)) { | |
219 std::string node_key; | |
220 for (const auto& mesh_value : *list) { | |
221 CHECK(mesh_value->GetAsString(&node_key)); | |
222 auto node_it = nodes.find(node_key); | |
223 CHECK(node_it != nodes.end()); | |
224 node->children.push_back(node_it->second); | |
225 } | |
226 } | |
227 } | |
228 } | |
229 | |
230 void GltfParser::SetScenes(const base::DictionaryValue& dict) { | |
231 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | |
232 const base::DictionaryValue* scene_dict; | |
233 CHECK(it.value().GetAsDictionary(&scene_dict)); | |
234 | |
235 auto scene = base::MakeUnique<gltf::Scene>(); | |
236 const base::ListValue* list; | |
237 CHECK(scene_dict->GetList("nodes", &list)); | |
mthiesse
2017/03/21 16:06:54
Not required per spec
acondor_
2017/03/21 19:31:29
Acknowledged.
| |
238 std::string node_key; | |
239 for (const auto& node_value : *list) { | |
240 CHECK(node_value->GetAsString(&node_key)); | |
241 auto node_it = node_ids_.find(node_key); | |
242 CHECK(node_it != node_ids_.end()); | |
243 scene->nodes.push_back(asset_->GetNode(node_it->second)); | |
244 } | |
245 | |
246 scene_ids_[it.key()] = asset_->AddScene(std::move(scene)); | |
247 } | |
248 } | |
249 | |
250 } // namespace vr_shell | |
OLD | NEW |