.glb imports now load bundled textures

This commit is contained in:
Lucas Dower 2023-05-07 14:01:56 +01:00
parent e5bc18f99c
commit f3b2a6dcc2
No known key found for this signature in database
GPG Key ID: B3EE6B8499593605
3 changed files with 43 additions and 8 deletions

View File

@ -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', 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}}"', failed_to_parse_line: 'Failed attempt to parse "{{line}}", because "{{error}}"',
gltf_experimental: 'The GLTF importer is experimental and may produce unexpected results', 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: { components: {
input: '3D Model (.obj, .glb)', input: '3D Model (.obj, .glb)',
rotation: 'Rotation', rotation: 'Rotation',

View File

@ -6,6 +6,7 @@ import { LOC } from '../localiser';
import { MaterialMap, MaterialType, Mesh, Tri } from '../mesh'; import { MaterialMap, MaterialType, Mesh, Tri } from '../mesh';
import { StatusHandler } from '../status'; import { StatusHandler } from '../status';
import { UV } from '../util'; import { UV } from '../util';
import { AppError } from '../util/error_util';
import { Vector3 } from '../vector'; import { Vector3 } from '../vector';
import { IImporter } from './base_importer'; import { IImporter } from './base_importer';
@ -14,7 +15,7 @@ export class GltfLoader extends IImporter {
StatusHandler.warning(LOC('import.gltf_experimental')); StatusHandler.warning(LOC('import.gltf_experimental'));
return new Promise<Mesh>((resolve, reject) => { return new Promise<Mesh>((resolve, reject) => {
parse(file, GLTFLoader, { limit: 0 }) parse(file, GLTFLoader, { loadImages: true })
.then((gltf: any) => { .then((gltf: any) => {
resolve(this._handleGLTF(gltf)); resolve(this._handleGLTF(gltf));
}) })
@ -82,12 +83,43 @@ export class GltfLoader extends IImporter {
if (pbr !== undefined) { if (pbr !== undefined) {
const diffuseTexture = pbr.baseColorTexture; const diffuseTexture = pbr.baseColorTexture;
if (diffuseTexture !== undefined) { if (diffuseTexture !== undefined) {
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, { meshMaterials.set(materialName, {
type: MaterialType.solid, type: MaterialType.solid,
colour: RGBAUtil.copy(RGBAColours.WHITE), colour: RGBAUtil.copy(RGBAColours.WHITE),
needsAttention: false, needsAttention: false,
canBeTextured: true, canBeTextured: true,
}); });
}
/*
*/
materialNameToUse = materialName; materialNameToUse = materialName;
materialMade = true; materialMade = true;

View File

@ -1,8 +1,8 @@
import { LOC } from '../../localiser';
import { TImageRawWrap } from '../../texture'; import { TImageRawWrap } from '../../texture';
import { getRandomID } from '../../util'; import { getRandomID } from '../../util';
import { ASSERT } from '../../util/error_util'; import { ASSERT } from '../../util/error_util';
import { UIUtil } from '../../util/ui_util'; import { UIUtil } from '../../util/ui_util';
import { LOC } from '../../localiser';
import { AppIcons } from '../icons'; import { AppIcons } from '../icons';
import { ConfigComponent } from './config'; import { ConfigComponent } from './config';
import { ToolbarItemComponent } from './toolbar_item'; import { ToolbarItemComponent } from './toolbar_item';
@ -60,6 +60,8 @@ export class ImageComponent extends ConfigComponent<Promise<TImageRawWrap>, HTML
const fileReader = new FileReader(); const fileReader = new FileReader();
fileReader.onload = function () { fileReader.onload = function () {
if (typeof fileReader.result === 'string') { 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 }); res({ filetype: file.type === 'image/jpeg' ? 'jpg' : 'png', raw: fileReader.result });
} else { } else {
rej(Error()); rej(Error());