Chromium Code Reviews| 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/vr_controller_model.h" | 5 #include "chrome/browser/android/vr_shell/vr_controller_model.h" |
| 6 | 6 |
| 7 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| 11 #include "chrome/browser/android/vr_shell/gltf_parser.h" | 11 #include "chrome/browser/android/vr_shell/gltf_parser.h" |
| 12 #include "components/component_updater/component_updater_paths.h" | 12 #include "components/component_updater/component_updater_paths.h" |
| 13 #include "third_party/skia/include/core/SkCanvas.h" | |
| 14 #include "third_party/skia/include/core/SkRect.h" | |
| 15 #include "third_party/skia/include/core/SkSurface.h" | |
| 13 #include "ui/gfx/codec/png_codec.h" | 16 #include "ui/gfx/codec/png_codec.h" |
| 14 | 17 |
| 15 namespace vr_shell { | 18 namespace vr_shell { |
| 16 | 19 |
| 17 namespace { | 20 namespace { |
| 18 | 21 |
| 19 enum { | 22 enum { |
| 20 ELEMENTS_BUFFER_ID = 0, | 23 ELEMENTS_BUFFER_ID = 0, |
| 21 INDICES_BUFFER_ID = 1, | 24 INDICES_BUFFER_ID = 1, |
| 22 }; | 25 }; |
| 23 | 26 |
| 24 constexpr char kPosition[] = "POSITION"; | 27 constexpr char kPosition[] = "POSITION"; |
| 25 constexpr char kTexCoord[] = "TEXCOORD_0"; | 28 constexpr char kTexCoord[] = "TEXCOORD_0"; |
| 26 | 29 |
| 30 // TODO(acondor): Remove these hardcoded paths once VrShell resources | |
| 31 // are delivered through component updater. | |
| 32 constexpr char const kComponentName[] = "VrShell"; | |
| 33 constexpr char const kDefaultVersion[] = "0"; | |
| 34 | |
| 35 constexpr char const kModelsDirectory[] = "models"; | |
| 36 constexpr char const kModelFilename[] = "controller.gltf"; | |
| 37 constexpr char const kTexturesDirectory[] = "tex"; | |
| 38 constexpr char const kBaseTextureFilename[] = "ddcontroller_idle.png"; | |
| 39 constexpr char const* kTexturePatchesFilenames[] = { | |
| 40 "", "ddcontroller_touchpad.png", "ddcontroller_app.png", | |
| 41 "ddcontroller_system.png", | |
| 42 }; | |
| 43 const gfx::Point kPatchesLocations[] = {{}, {5, 5}, {47, 165}, {47, 234}}; | |
| 44 | |
| 45 sk_sp<SkImage> LoadPng(const base::FilePath& path) { | |
| 46 std::string data; | |
| 47 SkBitmap bitmap; | |
| 48 if (!base::ReadFileToString(path, &data) || | |
| 49 !gfx::PNGCodec::Decode( | |
| 50 reinterpret_cast<const unsigned char*>(data.data()), data.size(), | |
| 51 &bitmap) || | |
| 52 bitmap.colorType() != kRGBA_8888_SkColorType) { | |
| 53 return nullptr; | |
| 54 } | |
| 55 return SkImage::MakeFromBitmap(bitmap); | |
| 56 } | |
| 57 | |
| 27 } // namespace | 58 } // namespace |
| 28 | 59 |
| 29 constexpr char const VrControllerModel::kComponentName[]; | |
| 30 constexpr char const VrControllerModel::kDefaultVersion[]; | |
| 31 constexpr char const VrControllerModel::kModelsDirectory[]; | |
| 32 constexpr char const VrControllerModel::kModelFilename[]; | |
| 33 constexpr char const VrControllerModel::kTexturesDirectory[]; | |
| 34 constexpr char const* VrControllerModel::kTextureFilenames[]; | |
| 35 | |
| 36 VrControllerModel::VrControllerModel( | 60 VrControllerModel::VrControllerModel( |
| 37 std::unique_ptr<gltf::Asset> gltf_asset, | 61 std::unique_ptr<gltf::Asset> gltf_asset, |
| 38 std::vector<std::unique_ptr<gltf::Buffer>> buffers) | 62 std::vector<std::unique_ptr<gltf::Buffer>> buffers) |
| 39 : gltf_asset_(std::move(gltf_asset)), | 63 : gltf_asset_(std::move(gltf_asset)), |
| 40 texture_bitmaps_(State::STATE_COUNT), | |
| 41 buffers_(std::move(buffers)) {} | 64 buffers_(std::move(buffers)) {} |
| 42 | 65 |
| 43 VrControllerModel::~VrControllerModel() = default; | 66 VrControllerModel::~VrControllerModel() = default; |
| 44 | 67 |
| 45 const GLvoid* VrControllerModel::ElementsBuffer() const { | 68 const GLvoid* VrControllerModel::ElementsBuffer() const { |
| 46 const gltf::BufferView* buffer_view = | 69 const gltf::BufferView* buffer_view = |
| 47 gltf_asset_->GetBufferView(ELEMENTS_BUFFER_ID); | 70 gltf_asset_->GetBufferView(ELEMENTS_BUFFER_ID); |
| 48 DCHECK(buffer_view && buffer_view->target == GL_ARRAY_BUFFER); | 71 DCHECK(buffer_view && buffer_view->target == GL_ARRAY_BUFFER); |
| 49 const char* buffer = Buffer(); | 72 const char* buffer = Buffer(); |
| 50 return buffer ? buffer + buffer_view->byte_offset : nullptr; | 73 return buffer ? buffer + buffer_view->byte_offset : nullptr; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 } | 108 } |
| 86 | 109 |
| 87 const gltf::Accessor* VrControllerModel::PositionAccessor() const { | 110 const gltf::Accessor* VrControllerModel::PositionAccessor() const { |
| 88 return Accessor(kPosition); | 111 return Accessor(kPosition); |
| 89 } | 112 } |
| 90 | 113 |
| 91 const gltf::Accessor* VrControllerModel::TextureCoordinateAccessor() const { | 114 const gltf::Accessor* VrControllerModel::TextureCoordinateAccessor() const { |
| 92 return Accessor(kTexCoord); | 115 return Accessor(kTexCoord); |
| 93 } | 116 } |
| 94 | 117 |
| 95 void VrControllerModel::SetTexture(int state, | 118 void VrControllerModel::SetBaseTexture(sk_sp<SkImage> image) { |
| 96 std::unique_ptr<SkBitmap> bitmap) { | 119 base_texture_ = image; |
| 97 DCHECK(state >= 0 && state < STATE_COUNT); | |
| 98 texture_bitmaps_[state] = std::move(bitmap); | |
| 99 } | 120 } |
| 100 | 121 |
| 101 const SkBitmap* VrControllerModel::GetTexture(int state) const { | 122 void VrControllerModel::SetTexturePatch(int state, sk_sp<SkImage> image) { |
| 102 DCHECK(state >= 0 && state < STATE_COUNT); | 123 DCHECK(state >= 0 && state < STATE_COUNT); |
| 103 return texture_bitmaps_[state].get(); | 124 patches_[state] = image; |
| 125 } | |
| 126 | |
| 127 sk_sp<SkImage> VrControllerModel::GetTexture(int state) const { | |
| 128 if (!patches_[state]) | |
| 129 return base_texture_; | |
| 130 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul( | |
| 131 base_texture_->width(), base_texture_->height()); | |
| 132 SkCanvas* canvas = surface->getCanvas(); | |
| 133 canvas->drawImage(base_texture_, 0, 0); | |
|
mthiesse
2017/04/28 18:26:39
Add a TODO to avoid drawing the pixels that will b
acondor_
2017/04/28 18:57:44
Not worth it due to the patches' small sizes.
| |
| 134 SkPaint paint; | |
| 135 paint.setBlendMode(SkBlendMode::kSrc); | |
| 136 canvas->drawImage(patches_[state], kPatchesLocations[state].x(), | |
| 137 kPatchesLocations[state].y(), &paint); | |
| 138 return sk_sp<SkImage>(surface->makeImageSnapshot()); | |
| 104 } | 139 } |
| 105 | 140 |
| 106 const char* VrControllerModel::Buffer() const { | 141 const char* VrControllerModel::Buffer() const { |
| 107 if (buffers_.empty()) | 142 if (buffers_.empty()) |
| 108 return nullptr; | 143 return nullptr; |
| 109 return buffers_[0]->data(); | 144 return buffers_[0]->data(); |
| 110 } | 145 } |
| 111 | 146 |
| 112 const gltf::Accessor* VrControllerModel::Accessor( | 147 const gltf::Accessor* VrControllerModel::Accessor( |
| 113 const std::string& key) const { | 148 const std::string& key) const { |
| 114 const gltf::Mesh* mesh = gltf_asset_->GetMesh(0); | 149 const gltf::Mesh* mesh = gltf_asset_->GetMesh(0); |
| 115 DCHECK(mesh && mesh->primitives.size()); | 150 DCHECK(mesh && mesh->primitives.size()); |
| 116 auto it = mesh->primitives[0]->attributes.find(key); | 151 auto it = mesh->primitives[0]->attributes.find(key); |
| 117 DCHECK(it != mesh->primitives[0]->attributes.begin()); | 152 DCHECK(it != mesh->primitives[0]->attributes.begin()); |
| 118 return it->second; | 153 return it->second; |
| 119 } | 154 } |
| 120 | 155 |
| 121 std::unique_ptr<VrControllerModel> VrControllerModel::LoadFromComponent() { | 156 std::unique_ptr<VrControllerModel> VrControllerModel::LoadFromComponent() { |
| 122 base::FilePath models_path; | 157 base::FilePath models_path; |
| 123 PathService::Get(component_updater::DIR_COMPONENT_USER, &models_path); | 158 PathService::Get(component_updater::DIR_COMPONENT_USER, &models_path); |
| 124 models_path = models_path.Append(VrControllerModel::kComponentName) | 159 models_path = models_path.Append(kComponentName) |
| 125 .Append(VrControllerModel::kDefaultVersion) | 160 .Append(kDefaultVersion) |
| 126 .Append(VrControllerModel::kModelsDirectory); | 161 .Append(kModelsDirectory); |
| 127 auto model_path = models_path.Append(VrControllerModel::kModelFilename); | 162 auto model_path = models_path.Append(kModelFilename); |
| 128 | 163 |
| 129 // No further action if model file is not present | 164 // No further action if model file is not present |
| 130 if (!base::PathExists(model_path)) { | 165 if (!base::PathExists(model_path)) { |
| 131 LOG(WARNING) << "Controller model files not found"; | 166 LOG(WARNING) << "Controller model files not found"; |
|
mthiesse
2017/04/28 18:26:39
DLOG
acondor_
2017/04/28 18:57:43
This will change with the resources CL.
| |
| 132 return nullptr; | 167 return nullptr; |
| 133 } | 168 } |
| 134 | 169 |
| 135 GltfParser gltf_parser; | 170 GltfParser gltf_parser; |
| 136 std::vector<std::unique_ptr<gltf::Buffer>> buffers; | 171 std::vector<std::unique_ptr<gltf::Buffer>> buffers; |
| 137 auto asset = gltf_parser.Parse(model_path, &buffers); | 172 auto asset = gltf_parser.Parse(model_path, &buffers); |
| 138 if (!asset) { | 173 if (!asset) { |
| 139 LOG(ERROR) << "Failed to read controller model"; | 174 LOG(ERROR) << "Failed to read controller model"; |
|
mthiesse
2017/04/28 18:26:39
DLOG
acondor_
2017/04/28 18:57:44
Acknowledged.
| |
| 140 return nullptr; | 175 return nullptr; |
| 141 } | 176 } |
| 142 | 177 |
| 143 auto controller_model = | 178 auto controller_model = |
| 144 base::MakeUnique<VrControllerModel>(std::move(asset), std::move(buffers)); | 179 base::MakeUnique<VrControllerModel>(std::move(asset), std::move(buffers)); |
| 145 | 180 |
| 146 auto textures_path = | 181 auto textures_path = models_path.Append(kTexturesDirectory); |
| 147 models_path.Append(VrControllerModel::kTexturesDirectory); | 182 |
| 183 auto base_texture = LoadPng(textures_path.Append(kBaseTextureFilename)); | |
| 184 if (!base_texture) { | |
| 185 LOG(ERROR) << "Failed to read controller base texture"; | |
| 186 return nullptr; | |
| 187 } | |
| 188 controller_model->SetBaseTexture(std::move(base_texture)); | |
| 148 | 189 |
| 149 for (int i = 0; i < VrControllerModel::STATE_COUNT; i++) { | 190 for (int i = 0; i < VrControllerModel::STATE_COUNT; i++) { |
| 150 auto texture_path = | 191 if (!kTexturePatchesFilenames[i][0]) |
| 151 textures_path.Append(VrControllerModel::kTextureFilenames[i]); | 192 continue; |
| 152 std::string data; | 193 auto patch_image = |
| 153 auto bitmap = base::MakeUnique<SkBitmap>(); | 194 LoadPng(textures_path.Append(kTexturePatchesFilenames[i])); |
| 154 if (!base::ReadFileToString(texture_path, &data) || | 195 if (!patch_image) { |
| 155 !gfx::PNGCodec::Decode( | 196 LOG(ERROR) << "Failed to read controller texture patch"; |
| 156 reinterpret_cast<const unsigned char*>(data.data()), data.size(), | 197 continue; |
| 157 bitmap.get()) || | |
| 158 bitmap->colorType() != kRGBA_8888_SkColorType) { | |
| 159 LOG(ERROR) << "Failed to read controller texture"; | |
| 160 return nullptr; | |
| 161 } | 198 } |
| 162 controller_model->SetTexture(i, std::move(bitmap)); | 199 controller_model->SetTexturePatch(i, patch_image); |
| 163 } | 200 } |
| 164 | 201 |
| 165 return controller_model; | 202 return controller_model; |
| 166 } | 203 } |
| 167 | 204 |
| 168 } // namespace vr_shell | 205 } // namespace vr_shell |
| OLD | NEW |