From f2a76bccbd2693ebdc4b6be7af62dcffc0a0a5f7 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Tue, 5 Mar 2024 23:36:00 -0300 Subject: [PATCH 1/5] add bevel and second material support --- src/components/svg-extruder.js | 141 +++++++++++++++++++++++++-------- 1 file changed, 110 insertions(+), 31 deletions(-) diff --git a/src/components/svg-extruder.js b/src/components/svg-extruder.js index cba92ac7c..443f2aa87 100644 --- a/src/components/svg-extruder.js +++ b/src/components/svg-extruder.js @@ -1,81 +1,160 @@ /* global AFRAME */ -var { SVGLoader } = require('../lib/SVGLoader.js'); +const { SVGLoader } = require('../lib/SVGLoader.js'); AFRAME.registerComponent('svg-extruder', { schema: { svgString: { type: 'string' }, - depth: { type: 'number', default: 4 } + depth: { type: 'number', default: 4 }, + bevelEnabled: { type: 'boolean', default: true }, + bevelThickness: { type: 'number', default: 1 }, + bevelSize: { type: 'number', default: 1 }, + bevelOffset: { type: 'number', default: 1 }, + bevelSegments: { type: 'number', default: 1 }, + topElement: { type: 'boolean', default: true }, + color: { type: 'color', default: 'white'}, + src: { type: 'string', default: '#grass-texture'}, + bevelColor: { type: 'color', default: 'grey'}, + bevelSrc: { type: 'string', default: ''}, + lineColor: { type: 'color', default: 'black'} }, init: function () { + const data = this.data; const el = this.el; - const svgString = this.data.svgString; + const svgString = data.svgString; + const lineColor = data.lineColor; this.loader = new SVGLoader(); this.stokeMaterial = new THREE.LineBasicMaterial({ - color: '#00A5E6' + color: lineColor }); - // set scale for extruded svg el.setAttribute('shadow', 'cast: true; receive: true'); }, + createTopEntity: function (topGeometryArray) { + const data = this.data; + let topElement = this.el.children[0]; + // remove existing topElement. It could be getting from loaded JSON + if (!topElement) { + topElement = document.createElement('a-entity'); + topElement.classList.add('topElement'); + this.el.appendChild(topElement); + } + + // merge shape geometries into one mergedGeometry + const mergedGeometry = this.mergedGeometryFromArray(topGeometryArray); + + mergedGeometry.translate(0, 0.15, 0); + + // create a mesh with the shape geometry + const mergedShapeMesh = new THREE.Mesh(mergedGeometry, + this.materialFromSrc(data.src, data.color)); + + if (topElement.getObject3D('mesh')) { + topElement.removeObject3D('mesh'); + } + topElement.setObject3D('mesh', mergedShapeMesh); + + //topElement.setAttribute('material', `src:${data.src};roughness:1;repeat: 0.01 0.01`); + + }, + materialFromSrc: function (imgSrc, color) { + let texture = null; + // create material with texture from img element with id imgSrc + const textureImg = (imgSrc !== '') ? document.querySelector(imgSrc): null; + if (textureImg) { + // create texture from img element + texture = new THREE.Texture(textureImg); + + texture.encoding = THREE.sRGBEncoding; + + // set repeat property for texture + texture.wrapS = THREE.RepeatWrapping; + texture.wrapT = THREE.RepeatWrapping; + texture.repeat.set(0.01, 0.01); + } + + const material = new THREE.MeshStandardMaterial({ + color: color, map: texture, roughness: 1 + }); + if (material.map) material.map.needsUpdate = true; + return material; + }, + mergedGeometryFromArray: function (geometryArray) { + // Merge array of extruded geometries into the mergedGeometry + const mergedGeometry = + THREE.BufferGeometryUtils.mergeGeometries(geometryArray); + + mergedGeometry.computeBoundingBox(); + mergedGeometry.computeVertexNormals(); + mergedGeometry.center(); + mergedGeometry.rotateX(Math.PI / 2); + mergedGeometry.scale(0.05, 0.05, 0.05); + + return mergedGeometry; + }, extrudeFromSVG: function (svgString) { - const depth = this.data.depth; + const data = this.data; const el = this.el; const svgData = this.loader.parse(svgString); - const fillMaterial = new THREE.MeshStandardMaterial(); const extrudeSettings = { - depth: depth, - bevelEnabled: false + depth: data.depth, + bevelEnabled: data.bevelEnabled, + bevelThickness: data.bevelThickness, + bevelSize: data.bevelSize, + bevelOffset: data.bevelOffset, + bevelSegments: data.bevelSegments }; - const shapeGeometryArray = []; + const extrudedGeometryArray = []; + const topGeometryArray = []; svgData.paths.forEach((path) => { const shapes = SVGLoader.createShapes(path); shapes.forEach((shape) => { + const topGeometry = new THREE.ExtrudeGeometry(shape, {depth: 1, bevelEnabled: false}); const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); - shapeGeometryArray.push(geometry); + topGeometryArray.push(topGeometry); + extrudedGeometryArray.push(geometry); }); }); - // Merge array of extruded geometries into the mergedGeometry - const mergedGeometry = - THREE.BufferGeometryUtils.mergeBufferGeometries(shapeGeometryArray); - - mergedGeometry.computeBoundingBox(); - mergedGeometry.computeVertexNormals(); - mergedGeometry.center(); - mergedGeometry.rotateX(Math.PI / 2); - mergedGeometry.scale(0.05, 0.05, 0.05); + const mergedGeometry = this.mergedGeometryFromArray(extrudedGeometryArray); + // create edges geometries and line segments from mergedGeometry const linesGeometry = new THREE.EdgesGeometry(mergedGeometry); const lines = new THREE.LineSegments(linesGeometry, this.stokeMaterial); el.setObject3D('lines', lines); // Finally, create a mesh with the merged geometry - const mergedMesh = new THREE.Mesh(mergedGeometry, fillMaterial); + const mergedMesh = new THREE.Mesh(mergedGeometry, + this.materialFromSrc(data.bevelSrc, data.bevelColor) + ); // remove existing mesh from entity - el.removeObject3D('mesh'); + if (el.getObject3D('mesh')) { + el.removeObject3D('mesh'); + } el.setObject3D('mesh', mergedMesh); + + //el.setAttribute('material', `src:${data.bevelSrc};roughness:1;repeat: 0.1 0.1`); + + if (data.topElement) { + // create entity from shapes for top level of extruded geometry + this.createTopEntity(topGeometryArray); + } + }, update: function (oldData) { // If `oldData` is empty, then this means we're in the initialization process. // No need to update. - // if (Object.keys(oldData).length === 0) { return; } + //if (Object.keys(oldData).length === 0) { return; } const el = this.el; const svgString = this.data.svgString; - - if (svgString) { - this.extrudeFromSVG(svgString); - if (!el.getAttribute('material')) { - // applies the default mixin material grass. If the element's material is not set via setAttribute - el.setAttribute('material', 'src:#grass-texture;roughness:1;repeat: 0.01 0.01'); - } - } + if (svgString) this.extrudeFromSVG(svgString); } + }); From 55de10a6225b04f6c8b0a99c9f6c0296087aeaa8 Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Wed, 6 Mar 2024 21:48:59 -0800 Subject: [PATCH 2/5] turn off bevel and top element by default --- src/components/svg-extruder.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/svg-extruder.js b/src/components/svg-extruder.js index 443f2aa87..e6c27f571 100644 --- a/src/components/svg-extruder.js +++ b/src/components/svg-extruder.js @@ -5,12 +5,12 @@ AFRAME.registerComponent('svg-extruder', { schema: { svgString: { type: 'string' }, depth: { type: 'number', default: 4 }, - bevelEnabled: { type: 'boolean', default: true }, + bevelEnabled: { type: 'boolean', default: false }, bevelThickness: { type: 'number', default: 1 }, bevelSize: { type: 'number', default: 1 }, bevelOffset: { type: 'number', default: 1 }, bevelSegments: { type: 'number', default: 1 }, - topElement: { type: 'boolean', default: true }, + topElement: { type: 'boolean', default: false }, color: { type: 'color', default: 'white'}, src: { type: 'string', default: '#grass-texture'}, bevelColor: { type: 'color', default: 'grey'}, From 0196fd372d29da84db8f9af18786228d4d1a7d43 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Thu, 7 Mar 2024 23:31:35 -0300 Subject: [PATCH 3/5] fix topElemet false --- src/components/svg-extruder.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/svg-extruder.js b/src/components/svg-extruder.js index e6c27f571..af34436f8 100644 --- a/src/components/svg-extruder.js +++ b/src/components/svg-extruder.js @@ -140,10 +140,13 @@ AFRAME.registerComponent('svg-extruder', { el.setObject3D('mesh', mergedMesh); //el.setAttribute('material', `src:${data.bevelSrc};roughness:1;repeat: 0.1 0.1`); - + + const topElement = this.el.children[0]; if (data.topElement) { // create entity from shapes for top level of extruded geometry this.createTopEntity(topGeometryArray); + } else if (topElement) { + el.removeChild(topElement); } }, From eac76851ef1fc246eb680d6566bd7753610137e1 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 8 Mar 2024 13:16:50 -0300 Subject: [PATCH 4/5] clean previous material data while init component clean material, that may come from JSON data --- src/components/svg-extruder.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/svg-extruder.js b/src/components/svg-extruder.js index af34436f8..d8165fb51 100644 --- a/src/components/svg-extruder.js +++ b/src/components/svg-extruder.js @@ -28,6 +28,7 @@ AFRAME.registerComponent('svg-extruder', { color: lineColor }); + el.removeAttribute('material'); el.setAttribute('shadow', 'cast: true; receive: true'); }, createTopEntity: function (topGeometryArray) { From 9b80ce65e2716aabda5686ef595ade9c5113d1d7 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 8 Mar 2024 13:37:35 -0300 Subject: [PATCH 5/5] changing line color in Editor --- src/components/svg-extruder.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/svg-extruder.js b/src/components/svg-extruder.js index d8165fb51..95bf92121 100644 --- a/src/components/svg-extruder.js +++ b/src/components/svg-extruder.js @@ -24,10 +24,6 @@ AFRAME.registerComponent('svg-extruder', { const lineColor = data.lineColor; this.loader = new SVGLoader(); - this.stokeMaterial = new THREE.LineBasicMaterial({ - color: lineColor - }); - el.removeAttribute('material'); el.setAttribute('shadow', 'cast: true; receive: true'); }, @@ -123,9 +119,13 @@ AFRAME.registerComponent('svg-extruder', { const mergedGeometry = this.mergedGeometryFromArray(extrudedGeometryArray); + const stokeMaterial = new THREE.LineBasicMaterial({ + color: data.lineColor + }); + // create edges geometries and line segments from mergedGeometry const linesGeometry = new THREE.EdgesGeometry(mergedGeometry); - const lines = new THREE.LineSegments(linesGeometry, this.stokeMaterial); + const lines = new THREE.LineSegments(linesGeometry, stokeMaterial); el.setObject3D('lines', lines);