import { Reporter } from '../../reporter/reporter.js';
import { WrappedTexture } from '../wrapped_texture.js';
import { WrappedMaterial } from '../material/wrapped_material.js';
import { checkPropTypes } from '../../lib.js';
import { BuildableComponent } from '../component/buildable_component.js';
import { Component } from '../../component/component.js';
import { Geometry } from '../geometry/geometry.js';
import { MaterialSet } from '../material/material_set.js';
import { Project } from '../../project.js';
import { GLTF } from './gltf.js';
import { ObjectSpaceNormalMap, Vector2, DoubleSide, sRGBEncoding, TextureLoader, RepeatWrapping } from '../../../node_modules/three/build/three.module.js';
//NodeMaterials
import { NodeMaterialLoader, NodeMaterialLoaderUtils } from '../../../node_modules/three/examples/jsm/loaders/NodeMaterialLoader.js';
import * as Nodes from '../../../node_modules/three/examples/jsm/nodes/Nodes.js';
import { buildNodeMaterial } from '../../utilities/nodeMaterialBuilder.js';
/** ProductBuilder Mesh */
class WrappedMesh extends BuildableComponent {
/**
* @param {Reporter} reporter
* @param {Object} settings
* @param {UUID} [settings.id]
* @param {string} [settings.name]
* @param {string} settings.meshName
* @param {GLTF} settings.gltf
* @param {MaterialSet} [settings.materialVariantGroup]
* @param {WrappedMaterial} settings.defaultMaterial
* @param {Geometry} [ settings.geometry ] // deze laten vervallen?
* @param {Number} [ settings.tilingMultiplier ]
* @param {WrappedTexture} [ settings.aoMap ]
* @param {Number} [ settings.aoMapIntensity ]
* @param {WrappedTexture} [ settings.normalMap ]
* @param {Object} [ settings.normalMapTiling ]
* @param {Number} [ settings.normalMapIntensity ]
* "materialConfigurable": true,
"castShadow": true,
"receiveShadow": true
*/
constructor(reporter, settings) {
super(
reporter,
settings
);
checkPropTypes(
settings,
{
meshName: 'string',
gltf: GLTF,
defaultMaterial: WrappedMaterial,
},
{
materialVariantGroup: MaterialSet,
tilingMultiplier: 'number',
aoMap: WrappedTexture,
aoMapIntensity: 'number',
normalMap: WrappedTexture,
normalMapIntensity: 'number'
//geometry: Geometry,
}
);
// fucking typescript
if (!Object.getOwnPropertyDescriptor(this,'materialVariantGroup')) {
/** @type {MaterialSet} */
this.materialVariantGroup = settings.materialVariantGroup;
}
this._tilingMultiplier = settings.tilingMultiplier
this._aoMap = settings.aoMap
this._aoMapIntensity = settings.aoMapIntensity
this._normalMap = settings.normalMap ///-> dit is dubbel
this._normalMapTiling = settings.normalMapTiling
this._normalMapScale = settings.normalMapIntensity ///-> dit is dubbel
this._meshObject = null;
}
static _exportName = {
singular: 'mesh',
plural: 'meshes'
};
/**
* @param {WrappedMaterial} material
*/
async buildMeshMaterial( material ){
//get the product normal map
const normalMap = this._normalMap.content.main.medium
normalMap.encoding = 3000
//normalMap.flipY = true; //deze is (nog) niet nodig
normalMap.wrapS = RepeatWrapping;
normalMap.wrapT = RepeatWrapping;
normalMap.repeat = this._normalMapTiling
const normalMapTiling = this._normalMapTiling
//create texture node with the product normal map
// const normalNode = normalMap
// ? new Nodes.TextureNode( normalMap )
// : undefined
const normalNode = new Nodes.TextureNode( normalMap )
//create the node material
const nodeMaterial = buildNodeMaterial(
material,
normalNode,
normalMapTiling
)
//copy the id from the currentmaterial
nodeMaterial.userData = { PB: { origin: material.userData.PB.origin } }
//add the environment map
nodeMaterial.envMap = material.envMap
this._meshObject.mesh.material = nodeMaterial
this._meshObject.mesh.material.normalScale = { x:2, y:2 }
this._meshObject.mesh.material.needsUpdate = true;
return nodeMaterial
}
/**
* @param {ComponentPart} part
* @param {LoadingQuality} quality
* @param {Object<string,Component>} dependencies
*/
async _build(part, quality, dependencies) {
this._status[ part ][ quality ].setState( 'loading');
switch (part) {
case 'UI':
if (this._settings.thumbnail) {
this._setContent('UI', quality, this._settings.thumbnail.content.main[quality]);
}
else {
this._setContent('UI', quality, Project.defaultImages.missing.cloneNode(true));
}
break;
case 'main':
//console.log( dependencies )
if ( this._settings.materialVariantGroup && ! this._settings.materialVariantGroup.has( this._settings.defaultMaterial)){
// console.log( settings.materialVariantGroup )
throw new Error( `Can not construct ${this.label} because def mat ${this._settings.defaultMaterial.name || this._settings.defaultMaterial.id} is not in its matVarGrp ${settings.materialVariantGroup.name || settings.materialVariantGroup.id}` )
}
this._meshObject = dependencies.gltf.content.main[ quality ].gltf[ this._settings.meshName ];
this._meshObject.mesh.material = dependencies.defaultMaterial.content.main[ quality ];
//tiling multiplier
if ( this.tilingMultiplier ){
for ( let mapType of [ 'bumpMap', 'emissiveMap', 'map', 'specularMap', 'roughnessMap', 'metalnessMap', 'normalMap' ])
{
if ( this._meshObject.mesh.material[ mapType ] )
{
this._meshObject.mesh.material = this._meshObject.mesh.material.clone();
this._meshObject.mesh.material[ mapType ] = this._meshObject.mesh.material[ mapType ].clone();
this._meshObject.mesh.material[ mapType ].repeat.x *= this._settings.tilingMultiplier;
this._meshObject.mesh.material[ mapType ].repeat.y *= this._settings.tilingMultiplier;
this._meshObject.mesh.material[ mapType ].needsUpdate = true;
}
}
}
//product maps
if( this._aoMap ){
//console.log( this._aoMap)
this._meshObject.mesh.material.aoMap = this._aoMap.content.main[ quality ];
this._meshObject.mesh.material.aoMap.needsUpdate = true;
}
if( this._aoMapIntensity ){
console.log( this._aoMapIntensity )
this._meshObject.mesh.material.aoMapIntensity = this._aoMapIntensity
this._meshObject.mesh.material.aoMap.needsUpdate = true;
}
if( this._normalMap ){
this.buildMeshMaterial( this._meshObject.mesh.material )
}
this._meshObject.mesh.castShadow = true;
this._meshObject.mesh.receiveShadow = true;
// const mesh = new Mesh(
// dependencies.geometry.content.main[ quality ],
// dependencies.defaultMaterial.content.main[ quality ]
// );
this._setContent( 'main', quality, this._meshObject );
break;
default:
this._setContent(part, quality, null);
break;
}
return this;
}
}
export { WrappedMesh };