admin管理员组

文章数量:1220926

I am creating a lithophane of uploaded image which is downloadable and working fine, now I need help in cutting the created lithophane into puzzle pieces and download the puzzle.

I am adding code of the lithophane and working screenshot. I am using angular 19 in the project. I will really appreciate if anyone can help me creating the puzzle. I can also pay the person for help.

Here is the code to create image lithphane -

private addLithophane(shapeType: 'flat' | 'bowl' | 'bell' | 'cylinder' | 'custom', textureUrl: string | null, options: any = {}): void {
    if (this.lithophane) this.scene.remove(this.lithophane);

    const   processImage = (img: HTMLImageElement | HTMLCanvasElement) => {
        this.canvas = document.createElement('canvas');
        const ctx = this.canvas.getContext('2d')!;
        this.canvas.width = img.width;  
        
        this.canvas.height = img.height;

        // Draw and blur image
        ctx.drawImage(img, 0, 0);
        ctx.filter = 'blur(3px)'; // Smooth the image
        ctx.drawImage(this.canvas, 0, 0);
        ctx.filter = 'none';

        const imageData = ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
        const data = imageData.data;

        // Improved brightness processing with gamma correction
        for (let i = 0; i < data.length; i += 4) {
            const brightness = (data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114);
            const invertedValue = 255 - brightness;
            const correctedValue = Math.pow(invertedValue / 255, 2.2) * 255;
            data[i] = correctedValue;
            data[i + 1] = correctedValue;
            data[i + 2] = correctedValue;
        }
        ctx.putImageData(imageData, 0, 0);

        const shapeOptions = {
            flat: {
                width: 20,
                height: 10,
                depth: 0.1,
                segments: 256
            },
            bowl: {
                radius: 5,
                height: 5,
                segments: 256,
                curvature: 0.3
            },
            bell: {
                radius: 5,
                height: 10,
                segments: 256,
                profile: [
                    { r: 0.2, h: 1.0 },
                    { r: 0.8, h: 0.8 },
                    { r: 0.9, h: 0.5 },
                    { r: 1.0, h: 0.2 },
                    { r: 1.1, h: 0.0 }
                ]
            },
            cylinder: {
                radius: 5,
                height: 10,
                segments: 256
            }
        };

        const finalOptions = {
            ...(shapeType === 'custom' ? {} : shapeOptions[shapeType]),
            ...options,
            width: options.width || 20,
            height: options.height || 10,
            baseThickness: options.baseThickness || 0.8,
            maxDepth: options.maxDepth || 1.0,
            segments: options.segments || 256
        };

        if (shapeType === 'flat') {
            // Create box geometry with segments
            const geometry = new THREE.BoxGeometry(
                finalOptions.width,
                finalOptions.height,
                finalOptions.baseThickness,
                finalOptions.segments,
                finalOptions.segments,
                1
            );

            // Get vertices for the front face only
            const positions = geometry.attributes['position'];
            const vertexCount = positions.count;

            for (let i = 0; i < vertexCount; i++) {
                const x = positions.getX(i);
                const y = positions.getY(i);
                let z = positions.getZ(i);

                // Only modify vertices on the front face (z > 0)
                if (z > 0) {
                    // Calculate UV coordinates
                    const u = (x / finalOptions.width + 0.5) * this.canvas.width;
                    const v = (-y / finalOptions.height + 0.5) * this.canvas.height;

                    const px = Math.floor(u) % this.canvas.width;
                    const py = Math.floor(v) % this.canvas.height;
                    const idx = (py * this.canvas.width + px) * 4;
                    const brightness = data[idx] / 255; // Normalized to 0-1

                    // Adjust the z-position based on brightness
                    z = finalOptions.baseThickness - brightness * finalOptions.maxDepth;
                    positions.setZ(i, z);
                }
            }

            positions.needsUpdate = true;
            geometryputeVertexNormals();
            geometry.center();

            const texture = new THREE.CanvasTexture(this.canvas);
            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            texture.flipY = false;

            // Create materials for front and back
            const frontMaterial = new THREE.MeshPhongMaterial({
                color: 0xdddddd,
                specular: 0x444444,
                shininess: 30,
                bumpMap: texture,
                bumpScale: -0.5,
                map: textureUrl ? new THREE.TextureLoader().load(textureUrl) : null
            });

            const backMaterial = new THREE.MeshPhongMaterial({
                color: 0xdddddd,
                specular: 0x000000,
                shininess: 0,
                flatShading: true
            });

            const sideMaterial = new THREE.MeshPhongMaterial({
                color: 0xdddddd,
                specular: 0x000000,
                shininess: 0,
                flatShading: true
            });

            // Create mesh with different materials for each face
            const materials = [
                sideMaterial, // right
                sideMaterial, // left
                sideMaterial, // top
                sideMaterial, // bottom
                frontMaterial, // front
                backMaterial  // back
            ];

            this.lithophane = new THREE.Mesh(geometry, materials);
            this.lithophane.position.set(0, 5, 0);
            this.lithophane.castShadow = true;
            this.lithophane.receiveShadow = true;

            this.scene.add(this.lithophane);
        } else {
            // Handle other shape types as before...
        }
    };


    if (textureUrl) {
        const img = new Image();
        img.onload = () => processImage(img);
        img.crossOrigin = "anonymous";
        img.src = textureUrl;
    } else {
        const grayCanvas = this.createGrayCanvas(256, 256);
        processImage(grayCanvas);
    }
}

本文标签: javascriptI want to create lithophane puzzle using threeJsStack Overflow