Skip to content

Commit

Permalink
convert: Speed up converter texture packing
Browse files Browse the repository at this point in the history
cythonized more the texture packing, also changed the
list passed to factor(), before was a list of frame objects, now
a list of only width, height and index of the frames.
  • Loading branch information
fabiobarkoski authored and heinezen committed Dec 8, 2024
1 parent ed26812 commit ceefb23
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 66 deletions.
22 changes: 12 additions & 10 deletions openage/convert/processor/export/texture_merge.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2014-2023 the openage authors. See copying.md for legal info.
# Copyright 2014-2024 the openage authors. See copying.md for legal info.
#
# cython: infer_types=True
# pylint: disable=too-many-locals
Expand All @@ -9,15 +9,16 @@ a terrain texture.
import numpy
from enum import Enum

cimport cython
cimport numpy

from ....log import spam
from ...service.export.png.binpack cimport block
from ...entity_object.export.texture import TextureImage
from ...service.export.png.binpack cimport Packer, DeterministicPacker, RowPacker, ColumnPacker, BinaryTreePacker, BestPacker
from ...service.export.png.binpack cimport DeterministicPacker, RowPacker, ColumnPacker, BinaryTreePacker, BestPacker
from ...value_object.read.media.hardcoded.texture import (MAX_TEXTURE_DIMENSION, MARGIN,
TERRAIN_ASPECT_RATIO)

cimport cython
cimport numpy

class PackerType(Enum):
"""
Packer types
Expand Down Expand Up @@ -57,14 +58,15 @@ cdef void cmerge_frames(texture, packer_type=PackerType.BINPACK, cache=None) exc
:type cache: list
"""
cdef list frames = texture.frames
cdef list blocks = [block(idx, frame.width, frame.height) for idx, frame in enumerate(frames)]

if len(frames) == 0:
raise ValueError("cannot create texture with empty input frame list")

cdef BestPacker packer

if cache:
packer = BestPacker([DeterministicPacker(margin=MARGIN,hints=cache)])
packer = BestPacker([DeterministicPacker(margin=MARGIN, hints=cache)])

else:
if packer_type == PackerType.ROW:
Expand All @@ -81,7 +83,7 @@ cdef void cmerge_frames(texture, packer_type=PackerType.BINPACK, cache=None) exc
RowPacker(margin=MARGIN),
ColumnPacker(margin=MARGIN)])

packer.pack(frames)
packer.pack(blocks)

cdef int width = packer.width()
cdef int height = packer.height()
Expand All @@ -106,11 +108,11 @@ cdef void cmerge_frames(texture, packer_type=PackerType.BINPACK, cache=None) exc
cdef int sub_h

cdef list drawn_frames_meta = []
for sub_frame in frames:
for index, sub_frame in enumerate(frames):
sub_w = sub_frame.width
sub_h = sub_frame.height

pos_x, pos_y = packer.pos(sub_frame)
pos_x, pos_y = packer.pos(index)

spam("drawing frame %03d on atlas at %d x %d...",
len(drawn_frames_meta), pos_x, pos_y)
Expand Down Expand Up @@ -143,4 +145,4 @@ cdef void cmerge_frames(texture, packer_type=PackerType.BINPACK, cache=None) exc
if isinstance(packer, BestPacker):
# Only generate these values if no custom packer was used
# TODO: It might make sense to do it anyway for debugging purposes
texture.best_packer_hints = packer.get_mapping_hints(frames)
texture.best_packer_hints = packer.get_mapping_hints(blocks)
34 changes: 23 additions & 11 deletions openage/convert/service/export/png/binpack.pxd
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# Copyright 2021-2021 the openage authors. See copying.md for legal info.
# Copyright 2021-2024 the openage authors. See copying.md for legal info.

from libcpp.memory cimport shared_ptr
from libcpp.unordered_map cimport unordered_map

ctypedef (unsigned int, unsigned int, (unsigned int, unsigned int)) mapping_value

cdef class Packer:
cdef unsigned int margin
cdef dict mapping
cdef unordered_map[int, mapping_value] mapping

cdef void pack(self, list blocks)
cdef (unsigned int, unsigned int) pos(self, block)
cdef (unsigned int, unsigned int) pos(self, int index)
cdef unsigned int width(self)
cdef unsigned int height(self)
cdef list get_mapping_hints(self, list blocks)
cdef (unsigned int) get_packer_settings(self)

cdef class DeterministicPacker(Packer):
pass
Expand All @@ -20,9 +24,11 @@ cdef class BestPacker:

cdef void pack(self, list blocks)
cdef Packer best_packer(self)
cdef (unsigned int, unsigned int) pos(self, block)
cdef (unsigned int, unsigned int) pos(self, int index)
cdef unsigned int width(self)
cdef unsigned int height(self)
cdef list get_mapping_hints(self, list blocks)
cdef (unsigned int) get_packer_settings(self)

cdef class RowPacker(Packer):
pass
Expand All @@ -34,12 +40,13 @@ cdef class BinaryTreePacker(Packer):
cdef unsigned int aspect_ratio
cdef packer_node *root

cdef void fit(self, block)
cdef packer_node *find_node(self, packer_node *root, unsigned int width, unsigned int height)
cdef packer_node *split_node(self, packer_node *node, unsigned int width, unsigned int height)
cdef packer_node *grow_node(self, unsigned int width, unsigned int height)
cdef packer_node *grow_right(self, unsigned int width, unsigned int height)
cdef packer_node *grow_down(self, unsigned int width, unsigned int height)
cdef void fit(self, block block)
cdef (unsigned int) get_packer_settings(self)
cdef packer_node *find_node(self, packer_node *root, unsigned int width, unsigned int height) noexcept
cdef packer_node *split_node(self, packer_node *node, unsigned int width, unsigned int height) noexcept
cdef packer_node *grow_node(self, unsigned int width, unsigned int height) noexcept
cdef packer_node *grow_right(self, unsigned int width, unsigned int height) noexcept
cdef packer_node *grow_down(self, unsigned int width, unsigned int height) noexcept

cdef struct packer_node:
unsigned int x
Expand All @@ -49,3 +56,8 @@ cdef struct packer_node:
bint used
packer_node *down
packer_node *right

cdef struct block:
unsigned int index
unsigned int width
unsigned int height
Loading

0 comments on commit ceefb23

Please sign in to comment.