17 Jun 2024

Explode along levels

There is an old blog post on creating an explode function that moves the levels apart. That was creating levels based on the bottom of the bounding box of each object.

In the meantime, AECModelData was introduced for AEC models which provides level information (elevation and height), so we can use that now.

The original sample code also moved the camera to the appropriate location.
In my version I just concentrate on the level-wise explode function and also made it work when multiple models are loaded at the same time. I was testing with rac_basic_sample_project.rvt and rst_basic_sample_project.rvt files.

function getFloorOffsetZ(fragMiddleZ, scale, levels, globalOffsetZ) {
  for (const key in levels) {
    const level = levels[key];
    // If the middle of the fragment is below the top of the level
    if (fragMiddleZ < level.elevation + level.height - globalOffsetZ) {
      return key * scale;
    }
  }
}

function floorExplode(viewer, scale, levels) {
  // We'll just use the AEC Model Data of the first model
  // If multiple models are loaded, they probably have that in common
  // You could also use the AEC Model Data of a specific model
  for (const model of viewer.getAllModels()) {
    const fragList = model.getFragmentList();
    let pt = new THREE.Vector3();

    const boxes = fragList.fragments.boxes;
    for (const fragId in fragList.fragments.fragId2dbId) {
      const fragIdInt = parseInt(fragId);
      if (scale == 0) {
        fragList.updateAnimTransform(fragIdInt);
      } else {
        const box_offset = fragIdInt * 6;

        const fragMiddleZ = (boxes[box_offset + 2] + boxes[box_offset + 5]) / 2;
        pt.z = getFloorOffsetZ(fragMiddleZ, scale, levels, model.myData.globalOffset.z);

        fragList.updateAnimTransform(fragIdInt, null, null, pt);
      }
    }
  }
}

Source code: https://github.com/adamenagy/floor-animation

See picture on top showing the sample in action.

Related Article