I want to export my glb files with a TextureData saved in an MeshStandardMaterial in the map attribute but when I try to export the files I get an error:
I create the texture in this way:
var size = 32;
var len = size * size
var textureSize = len * 3;
var textureData = new Uint8Array(textureSize);
var color = new THREE.Color();
for (var i=0; i<len; i++){
color.setHex(i);
textureData[i*3] = Math.floor(color.r * 255);
textureData[i*3+1] = Math.floor(color.g * 255);
textureData[i*3+2] = Math.floor(color.b * 255);
}
var texture = new THREE.DataTexture( textureData , size, size, THREE.RGBFormat );
Then I assign the texture to material.map
When I use the GLTFExporter I get this error message:
Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
at processImage (GLTFExporter.js:803)
at processTexture (GLTFExporter.js:894)
at processMaterial (GLTFExporter.js:1027)
at processMesh (GLTFExporter.js:1445)
at processNode (GLTFExporter.js:1812)
at processNode (GLTFExporter.js:1860)
at processNode (GLTFExporter.js:1860)
at processScene (GLTFExporter.js:1921)
at processInput (GLTFExporter.js:1974)
at GLTFExporter.parse (GLTFExporter.js:2004)
Iāve quickly hacked in support via ImageData however this requires that the data texture is always in RGBA format. Guess this feature request requires a separate code path in processImage() with no dependencies to canvas.
function createImage(uint8array, w, h){
// we asume that uint8array is always a Uint8Array with size w*h*4;
console.log(uint8array);
var len = uint8array.length / 4;
console.log("len: ", len);
//var image = document.createElement("img");
var header_size = 54;
var width = w;
var height = h;
var image_size = width * height * 4;
var arr = new Uint8Array(header_size + image_size);
var view = new DataView(arr.buffer);
view.setUint16(0, 0x424D, false);
view.setUint32(2, arr.length, true);
view.setUint32(10, header_size, true);
view.setUint32(14, 40, true);
view.setInt32(18, width, true);
view.setInt32(22, height, true);
view.setUint16(26, 1, true);
view.setUint16(28, 32, true);
view.setUint32(30, 0, true);
view.setUint32(34, image_size, true);
view.setInt32(38, 10000, true);
view.setInt32(42, 10000, true);
view.setUint32(46, 0, true);
view.setUint32(50, 0, true);
for (var i=0; i<len; i++) {
var index = header_size + (i*4);
arr[index] = uint8array[i*4];
arr[index+1] = uint8array[i*4+1];
arr[index+2] = uint8array[i*4+2];
}
var buf1 = new Buffer.from(arr.buffer, 'base64');
var image = new Image(width, height);
var blob = new Blob([buf1], { type: "image/bmp" });
var url = window.URL.createObjectURL(blob);
image.src = url;
return image;
}
The problem is that from browser it works but from my nodejs conversion process it complains about createObjectURL method. The error is on GLTFExporter.js library.
In fact my code is working on nodejs but only without using textures.
About Buffer.from() method, it works if you use the appropiate requires in nodejs script.
However, this approach is too restrictive since it only supports RGBA textures. It does not honor the maxTextureSize and forcePowerOfTwoTextures options, too.
@donmccurdy Would the above code would be sufficient for exporting a model using DataTextures to glTF? I donāt think it makes sense to support all possible configurations of data textures. Besides, a data texture has to be generate by the user so maybe missing support for maxTextureSize and forcePowerOfTwoTextures is tolerable?
@Mugen87 I think so, yes. The option for forcePowerOfTwoTextures goes back to Facebook 3D posts requiring it. Since that product has been discontinued, Iām not sure we even need the option now.