AR.js
AR.js copied to clipboard
multiple markers to place a image in same place..
i been trying to understand how i can use the old example from 2018(that works).. but i like to use the newer release, my result here can look quite messy... i tried generate one image, one pattern by https://ar-js-org.github.io/studio/ and it works great, the generated html code also looks clean, great. i modifiered the result and added new pattern letterB and it loaded the next image, works great.. But using multiple markers to place and keep image in same place was harder... i tried diffrent approaches
how would a multiple marker to place image in same place look like..?
Generated by AR-studio (one pattern, one image) but modified to add one more image...
<!doctype html>
<html>
<head>
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js"></script>
<script src="https://raw.githack.com/AR-js-org/studio-backend/master/src/modules/marker/tools/gesture-detector.js"></script>
<script src="https://raw.githack.com/AR-js-org/studio-backend/master/src/modules/marker/tools/gesture-handler.js"></script>
</head>
<body style="margin: 0; overflow: hidden;">
<a-scene
vr-mode-ui="enabled: false;"
loading-screen="enabled: false;"
arjs="trackingMethod: best; sourceType: webcam; debugUIEnabled: false;"
id="scene"
embedded
gesture-detector
>
<a-marker
id="animated-marker"
type="pattern"
preset="custom"
url="assets/letterA.patt"
raycaster="objects: .clickable"
emitevents="true"
cursor="fuse: false; rayOrigin: mouse;"
id="markerA"
>
<a-image
src="assets/asset.png"
scale="5 5 5"
class="clickable"
rotation="-90 0 0"
gesture-handler
></a-image>
</a-marker>
<a-marker
id="animated-marker2"
type="pattern"
preset="custom"
url="assets/letterB.patt"
raycaster="objects: .clickable"
emitevents="true"
cursor="fuse: false; rayOrigin: mouse;"
id="markerB"
>
<a-image
src="assets/asset2.png"
scale="5 5 5"
class="clickable"
rotation="-90 0 0"
gesture-handler
></a-image>
</a-marker>
<a-entity camera></a-entity>
</a-scene>
</body>
</html>
used three.js\examples\multi-markers\examples\player.html and grabbed this ARjsMultiMarkerFile but i am unsure how to use it....
{
"meta": {
"createdBy": "Area Learning - AR.js 3.4.0",
"createdAt": "2022-10-18T14:06:38.272Z"
},
"trackingBackend": "artoolkit",
"subMarkersControls": [
{
"parameters": {
"type": "pattern",
"patternUrl": "http://127.0.0.1/ARJS/three.js/examples/marker-training/examples/pattern-files/pattern-hiro.patt"
},
"poseMatrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
]
},
{
"parameters": {
"type": "pattern",
"patternUrl": "http://127.0.0.1/ARJS/three.js/examples/marker-training/examples/pattern-files/pattern-kanji.patt"
},
"poseMatrix": [
-0.9781551903813726,
0.19662227547793062,
-0.06746932364276789,
0,
0.1965871572636355,
0.9804597176475831,
0.0072252012489948236,
0,
0.0675715899959803,
-0.006196234253715697,
-0.9976951983947997,
0,
-1.4854915236843194,
0.08008392358066527,
-0.06471718489939211,
1
]
},
{
"parameters": {
"type": "pattern",
"patternUrl": "http://127.0.0.1/ARJS/three.js/examples/marker-training/examples/pattern-files/pattern-letterA.patt"
},
"poseMatrix": [
0.9941158209515499,
-0.06367972928824064,
0.08762792673215139,
0,
0.05693128984872921,
0.9953679395435098,
0.07746922034629011,
0,
-0.0921552511596545,
-0.07202460634141038,
0.9931363629072636,
0,
-1.526524370847054,
0.5263067663150608,
-3.662685636599042,
1
]
},
{
"parameters": {
"type": "pattern",
"patternUrl": "http://127.0.0.1/ARJS/three.js/examples/marker-training/examples/pattern-files/pattern-letterB.patt"
},
"poseMatrix": [
0.9987688935401889,
-0.04933614451918826,
-0.005161520722817482,
0,
0.04957907717350931,
0.9962099795472424,
0.07146740992075896,
0,
0.0016160319910011036,
-0.0716353294173569,
0.9974295796350606,
0,
-1.6382753629053766,
0.2418420516997672,
-2.0666450779165406,
1
]
}
]
}
below is the modified old examplecode(globe-multi-marker.html from stemkoskis github that works but using old releases.
<!DOCTYPE html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<title></title>
<script src='js/keyboard.js'></script>
<script src='js/three.js'></script>
<script src="jsartoolkit5/artoolkit.min.js"></script>
<script src="jsartoolkit5/artoolkit.api.js"></script>
<script src="threex/threex-artoolkitsource.js"></script>
<script src="threex/threex-artoolkitcontext.js"></script>
<script src="threex/threex-arbasecontrols.js"></script>
<script src="threex/threex-armarkercontrols.js"></script>
</head>
<body style='margin : 0px; overflow: hidden; font-family: Monospace;'>
<!--
Example created by Lee Stemkoski: https://github.com/stemkoski
Based on the AR.js library and examples created by Jerome Etienne: https://github.com/jeromeetienne/AR.js/
-->
<script>
var scene, camera, renderer, clock, deltaTime, totalTime, keyboard;
var arToolkitSource, arToolkitContext;
var markerNames, markerArray, currentMarkerName;
var sceneGroup;
var mesh1;
initialize();
animate();
function initialize()
{
scene = new THREE.Scene();
camera = new THREE.Camera();
scene.add(camera);
renderer = new THREE.WebGLRenderer({
antialias : true,
alpha: true
});
renderer.setClearColor(new THREE.Color('lightgrey'), 0)
renderer.setSize( 800, 600 );
renderer.domElement.style.position = 'absolute'
renderer.domElement.style.top = '0px'
renderer.domElement.style.left = '0px'
document.body.appendChild( renderer.domElement );
clock = new THREE.Clock();
deltaTime = 0;
totalTime = 0;
keyboard = new Keyboard();
////////////////////////////////////////////////////////////
// setup arToolkitSource
////////////////////////////////////////////////////////////
arToolkitSource = new THREEx.ArToolkitSource({
sourceType : 'webcam',
});
function onResize()
{
arToolkitSource.onResize()
arToolkitSource.copySizeTo(renderer.domElement)
if ( arToolkitContext.arController !== null )
{
arToolkitSource.copySizeTo(arToolkitContext.arController.canvas)
}
}
arToolkitSource.init(function onReady(){
onResize()
});
// handle resize event
window.addEventListener('resize', function(){
onResize()
});
////////////////////////////////////////////////////////////
// setup arToolkitContext
////////////////////////////////////////////////////////////
// create atToolkitContext
arToolkitContext = new THREEx.ArToolkitContext({
cameraParametersUrl: 'data/camera_para.dat',
detectionMode: 'mono',
maxDetectionRate: 30,
});
// copy projection matrix to camera when initialization complete
arToolkitContext.init( function onCompleted(){
camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() );
});
////////////////////////////////////////////////////////////
// setup markerRoots
////////////////////////////////////////////////////////////
markerNames = ["kanji", "letterA", "letterB", "letterC", "letterD"];
markerArray = [];
for (let i = 0; i < markerNames.length; i++)
{
let marker = new THREE.Group();
scene.add(marker);
markerArray.push(marker);
let markerControls = new THREEx.ArMarkerControls(arToolkitContext, marker, {
type: 'pattern', patternUrl: "data/" + markerNames[i] + ".patt",
});
let markerGroup = new THREE.Group();
marker.add(markerGroup);
}
////////////////////////////////////////////////////////////
// setup scene
////////////////////////////////////////////////////////////
sceneGroup = new THREE.Group();
let loader = new THREE.TextureLoader();
let geometry1 = new THREE.PlaneBufferGeometry(7,5, 4,4);
let texture = loader.load( 'images/globe.png' );
let material1 = new THREE.MeshBasicMaterial( { map: texture } );
mesh1 = new THREE.Mesh( geometry1, material1 );
mesh1.position.z = 2,5;
sceneGroup.add(mesh1);
markerArray[0].children[0].add( sceneGroup );
currentMarkerName = markerNames[0];
let pointLight = new THREE.PointLight( 0xffffff, 1, 5 );
camera.add( pointLight );
}
function update()
{
keyboard.update();
mesh1.rotation.x = -Math.PI/2;
let anyMarkerVisible = false;
for (let i = 0; i < markerArray.length; i++)
{
if ( markerArray[i].visible )
{
anyMarkerVisible = true;
markerArray[i].children[0].add( sceneGroup );
if ( currentMarkerName != markerNames[i] )
{
currentMarkerName = markerNames[i];
// console.log("Switching to " + currentMarkerName);
}
let p = markerArray[i].children[0].getWorldPosition();
let q = markerArray[i].children[0].getWorldQuaternion();
let s = markerArray[i].children[0].getWorldScale();
let lerpAmount = 0.5;
scene.add(sceneGroup);
sceneGroup.position.lerp(p, lerpAmount);
sceneGroup.quaternion.slerp(q, lerpAmount);
sceneGroup.scale.lerp(s, lerpAmount);
break;
}
}
if ( !anyMarkerVisible )
{
// console.log("No marker currently visible.");
}
let baseMarker = markerArray[0];
// update relative positions of markers
for (let i = 1; i < markerArray.length; i++)
{
let currentMarker = markerArray[i];
let currentGroup = currentMarker.children[0];
if ( baseMarker.visible && currentMarker.visible )
{
// console.log("updating marker " + i " -> base offset");
let relativePosition = currentMarker.worldToLocal( baseMarker.position.clone() );
currentGroup.position.copy( relativePosition );
let relativeRotation = currentMarker.quaternion.clone().inverse().multiply( baseMarker.quaternion.clone() );
currentGroup.quaternion.copy( relativeRotation );
}
}
// update artoolkit on every frame
if ( arToolkitSource.ready !== false )
arToolkitContext.update( arToolkitSource.domElement );
}
function render()
{
renderer.render( scene, camera );
}
function animate()
{
requestAnimationFrame(animate);
deltaTime = clock.getDelta();
totalTime += deltaTime;
update();
render();
}
</script>
</body>
</html>