Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions example/babylonjs/googleMapsAerial.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as BABYLON from 'babylonjs';
import { Scene, Engine, Vector3, ArcRotateCamera } from '@babylonjs';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to import from @babylonjs/core?

import { TilesRenderer } from '3d-tiles-renderer/babylonjs';
import { CesiumIonAuthPlugin } from '3d-tiles-renderer/core/plugins';
import GUI from 'lil-gui';
Expand All @@ -19,27 +19,27 @@ gui.add( params, 'errorTarget', 1, 100 );

// engine
const canvas = document.getElementById( 'renderCanvas' );
const engine = new BABYLON.Engine( canvas, true );
const engine = new Engine( canvas, true );
engine.setHardwareScalingLevel( 1 / window.devicePixelRatio );

// scene
const scene = new BABYLON.Scene( engine );
const scene = new Scene( engine );
scene.useRightHandedSystem = true;

// camera
const camera = new BABYLON.ArcRotateCamera(
const camera = new ArcRotateCamera(
'camera',
- Math.PI / 2,
Math.PI / 3,
100000,
new BABYLON.Vector3( 0, 0, 0 ),
new Vector3( 0, 0, 0 ),
scene,
);
camera.attachControl( canvas, true );
camera.minZ = 1;
camera.maxZ = 1e7;
camera.wheelPrecision = 0.25;
camera.setPosition( new BABYLON.Vector3( 500, 300, - 500 ) );
camera.setPosition( new Vector3( 500, 300, - 500 ) );

// tiles
const tiles = new TilesRenderer( null, scene );
Expand Down
13 changes: 8 additions & 5 deletions example/babylonjs/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as BABYLON from 'babylonjs';
import { Engine, Scene, ArcRotateCamera, Vector3 } from '@babylonjs/core'
import { TilesRenderer } from '3d-tiles-renderer/babylonjs';
import GUI from 'lil-gui';

Expand All @@ -16,21 +16,21 @@ gui.add( params, 'visibleTiles' ).listen().disable();

// init engine
const canvas = document.getElementById( 'renderCanvas' );
const engine = new BABYLON.Engine( canvas, true );
const engine = new Engine( canvas, true );
engine.setHardwareScalingLevel( 1 / window.devicePixelRatio );

// TODO: Babylon uses left handed coordinate system but our data is in a right handed one.
// The coordinate system flag may need to be accounted for when parsing the data
const scene = new BABYLON.Scene( engine );
const scene = new Scene( engine );
scene.useRightHandedSystem = true;

// Camera controls
const camera = new BABYLON.ArcRotateCamera(
const camera = new ArcRotateCamera(
'camera',
- Math.PI / 2,
Math.PI / 2.5,
50,
new BABYLON.Vector3( 0, 0, 0 ),
new Vector3( 0, 0, 0 ),
scene,
);
camera.attachControl( canvas, true );
Expand All @@ -40,6 +40,9 @@ camera.maxZ = 1000;
// instantiate tiles renderer and orient the group so it's Z+ down
const tiles = new TilesRenderer( TILESET_URL, scene );
tiles.group.rotation.x = Math.PI / 2;
tiles.addEventListener('load-tileset', ( tileset ) => {
console.log('tileset loaded!');
});

// render
scene.onBeforeRenderObservable.add( () => {
Expand Down
43 changes: 34 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@
"@types/three": "^0.170.0",
"@vitejs/plugin-react": "^4.3.2",
"@vitest/eslint-plugin": "^1.5.1",
"babylonjs": "^7.0.0",
"babylonjs-loaders": "^7.0.0",
"@babylonjs/core": "^8.39.3",
"@babylonjs/loaders": "^8.39.3",
Comment on lines -94 to +95
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's update the "peerDependencies" section, too. I'll let you decide which versions are needed for the current babylon support but >=8.0.0 seem reasonable to me.

"cesium": "^1.132.0",
"concurrently": "^6.2.1",
"eslint": "^9.0.0",
Expand Down
8 changes: 4 additions & 4 deletions src/babylonjs/renderer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ Implementation of the TilesRendererBase class for Babylon js.
# Use

```js
import * as BABYLON from 'babylonjs';
import { Engine, Scene } from '@babylonjs/core';
import { TilesRenderer } from '3d-tiles-renderer/babylonjs';

// create engine
const canvas = document.getElementById( 'renderCanvas' );
const engine = new BABYLON.Engine( canvas, true );
const engine = new Engine( canvas, true );

// right handed coordinate system is required
const scene = new BABYLON.Scene( engine );
const scene = new Scene( engine );
scene.useRightHandedSystem = true;

// create the babylon tile renderer
const tiles = new BabylonTilesRenderer( TILESET_URL, scene );
const tiles = new TilesRenderer( TILESET_URL, scene );

// ... initialize the camera

Expand Down
69 changes: 60 additions & 9 deletions src/babylonjs/renderer/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { LoaderBase } from '3d-tiles-renderer/core';
import { Matrix, Quaternion, SceneLoader } from 'babylonjs';
import 'babylonjs-loaders';
import { Matrix, Quaternion, ImportMeshAsync } from '@babylonjs/core';
import "@babylonjs/loaders/glTF/2.0";

// GLB magic bytes: "glTF" in ASCII (0x67, 0x6C, 0x54, 0x46)
const GLB_MAGIC = 0x46546C67;
const _worldMatrix = /* @__PURE__ */ Matrix.Identity();

export class GLTFLoader extends LoaderBase {

constructor( scene ) {
Expand All @@ -13,6 +16,57 @@ export class GLTFLoader extends LoaderBase {

}

/**
* Detect if buffer contains GLB binary data by checking magic bytes
* @param {ArrayBuffer|Uint8Array} buffer - The file buffer
* @returns {boolean} True if GLB format
*/
isGLB( buffer ) {

// Handle both ArrayBuffer and typed arrays (e.g., Uint8Array)
const arrayBuffer = buffer instanceof ArrayBuffer ? buffer : buffer.buffer;
const byteOffset = buffer instanceof ArrayBuffer ? 0 : buffer.byteOffset;
const byteLength = buffer.byteLength;

if ( byteLength < 4 ) {

return false;

}

const view = new DataView( arrayBuffer, byteOffset, byteLength );
const magic = view.getUint32( 0, true ); // little-endian
return magic === GLB_MAGIC;

}
Comment on lines +19 to +41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be sure: there's no way for Babylon to determine whether a file is a binary or ascii glTF automatically?


/**
* Detect file extension from URI or buffer content
* @param {ArrayBuffer} buffer - The file buffer
* @param {string} uri - The file URI
* @returns {string} '.glb' or '.gltf'
*/
detectExtension( buffer, uri ) {

// First check magic bytes in buffer (most reliable)
if ( this.isGLB( buffer ) ) {

return '.glb';

}

// Fallback to URI extension
const lowerUri = uri.toLowerCase();
if ( lowerUri.endsWith( '.glb' ) ) {

return '.glb';

}

// Default to gltf
return '.gltf';
}

async parse( buffer, uri ) {

const { scene, workingPath, adjustmentTransform } = this;
Expand All @@ -25,18 +79,15 @@ export class GLTFLoader extends LoaderBase {

}

// Detect format from buffer magic bytes or URI extension
const pluginExtension = this.detectExtension( buffer, uri );
// Use unique filename to prevent texture caching issues
// TODO: What is the correct method for loading gltf files in babylon?
const container = await SceneLoader.LoadAssetContainerAsync(
rootUrl,
const container = await ImportMeshAsync(
new File( [ buffer ], uri ),
scene,
null,
'.glb',
{ pluginExtension }
);

container.addAllToScene();

// retrieve the primary scene
const root = container.meshes[ 0 ];

Expand Down
57 changes: 52 additions & 5 deletions src/babylonjs/renderer/tiles/TilesRenderer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TilesRendererBase, LoaderUtils } from '3d-tiles-renderer/core';
import { Matrix, Vector3, Plane, TransformNode, Frustum } from 'babylonjs';
import { TransformNode, Matrix, Vector3, Frustum, Observable, Plane } from '@babylonjs/core';
import { B3DMLoader } from '../loaders/B3DMLoader.js';
import { GLTFLoader } from '../loaders/GLTFLoader.js';
import { TileBoundingVolume } from '../math/TileBoundingVolume.js';
Expand All @@ -19,15 +19,62 @@ export class TilesRenderer extends TilesRendererBase {
this.scene = scene;
this.group = new TransformNode( 'tiles-root', scene );
this._upRotationMatrix = Matrix.Identity();

// Babylon.js Observables for events
this._observables = new Map();

}

// TODO: implement these with Babylon constructs
addEventListener() {}
/**
* Get or create an observable for the given event type
* @param {string} type - Event type name
* @returns {Observable} The observable for this event type
*/
getObservable( type ) {

removeEventListener() {}
if ( ! this._observables.has( type ) ) {

dispatchEvent() {}
this._observables.set( type, new Observable() );

}

return this._observables.get( type );

}

// Event handling - adapter for TilesRendererBase using Babylon Observables
addEventListener( type, listener ) {

const observable = this.getObservable( type );
observable.add( listener );

}

removeEventListener( type, listener ) {

if ( ! this._observables.has( type ) ) {

return;

}

const observable = this._observables.get( type );
observable.removeCallback( listener );

}

dispatchEvent( event ) {

if ( ! this._observables.has( event.type ) ) {

return;

}

const observable = this._observables.get( event.type );
observable.notifyObservers( event );

}

loadRootTileset( ...args ) {

Expand Down