MaterialXWeb 1.39.5
Utilities for using MaterialX Packages with Web clients
Loading...
Searching...
No Matches
AmbientCGLoader Class Reference

Public Member Functions

 constructor ()
 Class to load materials from the AmbientCG site.
 loadMaterialsFromCache ()
 setDebugging (debug=true)
 getMaterialNames (key='assetId')
 writeMaterialList (materialList, filename)
 buildDownloadAttribute (imageFormat='PNG', imageResolution='1')
 splitDownloadAttribute (downloadAttribute)
 getDownloadedMaterialInformation ()
 clearDownloadMaterial ()
 writeDownloadedMaterialToFile (path='')
async downloadMaterialAsset (assetId, imageFormat='PNG', imageResolution='1', downloadAttributeKey='downloadAttribute', downloadLinkKey='downloadLink')
 findMaterial (assetId, key='assetId')
 loadMaterialsList (fileName)
async downloadMaterialsList ()
 getDataBase ()
async downloadAssetDatabase ()
 writeDatabaseToFile (filename)
 readDatabaseFromFile (filename)
 validateMaterialXDocument (doc)
 addComment (doc, commentString)
 getMaterialXString (doc)

Detailed Description

Definition at line 10 of file JsAmbientCGLoader.js.

Member Function Documentation

◆ addComment()

AmbientCGLoader::addComment ( doc,
commentString )

Add a comment to the MaterialX document.

Parameters
{Object}doc - The MaterialX document to add the comment to.
{string}commentString - The comment string to add.

Definition at line 446 of file JsAmbientCGLoader.js.

446 {
452 const comment = doc.addChildOfCategory('comment');
453 comment.setDocString(commentString);
454 }

◆ buildDownloadAttribute()

AmbientCGLoader::buildDownloadAttribute ( imageFormat = 'PNG',
imageResolution = '1' )

Build the download attribute string for a given image format and resolution.

Parameters
{string}imageFormat - The image format to download.
{string}imageResolution - The image resolution to download.
Returns
{string} The download attribute string.

Definition at line 80 of file JsAmbientCGLoader.js.

80 {
87 return `${imageResolution}K-${imageFormat}`;
88 }

◆ clearDownloadMaterial()

AmbientCGLoader::clearDownloadMaterial ( )

Clear any cached current material asset.

Definition at line 111 of file JsAmbientCGLoader.js.

111 {
115 if (this.downloadMaterial) {
116 this.downloadMaterial = null;
117 }
118 this.downloadMaterialFileName = '';
119 }

◆ constructor()

AmbientCGLoader::constructor ( )

Class to load materials from the AmbientCG site.

The class can convert the materials to MaterialX format for given target shading models.

Parameters
{Object}mxModule - The MaterialX module. Required.
{Object}mxStdlib - The MaterialX standard library. Optional.

Definition at line 17 of file JsAmbientCGLoader.js.

17 {
18 if (AmbientCGLoader.instance) {
19 return AmbientCGLoader.instance;
20 }
21
22 this.logger = console;
23 this.database = {};
24 this.materials = null;
25 this.materialNames = [];
26 this.csvMaterials = null;
27 this.downloadMaterial = null;
28 this.downloadMaterialFileName = '';
29
30 // Cache the instance
31 AmbientCGLoader.instance = this;
32 }

◆ downloadAssetDatabase()

async AmbientCGLoader::downloadAssetDatabase ( )

Download the asset database for materials from the ambientCG site.

Returns
{Object} The downloaded database.

Definition at line 306 of file JsAmbientCGLoader.js.

