Create mesh-based physics for ship and optimize planet geometry
Some checks failed
Build / build (push) Failing after 18s
Some checks failed
Build / build (push) Failing after 18s
- Update Ship class to use CONVEX_HULL physics from ship1.glb - Find geometry mesh from loaded GLB and create physics from it - Move physics creation to initialize() after mesh loads - Add fallback to BOX shape if mesh not found - Fix ship position setter for async initialization - Add null check for physics body - Set transform position directly if body doesn't exist yet - Prevents crash when position set before mesh loads - Optimize planet vertex count for performance - Reduce sphere segments from 32 to 12 - ~144 vertices vs ~1024 vertices per planet - Planets are background objects, lower poly acceptable - Update ship1.glb model 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a9054c2389
commit
03f170e150
BIN
public/ship1.glb
BIN
public/ship1.glb
Binary file not shown.
@ -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
|
||||
|
||||
@ -21,12 +21,8 @@ export class Scoreboard {
|
||||
private _done = false;
|
||||
public readonly onScoreObservable: Observable<ScoreEvent> = new Observable<ScoreEvent>();
|
||||
constructor() {
|
||||
DefaultScene.MainScene.onNewMeshAddedObservable.add((mesh) => {
|
||||
if (mesh.id == 'RightUpperDisplay') {
|
||||
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";
|
||||
|
||||
54
src/ship.ts
54
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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user