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}}; | |
cjgrant
2017/04/27 18:47:29
How will you deliver these coordinates through com
acondor_
2017/04/27 19:01:19
I'm in favor of delivering them in the component a
| |
44 | |
45 sk_sp<SkImage> LoadPNG(const base::FilePath& path) { | |
cjgrant
2017/04/27 18:47:29
nit: You're probably following the gfx::PNGCodec s
acondor_
2017/04/27 19:01:19
Acknowledged.
acondor_
2017/04/28 14:22:38
Done.
| |
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[]; | 60 VrControllerModel::Patch::Patch() = default; |
30 constexpr char const VrControllerModel::kDefaultVersion[]; | 61 VrControllerModel::Patch::Patch(sk_sp<SkImage> image, const gfx::Point& offset) |
31 constexpr char const VrControllerModel::kModelsDirectory[]; | 62 : image(image), offset(offset) {} |
32 constexpr char const VrControllerModel::kModelFilename[]; | 63 VrControllerModel::Patch::~Patch() = default; |
33 constexpr char const VrControllerModel::kTexturesDirectory[]; | |
34 constexpr char const* VrControllerModel::kTextureFilenames[]; | |
35 | 64 |
36 VrControllerModel::VrControllerModel( | 65 VrControllerModel::VrControllerModel( |
37 std::unique_ptr<gltf::Asset> gltf_asset, | 66 std::unique_ptr<gltf::Asset> gltf_asset, |
38 std::vector<std::unique_ptr<gltf::Buffer>> buffers) | 67 std::vector<std::unique_ptr<gltf::Buffer>> buffers) |
39 : gltf_asset_(std::move(gltf_asset)), | 68 : gltf_asset_(std::move(gltf_asset)), |
40 texture_bitmaps_(State::STATE_COUNT), | |
41 buffers_(std::move(buffers)) {} | 69 buffers_(std::move(buffers)) {} |
42 | 70 |
43 VrControllerModel::~VrControllerModel() = default; | 71 VrControllerModel::~VrControllerModel() = default; |
44 | 72 |
45 const GLvoid* VrControllerModel::ElementsBuffer() const { | 73 const GLvoid* VrControllerModel::ElementsBuffer() const { |
46 const gltf::BufferView* buffer_view = | 74 const gltf::BufferView* buffer_view = |
47 gltf_asset_->GetBufferView(ELEMENTS_BUFFER_ID); | 75 gltf_asset_->GetBufferView(ELEMENTS_BUFFER_ID); |
48 DCHECK(buffer_view && buffer_view->target == GL_ARRAY_BUFFER); | 76 DCHECK(buffer_view && buffer_view->target == GL_ARRAY_BUFFER); |
49 const char* buffer = Buffer(); | 77 const char* buffer = Buffer(); |
50 return buffer ? buffer + buffer_view->byte_offset : nullptr; | 78 return buffer ? buffer + buffer_view->byte_offset : nullptr; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 } | 113 } |
86 | 114 |
87 const gltf::Accessor* VrControllerModel::PositionAccessor() const { | 115 const gltf::Accessor* VrControllerModel::PositionAccessor() const { |
88 return Accessor(kPosition); | 116 return Accessor(kPosition); |
89 } | 117 } |
90 | 118 |
91 const gltf::Accessor* VrControllerModel::TextureCoordinateAccessor() const { | 119 const gltf::Accessor* VrControllerModel::TextureCoordinateAccessor() const { |
92 return Accessor(kTexCoord); | 120 return Accessor(kTexCoord); |
93 } | 121 } |
94 | 122 |
95 void VrControllerModel::SetTexture(int state, | 123 void VrControllerModel::SetBaseTexture(sk_sp<SkImage> image) { |
96 std::unique_ptr<SkBitmap> bitmap) { | 124 base_texture_ = image; |
97 DCHECK(state >= 0 && state < STATE_COUNT); | |
98 texture_bitmaps_[state] = std::move(bitmap); | |
99 } | 125 } |
100 | 126 |
101 const SkBitmap* VrControllerModel::GetTexture(int state) const { | 127 void VrControllerModel::SetTexturePatch(int state, sk_sp<SkImage> image) { |
102 DCHECK(state >= 0 && state < STATE_COUNT); | 128 DCHECK(state >= 0 && state < STATE_COUNT); |
103 return texture_bitmaps_[state].get(); | 129 patches_[state] = image; |
130 } | |
131 | |
132 sk_sp<SkImage> VrControllerModel::GetTexture(int state) const { | |
133 if (!patches_[state]) | |
134 return base_texture_; | |
135 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul( | |
136 base_texture_->width(), base_texture_->height()); | |
137 SkCanvas* canvas = surface->getCanvas(); | |
138 canvas->drawImage(base_texture_, 0, 0); | |
139 SkPaint paint; | |
140 paint.setBlendMode(SkBlendMode::kSrc); | |
141 canvas->drawImage(patches_[state], kPatchesLocations[state].x(), | |
142 kPatchesLocations[state].y(), &paint); | |
143 return sk_sp<SkImage>(surface->makeImageSnapshot()); | |
104 } | 144 } |
105 | 145 |
106 const char* VrControllerModel::Buffer() const { | 146 const char* VrControllerModel::Buffer() const { |
107 if (buffers_.empty()) | 147 if (buffers_.empty()) |
108 return nullptr; | 148 return nullptr; |
109 return buffers_[0]->data(); | 149 return buffers_[0]->data(); |
110 } | 150 } |
111 | 151 |
112 const gltf::Accessor* VrControllerModel::Accessor( | 152 const gltf::Accessor* VrControllerModel::Accessor( |
113 const std::string& key) const { | 153 const std::string& key) const { |
114 const gltf::Mesh* mesh = gltf_asset_->GetMesh(0); | 154 const gltf::Mesh* mesh = gltf_asset_->GetMesh(0); |
115 DCHECK(mesh && mesh->primitives.size()); | 155 DCHECK(mesh && mesh->primitives.size()); |
116 auto it = mesh->primitives[0]->attributes.find(key); | 156 auto it = mesh->primitives[0]->attributes.find(key); |
117 DCHECK(it != mesh->primitives[0]->attributes.begin()); | 157 DCHECK(it != mesh->primitives[0]->attributes.begin()); |
118 return it->second; | 158 return it->second; |
119 } | 159 } |
120 | 160 |
121 std::unique_ptr<VrControllerModel> VrControllerModel::LoadFromComponent() { | 161 std::unique_ptr<VrControllerModel> VrControllerModel::LoadFromComponent() { |
122 base::FilePath models_path; | 162 base::FilePath models_path; |
123 PathService::Get(component_updater::DIR_COMPONENT_USER, &models_path); | 163 PathService::Get(component_updater::DIR_COMPONENT_USER, &models_path); |
124 models_path = models_path.Append(VrControllerModel::kComponentName) | 164 models_path = models_path.Append(kComponentName) |
125 .Append(VrControllerModel::kDefaultVersion) | 165 .Append(kDefaultVersion) |
126 .Append(VrControllerModel::kModelsDirectory); | 166 .Append(kModelsDirectory); |
127 auto model_path = models_path.Append(VrControllerModel::kModelFilename); | 167 auto model_path = models_path.Append(kModelFilename); |
128 | 168 |
129 // No further action if model file is not present | 169 // No further action if model file is not present |
130 if (!base::PathExists(model_path)) { | 170 if (!base::PathExists(model_path)) { |
131 LOG(WARNING) << "Controller model files not found"; | 171 LOG(WARNING) << "Controller model files not found"; |
132 return nullptr; | 172 return nullptr; |
133 } | 173 } |
134 | 174 |
135 GltfParser gltf_parser; | 175 GltfParser gltf_parser; |
136 std::vector<std::unique_ptr<gltf::Buffer>> buffers; | 176 std::vector<std::unique_ptr<gltf::Buffer>> buffers; |
137 auto asset = gltf_parser.Parse(model_path, &buffers); | 177 auto asset = gltf_parser.Parse(model_path, &buffers); |
138 if (!asset) { | 178 if (!asset) { |
139 LOG(ERROR) << "Failed to read controller model"; | 179 LOG(ERROR) << "Failed to read controller model"; |
140 return nullptr; | 180 return nullptr; |
141 } | 181 } |
142 | 182 |
143 auto controller_model = | 183 auto controller_model = |
144 base::MakeUnique<VrControllerModel>(std::move(asset), std::move(buffers)); | 184 base::MakeUnique<VrControllerModel>(std::move(asset), std::move(buffers)); |
145 | 185 |
146 auto textures_path = | 186 auto textures_path = models_path.Append(kTexturesDirectory); |
147 models_path.Append(VrControllerModel::kTexturesDirectory); | 187 |
188 auto base_texture = LoadPNG(textures_path.Append(kBaseTextureFilename)); | |
189 if (!base_texture) { | |
190 LOG(ERROR) << "Failed to read controller base texture"; | |
191 return nullptr; | |
192 } | |
193 controller_model->SetBaseTexture(std::move(base_texture)); | |
148 | 194 |
149 for (int i = 0; i < VrControllerModel::STATE_COUNT; i++) { | 195 for (int i = 0; i < VrControllerModel::STATE_COUNT; i++) { |
150 auto texture_path = | 196 if (!kTexturePatchesFilenames[i][0]) |
151 textures_path.Append(VrControllerModel::kTextureFilenames[i]); | 197 continue; |
152 std::string data; | 198 auto patch_image = |
153 auto bitmap = base::MakeUnique<SkBitmap>(); | 199 LoadPNG(textures_path.Append(kTexturePatchesFilenames[i])); |
154 if (!base::ReadFileToString(texture_path, &data) || | 200 if (!patch_image) { |
155 !gfx::PNGCodec::Decode( | 201 LOG(ERROR) << "Failed to read controller texture patch"; |
156 reinterpret_cast<const unsigned char*>(data.data()), data.size(), | 202 continue; |
cjgrant
2017/04/27 18:47:29
If this fails, do we want to feed back the failure
acondor_
2017/04/27 19:01:19
There are only patches for clicked buttons, so it
| |
157 bitmap.get()) || | |
158 bitmap->colorType() != kRGBA_8888_SkColorType) { | |
159 LOG(ERROR) << "Failed to read controller texture"; | |
160 return nullptr; | |
161 } | 203 } |
162 controller_model->SetTexture(i, std::move(bitmap)); | 204 controller_model->SetTexturePatch(i, patch_image); |
163 } | 205 } |
164 | 206 |
165 return controller_model; | 207 return controller_model; |
166 } | 208 } |
167 | 209 |
168 } // namespace vr_shell | 210 } // namespace vr_shell |
OLD | NEW |