306 {
311 this.database = {};
312
313 haveDatabase = false;
314 const MATERIALS_DATABASE_FILE = 'ambientcg_database.json';
315 if (fs.existsSync(MATERIALS_DATABASE_FILE)) {
316 try {
317 const data = fs.readFileSync(MATERIALS_DATABASE_FILE, 'utf8');
318 this.database = JSON.parse(data);
319 this.logger.info(`Loaded AmbientCG database from file: ${MATERIALS_DATABASE_FILE}`);
320 haveDatabase = true;
321 } catch (e) {
322 this.logger.warn(`Failed to load AmbientCG database from file: ${e.message}`);
323 }
324 }
325
326 if (!haveDatabase) {
327
328 const limit = 500
329 //https://ambientcg.com/api/v2/full_json?type=material
330 const headers = { Accept: 'application/json' };
331 let url = new URL('https://ambientcg.com/api/v2/full_json');
332 url.searchParams.append('method', 'PBRPhotogrammetry');
333 url.searchParams.append('type', 'Material');
334 url.searchParams.append('sort', 'Alphabet');
335 url.searchParams.append('limit', limit);
336 url.searchParams.append('offset', 0);
337 url.searchParams.append('include', 'tagData,previewData')
338
339 let numberOfResults = -1;
340 let offset = 0
341
342 //let data_list = []
343 let asset_list = []
344 while (numberOfResults === -1 || offset < numberOfResults) {
345 this.logger.info(`Downloading asset database from: ${url.toString()}`);
346
347 try {
348 const response = await fetch(url, { headers });
349 if (response.status === 200) {
350 const data = await response.json();
351 this.logger.info(`Downloaded data at offset ${offset}. ${data.foundAssets.length} assets found.`);
352 //data_list.push(data);
353
354 // Only keep desired fiels: displayCategory, previewImage, tags and assetId from each entry
355 let reduced_assets = data.foundAssets.map(asset => {
356 return {
357 assetId: asset.assetId,
358 displayCategory: asset.displayCategory,
359 previewImage: asset.previewImage,
360 tags: asset.tags
361 }
362 });
363 asset_list = asset_list.concat(reduced_assets);
364
365 if (numberOfResults === -1) {
366 numberOfResults = data.numberOfResults;
367 }
368 // Update offset for next page
369 if (!data.nextPageHttp)
370 {
371 break;
372 }
373 offset = offset + limit;
374
375 url.searchParams.set('offset', offset);
376 } else {
377 this.logger.error(`Status: ${response.status}, ${response.data}`);
378 }
379 }
380 catch (error) {
381 this.logger.error(`Error downloading asset database: ${error}`);
382 }
383 }
384
385 this.database = asset_list;
386
387 // Pull out the preview image link from database and put it
388 // into the materials.
389 }
390
391 return this.database;
392 }

◆ downloadMaterialAsset()

async AmbientCGLoader::downloadMaterialAsset ( assetId,
imageFormat = 'PNG',
imageResolution = '1',
downloadAttributeKey = 'downloadAttribute',
downloadLinkKey = 'downloadLink' )

Download a material with a given id and format + resolution for images.

Parameters
{string}assetId - The string id of the material.
{string}imageFormat - The image format to download. Default is PNG.
{string}imageResolution - The image resolution to download. Default is 1.
{string}downloadAttributeKey - The download attribute key. Default is 'downloadAttribute'.
{string}downloadLinkKey - The download link key. Default is 'downloadLink'.
Returns
{string} File name of downloaded content.

Definition at line 137 of file JsAmbientCGLoader.js.

137 {
148
149 const items = this.findMaterial(assetId);
150 const target = this.buildDownloadAttribute(imageFormat, imageResolution);
151 let url = '';
152 let downloadAttribute = '';
153
154 items.forEach(item => {
155 downloadAttribute = item[downloadAttributeKey];
156 if (downloadAttribute === target) {
157 url = item[downloadLinkKey];
158 this.logger.info(`Found Asset: ${assetId}. Download Attribute: ${downloadAttribute} -> ${url}`);
159 }
160 });
161
162 if (!url) {
163 this.logger.error(`No download link found for asset: ${assetId}, attribute: ${target}`);
164 return '';
165 }
166
167 this.downloadMaterialFileName = url.split('file=')[1];
168
169 try {
170 const response = await fetch(url);
171 if (!response.ok) {
172 throw new Error(`HTTP error! Status: ${response.status}`);
173 }
174
175 // Get the response as an ArrayBuffer
176 const arrayBuffer = await response.arrayBuffer();
177
178 // Convert ArrayBuffer to Buffer
179 this.downloadMaterial = Buffer.from(arrayBuffer);
180 this.logger.info(`Material file downloaded: ${this.downloadMaterialFileName}`);
181
182 } catch (error) {
183 this.downloadMaterialFileName = '';
184 this.logger.error(`Error occurred while downloading the file: ${error}`);
185 }
186
187 return this.downloadMaterialFileName;
188 }
buildDownloadAttribute(imageFormat='PNG', imageResolution='1')
findMaterial(assetId, key='assetId')

◆ downloadMaterialsList()

async AmbientCGLoader::downloadMaterialsList ( )

Download the list of materials from the ambientCG site.

Returns
{Array} Materials list.

Definition at line 214 of file JsAmbientCGLoader.js.

214 {
219 let haveMaterials = false;
220 const MATERIALS_CACHE_FILE = 'ambientcg_materials.json';
221 // 1. Try to load from cache file
222 if (fs.existsSync(MATERIALS_CACHE_FILE)) {
223 try {
224 const data = fs.readFileSync(MATERIALS_CACHE_FILE, 'utf8');
225 this.materials = JSON.parse(data);
226 this.logger.info(`Loaded AmbientCG materials from cache: ${MATERIALS_CACHE_FILE}`);
227 haveMaterials = true;
228 } catch (e) {
229 this.logger.warn(`Failed to load AmbientCG materials cache: ${e.message}`);
230 }
231 }
232
233 // 2. If not in cache, fetch from network
234 if (!haveMaterials)
235 {
236 const headers = { Accept: 'application/csv' };
237 const url = new URL('https://ambientCG.com/api/v2/downloads_csv');
238 url.searchParams.append('method', 'PBRPhotogrammetry');
239 url.searchParams.append('type', 'Material');
240 url.searchParams.append('sort', 'Alphabet');
241
242 this.logger.info('Downloading materials CSV list from network...');
243 try {
244 const response = await fetch(url, { headers });
245 if (response.status === 200) {
246 const csvContent = await response.text();
247 this.csvMaterials = csvContent;
248 this.materials = parse(csvContent, { columns: true });
249 this.logger.info('Downloaded CSV material list as JSON.');
250 } else {
251 this.materials = null;
252 this.logger.warning(`Failed to fetch the CSV material content. HTTP status code: ${response.status}`);
253 }
254 } catch (error) {
255 this.materials = null;
256 this.logger.error(`Error downloading materials list: ${error}`);
257 }
258
259 // Read database list from file.
260 this.readDatabaseFromFile('ambientcg_database.json');
261 const have_database = this.database && Object.keys(this.database).length > 0;
262 if (have_database) {
263 for (let material of this.materials) {
264 const assetId = material.assetId;
265 const databaseEntry = this.database.find(entry => entry.assetId === assetId);
266 if (databaseEntry) {
267 // Get "256-PNG" from previewImage (object, not Map)
268 let preview = '';
269 if (databaseEntry.previewImage && typeof databaseEntry.previewImage === 'object') {
270 preview = databaseEntry.previewImage['256-PNG'] || '';
271 }
272 material.displayCategory = databaseEntry.displayCategory;
273 material.previewImage = preview;
274 material.tags = databaseEntry.tags;
275 }
276 else {
277 this.logger.warn('No database entry found for assetId:', assetId);
278 }
279
280 }
281 }
282
283 // Save to cache file after fetching
284 try {
285 fs.writeFileSync(MATERIALS_CACHE_FILE, JSON.stringify(this.materials, null, 2));
286 this.logger.info(`Saved AmbientCG materials to cache: ${MATERIALS_CACHE_FILE}`);
287 } catch (e) {
288 this.logger.warn(`Failed to write AmbientCG materials cache: ${e.message}`);
289 }
290 }
291
292 //console.log('>>> WRITE MATERIALS TO FILE:', this.materials.length);
293 //this.writeMaterialList(this.materials, 'ambientcg_materials.json');
294
295 return this.materials;
296 }
readDatabaseFromFile(filename)

