@archvisioninc/canvas 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -142,26 +142,32 @@ const applyUVSettings = args => {
|
|
|
142
142
|
|
|
143
143
|
// TODO: Future uses should support red, green, blue, and alpha channels with defaults for each
|
|
144
144
|
const combineMetallicRoughnessTextures = (metallicImage, roughnessImage) => {
|
|
145
|
-
const roughnessHeight = roughnessImage
|
|
146
|
-
const roughnessWidth = roughnessImage
|
|
147
|
-
const metallicHeight = metallicImage
|
|
148
|
-
const metallicWidth = metallicImage
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
const roughnessHeight = roughnessImage?.naturalHeight ?? 0;
|
|
146
|
+
const roughnessWidth = roughnessImage?.naturalWidth ?? 0;
|
|
147
|
+
const metallicHeight = metallicImage?.naturalHeight ?? 0;
|
|
148
|
+
const metallicWidth = metallicImage?.naturalWidth ?? 0;
|
|
149
|
+
let roughnessData;
|
|
150
|
+
let metallicData;
|
|
151
|
+
const maxHeight = Math.max(...[roughnessHeight, metallicHeight, 1024]);
|
|
152
|
+
const maxWidth = Math.max(...[roughnessWidth, metallicWidth, 1024]);
|
|
151
153
|
const canvas = document.createElement('canvas');
|
|
152
154
|
const ctx = canvas.getContext('2d');
|
|
153
155
|
canvas.width = maxWidth;
|
|
154
156
|
canvas.height = maxHeight;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
if (roughnessImage) {
|
|
158
|
+
ctx.drawImage(roughnessImage, 0, 0, maxWidth, maxHeight);
|
|
159
|
+
roughnessData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
|
|
160
|
+
}
|
|
161
|
+
if (metallicImage) {
|
|
162
|
+
ctx.drawImage(metallicImage, 0, 0, maxWidth, maxHeight);
|
|
163
|
+
metallicData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
|
|
164
|
+
}
|
|
159
165
|
const combinedImageData = ctx.createImageData(maxWidth, maxHeight);
|
|
160
166
|
const combinedData = combinedImageData.data;
|
|
161
167
|
for (let i = 0; i < combinedData.length; i += 4) {
|
|
162
168
|
combinedData[i] = 255;
|
|
163
|
-
combinedData[i + 1] = roughnessData[i + 1];
|
|
164
|
-
combinedData[i + 2] = metallicData[i + 2];
|
|
169
|
+
combinedData[i + 1] = roughnessData ? roughnessData[i + 1] : 255;
|
|
170
|
+
combinedData[i + 2] = metallicData ? metallicData[i + 2] : 255;
|
|
165
171
|
combinedData[i + 3] = 255;
|
|
166
172
|
}
|
|
167
173
|
ctx.putImageData(combinedImageData, 0, 0);
|
|
@@ -170,22 +176,28 @@ const combineMetallicRoughnessTextures = (metallicImage, roughnessImage) => {
|
|
|
170
176
|
|
|
171
177
|
// eslint-disable-next-line
|
|
172
178
|
const loadImage = async file => {
|
|
173
|
-
return new Promise(
|
|
179
|
+
return new Promise(resolve => {
|
|
174
180
|
const reader = new FileReader();
|
|
175
181
|
reader.onload = event => {
|
|
176
182
|
const img = new Image();
|
|
177
|
-
img.onload = () =>
|
|
178
|
-
|
|
183
|
+
img.onload = () => resolve(img);
|
|
184
|
+
img.onerror = () => {
|
|
185
|
+
resolve(null);
|
|
179
186
|
};
|
|
180
|
-
img.onerror = reject;
|
|
181
187
|
img.src = event.target.result;
|
|
182
188
|
};
|
|
183
|
-
reader.onerror =
|
|
189
|
+
reader.onerror = () => {
|
|
190
|
+
resolve(null);
|
|
191
|
+
};
|
|
184
192
|
reader.readAsDataURL(file);
|
|
185
193
|
});
|
|
186
194
|
};
|
|
187
|
-
const textureToImage =
|
|
188
|
-
return new Promise(
|
|
195
|
+
const textureToImage = texture => {
|
|
196
|
+
return new Promise(resolve => {
|
|
197
|
+
if (!texture.readPixels()) {
|
|
198
|
+
resolve(null);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
189
201
|
texture.readPixels().then(pixels => {
|
|
190
202
|
const canvas = document.createElement('canvas');
|
|
191
203
|
const ctx = canvas.getContext('2d');
|
|
@@ -202,11 +214,12 @@ const textureToImage = (texture, textureName) => {
|
|
|
202
214
|
img.onload = () => {
|
|
203
215
|
resolve(img);
|
|
204
216
|
};
|
|
205
|
-
img.onerror =
|
|
206
|
-
|
|
207
|
-
reject(event);
|
|
217
|
+
img.onerror = () => {
|
|
218
|
+
resolve(null);
|
|
208
219
|
};
|
|
209
220
|
img.src = canvas.toDataURL();
|
|
221
|
+
}).catch(() => {
|
|
222
|
+
resolve(null);
|
|
210
223
|
});
|
|
211
224
|
});
|
|
212
225
|
};
|
|
@@ -255,6 +268,9 @@ export const updateMaterial = inboundData => {
|
|
|
255
268
|
metallicTexture,
|
|
256
269
|
roughness,
|
|
257
270
|
roughnessTexture,
|
|
271
|
+
ambientColor,
|
|
272
|
+
ambientTextureStrength,
|
|
273
|
+
ambientTexture,
|
|
258
274
|
microSurfaceTexture,
|
|
259
275
|
emissiveColor,
|
|
260
276
|
emissiveIntensity,
|
|
@@ -363,10 +379,11 @@ export const updateMaterial = inboundData => {
|
|
|
363
379
|
let currentTexture = material.metallicTexture;
|
|
364
380
|
if (!currentTexture) {
|
|
365
381
|
material.metallicTexture = newTexture();
|
|
382
|
+
material.metallicTexture.name = `${material.name} (Metallic-Roughness)`;
|
|
366
383
|
currentTexture = material.metallicTexture;
|
|
367
384
|
}
|
|
368
385
|
const metallicBlob = dataUrlToBlob(texture.url);
|
|
369
|
-
Promise.all([loadImage(metallicBlob), textureToImage(currentTexture
|
|
386
|
+
Promise.all([loadImage(metallicBlob), textureToImage(currentTexture)]).then(data => {
|
|
370
387
|
const [metallicImage, currentImage] = data;
|
|
371
388
|
const combinedTexture = combineMetallicRoughnessTextures(metallicImage, currentImage);
|
|
372
389
|
currentTexture.updateURL(combinedTexture);
|
|
@@ -375,7 +392,14 @@ export const updateMaterial = inboundData => {
|
|
|
375
392
|
texture: material.metallicTexture,
|
|
376
393
|
material
|
|
377
394
|
});
|
|
378
|
-
|
|
395
|
+
newMetaDataEntry('materials', buildMaterialsArray());
|
|
396
|
+
newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
|
|
397
|
+
}).catch(err => {
|
|
398
|
+
console.log(`Error updating the roughness texture of material: ${material.name}`);
|
|
399
|
+
console.log({
|
|
400
|
+
err
|
|
401
|
+
});
|
|
402
|
+
});
|
|
379
403
|
}
|
|
380
404
|
|
|
381
405
|
// Roughness
|
|
@@ -394,10 +418,11 @@ export const updateMaterial = inboundData => {
|
|
|
394
418
|
let currentTexture = material.metallicTexture;
|
|
395
419
|
if (!currentTexture) {
|
|
396
420
|
material.metallicTexture = newTexture();
|
|
421
|
+
material.metallicTexture.name = `${material.name} (Metallic-Roughness)`;
|
|
397
422
|
currentTexture = material.metallicTexture;
|
|
398
423
|
}
|
|
399
424
|
const roughnessBlob = dataUrlToBlob(texture.url);
|
|
400
|
-
Promise.all([loadImage(roughnessBlob), textureToImage(currentTexture
|
|
425
|
+
Promise.all([loadImage(roughnessBlob), textureToImage(currentTexture)]).then(data => {
|
|
401
426
|
const [roughnessImage, metallicImage] = data;
|
|
402
427
|
const combinedTexture = combineMetallicRoughnessTextures(metallicImage, roughnessImage);
|
|
403
428
|
currentTexture.updateURL(combinedTexture);
|
|
@@ -406,7 +431,26 @@ export const updateMaterial = inboundData => {
|
|
|
406
431
|
texture: material.metallicTexture,
|
|
407
432
|
material
|
|
408
433
|
});
|
|
409
|
-
|
|
434
|
+
newMetaDataEntry('materials', buildMaterialsArray());
|
|
435
|
+
newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
|
|
436
|
+
}).catch(err => {
|
|
437
|
+
console.log(`Error updating the roughness texture of material: ${material.name}`);
|
|
438
|
+
console.log({
|
|
439
|
+
err
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Ambient
|
|
445
|
+
if (ambientColor) material.ambientColor = newColor(emissiveColor);
|
|
446
|
+
if (ambientTextureStrength !== undefined) material.ambientTextureStrength = ambientTextureStrength;
|
|
447
|
+
if (!_.isEmpty(ambientTexture?.src || ambientTexture?.url)) {
|
|
448
|
+
material.ambientTexture = newTexture(ambientTexture?.src || ambientTexture?.url);
|
|
449
|
+
material.ambientTexture.name = ambientTexture.name;
|
|
450
|
+
applyUVSettings({
|
|
451
|
+
texture: material.ambientTexture,
|
|
452
|
+
material
|
|
453
|
+
});
|
|
410
454
|
}
|
|
411
455
|
|
|
412
456
|
// Emissive
|
package/package.json
CHANGED
|
@@ -179,13 +179,16 @@ const applyUVSettings = args => {
|
|
|
179
179
|
|
|
180
180
|
// TODO: Future uses should support red, green, blue, and alpha channels with defaults for each
|
|
181
181
|
const combineMetallicRoughnessTextures = (metallicImage, roughnessImage) => {
|
|
182
|
-
const roughnessHeight = roughnessImage
|
|
183
|
-
const roughnessWidth = roughnessImage
|
|
184
|
-
const metallicHeight = metallicImage
|
|
185
|
-
const metallicWidth = metallicImage
|
|
182
|
+
const roughnessHeight = roughnessImage?.naturalHeight ?? 0;
|
|
183
|
+
const roughnessWidth = roughnessImage?.naturalWidth ?? 0;
|
|
184
|
+
const metallicHeight = metallicImage?.naturalHeight ?? 0;
|
|
185
|
+
const metallicWidth = metallicImage?.naturalWidth ?? 0;
|
|
186
186
|
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
let roughnessData;
|
|
188
|
+
let metallicData;
|
|
189
|
+
|
|
190
|
+
const maxHeight = Math.max(...[ roughnessHeight, metallicHeight, 1024 ]);
|
|
191
|
+
const maxWidth = Math.max(...[ roughnessWidth, metallicWidth, 1024 ]);
|
|
189
192
|
|
|
190
193
|
const canvas = document.createElement('canvas');
|
|
191
194
|
|
|
@@ -194,19 +197,23 @@ const combineMetallicRoughnessTextures = (metallicImage, roughnessImage) => {
|
|
|
194
197
|
canvas.width = maxWidth;
|
|
195
198
|
canvas.height = maxHeight;
|
|
196
199
|
|
|
197
|
-
|
|
198
|
-
|
|
200
|
+
if (roughnessImage) {
|
|
201
|
+
ctx.drawImage(roughnessImage, 0, 0, maxWidth, maxHeight);
|
|
202
|
+
roughnessData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
|
|
203
|
+
}
|
|
199
204
|
|
|
200
|
-
|
|
201
|
-
|
|
205
|
+
if (metallicImage) {
|
|
206
|
+
ctx.drawImage(metallicImage, 0, 0, maxWidth, maxHeight);
|
|
207
|
+
metallicData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
|
|
208
|
+
}
|
|
202
209
|
|
|
203
210
|
const combinedImageData = ctx.createImageData(maxWidth, maxHeight);
|
|
204
211
|
const combinedData = combinedImageData.data;
|
|
205
212
|
|
|
206
213
|
for (let i = 0; i < combinedData.length; i += 4) {
|
|
207
214
|
combinedData[i] = 255;
|
|
208
|
-
combinedData[i + 1] = roughnessData[i + 1];
|
|
209
|
-
combinedData[i + 2] = metallicData[i + 2];
|
|
215
|
+
combinedData[i + 1] = roughnessData ? roughnessData[i + 1] : 255;
|
|
216
|
+
combinedData[i + 2] = metallicData ? metallicData[i + 2] : 255;
|
|
210
217
|
combinedData[i + 3] = 255;
|
|
211
218
|
}
|
|
212
219
|
|
|
@@ -218,23 +225,29 @@ const combineMetallicRoughnessTextures = (metallicImage, roughnessImage) => {
|
|
|
218
225
|
|
|
219
226
|
// eslint-disable-next-line
|
|
220
227
|
const loadImage = async file => {
|
|
221
|
-
return new Promise(
|
|
228
|
+
return new Promise(resolve => {
|
|
222
229
|
const reader = new FileReader();
|
|
223
230
|
reader.onload = event => {
|
|
224
231
|
const img = new Image();
|
|
225
|
-
img.onload = () =>
|
|
226
|
-
|
|
232
|
+
img.onload = () => resolve(img);
|
|
233
|
+
img.onerror = () => {
|
|
234
|
+
resolve(null);
|
|
227
235
|
};
|
|
228
|
-
img.onerror = reject;
|
|
229
236
|
img.src = event.target.result;
|
|
230
237
|
};
|
|
231
|
-
reader.onerror =
|
|
238
|
+
reader.onerror = () => {
|
|
239
|
+
resolve(null);
|
|
240
|
+
};
|
|
232
241
|
reader.readAsDataURL(file);
|
|
233
242
|
});
|
|
234
243
|
};
|
|
235
244
|
|
|
236
|
-
const textureToImage =
|
|
237
|
-
return new Promise(
|
|
245
|
+
const textureToImage = texture => {
|
|
246
|
+
return new Promise(resolve => {
|
|
247
|
+
if (!texture.readPixels()) {
|
|
248
|
+
resolve(null);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
238
251
|
texture.readPixels()
|
|
239
252
|
.then(pixels => {
|
|
240
253
|
const canvas = document.createElement('canvas');
|
|
@@ -254,13 +267,15 @@ const textureToImage = (texture, textureName) => {
|
|
|
254
267
|
resolve(img);
|
|
255
268
|
};
|
|
256
269
|
|
|
257
|
-
img.onerror =
|
|
258
|
-
|
|
259
|
-
reject(event);
|
|
270
|
+
img.onerror = () => {
|
|
271
|
+
resolve(null);
|
|
260
272
|
};
|
|
261
273
|
|
|
262
274
|
|
|
263
275
|
img.src = canvas.toDataURL();
|
|
276
|
+
})
|
|
277
|
+
.catch(() => {
|
|
278
|
+
resolve(null);
|
|
264
279
|
});
|
|
265
280
|
|
|
266
281
|
});
|
|
@@ -308,6 +323,9 @@ export const updateMaterial = inboundData => {
|
|
|
308
323
|
metallicTexture,
|
|
309
324
|
roughness,
|
|
310
325
|
roughnessTexture,
|
|
326
|
+
ambientColor,
|
|
327
|
+
ambientTextureStrength,
|
|
328
|
+
ambientTexture,
|
|
311
329
|
microSurfaceTexture,
|
|
312
330
|
emissiveColor,
|
|
313
331
|
emissiveIntensity,
|
|
@@ -412,12 +430,16 @@ export const updateMaterial = inboundData => {
|
|
|
412
430
|
let currentTexture = material.metallicTexture;
|
|
413
431
|
if (!currentTexture) {
|
|
414
432
|
material.metallicTexture = newTexture();
|
|
433
|
+
material.metallicTexture.name = `${material.name} (Metallic-Roughness)`;
|
|
415
434
|
currentTexture = material.metallicTexture;
|
|
416
435
|
}
|
|
417
436
|
|
|
418
437
|
const metallicBlob = dataUrlToBlob(texture.url);
|
|
419
438
|
|
|
420
|
-
Promise.all([
|
|
439
|
+
Promise.all([
|
|
440
|
+
loadImage(metallicBlob),
|
|
441
|
+
textureToImage(currentTexture),
|
|
442
|
+
])
|
|
421
443
|
.then(data => {
|
|
422
444
|
const [ metallicImage, currentImage ] = data;
|
|
423
445
|
const combinedTexture = combineMetallicRoughnessTextures(metallicImage, currentImage);
|
|
@@ -425,8 +447,13 @@ export const updateMaterial = inboundData => {
|
|
|
425
447
|
|
|
426
448
|
texture.dispose();
|
|
427
449
|
applyUVSettings({ texture: material.metallicTexture, material });
|
|
450
|
+
newMetaDataEntry('materials', buildMaterialsArray());
|
|
451
|
+
newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
|
|
428
452
|
})
|
|
429
|
-
|
|
453
|
+
.catch(err => {
|
|
454
|
+
console.log(`Error updating the roughness texture of material: ${material.name}`);
|
|
455
|
+
console.log({ err });
|
|
456
|
+
});
|
|
430
457
|
}
|
|
431
458
|
|
|
432
459
|
// Roughness
|
|
@@ -444,12 +471,13 @@ export const updateMaterial = inboundData => {
|
|
|
444
471
|
let currentTexture = material.metallicTexture;
|
|
445
472
|
if (!currentTexture) {
|
|
446
473
|
material.metallicTexture = newTexture();
|
|
474
|
+
material.metallicTexture.name = `${material.name} (Metallic-Roughness)`;
|
|
447
475
|
currentTexture = material.metallicTexture;
|
|
448
476
|
}
|
|
449
477
|
|
|
450
478
|
const roughnessBlob = dataUrlToBlob(texture.url);
|
|
451
479
|
|
|
452
|
-
Promise.all([ loadImage(roughnessBlob), textureToImage(currentTexture
|
|
480
|
+
Promise.all([ loadImage(roughnessBlob), textureToImage(currentTexture) ])
|
|
453
481
|
.then(data => {
|
|
454
482
|
const [ roughnessImage, metallicImage ] = data;
|
|
455
483
|
const combinedTexture = combineMetallicRoughnessTextures(metallicImage, roughnessImage);
|
|
@@ -457,8 +485,24 @@ export const updateMaterial = inboundData => {
|
|
|
457
485
|
|
|
458
486
|
texture.dispose();
|
|
459
487
|
applyUVSettings({ texture: material.metallicTexture, material });
|
|
488
|
+
newMetaDataEntry('materials', buildMaterialsArray());
|
|
489
|
+
newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
|
|
460
490
|
})
|
|
461
|
-
.catch(
|
|
491
|
+
.catch(err => {
|
|
492
|
+
console.log(`Error updating the roughness texture of material: ${material.name}`);
|
|
493
|
+
console.log({ err });
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Ambient
|
|
499
|
+
if (ambientColor) material.ambientColor = newColor(emissiveColor);
|
|
500
|
+
if (ambientTextureStrength !== undefined) material.ambientTextureStrength = ambientTextureStrength;
|
|
501
|
+
if (!_.isEmpty(ambientTexture?.src || ambientTexture?.url)) {
|
|
502
|
+
material.ambientTexture = newTexture(ambientTexture?.src || ambientTexture?.url);
|
|
503
|
+
material.ambientTexture.name = ambientTexture.name;
|
|
504
|
+
|
|
505
|
+
applyUVSettings({ texture: material.ambientTexture, material });
|
|
462
506
|
|
|
463
507
|
}
|
|
464
508
|
|
package/src/scenes/App/App.js
CHANGED
|
@@ -143,7 +143,10 @@ const App = () => {
|
|
|
143
143
|
const file = e.currentTarget.files[0];
|
|
144
144
|
const reader = new FileReader();
|
|
145
145
|
reader.readAsDataURL(file);
|
|
146
|
-
reader.onload = () => onImageLoad({
|
|
146
|
+
reader.onload = () => onImageLoad({
|
|
147
|
+
name: file.name,
|
|
148
|
+
src: reader.result,
|
|
149
|
+
});
|
|
147
150
|
};
|
|
148
151
|
|
|
149
152
|
useEffect(() => {
|
|
@@ -207,7 +210,11 @@ const App = () => {
|
|
|
207
210
|
Import material
|
|
208
211
|
</Button>
|
|
209
212
|
|
|
210
|
-
<input
|
|
213
|
+
<input
|
|
214
|
+
type={'file'}
|
|
215
|
+
onChange={handleUpload}
|
|
216
|
+
accept={'image/*'}
|
|
217
|
+
/>
|
|
211
218
|
|
|
212
219
|
<Button
|
|
213
220
|
theme={theme}
|