Hello
I have a create a mesh with textures in Node backend using three.js.
And While exporting it using GLTFExporter but I faced this issues.
error: TypeError: Cannot read properties of undefined (reading 'width') at processImage (\controllers\/GLTFExporter.js:732:2
Without texture, I can export it to gltf model.
How can we solve this issue?
Any solutions are welcome! Thank you.
GLTFExporter
does not fully work in a node environment out-of-the-box since the module depends on web APIs. For texture support, you have to implement fallbacks for stuff like canvas and Blob to make things work.
Thanks @Mugen87
Actually, I used three.js on backend and I could export a cube as gltf with gltf exporter.
This is my current code.
import * as THREE from 'three';
import { GLTFExporter } from './GLTFExporter';
import fs from 'fs';
import { JSDOM } from 'jsdom';
import { Blob, FileReader } from 'vblob';
import { async } from 'regenerator-runtime';
const gl = require('gl')(1200, 800, { preserveDrawingBuffer: true }); //headless-gl
// Create a DOM
const { window } = new JSDOM();
global.document = window.document;
let request = require('request');
export async function GenerateGLB(props) {
let frontMaterial, backMaterial;
const card = {
width: 4,
height: 6,
thick: 0.06
};
var glbPath;
// init scene
let scene = new THREE.Scene();
scene.background = new THREE.Color(0x123456);
// init camera
let camera = new THREE.PerspectiveCamera(45, 1200 / 800, 0.1, 10000);
camera.position.set(-1, 1, 10);
camera.lookAt(scene.position);
scene.add(camera);
// init renderer
let renderer = new THREE.WebGLRenderer({ context: gl });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
const textureLoader = new THREE.TextureLoader();
var base64str = base64_encode("download/4.jpg");
const frontImage = textureLoader.load(base64str);
frontMaterial = new THREE.MeshBasicMaterial({
map: frontImage,
side: THREE.DoubleSide
});
let frontPlane = new THREE.Mesh(new THREE.PlaneBufferGeometry(card.width, card.height), frontMaterial);
frontPlane.overdraw = true;
frontPlane.position.set(0, 0, card.thick / 2.0 + 0.001);
scene.add(frontPlane);
const backImage = textureLoader.load(props.backImageUrl);
backMaterial = new THREE.MeshBasicMaterial({
map: backImage,
side: THREE.DoubleSide
});
backMaterial.needsUpdate = true;
let backPlane = new THREE.Mesh(new THREE.PlaneGeometry(card.width, card.height), backMaterial);
backPlane.overdraw = true;
backPlane.position.set(0, 0, -card.thick / 2.0 - 0.001);
scene.add(backPlane);
const geometry = new THREE.BoxBufferGeometry(card.width, card.height, card.thick);
const material = new THREE.MeshBasicMaterial({ color: 0xddff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
glbPath = await exportGLTF(scene);
return glbPath;
}
function download(uri, filename, callback) {
request.head(uri, function (err, res, body) {
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
});
}
function base64_encode(file) {
var bitmap = fs.readFileSync(file);
return new Buffer(bitmap).toString('base64');
}
const exportGLTF = async (input) => {
const gltfExporter = new GLTFExporter();
const options = {
trs: false,
onlyVisible: false,
trunteDrawRange: true,
binary: false,
forcePowerOfTwoTextures: false,
maxTextureSize: 1024 || Infinity
};
return new Promise((resolve, reject) => {
gltfExporter.parse(
input,
function (result) {
if (result instanceof ArrayBuffer) {
console.log('ArrayBuffer')
} else {
const output = JSON.stringify(result, null, 2);
const nowDate = new Date().getTime();
var path = 'download/' + nowDate + '.gltf';
fs.writeFile(path, output, (error) => {
if (error) {
console.log('An error has occurred ', error);
reject(error)
}
console.log('Data written successfully to disk', path);
resolve(path)
// return path;
});
}
},
function (error) {
console.log('An error happened during parsing', error);
},
options
);
})
};
Without frontPlan and backPlan, I could export the model as gltf successfully.
But when I exporty frontplan and backplan, it occurred undefined width
of the texture.
Actually, even though, I added texture, but the image properites is undefined now.
That’s weird…
1 Like