diff --git a/packages/loader/src/gltf/GLTFUtils.ts b/packages/loader/src/gltf/GLTFUtils.ts index ad4e706a0..a87f85dc5 100644 --- a/packages/loader/src/gltf/GLTFUtils.ts +++ b/packages/loader/src/gltf/GLTFUtils.ts @@ -134,7 +134,8 @@ export class GLTFUtils { accessor: IAccessor ): Promise { const componentType = accessor.componentType; - const bufferView = bufferViews[accessor.bufferView]; + const bufferViewIndex = accessor.bufferView ?? 0; + const bufferView = bufferViews[bufferViewIndex]; return context.get(GLTFParserType.BufferView, accessor.bufferView).then((bufferViewData) => { const bufferIndex = bufferView.buffer; @@ -152,7 +153,7 @@ export class GLTFUtils { // According to the glTF official documentation only byteStride not undefined is allowed if (bufferStride !== undefined && bufferStride !== elementStride) { const bufferSlice = Math.floor(byteOffset / bufferStride); - const bufferCacheKey = accessor.bufferView + ":" + componentType + ":" + bufferSlice + ":" + accessorCount; + const bufferCacheKey = bufferViewIndex + ":" + componentType + ":" + bufferSlice + ":" + accessorCount; const accessorBufferCache = context.accessorBufferCache; bufferInfo = accessorBufferCache[bufferCacheKey]; if (!bufferInfo) { @@ -205,7 +206,7 @@ export class GLTFUtils { */ static getAccessorData(glTF: IGLTF, accessor: IAccessor, buffers: ArrayBuffer[]): TypedArray { const bufferViews = glTF.bufferViews; - const bufferView = bufferViews[accessor.bufferView]; + const bufferView = bufferViews[accessor.bufferView ?? 0]; const arrayBuffer = buffers[bufferView.buffer]; const accessorByteOffset = accessor.hasOwnProperty("byteOffset") ? accessor.byteOffset : 0; const bufferViewByteOffset = bufferView.hasOwnProperty("byteOffset") ? bufferView.byteOffset : 0; diff --git a/packages/physics-lite/src/LitePhysicsScene.ts b/packages/physics-lite/src/LitePhysicsScene.ts index d7b8290c9..f5806a1bc 100644 --- a/packages/physics-lite/src/LitePhysicsScene.ts +++ b/packages/physics-lite/src/LitePhysicsScene.ts @@ -1,5 +1,5 @@ -import { ICharacterController, IPhysicsScene } from "@galacean/engine-design"; import { BoundingBox, BoundingSphere, CollisionUtil, Ray, Vector3 } from "@galacean/engine"; +import { ICharacterController, IPhysicsScene } from "@galacean/engine-design"; import { DisorderedArray } from "./DisorderedArray"; import { LiteCollider } from "./LiteCollider"; import { LiteHitResult } from "./LiteHitResult"; @@ -65,16 +65,21 @@ export class LitePhysicsScene implements IPhysicsScene { * {@inheritDoc IPhysicsManager.removeColliderShape } */ removeColliderShape(colliderShape: LiteColliderShape): void { - const { _eventPool: eventPool, _currentEvents: currentEvents } = this; - const { _id: shapeID } = colliderShape; + const { _eventPool: eventPool, _currentEvents: currentEvents, _eventMap: eventMap } = this; + const { _id: id } = colliderShape; for (let i = currentEvents.length - 1; i >= 0; i--) { const event = currentEvents.get(i); - if (event.index1 == shapeID || event.index2 == shapeID) { + if (event.index1 == id) { currentEvents.deleteByIndex(i); eventPool.push(event); + } else if (event.index2 == id) { + currentEvents.deleteByIndex(i); + eventPool.push(event); + // If the shape is big index, should clear from the small index shape subMap + eventMap[event.index1][id] = undefined; } } - delete this._eventMap[shapeID]; + delete eventMap[id]; } /** diff --git a/packages/physics-physx/src/PhysXPhysicsScene.ts b/packages/physics-physx/src/PhysXPhysicsScene.ts index 58e6c26f9..c1432f754 100644 --- a/packages/physics-physx/src/PhysXPhysicsScene.ts +++ b/packages/physics-physx/src/PhysXPhysicsScene.ts @@ -116,15 +116,21 @@ export class PhysXPhysicsScene implements IPhysicsScene { */ removeColliderShape(colliderShape: PhysXColliderShape) { const { _eventPool: eventPool, _currentEvents: currentEvents } = this; - const { _id: shapeID } = colliderShape; + const { _id: id } = colliderShape; + const { _eventMap: eventMap } = this._physXManager; for (let i = currentEvents.length - 1; i >= 0; i--) { const event = currentEvents.get(i); - if (event.index1 == shapeID || event.index2 == shapeID) { + if (event.index1 == id) { currentEvents.deleteByIndex(i); eventPool.push(event); + } else if (event.index2 == id) { + currentEvents.deleteByIndex(i); + eventPool.push(event); + // If the shape is big index, should clear from the small index shape subMap + eventMap[event.index1][id] = undefined; } } - delete this._physXManager._eventMap[shapeID]; + delete eventMap[id]; } /** diff --git a/tests/src/core/physics/PhysicsManager.test.ts b/tests/src/core/physics/PhysicsManager.test.ts index 422767344..fe22fffaf 100644 --- a/tests/src/core/physics/PhysicsManager.test.ts +++ b/tests/src/core/physics/PhysicsManager.test.ts @@ -1,17 +1,16 @@ import { - Camera, BoxColliderShape, - Layer, - StaticCollider, - DynamicCollider, - HitResult, + Camera, CharacterController, - CapsuleColliderShape, - SphereColliderShape, - Script, + Collider, ColliderShape, + DynamicCollider, Entity, - Collider + HitResult, + Layer, + Script, + SphereColliderShape, + StaticCollider } from "@galacean/engine-core"; import { Ray, Vector3 } from "@galacean/engine-math"; import { LitePhysics } from "@galacean/engine-physics-lite"; @@ -136,6 +135,75 @@ describe("Physics Test", () => { engineLite.run(); }); + it("removeShape", () => { + const scene = engineLite.sceneManager.activeScene; + const root = scene.createRootEntity("root"); + const removeShapeRoot1 = root.createChild("root"); + removeShapeRoot1.transform.position = new Vector3(1000, 1000, 1000); + + const enterEvent = []; + const collider1 = removeShapeRoot1.addComponent(StaticCollider); + const box1 = new BoxColliderShape(); + enterEvent[box1.id] = []; + collider1.addShape(box1); + removeShapeRoot1.addComponent( + class extends Script { + onTriggerEnter(other: ColliderShape): void { + ++enterEvent[box1.id][other.id]; + } + } + ); + const removeShapeRoot2 = root.createChild("root"); + removeShapeRoot2.transform.position = new Vector3(1000, 1000, 1000); + const collider2 = removeShapeRoot2.addComponent(StaticCollider); + const box2 = new BoxColliderShape(); + enterEvent[box2.id] = []; + collider2.addShape(box2); + removeShapeRoot2.addComponent( + class extends Script { + onTriggerEnter(other: ColliderShape) { + ++enterEvent[box2.id][other.id]; + } + } + ); + // @ts-ignore + engineLite.physicsManager._update(8); + // Remove collider shape. + removeShapeRoot2.isActive = false; + const removeShapeRoot3 = root.createChild("root"); + removeShapeRoot3.transform.position = new Vector3(1000, 1000, 1000); + const collider3 = removeShapeRoot3.addComponent(StaticCollider); + const box3 = new BoxColliderShape(); + enterEvent[box3.id] = []; + collider3.addShape(box3); + removeShapeRoot3.addComponent( + class extends Script { + onTriggerEnter(other: ColliderShape) { + ++enterEvent[box3.id][other.id]; + } + } + ); + removeShapeRoot2.isActive = true; + enterEvent[box1.id][box2.id] = 0; + enterEvent[box1.id][box3.id] = 0; + enterEvent[box2.id][box1.id] = 0; + enterEvent[box2.id][box3.id] = 0; + enterEvent[box3.id][box1.id] = 0; + enterEvent[box3.id][box2.id] = 0; + // @ts-ignore + engineLite.physicsManager._update(8); + expect(enterEvent[box1.id][box2.id]).to.eq(1); + expect(enterEvent[box1.id][box3.id]).to.eq(1); + expect(enterEvent[box2.id][box1.id]).to.eq(1); + expect(enterEvent[box2.id][box3.id]).to.eq(1); + expect(enterEvent[box3.id][box1.id]).to.eq(1); + expect(enterEvent[box3.id][box2.id]).to.eq(1); + + removeShapeRoot1.destroy(); + removeShapeRoot2.destroy(); + removeShapeRoot3.destroy(); + }); + it("constructor", () => { expect(engineLite.physicsManager.gravity.y).to.eq(-9.81); expect(engineLite.physicsManager.fixedTimeStep).to.eq(1 / 60);