简体   繁体   中英

Extrude 2D Colored Image in Three.js

I've looked for resources online, but I have not seen a way to extrude a colored image in Three.js. I'm trying to create something like a Minecraft item where the image is used to then create an extruded geometry. An example would be: https://minecraft.gamepedia.com/File:BowSpinning3.gif

I've tried looking at this resource: https://muffinman.io/three-js-extrude-svg-path/ but this only extrudes uncolored SVGs.


loader.load('./textures/diamondbleu.svg', function (data) {

  // Group we'll use for all SVG paths
  const svgGroup = new THREE.Group();
  // When importing SVGs paths are inverted on Y axis
  // it happens in the process of mapping from 2d to 3d coordinate system
  svgGroup.scale.y *= -1;

  const material = new THREE.MeshLambertMaterial();

  // Loop through all of the parsed paths
  data.paths.forEach((path, i) => {
    const shapes = path.toShapes(true);

    // Each path has array of shapes
    shapes.forEach((shape, j) => {
      // Finally we can take each shape and extrude it
      const geometry = new THREE.ExtrudeGeometry(shape, {
        depth: 20,
        bevelEnabled: false
      });

      // Create a mesh and add it to the group
      const mesh = new THREE.Mesh(geometry, material);

      svgGroup.add(mesh);
    });
  });

  // Get group's size
  const box = new THREE.Box3().setFromObject(svgGroup);
  const size = new THREE.Vector3();
  box.getSize(size);

  const yOffset = size.y / -2;
  const xOffset = size.x / -2;

  // Offset all of group's elements, to center them
  svgGroup.children.forEach(item => {
    item.position.x = xOffset;
    item.position.y = yOffset;
  });

  svgGroup.position.set(0, blockSize*75, 0);

  // Finally we add svg group to the scene
  scene.add(svgGroup);
})

Is there a way to modify the code to allow for colored SVGs? Thanks!

You can use the SVGLoader that's available in the "examples/jsm/loaders/" folder.

The docs have outlined how to generate SVGs in 3D space , it looks like your code sample is missing the part where the paths loop makes a new material and assigns a color for each path :

var material = new THREE.MeshBasicMaterial( {
    color: path.color,
    side: THREE.DoubleSide,
    depthWrite: false
} );

Your code seems to create a single LambertMaterial with no colors assigned, and no lights. Lambert materials need lights to be illuminated, whereas BasicMaterial just shows the color without need of lights.

Look at the code in this demo for another example. Instead of using path.color , this demo finds the color by accessing path.userData.style.fill . I think you'll want the latter approach, depending on your SVG file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM