Mercurial > games > semicongine
comparison semiconginev2/contrib/algorithms/texture_packing.nim @ 1228:4e465583ea32
did: rename texture to image
author | sam <sam@basx.dev> |
---|---|
date | Thu, 18 Jul 2024 16:33:24 +0700 |
parents | c8e3037aca66 |
children | 841e12f33c47 |
comparison
equal
deleted
inserted
replaced
1227:4d97cfc4888b | 1228:4e465583ea32 |
---|---|
40 newRect.y += 1 | 40 newRect.y += 1 |
41 | 41 |
42 return (false, newRect) | 42 return (false, newRect) |
43 | 43 |
44 | 44 |
45 proc Pack*[T](textures: seq[Texture[T]]): tuple[atlas: Texture[T], coords: seq[tuple[x: uint32, y: uint32]]] = | 45 proc Pack*[T: PixelType](images: seq[Image[T]]): tuple[atlas: Image[T], coords: seq[tuple[x: uint32, y: uint32]]] = |
46 const MAX_ATLAS_SIZE = 4096'u32 | 46 const MAX_ATLAS_SIZE = 4096'u32 |
47 var areas: seq[tuple[i: int, w, h: uint32]] | 47 var areas: seq[tuple[i: int, w, h: uint32]] |
48 | 48 |
49 for i in 0 ..< textures.len: | 49 for i in 0 ..< images.len: |
50 areas.add (i, textures[i].width, textures[i].height) | 50 areas.add (i, images[i].width, images[i].height) |
51 | 51 |
52 let areasBySize = areas.sortedByIt(-(it[1] * it[2]).int64) | 52 let areasBySize = areas.sortedByIt(-(it[1] * it[2]).int64) |
53 var assignedAreas: seq[Rect] | 53 var assignedAreas: seq[Rect] |
54 var maxDim = 128'u32 | 54 var maxDim = 128'u32 |
55 | 55 |
56 for area in areasBySize: | 56 for area in areasBySize: |
57 var pos = find_insertion_position(assignedAreas, area, maxDim) | 57 var pos = find_insertion_position(assignedAreas, area, maxDim) |
58 while not pos[0]: # this should actually never loop more than once, but weird things happen ¯\_(ツ)_/¯ | 58 while not pos[0]: # this should actually never loop more than once, but weird things happen ¯\_(ツ)_/¯ |
59 maxDim = maxDim * 2 | 59 maxDim = maxDim * 2 |
60 assert maxDim <= MAX_ATLAS_SIZE, &"Atlas gets bigger than {MAX_ATLAS_SIZE}, cannot pack textures" | 60 assert maxDim <= MAX_ATLAS_SIZE, &"Atlas gets bigger than {MAX_ATLAS_SIZE}, cannot pack images" |
61 pos = find_insertion_position(assignedAreas, area, maxDim) | 61 pos = find_insertion_position(assignedAreas, area, maxDim) |
62 | 62 |
63 assignedAreas.add pos[1] | 63 assignedAreas.add pos[1] |
64 | 64 |
65 # check there are overlaps | 65 # check there are overlaps |
66 for i in 0 ..< assignedAreas.len - 1: | 66 for i in 0 ..< assignedAreas.len - 1: |
67 for j in i + 1 ..< assignedAreas.len: | 67 for j in i + 1 ..< assignedAreas.len: |
68 assert not assignedAreas[i].advanceIfOverlap(assignedAreas[j])[0], &"{assignedAreas[i]} and {assignedAreas[j]} overlap!" | 68 assert not assignedAreas[i].advanceIfOverlap(assignedAreas[j])[0], &"{assignedAreas[i]} and {assignedAreas[j]} overlap!" |
69 | 69 |
70 result.atlas = Texture[T](width: maxDim, height: maxDim, data: newSeq[T](maxDim * maxDim)) | 70 result.atlas = Image[T](width: maxDim, height: maxDim, data: newSeq[T](maxDim * maxDim)) |
71 result.coords.setLen(textures.len) | 71 result.coords.setLen(images.len) |
72 for rect in assignedAreas: | 72 for rect in assignedAreas: |
73 for y in 0 ..< rect.h: | 73 for y in 0 ..< rect.h: |
74 for x in 0 ..< rect.w: | 74 for x in 0 ..< rect.w: |
75 assert result.atlas[rect.x + x, rect.y + y] == 0, "Atlas texture packing encountered an overlap error" | 75 assert result.atlas[rect.x + x, rect.y + y] == 0, "Atlas texture packing encountered an overlap error" |
76 result.atlas[rect.x + x, rect.y + y] = textures[rect.i][x, y] | 76 result.atlas[rect.x + x, rect.y + y] = images[rect.i][x, y] |
77 result.coords[rect.i] = (x: rect.x, y: rect.y) | 77 result.coords[rect.i] = (x: rect.x, y: rect.y) |