Skip to content

Commit 1f75a58

Browse files
committed
Examples: Refactored webgl_morphtargets_webcam.
1 parent 0d8676b commit 1f75a58

File tree

1 file changed

+48
-50
lines changed

1 file changed

+48
-50
lines changed

examples/webgl_morphtargets_webcam.html

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535

3636
import * as THREE from 'three';
3737

38-
import Stats from 'three/addons/libs/stats.module.js';
39-
4038
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
4139
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
4240

@@ -108,40 +106,6 @@
108106
// '': 'tongueOut'
109107
};
110108

111-
const video = document.createElement( 'video' );
112-
113-
const filesetResolver = await FilesetResolver.forVisionTasks(
114-
'https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/wasm'
115-
);
116-
117-
const faceLandmarker = await FaceLandmarker.createFromOptions( filesetResolver, {
118-
baseOptions: {
119-
modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task',
120-
delegate: 'GPU'
121-
},
122-
outputFaceBlendshapes: true,
123-
outputFacialTransformationMatrixes: true,
124-
runningMode: 'VIDEO',
125-
numFaces: 1
126-
} );
127-
128-
if ( navigator.mediaDevices && navigator.mediaDevices.getUserMedia ) {
129-
130-
navigator.mediaDevices.getUserMedia( { video: { facingMode: 'user' } } )
131-
.then( function ( stream ) {
132-
133-
video.srcObject = stream;
134-
video.play();
135-
136-
} )
137-
.catch( function ( error ) {
138-
139-
console.error( 'Unable to access the camera/webcam.', error );
140-
141-
} );
142-
143-
}
144-
145109
//
146110

147111
const renderer = new THREE.WebGLRenderer( { antialias: true } );
@@ -178,13 +142,14 @@
178142
const mesh = gltf.scene.children[ 0 ];
179143
scene.add( mesh );
180144

145+
const head = mesh.getObjectByName( 'mesh_2' );
146+
head.material = new THREE.MeshNormalMaterial();
147+
181148
// GUI
182149

183150
const gui = new GUI();
184151
gui.close();
185152

186-
const head = mesh.getObjectByName( 'mesh_2' );
187-
head.material = new THREE.MeshNormalMaterial();
188153
const influences = head.morphTargetInfluences;
189154

190155
for ( const [ key, value ] of Object.entries( head.morphTargetDictionary ) ) {
@@ -194,11 +159,15 @@
194159
.listen( influences );
195160

196161
}
162+
163+
renderer.setAnimationLoop( animation );
197164

198165
} );
199166

200167
// Video Texture
201168

169+
const video = document.createElement( 'video' );
170+
202171
const texture = new THREE.VideoTexture( video );
203172
texture.colorSpace = THREE.SRGBColorSpace;
204173

@@ -207,14 +176,43 @@
207176
const videomesh = new THREE.Mesh( geometry, material );
208177
scene.add( videomesh );
209178

210-
//
179+
// MediaPipe
180+
181+
const filesetResolver = await FilesetResolver.forVisionTasks(
182+
'https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/wasm'
183+
);
184+
185+
const faceLandmarker = await FaceLandmarker.createFromOptions( filesetResolver, {
186+
baseOptions: {
187+
modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task',
188+
delegate: 'GPU'
189+
},
190+
outputFaceBlendshapes: true,
191+
outputFacialTransformationMatrixes: true,
192+
runningMode: 'VIDEO',
193+
numFaces: 1
194+
} );
211195

212-
const stats = new Stats();
213-
document.body.appendChild( stats.dom );
196+
if ( navigator.mediaDevices && navigator.mediaDevices.getUserMedia ) {
197+
198+
navigator.mediaDevices.getUserMedia( { video: { facingMode: 'user' } } )
199+
.then( function ( stream ) {
200+
201+
video.srcObject = stream;
202+
video.play();
203+
204+
} )
205+
.catch( function ( error ) {
206+
207+
console.error( 'Unable to access the camera/webcam.', error );
208+
209+
} );
210+
211+
}
214212

215213
const transform = new THREE.Object3D();
216214

217-
renderer.setAnimationLoop( function () {
215+
function animation() {
218216

219217
if ( video.readyState >= HTMLMediaElement.HAVE_METADATA ) {
220218

@@ -241,18 +239,20 @@
241239

242240
if ( results.faceBlendshapes.length > 0 ) {
243241

244-
const faceBlendshapes = results.faceBlendshapes[ 0 ].categories;;
242+
const face = scene.getObjectByName( 'mesh_2' );
245243

246-
const object = scene.getObjectByName( 'mesh_2' );
244+
const faceBlendshapes = results.faceBlendshapes[ 0 ].categories;
247245

248246
for ( const blendshape of faceBlendshapes ) {
249247

250-
const name = blendshapesMap[ blendshape.categoryName ];
251-
const index = object.morphTargetDictionary[ name ];
248+
const categoryName = blendshape.categoryName;
249+
const score = blendshape.score;
250+
251+
const index = face.morphTargetDictionary[ blendshapesMap[ categoryName ] ];
252252

253253
if ( index !== undefined ) {
254254

255-
object.morphTargetInfluences[ index ] = blendshape.score;
255+
face.morphTargetInfluences[ index ] = score;
256256

257257
}
258258

@@ -269,9 +269,7 @@
269269

270270
controls.update();
271271

272-
stats.update();
273-
274-
} );
272+
}
275273

276274
window.addEventListener( 'resize', function () {
277275

0 commit comments

Comments
 (0)