OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/android/vr_shell/gltf_parser.h" | 5 #include "chrome/browser/android/vr_shell/gltf_parser.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/files/file_util.h" |
8 #include "base/json/json_file_value_serializer.h" | |
8 #include "base/logging.h" | 9 #include "base/logging.h" |
9 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "net/base/data_url.h" | |
12 #include "net/base/filename_util.h" | |
13 #include "url/gurl.h" | |
10 | 14 |
11 namespace vr_shell { | 15 namespace vr_shell { |
12 | 16 |
13 constexpr char kBase64Header[] = "data:application/octet-stream;base64,"; | |
14 constexpr size_t kBase64HeaderSize = 37; | |
15 | |
16 GltfParser::GltfParser() {} | 17 GltfParser::GltfParser() {} |
17 | 18 |
18 GltfParser::~GltfParser() = default; | 19 GltfParser::~GltfParser() = default; |
19 | 20 |
21 GltfParser::Helper::Helper(const base::FilePath& path) | |
22 : asset(base::MakeUnique<gltf::Asset>()), path(path) {} | |
23 | |
24 GltfParser::Helper::~Helper() = default; | |
25 | |
20 std::unique_ptr<gltf::Asset> GltfParser::Parse( | 26 std::unique_ptr<gltf::Asset> GltfParser::Parse( |
21 const base::DictionaryValue& dict) { | 27 const base::DictionaryValue& dict, |
28 const base::FilePath& path) { | |
29 Helper helper(path); | |
30 helper_ = &helper; | |
mthiesse
2017/03/24 18:11:10
Okay, this is worse than what you had before ;)
I
acondor_
2017/03/24 20:36:13
Done.
| |
31 | |
22 std::string gltf_version; | 32 std::string gltf_version; |
23 if (!dict.GetString("asset.version", &gltf_version) || gltf_version != "1.0") | 33 if (!dict.GetString("asset.version", &gltf_version) || gltf_version != "1.0") |
24 return nullptr; | 34 return nullptr; |
25 | 35 |
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; | 36 const base::DictionaryValue* sub_dict; |
38 if (dict.GetDictionary("buffers", &sub_dict) && !SetBuffers(*sub_dict)) | 37 if (dict.GetDictionary("buffers", &sub_dict) && !SetBuffers(*sub_dict)) |
39 return false; | 38 return nullptr; |
40 if (dict.GetDictionary("bufferViews", &sub_dict) && | 39 if (dict.GetDictionary("bufferViews", &sub_dict) && |
41 !SetBufferViews(*sub_dict)) | 40 !SetBufferViews(*sub_dict)) |
42 return false; | 41 return nullptr; |
43 if (dict.GetDictionary("accessors", &sub_dict) && !SetAccessors(*sub_dict)) | 42 if (dict.GetDictionary("accessors", &sub_dict) && !SetAccessors(*sub_dict)) |
44 return false; | 43 return nullptr; |
45 if (dict.GetDictionary("meshes", &sub_dict) && !SetMeshes(*sub_dict)) | 44 if (dict.GetDictionary("meshes", &sub_dict) && !SetMeshes(*sub_dict)) |
46 return false; | 45 return nullptr; |
47 if (dict.GetDictionary("nodes", &sub_dict) && !SetNodes(*sub_dict)) | 46 if (dict.GetDictionary("nodes", &sub_dict) && !SetNodes(*sub_dict)) |
48 return false; | 47 return nullptr; |
49 if (dict.GetDictionary("scenes", &sub_dict) && !SetScenes(*sub_dict)) | 48 if (dict.GetDictionary("scenes", &sub_dict) && !SetScenes(*sub_dict)) |
50 return false; | 49 return nullptr; |
51 | 50 |
52 std::string scene_key; | 51 std::string scene_key; |
53 if (dict.GetString("scene", &scene_key)) { | 52 if (dict.GetString("scene", &scene_key)) { |
54 auto scene_it = scene_ids_.find(scene_key); | 53 auto scene_it = helper.scene_ids.find(scene_key); |
55 if (scene_it == scene_ids_.end()) | 54 if (scene_it == helper.scene_ids.end()) |
56 return false; | 55 return nullptr; |
57 asset_->SetMainScene(asset_->GetScene(scene_it->second)); | 56 helper.asset->SetMainScene(helper.asset->GetScene(scene_it->second)); |
58 } | 57 } |
59 | 58 |
60 return true; | 59 return std::move(helper.asset); |
60 } | |
61 | |
62 std::unique_ptr<gltf::Asset> GltfParser::Parse( | |
63 const base::FilePath& gltf_path) { | |
64 JSONFileValueDeserializer json_deserializer(gltf_path); | |
65 int error_code; | |
66 std::string error_msg; | |
67 auto asset_value = json_deserializer.Deserialize(&error_code, &error_msg); | |
68 if (!asset_value) | |
69 return nullptr; | |
70 base::DictionaryValue* asset; | |
71 if (!asset_value->GetAsDictionary(&asset)) | |
72 return nullptr; | |
73 return Parse(*asset, gltf_path); | |
61 } | 74 } |
62 | 75 |
63 bool GltfParser::SetBuffers(const base::DictionaryValue& dict) { | 76 bool GltfParser::SetBuffers(const base::DictionaryValue& dict) { |
64 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | 77 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { |
65 const base::DictionaryValue* buffer_dict; | 78 const base::DictionaryValue* buffer_dict; |
66 if (!it.value().GetAsDictionary(&buffer_dict)) | 79 if (!it.value().GetAsDictionary(&buffer_dict)) |
67 return false; | 80 return false; |
68 | 81 |
69 std::string uri; | 82 std::string uri_str; |
70 // TODO(acondor): Support files. Only inline data is supported now. | 83 if (!buffer_dict->GetString("uri", &uri_str)) |
71 if (!buffer_dict->GetString("uri", &uri) || | |
72 uri.substr(0, kBase64HeaderSize) != kBase64Header) | |
73 return false; | 84 return false; |
74 | 85 auto buffer = ProcessUri(uri_str); |
75 auto buffer = base::MakeUnique<gltf::Buffer>(); | 86 if (!buffer) |
76 if (!base::Base64Decode(uri.substr(kBase64HeaderSize), buffer.get())) | |
77 return false; | 87 return false; |
78 | 88 |
79 int byte_length; | 89 int byte_length; |
80 if (buffer_dict->GetInteger("byteLength", &byte_length) && | 90 if (buffer_dict->GetInteger("byteLength", &byte_length) && |
81 static_cast<int>(buffer->length()) != byte_length) | 91 static_cast<int>(buffer->length()) != byte_length) |
82 return false; | 92 return false; |
83 | 93 |
84 buffer_ids_[it.key()] = asset_->AddBuffer(std::move(buffer)); | 94 helper_->buffer_ids[it.key()] = |
95 helper_->asset->AddBuffer(std::move(buffer)); | |
85 } | 96 } |
86 return true; | 97 return true; |
87 } | 98 } |
88 | 99 |
100 std::unique_ptr<gltf::Buffer> GltfParser::ProcessUri( | |
101 const std::string& uri_str) { | |
102 auto uri = helper_->path.empty() | |
103 ? GURL(uri_str) | |
104 : net::FilePathToFileURL(helper_->path).Resolve(uri_str); | |
105 if (!uri.is_valid()) | |
106 return nullptr; | |
107 if (uri.SchemeIs(url::kDataScheme)) { | |
108 std::string mime_type; | |
109 std::string charset; | |
110 auto data = base::MakeUnique<gltf::Buffer>(); | |
111 if (!net::DataURL::Parse(uri, &mime_type, &charset, data.get())) | |
112 return nullptr; | |
113 return data; | |
114 } | |
115 if (uri.SchemeIsFile()) { | |
116 auto data = base::MakeUnique<gltf::Buffer>(); | |
117 if (!base::ReadFileToString(base::FilePath(uri.path()), data.get())) | |
118 return nullptr; | |
119 return data; | |
120 } | |
121 // No other schemes are supported yet. | |
122 return nullptr; | |
123 } | |
124 | |
89 bool GltfParser::SetBufferViews(const base::DictionaryValue& dict) { | 125 bool GltfParser::SetBufferViews(const base::DictionaryValue& dict) { |
90 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | 126 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { |
91 const base::DictionaryValue* buffer_view_dict; | 127 const base::DictionaryValue* buffer_view_dict; |
92 if (!it.value().GetAsDictionary(&buffer_view_dict)) | 128 if (!it.value().GetAsDictionary(&buffer_view_dict)) |
93 return false; | 129 return false; |
94 | 130 |
95 auto buffer_view = base::MakeUnique<gltf::BufferView>(); | 131 auto buffer_view = base::MakeUnique<gltf::BufferView>(); |
96 std::string buffer_key; | 132 std::string buffer_key; |
97 if (!buffer_view_dict->GetString("buffer", &buffer_key)) | 133 if (!buffer_view_dict->GetString("buffer", &buffer_key)) |
98 return false; | 134 return false; |
99 auto buffer_it = buffer_ids_.find(buffer_key); | 135 auto buffer_it = helper_->buffer_ids.find(buffer_key); |
100 if (buffer_it == buffer_ids_.end()) | 136 if (buffer_it == helper_->buffer_ids.end()) |
101 return false; | 137 return false; |
102 buffer_view->buffer = asset_->GetBuffer(buffer_it->second); | 138 buffer_view->buffer = helper_->asset->GetBuffer(buffer_it->second); |
103 if (!buffer_view_dict->GetInteger("byteOffset", &buffer_view->byte_offset)) | 139 if (!buffer_view_dict->GetInteger("byteOffset", &buffer_view->byte_offset)) |
104 return false; | 140 return false; |
105 buffer_view_dict->GetInteger("byteLength", &buffer_view->byte_length); | 141 buffer_view_dict->GetInteger("byteLength", &buffer_view->byte_length); |
106 buffer_view_dict->GetInteger("target", &buffer_view->target); | 142 buffer_view_dict->GetInteger("target", &buffer_view->target); |
107 | 143 |
108 buffer_view_ids_[it.key()] = asset_->AddBufferView(std::move(buffer_view)); | 144 helper_->buffer_view_ids[it.key()] = |
145 helper_->asset->AddBufferView(std::move(buffer_view)); | |
109 } | 146 } |
110 return true; | 147 return true; |
111 } | 148 } |
112 | 149 |
113 bool GltfParser::SetAccessors(const base::DictionaryValue& dict) { | 150 bool GltfParser::SetAccessors(const base::DictionaryValue& dict) { |
114 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | 151 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { |
115 const base::DictionaryValue* accessor_dict; | 152 const base::DictionaryValue* accessor_dict; |
116 if (!it.value().GetAsDictionary(&accessor_dict)) | 153 if (!it.value().GetAsDictionary(&accessor_dict)) |
117 return false; | 154 return false; |
118 | 155 |
119 auto accessor = base::MakeUnique<gltf::Accessor>(); | 156 auto accessor = base::MakeUnique<gltf::Accessor>(); |
120 std::string buffer_view_key; | 157 std::string buffer_view_key; |
121 std::string type_str; | 158 std::string type_str; |
122 if (!accessor_dict->GetString("bufferView", &buffer_view_key)) | 159 if (!accessor_dict->GetString("bufferView", &buffer_view_key)) |
123 return false; | 160 return false; |
124 auto buffer_view_it = buffer_view_ids_.find(buffer_view_key); | 161 auto buffer_view_it = helper_->buffer_view_ids.find(buffer_view_key); |
125 if (buffer_view_it == buffer_view_ids_.end()) | 162 if (buffer_view_it == helper_->buffer_view_ids.end()) |
126 return false; | 163 return false; |
127 accessor->buffer_view = asset_->GetBufferView(buffer_view_it->second); | 164 accessor->buffer_view = |
165 helper_->asset->GetBufferView(buffer_view_it->second); | |
128 if (!accessor_dict->GetInteger("byteOffset", &accessor->byte_offset)) | 166 if (!accessor_dict->GetInteger("byteOffset", &accessor->byte_offset)) |
129 return false; | 167 return false; |
130 accessor_dict->GetInteger("byteStride", &accessor->byte_stride); | 168 accessor_dict->GetInteger("byteStride", &accessor->byte_stride); |
131 if (!accessor_dict->GetInteger("componentType", &accessor->component_type)) | 169 if (!accessor_dict->GetInteger("componentType", &accessor->component_type)) |
132 return false; | 170 return false; |
133 if (!accessor_dict->GetInteger("count", &accessor->count)) | 171 if (!accessor_dict->GetInteger("count", &accessor->count)) |
134 return false; | 172 return false; |
135 if (!accessor_dict->GetString("type", &type_str)) | 173 if (!accessor_dict->GetString("type", &type_str)) |
136 return false; | 174 return false; |
137 gltf::Type type = gltf::GetType(type_str); | 175 gltf::Type type = gltf::GetType(type_str); |
138 if (type == gltf::UNKNOWN) | 176 if (type == gltf::UNKNOWN) |
139 return false; | 177 return false; |
140 accessor->type = type; | 178 accessor->type = type; |
141 | 179 |
142 accessor_ids_[it.key()] = asset_->AddAccessor(std::move(accessor)); | 180 helper_->accessor_ids[it.key()] = |
181 helper_->asset->AddAccessor(std::move(accessor)); | |
143 } | 182 } |
144 return true; | 183 return true; |
145 } | 184 } |
146 | 185 |
147 bool GltfParser::SetMeshes(const base::DictionaryValue& dict) { | 186 bool GltfParser::SetMeshes(const base::DictionaryValue& dict) { |
148 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | 187 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { |
149 const base::DictionaryValue* mesh_dict; | 188 const base::DictionaryValue* mesh_dict; |
150 if (!it.value().GetAsDictionary(&mesh_dict)) | 189 if (!it.value().GetAsDictionary(&mesh_dict)) |
151 return false; | 190 return false; |
152 | 191 |
153 auto mesh = base::MakeUnique<gltf::Mesh>(); | 192 auto mesh = base::MakeUnique<gltf::Mesh>(); |
154 const base::ListValue* list; | 193 const base::ListValue* list; |
155 if (mesh_dict->GetList("primitives", &list)) { | 194 if (mesh_dict->GetList("primitives", &list)) { |
156 for (const auto& primitive_value : *list) { | 195 for (const auto& primitive_value : *list) { |
157 const base::DictionaryValue* primitive_dict; | 196 const base::DictionaryValue* primitive_dict; |
158 if (!primitive_value->GetAsDictionary(&primitive_dict)) | 197 if (!primitive_value->GetAsDictionary(&primitive_dict)) |
159 return false; | 198 return false; |
160 | 199 |
161 auto primitive = ProcessPrimitive(*primitive_dict); | 200 auto primitive = ProcessPrimitive(*primitive_dict); |
162 if (!primitive) | 201 if (!primitive) |
163 return false; | 202 return false; |
164 mesh->primitives.push_back(std::move(primitive)); | 203 mesh->primitives.push_back(std::move(primitive)); |
165 } | 204 } |
166 } | 205 } |
167 | 206 |
168 mesh_ids_[it.key()] = asset_->AddMesh(std::move(mesh)); | 207 helper_->mesh_ids[it.key()] = helper_->asset->AddMesh(std::move(mesh)); |
169 } | 208 } |
170 return true; | 209 return true; |
171 } | 210 } |
172 | 211 |
173 std::unique_ptr<gltf::Mesh::Primitive> GltfParser::ProcessPrimitive( | 212 std::unique_ptr<gltf::Mesh::Primitive> GltfParser::ProcessPrimitive( |
174 const base::DictionaryValue& dict) { | 213 const base::DictionaryValue& dict) { |
175 auto primitive = base::MakeUnique<gltf::Mesh::Primitive>(); | 214 auto primitive = base::MakeUnique<gltf::Mesh::Primitive>(); |
176 std::string indices_key; | 215 std::string indices_key; |
177 const base::DictionaryValue* attributes; | 216 const base::DictionaryValue* attributes; |
178 if (dict.GetString("indices", &indices_key)) { | 217 if (dict.GetString("indices", &indices_key)) { |
179 auto accessor_it = accessor_ids_.find(indices_key); | 218 auto accessor_it = helper_->accessor_ids.find(indices_key); |
180 if (accessor_it == accessor_ids_.end()) | 219 if (accessor_it == helper_->accessor_ids.end()) |
181 return nullptr; | 220 return nullptr; |
182 primitive->indices = asset_->GetAccessor(accessor_it->second); | 221 primitive->indices = helper_->asset->GetAccessor(accessor_it->second); |
183 } | 222 } |
184 dict.GetInteger("mode", &primitive->mode); | 223 dict.GetInteger("mode", &primitive->mode); |
185 if (dict.GetDictionary("attributes", &attributes)) { | 224 if (dict.GetDictionary("attributes", &attributes)) { |
186 for (base::DictionaryValue::Iterator it(*attributes); !it.IsAtEnd(); | 225 for (base::DictionaryValue::Iterator it(*attributes); !it.IsAtEnd(); |
187 it.Advance()) { | 226 it.Advance()) { |
188 std::string accessor_key; | 227 std::string accessor_key; |
189 if (!it.value().GetAsString(&accessor_key)) | 228 if (!it.value().GetAsString(&accessor_key)) |
190 return nullptr; | 229 return nullptr; |
191 auto accessor_it = accessor_ids_.find(accessor_key); | 230 auto accessor_it = helper_->accessor_ids.find(accessor_key); |
192 if (accessor_it == accessor_ids_.end()) | 231 if (accessor_it == helper_->accessor_ids.end()) |
193 return nullptr; | 232 return nullptr; |
194 primitive->attributes[it.key()] = | 233 primitive->attributes[it.key()] = |
195 asset_->GetAccessor(accessor_it->second); | 234 helper_->asset->GetAccessor(accessor_it->second); |
196 } | 235 } |
197 } | 236 } |
198 return primitive; | 237 return primitive; |
199 } | 238 } |
200 | 239 |
201 bool GltfParser::SetNodes(const base::DictionaryValue& dict) { | 240 bool GltfParser::SetNodes(const base::DictionaryValue& dict) { |
202 std::unordered_map<std::string, gltf::Node*> nodes; | 241 std::unordered_map<std::string, gltf::Node*> nodes; |
203 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | 242 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { |
204 const base::DictionaryValue* node_dict; | 243 const base::DictionaryValue* node_dict; |
205 if (!it.value().GetAsDictionary(&node_dict)) | 244 if (!it.value().GetAsDictionary(&node_dict)) |
206 return false; | 245 return false; |
207 | 246 |
208 auto node = base::MakeUnique<gltf::Node>(); | 247 auto node = base::MakeUnique<gltf::Node>(); |
209 const base::ListValue* list; | 248 const base::ListValue* list; |
210 if (node_dict->GetList("meshes", &list)) { | 249 if (node_dict->GetList("meshes", &list)) { |
211 std::string mesh_key; | 250 std::string mesh_key; |
212 for (const auto& mesh_value : *list) { | 251 for (const auto& mesh_value : *list) { |
213 if (!mesh_value->GetAsString(&mesh_key)) | 252 if (!mesh_value->GetAsString(&mesh_key)) |
214 return false; | 253 return false; |
215 auto mesh_it = mesh_ids_.find(mesh_key); | 254 auto mesh_it = helper_->mesh_ids.find(mesh_key); |
216 if (mesh_it == mesh_ids_.end()) | 255 if (mesh_it == helper_->mesh_ids.end()) |
217 return false; | 256 return false; |
218 node->meshes.push_back(asset_->GetMesh(mesh_it->second)); | 257 node->meshes.push_back(helper_->asset->GetMesh(mesh_it->second)); |
219 } | 258 } |
220 } | 259 } |
221 | 260 |
222 nodes[it.key()] = node.get(); | 261 nodes[it.key()] = node.get(); |
223 node_ids_[it.key()] = asset_->AddNode(std::move(node)); | 262 helper_->node_ids[it.key()] = helper_->asset->AddNode(std::move(node)); |
224 } | 263 } |
225 | 264 |
226 // Processing children after all nodes have been added to the asset. | 265 // Processing children after all nodes have been added to the asset. |
227 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { | 266 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { |
228 const base::DictionaryValue* node_dict; | 267 const base::DictionaryValue* node_dict; |
229 it.value().GetAsDictionary(&node_dict); | 268 it.value().GetAsDictionary(&node_dict); |
230 | 269 |
231 gltf::Node* node = nodes[it.key()]; | 270 gltf::Node* node = nodes[it.key()]; |
232 const base::ListValue* list; | 271 const base::ListValue* list; |
233 if (node_dict->GetList("children", &list)) { | 272 if (node_dict->GetList("children", &list)) { |
(...skipping 18 matching lines...) Expand all Loading... | |
252 if (!it.value().GetAsDictionary(&scene_dict)) | 291 if (!it.value().GetAsDictionary(&scene_dict)) |
253 return false; | 292 return false; |
254 | 293 |
255 auto scene = base::MakeUnique<gltf::Scene>(); | 294 auto scene = base::MakeUnique<gltf::Scene>(); |
256 const base::ListValue* list; | 295 const base::ListValue* list; |
257 if (scene_dict->GetList("nodes", &list)) { | 296 if (scene_dict->GetList("nodes", &list)) { |
258 std::string node_key; | 297 std::string node_key; |
259 for (const auto& node_value : *list) { | 298 for (const auto& node_value : *list) { |
260 if (!node_value->GetAsString(&node_key)) | 299 if (!node_value->GetAsString(&node_key)) |
261 return false; | 300 return false; |
262 auto node_it = node_ids_.find(node_key); | 301 auto node_it = helper_->node_ids.find(node_key); |
263 if (node_it == node_ids_.end()) | 302 if (node_it == helper_->node_ids.end()) |
264 return false; | 303 return false; |
265 scene->nodes.push_back(asset_->GetNode(node_it->second)); | 304 scene->nodes.push_back(helper_->asset->GetNode(node_it->second)); |
266 } | 305 } |
267 } | 306 } |
268 | 307 |
269 scene_ids_[it.key()] = asset_->AddScene(std::move(scene)); | 308 helper_->scene_ids[it.key()] = helper_->asset->AddScene(std::move(scene)); |
270 } | 309 } |
271 return true; | 310 return true; |
272 } | 311 } |
273 | 312 |
274 } // namespace vr_shell | 313 } // namespace vr_shell |
OLD | NEW |