nartc / angular-three

🧊 THREE.js integration for Angular 🧊
https://angular-three.netlify.app/
MIT License
306 stars 23 forks source link

[Feature] Physics body addShape support for offset and orientation. #87

Closed IRobot1 closed 2 years ago

IRobot1 commented 2 years ago

I'm converting the rigid body example

        const chassisBody = new CANNON.Body({ mass: 1 })
        const centerOfMassAdjust = new CANNON.Vec3(0, -1, 0)
        chassisBody.addShape(chassisShape, centerOfMassAdjust)

This is to request updating NgtPhysics properties to support optional offset and orientation when calling addShape. This will allow the center of mass to be set when defining the body properties.

I noticed for Ngt Compound bodies, position and rotation are being passed to addShape offset and orientation. Perhaps these names can be changed in shapes array to localoffset and orientation to avoid confusion.

IRobot1 commented 2 years ago

I've created center of mass example to demonstrate this missing feature. By setting the center of mass above the pointy end of the cone, it should be possible to remain upright. At the moment, it falls over.

image

IRobot1 commented 2 years ago

One work-around to change center of mass it so add a mass outside the body and use a cone twist constraint.

<ngt-mesh [ref]="cone.ref">
  <ngt-cylinder-geometry [args]="[1, 0, 1, 20]"></ngt-cylinder-geometry>
</ngt-mesh>

<ngt-mesh [ref]="particle.ref" [visible]="false">
  <ngt-sphere-geometry [args]="[particlesize, 6, 6]"></ngt-sphere-geometry>
</ngt-mesh>
import { Component } from "@angular/core";

import { AfterViewInit } from "@angular/core";

import { NgtPhysicBody, NgtPhysicConstraint } from "@angular-three/cannon";

@Component({
  selector: 'centerofmass-example',
  templateUrl: 'centerofmass-example.component.html',
  providers: [NgtPhysicBody, NgtPhysicConstraint],
})
export class CenterOfMassExample implements AfterViewInit {

  cone = this.physicBody.useCylinder(() => ({
    mass: 1,
    args: [1, 0, 1, 20],
    position: [0, 5, 0],
    rotation: [0, 0, 0],
    angularDamping: 0.5,
    linearDamping: 0.5,
  }))

  particlesize = 0.1
  particle = this.physicBody.useSphere(() => ({
    mass: 2,
    args: [this.particlesize],
    position: [0, 3, 0],
    angularDamping: 0.5,
    linearDamping: 0.5,
    collisionResponse: false,
  }))

  constructor(
    private physicBody: NgtPhysicBody,
    private physicConstraint: NgtPhysicConstraint,
  ) { }

  ngAfterViewInit(): void {
    this.physicConstraint.useConeTwistConstraint(
      this.particle.ref, this.cone.ref, {
        pivotA: [0, 0, 0],
        pivotB: [0, -2, 0],

    });
    this.cone.api.rotation.set(1, 0, 0);
  }
}

center of mass using constraint

nartc commented 2 years ago

Since @angular-three/cannon depends on cannon-worker-api, if an API is not exposed/supported by cannon-worker-api (https://github.com/pmndrs/use-cannon/tree/master/packages/cannon-worker-api) then there's nothing I can do from @angular-three/cannon.

For this case, I think it's somewhat similar to the light fixture in Monday Morning example. If yes, what you could do is instead of creating a particle with a visible=false Mesh, you can just pass false to the second parameter to useSphere. That way, the Body is still created with an empty Object3D and still be constrained in the Physic World. (https://github.com/nartc/angular-three/blob/main/apps/sandbox/src/app/monday-morning/monday-morning.component.ts#L442)