Permalink
Browse files

updated thingiview to Iso as default camera view; added ability to pa…

…rse binary STLs
  • Loading branch information...
1 parent dbc464f commit d08bb54dca80fed0a021dd0c910944d7018ad82e @garyhodgson committed Oct 2, 2012
View
@@ -122,7 +122,8 @@ <h1 id="title">{{ site.githubiverse.title }}<small> by {{ site.githubiverse.auth
<script src="js/lightbox/lightbox.min.js"></script>
<script src="js/thingiview/Three.js"></script>
<script src="js/thingiview/plane.js"></script>
- <script src="js/thingiview/thingiview.min.js"></script>
+ <script src="js/thingiview/Base64Binary.js"></script>
+ <script src="js/thingiview/thingiview.js"></script>
<script src="js/underscore/underscore.min.js"></script>
<script src="js/github/gh3.min.js"></script>
@@ -210,6 +211,7 @@ <h1 id="title">{{ site.githubiverse.title }}<small> by {{ site.githubiverse.auth
});
}
+
function addSTLFile(content,dirname){
if (! /\.stl$/i.test(content.name)) {
return
@@ -233,7 +235,15 @@ <h1 id="title">{{ site.githubiverse.title }}<small> by {{ site.githubiverse.auth
githubFile.fetchContent(function (err, res) {
if(err) { throw "Error retrieving github file contents." }
- thingiview.loadSTLString(githubFile.getRawContent());
+ var stlString = githubFile.getRawContent();
+
+ if (stlString.match(/^solid/)){
+ thingiview.loadSTLString(stlString);
+ } else {
+ var uintArray = Base64Binary.decode(githubFile.content);
+ thingiview.loadSTLBinary(String.fromCharCode.apply(null, new Uint16Array(uintArray)));
+ }
+
});
}
@@ -0,0 +1,91 @@
+/*
+Copyright (c) 2011, Daniel Guerrero
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Daniel Guerrero nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL DANIEL GUERRERO BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Uses the new array typed in javascript to binary base64 encode/decode
+ * at the moment just decodes a binary base64 encoded
+ * into either an ArrayBuffer (decodeArrayBuffer)
+ * or into an Uint8Array (decode)
+ *
+ * References:
+ * https://developer.mozilla.org/en/JavaScript_typed_arrays/ArrayBuffer
+ * https://developer.mozilla.org/en/JavaScript_typed_arrays/Uint8Array
+ */
+
+var Base64Binary = {
+ _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+
+ /* will return a Uint8Array type */
+ decodeArrayBuffer: function(input) {
+ var bytes = (input.length/4) * 3;
+ var ab = new ArrayBuffer(bytes);
+ this.decode(input, ab);
+
+ return ab;
+ },
+
+ decode: function(input, arrayBuffer) {
+ //get last chars to see if are valid
+ var lkey1 = this._keyStr.indexOf(input.charAt(input.length-1));
+ var lkey2 = this._keyStr.indexOf(input.charAt(input.length-2));
+
+ var bytes = (input.length/4) * 3;
+ if (lkey1 == 64) bytes--; //padding chars, so skip
+ if (lkey2 == 64) bytes--; //padding chars, so skip
+
+ var uarray;
+ var chr1, chr2, chr3;
+ var enc1, enc2, enc3, enc4;
+ var i = 0;
+ var j = 0;
+
+ if (arrayBuffer)
+ uarray = new Uint8Array(arrayBuffer);
+ else
+ uarray = new Uint8Array(bytes);
+
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+ for (i=0; i<bytes; i+=3) {
+ //get the 3 octects in 4 ascii chars
+ enc1 = this._keyStr.indexOf(input.charAt(j++));
+ enc2 = this._keyStr.indexOf(input.charAt(j++));
+ enc3 = this._keyStr.indexOf(input.charAt(j++));
+ enc4 = this._keyStr.indexOf(input.charAt(j++));
+
+ chr1 = (enc1 << 2) | (enc2 >> 4);
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+ chr3 = ((enc3 & 3) << 6) | enc4;
+
+ uarray[i] = chr1;
+ if (enc3 != 64) uarray[i+1] = chr2;
+ if (enc4 != 64) uarray[i+2] = chr3;
+ }
+
+ return uarray;
+ }
+}
@@ -71,7 +71,12 @@ Thingiloader = function(event) {
this.loadSTLBinary = function(STLBinary) {
workerFacadeMessage({'status':'message', 'content':'Parsing STL Binary...'});
- workerFacadeMessage({'status':'complete', 'content':this.ParseSTLBinary(STLBinary)});
+
+ if (STLBinary instanceof BinaryReader){
+ workerFacadeMessage({'status':'complete', 'content':this.ParseSTLBinary(STLBinary)});
+ } else {
+ workerFacadeMessage({'status':'complete', 'content':this.ParseSTLBinary(new BinaryReader(STLBinary))});
+ }
};
this.loadOBJString = function(OBJString) {
@@ -42,7 +42,7 @@ Thingiview = function(containerId) {
var rotateListener = null;
var wasRotating = null;
- var cameraView = 'diagonal';
+ var cameraView = 'iso';
var cameraZoom = 0;
var rotate = false;
var backgroundColor = '#606060';
@@ -456,6 +456,12 @@ Thingiview = function(containerId) {
if (showPlane) {
plane.flipSided = true;
}
+ } else if (dir == 'iso') {
+ targetXRotation = 45;
+ targetYRotation = 0;
+ if (showPlane) {
+ plane.flipSided = true;
+ }
} else {
// camera.position.y = -70;
// camera.position.z = 70;
@@ -585,7 +591,7 @@ Thingiview = function(containerId) {
// zoom backwards about half that distance, I don't think I'm doing the math or backwards vector calculation correctly?
// scope.setCameraZoom(-distance/1.8);
// scope.setCameraZoom(-distance/1.5);
- scope.setCameraZoom(-distance/1.9);
+ scope.setCameraZoom(-distance/0.9);
directionalLight.position.x = geometry.min_y * 2;
directionalLight.position.y = geometry.min_y * 2;
@@ -634,6 +640,7 @@ Thingiview = function(containerId) {
scope.setRotation(false);
//scope.setRotation(true);
log("finished loading " + geometry.faces.length + " faces.");
+ thingiview.setCameraView(cameraView);
scope.centerCamera();
} else if (event.data.status == "complete_points") {
progressBar.innerHTML = 'Initializing points...';
@@ -1,21 +0,0 @@
-Thingiview=function(j){function k(){l=new THREE.Mesh(new Plane(100,100,10,10),new THREE.MeshBasicMaterial({color:11513775,wireframe:!0}));m.addObject(l)}function b(){m&&g&&(material="wireframe"==u?new THREE.MeshBasicMaterial({color:G,wireframe:!0}):new THREE.MeshLambertMaterial({color:G,shading:THREE.FlatShading}),c&&(c.materials=[new THREE.MeshBasicMaterial({color:16777215,opacity:0})],m.removeObject(c)),c=new THREE.Mesh(g,material),m.addObject(c),"wireframe"!=u&&(c.overdraw=!0,c.doubleSided=!0),
-c.updateMatrix(),p=o=0,sceneLoop())}scope=this;this.containerId=j;var e=document.getElementById(j),d=null,m=null,f=null,c=null,l=null,M=null,r=null,t=null,o=0,B=0,v=0,w=0,p=0,C=0,x=0,y=0,z=!1,H=!1,D=window.innerWidth/2,E=window.innerHeight/2,h=null,n=null,s=null,F=null,I=null,J=null,A="diagonal",N="#606060",u="solid",G=16777215,q=!0;if(document.defaultView&&document.defaultView.getComputedStyle)var K=parseFloat(document.defaultView.getComputedStyle(e,null).getPropertyValue("width")),L=parseFloat(document.defaultView.getComputedStyle(e,
-null).getPropertyValue("height"));else K=parseFloat(e.currentStyle.width),L=parseFloat(e.currentStyle.height);var g;this.initScene=function(){e.style.position="relative";e.innerHTML="";d=new THREE.Camera(45,K/L,1,1E5);d.updateMatrix();m=new THREE.Scene;M=new THREE.AmbientLight(2105376);m.addLight(M);r=new THREE.DirectionalLight(16777215,0.75);r.position.x=1;r.position.y=1;r.position.z=2;r.position.normalize();m.addLight(r);t=new THREE.PointLight(16777215,0.3);t.position.x=0;t.position.y=-25;t.position.z=
-10;m.addLight(t);h=document.createElement("div");h.style.position="absolute";h.style.top="0px";h.style.left="0px";h.style.backgroundColor="red";h.style.padding="5px";h.style.display="none";h.style.overflow="visible";h.style.whiteSpace="nowrap";h.style.zIndex=100;e.appendChild(h);n=document.createElement("div");n.id="alertBox";n.style.position="absolute";n.style.top="25%";n.style.left="25%";n.style.width="50%";n.style.height="50%";n.style.backgroundColor="#dddddd";n.style.padding="10px";n.style.display=
-"none";n.style.zIndex=100;e.appendChild(n);q&&k();this.setCameraView(A);this.setObjectMaterial(u);testCanvas=document.createElement("canvas");try{f=testCanvas.getContext("experimental-webgl")?new THREE.WebGLRenderer:new THREE.CanvasRenderer}catch(a){f=new THREE.CanvasRenderer}f.setSize(K,L);f.domElement.style.backgroundColor=N;e.appendChild(f.domElement);window.addEventListener("mousemove",onRendererMouseMove,!1);f.domElement.addEventListener("mouseover",onRendererMouseOver,!1);f.domElement.addEventListener("mouseout",
-onRendererMouseOut,!1);f.domElement.addEventListener("mousedown",onRendererMouseDown,!1);window.addEventListener("mouseup",onRendererMouseUp,!1);f.domElement.addEventListener("touchstart",onRendererTouchStart,!1);f.domElement.addEventListener("touchend",onRendererTouchEnd,!1);f.domElement.addEventListener("touchmove",onRendererTouchMove,!1);f.domElement.addEventListener("DOMMouseScroll",onRendererScroll,!1);f.domElement.addEventListener("mousewheel",onRendererScroll,!1);f.domElement.addEventListener("gesturechange",
-onRendererGestureChange,!1)};onRendererScroll=function(a){a.preventDefault();var b=0,b=void 0===a.wheelDelta?-40*a.detail:a.wheelDelta;0<b?scope.setCameraZoom(10):scope.setCameraZoom(-10)};onRendererGestureChange=function(a){a.preventDefault();1<a.scale?scope.setCameraZoom(5):scope.setCameraZoom(-5)};onRendererMouseOver=function(){H=!0;null==s&&(s=setInterval(sceneLoop,1E3/60))};onRendererMouseDown=function(a){a.preventDefault();z=!0;scope.getRotation()?(J=!0,scope.setRotation(!1)):J=!1;w=a.clientX-
-D;y=a.clientY-E;B=o;C=p};onRendererMouseMove=function(a){z&&(v=a.clientX-D,xrot=B+0.02*(v-w),x=a.clientY-E,yrot=C+0.02*(x-y),o=xrot,p=yrot)};onRendererMouseUp=function(){z&&(z=!1,H||(clearInterval(s),s=null),J&&scope.setRotation(!0))};onRendererMouseOut=function(){z||(clearInterval(s),s=null);H=!1};onRendererTouchStart=function(a){o=c.rotation.z;p=c.rotation.x;s=setInterval(sceneLoop,1E3/60);1==a.touches.length&&(a.preventDefault(),w=a.touches[0].pageX-D,B=o,y=a.touches[0].pageY-E,C=p)};onRendererTouchEnd=
-function(){clearInterval(s);s=null};onRendererTouchMove=function(a){1==a.touches.length&&(a.preventDefault(),v=a.touches[0].pageX-D,o=B+0.05*(v-w),x=a.touches[0].pageY-E,p=C+0.05*(x-y))};sceneLoop=function(){c&&(q?(l.rotation.z=c.rotation.z=0.2*(o-c.rotation.z),l.rotation.x=c.rotation.x=0.2*(p-c.rotation.x)):(c.rotation.z=0.2*(o-c.rotation.z),c.rotation.x=0.2*(p-c.rotation.x)),d.updateMatrix(),c.updateMatrix(),q&&l.updateMatrix(),f.render(m,d))};rotateLoop=function(){o+=0.05;sceneLoop()};this.getShowPlane=
-function(){return q};this.setShowPlane=function(a){(q=a)?(m&&!l&&k(),l.material[0].opacity=1):m&&l&&(l.material[0].opacity=0);sceneLoop()};this.getRotation=function(){return null!==F};this.setRotation=function(a){(rotation=a)?F=setInterval(rotateLoop,1E3/60):(clearInterval(F),F=null);scope.onSetRotation()};this.onSetRotation=function(a){if(void 0===a){if(null!==I)try{I(scope.getRotation())}catch(b){}}else I=a};this.setCameraView=function(a){A=a;p=o=0;c&&(c.rotation.x=0,c.rotation.y=0,c.rotation.z=
-0);q&&c&&(l.rotation.x=c.rotation.x,l.rotation.y=c.rotation.y,l.rotation.z=c.rotation.z);"top"==a?q&&(l.flipSided=!1):"side"==a?(p=-4.5,q&&(l.flipSided=!1)):"bottom"==a?q&&(l.flipSided=!0):q&&(l.flipSided=!1);w=v=o;y=x=p;scope.centerCamera();sceneLoop()};this.setCameraZoom=function(a){"bottom"==A?0<d.position.z+a&&(a=0):0>d.position.z-a&&(a=0);"top"==A?d.position.z-=a:"bottom"==A?d.position.z+=a:(d.position.y+=a,d.position.z-=a);sceneLoop()};this.getObjectMaterial=function(){return u};this.setObjectMaterial=
-function(a){u=a;b()};this.setBackgroundColor=function(a){N=a;f&&(f.domElement.style.backgroundColor=a)};this.setObjectColor=function(a){G=parseInt(a.replace(/\#/g,""),16);b()};this.loadSTL=function(a){scope.newWorker("loadSTL",a)};this.loadOBJ=function(a){scope.newWorker("loadOBJ",a)};this.loadSTLString=function(a){scope.newWorker("loadSTLString",a)};this.loadSTLBinary=function(a){scope.newWorker("loadSTLBinary",a)};this.loadOBJString=function(a){scope.newWorker("loadOBJString",a)};this.loadJSON=
-function(a){scope.newWorker("loadJSON",a)};this.loadPLY=function(a){scope.newWorker("loadPLY",a)};this.loadPLYString=function(a){scope.newWorker("loadPLYString",a)};this.loadPLYBinary=function(a){scope.newWorker("loadPLYBinary",a)};this.centerCamera=function(){g?(d.target.position.x=g.center_x,d.target.position.y=g.center_y,d.target.position.z=g.center_z,d.position.x=g.center_x,d.position.y=g.center_y,d.position.z=g.center_z,distance=g.boundingSphere.radius/Math.sin(d.fov/2*(Math.PI/180)),scope.setCameraZoom(-distance/
-1.9),r.position.x=2*g.min_y,r.position.y=2*g.min_y,r.position.z=2*g.max_z,t.position.x=g.center_y,t.position.y=g.center_y,t.position.z=2*g.max_z):(d.position.y=-70,d.position.z=70,d.target.position.z=0)};this.loadArray=function(a){log("loading array...");g=new STLGeometry(a);b();scope.setRotation(!1);scope.setRotation(!0);scope.centerCamera();log("finished loading "+g.faces.length+" faces.")};this.progressBarMessage=function(a){h.style.display="block";h.innerHTML=a};this.newWorker=function(a,c){scope.setRotation(!1);
-var e=new WorkerFacade(thingiurlbase+"/thingiloader.js");e.onmessage=function(a){if("complete"==a.data.status)h.innerHTML="Initializing geometry...",g=new STLGeometry(a.data.content),b(),h.innerHTML="",h.style.display="none",scope.setRotation(!1),log("finished loading "+g.faces.length+" faces."),scope.centerCamera();else if("complete_points"==a.data.status){h.innerHTML="Initializing points...";g=new THREE.Geometry;var c=new THREE.ParticleBasicMaterial({color:16711680,opacity:1});for(i in a.data.content[0])vector=
-new THREE.Vector3(a.data.content[0][i][0],a.data.content[0][i][1],a.data.content[0][i][2]),g.vertices.push(new THREE.Vertex(vector));particles=new THREE.ParticleSystem(g,c);particles.sortParticles=!0;particles.updateMatrix();m.addObject(particles);d.updateMatrix();f.render(m,d);h.innerHTML="";h.style.display="none";scope.setRotation(!1);scope.setRotation(!0);log("finished loading "+a.data.content[0].length+" points.")}else"progress"==a.data.status?(h.style.display="block",h.style.width=a.data.content):
-"message"==a.data.status?(h.style.display="block",h.innerHTML=a.data.content,log(a.data.content)):"alert"==a.data.status?scope.displayAlert(a.data.content):(alert("Error: "+a.data),log("Unknown Worker Message: "+a.data))};e.onerror=function(a){log(a);a.preventDefault()};e.postMessage({cmd:a,param:c})};this.displayAlert=function(a){n.innerHTML=a+'<br/><br/><center><input type="button" value="Ok" onclick="document.getElementById(\'alertBox\').style.display=\'none\'"></center>';n.style.display="block"}};
-var STLGeometry=function(j){function k(d,e,f){b.vertices.push(new THREE.Vertex(new THREE.Vector3(d,e,f)))}THREE.Geometry.call(this);for(var b=this,e=0;e<j[0].length;e++)k(j[0][e][0],j[0][e][1],j[0][e][2]);for(e=0;e<j[1].length;e++)b.faces.push(new THREE.Face3(j[1][e][0],j[1][e][1],j[1][e][2]));this.computeCentroids();this.computeFaceNormals();this.sortFacesByMaterial();b.min_x=0;b.min_y=0;b.min_z=0;b.max_x=0;b.max_y=0;k=b.max_z=0;for(j=b.vertices.length;k<j;k++)b.max_x=Math.max(b.max_x,b.vertices[k].position.x),
-b.max_y=Math.max(b.max_y,b.vertices[k].position.y),b.max_z=Math.max(b.max_z,b.vertices[k].position.z),b.min_x=Math.min(b.min_x,b.vertices[k].position.x),b.min_y=Math.min(b.min_y,b.vertices[k].position.y),b.min_z=Math.min(b.min_z,b.vertices[k].position.z);b.center_x=(b.max_x+b.min_x)/2;b.center_y=(b.max_y+b.min_y)/2;b.center_z=(b.max_z+b.min_z)/2};STLGeometry.prototype=new THREE.Geometry;STLGeometry.prototype.constructor=STLGeometry;function log(j){this.console&&console.log(j)}var WorkerFacade;
-WorkerFacade=window.Worker?function(){return function(j){return new window.Worker(j)}}():function(){var j={},k={},b=function(b){var d={},m=!1,f=[];d.postToWorkerFunction=function(c){try{j[b]({data:c})}catch(f){d.onerror(f)}};d.postMessage=function(b){m?d.postToWorkerFunction(b):f.push(b)};k[b]=d;var c=document.createElement("SCRIPT");c.src=b;c.type="text/javascript";c.onload=function(){for(m=!0;0<f.length;)d.postToWorkerFunction(f[0]),f.shift()};document.body.appendChild(c);c=document.createElement("SCRIPT");
-c.src=thingiurlbase+"/binaryReader.js";c.type="text/javascript";document.body.appendChild(c);return d};b.fake=!0;b.add=function(b,d){j[b]=d;return function(d){k[b].onmessage({data:d})}};b.toString=function(){return"FakeWorker('"+path+"')"};return b}();

0 comments on commit d08bb54

Please sign in to comment.