-
Notifications
You must be signed in to change notification settings - Fork 104
Thick Rings Texture Python Script
Max Hyper edited this page Jun 3, 2025
·
3 revisions
The following python script can be executed to generate the textures for the thick rings from a base texture
import tkinter as tk
from tkinter import filedialog
from enum import Enum
import numpy as np
import cv2
import sys
class Direction(object):
def __init__(self, name, xOffset, zOffset, axis, rotateClockWiseIndex):
self.name = name
self._xOffset = xOffset
self._zOffset = zOffset
self._axis = axis
self._rotateClockWiseIndex = rotateClockWiseIndex
@property
def xOffset(self):
return self._xOffset
@property
def zOffset(self):
return self._zOffset
@property
def axis(self):
return self._axis
@property
def rotateClockWiseIndex(self):
return self._rotateClockWiseIndex
def rotateY(dir):
return Horizontals[dir.rotateClockWiseIndex]
Horizontals = [Direction("SOUTH", 0, 1, "Z", 1), Direction("WEST", -1, 0, "X", 2), Direction("NORTH", 0, -1, "Z", 3), Direction("EAST", 1, 0, "X", 0)]
def newImage (width, height):
return np.zeros((width,height,3), np.uint8)
def setPixel (image, x, y, color):
w, h, channels = image.shape
if x >= 0 and x < w and y >= 0 and y < h:
image[x,y] = color
def blit (imageTo, imageFrom, offX, offY, rotCW90):
w, h, channels = imageFrom.shape
rotation = rotCW90 & 3
if rotation == 0:
for y in range(h):
for x in range(w):
setPixel(imageTo, x + offX, y + offY, imageFrom[x,y])
return
if rotation == 1:
for y in range(h):
for x in range(w):
destX = h - y - 1
setPixel(imageTo, destX + offX, x + offY, imageFrom[x,y])
return
if rotation == 2:
for y in range(h):
for x in range(w):
destX = w - x - 1
destY = h - y - 1
setPixel(imageTo, destX + offX, destY + offY, imageFrom[x,y])
return
if rotation == 3:
for y in range(h):
for x in range(w):
destY = w - x - 1
setPixel(imageTo, y + offX, destY + offY, imageFrom[x,y])
return
def createBarklessAntecedent (baseBuffer):
baseW, baseH, baseChannels = baseBuffer.shape
antecedent = newImage(baseW,baseH)
scale = int(baseW / 16)
blit(antecedent, baseBuffer, 3*scale, 3*scale, 1)
blit(antecedent, baseBuffer, -3*scale, 3*scale, 1)
blit(antecedent, baseBuffer, 3*scale, -3*scale, 1)
blit(antecedent, baseBuffer, -3*scale, -3*scale, 1)
ringStrip = newImage(6*scale,scale)
blit(ringStrip, baseBuffer, -5*scale, -3*scale, 0)
blit(antecedent, ringStrip, 0*scale, 2*scale, -1)
blit(antecedent, ringStrip, 15*scale, 8*scale, 1)
blit(ringStrip, baseBuffer, -5*scale, -12*scale, 0)
blit(antecedent, ringStrip, 0*scale, 8*scale, 1)
blit(antecedent, ringStrip, 15*scale, 2*scale, -1)
ringStrip = newImage(scale,6*scale)
blit(ringStrip, baseBuffer, -3*scale, -5*scale, 0)
blit(antecedent, ringStrip, 2*scale, 0*scale, -1)
blit(antecedent, ringStrip, 8*scale, 15*scale, 1)
blit(ringStrip, baseBuffer, -12*scale, -5*scale, 0)
blit(antecedent, ringStrip, 8*scale, 0*scale, 1)
blit(antecedent, ringStrip, 2*scale, 15*scale, -1)
center = newImage(14*scale, 14*scale)
blit(center, baseBuffer, -1*scale, -1*scale, 0)
blit(antecedent, center, 1*scale, 1*scale, 0)
return antecedent
def createMajorTexture(baseBuffer):
baseW, baseH, baseChannels = baseBuffer.shape
scale = int(baseW / 16)
majorW = 3*baseW
majorH = 3*baseH
antec_image = createBarklessAntecedent(baseBuffer)
major_image = newImage(majorW,majorH)
corners = [0]*4
edges = [0]*4
for i in range(4):
corners[i] = newImage(6*scale, 6*scale)
edges[i] = newImage(4*scale, 6*scale)
blit(corners[i], antec_image, 0, 0, i)
blit(edges[i], antec_image, -6*scale, 0, i)
centerX = 24
centerY = 24
for nesting in range(3):
edge = 2
imgSel = 0
for dir in Horizontals:
ovr = Direction.rotateY(dir)
offX = dir.xOffset
offY = dir.zOffset
compX = (-6 if offX == 1 else 0) + (-2 if dir.axis == "Z" else 0)
compY = (-6 if offY == 1 else 0) + (-2 if dir.axis == "X" else 0)
startX = offX * (14 + nesting * 6)
startY = offY * (14 + nesting * 6)
for way in [-1, 1]:
for i in range(4+nesting):
rowX = ovr.xOffset * i * way * 4
rowY = ovr.zOffset * i * way * 4
realX = centerX + startX + compX + rowX
realY = centerY + startY + compY + rowY
blit(major_image, edges[((imgSel * 13402141) >> 1) & 3], realX * scale, realY * scale, edge)
imgSel = imgSel+1
edge = edge+1
cornerX = [-1, 1, 1, -1]
cornerY = [-1, -1, 1, 1]
blit(major_image, antec_image, 16*scale, 16*scale, 0)
for nesting in [1,2,3]:
for corner in range(4):
corner_pixels = corners[(corner + nesting) & 0x3 ]
cX = cornerX[corner]
cY = cornerY[corner]
offX = cX * 6 * nesting + cX * 5
offY = cY * 6 * nesting + cY * 5
realX = 16 + 5 + offX
realY = 16 + 5 + offY
blit(major_image, corner_pixels, realX * scale, realY * scale, corner)
cornersW = scale
cornersH = scale
edgesW = 14*scale
edgesH = scale
for i in range(4):
corners[i] = newImage(cornersW, cornersH)
edges[i] = newImage(edgesW, edgesH)
blit(corners[i], baseBuffer, 0, 0, i)
blit(edges[i], baseBuffer, -1*scale, 0, i)
pixSel = 0
for row in range(4):
edge = edges[((pixSel * 13402141) >> 1) & 3]
pixSel = pixSel+1
span = edgesW
blit(major_image, edge, (1 + row * span) * scale, 0, 0)
blit(major_image, edge, (majorW - edgesH) * scale, (1 + row * span) * scale, 1)
blit(major_image, edge, (majorW - 1 - span - row * span) * scale, (majorH - edgesH) * scale, 2)
blit(major_image, edge, 0, (majorH - 1 - edgesW - row * span) * scale, 3)
return major_image
tk.Tk().withdraw()
if len(sys.argv) > 1:
paths = sys.argv
del paths[0]
else:
paths = filedialog.askopenfilenames()
for path in paths:
print("Loading file {}".format(path))
img = cv2.imread(path)
if img is None:
print("Unable to load file {}".format(path))
exit()
print("Generating texture")
thick_img = createMajorTexture(img)
path_split = path.split('.')
thick_path = path_split[0] + "_thick." + path_split[1]
cv2.imwrite(thick_path, thick_img)
print("Successfully created texture {}".format(thick_path))