Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: chrome/browser/android/vr_shell/gltf_parser.cc

Issue 2757213003: Implementing glTF 1.0 parser (Closed)
Patch Set: Resolving merge. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 GltfParser::GltfParser() {}
17
18 GltfParser::~GltfParser() = default;
19
20 std::unique_ptr<gltf::Asset> GltfParser::Parse(
21 const base::DictionaryValue& dict) {
22 std::string gltf_version;
23 if (!dict.GetString("asset.version", &gltf_version) || gltf_version != "1.0")
24 return nullptr;
25
26 asset_ = base::MakeUnique<gltf::Asset>();
27
28 if (!ParseInternal(dict)) {
29 asset_.reset();
30 return nullptr;
31 }
32
33 return std::move(asset_);
34 }
35
36 bool GltfParser::ParseInternal(const base::DictionaryValue& dict) {
37 const base::DictionaryValue* sub_dict;
38 if (dict.GetDictionary("buffers", &sub_dict) && !SetBuffers(*sub_dict))
39 return false;
40 if (dict.GetDictionary("bufferViews", &sub_dict) &&
41 !SetBufferViews(*sub_dict))
42 return false;
43 if (dict.GetDictionary("accessors", &sub_dict) && !SetAccessors(*sub_dict))
44 return false;
45 if (dict.GetDictionary("meshes", &sub_dict) && !SetMeshes(*sub_dict))
46 return false;
47 if (dict.GetDictionary("nodes", &sub_dict) && !SetNodes(*sub_dict))
48 return false;
49 if (dict.GetDictionary("scenes", &sub_dict) && !SetScenes(*sub_dict))
50 return false;
51
52 std::string scene_key;
53 if (dict.GetString("scene", &scene_key)) {
54 auto scene_it = scene_ids_.find(scene_key);
55 if (scene_it == scene_ids_.end())
56 return false;
57 asset_->SetMainScene(asset_->GetScene(scene_it->second));
58 }
59
60 return true;
61 }
62
63 bool GltfParser::SetBuffers(const base::DictionaryValue& dict) {
64 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
65 const base::DictionaryValue* buffer_dict;
66 if (!it.value().GetAsDictionary(&buffer_dict))
67 return false;
68
69 std::string uri;
70 // TODO(acondor): Support files. Only inline data is supported now.
71 if (!buffer_dict->GetString("uri", &uri) ||
72 uri.substr(0, kBase64HeaderSize) != kBase64Header)
73 return false;
74
75 auto buffer = base::MakeUnique<gltf::Buffer>();
76 if (!base::Base64Decode(uri.substr(kBase64HeaderSize), buffer.get()))
77 return false;
78
79 int byte_length;
80 if (buffer_dict->GetInteger("byteLength", &byte_length) &&
81 static_cast<int>(buffer->length()) != byte_length)
82 return false;
83
84 buffer_ids_[it.key()] = asset_->AddBuffer(std::move(buffer));
85 }
86 return true;
87 }
88
89 bool GltfParser::SetBufferViews(const base::DictionaryValue& dict) {
90 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
91 const base::DictionaryValue* buffer_view_dict;
92 if (!it.value().GetAsDictionary(&buffer_view_dict))
93 return false;
94
95 auto buffer_view = base::MakeUnique<gltf::BufferView>();
96 std::string buffer_key;
97 if (!buffer_view_dict->GetString("buffer", &buffer_key))
98 return false;
99 auto buffer_it = buffer_ids_.find(buffer_key);
100 if (buffer_it == buffer_ids_.end())
101 return false;
102 buffer_view->buffer = asset_->GetBuffer(buffer_it->second);
103 if (!buffer_view_dict->GetInteger("byteOffset", &buffer_view->byte_offset))
104 return false;
105 buffer_view_dict->GetInteger("byteLength", &buffer_view->byte_length);
106 buffer_view_dict->GetInteger("target", &buffer_view->target);
107
108 buffer_view_ids_[it.key()] = asset_->AddBufferView(std::move(buffer_view));
109 }
110 return true;
111 }
112
113 bool GltfParser::SetAccessors(const base::DictionaryValue& dict) {
114 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
115 const base::DictionaryValue* accessor_dict;
116 if (!it.value().GetAsDictionary(&accessor_dict))
117 return false;
118
119 auto accessor = base::MakeUnique<gltf::Accessor>();
120 std::string buffer_view_key;
121 std::string type_str;
122 if (!accessor_dict->GetString("bufferView", &buffer_view_key))
123 return false;
124 auto buffer_view_it = buffer_view_ids_.find(buffer_view_key);
125 if (buffer_view_it == buffer_view_ids_.end())
126 return false;
127 accessor->buffer_view = asset_->GetBufferView(buffer_view_it->second);
128 if (!accessor_dict->GetInteger("byteOffset", &accessor->byte_offset))
129 return false;
130 accessor_dict->GetInteger("byteStride", &accessor->byte_stride);
131 if (!accessor_dict->GetInteger("componentType", &accessor->component_type))
132 return false;
133 if (!accessor_dict->GetInteger("count", &accessor->count))
134 return false;
135 if (!accessor_dict->GetString("type", &type_str))
136 return false;
137 gltf::Type type = gltf::GetType(type_str);
138 if (type == gltf::UNKNOWN)
139 return false;
140 accessor->type = type;
141
142 accessor_ids_[it.key()] = asset_->AddAccessor(std::move(accessor));
143 }
144 return true;
145 }
146
147 bool GltfParser::SetMeshes(const base::DictionaryValue& dict) {
148 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
149 const base::DictionaryValue* mesh_dict;
150 if (!it.value().GetAsDictionary(&mesh_dict))
151 return false;
152
153 auto mesh = base::MakeUnique<gltf::Mesh>();
154 const base::ListValue* list;
155 if (mesh_dict->GetList("primitives", &list)) {
156 for (const auto& primitive_value : *list) {
157 const base::DictionaryValue* primitive_dict;
158 if (!primitive_value->GetAsDictionary(&primitive_dict))
159 return false;
160
161 auto primitive = ProcessPrimitive(*primitive_dict);
162 if (!primitive)
163 return false;
164 mesh->primitives.push_back(std::move(primitive));
165 }
166 }
167
168 mesh_ids_[it.key()] = asset_->AddMesh(std::move(mesh));
169 }
170 return true;
171 }
172
173 std::unique_ptr<gltf::Mesh::Primitive> GltfParser::ProcessPrimitive(
174 const base::DictionaryValue& dict) {
175 auto primitive = base::MakeUnique<gltf::Mesh::Primitive>();
176 std::string indices_key;
177 const base::DictionaryValue* attributes;
178 if (dict.GetString("indices", &indices_key)) {
179 auto accessor_it = accessor_ids_.find(indices_key);
180 if (accessor_it == accessor_ids_.end())
181 return nullptr;
182 primitive->indices = asset_->GetAccessor(accessor_it->second);
183 }
184 dict.GetInteger("mode", &primitive->mode);
185 if (dict.GetDictionary("attributes", &attributes)) {
186 for (base::DictionaryValue::Iterator it(*attributes); !it.IsAtEnd();
187 it.Advance()) {
188 std::string accessor_key;
189 if (!it.value().GetAsString(&accessor_key))
190 return nullptr;
191 auto accessor_it = accessor_ids_.find(accessor_key);
192 if (accessor_it == accessor_ids_.end())
193 return nullptr;
194 primitive->attributes[it.key()] =
195 asset_->GetAccessor(accessor_it->second);
196 }
197 }
198 return primitive;
199 }
200
201 bool GltfParser::SetNodes(const base::DictionaryValue& dict) {
202 std::unordered_map<std::string, gltf::Node*> nodes;
203 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
204 const base::DictionaryValue* node_dict;
205 if (!it.value().GetAsDictionary(&node_dict))
206 return false;
207
208 auto node = base::MakeUnique<gltf::Node>();
209 const base::ListValue* list;
210 if (node_dict->GetList("meshes", &list)) {
211 std::string mesh_key;
212 for (const auto& mesh_value : *list) {
213 if (!mesh_value->GetAsString(&mesh_key))
214 return false;
215 auto mesh_it = mesh_ids_.find(mesh_key);
216 if (mesh_it == mesh_ids_.end())
217 return false;
218 node->meshes.push_back(asset_->GetMesh(mesh_it->second));
219 }
220 }
221
222 nodes[it.key()] = node.get();
223 node_ids_[it.key()] = asset_->AddNode(std::move(node));
224 }
225
226 // Processing children after all nodes have been added to the asset.
227 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
228 const base::DictionaryValue* node_dict;
229 it.value().GetAsDictionary(&node_dict);
230
231 gltf::Node* node = nodes[it.key()];
232 const base::ListValue* list;
233 if (node_dict->GetList("children", &list)) {
234 std::string node_key;
235 for (const auto& mesh_value : *list) {
236 if (!mesh_value->GetAsString(&node_key))
237 return false;
238 auto node_it = nodes.find(node_key);
239 if (node_it == nodes.end())
240 return false;
241 node->children.push_back(node_it->second);
242 }
243 }
244 }
245
246 return true;
247 }
248
249 bool GltfParser::SetScenes(const base::DictionaryValue& dict) {
250 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
251 const base::DictionaryValue* scene_dict;
252 if (!it.value().GetAsDictionary(&scene_dict))
253 return false;
254
255 auto scene = base::MakeUnique<gltf::Scene>();
256 const base::ListValue* list;
257 if (scene_dict->GetList("nodes", &list)) {
258 std::string node_key;
259 for (const auto& node_value : *list) {
260 if (!node_value->GetAsString(&node_key))
261 return false;
262 auto node_it = node_ids_.find(node_key);
263 if (node_it == node_ids_.end())
264 return false;
265 scene->nodes.push_back(asset_->GetNode(node_it->second));
266 }
267 }
268
269 scene_ids_[it.key()] = asset_->AddScene(std::move(scene));
270 }
271 return true;
272 }
273
274 } // namespace vr_shell
OLDNEW
« no previous file with comments | « chrome/browser/android/vr_shell/gltf_parser.h ('k') | chrome/browser/android/vr_shell/gltf_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698