I use the SVG loader to extrude a 3D object and then make a brush out of it using the Three CSG. But this causes alot of lag and performance issues and I think this is because of the post processing. What is the problem with my code structure?
import * as THREE from 'three';
import { SUBTRACTION, INTERSECTION, ADDITION, Brush, Evaluator } from 'three-bvh-csg';
import { SVGLoader } from 'three/addons/loaders/SVGLoader';
import { OrbitControls } from 'three/addons/controls/OrbitControls';
const loader = new SVGLoader();
let renderer, camera, scene;
let brush1, brush2, result;
const modelViewerWidth = (window.innerWidth / 4) * 3;
const modelViewerHeight = window.innerHeight;
let csgEvaluator = new Evaluator();
csgEvaluator.attributes = [ 'position', 'normal' ];
csgEvaluator.useGroups = false;
const params = {
displayBrush: true,
operation: ADDITION,
};
start();
init();
async function init() {
// create the scene and set a background color
scene = new THREE.Scene();
scene.background = new THREE.Color( "#dadada" );
// set up the camera, its position and rotation
camera = new THREE.PerspectiveCamera( 50, modelViewerWidth/modelViewerHeight, 1, 100 );
camera.position.set(0, 15, 20);
camera.rotation.x = Math.PI * -0.2;
// set up the renderer and the size of the model viewer
renderer = new THREE.WebGLRenderer ( { antialias: false } );
renderer.setSize(modelViewerWidth, modelViewerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = false;
// add the renderer to the modelViewer element
document.getElementById("modelViewer").appendChild( renderer.domElement );
// add the gridHelper to show orientation
const gridHelper = new THREE.GridHelper( 20, 20 );
scene.add(gridHelper);
// add the grid axis
const axesHelper = new THREE.AxesHelper( 3 );
axesHelper.position.set(-10, 0, -10);
scene.add(axesHelper);
// add controls to enable the user to view the model from different angles
const controls = new OrbitControls( camera, renderer.domElement );
brush1 = new Brush(
renderSVG(),
new THREE.MeshBasicMaterial({ color: "#ff0000" })
);
brush2 = new Brush(
renderSVG(),
new THREE.MeshBasicMaterial({ color: "#ff0000" })
);
result = new THREE.Mesh();
scene.add( result );
render()
}
function renderSVG() {
let bufferGeometry = new THREE.BufferGeometry();
const positions = [];
const normals = [];
loader.load(
'Merry Christmas.svg',
function (data) {
const paths = data.paths;
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const shapes = path.toShapes(true);
const extrudeSettings = {
depth: 20,
bevelEnabled: false,
};
for (let j = 0; j < shapes.length; j++) {
const shape = shapes[j];
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
// Extract data from geometry and add it to the arrays
const vertices = geometry.getAttribute('position').array;
const vertexCount = vertices.length / 3;
for (let k = 0; k < vertexCount; k++) {
positions.push(vertices[k * 3], vertices[k * 3 + 1], vertices[k * 3 + 2]);
normals.push(0, 0, 1);
}
}
}
// Set attributes to bufferGeometry
bufferGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
bufferGeometry.setAttribute('normal', new THREE.Float32BufferAttribute(normals, 3));
// Optional: Scale or transform the bufferGeometry if needed
bufferGeometry.scale(0.02, 0.02, 0.02);
}
);
return bufferGeometry;
}
function render() {
setTimeout(() => {
requestAnimationFrame( render );
}, 1000 / 30 );
// Update the scene every updateFrequency frames
if (params.operation === -1) {
result.geometry.dispose();
result.geometry.copy(brush1.geometry);
} else {
result = csgEvaluator.evaluate(brush1, brush2, params.operation, result);
}
renderer.render(scene, camera);
}
I tried to tweak with the renderer and adding intervals, but that did not do the job. Should I call the SVGLoader get an object and then use that through out the entire run. How would I accomplish that?