WebVR Extension with Basic Application Example - autodesk-forge

I am trying to use the WebVR extension with a basic application. Instead of a 3D model in VR, the below html renders a 2D model. The code is mostly boilerplate except for where I call the WebVR extension. Thanks in advance!
<!DOCTYPE html>
<!-- vr.html -->
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
<meta charset="utf-8">
<!-- The Viewer CSS -->
<link rel="stylesheet" href="https://developer.api.autodesk.com/viewingservice/v1/viewers/style.min.css" type="text/css">
<!-- Developer CSS -->
<style>
body {
margin: 0;
}
#MyViewerDiv {
width: 100%;
height: 100%;
margin: 0;
background-color: #F0F8FF;
}
</style>
</head>
<body>
<!-- The Viewer will be instantiated here -->
<div id="MyViewerDiv"></div>
<!-- The Viewer JS -->
<script src="https://developer.api.autodesk.com/viewingservice/v1/viewers/three.min.js"></script>
<script src="https://developer.api.autodesk.com/viewingservice/v1/viewers/viewer3D.min.js"></script>
<!-- Developer JS -->
<script>
var viewerApp;
var options = {
env: 'AutodeskProduction',
// Here is the WebVR extension
extensions: ['Autodesk.Viewing.WebVR'],
getAccessToken: function(onGetAccessToken) {
//
// TODO: Replace static access token string below with call to fetch new token from your backend
// Both values are provided by Forge's Authentication (OAuth) API.
//
// Example Forge's Authentication (OAuth) API return value:
// {
// "access_token": "<YOUR_APPLICATION_TOKEN>",
// "token_type": "Bearer",
// "expires_in": 86400
// }
//
var accessToken = {{ accessToken }};
var expireTimeSeconds = 60 * 30;
onGetAccessToken(accessToken, expireTimeSeconds);
}
};
var documentId = {{ documentID }};
// var config = {
// extensions: ['Autodesk.Viewing.WebVR'],
// experimental: ['webVR_orbitModel']
// };
Autodesk.Viewing.Initializer(options, function(){
viewerApp = new Autodesk.Viewing.ViewingApplication('MyViewerDiv');
viewerApp.registerViewer(viewerApp.k3D, Autodesk.Viewing.Private.GuiViewer3D);
viewerApp.loadDocument(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
});
function onDocumentLoadSuccess(doc) {
// We could still make use of Document.getSubItemsWithProperties()
// However, when using a ViewingApplication, we have access to the **bubble** attribute,
// which references the root node of a graph that wraps each object from the Manifest JSON.
var viewables = viewerApp.bubble.search({'type':'geometry'});
if (viewables.length === 0) {
console.error('Document contains no viewables.');
return;
}
// Choose any of the avialble viewables
viewerApp.selectItem(viewables[0].data, onItemLoadSuccess, onItemLoadFail);
}
function onDocumentLoadFailure(viewerErrorCode) {
console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);
}
function onItemLoadSuccess(viewer, item) {
console.log('onItemLoadSuccess()!');
console.log(viewer);
console.log(item);
// Congratulations! The viewer is now ready to be used.
console.log('Viewers are equal: ' + (viewer === viewerApp.getCurrentViewer()));
}
function onItemLoadFail(errorCode) {
console.error('onItemLoadFail() - errorCode:' + errorCode);
}
</script>
</body>
</html>
Where {{ documentID }} is my urn and {{ accessToken }} is my token.

First of all, I don't think the WebVR extension works for 2D model, I just tried with a f2d file, and it's not working, what do you expect for 2D in VR?
I also suggest you to use the Viewer version at least 2.13, if you do not specify any version of viewer, it will use 2.12 by default as I tried. And if you check the viewer 2.12 code of WebVR extension at https://developer.api.autodesk.com/viewingservice/v1/viewers/viewer3D.js?v=2.12, you will see it does not use webvr-polyfill when your browser does not support WebVR natively. But, since from viewer 2.13, the following code is added to support webvr-polyfill, that makes your browser to support WebVR even it does not natively support WebVR yet.
// check if browser supports webVR1.1 natively, if not, load polyfill
avp.loadDependency('VRFrameData', 'webvr-polyfill.min.js', function() {})
Last, I have a simple running sample for WebVR at https://viewervr.herokuapp.com if you want to check the result, nothing more but just load the "'Autodesk.Viewing.WebVR" extension, if you run it on your mobile device, you will see the expected result.
Hope it helps.