◆ findMaterial()

AmbientCGLoader::findMaterial ( assetId,
key = 'assetId' )

Get the list of materials matching a material identifier.

Parameters
{string}assetId - Material string identifier.
{string}key - The key to lookup asset identifiers. Default is 'assetId'.
Returns
{Array} List of materials, or empty array if not found.

Definition at line 190 of file JsAmbientCGLoader.js.

190 {
197 if (this.materials) {
198 return this.materials.filter(item => item[key] === assetId);
199 }
200 return [];
201 }

◆ getDataBase()

AmbientCGLoader::getDataBase ( )

Get asset database.

Returns
{Object} Asset database.

Definition at line 298 of file JsAmbientCGLoader.js.

298 {
303 return this.database;
304 }

◆ getDownloadedMaterialInformation()

AmbientCGLoader::getDownloadedMaterialInformation ( )

Get the current downloaded material information.

Returns
{Object} The downloaded material information.

Definition at line 100 of file JsAmbientCGLoader.js.

100 {
105 return {
106 filename: this.downloadMaterialFileName,
107 content: this.downloadMaterial
108 };
109 }

◆ getMaterialNames()

AmbientCGLoader::getMaterialNames ( key = 'assetId')

Get the list of material names.

Parameters
{string}key - The key to use for the material name. Default is 'assetId'.
Returns
{Array} The list of material names.

Definition at line 55 of file JsAmbientCGLoader.js.

55 {
61 this.materialNames = [];
62 const uniqueNames = new Set();
63 if (this.materials) {
64 this.materials.forEach(item => uniqueNames.add(item[key]));
65 }
66 this.materialNames = Array.from(uniqueNames).sort();
67 return this.materialNames;
68 }

◆ getMaterialXString()

AmbientCGLoader::getMaterialXString ( doc)

Convert the MaterialX document to a string.

Parameters
{Object}doc - The MaterialX document to convert.
Returns
{string} The MaterialX document as a string.

Definition at line 456 of file JsAmbientCGLoader.js.

456 {
462 if (!this.mx) {
463 this.logger.error('MaterialX module is required');
464 return;
465 }
466
467 const writeOptions = this.mx.XmlWriteOptions();
468 writeOptions.writeXIncludeEnable = false;
469 writeOptions.elementPredicate = this.skipLibraryElement;
470 return this.mx.writeToXmlString(doc, writeOptions);
471 }

◆ loadMaterialsFromCache()

AmbientCGLoader::loadMaterialsFromCache ( )

Definition at line 34 of file JsAmbientCGLoader.js.

34 {
35 const MATERIALS_CACHE_FILE = 'ambientcg_materials.json';
36 if (fs.existsSync(MATERIALS_CACHE_FILE)) {
37 try {
38 const data = fs.readFileSync(MATERIALS_CACHE_FILE, 'utf8');
39 this.materials = JSON.parse(data);
40 this.logger.info(`Loaded AmbientCG materials from cache: ${MATERIALS_CACHE_FILE}`);
41 } catch (e) {
42 this.logger.warn(`Failed to load AmbientCG materials cache: ${e.message}`);
43 }
44 }
45 }

◆ loadMaterialsList()

AmbientCGLoader::loadMaterialsList ( fileName)

Load in the list of downloadable materials from file.

Parameters
{string}fileName - Name of JSON containing list.
Returns
{Array} Materials list.

Definition at line 203 of file JsAmbientCGLoader.js.

203 {
209 this.materials = JSON.parse(fs.readFileSync(fileName, 'utf8'));
210 this.logger.info(`Loaded materials list from: ${fileName}`);
211 return this.materials;
212 }

