Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mutable compound shape #88

Merged
merged 4 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@gamebop/physics",
"description": "Physics components for PlayCanvas engine",
"version": "0.3.2",
"version": "0.3.3",
"main": "dist/physics.min.mjs",
"author": "Gamebop",
"license": "MIT",
Expand Down
16 changes: 12 additions & 4 deletions src/physics/jolt/back/operators/creator.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
CMD_CREATE_SOFT_BODY, CMD_CREATE_VEHICLE, MOTION_QUALITY_DISCRETE, MOTION_TYPE_DYNAMIC,
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_MUTABLE_COMPOUND,
SHAPE_SPHERE, SHAPE_STATIC_COMPOUND
} from '../../constants.mjs';
import { ConstraintCreator } from './helpers/constraint-creator.mjs';
Expand Down Expand Up @@ -106,7 +107,8 @@ class Creator {
break;

case SHAPE_STATIC_COMPOUND:
settings = createStaticCompoundShapeSettings(cb, meshBuffers, Jolt, jv, jq);
case SHAPE_MUTABLE_COMPOUND:
settings = createCompoundShapeSettings(cb, meshBuffers, Jolt, jv, jq);
break;

case SHAPE_HEIGHTFIELD:
Expand All @@ -124,8 +126,11 @@ class Creator {
return null;
}

if (shapeType === SHAPE_STATIC_COMPOUND) {
const compoundSettings = new Jolt.StaticCompoundShapeSettings();
const isStaticCompound = shapeType === SHAPE_STATIC_COMPOUND;
const isMutableCompound = shapeType === SHAPE_MUTABLE_COMPOUND;
if (isStaticCompound || isMutableCompound) {
const compoundSettings = isStaticCompound ?
new Jolt.StaticCompoundShapeSettings() : new Jolt.MutableCompoundShapeSettings();

for (let i = 0, end = settings.length; i < end; i += 3) {
const childSettings = settings[i];
Expand Down Expand Up @@ -360,6 +365,9 @@ class Creator {
const shape = shapeResult.Get();
shape.AddRef();

// mark it for release, e.g. when removing a child from compound shape
shape.needsRelease = true;

this._backend.tracker.shapeMap.set(num, shape);

return true;
Expand Down Expand Up @@ -966,7 +974,7 @@ function createMeshShapeSettings(cb, Jolt, meshBuffers, shapeType, jv) {
return settings;
}

function createStaticCompoundShapeSettings(cb, meshBuffers, Jolt, jv, jq) {
function createCompoundShapeSettings(cb, meshBuffers, Jolt, jv, jq) {
const childrenCount = cb.read(BUFFER_READ_UINT32);
const children = [];

Expand Down
4 changes: 3 additions & 1 deletion src/physics/jolt/back/operators/helpers/char-modifier.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
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 { Cleaner } from '../cleaner.mjs';

class CharModifier {
_modifier = null;
Expand All @@ -18,6 +19,7 @@ class CharModifier {
constructor(modifier) {
this._modifier = modifier;
this._tracker = modifier.backend.tracker;
this._cleaner = modifier.backend.cleaner;
}

modify(command, cb) {
Expand Down Expand Up @@ -194,7 +196,7 @@ class CharModifier {
}

// invalidate current debug draw, so we draw a new shape instead
char.debugDrawData = null;
Cleaner.cleanDebugDrawData(char, backend.Jolt);
}

let shape;
Expand Down
185 changes: 180 additions & 5 deletions src/physics/jolt/back/operators/modifier.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { ConstraintModifier } from './helpers/constraint-modifier.mjs';
import {
BUFFER_READ_BOOL, BUFFER_READ_FLOAT32, BUFFER_READ_INT32, BUFFER_READ_UINT16,
BUFFER_READ_UINT32, BUFFER_READ_UINT8, CMD_ADD_ANGULAR_IMPULSE, CMD_ADD_FORCE, CMD_ADD_IMPULSE,
CMD_ADD_SHAPE,
CMD_ADD_TORQUE, CMD_APPLY_BUOYANCY_IMPULSE, CMD_CHANGE_GRAVITY, CMD_CLAMP_ANG_VEL,
CMD_CLAMP_LIN_VEL, CMD_MOVE_BODY, CMD_MOVE_KINEMATIC, CMD_RESET_MOTION, CMD_RESET_SLEEP_TIMER,
CMD_CLAMP_LIN_VEL, CMD_MODIFY_SHAPE, CMD_MOVE_BODY, CMD_MOVE_KINEMATIC, CMD_REMOVE_SHAPE, CMD_RESET_MOTION, CMD_RESET_SLEEP_TIMER,
CMD_SET_ALLOW_SLEEPING, CMD_SET_ANG_FACTOR, CMD_SET_ANG_VEL, CMD_SET_ANG_VEL_CLAMPED,
CMD_SET_APPLY_GYRO_FORCE, CMD_SET_AUTO_UPDATE_ISOMETRY, CMD_SET_COL_GROUP, CMD_SET_DEBUG_DRAW,
CMD_SET_DEBUG_DRAW_DEPTH, CMD_SET_DOF, CMD_SET_FRICTION, CMD_SET_GRAVITY_FACTOR,
Expand Down Expand Up @@ -136,10 +137,6 @@ class Modifier {
ok = this._useMotionState(cb);
break;

// case CMD_SET_DRIVER_INPUT:
// ok = this._setDriverInput(cb);
// break;

case CMD_SET_GRAVITY_FACTOR:
ok = this._setGravityFactor(cb);
break;
Expand All @@ -160,6 +157,18 @@ class Modifier {
ok = this._setShape(cb, meshBuffers);
break;

case CMD_ADD_SHAPE:
ok = this._addShape(cb);
break;

case CMD_REMOVE_SHAPE:
ok = this._removeShape(cb);
break;

case CMD_MODIFY_SHAPE:
ok = this._modifyShape(cb);
break;

case CMD_SET_DEBUG_DRAW:
ok = this._setDebugDraw(cb);
break;
Expand Down Expand Up @@ -348,6 +357,172 @@ class Modifier {
return true;
}

_addShape(cb) {
const backend = this._backend;
const Jolt = backend.Jolt;
const body = this._getBody(cb);
const jv = this._joltVec3_1;
const jq = this._joltQuat_1;

try {
const shapeIndex = cb.read(BUFFER_READ_UINT32);
const shape = backend.tracker.shapeMap.get(shapeIndex);
if ($_DEBUG) {
const ok = Debug.assert(!!shape, `Unable to locate shape: ${shapeIndex}`);
if (!ok) {
return false;
}
}

jv.FromBuffer(cb);
jq.FromBuffer(cb);

const userData = cb.read(BUFFER_READ_UINT32);
const bodyShape = body.GetShape();

if ($_DEBUG) {
const isValid = bodyShape.GetType() === Jolt.EShapeType_Compound &&
bodyShape.GetSubType() === Jolt.EShapeSubType_MutableCompound;
if (!isValid) {
Debug.warn('Current shape does not support adding child shapes.');
return false;
}
}

const com = bodyShape.GetCenterOfMass();
const compoundShape = Jolt.castObject(bodyShape, Jolt.MutableCompoundShape);
compoundShape.AddShape(jv, jq, shape, userData);
compoundShape.AdjustCenterOfMass();
backend.bodyInterface.NotifyShapeChanged(body.GetID(), com, true, Jolt.EActivation_Activate);

// If there is debug draw context, we need to reset it to view a new shape
Cleaner.cleanDebugDrawData(body, Jolt);

} catch (e) {
if ($_DEBUG) {
Debug.error(e);
}
return false;
}

return true;
}

_removeShape(cb) {
const backend = this._backend;
const Jolt = backend.Jolt;
const body = this._getBody(cb);

const childIndex = cb.read(BUFFER_READ_UINT32);

try {
const bodyShape = body.GetShape();
const compoundShape = Jolt.castObject(bodyShape, Jolt.MutableCompoundShape);

if ($_DEBUG) {
const isValid = bodyShape.GetType() === Jolt.EShapeType_Compound &&
bodyShape.GetSubType() === Jolt.EShapeSubType_MutableCompound;
if (!isValid) {
Debug.warn('Current shape does not support adding child shapes.');
return false;
}
}

const childShapesCount = compoundShape.GetNumSubShapes();
if (childIndex > childShapesCount - 1) {
if ($_DEBUG) {
Debug.warn('Trying to remove invalid child shape. Index exceeds number of child shapes.');
}
return true;
}

const shape = compoundShape.GetSubShape(childIndex);
const com = bodyShape.GetCenterOfMass();
compoundShape.RemoveShape(childIndex);
compoundShape.AdjustCenterOfMass();
backend.bodyInterface.NotifyShapeChanged(body.GetID(), com, true, Jolt.EActivation_Activate);

// release, if the child shape was created by user via creator
if (shape.needsRelease) {
shape.Release();
}

Cleaner.cleanDebugDrawData(body, Jolt);
} catch (e) {
if ($_DEBUG) {
Debug.error(e);
}
return false;
}

return true;
}

_modifyShape(cb) {
const backend = this._backend;
const Jolt = backend.Jolt;
const body = this._getBody(cb);
const jv = this._joltVec3_1;
const jq = this._joltQuat_1;

try {
const childIndex = cb.read(BUFFER_READ_UINT32);

jv.FromBuffer(cb);
jq.FromBuffer(cb);

const bodyShape = body.GetShape();

if ($_DEBUG) {
const isValid = bodyShape.GetType() === Jolt.EShapeType_Compound &&
bodyShape.GetSubType() === Jolt.EShapeSubType_MutableCompound;
if (!isValid) {
Debug.warn('Current shape does not support adding child shapes.');
return false;
}
}

let shape;
if (cb.flag) {
const shapeIndex = cb.read(BUFFER_READ_UINT32);
shape = backend.tracker.shapeMap.get(shapeIndex);
if ($_DEBUG) {
const ok = Debug.assert(!!shape, `Unable to locate shape: ${shapeIndex}`);
if (!ok) {
return false;
}
}
}

const com = bodyShape.GetCenterOfMass();
const compoundShape = Jolt.castObject(bodyShape, Jolt.MutableCompoundShape);

let existingShape;
if (shape) {
existingShape = compoundShape.GetSubShape(childIndex);
}

compoundShape.ModifyShape(childIndex, jv, jq, shape);
compoundShape.AdjustCenterOfMass();
backend.bodyInterface.NotifyShapeChanged(body.GetID(), com, true, Jolt.EActivation_Activate);

if (existingShape?.needsRelease) {
existingShape.Release();
}

// If there is debug draw context, we need to reset it to view a new shape
Cleaner.cleanDebugDrawData(body, Jolt);

} catch (e) {
if ($_DEBUG) {
Debug.error(e);
}
return false;
}

return true;
}

_useMotionState(cb) {
const body = this._getBody(cb);
const useMotionState = cb.read(BUFFER_READ_BOOL);
Expand Down
4 changes: 4 additions & 0 deletions src/physics/jolt/constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export const SHAPE_MESH = 4;
export const SHAPE_CONVEX_HULL = 5;
export const SHAPE_HEIGHTFIELD = 6;
export const SHAPE_STATIC_COMPOUND = 7;
export const SHAPE_MUTABLE_COMPOUND = 8;

export const CONTACT_TYPE_ADDED = 0;
export const CONTACT_TYPE_PERSISTED = 1;
Expand Down Expand Up @@ -189,6 +190,9 @@ export const CMD_SET_POS_STEPS = 58;
export const CMD_SET_SHAPE = 59;
export const CMD_SET_DEBUG_DRAW = 60;
export const CMD_SET_DEBUG_DRAW_DEPTH = 61;
export const CMD_ADD_SHAPE = 62;
export const CMD_REMOVE_SHAPE = 63;
export const CMD_MODIFY_SHAPE = 64;


// Char Virtual 400-499
Expand Down
Loading