Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop while loading xkt file #1515

Open
lzoia-bc opened this issue May 31, 2024 · 2 comments
Open

Infinite loop while loading xkt file #1515

lzoia-bc opened this issue May 31, 2024 · 2 comments
Labels
good first issue Good for newcomers
Milestone

Comments

@lzoia-bc
Copy link
Contributor

Describe the bug
While loading a big xkt file using the xeokitSdk.XKTLoaderPlugin the load method entered into an infinite loop.
After debugging the issue, I found out that the code got stuck in this loop inside the _getVBOBatchingLayer method of the SceneModel class:

while (!vboBatchingLayer) {
	switch (cfg.primitive) {
		case "triangles":
			// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);
			vboBatchingLayer = new VBOBatchingTrianglesLayer({
				model,
				textureSet,
				layerIndex: 0, // This is set in #finalize()
				scratchMemory: this._vboBatchingLayerScratchMemory,
				positionsDecodeMatrix: cfg.positionsDecodeMatrix,  // Can be undefined
				uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
				origin,
				maxGeometryBatchSize: this._maxGeometryBatchSize,
				solid: (cfg.primitive === "solid"),
				autoNormals: true
			});
			break;
		case "solid":
			// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);
			vboBatchingLayer = new VBOBatchingTrianglesLayer({
				model,
				textureSet,
				layerIndex: 0, // This is set in #finalize()
				scratchMemory: this._vboBatchingLayerScratchMemory,
				positionsDecodeMatrix: cfg.positionsDecodeMatrix,  // Can be undefined
				uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
				origin,
				maxGeometryBatchSize: this._maxGeometryBatchSize,
				solid: (cfg.primitive === "solid"),
				autoNormals: true
			});
			break;
		case "surface":
			// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);
			vboBatchingLayer = new VBOBatchingTrianglesLayer({
				model,
				textureSet,
				layerIndex: 0, // This is set in #finalize()
				scratchMemory: this._vboBatchingLayerScratchMemory,
				positionsDecodeMatrix: cfg.positionsDecodeMatrix,  // Can be undefined
				uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
				origin,
				maxGeometryBatchSize: this._maxGeometryBatchSize,
				solid: (cfg.primitive === "solid"),
				autoNormals: true
			});
			break;
		case "lines":
			// console.info(`[SceneModel ${this.id}]: creating VBOBatchingLinesLayer`);
			vboBatchingLayer = new VBOBatchingLinesLayer({
				model,
				layerIndex: 0, // This is set in #finalize()
				scratchMemory: this._vboBatchingLayerScratchMemory,
				positionsDecodeMatrix: cfg.positionsDecodeMatrix,  // Can be undefined
				uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
				origin,
				maxGeometryBatchSize: this._maxGeometryBatchSize
			});
			break;
		case "points":
			// console.info(`[SceneModel ${this.id}]: creating VBOBatchingPointsLayer`);
			vboBatchingLayer = new VBOBatchingPointsLayer({
				model,
				layerIndex: 0, // This is set in #finalize()
				scratchMemory: this._vboBatchingLayerScratchMemory,
				positionsDecodeMatrix: cfg.positionsDecodeMatrix,  // Can be undefined
				uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
				origin,
				maxGeometryBatchSize: this._maxGeometryBatchSize
			});
			break;
	}
	const lenPositions = cfg.positionsCompressed ? cfg.positionsCompressed.length : cfg.positions.length;
	const canCreatePortion = (cfg.primitive === "points")
		? vboBatchingLayer.canCreatePortion(lenPositions)
		: vboBatchingLayer.canCreatePortion(lenPositions, cfg.indices.length);
	if (!canCreatePortion) {
		vboBatchingLayer.finalize();
		delete this._vboBatchingLayers[layerId];
		vboBatchingLayer = null;
	}
}

It seems that if the requested geometry doesn't pass the canCreatePortion check the code goes into infinite loop.

Steps to reproduce the behavior:

  1. Load a xkt file large enough to not pass the canCreatePortion check

Expected behavior
The falsy case should be handled properly. Worst scenario could be raise a proper error

Desktop:

  • OS: Windows
  • Browser Chrome
  • Version 2.6.6 (Before opening the bug, I also checked and the code is the same also in newer versions)
@xeolabs
Copy link
Member

xeolabs commented May 31, 2024

Right, we've probably never hit this condition because we're always splitting conversion into multiple smaller XKT files (like here).

BTW if that loop never ends, then it means WebGL is out of memory for your model, a dire situation, but we'll at least be optimistic and add a recovery attempt of some sort.

Are you able to provide your XKT file so we can test the fix?

@xeolabs xeolabs added the good first issue Good for newcomers label May 31, 2024
@xeolabs xeolabs added this to the 2.6.0 milestone May 31, 2024
@lzoia-bc
Copy link
Contributor Author

lzoia-bc commented Jun 3, 2024

Unfortunately we can't share with you the XKT files because they cannot be disclosed as they are property of a client.
If you want, we can still test your fixes in our environment before releasing.

If it cab be helpful, those files were working with the 2.3.5 version of @xeokit/xeokit-sdk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants