11import { 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' ;
33import {
44 applyProps ,
55 extend ,
@@ -15,6 +15,8 @@ import { map } from 'rxjs';
1515import * as THREE from 'three' ;
1616import { CCDIKHelper , CCDIKSolver , DRACOLoader , GLTFLoader , IKS , OrbitControls , TransformControls } from 'three-stdlib' ;
1717import { 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
1921const iks = [
2022 {
@@ -35,7 +37,7 @@ const iks = [
3537 } ,
3638 ] ,
3739 } ,
38- ] ;
40+ ] as any satisfies IKS [ ] ;
3941const v0 = new THREE . Vector3 ( ) ;
4042
4143extend ( { 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} )
6662export 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