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

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: 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[] =
mthiesse 2017/04/28 15:51:34 Wrap this in #if defined(DCHECK_IS_ON)
mthiesse 2017/04/28 16:11:45 I know this makes the code cleaner, but to avoid e
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
30 enum {
mthiesse 2017/04/28 15:51:34 Why is this an enum? Looks like just making consta
acondor_ 2017/04/28 16:07:01 Done.
31 kVersionStart = 4,
32 kLengthStart = 8,
33 kContentLengthStart = 12,
34 kContentFormatStart = 16,
35 kContentStart = 20
36 };
37
38 uint32_t GetLE32(const char* data) {
39 const uint32_t* int_data = reinterpret_cast<const uint32_t*>(data);
40 return base::ByteSwapToLE32(*int_data);
41 }
42
43 } // namespace
44
20 GltfParser::GltfParser() {} 45 GltfParser::GltfParser() {}
21 46
22 GltfParser::~GltfParser() = default; 47 GltfParser::~GltfParser() = default;
23 48
24 std::unique_ptr<gltf::Asset> GltfParser::Parse( 49 std::unique_ptr<gltf::Asset> GltfParser::Parse(
25 const base::DictionaryValue& dict, 50 const base::DictionaryValue& dict,
26 std::vector<std::unique_ptr<gltf::Buffer>>* buffers, 51 std::vector<std::unique_ptr<gltf::Buffer>>* buffers,
27 const base::FilePath& path) { 52 const base::FilePath& path) {
53 DCHECK(buffers && buffers->size() <= 1);
28 path_ = path; 54 path_ = path;
29 asset_ = base::MakeUnique<gltf::Asset>(); 55 asset_ = base::MakeUnique<gltf::Asset>();
30 56
31 base::ScopedClosureRunner runner( 57 base::ScopedClosureRunner runner(
32 base::Bind(&GltfParser::Clear, base::Unretained(this))); 58 base::Bind(&GltfParser::Clear, base::Unretained(this)));
33 59
34 if (!ParseInternal(dict, buffers)) 60 if (!ParseInternal(dict, buffers))
35 return nullptr; 61 return nullptr;
36 62
37 return std::move(asset_); 63 return std::move(asset_);
38 } 64 }
39 65
40 std::unique_ptr<gltf::Asset> GltfParser::Parse( 66 std::unique_ptr<gltf::Asset> GltfParser::Parse(
41 const base::FilePath& gltf_path, 67 const base::FilePath& gltf_path,
42 std::vector<std::unique_ptr<gltf::Buffer>>* buffers) { 68 std::vector<std::unique_ptr<gltf::Buffer>>* buffers) {
69 DCHECK(buffers && buffers->size() <= 1);
43 JSONFileValueDeserializer json_deserializer(gltf_path); 70 JSONFileValueDeserializer json_deserializer(gltf_path);
44 int error_code; 71 int error_code;
45 std::string error_msg; 72 std::string error_msg;
46 auto asset_value = json_deserializer.Deserialize(&error_code, &error_msg); 73 auto asset_value = json_deserializer.Deserialize(&error_code, &error_msg);
47 if (!asset_value) 74 if (!asset_value)
48 return nullptr; 75 return nullptr;
49 base::DictionaryValue* asset; 76 base::DictionaryValue* asset;
50 if (!asset_value->GetAsDictionary(&asset)) 77 if (!asset_value->GetAsDictionary(&asset))
51 return nullptr; 78 return nullptr;
52 return Parse(*asset, buffers, gltf_path); 79 return Parse(*asset, buffers, gltf_path);
(...skipping 29 matching lines...) Expand all
82 return false; 109 return false;
83 asset_->SetMainScene(asset_->GetScene(scene_it->second)); 110 asset_->SetMainScene(asset_->GetScene(scene_it->second));
84 } 111 }
85 112
86 return true; 113 return true;
87 } 114 }
88 115
89 bool GltfParser::SetBuffers( 116 bool GltfParser::SetBuffers(
90 const base::DictionaryValue& dict, 117 const base::DictionaryValue& dict,
91 std::vector<std::unique_ptr<gltf::Buffer>>* buffers) { 118 std::vector<std::unique_ptr<gltf::Buffer>>* buffers) {
92 buffers->clear(); 119 size_t buffer_cnt = 0;
mthiesse 2017/04/28 15:51:34 nit: avoid using abbreviations in variable names l
acondor_ 2017/04/28 16:07:01 Done.
93 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { 120 for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
94 const base::DictionaryValue* buffer_dict; 121 const base::DictionaryValue* buffer_dict;
95 if (!it.value().GetAsDictionary(&buffer_dict)) 122 if (!it.value().GetAsDictionary(&buffer_dict))
96 return false; 123 return false;
97 124
125 if (it.key() == kBinaryGltfBufferName) {
126 if (buffers->size() == buffer_cnt)
127 return false;
128 buffer_ids_[it.key()] = 0;
129 continue;
130 }
131
98 std::string uri_str; 132 std::string uri_str;
99 if (!buffer_dict->GetString("uri", &uri_str)) 133 if (!buffer_dict->GetString("uri", &uri_str))
100 return false; 134 return false;
101 auto buffer = ProcessUri(uri_str); 135 auto buffer = ProcessUri(uri_str);
102 if (!buffer) 136 if (!buffer)
103 return false; 137 return false;
104 138
105 int byte_length; 139 int byte_length;
106 if (buffer_dict->GetInteger("byteLength", &byte_length) && 140 if (buffer_dict->GetInteger("byteLength", &byte_length) &&
107 static_cast<int>(buffer->length()) != byte_length) 141 static_cast<int>(buffer->length()) != byte_length)
108 return false; 142 return false;
109 143
110 buffer_ids_[it.key()] = buffers->size(); 144 buffer_ids_[it.key()] = buffers->size();
111 buffers->push_back(std::move(buffer)); 145 buffers->push_back(std::move(buffer));
146 ++buffer_cnt;
112 } 147 }
113 return true; 148 return true;
114 } 149 }
115 150
116 std::unique_ptr<gltf::Buffer> GltfParser::ProcessUri( 151 std::unique_ptr<gltf::Buffer> GltfParser::ProcessUri(
117 const std::string& uri_str) { 152 const std::string& uri_str) {
118 auto uri = path_.empty() ? GURL(uri_str) 153 auto uri = path_.empty() ? GURL(uri_str)
119 : net::FilePathToFileURL(path_).Resolve(uri_str); 154 : net::FilePathToFileURL(path_).Resolve(uri_str);
120 if (!uri.is_valid()) 155 if (!uri.is_valid())
121 return nullptr; 156 return nullptr;
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 asset_.reset(); 361 asset_.reset();
327 path_.clear(); 362 path_.clear();
328 buffer_ids_.clear(); 363 buffer_ids_.clear();
329 buffer_view_ids_.clear(); 364 buffer_view_ids_.clear();
330 accessor_ids_.clear(); 365 accessor_ids_.clear();
331 node_ids_.clear(); 366 node_ids_.clear();
332 mesh_ids_.clear(); 367 mesh_ids_.clear();
333 scene_ids_.clear(); 368 scene_ids_.clear();
334 } 369 }
335 370
371 std::unique_ptr<gltf::Asset> BinaryGltfParser::Parse(
372 const base::StringPiece& glb_content,
373 std::vector<std::unique_ptr<gltf::Buffer>>* buffers,
374 const base::FilePath& path) {
375 DCHECK(buffers && buffers->empty());
376 if (glb_content.length() < kContentStart) {
377 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Incomplete data";
mthiesse 2017/04/28 15:51:34 Make these DLOGs? Best to avoid adding strings to
378 return nullptr;
379 }
380 if (!glb_content.starts_with(kGltfMagic)) {
381 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Unknown magic number";
382 return nullptr;
383 }
384 if (GetLE32(glb_content.data() + kVersionStart) != 1) {
385 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Unknown version";
mthiesse 2017/04/28 15:51:34 nit: s/Unknown/Unsupported
386 return nullptr;
387 }
388 if (GetLE32(glb_content.data() + kLengthStart) != glb_content.length()) {
389 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Incorrect file size";
390 return nullptr;
391 }
392 uint32_t content_length = GetLE32(glb_content.data() + kContentLengthStart);
393 if (kContentStart + content_length > glb_content.length()) {
394 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Invalid content length";
395 return nullptr;
396 }
397 if (GetLE32(glb_content.data() + kContentFormatStart) != kJsonGltfFormat) {
398 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Unknown glTF format";
mthiesse 2017/04/28 15:51:34 nit: s/Unknown/Unsupported
399 return nullptr;
400 }
401
402 base::StringPiece gltf_content(glb_content.data() + kContentStart,
403 content_length);
404 int error_code;
405 std::string error_msg;
406 JSONStringValueDeserializer json_deserializer(gltf_content);
407 auto gltf_value = json_deserializer.Deserialize(&error_code, &error_msg);
408 if (!gltf_value) {
409 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Content not a valid JSON";
410 return nullptr;
411 }
412 base::DictionaryValue* gltf_dict;
413 if (!gltf_value->GetAsDictionary(&gltf_dict)) {
414 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Content is not a valid glTF";
415 return nullptr;
416 }
417
418 auto glb_buffer = base::MakeUnique<gltf::Buffer>(
419 glb_content.substr(kContentStart + content_length));
420 buffers->push_back(std::move(glb_buffer));
421 GltfParser gltf_parser;
422 auto gltf_asset = gltf_parser.Parse(*gltf_dict, buffers);
423 if (!gltf_asset) {
424 LOG(ERROR) << kFailedtoReadBinaryGltfMsg << "Content is not a valid glTF";
425 buffers->clear();
426 return nullptr;
427 }
428 return gltf_asset;
429 }
430
336 } // namespace vr_shell 431 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698