Skip to content

Commit

Permalink
refactor: implement physics debug
Browse files Browse the repository at this point in the history
### Description

- Move out of the core the `Physics` helper
  - Register it in the dependency container
- Add debug module
  - Implement physics debug
- Add new turbo env to the dev process
  - use vite `import.meta.env?.DEV` env as debug mode checker
  • Loading branch information
Neosoulink committed Aug 20, 2024
1 parent 8a915ea commit 288962c
Show file tree
Hide file tree
Showing 14 changed files with 137 additions and 40 deletions.
4 changes: 3 additions & 1 deletion apps/web/src/common/models/piece.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Subject } from "rxjs";
import type { BoardCoords, PieceId } from "../interfaces";
import { ColorVariant, PieceType } from "../enums";
import { MATRIX, QUATERNION, SCALE, VECTOR } from "../constants";
import { PhysicsProperties } from "@chess-d/rapier-physics/dist/types";

export class PieceModel<
T extends PieceType = PieceType,
Expand All @@ -18,6 +19,7 @@ export class PieceModel<
public readonly id: PieceId,
public readonly type: T,
public readonly color: C,
public readonly physics: PhysicsProperties,
public readonly promotedFromType?: PieceType
) {
super();
Expand All @@ -39,7 +41,7 @@ export class PieceModel<
MATRIX.decompose(VECTOR, QUATERNION, SCALE);
VECTOR.setY(VECTOR.y + yOffset);

this.setPosition(VECTOR);
this.physics.rigidBody.setTranslation(VECTOR, true);
this.update$$.next(this);
}
}
25 changes: 23 additions & 2 deletions apps/web/src/common/models/pieces-group.model.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { BufferGeometry, DynamicDrawUsage, InstancedMesh } from "three";
import { Subject, Subscription } from "rxjs";
import { Physics } from "@chess-d/rapier-physics";

import { ColorVariant, PieceType } from "../enums";
import { PieceModel } from "./piece.model";
import { COLOR_BLACK, COLOR_WHITE } from "../constants";
import { BoardCoords, PieceId } from "../interfaces";
import { PhysicsProperties } from "@chess-d/rapier-physics/dist/types";

export class PiecesGroupModel<
type extends PieceType,
Expand All @@ -16,20 +18,37 @@ export class PiecesGroupModel<
public readonly pieceMoved$$ = new Subject<PieceModel<type, color>>();

constructor(
private readonly physics: Physics,
public readonly piecesType: type,
public readonly piecesColor: color,
count: PieceId,
geometry: BufferGeometry,
pieces?: Record<PieceId, PieceModel<type, color>>
) {
super(geometry, undefined, count);

const physicsProperties = this.physics.addToWorld(
this,
1
) as PhysicsProperties[];

this.instanceMatrix.setUsage(DynamicDrawUsage);

(pieces ? Object.keys(pieces) : Array.from(Array(this.count))).forEach(
(pieceKey: number, i) => {
const oldPiece = pieces?.[pieceKey];
const piecePhysicsProperties = physicsProperties[
i
] as PhysicsProperties;

const piece =
oldPiece ?? new PieceModel(i, this.piecesType, this.piecesColor);
oldPiece ??
new PieceModel(
i,
this.piecesType,
this.piecesColor,
piecePhysicsProperties
);
piece.index = i;

this.setMatrixAt(i, piece);
Expand Down Expand Up @@ -72,9 +91,11 @@ export class PiecesGroupModel<
// const width = boundingBox.max.x - boundingBox.min.x;
const height = boundingBox.max.y - boundingBox.min.y;

this.pieces[id]?.setCoords(board, coords, height / 2);
this.pieces[id]?.setCoords(board, coords, height / 2 + 2);
}
}

return this.pieces[id];
}

