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

【Design】Physical system #496

Closed
GuoLei1990 opened this issue Sep 8, 2021 · 0 comments · Fixed by #505
Closed

【Design】Physical system #496

GuoLei1990 opened this issue Sep 8, 2021 · 0 comments · Fixed by #505
Assignees
Labels
design engine design high priority High priority issue physics Engine's physical system
Milestone

Comments

@GuoLei1990
Copy link
Member

GuoLei1990 commented Sep 8, 2021

This is the design of physical system.

Multi-backend subcontracting design of physical system

物理引擎分包设计 001

API Design

UML:
image

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 {}

/**
 * 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 mass of the RigidBody. */
  mass: number;
  /** Controls whether physics affects the RigidBody. */
  isKinematic: boolean;

  /** 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;
}

Design Source Code

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

@GuoLei1990 GuoLei1990 added the physics Engine's physical system label Sep 8, 2021
@GuoLei1990 GuoLei1990 added this to the 0.6 milestone Sep 8, 2021
@GuoLei1990 GuoLei1990 self-assigned this Sep 8, 2021
@GuoLei1990 GuoLei1990 linked a pull request Sep 8, 2021 that will close this issue
3 tasks
@GuoLei1990 GuoLei1990 added the high priority High priority issue label Sep 9, 2021
@yangfengzzz yangfengzzz removed a link to a pull request Sep 11, 2021
3 tasks
@yangfengzzz yangfengzzz linked a pull request Sep 11, 2021 that will close this issue
3 tasks
@GuoLei1990 GuoLei1990 added the design engine design label Sep 13, 2021
@GuoLei1990 GuoLei1990 changed the title Physical system Design 【design】Physical system Design Sep 17, 2021
@GuoLei1990 GuoLei1990 changed the title 【design】Physical system Design 【design】Physical system Sep 17, 2021
@GuoLei1990 GuoLei1990 changed the title 【design】Physical system 【Design】Physical system Sep 17, 2021
@yangfengzzz yangfengzzz mentioned this issue Sep 28, 2021
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design engine design high priority High priority issue physics Engine's physical system
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant