Search code examples
autodesk-forgeautodesk-viewer

Why does ModelBuilder addGeometry function throw error


I want to add a custom geometry to my model in the forge viewer. To do so, I use the model builder extension, but the modelBuilder.addGeometry function throws the following error:

thirdparty/three.js/three.js:33 Unhandled Promise rejection: Cannot read property 'position' of undefined

const sceneBuilder: any = await this.viewer.loadExtension('Autodesk.Viewing.SceneBuilder');
const modelBuilder: any = await sceneBuilder.addNewModel({
    modelNameOverride: 'My Custom Model',
    conserveMemory: false
});

const geometry: THREE.Geometry = new THREE.Geometry();
    
let vertexIndex = 0;
// room is a custom object coming from our database containing 2D geometrical information
    for (let i = 1; i < room.Outline.Vertices.length; i++) {
      const bimV1 = room.Outline.Vertices[i - 1];
      const bimV2 = room.Outline.Vertices[i];
      if (i === 1) {
        const v1 = new THREE.Vector3(bimV1.X, bimV1.Y, room.Zbase);
        const v2 = new THREE.Vector3(bimV1.X, bimV1.Y, room.Zbase + 5);
        geometry.vertices.push(v1);
        geometry.vertices.push(v2);
      }
      
      const v3 = new THREE.Vector3(bimV2.X, bimV2.Y, room.Zbase);      
      const v4 = new THREE.Vector3(bimV2.X, bimV2.Y, room.Zbase + 5);
      
      geometry.vertices.push(v3);      
      geometry.vertices.push(v4);

      const face1 = new THREE.Face3(vertexIndex, vertexIndex + 1, vertexIndex + 2);
      const face2 = new THREE.Face3(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3);

      geometry.faces.push(face1);
      geometry.faces.push(face2);

      vertexIndex += 2;
    }

geometry.computeFaceNormals();

const bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);
const material = new THREE.MeshPhongMaterial({ color: new THREE.Color(0, 0, 1), opacity: 0.5 });
const transform = new THREE.Matrix4().identity();
modelBuilder.addMaterial('MyCustomMaterial', material);
const geometryId = modelBuilder.addGeometry(geometry);
const cylinderFragId = modelBuilder.addFragment(geometryId, 'MyCustomMaterial', transform);

What causes this error? It works, when I am using a three cylinder like this:

const sceneBuilder: any = await this.viewer.loadExtension('Autodesk.Viewing.SceneBuilder');
const modelBuilder: any = await sceneBuilder.addNewModel({
    modelNameOverride: 'My Custom Model',
    conserveMemory: false
});
const cylinderGeometry = new THREE.BufferGeometry().fromGeometry(new THREE.CylinderGeometry(5, 5, 10));
const cylinderMaterial = new THREE.MeshPhongMaterial({ color: new THREE.Color(0, 0, 1) });
const cylinderTransform = new THREE.Matrix4().compose(
    new THREE.Vector3(+10, +10, 0),
    new THREE.Quaternion(0, 0, 0, 1),
    new THREE.Vector3(1, 1, 1)
);
modelBuilder.addMaterial('MyCustomMaterial', cylinderMaterial);
const cylinderGeomId = modelBuilder.addGeometry(cylinderGeometry);
const cylinderFragId = modelBuilder.addFragment(cylinderGeomId, 'MyCustomMaterial', cylinderTransform);

I already tried to use BufferGeometry as well, but that didn't help...

Edit: I also tried to use the 'ConvexGeomtry' class:

let vertices :THREE.Vector3[] = [];
for (let i = 0; i < room.Outline.Vertices.length; i++) {
  const bimV1 = room.Outline.Vertices[i];
  vertices.push(new THREE.Vector3(bimV1.X, bimV1.Y, bimV1.Zbase));
  vertices.push(new THREE.Vector3(bimV1.X, bimV1.Y, bimV1.Zbase + 5));
}

const geometry = new ConvexGeometry(vertices);

const material = new THREE.MeshPhongMaterial({ color: new THREE.Color(0, 0, 1), opacity: 0.5 });
const transform = new THREE.Matrix4().identity();
modelBuilder.addMaterial('MyCustomMaterial', material);
const geometryId = modelBuilder.addGeometry(geometry);
modelBuilder.addFragment(geometryId, 'MyCustomMaterial', transform);

It throws the same error when calling 'modelBuilder.addGeometry(geometry)'


Solution

  • It looks like there's an error in your code snippet. While you are converting your THREE.Geometry object into THREE.BufferGeometry object (required by Forge Viewer), you are passing the wrong variable into the modelBuilder.addGeometry method.

    Try replacing

    const geometryId = modelBuilder.addGeometry(geometry);
    

    with

    const geometryId = modelBuilder.addGeometry(bufferGeometry);