提交 d4fa285d 编写于 作者: J Jerome Etienne

more on new API

上级 11245c10
## New API
- make each
- arjs-session.html - with a select input on trackingMethod
- pick real world with all trackingMethod
- hit tester with plane
- trackingMethod
- build a aframe version of that to see how it fit
- check it works on all cases
- no special cases incompatibilities
- full markers area
- learner
- option: markerhelper visibility
- reset area
- store defaultareaifneeded
- in tango
- make point cloud or not an live option
- DONE tango point cloud visible
- how to handle trackingMethod
- area-aruco
- area-artoolkit
- aruco
......@@ -11,6 +26,8 @@
- arkit
- best
## New API - no three.js dependancy
- first remove it externally
- then remove it internally
......
......@@ -17,44 +17,84 @@ ARjs.Anchor = function(arSession, markerParameters){
scene.add(markerRoot)
if( markerParameters.changeMatrixMode === 'modelViewMatrix' ){
var markerControls = new THREEx.ArMarkerControls(arContext, markerRoot, markerParameters)
var controlledObject = markerRoot
}else if( markerParameters.changeMatrixMode === 'cameraTransformMatrix' ){
var markerControls = new THREEx.ArMarkerControls(arContext, camera, markerParameters)
var controlledObject = camera
}else console.assert(false)
// FIXME tango - the pickability is on the marker
// - aka handle the object positioning in a special function of ArMarkerControls
// - arkitanchor is like ArMarkerControls
// - make it generic to work on plane too, if the marker is markerBased
if( markerParameters.markersAreaEnabled === false ){
var markerControls = new THREEx.ArMarkerControls(arContext, controlledObject, markerParameters)
}else{
// get multiMarkerFile from localStorage
console.assert( localStorage.getItem('ARjsMultiMarkerFile') !== null )
var multiMarkerFile = localStorage.getItem('ARjsMultiMarkerFile')
// build a multiMarkerControls
var multiMarkerControls = THREEx.ArMultiMarkerControls.fromJSON(arContext, scene, markerRoot, multiMarkerFile)
// build a smoothedControls
var smoothedRoot = new THREE.Group()
scene.add(smoothedRoot)
var smoothedControls = new THREEx.ArSmoothedControls(smoothedRoot)
// create ArMarkerHelper - useful to debug
var markerHelpers = []
multiMarkerControls.subMarkersControls.forEach(function(subMarkerControls){
// add an helper to visuable each sub-marker
var markerHelper = new THREEx.ArMarkerHelper(subMarkerControls)
markerHelper.object3d.visible = false
subMarkerControls.object3d.add( markerHelper.object3d )
// add it to markerHelpers
markerHelpers.push(markerHelper)
})
this.setSubMarkersVisibility = function(visible){
markerHelpers.forEach(function(markerHelper){
markerHelper.object3d.visible = visible
})
}
}
this.object3d = new THREE.Group()
// markerRoot.add(arWorldRoot)
smoothedRoot.add(this.object3d)
//////////////////////////////////////////////////////////////////////////////
// THREEx.ArSmoothedControls
//////////////////////////////////////////////////////////////////////////////
var shouldBeSmoothed = true
if( arContext.parameters.trackingBackend === 'tango' ) shouldBeSmoothed = false
if( shouldBeSmoothed === true ){
// build a smoothedControls
var smoothedRoot = new THREE.Group()
scene.add(smoothedRoot)
var smoothedControls = new THREEx.ArSmoothedControls(smoothedRoot)
smoothedRoot.add(this.object3d)
}else{
markerRoot.add(this.object3d)
}
this.update = function(){
//////////////////////////////////////////////////////////////////////////////
// Code Separator
//////////////////////////////////////////////////////////////////////////////
this.update = function(){
// update scene.visible if the marker is seen
if( markerParameters.changeMatrixMode === 'cameraTransformMatrix' ){
_this.object3d.visible = smoothedRoot.visible
_this.object3d.visible = controlledObject.visible
}
// update smoothedControls
smoothedControls.update(markerRoot)
}
if( smoothedControls !== undefined ){
// update smoothedControls parameters depending on how many markers are visible in multiMarkerControls
if( multiMarkerControls !== undefined ){
multiMarkerControls.updateSmoothedControls(smoothedControls)
}
// update smoothedControls
smoothedControls.update(markerRoot)
}
}
}
/**
* Apply ARjs.Session.HitTestResult to the controlled object3d
*
* @param {ARjs.Session.HitTestResult} hitTestResult - the result to apply
* @param {ARjs.HitTester.Result} hitTestResult - the result to apply
*/
ARjs.Anchor.prototype.applyHitTestResult = function(hitTestResult){
this.object3d.position.copy(hitTestResult.position)
......
// @namespace
var ARjs = ARjs || {}
/**
* Create an anchor in the real world
*
* @param {ARjs.Session} arSession - the session on which we create the anchor
* @param {Object} markerParameters - parameter of this anchor
*/
ARjs.HitTester = function(arSession){
this.arSession = arSession
}
/**
* Test the real world for intersections.
*
* @param {Number} mouseX - position X of the hit [-1, +1]
* @param {Number} mouseY - position Y of the hit [-1, +1]
* @return {[ARjs.HitTester.Result]} - array of result
*/
ARjs.HitTester.prototype.test = function(mouseX, mouseY){
var arContext = this.arSession.arContext
var hitTestResults = []
var result = THREEx.ARClickability.tangoPickingPointCloud(arContext, mouseX, mouseY)
if( result !== null ){
var scale = new THREE.Vector3(1,1,1).multiplyScalar(0.1)
var hitTestResult = new ARjs.HitTester.Result(result.position, result.quaternion, scale)
hitTestResults.push(hitTestResult)
}
// TODO use clickability
return hitTestResults
}
/**
* Contains the result of ARjs.HitTester.test()
*
* @param {THREE.Vector3} position - position to use
* @param {THREE.Quaternion} quaternion - quaternion to use
* @param {THREE.Vector3} scale - scale
*/
ARjs.HitTester.Result = function(position, quaternion, scale){
this.position = position
this.quaternion = quaternion
this.scale = scale
}
var ARjs = ARjs || {}
function arSession_usage_example(){
var arSession = new ARjs.Session({
scene: scene,
renderer: renderer,
camera: camera,
sourceParameters: sourceParameters,
contextParameters: contextParameters
})
var arAnchor = new ARjs.Anchor(arSession, parameters)
var intersects = asSession.hitTest(mouseX, mouseY)
// intersects is an array of ARjs.HitTestingResult = function(position, quaternion, scale){}
// similar intersects that three.js raycasting
arAnchor.applyHitTestResult(intersects[0])
}
/**
* define a ARjs.Session
*
......@@ -72,40 +54,3 @@ ARjs.Session = function(parameters){
arContext.update( arSource.domElement )
}
}
//////////////////////////////////////////////////////////////////////////////
// Hit Testing
//////////////////////////////////////////////////////////////////////////////
/**
* Test the real world for intersections.
*
* @param {Number} mouseX - position X of the hit [-1, +1]
* @param {Number} mouseY - position Y of the hit [-1, +1]
* @return {[ARjs.Session.HitTestResult]} - array of HitTestResult
*/
ARjs.Session.prototype.hitTest = function(mouseX, mouseY){
var intersects = []
var result = THREEx.ARClickability.tangoPickingPointCloud(this.arContext, mouseX, mouseY)
if( result !== null ){
intersects.push(new ARjs.Session.HitTestResult(result.position, result.quaternion, new THREE.Vector3(1,1,1).multiplyScalar(0.1)))
}
// TODO use clickability
return intersects
}
/**
* Contains the result of arSession.hitTest.
*
* @param {THREE.Vector3} position - position to use
* @param {THREE.Quaternion} quaternion - quaternion to use
* @param {THREE.Vector3} scale - scale
* @return {[type]} [description]
*/
ARjs.Session.HitTestResult = function(position, quaternion, scale){
this.position = position
this.quaternion = quaternion
this.scale = scale
}
// @namespace
var ARjs = ARjs || {}
ARjs.TangoPointCloud = function(arSession){
var _this = this
var arContext = arSession.arContext
this.object3d = new THREE.Group
console.warn('Work only on cameraTransformMatrix - fix me - useless limitation')
arContext.addEventListener('initialized', function(event){
var vrPointCloud = arContext._tangoContext.vrPointCloud
var geometry = vrPointCloud.getBufferGeometry()
var material = new THREE.PointsMaterial({
size: 0.01,
// colorWrite: false, // good for occlusion
depthWrite: false,
})
var pointsObject = new THREE.Points(geometry, material)
// Points are changing all the time so calculating the frustum culling volume is not very convenient.
pointsObject.frustumCulled = false;
pointsObject.renderDepth = 0;
_this.object3d.add(pointsObject)
})
}
......@@ -25,6 +25,10 @@ ARjs.TangoVideoMesh = function(arSession){
sceneOrtho.add(videoMesh)
})
//////////////////////////////////////////////////////////////////////////////
// Code Separator
//////////////////////////////////////////////////////////////////////////////
this.update = function(){
// sanity check
console.assert( arContext.parameters.trackingBackend === 'tango' )
......@@ -34,6 +38,10 @@ ARjs.TangoVideoMesh = function(arSession){
THREE.WebAR.updateCameraMeshOrientation(vrDisplay, videoMesh)
}
//////////////////////////////////////////////////////////////////////////////
// Code Separator
//////////////////////////////////////////////////////////////////////////////
this.render = function(){
// sanity check
console.assert( arContext.parameters.trackingBackend === 'tango' )
......
......@@ -6,7 +6,8 @@ ARjs.Utils = {}
* @param {string} trackingBackend - the tracking to user
* @return {THREE.Camera} the created camera
*/
ARjs.Utils.createDefaultCamera = function(trackingBackend){
ARjs.Utils.createDefaultCamera = function(trackingMethod){
var trackingBackend = this.parseTrackingMethod(trackingMethod).trackingBackend
// Create a camera
if( trackingBackend === 'artoolkit' ){
var camera = new THREE.Camera();
......@@ -28,3 +29,18 @@ ARjs.Utils.isTango = function(){
var isTango = navigator.userAgent.match('Chrome/57.0.2987.5') !== null ? true : false
return isTango
}
ARjs.Utils.parseTrackingMethod = function(trackingMethod){
if( trackingMethod.startsWith('area-') ){
return {
trackingBackend : trackingMethod.replace('area-', ''),
markersAreaEnabled : true,
}
}else{
return {
trackingBackend : trackingMethod,
markersAreaEnabled : false,
}
}
}
......@@ -18,12 +18,15 @@
<script src='../arjs-utils.js'></script>
<script src='../arjs-session.js'></script>
<script src='../arjs-anchor.js'></script>
<script src='../arjs-hittester.js'></script>
<script src='../arjs-tangovideomesh.js'></script>
<script src='../arjs-tangopointcloud.js'></script>
<script src='../threex-artoolkitsource.js'></script>
<script src='../threex-artoolkitcontext.js'></script>
<script src='../threex-artoolkitprofile.js'></script>
<script src='../threex-arbasecontrols.js'></script>
<script src='../threex-armarkercontrols.js'></script>
<script src='../threex-armarkerhelper.js'></script>
<script src='../threex-arsmoothedcontrols.js'></script>
<script src='../threex-arclickability.js'></script>
<script>THREEx.ArToolkitContext.baseURL = '../'</script>
......@@ -42,41 +45,36 @@
/
<a href='../../three.js/threex/threex-aruco/examples/images/1001.png' target='_blank'>1001 for aruco</a>
<br/>
<strong>Tracking Backend:</strong> <span id='currentTracking'>unknown</span>
<strong>Tracking Method:</strong> <span id='trackingMethod'>unknown</span>
-
Switch to :
<a href='#artoolkit' onclick='location.reload()'>artoolkit</a>
/
<a href='#aruco' onclick='location.reload()'>aruco</a>
/
<a href='#area-artoolkit' onclick='location.reload()'>area artoolkit</a>
/
<a href='#area-aruco' onclick='location.reload()'>area aruco</a>
/
<a href='#tango' onclick='location.reload()'>tango</a>
/
<a href='#best' onclick='location.reload()'>best</a>
</div><script>
;(function(){
// TODO put that in a function
var trackingMethod = location.hash.substring(1) ? location.hash.substring(1) : 'best'
if( trackingMethod === 'best' ){
var trackingMethod = ARjs.Utils.isTango() ? 'tango' : 'area-artoolkit'
}
var trackingBackend = location.hash.substring(1) ? location.hash.substring(1) : 'artoolkit'
document.querySelector('#currentTracking').innerHTML = trackingBackend
// if we are running on tango device, ensure trackingBackend is 'tango'
if( trackingBackend !== 'tango' && ARjs.Utils.isTango() === true ){
location.hash = '#tango'
location.reload()
if( trackingMethod.startsWith('area-') ){
var trackingBackend = trackingMethod.replace('area-', '')
}else{
var trackingBackend = trackingMethod
}
// - aruco-area
// - artoolkit-area
// - trackingMethod=
// - trackingBackend=
//
// - thus you got the whole stack available here
// - it dramatically reduce the boilerplate
// - it is the base of the aframe ar.js, the base of webar-playground
// - maybe put all that in a class
// - this is the base of a typical AR.js application - aka support all tracking transparantly
//
// TODO is that required ?
var changeMatrixMode = 'cameraTransformMatrix'
// var changeMatrixMode = 'modelViewMatrix'
document.querySelector('#trackingMethod').innerHTML = trackingMethod
//////////////////////////////////////////////////////////////////////////////////
// Init
......@@ -89,7 +87,7 @@
});
renderer.autoClear = false;
renderer.setClearColor(new THREE.Color('lightgrey'), 0)
renderer.setSize( 640, 480 );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.domElement.style.position = 'absolute'
renderer.domElement.style.top = '0px'
renderer.domElement.style.left = '0px'
......@@ -105,7 +103,7 @@
// Initialize the camera
//////////////////////////////////////////////////////////////////////////////////
var camera = ARjs.Utils.createDefaultCamera(trackingBackend)
var camera = ARjs.Utils.createDefaultCamera(trackingMethod)
scene.add(camera);
////////////////////////////////////////////////////////////////////////////////
......@@ -114,15 +112,23 @@
var arProfile = new THREEx.ArToolkitProfile()
.sourceWebcam()
.trackingBackend(trackingBackend)
.defaultMarker(trackingBackend)
.trackingMethod(trackingMethod)
.defaultMarker()
// FIXME temporary placeholder - to reevaluate later
if( trackingBackend === 'tango' ){
if( trackingMethod === 'tango' ){
arProfile.sourceImage(THREEx.ArToolkitContext.baseURL + '../data/images/img.jpg')
}
// honor changeMatrixMode
arProfile.defaultMarkerParameters.changeMatrixMode = 'cameraTransformMatrix'
// arProfile.defaultMarkerParameters.changeMatrixMode = 'modelViewMatrix'
//////////////////////////////////////////////////////////////////////////////
// build ARjs.Session
//////////////////////////////////////////////////////////////////////////////
var arSession = new ARjs.Session({
scene: scene,
renderer: renderer,
......@@ -133,14 +139,10 @@
onRenderFcts.push(function(){
arSession.update()
})
var arContext = arSession.arContext
////////////////////////////////////////////////////////////////////////////////
// Create a ArMarkerControls
////////////////////////////////////////////////////////////////////////////////
// honor changeMatrixMode
arProfile.defaultMarkerParameters.changeMatrixMode = changeMatrixMode
var arAnchor = new ARjs.Anchor(arSession, arProfile.defaultMarkerParameters)
onRenderFcts.push(function(){
......@@ -151,22 +153,30 @@
// handle videoMesh for tango
//////////////////////////////////////////////////////////////////////////////
if( trackingBackend === 'tango' ){
var videoMeshTango = new ARjs.TangoVideoMesh(arSession)
if( trackingMethod === 'tango' ){
var tangoVideoMesh = new ARjs.TangoVideoMesh(arSession)
onRenderFcts.push(function(){
videoMeshTango.update()
tangoVideoMesh.update()
})
}
if( trackingMethod === 'tango' ){
var tangoPointCloud = new ARjs.TangoPointCloud(arSession)
scene.add(tangoPointCloud.object3d)
}
var hitTester = new ARjs.HitTester(arSession)
// tango only - picking to set object position
renderer.domElement.addEventListener("click", function(event) {
var arContext = arSession.arContext
if( arContext.parameters.trackingBackend !== 'tango' ) return
var mousePosition = new THREE.Vector3()
mousePosition.x = event.pageX / window.innerWidth
mousePosition.y = event.pageY / window.innerHeight
var mouseX = event.pageX / window.innerWidth
var mouseY = event.pageY / window.innerHeight
var hitTestResults = arSession.hitTest(mousePosition.x, mousePosition.y)
var hitTestResults = hitTester.test(mouseX, mouseY)
if( hitTestResults.length === 0 ) return
var hitTestResult = hitTestResults[0]
......@@ -211,8 +221,8 @@
renderer.clear()
// render videoMesh for tango
if( arContext.parameters.trackingBackend === 'tango'){
videoMeshTango.render()
if( trackingMethod === 'tango' ){
tangoVideoMesh.render()
}
renderer.render( scene, camera );
......
......@@ -174,7 +174,7 @@
onRenderFcts.push(function(){
// Update the point cloud. Only if the point cloud will be shown the
// geometry is also updated.
vrPointCloud.update(parameters.showPointCloud, parameters.pointsToSkip)
vrPointCloud.update(parameters.showPointCloud, parameters.pointsToSkip, true)
})
// handle datGUI
datGUI.add(parameters, 'showPointCloud').onFinishChange(function(value) {
......
var THREEx = THREEx || {}
// TODO this is useless - prefere arjs-hittester.js
/**
* - maybe support .onClickFcts in each object3d
* - seems an easy light layer for clickable object
......@@ -11,6 +13,8 @@ THREEx.ARClickability = function(sourceElement){
var fullWidth = parseInt(sourceElement.style.width)
var fullHeight = parseInt(sourceElement.style.height)
this._cameraPicking = new THREE.PerspectiveCamera(42, fullWidth / fullHeight, 0.1, 100);
console.warn('THREEx.ARClickability works only in modelViewMatrix')
}
THREEx.ARClickability.prototype.onResize = function(){
......@@ -50,7 +54,7 @@ THREEx.ARClickability.prototype.update = function(){
THREEx.ARClickability.tangoPickingPointCloud = function(artoolkitContext, mouseX, mouseY){
var vrDisplay = artoolkitContext._tangoContext.vrDisplay
if (vrDisplay === null ) return
if (vrDisplay === null ) return null
var pointAndPlane = vrDisplay.getPickingPointAndPlaneInPointCloud(mouseX, mouseY)
if( pointAndPlane == null ) {
console.warn('Could not retrieve the correct point and plane.')
......
......@@ -48,7 +48,8 @@ THREEx.ArToolkitProfile.prototype.reset = function () {
}
this.defaultMarkerParameters = {
type : 'pattern',
patternUrl : THREEx.ArToolkitContext.baseURL + '../data/data/patt.hiro'
patternUrl : THREEx.ArToolkitContext.baseURL + '../data/data/patt.hiro',
changeMatrixMode: 'modelViewMatrix',
}
return this
};
......@@ -139,6 +140,26 @@ THREEx.ArToolkitProfile.prototype.sourceImage = function (url) {
// trackingBackend
//////////////////////////////////////////////////////////////////////////////
THREEx.ArToolkitProfile.prototype.trackingBackend = function (trackingBackend) {
console.warn('use profile.trackingBackend() obsolete function')
this.contextParameters.trackingBackend = trackingBackend
return this
}
//////////////////////////////////////////////////////////////////////////////
// trackingBackend
//////////////////////////////////////////////////////////////////////////////
THREEx.ArToolkitProfile.prototype.trackingMethod = function (trackingMethod) {
if( trackingMethod.startsWith('area-') ){
var trackingBackend = trackingMethod.replace('area-', '')
var markersAreaEnabled = true
}else{
var trackingBackend = trackingMethod
var markersAreaEnabled = false
}
this.defaultMarkerParameters.markersAreaEnabled = markersAreaEnabled
this.contextParameters.trackingBackend = trackingBackend
return this
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册