diff --git a/public/ship1.glb b/public/ship1.glb index ab61fba..af17b15 100644 Binary files a/public/ship1.glb and b/public/ship1.glb differ diff --git a/src/levelDeserializer.ts b/src/levelDeserializer.ts index 6d9e4ea..6986f0f 100644 --- a/src/levelDeserializer.ts +++ b/src/levelDeserializer.ts @@ -138,9 +138,11 @@ export class LevelDeserializer { const sunPosition = this.arrayToVector3(this.config.sun.position); for (const planetConfig of this.config.planets) { + // Use fewer segments for better performance - planets are background objects + // 16 segments = ~256 vertices vs 32 segments = ~1024 vertices const planet = MeshBuilder.CreateSphere(planetConfig.name, { diameter: planetConfig.diameter, - segments: 32 + segments: 12 // Reduced from 32 for performance }, this.scene); const planetPosition = this.arrayToVector3(planetConfig.position); @@ -156,7 +158,7 @@ export class LevelDeserializer { // Create lightmap with bright light pointing toward sun const lightmap = createSphereLightmap( planetConfig.name + "-lightmap", - 512, // texture size + 256, // texture size DefaultScene.MainScene, toSun, // bright light from sun direction 1, // bright intensity diff --git a/src/scoreboard.ts b/src/scoreboard.ts index e080592..515f7d7 100644 --- a/src/scoreboard.ts +++ b/src/scoreboard.ts @@ -21,11 +21,7 @@ export class Scoreboard { private _done = false; public readonly onScoreObservable: Observable = new Observable(); constructor() { - DefaultScene.MainScene.onNewMeshAddedObservable.add((mesh) => { - if (mesh.id == 'RightUpperDisplay') { - this.initialize(); - } - }); + this.initialize(); } public get done() { return this._done; @@ -39,18 +35,20 @@ export class Scoreboard { private initialize() { const scene = DefaultScene.MainScene; - const parent = scene.getMeshById('RightUpperDisplay'); + const parent = scene.getNodeById('ship'); + console.log('Scoreboard parent:', parent); + console.log('Initializing scoreboard'); const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene); scoreboard.renderingGroupId = 3; const material = new StandardMaterial("scoreboard", scene); scoreboard.parent =parent; - scoreboard.position.x = -.76; - scoreboard.position.y = 4.19; - scoreboard.position.z = .53; - scoreboard.rotation.x = Angle.FromDegrees(104).radians(); - scoreboard.rotation.z = Math.PI; - scoreboard.scaling = new Vector3(.3, .3, .3); + + scoreboard.position.y = 1.05; + scoreboard.position.z = 2.1; + scoreboard.visibility = .5; + + scoreboard.scaling = new Vector3(.4, .4, .4); const advancedTexture = AdvancedDynamicTexture.CreateForMesh(scoreboard, 512, 512); advancedTexture.background = "black"; diff --git a/src/ship.ts b/src/ship.ts index 0bff303..a9e13a0 100644 --- a/src/ship.ts +++ b/src/ship.ts @@ -123,6 +123,14 @@ export class Ship { public set position(newPosition: Vector3) { const body = this._ship.physicsBody; + + // Physics body might not exist yet if called before initialize() completes + if (!body) { + // Just set position directly on transform node + this._ship.position.copyFrom(newPosition); + return; + } + body.disablePreStep = false; body.transformNode.position.copyFrom(newPosition); DefaultScene.MainScene.onAfterRenderObservable.addOnce(() => { @@ -150,17 +158,9 @@ export class Ship { //const landingLight = new SpotLight("landingLight", new Vector3(0, 0, 0), new Vector3(0, -.5, .5), 1.5, .5, DefaultScene.MainScene); // landingLight.parent = this._ship; // landingLight.position.z = 5; - const agg = new PhysicsAggregate(this._ship, PhysicsShapeType.BOX, { - mass: 100, - extents: new Vector3(4, 4, 7.4), - center: new Vector3(0, 1, 1.8) - }, DefaultScene.MainScene); - agg.body.setMotionType(PhysicsMotionType.DYNAMIC); - agg.body.setLinearDamping(.1); - agg.body.setAngularDamping(.2); - agg.body.setAngularVelocity(new Vector3(0, 0, 0)); - agg.body.setCollisionCallbackEnabled(true); + // Physics will be set up after mesh loads in initialize() + this.setupKeyboard(); this.setupMouse(); this._controllerObservable.add(this.controllerCallback); @@ -201,6 +201,40 @@ export class Ship { shipMesh.id = "shipMesh"; shipMesh.name = "shipMesh"; shipMesh.parent = this._ship; + + // Create physics aggregate based on the loaded mesh + // Find the actual geometry mesh (usually meshes[1] or a child) + //const geometryMesh = importMesh.meshes.find(m => m instanceof Mesh && m.getTotalVertices() > 0) as Mesh; + const geo = shipMesh.getChildMeshes()[0] + if (geo) { + + + // Create physics aggregate on the ship TransformNode using the mesh shape + const agg = new PhysicsAggregate(this._ship, PhysicsShapeType.CONVEX_HULL, { + mass: 100, + mesh: (geo as Mesh) // Use the actual ship geometry + }, DefaultScene.MainScene); + + agg.body.setMotionType(PhysicsMotionType.DYNAMIC); + agg.body.setLinearDamping(.1); + agg.body.setAngularDamping(.2); + agg.body.setAngularVelocity(new Vector3(0, 0, 0)); + agg.body.setCollisionCallbackEnabled(true); + } else { + console.warn("No geometry mesh found in ship1.glb, falling back to box shape"); + // Fallback to box shape if mesh not found + const agg = new PhysicsAggregate(this._ship, PhysicsShapeType.BOX, { + mass: 100, + extents: new Vector3(4, 4, 7.4), + center: new Vector3(0, 1, 1.8) + }, DefaultScene.MainScene); + + agg.body.setMotionType(PhysicsMotionType.DYNAMIC); + agg.body.setLinearDamping(.1); + agg.body.setAngularDamping(.2); + agg.body.setAngularVelocity(new Vector3(0, 0, 0)); + agg.body.setCollisionCallbackEnabled(true); + } //shipMesh.rotation.y = Angle.FromDegrees(90).radians(); //shipMesh.rotation.y = Math.PI; //shipMesh.position.y = 1;