Skip to content

Box3.setFromBufferAttribute does not correctly handle InterleavedBufferAttribute with offset #30948

@AlexOct

Description

@AlexOct

Description

When using Box3.setFromBufferAttribute() on an InterleavedBufferAttribute, the resulting bounding box can be incorrect if the attribute has a non-zero offset. This is because fromBufferAttribute() does not appear to correctly take the offset into account for interleaved data.

In the setFromBufferAttribute function,the real count in loop should be equal to attribute.count - attribute.offset.Or attribute cout of interleavedBufferAttribute equal to attribute.data.count - attribute.offset

Reproduction steps

Steps to reproduce the behavior:

  1. Create a geometry using InterleavedBufferAttribute for positions.
  2. Provide a non-zero offset
  3. Call box.setFromBufferAttribute(positionAttribute);
  4. The resulting box may be invalid or incorrect.

Code

      const ReverseWindingOrder = function (idxArray: number[]) {
  for (let i = 0; i < idxArray.length; i += 3) {
      let tem = idxArray[i];
      idxArray[i] = idxArray[i + 1];
      idxArray[i + 1] = tem;
  }
      };
     const posData = [
        0, 0, 0, 0, 0, 0, 0, 0, 0,//0
        1, 0, 0, 1, 0, 0, 1, 0, 0,//1
        0, 0, 1, 0, 0, 1, 0, 0, 1,//2
        1, 0, 1, 1, 0, 1, 1, 0, 1,//3
        0, 1, 0, 0, 1, 0, 0, 1, 0,//4
        1, 1, 0, 1, 1, 0, 1, 1, 0,//5
        0, 1, 1, 0, 1, 1, 0, 1, 1,//6
        1, 1, 1, 1, 1, 1, 1, 1, 1,//7
        
        0, 0, 0, 0, 0, 0, 0, 0, 0,//0
        2, 0, 0, 2, 0, 0, 2, 0, 0,//2
        0, 0, 2, 0, 0, 2, 0, 0, 2,//2
        2, 0, 2, 2, 0, 2, 2, 0, 2,//3
        0, 2, 0, 0, 2, 0, 0, 2, 0,//4
        2, 2, 0, 2, 2, 0, 2, 2, 0,//5
        0, 2, 2, 0, 2, 2, 0, 2, 2,//6
        2, 2, 2, 2, 2, 2, 2, 2, 2,//7
     ];
      const idxData = [
          1 * 3 + 0, 5 * 3 + 0, 7 * 3 + 0, 1 * 3 + 0, 7 * 3 + 0, 3 * 3 + 0,//+x
          2 * 3 + 0, 6 * 3 + 0, 4 * 3 + 0, 2 * 3 + 0, 4 * 3 + 0, 0 * 3 + 0,//-x
          4 * 3 + 1, 6 * 3 + 1, 5 * 3 + 1, 5 * 3 + 1, 6 * 3 + 1, 7 * 3 + 1,//+y
          0 * 3 + 1, 1 * 3 + 1, 2 * 3 + 1, 2 * 3 + 1, 1 * 3 + 1, 3 * 3 + 1,//-y
          2 * 3 + 2, 7 * 3 + 2, 6 * 3 + 2, 2 * 3 + 2, 3 * 3 + 2, 7 * 3 + 2,//+z
          0 * 3 + 2, 4 * 3 + 2, 5 * 3 + 2, 0 * 3 + 2, 5 * 3 + 2, 1 * 3 + 2,//-z

          
          1 * 3 + 0, 5 * 3 + 0, 7 * 3 + 0, 1 * 3 + 0, 7 * 3 + 0, 3 * 3 + 0,//+x
          2 * 3 + 0, 6 * 3 + 0, 4 * 3 + 0, 2 * 3 + 0, 4 * 3 + 0, 0 * 3 + 0,//-x
          4 * 3 + 1, 6 * 3 + 1, 5 * 3 + 1, 5 * 3 + 1, 6 * 3 + 1, 7 * 3 + 1,//+y
          0 * 3 + 1, 1 * 3 + 1, 2 * 3 + 1, 2 * 3 + 1, 1 * 3 + 1, 3 * 3 + 1,//-y
          2 * 3 + 2, 7 * 3 + 2, 6 * 3 + 2, 2 * 3 + 2, 3 * 3 + 2, 7 * 3 + 2,//+z
          0 * 3 + 2, 4 * 3 + 2, 5 * 3 + 2, 0 * 3 + 2, 5 * 3 + 2, 1 * 3 + 2,//-z
      ];
      ReverseWindingOrder(idxData);
      const pos = new THREE.InterleavedBuffer(new Float32Array(posData),3);
      const idx = new THREE.BufferAttribute(new Uint16Array(idxData), 1)

      const geo = new THREE.BufferGeometry();
      const attpos = new THREE.InterleavedBufferAttribute(pos,pos.stride,0);
      geo.setAttribute('position',attpos);
      geo.setIndex(idx);
      geo.addGroup(0,36);

      const geo0 = new THREE.BufferGeometry();
      const attpos0 = new THREE.InterleavedBufferAttribute(pos,pos.stride,24 * pos.stride);
      geo0.setAttribute('position',attpos0);
      geo0.setIndex(idx);
      geo0.addGroup(0,Infinity);

      const material= new THREE.MeshStandardMaterial({
        side:THREE.BackSide,
        color: 0x00ff00,
        metalness: 0.8,
        roughness:0.5,
      });
      const cube = new THREE.Mesh(geo, [material]);
      cube.position.set(5,0,0);
      const cube0 = new THREE.Mesh(geo0, [material]);
      cube0.position.set(10,0,0);

      this.scene.add(cube);
      this.scene.add(cube0);

Screenshots

No response

Version

r167

Device

No response

Browser

No response

OS

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions