Skip to content

Instantly share code, notes, and snippets.

@cpascal-gr
Forked from AlexisTheLarge/angle_capture.user.js
Created March 27, 2018 19:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cpascal-gr/5c5dec6c5ae545a9b4d1f2a2f8707633 to your computer and use it in GitHub Desktop.
Save cpascal-gr/5c5dec6c5ae545a9b4d1f2a2f8707633 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Face Angle Capture
// @namespace http://github.com/AlexisTheLarge
// @version 1.3
// @description Capture angles from 3D face reconstruction automatically
// @author Alexis_TheLarge
// @match http://cvl-demos.cs.nott.ac.uk/vrn/view.php*
// @grant GM_addStyle
// @grant GM.addStyle
// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @require https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js
// ==/UserScript==
GM.addStyle("button.button.purple {background-color: #E80C7A !important; width: 100% !important; cursor:pointer; }");
GM.addStyle("#ProgressOverlay {color:white; width: 462px; height:462px; background-color: rgba(0,0,0,0.4); position: absolute; top: 0; left: 0; padding-top:40%; padding-left:10%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;");
GM.addStyle("#myProgress { width: 80%; background-color: white;} #myBar { width: 1%; height: 30px; background-color: #E80C7A; }");
var progress = 1;
var step = 100/130;
var progressbar = null;
var progress_container = null;
(function() {
'use strict';
window.addEventListener('load', function() {
var viewer_frame = document.getElementById("viewer_frame");
progress_container = document.createElement('div');
progress_container.innerHTML = '<p>Capturing Angles...</p><div id="myProgress"><div id="myBar"></div></div>';
progress_container.setAttribute ('id', 'ProgressOverlay');
progress_container.style.display = 'none';
viewer_frame.appendChild(progress_container);
var viewer_controls = document.getElementById("viewer_controls");
var hr = viewer_controls.getElementsByTagName("hr")[0];
var zNode = document.createElement('p');
zNode.innerHTML = '<button id="generateAnglesButton" class="button purple" type="button">Capture angles</button>';
viewer_controls.insertBefore(zNode, hr);
document.getElementById ("generateAnglesButton").addEventListener (
"click", ButtonClickAction, false
);
}, false);
})();
function ButtonClickAction (zEvent) {
generate_angles();
}
/* jshint ignore:start */
async function generate_angles() {
if (typeof objname === 'undefined') {
var objname = unsafeWindow.objname;
}
objpath = "queue/obj/" + objname + ".obj";
jpgpath = "queue/obj/" + objname + ".jpg";
progressbar = document.getElementById("myBar");
progress_container.style.display = 'block';
var zip = new JSZip();
await generate(zip, 'a_', function(){});
await generate(zip, 'b_', function(face, plane, pivot, scene) {
var axis = new THREE.Vector3( 1, 0, 0 ).normalize();
rotate(face, plane, pivot, scene, axis, ((Math.PI*0.5)/5));
});
await generate(zip, 'ba_', function(face, plane, pivot, scene) {
var axis_y = new THREE.Vector3( 1, 0, 0 ).normalize();
var axis_z = new THREE.Vector3( 0, 0, 1 ).normalize();
rotate(face, plane, pivot, scene, axis_y, ((Math.PI*0.5)/5));
rotate(face, plane, pivot, scene, axis_z, ((Math.PI*0.5)/7));
});
await generate(zip, 'bb_', function(face, plane, pivot, scene) {
var axis_y = new THREE.Vector3( 1, 0, 0 ).normalize();
var axis_z = new THREE.Vector3( 0, 0, 1 ).normalize();
rotate(face, plane, pivot, scene, axis_y, ((Math.PI*0.5)/5));
rotate(face, plane, pivot, scene, axis_z, -((Math.PI*0.5)/7));
});
await generate(zip, 'c_', function(face, plane, pivot, scene) {
var axis = new THREE.Vector3( 1, 0, 0 ).normalize();
rotate(face, plane, pivot, scene, axis, ((Math.PI*0.5)/2));
});
await generate(zip, 'ca_', function(face, plane, pivot, scene) {
var axis_y = new THREE.Vector3( 1, 0, 0 ).normalize();
var axis_z = new THREE.Vector3( 0, 0, 1 ).normalize();
rotate(face, plane, pivot, scene, axis_y, ((Math.PI*0.5)/2));
rotate(face, plane, pivot, scene, axis_z, ((Math.PI*0.5)/5));
});
await generate(zip, 'cb_', function(face, plane, pivot, scene) {
var axis_y = new THREE.Vector3( 1, 0, 0 ).normalize();
var axis_z = new THREE.Vector3( 0, 0, 1 ).normalize();
rotate(face, plane, pivot, scene, axis_y, ((Math.PI*0.5)/2));
rotate(face, plane, pivot, scene, axis_z, -((Math.PI*0.5)/5));
});
await generate(zip, 'd_', function(face, plane, pivot, scene) {
var axis = new THREE.Vector3( 1, 0, 0 ).normalize();
rotate(face, plane, pivot, scene, axis, -((Math.PI*0.5)/5));
});
await generate(zip, 'da_', function(face, plane, pivot, scene) {
var axis_y = new THREE.Vector3( 1, 0, 0 ).normalize();
var axis_z = new THREE.Vector3( 0, 0, 1 ).normalize();
rotate(face, plane, pivot, scene, axis_y, -((Math.PI*0.5)/5));
rotate(face, plane, pivot, scene, axis_z, ((Math.PI*0.5)/7));
});
await generate(zip, 'db_', function(face, plane, pivot, scene) {
var axis_y = new THREE.Vector3( 1, 0, 0 ).normalize();
var axis_z = new THREE.Vector3( 0, 0, 1 ).normalize();
rotate(face, plane, pivot, scene, axis_y, -((Math.PI*0.5)/5));
rotate(face, plane, pivot, scene, axis_z, -((Math.PI*0.5)/7));
});
await generate(zip, 'e_', function(face, plane, pivot, scene) {
var axis = new THREE.Vector3( 1, 0, 0 ).normalize();
rotate(face, plane, pivot, scene, axis, -((Math.PI*0.5)/2));
});
await generate(zip, 'ea_', function(face, plane, pivot, scene) {
var axis_y = new THREE.Vector3( 1, 0, 0 ).normalize();
var axis_z = new THREE.Vector3( 0, 0, 1 ).normalize();
rotate(face, plane, pivot, scene, axis_y, -((Math.PI*0.5)/2));
rotate(face, plane, pivot, scene, axis_z, ((Math.PI*0.5)/5));
});
await generate(zip, 'eb_', function(face, plane, pivot, scene) {
var axis_y = new THREE.Vector3( 1, 0, 0 ).normalize();
var axis_z = new THREE.Vector3( 0, 0, 1 ).normalize();
rotate(face, plane, pivot, scene, axis_y, -((Math.PI*0.5)/2));
rotate(face, plane, pivot, scene, axis_z, -((Math.PI*0.5)/5));
});
/*jshint ignore:end */
zip.generateAsync({type:"blob"})
.then(function(content) {
// Force down of the Zip file
saveAs(content, "face_angles.zip");
progress_container.style.display = 'none';
progress = 1;
progressbar.style.width = progress + '%';
location.reload();
});
function generate(zip, prefix, pretransform) {
camera = new THREE.OrthographicCamera(-96, 96, -96, 96, 1, 1000);
camera.up.set( 0, 1, 0 );
camera.position.x = 80;
camera.position.y = 0;
camera.position.z = 100;
camera.zoom = 1;
camera.updateProjectionMatrix();
scene = new THREE.Scene();
scene.position.z = 0;
scene.position.y = 0;
var geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
var material_p = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
var mesh = new THREE.Mesh( geometry, material_p );
mesh.position.y = -96;
mesh.position.x = -96;
mesh.position.z = -30;
var pivot = new THREE.Object3D();
pivot.add( mesh );
scene.add( pivot );
var manager = new THREE.LoadingManager();
var material = new THREE.MeshBasicMaterial({
map : THREE.ImageUtils.loadTexture(jpgpath),
});
// plane
plane = new THREE.Mesh(new THREE.PlaneGeometry(192, 192), material);
plane.material.side = THREE.DoubleSide;
plane.scale.y = -1;
if (document.getElementById('checkBackground').checked) {
scene.add(plane);
}
face = null;
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setPixelRatio( 1 );
renderer.setSize( 320,320 );
return new Promise((resolve, reject) => {
var loader = new THREE.OBJVertexColorLoader(manager);
loader.load(objpath, function (object) {
object.children[0].material.side = THREE.DoubleSide;
object.translateX(-96);
object.translateY(-96);
object.translateZ(-30);
scene.add(object);
face = object;
render();
pretransform(face, plane, pivot, scene);
for (var i = 0; i < 10 ; i++) {
var axis = new THREE.Vector3( 0, 1, 0 ).normalize();
rotate(face, plane, pivot, scene, axis, ((Math.PI*0.5)/10));
imgData = renderer.domElement.toDataURL("image/jpeg").split(',')[1];
zip.file(prefix+i+".jpg", imgData, {base64: true});
progress += step;
progressbar.style.width = progress + '%';
}
resolve(true);
}, function() {}, function () {});
});
}
function rotate(face, plane, pivot, scene, axis, angle) {
pivot_rotate(face, scene, pivot, angle, axis);
pivot_rotate(plane, scene, pivot, angle, axis);
render();
}
function render() {
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
function pivot_rotate(object, scene, pivot, angle, axis){
pivot_attach(object, scene, pivot);
pivot.rotateOnAxis(axis,angle);
pivot_detach(object, scene, pivot);
}
function pivot_attach(object, scene, pivot) {
pivot.updateMatrixWorld();
THREE.SceneUtils.attach( object, scene, pivot );
}
function pivot_detach(object, scene, pivot) {
pivot.updateMatrixWorld();
object.updateMatrixWorld(); // if not done by the renderer
THREE.SceneUtils.detach( object, pivot, scene );
pivot.rotation.set( 0, 0, 0 );
}
}
THREE.OBJVertexColorLoader = function (manager) {
this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
this.materials = null;
};
THREE.OBJVertexColorLoader.prototype = {
constructor: THREE.OBJVertexColorLoader,
load: function (url, onLoad, onProgress, onError) {
var scope = this;
var loader = new THREE.XHRLoader(scope.manager);
loader.setPath(this.path);
loader.load(url, function (text) {
onLoad(scope.parse(text));
}, onProgress, onError);
},
setPath: function (value) {
this.path = value;
},
parse: function (text) {
var container = new THREE.Group();
var geometry = new THREE.Geometry();
var vertices = [];
var vertexColors = [];
var faces = [];
// v float float float float float float (vertex with rgb)
var vertex_colour_pattern = /^v\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/;
// f vertex vertex vertex ...
var face_pattern1 = /^f\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)(?:\s+(-?\d+))?/;
var lines = text.split('\n');
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
line = line.trim();
var result;
if (line.length === 0 || line.charAt(0) === '#') {
continue;
} else if ((result = vertex_colour_pattern.exec(line)) !== null) {
vertices.push(
new THREE.Vector3(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]))
);
vertexColors.push(new THREE.Color(parseFloat(result[4]), parseFloat(result[5]), parseFloat(result[6])));
} else if ((result = face_pattern1.exec(line)) !== null) {
faces.push(new THREE.Face3(result[1] - 1, result[2] - 1, result[3] - 1));
}
}
for (var i = 0; i < vertices.length; i++) {
geometry.vertices.push(vertices[i]);
}
for (var i = 0; i < faces.length; i++) {
faces[i].vertexColors[0] = vertexColors[faces[i].a];
faces[i].vertexColors[1] = vertexColors[faces[i].b];
faces[i].vertexColors[2] = vertexColors[faces[i].c];
geometry.faces.push(faces[i]);
}
var material = new THREE.MeshBasicMaterial({ vertexColors: THREE.VertexColors });
var mesh = new THREE.Mesh(geometry, material);
container.add(mesh);
return container;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment