Reputation: 43
Hello i am trying to export a uvmap for a model and i am filling triangles(meshes) with color, it works but i always see grey mesh lines. i tried to draw lines if i draw the lines with different color i can see lines but if i chose same color its always grey Any idea how to accomplish that thanks
const { Scene } = tshirtNodes; // Access Three.js state
const geometry = Scene.children[0].geometry; // Access geometry of the 3D model
const uvAttribute = geometry.attributes.uv; // UV data
const indexAttribute = geometry.index; // Triangle indices
const canvasSize = 10000; // Canvas size
const uvArray = uvAttribute.array; // UV coordinates
const indexArray = indexAttribute.array; // Triangle indices
const renderUVMap = () => {
console.log("render uvmap");
for (let i = 0; i < indexArray.length; i += 3) {
const i1 = indexArray[i] * 2;
const i2 = indexArray[i + 1] * 2;
const i3 = indexArray[i + 2] * 2;
const uv1 = { x: uvArray[i1], y: uvArray[i1 + 1] };
const uv2 = { x: uvArray[i2], y: uvArray[i2 + 1] };
const uv3 = { x: uvArray[i3], y: uvArray[i3 + 1] };
let part = null;
for (const [key, condition] of Object.entries(uvConditions)) {
if (
isWithinCondition(uv1, condition) ||
isWithinCondition(uv2, condition) ||
isWithinCondition(uv3, condition)
) {
part = key;
break; // Stop once the part is determined
}
}
if (!part) continue;
if (partColorType[part] === "single") {
const color = colorsForparts[part];
if (!color) continue;
const [r, g, b] = color.map((c) => Math.floor(c * 255));
ctx.fillStyle = `rgb(${r}, ${g}, ${b})`;
ctx.beginPath();
ctx.moveTo(uv1.x * canvasSize, uv1.y * canvasSize);
ctx.lineTo(uv2.x * canvasSize, uv2.y * canvasSize);
ctx.lineTo(uv3.x * canvasSize, uv3.y * canvasSize);
ctx.closePath();
ctx.fill();
// ctx.strokeStyle = `rgb(${r}, ${g}, ${b})`;
// ctx.beginPath();
// ctx.moveTo(uv1.x * canvasSize, uv1.y * canvasSize);
// ctx.lineTo(uv2.x * canvasSize, uv2.y * canvasSize);
// ctx.lineTo(uv3.x * canvasSize, uv3.y * canvasSize);
// ctx.lineWidth = 0.05;
// ctx.stroke();
}
}
};
At the left side you can see meshes as grey and right side green when i chose different color than the triangles
Upvotes: 2
Views: 65
Reputation: 376
ctx.stroke()
was correct idea but you set ctx.lineWidth = 0.05;
and this is the reason so try to use ctx.fill()
and ctx.stroke()
but with ctx.lineWidth = 1
(default value for this parameter) like:
ctx.lineWidth = 1;
for (let i = 0; i < indexArray.length; i += 3) {
...
if (partColorType[part] === "single") {
const color = colorsForparts[part];
if (!color) continue;
const [r, g, b] = color.map((c) => Math.floor(c * 255));
ctx.fillStyle = `rgb(${r}, ${g}, ${b})`;
ctx.strokeStyle = ctx.fillStyle;
ctx.beginPath();
ctx.moveTo(uv1.x * canvasSize, uv1.y * canvasSize);
ctx.lineTo(uv2.x * canvasSize, uv2.y * canvasSize);
ctx.lineTo(uv3.x * canvasSize, uv3.y * canvasSize);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
}
here is small example with canvas 100x100px:
const uvDots = [
5, 5,
75, 25,
25, 75,
95, 95,
95, 5,
].map(a=>a+(Math.random()*2-1)*3 );
const Index = [
0, 1, 2,
1, 3, 2,
0, 4, 1,
1, 4, 3,
];
function draw(ctx, fill, stroke, lineWidth) {
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, 100, 100);
ctx.fillStyle = "#f00";
ctx.strokeStyle = ctx.fillStyle;
ctx.lineWidth = lineWidth;
for (let i = 0; i < Index.length; i+=3) {
ctx.beginPath();
ctx.moveTo(uvDots[ Index[i ]*2 ], uvDots[ Index[i ]*2+1 ]);
ctx.lineTo(uvDots[ Index[i+1]*2 ], uvDots[ Index[i+1]*2+1 ]);
ctx.lineTo(uvDots[ Index[i+2]*2 ], uvDots[ Index[i+2]*2+1 ]);
ctx.closePath()
if (fill ) {ctx.fill ()}
if (stroke) {ctx.stroke()}
}
}
const getCtxBySelector = s=>document.querySelector(s).getContext('2d');
draw(getCtxBySelector('#canvas1'), true, false, 1)
draw(getCtxBySelector('#canvas2'), false, true, 1)
draw(getCtxBySelector('#canvas3'), true, true, 1)
draw(getCtxBySelector('#canvas4'), true, true, 0.05)
body {
display: grid;
grid-template-columns: repeat(2, auto);
column-gap: 10px;
row-gap: 10px;
width: fit-content;
}
canvas {
width: 300px;
height: 300px;
image-rendering: pixelated;
}
span {
text-align: center;
}
<body>
<span>only fill</span>
<span>only stroke (lineWidth = 1)</span>
<canvas id="canvas1" width="100" height="100"></canvas>
<canvas id="canvas2" width="100" height="100"></canvas>
<span>fill + stroke (lineWidth = 1)</span>
<span>fill + stroke (lineWidth = 0.05)</span>
<canvas id="canvas3" width="100" height="100"></canvas>
<canvas id="canvas4" width="100" height="100"></canvas>
</body>
also you can make this work much faster if you use UV as geometry for mesh and render it with shader which will define how to fill polygons. Also in that case there will be no such problem with lines.
Upvotes: 1