Open bnolan opened 10 years ago
@bnolan what version of three.js, can you narrow down when it first broke? Works with at least 0.58.9 and 0.56.0 (version used by voxel-engine 0.20.1)
Tested myself, works on 0.58.10, broken on 0.66.2 (there is a gap between these versions for three.js on NPM, didn't test in between), I suspect this is related to this change:
https://github.com/mrdoob/three.js/wiki/Migration
r59 → r60 Face4 removed. Use 2 Face3 to emulate it.
which also broke https://github.com/maxogden/voxel-mesh/issues/13 .. but minecraft-skin does not explicitly use Face4 (quads). Found this hint on http://solutiondesign.com/webgl-and-three-js-texture-mapping/:
edA-qa mort-ora-y says: December 17, 2013 at 1:45 pm I think it should be noted that the coordinates used for your UV are tightly coupled to the vertex arrangement created by the CubeGeometry. This may be a problem since the Cube could in theory change it’s vertex structure and break your UVs.
I also tried the code with a PlaneGeometry and sure enough it has a different face arrangement, yielding an upside-down texture. I could have figured out that exact arrangement, but to be safe I created a new geometry instead with my explicit ordering of the vertices/faces.
I'd guess CubeGeometry changed from using Face4
(quads) to two Face3
(triangles).. yep, changed in: https://github.com/mrdoob/three.js/commit/44b1b3ab11723d94f9bdbdfd933c1096e0cce30e. Then in three.js r66, CubeGeometry was renamed to BoxGeometry.
I came across this issue as well. Here is my working update to a single function to make it work again:
Skin.prototype.UVMap = function(mesh, face, x, y, w, h, rotateBy) {
if (!rotateBy) rotateBy = 0;
var geo = (mesh.geometry) ? mesh.geometry: mesh;
var uvs1, uvs2, vCount;
if(geo.faceVertexUvs[0][0].length == 3){
//newer versions of Three use triangles for faces
uvs1 = geo.faceVertexUvs[0][face*2];
uvs2 = geo.faceVertexUvs[0][face*2+1];
vCount = 3;
}
else if(geo.faceVertexUvs[0][0].length >=4) {
//compatibility for older versions of Three
uvs1 = geo.faceVertexUvs[0][face];
uvs2 = [{x:0,y:0},{x:0,y:0},{x:0,y:0},{x:0,y:0}];
vCount = 4;
}
else{
//might want to handle exception
}
var tileU = x;
var tileV = y;
var tileUvWidth = 1/64;
var tileUvHeight = 1/32;
var xtopleft, ytopleft, xbotleft, ybotleft, xbotright, ybotright, xtopright, ytopright;
xtopleft = (tileU * tileUvWidth)
ytopleft = 1 - (tileV * tileUvHeight)
xbotleft = (tileU * tileUvWidth)
ybotleft = 1 - (tileV * tileUvHeight + h * tileUvHeight)
xbotright = (tileU * tileUvWidth + w * tileUvWidth)
ybotright = 1 - (tileV * tileUvHeight + h * tileUvHeight)
xtopright = (tileU * tileUvWidth + w * tileUvWidth)
ytopright = 1 - (tileV * tileUvHeight)
uvs1[ (0 + rotateBy) % vCount ].x = xtopleft
uvs1[ (0 + rotateBy) % vCount ].y = ytopleft
uvs1[ (1 + rotateBy) % vCount ].x = uvs2[ (0 + rotateBy) % vCount ].x = xbotleft
uvs1[ (1 + rotateBy) % vCount ].y = uvs2[ (0 + rotateBy) % vCount ].y = ybotleft
uvs2[ (1 + rotateBy) % vCount ].x = xbotright
uvs2[ (1 + rotateBy) % vCount ].y = ybotright
uvs1[ (2 + rotateBy) % vCount ].x = uvs2[ (2 + rotateBy) % vCount ].x = xtopright
uvs1[ (2 + rotateBy) % vCount ].y = uvs2[ (2 + rotateBy) % vCount ].y = ytopright
if(vCount >=4){
uvs1[ (2 + rotateBy) % vCount ].x = xbotright
uvs1[ (2 + rotateBy) % vCount ].y = ybotright
uvs1[ (3 + rotateBy) % vCount ].x = xtopright
uvs1[ (3 + rotateBy) % vCount ].y = ytopright
}
geo.uvsNeedUpdate = true;
}
Untested on older versions of Three
I've just tried this out with a modern version of Three.js and got an error around line 142...
I'm guessing the mesh building code has changed in three.js and it breaks the UVs somehow - but I don't really know what I'm doing so I couldn't work out how to fix it. :( It still works if you disable uv mapping, but then the man obviously looks retarded.