Files
armorpaint/base/Sources/UtilUV.ts
T

186 lines
6.3 KiB
TypeScript
Raw Normal View History

2024-01-17 18:53:31 +01:00
class UtilUV {
static uvmap: Image = null;
static uvmapCached = false;
static trianglemap: Image = null;
static trianglemapCached = false;
static dilatemap: Image = null;
static dilatemapCached = false;
static uvislandmap: Image = null;
static uvislandmapCached = false;
static dilateBytes: ArrayBuffer = null;
static pipeDilate: PipelineState = null;
static cacheUVMap = () => {
if (UtilUV.uvmap != null && (UtilUV.uvmap.width != Config.getTextureResX() || UtilUV.uvmap.height != Config.getTextureResY())) {
UtilUV.uvmap.unload();
UtilUV.uvmap = null;
UtilUV.uvmapCached = false;
}
if (UtilUV.uvmapCached) return;
let resX = Config.getTextureResX();
let resY = Config.getTextureResY();
if (UtilUV.uvmap == null) {
UtilUV.uvmap = Image.createRenderTarget(resX, resY);
}
UtilUV.uvmapCached = true;
let merged = Context.raw.mergedObject;
let mesh = (Context.raw.layerFilter == 0 && merged != null) ?
merged.data.raw : Context.raw.paintObject.data.raw;
let texa = mesh.vertex_arrays[2].values;
let inda = mesh.index_arrays[0].values;
UtilUV.uvmap.g2.begin(true, 0x00000000);
UtilUV.uvmap.g2.color = 0xffcccccc;
let strength = resX > 2048 ? 2.0 : 1.0;
let f = (1 / 32767) * UtilUV.uvmap.width;
for (let i = 0; i < Math.floor(inda.length / 3); ++i) {
let x1 = (texa[inda[i * 3 ] * 2 ]) * f;
let x2 = (texa[inda[i * 3 + 1] * 2 ]) * f;
let x3 = (texa[inda[i * 3 + 2] * 2 ]) * f;
let y1 = (texa[inda[i * 3 ] * 2 + 1]) * f;
let y2 = (texa[inda[i * 3 + 1] * 2 + 1]) * f;
let y3 = (texa[inda[i * 3 + 2] * 2 + 1]) * f;
UtilUV.uvmap.g2.drawLine(x1, y1, x2, y2, strength);
UtilUV.uvmap.g2.drawLine(x2, y2, x3, y3, strength);
UtilUV.uvmap.g2.drawLine(x3, y3, x1, y1, strength);
}
UtilUV.uvmap.g2.end();
}
static cacheTriangleMap = () => {
if (UtilUV.trianglemap != null && (UtilUV.trianglemap.width != Config.getTextureResX() || UtilUV.trianglemap.height != Config.getTextureResY())) {
UtilUV.trianglemap.unload();
UtilUV.trianglemap = null;
UtilUV.trianglemapCached = false;
}
if (UtilUV.trianglemapCached) return;
if (UtilUV.trianglemap == null) {
UtilUV.trianglemap = Image.createRenderTarget(Config.getTextureResX(), Config.getTextureResY());
}
UtilUV.trianglemapCached = true;
let merged = Context.raw.mergedObject != null ? Context.raw.mergedObject.data.raw : Context.raw.paintObject.data.raw;
let mesh = merged;
let texa = mesh.vertex_arrays[2].values;
let inda = mesh.index_arrays[0].values;
UtilUV.trianglemap.g2.begin(true, 0xff000000);
let f = (1 / 32767) * UtilUV.trianglemap.width;
let color = 0xff000001;
for (let i = 0; i < Math.floor(inda.length / 3); ++i) {
if (color == 0xffffffff) color = 0xff000001;
color++;
UtilUV.trianglemap.g2.color = color;
let x1 = (texa[inda[i * 3 ] * 2 ]) * f;
let x2 = (texa[inda[i * 3 + 1] * 2 ]) * f;
let x3 = (texa[inda[i * 3 + 2] * 2 ]) * f;
let y1 = (texa[inda[i * 3 ] * 2 + 1]) * f;
let y2 = (texa[inda[i * 3 + 1] * 2 + 1]) * f;
let y3 = (texa[inda[i * 3 + 2] * 2 + 1]) * f;
UtilUV.trianglemap.g2.fillTriangle(x1, y1, x2, y2, x3, y3);
}
UtilUV.trianglemap.g2.end();
}
static cacheDilateMap = () => {
if (UtilUV.dilatemap != null && (UtilUV.dilatemap.width != Config.getTextureResX() || UtilUV.dilatemap.height != Config.getTextureResY())) {
UtilUV.dilatemap.unload();
UtilUV.dilatemap = null;
UtilUV.dilatemapCached = false;
}
if (UtilUV.dilatemapCached) return;
if (UtilUV.dilatemap == null) {
UtilUV.dilatemap = Image.createRenderTarget(Config.getTextureResX(), Config.getTextureResY(), TextureFormat.R8);
}
if (UtilUV.pipeDilate == null) {
UtilUV.pipeDilate = new PipelineState();
UtilUV.pipeDilate.vertexShader = System.getShader("dilate_map.vert");
UtilUV.pipeDilate.fragmentShader = System.getShader("dilate_map.frag");
let vs = new VertexStructure();
///if (krom_metal || krom_vulkan)
vs.add("tex", VertexData.I16_2X_Normalized);
///else
vs.add("pos", VertexData.I16_4X_Normalized);
vs.add("nor", VertexData.I16_2X_Normalized);
vs.add("tex", VertexData.I16_2X_Normalized);
///end
UtilUV.pipeDilate.inputLayout = [vs];
UtilUV.pipeDilate.depthWrite = false;
UtilUV.pipeDilate.depthMode = CompareMode.Always;
UtilUV.pipeDilate.colorAttachments[0] = TextureFormat.R8;
UtilUV.pipeDilate.compile();
// dilateTexUnpack = UtilUV.pipeDilate.getConstantLocation("texUnpack");
}
let mask = Context.objectMaskUsed() ? Context.raw.layer.getObjectMask() : 0;
if (Context.layerFilterUsed()) mask = Context.raw.layerFilter;
let geom = mask == 0 && Context.raw.mergedObject != null ? Context.raw.mergedObject.data : Context.raw.paintObject.data;
let g4 = UtilUV.dilatemap.g4;
g4.begin();
g4.clear(0x00000000);
g4.setPipeline(UtilUV.pipeDilate);
///if (krom_metal || krom_vulkan)
g4.setVertexBuffer(geom.get([{name: "tex", data: "short2norm"}]));
///else
g4.setVertexBuffer(geom.vertexBuffer);
///end
g4.setIndexBuffer(geom.indexBuffers[0]);
g4.drawIndexedVertices();
g4.end();
UtilUV.dilatemapCached = true;
UtilUV.dilateBytes = null;
}
static cacheUVIslandMap = () => {
UtilUV.cacheDilateMap();
if (UtilUV.dilateBytes == null) {
UtilUV.dilateBytes = UtilUV.dilatemap.getPixels();
}
UtilRender.pickPosNorTex();
let w = 2048; // Config.getTextureResX()
let h = 2048; // Config.getTextureResY()
let x = Math.floor(Context.raw.uvxPicked * w);
let y = Math.floor(Context.raw.uvyPicked * h);
let bytes = new ArrayBuffer(w * h);
let view = new DataView(bytes);
let coords: TCoord[] = [{ x: x, y: y }];
let r = Math.floor(UtilUV.dilatemap.width / w);
let check = (c: TCoord) => {
if (c.x < 0 || c.x >= w || c.y < 0 || c.y >= h) return;
if (view.getUint8(c.y * w + c.x) == 255) return;
let dilateView = new DataView(UtilUV.dilateBytes);
if (dilateView.getUint8(c.y * r * UtilUV.dilatemap.width + c.x * r) == 0) return;
view.setUint8(c.y * w + c.x, 255);
coords.push({ x: c.x + 1, y: c.y });
coords.push({ x: c.x - 1, y: c.y });
coords.push({ x: c.x, y: c.y + 1 });
coords.push({ x: c.x, y: c.y - 1 });
}
while (coords.length > 0) {
check(coords.pop());
}
if (UtilUV.uvislandmap != null) {
UtilUV.uvislandmap.unload();
}
UtilUV.uvislandmap = Image.fromBytes(bytes, w, h, TextureFormat.R8);
UtilUV.uvislandmapCached = true;
}
}
type TCoord = {
x: i32;
y: i32;
}