使用带有Three.js的画布旋转纹理

时间:2013-11-15 10:16:10

标签: javascript canvas three.js

我想用Three.js旋转出现在立方体一面上的纹理。

由于这个立方体是用不同的纹理多次创建的,我使用了一个用纹理参数创建材质和网格的函数。

但是我需要将这个纹理旋转90°,我发现最好的方法是创建一个画布,将纹理放入,旋转它并使用这个画布作为网格纹理。我尝试使用此代码实现此目的:Three.js Rotate Texture,但不幸的是我总是得到黑色纹理。

这是我的功能:

function createCube(pos, texture) {
     var img = new Image();
     img.src = texture;

     var imgWidth = imgHeight = img.width;
     var mapCanvas = document.createElement( 'canvas' );
     mapCanvas.width = mapCanvas.height = img.width;

     // document.body.appendChild( mapCanvas );
     var ctx = mapCanvas.getContext( '2d' );
     ctx.translate( imgWidth / 2, imgHeight / 2 );
     ctx.rotate( Math.PI / 2 );
     ctx.translate( -imgWidth / 2, -imgHeight / 2 );
     ctx.drawImage( img, 0, 0, imgWidth, imgHeight );

     var texture = new THREE.Texture( mapCanvas );
     texture.needsUpdate = true;
     var materials = [
                //Left side (posx)
                new THREE.MeshLambertMaterial({
                    color: 0x1a0e05
                }),
                //Right side (negx)
                new THREE.MeshLambertMaterial({
                    color: 0x1a0e05
                }),
                //Top side (posy)
                new THREE.MeshLambertMaterial({
                    color: 0x1a0e05
                }),
                //Bottom side (negy)
                new THREE.MeshLambertMaterial({
                    color: 0xffffff,
                    map: texture
                }),
                //Front side (posz)
                new THREE.MeshLambertMaterial({
                    color: 0x1a0e05
                }),
                //Back side (negz)
                new THREE.MeshLambertMaterial({
                    color: 0x1a0e05
                })
    ];

    cube = new THREE.Mesh(new THREE.CubeGeometry(100, 2, 100, 1, 1, 1), new THREE.MeshFaceMaterial(materials));

    ...

    return cube;

}

也许这可能是因为当附加到画布时纹理尚未加载? 我删除了img.onLoad(来自Three.js Rotate Texture),因为我不知道如何在多次调用函数中使用此回调... 此外,这个函数用于返回网格,我可以使用extern .onLoad函数吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

你猜测“由于纹理尚未加载到画布上”,这绝对是正确的。

您只需要重新引入回调,这需要对代码进行一些重新排序。应该有点像这样(未经测试,但如果不立即工作,应该明确的想法):

function createCube(pos, texture) {
     var img = new Image();

     var imgWidth = imgHeight = img.width;
     var mapCanvas = document.createElement( 'canvas' );
     mapCanvas.width = mapCanvas.height = img.width;

     var texture = new THREE.Texture( mapCanvas );


     img.onload = function() {


         // document.body.appendChild( mapCanvas );
         var ctx = mapCanvas.getContext( '2d' );
         ctx.translate( imgWidth / 2, imgHeight / 2 );
         ctx.rotate( Math.PI / 2 );
         ctx.translate( -imgWidth / 2, -imgHeight / 2 );
         ctx.drawImage( img, 0, 0, imgWidth, imgHeight );

         texture.needsUpdate = true;


    }

    var materials = [
              //Left side (posx)
              new THREE.MeshLambertMaterial({
                  color: 0x1a0e05
              }),
              //Right side (negx)
              new THREE.MeshLambertMaterial({
                  color: 0x1a0e05
              }),
              //Top side (posy)
              new THREE.MeshLambertMaterial({
                  color: 0x1a0e05
              }),
              //Bottom side (negy)
              new THREE.MeshLambertMaterial({
                  color: 0xffffff,
                  map: texture
              }),
              //Front side (posz)
              new THREE.MeshLambertMaterial({
                  color: 0x1a0e05
              }),
              //Back side (negz)
              new THREE.MeshLambertMaterial({
                  color: 0x1a0e05
              })
    ];

    img.src = texture; 

    cube = new THREE.Mesh(new THREE.CubeGeometry(100, 2, 100, 1, 1, 1), new THREE.MeshFaceMaterial(materials));

    ...

    return cube;

}

你需要有一个渲染循环,或者也可以在onload回调中重新渲染场景。