public update() {
Expand Down
14 changes: 6 additions & 8 deletions apps/web/src/core/chess-board/chess-board.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import "reflect-metadata";
import { inject, singleton } from "tsyringe";
import { Color, InstancedMesh, PlaneGeometry } from "three";
import { PhysicsProperties } from "@chess-d/rapier-physics/dist/types";
import { Physics } from "@chess-d/rapier-physics";

import { BoardCell } from "../../common";
import { CoreComponent } from "../core.component";

@singleton()
export class ChessBoardComponent {
Expand All @@ -31,20 +31,18 @@ export class ChessBoardComponent {
.clone()
.setHex(this.whiteAccent.getHex() * Math.random());

public physicsBody?: PhysicsProperties;
public physics!: PhysicsProperties;

constructor(
@inject(CoreComponent) private readonly coreComponent: CoreComponent
) {}
constructor(@inject(Physics) private readonly _physics: Physics) {}

public init() {
this.board.name = ChessBoardComponent.name;

this.board.userData = {
...this.board.userData,
useBoundingBox: true
};

this.physicsBody = this.coreComponent.physics?.addToWorld(
this.board
) as PhysicsProperties;
this.physics = this._physics?.addToWorld(this.board) as PhysicsProperties;
}
}
2 changes: 1 addition & 1 deletion apps/web/src/core/chess-board/chess-board.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class ChessBoardModule implements Module {
-this.component.halfSize
);

this.component.physicsBody?.rigidBody.setTranslation(
this.component.physics?.rigidBody.setTranslation(
{ x: this.component.halfSize, y: 0, z: -this.component.halfSize },
true
);
Expand Down
7 changes: 0 additions & 7 deletions apps/web/src/core/core.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import "reflect-metadata";

import { singleton } from "tsyringe";
import { RapierPhysics } from "@chess-d/rapier-physics";

@singleton()
export class CoreComponent {
public physics!: Awaited<ReturnType<typeof RapierPhysics>>;

constructor() {}

public async init() {
this.physics = await RapierPhysics();
}

public dispose() {}
}
8 changes: 1 addition & 7 deletions apps/web/src/core/core.controller.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import "reflect-metadata";
import { Subject } from "rxjs";

import { Subject } from "rxjs";
import { singleton } from "tsyringe";

@singleton()
export class CoreController {
public readonly gui$$ = new Subject<any>();

constructor() {}

public init() {}

public dispose() {}
}
22 changes: 14 additions & 8 deletions apps/web/src/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { GameModule } from "./game/game.module";
import { WorldModule } from "./world/world.module";
import { ChessBoardModule } from "./chess-board/chess-board.module";
import { PiecesModule } from "./pieces/pieces.module";
import { DebugModule } from "./debug/debug.module";
import { Physics } from "@chess-d/rapier-physics";

@singleton()
export class CoreModule implements Module {
Expand All @@ -22,29 +24,32 @@ export class CoreModule implements Module {
@inject(ChessBoardModule)
private readonly chessBoardModule: ChessBoardModule,
@inject(PiecesModule)
private readonly piecesModule: PiecesModule
private readonly piecesModule: PiecesModule,
@inject(DebugModule) private readonly debugModule: DebugModule,
@inject(Physics) private readonly physics: Physics
) {
this.appModule.camera.instance()?.position.set(0, 5, -5);
this.appModule.camera.miniCamera()?.position.set(2, 5, -6);

this.init();

this.appModule.timer.step$().subscribe(() => {
this.physics.step();
});

self.onmessage = (e: MessageEvent) => {
if ((e.data?.type as string)?.startsWith("pawn"))
controller.gui$$.next(e.data);
};

this.appModule.timer.step$().subscribe(() => {
this.component.physics?.step();
});
this.init();
}

public async init() {
await this.component.init();
public init() {
this.resourceModule.init();
this.worldModule.init();
this.gameModule.init();
this.chessBoardModule.init();
this.piecesModule.init();
this.debugModule.init();
}

public dispose() {
Expand All @@ -54,5 +59,6 @@ export class CoreModule implements Module {
this.chessBoardModule.dispose();
this.piecesModule.dispose();
this.appModule.dispose();
this.debugModule.dispose();
}
}
5 changes: 4 additions & 1 deletion apps/web/src/core/core.util.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { container } from "tsyringe";
import { isObject } from "@quick-threejs/utils";
import { AppModule } from "@quick-threejs/reactive";
import { Physics, RapierPhysics } from "@chess-d/rapier-physics";

import { CoreModule } from "./core.module";

export const setupCoreModule = (app: AppModule) => {
export const setupCoreModule = async (app: AppModule) => {
if (!isObject(app))
throw new Error("Unable to retrieve the application context.");

container.register(AppModule, { useValue: app });
container.register(Physics, { useValue: await RapierPhysics() });

return container.resolve<CoreModule>(CoreModule);
};
10 changes: 10 additions & 0 deletions apps/web/src/core/debug/debug.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BufferGeometry, LineSegments, MeshBasicMaterial } from "three";
import { singleton } from "tsyringe";

@singleton()
export class DebugComponent {
public readonly lines = new LineSegments(
new BufferGeometry(),
new MeshBasicMaterial({ color: 0xff40f0 })
);
}
24 changes: 24 additions & 0 deletions apps/web/src/core/debug/debug.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { inject, singleton } from "tsyringe";
import { filter, map, Observable } from "rxjs";
import { AppModule } from "@quick-threejs/reactive";
import { Physics } from "@chess-d/rapier-physics";

import { DebugComponent } from "./debug.component";

@singleton()
export class DebugController {
public readonly physicsDebugRender$: Observable<
InstanceType<Physics["rapier"]["DebugRenderBuffers"]>
>;

constructor(
@inject(AppModule) private readonly appModule: AppModule,
@inject(DebugComponent) private readonly component: DebugComponent,
@inject(Physics) private readonly _physics: Physics
) {
this.physicsDebugRender$ = this.appModule.timer.step$().pipe(
filter(() => !!this.appModule?.debug?.enabled),
map(() => this._physics.world.debugRender())
);
}
}
37 changes: 37 additions & 0 deletions apps/web/src/core/debug/debug.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { inject, singleton } from "tsyringe";
import { BufferAttribute } from "three";
import { AppModule, Module } from "@quick-threejs/reactive";

import { DebugComponent } from "./debug.component";
import { DebugController } from "./debug.controller";

@singleton()
export class DebugModule implements Module {
constructor(
@inject(DebugComponent) private readonly component: DebugComponent,
@inject(DebugController) private readonly controller: DebugController,
@inject(AppModule) private readonly appModule: AppModule
) {
if (this.appModule.debug.enabled())
appModule.world.scene().add(this.component.lines);

this.controller.physicsDebugRender$.subscribe({
next: (buffers) => {
this.component.lines.geometry.setAttribute(
"position",
new BufferAttribute(buffers.vertices, 3)
);
this.component.lines.geometry.setAttribute(
"color",
new BufferAttribute(buffers.colors, 4)
);
}
});
}

init(): void {}

dispose(): void {
throw new Error("Method not implemented.");
}
}
8 changes: 4 additions & 4 deletions apps/web/src/core/pieces/pieces.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { inject, singleton } from "tsyringe";
import { BufferGeometry } from "three";
import { Physics } from "@chess-d/rapier-physics";

import {
PiecesGroupModel,
Expand All @@ -8,8 +10,6 @@ import {
} from "../../common";
import { ChessBoardComponent } from "../chess-board/chess-board.component";
import { ResourceComponent } from "../resource/resource.component";
import { CoreComponent } from "../core.component";
import { BufferGeometry } from "three";

@singleton()
export class PiecesComponent {
Expand All @@ -20,7 +20,7 @@ export class PiecesComponent {
private readonly chessBoardComponent: ChessBoardComponent,
@inject(ResourceComponent)
private readonly resourceComponent: ResourceComponent,
@inject(CoreComponent) private readonly coreComponent: CoreComponent
@inject(Physics) private readonly _physics: Physics
) {}

private _initPawns<Color extends ColorVariant>(color: Color) {
Expand Down Expand Up @@ -188,7 +188,7 @@ export class PiecesComponent {
pieces?: PiecesGroupModel<Type, Color>["pieces"]
) {
return new PiecesGroupModel(
this.coreComponent.physics,
this._physics,
type,
color,
count,
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import "./assets/styles/main.css";

register({
location: new URL("./main.worker.ts", import.meta.url) as unknown as string,
enableDebug: true,
enableDebug: !!import.meta.env?.DEV,
axesSizes: 5,
gridSizes: 10,
withMiniCamera: true,
Expand Down
9 changes: 9 additions & 0 deletions apps/web/turbo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://turborepo.org/schema.json",
"extends": ["//"],
"tasks": {
"dev": {
"env": ["DEV"]
}
}
}

0 comments on commit 288962c

Please sign in to comment.