Related

SciChart: Working with Zooming module is not working

I am using SciChart Library for showing Graphs.
I want to know, how can I use MouseWheelZoomModifier module of SciChart library in my pure HTML & CSS based website.
I know there is a documentation available related to React but I am not using it in my Website.
I have written the following Code:
Code:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Include SciChart.js -->
<script
src="https://cdn.jsdelivr.net/npm/scichart#2.1.2290/_wasm/scichart.browser.js"
crossorigin="anonymous"
></script>
<title>Hello, SciChart.js world!</title>
</head>
<body>
<h1>Hello, SciChart.js world!</h1>
<!-- Create the Div to host the SciChartSurface -->
<div id="scichart-root" style="width: 800px; height: 600px;"></div>
<!-- The JavaScript to create a SciChartSurface -->
<script>
async function initSciChart() {
// In order to load data file from the CDN we need to set dataUrl
SciChart.SciChartSurface.configure({
dataUrl: `https://cdn.jsdelivr.net/npm/scichart#${SciChart.libraryVersion}/_wasm/scichart2d.data`,
wasmUrl: `https://cdn.jsdelivr.net/npm/scichart#${SciChart.libraryVersion}/_wasm/scichart2d.wasm`
});
// Create a SciChartSurface inside the div with id 'scichart-root'
const {
sciChartSurface,
wasmContext
} = await SciChart.SciChartSurface.create("scichart-root");
// Add an X and a Y Axis
const xAxis = new SciChart.NumericAxis(wasmContext);
sciChartSurface.xAxes.add(xAxis);
const yAxis = new SciChart.NumericAxis(wasmContext);
sciChartSurface.yAxes.add(yAxis);
// Create 100 dataseries, each with 10k points
for (let seriesCount = 0; seriesCount < 100; seriesCount++) {
const xyDataSeries = new SciChart.XyDataSeries(wasmContext);
const opacity = (1 - ((seriesCount / 120))).toFixed(2);
// Populate with some data
for(let i = 0; i < 10000; i++) {
xyDataSeries.append(i, Math.sin(i* 0.01) * Math.exp(i*(0.00001*(seriesCount+1))));
}
// Add and create a line series with this data to the chart
// Create a line series
const lineSeries = new SciChart.FastLineRenderableSeries(wasmContext, {
dataSeries: xyDataSeries,
stroke: `rgba(176,196,222,${opacity})`,
strokeThickness:2
});
sciChartSurface.renderableSeries.add(lineSeries);
}
// BELOW ONE NOT WORKING
// Add zoom, pan behaviours to the chart. Mousewheel zoom, panning and double-click to
// zoom to fit
const mouseWheelZoomModifier = new MouseWheelZoomModifier();
const zoomPanModifier = new ZoomPanModifier();
const rubberBandZoomModifier = new RubberBandXyZoomModifier();
const zoomExtentsModifier = new ZoomExtentsModifier();
sciChartSurface.chartModifiers.add(zoomExtentsModifier);
sciChartSurface.chartModifiers.add(zoomPanModifier);
sciChartSurface.chartModifiers.add(rubberBandZoomModifier);
sciChartSurface.chartModifiers.add(mouseWheelZoomModifier);
const inputEnablePan = document.getElementById("enable-pan");
const inputEnableZoom = document.getElementById("enable-zoom");
const inputEnableZoomToFit = document.getElementById("enable-zoom-to-fit");
const inputEnableMouseWheel = document.getElementById("enable-mouse-wheel-zoom");
inputEnablePan.addEventListener("input", (event) => {
zoomPanModifier.isEnabled = inputEnablePan.checked;
rubberBandZoomModifier.isEnabled = !inputEnablePan.checked;
inputEnableZoom.checked = !inputEnablePan.checked;
console.log(`Enabling Drag to Pan. Status: rubberBand checkbox ${inputEnableZoom.checked}, rubberBand ${rubberBandZoomModifier.isEnabled}, zoomPan checkbox ${inputEnablePan.isEnabled}, zoomPan ${zoomPanModifier.isEnabled} `);
});
inputEnableZoom.addEventListener("input", (event) => {
rubberBandZoomModifier.isEnabled = inputEnableZoom.checked;
zoomPanModifier.isEnabled = !inputEnableZoom.checked;
inputEnablePan.checked = !inputEnableZoom.checked;
console.log(`Enabling Drag to Zoom. Status: rubberBand checkbox ${inputEnableZoom.checked}, rubberBand ${rubberBandZoomModifier.isEnabled}, zoomPan checkbox ${inputEnablePan.isEnabled}, zoomPan ${zoomPanModifier.isEnabled} `);
});
inputEnableZoomToFit.addEventListener("input", (event) => {
zoomExtentsModifier.isEnabled = inputEnableZoomToFit.checked;
console.log("Enabling zoom extents");
});
inputEnableMouseWheel.addEventListener("input", (event) => {
mouseWheelZoomModifier.isEnabled = inputEnableMouseWheel.checked;
console.log("Enabling Mousewheel zoom");
});
}
initSciChart();
</script>
</body>
</html>
Output:
The MouseWheelZoomModifier is actually the module that is import using import keyword in React tutorial but how can I use it in HTML & CSS based Web Page.
Kindly Help.
Because you are using SciChart's Browser module (where the code is served from CDN and JS rather than npm/webpack) you need to use a slightly different way to declare objects in code.
Note the Tutorial for setting up SciChart.js with browser module says
Notice every API call is prefixed by SciChart. when using the browser bundle. This is the global namespace for all SciChart apis, functions and types.
Once you have added the script to include scichart.js (and version)
<script src="https://cdn.jsdelivr.net/npm/scichart#2.1.2290/_wasm/scichart.browser.js" crossorigin="anonymous"></script>
You must now tell SciChart where to load the wasm files from. The easiest way to do this is to call SciChartSurface.useWasmFromCDN();
SciChart.SciChartSurface.useWasmFromCDN();
Next, when not using npm/webpack every type in the SciChart library is now prepended with the global variable SciChart.
For example in our npm/webpack docs this code:
const mouseWheelZoomModifier = new MouseWheelZoomModifier();
sciChartSurface.chartModifiers.add(mouseWheelZoomModifier);
must become this
const mouseWheelZoomModifier = new SciChart.MouseWheelZoomModifier();
sciChartSurface.chartModifiers.add(mouseWheelZoomModifier);
Alternatively you can pre-declare these types as follows:
// When using SciChart from CDN / browser bundle, there are no imports
// so either prepend every variable by global namespace SciChart.
// or use code like this to get the types out
const {
MouseWheelZoomModifier,
SciChartSurface,
NumericAxis
} = SciChart;
// static func. Call once. load wasm from CDN
SciChartSurface.useWasmFromCDN();
// Create a SciChartSurface in <div id="div-id"/>
const { sciChartSurface, wasmContext } = SciChartSurface.create("div-id");
// Add x,y axis
sciChartSurface.xAxes.add(new NumericAxis(wasmContext));
sciChartSurface.yAxes.add(new NumericAxis(wasmContext));
// Add modifiers for zooming, panning
const mouseWheelZoomModifier = new MouseWheelZoomModifier();
sciChartSurface.chartModifiers.add(mouseWheelZoomModifier);
Try that and see if it works

