Hi i am trying to use fabric js output data url of canvas to fit exactly as if it is rolled and cylinder is created but not getting how would one do that?
As i worked on project that was needed to be completed fast, i used same square geometry which is what three js gives as a default and nicely converted to cylinder of intended shape.
This is how my shape is currently which is inside the mask of canvas in fabric js. I am not sure how to exactly prepare png from mask but that i will figure out on my own
but unfortunately the shape which is inside clipping area is not what being currently converted to 3d but it is this square image which i am getting after performing toDataUrl
over canvas.
and thus, all parts which are outside clipping mask are also coming to 3d…
I only need to convert the cross section shape to cylinder so that it is perfectly covered with whole texture as it it were rollled over that. How to do that?
Here is some code how 2d image is prepared in fabric js
window.__canvas.clone(function(clonedCanvas) {
clonedCanvas.clipPath = null;
window.clonedCanvas = clonedCanvas;
const clonedCanvasObjects = clonedCanvas.getObjects();
clonedCanvasObjects.forEach(function(clonedCanvasObject,i) {
clonedCanvasObject.set({
clipPath: null,
})
if(clonedCanvasObject.excludeFromExportIn3D) {
clonedCanvas.remove(clonedCanvasObject)
}
});
if(self.isInside3dView) {
window.dispatchEvent(new CustomEvent('toggle-3d', { detail: {
url: url,
topBottomTextureUrl: clonedCanvas.backgroundImage?.src,
formData: formData,
tagImageTextureUrl: img._originalElement.src
}, bubbles: true }));
}
},['excludeFromExportIn3D','name', 'filters', 'viewportTransform'])
|
and once toggle-3d event is fired, here is how i handled it in three js via script type module in other file.
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const canvas3dwrapper = document.querySelector('.canvas-wrapper-container');
const canvas3dholder = document.getElementById('canvas-3d-holder')
var renderer = new THREE.WebGLRenderer({alpha: false, antialias : true});
renderer.setClearColor( 0xFFFFFF, 0 );
renderer.setSize( canvas3dwrapper.offsetWidth, canvas3dwrapper.offsetWidth );
canvas3dholder.appendChild( renderer.domElement );
//addMouseHandler(renderer.domElement )
const cylinder = new THREE.Mesh();
const camera = new THREE.PerspectiveCamera( 75, 1, 0.1, 800 );
const controls = new OrbitControls( camera, renderer.domElement );
controls.maxZoom = 20;
controls.minZoom = 1;
const scene = new THREE.Scene();
camera.position.set( 0, 0, 20);
//camera.position.z = 30;
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
animate();
window.addEventListener('toggle-3d',function(event) {
renderer.setSize( canvas3dwrapper.offsetWidth, canvas3dwrapper.offsetWidth );
//remove old objects from scene
while(scene.children.length > 0){
scene.remove(scene.children[0]);
}
const textureUrl = event.detail.url;
const texture = new THREE.TextureLoader().load(textureUrl,(texture) => {
texture.colorSpace = THREE.SRGBColorSpace;
const materials = [
new THREE.MeshBasicMaterial({map: texture, side: THREE.DoubleSide})
];
if(event.detail.topBottomTextureUrl) {
const topBottomTexture = new THREE.TextureLoader().load( event.detail.topBottomTextureUrl,(texture) => {
texture.colorSpace = THREE.SRGBColorSpace;
const material = new THREE.MeshBasicMaterial({
map: texture
})
materials.push(material, material)
})
} else {
const material = new THREE.MeshBasicMaterial({
color: 0Xffffff
});
materials.push(material, material)
}
const geometry = new THREE.CylinderGeometry(0.7, 3.0, 13.5, 1500);
cylinder.geometry = geometry;
cylinder.material = materials;
//const cylinder = new THREE.Mesh( geometry, materials );
cylinder.position.set(0, 2, 0);
cylinder.rotation.y = Math.PI;
if(event.detail.formData) {
camera.position.set( 0, 0, 20);
}
scene.add(cylinder);
})
})