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)'
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);