UNPKG

@derschmale/threejs-googly-eyes

Version:
111 lines (106 loc) 4.8 kB
var GooglyEyes = (function (three) { 'use strict'; const v = new three.Vector3(); class EyePhysics { constructor(target, eyeRadius, irisRadius) { this._target = target; this._eyeRadius = eyeRadius; this._irisRadius = irisRadius; this._worldPos = target.getWorldPosition(new three.Vector3()); this._oldPos = this._worldPos.clone(); } update(dt, gravity, friction) { const eye = this._target.parent; const p = this._worldPos; v.subVectors(p, this._oldPos); this._oldPos.copy(p); v.y -= gravity * dt; v.multiplyScalar(1.0 - friction); p.add(v); eye.worldToLocal(p); // clamp p to local plane p.z = 0.0; const dist = Math.sqrt(p.x * p.x + p.y * p.y); const maxDist = this._eyeRadius - this._irisRadius; // clamp to own distance if (dist > maxDist) p.multiplyScalar(maxDist / dist); this._target.position.copy(p); eye.localToWorld(p); } } class GooglyEyes extends three.Group { constructor(eyeRadius = 0.02, eyeSpacing = 0.05, irisRadius = undefined, inwardRotation = 0.1, materialType) { super(); this._gravity = 0.981; this._friction = 0.01; materialType = materialType || three.MeshStandardMaterial; irisRadius = irisRadius || eyeRadius * .5; const whiteGeom = new three.SphereBufferGeometry(eyeRadius, 6, 12, Math.PI, Math.PI * 2); const blackGeom = new three.SphereBufferGeometry(irisRadius, 6, 12); const transGeom = new three.SphereBufferGeometry(eyeRadius, 6, 12, 0, Math.PI); whiteGeom.scale(1, 1, -0.05); blackGeom.scale(1, 1, 0.1); transGeom.scale(1, 1, 0.25); whiteGeom.computeVertexNormals(); blackGeom.computeVertexNormals(); transGeom.computeVertexNormals(); this._eyeWhiteMaterial = new materialType({ color: 0xffffff, roughness: 0.3 }); this._eyeBlackMaterial = new materialType({ color: 0x050505, roughness: 0.2 }); this._transparentMaterial = new materialType({ color: 0x000000, transparent: true, blending: three.AdditiveBlending, roughness: 0.01 }); // this._transparentMaterial = new materialType({ color: 0x000000 }); this._whiteLeft = new three.Mesh(whiteGeom, this._eyeWhiteMaterial); this._whiteRight = new three.Mesh(whiteGeom, this._eyeWhiteMaterial); this._whiteLeft.position.x = -eyeSpacing * .5; this._whiteRight.position.x = eyeSpacing * .5; this._whiteLeft.rotation.y = inwardRotation; this._whiteRight.rotation.y = -inwardRotation; this.add(this._whiteLeft); this.add(this._whiteRight); this._irisLeft = new three.Mesh(blackGeom, this._eyeBlackMaterial); this._irisRight = new three.Mesh(blackGeom, this._eyeBlackMaterial); this._whiteLeft.add(this._irisLeft); this._whiteRight.add(this._irisRight); this._transLeft = new three.Mesh(transGeom, this._transparentMaterial); this._transRight = new three.Mesh(transGeom, this._transparentMaterial); this._whiteLeft.add(this._transLeft); this._whiteRight.add(this._transRight); this._left = new EyePhysics(this._irisLeft, eyeRadius, irisRadius); this._right = new EyePhysics(this._irisRight, eyeRadius, irisRadius); } get eyeWhiteMaterial() { return this._eyeWhiteMaterial; } set eyeWhiteMaterial(value) { this._eyeWhiteMaterial = value; this._whiteLeft.material = value; this._whiteRight.material = value; } get eyeBlackMaterial() { return this._eyeBlackMaterial; } get transparentMaterial() { return this._transparentMaterial; } set transparentMaterial(value) { this._transparentMaterial = value; } get gravity() { return this._gravity; } set gravity(value) { this._gravity = value; } get friction() { return this._friction; } set friction(value) { this._friction = value; } update(dt) { this._left.update(dt, this._gravity, this._friction); this._right.update(dt, this._gravity, this._friction); } } return GooglyEyes; }(THREE));