How do I load extension when viewing local file

I am using the example taken from viewer-javascsript-offline.sample
I have an extension that was created using nodejs tutorial (link) that I got it working using the tutorial code to register the extension. However, when I tried the same thing using the offline viewer code sample (using viewer3D instead of viewingApplication), I am not able to view the extension's button.
note: I can guarantee that the handleselectionextension.js is working fine as I've got it working in the tutorial version.
codes:
index.css and index.html
.handleSelectionToolbarButton {
background-image: url(https://github.com/encharm/Font-Awesome-SVG-PNG/raw/master/white/png/24/object-group.png);
background-size: 24px;
background-repeat: no-repeat;
background-position: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Very Basic 3D Viewer</title>
<link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/style.min.css?v=4.2.*" type="text/css">
<link href="index.css" rel="stylesheet" />
</head>
<body>
<div id="MyViewerDiv"></div>
<!-- The Viewer JS -->
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/three.min.js?v=4.2.*"></script>
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/viewer3D.min.js?v=4.2.*"></script>
<script src="handleselectionextension.js"></script>
<!-- Developer JS -->
<script>
var myViewerDiv = document.getElementById('MyViewerDiv');
var viewer = new Autodesk.Viewing.Private.GuiViewer3D(myViewerDiv);
var options = {
'env': 'Local',
'document': "0/1/Design.svf",
'extensions': ["HandleSelectionExtension"]
};
Autodesk.Viewing.Initializer(options, function() {
viewer.start(options.document, options);
});
</script>
</body>
</html>
The extension config is not for Initializer, you have to pass it to 2nd argument of the viewer constructor like this:
var config3d = {
'extensions': ["HandleSelectionExtension"]
};
var myViewerDiv = document.getElementById('MyViewerDiv');
var viewer = new Autodesk.Viewing.Private.GuiViewer3D(myViewerDiv, config3d);
var options = {
'env': 'Local',
'document': "0/1/Design.svf"
};
Autodesk.Viewing.Initializer(options, function() {
viewer.start(options.document, options);
});

XMLHttpRequest error for the Viewer

I use the following HTML file to test the Headless Viewer of Autodesk Forge. The test url will look like:
http://localhost:8080/HeadlessViewer.html?token={{Bearer}}&urn={{base64URN}}
The token has scope=data:read, urn is base64 format.
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
</head>
<body>
<div id="MyViewerDiv"></div>
<!-- The Viewer JS -->
<script src="https://developer.api.autodesk.com/viewingservice/v1/viewers/three.min.js?v=v2.10.*"></script>
<script src="https://developer.api.autodesk.com/viewingservice/v1/viewers/viewer3D.js?v=v2.10.*"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<!-- Developer JS -->
<script>
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
function initViewer(token, urn) {
var viewerApp;
var options = {
env: 'AutodeskProduction',
accessToken: token
};
var documentId = atob(urn); // 'urn:<YOUR_URN_ID>';
Autodesk.Viewing.Initializer(options, onInitialized);
function onInitialized() {
viewerApp = new Autodesk.Viewing.ViewingApplication('MyViewerDiv');
viewerApp.registerViewer(viewerApp.k3D, Autodesk.Viewing.Viewer3D);
viewerApp.loadDocument(documentId, onDocumentLoaded);
}
function onDocumentLoaded(lmvDoc) {
var modelNodes = viewerApp.bubble.search(av.BubbleNode.MODEL_NODE); // 3D designs
var sheetNodes = viewerApp.bubble.search(av.BubbleNode.SHEET_NODE); // 2D designs
var allNodes = modelNodes.concat(sheetNodes);
if (allNodes.length) {
viewerApp.selectItem(allNodes[0].data);
if (allNodes.length === 1) {
alert('This tutorial works best with documents with more than one viewable!');
}
} else {
alert('There are no viewables for the provided URN!');
}
}
}
$(document).ready(function () {
var url = window.location.href,
token = getParameterByName('token', url),
urn = getParameterByName('urn', url);
initViewer(token, urn);
});
</script>
</body>
</html>
However, it stops at the exception XMLHttpRequest.responseText. Please see the attached image: Error image
I tried your code just replacing the "accessToken: <>" and "var documentId = <>" and worked fine. Looking at your code, I believe the problem may be at the following line:
var documentId = atob(urn); // 'urn:<YOUR_URN_ID>';
The atob function will decode the string, which means it will not be on Base64. But the documentId should be like:
var documentId = 'urn:c29tZSByYW5kb20gd29yZHMgaGVyZQ==';
Please make sure the documentId is properly formed.
Finally, note the Viewer requires URL Safe encoding. Consider encoding on server (safer to transmit) or doing it on client-side, see this answer.

HTML5 getUserMedia() media sources

I have created a streaming webcam with html5. At the moment I can take a picture through my web cam, but I would like to know if it is possible to choose media stream device from the list, e.g. I have two web cams I want to choose the webcam to activate. How can I do that with html5 getUserMedia() call?
Thanks!
You can get the list of web camera
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Video Camera List</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js" ></script>
<style type="text/css" media="screen">
video {
border:1px solid gray;
}
</style>
</head>
<body>
<script>
if (!MediaStreamTrack) document.body.innerHTML = '<h1>Incompatible Browser Detected. Try <strong style="color:red;">Chrome Canary</strong> instead.</h1>';
var videoSources = [];
MediaStreamTrack.getSources(function(media_sources) {
console.log(media_sources);
// alert('media_sources : '+media_sources);
media_sources.forEach(function(media_source){
if (media_source.kind === 'video') {
videoSources.push(media_source);
}
});
getMediaSource(videoSources);
});
var get_and_show_media = function(id) {
var constraints = {};
constraints.video = {
optional: [{ sourceId: id}]
};
navigator.webkitGetUserMedia(constraints, function(stream) {
console.log('webkitGetUserMedia');
console.log(constraints);
console.log(stream);
var mediaElement = document.createElement('video');
mediaElement.src = window.URL.createObjectURL(stream);
document.body.appendChild(mediaElement);
mediaElement.controls = true;
mediaElement.play();
}, function (e)
{
// alert('Hii');
document.body.appendChild(document.createElement('hr'));
var strong = document.createElement('strong');
strong.innerHTML = JSON.stringify(e);
alert('strong.innerHTML : '+strong.innerHTML);
document.body.appendChild(strong);
});
};
var getMediaSource = function(media) {
console.log(media);
media.forEach(function(media_source) {
if (!media_source) return;
if (media_source.kind === 'video')
{
// add buttons for each media item
var button = $('<input/>', {id: media_source.id, value:media_source.id, type:'submit'});
$("body").append(button);
// show video on click
$(document).on("click", "#"+media_source.id, function(e){
console.log(e);
console.log(media_source.id);
get_and_show_media(media_source.id);
});
}
});
}
</script>
</body>
</html>
In the latest Chrome Canary (30.0.1587.2) it looks like you can enable device enumeration in chrome://flags (looks like it might already be enabled) and use the MediaStreamTrack.getSources API to select the camera.
See this WebRTC bug and mailing list post for more details.

How do I display the location of the user on a Google Map in HTML5?

I'm trying to put a Google map in my page and make it so that when the page loads the map will display exactly the location of the user. In order to do so, I've taken the google maps API code and inserted it into my HTML5 page. At first the browser did ask for permission to share my location but it isn't actually showing this location on the map; I've tried with two or more combinations of functions but it is still not working.... please, I need help! If anyone can tell me what is wrong with the code please do:
<html lang="en" manifest="halma.manifest">
<head>
<meta charset="utf-8">
<title>helmas</title>
<link rel="stylesheet" type="text/css" href="css2.css">
<script src="jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key=ABQIAAAAycdS3aS7dItIegOaJzT2RBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSiGkO1l1KdZvNzo-8b-o7M21o4UA"></script>
<!--[if IE]>
<script src="excanvas.js"></script>
<![endif]-->
</head>
<<body onload="loadMap()" onunload="GUnload()">
<article>
<div id="map" style="width:100%;height:800px;"></div>
<script>
if (navigator.geolocation) {
// try to get the users location
}
if (navigator.geolocation) {
var timeoutVal = 10 * 1000 * 1000;
navigator.geolocation.watchPosition(showPositionOnMap, errorMessage,
{ enableHighAccuracy: true, timeout: timeoutVal, maximumAge: 0 });
}
else {
alert("Geolocation is not supported by this browser");
}
var map = null;
function loadMap() {
map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(52.2021, 0.1346 ), 12); // (sets the map centre to Cambridge UK)
map.setUIToDefault();
}
function showPositionOnMap(position) {
var geoCoords = new GLatLng(position.coords.latitude, position.coords.longitude);
map.addOverlay(new GMarker(geoCoords));
}
function errorMessage(error) {
var errors = {
1: 'Permission denied',
2: 'Position unavailable',
3: 'Request timeout'
};
alert("Error: " + errors[error.code]);
}
</script>
Perhaps the sensor parameter in the maps invocation needs to be set to "true" - at the moment you have it set to "false". So your script tag should contain this url
<script src="http://maps.google.com/maps?file=api&v=2&sensor=true&key=ABQIAAAAycdS3aS7dItIegOaJzT2RBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSiGkO1l1KdZvNzo-8b-o7M21o4UA"></script>
For more info:
Google Maps Api sensor location