Hello,
We are using rhino3dm to compress and decompress meshes. We ran into an issue the other day where the app crashed with no error message. When using the debugger we could see this error message: Uncaught RuntimeError: memory access out of bounds
The decompress method has never produced an issue like this. We have also used compress before but then there was only one mesh with the same rhino3dm instance. In this situation we compressed 3 meshes with the same instance and on the fourth the error occured.
Our code then looked like this:
// This is any since the library has incorrect type declarations
private rhinoInstance: any
private async getRhinoInstance() {
if (this.rhinoInstance) return this.rhinoInstance
this.rhinoInstance = await rhino3dm()
return this.rhinoInstance
}
/**
* Converts a three mesh into a base64 string using draco compression
*/
async compressThreeMesh(threeMesh: THREE.Mesh): Promise<string> {
const rhino = await this.getRhinoInstance()
const bufferGeometry = threeMesh.geometry.clone().rotateX((3 * Math.PI) / 2)
bufferGeometry.computeVertexNormals()
let rhinoMesh = rhino.Mesh.createFromThreejsJSON({ data: bufferGeometry })
const jsonMesh = rhinoMesh.encode()
rhinoMesh = rhino.CommonObject.decode(jsonMesh)
const compressed = rhino.DracoCompression.compress(rhinoMesh).toBase64String()
return compressed
}
When researching this we found a similar issue with a user of three JS: Unsafe to reuse a Decoder instance · Issue #656 · google/draco · GitHub
We then tested this by creating a new rhino instance for each call:
// This is any since the library has incorrect type declarations
private rhinoInstance: any
private async getRhinoInstance() {
// New instance for every call
return await rhino3dm()
}
/**
* Converts a three mesh into a base64 string using draco compression
*/
async compressThreeMesh(threeMesh: THREE.Mesh): Promise<string> {
const rhino = await this.getRhinoInstance()
const bufferGeometry = threeMesh.geometry.clone().rotateX((3 * Math.PI) / 2)
bufferGeometry.computeVertexNormals()
let rhinoMesh = rhino.Mesh.createFromThreejsJSON({ data: bufferGeometry })
const jsonMesh = rhinoMesh.encode()
rhinoMesh = rhino.CommonObject.decode(jsonMesh)
const compressed = rhino.DracoCompression.compress(rhinoMesh).toBase64String()
return compressed
}
With this change we don’t run into this issue anymore.
Now the questions is: What is the best practices for this? Is this solution feasible? Could there be a memory leak in the rhino3dm.wasm binary?