From 5189e31ec6e27bf866a0f04b87515d4f38ee2c4d Mon Sep 17 00:00:00 2001 From: LeXXik Date: Mon, 19 Aug 2024 18:00:01 +0300 Subject: [PATCH 1/4] wip --- package-lock.json | 18 +-- package.json | 2 +- .../back/operators/helpers/char-modifier.mjs | 80 ++++++++-- src/physics/jolt/back/operators/modifier.mjs | 10 ++ src/physics/jolt/back/operators/querier.mjs | 49 +++++- src/physics/jolt/constants.mjs | 2 + src/physics/jolt/debug.mjs | 4 + src/physics/jolt/front/char/component.mjs | 141 +++++++++++++++--- src/physics/jolt/front/char/system.mjs | 7 +- src/physics/jolt/front/response-handler.mjs | 12 +- src/physics/jolt/interfaces/query-results.mjs | 16 +- src/physics/jolt/interfaces/settings.mjs | 27 ++-- src/physics/jolt/manager.mjs | 11 +- 13 files changed, 300 insertions(+), 79 deletions(-) diff --git a/package-lock.json b/package-lock.json index 85284f2..becccb2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@rollup/plugin-terser": "^0.4.4", "chai": "^5.1.1", "eslint": "^8.57.0", + "jolt-physics": "^0.25.0", "mocha": "^10.4.0", "publint": "^0.2.7", "rimraf": "^5.0.5", @@ -25,7 +26,6 @@ "typescript": "^5.5.3" }, "peerDependencies": { - "jolt-physics": "^0.24.0", "playcanvas": "^1.71.3" } }, @@ -2831,10 +2831,10 @@ } }, "node_modules/jolt-physics": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/jolt-physics/-/jolt-physics-0.24.0.tgz", - "integrity": "sha512-wc1ACf+bSlNSsGWiXaUTwzGpLm45gBNu8DcYAGQiyIi2O2xOozz9qkB5J2sQeSh9JmW0Y8dzMaoTINdgMSOHZQ==", - "peer": true + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/jolt-physics/-/jolt-physics-0.25.0.tgz", + "integrity": "sha512-dSAdGhEbKO8QWA204vxryN5Ol5+wFJG0lr169kry7zeFp2Mqmly9KdgVtd5vTJao5bPFS7N1yBk8YjtUPcbcWg==", + "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", @@ -6712,10 +6712,10 @@ } }, "jolt-physics": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/jolt-physics/-/jolt-physics-0.24.0.tgz", - "integrity": "sha512-wc1ACf+bSlNSsGWiXaUTwzGpLm45gBNu8DcYAGQiyIi2O2xOozz9qkB5J2sQeSh9JmW0Y8dzMaoTINdgMSOHZQ==", - "peer": true + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/jolt-physics/-/jolt-physics-0.25.0.tgz", + "integrity": "sha512-dSAdGhEbKO8QWA204vxryN5Ol5+wFJG0lr169kry7zeFp2Mqmly9KdgVtd5vTJao5bPFS7N1yBk8YjtUPcbcWg==", + "dev": true }, "js-yaml": { "version": "4.1.0", diff --git a/package.json b/package.json index 4aaa870..7e44438 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "dist/*" ], "peerDependencies": { - "jolt-physics": "^0.24.0", + "jolt-physics": "^0.25.0", "playcanvas": "^1.71.3" }, "devDependencies": { diff --git a/src/physics/jolt/back/operators/helpers/char-modifier.mjs b/src/physics/jolt/back/operators/helpers/char-modifier.mjs index 3471422..fbee904 100644 --- a/src/physics/jolt/back/operators/helpers/char-modifier.mjs +++ b/src/physics/jolt/back/operators/helpers/char-modifier.mjs @@ -4,7 +4,11 @@ import { CMD_CHAR_SET_HIT_RED_ANGLE, CMD_CHAR_PAIR_BODY, CMD_CHAR_SET_LIN_VEL, CMD_CHAR_SET_MASS, CMD_CHAR_SET_MAX_STR, CMD_CHAR_SET_NUM_HITS, CMD_CHAR_SET_POS_ROT, CMD_CHAR_SET_REC_SPD, CMD_CHAR_SET_SHAPE, CMD_REPORT_SET_SHAPE, COMPONENT_SYSTEM_CHAR, CMD_CHAR_SET_SHAPE_OFFSET, - CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP + CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, + BUFFER_WRITE_BOOL, + BUFFER_READ_UINT16, + CMD_CHAR_WALK_STAIRS, + BUFFER_WRITE_UINT16 } from '../../../constants.mjs'; class CharModifier { @@ -54,6 +58,9 @@ class CharModifier { case CMD_CHAR_SET_UP: return this._setUp(cb); + + case CMD_CHAR_WALK_STAIRS: + return this._walkStairs(cb); } if ($_DEBUG) { @@ -157,7 +164,6 @@ class CharModifier { const backend = this._modifier.backend; const tracker = this._tracker; const pcid = cb.read(BUFFER_READ_UINT32); - const useCallback = cb.read(BUFFER_READ_BOOL); const shapeIndex = cb.flag ? cb.read(BUFFER_READ_UINT32) : null; const char = tracker.getBodyByPCID(pcid); @@ -181,10 +187,7 @@ class CharModifier { shape = char.originalShape; } - let cbIndex; - if (useCallback) { - cbIndex = cb.read(BUFFER_READ_UINT32); - } + const cbIndex = cb.read(BUFFER_READ_UINT16); try { const ok = char.SetShape(shape, @@ -195,13 +198,11 @@ class CharModifier { backend.shapeFilter, backend.joltInterface.GetTempAllocator()); - if (ok && useCallback) { - const cb = backend.outBuffer; - - cb.writeOperator(COMPONENT_SYSTEM_CHAR); - cb.writeCommand(CMD_REPORT_SET_SHAPE); - cb.write(cbIndex, BUFFER_WRITE_UINT32, false); - } + const outBuffer = backend.outBuffer; + outBuffer.writeOperator(COMPONENT_SYSTEM_CHAR); + outBuffer.writeCommand(CMD_REPORT_SET_SHAPE); + outBuffer.write(cbIndex, BUFFER_WRITE_UINT16, false); + outBuffer.write(ok, BUFFER_WRITE_BOOL, false); } catch (e) { if ($_DEBUG) { Debug.error(e); @@ -320,6 +321,59 @@ class CharModifier { return true; } + + _walkStairs(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + const modifier = this._modifier; + const backend = modifier.backend; + const Jolt = backend.Jolt; + const joltInterface = backend.joltInterface; + const jv1 = modifier.joltVec3_1; + const jv2 = modifier.joltVec3_2; + const jv3 = modifier.joltVec3_3; + const jv4 = modifier.joltVec3_4; + + const inDeltaTime = cb.read(BUFFER_READ_FLOAT32); + const inStepUp = jv1.FromBuffer(cb); + const inStepForward = jv2.FromBuffer(cb); + const inStepForwardTest = jv3.FromBuffer(cb); + const inStepDownExtra = jv4.FromBuffer(cb); + + const customBPFilter = cb.flag; + const bpFilter = customBPFilter ? new Jolt.DefaultBroadPhaseLayerFilter(joltInterface.GetObjectVsBroadPhaseLayerFilter(), cb.read(BUFFER_READ_UINT32)) : backend.bpFilter; + + const customObjFilter = cb.flag; + const objFilter = customObjFilter ? new Jolt.DefaultObjectLayerFilter(joltInterface.GetObjectLayerPairFilter(), cb.read(BUFFER_READ_UINT32)) : backend.objFilter; + + const cbIndex = cb.read(BUFFER_READ_UINT16); + const allocator = joltInterface.GetTempAllocator(); + + try { + const success = char.WalkStairs(inDeltaTime, + inStepUp, + inStepForward, + inStepForwardTest, + inStepDownExtra, + bpFilter, + objFilter, + backend.bodyFilter, + backend.shapeFilter, + allocator); + + const outBuffer = backend.outBuffer; + outBuffer.writeOperator(COMPONENT_SYSTEM_CHAR); + outBuffer.writeCommand(CMD_CHAR_WALK_STAIRS); + outBuffer.write(cbIndex, BUFFER_WRITE_UINT16, false); + outBuffer.write(success, BUFFER_WRITE_BOOL, false); + } catch (e) { + if ($_DEBUG) { + Debug.error(e); + } + return false; + } + + return true; + } } export { CharModifier }; diff --git a/src/physics/jolt/back/operators/modifier.mjs b/src/physics/jolt/back/operators/modifier.mjs index 33fe721..a3462f5 100644 --- a/src/physics/jolt/back/operators/modifier.mjs +++ b/src/physics/jolt/back/operators/modifier.mjs @@ -28,6 +28,7 @@ class Modifier { this._joltVec3_1 = new Jolt.Vec3(); this._joltVec3_2 = new Jolt.Vec3(); this._joltVec3_3 = new Jolt.Vec3(); + this._joltVec3_4 = new Jolt.Vec3(); this._joltQuat_1 = new Jolt.Quat(); this._constraintModifier = new ConstraintModifier(this); @@ -44,6 +45,14 @@ class Modifier { return this._joltVec3_2; } + get joltVec3_3() { + return this._joltVec3_3; + } + + get joltVec3_4() { + return this._joltVec3_4; + } + get joltQuat() { return this._joltQuat_1; } @@ -241,6 +250,7 @@ class Modifier { Jolt.destroy(this._joltVec3_1); Jolt.destroy(this._joltVec3_2); Jolt.destroy(this._joltVec3_3); + Jolt.destroy(this._joltVec3_4); Jolt.destroy(this._joltQuat_1); this._joltVec3_1 = null; diff --git a/src/physics/jolt/back/operators/querier.mjs b/src/physics/jolt/back/operators/querier.mjs index bca131e..559ddd4 100644 --- a/src/physics/jolt/back/operators/querier.mjs +++ b/src/physics/jolt/back/operators/querier.mjs @@ -1,9 +1,10 @@ import { Debug } from '../../debug.mjs'; import { BFM_IGNORE_BACK_FACES, - BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_UINT32, BUFFER_READ_UINT8, BUFFER_WRITE_BOOL, + BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_UINT16, BUFFER_READ_UINT32, BUFFER_READ_UINT8, BUFFER_WRITE_BOOL, BUFFER_WRITE_FLOAT32, BUFFER_WRITE_JOLTVEC32, BUFFER_WRITE_UINT16, BUFFER_WRITE_UINT32, CMD_CAST_RAY, - CMD_CAST_SHAPE, CMD_COLLIDE_POINT, CMD_COLLIDE_SHAPE_IDX, COMPONENT_SYSTEM_MANAGER + CMD_CAST_SHAPE, CMD_CHAR_CAN_WALK_STAIRS, CMD_COLLIDE_POINT, CMD_COLLIDE_SHAPE_IDX, COMPONENT_SYSTEM_CHAR, COMPONENT_SYSTEM_MANAGER, + FLOAT32_SIZE } from '../../constants.mjs'; function writeRayHit(cb, system, tracker, cast, calculateNormal, hit, Jolt) { @@ -111,6 +112,10 @@ class Querier { ok = this._collideShapeIdx(cb); break; + case CMD_CHAR_CAN_WALK_STAIRS: + ok = this._charCanWalkStairs(cb); + break; + default: if ($_DEBUG) { Debug.error(`Invalid querier command: ${command}`); @@ -169,6 +174,35 @@ class Querier { params = undefined; } + _charCanWalkStairs(cb) { + const backend = this._backend; + const buffer = backend.outBuffer; + const index = cb.read(BUFFER_READ_UINT32); + const char = backend.tracker.getBodyByPCID(index); + const jv = this._tempVectors[1]; + if (!char) { + cb.skip(FLOAT32_SIZE, 3); + return; + } + + buffer.writeOperator(COMPONENT_SYSTEM_CHAR); + buffer.writeCommand(CMD_CHAR_CAN_WALK_STAIRS); + + try { + jv.FromBuffer(cb); + const queryIndex = cb.read(BUFFER_READ_UINT16); + buffer.write(queryIndex, BUFFER_WRITE_UINT16, false); + buffer.write(char.CanWalkStairs(jv), BUFFER_WRITE_BOOL, false); + } catch (e) { + if ($_DEBUG) { + Debug.error(e); + } + return false; + } + + return true; + } + _castRay(cb) { const backend = this._backend; const castSettings = this._rayCastSettings; @@ -183,7 +217,7 @@ class Querier { buffer.writeOperator(COMPONENT_SYSTEM_MANAGER); buffer.writeCommand(CMD_CAST_RAY); - const queryIndex = cb.read(BUFFER_READ_UINT32); + const queryIndex = cb.read(BUFFER_READ_UINT16); buffer.write(queryIndex, BUFFER_WRITE_UINT16, false); try { @@ -272,10 +306,11 @@ class Querier { const Jolt = backend.Jolt; const joltInterface = backend.joltInterface; - const queryIndex = cb.read(BUFFER_READ_UINT32); - + buffer.writeOperator(COMPONENT_SYSTEM_MANAGER); buffer.writeCommand(CMD_CAST_SHAPE); + + const queryIndex = cb.read(BUFFER_READ_UINT16); buffer.write(queryIndex, BUFFER_WRITE_UINT16, false); try { @@ -389,7 +424,7 @@ class Querier { buffer.writeOperator(COMPONENT_SYSTEM_MANAGER); buffer.writeCommand(CMD_COLLIDE_POINT); - const queryIndex = cb.read(BUFFER_READ_UINT32); + const queryIndex = cb.read(BUFFER_READ_UINT16); buffer.write(queryIndex, BUFFER_WRITE_UINT16, false); if (!collidePointResult) { @@ -471,7 +506,7 @@ class Querier { buffer.writeOperator(COMPONENT_SYSTEM_MANAGER); buffer.writeCommand(CMD_COLLIDE_SHAPE_IDX); - const queryIndex = cb.read(BUFFER_READ_UINT32); + const queryIndex = cb.read(BUFFER_READ_UINT16); buffer.write(queryIndex, BUFFER_WRITE_UINT16, false); const firstOnly = cb.flag ? cb.read(BUFFER_READ_BOOL) : true; diff --git a/src/physics/jolt/constants.mjs b/src/physics/jolt/constants.mjs index ba63ae5..8a350f7 100644 --- a/src/physics/jolt/constants.mjs +++ b/src/physics/jolt/constants.mjs @@ -204,6 +204,8 @@ export const CMD_CHAR_SET_HIT_RED_ANGLE = 408; export const CMD_CHAR_SET_SHAPE_OFFSET = 409; export const CMD_CHAR_SET_USER_DATA = 410; export const CMD_CHAR_SET_UP = 411; +export const CMD_CHAR_CAN_WALK_STAIRS = 412; +export const CMD_CHAR_WALK_STAIRS = 413; // Constraints 500-599 diff --git a/src/physics/jolt/debug.mjs b/src/physics/jolt/debug.mjs index 323806f..89a3f49 100644 --- a/src/physics/jolt/debug.mjs +++ b/src/physics/jolt/debug.mjs @@ -78,6 +78,10 @@ class Debug { return ok; } + static checkFunc(func) { + return Debug.assert(typeof func === 'function', 'Invalid function.', func); + } + static checkBool(bool) { return Debug.assert((bool === true || bool === false), 'Invalid boolean.', bool); } diff --git a/src/physics/jolt/front/char/component.mjs b/src/physics/jolt/front/char/component.mjs index 10efaab..2843ff1 100644 --- a/src/physics/jolt/front/char/component.mjs +++ b/src/physics/jolt/front/char/component.mjs @@ -9,9 +9,18 @@ import { CMD_DESTROY_BODY, CMD_CHAR_PAIR_BODY, CMD_USE_MOTION_STATE, GROUND_STATE_NOT_SUPPORTED, OPERATOR_CLEANER, OPERATOR_MODIFIER, SHAPE_CAPSULE, CMD_CHAR_SET_REC_SPD, CMD_CHAR_SET_NUM_HITS, CMD_CHAR_SET_HIT_RED_ANGLE, CMD_CHAR_SET_SHAPE_OFFSET, - CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP + CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, + OPERATOR_QUERIER, + CMD_CHAR_CAN_WALK_STAIRS, + BUFFER_WRITE_UINT16, + CMD_CHAR_WALK_STAIRS } from '../../constants.mjs'; +/** + * @import {CanWalkStairsCallback, CharSetShapeCallback} from "../../interfaces/query-results.mjs" + * @import {FilterSettings} from "../../interfaces/settings.mjs" + */ + /** * Char Component. Describes the properties of a Jolt Virtual Character. * @@ -175,7 +184,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - const ok = Debug.checkFloat(angle, `Invalid angle scalar: ${angle}`); + const ok = Debug.checkFloat(angle); if (!ok) { return; } @@ -230,7 +239,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - Debug.checkVec(vel, `Invalid character linear velocity`, vel); + Debug.checkVec(vel); } // backend response will write to this._linearVelocity @@ -261,7 +270,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - const ok = Debug.checkFloat(mass, `Invalid mass: ${mass}`); + const ok = Debug.checkFloat(mass); if (!ok) { return; } @@ -316,7 +325,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - const ok = Debug.checkFloat(hits, `Invalid hits scalar: ${hits}`); + const ok = Debug.checkFloat(hits); if (!ok) { return; } @@ -358,7 +367,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - const ok = Debug.checkFloat(strength, `Invalid strength scalar: ${strength}`); + const ok = Debug.checkFloat(strength); if (!ok) { return; } @@ -398,7 +407,7 @@ class CharComponent extends ShapeComponent { */ set pairedEntity(entity) { if ($_DEBUG) { - const ok = Debug.assert(!!entity.body, `Invalid entity to pair. Needs to have a "body" component.`, entity); + const ok = Debug.assert(!!entity.body); if (!ok) return; } @@ -432,7 +441,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - const ok = Debug.checkFloat(factor, `Invalid speed factor: ${factor}`); + const ok = Debug.checkFloat(factor); if (!ok) { return; } @@ -488,7 +497,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - const ok = Debug.checkVec(offset, `Invalid offset vector: ${offset}`); + const ok = Debug.checkVec(offset); if (!ok) { return; } @@ -539,7 +548,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - const ok = Debug.checkVec(vec, `Invalid up vector`, vec); + const ok = Debug.checkVec(vec); if (!ok) { return; } @@ -578,7 +587,7 @@ class CharComponent extends ShapeComponent { */ set userData(num) { if ($_DEBUG) { - const ok = Debug.checkFloat(num, `Invalid user data value. Should be a number: ${num}`); + const ok = Debug.checkFloat(num); if (!ok) { return; } @@ -613,7 +622,7 @@ class CharComponent extends ShapeComponent { } if ($_DEBUG) { - const ok = Debug.checkBool(bool, `Invalid bool value for useMotionState property: ${bool}`); + const ok = Debug.checkBool(bool); if (!ok) return; } @@ -636,6 +645,32 @@ class CharComponent extends ShapeComponent { return this._useMotionState; } + /** + * This function will return true if the character has moved into a slope that is too steep + * (e.g. a vertical wall). You would call WalkStairs to attempt to step up stairs. + * + * @param {Vec3} linVel - The linear velocity that the player desired. This is used to + * determine if we're pushing into a step. + * @param {CanWalkStairsCallback} callback - A callback function that will return `true` or + * `false`, if a char can walk up the stairs. + */ + canWalkStairs(linVel, callback) { + if ($_DEBUG) { + let ok = Debug.checkVec(linVel); + ok = ok && Debug.checkFunc(callback); + if (!ok) { + return; + } + } + + this.system.addCommand( + OPERATOR_QUERIER, CMD_CHAR_CAN_WALK_STAIRS, this._index, + linVel, BUFFER_WRITE_VEC32, false + ); + + this._writeCallback(callback); + } + /** * Instant position and rotation change. * @@ -644,8 +679,8 @@ class CharComponent extends ShapeComponent { */ teleport(pos, rot = Quat.IDENTITY) { if ($_DEBUG) { - let ok = Debug.checkVec(pos, `Invalid position vector`, pos); - ok = ok && Debug.checkQuat(rot, `Invalid rotation quaternion`, rot); + let ok = Debug.checkVec(pos); + ok = ok && Debug.checkQuat(rot); if (!ok) { return; } @@ -665,18 +700,30 @@ class CharComponent extends ShapeComponent { } } - setShape(shapeIndex = null, callback = null) { - const system = this.system; + /** + * Allows to change the shape of the character collider. + * + * @param {number} shapeIndex - The shape index to switch to. It can be created by + * {@link JoltManager.createShape | createShape}. Use negative number to reset to original + * shape. + * @param {CharSetShapeCallback} callback - Callback function that will accept a boolean, + * telling if the shape change was successful. + */ + setShape(shapeIndex, callback) { + if ($_DEBUG) { + let ok = Debug.checkInt(shapeIndex); + ok = ok && Debug.checkFunc(callback); + if (!ok) { + return; + } + } - system.addCommand( + this.system.addCommand( OPERATOR_MODIFIER, CMD_CHAR_SET_SHAPE, this._index, - !!callback, BUFFER_WRITE_BOOL, false, - shapeIndex, BUFFER_WRITE_UINT32, true + shapeIndex < 0 ? null : shapeIndex, BUFFER_WRITE_UINT32 ); - if (callback) { - this._writeCallback(callback); - } + this._writeCallback(callback); } writeComponentData(cb) { @@ -790,11 +837,59 @@ class CharComponent extends ShapeComponent { system.addCommand(OPERATOR_CLEANER, CMD_DESTROY_BODY, componentIndex); } + /** + * When stair walking is needed, you can call the WalkStairs function to cast up, forward and + * down again to try to find a valid position. + * + * @param {number} dt - Time step to simulate. + * @param {Vec3} stepUp - The direction and distance to step up (this corresponds to the max + * step height). + * @param {Vec3} stepForward - The direction and distance to step forward after the step up. + * @param {Vec3} stepForwardTest - When running at a high frequency, inStepForward can be very + * small and it's likely that you hit the side of the stairs on the way down. This could + * produce a normal that violates the max slope angle. If this happens, we test again using + * this distance from the up position to see if we find a valid slope. + * @param {Vec3} stepDownExtra - An additional translation that is added when stepping down at + * the end. Allows you to step further down than up. Set to zero if you don't want this. Should + * be in the opposite direction of up. + * @param {CanWalkStairsCallback} callback - Callback function that accepts a boolean, telling + * if the walk was successful. + * @param {FilterSettings} opts - Filtering settings, affecting which bodies character can + * collide with. + */ + walkStairs(dt, stepUp, stepForward, stepForwardTest, stepDownExtra, callback, opts) { + if ($_DEBUG) { + let ok = Debug.checkFloat(dt); + ok = ok && Debug.checkVec(stepUp); + ok = ok && Debug.checkVec(stepForward); + ok = ok && Debug.checkVec(stepForwardTest); + ok = ok && Debug.checkVec(stepDownExtra); + if (ok && opts?.bpFilterLayer != null) { + ok = Debug.checkUint(opts.bpFilterLayer); + } + if (ok && opts?.objFilterLayer != null) { + ok = Debug.checkUint(opts.objFilterLayer); + } + } + + this.system.addCommand( + OPERATOR_MODIFIER, CMD_CHAR_WALK_STAIRS, this._index, + stepUp, BUFFER_WRITE_VEC32, false, + stepForward, BUFFER_WRITE_VEC32, false, + stepForwardTest, BUFFER_WRITE_VEC32, false, + stepDownExtra, BUFFER_WRITE_VEC32, false, + opts?.bpFilterLayer, BUFFER_WRITE_UINT32, + opts?.objFilterLayer, BUFFER_WRITE_UINT32 + ); + + this._writeCallback(callback); + } + _writeCallback(callback) { if (callback) { const system = this.system; const callbackIndex = system.getCallbackIndex(callback); - system.addCommandArgs(callbackIndex, BUFFER_WRITE_UINT32, false); + system.addCommandArgs(callbackIndex, BUFFER_WRITE_UINT16, false); } } } diff --git a/src/physics/jolt/front/char/system.mjs b/src/physics/jolt/front/char/system.mjs index ca8814c..c7d53e7 100644 --- a/src/physics/jolt/front/char/system.mjs +++ b/src/physics/jolt/front/char/system.mjs @@ -4,7 +4,7 @@ import { CharComponent } from './component.mjs'; import { ResponseHandler } from '../response-handler.mjs'; import { ShapeComponentSystem } from '../shape/system.mjs'; import { - BUFFER_READ_UINT32, CMD_CREATE_CHAR, CMD_REPORT_CONTACTS, CMD_REPORT_SET_SHAPE, + BUFFER_READ_UINT32, CMD_CHAR_CAN_WALK_STAIRS, CMD_CHAR_WALK_STAIRS, CMD_CREATE_CHAR, CMD_REPORT_CONTACTS, CMD_REPORT_SET_SHAPE, CMD_REPORT_TRANSFORMS, OPERATOR_CREATOR } from '../../constants.mjs'; @@ -46,7 +46,6 @@ class CharComponentSystem extends ShapeComponentSystem { super(app, manager); this._schema = [...this._schema, ...schema]; - this._queryMap = new IndexedCache(); this._exposeConstants(); } @@ -76,7 +75,9 @@ class CharComponentSystem extends ShapeComponentSystem { break; case CMD_REPORT_SET_SHAPE: - ResponseHandler.handleCharSetShape(cb, this._manager.queryMap); + case CMD_CHAR_CAN_WALK_STAIRS: + case CMD_CHAR_WALK_STAIRS: + ResponseHandler.handleCharCallback(cb, this._manager.queryMap); break; } } diff --git a/src/physics/jolt/front/response-handler.mjs b/src/physics/jolt/front/response-handler.mjs index 9cac534..e02cad0 100644 --- a/src/physics/jolt/front/response-handler.mjs +++ b/src/physics/jolt/front/response-handler.mjs @@ -328,17 +328,13 @@ class ResponseHandler { callback?.(result); } - static handleCharSetShape(cb, queryMap) { - const cbIndex = cb.read(BUFFER_READ_UINT32); + static handleCharCallback(cb, queryMap) { + const cbIndex = cb.read(BUFFER_READ_UINT16); const callback = queryMap.get(cbIndex); - - if ($_DEBUG && !callback) { - Debug.warn(`Unable to locate callback with index: ${cbIndex}`); - return; - } + const bool = cb.read(BUFFER_READ_BOOL); queryMap.free(cbIndex); - callback(); + callback?.(bool); } } diff --git a/src/physics/jolt/interfaces/query-results.mjs b/src/physics/jolt/interfaces/query-results.mjs index 4269c06..5a96df4 100644 --- a/src/physics/jolt/interfaces/query-results.mjs +++ b/src/physics/jolt/interfaces/query-results.mjs @@ -9,4 +9,18 @@ */ function CastShapeCallback(results) {} -export { CastShapeCallback }; +/** + * @interface + * @param {boolean} canWalk - Boolean, telling if a character can walk the stairs. + */ +function CanWalkStairsCallback(canWalk) {} + +/** + * @interface + * @param {boolean} wasSet - Boolean, whether the shape was successfully changed or not. If there + * is not enough physical space to create the shape, the shape change will fail and this will be + * `false`. + */ +function CharSetShapeCallback(wasSet) {} + +export { CastShapeCallback, CanWalkStairsCallback, CharSetShapeCallback }; diff --git a/src/physics/jolt/interfaces/settings.mjs b/src/physics/jolt/interfaces/settings.mjs index 5a4b1e4..2307244 100644 --- a/src/physics/jolt/interfaces/settings.mjs +++ b/src/physics/jolt/interfaces/settings.mjs @@ -3,15 +3,7 @@ * @group Managers * @category Utilities */ -class QuerySettings { - /** - * If `true`, the ray will ignore sensors. - * - * @type {boolean} - * @defaultValue false - */ - ignoreSensors; - +class FilterSettings { /** * Broadphase layer number for filtering. * @@ -29,6 +21,21 @@ class QuerySettings { objFilterLayer; } +/** + * @interface + * @group Managers + * @category Utilities + */ +class QuerySettings extends FilterSettings { + /** + * If `true`, the ray will ignore sensors. + * + * @type {boolean} + * @defaultValue false + */ + ignoreSensors; +} + /** * @interface * @group Managers @@ -257,5 +264,5 @@ class ShapeSettings { export { QuerySettings, CastSettings, CastRaySettings, CastShapeSettings, CollideShapeSettings, - ShapeSettings + ShapeSettings, FilterSettings }; diff --git a/src/physics/jolt/manager.mjs b/src/physics/jolt/manager.mjs index 3a4de6d..8396d6c 100644 --- a/src/physics/jolt/manager.mjs +++ b/src/physics/jolt/manager.mjs @@ -12,6 +12,7 @@ import { Quat, Vec3, Color, LAYERID_IMMEDIATE, KEY_Q, EVENT_KEYDOWN } from 'play import { BUFFER_WRITE_BOOL, BUFFER_WRITE_FLOAT32, BUFFER_WRITE_UINT16, BUFFER_WRITE_UINT32, BUFFER_WRITE_UINT8, BUFFER_WRITE_VEC32, CMD_CAST_RAY, CMD_CAST_SHAPE, CMD_CHANGE_GRAVITY, + CMD_CHAR_CAN_WALK_STAIRS, CMD_COLLIDE_POINT, CMD_COLLIDE_SHAPE_IDX, CMD_CREATE_GROUPS, CMD_CREATE_SHAPE, CMD_DESTROY_SHAPE, CMD_TOGGLE_GROUP_PAIR, COMPONENT_SYSTEM_BODY, COMPONENT_SYSTEM_CHAR, COMPONENT_SYSTEM_CONSTRAINT, COMPONENT_SYSTEM_MANAGER, COMPONENT_SYSTEM_SOFT_BODY, @@ -131,6 +132,8 @@ class JoltManager extends PhysicsManager { systems.set(COMPONENT_SYSTEM_CONSTRAINT, constraintCS); systems.set(COMPONENT_SYSTEM_MANAGER, this); + // TODO + // clear caches on destroy this._queryMap = new IndexedCache(); this._shapeMap = new IndexedCache(); this._gravity = new Vec3(0, -9.81, 0); @@ -429,7 +432,7 @@ class JoltManager extends PhysicsManager { cb.writeOperator(OPERATOR_QUERIER); cb.writeCommand(CMD_CAST_RAY); - cb.write(callbackIndex, BUFFER_WRITE_UINT32, false); + cb.write(callbackIndex, BUFFER_WRITE_UINT16, false); cb.write(origin, BUFFER_WRITE_VEC32, false); cb.write(dir, BUFFER_WRITE_VEC32, false); cb.write(opts?.firstOnly, BUFFER_WRITE_BOOL); @@ -490,7 +493,7 @@ class JoltManager extends PhysicsManager { cb.writeOperator(OPERATOR_QUERIER); cb.writeCommand(CMD_CAST_SHAPE); - cb.write(queryIndex, BUFFER_WRITE_UINT32, false); + cb.write(queryIndex, BUFFER_WRITE_UINT16, false); cb.write(pos, BUFFER_WRITE_VEC32, false); cb.write(rot, BUFFER_WRITE_VEC32, false); cb.write(dir, BUFFER_WRITE_VEC32, false); @@ -553,7 +556,7 @@ class JoltManager extends PhysicsManager { cb.writeOperator(OPERATOR_QUERIER); cb.writeCommand(CMD_COLLIDE_POINT); - cb.write(queryIndex, BUFFER_WRITE_UINT32, false); + cb.write(queryIndex, BUFFER_WRITE_UINT16, false); cb.write(opts?.ignoreSensors, BUFFER_WRITE_BOOL); cb.write(opts?.bpFilterLayer, BUFFER_WRITE_UINT32); cb.write(opts?.objFilterLayer, BUFFER_WRITE_UINT32); @@ -624,7 +627,7 @@ class JoltManager extends PhysicsManager { cb.writeOperator(OPERATOR_QUERIER); cb.writeCommand(CMD_COLLIDE_SHAPE_IDX); - cb.write(queryIndex, BUFFER_WRITE_UINT32, false); + cb.write(queryIndex, BUFFER_WRITE_UINT16, false); cb.write(opts?.firstOnly, BUFFER_WRITE_BOOL); cb.write(opts?.ignoreSensors, BUFFER_WRITE_BOOL); cb.write(shapeIndex, BUFFER_WRITE_UINT32, false); From 104cb34fda75476dbbb94d3a55284ebf37ef351b Mon Sep 17 00:00:00 2001 From: LeXXik Date: Tue, 20 Aug 2024 13:13:02 +0300 Subject: [PATCH 2/4] wip --- .../back/operators/helpers/char-modifier.mjs | 58 +----- src/physics/jolt/back/operators/querier.mjs | 33 --- src/physics/jolt/constants.mjs | 2 - src/physics/jolt/front/char/component.mjs | 194 ++++++------------ src/physics/jolt/interfaces/query-results.mjs | 8 +- src/physics/jolt/interfaces/settings.mjs | 27 +-- 6 files changed, 79 insertions(+), 243 deletions(-) diff --git a/src/physics/jolt/back/operators/helpers/char-modifier.mjs b/src/physics/jolt/back/operators/helpers/char-modifier.mjs index fbee904..406da19 100644 --- a/src/physics/jolt/back/operators/helpers/char-modifier.mjs +++ b/src/physics/jolt/back/operators/helpers/char-modifier.mjs @@ -57,10 +57,7 @@ class CharModifier { return this._setUserData(cb); case CMD_CHAR_SET_UP: - return this._setUp(cb); - - case CMD_CHAR_WALK_STAIRS: - return this._walkStairs(cb); + return this._setUp(cb); } if ($_DEBUG) { @@ -321,59 +318,6 @@ class CharModifier { return true; } - - _walkStairs(cb) { - const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); - const modifier = this._modifier; - const backend = modifier.backend; - const Jolt = backend.Jolt; - const joltInterface = backend.joltInterface; - const jv1 = modifier.joltVec3_1; - const jv2 = modifier.joltVec3_2; - const jv3 = modifier.joltVec3_3; - const jv4 = modifier.joltVec3_4; - - const inDeltaTime = cb.read(BUFFER_READ_FLOAT32); - const inStepUp = jv1.FromBuffer(cb); - const inStepForward = jv2.FromBuffer(cb); - const inStepForwardTest = jv3.FromBuffer(cb); - const inStepDownExtra = jv4.FromBuffer(cb); - - const customBPFilter = cb.flag; - const bpFilter = customBPFilter ? new Jolt.DefaultBroadPhaseLayerFilter(joltInterface.GetObjectVsBroadPhaseLayerFilter(), cb.read(BUFFER_READ_UINT32)) : backend.bpFilter; - - const customObjFilter = cb.flag; - const objFilter = customObjFilter ? new Jolt.DefaultObjectLayerFilter(joltInterface.GetObjectLayerPairFilter(), cb.read(BUFFER_READ_UINT32)) : backend.objFilter; - - const cbIndex = cb.read(BUFFER_READ_UINT16); - const allocator = joltInterface.GetTempAllocator(); - - try { - const success = char.WalkStairs(inDeltaTime, - inStepUp, - inStepForward, - inStepForwardTest, - inStepDownExtra, - bpFilter, - objFilter, - backend.bodyFilter, - backend.shapeFilter, - allocator); - - const outBuffer = backend.outBuffer; - outBuffer.writeOperator(COMPONENT_SYSTEM_CHAR); - outBuffer.writeCommand(CMD_CHAR_WALK_STAIRS); - outBuffer.write(cbIndex, BUFFER_WRITE_UINT16, false); - outBuffer.write(success, BUFFER_WRITE_BOOL, false); - } catch (e) { - if ($_DEBUG) { - Debug.error(e); - } - return false; - } - - return true; - } } export { CharModifier }; diff --git a/src/physics/jolt/back/operators/querier.mjs b/src/physics/jolt/back/operators/querier.mjs index 559ddd4..0225e2c 100644 --- a/src/physics/jolt/back/operators/querier.mjs +++ b/src/physics/jolt/back/operators/querier.mjs @@ -112,10 +112,6 @@ class Querier { ok = this._collideShapeIdx(cb); break; - case CMD_CHAR_CAN_WALK_STAIRS: - ok = this._charCanWalkStairs(cb); - break; - default: if ($_DEBUG) { Debug.error(`Invalid querier command: ${command}`); @@ -174,35 +170,6 @@ class Querier { params = undefined; } - _charCanWalkStairs(cb) { - const backend = this._backend; - const buffer = backend.outBuffer; - const index = cb.read(BUFFER_READ_UINT32); - const char = backend.tracker.getBodyByPCID(index); - const jv = this._tempVectors[1]; - if (!char) { - cb.skip(FLOAT32_SIZE, 3); - return; - } - - buffer.writeOperator(COMPONENT_SYSTEM_CHAR); - buffer.writeCommand(CMD_CHAR_CAN_WALK_STAIRS); - - try { - jv.FromBuffer(cb); - const queryIndex = cb.read(BUFFER_READ_UINT16); - buffer.write(queryIndex, BUFFER_WRITE_UINT16, false); - buffer.write(char.CanWalkStairs(jv), BUFFER_WRITE_BOOL, false); - } catch (e) { - if ($_DEBUG) { - Debug.error(e); - } - return false; - } - - return true; - } - _castRay(cb) { const backend = this._backend; const castSettings = this._rayCastSettings; diff --git a/src/physics/jolt/constants.mjs b/src/physics/jolt/constants.mjs index 8a350f7..ba63ae5 100644 --- a/src/physics/jolt/constants.mjs +++ b/src/physics/jolt/constants.mjs @@ -204,8 +204,6 @@ export const CMD_CHAR_SET_HIT_RED_ANGLE = 408; export const CMD_CHAR_SET_SHAPE_OFFSET = 409; export const CMD_CHAR_SET_USER_DATA = 410; export const CMD_CHAR_SET_UP = 411; -export const CMD_CHAR_CAN_WALK_STAIRS = 412; -export const CMD_CHAR_WALK_STAIRS = 413; // Constraints 500-599 diff --git a/src/physics/jolt/front/char/component.mjs b/src/physics/jolt/front/char/component.mjs index 2843ff1..f072896 100644 --- a/src/physics/jolt/front/char/component.mjs +++ b/src/physics/jolt/front/char/component.mjs @@ -9,79 +9,93 @@ import { CMD_DESTROY_BODY, CMD_CHAR_PAIR_BODY, CMD_USE_MOTION_STATE, GROUND_STATE_NOT_SUPPORTED, OPERATOR_CLEANER, OPERATOR_MODIFIER, SHAPE_CAPSULE, CMD_CHAR_SET_REC_SPD, CMD_CHAR_SET_NUM_HITS, CMD_CHAR_SET_HIT_RED_ANGLE, CMD_CHAR_SET_SHAPE_OFFSET, - CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, - OPERATOR_QUERIER, - CMD_CHAR_CAN_WALK_STAIRS, - BUFFER_WRITE_UINT16, - CMD_CHAR_WALK_STAIRS + CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, BUFFER_WRITE_UINT16 } from '../../constants.mjs'; /** - * @import {CanWalkStairsCallback, CharSetShapeCallback} from "../../interfaces/query-results.mjs" - * @import {FilterSettings} from "../../interfaces/settings.mjs" + * @import {CharSetShapeCallback} from "../../interfaces/query-results.mjs" */ +// [Value] attribute Vec3 mStickToFloorStepDown; +// [Value] attribute Vec3 mWalkStairsStepUp; +// attribute float mWalkStairsMinStepForward; +// attribute float mWalkStairsStepForwardTest; +// attribute float mWalkStairsCosAngleForwardContact; +// [Value] attribute Vec3 mWalkStairsStepDownExtra; + /** * Char Component. Describes the properties of a Jolt Virtual Character. * * @group Components * @category Char Component */ -class CharComponent extends ShapeComponent { - _shape = SHAPE_CAPSULE; +class CharComponent extends ShapeComponent { + _backFaceMode = BFM_COLLIDE_BACK_FACES; - _up = Vec3.UP; + _characterPadding = 0.02; - _useMotionState = true; + _collisionTolerance = 1.0e-3; - _linearVelocity = new Vec3(); + _hitReductionCosMaxAngle = 0.999; - _supportingVolume = new Plane(Vec3.UP, -1); + _groundEntity = null; - _maxSlopeAngle = 45 * math.DEG_TO_RAD; + _groundNormal = new Vec3(); - _mass = 70; + _groundVelocity = new Vec3(); - _maxStrength = 100; + _isSlopeTooSteep = false; - _shapeOffset = Vec3.ZERO; + _isSupported = false; - _backFaceMode = BFM_COLLIDE_BACK_FACES; + _linearVelocity = new Vec3(); - _predictiveContactDistance = 0.1; + _mass = 70; _maxCollisionIterations = 5; _maxConstraintIterations = 15; - _minTimeRemaining = 1.0e-4; + _maxNumHits = 256; - _collisionTolerance = 1.0e-3; + _maxSlopeAngle = 45 * math.DEG_TO_RAD; - _characterPadding = 0.02; + _maxStrength = 100; - _maxNumHits = 256; + _minTimeRemaining = 1.0e-4; - _hitReductionCosMaxAngle = 0.999; + _pairedEntity = null; _penetrationRecoverySpeed = 1; - _isSupported = false; + _predictiveContactDistance = 0.1; - _isSlopeTooSteep = false; + _shape = SHAPE_CAPSULE; - _groundEntity = null; + _shapeOffset = Vec3.ZERO; - _groundNormal = new Vec3(); + _state = GROUND_STATE_NOT_SUPPORTED; - _groundVelocity = new Vec3(); + _stickToFloorStepDown = new Vec3(0, -0.5, 0); - _state = GROUND_STATE_NOT_SUPPORTED; + _supportingVolume = new Plane(Vec3.UP, -1); + + _up = Vec3.UP; + + _useMotionState = true; _userData = null; - _pairedEntity = null; + _walkStairsCosAngleForwardContact = 0.25881904510252074; + + _walkStairsMinStepForward = 0.02; + + _walkStairsStepForwardTest = 0.15; + + _walkStairsStepDownExtra = Vec3.ZERO; + _walkStairsStepUp = new Vec3(0, 0.4, 0); + /** * When colliding with back faces, the character will not be able to move through back facing * triangles. Use this if you have triangles that need to collide on both sides. Following @@ -153,28 +167,6 @@ class CharComponent extends ShapeComponent { return this._groundVelocity; } - /** - * Ground state. Following constants available: - * ``` - * GROUND_STATE_ON_GROUND - * ``` - * ``` - * GROUND_STATE_ON_STEEP_GROUND - * ``` - * ``` - * GROUND_STATE_NOT_SUPPORTED - * ``` - * ``` - * GROUND_STATE_IN_AIR - * ``` - * - * @returns {number} Number, representing the ground state. - * @defaultValue GROUND_STATE_NOT_SUPPORTED - */ - get state() { - return this._state; - } - /** * @param {number} angle - Max angle. */ @@ -526,6 +518,28 @@ class CharComponent extends ShapeComponent { return this._shapeOffset; } + /** + * Ground state. Following constants available: + * ``` + * GROUND_STATE_ON_GROUND + * ``` + * ``` + * GROUND_STATE_ON_STEEP_GROUND + * ``` + * ``` + * GROUND_STATE_NOT_SUPPORTED + * ``` + * ``` + * GROUND_STATE_IN_AIR + * ``` + * + * @returns {number} Number, representing the ground state. + * @defaultValue GROUND_STATE_NOT_SUPPORTED + */ + get state() { + return this._state; + } + /** * A plane, defined in local space relative to the character. Every contact behind this plane * can support the character, every contact in front of this plane is treated as only colliding @@ -645,32 +659,6 @@ class CharComponent extends ShapeComponent { return this._useMotionState; } - /** - * This function will return true if the character has moved into a slope that is too steep - * (e.g. a vertical wall). You would call WalkStairs to attempt to step up stairs. - * - * @param {Vec3} linVel - The linear velocity that the player desired. This is used to - * determine if we're pushing into a step. - * @param {CanWalkStairsCallback} callback - A callback function that will return `true` or - * `false`, if a char can walk up the stairs. - */ - canWalkStairs(linVel, callback) { - if ($_DEBUG) { - let ok = Debug.checkVec(linVel); - ok = ok && Debug.checkFunc(callback); - if (!ok) { - return; - } - } - - this.system.addCommand( - OPERATOR_QUERIER, CMD_CHAR_CAN_WALK_STAIRS, this._index, - linVel, BUFFER_WRITE_VEC32, false - ); - - this._writeCallback(callback); - } - /** * Instant position and rotation change. * @@ -837,54 +825,6 @@ class CharComponent extends ShapeComponent { system.addCommand(OPERATOR_CLEANER, CMD_DESTROY_BODY, componentIndex); } - /** - * When stair walking is needed, you can call the WalkStairs function to cast up, forward and - * down again to try to find a valid position. - * - * @param {number} dt - Time step to simulate. - * @param {Vec3} stepUp - The direction and distance to step up (this corresponds to the max - * step height). - * @param {Vec3} stepForward - The direction and distance to step forward after the step up. - * @param {Vec3} stepForwardTest - When running at a high frequency, inStepForward can be very - * small and it's likely that you hit the side of the stairs on the way down. This could - * produce a normal that violates the max slope angle. If this happens, we test again using - * this distance from the up position to see if we find a valid slope. - * @param {Vec3} stepDownExtra - An additional translation that is added when stepping down at - * the end. Allows you to step further down than up. Set to zero if you don't want this. Should - * be in the opposite direction of up. - * @param {CanWalkStairsCallback} callback - Callback function that accepts a boolean, telling - * if the walk was successful. - * @param {FilterSettings} opts - Filtering settings, affecting which bodies character can - * collide with. - */ - walkStairs(dt, stepUp, stepForward, stepForwardTest, stepDownExtra, callback, opts) { - if ($_DEBUG) { - let ok = Debug.checkFloat(dt); - ok = ok && Debug.checkVec(stepUp); - ok = ok && Debug.checkVec(stepForward); - ok = ok && Debug.checkVec(stepForwardTest); - ok = ok && Debug.checkVec(stepDownExtra); - if (ok && opts?.bpFilterLayer != null) { - ok = Debug.checkUint(opts.bpFilterLayer); - } - if (ok && opts?.objFilterLayer != null) { - ok = Debug.checkUint(opts.objFilterLayer); - } - } - - this.system.addCommand( - OPERATOR_MODIFIER, CMD_CHAR_WALK_STAIRS, this._index, - stepUp, BUFFER_WRITE_VEC32, false, - stepForward, BUFFER_WRITE_VEC32, false, - stepForwardTest, BUFFER_WRITE_VEC32, false, - stepDownExtra, BUFFER_WRITE_VEC32, false, - opts?.bpFilterLayer, BUFFER_WRITE_UINT32, - opts?.objFilterLayer, BUFFER_WRITE_UINT32 - ); - - this._writeCallback(callback); - } - _writeCallback(callback) { if (callback) { const system = this.system; diff --git a/src/physics/jolt/interfaces/query-results.mjs b/src/physics/jolt/interfaces/query-results.mjs index 5a96df4..c902dc6 100644 --- a/src/physics/jolt/interfaces/query-results.mjs +++ b/src/physics/jolt/interfaces/query-results.mjs @@ -9,12 +9,6 @@ */ function CastShapeCallback(results) {} -/** - * @interface - * @param {boolean} canWalk - Boolean, telling if a character can walk the stairs. - */ -function CanWalkStairsCallback(canWalk) {} - /** * @interface * @param {boolean} wasSet - Boolean, whether the shape was successfully changed or not. If there @@ -23,4 +17,4 @@ function CanWalkStairsCallback(canWalk) {} */ function CharSetShapeCallback(wasSet) {} -export { CastShapeCallback, CanWalkStairsCallback, CharSetShapeCallback }; +export { CastShapeCallback, CharSetShapeCallback }; diff --git a/src/physics/jolt/interfaces/settings.mjs b/src/physics/jolt/interfaces/settings.mjs index 2307244..67184b5 100644 --- a/src/physics/jolt/interfaces/settings.mjs +++ b/src/physics/jolt/interfaces/settings.mjs @@ -3,7 +3,15 @@ * @group Managers * @category Utilities */ -class FilterSettings { +class QuerySettings extends FilterSettings { + /** + * If `true`, the ray will ignore sensors. + * + * @type {boolean} + * @defaultValue false + */ + ignoreSensors; + /** * Broadphase layer number for filtering. * @@ -21,21 +29,6 @@ class FilterSettings { objFilterLayer; } -/** - * @interface - * @group Managers - * @category Utilities - */ -class QuerySettings extends FilterSettings { - /** - * If `true`, the ray will ignore sensors. - * - * @type {boolean} - * @defaultValue false - */ - ignoreSensors; -} - /** * @interface * @group Managers @@ -264,5 +257,5 @@ class ShapeSettings { export { QuerySettings, CastSettings, CastRaySettings, CastShapeSettings, CollideShapeSettings, - ShapeSettings, FilterSettings + ShapeSettings }; From 93fce614d57e4fe8557a8c36777335bb8775e3e0 Mon Sep 17 00:00:00 2001 From: LeXXik Date: Tue, 20 Aug 2024 17:01:37 +0300 Subject: [PATCH 3/4] stairs feature --- package.json | 2 +- src/physics/jolt/back/backend.mjs | 32 +- src/physics/jolt/back/operators/cleaner.mjs | 10 + src/physics/jolt/back/operators/creator.mjs | 26 +- .../back/operators/helpers/char-modifier.mjs | 144 +++++++- src/physics/jolt/back/operators/querier.mjs | 11 +- src/physics/jolt/constants.mjs | 8 + src/physics/jolt/front/char/component.mjs | 329 ++++++++++++++++-- src/physics/jolt/front/char/system.mjs | 12 +- src/physics/jolt/interfaces/settings.mjs | 2 +- src/physics/jolt/manager.mjs | 1 - 11 files changed, 508 insertions(+), 69 deletions(-) diff --git a/package.json b/package.json index 7e44438..aad1d93 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@gamebop/physics", "description": "Physics components for PlayCanvas engine", - "version": "0.2.1", + "version": "0.3.0", "main": "dist/physics.min.mjs", "author": "Gamebop", "license": "MIT", diff --git a/src/physics/jolt/back/backend.mjs b/src/physics/jolt/back/backend.mjs index 4c46755..d734df9 100644 --- a/src/physics/jolt/back/backend.mjs +++ b/src/physics/jolt/back/backend.mjs @@ -361,11 +361,6 @@ class JoltBackend { this._dispatcher = null; - if (this._charUpdateSettings) { - Jolt.destroy(this._charUpdateSettings); - this._charUpdateSettings = null; - } - if (this._joltInterface) { Jolt.destroy(this._joltInterface); this._joltInterface = null; @@ -497,34 +492,26 @@ class JoltBackend { const characters = this._tracker.character; if (characters.size === 0) return true; - const movingBPFilter = this._bpFilter; - const movingLayerFilter = this._objFilter; + const defaultMovingBPLayerFilter = this._bpFilter; + const defaultMovingObjLayerFilter = this._objFilter; const bodyFilter = this._bodyFilter; const shapeFilter = this._shapeFilter; - let updateSettings = this._charUpdateSettings; try { - if (!updateSettings) { - updateSettings = this._charUpdateSettings = new Jolt.ExtendedUpdateSettings(); - } const allocator = joltInterface.GetTempAllocator(); - // TODO - // make it customizable, like the raycast - // const objectVsBroadPhaseLayerFilter = joltInterface.GetObjectVsBroadPhaseLayerFilter(); - // const objectLayerPairFilter = joltInterface.GetObjectLayerPairFilter(); - // const movingBPFilter = new Jolt.DefaultBroadPhaseLayerFilter(objectVsBroadPhaseLayerFilter, BP_LAYER_MOVING); - // const movingLayerFilter = new Jolt.DefaultObjectLayerFilter(objectLayerPairFilter, 2); - characters.forEach((char) => { + // body filter for paired body + // TODO + // switch to new Jolt's inner body, instead of paired body const bFilter = char.bodyFilter || bodyFilter; char.ExtendedUpdate( fixedStep, char.GetUp(), - updateSettings, - movingBPFilter, - movingLayerFilter, + char.updateSettings, + char.bpFilter ? char.bpFilter : defaultMovingBPLayerFilter, + char.objFilter ? char.objFilter : defaultMovingObjLayerFilter, bFilter, shapeFilter, allocator @@ -540,9 +527,6 @@ class JoltBackend { bodyInterface.MoveKinematic(pairedBody.GetID(), pos, Jolt.Quat.prototype.sIdentity(), fixedStep); } }); - - // Jolt.destroy(movingBPFilter); - // Jolt.destroy(movingLayerFilter); } catch (e) { if ($_DEBUG) { Debug.error(e); diff --git a/src/physics/jolt/back/operators/cleaner.mjs b/src/physics/jolt/back/operators/cleaner.mjs index aa6585c..156b6af 100644 --- a/src/physics/jolt/back/operators/cleaner.mjs +++ b/src/physics/jolt/back/operators/cleaner.mjs @@ -105,9 +105,19 @@ class Cleaner { if (body.isCharacter) { if (body.bodyFilter) { + // body filter for paired body Jolt.destroy(body.bodyFilter); } + if (body.bpFilter) { + Jolt.destroy(body.bpFilter); + } + + if (body.objFilter) { + Jolt.destroy(body.objFilter); + } + + Jolt.destroy(body.updateSettings); Jolt.destroy(body); } else { const id = body.GetID(); diff --git a/src/physics/jolt/back/operators/creator.mjs b/src/physics/jolt/back/operators/creator.mjs index 9f6503e..9827009 100644 --- a/src/physics/jolt/back/operators/creator.mjs +++ b/src/physics/jolt/back/operators/creator.mjs @@ -1,11 +1,11 @@ import { Debug } from '../../debug.mjs'; import { MotionState } from '../motion-state.mjs'; import { - BFM_IGNORE_BACK_FACES, BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, + BFM_IGNORE_BACK_FACES, BP_LAYER_MOVING, BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_UINT16, BUFFER_READ_UINT32, BUFFER_READ_UINT8, CMD_CREATE_BODY, CMD_CREATE_CHAR, CMD_CREATE_CONSTRAINT, CMD_CREATE_GROUPS, CMD_CREATE_SHAPE, CMD_CREATE_SOFT_BODY, CMD_CREATE_VEHICLE, MOTION_QUALITY_DISCRETE, MOTION_TYPE_DYNAMIC, - MOTION_TYPE_KINEMATIC, OMP_CALCULATE_MASS_AND_INERTIA, OMP_MASS_AND_INERTIA_PROVIDED, + MOTION_TYPE_KINEMATIC, OBJ_LAYER_MOVING, OMP_CALCULATE_MASS_AND_INERTIA, OMP_MASS_AND_INERTIA_PROVIDED, SHAPE_BOX, SHAPE_CAPSULE, SHAPE_CONVEX_HULL, SHAPE_CYLINDER, SHAPE_HEIGHTFIELD, SHAPE_MESH, SHAPE_SPHERE, SHAPE_STATIC_COMPOUND } from '../../constants.mjs'; @@ -630,6 +630,7 @@ class Creator { const Jolt = backend.Jolt; const listener = backend.listener; const config = backend.config; + const joltInterface = backend.joltInterface; const charEvents = config.charContactEventsEnabled; const jv = this._joltVec3; const jq = this._joltQuat; @@ -691,6 +692,27 @@ class Creator { } const character = new Jolt.CharacterVirtual(settings, jv, jq, backend.physicsSystem); + const updateSettings = new Jolt.ExtendedUpdateSettings(); + + updateSettings.mStickToFloorStepDown.FromBuffer(cb); + updateSettings.mWalkStairsStepUp.FromBuffer(cb); + updateSettings.mWalkStairsMinStepForward = cb.read(BUFFER_READ_FLOAT32); + updateSettings.mWalkStairsStepForwardTest = cb.read(BUFFER_READ_FLOAT32); + updateSettings.mWalkStairsCosAngleForwardContact = cb.read(BUFFER_READ_FLOAT32); + updateSettings.mWalkStairsStepDownExtra.FromBuffer(cb); + + const bpLayer = cb.read(BUFFER_READ_UINT16); + const objLayer = cb.read(BUFFER_READ_UINT16); + + character.bpFilter = bpLayer !== BP_LAYER_MOVING ? + new Jolt.DefaultBroadPhaseLayerFilter(joltInterface.GetObjectVsBroadPhaseLayerFilter(), + bpLayer) : null; + + character.objFilter = objLayer !== OBJ_LAYER_MOVING ? + new Jolt.DefaultObjectLayerFilter(joltInterface.GetObjectLayerPairFilter(), objLayer) : + null; + + character.updateSettings = updateSettings; if ($_DEBUG) { character.debugDrawDepth = cb.read(BUFFER_READ_BOOL); diff --git a/src/physics/jolt/back/operators/helpers/char-modifier.mjs b/src/physics/jolt/back/operators/helpers/char-modifier.mjs index 406da19..73d5092 100644 --- a/src/physics/jolt/back/operators/helpers/char-modifier.mjs +++ b/src/physics/jolt/back/operators/helpers/char-modifier.mjs @@ -4,11 +4,10 @@ import { CMD_CHAR_SET_HIT_RED_ANGLE, CMD_CHAR_PAIR_BODY, CMD_CHAR_SET_LIN_VEL, CMD_CHAR_SET_MASS, CMD_CHAR_SET_MAX_STR, CMD_CHAR_SET_NUM_HITS, CMD_CHAR_SET_POS_ROT, CMD_CHAR_SET_REC_SPD, CMD_CHAR_SET_SHAPE, CMD_REPORT_SET_SHAPE, COMPONENT_SYSTEM_CHAR, CMD_CHAR_SET_SHAPE_OFFSET, - CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, - BUFFER_WRITE_BOOL, - BUFFER_READ_UINT16, - CMD_CHAR_WALK_STAIRS, - BUFFER_WRITE_UINT16 + CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, BUFFER_WRITE_BOOL, BUFFER_READ_UINT16, + BUFFER_WRITE_UINT16, CMD_CHAR_SET_BP_FILTER_LAYER, BP_LAYER_MOVING, OBJ_LAYER_MOVING, + CMD_CHAR_SET_OBJ_FILTER_LAYER, CMD_CHAR_SET_COS_ANGLE, CMD_CHAR_SET_MIN_DIST, + CMD_CHAR_SET_TEST_DIST, CMD_CHAR_SET_EXTRA_DOWN, CMD_CHAR_SET_STEP_UP, CMD_CHAR_SET_STICK_DOWN } from '../../../constants.mjs'; class CharModifier { @@ -57,7 +56,31 @@ class CharModifier { return this._setUserData(cb); case CMD_CHAR_SET_UP: - return this._setUp(cb); + return this._setUp(cb); + + case CMD_CHAR_SET_BP_FILTER_LAYER: + return this._setBPFilterLayer(cb); + + case CMD_CHAR_SET_OBJ_FILTER_LAYER: + return this._setObjFilterLayer(cb); + + case CMD_CHAR_SET_COS_ANGLE: + return this._setCosAngle(cb); + + case CMD_CHAR_SET_MIN_DIST: + return this._setMinDist(cb); + + case CMD_CHAR_SET_TEST_DIST: + return this._setTestDist(cb); + + case CMD_CHAR_SET_EXTRA_DOWN: + return this._setExtraDown(cb); + + case CMD_CHAR_SET_STEP_UP: + return this._setStepUp(cb); + + case CMD_CHAR_SET_STICK_DOWN: + return this._setStickDown(cb); } if ($_DEBUG) { @@ -318,6 +341,115 @@ class CharModifier { return true; } + + _setBPFilterLayer(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + const backend = this._modifier.backend; + + try { + if (char.bpFilter) { + Jolt.destroy(char.bpFilter); + } + + const layer = cb.read(BUFFER_READ_UINT16); + char.bpFilter = layer !== BP_LAYER_MOVING ? + new backend.Jolt.DefaultBroadPhaseLayerFilter( + backend.joltInterface.GetObjectVsBroadPhaseLayerFilter(), layer) : null; + } catch (e) { + if ($_DEBUG) { + Debug.error(e); + } + return false; + } + + return true; + } + + _setObjFilterLayer(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + const backend = this._modifier.backend; + + try { + if (char.objFilter) { + Jolt.destroy(char.objFilter); + } + + const layer = cb.read(BUFFER_READ_UINT16); + char.objFilter = layer !== OBJ_LAYER_MOVING ? + new backend.Jolt.DefaultObjectLayerFilter( + backend.joltInterface.GetObjectLayerPairFilter(), layer) : null; + } catch (e) { + if ($_DEBUG) { + Debug.error(e); + } + return false; + } + + return true; + } + + _setCosAngle(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + char.updateSettings.mWalkStairsCosAngleForwardContact = cb.read(BUFFER_READ_FLOAT32); + return true; + } + + _setMinDist(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + char.updateSettings.mWalkStairsMinStepForward = cb.read(BUFFER_READ_FLOAT32); + return true; + } + + _setTestDist(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + char.updateSettings.mWalkStairsStepForwardTest = cb.read(BUFFER_READ_FLOAT32); + return true; + } + + _setExtraDown(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + + try { + char.updateSettings.mWalkStairsStepDownExtra.FromBuffer(cb); + } catch (e) { + if ($_DEBUG) { + Debug.error(e); + } + return false; + } + + return true; + } + + _setStepUp(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + + try { + char.updateSettings.mWalkStairsStepUp.FromBuffer(cb); + } catch (e) { + if ($_DEBUG) { + Debug.error(e); + } + return false; + } + + return true; + } + + _setStickDown(cb) { + const char = this._tracker.getBodyByPCID(cb.read(BUFFER_READ_UINT32)); + + try { + char.updateSettings.mStickToFloorStepDown.FromBuffer(cb); + } catch (e) { + if ($_DEBUG) { + Debug.error(e); + } + return false; + } + + return true; + } } export { CharModifier }; diff --git a/src/physics/jolt/back/operators/querier.mjs b/src/physics/jolt/back/operators/querier.mjs index 0225e2c..4e4a7b0 100644 --- a/src/physics/jolt/back/operators/querier.mjs +++ b/src/physics/jolt/back/operators/querier.mjs @@ -1,11 +1,10 @@ -import { Debug } from '../../debug.mjs'; import { - BFM_IGNORE_BACK_FACES, - BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_UINT16, BUFFER_READ_UINT32, BUFFER_READ_UINT8, BUFFER_WRITE_BOOL, - BUFFER_WRITE_FLOAT32, BUFFER_WRITE_JOLTVEC32, BUFFER_WRITE_UINT16, BUFFER_WRITE_UINT32, CMD_CAST_RAY, - CMD_CAST_SHAPE, CMD_CHAR_CAN_WALK_STAIRS, CMD_COLLIDE_POINT, CMD_COLLIDE_SHAPE_IDX, COMPONENT_SYSTEM_CHAR, COMPONENT_SYSTEM_MANAGER, - FLOAT32_SIZE + BFM_IGNORE_BACK_FACES, BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_UINT16, BUFFER_READ_UINT32, + BUFFER_READ_UINT8, BUFFER_WRITE_BOOL, BUFFER_WRITE_FLOAT32, BUFFER_WRITE_JOLTVEC32, + BUFFER_WRITE_UINT16, BUFFER_WRITE_UINT32, CMD_CAST_RAY, CMD_CAST_SHAPE, CMD_COLLIDE_POINT, + CMD_COLLIDE_SHAPE_IDX, COMPONENT_SYSTEM_MANAGER } from '../../constants.mjs'; +import { Debug } from '../../debug.mjs'; function writeRayHit(cb, system, tracker, cast, calculateNormal, hit, Jolt) { const body = system.GetBodyLockInterfaceNoLock().TryGetBody(hit.mBodyID); diff --git a/src/physics/jolt/constants.mjs b/src/physics/jolt/constants.mjs index ba63ae5..90cd0a8 100644 --- a/src/physics/jolt/constants.mjs +++ b/src/physics/jolt/constants.mjs @@ -204,6 +204,14 @@ export const CMD_CHAR_SET_HIT_RED_ANGLE = 408; export const CMD_CHAR_SET_SHAPE_OFFSET = 409; export const CMD_CHAR_SET_USER_DATA = 410; export const CMD_CHAR_SET_UP = 411; +export const CMD_CHAR_SET_BP_FILTER_LAYER = 422; +export const CMD_CHAR_SET_OBJ_FILTER_LAYER = 423; +export const CMD_CHAR_SET_COS_ANGLE = 424; +export const CMD_CHAR_SET_MIN_DIST = 425; +export const CMD_CHAR_SET_TEST_DIST = 426; +export const CMD_CHAR_SET_EXTRA_DOWN = 427; +export const CMD_CHAR_SET_STEP_UP = 428; +export const CMD_CHAR_SET_STICK_DOWN = 429; // Constraints 500-599 diff --git a/src/physics/jolt/front/char/component.mjs b/src/physics/jolt/front/char/component.mjs index f072896..3024c11 100644 --- a/src/physics/jolt/front/char/component.mjs +++ b/src/physics/jolt/front/char/component.mjs @@ -9,20 +9,16 @@ import { CMD_DESTROY_BODY, CMD_CHAR_PAIR_BODY, CMD_USE_MOTION_STATE, GROUND_STATE_NOT_SUPPORTED, OPERATOR_CLEANER, OPERATOR_MODIFIER, SHAPE_CAPSULE, CMD_CHAR_SET_REC_SPD, CMD_CHAR_SET_NUM_HITS, CMD_CHAR_SET_HIT_RED_ANGLE, CMD_CHAR_SET_SHAPE_OFFSET, - CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, BUFFER_WRITE_UINT16 + CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, BUFFER_WRITE_UINT16, BP_LAYER_MOVING, + OBJ_LAYER_MOVING, CMD_CHAR_SET_BP_FILTER_LAYER, CMD_CHAR_SET_OBJ_FILTER_LAYER, + CMD_CHAR_SET_COS_ANGLE, CMD_CHAR_SET_MIN_DIST, CMD_CHAR_SET_TEST_DIST, + CMD_CHAR_SET_EXTRA_DOWN, CMD_CHAR_SET_STEP_UP, CMD_CHAR_SET_STICK_DOWN } from '../../constants.mjs'; /** * @import {CharSetShapeCallback} from "../../interfaces/query-results.mjs" */ -// [Value] attribute Vec3 mStickToFloorStepDown; -// [Value] attribute Vec3 mWalkStairsStepUp; -// attribute float mWalkStairsMinStepForward; -// attribute float mWalkStairsStepForwardTest; -// attribute float mWalkStairsCosAngleForwardContact; -// [Value] attribute Vec3 mWalkStairsStepDownExtra; - /** * Char Component. Describes the properties of a Jolt Virtual Character. * @@ -32,6 +28,8 @@ import { class CharComponent extends ShapeComponent { _backFaceMode = BFM_COLLIDE_BACK_FACES; + _bpFilterLayer = BP_LAYER_MOVING; + _characterPadding = 0.02; _collisionTolerance = 1.0e-3; @@ -64,6 +62,8 @@ class CharComponent extends ShapeComponent { _minTimeRemaining = 1.0e-4; + _objFilterLayer = OBJ_LAYER_MOVING; + _pairedEntity = null; _penetrationRecoverySpeed = 1; @@ -90,10 +90,10 @@ class CharComponent extends ShapeComponent { _walkStairsMinStepForward = 0.02; - _walkStairsStepForwardTest = 0.15; - _walkStairsStepDownExtra = Vec3.ZERO; + _walkStairsStepForwardTest = 0.15; + _walkStairsStepUp = new Vec3(0, 0.4, 0); /** @@ -114,6 +114,38 @@ class CharComponent extends ShapeComponent { return this._backFaceMode; } + /** + * @param {number} - Broadphase Filter Layer number. + */ + set bpFilterLayer(layerNum) { + if (this._bpFilterLayer === layerNum) { + return; + } + + if ($_DEBUG) { + const ok = Debug.checkUint(layerNum); + if (!ok) { + return; + } + } + + this._bpFilterLayer = layerNum; + this.system.addCommand( + OPERATOR_MODIFIER, CMD_CHAR_SET_BP_FILTER_LAYER, this._index, + layerNum, BUFFER_WRITE_UINT16, false + ); + } + + /** + * Broadphase Filter Layer. Specifies what objects character can collide with. + * + * @type {number} + * @defaultValue BP_LAYER_MOVING (1) + */ + get bpFilterLayer() { + return this._bpFilterLayer; + } + /** * How far we try to stay away from the geometry. This ensures that the sweep will hit as * little as possible lowering the collision cost and reducing the risk of getting stuck. @@ -392,6 +424,38 @@ class CharComponent extends ShapeComponent { return this._minTimeRemaining; } + /** + * @param {number} - Object Filter Layer number. + */ + set objFilterLayer(layerNum) { + if (this._objFilterLayer === layerNum) { + return; + } + + if ($_DEBUG) { + const ok = Debug.checkUint(layerNum); + if (!ok) { + return; + } + } + + this._objFilterLayer = layerNum; + this.system.addCommand( + OPERATOR_MODIFIER, CMD_CHAR_SET_OBJ_FILTER_LAYER, this._index, + layerNum, BUFFER_WRITE_UINT16, false + ); + } + + /** + * Object Filter Layer. Defines which objects character can collide with. + * + * @type {number} + * @defaultValue OBJ_LAYER_MOVING (1) + */ + get objFilterLayer() { + return this._objFilterLayer; + } + /** * Pairs an Entity with a body component to a character. * @@ -540,6 +604,38 @@ class CharComponent extends ShapeComponent { return this._state; } + /** + * @param {Vec3} - Direction and distance for stepping down. + */ + set stickToFloorStepDown(vec) { + if (this._stickToFloorStepDown.equals(vec)) { + return; + } + + if ($_DEBUG) { + const ok = Debug.checkVec(vec); + if (!ok) { + return; + } + } + + this._stickToFloorStepDown.copy(vec); + this.system.addCommand( + OPERATOR_MODIFIER, CMD_CHAR_SET_STICK_DOWN, this._index, + vec, BUFFER_WRITE_VEC32, false + ); + } + + /** + * Max amount to project the character downwards. + * + * @type {Vec3} + * @defaultValue Vec3(0, -0.5, 0) (m) + */ + get stickToFloorStepDown() { + return this._stickToFloorStepDown; + } + /** * A plane, defined in local space relative to the character. Every contact behind this plane * can support the character, every contact in front of this plane is treated as only colliding @@ -590,6 +686,40 @@ class CharComponent extends ShapeComponent { return this._up; } + /** + * Enables/Disables a motion state for this character. + * + * @param {boolean} bool - Boolean to enable/disable the motion state. + */ + set useMotionState(bool) { + if (this._useMotionState === bool) { + return; + } + + if ($_DEBUG) { + const ok = Debug.checkBool(bool); + if (!ok) + return; + } + + this._useMotionState = bool; + this.system.addCommand( + OPERATOR_MODIFIER, CMD_USE_MOTION_STATE, this._index, + bool, BUFFER_WRITE_BOOL, false + ); + } + + /** + * Enables/disables the use of motion state for the character. Refer to + * {@link BodyComponent.useMotionState} for details. + * + * @returns {boolean} Boolean, telling whether character controller will use a motion state. + * @defaultValue true + */ + get useMotionState() { + return this._useMotionState; + } + /** * Sets a number on the character shape. * @@ -626,37 +756,175 @@ class CharComponent extends ShapeComponent { } /** - * Enables/Disables a motion state for this character. + * @param {number} - Radians. + */ + set walkStairsCosAngleForwardContact(angle) { + if (this._walkStairsCosAngleForwardContact === angle) { + return; + } + + if ($_DEBUG) { + const ok = Debug.checkFloat(angle); + if (!ok) { + return; + } + } + + this._walkStairsCosAngleForwardContact = angle; + this.system.addCommand( + OPERATOR_MODIFIER, CMD_CHAR_SET_COS_ANGLE, this._index, + angle, BUFFER_WRITE_FLOAT32, false + ); + } + + /** + * Maximum angle in radians between the ground normal in the horizontal plane and the character + * forward vector where we're willing to adjust the step forward test towards the contact + * normal. * - * @param {boolean} bool - Boolean to enable/disable the motion state. + * @type {number} + * @defaultValue cos(75) */ - set useMotionState(bool) { - if (this._useMotionState === bool) { + get walkStairsCosAngleForwardContact() { + return this._walkStairsCosAngleForwardContact; + } + + /** + * @param {number} - Minimum distance. + */ + set walkStairsMinStepForward(dist) { + if (this._walkStairsMinStepForward === dist) { return; } if ($_DEBUG) { - const ok = Debug.checkBool(bool); - if (!ok) + const ok = Debug.checkFloat(dist); + if (!ok) { return; + } } - this._useMotionState = bool; + this._walkStairsMinStepForward = dist; this.system.addCommand( - OPERATOR_MODIFIER, CMD_USE_MOTION_STATE, this._index, - bool, BUFFER_WRITE_BOOL, false + OPERATOR_MODIFIER, CMD_CHAR_SET_MIN_DIST, this._index, + dist, BUFFER_WRITE_FLOAT32, false ); } /** - * Enables/disables the use of motion state for the character. Refer to - * {@link BodyComponent.useMotionState} for details. + * The distance to step forward after the step up. * - * @returns {boolean} Boolean, telling whether character controller will use a motion state. - * @defaultValue true + * @type {number} + * @defaultValue 0.02 (m) */ - get useMotionState() { - return this._useMotionState; + get walkStairsMinStepForward() { + return this._walkStairsMinStepForward; + } + + /** + * @param {Vec3} - Extra translation. + */ + set walkStairsStepDownExtra(vec) { + if (this._walkStairsStepDownExtra.equals(vec)) { + return; + } + + if ($_DEBUG) { + const ok = Debug.checkVec(vec); + if (!ok) { + return; + } + } + + if (this._walkStairsStepDownExtra === Vec3.ZERO) { + this._walkStairsStepDownExtra = vec.clone(); + } else { + this._walkStairsStepDownExtra.copy(vec); + } + + this.system.addCommand( + OPERATOR_MODIFIER, CMD_CHAR_SET_EXTRA_DOWN, this._index, + vec, BUFFER_WRITE_VEC32, false + ); + } + + /** + * An additional translation that is added when stepping down at the end. Allows you to step + * further down than up. Set to zero vector if you don't want this. Should be in the opposite + * direction of up. + * + * @type {Vec3} + * @defaultValue Vec3(0, 0, 0) + */ + get walkStairsStepDownExtra() { + return this._walkStairsStepDownExtra; + } + + /** + * @param {number} - Test distance. + */ + set walkStairsStepForwardTest(dist) { + if (this._walkStairsStepForwardTest === dist) { + return; + } + + if ($_DEBUG) { + const ok = Debug.checkFloat(dist); + if (!ok) { + return; + } + } + + this._walkStairsStepForwardTest = dist; + this.system.addCommand( + OPERATOR_MODIFIER, CMD_CHAR_SET_TEST_DIST, this._index, + dist, BUFFER_WRITE_FLOAT32, false + ); + } + + /** + * When running at a high frequency, stepForward can be very small and it's likely that you hit + * the side of the stairs on the way down. This could produce a normal that violates the max + * slope angle. If this happens, we test again using this distance from the up position to see + * if we find a valid slope. + * + * @type {number} + * @defaultValue 0.15 (m) + */ + get walkStairsStepForwardTest() { + return this._walkStairsStepForwardTest; + } + + /** + * @param {Vec3} - Direction and distance of the step. + */ + set walkStairsStepUp(vec) { + if (this._walkStairsStepUp.equals(vec)) { + return; + } + + if ($_DEBUG) { + const ok = Debug.checkVec(vec); + if (!ok) { + return; + } + } + + this._walkStairsStepUp.copy(vec); + this.system.addCommand( + OPERATOR_MODIFIER, CMD_CHAR_SET_STEP_UP, this._index, + vec, BUFFER_WRITE_VEC32, false + ); + } + + /** + * The direction and distance to step up (this corresponds to the max step height). + * + * @param {Vec3} + * @defaultValue Vec3(0, 0.4, 0) (m) + */ + get walkStairsStepUp() { + return this._walkStairsStepUp; } /** @@ -743,11 +1011,20 @@ class CharComponent extends ShapeComponent { const entity = this.entity; const pos = entity.getPosition(); const rot = entity.getRotation(); - + // Loss of precision for pos/rot (64 -> 32) cb.write(pos, BUFFER_WRITE_VEC32, false); cb.write(rot, BUFFER_WRITE_VEC32, false); + cb.write(this._stickToFloorStepDown, BUFFER_WRITE_VEC32, false); + cb.write(this._walkStairsStepUp, BUFFER_WRITE_VEC32, false); + cb.write(this._walkStairsMinStepForward, BUFFER_WRITE_FLOAT32, false); + cb.write(this._walkStairsStepForwardTest, BUFFER_WRITE_FLOAT32, false); + cb.write(this._walkStairsCosAngleForwardContact, BUFFER_WRITE_FLOAT32, false); + cb.write(this._walkStairsStepDownExtra, BUFFER_WRITE_VEC32, false); + cb.write(this._bpFilterLayer, BUFFER_WRITE_UINT16, false); + cb.write(this._objFilterLayer, BUFFER_WRITE_UINT16, false); + if ($_DEBUG) { cb.write(this._debugDrawDepth, BUFFER_WRITE_BOOL, false); cb.write(this._debugDraw, BUFFER_WRITE_BOOL, false); diff --git a/src/physics/jolt/front/char/system.mjs b/src/physics/jolt/front/char/system.mjs index c7d53e7..48b4d5e 100644 --- a/src/physics/jolt/front/char/system.mjs +++ b/src/physics/jolt/front/char/system.mjs @@ -4,7 +4,7 @@ import { CharComponent } from './component.mjs'; import { ResponseHandler } from '../response-handler.mjs'; import { ShapeComponentSystem } from '../shape/system.mjs'; import { - BUFFER_READ_UINT32, CMD_CHAR_CAN_WALK_STAIRS, CMD_CHAR_WALK_STAIRS, CMD_CREATE_CHAR, CMD_REPORT_CONTACTS, CMD_REPORT_SET_SHAPE, + BUFFER_READ_UINT32, CMD_CREATE_CHAR, CMD_REPORT_CONTACTS, CMD_REPORT_SET_SHAPE, CMD_REPORT_TRANSFORMS, OPERATOR_CREATOR } from '../../constants.mjs'; @@ -32,7 +32,15 @@ const schema = [ 'groundNormal', 'groundVelocity', 'state', - 'pairedEntity' + 'pairedEntity', + 'bpFilterLayer', + 'objFilterLayer', + 'stickToFloorStepDown', + 'walkStairsCosAngleForwardContact', + 'walkStairsMinStepForward', + 'walkStairsStepForwardTest', + 'walkStairsStepDownExtra', + 'walkStairsStepUp' ]; /** diff --git a/src/physics/jolt/interfaces/settings.mjs b/src/physics/jolt/interfaces/settings.mjs index 67184b5..5a4b1e4 100644 --- a/src/physics/jolt/interfaces/settings.mjs +++ b/src/physics/jolt/interfaces/settings.mjs @@ -3,7 +3,7 @@ * @group Managers * @category Utilities */ -class QuerySettings extends FilterSettings { +class QuerySettings { /** * If `true`, the ray will ignore sensors. * diff --git a/src/physics/jolt/manager.mjs b/src/physics/jolt/manager.mjs index 8396d6c..1bff69d 100644 --- a/src/physics/jolt/manager.mjs +++ b/src/physics/jolt/manager.mjs @@ -12,7 +12,6 @@ import { Quat, Vec3, Color, LAYERID_IMMEDIATE, KEY_Q, EVENT_KEYDOWN } from 'play import { BUFFER_WRITE_BOOL, BUFFER_WRITE_FLOAT32, BUFFER_WRITE_UINT16, BUFFER_WRITE_UINT32, BUFFER_WRITE_UINT8, BUFFER_WRITE_VEC32, CMD_CAST_RAY, CMD_CAST_SHAPE, CMD_CHANGE_GRAVITY, - CMD_CHAR_CAN_WALK_STAIRS, CMD_COLLIDE_POINT, CMD_COLLIDE_SHAPE_IDX, CMD_CREATE_GROUPS, CMD_CREATE_SHAPE, CMD_DESTROY_SHAPE, CMD_TOGGLE_GROUP_PAIR, COMPONENT_SYSTEM_BODY, COMPONENT_SYSTEM_CHAR, COMPONENT_SYSTEM_CONSTRAINT, COMPONENT_SYSTEM_MANAGER, COMPONENT_SYSTEM_SOFT_BODY, From 03b794daef152f99b8fb7ae26c3410bbc6c8b512 Mon Sep 17 00:00:00 2001 From: LeXXik Date: Tue, 20 Aug 2024 17:17:50 +0300 Subject: [PATCH 4/4] lint --- src/physics/jolt/back/operators/creator.mjs | 10 +++---- .../back/operators/helpers/char-modifier.mjs | 18 ++++++------ src/physics/jolt/back/operators/querier.mjs | 1 - src/physics/jolt/front/char/component.mjs | 28 +++++++++---------- src/physics/jolt/front/char/system.mjs | 3 -- src/physics/jolt/front/response-handler.mjs | 1 - 6 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/physics/jolt/back/operators/creator.mjs b/src/physics/jolt/back/operators/creator.mjs index 9827009..a01a579 100644 --- a/src/physics/jolt/back/operators/creator.mjs +++ b/src/physics/jolt/back/operators/creator.mjs @@ -704,13 +704,11 @@ class Creator { const bpLayer = cb.read(BUFFER_READ_UINT16); const objLayer = cb.read(BUFFER_READ_UINT16); - character.bpFilter = bpLayer !== BP_LAYER_MOVING ? - new Jolt.DefaultBroadPhaseLayerFilter(joltInterface.GetObjectVsBroadPhaseLayerFilter(), - bpLayer) : null; + character.bpFilter = bpLayer !== BP_LAYER_MOVING ? new Jolt.DefaultBroadPhaseLayerFilter( + joltInterface.GetObjectVsBroadPhaseLayerFilter(), bpLayer) : null; - character.objFilter = objLayer !== OBJ_LAYER_MOVING ? - new Jolt.DefaultObjectLayerFilter(joltInterface.GetObjectLayerPairFilter(), objLayer) : - null; + character.objFilter = objLayer !== OBJ_LAYER_MOVING ? new Jolt.DefaultObjectLayerFilter( + joltInterface.GetObjectLayerPairFilter(), objLayer) : null; character.updateSettings = updateSettings; diff --git a/src/physics/jolt/back/operators/helpers/char-modifier.mjs b/src/physics/jolt/back/operators/helpers/char-modifier.mjs index 73d5092..97596ea 100644 --- a/src/physics/jolt/back/operators/helpers/char-modifier.mjs +++ b/src/physics/jolt/back/operators/helpers/char-modifier.mjs @@ -1,13 +1,13 @@ import { Debug } from '../../../debug.mjs'; import { - BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_UINT32, BUFFER_WRITE_UINT32, - CMD_CHAR_SET_HIT_RED_ANGLE, CMD_CHAR_PAIR_BODY, CMD_CHAR_SET_LIN_VEL, CMD_CHAR_SET_MASS, - CMD_CHAR_SET_MAX_STR, CMD_CHAR_SET_NUM_HITS, CMD_CHAR_SET_POS_ROT, CMD_CHAR_SET_REC_SPD, - CMD_CHAR_SET_SHAPE, CMD_REPORT_SET_SHAPE, COMPONENT_SYSTEM_CHAR, CMD_CHAR_SET_SHAPE_OFFSET, - CMD_CHAR_SET_USER_DATA, CMD_CHAR_SET_UP, BUFFER_WRITE_BOOL, BUFFER_READ_UINT16, - BUFFER_WRITE_UINT16, CMD_CHAR_SET_BP_FILTER_LAYER, BP_LAYER_MOVING, OBJ_LAYER_MOVING, - CMD_CHAR_SET_OBJ_FILTER_LAYER, CMD_CHAR_SET_COS_ANGLE, CMD_CHAR_SET_MIN_DIST, - CMD_CHAR_SET_TEST_DIST, CMD_CHAR_SET_EXTRA_DOWN, CMD_CHAR_SET_STEP_UP, CMD_CHAR_SET_STICK_DOWN + BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_UINT32, CMD_CHAR_SET_HIT_RED_ANGLE, + CMD_CHAR_PAIR_BODY, CMD_CHAR_SET_LIN_VEL, CMD_CHAR_SET_MASS, CMD_CHAR_SET_MAX_STR, + CMD_CHAR_SET_NUM_HITS, CMD_CHAR_SET_POS_ROT, CMD_CHAR_SET_REC_SPD, CMD_CHAR_SET_SHAPE, + CMD_REPORT_SET_SHAPE, COMPONENT_SYSTEM_CHAR, CMD_CHAR_SET_SHAPE_OFFSET, CMD_CHAR_SET_USER_DATA, + CMD_CHAR_SET_UP, BUFFER_WRITE_BOOL, BUFFER_READ_UINT16, BUFFER_WRITE_UINT16, + CMD_CHAR_SET_BP_FILTER_LAYER, BP_LAYER_MOVING, OBJ_LAYER_MOVING, CMD_CHAR_SET_OBJ_FILTER_LAYER, + CMD_CHAR_SET_COS_ANGLE, CMD_CHAR_SET_MIN_DIST, CMD_CHAR_SET_TEST_DIST, CMD_CHAR_SET_EXTRA_DOWN, + CMD_CHAR_SET_STEP_UP, CMD_CHAR_SET_STICK_DOWN } from '../../../constants.mjs'; class CharModifier { @@ -57,7 +57,7 @@ class CharModifier { case CMD_CHAR_SET_UP: return this._setUp(cb); - + case CMD_CHAR_SET_BP_FILTER_LAYER: return this._setBPFilterLayer(cb); diff --git a/src/physics/jolt/back/operators/querier.mjs b/src/physics/jolt/back/operators/querier.mjs index 4e4a7b0..c351d3a 100644 --- a/src/physics/jolt/back/operators/querier.mjs +++ b/src/physics/jolt/back/operators/querier.mjs @@ -272,7 +272,6 @@ class Querier { const Jolt = backend.Jolt; const joltInterface = backend.joltInterface; - buffer.writeOperator(COMPONENT_SYSTEM_MANAGER); buffer.writeCommand(CMD_CAST_SHAPE); diff --git a/src/physics/jolt/front/char/component.mjs b/src/physics/jolt/front/char/component.mjs index 3024c11..32baf99 100644 --- a/src/physics/jolt/front/char/component.mjs +++ b/src/physics/jolt/front/char/component.mjs @@ -25,7 +25,7 @@ import { * @group Components * @category Char Component */ -class CharComponent extends ShapeComponent { +class CharComponent extends ShapeComponent { _backFaceMode = BFM_COLLIDE_BACK_FACES; _bpFilterLayer = BP_LAYER_MOVING; @@ -95,7 +95,7 @@ class CharComponent extends ShapeComponent { _walkStairsStepForwardTest = 0.15; _walkStairsStepUp = new Vec3(0, 0.4, 0); - + /** * When colliding with back faces, the character will not be able to move through back facing * triangles. Use this if you have triangles that need to collide on both sides. Following @@ -115,7 +115,7 @@ class CharComponent extends ShapeComponent { } /** - * @param {number} - Broadphase Filter Layer number. + * @param {number} layerNum - Broadphase Filter Layer number. */ set bpFilterLayer(layerNum) { if (this._bpFilterLayer === layerNum) { @@ -425,7 +425,7 @@ class CharComponent extends ShapeComponent { } /** - * @param {number} - Object Filter Layer number. + * @param {number} layerNum - Object Filter Layer number. */ set objFilterLayer(layerNum) { if (this._objFilterLayer === layerNum) { @@ -605,7 +605,7 @@ class CharComponent extends ShapeComponent { } /** - * @param {Vec3} - Direction and distance for stepping down. + * @param {Vec3} vec - Direction and distance for stepping down. */ set stickToFloorStepDown(vec) { if (this._stickToFloorStepDown.equals(vec)) { @@ -756,7 +756,7 @@ class CharComponent extends ShapeComponent { } /** - * @param {number} - Radians. + * @param {number} angle - Radians. */ set walkStairsCosAngleForwardContact(angle) { if (this._walkStairsCosAngleForwardContact === angle) { @@ -790,7 +790,7 @@ class CharComponent extends ShapeComponent { } /** - * @param {number} - Minimum distance. + * @param {number} dist - Minimum distance. */ set walkStairsMinStepForward(dist) { if (this._walkStairsMinStepForward === dist) { @@ -822,7 +822,7 @@ class CharComponent extends ShapeComponent { } /** - * @param {Vec3} - Extra translation. + * @param {Vec3} vec - Extra translation. */ set walkStairsStepDownExtra(vec) { if (this._walkStairsStepDownExtra.equals(vec)) { @@ -853,7 +853,7 @@ class CharComponent extends ShapeComponent { * further down than up. Set to zero vector if you don't want this. Should be in the opposite * direction of up. * - * @type {Vec3} + * @returns {Vec3} - Extra translation vector. * @defaultValue Vec3(0, 0, 0) */ get walkStairsStepDownExtra() { @@ -861,7 +861,7 @@ class CharComponent extends ShapeComponent { } /** - * @param {number} - Test distance. + * @param {number} dist - Test distance. */ set walkStairsStepForwardTest(dist) { if (this._walkStairsStepForwardTest === dist) { @@ -896,7 +896,7 @@ class CharComponent extends ShapeComponent { } /** - * @param {Vec3} - Direction and distance of the step. + * @param {Vec3} vec - Direction and distance of the step. */ set walkStairsStepUp(vec) { if (this._walkStairsStepUp.equals(vec)) { @@ -920,7 +920,7 @@ class CharComponent extends ShapeComponent { /** * The direction and distance to step up (this corresponds to the max step height). * - * @param {Vec3} + * @returns {Vec3} - Vector, representing step direction and distance. * @defaultValue Vec3(0, 0.4, 0) (m) */ get walkStairsStepUp() { @@ -958,7 +958,7 @@ class CharComponent extends ShapeComponent { /** * Allows to change the shape of the character collider. - * + * * @param {number} shapeIndex - The shape index to switch to. It can be created by * {@link JoltManager.createShape | createShape}. Use negative number to reset to original * shape. @@ -1011,7 +1011,7 @@ class CharComponent extends ShapeComponent { const entity = this.entity; const pos = entity.getPosition(); const rot = entity.getRotation(); - + // Loss of precision for pos/rot (64 -> 32) cb.write(pos, BUFFER_WRITE_VEC32, false); cb.write(rot, BUFFER_WRITE_VEC32, false); diff --git a/src/physics/jolt/front/char/system.mjs b/src/physics/jolt/front/char/system.mjs index 48b4d5e..3c134a8 100644 --- a/src/physics/jolt/front/char/system.mjs +++ b/src/physics/jolt/front/char/system.mjs @@ -1,5 +1,4 @@ import { Debug } from '../../debug.mjs'; -import { IndexedCache } from '../../../indexed-cache.mjs'; import { CharComponent } from './component.mjs'; import { ResponseHandler } from '../response-handler.mjs'; import { ShapeComponentSystem } from '../shape/system.mjs'; @@ -83,8 +82,6 @@ class CharComponentSystem extends ShapeComponentSystem { break; case CMD_REPORT_SET_SHAPE: - case CMD_CHAR_CAN_WALK_STAIRS: - case CMD_CHAR_WALK_STAIRS: ResponseHandler.handleCharCallback(cb, this._manager.queryMap); break; } diff --git a/src/physics/jolt/front/response-handler.mjs b/src/physics/jolt/front/response-handler.mjs index e02cad0..d040923 100644 --- a/src/physics/jolt/front/response-handler.mjs +++ b/src/physics/jolt/front/response-handler.mjs @@ -1,5 +1,4 @@ import { Vec3 } from 'playcanvas'; -import { Debug } from '../debug.mjs'; import { ShapeComponentSystem } from './shape/system.mjs'; import { BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_UINT16, BUFFER_READ_UINT32,