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

V3.8.2 physics debug draw #16208

Closed
wants to merge 13 commits into from
3 changes: 2 additions & 1 deletion cocos/physics/bullet/bullet-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/

import { Collider, TriggerEventType, CollisionEventType, IContactEquation, CharacterController } from '../../../exports/physics-framework';
import { Vec3, Quat, Mat4 } from '../../core';
import { Vec3, Quat, Mat4, Color } from '../../core';
import { CharacterTriggerEventType } from '../framework';
import { bt } from './instantiated';

Expand Down Expand Up @@ -88,5 +88,6 @@ export const CC_QUAT_0 = new Quat();
export const CC_QUAT_1 = new Quat();
export const CC_MAT4_0 = new Mat4();
export const CC_MAT4_1 = new Mat4();
export const CC_COLOR_0 = new Color();

bt.CACHE = BulletCache;
17 changes: 17 additions & 0 deletions cocos/physics/bullet/bullet-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,21 @@ export const importFunc = {
const cct = bt.CACHE.getWrapper(controller, bt.CCT_CACHE_NAME);
cct.onShapeHitExt(hit);
},
onDebugDrawLine (from: number, to: number, color: number): void {
const bt = globalThis.Bullet;
const world = bt.CACHE.world;
if (world) {
world.onDebugDrawLine(from, to, color);
}
},
onClearLines (): void {
const bt = globalThis.Bullet;
const world = bt.CACHE.world;
if (world) {
world.onClearLines();
}
},
onFlushLines (): void {
//empty
},
};
99 changes: 95 additions & 4 deletions cocos/physics/bullet/bullet-world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,24 @@ import { BulletRigidBody } from './bullet-rigid-body';
import { BulletShape } from './shapes/bullet-shape';
import { ArrayCollisionMatrix } from '../utils/array-collision-matrix';
import { TupleDictionary } from '../utils/tuple-dictionary';
import { TriggerEventObject, CollisionEventObject, CC_V3_0, CC_V3_1, CC_V3_2, BulletCache, CharacterTriggerEventObject } from './bullet-cache';
import { TriggerEventObject, CollisionEventObject, CC_V3_0, CC_V3_1, CC_V3_2, CC_COLOR_0, BulletCache, CharacterTriggerEventObject } from './bullet-cache';
import { bullet2CocosVec3, cocos2BulletQuat, cocos2BulletVec3 } from './bullet-utils';
import { IRaycastOptions, IPhysicsWorld } from '../spec/i-physics-world';
import { PhysicsRayResult, PhysicsMaterial, CharacterControllerContact } from '../framework';
import { error, RecyclePool, Vec3, js, IVec3Like, geometry, IQuatLike, Quat } from '../../core';
import { PhysicsRayResult, PhysicsMaterial, CharacterControllerContact, EPhysicsDrawFlags } from '../framework';
import { error, RecyclePool, Vec3, js, IVec3Like, geometry, IQuatLike, Quat, Color } from '../../core';
import { BulletContactData } from './bullet-contact-data';
import { BulletConstraint } from './constraints/bullet-constraint';
import { BulletCharacterController } from './character-controllers/bullet-character-controller';
import { bt, EBulletType, EBulletTriangleRaycastFlag } from './instantiated';
import { bt, EBulletType, EBulletTriangleRaycastFlag, EBulletDebugDrawModes } from './instantiated';
import { Node } from '../../scene-graph';
import { director } from '../../game';
import { GeometryRenderer } from '../../rendering/geometry-renderer';

