From f3b2a6dcc2d22826e46f397740e575a40836de1b Mon Sep 17 00:00:00 2001 From: Lucas Dower Date: Sun, 7 May 2023 14:01:56 +0100 Subject: [PATCH] .glb imports now load bundled textures --- loc/en_GB.ts | 1 + src/importers/gltf_loader.ts | 46 ++++++++++++++++++++++++++++++------ src/ui/components/image.ts | 4 +++- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/loc/en_GB.ts b/loc/en_GB.ts index 89f8996..9877fc6 100644 --- a/loc/en_GB.ts +++ b/loc/en_GB.ts @@ -36,6 +36,7 @@ export const en_GB = { missing_normals: 'Some vertices do not have their normals defined, this may cause voxels to be aligned incorrectly', failed_to_parse_line: 'Failed attempt to parse "{{line}}", because "{{error}}"', gltf_experimental: 'The GLTF importer is experimental and may produce unexpected results', + unsupported_image_type: 'Cannot read \'{{file_name}}\', unsupported file type \'{{file_type}}\'', components: { input: '3D Model (.obj, .glb)', rotation: 'Rotation', diff --git a/src/importers/gltf_loader.ts b/src/importers/gltf_loader.ts index f6684f3..9a16b2d 100644 --- a/src/importers/gltf_loader.ts +++ b/src/importers/gltf_loader.ts @@ -6,6 +6,7 @@ import { LOC } from '../localiser'; import { MaterialMap, MaterialType, Mesh, Tri } from '../mesh'; import { StatusHandler } from '../status'; import { UV } from '../util'; +import { AppError } from '../util/error_util'; import { Vector3 } from '../vector'; import { IImporter } from './base_importer'; @@ -14,7 +15,7 @@ export class GltfLoader extends IImporter { StatusHandler.warning(LOC('import.gltf_experimental')); return new Promise((resolve, reject) => { - parse(file, GLTFLoader, { limit: 0 }) + parse(file, GLTFLoader, { loadImages: true }) .then((gltf: any) => { resolve(this._handleGLTF(gltf)); }) @@ -82,12 +83,43 @@ export class GltfLoader extends IImporter { if (pbr !== undefined) { const diffuseTexture = pbr.baseColorTexture; if (diffuseTexture !== undefined) { - meshMaterials.set(materialName, { - type: MaterialType.solid, - colour: RGBAUtil.copy(RGBAColours.WHITE), - needsAttention: false, - canBeTextured: true, - }); + const imageData: Uint8Array = diffuseTexture.texture.source.bufferView.data; + const mimeType: string = diffuseTexture.texture.source.mimeType; + + try { + if (mimeType !== 'image/png' && mimeType !== 'image/jpeg') { + StatusHandler.warning(LOC('import.unsupported_image_type', { file_name: diffuseTexture.texture.source.id, file_type: mimeType })); + throw new Error('Unsupported image type'); + } + + const base64 = btoa( + imageData.reduce((data, byte) => data + String.fromCharCode(byte), ''), + ); + + meshMaterials.set(materialName, { + type: MaterialType.textured, + diffuse: { + filetype: mimeType === 'image/jpeg' ? 'jpg' : 'png', + raw: (mimeType === 'image/jpeg' ? 'data:image/jpeg;base64,' : 'data:image/png;base64,') + base64, + }, + extension: 'clamp', + interpolation: 'linear', + needsAttention: false, + transparency: { type: 'None' }, + }); + } catch { + meshMaterials.set(materialName, { + type: MaterialType.solid, + colour: RGBAUtil.copy(RGBAColours.WHITE), + needsAttention: false, + canBeTextured: true, + }); + } + + + /* + + */ materialNameToUse = materialName; materialMade = true; diff --git a/src/ui/components/image.ts b/src/ui/components/image.ts index 7a0d6e0..b277ad2 100644 --- a/src/ui/components/image.ts +++ b/src/ui/components/image.ts @@ -1,8 +1,8 @@ +import { LOC } from '../../localiser'; import { TImageRawWrap } from '../../texture'; import { getRandomID } from '../../util'; import { ASSERT } from '../../util/error_util'; import { UIUtil } from '../../util/ui_util'; -import { LOC } from '../../localiser'; import { AppIcons } from '../icons'; import { ConfigComponent } from './config'; import { ToolbarItemComponent } from './toolbar_item'; @@ -60,6 +60,8 @@ export class ImageComponent extends ConfigComponent, HTML const fileReader = new FileReader(); fileReader.onload = function () { if (typeof fileReader.result === 'string') { + // convert image file to base64 string + console.log('base64 png', fileReader.result); res({ filetype: file.type === 'image/jpeg' ? 'jpg' : 'png', raw: fileReader.result }); } else { rej(Error());