summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2019-01-17 15:10:19 +0100
committerJules Laplace <julescarbon@gmail.com>2019-01-17 15:10:19 +0100
commitc293006ba43944ffeb4dcab17b2256f3a5491a36 (patch)
treec645c59758557715ef6abb7a93bb8d23221e8ae5
parent8dcb846682542c609a5498ed69a30a69cb1eace5 (diff)
build cloud
-rw-r--r--README.md7
-rw-r--r--site/assets/cloud/.gitignore1
-rw-r--r--site/assets/cloud/.npmignore4
-rw-r--r--site/assets/cloud/LICENSE21
-rw-r--r--site/assets/cloud/README.md109
-rw-r--r--site/assets/cloud/THREE.TextSprite.js1
-rw-r--r--site/assets/cloud/demo/script.js129
-rw-r--r--site/assets/cloud/index.html31
-rw-r--r--site/assets/cloud/package.json40
-rw-r--r--site/assets/cloud/rollup.config.js25
-rw-r--r--site/assets/cloud/src/getOptimalFontSize.js18
-rw-r--r--site/assets/cloud/src/index.js78
-rw-r--r--site/assets/css/css.css15
-rw-r--r--site/assets/js/app/face.js68
-rw-r--r--site/public/index.html30
-rw-r--r--site/templates/home.html30
16 files changed, 543 insertions, 64 deletions
diff --git a/README.md b/README.md
index 48e06b6e..0348562f 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ pip install urllib3 flask flask_sqlalchemy mysql-connector
pip install pymediainfo tqdm opencv-python imutils
pip install scikit-image python-dotenv imagehash scikit-learn colorlog
pip install celery keras tensorflow
-pip install python.app # OSX only!
+pip install python.app # OSX only! needed for matplotlib
sudo apt-get install libmysqlclient-dev
@@ -40,6 +40,8 @@ ALTER DATABASE megapixels CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
## Building the site
+The most recently built copy of the site is kept in the repo. This is generated directly from NextCloud. Be mindful that NextCloud will create extra copies of things if there are merge conflicts.
+
```
npm install
npm run build
@@ -52,9 +54,12 @@ python cli_site.py build
## Running the site
+On OSX, you must run `pythonw` to use matplotlib.
+
```
python cli_flask.py run
python `which celery` worker -A app.server.tasks --loglevel=info -E
redis-server /usr/local/etc/redis.conf
npm run watch
```
+
diff --git a/site/assets/cloud/.gitignore b/site/assets/cloud/.gitignore
new file mode 100644
index 00000000..2ccbe465
--- /dev/null
+++ b/site/assets/cloud/.gitignore
@@ -0,0 +1 @@
+/node_modules/
diff --git a/site/assets/cloud/.npmignore b/site/assets/cloud/.npmignore
new file mode 100644
index 00000000..dcaf4a28
--- /dev/null
+++ b/site/assets/cloud/.npmignore
@@ -0,0 +1,4 @@
+/demo/
+/index.html
+/rollup.config.js
+/src/
diff --git a/site/assets/cloud/LICENSE b/site/assets/cloud/LICENSE
new file mode 100644
index 00000000..edeba37c
--- /dev/null
+++ b/site/assets/cloud/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-2018 Sergej Sintschilin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/site/assets/cloud/README.md b/site/assets/cloud/README.md
new file mode 100644
index 00000000..de6e882e
--- /dev/null
+++ b/site/assets/cloud/README.md
@@ -0,0 +1,109 @@
+# THREE.TextSprite
+
+`class THREE.TextSprite extends THREE.Sprite`
+
+An instance of `TextSprite` automatically computes the optimal font size depending on the distance to the camera and the size of the renderer canvas.
+
+## demo
+
+[Try it out!](https://seregpie.github.io/THREE.TextSprite/)
+
+## dependencies
+
+- [THREE.TextTexture](https://github.com/SeregPie/THREE.TextTexture)
+
+## setup
+
+### npm
+
+```shell
+npm install three.textsprite
+```
+
+### ES module
+
+```javascript
+import TextSprite from 'three.textsprite';
+```
+
+### browser
+
+```html
+<script src="https://unpkg.com/three"></script>
+<script src="https://unpkg.com/three.texttexture"></script>
+<script src="https://unpkg.com/three.textsprite"></script>
+```
+
+The class `TextSprite` will be available under the namespace `THREE`.
+
+## members
+
+```
+.constructor({
+ material,
+ maxFontSize,
+ minFontSize,
+ redrawInterval,
+ textSize,
+ texture,
+})
+```
+
+| argument | description |
+| ---: | :--- |
+| `material` | The parameters to pass to the constructor of [`SpriteMaterial`](https://threejs.org/docs/index.html#api/materials/SpriteMaterial). |
+| `texture` | The parameters to pass to the constructor of [`TextTexture`](https://github.com/SeregPie/THREE.TextTexture). |
+
+```javascript
+let sprite = new THREE.TextSprite({
+ material: {
+ color: 0xffbbff,
+ fog: true,
+ },
+ redrawInterval: 250,
+ textSize: 10,
+ texture: {
+ text: 'Carpe Diem',
+ fontFamily: 'Arial, Helvetica, sans-serif',
+ },
+});
+scene.add(sprite);
+```
+
+---
+
+`.isTextSprite = true`
+
+Used to check whether this is an instance of `TextSprite`.
+
+You should not change this, as it is used internally for optimisation.
+
+---
+
+`.textSize = 1`
+
+The size of the text.
+
+---
+
+`.redrawInterval = 1`
+
+The minimum time that must elapse before the canvas is redrawn. If 0, the canvas is redrawn immediately whenever `TextSprite` is rendered, otherwise the redrawing is deferred.
+
+---
+
+`.minFontSize = 0`
+
+The minimum font size.
+
+---
+
+`.maxFontSize = Infinity`
+
+The maximum font size.
+
+---
+
+`.dispose()`
+
+Disposes the texture and the material.
diff --git a/site/assets/cloud/THREE.TextSprite.js b/site/assets/cloud/THREE.TextSprite.js
new file mode 100644
index 00000000..525d22cd
--- /dev/null
+++ b/site/assets/cloud/THREE.TextSprite.js
@@ -0,0 +1 @@
+(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b(require("three"),require("three.texttexture")):"function"==typeof define&&define.amd?define(["three","three.texttexture"],b):(a.THREE=a.THREE||{},a.THREE.TextSprite=b(a.THREE,a.THREE.TextTexture))})(this,function(a,b){"use strict";function c(a,b,c){var g=Math.round;if(b.domElement.width&&b.domElement.height&&a.material.map.textLines.length){var h=a.getWorldPosition(d).distanceTo(c.getWorldPosition(e));if(h){var i=a.getWorldScale(f).y*b.domElement.height/h;if(i)return g(i/a.material.map.imageHeight)}}return 0}b=b&&b.hasOwnProperty("default")?b["default"]:b;var d=new a.Vector3,e=new a.Vector3,f=new a.Vector3,g=function(d){function e(c){void 0===c&&(c={});var e=c.textSize;void 0===e&&(e=1);var f=c.redrawInterval;void 0===f&&(f=1);var g=c.minFontSize;void 0===g&&(g=0);var h=c.maxFontSize;void 0===h&&(h=1/0);var i=c.material;void 0===i&&(i={});var j=c.texture;void 0===j&&(j={}),d.call(this,new a.SpriteMaterial(Object.assign({},i,{map:new b(j)}))),this.textSize=e,this.redrawInterval=f,this.minFontSize=g,this.maxFontSize=h,this.lastRedraw=0}d&&(e.__proto__=d),e.prototype=Object.create(d&&d.prototype),e.prototype.constructor=e;var f={isTextSprite:{configurable:!0}};return f.isTextSprite.get=function(){return!0},e.prototype.onBeforeRender=function(a,b,c){this.redraw(a,c)},e.prototype.updateScale=function(){this.scale.set(this.material.map.imageAspect,1,1).multiplyScalar(this.textSize*this.material.map.imageHeight)},e.prototype.updateMatrix=function(){for(var a=[],b=arguments.length;b--;)a[b]=arguments[b];return this.updateScale(),d.prototype.updateMatrix.apply(this,a)},e.prototype.redraw=function(a,b){var c=this;this.lastRedraw+this.redrawInterval<Date.now()&&(this.redrawInterval?setTimeout(function(){c.redrawNow(a,b)},1):this.redrawNow(a,b))},e.prototype.redrawNow=function(b,d){this.updateScale(),this.material.map.autoRedraw=!0,this.material.map.fontSize=a.Math.clamp(a.Math.ceilPowerOfTwo(c(this,b,d)),this.minFontSize,this.maxFontSize),this.lastRedraw=Date.now()},e.prototype.dispose=function(){this.material.map.dispose(),this.material.dispose()},Object.defineProperties(e.prototype,f),e}(a.Sprite);return g});
diff --git a/site/assets/cloud/demo/script.js b/site/assets/cloud/demo/script.js
new file mode 100644
index 00000000..a6fc540a
--- /dev/null
+++ b/site/assets/cloud/demo/script.js
@@ -0,0 +1,129 @@
+/* eslint-disable */
+(function() {
+
+ var datasets = ["10K US Adult Faces","3D-RMA","3D Dynamic","3DPeS","4DFAB","50 People One Question","aPascal","Aberdeen","Adience","AFAD","AFEW-VA","AffectNet","AFLW","AFW","AgeDB","ALERT Airport","AM-FED","APiS1.0","AR Face","AWE Ears","B3D(AC)","BBC Pose","BPAD","BFM","BioID Face","BJUT-3D","The Bosphorus","BP4D+","BP4D-Spontanous","Brainwash","BU-3DFE","BUHMAP-DB ","CAFE","Caltech 10K Web Faces","Caltech Faces","Caltech Pedestrians","CAMEL","CAS-PEAL","Casablanca","CASIA Webface","CAVIAR4REID","CelebA","CelebFaces+","CFD","ChaLearn","ChokePoint","Cityscapes","CCP","CMDP","CMU PIE","COCO","COCO-a","COCO QA","COFW","CK","CK+","Columbia Gaze","Ongoing Complex Activities","CUHK01","CUHK02","CUHK03","CVC-01","UFI","D3DFACS","Dartmouth Children","Data61 Pedestrian","DeepFashion","DISFA","Long Distance Heterogeneous Face","Duke MTMC","EmotioNet Database","ETHZ Pedestrian","EuroCity Persons","ExpW","Face Research Lab London","FaceScrub","FaceTracer","SFC","Facebook100","Face Place","Faces94","Faces95","Faces96","FIW","FDDB","FEI","FERET","FER+","CMU FiA","300-W","Florida Inmate","FRAV2D","FRAV3D","GRIMACE","FRGC","Gallagher","Gavab","GeoFaces","Georgia Tech Face","Google Makeup","Google (private)","Graz Pedestrian","H3D","HDA+","Helen","Hi4D-ADSIP","HID","Hipsterwars","HollywoodHeads","HRT Transgender","IFAD","IFDB","IIT Dehli Ear","IJB-A","IJB-B","IJB-C","","iLIDS-VID","Images of Groups","IMDB","IMFDB","IMM Face Dataset","Immediacy","imSitu","INRIA Pedestrian","iQIYI-VID dataset ","JAFFE","Jiku Mobile Video Dataset","JPL-Interaction dataset","Karpathy Instagram","KDEF","UB KinFace","KinectFaceDB","KITTI","LAG","Large Scale Person Search","Leeds Sports Pose","Leeds Sports Pose Extended","LFW","LFW-a","LFWP","m2vts","xm2vtsdb","MAFL","MALF","Mapillary","Market 1501","Market 1203","MARS","McGill Real World","Multiple Encounter Dataset","MegaAge","MegaFace","MIFS","MIKKI dataset","MIT CBCL","CBCL","CBCLSS","MIW","MMI Facial Expression Dataset","Moments in Time","MORPH Commercial","MORPH Non-Commercial","MOT","Large MPI Facial Expression","Small MPI Facial Expression","MPIIGaze","MPII Human Pose","MR2","MRP Drone","MsCeleb","MSMT17","MUCT","MUG Faces","MULTIPIE","MTFL","News Dataset","ND-2006","MID","Novaemötions Dataset","Nude Detection","ORL","Penn Fudan","PETA","PETS 2017","PPB","PIPA","PKU","PKU-Reid","Pornography DB","Precarious","PRID","PRW","PSU","PubFig","pubfig83","Put Face","GRID","QMUL-iLIDS","QMUL-SurvFace","RaFD","RAiD","RAP","ReSEED","SAIVT SoftBio","SAMM","Sarc3D","SCface","SCUT-FBP","SCUT HEAD","SDU-VID","SED Dataset","Sheffield Face","Shinpuhkan 2014","Social Relation","SOTON HiD","SVW","STAIR Action","Stanford Drone","Buffy Stickmen","We Are Family Stickmen","Stickmen PASCAL","Stirling/ESRC 3D Face","SUN","SVS","Texas 3DFRD","TinyFace","Tiny Images","TownCenter","TUD-Brussels","TUD-Campus","TUD-Crossing","TUD-Motionparis","TUD-Multiview","TUD-Pedestrian","TUD-Stadtmitte","TVHI","ND-TWINS-2009-2010","UCCS","UCF101","UCF-CC-50","UCF Selfie","UFDD","UMB","UMD","UNBC-McMaster Pain","Urban Tribes","USED Social Event Dataset","UTKFace","V47","VADANA","CIP","VGG Face","VGG Face2","Violent Flows","VIPeR","Phrasal Recognition","VMU","VOC","VQA","WARD","WGT","WIDER","WIDER FACE","WIDER Attribute","WildTrack","YaleFaces","Yale Face Database B","Extended Yale Face Database B ","YawDD","YFCC100M","UOY 3D Face Database","YouTubeFaces","YMU","YouTube Pose","WLFDB","SAL","Semaine","Belfast naturalistic","Belfast induced","VAM-faces","MAHNOB-HCI","DEAP","AMFED","Recola","AVEC13","AVEC14","Mimicry","Meissner Caucasian and African American","Nottingham Scans","Nottingham Originals","Stirling Pain","Utrecht ECVP","Mooney","Visual Commonsense Reasoning","HUFRD Pilgrims Dataset"]
+ var getRandomText = function() {
+ return chance.pickone(datasets)
+ };
+ var getRandomFontFamily = function() {
+ return 'Helvetica, Arial, sans-serif'
+ // return chance.pickone([
+ // 'Georgia, serif',
+ // '"Palatino Linotype", "Book Antiqua", Palatino, serif',
+ // '"Times New Roman", Times, serif',
+ // 'Helvetica, Arial, sans-serif',
+ // '"Arial Black", Gadget, sans-serif',
+ // '"Comic Sans MS", cursive, sans-serif',
+ // 'Impact, Charcoal, sans-serif',
+ // '"Lucida Sans Unicode", "Lucida Grande", sans-serif',
+ // 'Tahoma, Geneva, sans-serif',
+ // '"Trebuchet MS", Helvetica, sans-serif',
+ // 'Verdana, Geneva, sans-serif',
+ // '"Courier New", Courier, monospace',
+ // '"Lucida Console", Monaco, monospace',
+ // ]);
+ };
+ var getRandomColor = function() {
+ return chance.pickone([ 0xffffff, 0xffffff, 0xffffff, 0xdddde6, 0x888896 ]) // chance.color({format: 'hex'});
+ };
+ var getRandomTextSize = function() {
+ return (1 + Math.random()) * 1/8;
+ };
+ var renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
+ renderer.setPixelRatio(devicePixelRatio);
+ renderer.setClearColor(0x000000, 0);
+ document.body.appendChild(renderer.domElement);
+ var scene = new THREE.Scene();
+ var camera = new THREE.PerspectiveCamera(75, 1, 1/128, 128);
+ camera.position.set(4, 0, 10);
+ var redrawInterval = 1;
+ var sprites = Array.from({length: datasets.length}, function(t, i) {
+ // console.log(i)
+ var sprite = new THREE.TextSprite({
+ textSize: getRandomTextSize(),
+ redrawInterval: redrawInterval,
+ material: {
+ color: getRandomColor(),
+ },
+ texture: {
+ text: datasets[i],
+ fontFamily: getRandomFontFamily(),
+ },
+ });
+ sprite.position
+ .setX(Math.random())
+ .setY(Math.random())
+ .setZ(Math.random())
+ .subScalar(1/2)
+ .setLength(1 + Math.random())
+ .multiplyScalar(6);
+ scene.add(sprite);
+ return sprite;
+ });
+ var controls = new THREE.OrbitControls(camera, renderer.domElement);
+ controls.maxDistance = camera.far/2;
+ controls.enableDamping = true;
+ controls.dampingFactor = 1/8;
+ controls.rotateSpeed = 1/4;
+ controls.zoomSpeed = 1;
+ controls.keyPanSpeed = 1/2;
+ var renderScene = function() {
+ renderer.setSize(document.body.offsetWidth, document.body.offsetHeight);
+ camera.aspect = renderer.domElement.width / renderer.domElement.height;
+ camera.updateProjectionMatrix();
+ // controls.update();
+ camera.position.z += -0.0025
+ camera.rotation.y += 0.00001
+ renderer.render(scene, camera);
+ };
+ window.addEventListener('resize', renderScene, false);
+ var startSceneRenderer = function() {
+ requestAnimationFrame(function() {
+ setTimeout(startSceneRenderer, 1000/60);
+ });
+ renderScene();
+ };
+ startSceneRenderer();
+ // var gui = new dat.GUI();
+ // (function() {
+ // var guiFolder = gui.addFolder('texture');
+ // guiFolder.add({
+ // text: function() {
+ // sprites.forEach(function(sprite) {
+ // sprite.material.map.text = getRandomText();
+ // });
+ // },
+ // }, 'text');
+ // guiFolder.add({
+ // fontFamily: function() {
+ // sprites.forEach(function(sprite) {
+ // sprite.material.map.fontFamily = getRandomFontFamily();
+ // });
+ // },
+ // }, 'fontFamily');
+ // guiFolder.open();
+ // })();
+ // (function() {
+ // var guiFolder = gui.addFolder('sprite');
+ // guiFolder.add({
+ // textSize: function() {
+ // sprites.forEach(function(sprite) {
+ // sprite.textSize = getRandomTextSize();
+ // });
+ // },
+ // }, 'textSize');
+ // guiFolder.add(Object.defineProperty({}, 'redrawInterval', {
+ // get: function() {
+ // return redrawInterval;
+ // },
+ // set: function(value) {
+ // redrawInterval = value;
+ // sprites.forEach(function(sprite) {
+ // sprite.redrawInterval = redrawInterval;
+ // });
+ // },
+ // }), 'redrawInterval', 0, 2000, 1);
+ // guiFolder.open();
+ // })();
+
+})();
diff --git a/site/assets/cloud/index.html b/site/assets/cloud/index.html
new file mode 100644
index 00000000..b97842f6
--- /dev/null
+++ b/site/assets/cloud/index.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html style="height: 100%;">
+ <head>
+ <meta charset="utf-8"/>
+ <meta
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
+ name="viewport"
+ />
+ <title>THREE.TextSprite</title>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.0.0/polyfill.min.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
+ <script src="https://unpkg.com/three.texttexture@18.10.24"></script>
+ <script src="THREE.TextSprite.js"></script>
+ <link
+ href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css"
+ rel="stylesheet"
+ />
+ <script src="https://cdn.rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/chance/1.0.16/chance.min.js"></script>
+ </head>
+ <body
+ style="
+ background: linear-gradient(#333,#001);
+ font-family: sans-serif;
+ height: 100%;
+ overflow: hidden;
+ "
+ >
+ <script src="demo/script.js"></script>
+ </body>
+</html>
diff --git a/site/assets/cloud/package.json b/site/assets/cloud/package.json
new file mode 100644
index 00000000..f7556104
--- /dev/null
+++ b/site/assets/cloud/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "three.textsprite",
+ "version": "18.10.24",
+ "description": "Automatically computes the optimal font size depending on the distance to the camera and the size of the renderer canvas.",
+ "keywords": [
+ "3d",
+ "canvas",
+ "class",
+ "font",
+ "group",
+ "object",
+ "plugin",
+ "resolution",
+ "scale",
+ "size",
+ "text",
+ "texture",
+ "three"
+ ],
+ "license": "MIT",
+ "author": "Sergej Sintschilin <seregpie@gmail.com>",
+ "main": "THREE.TextSprite.js",
+ "repository": "https://github.com/SeregPie/THREE.TextSprite.git",
+ "scripts": {
+ "build": "rollup -c",
+ "dev": "rollup -c -w",
+ "prepublishOnly": "npm run build"
+ },
+ "dependencies": {
+ "three.texttexture": "^18.10.24"
+ },
+ "devDependencies": {
+ "rollup": "^0.66.6",
+ "rollup-plugin-babel-minify": "^6.1.1",
+ "rollup-plugin-buble": "^0.19.4"
+ },
+ "peerDependencies": {
+ "three": "^0.97.0"
+ }
+}
diff --git a/site/assets/cloud/rollup.config.js b/site/assets/cloud/rollup.config.js
new file mode 100644
index 00000000..57415169
--- /dev/null
+++ b/site/assets/cloud/rollup.config.js
@@ -0,0 +1,25 @@
+import buble from 'rollup-plugin-buble';
+import minify from 'rollup-plugin-babel-minify';
+import path from 'path';
+
+import {main} from './package.json';
+
+let globals = {
+ 'three': 'THREE',
+ 'three.texttexture': 'THREE.TextTexture',
+};
+
+export default {
+ input: 'src/index.js',
+ external: Object.keys(globals),
+ output: {
+ file: main,
+ format: 'umd',
+ name: path.basename(main, path.extname(main)),
+ globals,
+ },
+ plugins: [
+ buble({objectAssign: 'Object.assign'}),
+ minify({comments: false}),
+ ],
+};
diff --git a/site/assets/cloud/src/getOptimalFontSize.js b/site/assets/cloud/src/getOptimalFontSize.js
new file mode 100644
index 00000000..02787516
--- /dev/null
+++ b/site/assets/cloud/src/getOptimalFontSize.js
@@ -0,0 +1,18 @@
+import {Vector3} from 'three';
+
+let objectWorldPosition = new Vector3();
+let cameraWorldPosition = new Vector3();
+let objectWorldScale = new Vector3();
+
+export default function(object, renderer, camera) {
+ if (renderer.domElement.width && renderer.domElement.height && object.material.map.textLines.length) {
+ let distance = object.getWorldPosition(objectWorldPosition).distanceTo(camera.getWorldPosition(cameraWorldPosition));
+ if (distance) {
+ let heightInPixels = object.getWorldScale(objectWorldScale).y * renderer.domElement.height / distance;
+ if (heightInPixels) {
+ return Math.round(heightInPixels / object.material.map.imageHeight);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/site/assets/cloud/src/index.js b/site/assets/cloud/src/index.js
new file mode 100644
index 00000000..270891d5
--- /dev/null
+++ b/site/assets/cloud/src/index.js
@@ -0,0 +1,78 @@
+import {
+ Math as THREE_Math,
+ Sprite,
+ SpriteMaterial,
+} from 'three';
+import TextTexture from 'three.texttexture';
+
+import getOptimalFontSize from './getOptimalFontSize';
+
+export default class extends Sprite {
+ constructor({
+ textSize = 1,
+ redrawInterval = 1,
+ minFontSize = 0,
+ maxFontSize = Infinity,
+ material = {},
+ texture = {},
+ } = {}) {
+ super(new SpriteMaterial({
+ ...material,
+ map: new TextTexture(texture),
+ }));
+ this.textSize = textSize;
+ this.redrawInterval = redrawInterval;
+ this.minFontSize = minFontSize;
+ this.maxFontSize = maxFontSize;
+ this.lastRedraw = 0;
+ }
+
+ get isTextSprite() {
+ return true;
+ }
+
+ onBeforeRender(renderer, scene, camera) {
+ this.redraw(renderer, camera);
+ }
+
+ updateScale() {
+ this.scale
+ .set(this.material.map.imageAspect, 1, 1)
+ .multiplyScalar(this.textSize * this.material.map.imageHeight);
+ }
+
+ updateMatrix(...args) {
+ this.updateScale();
+ return super.updateMatrix(...args);
+ }
+
+ redraw(renderer, camera) {
+ if (this.lastRedraw + this.redrawInterval < Date.now()) {
+ if (this.redrawInterval) {
+ setTimeout(() => {
+ this.redrawNow(renderer, camera);
+ }, 1);
+ } else {
+ this.redrawNow(renderer, camera);
+ }
+ }
+ }
+
+ redrawNow(renderer, camera) {
+ this.updateScale();
+ this.material.map.autoRedraw = true;
+ this.material.map.fontSize = THREE_Math.clamp(
+ THREE_Math.ceilPowerOfTwo(
+ getOptimalFontSize(this, renderer, camera)
+ ),
+ this.minFontSize,
+ this.maxFontSize,
+ );
+ this.lastRedraw = Date.now();
+ }
+
+ dispose() {
+ this.material.map.dispose();
+ this.material.dispose();
+ }
+}
diff --git a/site/assets/css/css.css b/site/assets/css/css.css
index 8239cfc7..18959c12 100644
--- a/site/assets/css/css.css
+++ b/site/assets/css/css.css
@@ -376,11 +376,17 @@ section.fullwidth .image {
/* home page */
.hero {
- position: relative;
width: 100%;
- max-width: 1200px;
+ background: black;
+ background: linear-gradient(#000,#222);
height: 50vw;
max-height: 70vh;
+}
+.hero .inner {
+ position: relative;
+ width: 100%;
+ max-width: 1200px;
+ height: 100%;
display: flex;
align-items: center;
margin: 0 auto;
@@ -393,7 +399,7 @@ section.fullwidth .image {
max-height: 70vh;
top: 0;
right: 0;
- z-index: -1;
+ z-index: 0;
text-align: center;
}
.currentFace {
@@ -451,6 +457,9 @@ section.fullwidth .image {
.desktop .intro .under a:hover {
color: #fff;
}
+.dataset-intro h2 {
+ margin-top: 40px;
+}
/* intro - list of datasets */
diff --git a/site/assets/js/app/face.js b/site/assets/js/app/face.js
index f3f1f2bf..1818e9aa 100644
--- a/site/assets/js/app/face.js
+++ b/site/assets/js/app/face.js
@@ -1,4 +1,5 @@
-var face = (function(){
+/* eslint-disable */
+var faceInit = function () {
var container = document.querySelector("#face_container")
var camera, controls, scene, renderer
var mouse = new THREE.Vector2(0.5, 0.5)
@@ -16,6 +17,7 @@ var face = (function(){
return a
})()
var last_t = 0, start_t = 0
+ var bgColor = 0x000000 // 0x191919
var colors = [
0xff3333,
0xff8833,
@@ -32,32 +34,33 @@ var face = (function(){
function init() {
fetch("/assets/data/3dlm_0_10.json")
- .then(req => req.json())
- .then(data => {
- face_names = Object.keys(data)
- faces = face_names.map(name => recenter(data[name]))
- setup()
- build(faces[0])
- updateFace(faces[0])
- setCurrentFace(face_names[0])
- swapTo = faces[0]
- animate()
- })
+ .then(req => req.json())
+ .then(data => {
+ face_names = Object.keys(data)
+ faces = face_names.map(name => recenter(data[name]))
+ setup()
+ build(faces[0])
+ updateFace(faces[0])
+ setCurrentFace(face_names[0])
+ swapTo = faces[0]
+ animate()
+ })
}
function setup() {
- var w = window.innerWidth / 2
+ var w = window.innerWidth * 2/3
var h = Math.min(window.innerWidth / 2, window.innerHeight * 0.7)
camera = new THREE.PerspectiveCamera(70, w/h, 1, 10000)
camera.position.x = 0
camera.position.y = 0
- camera.position.z = 250
+ camera.position.z = 200
scene = new THREE.Scene()
- scene.background = new THREE.Color(0x191919)
+ // scene.background = new THREE.Color(bgColor)
- renderer = new THREE.WebGLRenderer({ antialias: true })
+ renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(w, h)
+ renderer.setClearColor(0x000000, 0);
container.appendChild(renderer.domElement)
document.body.addEventListener('mousemove', onMouseMove)
// renderer.domElement.addEventListener('mousedown', swap)
@@ -75,7 +78,7 @@ var face = (function(){
// console.log("done")
// }
// })
- setInterval(swap, 5000)
+ swap()
}
function build(points) {
var matrix = new THREE.Matrix4()
@@ -125,27 +128,28 @@ var face = (function(){
return (b-a) * n + a
}
function swap(){
- if (swapping) return
- start_t = last_t
- swapping = true
swap_count = (swap_count + 1) % faces.length
- swapFrom = swapTo
+ swapFrom = swapTo || faces[0]
swapTo = faces[swap_count]
setCurrentFace(face_names[swap_count])
+ oktween.add({
+ from: { n: 0 },
+ to: { n: 1 },
+ duration: 1000,
+ easing: oktween.easing.quad_in_out,
+ update: function(obj){
+ lerpPoints(obj.n, swapFrom, swapTo, faceBuffer)
+ updateFace(faceBuffer)
+ },
+ finished: function(){
+ setTimeout(swap, 2000)
+ }
+ })
}
function setCurrentFace(name) {
name = name.replace('.png', '').split('_').filter(s => !s.match(/\d+/)).join(' ')
currentFace.innerHTML = name
}
- function update_swap(t){
- var n = (t - start_t) / SWAP_TIME
- if (n > 1) {
- swapping = false
- n = 1
- }
- lerpPoints(n, swapFrom, swapTo, faceBuffer)
- updateFace(faceBuffer)
- }
function updateFace(points) {
updateCubeGeometry(points)
updateLineGeometry(points)
@@ -214,7 +218,6 @@ var face = (function(){
}
function animate(t) {
requestAnimationFrame(animate)
- if (swapping) update_swap(t)
renderer.render(scene, camera)
// scene.rotation.y += 0.01 * Math.PI
mouseTarget.x += (mouse.x - mouseTarget.x) * 0.1
@@ -224,4 +227,5 @@ var face = (function(){
// scene.rotation.y += 0.01
last_t = t
}
-})()
+}
+faceInit() \ No newline at end of file
diff --git a/site/public/index.html b/site/public/index.html
index b322b093..a9f16f30 100644
--- a/site/public/index.html
+++ b/site/public/index.html
@@ -28,27 +28,29 @@
<div class="content">
<div class='hero'>
- <div id="face_container">
- <div class='currentFace'></div>
- </div>
- <div class='intro'>
- <div class='headline'>
- MegaPixels is an art project that explores the dark side of face recognition datasets and the future of computer vision.
+ <div class='inner'>
+ <div id="face_container">
+ <div class='currentFace'></div>
</div>
+ <div class='intro'>
+ <div class='headline'>
+ MegaPixels is an art project that explores the dark side of face recognition datasets and the future of computer vision.
+ </div>
- <div class='buttons'>
- <a href="/datasets/"><button class='important'>Find Your Face</button></a>
- <a href="/analyze/"><button class='normal'>Analyze Your Face</button></a>
- </div>
+ <div class='buttons'>
+ <a href="/datasets/"><button class='important'>Find Your Face</button></a>
+ <a href="/analyze/"><button class='normal'>Analyze Your Face</button></a>
+ </div>
- <div class='under'>
- Made by Adam Harvey in collaboration with Jules Laplace, and in partnership with Mozilla.<br/>
- <a href='/about/'>Read more about MegaPixels</a>
+ <div class='under'>
+ Made by Adam Harvey in collaboration with Jules Laplace, and in partnership with Mozilla.<br/>
+ <a href='/about/'>Read more about MegaPixels</a>
+ </div>
</div>
</div>
</div>
- <section class='wide'>
+ <section class='wide dataset-intro'>
<h2>Facial Recognition Datasets</h2>
<div class='right-sidebar'>
<h4>SUMMARY</h4>
diff --git a/site/templates/home.html b/site/templates/home.html
index fc821731..03a61af2 100644
--- a/site/templates/home.html
+++ b/site/templates/home.html
@@ -2,27 +2,29 @@
{% block content %}
<div class='hero'>
- <div id="face_container">
- <div class='currentFace'></div>
- </div>
- <div class='intro'>
- <div class='headline'>
- MegaPixels is an art project that explores the dark side of face recognition datasets and the future of computer vision.
+ <div class='inner'>
+ <div id="face_container">
+ <div class='currentFace'></div>
</div>
+ <div class='intro'>
+ <div class='headline'>
+ MegaPixels is an art project that explores the dark side of face recognition datasets and the future of computer vision.
+ </div>
- <div class='buttons'>
- <a href="/datasets/"><button class='important'>Find Your Face</button></a>
- <a href="/analyze/"><button class='normal'>Analyze Your Face</button></a>
- </div>
+ <div class='buttons'>
+ <a href="/datasets/"><button class='important'>Find Your Face</button></a>
+ <a href="/analyze/"><button class='normal'>Analyze Your Face</button></a>
+ </div>
- <div class='under'>
- Made by Adam Harvey in collaboration with Jules Laplace, and in partnership with Mozilla.<br/>
- <a href='/about/'>Read more about MegaPixels</a>
+ <div class='under'>
+ Made by Adam Harvey in collaboration with Jules Laplace, and in partnership with Mozilla.<br/>
+ <a href='/about/'>Read more about MegaPixels</a>
+ </div>
</div>
</div>
</div>
- <section class='wide'>
+ <section class='wide dataset-intro'>
<h2>Facial Recognition Datasets</h2>
<div class='right-sidebar'>
<h4>SUMMARY</h4>