From b3dd7db253b05a405ba0d36155699df82580f429 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Tue, 5 Sep 2023 16:58:44 +0800 Subject: [PATCH 01/15] init debug draw --- cocos/physics/bullet/bullet-cache.ts | 3 +- cocos/physics/bullet/bullet-env.ts | 17 ++ cocos/physics/bullet/bullet-world.ts | 97 +++++++++- .../bullet-configurable-constraint.ts | 1 + .../bullet/constraints/bullet-constraint.ts | 10 +- .../constraints/bullet-fixed-constraint.ts | 1 + .../constraints/bullet-hinge-constraint.ts | 1 + .../constraints/bullet-p2p-constraint.ts | 1 + cocos/physics/bullet/instantiated.ts | 26 ++- cocos/physics/framework/physics-enum.ts | 32 ++++ cocos/physics/framework/physics-selector.ts | 2 + cocos/physics/framework/physics-system.ts | 135 ++++++++++--- .../physx/joints/physx-configurable-joint.ts | 7 +- .../physics/physx/joints/physx-fixed-joint.ts | 1 + cocos/physics/physx/joints/physx-joint.ts | 6 + .../physx/joints/physx-revolute-joint.ts | 1 + .../physx/joints/physx-spherical-joint.ts | 1 + cocos/physics/physx/physx-adapter.ts | 155 ++++++++++++--- cocos/physics/physx/physx-shared-body.ts | 2 + cocos/physics/physx/physx-world.ts | 178 ++++++++++++++++-- cocos/physics/spec/i-physics-world.ts | 2 + exports/physics-framework.ts | 1 + 22 files changed, 598 insertions(+), 82 deletions(-) diff --git a/cocos/physics/bullet/bullet-cache.ts b/cocos/physics/bullet/bullet-cache.ts index fe8c0567173..3e13c29795d 100644 --- a/cocos/physics/bullet/bullet-cache.ts +++ b/cocos/physics/bullet/bullet-cache.ts @@ -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'; @@ -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; diff --git a/cocos/physics/bullet/bullet-env.ts b/cocos/physics/bullet/bullet-env.ts index 096a0fe310f..c8341da93e3 100644 --- a/cocos/physics/bullet/bullet-env.ts +++ b/cocos/physics/bullet/bullet-env.ts @@ -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 + }, }; diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index 431158135f4..39556145557 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -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 { @@ -115,6 +118,9 @@ 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 _needEmitEvents = false; private _needSyncAfterEvents = false; @@ -136,10 +142,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 { @@ -148,6 +167,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; @@ -165,6 +185,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 { @@ -808,4 +829,72 @@ export class BulletWorld implements IPhysicsWorld { } } } + + _debugDrawFlags = 0; + get debugDrawFlags (): number { + return this._debugDrawFlags; + } + + set debugDrawFlags (v) { + this._debugDrawFlags = v; + if (this._debugDraw) { + this._setDebugDrawMode(); + } + } + + _debugConstraintSize = 0.3; //B3_DEFAULT_DEBUGDRAW_SIZE + 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(); + } + } + + _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); + } + + _getDebugRenderer (): GeometryRenderer|null { + const cameras = director.root!.cameraList; + if (!cameras) return null; + if (cameras.length === 0) return null; + if (!cameras[0]) return null; + cameras[0].initGeometryRenderer(); + + return cameras[0].geometryRenderer; + } + + 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); + } + } + + onClearLines (): void { + this._debugLineCount = 0; + } } diff --git a/cocos/physics/bullet/constraints/bullet-configurable-constraint.ts b/cocos/physics/bullet/constraints/bullet-configurable-constraint.ts index 491943f761c..1715e442dc8 100644 --- a/cocos/physics/bullet/constraints/bullet-configurable-constraint.ts +++ b/cocos/physics/bullet/constraints/bullet-configurable-constraint.ts @@ -360,6 +360,7 @@ export class BulletConfigurableConstraint extends BulletConstraint implements IC this.setBreakTorque(this.constraint.breakTorque); this.updateFrames(); + this.updateDebugDrawSize(); } updateFrames (): void { diff --git a/cocos/physics/bullet/constraints/bullet-constraint.ts b/cocos/physics/bullet/constraints/bullet-constraint.ts index 4676a79fdfd..21f7f32b83f 100644 --- a/cocos/physics/bullet/constraints/bullet-constraint.ts +++ b/cocos/physics/bullet/constraints/bullet-constraint.ts @@ -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 { @@ -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; diff --git a/cocos/physics/bullet/constraints/bullet-fixed-constraint.ts b/cocos/physics/bullet/constraints/bullet-fixed-constraint.ts index afdc2567432..1168953a6f5 100644 --- a/cocos/physics/bullet/constraints/bullet-fixed-constraint.ts +++ b/cocos/physics/bullet/constraints/bullet-fixed-constraint.ts @@ -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 { diff --git a/cocos/physics/bullet/constraints/bullet-hinge-constraint.ts b/cocos/physics/bullet/constraints/bullet-hinge-constraint.ts index b11fde4a362..d736cb5e3c3 100644 --- a/cocos/physics/bullet/constraints/bullet-hinge-constraint.ts +++ b/cocos/physics/bullet/constraints/bullet-hinge-constraint.ts @@ -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 { diff --git a/cocos/physics/bullet/constraints/bullet-p2p-constraint.ts b/cocos/physics/bullet/constraints/bullet-p2p-constraint.ts index 248e4125c09..2b402adc136 100644 --- a/cocos/physics/bullet/constraints/bullet-p2p-constraint.ts +++ b/cocos/physics/bullet/constraints/bullet-p2p-constraint.ts @@ -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 { diff --git a/cocos/physics/bullet/instantiated.ts b/cocos/physics/bullet/instantiated.ts index ed709063cfa..17d479cc3f3 100644 --- a/cocos/physics/bullet/instantiated.ts +++ b/cocos/physics/bullet/instantiated.ts @@ -44,7 +44,8 @@ export enum EBulletType{ EBulletTypeDbvtBroadPhase, EBulletTypeSequentialImpulseConstraintSolver, EBulletTypeCollisionWorld, - EBulletTypeTypedConstraint + EBulletTypeTypedConstraint, + EBulletTypeDebugDraw } //corresponds to btTriangleRaycastCallback::EFlags @@ -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, diff --git a/cocos/physics/framework/physics-enum.ts b/cocos/physics/framework/physics-enum.ts index a84d210aa48..6d7a00cd3bd 100644 --- a/cocos/physics/framework/physics-enum.ts +++ b/cocos/physics/framework/physics-enum.ts @@ -402,3 +402,35 @@ export enum PhysicsGroup { DEFAULT = 1, } Enum(PhysicsGroup); + +export enum EPhysicsDrawFlags { + /** + * @en + * Draw nothing. + * @zh + * 不绘制。 + */ + None = 0, + /** + * @en + * Draw wireframe + * @zh + * 绘制线框。 + */ + WireFrame = 0x0001, + /** + * @en + * Draw Constraint. + * @zh + * 绘制约束 + */ + Constraint = 0x0002, + /** + * @en + * Draw AABB. + * @zh + * 绘制包围盒。 + */ + Aabb = 0x0004, +} +Enum(EPhysicsDrawFlags); diff --git a/cocos/physics/framework/physics-selector.ts b/cocos/physics/framework/physics-selector.ts index 9be81501389..f65b5cc6bc0 100644 --- a/cocos/physics/framework/physics-selector.ts +++ b/cocos/physics/framework/physics-selector.ts @@ -202,6 +202,8 @@ export function constructDefaultWorld (data: IWorldInitData): void { const FUNC = (...v: any): any => 0 as any; const ENTIRE_WORLD: IPhysicsWorld = { impl: null, + debugDrawFlags: 0, + debugDrawConstraintSize: 0, setGravity: FUNC, setAllowSleep: FUNC, setDefaultMaterial: FUNC, diff --git a/cocos/physics/framework/physics-system.ts b/cocos/physics/framework/physics-system.ts index ae6668b9642..f25a00257cf 100644 --- a/cocos/physics/framework/physics-system.ts +++ b/cocos/physics/framework/physics-system.ts @@ -339,7 +339,7 @@ export class PhysicsSystem extends System implements IWorldInitData { mask: -1, queryTrigger: true, maxDistance: 10000000, - } + }; private readonly raycastResultPool = new RecyclePool((): PhysicsRayResult => new PhysicsRayResult(), 1); private readonly sweepResultPool = new RecyclePool((): PhysicsRayResult => new PhysicsRayResult(), 1); @@ -462,6 +462,22 @@ export class PhysicsSystem extends System implements IWorldInitData { if (this.physicsWorld) this.physicsWorld.emitEvents(); } + get debugDrawFlags (): number { + return this.physicsWorld.debugDrawFlags; + } + + set debugDrawFlags (v) { + this.physicsWorld.debugDrawFlags = v; + } + + get debugDrawConstraintSize (): number { + return this.physicsWorld.debugDrawConstraintSize; + } + + set debugDrawConstraintSize (v) { + this.physicsWorld.debugDrawConstraintSize = v; + } + /** * @en * Collision detect all collider, and record all the detected results, through PhysicsSystem.Instance.RaycastResults access to the results. @@ -607,16 +623,28 @@ export class PhysicsSystem extends System implements IWorldInitData { * @param queryTrigger @zh 是否检测触发器 @en Whether to detect triggers * @return {boolean} @zh 表示是否有检测到碰撞 @en Indicates whether a collision has been detected */ - sweepBox (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - mask = 0xffffffff, maxDistance = 10000000, queryTrigger = true): boolean { + sweepBox ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + mask = 0xffffffff, + maxDistance = 10000000, + queryTrigger = true, + ): boolean { if (!this.physicsWorld) return false; this.sweepResultPool.reset(); this.sweepCastResults.length = 0; this.raycastOptions.mask = mask >>> 0; this.raycastOptions.maxDistance = maxDistance; this.raycastOptions.queryTrigger = queryTrigger; - return this.physicsWorld.sweepBox(worldRay, halfExtent, orientation, - this.raycastOptions, this.sweepResultPool, this.sweepCastResults); + return this.physicsWorld.sweepBox( + worldRay, + halfExtent, + orientation, + this.raycastOptions, + this.sweepResultPool, + this.sweepCastResults, + ); } /** @@ -634,14 +662,25 @@ export class PhysicsSystem extends System implements IWorldInitData { * @param queryTrigger @zh 是否检测触发器 @en Whether to detect triggers * @return {boolean} @zh 表示是否有检测到碰撞 @en Indicates whether a collision has been detected */ - sweepBoxClosest (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - mask = 0xffffffff, maxDistance = 10000000, queryTrigger = true): boolean { + sweepBoxClosest ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + mask = 0xffffffff, + maxDistance = 10000000, + queryTrigger = true, + ): boolean { if (!this.physicsWorld) return false; this.raycastOptions.mask = mask >>> 0; this.raycastOptions.maxDistance = maxDistance; this.raycastOptions.queryTrigger = queryTrigger; - return this.physicsWorld.sweepBoxClosest(worldRay, halfExtent, orientation, - this.raycastOptions, this.sweepCastClosestResult); + return this.physicsWorld.sweepBoxClosest( + worldRay, + halfExtent, + orientation, + this.raycastOptions, + this.sweepCastClosestResult, + ); } /** @@ -658,16 +697,26 @@ export class PhysicsSystem extends System implements IWorldInitData { * @param queryTrigger @zh 是否检测触发器 @en Whether to detect triggers * @return {boolean} @zh 表示是否有检测到碰撞 @en Indicates whether a collision has been detected */ - sweepSphere (worldRay: geometry.Ray, radius: number, - mask = 0xffffffff, maxDistance = 10000000, queryTrigger = true): boolean { + sweepSphere ( + worldRay: geometry.Ray, + radius: number, + mask = 0xffffffff, + maxDistance = 10000000, + queryTrigger = true, + ): boolean { if (!this.physicsWorld) return false; this.sweepResultPool.reset(); this.sweepCastResults.length = 0; this.raycastOptions.mask = mask >>> 0; this.raycastOptions.maxDistance = maxDistance; this.raycastOptions.queryTrigger = queryTrigger; - return this.physicsWorld.sweepSphere(worldRay, radius, - this.raycastOptions, this.sweepResultPool, this.sweepCastResults); + return this.physicsWorld.sweepSphere( + worldRay, + radius, + this.raycastOptions, + this.sweepResultPool, + this.sweepCastResults, + ); } /** @@ -684,14 +733,23 @@ export class PhysicsSystem extends System implements IWorldInitData { * @param queryTrigger @zh 是否检测触发器 @en Whether to detect triggers * @return {boolean} @zh 表示是否有检测到碰撞 @en Indicates whether a collision has been detected */ - sweepSphereClosest (worldRay: geometry.Ray, radius: number, - mask = 0xffffffff, maxDistance = 10000000, queryTrigger = true): boolean { + sweepSphereClosest ( + worldRay: geometry.Ray, + radius: number, + mask = 0xffffffff, + maxDistance = 10000000, + queryTrigger = true, + ): boolean { if (!this.physicsWorld) return false; this.raycastOptions.mask = mask >>> 0; this.raycastOptions.maxDistance = maxDistance; this.raycastOptions.queryTrigger = queryTrigger; - return this.physicsWorld.sweepSphereClosest(worldRay, radius, - this.raycastOptions, this.sweepCastClosestResult); + return this.physicsWorld.sweepSphereClosest( + worldRay, + radius, + this.raycastOptions, + this.sweepCastClosestResult, + ); } /** @@ -712,16 +770,30 @@ export class PhysicsSystem extends System implements IWorldInitData { * @param queryTrigger @zh 是否检测触发器 @en Whether to detect triggers * @return {boolean} @zh 表示是否有检测到碰撞 @en Indicates whether a collision has been detected */ - sweepCapsule (worldRay: geometry.Ray, radius: number, height: number, orientation: IQuatLike, - mask = 0xffffffff, maxDistance = 10000000, queryTrigger = true): boolean { + sweepCapsule ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + mask = 0xffffffff, + maxDistance = 10000000, + queryTrigger = true, + ): boolean { if (!this.physicsWorld) return false; this.sweepResultPool.reset(); this.sweepCastResults.length = 0; this.raycastOptions.mask = mask >>> 0; this.raycastOptions.maxDistance = maxDistance; this.raycastOptions.queryTrigger = queryTrigger; - return this.physicsWorld.sweepCapsule(worldRay, radius, height, orientation, - this.raycastOptions, this.sweepResultPool, this.sweepCastResults); + return this.physicsWorld.sweepCapsule( + worldRay, + radius, + height, + orientation, + this.raycastOptions, + this.sweepResultPool, + this.sweepCastResults, + ); } /** @@ -742,14 +814,27 @@ export class PhysicsSystem extends System implements IWorldInitData { * @param queryTrigger @zh 是否检测触发器 @en Whether to detect triggers * @return {boolean} @zh 表示是否有检测到碰撞 @en Indicates whether a collision has been detected */ - sweepCapsuleClosest (worldRay: geometry.Ray, radius: number, height: number, orientation: IQuatLike, - mask = 0xffffffff, maxDistance = 10000000, queryTrigger = true): boolean { + sweepCapsuleClosest ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + mask = 0xffffffff, + maxDistance = 10000000, + queryTrigger = true, + ): boolean { if (!this.physicsWorld) return false; this.raycastOptions.mask = mask >>> 0; this.raycastOptions.maxDistance = maxDistance; this.raycastOptions.queryTrigger = queryTrigger; - return this.physicsWorld.sweepCapsuleClosest(worldRay, radius, height, orientation, - this.raycastOptions, this.sweepCastClosestResult); + return this.physicsWorld.sweepCapsuleClosest( + worldRay, + radius, + height, + orientation, + this.raycastOptions, + this.sweepCastClosestResult, + ); } private _updateMaterial (): void { diff --git a/cocos/physics/physx/joints/physx-configurable-joint.ts b/cocos/physics/physx/joints/physx-configurable-joint.ts index fcedd4401e1..76c6648c991 100644 --- a/cocos/physics/physx/joints/physx-configurable-joint.ts +++ b/cocos/physics/physx/joints/physx-configurable-joint.ts @@ -359,6 +359,7 @@ export class PhysXConfigurableJoint extends PhysXJoint implements IConfigurableC this._updateDriveSettings(); this.updateFrames(); + this.enableDebugVisualization(true); } updateFrames (): void { @@ -422,9 +423,9 @@ export class PhysXConfigurableJoint extends PhysXJoint implements IConfigurableC private static _drive_x: any = null; private static _drive_y: any = null; private static _drive_z: any = null; - private static _drive_twist: any= null; - private static _drive_swing1: any= null; - private static _drive_swing2: any= null; + private static _drive_twist: any = null; + private static _drive_swing1: any = null; + private static _drive_swing2: any = null; private static _drive: any[] = []; private static _initCache (): void { if (!PhysXConfigurableJoint._jointToleranceScale) { diff --git a/cocos/physics/physx/joints/physx-fixed-joint.ts b/cocos/physics/physx/joints/physx-fixed-joint.ts index 1609e81cf11..25c276c1478 100644 --- a/cocos/physics/physx/joints/physx-fixed-joint.ts +++ b/cocos/physics/physx/joints/physx-fixed-joint.ts @@ -59,6 +59,7 @@ export class PhysXFixedJoint extends PhysXJoint implements IFixedConstraint { this.setBreakForce(this.constraint.breakForce); this.setBreakTorque(this.constraint.breakTorque); this.updateFrame(); + this.enableDebugVisualization(true); } updateFrame (): void { diff --git a/cocos/physics/physx/joints/physx-joint.ts b/cocos/physics/physx/joints/physx-joint.ts index 86a5dd5a691..6be6778e8e0 100644 --- a/cocos/physics/physx/joints/physx-joint.ts +++ b/cocos/physics/physx/joints/physx-joint.ts @@ -92,6 +92,12 @@ export class PhysXJoint implements IBaseConstraint { } } + enableDebugVisualization (v: boolean): void { + if (this.impl) { + this.impl.setConstraintFlag(1 << 4, v);// PxConstraintFlag::eVISUALIZATION + } + } + // virtual protected onComponentSet (): void { } diff --git a/cocos/physics/physx/joints/physx-revolute-joint.ts b/cocos/physics/physx/joints/physx-revolute-joint.ts index 4099c72b52e..83d2c12aeb4 100644 --- a/cocos/physics/physx/joints/physx-revolute-joint.ts +++ b/cocos/physics/physx/joints/physx-revolute-joint.ts @@ -113,6 +113,7 @@ export class PhysXRevoluteJoint extends PhysXJoint implements IHingeConstraint { this.setMotorVelocity(this.constraint.motorVelocity); this.setMotorForceLimit(this.constraint.motorForceLimit); this.updateFrames(); + this.enableDebugVisualization(true); } updateFrames (): void { diff --git a/cocos/physics/physx/joints/physx-spherical-joint.ts b/cocos/physics/physx/joints/physx-spherical-joint.ts index cba277046cd..f463614754a 100644 --- a/cocos/physics/physx/joints/physx-spherical-joint.ts +++ b/cocos/physics/physx/joints/physx-spherical-joint.ts @@ -66,6 +66,7 @@ export class PhysXSphericalJoint extends PhysXJoint implements IPointToPointCons this._impl = PX.createSphericalJoint(PhysXJoint.tempActor, _pxtrans, null, _pxtrans); this.setPivotA(this.constraint.pivotA); this.setPivotB(this.constraint.pivotB); + this.enableDebugVisualization(true); } updateScale0 (): void { diff --git a/cocos/physics/physx/physx-adapter.ts b/cocos/physics/physx/physx-adapter.ts index 0ef51b2e365..37aa5113b10 100644 --- a/cocos/physics/physx/physx-adapter.ts +++ b/cocos/physics/physx/physx-adapter.ts @@ -35,7 +35,7 @@ import { wasmFactory, PhysXWasmUrl } from './physx.wasmjs'; import { WebAssemblySupportMode } from '../../misc/webassembly-support'; import { instantiateWasm } from 'pal/wasm'; import { BYTEDANCE, DEBUG, EDITOR, TEST, WASM_SUPPORT_MODE } from 'internal:constants'; -import { IQuatLike, IVec3Like, Quat, RecyclePool, Vec3, cclegacy, geometry, Settings, settings, sys } from '../../core'; +import { IQuatLike, IVec3Like, Quat, RecyclePool, Vec3, cclegacy, geometry, Settings, settings, sys, Color } from '../../core'; import { shrinkPositions } from '../utils/util'; import { IRaycastOptions } from '../spec/i-physics-world'; import { IPhysicsConfig, PhysicsRayResult, PhysicsSystem, CharacterControllerContact } from '../framework'; @@ -101,8 +101,10 @@ function initWASM (): any { globalThis.PhysX = globalThis.PHYSX ? globalThis.PHYSX : wasmFactory; if (globalThis.PhysX != null) { return globalThis.PhysX({ - instantiateWasm (importObject: WebAssembly.Imports, - receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void): any { + instantiateWasm ( + importObject: WebAssembly.Imports, + receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void, + ): any { return instantiateWasm(PhysXWasmUrl, importObject).then((result: any): void => { receiveInstance(result.instance, result.module); }); @@ -179,6 +181,13 @@ type IPxTransformExt = { [x in keyof typeof _trans]: typeof _trans[x]; } & setQuaternion(quat: IQuatLike): void; }; +export function getColorPXColor (color: Color, rgba: number): void { + color.b = ((rgba >> 16) & 0xff); + color.g = ((rgba >> 8) & 0xff); + color.r = ((rgba) & 0xff); + color.a = 255; +} + export const _pxtrans = _trans as unknown as IPxTransformExt; export function addReference (shape: PhysXShape, impl: any): void { @@ -317,11 +326,11 @@ export function applyTorqueForce (impl: any, vec: IVec3Like): void { export function getShapeFlags (isTrigger: boolean): any { if (USE_BYTEDANCE) { const flag = (isTrigger ? PX.ShapeFlag.eTRIGGER_SHAPE : PX.ShapeFlag.eSIMULATION_SHAPE) - | PX.ShapeFlag.eSCENE_QUERY_SHAPE; + | PX.ShapeFlag.eSCENE_QUERY_SHAPE | PX.ShapeFlag.eVISUALIZATION; return flag; } const flag = (isTrigger ? PX.PxShapeFlag.eTRIGGER_SHAPE.value : PX.PxShapeFlag.eSIMULATION_SHAPE.value) - | PX.PxShapeFlag.eSCENE_QUERY_SHAPE.value; + | PX.PxShapeFlag.eSCENE_QUERY_SHAPE.value | PX.PxShapeFlag.eVISUALIZATION.value; return new PX.PxShapeFlags(flag); } @@ -422,11 +431,17 @@ export function createTriangleMesh (vertices: Float32Array | number[], indices: } } -export function createBV33TriangleMesh (vertices: number[], indices: Uint32Array, cooking: any, physics: any, +export function createBV33TriangleMesh ( + vertices: number[], + indices: Uint32Array, + cooking: any, + physics: any, skipMeshCleanUp = false, skipEdgeData = false, cookingPerformance = false, - meshSizePerfTradeoff = true, inserted = true): any { + meshSizePerfTradeoff = true, + inserted = true, +): any { if (!USE_BYTEDANCE) return; const meshDesc = new PX.TriangleMeshDesc(); meshDesc.setPointsData(vertices); @@ -448,11 +463,16 @@ export function createBV33TriangleMesh (vertices: number[], indices: Uint32Array return cooking.createTriangleMesh(meshDesc); } -export function createBV34TriangleMesh (vertices: number[], indices: Uint32Array, cooking: any, physics: any, +export function createBV34TriangleMesh ( + vertices: number[], + indices: Uint32Array, + cooking: any, + physics: any, skipMeshCleanUp = false, skipEdgeData = false, numTrisPerLeaf = true, - inserted = true): void { + inserted = true, +): void { if (!USE_BYTEDANCE) return; const meshDesc = new PX.TriangleMeshDesc(); meshDesc.setPointsData(vertices); @@ -503,8 +523,13 @@ export function createHeightFieldGeometry (hf: any, flags: number, hs: number, x if (USE_BYTEDANCE) { return new PX.HeightFieldGeometry(hf, hs, xs, zs); } - return new PX.PxHeightFieldGeometry(hf, new PX.PxMeshGeometryFlags(flags), - hs, xs, zs); + return new PX.PxHeightFieldGeometry( + hf, + new PX.PxMeshGeometryFlags(flags), + hs, + xs, + zs, + ); } export function simulateScene (scene: any, deltaTime: number): void { @@ -515,8 +540,13 @@ export function simulateScene (scene: any, deltaTime: number): void { } } -export function raycastAll (world: PhysXWorld, worldRay: geometry.Ray, options: IRaycastOptions, - pool: RecyclePool, results: PhysicsRayResult[]): boolean { +export function raycastAll ( + world: PhysXWorld, + worldRay: geometry.Ray, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], +): boolean { const maxDistance = options.maxDistance; const flags = PxHitFlag.ePOSITION | PxHitFlag.eNORMAL; const word3 = EFilterDataWord3.QUERY_FILTER | (options.queryTrigger ? 0 : EFilterDataWord3.QUERY_CHECK_TRIGGER); @@ -529,8 +559,16 @@ export function raycastAll (world: PhysXWorld, worldRay: geometry.Ray, options: queryfilterData.data.word3 = word3; queryfilterData.data.word0 = options.mask >>> 0; queryfilterData.flags = queryFlags; - const r = PX.SceneQueryExt.raycastMultiple(world.scene, worldRay.o, worldRay.d, maxDistance, flags, - mutipleResultSize, queryfilterData, queryFilterCB); + const r = PX.SceneQueryExt.raycastMultiple( + world.scene, + worldRay.o, + worldRay.d, + maxDistance, + flags, + mutipleResultSize, + queryfilterData, + queryFilterCB, + ); if (r) { for (let i = 0; i < r.length; i++) { @@ -547,8 +585,17 @@ export function raycastAll (world: PhysXWorld, worldRay: geometry.Ray, options: queryfilterData.setWords(word3, 3); queryfilterData.setFlags(queryFlags); const blocks = mutipleResults; - const r = world.scene.raycastMultiple(worldRay.o, worldRay.d, maxDistance, flags, - blocks, blocks.size(), queryfilterData, queryFilterCB, null); + const r = world.scene.raycastMultiple( + worldRay.o, + worldRay.d, + maxDistance, + flags, + blocks, + blocks.size(), + queryfilterData, + queryFilterCB, + null, + ); if (r > 0) { for (let i = 0; i < r; i++) { @@ -579,8 +626,15 @@ export function raycastClosest (world: PhysXWorld, worldRay: geometry.Ray, optio queryfilterData.data.word3 = word3; queryfilterData.data.word0 = options.mask >>> 0; queryfilterData.flags = queryFlags; - const block = PX.SceneQueryExt.raycastSingle(world.scene, worldRay.o, worldRay.d, maxDistance, - flags, queryfilterData, queryFilterCB); + const block = PX.SceneQueryExt.raycastSingle( + world.scene, + worldRay.o, + worldRay.d, + maxDistance, + flags, + queryfilterData, + queryFilterCB, + ); if (block) { const collider = getWrapShape(block.shapeData).collider; result._assign(block.position, block.distance, collider, block.normal); @@ -591,8 +645,16 @@ export function raycastClosest (world: PhysXWorld, worldRay: geometry.Ray, optio queryfilterData.setWords(word3, 3); queryfilterData.setFlags(queryFlags); const block = PhysXInstance.singleResult; - const r = world.scene.raycastSingle(worldRay.o, worldRay.d, options.maxDistance, flags, - block, queryfilterData, queryFilterCB, null); + const r = world.scene.raycastSingle( + worldRay.o, + worldRay.d, + options.maxDistance, + flags, + block, + queryfilterData, + queryFilterCB, + null, + ); if (r) { const collider = getWrapShape(block.getShape()).collider; result._assign(block.position, block.distance, collider, block.normal); @@ -602,8 +664,15 @@ export function raycastClosest (world: PhysXWorld, worldRay: geometry.Ray, optio return false; } -export function sweepAll (world: PhysXWorld, worldRay: geometry.Ray, geometry: any, geometryRotation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { +export function sweepAll ( + world: PhysXWorld, + worldRay: geometry.Ray, + geometry: any, + geometryRotation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], +): boolean { const maxDistance = options.maxDistance; const flags = PxHitFlag.ePOSITION | PxHitFlag.eNORMAL; const word3 = EFilterDataWord3.QUERY_FILTER | (options.queryTrigger ? 0 : EFilterDataWord3.QUERY_CHECK_TRIGGER); @@ -617,8 +686,19 @@ export function sweepAll (world: PhysXWorld, worldRay: geometry.Ray, geometry: a queryfilterData.setWords(word3, 3); queryfilterData.setFlags(queryFlags); const blocks = mutipleResults; - const r = world.scene.sweepMultiple(geometry, getTempTransform(worldRay.o, geometryRotation), worldRay.d, maxDistance, flags, - blocks, blocks.size(), queryfilterData, queryFilterCB, null, 0); + const r = world.scene.sweepMultiple( + geometry, + getTempTransform(worldRay.o, geometryRotation), + worldRay.d, + maxDistance, + flags, + blocks, + blocks.size(), + queryfilterData, + queryFilterCB, + null, + 0, + ); if (r > 0) { for (let i = 0; i < r; i++) { @@ -637,8 +717,14 @@ export function sweepAll (world: PhysXWorld, worldRay: geometry.Ray, geometry: a return false; } -export function sweepClosest (world: PhysXWorld, worldRay: geometry.Ray, geometry: any, geometryRotation: IQuatLike, - options: IRaycastOptions, result: PhysicsRayResult): boolean { +export function sweepClosest ( + world: PhysXWorld, + worldRay: geometry.Ray, + geometry: any, + geometryRotation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, +): boolean { const maxDistance = options.maxDistance; const flags = PxHitFlag.ePOSITION | PxHitFlag.eNORMAL; const word3 = EFilterDataWord3.QUERY_FILTER | (options.queryTrigger ? 0 : EFilterDataWord3.QUERY_CHECK_TRIGGER) @@ -651,8 +737,18 @@ export function sweepClosest (world: PhysXWorld, worldRay: geometry.Ray, geometr const queryFilterCB = PhysXInstance.queryFilterCB; const block = PhysXInstance.singleSweepResult; - const r = world.scene.sweepSingle(geometry, getTempTransform(worldRay.o, geometryRotation), worldRay.d, maxDistance, - flags, block, queryfilterData, queryFilterCB, null, 0); + const r = world.scene.sweepSingle( + geometry, + getTempTransform(worldRay.o, geometryRotation), + worldRay.d, + maxDistance, + flags, + block, + queryfilterData, + queryFilterCB, + null, + 0, + ); if (r) { const collider = getWrapShape(block.getShape()).collider; result._assign(block.position, block.distance, collider, block.normal); @@ -720,6 +816,7 @@ export function initializeWorld (world: any): void { const sceneDesc = PX.getDefaultSceneDesc(PhysXInstance.physics.getTolerancesScale(), 0, PhysXInstance.simulationCB); world.scene = PhysXInstance.physics.createScene(sceneDesc); + world.scene.setVisualizationParameter(PX.PxVisualizationParameter.eSCALE, 1); world.controllerManager = PX.PxCreateControllerManager(world.scene, false); } } diff --git a/cocos/physics/physx/physx-shared-body.ts b/cocos/physics/physx/physx-shared-body.ts index cae1a5e9c44..8695c571df0 100644 --- a/cocos/physics/physx/physx-shared-body.ts +++ b/cocos/physics/physx/physx-shared-body.ts @@ -149,6 +149,7 @@ export class PhysXSharedBody { if (this._staticActor) return; const t = getTempTransform(this.node.worldPosition, this.node.worldRotation); this._staticActor = PhysXInstance.physics.createRigidStatic(t); + this._staticActor.setActorFlag(PX.ActorFlag.eVISUALIZATION, true); if (this._staticActor.$$) PX.IMPL_PTR[this._staticActor.$$.ptr] = this; } @@ -161,6 +162,7 @@ export class PhysXSharedBody { if (wb) { const rb = wb.rigidBody; this._dynamicActor.setMass(rb.mass); + this._dynamicActor.setActorFlag(PX.ActorFlag.eVISUALIZATION, true); this._dynamicActor.setActorFlag(PX.ActorFlag.eDISABLE_GRAVITY, !rb.useGravity); this.setLinearDamping(rb.linearDamping); this.setAngularDamping(rb.angularDamping); diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index 6ffe301e263..7c26c46ac24 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -25,13 +25,14 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */ import { IPhysicsWorld, IRaycastOptions } from '../spec/i-physics-world'; import { PhysicsMaterial, PhysicsRayResult, CollisionEventType, TriggerEventType, CharacterTriggerEventType, - CharacterControllerContact } from '../framework'; -import { error, RecyclePool, js, IVec3Like, geometry, IQuatLike, Vec3, Quat } from '../../core'; + CharacterControllerContact, + EPhysicsDrawFlags } from '../framework'; +import { error, RecyclePool, js, IVec3Like, geometry, IQuatLike, Vec3, Quat, Color } from '../../core'; import { IBaseConstraint } from '../spec/i-physics-constraint'; import { PhysXRigidBody } from './physx-rigid-body'; import { addActorToScene, raycastAll, simulateScene, initializeWorld, raycastClosest, sweepClosest, - gatherEvents, getWrapShape, PX, getContactDataOrByteOffset, sweepAll, + gatherEvents, getWrapShape, PX, getContactDataOrByteOffset, sweepAll, getColorPXColor, } from './physx-adapter'; import { PhysXSharedBody } from './physx-shared-body'; import { TupleDictionary } from '../utils/tuple-dictionary'; @@ -42,9 +43,14 @@ import { EFilterDataWord3 } from './physx-enum'; import { PhysXInstance } from './physx-instance'; import { Node } from '../../scene-graph'; import { PhysXCharacterController } from './character-controllers/physx-character-controller'; +import { GeometryRenderer } from '../../rendering/geometry-renderer'; +import { director } from '../../game'; const CC_QUAT_0 = new Quat(); - +const CC_V3_0 = new Vec3(); +const CC_V3_1 = new Vec3(); +const CC_V3_2 = new Vec3(); +const CC_COLOR_0 = new Color(0, 0, 0, 0); export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { setAllowSleep (_v: boolean): void { } setDefaultMaterial (_v: PhysicsMaterial): void { } @@ -86,6 +92,8 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { body.syncPhysicsToScene(); } } + + this._debugDraw(); } private _simulate (dt: number): void { @@ -131,6 +139,104 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { } } + private _debugLineCount = 0; + private _MAX_DEBUG_LINE_COUNT = 16384; + + _debugDrawFlags = 0; + get debugDrawFlags (): number { + return this._debugDrawFlags; + } + + set debugDrawFlags (v) { + this._debugDrawFlags = v; + this._setDebugDrawMode(); + } + + _debugConstraintSize = 0.3; + get debugDrawConstraintSize (): number { + return this._debugConstraintSize; + } + + set debugDrawConstraintSize (v) { + this._debugConstraintSize = v; + this._setDebugDrawMode(); + } + + _setDebugDrawMode (): void { + if (this._debugDrawFlags & EPhysicsDrawFlags.WireFrame) { + this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_SHAPES, 1); + } else { + this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_SHAPES, 0); + } + + const drawConstraint = Boolean(this._debugDrawFlags & EPhysicsDrawFlags.Constraint); + const internalConstraintSize = drawConstraint ? this._debugConstraintSize : 0; + this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eJOINT_LOCAL_FRAMES, internalConstraintSize); + this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eJOINT_LIMITS, internalConstraintSize); + + if (this._debugDrawFlags & EPhysicsDrawFlags.Aabb) { + this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_AABBS, 1); + } else { + this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_AABBS, 0); + } + } + + _getDebugRenderer (): GeometryRenderer|null { + const cameras = director.root!.cameraList; + if (!cameras) return null; + if (cameras.length === 0) return null; + if (!cameras[0]) return null; + cameras[0].initGeometryRenderer(); + + return cameras[0].geometryRenderer; + } + + private _debugDraw (): void { + const debugRenderer = this._getDebugRenderer(); + if (!debugRenderer) return; + + this._debugLineCount = 0; + const rb = this.scene.getRenderBuffer();//PxRenderBuffer + for (let i = 0; i < rb.getNbPoints(); i++) { + const point = rb.getPointAt(i);//PxDebugPoint + Vec3.copy(CC_V3_0, point.pos); + getColorPXColor(CC_COLOR_0, point.color0 as number); + debugRenderer.addSphere(CC_V3_0, 0.1, CC_COLOR_0); + } + for (let i = 0; i < rb.getNbLines(); i++) { + const line = rb.getLineAt(i);//PxDebugLine + this._onDebugDrawLine(line); + } + for (let i = 0; i < rb.getNbTriangles(); i++) { + const triangle = rb.getTriangleAt(i);//PxDebugTriangle + this._onDebugDrawTriangle(triangle); + } + } + + private _onDebugDrawLine (line: PX.PxDebugLine): void { + const debugRenderer = this._getDebugRenderer(); + if (debugRenderer && this._debugLineCount < this._MAX_DEBUG_LINE_COUNT) { + this._debugLineCount++; + Vec3.copy(CC_V3_0, line.pos0); + Vec3.copy(CC_V3_1, line.pos1); + getColorPXColor(CC_COLOR_0, line.color0 as number); + debugRenderer.addLine(CC_V3_0, CC_V3_1, CC_COLOR_0); + } + } + private _onDebugDrawTriangle (triangle: PX.PxDebugTriangle): void { + const debugRenderer = this._getDebugRenderer(); + if (debugRenderer && (this._MAX_DEBUG_LINE_COUNT - this._debugLineCount) >= 3) { + this._debugLineCount += 3; + Vec3.copy(CC_V3_0, triangle.pos0); + Vec3.copy(CC_V3_1, triangle.pos1); + Vec3.copy(CC_V3_2, triangle.pos2); + getColorPXColor(CC_COLOR_0, triangle.color0 as number); + debugRenderer.addLine(CC_V3_0, CC_V3_1, CC_COLOR_0); + debugRenderer.addLine(CC_V3_1, CC_V3_2, CC_COLOR_0); + debugRenderer.addLine(CC_V3_2, CC_V3_0, CC_COLOR_0); + } + } + getSharedBody (node: Node, wrappedBody?: PhysXRigidBody): PhysXSharedBody { return PhysXSharedBody.getSharedBody(node, this, wrappedBody); } @@ -177,8 +283,14 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { return raycastClosest(this, worldRay, options, result); } - sweepBox (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepBox ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { if (!PhysXWorld._sweepBoxGeometry) { PhysXWorld._sweepBoxGeometry = new PX.BoxGeometry(halfExtent); } @@ -186,8 +298,13 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { return sweepAll(this, worldRay, PhysXWorld._sweepBoxGeometry, orientation, options, pool, results); } - sweepBoxClosest (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepBoxClosest ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { if (!PhysXWorld._sweepBoxGeometry) { PhysXWorld._sweepBoxGeometry = new PX.BoxGeometry(halfExtent); } @@ -195,8 +312,13 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { return sweepClosest(this, worldRay, PhysXWorld._sweepBoxGeometry, orientation, options, result); } - sweepSphere (worldRay: geometry.Ray, radius: number, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepSphere ( + worldRay: geometry.Ray, + radius: number, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { if (!PhysXWorld._sweepSphereGeometry) { PhysXWorld._sweepSphereGeometry = new PX.SphereGeometry(radius); } @@ -204,8 +326,12 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { return sweepAll(this, worldRay, PhysXWorld._sweepSphereGeometry, Quat.IDENTITY, options, pool, results); } - sweepSphereClosest (worldRay: geometry.Ray, radius: number, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepSphereClosest ( + worldRay: geometry.Ray, + radius: number, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { if (!PhysXWorld._sweepSphereGeometry) { PhysXWorld._sweepSphereGeometry = new PX.SphereGeometry(radius); } @@ -213,8 +339,15 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { return sweepClosest(this, worldRay, PhysXWorld._sweepSphereGeometry, Quat.IDENTITY, options, result); } - sweepCapsule (worldRay: geometry.Ray, radius: number, height: number, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepCapsule ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { if (!PhysXWorld._sweepCapsuleGeometry) { PhysXWorld._sweepCapsuleGeometry = new PX.CapsuleGeometry(radius, height / 2); } @@ -227,8 +360,14 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { return sweepAll(this, worldRay, PhysXWorld._sweepCapsuleGeometry, finalOrientation, options, pool, results); } - sweepCapsuleClosest (worldRay: geometry.Ray, radius: number, height: number, orientation: IQuatLike, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepCapsuleClosest ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { if (!PhysXWorld._sweepCapsuleGeometry) { PhysXWorld._sweepCapsuleGeometry = new PX.CapsuleGeometry(radius, height / 2); } @@ -518,8 +657,11 @@ const PhysXCallback = { const motionDir = new Vec3(); motionDir.set(hit.dir.x, hit.dir.y, hit.dir.z); const motionLength = hit.length; - item = cctShapeEventDic.set(hit.getCurrentController(), hit.getTouchedShape(), - { PhysXCharacterController: cct, PhysXShape: s, worldPos, worldNormal, motionDir, motionLength }); + item = cctShapeEventDic.set( + hit.getCurrentController(), + hit.getTouchedShape(), + { PhysXCharacterController: cct, PhysXShape: s, worldPos, worldNormal, motionDir, motionLength }, + ); } }, onControllerHit (hit: any): void { //PX.ControllersHit diff --git a/cocos/physics/spec/i-physics-world.ts b/cocos/physics/spec/i-physics-world.ts index 170b838ecf3..63b87d79e07 100644 --- a/cocos/physics/spec/i-physics-world.ts +++ b/cocos/physics/spec/i-physics-world.ts @@ -35,6 +35,8 @@ export interface IRaycastOptions { export interface IPhysicsWorld { readonly impl: any; + debugDrawFlags: number; + debugDrawConstraintSize: number; setGravity: (v: IVec3Like) => void; setAllowSleep: (v: boolean) => void; setDefaultMaterial: (v: PhysicsMaterial) => void; diff --git a/exports/physics-framework.ts b/exports/physics-framework.ts index cbadf86dfa5..1cb60ec9de5 100644 --- a/exports/physics-framework.ts +++ b/exports/physics-framework.ts @@ -65,6 +65,7 @@ export { EAxisDirection, ERigidBodyType, EColliderType, + EPhysicsDrawFlags, } from '../cocos/physics/framework'; export type { From 900a1088f202bdf125ff0cfc89fe9914e2008b03 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Tue, 5 Sep 2023 17:12:35 +0800 Subject: [PATCH 02/15] tweak _debugDrawFlags --- cocos/physics/bullet/bullet-world.ts | 6 +++--- cocos/physics/physx/physx-world.ts | 6 +++--- cocos/physics/spec/i-physics-world.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index 39556145557..f2f438b1f8b 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -830,12 +830,12 @@ export class BulletWorld implements IPhysicsWorld { } } - _debugDrawFlags = 0; - get debugDrawFlags (): number { + _debugDrawFlags = EPhysicsDrawFlags.None; + get debugDrawFlags (): EPhysicsDrawFlags { return this._debugDrawFlags; } - set debugDrawFlags (v) { + set debugDrawFlags (v: EPhysicsDrawFlags) { this._debugDrawFlags = v; if (this._debugDraw) { this._setDebugDrawMode(); diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index 7c26c46ac24..2553baa2805 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -142,12 +142,12 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { private _debugLineCount = 0; private _MAX_DEBUG_LINE_COUNT = 16384; - _debugDrawFlags = 0; - get debugDrawFlags (): number { + _debugDrawFlags = EPhysicsDrawFlags.None; + get debugDrawFlags (): EPhysicsDrawFlags { return this._debugDrawFlags; } - set debugDrawFlags (v) { + set debugDrawFlags (v: EPhysicsDrawFlags) { this._debugDrawFlags = v; this._setDebugDrawMode(); } diff --git a/cocos/physics/spec/i-physics-world.ts b/cocos/physics/spec/i-physics-world.ts index 63b87d79e07..fdaaaa41e48 100644 --- a/cocos/physics/spec/i-physics-world.ts +++ b/cocos/physics/spec/i-physics-world.ts @@ -24,7 +24,7 @@ import { IVec3Like, RecyclePool, geometry, IQuatLike } from '../../core'; import { PhysicsRayResult } from '../framework/physics-ray-result'; -import { PhysicsMaterial } from '../framework'; +import { EPhysicsDrawFlags, PhysicsMaterial } from '../framework'; export interface IRaycastOptions { mask: number; @@ -35,7 +35,7 @@ export interface IRaycastOptions { export interface IPhysicsWorld { readonly impl: any; - debugDrawFlags: number; + debugDrawFlags: EPhysicsDrawFlags; debugDrawConstraintSize: number; setGravity: (v: IVec3Like) => void; setAllowSleep: (v: boolean) => void; From 6cdd2c1359ea1c94b30255bfdcbf3d31fca635b0 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Tue, 5 Sep 2023 18:22:15 +0800 Subject: [PATCH 03/15] px debug draw performance opt --- cocos/physics/physx/physx-adapter.ts | 6 +-- cocos/physics/physx/physx-world.ts | 61 ++++++++++++++++++---------- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/cocos/physics/physx/physx-adapter.ts b/cocos/physics/physx/physx-adapter.ts index 37aa5113b10..985e324a0c1 100644 --- a/cocos/physics/physx/physx-adapter.ts +++ b/cocos/physics/physx/physx-adapter.ts @@ -48,7 +48,7 @@ import { Director, director, game } from '../../game'; import { degreesToRadians } from '../../core/utils/misc'; import { PhysXCharacterController } from './character-controllers/physx-character-controller'; -export const PX = {} as any; +export let PX = {} as any; const globalThis = cclegacy._global; // Use bytedance native or js physics if nativePhysX is not null. const USE_BYTEDANCE = BYTEDANCE && globalThis.nativePhysX; @@ -87,7 +87,7 @@ function initASM (): any { if (!EDITOR && !TEST) console.debug('[PHYSICS]:', `${USE_EXTERNAL_PHYSX ? 'External' : 'Internal'} PhysX asm libs loaded.`); initAdaptWrapper(Instance); initConfigAndCacheObject(Instance); - Object.assign(PX, Instance); + PX = Instance; }, (reason: any): void => { console.error('[PHYSICS]:', `PhysX asm load failed: ${reason}`); }); } else { if (!EDITOR && !TEST) console.error('[PHYSICS]:', 'Failed to load PhysX js libs, package may be not found.'); @@ -113,7 +113,7 @@ function initWASM (): any { if (!EDITOR && !TEST) console.debug('[PHYSICS]:', `${USE_EXTERNAL_PHYSX ? 'External' : 'Internal'} PhysX wasm libs loaded.`); initAdaptWrapper(Instance); initConfigAndCacheObject(Instance); - Object.assign(PX, Instance); + PX = Instance; }, (reason: any): void => { console.error('[PHYSICS]:', `PhysX wasm load failed: ${reason}`); }); } else { if (!EDITOR && !TEST) console.error('[PHYSICS]:', 'Failed to load PhysX wasm libs, package may be not found.'); diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index 2553baa2805..25470082df9 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -196,43 +196,60 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { if (!debugRenderer) return; this._debugLineCount = 0; - const rb = this.scene.getRenderBuffer();//PxRenderBuffer - for (let i = 0; i < rb.getNbPoints(); i++) { - const point = rb.getPointAt(i);//PxDebugPoint - Vec3.copy(CC_V3_0, point.pos); - getColorPXColor(CC_COLOR_0, point.color0 as number); - debugRenderer.addSphere(CC_V3_0, 0.1, CC_COLOR_0); + const rbPtr = this.scene.getRenderBufferPtr();//PxRenderBuffer + const nbLine = PX.PxRenderBuffer_GetNbLines(rbPtr); + for (let i = 0; i < nbLine; i++) { + const linePtr = PX.PxRenderBuffer_GetLineAt(rbPtr, i) as number;//PxDebugLine + this._onDebugDrawLine(linePtr); } - for (let i = 0; i < rb.getNbLines(); i++) { - const line = rb.getLineAt(i);//PxDebugLine - this._onDebugDrawLine(line); - } - for (let i = 0; i < rb.getNbTriangles(); i++) { - const triangle = rb.getTriangleAt(i);//PxDebugTriangle - this._onDebugDrawTriangle(triangle); + const nbTriangle = PX.PxRenderBuffer_GetNbTriangles(rbPtr); + for (let i = 0; i < nbTriangle; i++) { + const trianglePtr = PX.PxRenderBuffer_GetTriangleAt(rbPtr, i) as number;//PxDebugTriangle + this._onDebugDrawTriangle(trianglePtr); } } - private _onDebugDrawLine (line: PX.PxDebugLine): void { + private _onDebugDrawLine (linePtr: number): void { const debugRenderer = this._getDebugRenderer(); if (debugRenderer && this._debugLineCount < this._MAX_DEBUG_LINE_COUNT) { this._debugLineCount++; - Vec3.copy(CC_V3_0, line.pos0); - Vec3.copy(CC_V3_1, line.pos1); - getColorPXColor(CC_COLOR_0, line.color0 as number); + const f32RawPtr = PX.HEAPF32.subarray(linePtr / 4, linePtr / 4 + 3 * 8); + const u32RawPtr = PX.HEAPU32.subarray(linePtr / 4, linePtr / 4 + 3 * 8); + CC_V3_0.x = f32RawPtr[0]; + CC_V3_0.y = f32RawPtr[1]; + CC_V3_0.z = f32RawPtr[2]; + const color0 = u32RawPtr[3] as number; + CC_V3_1.x = f32RawPtr[4]; + CC_V3_1.y = f32RawPtr[5]; + CC_V3_1.z = f32RawPtr[6]; + getColorPXColor(CC_COLOR_0, color0); debugRenderer.addLine(CC_V3_0, CC_V3_1, CC_COLOR_0); } } - private _onDebugDrawTriangle (triangle: PX.PxDebugTriangle): void { + + private _onDebugDrawTriangle (trianglePtr: number): void { const debugRenderer = this._getDebugRenderer(); if (debugRenderer && (this._MAX_DEBUG_LINE_COUNT - this._debugLineCount) >= 3) { this._debugLineCount += 3; - Vec3.copy(CC_V3_0, triangle.pos0); - Vec3.copy(CC_V3_1, triangle.pos1); - Vec3.copy(CC_V3_2, triangle.pos2); - getColorPXColor(CC_COLOR_0, triangle.color0 as number); + const f32RawPtr = PX.HEAPF32.subarray(trianglePtr / 4, trianglePtr / 4 + 3 * 12); + const u32RawPtr = PX.HEAPU32.subarray(trianglePtr / 4, trianglePtr / 4 + 3 * 12); + CC_V3_0.x = f32RawPtr[0]; + CC_V3_0.y = f32RawPtr[1]; + CC_V3_0.z = f32RawPtr[2]; + const color0 = u32RawPtr[3] as number; + CC_V3_1.x = f32RawPtr[4]; + CC_V3_1.y = f32RawPtr[5]; + CC_V3_1.z = f32RawPtr[6]; + // const color1 = u32RawPtr[7] as number; + CC_V3_2.x = f32RawPtr[8]; + CC_V3_2.y = f32RawPtr[9]; + CC_V3_2.z = f32RawPtr[10]; + // const color2 = u32RawPtr[11] as number; + getColorPXColor(CC_COLOR_0, color0); debugRenderer.addLine(CC_V3_0, CC_V3_1, CC_COLOR_0); + // getColorPXColor(CC_COLOR_0, color1); debugRenderer.addLine(CC_V3_1, CC_V3_2, CC_COLOR_0); + // getColorPXColor(CC_COLOR_0, color2); debugRenderer.addLine(CC_V3_2, CC_V3_0, CC_COLOR_0); } } From 48edbb5ca074a9f17963f969b7b475692ecd5f56 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Wed, 6 Sep 2023 09:47:29 +0800 Subject: [PATCH 04/15] tweaks --- cocos/physics/bullet/bullet-world.ts | 14 ++++++++------ cocos/physics/physx/physx-adapter.ts | 2 +- cocos/physics/physx/physx-world.ts | 14 +++++++------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index f2f438b1f8b..f7ba30adf04 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -119,8 +119,11 @@ export class BulletWorld implements IPhysicsWorld { 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; @@ -830,7 +833,6 @@ export class BulletWorld implements IPhysicsWorld { } } - _debugDrawFlags = EPhysicsDrawFlags.None; get debugDrawFlags (): EPhysicsDrawFlags { return this._debugDrawFlags; } @@ -842,7 +844,6 @@ export class BulletWorld implements IPhysicsWorld { } } - _debugConstraintSize = 0.3; //B3_DEFAULT_DEBUGDRAW_SIZE get debugDrawConstraintSize (): number { return this._debugConstraintSize; } @@ -854,7 +855,7 @@ export class BulletWorld implements IPhysicsWorld { } } - _setDebugDrawMode (): void { + private _setDebugDrawMode (): void { let btDrawMode = 0; if (this._debugDrawFlags & EPhysicsDrawFlags.WireFrame) { btDrawMode |= EBulletDebugDrawModes.DBG_DrawWireframe; @@ -872,7 +873,7 @@ export class BulletWorld implements IPhysicsWorld { bt.DebugDraw_setDebugMode(this._debugDraw, btDrawMode); } - _getDebugRenderer (): GeometryRenderer|null { + private _getDebugRenderer (): GeometryRenderer|null { const cameras = director.root!.cameraList; if (!cameras) return null; if (cameras.length === 0) return null; @@ -882,7 +883,8 @@ export class BulletWorld implements IPhysicsWorld { return cameras[0].geometryRenderer; } - onDebugDrawLine (from: number, to: number, color: number): void { + // 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++; @@ -894,7 +896,7 @@ export class BulletWorld implements IPhysicsWorld { } } - onClearLines (): void { + public onClearLines (): void { this._debugLineCount = 0; } } diff --git a/cocos/physics/physx/physx-adapter.ts b/cocos/physics/physx/physx-adapter.ts index 985e324a0c1..7de52294d54 100644 --- a/cocos/physics/physx/physx-adapter.ts +++ b/cocos/physics/physx/physx-adapter.ts @@ -60,7 +60,7 @@ game.onPostInfrastructureInitDelegate.add(InitPhysXLibs); export function InitPhysXLibs (): any { if (USE_BYTEDANCE) { if (!EDITOR && !TEST) console.debug('[PHYSICS]:', `Use PhysX Libs in BYTEDANCE.`); - Object.assign(PX, globalThis.nativePhysX); + PX = globalThis.nativePhysX; Object.assign(_pxtrans, new PX.Transform(_v3, _v4)); _pxtrans.setPosition = PX.Transform.prototype.setPosition.bind(_pxtrans); _pxtrans.setQuaternion = PX.Transform.prototype.setQuaternion.bind(_pxtrans); diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index 25470082df9..a3b424e775d 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -72,6 +72,11 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { private static _sweepSphereGeometry: any; private static _sweepCapsuleGeometry: any; + private _debugLineCount = 0; + private _MAX_DEBUG_LINE_COUNT = 16384; + private _debugDrawFlags = EPhysicsDrawFlags.None; + private _debugConstraintSize = 0.3; + constructor () { super(); initializeWorld(this); @@ -139,10 +144,6 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { } } - private _debugLineCount = 0; - private _MAX_DEBUG_LINE_COUNT = 16384; - - _debugDrawFlags = EPhysicsDrawFlags.None; get debugDrawFlags (): EPhysicsDrawFlags { return this._debugDrawFlags; } @@ -152,7 +153,6 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { this._setDebugDrawMode(); } - _debugConstraintSize = 0.3; get debugDrawConstraintSize (): number { return this._debugConstraintSize; } @@ -162,7 +162,7 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { this._setDebugDrawMode(); } - _setDebugDrawMode (): void { + private _setDebugDrawMode (): void { if (this._debugDrawFlags & EPhysicsDrawFlags.WireFrame) { this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_SHAPES, 1); } else { @@ -181,7 +181,7 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { } } - _getDebugRenderer (): GeometryRenderer|null { + private _getDebugRenderer (): GeometryRenderer|null { const cameras = director.root!.cameraList; if (!cameras) return null; if (cameras.length === 0) return null; From 94b709ef93c81fd03089012e0c372f11489378c3 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Wed, 6 Sep 2023 15:29:22 +0800 Subject: [PATCH 05/15] add debug draw for physx c++ --- native/cocos/physics/physx/PhysXWorld.cpp | 110 ++++++++++++++++++ native/cocos/physics/physx/PhysXWorld.h | 17 +++ .../physics/physx/joints/PhysXFixedJoint.cpp | 1 + .../physx/joints/PhysXGenericJoint.cpp | 1 + .../cocos/physics/physx/joints/PhysXJoint.cpp | 7 ++ .../cocos/physics/physx/joints/PhysXJoint.h | 2 + .../physics/physx/joints/PhysXRevolute.cpp | 2 + .../physics/physx/joints/PhysXSpherical.cpp | 1 + native/cocos/physics/sdk/World.cpp | 16 +++ native/cocos/physics/sdk/World.h | 4 + native/cocos/physics/spec/IWorld.h | 11 ++ platforms/native/engine/jsb-physics.js | 16 +++ 12 files changed, 188 insertions(+) diff --git a/native/cocos/physics/physx/PhysXWorld.cpp b/native/cocos/physics/physx/PhysXWorld.cpp index 96f0d4084f7..57f8c89393c 100644 --- a/native/cocos/physics/physx/PhysXWorld.cpp +++ b/native/cocos/physics/physx/PhysXWorld.cpp @@ -29,6 +29,9 @@ #include "physics/physx/PhysXUtils.h" #include "physics/physx/joints/PhysXJoint.h" #include "physics/spec/IWorld.h" +#include "core/Root.h" +#include "scene/Camera.h" +#include "renderer/pipeline/Define.h" namespace cc { namespace physics { @@ -86,6 +89,7 @@ PhysXWorld::PhysXWorld() { sceneDesc.filterShader = simpleFilterShader; sceneDesc.simulationEventCallback = &_mEventMgr->getEventCallback(); _mScene = _mPhysics->createScene(sceneDesc); + _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE, 1.0F); _mControllerManager = PxCreateControllerManager(*_mScene); @@ -119,6 +123,112 @@ void PhysXWorld::step(float fixedTimeStep) { _mScene->simulate(fixedTimeStep); _mScene->fetchResults(true); syncPhysicsToScene(); + debugDraw(); +} + +pipeline::GeometryRenderer* PhysXWorld::getDebugRenderer () { + auto cameras = Root::getInstance()->getCameraList(); + scene::Camera* camera = nullptr; + for (int c = 0; c < cameras.size(); c++) { + if (!cameras[c]) continue; + + const bool defaultCamera = cameras[c]->getVisibility() & static_cast(pipeline::LayerList::DEFAULT); + bool validPointer = cameras[c]->getRefCount() < 10000; + if (defaultCamera && validPointer) { + camera = cameras[c]; + //CC_LOG_WARNING("use camera %d\n", c); + break; + } + } + + if (camera) { + camera->initGeometryRenderer(); + return camera->getGeometryRenderer(); + } + + return nullptr; +} + +static void getColorPXColor (gfx::Color& color, physx::PxU32 rgba) { + color.z = ((rgba >> 16) & 0xff); + color.y = ((rgba >> 8) & 0xff); + color.x = ((rgba) & 0xff); + color.w = 255; +} + +void PhysXWorld::debugDraw () { + pipeline::GeometryRenderer* debugRenderer = getDebugRenderer(); + if (!debugRenderer) return; + auto cameras = Root::getInstance()->getCameraList(); + _debugLineCount = 0; + static Vec3 v0, v1; + static gfx::Color c; + auto& rb = _mScene->getRenderBuffer();//PxRenderBuffer + // lines + for (int i = 0; i < rb.getNbLines(); i++) { + if (_debugLineCount < _MAX_DEBUG_LINE_COUNT){ + _debugLineCount++; + const physx::PxDebugLine& line = rb.getLines()[i]; + getColorPXColor(c, line.color0); + pxSetVec3Ext(v0, line.pos0); + pxSetVec3Ext(v1, line.pos1); + debugRenderer->addLine(v0, v1, c); + } + } + // triangles + for (int i = 0; i < rb.getNbTriangles(); i++) { + if (_debugLineCount < _MAX_DEBUG_LINE_COUNT - 3) { + _debugLineCount = _debugLineCount + 3; + const physx::PxDebugTriangle& triangle = rb.getTriangles()[i]; + getColorPXColor(c, triangle.color0); + pxSetVec3Ext(v0, triangle.pos0); + pxSetVec3Ext(v1, triangle.pos1); + debugRenderer->addLine(v0, v1, c); + pxSetVec3Ext(v0, triangle.pos1); + pxSetVec3Ext(v1, triangle.pos2); + debugRenderer->addLine(v0, v1, c); + pxSetVec3Ext(v0, triangle.pos2); + pxSetVec3Ext(v1, triangle.pos0); + debugRenderer->addLine(v0, v1, c); + } + } +} + +void PhysXWorld::setDebugDrawMode() { + if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::WireFrame)) { + _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 1); + } else { + _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 0); + } + + bool drawConstraint = bool(uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::Constraint)); + float internalConstraintSize = drawConstraint ? _debugConstraintSize : 0; + _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eJOINT_LOCAL_FRAMES, internalConstraintSize); + _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eJOINT_LIMITS, internalConstraintSize); + + if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::Aabb)) { + _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_AABBS, 1); + } else { + _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_AABBS, 0); + } +} + +void PhysXWorld::setDebugDrawFlags(EPhysicsDrawFlags flags) { + _debugDrawFlags = flags; + setDebugDrawMode(); +} + +EPhysicsDrawFlags PhysXWorld::getDebugDrawFlags() { + return _debugDrawFlags; +} + +void PhysXWorld::setDebugDrawConstraintSize(float size) { + _debugConstraintSize = size; + setDebugDrawMode(); +} + +float PhysXWorld::getDebugDrawConstraintSize() { + return _debugConstraintSize; } void PhysXWorld::setGravity(float x, float y, float z) { diff --git a/native/cocos/physics/physx/PhysXWorld.h b/native/cocos/physics/physx/PhysXWorld.h index 08cfa6a9d43..d13304b0843 100644 --- a/native/cocos/physics/physx/PhysXWorld.h +++ b/native/cocos/physics/physx/PhysXWorld.h @@ -28,6 +28,7 @@ #include "base/Macros.h" #include "base/std/container/vector.h" #include "core/scene-graph/Node.h" +#include "renderer/pipeline/GeometryRenderer.h" #include "physics/physx/PhysXEventManager.h" #include "physics/physx/PhysXFilterShader.h" #include "physics/physx/PhysXInc.h" @@ -124,6 +125,17 @@ class PhysXWorld final : virtual public IPhysicsWorld { float getFixedTimeStep() const override { return _fixedTimeStep; } void setFixedTimeStep(float fixedTimeStep) override { _fixedTimeStep = fixedTimeStep; } + virtual void setDebugDrawFlags(EPhysicsDrawFlags flags) override; + virtual EPhysicsDrawFlags getDebugDrawFlags() override; + + virtual void setDebugDrawConstraintSize(float size) override; + virtual float getDebugDrawConstraintSize() override; + +private: + pipeline::GeometryRenderer* getDebugRenderer(); + void debugDraw(); + void setDebugDrawMode(); + private: static PhysXWorld *instance; physx::PxFoundation *_mFoundation; @@ -147,6 +159,11 @@ class PhysXWorld final : virtual public IPhysicsWorld { ccstd::unordered_map _mWrapperObjects; float _fixedTimeStep{1 / 60.0F}; + + uint32_t _debugLineCount = 0; + uint32_t _MAX_DEBUG_LINE_COUNT = 16384; + EPhysicsDrawFlags _debugDrawFlags = EPhysicsDrawFlags::None; + float _debugConstraintSize = 0.3; }; } // namespace physics diff --git a/native/cocos/physics/physx/joints/PhysXFixedJoint.cpp b/native/cocos/physics/physx/joints/PhysXFixedJoint.cpp index c44b5f2e39d..fd172d9d032 100644 --- a/native/cocos/physics/physx/joints/PhysXFixedJoint.cpp +++ b/native/cocos/physics/physx/joints/PhysXFixedJoint.cpp @@ -44,6 +44,7 @@ void PhysXFixedJoint::onComponentSet() { _mJoint = PxFixedJointCreate(PxGetPhysics(), actor0, _transA, actor1, _transB); updatePose(); + setEnableDebugVisualization(true); } void PhysXFixedJoint::setBreakForce(float force) { diff --git a/native/cocos/physics/physx/joints/PhysXGenericJoint.cpp b/native/cocos/physics/physx/joints/PhysXGenericJoint.cpp index 2519189da09..cace104cb28 100644 --- a/native/cocos/physics/physx/joints/PhysXGenericJoint.cpp +++ b/native/cocos/physics/physx/joints/PhysXGenericJoint.cpp @@ -36,6 +36,7 @@ namespace physics { void PhysXGenericJoint::onComponentSet() { _mJoint = PxD6JointCreate(PxGetPhysics(), &getTempRigidActor(), physx::PxTransform{physx::PxIdentity}, nullptr, physx::PxTransform{physx::PxIdentity}); + setEnableDebugVisualization(true); } inline auto mapAxis(uint32_t index) -> physx::PxD6Axis::Enum { diff --git a/native/cocos/physics/physx/joints/PhysXJoint.cpp b/native/cocos/physics/physx/joints/PhysXJoint.cpp index aff2e264f05..1b1fa4a4c9f 100644 --- a/native/cocos/physics/physx/joints/PhysXJoint.cpp +++ b/native/cocos/physics/physx/joints/PhysXJoint.cpp @@ -104,6 +104,13 @@ void PhysXJoint::setEnableCollision(const bool v) { } } +void PhysXJoint::setEnableDebugVisualization(const bool v) { + _mEnableDebugVisualization = v; + if (_mJoint) { + _mJoint->setConstraintFlag(physx::PxConstraintFlag::eVISUALIZATION, _mEnableDebugVisualization); + } +} + physx::PxRigidActor &PhysXJoint::getTempRigidActor() { if (!PhysXJoint::tempRigidActor) { PhysXJoint::tempRigidActor = PxGetPhysics().createRigidDynamic(physx::PxTransform{physx::PxIdentity}); diff --git a/native/cocos/physics/physx/joints/PhysXJoint.h b/native/cocos/physics/physx/joints/PhysXJoint.h index f7f02836b85..d17f48c3654 100644 --- a/native/cocos/physics/physx/joints/PhysXJoint.h +++ b/native/cocos/physics/physx/joints/PhysXJoint.h @@ -45,6 +45,7 @@ class PhysXJoint : virtual public IBaseJoint { void onDestroy() override; void setConnectedBody(uint32_t rigidBodyID) override; void setEnableCollision(bool v) override; + void setEnableDebugVisualization(bool v); virtual void updateScale0() = 0; virtual void updateScale1() = 0; static physx::PxRigidActor &getTempRigidActor(); @@ -56,6 +57,7 @@ class PhysXJoint : virtual public IBaseJoint { PhysXSharedBody *_mSharedBody{nullptr}; PhysXSharedBody *_mConnectedBody{nullptr}; bool _mEnableCollision{false}; + bool _mEnableDebugVisualization{ false }; virtual void onComponentSet() = 0; uint32_t _mObjectID{0}; diff --git a/native/cocos/physics/physx/joints/PhysXRevolute.cpp b/native/cocos/physics/physx/joints/PhysXRevolute.cpp index 6ceb5ef3d92..b8e69174d64 100644 --- a/native/cocos/physics/physx/joints/PhysXRevolute.cpp +++ b/native/cocos/physics/physx/joints/PhysXRevolute.cpp @@ -45,6 +45,8 @@ void PhysXRevolute::onComponentSet() { joint->setConstraintFlag(physx::PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES, true); joint->setProjectionAngularTolerance(0.2); joint->setProjectionLinearTolerance(0.2); + + setEnableDebugVisualization(true); } void PhysXRevolute::setPivotA(float x, float y, float z) { diff --git a/native/cocos/physics/physx/joints/PhysXSpherical.cpp b/native/cocos/physics/physx/joints/PhysXSpherical.cpp index 6458f73cb3b..df51ecbdfde 100644 --- a/native/cocos/physics/physx/joints/PhysXSpherical.cpp +++ b/native/cocos/physics/physx/joints/PhysXSpherical.cpp @@ -32,6 +32,7 @@ namespace physics { void PhysXSpherical::onComponentSet() { _mJoint = PxSphericalJointCreate(PxGetPhysics(), &getTempRigidActor(), physx::PxTransform{physx::PxIdentity}, nullptr, physx::PxTransform{physx::PxIdentity}); + setEnableDebugVisualization(true); } void PhysXSpherical::setPivotA(float x, float y, float z) { diff --git a/native/cocos/physics/sdk/World.cpp b/native/cocos/physics/sdk/World.cpp index 6849def1576..5bdbeeb9653 100644 --- a/native/cocos/physics/sdk/World.cpp +++ b/native/cocos/physics/sdk/World.cpp @@ -86,6 +86,22 @@ ccstd::vector> &World::getCCTTriggerEventPa return _impl->getCCTTriggerEventPairs(); } +void World::setDebugDrawFlags(EPhysicsDrawFlags flags) { + _impl->setDebugDrawFlags(flags); +} + +EPhysicsDrawFlags World::getDebugDrawFlags() { + return _impl->getDebugDrawFlags(); +} + +void World::setDebugDrawConstraintSize(float size) { + _impl->setDebugDrawConstraintSize(size); +} + +float World::getDebugDrawConstraintSize() { + return _impl->getDebugDrawConstraintSize(); +} + void World::setCollisionMatrix(uint32_t i, uint32_t m) { _impl->setCollisionMatrix(i, m); } diff --git a/native/cocos/physics/sdk/World.h b/native/cocos/physics/sdk/World.h index 33be08ac30c..dec44009df6 100644 --- a/native/cocos/physics/sdk/World.h +++ b/native/cocos/physics/sdk/World.h @@ -40,6 +40,10 @@ class CC_DLL World final : public IPhysicsWorld { void emitEvents() override; void syncSceneToPhysics() override; void syncSceneWithCheck() override; + void setDebugDrawFlags(EPhysicsDrawFlags flags) override; + EPhysicsDrawFlags getDebugDrawFlags() override; + void setDebugDrawConstraintSize(float size) override; + float getDebugDrawConstraintSize() override; void setCollisionMatrix(uint32_t i, uint32_t m) override; ccstd::vector> &getTriggerEventPairs() override; ccstd::vector>& getContactEventPairs() override; diff --git a/native/cocos/physics/spec/IWorld.h b/native/cocos/physics/spec/IWorld.h index 062b8d37cdc..7f2eaa94a24 100644 --- a/native/cocos/physics/spec/IWorld.h +++ b/native/cocos/physics/spec/IWorld.h @@ -39,6 +39,13 @@ enum class ETouchState : uint8_t { EXIT = 2, }; +enum class EPhysicsDrawFlags : uint32_t { + None = 0, + WireFrame = 0x0001, + Constraint = 0x0002, + Aabb = 0x0004 +}; + struct TriggerEventPair { uint32_t shapeA; //wrapper object ID uint32_t shapeB; //wrapper object ID @@ -145,6 +152,10 @@ class IPhysicsWorld { virtual void syncSceneToPhysics() = 0; virtual void syncSceneWithCheck() = 0; virtual void destroy() = 0; + virtual void setDebugDrawFlags(EPhysicsDrawFlags f) = 0; + virtual EPhysicsDrawFlags getDebugDrawFlags() = 0; + virtual void setDebugDrawConstraintSize(float s) = 0; + virtual float getDebugDrawConstraintSize() = 0; virtual void setCollisionMatrix(uint32_t i, uint32_t m) = 0; virtual ccstd::vector> &getTriggerEventPairs() = 0; virtual ccstd::vector>& getContactEventPairs() = 0; diff --git a/platforms/native/engine/jsb-physics.js b/platforms/native/engine/jsb-physics.js index 89a488659c1..87b4d8b93cc 100644 --- a/platforms/native/engine/jsb-physics.js +++ b/platforms/native/engine/jsb-physics.js @@ -192,6 +192,22 @@ class PhysicsWorld { this._impl.step(f); } + set debugDrawFlags (v) { + this._impl.setDebugDrawFlags(v); + } + + get debugDrawFlags () { + return this._impl.getDebugDrawFlags(); + } + + set debugDrawConstraintSize (v) { + this._impl.setDebugDrawConstraintSize(v); + } + + get debugDrawConstraintSize () { + return this._impl.getDebugDrawConstraintSize(); + } + raycast (r, o, p, rs) { raycastOptions.origin = r.o; raycastOptions.unitDir = r.d; From f306ab8b301368f2c3f5c1eb14d4207b7c25c7b6 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Thu, 7 Sep 2023 15:05:31 +0800 Subject: [PATCH 06/15] debug draw use MainWindow's cameras --- cocos/physics/bullet/bullet-world.ts | 2 +- cocos/physics/physx/physx-world.ts | 2 +- native/cocos/physics/physx/PhysXUtils.h | 8 +++++++ native/cocos/physics/physx/PhysXWorld.cpp | 26 ++++++++--------------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index f7ba30adf04..180b9f62403 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -874,7 +874,7 @@ export class BulletWorld implements IPhysicsWorld { } private _getDebugRenderer (): GeometryRenderer|null { - const cameras = director.root!.cameraList; + const cameras = director.root!.mainWindow?.cameras; if (!cameras) return null; if (cameras.length === 0) return null; if (!cameras[0]) return null; diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index a3b424e775d..15a68cda976 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -182,7 +182,7 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { } private _getDebugRenderer (): GeometryRenderer|null { - const cameras = director.root!.cameraList; + const cameras = director.root!.mainWindow?.cameras; if (!cameras) return null; if (cameras.length === 0) return null; if (!cameras[0]) return null; diff --git a/native/cocos/physics/physx/PhysXUtils.h b/native/cocos/physics/physx/PhysXUtils.h index 46fc6444571..59a79a771cd 100644 --- a/native/cocos/physics/physx/PhysXUtils.h +++ b/native/cocos/physics/physx/PhysXUtils.h @@ -27,6 +27,7 @@ #include "base/Macros.h" #include "base/std/container/unordered_map.h" #include "base/std/container/vector.h" +#include "renderer/pipeline/Define.h" #include "math/Vec3.h" #include "math/Vec4.h" #include "physics/physx/PhysXFilterShader.h" @@ -116,6 +117,13 @@ inline void pxSetQuatExt(T1 &p, const T2 &cp) { p = T1(cp.x, cp.y, cp.z, cp.w); } +inline void pxSetColor(gfx::Color& color, physx::PxU32 rgba) { + color.z = ((rgba >> 16) & 0xff); + color.y = ((rgba >> 8) & 0xff); + color.x = ((rgba) & 0xff); + color.w = 255; +} + template inline T pxAbsMax(const T &a, const T &b) { return physx::PxAbs(a) > physx::PxAbs(b) ? a : b; diff --git a/native/cocos/physics/physx/PhysXWorld.cpp b/native/cocos/physics/physx/PhysXWorld.cpp index 57f8c89393c..03ca908d4cc 100644 --- a/native/cocos/physics/physx/PhysXWorld.cpp +++ b/native/cocos/physics/physx/PhysXWorld.cpp @@ -31,7 +31,9 @@ #include "physics/spec/IWorld.h" #include "core/Root.h" #include "scene/Camera.h" +#include "scene/RenderWindow.h" #include "renderer/pipeline/Define.h" +#include "renderer/pipeline/RenderPipeline.h" namespace cc { namespace physics { @@ -127,16 +129,14 @@ void PhysXWorld::step(float fixedTimeStep) { } pipeline::GeometryRenderer* PhysXWorld::getDebugRenderer () { - auto cameras = Root::getInstance()->getCameraList(); + auto cameras = Root::getInstance()->getMainWindow()->getCameras(); scene::Camera* camera = nullptr; for (int c = 0; c < cameras.size(); c++) { - if (!cameras[c]) continue; - + if (!cameras[c]) + continue; const bool defaultCamera = cameras[c]->getVisibility() & static_cast(pipeline::LayerList::DEFAULT); - bool validPointer = cameras[c]->getRefCount() < 10000; - if (defaultCamera && validPointer) { + if (defaultCamera) { camera = cameras[c]; - //CC_LOG_WARNING("use camera %d\n", c); break; } } @@ -149,27 +149,19 @@ pipeline::GeometryRenderer* PhysXWorld::getDebugRenderer () { return nullptr; } -static void getColorPXColor (gfx::Color& color, physx::PxU32 rgba) { - color.z = ((rgba >> 16) & 0xff); - color.y = ((rgba >> 8) & 0xff); - color.x = ((rgba) & 0xff); - color.w = 255; -} - void PhysXWorld::debugDraw () { pipeline::GeometryRenderer* debugRenderer = getDebugRenderer(); if (!debugRenderer) return; - auto cameras = Root::getInstance()->getCameraList(); _debugLineCount = 0; static Vec3 v0, v1; static gfx::Color c; - auto& rb = _mScene->getRenderBuffer();//PxRenderBuffer + auto& rb = _mScene->getRenderBuffer(); // lines for (int i = 0; i < rb.getNbLines(); i++) { if (_debugLineCount < _MAX_DEBUG_LINE_COUNT){ _debugLineCount++; const physx::PxDebugLine& line = rb.getLines()[i]; - getColorPXColor(c, line.color0); + pxSetColor(c, line.color0); pxSetVec3Ext(v0, line.pos0); pxSetVec3Ext(v1, line.pos1); debugRenderer->addLine(v0, v1, c); @@ -180,7 +172,7 @@ void PhysXWorld::debugDraw () { if (_debugLineCount < _MAX_DEBUG_LINE_COUNT - 3) { _debugLineCount = _debugLineCount + 3; const physx::PxDebugTriangle& triangle = rb.getTriangles()[i]; - getColorPXColor(c, triangle.color0); + pxSetColor(c, triangle.color0); pxSetVec3Ext(v0, triangle.pos0); pxSetVec3Ext(v1, triangle.pos1); debugRenderer->addLine(v0, v1, c); From d52f30af1143b6b9df42cd7045e9f4c30c9ef3d5 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Fri, 8 Sep 2023 12:04:53 +0800 Subject: [PATCH 07/15] builtin physics draw; WireFrame-->wireframe --- cocos/physics/bullet/bullet-world.ts | 2 +- cocos/physics/cocos/builtin-world.ts | 133 +++++++++++++++--- .../physics/cocos/shapes/builtin-box-shape.ts | 8 ++ .../cocos/shapes/builtin-capsule-shape.ts | 20 ++- .../cocos/shapes/builtin-sphere-shape.ts | 9 +- cocos/physics/framework/physics-enum.ts | 2 +- cocos/physics/physx/physx-world.ts | 2 +- native/cocos/physics/physx/PhysXWorld.cpp | 2 +- native/cocos/physics/spec/IWorld.h | 2 +- 9 files changed, 156 insertions(+), 24 deletions(-) diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index 180b9f62403..7ba7ae2cf6f 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -857,7 +857,7 @@ export class BulletWorld implements IPhysicsWorld { private _setDebugDrawMode (): void { let btDrawMode = 0; - if (this._debugDrawFlags & EPhysicsDrawFlags.WireFrame) { + if (this._debugDrawFlags & EPhysicsDrawFlags.Wireframe) { btDrawMode |= EBulletDebugDrawModes.DBG_DrawWireframe; } diff --git a/cocos/physics/cocos/builtin-world.ts b/cocos/physics/cocos/builtin-world.ts index 304cea733a2..1689ae80325 100644 --- a/cocos/physics/cocos/builtin-world.ts +++ b/cocos/physics/cocos/builtin-world.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { Vec3, RecyclePool, error, js, IVec3Like, geometry, IQuatLike, warnID } from '../../core'; +import { Vec3, RecyclePool, error, js, IVec3Like, geometry, IQuatLike, warnID, Color } from '../../core'; import { PhysicsRayResult } from '../framework/physics-ray-result'; import { BuiltinSharedBody } from './builtin-shared-body'; import { BuiltinShape } from './shapes/builtin-shape'; @@ -30,9 +30,12 @@ import { ArrayCollisionMatrix } from '../utils/array-collision-matrix'; import { IPhysicsWorld, IRaycastOptions } from '../spec/i-physics-world'; import { PhysicsMaterial } from '../framework/assets/physics-material'; import { TriggerEventType } from '../framework/physics-interface'; -import { Collider } from '../../../exports/physics-framework'; +import { Collider, EPhysicsDrawFlags } from '../../../exports/physics-framework'; import { BuiltinRigidBody } from './builtin-rigid-body'; import { Node } from '../../scene-graph'; +import { GeometryRenderer } from '../../rendering/geometry-renderer'; +import { director } from '../../game'; +import { VEC3_0 } from '../utils/util'; const hitPoint = new Vec3(); const TriggerEventObject = { @@ -42,51 +45,92 @@ const TriggerEventObject = { impl: {} as any, }; +const aabbTemp = new geometry.AABB(); + /** * Built-in collision system, intended for use as a * efficient discrete collision detector, * not a full physical simulator */ export class BuiltInWorld implements IPhysicsWorld { - sweepBox (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepBox ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { warnID(9640); return false; } - sweepBoxClosest (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepBoxClosest ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { warnID(9640); return false; } - sweepSphere (worldRay: geometry.Ray, radius: number, options: IRaycastOptions, - pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepSphere ( + worldRay: geometry.Ray, + radius: number, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { warnID(9640); return false; } - sweepSphereClosest (worldRay: geometry.Ray, radius: number, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepSphereClosest ( + worldRay: geometry.Ray, + radius: number, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { warnID(9640); return false; } - sweepCapsule (worldRay: geometry.Ray, radius: number, height: number, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepCapsule ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { warnID(9640); return false; } - sweepCapsuleClosest (worldRay: geometry.Ray, radius: number, height: number, - orientation: IQuatLike, options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepCapsuleClosest ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { warnID(9640); return false; } - setGravity (v: IVec3Like): void { } - setAllowSleep (v: boolean): void { } - setDefaultMaterial (v: PhysicsMaterial): void { } + setGravity (v: IVec3Like): void { + //empty + } + setAllowSleep (v: boolean): void { + //empty + } + setDefaultMaterial (v: PhysicsMaterial): void { + //empty + } get impl (): BuiltInWorld { return this; } shapeArr: BuiltinShape[] = []; readonly bodies: BuiltinSharedBody[] = []; @@ -95,6 +139,29 @@ export class BuiltInWorld implements IPhysicsWorld { private _collisionMatrix: ArrayCollisionMatrix = new ArrayCollisionMatrix(); private _collisionMatrixPrev: ArrayCollisionMatrix = new ArrayCollisionMatrix(); + private _debugLineCount = 0; + private _MAX_DEBUG_LINE_COUNT = 16384; + private _debugDrawFlags = EPhysicsDrawFlags.None; + private _debugConstraintSize = 0.3; + private _aabbColor = new Color(0, 255, 255, 255); + private _wireframeColor = new Color(255, 0, 255, 255); + + get debugDrawFlags (): EPhysicsDrawFlags { + return this._debugDrawFlags; + } + + set debugDrawFlags (v: EPhysicsDrawFlags) { + this._debugDrawFlags = v; + } + + get debugDrawConstraintSize (): number { + return this._debugConstraintSize; + } + + set debugDrawConstraintSize (v) { + this._debugConstraintSize = v; + } + destroy (): void { if (this.bodies.length) error('You should destroy all physics component first.'); } @@ -120,6 +187,8 @@ export class BuiltInWorld implements IPhysicsWorld { bodyA.intersects(bodyB); } } + + this._debugDraw(); } syncSceneToPhysics (): void { @@ -265,4 +334,34 @@ export class BuiltInWorld implements IPhysicsWorld { this._collisionMatrix.matrix = temp; this._collisionMatrix.reset(); } + + 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; + } + + private _debugDraw (): void { + const debugRenderer = this._getDebugRenderer(); + if (!debugRenderer) return; + + this._debugLineCount = 0; + if (this._debugDrawFlags & EPhysicsDrawFlags.Aabb) { + for (let i = 0; i < this.bodies.length; i++) { + const body = this.bodies[i]; + for (let j = 0; j < body.shapes.length; j++) { + const shape = body.shapes[j]; + if (this._debugLineCount + 12 < this._MAX_DEBUG_LINE_COUNT) { + this._debugLineCount += 12; + shape.getAABB(aabbTemp); + debugRenderer.addBoundingBox(aabbTemp, this._aabbColor); + } + } + } + } + } } diff --git a/cocos/physics/cocos/shapes/builtin-box-shape.ts b/cocos/physics/cocos/shapes/builtin-box-shape.ts index 5c868652725..dba0245cfc1 100644 --- a/cocos/physics/cocos/shapes/builtin-box-shape.ts +++ b/cocos/physics/cocos/shapes/builtin-box-shape.ts @@ -27,6 +27,9 @@ import { BuiltinShape } from './builtin-shape'; import { IBoxShape } from '../../spec/i-physics-shape'; import { BoxCollider } from '../../../../exports/physics-framework'; +const tempMin = new Vec3(); +const tempMax = new Vec3(); + export class BuiltinBoxShape extends BuiltinShape implements IBoxShape { get localObb (): geometry.OBB { return this._localShape as geometry.OBB; @@ -55,4 +58,9 @@ export class BuiltinBoxShape extends BuiltinShape implements IBoxShape { super.onLoad(); this.updateSize(); } + + getAABB (v: geometry.AABB): void { + this.worldObb.getBoundary(tempMin, tempMax); + geometry.AABB.fromPoints(v, tempMin, tempMax); + } } diff --git a/cocos/physics/cocos/shapes/builtin-capsule-shape.ts b/cocos/physics/cocos/shapes/builtin-capsule-shape.ts index c687c5eeea5..32f9bc0f37e 100644 --- a/cocos/physics/cocos/shapes/builtin-capsule-shape.ts +++ b/cocos/physics/cocos/shapes/builtin-capsule-shape.ts @@ -24,9 +24,11 @@ import { BuiltinShape } from './builtin-shape'; import { ICapsuleShape } from '../../spec/i-physics-shape'; -import { geometry } from '../../../core'; +import { Vec3, geometry } from '../../../core'; import { EAxisDirection, CapsuleCollider } from '../../framework'; +const temp0 = new Vec3(); +const temp1 = new Vec3(); export class BuiltinCapsuleShape extends BuiltinShape implements ICapsuleShape { get localCapsule (): geometry.Capsule { return this._localShape as geometry.Capsule; @@ -90,4 +92,20 @@ export class BuiltinCapsuleShape extends BuiltinShape implements ICapsuleShape { this.setRadius(this.collider.radius); this.setDirection(this.collider.direction); } + + getAABB (v: geometry.AABB): void { + //capsule has not implement getBoundary + v.center.set(this.worldCapsule.center); + v.halfExtents.set(0, 0, 0); + temp0.set(this.worldCapsule.radius, this.worldCapsule.radius, this.worldCapsule.radius); + + Vec3.add(temp1, this.worldCapsule.ellipseCenter0, temp0); + v.mergePoint(temp1); + Vec3.subtract(temp1, this.worldCapsule.ellipseCenter0, temp0); + v.mergePoint(temp1); + Vec3.add(temp1, this.worldCapsule.ellipseCenter1, temp0); + v.mergePoint(temp1); + Vec3.subtract(temp1, this.worldCapsule.ellipseCenter1, temp0); + v.mergePoint(temp1); + } } diff --git a/cocos/physics/cocos/shapes/builtin-sphere-shape.ts b/cocos/physics/cocos/shapes/builtin-sphere-shape.ts index 45a82ff5e1f..5d1b63cbacb 100644 --- a/cocos/physics/cocos/shapes/builtin-sphere-shape.ts +++ b/cocos/physics/cocos/shapes/builtin-sphere-shape.ts @@ -22,12 +22,14 @@ THE SOFTWARE. */ -import { geometry } from '../../../core'; +import { Vec3, geometry } from '../../../core'; import { BuiltinShape } from './builtin-shape'; import { ISphereShape } from '../../spec/i-physics-shape'; import { maxComponent } from '../../utils/util'; import { SphereCollider } from '../../../../exports/physics-framework'; +const tempMin = new Vec3(); +const tempMax = new Vec3(); export class BuiltinSphereShape extends BuiltinShape implements ISphereShape { updateRadius (): void { this.localSphere.radius = this.collider.radius; @@ -57,4 +59,9 @@ export class BuiltinSphereShape extends BuiltinShape implements ISphereShape { super.onLoad(); this.updateRadius(); } + + getAABB (v: geometry.AABB): void { + this.worldSphere.getBoundary(tempMin, tempMax); + geometry.AABB.fromPoints(v, tempMin, tempMax); + } } diff --git a/cocos/physics/framework/physics-enum.ts b/cocos/physics/framework/physics-enum.ts index 6d7a00cd3bd..6d841f61005 100644 --- a/cocos/physics/framework/physics-enum.ts +++ b/cocos/physics/framework/physics-enum.ts @@ -417,7 +417,7 @@ export enum EPhysicsDrawFlags { * @zh * 绘制线框。 */ - WireFrame = 0x0001, + Wireframe = 0x0001, /** * @en * Draw Constraint. diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index 15a68cda976..350cb2a7fb5 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -163,7 +163,7 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { } private _setDebugDrawMode (): void { - if (this._debugDrawFlags & EPhysicsDrawFlags.WireFrame) { + if (this._debugDrawFlags & EPhysicsDrawFlags.Wireframe) { this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_SHAPES, 1); } else { this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_SHAPES, 0); diff --git a/native/cocos/physics/physx/PhysXWorld.cpp b/native/cocos/physics/physx/PhysXWorld.cpp index 03ca908d4cc..7fa9bf9f68e 100644 --- a/native/cocos/physics/physx/PhysXWorld.cpp +++ b/native/cocos/physics/physx/PhysXWorld.cpp @@ -187,7 +187,7 @@ void PhysXWorld::debugDraw () { } void PhysXWorld::setDebugDrawMode() { - if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::WireFrame)) { + if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::Wireframe)) { _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 1); } else { _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 0); diff --git a/native/cocos/physics/spec/IWorld.h b/native/cocos/physics/spec/IWorld.h index 7f2eaa94a24..30f2e2ff423 100644 --- a/native/cocos/physics/spec/IWorld.h +++ b/native/cocos/physics/spec/IWorld.h @@ -41,7 +41,7 @@ enum class ETouchState : uint8_t { enum class EPhysicsDrawFlags : uint32_t { None = 0, - WireFrame = 0x0001, + Wireframe = 0x0001, Constraint = 0x0002, Aabb = 0x0004 }; From 34b0a447255e4f704e5caebbbd6255b60a4b26f9 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Fri, 8 Sep 2023 13:49:51 +0800 Subject: [PATCH 08/15] cannon.js supports debug draw --- cocos/physics/cannon/cannon-world.ts | 120 ++++++++++++++++-- .../cocos/shapes/builtin-capsule-shape.ts | 2 +- 2 files changed, 107 insertions(+), 15 deletions(-) diff --git a/cocos/physics/cannon/cannon-world.ts b/cocos/physics/cannon/cannon-world.ts index 03b271d7aed..59f8e58e8e3 100644 --- a/cocos/physics/cannon/cannon-world.ts +++ b/cocos/physics/cannon/cannon-world.ts @@ -23,15 +23,19 @@ */ import CANNON from '@cocos/cannon'; -import { Vec3, RecyclePool, error, js, geometry, IVec3Like, IQuatLike, warnID } from '../../core'; +import { Vec3, RecyclePool, error, js, geometry, IVec3Like, IQuatLike, warnID, Color } from '../../core'; import { fillRaycastResult, toCannonRaycastOptions } from './cannon-util'; import { CannonConstraint } from './constraints/cannon-constraint'; import { CannonShape } from './shapes/cannon-shape'; import { CannonSharedBody } from './cannon-shared-body'; import { IPhysicsWorld, IRaycastOptions } from '../spec/i-physics-world'; -import { PhysicsMaterial, PhysicsRayResult } from '../framework'; +import { EPhysicsDrawFlags, PhysicsMaterial, PhysicsRayResult } from '../framework'; import { CannonRigidBody } from './cannon-rigid-body'; import { Node } from '../../scene-graph'; +import { GeometryRenderer } from '../../rendering/geometry-renderer'; +import { director } from '../../game'; + +const aabbTemp = new geometry.AABB(); export class CannonWorld implements IPhysicsWorld { get impl (): CANNON.World { @@ -64,6 +68,13 @@ export class CannonWorld implements IPhysicsWorld { private _world: CANNON.World; static readonly rayResult = new CANNON.RaycastResult(); + private _debugLineCount = 0; + private _MAX_DEBUG_LINE_COUNT = 16384; + private _debugDrawFlags = EPhysicsDrawFlags.None; + private _debugConstraintSize = 0.3; + private _aabbColor = new Color(0, 255, 255, 255); + private _wireframeColor = new Color(255, 0, 255, 255); + constructor () { this._world = new CANNON.World(); this._world.broadphase = new CANNON.NaiveBroadphase(); @@ -76,38 +87,71 @@ export class CannonWorld implements IPhysicsWorld { this._world.defaultContactMaterial.frictionEquationRelaxation = 3; } - sweepBox (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepBox ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { warnID(9641); return false; } - sweepBoxClosest (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepBoxClosest ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { warnID(9641); return false; } - sweepSphere (worldRay: geometry.Ray, radius: number, options: IRaycastOptions, - pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepSphere ( + worldRay: geometry.Ray, + radius: number, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { warnID(9641); return false; } - sweepSphereClosest (worldRay: geometry.Ray, radius: number, options: IRaycastOptions, - result: PhysicsRayResult): boolean { + sweepSphereClosest ( + worldRay: geometry.Ray, + radius: number, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { warnID(9641); return false; } - sweepCapsule (worldRay: geometry.Ray, radius: number, height: number, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepCapsule ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { warnID(9641); return false; } - sweepCapsuleClosest (worldRay: geometry.Ray, radius: number, height: number, - orientation: IQuatLike, options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepCapsuleClosest ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { warnID(9641); return false; } @@ -141,6 +185,8 @@ export class CannonWorld implements IPhysicsWorld { for (let i = 0; i < this.bodies.length; i++) { this.bodies[i].syncPhysicsToScene(); } + + this._debugDraw(); } raycastClosest (worldRay: geometry.Ray, options: IRaycastOptions, result: PhysicsRayResult): boolean { @@ -203,6 +249,52 @@ export class CannonWorld implements IPhysicsWorld { this._world.removeConstraint(constraint.impl); } } + + get debugDrawFlags (): EPhysicsDrawFlags { + return this._debugDrawFlags; + } + + set debugDrawFlags (v: EPhysicsDrawFlags) { + this._debugDrawFlags = v; + } + + get debugDrawConstraintSize (): number { + return this._debugConstraintSize; + } + + set debugDrawConstraintSize (v) { + this._debugConstraintSize = v; + } + + 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; + } + + private _debugDraw (): void { + const debugRenderer = this._getDebugRenderer(); + if (!debugRenderer) return; + + this._debugLineCount = 0; + if (this._debugDrawFlags & EPhysicsDrawFlags.Aabb) { + for (let i = 0; i < this.bodies.length; i++) { + const body = this.bodies[i]; + for (let j = 0; j < body.wrappedShapes.length; j++) { + const shape = body.wrappedShapes[j]; + if (this._debugLineCount + 12 < this._MAX_DEBUG_LINE_COUNT) { + this._debugLineCount += 12; + shape.getAABB(aabbTemp); + debugRenderer.addBoundingBox(aabbTemp, this._aabbColor); + } + } + } + } + } } const from = new CANNON.Vec3(); diff --git a/cocos/physics/cocos/shapes/builtin-capsule-shape.ts b/cocos/physics/cocos/shapes/builtin-capsule-shape.ts index 32f9bc0f37e..650727a0071 100644 --- a/cocos/physics/cocos/shapes/builtin-capsule-shape.ts +++ b/cocos/physics/cocos/shapes/builtin-capsule-shape.ts @@ -94,7 +94,7 @@ export class BuiltinCapsuleShape extends BuiltinShape implements ICapsuleShape { } getAABB (v: geometry.AABB): void { - //capsule has not implement getBoundary + //capsule has not implemented getBoundary v.center.set(this.worldCapsule.center); v.halfExtents.set(0, 0, 0); temp0.set(this.worldCapsule.radius, this.worldCapsule.radius, this.worldCapsule.radius); From 78ab3fda71458996d3a74071d09171a6ecf66b36 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Fri, 8 Sep 2023 16:35:59 +0800 Subject: [PATCH 09/15] update engine-native-external --> v3.8.2-5 --- cocos/physics/framework/physics-enum.ts | 3 +++ native/external-config.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cocos/physics/framework/physics-enum.ts b/cocos/physics/framework/physics-enum.ts index 6d841f61005..cc8c44523e3 100644 --- a/cocos/physics/framework/physics-enum.ts +++ b/cocos/physics/framework/physics-enum.ts @@ -411,6 +411,7 @@ export enum EPhysicsDrawFlags { * 不绘制。 */ None = 0, + /** * @en * Draw wireframe @@ -418,6 +419,7 @@ export enum EPhysicsDrawFlags { * 绘制线框。 */ Wireframe = 0x0001, + /** * @en * Draw Constraint. @@ -425,6 +427,7 @@ export enum EPhysicsDrawFlags { * 绘制约束 */ Constraint = 0x0002, + /** * @en * Draw AABB. diff --git a/native/external-config.json b/native/external-config.json index 4a48991f692..b639506038a 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.2-2" + "checkout": "v3.8.2-5" } } \ No newline at end of file From b764ad3142bd747304352272e19c7fd7c9949f68 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Mon, 25 Sep 2023 11:40:59 +0800 Subject: [PATCH 10/15] tweak --- cocos/physics/bullet/bullet-world.ts | 8 ++++---- cocos/physics/cannon/cannon-world.ts | 4 ++-- cocos/physics/cocos/builtin-world.ts | 4 ++-- cocos/physics/framework/physics-enum.ts | 8 ++++---- cocos/physics/framework/physics-system.ts | 14 ++++++++++++++ cocos/physics/physx/physx-world.ts | 8 ++++---- native/cocos/physics/physx/PhysXWorld.cpp | 6 +++--- native/cocos/physics/physx/PhysXWorld.h | 2 +- native/cocos/physics/spec/IWorld.h | 8 ++++---- 9 files changed, 38 insertions(+), 24 deletions(-) diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index 7ba7ae2cf6f..9f0ad0660b8 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -122,7 +122,7 @@ export class BulletWorld implements IPhysicsWorld { private _debugLineCount = 0; private _MAX_DEBUG_LINE_COUNT = 16384; - private _debugDrawFlags = EPhysicsDrawFlags.None; + private _debugDrawFlags = EPhysicsDrawFlags.NONE; private _debugConstraintSize = 0.3; //B3_DEFAULT_DEBUGDRAW_SIZE private _needEmitEvents = false; @@ -857,16 +857,16 @@ export class BulletWorld implements IPhysicsWorld { private _setDebugDrawMode (): void { let btDrawMode = 0; - if (this._debugDrawFlags & EPhysicsDrawFlags.Wireframe) { + if (this._debugDrawFlags & EPhysicsDrawFlags.WIRE_FRAME) { btDrawMode |= EBulletDebugDrawModes.DBG_DrawWireframe; } - if (this._debugDrawFlags & EPhysicsDrawFlags.Constraint) { + if (this._debugDrawFlags & EPhysicsDrawFlags.CONSTRAINT) { btDrawMode |= EBulletDebugDrawModes.DBG_DrawConstraints; btDrawMode |= EBulletDebugDrawModes.DBG_DrawConstraintLimits; } - if (this._debugDrawFlags & EPhysicsDrawFlags.Aabb) { + if (this._debugDrawFlags & EPhysicsDrawFlags.AABB) { btDrawMode |= EBulletDebugDrawModes.DBG_DrawAabb; } diff --git a/cocos/physics/cannon/cannon-world.ts b/cocos/physics/cannon/cannon-world.ts index 59f8e58e8e3..325d9e2f75e 100644 --- a/cocos/physics/cannon/cannon-world.ts +++ b/cocos/physics/cannon/cannon-world.ts @@ -70,7 +70,7 @@ export class CannonWorld implements IPhysicsWorld { private _debugLineCount = 0; private _MAX_DEBUG_LINE_COUNT = 16384; - private _debugDrawFlags = EPhysicsDrawFlags.None; + private _debugDrawFlags = EPhysicsDrawFlags.NONE; private _debugConstraintSize = 0.3; private _aabbColor = new Color(0, 255, 255, 255); private _wireframeColor = new Color(255, 0, 255, 255); @@ -281,7 +281,7 @@ export class CannonWorld implements IPhysicsWorld { if (!debugRenderer) return; this._debugLineCount = 0; - if (this._debugDrawFlags & EPhysicsDrawFlags.Aabb) { + if (this._debugDrawFlags & EPhysicsDrawFlags.AABB) { for (let i = 0; i < this.bodies.length; i++) { const body = this.bodies[i]; for (let j = 0; j < body.wrappedShapes.length; j++) { diff --git a/cocos/physics/cocos/builtin-world.ts b/cocos/physics/cocos/builtin-world.ts index 1689ae80325..ca17e934851 100644 --- a/cocos/physics/cocos/builtin-world.ts +++ b/cocos/physics/cocos/builtin-world.ts @@ -141,7 +141,7 @@ export class BuiltInWorld implements IPhysicsWorld { private _debugLineCount = 0; private _MAX_DEBUG_LINE_COUNT = 16384; - private _debugDrawFlags = EPhysicsDrawFlags.None; + private _debugDrawFlags = EPhysicsDrawFlags.NONE; private _debugConstraintSize = 0.3; private _aabbColor = new Color(0, 255, 255, 255); private _wireframeColor = new Color(255, 0, 255, 255); @@ -350,7 +350,7 @@ export class BuiltInWorld implements IPhysicsWorld { if (!debugRenderer) return; this._debugLineCount = 0; - if (this._debugDrawFlags & EPhysicsDrawFlags.Aabb) { + if (this._debugDrawFlags & EPhysicsDrawFlags.AABB) { for (let i = 0; i < this.bodies.length; i++) { const body = this.bodies[i]; for (let j = 0; j < body.shapes.length; j++) { diff --git a/cocos/physics/framework/physics-enum.ts b/cocos/physics/framework/physics-enum.ts index cc8c44523e3..90766a75d69 100644 --- a/cocos/physics/framework/physics-enum.ts +++ b/cocos/physics/framework/physics-enum.ts @@ -410,7 +410,7 @@ export enum EPhysicsDrawFlags { * @zh * 不绘制。 */ - None = 0, + NONE = 0, /** * @en @@ -418,7 +418,7 @@ export enum EPhysicsDrawFlags { * @zh * 绘制线框。 */ - Wireframe = 0x0001, + WIRE_FRAME = 0x0001, /** * @en @@ -426,7 +426,7 @@ export enum EPhysicsDrawFlags { * @zh * 绘制约束 */ - Constraint = 0x0002, + CONSTRAINT = 0x0002, /** * @en @@ -434,6 +434,6 @@ export enum EPhysicsDrawFlags { * @zh * 绘制包围盒。 */ - Aabb = 0x0004, + AABB = 0x0004, } Enum(EPhysicsDrawFlags); diff --git a/cocos/physics/framework/physics-system.ts b/cocos/physics/framework/physics-system.ts index f25a00257cf..ec68a04ef09 100644 --- a/cocos/physics/framework/physics-system.ts +++ b/cocos/physics/framework/physics-system.ts @@ -462,6 +462,14 @@ export class PhysicsSystem extends System implements IWorldInitData { if (this.physicsWorld) this.physicsWorld.emitEvents(); } + /** + * @en + * Get or set debug draw flags. Default is EPhysicsDrawFlags.NONE. + * Refer to EPhysicsDrawFlags. + * @zh + * 获取或设置调试绘制标志。默认为 EPhysicsDrawFlags.NONE。 + * 参考 EPhysicsDrawFlags。 + */ get debugDrawFlags (): number { return this.physicsWorld.debugDrawFlags; } @@ -470,6 +478,12 @@ export class PhysicsSystem extends System implements IWorldInitData { this.physicsWorld.debugDrawFlags = v; } + /** + * @en + * Get or set constraint debug draw size. Default is 0.3. + * @zh + * 获取或设置约束的调试绘制尺寸。默认为 0.3。 + */ get debugDrawConstraintSize (): number { return this.physicsWorld.debugDrawConstraintSize; } diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index 350cb2a7fb5..6d1a9a63966 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -74,7 +74,7 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { private _debugLineCount = 0; private _MAX_DEBUG_LINE_COUNT = 16384; - private _debugDrawFlags = EPhysicsDrawFlags.None; + private _debugDrawFlags = EPhysicsDrawFlags.NONE; private _debugConstraintSize = 0.3; constructor () { @@ -163,18 +163,18 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { } private _setDebugDrawMode (): void { - if (this._debugDrawFlags & EPhysicsDrawFlags.Wireframe) { + if (this._debugDrawFlags & EPhysicsDrawFlags.WIRE_FRAME) { this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_SHAPES, 1); } else { this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_SHAPES, 0); } - const drawConstraint = Boolean(this._debugDrawFlags & EPhysicsDrawFlags.Constraint); + const drawConstraint = Boolean(this._debugDrawFlags & EPhysicsDrawFlags.CONSTRAINT); const internalConstraintSize = drawConstraint ? this._debugConstraintSize : 0; this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eJOINT_LOCAL_FRAMES, internalConstraintSize); this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eJOINT_LIMITS, internalConstraintSize); - if (this._debugDrawFlags & EPhysicsDrawFlags.Aabb) { + if (this._debugDrawFlags & EPhysicsDrawFlags.AABB) { this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_AABBS, 1); } else { this.scene.setVisualizationParameter(PX.PxVisualizationParameter.eCOLLISION_AABBS, 0); diff --git a/native/cocos/physics/physx/PhysXWorld.cpp b/native/cocos/physics/physx/PhysXWorld.cpp index 7fa9bf9f68e..bc19ec27eb2 100644 --- a/native/cocos/physics/physx/PhysXWorld.cpp +++ b/native/cocos/physics/physx/PhysXWorld.cpp @@ -187,18 +187,18 @@ void PhysXWorld::debugDraw () { } void PhysXWorld::setDebugDrawMode() { - if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::Wireframe)) { + if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::WIRE_FRAME)) { _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 1); } else { _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 0); } - bool drawConstraint = bool(uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::Constraint)); + bool drawConstraint = bool(uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::CONSTRAINT)); float internalConstraintSize = drawConstraint ? _debugConstraintSize : 0; _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eJOINT_LOCAL_FRAMES, internalConstraintSize); _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eJOINT_LIMITS, internalConstraintSize); - if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::Aabb)) { + if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::AABB)) { _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_AABBS, 1); } else { _mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_AABBS, 0); diff --git a/native/cocos/physics/physx/PhysXWorld.h b/native/cocos/physics/physx/PhysXWorld.h index d13304b0843..561fde2efaf 100644 --- a/native/cocos/physics/physx/PhysXWorld.h +++ b/native/cocos/physics/physx/PhysXWorld.h @@ -162,7 +162,7 @@ class PhysXWorld final : virtual public IPhysicsWorld { uint32_t _debugLineCount = 0; uint32_t _MAX_DEBUG_LINE_COUNT = 16384; - EPhysicsDrawFlags _debugDrawFlags = EPhysicsDrawFlags::None; + EPhysicsDrawFlags _debugDrawFlags = EPhysicsDrawFlags::NONE; float _debugConstraintSize = 0.3; }; diff --git a/native/cocos/physics/spec/IWorld.h b/native/cocos/physics/spec/IWorld.h index 30f2e2ff423..e0c9d8c09fb 100644 --- a/native/cocos/physics/spec/IWorld.h +++ b/native/cocos/physics/spec/IWorld.h @@ -40,10 +40,10 @@ enum class ETouchState : uint8_t { }; enum class EPhysicsDrawFlags : uint32_t { - None = 0, - Wireframe = 0x0001, - Constraint = 0x0002, - Aabb = 0x0004 + NONE = 0, + WIRE_FRAME = 0x0001, + CONSTRAINT = 0x0002, + AABB = 0x0004 }; struct TriggerEventPair { From 3aebeba4aab2c1e5f2c2e377f03b9eeb598f7877 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Mon, 25 Sep 2023 14:05:58 +0800 Subject: [PATCH 11/15] set engine-native-external --> v3.8.2-5, so that we can pass npm test --- native/external-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/external-config.json b/native/external-config.json index e1d7e3fb97e..b639506038a 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.2-7" + "checkout": "v3.8.2-5" } } \ No newline at end of file From 2fb79081024f8c8f614518e7a9c1411d10936894 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Mon, 25 Sep 2023 14:21:23 +0800 Subject: [PATCH 12/15] fix: bullet debug draw by default should draw nothing --- cocos/physics/bullet/bullet-world.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index 9f0ad0660b8..4db8edf017f 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -153,6 +153,7 @@ export class BulletWorld implements IPhysicsWorld { this._world = bt.ccDiscreteDynamicsWorld_new(this._dispatcher, this._broadphase, this._solver); bt.CollisionWorld_setDebugDrawer(this._world, this._debugDraw); + bt.DebugDraw_setDebugMode(this._debugDraw, EBulletDebugDrawModes.DBG_NoDebug); bt.DebugDraw_setAABBColor(this._debugDraw, 0, 1, 1); // set color for all shapes bt.DebugDraw_setActiveObjectColor(this._debugDraw, 1, 0, 1); From d36b3f82166006a8797f0ad06d75929353836ed8 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Mon, 25 Sep 2023 15:31:49 +0800 Subject: [PATCH 13/15] comment tweaks --- cocos/physics/framework/physics-system.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cocos/physics/framework/physics-system.ts b/cocos/physics/framework/physics-system.ts index ec68a04ef09..e83c672d0aa 100644 --- a/cocos/physics/framework/physics-system.ts +++ b/cocos/physics/framework/physics-system.ts @@ -466,9 +466,12 @@ export class PhysicsSystem extends System implements IWorldInitData { * @en * Get or set debug draw flags. Default is EPhysicsDrawFlags.NONE. * Refer to EPhysicsDrawFlags. + * Note: Since physics debug draw uses Geometry-Renderer to do drawing, + * make sure Geometry-Renderer is not cropped in Project Setting. * @zh * 获取或设置调试绘制标志。默认为 EPhysicsDrawFlags.NONE。 * 参考 EPhysicsDrawFlags。 + * 注意:因为物理调试绘制使用几何渲染器来绘制,请确保项目设置中几何渲染器没有被裁剪掉。 */ get debugDrawFlags (): number { return this.physicsWorld.debugDrawFlags; From d467c3402102defddc5b50e4f5268441666dc894 Mon Sep 17 00:00:00 2001 From: lealzhan Date: Mon, 25 Sep 2023 16:17:58 +0800 Subject: [PATCH 14/15] tweaek --- cocos/physics/cannon/cannon-world.ts | 5 +++-- cocos/physics/cocos/builtin-world.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cocos/physics/cannon/cannon-world.ts b/cocos/physics/cannon/cannon-world.ts index 325d9e2f75e..26c87052436 100644 --- a/cocos/physics/cannon/cannon-world.ts +++ b/cocos/physics/cannon/cannon-world.ts @@ -36,6 +36,7 @@ import { GeometryRenderer } from '../../rendering/geometry-renderer'; import { director } from '../../game'; const aabbTemp = new geometry.AABB(); +const AABB_LINE_COUNT = 12; export class CannonWorld implements IPhysicsWorld { get impl (): CANNON.World { @@ -286,8 +287,8 @@ export class CannonWorld implements IPhysicsWorld { const body = this.bodies[i]; for (let j = 0; j < body.wrappedShapes.length; j++) { const shape = body.wrappedShapes[j]; - if (this._debugLineCount + 12 < this._MAX_DEBUG_LINE_COUNT) { - this._debugLineCount += 12; + if (this._debugLineCount + AABB_LINE_COUNT < this._MAX_DEBUG_LINE_COUNT) { + this._debugLineCount += AABB_LINE_COUNT; shape.getAABB(aabbTemp); debugRenderer.addBoundingBox(aabbTemp, this._aabbColor); } diff --git a/cocos/physics/cocos/builtin-world.ts b/cocos/physics/cocos/builtin-world.ts index ca17e934851..6ef27c336fb 100644 --- a/cocos/physics/cocos/builtin-world.ts +++ b/cocos/physics/cocos/builtin-world.ts @@ -46,6 +46,7 @@ const TriggerEventObject = { }; const aabbTemp = new geometry.AABB(); +const AABB_LINE_COUNT = 12; /** * Built-in collision system, intended for use as a @@ -355,8 +356,8 @@ export class BuiltInWorld implements IPhysicsWorld { const body = this.bodies[i]; for (let j = 0; j < body.shapes.length; j++) { const shape = body.shapes[j]; - if (this._debugLineCount + 12 < this._MAX_DEBUG_LINE_COUNT) { - this._debugLineCount += 12; + if (this._debugLineCount + AABB_LINE_COUNT < this._MAX_DEBUG_LINE_COUNT) { + this._debugLineCount += AABB_LINE_COUNT; shape.getAABB(aabbTemp); debugRenderer.addBoundingBox(aabbTemp, this._aabbColor); } From eeaef5995792a4295ef998b8354b391a21eea71b Mon Sep 17 00:00:00 2001 From: lealzhan Date: Mon, 25 Sep 2023 17:26:47 +0800 Subject: [PATCH 15/15] update native/external-config.json --> 3.8.2-8 --- native/external-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/external-config.json b/native/external-config.json index b639506038a..a768805a4d8 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.2-5" + "checkout": "v3.8.2-8" } } \ No newline at end of file