Skip to content

Instantly share code, notes, and snippets.

@AlexisTheLarge
Last active August 24, 2019 19:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save AlexisTheLarge/d0f8602c030733ccbafa9d6e8fd50666 to your computer and use it in GitHub Desktop.
Save AlexisTheLarge/d0f8602c030733ccbafa9d6e8fd50666 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;
}
};
@tfis2
Copy link

tfis2 commented Jul 11, 2019

Seems the scripts doesen't work anymore with firefox?

@RRP777
Copy link

RRP777 commented Jul 17, 2019

Seems the scripts doesen't work anymore with firefox?

Yeah it recently broke with both Firefox and Chrome. I think maybe an update to grease/tamper monkey broke it. I have tried contacting the author but he hasn't replied. Hopefully it gets updated but I am looking for someone to fix it as the errors are listed if you open up the script, I just don't have the ability to fix it myself. If I get any updates I'll let you know.

@Virtike
Copy link

Virtike commented Aug 18, 2019

Yeah it recently broke with both Firefox and Chrome.

Working for me currently, though it seems the script is only matching HTTP and not HTTPS. Add the following at the top of the script under the HTTP entry & it will match HTTPS too:

// @match https://cvl-demos.cs.nott.ac.uk/vrn/view.php*

@honkymchonkerston
Copy link

honkymchonkerston commented Aug 24, 2019

@Virtike

Oh wow, I feel like an idiot. Thanks for pointing that out man, works like a charm now.

Sincerely appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment