@@ -66,6 +66,16 @@ namespace plateau::texture {
6666 }
6767 }
6868
69+ bool TextureAtlasCanvas::isTexturePacked (const std::string& src_file_path, AtlasInfo& out_atlas_info) {
70+ for (const auto & tex_info : packed_textures_info) {
71+ if (tex_info.getSrcTexturePath () == src_file_path) {
72+ out_atlas_info = tex_info;
73+ return true ;
74+ }
75+ }
76+ return false ;
77+ }
78+
6979 void TexturePacker::process (Model& model) {
7080 for (size_t i = 0 ; i < model.getRootNodeCount (); ++i) {
7181 const auto & child_node = model.getRootNodeAt (i);
@@ -79,7 +89,7 @@ namespace plateau::texture {
7989 }
8090 }
8191
82- void TexturePacker::processNodeRecursive (const Node& node) {
92+ void TexturePacker::processNodeRecursive (const Node& node) { // NOLINT(misc-no-recursion)
8393 Mesh* mesh = node.getMesh ();
8494 processMesh (mesh);
8595 for (int i = 0 ; i < node.getChildCount (); ++i) {
@@ -88,6 +98,32 @@ namespace plateau::texture {
8898 }
8999 }
90100
101+ namespace {
102+ void updateUVOfSubMesh (Mesh* mesh, const SubMesh& sub_mesh, const AtlasInfo& info) {
103+ constexpr auto delta = 1.0 ;
104+ const auto u = info.getUPos ();
105+ const auto v = info.getVPos ();
106+ const auto u_fac = info.getUFactor () * delta;
107+ const auto v_fac = info.getVFactor () * delta;
108+
109+
110+
111+ // SubMesh中に含まれる頂点番号を求めます。
112+ const auto & indices = mesh->getIndices ();
113+ std::set<size_t > vertices_in_sub_mesh;
114+ for (auto i = sub_mesh.getStartIndex (); i <= sub_mesh.getEndIndex (); i++) {
115+ vertices_in_sub_mesh.insert (indices.at (i));
116+ }
117+ // SubMesh中に含まれる頂点について、UVを変更します。
118+ auto & uv1 = mesh->getUV1 ();
119+ for (const auto vs : vertices_in_sub_mesh) {
120+ const double uv_x = u + (uv1.at (vs).x * u_fac);
121+ const double uv_y = 1 - v - v_fac + (uv1.at (vs).y * v_fac);
122+ uv1[vs] = TVec2f{(float )uv_x, (float )uv_y};
123+ }
124+ }
125+ }
126+
91127 void TexturePacker::processMesh (plateau::polygonMesh::Mesh* mesh) {
92128 if (mesh == nullptr ) {
93129 return ;
@@ -129,12 +165,26 @@ namespace plateau::texture {
129165 continue ;
130166 }
131167
168+ // すでにパック済みならばそれを利用
169+ AtlasInfo packed_info = AtlasInfo::empty ();
170+ TextureAtlasCanvas* packed_atlas_canvas_ptr = nullptr ;
171+ if (isTexturePacked (tex_url, packed_atlas_canvas_ptr, packed_info)) {
172+ if (packed_atlas_canvas_ptr != nullptr ) {
173+ SubMesh new_sub_mesh = sub_mesh;
174+ new_sub_mesh.setTexturePath (packed_atlas_canvas_ptr->getSaveFilePath ());
175+ updateUVOfSubMesh (mesh, sub_mesh, packed_info);
176+ sub_mesh_list.push_back (new_sub_mesh);
177+ ++index;
178+ continue ;
179+ }
180+ }
181+
132182 // canvasのどれかにパックできるか確認
133183 int target_canvas_id = -1 ;
134184 AtlasInfo info = AtlasInfo::empty ();
135185 for (int i=0 ; i<canvases_.size (); i++) {
136186 auto & canvas = canvases_.at (i);
137- info = canvas->insert (width, height);
187+ info = canvas->insert (width, height, tex_url );
138188 if (info.getValid ()) {
139189 target_canvas_id = i;
140190 break ;
@@ -157,58 +207,38 @@ namespace plateau::texture {
157207 target_canvas_id = (int )max_coverage_index;
158208 canvases_.at (max_coverage_index)->flush ();
159209 canvases_.at (max_coverage_index) = std::make_shared<TextureAtlasCanvas>(canvas_width_, canvas_height_);
160- info = canvases_.at (max_coverage_index)->insert (width, height);
210+ info = canvases_.at (max_coverage_index)->insert (width, height, tex_url );
161211 }
162212
163213 assert (info.getValid ());
164214
165- constexpr auto delta = 1.0 ;
166- const auto x = info.getLeft ();
167- const auto y = info.getTop ();
168- const auto u = info.getUPos ();
169- const auto v = info.getVPos ();
170- const auto u_fac = info.getUFactor () * delta;
171- const auto v_fac = info.getVFactor () * delta;
172- auto tex = sub_mesh.getTexturePath ();
173215
174216 auto & target_canvas = canvases_.at (target_canvas_id);
175- image->packTo (&target_canvas->getCanvas (), x, y );
217+ image->packTo (&target_canvas->getCanvas (), info. getLeft (), info. getTop () );
176218 target_canvas->setSaveFilePathIfEmpty (image->getFilePath ());
177-
178219 SubMesh new_sub_mesh = sub_mesh;
179220 new_sub_mesh.setTexturePath (target_canvas->getSaveFilePath ());
180221 sub_mesh_list.push_back (new_sub_mesh);
181222
182- // SubMesh中に含まれる頂点番号を求めます。
183- const auto & indices = mesh->getIndices ();
184- std::set<size_t > vertices_in_sub_mesh;
185- for (auto i = sub_mesh.getStartIndex (); i <= sub_mesh.getEndIndex (); i++) {
186- vertices_in_sub_mesh.insert (indices.at (i));
187- }
188- // SubMesh中に含まれる頂点について、UVを変更します。
189- auto & uv1 = mesh->getUV1 ();
190- for (const auto vs : vertices_in_sub_mesh) {
191- const double uv_x = u + (uv1.at (vs).x * u_fac);
192- const double uv_y = 1 - v - v_fac + (uv1.at (vs).y * v_fac);
193- uv1[vs] = TVec2f{(float )uv_x, (float )uv_y};
194- }
223+ updateUVOfSubMesh (mesh, sub_mesh, info);
195224
196225 ++index;
197226 }
198227 mesh->setSubMeshes (sub_mesh_list);
199228 }
200229
201- void TextureAtlasCanvas::update (const size_t width, const size_t height, const bool is_new_container) {
230+ void TextureAtlasCanvas::update (const size_t width, const size_t height, const bool is_new_container, const AtlasInfo& packed_texture_info ) {
202231
203232 capacity_ += (width * height);
204233 coverage_ = (double )capacity_ / static_cast <double >(canvas_width_ * canvas_height_) * 100.0 ;
234+ packed_textures_info.push_back (packed_texture_info);
205235
206236 if (is_new_container) {
207237 vertical_range_ += height;
208238 }
209239 }
210240
211- AtlasInfo TextureAtlasCanvas::insert (const size_t width, const size_t height) {
241+ AtlasInfo TextureAtlasCanvas::insert (const size_t width, const size_t height, const std::string& src_texture_path ) {
212242 AtlasInfo atlas_info = AtlasInfo::empty ();
213243
214244 for (auto & container : container_list_) {
@@ -223,8 +253,9 @@ namespace plateau::texture {
223253 true , container.getHorizontalRange (), container.getVerticalRange (), width, height,
224254 (double )container.getHorizontalRange () / static_cast <double >(canvas_width_),
225255 (double )container.getVerticalRange () / static_cast <double >(canvas_height_),
226- (double )width / static_cast <double >(canvas_width_), (double )height / static_cast <double >(canvas_height_));
227- this ->update (width, height, false );
256+ (double )width / static_cast <double >(canvas_width_), (double )height / static_cast <double >(canvas_height_),
257+ src_texture_path);
258+ this ->update (width, height, false , atlas_info);
228259
229260 break ;
230261 }
@@ -235,10 +266,27 @@ namespace plateau::texture {
235266 container_list_.push_back (container);
236267 atlas_info = AtlasInfo (true , container.getHorizontalRange (), container.getVerticalRange (), width, height,
237268 (double )container.getHorizontalRange () / static_cast <double >(canvas_width_), (double )container.getVerticalRange () / static_cast <double >(canvas_height_),
238- (double )width / static_cast <double >(canvas_width_), (double )height / static_cast <double >(canvas_height_));
239- this ->update (width, height, true );
269+ (double )width / static_cast <double >(canvas_width_), (double )height / static_cast <double >(canvas_height_),
270+ src_texture_path);
271+ this ->update (width, height, true , atlas_info);
240272 }
241273
242274 return atlas_info;
243275 }
276+
277+
278+
279+ bool TexturePacker::isTexturePacked (const std::string& src_file_path, TextureAtlasCanvas*& out_contained_canvas_ptr, AtlasInfo& out_atlas_info) {
280+ out_contained_canvas_ptr = nullptr ;
281+ for (const auto & canvas : canvases_) {
282+ auto packed_info = AtlasInfo::empty ();
283+ if (canvas->isTexturePacked (src_file_path, packed_info)) {
284+ out_contained_canvas_ptr = canvas.get ();
285+ out_atlas_info = packed_info;
286+ return true ;
287+ }
288+ }
289+ return false ;
290+ }
291+
244292} // namespace plateau::texture
0 commit comments