Last active
August 24, 2019 19:20
-
-
Save AlexisTheLarge/d0f8602c030733ccbafa9d6e8fd50666 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==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; | |
} | |
}; |
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
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*