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

spherical joint used for ragdoll and spring bone #919

Closed
wants to merge 3 commits into from
Closed
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
86 changes: 86 additions & 0 deletions packages/core/src/physics/joint/SphericalJoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Joint } from "./Joint";
import { ISphericalJoint } from "@oasis-engine/design";
import { Collider } from "../Collider";
import { PhysicsManager } from "../PhysicsManager";

/**
* A joint which behaves in a similar way to a ball and socket.
*/
export class SphericalJoint extends Joint {
private _yLimit = Math.PI / 2;
private _zLimit = Math.PI / 2;
private _contactDistance = -1;
private _stiffness = 0;
private _damping = 0;
private _enableSpring = false;

/** Whether enable spring limit */
get enableSpring(): boolean {
return this._enableSpring;
}

set enableSpring(value: boolean) {
this._enableSpring = value;
(<ISphericalJoint>this._nativeJoint).enableSpring(value);
}

/** The limit angle from the Y-axis of the constraint frame. */
get yLimit(): number {
return this._yLimit;
}

set yLimit(value: number) {
this._yLimit = value;
(<ISphericalJoint>this._nativeJoint).setYLimit(value);
}

/** The limit angle from the Z-axis of the constraint frame. */
get zLimit(): number {
return this._zLimit;
}

set zLimit(value: number) {
this._zLimit = value;
(<ISphericalJoint>this._nativeJoint).setZLimit(value);
}

/** Distance inside the limit value at which the limit will be considered to be active by the solver. */
get contactDistance(): number {
return this._contactDistance;
}

set contactDistance(value: number) {
this._contactDistance = value;
(<ISphericalJoint>this._nativeJoint).setContactDistance(value);
}

/** The spring forces used to reach the target position. */
get stiffness(): number {
return this._stiffness;
}

set stiffness(value: number) {
this._stiffness = value;
(<ISphericalJoint>this._nativeJoint).setStiffness(value);
}

/** The damper force uses to dampen the spring. */
get damping(): number {
return this._damping;
}

set damping(value: number) {
this._damping = value;
(<ISphericalJoint>this._nativeJoint).setDamping(value);
}

/**
* @override
* @internal
*/
_onAwake() {
const collider = this._collider;
collider.collider = this.entity.getComponent(Collider);
this._nativeJoint = PhysicsManager._nativePhysics.createSphericalJoint(collider.collider._nativeCollider);
}
}
1 change: 1 addition & 0 deletions packages/core/src/physics/joint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { Joint } from "./Joint";
export { FixedJoint } from "./FixedJoint";
export { HingeJoint } from "./HingeJoint";
export { SpringJoint } from "./SpringJoint";
export { SphericalJoint } from "./SphericalJoint";

export { JointLimits } from "./JointLimits";
export { JointMotor } from "./JointMotor";
8 changes: 7 additions & 1 deletion packages/design/src/physics/IPhysics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { IStaticCollider } from "./IStaticCollider";
import { Quaternion, Vector3 } from "@oasis-engine/math";
import { ICollider } from "./ICollider";
import { ICharacterController } from "./ICharacterController";
import { IFixedJoint, IHingeJoint, ISpringJoint } from "./joints";
import { IFixedJoint, IHingeJoint, ISpringJoint, ISphericalJoint } from "./joints";

/**
* The interface of physics creation.
Expand Down Expand Up @@ -119,4 +119,10 @@ export interface IPhysics {
* @param collider - Affector of joint
*/
createSpringJoint(collider: ICollider): ISpringJoint;

/**
* Create spherical joint
* @param collider - Affector of joint
*/
createSphericalJoint(collider: ICollider): ISphericalJoint;
}
24 changes: 24 additions & 0 deletions packages/design/src/physics/joints/ISphericalJoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IJoint } from "./IJoint";

