import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { ModalController } from '@ionic/angular'; import { IJeelizFaceFilter } from 'vendors/jeelizFaceFilter/typescript/JeelizFaceFilterInterfaces'; import { SocialSharing } from '@ionic-native/social-sharing/ngx'; declare var JEELIZFACEFILTER: IJeelizFaceFilter; declare var JeelizThreeHelper: any; declare var JeelizResizer: any; declare var THREE: any; @Component({ selector: 'app-ar-fan-cam', templateUrl: './ar-fan-cam.page.html', styleUrls: ['./ar-fan-cam.page.scss'], }) export class ArFanCamPage implements OnInit { @ViewChild('sourceCanvasElement') sourceCanvasElement: ElementRef; THREECAMERA = null; width: number; height: number; tempImg = ''; glassesFramesMeshLoaded: boolean = false; glassesLensMeshLoaded: boolean = false; constructor( private modalController: ModalController, private socialSharing: SocialSharing ) { } back() { JEELIZFACEFILTER.destroy(); this.modalController.dismiss(); } // AR Face detection and drawing detect_callback(faceIndex, isDetected) { if (isDetected) { console.log('INFO in detect_callback(): DETECTED'); } else { console.log('INFO in detect_callback(): LOST'); } } // build the 3D. called once when Jeeliz Face Filter is OK init_threeScene(spec) { const threeStuffs = JeelizThreeHelper.init(spec, this.detect_callback); // improve WebGLRenderer settings: threeStuffs.renderer.toneMapping = THREE.ACESFilmicToneMapping; threeStuffs.renderer.outputEncoding = THREE.sRGBEncoding; // CREATE THE GLASSES AND ADD THEM const r = this.JeelizThreeGlassesCreator({ envMapURL: "assets/ar-accessories/envMap.jpg", frameMeshURL: "assets/ar-accessories/models3D/glassesFramesBranchesBent.json", lensesMeshURL: "assets/ar-accessories/models3D/glassesLenses.json", occluderURL: "assets/ar-accessories/models3D/face.json" }); // vertical offset: const dy = 0.07; // create and add the occluder: r.occluder.rotation.set(0.3, 0, 0); r.occluder.position.set(0, 0.03 + dy,-0.04); r.occluder.scale.multiplyScalar(0.0084); threeStuffs.faceObject.add(r.occluder); // create and add the glasses mesh: const threeGlasses = r.glasses; //threeGlasses.rotation.set(-0.15,0,0); / /X neg -> rotate branches down threeGlasses.position.set(0, dy, 0.4); threeGlasses.scale.multiplyScalar(0.006); threeStuffs.faceObject.add(threeGlasses); // add a debug cube: /* const sc = 0.1; const debugCube = new THREE.Mesh(new THREE.BoxGeometry(sc,sc,sc), new THREE.MeshNormalMaterial()); threeStuffs.faceObject.add(debugCube); //*/ // CREATE THE CAMERA: this.THREECAMERA = JeelizThreeHelper.create_camera(); } JeelizThreeGlassesCreator(spec) { const threeGlasses = new THREE.Object3D(); // envMap texture: const textureEquirec = new THREE.TextureLoader().load( spec.envMapURL ); textureEquirec.mapping = THREE.EquirectangularReflectionMapping; textureEquirec.magFilter = THREE.LinearFilter; textureEquirec.minFilter = THREE.LinearMipMapLinearFilter; // glasses frames: new THREE.BufferGeometryLoader().load(spec.frameMeshURL, function(glassesFramesGeometry){ glassesFramesGeometry.computeVertexNormals(); // custom material with fading at the end of the branches: const us = THREE.ShaderLib.standard.uniforms; const uniforms = { roughness: {value: 0}, metalness: {value: 0.05}, reflectivity: {value: 1}, envMap: {value: textureEquirec}, envMapIntensity: {value: 1}, diffuse: {value: new THREE.Color().setHex(0xffffff)}, uBranchFading: {value: new THREE.Vector2(-90, 60)} // first value: position (lower -> to the back), second: transition brutality }; // tweak vertex shader to give the Z of the current point: let vertexShaderSource = "varying float vPosZ;\n" + THREE.ShaderLib.standard.vertexShader; vertexShaderSource = vertexShaderSource.replace('#include ', 'vPosZ = position.z;'); // tweak fragment shader to apply transparency at the end of the branches: let fragmentShaderSource = "uniform vec2 uBranchFading;\n varying float vPosZ;\n" + THREE.ShaderLib.standard.fragmentShader; const GLSLcomputeAlpha = 'gl_FragColor.a = smoothstep(uBranchFading.x - uBranchFading.y*0.5, uBranchFading.x + uBranchFading.y*0.5, vPosZ);' fragmentShaderSource = fragmentShaderSource.replace('#include ', GLSLcomputeAlpha); const mat = new THREE.ShaderMaterial({ vertexShader: vertexShaderSource, fragmentShader: fragmentShaderSource, uniforms: uniforms, flatShading: false, transparent: true, extensions: { // fix for https://github.com/jeeliz/jeelizFaceFilter/issues/154 //derivatives: true, //shaderTextureLOD: true } }); mat.envMap = textureEquirec; const glassesFramesMesh = new THREE.Mesh(glassesFramesGeometry, mat); threeGlasses.add(glassesFramesMesh); this.glassesFramesMeshLoaded = true; // window.debugMatFrames = mat; // to debug the material il the JS console }); // glasses lenses: new THREE.BufferGeometryLoader().load(spec.lensesMeshURL, function(glassesLensesGeometry){ glassesLensesGeometry.computeVertexNormals(); const mat = new THREE.MeshBasicMaterial({ envMap: textureEquirec, opacity: 0.7, color: new THREE.Color().setHex(0x2233aa), transparent: true, fog: false }); const glassesLensesMesh = new THREE.Mesh(glassesLensesGeometry, mat); threeGlasses.add(glassesLensesMesh); this.glassesLensMeshLoaded = true; // window.debugMatLens = mat; // to debug the material il the JS console }); const occluderMesh = JeelizThreeHelper.create_threejsOccluder(spec.occluderURL); return { glasses: threeGlasses, occluder: occluderMesh }; } main(){ JeelizResizer.size_canvas({ canvasId: 'source-canvas', isApplyCSS: true, callback: (isError, bestVideoSettings) => { this.init_faceFilter(bestVideoSettings); } }) } init_faceFilter(videoSettings){ JEELIZFACEFILTER.init({ followZRot: true, canvasId: 'source-canvas', NNCPath: 'assets/ar-accessories/neuralNets/', // root of NN_DEFAULT.json file maxFacesDetected: 1, videoSettings: { ...videoSettings, idealWidth: window.innerWidth, idealHeight: window.innerHeight, maxWidth: window.innerWidth, maxHeight: window.innerHeight, }, callbackReady: (errCode, spec) => { if (errCode){ console.log('AN ERROR HAPPENS. ERR =', errCode); return; } console.log('INFO: JEELIZFACEFILTER IS READY'); this.init_threeScene(spec); }, // called at each render iteration (drawing loop): callbackTrack: (detectState) => { JeelizThreeHelper.render(detectState, this.THREECAMERA); } }); //end JEELIZFACEFILTER.init call } // End AR Face detection and drawing async capture() { const dataURI = this.sourceCanvasElement.nativeElement.toDataURL('image/jpeg'); this.tempImg = dataURI; } ngOnInit() { this.width = window.innerWidth; this.height = window.innerHeight; this.main(); } approveImage() { this.modalController.dismiss({ imageData: this.tempImg }); } shareVia(media: 'WhastApp' | 'Instagram' | 'Facebook' | 'others') { switch(media) { case 'WhastApp': this.socialSharing.shareViaWhatsApp('#SaddaPunjab, Download Punjab kings to checkout new filters', this.tempImg, ''); break; case 'Instagram': this.socialSharing.shareViaInstagram('#SaddaPunjab, Download Punjab kings to checkout new filters', this.tempImg); break; case 'Facebook': this.socialSharing.shareViaFacebook('#SaddaPunjab, Download Punjab kings to checkout new filters', this.tempImg, ''); break; case 'others': this.socialSharing.share('#SaddaPunjab, Download Punjab kings to checkout new filters', '', this.tempImg, ''); break; default: break; } } }