13

我对html5和three.js很陌生。我一直在用它做一些试验,基本上我想做的是有一个网格(我使用的是 planeGeometry,因为我遵循的教程使用了它)。网格显示不同的纹理,稍后可以更改。

这是我的代码的样子:

angelTexture = THREE.ImageUtils.loadTexture("images/textures/chars/angel/angel.png");
angelTexture.offset.x = -0.75;
angelTexture.offset.y = -0.75;

angelMesh = new THREE.Mesh( new THREE.PlaneGeometry(79, 53, 79, 53), new THREE.MeshBasicMaterial( { map: angelTexture, wireframe: false } ));

angelMesh.position.x = 0;
angelMesh.position.y = 0;
scene.add(angelMesh);

问题是每当我偏移时,Mesh 似乎足够大以显示所有其他 Sprite(我将纹理用作我偏移的 2D Sprite 以对其进行动画处理)。结果是非常灾难性的,我仍在研究如何控制 Mesh 的大小,以便它只显示 Sprite 的一个快照。我所有的尝试似乎只是调整网格以及底层纹理的大小,并且仍然显示所有精灵。

有人可以指出我正确的方向吗?提前致谢。

...

我的朋友想出了一个解决方案......我错过了重复属性。

angelTexture = THREE.ImageUtils.loadTexture("images/textures/chars/angel/angel.png");
angelTexture.offset.x = -0.75; 
angelTexture.offset.y = -0.75;

angelTexture.repeat.x = 0.25;
angelTexture.repeat.y = 0.25;   
scene.add(angelMesh);

希望这可以帮助其他有同样问题的人。

4

4 回答 4

26

前段时间我有同样的问题,所以我写了一个完整的例子,使用 spritesheet 作为 PlaneGeometry 的纹理,然后定期更新纹理 - 查看示例

http://stemkoski.github.io/Three.js/Texture-Animation.html

并查看注释的源代码以获取更多说明。


更新(2021 年):

这是我推荐使用的功能的更新版本。它修复了不正确的平铺显示顺序的问题,它会自动更新下一帧,并返回一个对象,您可以使用它来根据需要停止和重新启动动画。

function TextureAnimator(texture, tilesHoriz, tilesVert, tileDispDuration) 
{ 
  let obj = {};

  obj.texture = texture;
  obj.tilesHorizontal = tilesHoriz;
  obj.tilesVertical = tilesVert;
  obj.tileDisplayDuration = tileDispDuration;

  obj.numberOfTiles = tilesHoriz * tilesVert;

  obj.texture.wrapS = THREE.RepeatWrapping;   
  obj.texture.wrapT = THREE.RepeatWrapping;   
  obj.texture.repeat.set( 1/tilesHoriz, 1/tilesVert );
  obj.currentTile = 0;

  obj.nextFrame = function()
  {
    obj.currentTile++;
    if (obj.currentTile == obj.numberOfTiles)
      obj.currentTile = 0;

    let currentColumn = obj.currentTile % obj.tilesHorizontal;
    obj.texture.offset.x = currentColumn / obj.tilesHorizontal;

    let currentRow = Math.floor( obj.currentTile / obj.tilesHorizontal );
    obj.texture.offset.y = obj.tilesVertical - currentRow / obj.tilesVertical;
  }

  obj.start = function()
  { obj.intervalID = setInterval(obj.nextFrame, obj.tileDisplayDuration); }

  obj.stop = function()
  { clearInterval(obj.intervalID); }

  obj.start();
  return obj;
}   
于 2013-04-16T13:55:27.363 回答
5

我在对 Lee Stemkoski 的评论中指出,具有多行的 spritesheets 在使用较新的THREE.TextureLoader().

我在测试中使用以下 4x4 精灵图像。

显示为每个预期图块突出显示的象限的图像

TextureAnimator假设您有一个完整的 16 瓦子精灵表,无需修改 Lee Stemkoski 的函数。

var texture = new THREE.TextureLoader().load('grid-sprite.jpg');
var annie = new TextureAnimator(texture, 4, 4, 16, 150);

动画纹理向后运行。 Codepen 演示

在此处输入图像描述

所以我做了我自己的,我称之为 THREE.SpriteSheetTexture

THREE.SpriteSheetTexture = function(imageURL, framesX, framesY, frameDelay, _endFrame) {

    var timer, frameWidth, frameHeight,
            x = 0, y = 0, count = 0, startFrame = 0, 
            endFrame = _endFrame || framesX * framesY,
            CORSProxy = 'https://cors-anywhere.herokuapp.com/',
            canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d'),
            canvasTexture = new THREE.CanvasTexture(canvas),
            img = new Image();

    img.crossOrigin = "Anonymous"
    img.onload = function(){
        canvas.width = frameWidth = img.width / framesX;
        canvas.height = frameHeight = img.height / framesY;
        timer = setInterval(nextFrame, frameDelay);
    }
    img.src = CORSProxy + imageURL;

    function nextFrame() {
        count++;

        if(count >= endFrame ) {
            count = 0;
        };

        x = (count % framesX) * frameWidth;
        y = ((count / framesX)|0) * frameHeight;

        ctx.clearRect(0, 0, frameWidth, frameHeight);
        ctx.drawImage(img, x, y, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);

        canvasTexture.needsUpdate = true;
    }

    return canvasTexture;
}

你需要知道 imageURL的是你的 spritesheet 的 URL framesX是沿着 x 轴(左和右) framesY有多少帧是沿着 y 轴(上下) delay有多少帧是纹理等待多长时间更改到下一帧 _endFrame是可选的 - 有多少帧(以防它不使用整行)

这一切看起来像这样

texture = new THREE.SpriteSheetTexture('https://s3-us-west-2.amazonaws.com/s.cdpn.io/68819/grid-sprite.jpg', 4, 4, 100, 16);
var material = new THREE.MeshBasicMaterial({ 
    map: texture
});
geometry = new THREE.BoxGeometry( 200, 200, 200 );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

有很多的欣喜!!! Codepen 演示在这里

于 2019-01-10T17:33:30.537 回答
1

@Cmndo 使帧流以正确的顺序移动,您只需要更新它:

texture.offset.y = currentRow / this.tilesVertical;

对此:

texture.offset.y = this.tilesVertical - (currentRow / this.tilesVertical);

在这个例子中: https ://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Texture-Animation.html

于 2020-10-09T13:20:56.830 回答
0

要使帧向正确的方向移动,请使用:

texture.offset.y = (1 - currentRow / _tilesVertical) - (1 / _tilesVertical);

代替

texture.offset.y = currentRow / this.tilesVertical;
于 2021-03-25T13:47:42.513 回答