const contactsPool: BulletContactData[] = [];
const v3_0 = CC_V3_0;
const v3_1 = CC_V3_1;
const v3_2 = CC_V3_2;
const c_0 = CC_COLOR_0;
const emitHit = new CharacterControllerContact();
export class BulletWorld implements IPhysicsWorld {
setDefaultMaterial (v: PhysicsMaterial): void {
Expand Down Expand Up @@ -115,6 +118,12 @@ export class BulletWorld implements IPhysicsWorld {
private readonly _broadphase: Bullet.ptr;
private readonly _solver: Bullet.ptr;
private readonly _dispatcher: Bullet.ptr;
private readonly _debugDraw: Bullet.ptr;

private _debugLineCount = 0;
private _MAX_DEBUG_LINE_COUNT = 16384;
private _debugDrawFlags = EPhysicsDrawFlags.None;
private _debugConstraintSize = 0.3; //B3_DEFAULT_DEBUGDRAW_SIZE

private _needEmitEvents = false;
private _needSyncAfterEvents = false;
Expand All @@ -136,10 +145,23 @@ export class BulletWorld implements IPhysicsWorld {
private static _sweepCapsuleGeometry: number;

constructor () {
bt.CACHE.world = this;
this._broadphase = bt.DbvtBroadphase_new();
this._dispatcher = bt.CollisionDispatcher_new();
this._solver = bt.SequentialImpulseConstraintSolver_new();
this._debugDraw = bt.DebugDraw_new();
this._world = bt.ccDiscreteDynamicsWorld_new(this._dispatcher, this._broadphase, this._solver);
bt.CollisionWorld_setDebugDrawer(this._world, this._debugDraw);

bt.DebugDraw_setAABBColor(this._debugDraw, 0, 1, 1);
// set color for all shapes
bt.DebugDraw_setActiveObjectColor(this._debugDraw, 1, 0, 1);
bt.DebugDraw_setDeactiveObjectColor(this._debugDraw, 1, 0, 1);
bt.DebugDraw_setWantsDeactivationObjectColor(this._debugDraw, 1, 0, 1);
bt.DebugDraw_setDisabledDeactivationObjectColor(this._debugDraw, 1, 0, 1);
bt.DebugDraw_setDisabledSimulationObjectColor(this._debugDraw, 1, 0, 1);
// set color for all shapes END
bt.DebugDraw_setConstraintLimitColor(this._debugDraw, 0.5, 0.5, 0.5);
}

destroy (): void {
Expand All @@ -148,6 +170,7 @@ export class BulletWorld implements IPhysicsWorld {
bt._safe_delete(this._broadphase, EBulletType.EBulletTypeDbvtBroadPhase);
bt._safe_delete(this._dispatcher, EBulletType.EBulletTypeCollisionDispatcher);
bt._safe_delete(this._solver, EBulletType.EBulletTypeSequentialImpulseConstraintSolver);
bt._safe_delete(this._debugDraw, EBulletType.EBulletTypeDebugDraw);
(this as any).bodies = null;
(this as any).ghosts = null;
(this as any).ccts = null;
Expand All @@ -165,6 +188,7 @@ export class BulletWorld implements IPhysicsWorld {
if (!this.bodies.length && !this.ghosts.length) return;
if (timeSinceLastCalled === undefined) timeSinceLastCalled = deltaTime;
bt.DynamicsWorld_stepSimulation(this._world, timeSinceLastCalled, maxSubStep, deltaTime);
bt.CollisionWorld_debugDrawWorld(this._world);
}

syncSceneToPhysics (): void {
Expand Down Expand Up @@ -808,4 +832,71 @@ export class BulletWorld implements IPhysicsWorld {
}
}
}

get debugDrawFlags (): EPhysicsDrawFlags {
return this._debugDrawFlags;
}

set debugDrawFlags (v: EPhysicsDrawFlags) {
this._debugDrawFlags = v;
if (this._debugDraw) {
this._setDebugDrawMode();
}
}

get debugDrawConstraintSize (): number {
return this._debugConstraintSize;
}

set debugDrawConstraintSize (v) {
this._debugConstraintSize = v;
for (let i = 0; i < this.constraints.length; i++) {
this.constraints[i].updateDebugDrawSize();
}
}

private _setDebugDrawMode (): void {
let btDrawMode = 0;
if (this._debugDrawFlags & EPhysicsDrawFlags.Wireframe) {
btDrawMode |= EBulletDebugDrawModes.DBG_DrawWireframe;
}

if (this._debugDrawFlags & EPhysicsDrawFlags.Constraint) {
btDrawMode |= EBulletDebugDrawModes.DBG_DrawConstraints;
btDrawMode |= EBulletDebugDrawModes.DBG_DrawConstraintLimits;
}

if (this._debugDrawFlags & EPhysicsDrawFlags.Aabb) {
btDrawMode |= EBulletDebugDrawModes.DBG_DrawAabb;
}

bt.DebugDraw_setDebugMode(this._debugDraw, btDrawMode);
}

private _getDebugRenderer (): GeometryRenderer|null {
const cameras = director.root!.mainWindow?.cameras;
if (!cameras) return null;
if (cameras.length === 0) return null;
if (!cameras[0]) return null;
cameras[0].initGeometryRenderer();

return cameras[0].geometryRenderer;
}

// callback function called by bullet wasm
public onDebugDrawLine (from: number, to: number, color: number): void {
const debugRenderer = this._getDebugRenderer();
if (debugRenderer && this._debugLineCount < this._MAX_DEBUG_LINE_COUNT) {
this._debugLineCount++;
bullet2CocosVec3(v3_0, from);
bullet2CocosVec3(v3_1, to);
bullet2CocosVec3(v3_2, color);
c_0.set(v3_2.x * 255, v3_2.y * 255, v3_2.z * 255, 255);
debugRenderer.addLine(v3_0, v3_1, c_0);
}
}

public onClearLines (): void {
this._debugLineCount = 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ export class BulletConfigurableConstraint extends BulletConstraint implements IC
this.setBreakTorque(this.constraint.breakTorque);

this.updateFrames();
this.updateDebugDrawSize();
}

updateFrames (): void {
Expand Down
10 changes: 9 additions & 1 deletion cocos/physics/bullet/constraints/bullet-constraint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@

/* eslint-disable new-cap */
import { IBaseConstraint } from '../../spec/i-physics-constraint';
import { Constraint, RigidBody } from '../../framework';
import { Constraint, PhysicsSystem, RigidBody } from '../../framework';
import { BulletRigidBody } from '../bullet-rigid-body';
import { bt, EBulletType } from '../instantiated';
import { BulletWorld } from '../bullet-world';

export abstract class BulletConstraint implements IBaseConstraint {
setConnectedBody (v: RigidBody | null): void {
Expand Down Expand Up @@ -100,6 +101,13 @@ export abstract class BulletConstraint implements IBaseConstraint {
this.setEnableCollision(this._collided);
}

updateDebugDrawSize (): void {
if (this.impl) {
const size = (PhysicsSystem.instance.physicsWorld as BulletWorld).debugDrawConstraintSize;
bt.TypedConstraint_setDbgDrawSize(this.impl, size);
}
}

// virtual
protected abstract onComponentSet(): void;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class BulletFixedConstraint extends BulletConstraint implements IFixedCon
this.setBreakForce(this.constraint.breakForce);
this.setBreakTorque(this.constraint.breakTorque);
this.updateFrames();
this.updateDebugDrawSize();
}

updateFrames (): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export class BulletHingeConstraint extends BulletConstraint implements IHingeCon
this.setMotorVelocity(this.constraint.motorVelocity);
this.setMotorForceLimit(this.constraint.motorForceLimit);
this.updateFrames();
this.updateDebugDrawSize();
}

updateFrames (): void {
Expand Down
1 change: 1 addition & 0 deletions cocos/physics/bullet/constraints/bullet-p2p-constraint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class BulletP2PConstraint extends BulletConstraint implements IPointToPoi
this._impl = bt.P2PConstraint_new(bodyA, bodyB, pivotA, pivotB);
this.setPivotA(this.constraint.pivotA);
this.setPivotB(this.constraint.pivotB);
this.updateDebugDrawSize();
}

updateScale0 (): void {
Expand Down
26 changes: 25 additions & 1 deletion cocos/physics/bullet/instantiated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ export enum EBulletType{
EBulletTypeDbvtBroadPhase,
EBulletTypeSequentialImpulseConstraintSolver,
EBulletTypeCollisionWorld,
EBulletTypeTypedConstraint
EBulletTypeTypedConstraint,
EBulletTypeDebugDraw
}

//corresponds to btTriangleRaycastCallback::EFlags
Expand All @@ -56,6 +57,29 @@ export enum EBulletTriangleRaycastFlag {
UseGjkConvexCastRaytest = 1 << 3
}

//btIDebugDraw::EBulletDebugDrawModes
export enum EBulletDebugDrawModes
{
DBG_NoDebug=0,
DBG_DrawWireframe = 1,
DBG_DrawAabb=2,
DBG_DrawFeaturesText=4,
DBG_DrawContactPoints=8,
DBG_NoDeactivation=16,
DBG_NoHelpText = 32,
DBG_DrawText=64,
DBG_ProfileTimings = 128,
DBG_EnableSatComparison = 256,
DBG_DisableBulletLCP = 512,
DBG_EnableCCD = 1024,
DBG_DrawConstraints = (1 << 11),
DBG_DrawConstraintLimits = (1 << 12),
DBG_FastWireframe = (1 << 13),
DBG_DrawNormals = (1 << 14),
DBG_DrawFrames = (1 << 15),
DBG_MAX_DEBUG_DRAW_MODE
}

interface instanceExt extends Bullet.instance {
CACHE: any,
BODY_CACHE_NAME: string,
Expand Down
Loading