/**
* A joint which behaves in a similar way to a ball and socket.
*/
export interface ISphericalJoint extends IJoint {
/** Whether enable spring limit */
enableSpring(value: boolean);

/** The limit angle from the Y-axis of the constraint frame. */
setYLimit(value: number);

/** The limit angle from the Z-axis of the constraint frame. */
setZLimit(value: number);

/** Distance inside the limit value at which the limit will be considered to be active by the solver. */
setContactDistance(value: number);

/** The spring forces used to reach the target position. */
setStiffness(value: number);

/** The damper force uses to dampen the spring. */
setDamping(value: number);
}
1 change: 1 addition & 0 deletions packages/design/src/physics/joints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export type { IJoint } from "./IJoint";
export type { IFixedJoint } from "./IFixedJoint";
export type { IHingeJoint } from "./IHingeJoint";
export type { ISpringJoint } from "./ISpringJoint";
export type { ISphericalJoint } from "./ISphericalJoint";
14 changes: 11 additions & 3 deletions packages/physics-lite/src/LitePhysics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
IFixedJoint,
IHingeJoint,
ISpringJoint,
ISphericalJoint
} from "@oasis-engine/design";
import { Quaternion, Vector3 } from "oasis-engine";
import { LiteDynamicCollider } from "./LiteDynamicCollider";
Expand Down Expand Up @@ -121,20 +122,27 @@ export class LitePhysics {
* {@inheritDoc IPhysics.createFixedJoint }
*/
static createFixedJoint(collider: LiteCollider): IFixedJoint {
throw "Physics-lite don't support CapsuleColliderShape. Use Physics-PhysX instead!";
throw "Physics-lite don't support FixedJoint. Use Physics-PhysX instead!";
}

/**
* {@inheritDoc IPhysics.createHingeJoint }
*/
static createHingeJoint(collider: LiteCollider): IHingeJoint {
throw "Physics-lite don't support CapsuleColliderShape. Use Physics-PhysX instead!";
throw "Physics-lite don't support HingeJoint. Use Physics-PhysX instead!";
}

/**
* {@inheritDoc IPhysics.createSpringJoint }
*/
static createSpringJoint(collider: LiteCollider): ISpringJoint {
throw "Physics-lite don't support CapsuleColliderShape. Use Physics-PhysX instead!";
throw "Physics-lite don't support SpringJoint. Use Physics-PhysX instead!";
}

/**
* {@inheritDoc IPhysics.createSphericalJoint }
*/
static createSphericalJoint(collider: LiteCollider): ISphericalJoint {
throw "Physics-lite don't support SphericalJoint. Use Physics-PhysX instead!";
}
}
11 changes: 10 additions & 1 deletion packages/physics-physx/src/PhysXPhysics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
IStaticCollider,
IFixedJoint,
IHingeJoint,
ISpringJoint
ISpringJoint,
ISphericalJoint
} from "@oasis-engine/design";
import { Quaternion, Vector3 } from "oasis-engine";
import { PhysXRuntimeMode } from "./enum/PhysXRuntimeMode";
Expand All @@ -27,6 +28,7 @@ import { PhysXSphereColliderShape } from "./shape/PhysXSphereColliderShape";
import { PhysXFixedJoint } from "./joint/PhysXFixedJoint";
import { PhysXHingeJoint } from "./joint/PhysXHingeJoint";
import { PhysXSpringJoint } from "./joint/PhysXSpringJoint";
import { PhysXSphericalJoint } from "./joint/PhysXSphericalJoint";
import { StaticInterfaceImplement } from "./StaticInterfaceImplement";
import { PhysXCollider } from "./PhysXCollider";

Expand Down Expand Up @@ -214,6 +216,13 @@ export class PhysXPhysics {
return new PhysXSpringJoint(collider);
}

/**
* {@inheritDoc IPhysics.createSpringJoint }
*/
static createSphericalJoint(collider: PhysXCollider): ISphericalJoint {
return new PhysXSphericalJoint(collider);
}

private static _init(PHYSX: any): void {
PhysXPhysics._physX = PHYSX;
const version = PhysXPhysics._physX.PX_PHYSICS_VERSION;
Expand Down
97 changes: 97 additions & 0 deletions packages/physics-physx/src/joint/PhysXSphericalJoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { ISphericalJoint } from "@oasis-engine/design";
import { PhysXJoint } from "./PhysXJoint";
import { PhysXCollider } from "../PhysXCollider";
import { PhysXPhysics } from "../PhysXPhysics";

/**
* A joint which behaves in a similar way to a ball and socket.
*/
export class PhysXSphericalJoint extends PhysXJoint implements ISphericalJoint {
private _yLimit = Math.PI / 2;
private _zLimit = Math.PI / 2;
private _contactDistance = -1;
private _stiffness = 0;
private _damping = 0;
private _enableSpring = false;

constructor(collider: PhysXCollider) {
super();
this._collider = collider;
this._pxJoint = PhysXPhysics._pxPhysics.createSphericalJoint(
null,
PhysXJoint._defaultVec,
PhysXJoint._defaultQuat,
collider._pxActor,
PhysXJoint._defaultVec,
PhysXJoint._defaultQuat
);
}

/**
* {@inheritDoc ISphericalJoint.enableSpring }
*/
enableSpring(value: boolean) {
if (this._enableSpring !== value) {
this._enableSpring = value;
this._setLimitCone();
}
}

/**
* {@inheritDoc ISphericalJoint.setYLimit }
*/
setYLimit(value: number) {
if (this._yLimit !== value) {
this._yLimit = value;
this._setLimitCone();
}
}

/**
* {@inheritDoc ISphericalJoint.setZLimit }
*/
setZLimit(value: number) {
if (this._zLimit !== value) {
this._zLimit = value;
this._setLimitCone();
}
}

/**
* {@inheritDoc ISphericalJoint.setContactDistance }
*/
setContactDistance(value: number) {
if (this._contactDistance !== value) {
this._contactDistance = value;
this._setLimitCone();
}
}

/**
* {@inheritDoc ISphericalJoint.setStiffness }
*/
setStiffness(value: number) {
if (this._stiffness !== value) {
this._stiffness = value;
this._setLimitCone();
}
}

/**
* {@inheritDoc ISphericalJoint.setDamping }
*/
setDamping(value: number) {
if (this._damping !== value) {
this._damping = value;
this._setLimitCone();
}
}

private _setLimitCone() {
if (this._enableSpring) {
this._pxJoint.setSoftLimitCone(this._yLimit, this._zLimit, this._stiffness, this._damping);
} else {
this._pxJoint.setHardLimitCone(this._yLimit, this._zLimit, this._contactDistance);
}
}
}