Skip to content

Commit 1dd5064

Browse files
committed
docs: clean up spinning ik more
1 parent a69179a commit 1dd5064

File tree

1 file changed

+39
-32
lines changed

1 file changed

+39
-32
lines changed

apps/demo/src/app/animation-skinning-ik/animation-skinning-ik.component.ts

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { NgIf } from '@angular/common';
2-
import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, ViewChild } from '@angular/core';
2+
import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, ViewChild } from '@angular/core';
33
import {
44
applyProps,
55
extend,
@@ -15,6 +15,8 @@ import { map } from 'rxjs';
1515
import * as THREE from 'three';
1616
import { CCDIKHelper, CCDIKSolver, DRACOLoader, GLTFLoader, IKS, OrbitControls, TransformControls } from 'three-stdlib';
1717
import { DemoOrbitControls } from '../ui-orbit-controls/orbit-controls.component';
18+
// @ts-expect-error
19+
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
1820

1921
const iks = [
2022
{
@@ -35,7 +37,7 @@ const iks = [
3537
},
3638
],
3739
},
38-
];
40+
] as any satisfies IKS[];
3941
const v0 = new THREE.Vector3();
4042

4143
extend({ TransformControls, CCDIKHelper });
@@ -46,36 +48,34 @@ extend({ TransformControls, CCDIKHelper });
4648
<ngt-color *args="['#dddddd']" attach="background" />
4749
<ngt-fog-exp2 *args="['#ffffff', 0.17]" attach="fog" />
4850
<ngt-ambient-light [intensity]="8" />
49-
<ngt-primitive *args="[model$ | ngtPush : null]" (afterAttach)="onAfterModelAttach()" />
50-
<ngt-cube-camera #cubeCamera *args="[0.05, 50, cubeRenderTarget]" />
51-
<ng-container *ngIf="ooi['kira']">
52-
<ngt-cCDIK-helper *args="[ooi['kira'], iks, 0.01]" />
51+
<ngt-primitive *args="[model$ | ngtPush]" (afterAttach)="onAfterModelAttach()" />
52+
<ngt-cube-camera #camera *args="[0.05, 50, cubeRenderTarget]" />
53+
<ng-container *ngIf="ooi['kira'] as kira">
54+
<ngt-cCDIK-helper *args="[kira, iks, 0.01]" />
5355
</ng-container>
5456
<demo-orbit-controls [minDistance]="0.2" [maxDistance]="1.5" (ready)="orbitControls = $any($event)" />
55-
<ngt-transform-controls
56-
#transformControls
57-
*args="[store.get('camera'), store.get('gl', 'domElement')]"
58-
[size]="0.75"
59-
[showX]="false"
60-
space="world"
61-
/>
57+
<ngt-transform-controls #controls *args="[camera, glDom]" [size]="0.75" [showX]="false" space="world" />
6258
`,
6359
imports: [NgtArgs, NgIf, DemoOrbitControls, NgtPush],
6460
schemas: [CUSTOM_ELEMENTS_SCHEMA],
6561
})
6662
export class Scene {
63+
private readonly config = { followSphere: false, turnHead: true, ikSolver: true };
64+
private readonly gui = new GUI();
65+
6766
readonly iks = iks;
6867
readonly cubeRenderTarget = new THREE.WebGLCubeRenderTarget(1024);
6968

70-
private readonly cdr = inject(ChangeDetectorRef);
7169
readonly store = inject(NgtStore);
70+
readonly camera = this.store.get('camera');
71+
readonly glDom = this.store.get('gl', 'domElement');
7272

73-
@ViewChild('transformControls') transformControls?: ElementRef<TransformControls>;
74-
@ViewChild('cubeCamera') cubeCamera?: ElementRef<THREE.CubeCamera>;
73+
@ViewChild('controls') transformControls?: ElementRef<TransformControls>;
74+
@ViewChild('camera') cubeCamera?: ElementRef<THREE.CubeCamera>;
7575
orbitControls?: OrbitControls;
7676
solver?: CCDIKSolver;
7777

78-
readonly ooi: Record<string, THREE.Object3D> = {};
78+
readonly ooi: { sphere: THREE.Mesh; kira: THREE.SkinnedMesh; [key: string]: THREE.Object3D } = {} as any;
7979

8080
readonly model$ = injectNgtLoader(
8181
() => GLTFLoader,
@@ -91,19 +91,22 @@ export class Scene {
9191
if (n.name === 'head') this.ooi['head'] = n;
9292
if (n.name === 'hand_l') this.ooi['hand_l'] = n;
9393
if (n.name === 'target_hand_l') this.ooi['target_hand_l'] = n;
94-
if (n.name === 'boule') this.ooi['sphere'] = n;
95-
if (n.name === 'Kira_Shirt_left') this.ooi['kira'] = n;
94+
if (n.name === 'boule') this.ooi.sphere = n as THREE.Mesh;
95+
if (n.name === 'Kira_Shirt_left') this.ooi.kira = n as THREE.SkinnedMesh;
9696
if ((n as THREE.Mesh).isMesh) n.frustumCulled = false;
9797
});
98-
this.cdr.detectChanges();
9998
return gltf.scene;
10099
})
101100
);
102101

103102
constructor() {
103+
this.gui.add(this.config, 'followSphere').name('follow sphere');
104+
this.gui.add(this.config, 'turnHead').name('turn head');
105+
this.gui.add(this.config, 'ikSolver').name('IK Auto update');
106+
104107
injectBeforeRender(({ gl, scene }) => {
105108
const head = this.ooi['head'];
106-
const sphere = this.ooi['sphere'];
109+
const sphere = this.ooi.sphere;
107110

108111
if (sphere && this.cubeCamera) {
109112
sphere.visible = false;
@@ -112,28 +115,30 @@ export class Scene {
112115
sphere.visible = true;
113116
}
114117

115-
if (this.solver) {
116-
this.solver.update();
118+
if (sphere && this.config.followSphere) {
119+
sphere.getWorldPosition(v0);
120+
this.orbitControls?.target.lerp(v0, 0.1);
117121
}
118122

119-
if (head && sphere) {
123+
if (head && sphere && this.config.turnHead) {
120124
sphere.getWorldPosition(v0);
121125
head.lookAt(v0);
122126
head.rotation.set(head.rotation.x, head.rotation.y + Math.PI, head.rotation.z);
123127
}
128+
129+
if (this.config.ikSolver && this.solver) this.solver.update();
124130
});
125131
}
126132

127133
onAfterModelAttach() {
128-
this.orbitControls?.target.copy(this.ooi['sphere'].position);
129-
this.ooi['hand_l'].attach(this.ooi['sphere']);
130-
applyProps(this.ooi['sphere'], {
131-
material: new THREE.MeshBasicMaterial({ envMap: this.cubeRenderTarget.texture }),
132-
});
134+
if (this.orbitControls) this.orbitControls.target.copy(this.ooi.sphere.position);
135+
this.ooi['hand_l'].attach(this.ooi.sphere);
136+
this.ooi.sphere.material = new THREE.MeshBasicMaterial({ envMap: this.cubeRenderTarget.texture });
137+
138+
if (this.transformControls) this.transformControls.nativeElement.attach(this.ooi['target_hand_l']);
133139

134-
this.transformControls?.nativeElement.attach(this.ooi['target_hand_l']);
135-
this.ooi['kira'].add((this.ooi['kira'] as THREE.SkinnedMesh).skeleton.bones[0]);
136-
this.solver = new CCDIKSolver(this.ooi['kira'] as THREE.SkinnedMesh, this.iks as unknown as IKS[]);
140+
this.ooi.kira.add(this.ooi.kira.skeleton.bones[0]);
141+
this.solver = new CCDIKSolver(this.ooi.kira, this.iks);
137142

138143
if (this.transformControls && this.orbitControls) {
139144
this.transformControls.nativeElement.addEventListener(
@@ -145,6 +150,8 @@ export class Scene {
145150
() => (this.orbitControls!.enabled = true)
146151
);
147152
}
153+
this.gui.add(this.solver, 'update').name('IK Manual update()');
154+
this.gui.open();
148155
}
149156
}
150157

0 commit comments

Comments
 (0)