◆ readDatabaseFromFile()

AmbientCGLoader::readDatabaseFromFile ( filename)

Read the database file.

Parameters
{string}filename - The filename to read the JSON file from.
Returns
{Object} The database object, or null if there was an error.

Definition at line 410 of file JsAmbientCGLoader.js.

410 {
416 try {
417 const data = fs.readFileSync(filename, 'utf8');
418 this.database = JSON.parse(data);
419 return this.database;
420 } catch (e) {
421 this.logger.error(`Failed to read database from file: ${e.message}`);
422 return null;
423 }
424 }

◆ setDebugging()

AmbientCGLoader::setDebugging ( debug = true)

Set the debugging level for the logger.

Parameters
{boolean}debug - True to set the logger to debug level, otherwise False.

Definition at line 47 of file JsAmbientCGLoader.js.

47 {
52 this.logger.level = debug ? 'debug' : 'info';
53 }

◆ splitDownloadAttribute()

AmbientCGLoader::splitDownloadAttribute ( downloadAttribute)

Split the download attribute into image format and resolution.

Parameters
{string}downloadAttribute - The download attribute string.
Returns
{Array} A tuple of (imageFormat, imageResolution).
Note
The download attribute is in the format: '1K-PNG'.

Definition at line 90 of file JsAmbientCGLoader.js.

90 {
97 const parts = downloadAttribute.split('-');
98 }

◆ validateMaterialXDocument()

AmbientCGLoader::validateMaterialXDocument ( doc)

Validate the MaterialX document.

Parameters
{Object}doc - The MaterialX document to validate.
Returns
{Array} A tuple of (valid, errors) where valid is True if the document is valid, and errors is a list of errors if the document is invalid.

Definition at line 426 of file JsAmbientCGLoader.js.

426 {
432 if (!this.mx) {
433 this.logger.error('MaterialX module is required');
434 return [false, ''];
435 }
436
437 if (!doc) {
438 this.logger.warning('MaterialX document is required');
439 return [false, ''];
440 }
441
442 const valid = doc.validate();
443 return [valid, valid ? '' : 'Validation failed'];
444 }

◆ writeDatabaseToFile()

AmbientCGLoader::writeDatabaseToFile ( filename)

Write the database file.

Parameters
{string}filename - The filename to write the JSON file to.
Returns
{boolean} True if the file was written successfully, otherwise False.

Definition at line 394 of file JsAmbientCGLoader.js.

394 {
400 if (!this.database) {
401 this.logger.info('No database to write');
402 return false;
403 }
404
405 this.logger.info(`Writing database to file: ${filename}`);
406 fs.writeFileSync(filename, JSON.stringify(this.database, null, 4));
407 return true;
408 }

◆ writeDownloadedMaterialToFile()

AmbientCGLoader::writeDownloadedMaterialToFile ( path = '')

Write the currently downloaded file to file.

Parameters
{string}path - The output path for the material. Default is empty.

Definition at line 121 of file JsAmbientCGLoader.js.

121 {
126 const haveDownload = this.downloadMaterialFileName && this.downloadMaterial;
127 if (!haveDownload) {
128 this.logger.warning('No current material downloaded');
129 return;
130 }
131
132 const filename = `${path}/${this.downloadMaterialFileName}`;
133 fs.writeFileSync(filename, this.downloadMaterial);
134 this.logger.info(`Saved downloaded material to: ${filename}`);
135 }

◆ writeMaterialList()

AmbientCGLoader::writeMaterialList ( materialList,
filename )

Write the material list in JSON format to a file.

Parameters
{Array}materialList - The list of materials to write.
{string}filename - The file path to write the list to.

Definition at line 70 of file JsAmbientCGLoader.js.

70 {
76 this.logger.info(`Writing material list to file: ${filename}`);
77 fs.writeFileSync(filename, JSON.stringify(materialList, null, 4));
78 }

The documentation for this class was generated from the following file: