Chromium Code Reviews| Index: chrome/browser/android/vr_shell/gltf_parser.cc |
| diff --git a/chrome/browser/android/vr_shell/gltf_parser.cc b/chrome/browser/android/vr_shell/gltf_parser.cc |
| index 17be0c8c098129ba39c62fd4acb0652695d2fa89..0c541a6e8b43ba5c874b6be36fdc981d2d68b5d9 100644 |
| --- a/chrome/browser/android/vr_shell/gltf_parser.cc |
| +++ b/chrome/browser/android/vr_shell/gltf_parser.cc |
| @@ -4,60 +4,73 @@ |
| #include "chrome/browser/android/vr_shell/gltf_parser.h" |
| -#include "base/base64.h" |
| +#include "base/files/file_util.h" |
| +#include "base/json/json_file_value_serializer.h" |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| +#include "net/base/data_url.h" |
| +#include "net/base/filename_util.h" |
| +#include "url/gurl.h" |
| namespace vr_shell { |
| -constexpr char kBase64Header[] = "data:application/octet-stream;base64,"; |
| -constexpr size_t kBase64HeaderSize = 37; |
| - |
| GltfParser::GltfParser() {} |
| GltfParser::~GltfParser() = default; |
| +GltfParser::Helper::Helper(const base::FilePath& path) |
| + : asset(base::MakeUnique<gltf::Asset>()), path(path) {} |
| + |
| +GltfParser::Helper::~Helper() = default; |
| + |
| std::unique_ptr<gltf::Asset> GltfParser::Parse( |
| - const base::DictionaryValue& dict) { |
| + const base::DictionaryValue& dict, |
| + const base::FilePath& path) { |
| + Helper helper(path); |
| + 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.
|
| + |
| std::string gltf_version; |
| if (!dict.GetString("asset.version", &gltf_version) || gltf_version != "1.0") |
| return nullptr; |
| - asset_ = base::MakeUnique<gltf::Asset>(); |
| - |
| - if (!ParseInternal(dict)) { |
| - asset_.reset(); |
| - return nullptr; |
| - } |
| - |
| - return std::move(asset_); |
| -} |
| - |
| -bool GltfParser::ParseInternal(const base::DictionaryValue& dict) { |
| const base::DictionaryValue* sub_dict; |
| if (dict.GetDictionary("buffers", &sub_dict) && !SetBuffers(*sub_dict)) |
| - return false; |
| + return nullptr; |
| if (dict.GetDictionary("bufferViews", &sub_dict) && |
| !SetBufferViews(*sub_dict)) |
| - return false; |
| + return nullptr; |
| if (dict.GetDictionary("accessors", &sub_dict) && !SetAccessors(*sub_dict)) |
| - return false; |
| + return nullptr; |
| if (dict.GetDictionary("meshes", &sub_dict) && !SetMeshes(*sub_dict)) |
| - return false; |
| + return nullptr; |
| if (dict.GetDictionary("nodes", &sub_dict) && !SetNodes(*sub_dict)) |
| - return false; |
| + return nullptr; |
| if (dict.GetDictionary("scenes", &sub_dict) && !SetScenes(*sub_dict)) |
| - return false; |
| + return nullptr; |
| std::string scene_key; |
| if (dict.GetString("scene", &scene_key)) { |
| - auto scene_it = scene_ids_.find(scene_key); |
| - if (scene_it == scene_ids_.end()) |
| - return false; |
| - asset_->SetMainScene(asset_->GetScene(scene_it->second)); |
| + auto scene_it = helper.scene_ids.find(scene_key); |
| + if (scene_it == helper.scene_ids.end()) |
| + return nullptr; |
| + helper.asset->SetMainScene(helper.asset->GetScene(scene_it->second)); |
| } |
| - return true; |
| + return std::move(helper.asset); |
| +} |
| + |
| +std::unique_ptr<gltf::Asset> GltfParser::Parse( |
| + const base::FilePath& gltf_path) { |
| + JSONFileValueDeserializer json_deserializer(gltf_path); |
| + int error_code; |
| + std::string error_msg; |
| + auto asset_value = json_deserializer.Deserialize(&error_code, &error_msg); |
| + if (!asset_value) |
| + return nullptr; |
| + base::DictionaryValue* asset; |
| + if (!asset_value->GetAsDictionary(&asset)) |
| + return nullptr; |
| + return Parse(*asset, gltf_path); |
| } |
| bool GltfParser::SetBuffers(const base::DictionaryValue& dict) { |
| @@ -66,14 +79,11 @@ bool GltfParser::SetBuffers(const base::DictionaryValue& dict) { |
| if (!it.value().GetAsDictionary(&buffer_dict)) |
| return false; |
| - std::string uri; |
| - // TODO(acondor): Support files. Only inline data is supported now. |
| - if (!buffer_dict->GetString("uri", &uri) || |
| - uri.substr(0, kBase64HeaderSize) != kBase64Header) |
| + std::string uri_str; |
| + if (!buffer_dict->GetString("uri", &uri_str)) |
| return false; |
| - |
| - auto buffer = base::MakeUnique<gltf::Buffer>(); |
| - if (!base::Base64Decode(uri.substr(kBase64HeaderSize), buffer.get())) |
| + auto buffer = ProcessUri(uri_str); |
| + if (!buffer) |
| return false; |
| int byte_length; |
| @@ -81,11 +91,37 @@ bool GltfParser::SetBuffers(const base::DictionaryValue& dict) { |
| static_cast<int>(buffer->length()) != byte_length) |
| return false; |
| - buffer_ids_[it.key()] = asset_->AddBuffer(std::move(buffer)); |
| + helper_->buffer_ids[it.key()] = |
| + helper_->asset->AddBuffer(std::move(buffer)); |
| } |
| return true; |
| } |
| +std::unique_ptr<gltf::Buffer> GltfParser::ProcessUri( |
| + const std::string& uri_str) { |
| + auto uri = helper_->path.empty() |
| + ? GURL(uri_str) |
| + : net::FilePathToFileURL(helper_->path).Resolve(uri_str); |
| + if (!uri.is_valid()) |
| + return nullptr; |
| + if (uri.SchemeIs(url::kDataScheme)) { |
| + std::string mime_type; |
| + std::string charset; |
| + auto data = base::MakeUnique<gltf::Buffer>(); |
| + if (!net::DataURL::Parse(uri, &mime_type, &charset, data.get())) |
| + return nullptr; |
| + return data; |
| + } |
| + if (uri.SchemeIsFile()) { |
| + auto data = base::MakeUnique<gltf::Buffer>(); |
| + if (!base::ReadFileToString(base::FilePath(uri.path()), data.get())) |
| + return nullptr; |
| + return data; |
| + } |
| + // No other schemes are supported yet. |
| + return nullptr; |
| +} |
| + |
| bool GltfParser::SetBufferViews(const base::DictionaryValue& dict) { |
| for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { |
| const base::DictionaryValue* buffer_view_dict; |
| @@ -96,16 +132,17 @@ bool GltfParser::SetBufferViews(const base::DictionaryValue& dict) { |
| std::string buffer_key; |
| if (!buffer_view_dict->GetString("buffer", &buffer_key)) |
| return false; |
| - auto buffer_it = buffer_ids_.find(buffer_key); |
| - if (buffer_it == buffer_ids_.end()) |
| + auto buffer_it = helper_->buffer_ids.find(buffer_key); |
| + if (buffer_it == helper_->buffer_ids.end()) |
| return false; |
| - buffer_view->buffer = asset_->GetBuffer(buffer_it->second); |
| + buffer_view->buffer = helper_->asset->GetBuffer(buffer_it->second); |
| if (!buffer_view_dict->GetInteger("byteOffset", &buffer_view->byte_offset)) |
| return false; |
| buffer_view_dict->GetInteger("byteLength", &buffer_view->byte_length); |
| buffer_view_dict->GetInteger("target", &buffer_view->target); |
| - buffer_view_ids_[it.key()] = asset_->AddBufferView(std::move(buffer_view)); |
| + helper_->buffer_view_ids[it.key()] = |
| + helper_->asset->AddBufferView(std::move(buffer_view)); |
| } |
| return true; |
| } |
| @@ -121,10 +158,11 @@ bool GltfParser::SetAccessors(const base::DictionaryValue& dict) { |
| std::string type_str; |
| if (!accessor_dict->GetString("bufferView", &buffer_view_key)) |
| return false; |
| - auto buffer_view_it = buffer_view_ids_.find(buffer_view_key); |
| - if (buffer_view_it == buffer_view_ids_.end()) |
| + auto buffer_view_it = helper_->buffer_view_ids.find(buffer_view_key); |
| + if (buffer_view_it == helper_->buffer_view_ids.end()) |
| return false; |
| - accessor->buffer_view = asset_->GetBufferView(buffer_view_it->second); |
| + accessor->buffer_view = |
| + helper_->asset->GetBufferView(buffer_view_it->second); |
| if (!accessor_dict->GetInteger("byteOffset", &accessor->byte_offset)) |
| return false; |
| accessor_dict->GetInteger("byteStride", &accessor->byte_stride); |
| @@ -139,7 +177,8 @@ bool GltfParser::SetAccessors(const base::DictionaryValue& dict) { |
| return false; |
| accessor->type = type; |
| - accessor_ids_[it.key()] = asset_->AddAccessor(std::move(accessor)); |
| + helper_->accessor_ids[it.key()] = |
| + helper_->asset->AddAccessor(std::move(accessor)); |
| } |
| return true; |
| } |
| @@ -165,7 +204,7 @@ bool GltfParser::SetMeshes(const base::DictionaryValue& dict) { |
| } |
| } |
| - mesh_ids_[it.key()] = asset_->AddMesh(std::move(mesh)); |
| + helper_->mesh_ids[it.key()] = helper_->asset->AddMesh(std::move(mesh)); |
| } |
| return true; |
| } |
| @@ -176,10 +215,10 @@ std::unique_ptr<gltf::Mesh::Primitive> GltfParser::ProcessPrimitive( |
| std::string indices_key; |
| const base::DictionaryValue* attributes; |
| if (dict.GetString("indices", &indices_key)) { |
| - auto accessor_it = accessor_ids_.find(indices_key); |
| - if (accessor_it == accessor_ids_.end()) |
| + auto accessor_it = helper_->accessor_ids.find(indices_key); |
| + if (accessor_it == helper_->accessor_ids.end()) |
| return nullptr; |
| - primitive->indices = asset_->GetAccessor(accessor_it->second); |
| + primitive->indices = helper_->asset->GetAccessor(accessor_it->second); |
| } |
| dict.GetInteger("mode", &primitive->mode); |
| if (dict.GetDictionary("attributes", &attributes)) { |
| @@ -188,11 +227,11 @@ std::unique_ptr<gltf::Mesh::Primitive> GltfParser::ProcessPrimitive( |
| std::string accessor_key; |
| if (!it.value().GetAsString(&accessor_key)) |
| return nullptr; |
| - auto accessor_it = accessor_ids_.find(accessor_key); |
| - if (accessor_it == accessor_ids_.end()) |
| + auto accessor_it = helper_->accessor_ids.find(accessor_key); |
| + if (accessor_it == helper_->accessor_ids.end()) |
| return nullptr; |
| primitive->attributes[it.key()] = |
| - asset_->GetAccessor(accessor_it->second); |
| + helper_->asset->GetAccessor(accessor_it->second); |
| } |
| } |
| return primitive; |
| @@ -212,15 +251,15 @@ bool GltfParser::SetNodes(const base::DictionaryValue& dict) { |
| for (const auto& mesh_value : *list) { |
| if (!mesh_value->GetAsString(&mesh_key)) |
| return false; |
| - auto mesh_it = mesh_ids_.find(mesh_key); |
| - if (mesh_it == mesh_ids_.end()) |
| + auto mesh_it = helper_->mesh_ids.find(mesh_key); |
| + if (mesh_it == helper_->mesh_ids.end()) |
| return false; |
| - node->meshes.push_back(asset_->GetMesh(mesh_it->second)); |
| + node->meshes.push_back(helper_->asset->GetMesh(mesh_it->second)); |
| } |
| } |
| nodes[it.key()] = node.get(); |
| - node_ids_[it.key()] = asset_->AddNode(std::move(node)); |
| + helper_->node_ids[it.key()] = helper_->asset->AddNode(std::move(node)); |
| } |
| // Processing children after all nodes have been added to the asset. |
| @@ -259,14 +298,14 @@ bool GltfParser::SetScenes(const base::DictionaryValue& dict) { |
| for (const auto& node_value : *list) { |
| if (!node_value->GetAsString(&node_key)) |
| return false; |
| - auto node_it = node_ids_.find(node_key); |
| - if (node_it == node_ids_.end()) |
| + auto node_it = helper_->node_ids.find(node_key); |
| + if (node_it == helper_->node_ids.end()) |
| return false; |
| - scene->nodes.push_back(asset_->GetNode(node_it->second)); |
| + scene->nodes.push_back(helper_->asset->GetNode(node_it->second)); |
| } |
| } |
| - scene_ids_[it.key()] = asset_->AddScene(std::move(scene)); |
| + helper_->scene_ids[it.key()] = helper_->asset->AddScene(std::move(scene)); |
| } |
| return true; |
| } |