1
1
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' ;
3
3
import {
4
4
applyProps ,
5
5
extend ,
@@ -15,6 +15,8 @@ import { map } from 'rxjs';
15
15
import * as THREE from 'three' ;
16
16
import { CCDIKHelper , CCDIKSolver , DRACOLoader , GLTFLoader , IKS , OrbitControls , TransformControls } from 'three-stdlib' ;
17
17
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' ;
18
20
19
21
const iks = [
20
22
{
@@ -35,7 +37,7 @@ const iks = [
35
37
} ,
36
38
] ,
37
39
} ,
38
- ] ;
40
+ ] as any satisfies IKS [ ] ;
39
41
const v0 = new THREE . Vector3 ( ) ;
40
42
41
43
extend ( { TransformControls, CCDIKHelper } ) ;
@@ -46,36 +48,34 @@ extend({ TransformControls, CCDIKHelper });
46
48
<ngt-color *args="['#dddddd']" attach="background" />
47
49
<ngt-fog-exp2 *args="['#ffffff', 0.17]" attach="fog" />
48
50
<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]" />
53
55
</ng-container>
54
56
<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" />
62
58
` ,
63
59
imports : [ NgtArgs , NgIf , DemoOrbitControls , NgtPush ] ,
64
60
schemas : [ CUSTOM_ELEMENTS_SCHEMA ] ,
65
61
} )
66
62
export class Scene {
63
+ private readonly config = { followSphere : false , turnHead : true , ikSolver : true } ;
64
+ private readonly gui = new GUI ( ) ;
65
+
67
66
readonly iks = iks ;
68
67
readonly cubeRenderTarget = new THREE . WebGLCubeRenderTarget ( 1024 ) ;
69
68
70
- private readonly cdr = inject ( ChangeDetectorRef ) ;
71
69
readonly store = inject ( NgtStore ) ;
70
+ readonly camera = this . store . get ( 'camera' ) ;
71
+ readonly glDom = this . store . get ( 'gl' , 'domElement' ) ;
72
72
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 > ;
75
75
orbitControls ?: OrbitControls ;
76
76
solver ?: CCDIKSolver ;
77
77
78
- readonly ooi : Record < string , THREE . Object3D > = { } ;
78
+ readonly ooi : { sphere : THREE . Mesh ; kira : THREE . SkinnedMesh ; [ key : string ] : THREE . Object3D } = { } as any ;
79
79
80
80
readonly model$ = injectNgtLoader (
81
81
( ) => GLTFLoader ,
@@ -91,19 +91,22 @@ export class Scene {
91
91
if ( n . name === 'head' ) this . ooi [ 'head' ] = n ;
92
92
if ( n . name === 'hand_l' ) this . ooi [ 'hand_l' ] = n ;
93
93
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 ;
96
96
if ( ( n as THREE . Mesh ) . isMesh ) n . frustumCulled = false ;
97
97
} ) ;
98
- this . cdr . detectChanges ( ) ;
99
98
return gltf . scene ;
100
99
} )
101
100
) ;
102
101
103
102
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
+
104
107
injectBeforeRender ( ( { gl, scene } ) => {
105
108
const head = this . ooi [ 'head' ] ;
106
- const sphere = this . ooi [ ' sphere' ] ;
109
+ const sphere = this . ooi . sphere ;
107
110
108
111
if ( sphere && this . cubeCamera ) {
109
112
sphere . visible = false ;
@@ -112,28 +115,30 @@ export class Scene {
112
115
sphere . visible = true ;
113
116
}
114
117
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 ) ;
117
121
}
118
122
119
- if ( head && sphere ) {
123
+ if ( head && sphere && this . config . turnHead ) {
120
124
sphere . getWorldPosition ( v0 ) ;
121
125
head . lookAt ( v0 ) ;
122
126
head . rotation . set ( head . rotation . x , head . rotation . y + Math . PI , head . rotation . z ) ;
123
127
}
128
+
129
+ if ( this . config . ikSolver && this . solver ) this . solver . update ( ) ;
124
130
} ) ;
125
131
}
126
132
127
133
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' ] ) ;
133
139
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 ) ;
137
142
138
143
if ( this . transformControls && this . orbitControls ) {
139
144
this . transformControls . nativeElement . addEventListener (
@@ -145,6 +150,8 @@ export class Scene {
145
150
( ) => ( this . orbitControls ! . enabled = true )
146
151
) ;
147
152
}
153
+ this . gui . add ( this . solver , 'update' ) . name ( 'IK Manual update()' ) ;
154
+ this . gui . open ( ) ;
148
155
}
149
156
}
150
157
0 commit comments