Closed IRobot1 closed 2 years ago
This component needs to be inside of
Looks like your comment was truncated
The component needs to be inside of ngt-physics which needs to be inside of ngt-canvas.
It is. All of my components where working with V4. Here's the full code for the bounce example.
<div style="height:100vh">
<ngt-canvas [camera]="{ position: [10, 2, 0], fov: 45, near:1, far:100 }"
[scene]="{ background: 'gray' | color }">
<ngt-directional-light [args]="['white' | color, 1.75]"
[position]="[20, 20, 20]" [castShadow]="true">
</ngt-directional-light>
<ngt-physics>
<ngt-cannon-debug [disabled]="true" [scale]="1.1" color="red">
<ngt-mesh [ref]="sphere1Props.ref" [castShadow]="true">
<ngt-sphere-geometry></ngt-sphere-geometry>
<ngt-mesh-standard-material [parameters]="{ color: 'red' | color }"></ngt-mesh-standard-material>
</ngt-mesh>
<ngt-mesh [ref]="sphere2Props.ref" [castShadow]="true">
<ngt-sphere-geometry></ngt-sphere-geometry>
<ngt-mesh-standard-material [parameters]="{ color: 'white' | color }"></ngt-mesh-standard-material>
</ngt-mesh>
<ngt-mesh [ref]="sphere3Props.ref" [castShadow]="true">
<ngt-sphere-geometry></ngt-sphere-geometry>
<ngt-mesh-standard-material [parameters]="{ color: 'blue' | color }"></ngt-mesh-standard-material>
</ngt-mesh>
<floor></floor>
</ngt-cannon-debug>
</ngt-physics>
<ngt-soba-orbit-controls></ngt-soba-orbit-controls>
<ngt-stats></ngt-stats>
</ngt-canvas>
</div>
import { Component } from "@angular/core";
import { NgtPhysicBody } from "@angular-three/cannon/bodies";
import { NgtTriple } from "@angular-three/core";
@Component({
templateUrl: './bounce.component.html',
providers: [NgtPhysicBody],
})
export class BounceComponent {
sphere1Props = this.physicBody.useSphere(() => ({
mass: 1,
position: [-3, 5, 3] as NgtTriple,
material: { restitution: 0.4 },
}));
sphere2Props = this.physicBody.useSphere(() => ({
mass: 1,
position: [-3, 5, 0] as NgtTriple,
material: { restitution: 0.6 },
}));
sphere3Props = this.physicBody.useSphere(() => ({
mass: 1,
position: [-3, 5, -3] as NgtTriple,
material: { restitution: 0.8 },
}));
constructor(private physicBody: NgtPhysicBody) { }
}
I added the following to AppModule, now the error changes to NullInjectorError: R3InjectorError(AppModule)[NgtStore -> ElementRef -> ElementRef -> ElementRef]
providers: [NgtStore],
I don't think this is the right solution though.
I've pushed the full cannon examples project to a v5 branch. Hopefully, it will repeat for you.
I'm outside right now. can you see if you can replicate the error on the physic-cubes example in apps/sandbox on the v5 branch?
What's the command to run this standbox server?
Figure it out. nx serve standbox
I think I see the problem. Your BounceComponent also includes the ngt-canvas which makes BounceComponent a parent (host) of NgtCanvas, not children.
Why don't you just bring the three spheres into the Bounce component instead of the whole canvas?
This is the whole example page. This worked fine in V4.
Sounds like if I want to pull NgtPhysicBody into a component, that component can't include ngt-canvas
As soon as I add those two lines to SandboxPhysicCubesComponent component, it starts failing in the same way.
@Component({
selector: 'sandbox-physic-cubes',
template: `
<div style="height:100vh">
<ngt-canvas
[dpr]="[1, 2]"
[gl]="{ alpha: false }"
[camera]="{ position: [-1, 5, 5], fov: 45 }">
<ngt-ambient-light></ngt-ambient-light>
<ngt-directional-light [position]="10" [castShadow]="true">
</ngt-directional-light>
<ngt-physics>
<sandbox-plane [position]="[0, -2.5, 0]"></sandbox-plane>
<sandbox-cube [position]="[0.1, 5, 0]"></sandbox-cube>
<sandbox-cube [position]="[0, 10, -1]"></sandbox-cube>
<sandbox-cube [position]="[0, 20, -2]"></sandbox-cube>
</ngt-physics>
</ngt-canvas>
</div>`,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [NgtPhysicBody],
})
export class SandboxPhysicCubesComponent {
constructor(private physicBody: NgtPhysicBody) { }
}
Can you confirm this is the path forward for V5?
Does this only apply for objects with physics enabled?
Correct. That's how DI works. In v4, the physic body directives get attached on the mesh which are children of the Canvas. In v5, the PhysicBody service needs to be a child of Canvas. Your wrapper component wraps the Canvas which makes your component the Canvas's parent.
Ok, I'll split all my examples into two components.
Hopefully, that subtly can be captured in your updated documentation.
Once I have everything migrated, I'll make some V4 to V5 migration notes based on my own experience.
Please do! And definitely lemme know any feedback at all as we can make changes now if needed:
In v5, all objects that NGT wraps THREE are Instances (NgtInstance
) and Instances have the concept of attaching
which allows one instance to attach itself on the parent instance based on an array of paths. Eg: attach="background"
-> parent.background
, [attach]="['shadow', 'mapSize']"
-> parent.shadow.mapSize
etc...
<!-- instead of doing this, which is fine, but requires some memory: scene Input, color pipe etc... -->
<ngt-canvas [scene]="{ background: 'blue' | color }"></ngt-canvas>
<!-- you can do this -->
<ngt-canvas>
<!-- here, you say: I have this Color instance that I want to attach on the scene.background -->
<!-- it is easy to remember and most importantly, it has its own lifecycle as an Angular Component -->
<!-- you can ngIf it, or make it a reusable component -->
<ngt-color attach="background" color="blue"></ngt-color>
</ngt-canvas>
In v5, most (if not all) Inputs that are boolean can accept a BooleanInput
- <ngt-mesh [castShadow]="true" [receiveShadow]="true"></ngt-mesh>
+ <ngt-mesh castShadow receiveShadow></ngt-mesh>
@IRobot1 here's my list so far https://github.com/nartc/angular-three/blob/v5/libs/documentations/docs/getting-started/migrate-to-v5.mdx
Can you give an example of how to use instanced mesh with physics? Its not clear to me how ref is applied to each instance.
Previously the following code worked, but now throws lots of errors in the tick method
count = 400;
private boxes: Array<NgtTriple> = []
constructor(private physicBody: NgtPhysicBody) {
for (let i = 0; i < this.count; i++) {
// start with random positions
this.boxes.push([
(Math.random() * 2 - 1) * 5,
Math.random() * 10,
(Math.random() * 2 - 1) * 5
])
}
}
cubeProps = this.physicBody.useBox((index: number) => ({
mass: 1,
position: this.boxes[index],
args: [1, 1, 1],
}));
ready(inst: InstancedMesh) {
for (let i = 0; i < this.count; i++) {
inst.setColorAt(i, new Color().setHex(Math.random() * 0xffffff));
}
}
tick() {
const index = Math.floor(Math.random() * this.count)
this.cubeProps.api.at(index).position.set(0, 5 + Math.random() * 15, 0);
}
<ngt-instanced-mesh #inst (ready)="ready(inst.instance.value)" [count]="count"
(animateReady)="tick()"
[ref]="cubeProps.ref" castShadow>
<ngt-box-geometry></ngt-box-geometry>
<ngt-mesh-standard-material></ngt-mesh-standard-material>
</ngt-instanced-mesh>
Uncaught TypeError: Cannot read properties of undefined (reading 'position')
Looks like at(index) no longer returns a valid object
Also, some documentation on the second and third parameters of the useXXX methods.
@IRobot1 There's a bug with InstancedMesh. I just released beta.2 that contains the fix. I also added the Kinematic Cube example to the sandbox. Please take a look
I confirmed instance mesh is now fixed with beta 2.
@IRobot1 https://github.com/nartc/angular-three/issues/96 can you chime in here all the findings that you've found so far?
As soon as I add NgtPhysicBody to a component, I get the NullInjectorError. Feels like I'm missing an import module, but not sure which.