mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-01-30 15:42:42 +08:00
Mask mesh polygons in template generator
Support keeping mesh textures in template generator bbmodel files now export type correctly on cubes
This commit is contained in:
parent
5cf1dd9cde
commit
f9698d37e5
@ -245,7 +245,8 @@ class Cube extends OutlinerElement {
|
||||
for (var face in this.faces) {
|
||||
el.faces[face] = this.faces[face].getSaveCopy(project)
|
||||
}
|
||||
el.uuid = this.uuid
|
||||
el.type = this.type;
|
||||
el.uuid = this.uuid;
|
||||
return el;
|
||||
}
|
||||
roll(axis, steps, origin) {
|
||||
|
@ -112,7 +112,7 @@ const TextureGenerator = {
|
||||
if (Mesh.selected[0]) {
|
||||
Blockbench.showQuickMessage('message.box_uv_for_meshes', 1600);
|
||||
}
|
||||
TextureGenerator.generateTemplate(options, makeTexture);
|
||||
TextureGenerator.generateBoxTemplate(options, makeTexture);
|
||||
} else {
|
||||
TextureGenerator.generateFaceTemplate(options, makeTexture);
|
||||
}
|
||||
@ -149,7 +149,7 @@ const TextureGenerator = {
|
||||
return this;
|
||||
},
|
||||
//BoxUV Template
|
||||
generateTemplate(options, cb) {
|
||||
generateBoxTemplate(options, cb) {
|
||||
var res = options.resolution;
|
||||
var background_color = options.color;
|
||||
var texture = options.texture;
|
||||
@ -627,7 +627,8 @@ const TextureGenerator = {
|
||||
mesh,
|
||||
faces: [face],
|
||||
keys: [0],
|
||||
normal: face.getNormal(true)
|
||||
normal: face.getNormal(true),
|
||||
texture: face.getTexture()
|
||||
})
|
||||
}
|
||||
|
||||
@ -776,6 +777,8 @@ const TextureGenerator = {
|
||||
if (axis == 1 && face_group.normal[1] <= 0) face_group.face_key = 'down';
|
||||
if (axis == 2 && face_group.normal[2] >= 0) face_group.face_key = 'south';
|
||||
if (axis == 2 && face_group.normal[2] <= 0) face_group.face_key = 'north';
|
||||
|
||||
|
||||
})
|
||||
face_list.push(...face_groups);
|
||||
}
|
||||
@ -793,6 +796,16 @@ const TextureGenerator = {
|
||||
|
||||
if (true) {
|
||||
|
||||
face_list.forEach(face_group => {
|
||||
if (!face_group.mesh) return;
|
||||
let face_uvs = face_group.faces.map((face) => {
|
||||
return face.getSortedVertices().map(vkey => {
|
||||
return face_group.vertex_uvs[vkey];
|
||||
})
|
||||
});
|
||||
face_group.matrix = getPolygonOccupationMatrix(face_uvs, face_group.width, face_group.height);
|
||||
})
|
||||
|
||||
face_list.sort(function(a,b) {
|
||||
return b.size - a.size;
|
||||
})
|
||||
@ -812,7 +825,9 @@ const TextureGenerator = {
|
||||
w++; h++;
|
||||
}
|
||||
for (var x = 0; x < w; x++) {
|
||||
if (tpl.matrix && !tpl.matrix[x]) continue;
|
||||
for (var y = 0; y < h; y++) {
|
||||
if (tpl.matrix && !tpl.matrix[x][y]) continue;
|
||||
if (cb(sx+x, sy+y)) return;
|
||||
}
|
||||
}
|
||||
@ -866,6 +881,51 @@ const TextureGenerator = {
|
||||
var ctx = canvas.getContext('2d')
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
|
||||
function getPolygonOccupationMatrix(vertex_uv_faces, width, height) {
|
||||
let matrix = {};
|
||||
function vSub(a, b) {
|
||||
return [a[0]-b[0], a[1]-b[1]];
|
||||
}
|
||||
function getSide(a, b) {
|
||||
let cosine_sign = a[0]*b[1] - a[1]*b[0];
|
||||
if (cosine_sign > 0) return 1;
|
||||
if (cosine_sign < 0) return -1;
|
||||
}
|
||||
function pointInsidePolygon(x, y) {
|
||||
face_uvs:
|
||||
for (let vertex_uvs of vertex_uv_faces) {
|
||||
let previous_side;
|
||||
let i = 0;
|
||||
vertices:
|
||||
for (let a of vertex_uvs) {
|
||||
let b = vertex_uvs[i+1] || vertex_uvs[0];
|
||||
let affine_segment = vSub(b, a);
|
||||
let affine_point = vSub([x, y], a);
|
||||
let side = getSide(affine_segment, affine_point);
|
||||
if (!side) continue face_uvs;
|
||||
if (!previous_side) previous_side = side;
|
||||
if (side !== previous_side) continue face_uvs;
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (let x = 0; x < (0 + width); x++) {
|
||||
for (let y =0; y < (0 + height); y++) {
|
||||
let inside = ( pointInsidePolygon(x+0.00001, y+0.00001)
|
||||
|| pointInsidePolygon(x+0.99999, y+0.00001)
|
||||
|| pointInsidePolygon(x+0.00001, y+0.99999)
|
||||
|| pointInsidePolygon(x+0.99999, y+0.99999));
|
||||
if (inside) {
|
||||
if (!matrix[x]) matrix[x] = {};
|
||||
matrix[x][y] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
||||
function drawTemplateRectangle(border_color, color, coords) {
|
||||
if (typeof background_color === 'string') {
|
||||
@ -889,7 +949,36 @@ const TextureGenerator = {
|
||||
)
|
||||
}
|
||||
}
|
||||
function drawTexture(face, coords) {
|
||||
function drawTemplatePolygons(border_color, color, ftemp, pos) {
|
||||
if (typeof background_color === 'string') {
|
||||
border_color = background_color
|
||||
color = undefined
|
||||
}
|
||||
|
||||
if (border_color) border_color = tinycolor(border_color).toRgb();
|
||||
if (color) color = tinycolor(color).toRgb();
|
||||
|
||||
let R = res_multiple;
|
||||
let matrix = ftemp.matrix;
|
||||
Painter.scanCanvas(ctx, pos.x * R, pos.y * R, pos.w * R, pos.h * R, (x, y) => {
|
||||
x -= pos.x*R;
|
||||
y -= pos.y*R;
|
||||
if (matrix[Math.floor(x / R)] && matrix[Math.floor(x / R)][Math.floor(y / R)]) {
|
||||
if (
|
||||
color &&
|
||||
(matrix[Math.floor((x+1) / R)] && matrix[Math.floor((x+1) / R)][Math.floor(y / R) ]) &&
|
||||
(matrix[Math.floor((x-1) / R)] && matrix[Math.floor((x-1) / R)][Math.floor(y / R) ]) &&
|
||||
(matrix[Math.floor(x / R) ] && matrix[Math.floor(x / R) ][Math.floor((y+1) / R)]) &&
|
||||
(matrix[Math.floor(x / R) ] && matrix[Math.floor(x / R) ][Math.floor((y-1) / R)])
|
||||
) {
|
||||
return [color.r, color.g, color.b, color.a * 255];
|
||||
} else {
|
||||
return [border_color.r, border_color.g, border_color.b, border_color.a * 255];
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
function drawCubeTexture(face, coords) {
|
||||
if (!Format.single_texture) {
|
||||
if (face.texture === undefined || face.texture === null) return false;
|
||||
texture = face.getTexture()
|
||||
@ -942,6 +1031,72 @@ const TextureGenerator = {
|
||||
ctx.restore()
|
||||
return true;
|
||||
}
|
||||
function drawMeshTexture(ftemp, coords) {
|
||||
if (!Format.single_texture) {
|
||||
if (ftemp.faces[0].texture === undefined) return false;
|
||||
texture = ftemp.faces[0].getTexture()
|
||||
} else {
|
||||
texture = Texture.getDefault();
|
||||
}
|
||||
if (!texture || !texture.img) return false;
|
||||
|
||||
/*
|
||||
ctx.save()
|
||||
let a_old = ftemp.faces[0].uv[ftemp.faces[0].vertices[0]];
|
||||
let b_old = ftemp.faces[0].uv[ftemp.faces[0].vertices[1]];
|
||||
let a_new = ftemp.vertex_uvs[ftemp.faces[0].vertices[0]];
|
||||
let b_new = ftemp.vertex_uvs[ftemp.faces[0].vertices[1]];
|
||||
let _old = Math.atan2(
|
||||
b_old[1] - a_old[1],
|
||||
b_old[0] - a_old[0],
|
||||
)
|
||||
let _new = Math.atan2(
|
||||
b_new[1] - a_new[1],
|
||||
b_new[0] - a_new[0],
|
||||
)
|
||||
let rotation_difference = Math.radToDeg(_new - _old);
|
||||
if (Math.abs(((rotation_difference + 540) % 360) - 180) > 15) return false;
|
||||
*/
|
||||
|
||||
ctx.save()
|
||||
let R = res_multiple;
|
||||
let min = [Infinity, Infinity];
|
||||
let max = [0, 0];
|
||||
ftemp.faces.forEach(face => {
|
||||
face.vertices.forEach(vkey => {
|
||||
min[0] = Math.min(min[0], face.uv[vkey][0]);
|
||||
min[1] = Math.min(min[1], face.uv[vkey][1]);
|
||||
max[0] = Math.max(max[0], face.uv[vkey][0]);
|
||||
max[1] = Math.max(max[1], face.uv[vkey][1]);
|
||||
})
|
||||
})
|
||||
|
||||
ctx.beginPath()
|
||||
// Mask
|
||||
for (let x in ftemp.matrix) {
|
||||
x = parseInt(x);
|
||||
for (let y in ftemp.matrix[x]) {
|
||||
y = parseInt(y);
|
||||
ctx.rect((coords.x + x)*R, (coords.y + y)*R, R, R);
|
||||
}
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
|
||||
ctx.drawImage(
|
||||
texture.img,
|
||||
min[0] / Project.texture_width * texture.img.naturalWidth,
|
||||
min[1] / Project.texture_height * texture.img.naturalHeight,
|
||||
Math.ceil((max[0] - min[0]) / Project.texture_width * texture.img.naturalWidth),
|
||||
Math.ceil((max[1] - min[1]) / Project.texture_height * texture.img.naturalHeight),
|
||||
coords.x*R,
|
||||
coords.y*R,
|
||||
coords.w*R,
|
||||
coords.h*R
|
||||
)
|
||||
ctx.restore()
|
||||
return true;
|
||||
}
|
||||
|
||||
//Drawing
|
||||
face_list.forEach(function(ftemp) {
|
||||
@ -953,14 +1108,24 @@ const TextureGenerator = {
|
||||
}
|
||||
var d = TextureGenerator.face_data[ftemp.face_key];
|
||||
var flip_rotation = false;
|
||||
|
||||
if (ftemp.cube) {
|
||||
// Cube
|
||||
if (!ftemp.texture ||
|
||||
ftemp.mesh ||
|
||||
!drawTexture(ftemp.face, pos)
|
||||
!drawCubeTexture(ftemp.face, pos)
|
||||
) {
|
||||
drawTemplateRectangle(d.c1, d.c2, pos)
|
||||
} else if (ftemp.cube) {
|
||||
flip_rotation = ftemp.face.rotation % 180 != 0;
|
||||
}
|
||||
} else if (ftemp.mesh) {
|
||||
// Mesh
|
||||
if (!ftemp.texture ||
|
||||
!drawMeshTexture(ftemp, pos)
|
||||
) {
|
||||
drawTemplatePolygons(d.c1, d.c2, ftemp, pos)
|
||||
}
|
||||
}
|
||||
|
||||
if (options.rearrange_uv) {
|
||||
if (ftemp.cube) {
|
||||
|
Loading…
Reference in New Issue
Block a user