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) {
|
for (var face in this.faces) {
|
||||||
el.faces[face] = this.faces[face].getSaveCopy(project)
|
el.faces[face] = this.faces[face].getSaveCopy(project)
|
||||||
}
|
}
|
||||||
el.uuid = this.uuid
|
el.type = this.type;
|
||||||
|
el.uuid = this.uuid;
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
roll(axis, steps, origin) {
|
roll(axis, steps, origin) {
|
||||||
|
@ -112,7 +112,7 @@ const TextureGenerator = {
|
|||||||
if (Mesh.selected[0]) {
|
if (Mesh.selected[0]) {
|
||||||
Blockbench.showQuickMessage('message.box_uv_for_meshes', 1600);
|
Blockbench.showQuickMessage('message.box_uv_for_meshes', 1600);
|
||||||
}
|
}
|
||||||
TextureGenerator.generateTemplate(options, makeTexture);
|
TextureGenerator.generateBoxTemplate(options, makeTexture);
|
||||||
} else {
|
} else {
|
||||||
TextureGenerator.generateFaceTemplate(options, makeTexture);
|
TextureGenerator.generateFaceTemplate(options, makeTexture);
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ const TextureGenerator = {
|
|||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
//BoxUV Template
|
//BoxUV Template
|
||||||
generateTemplate(options, cb) {
|
generateBoxTemplate(options, cb) {
|
||||||
var res = options.resolution;
|
var res = options.resolution;
|
||||||
var background_color = options.color;
|
var background_color = options.color;
|
||||||
var texture = options.texture;
|
var texture = options.texture;
|
||||||
@ -627,7 +627,8 @@ const TextureGenerator = {
|
|||||||
mesh,
|
mesh,
|
||||||
faces: [face],
|
faces: [face],
|
||||||
keys: [0],
|
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 == 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 = 'south';
|
||||||
if (axis == 2 && face_group.normal[2] <= 0) face_group.face_key = 'north';
|
if (axis == 2 && face_group.normal[2] <= 0) face_group.face_key = 'north';
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
face_list.push(...face_groups);
|
face_list.push(...face_groups);
|
||||||
}
|
}
|
||||||
@ -793,6 +796,16 @@ const TextureGenerator = {
|
|||||||
|
|
||||||
if (true) {
|
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) {
|
face_list.sort(function(a,b) {
|
||||||
return b.size - a.size;
|
return b.size - a.size;
|
||||||
})
|
})
|
||||||
@ -812,7 +825,9 @@ const TextureGenerator = {
|
|||||||
w++; h++;
|
w++; h++;
|
||||||
}
|
}
|
||||||
for (var x = 0; x < w; x++) {
|
for (var x = 0; x < w; x++) {
|
||||||
|
if (tpl.matrix && !tpl.matrix[x]) continue;
|
||||||
for (var y = 0; y < h; y++) {
|
for (var y = 0; y < h; y++) {
|
||||||
|
if (tpl.matrix && !tpl.matrix[x][y]) continue;
|
||||||
if (cb(sx+x, sy+y)) return;
|
if (cb(sx+x, sy+y)) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -866,6 +881,51 @@ const TextureGenerator = {
|
|||||||
var ctx = canvas.getContext('2d')
|
var ctx = canvas.getContext('2d')
|
||||||
ctx.imageSmoothingEnabled = false;
|
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) {
|
function drawTemplateRectangle(border_color, color, coords) {
|
||||||
if (typeof background_color === 'string') {
|
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 (!Format.single_texture) {
|
||||||
if (face.texture === undefined || face.texture === null) return false;
|
if (face.texture === undefined || face.texture === null) return false;
|
||||||
texture = face.getTexture()
|
texture = face.getTexture()
|
||||||
@ -942,6 +1031,72 @@ const TextureGenerator = {
|
|||||||
ctx.restore()
|
ctx.restore()
|
||||||
return true;
|
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
|
//Drawing
|
||||||
face_list.forEach(function(ftemp) {
|
face_list.forEach(function(ftemp) {
|
||||||
@ -953,14 +1108,24 @@ const TextureGenerator = {
|
|||||||
}
|
}
|
||||||
var d = TextureGenerator.face_data[ftemp.face_key];
|
var d = TextureGenerator.face_data[ftemp.face_key];
|
||||||
var flip_rotation = false;
|
var flip_rotation = false;
|
||||||
|
|
||||||
|
if (ftemp.cube) {
|
||||||
|
// Cube
|
||||||
if (!ftemp.texture ||
|
if (!ftemp.texture ||
|
||||||
ftemp.mesh ||
|
!drawCubeTexture(ftemp.face, pos)
|
||||||
!drawTexture(ftemp.face, pos)
|
|
||||||
) {
|
) {
|
||||||
drawTemplateRectangle(d.c1, d.c2, pos)
|
drawTemplateRectangle(d.c1, d.c2, pos)
|
||||||
} else if (ftemp.cube) {
|
} else if (ftemp.cube) {
|
||||||
flip_rotation = ftemp.face.rotation % 180 != 0;
|
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 (options.rearrange_uv) {
|
||||||
if (ftemp.cube) {
|
if (ftemp.cube) {
|
||||||
|
Loading…
Reference in New Issue
Block a user