Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

PDF features for MozFest 2012

1. Updated pdf.js to latest.
2. Minor tweaks to pdf.js to let it run properly and give annotations without exploding.
3. Changes in CubicVR Texture/PDF to use new pdf.js async API.
4. CubicVR::Scene::bind accepts `pickable` param for sceneObjects.
5. mozfest2012 sample uses PDF annotations and pickables to emulate anchor tags.
6. DS_Store in gitignore (rhymes).
  • Loading branch information...
commit b333c5fd634978e214f2dccec8d96cac2f4e5907 1 parent 0a0ea7a
@secretrobotron secretrobotron authored
View
1  .gitignore
@@ -1,3 +1,4 @@
*~
*.swp
cubicvr
+.DS_Store
View
39,879 lib/pdf.js
30,002 additions, 9,877 deletions not shown
View
111 samples/mozfest2012/mozfest.html
@@ -5,6 +5,7 @@
</title>
<script src="../../CubicVR.js" type="text/javascript"></script>
<script src="../../lib/pdf.js" type="text/javascript"></script>
+ <script type="text/javascript">PDFJS.disableWorker = true; PDFJS.workerSrc = '../../lib/pdf.js';</script>
<style type='text/css'></style>
<script type='text/javascript'>
function initGallery() {
@@ -13,18 +14,50 @@
var scene;
var light;
- function makePanel(material,w,h,pageNum,numPages) {
+ var annotationMaterial;
+ var annotationMesh;
+
+ function generateAnnotationAssets() {
+ annotationMaterial = new CubicVR.Material({
+ color: [1, 0, .8],
+ opacity: 0
+ });
+
+ annotationMesh = new CubicVR.Mesh({
+ material: annotationMaterial,
+ primitive: {
+ type: "plane",
+ material: annotationMaterial,
+ uv: {
+ type: "planar",
+ projectionAxis: "z",
+ scale: [-1,1,1]
+ }
+ },
+ compile: true
+ });
+ }
+
+ function makePanel(material,w,h,pageNum,numPages,page,annotationsArray) {
var xscale = 1.0,
yscale = 1.0;
var panelSize = 1.5,
hp = panelSize / 2.0;
var imageAspect = w / h;
+ var pageRect = page.view;
+
if (imageAspect < 1.0) {
xscale = imageAspect;
} else {
yscale = 1.0 / imageAspect;
}
+
+ var sx = panelSize * xscale;
+ var sy = panelSize * yscale;
+
+ var annotationXScale = sx / page.view[2];
+ var annotationYScale = sy / page.view[3];
var panelMesh = new CubicVR.Mesh({
material: material,
@@ -42,11 +75,41 @@
var pageOfs = (numPages%2==0)?0:(pageSpacing/2);
+ var px = (pageNum - (numPages / 2.0))*pageSpacing+pageOfs;
+
var panel = new CubicVR.SceneObject({
mesh: panelMesh,
- position: [(pageNum - (numPages / 2.0))*pageSpacing+pageOfs, 0, 0],
- scale: [ panelSize * xscale, panelSize * yscale, 1 ]
+ position: [px, 0, 0],
+ scale: [ sx, sy, 1 ]
});
+
+ if ( annotationsArray && annotationsArray.length ) {
+ annotationsArray.forEach(function(annotationDef, index){
+ var annotationRect = annotationDef.rect;
+ var w = (annotationRect[2] - annotationRect[0])*annotationXScale;
+ var h = (annotationRect[3] - annotationRect[1])*annotationYScale;
+ var x = annotationRect[0]*annotationXScale;
+ var y = annotationRect[1]*annotationYScale;
+
+ var annotationPanel = new CubicVR.SceneObject({
+ mesh: annotationMesh,
+ position: [
+ px + x - sx/2 + w/2,
+ y - sy/2 + h/2,
+ 0.001
+ ],
+ scale: [
+ w,
+ h,
+ 1
+ ]
+ });
+
+ annotationPanel.url = annotationDef.url;
+
+ scene.bind(annotationPanel, true);
+ });
+ }
scene.bind(panel);
panels.push(panel);
@@ -88,17 +151,30 @@
var gl = CubicVR.init();
var canvas = CubicVR.getCanvas();
-
+
+ generateAnnotationAssets();
+
scene = new CubicVR.Scene(canvas.width, canvas.height, 60.0);
var pdf = new CubicVR.PDF({
src: "cubic_presentation.pdf",
- callback: function() {
- for (var i = 0, iMax = pdf.pages; i < iMax; i++) {
- makePanel(new CubicVR.Material({
- textures: { color: pdf.getPageTexture(i+1, 1024, 1024) }
- }),25.4,19.05,i,pdf.pages);
+ callback: function() {
+ function generatePage(index){
+ var page = pdf.getPage(index);
+ page.getAnnotations().then(function(annotationsArray){
+ makePanel(new CubicVR.Material({
+ textures: { color: pdf.getPageTexture(index) }
+ }),25.4,19.05,index-1,pdf.pages,page,annotationsArray);
+ });
+
+ if ( index < pdf.pages ) {
+ generatePage(index+1);
+ }
+
}
+
+ generatePage(1);
+
scene.camera.x = scene.camera.targetX = light.x = pageSpacing*(-pdf.pages/2)-pageSpacing;
}
});
@@ -123,7 +199,17 @@
var keyMove = 0;
var scrollTimer = 0;
+ var rayTest;
+
CubicVR.MainLoop(function(timer, gl) {
+ rayTest = scene.bbRayTest(scene.camera.position, mvc.getMousePosition(), 3);
+ if (rayTest.length) {
+ canvas.style.cursor = "pointer";
+ }
+ else {
+ canvas.style.cursor = "";
+ }
+
if (!mvc.mdown) {
var xmove = 0
var moveSpeed = 5.0;
@@ -190,7 +276,12 @@
if (scene.camera.fov > max) scene.camera.setFOV(max);
scrollTimer = Date.now();
},
- mouseDown: null, mouseUp: null
+ mouseDown: function(ctx, mpos){
+ if (rayTest && rayTest[0]) {
+ window.open(rayTest[0].obj.url, '_blank');
+ }
+ },
+ mouseUp: null
});
CubicVR.addResizeable(scene);
View
121 source/CubicVR.PDF.js
@@ -4,6 +4,64 @@ CubicVR.RegisterModule("PDF", function (base) {
var GLCore = base.GLCore;
var enums = CubicVR.enums;
+ // Variant of pdf.js's getPdf
+ function getPdf(arg, callback) {
+ var params = arg;
+ if (typeof arg === 'string')
+ params = { url: arg };
+ //#if !B2G
+ var xhr = new XMLHttpRequest();
+ //#else
+ //var xhr = new XMLHttpRequest({mozSystem: true});
+ //#endif
+ xhr.open('GET', params.url);
+
+ var headers = params.headers;
+ if (headers) {
+ for (var property in headers) {
+ if (typeof headers[property] === 'undefined')
+ continue;
+
+ xhr.setRequestHeader(property, params.headers[property]);
+ }
+ }
+
+ xhr.mozResponseType = xhr.responseType = 'arraybuffer';
+
+ var protocol = params.url.substring(0, params.url.indexOf(':') + 1);
+
+ //XXXsecretrobotron: Need to interject here. Protocol could be '', but still need 200 status to continue
+ xhr.expected = (['http:', 'https:', ''].indexOf(protocol) > -1) ? 200 : 0;
+
+ if ('progress' in params)
+ xhr.onprogress = params.progress || undefined;
+
+ var calledErrorBack = false;
+
+ if ('error' in params) {
+ xhr.onerror = function errorBack() {
+ if (!calledErrorBack) {
+ calledErrorBack = true;
+ params.error();
+ }
+ }
+ }
+
+ xhr.onreadystatechange = function getPdfOnreadystatechange(e) {
+ if (xhr.readyState === 4) {
+ if (xhr.status === xhr.expected) {
+ var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
+ xhr.responseArrayBuffer || xhr.response);
+ callback(data);
+ } else if (params.error && !calledErrorBack) {
+ calledErrorBack = true;
+ params.error(e);
+ }
+ }
+ };
+ xhr.send(null);
+ }
+
function PDF(options) {
if (!options.src) {
throw("PDF Error: you must specify a src url for a PDF.");
@@ -48,30 +106,53 @@ CubicVR.RegisterModule("PDF", function (base) {
*/
this.getPageTexture = function(n, width, height) {
var page = this.getPage(n);
- width = width || page.width;
- height = height || page.height;
-
- return new CubicVR.PdfTexture(page, {width: width, height: height});
+ var viewport = page.getViewport(1);
+ width = width || viewport.width;
+ height = height || viewport.height;
+ return new CubicVR.PdfTexture(page, {width: width, height: height, viewport: viewport});
};
- getPdf(
- {
- url: src,
- error: function() {
- console.log('PDF Error: error loading pdf `' + src + '`');
- }
+
+ var pdfParams = {
+ url: src,
+ progress: function(e){
},
- function(data) {
- pdf = new PDFDoc(data);
-
- for (var i = 1, pp = pdf.numPages; i <= pp; i++) {
- var page = pdf.getPage(i);
- pages.push(page);
- thumbnails.push(page);
- }
- callback();
+ error: function(e) {
+ console.log('PDF Error: error loading pdf `' + src + '`');
}
- );
+ };
+
+ getPdf(pdfParams, function successCallback(data) {
+ PDFJS.getDocument({
+ data: data
+ }).then(
+ function(doc){
+ pdf = doc;
+
+ var i = 0;
+
+ // get pages in order
+ function getNextPage() {
+ if ( i++ >= doc.numPages ) {
+ callback();
+ }
+ else {
+ doc.getPage(i).then(function(page){
+ pages.push(page);
+ thumbnails.push(page);
+ getNextPage();
+ });
+ }
+ }
+
+ getNextPage();
+ },
+ function(msg, e){
+ console.warn(msg, e);
+ callback();
+ });
+ });
+
}
var extend = {
View
4 source/CubicVR.Scene.js
@@ -840,11 +840,11 @@ CubicVR.RegisterModule("Scene", function (base) {
return cameraObj;
},
- bind: function(obj) {
+ bind: function(obj, pickable) {
if (obj instanceof base.Light) {
this.bindLight(obj);
} else if (obj instanceof base.SceneObject) {
- this.bindSceneObject(obj);
+ this.bindSceneObject(obj, pickable);
} else if (obj instanceof base.Camera) {
this.bindCamera(obj);
} else if (obj instanceof base.Vehicle) {
View
18 source/CubicVR.Texture.js
@@ -293,7 +293,23 @@ CubicVR.RegisterModule("Texture", function (base) {
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
- page.startRendering(ctx, function() { self.update(); });
+ var pdfViewport = options.viewport || page.getViewport(1);
+
+ pdfViewport.width = canvas.width;
+ pdfViewport.height = canvas.height;
+
+ var renderContext = {
+ canvasContext: ctx,
+ viewport: pdfViewport,
+ //textLayer: textLayer,
+ continueCallback: function pdfViewcContinueCallback(cont) {
+ cont();
+ }
+ };
+
+ page.render(renderContext).then(function(){
+ self.update();
+ });
this.texture = new base.Texture();
Please sign in to comment.
Something went wrong with that request. Please try again.