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

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

Issue 2852533004: Implementing Binary glTF reader for the VR controller model (Closed)
Patch Set: Addressing suggestions. Created 3 years, 7 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
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/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
11 #include "base/json/json_file_value_serializer.h" 11 #include "base/json/json_file_value_serializer.h"
12 #include "base/json/json_string_value_serializer.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/strings/string_util.h"
16 #include "base/sys_byteorder.h"
14 #include "net/base/data_url.h" 17 #include "net/base/data_url.h"
15 #include "net/base/filename_util.h" 18 #include "net/base/filename_util.h"
16 #include "url/gurl.h" 19 #include "url/gurl.h"
17 20
18 namespace vr_shell { 21 namespace vr_shell {
19 22
23 namespace {
24 constexpr const char kFailedtoReadBinaryGltfMsg[] =
25 "Failed to read binary glTF: ";
26 constexpr const char kGltfMagic[] = "glTF";
27 constexpr const char kBinaryGltfBufferName[] = "binary_glTF";
28 constexpr uint32_t kJsonGltfFormat = 0;
29 constexpr size_t kVersionStart = 4;
30 constexpr size_t kLengthStart = 8;
31 constexpr size_t kContentLengthStart = 12;
32 constexpr size_t kContentFormatStart = 16;
33 constexpr size_t kContentStart = 20;
34
35 uint32_t GetLE32(const char* data) {
36 const uint32_t* int_data = reinterpret_cast<const uint32_t*>(data);
37 return base::ByteSwapToLE32(*int_data);
38 }
39
40 } // namespace
41
20 GltfParser::GltfParser() {} 42 GltfParser::GltfParser() {}
21 43
22 GltfParser::~GltfParser() = default; 44 GltfParser::~GltfParser() = default;
23 45
24 std::unique_ptr<gltf::Asset> GltfParser::Parse( 46 std::unique_ptr<gltf::Asset> GltfParser::Parse(
25 const base::DictionaryValue& dict, 47 const base::DictionaryValue& dict,
26 std::vector<std::unique_ptr<gltf::Buffer>>* buffers, 48 std::vector<std::unique_ptr<gltf::Buffer>>* buffers,
27 const base::FilePath& path) { 49 const base::FilePath& path) {
50 DCHECK(buffers && buffers->size() <= 1);
28 path_ = path; 51 path_ = path;
29 asset_ = base::MakeUnique<gltf::Asset>(); 52 asset_ = base::MakeUnique<gltf::Asset>();
30 53
31 base::ScopedClosureRunner runner( 54 base::ScopedClosureRunner runner(
32 base::Bind(&GltfParser::Clear, base::Unretained(this))); 55 base::Bind(&GltfParser::Clear, base::Unretained(this)));
33 56
34 if (!ParseInternal(dict, buffers)) 57 if (!ParseInternal(dict, buffers))
35 return nullptr; 58 return nullptr;
36 59
37 return std::move(asset_); 60 return std::move(asset_);
38 } 61 }
39 62
40 std::unique_ptr<gltf::Asset> GltfParser::Parse( 63 std::unique_ptr<gltf::Asset> GltfParser::Parse(
41 const base::FilePath& gltf_path, 64 const base::FilePath& gltf_path,
42 std::vector<std::unique_ptr<gltf::Buffer>>* buffers) { 65 std::vector<std::unique_ptr<gltf::Buffer>>* buffers) {
66 DCHECK(buffers && buffers->size() <= 1);
43 JSONFileValueDeserializer json_deserializer(gltf_path); 67 JSONFileValueDeserializer json_deserializer(gltf_path);
44 int error_code; 68 int error_code;
45 std::string error_msg; 69 std::string error_msg;
46 auto asset_value = json_deserializer.Deserialize(&error_code, &error_msg); 70 auto asset_value = json_deserializer.Deserialize(&error_code, &error_msg);
47 if (!asset_value) 71 if (!asset_value)
48 return nullptr; 72 return nullptr;
49 base::DictionaryValue* asset; 73 base::DictionaryValue* asset;
50 if (!asset_value->GetAsDictionary(&asset)) 74 if (!asset_value->GetAsDictionary(&asset))
51 return nullptr; 75 return nullptr;
52 return Parse(*asset, buffers, gltf_path); 76 return Parse(*asset, buffers, gltf_path);
(...skipping 29 matching lines...) Expand all
82 return false; 106 return false;
83 asset_->SetMainScene(asset_->GetScene(scene_it->second)); 107 asset_->SetMainScene(asset_->GetScene(scene_it->second));
84 } 108 }
85 109
86 return true; 110 return true;
87 } 111 }
88 112
89 bool GltfParser::SetBuffers( 113 bool GltfParser::SetBuffers(
90 const base::DictionaryValue& dict, 114 const base::DictionaryValue& dict,
91 std::vector<std::unique_ptr<gltf::Buffer>>* buffers) { 115 std::vector<std::unique_ptr<gltf::Buffer>>* buffers) {
92 buffers->clear(); 116 size_t buffer_count = 0;
93 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { 117 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
94 const base::DictionaryValue* buffer_dict; 118 const base::DictionaryValue* buffer_dict;
95 if (!it.value().GetAsDictionary(&buffer_dict)) 119 if (!it.value().GetAsDictionary(&buffer_dict))
96 return false; 120 return false;
97 121
122 if (it.key() == kBinaryGltfBufferName) {
123 if (buffers->size() == buffer_count)
124 return false;
125 buffer_ids_[it.key()] = 0;
126 continue;
127 }
128
98 std::string uri_str; 129 std::string uri_str;
99 if (!buffer_dict->GetString("uri", &uri_str)) 130 if (!buffer_dict->GetString("uri", &uri_str))
100 return false; 131 return false;
101 auto buffer = ProcessUri(uri_str); 132 auto buffer = ProcessUri(uri_str);
102 if (!buffer) 133 if (!buffer)
103 return false; 134 return false;
104 135
105 int byte_length; 136 int byte_length;
106 if (buffer_dict->GetInteger("byteLength", &byte_length) && 137 if (buffer_dict->GetInteger("byteLength", &byte_length) &&
107 static_cast<int>(buffer->length()) != byte_length) 138 static_cast<int>(buffer->length()) != byte_length)
108 return false; 139 return false;
109 140
110 buffer_ids_[it.key()] = buffers->size(); 141 buffer_ids_[it.key()] = buffers->size();
111 buffers->push_back(std::move(buffer)); 142 buffers->push_back(std::move(buffer));
143 ++buffer_count;
112 } 144 }
113 return true; 145 return true;
114 } 146 }
115 147
116 std::unique_ptr<gltf::Buffer> GltfParser::ProcessUri( 148 std::unique_ptr<gltf::Buffer> GltfParser::ProcessUri(
117 const std::string& uri_str) { 149 const std::string& uri_str) {
118 auto uri = path_.empty() ? GURL(uri_str) 150 auto uri = path_.empty() ? GURL(uri_str)
119 : net::FilePathToFileURL(path_).Resolve(uri_str); 151 : net::FilePathToFileURL(path_).Resolve(uri_str);
120 if (!uri.is_valid()) 152 if (!uri.is_valid())
121 return nullptr; 153 return nullptr;
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 asset_.reset(); 358 asset_.reset();
327 path_.clear(); 359 path_.clear();
328 buffer_ids_.clear(); 360 buffer_ids_.clear();
329 buffer_view_ids_.clear(); 361 buffer_view_ids_.clear();
330 accessor_ids_.clear(); 362 accessor_ids_.clear();
331 node_ids_.clear(); 363 node_ids_.clear();
332 mesh_ids_.clear(); 364 mesh_ids_.clear();
333 scene_ids_.clear(); 365 scene_ids_.clear();
334 } 366 }
335 367
368 std::unique_ptr<gltf::Asset> BinaryGltfParser::Parse(
369 const base::StringPiece& glb_content,
370 std::vector<std::unique_ptr<gltf::Buffer>>* buffers,
371 const base::FilePath& path) {
372 DCHECK(buffers && buffers->empty());
373 if (glb_content.length() < kContentStart) {
374 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Incomplete data";
375 return nullptr;
376 }
377 if (!glb_content.starts_with(kGltfMagic)) {
378 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Unknown magic number";
379 return nullptr;
380 }
381 if (GetLE32(glb_content.data() + kVersionStart) != 1) {
382 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Unsupported version";
383 return nullptr;
384 }
385 if (GetLE32(glb_content.data() + kLengthStart) != glb_content.length()) {
386 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Incorrect file size";
387 return nullptr;
388 }
389 uint32_t content_length = GetLE32(glb_content.data() + kContentLengthStart);
390 if (kContentStart + content_length > glb_content.length()) {
391 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Invalid content length";
392 return nullptr;
393 }
394 if (GetLE32(glb_content.data() + kContentFormatStart) != kJsonGltfFormat) {
395 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Unsupported glTF format";
396 return nullptr;
397 }
398
399 base::StringPiece gltf_content(glb_content.data() + kContentStart,
400 content_length);
401 int error_code;
402 std::string error_msg;
403 JSONStringValueDeserializer json_deserializer(gltf_content);
404 auto gltf_value = json_deserializer.Deserialize(&error_code, &error_msg);
405 if (!gltf_value) {
406 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Content not a valid JSON";
407 return nullptr;
408 }
409 base::DictionaryValue* gltf_dict;
410 if (!gltf_value->GetAsDictionary(&gltf_dict)) {
411 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Content is not a valid glTF";
412 return nullptr;
413 }
414
415 auto glb_buffer = base::MakeUnique<gltf::Buffer>(
416 glb_content.substr(kContentStart + content_length));
417 buffers->push_back(std::move(glb_buffer));
418 GltfParser gltf_parser;
419 auto gltf_asset = gltf_parser.Parse(*gltf_dict, buffers);
420 if (!gltf_asset) {
421 DLOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Content is not a valid glTF";
bajones 2017/04/28 17:02:37 Nit: For the sake of future debugging it would be
acondor_ 2017/04/28 22:11:47 Done.
422 buffers->clear();
423 return nullptr;
424 }
425 return gltf_asset;
426 }
427
336 } // namespace vr_shell 428 } // 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