-
-
Notifications
You must be signed in to change notification settings - Fork 310
Physical system design
ChenMo edited this page Mar 8, 2022
·
9 revisions
This is the design of physical system.
UML:
Colliders:
/**
* Basic class of rigid body collider.
*/
export abstract class Collider extends Component {
/** The shape of the Collider. */
get shapes(): Readonly<ColliderShape[]> { }
/**
* Add a collider shape.
* @param shape - The collider shape.
*/
addShape(shape: ColliderShape): void {}
/**
* Remove a collider shape.
* @param shape - The collider shape.
*/
removeShape(shape: ColliderShape): void {}
/**
* Clear all shape collection.
*/
clearShapes(): void {}
}
/**
* A static rigid body collider component that will not move when colliding with a dynamic rigid body collider.
* @remarks Mostly used for object which always stays at the same place and never moves around.
*/
export class StaticCollider extends Collider {}
/**
* Basic class of rigid body collider.
*/
export abstract class Collider extends Component {
/** The shape of the Collider. */
get shapes(): Readonly<ColliderShape[]> { }
/**
* Add a collider shape.
* @param shape - The collider shape.
*/
addShape(shape: ColliderShape): void {}
/**
* Remove a collider shape.
* @param shape - The collider shape.
*/
removeShape(shape: ColliderShape): void {}
/**
* Clear all shape collection.
*/
clearShapes(): void {}
}
/**
* A static rigid body collider component that will not move when colliding with a dynamic rigid body collider.
* @remarks Mostly used for object which always stays at the same place and never moves around.
*/
export class StaticCollider extends Collider {}
/**
* A dynamic rigid body collider component.
*/
export class DynamicCollider extends Collider {
/** The linear velocity vector of the RigidBody measured in world unit per second. */
linearVelocity: number;
/** The angular velocity vector of the RigidBody measured in radians per second. */
angularVelocity: number;
/** The linear damping of the RigidBody. */
linearDamping: number;
/** The angular damping of the RigidBody. */
angularDamping: number;
/** The center of mass relative to the transform's origin. */
centerOfMass: number;
/** The diagonal inertia tensor of mass relative to the center of mass. */
inertiaTensor: Vector3;
/** The maximum angular velocity of the collider measured in radians per second. (Default 7) range { 0, infinity }. */
maxAngularVelocity: number;
/** Maximum velocity of a collider when moving out of penetrating state. */
maxDepenetrationVelocity: number;
/** The mass of the RigidBody. */
mass: number;
/** The mass-normalized energy threshold, below which objects start going to sleep. */
sleepThreshold: number;
/** The solverIterations determines how accurately collider joints and collision contacts are resolved. */
solverIterations: number;
/** Controls whether physics will change the rotation of the object. */
freezeRotation: boolean;
/** The particular rigid dynamic lock flag. */
constraints: number;
/** The colliders' collision detection mode. */
collisionDetectionMode: number;
/** Controls whether physics affects the RigidBody. */
isKinematic: boolean;
constructor(entity: Entity) {
super(entity);
}
/** apply a force to the DynamicCollider. */
applyForce(force: Vector3): void {}
/** apply a torque to the DynamicCollider. */
applyTorque(torque: Vector3): void {}
}
Shapes:
/**
* Basic class of collider shape.
*/
export abstract class ColliderShape {
/** The position of this ColliderShape. */
position: Vector3;
/** Whether the ColliderShape is a trigger. */
isTrigger: boolean;
/** The physic material of this ColliderShape. */
material: PhysicsMaterial;
}
/**
* Box-shaped collider shape.
*/
export class BoxColliderShape extends ColliderShape {
/** The size of this BoxColliderShape. */
size: Vector3;
}
/**
* Sphere-shaped collider shape.
*/
export class SphereColliderShape extends ColliderShape {
/** The radius of this SphereColliderShape. */
radius: number;
}
/**
* Plane-shaped collider shape.
*/
export class PlaneColliderShape extends ColliderShape {
/** The rotation of this PlaneColliderShape. */
rotation: Vector3;
}
/**
* Capsule-shaped collider shape.
*/
export class CapsuleColliderShape extends ColliderShape {
/** The radius of this CapsuleColliderShape. */
radius: number;
/** The height of this CapsuleColliderShape. */
height: number;
/** The up axis of this CapsuleColliderShape. */
upAxis: ColliderShapeUpAxis;
}
Script Call back:
export class Script extends Component {
..............
/**
* Called when the collision enter.
* @param other - Other ColliderShape
*/
onTriggerEnter(other: ColliderShape): void {}
/**
* Called when the collision stay.
* @remarks onTriggerStay is called every frame while the collision stay.
* @param other - Other ColliderShape
*/
onTriggerStay(other: ColliderShape): void {}
/**
* Called when the collision exit.
* @param other - Other ColliderShape
*/
onTriggerExit(other: ColliderShape): void {}
..............
}
PhysicsManager:
export class PhysicsManager {
/**
* Casts a ray through the Scene and returns the first hit.
* @param ray - The ray
* @returns Returns true if the ray intersects with a Collider, otherwise false.
*/
raycast(ray: Ray): Boolean;
/**
* Casts a ray through the Scene and returns the first hit.
* @param ray - The ray
* @param outHitResult - If true is returned, outHitResult will contain more detailed collision information
* @returns Returns true if the ray intersects with a Collider, otherwise false.
*/
raycast(ray: Ray, outHitResult: HitResult): Boolean;
/**
* Casts a ray through the Scene and returns the first hit.
* @param ray - The ray
* @param distance - The max distance the ray should check
* @returns Returns true if the ray intersects with a Collider, otherwise false.
*/
raycast(ray: Ray, distance: number): Boolean;
/**
* Casts a ray through the Scene and returns the first hit.
* @param ray - The ray
* @param distance - The max distance the ray should check
* @param outHitResult - If true is returned, outHitResult will contain more detailed collision information
* @returns Returns true if the ray intersects with a Collider, otherwise false.
*/
raycast(ray: Ray, distance: number, outHitResult: HitResult): Boolean;
/**
* Casts a ray through the Scene and returns the first hit.
* @param ray - The ray
* @param distance - The max distance the ray should check
* @param layerMask - Layer mask that is used to selectively ignore Colliders when casting
* @returns Returns true if the ray intersects with a Collider, otherwise false.
*/
raycast(ray: Ray, distance: number, layerMask: Layer): Boolean;
/**
* Casts a ray through the Scene and returns the first hit.
* @param ray - The ray
* @param distance - The max distance the ray should check
* @param layerMask - Layer mask that is used to selectively ignore Colliders when casting
* @param outHitResult - If true is returned, outHitResult will contain more detailed collision information
* @returns Returns true if the ray intersects with a Collider, otherwise false.
*/
raycast(ray: Ray, distance: number, layerMask: Layer, outHitResult: HitResult): Boolean;
Auxiliary Class:
/**
* The up axis of the collider shape.
*/
export enum ColliderShapeUpAxis {
/** Up axis is X. */
X,
/** Up axis is Y. */
Y,
/** Up axis is Z. */
Z
}
/**
* Describe how to handle with collisions between colliders.
*/
export class PhysicsMaterial {
/** The bounciness of collider surface. */
bounciness: number;
/** The friction coefficient used when already moving. */
dynamicFriction: number;
/** The friction coefficient used when an object is lying on a surface. */
staticFriction: number;
/** The friction bounce mode.*/
bounceCombine: PhysicsMaterialCombineMode;
/** The friction combine mode. */
frictionCombine: PhysicsMaterialCombineMode;
}
/**
* Describes how physics materials of the colliders are combined.
*/
export enum PhysicsMaterialCombineMode {
/** Averages the friction/bounce of the two colliding materials. */
Average,
/** Uses the smaller friction/bounce of the two colliding materials. */
Minimum,
/** Uses the larger friction/bounce of the two colliding materials. */
Maximum,
/** Multiplies the friction/bounce of the two colliding materials. */
Multiply
}
/**
* Structure used to get information back from a raycast or a sweep.
*/
export class HitResult {
/** The collider shape that was hit. */
colliderShape: ColliderShape = null;
/** The distance from the origin to the hit point. */
distance: number = 0;
/** The hit point of the collider that was hit in world space. */
point: Vector3 = new Vector3();
/** The hit normal of the collider that was hit in world space. */
normal: Vector3 = new Vector3();
}
Physics engine interface:
export interface IColliderShape {
setPosition(position: Vector3): void;
setIsTrigger(isTrigger: boolean): void;
setMaterial(material: IPhysicsMaterial): void;
setWorldScale(scale: Vector3): void;
}
export interface IBoxColliderShape extends IColliderShape {
setSize(size: Vector3): void;
}
export interface ICapsuleColliderShape extends ICollider {
setUpAxis(upAxis: number): void;
setRadius(radius: number): void;
setHeight(height: number): void;
}
export interface IPlaneColliderShape extends ICollider {
setRotation(rotation: Vector3): void;
}
export interface ISphereColliderShape extends ICollider {
setRadius(radius: number): void;
}
export interface ICollider {
getWorldTransform(outPosition: Vector3, outRotation: Quaternion): void;
setWorldTransform(position: Vector3, rotation: Quaternion): void;
addShape(shape: IColliderShape): void;
removeShape(shape: IColliderShape): void;
clearShapes(): void;
}
export interface IStaticCollider extends ICollider {}
export interface IDynamicCollider extends ICollider {
linearVelocity: number;
angularVelocity: number;
linearDamping: number;
angularDamping: number;
mass: number;
isKinematic: boolean;
applyForce(force: Vector3): void;
applyTorque(torque: Vector3): void;
}
export interface IPhysics {
createPhysicsManager(): IPhysicsManager;
createStaticCollider(): IStaticCollider;
createDynamicCollider(): IDynamicCollider;
createBoxColliderShape(size: Vector3): IBoxColliderShape;
createSphereColliderShape(radius: number): ISphereColliderShape;
createPlaneColliderShape(normal: Vector3,distance:number): IPlaneColliderShape;
createCapsuleColliderShape(radius: number, height: number): ICapsuleColliderShape;
}
export interface IPhysicsManager {
addCollider(collider: ICollider): void;
removeCollider(collider: ICollider): void;
raycast(
ray: Ray,
distance: number,
layerMask: number,
outHitResult?: (colliderShapeID: number, distance: number, point: Vector3, normal: Vector3) => void
): Boolean;
}
export interface IPhysicsMaterial {
bounciness: number;
dynamicFriction: number;
staticFriction: number;
bounceCombine: number;
frictionCombine: number;
}
https://github.com/GuoLei1990/engine/tree/design/physics
User API Design: packages/core/src/physics
Physics engine interface Design: packages/design/src/physics
Physics engine implement sample: packages/physics-physX
and packages/physics-lite