<!DOCTYPE html> <html> <title>SpaSca : Spatial Scaffolding</title> <head> <!-- Suggestions? https://git.benetou.fr/utopiah/text-code-xr-engine/issues/ --> <!--<script src='dependencies/aframe.min.js'></script>--> <script src='dependencies/aframe.offline.min.js'></script> <script src="dependencies/a-console.js"></script> <script src='dependencies/aframe-html.js'></script> <script src='dependencies/aframe-mirror.js'></script> <script src='dependencies/aframe-troika-text.min.js'></script> <!--<script type="module" id=immersbundle src='dependencies/immers-client.js?save=true'></script>--> <!--<script type="module" id=immersbundle src="https://cdn.jsdelivr.net/npm/immers-client/dist/destination.bundle.js?role=modFull"></script>--> <!--<script src="https://threejs.org/examples/js/exporters/GLTFExporter.js"></script>--> <script src="https://cdn.jsdelivr.net/gh/c-frame/aframe-extras@7.1.0/dist/aframe-extras.min.js"></script> <script src="dependencies/shiki0.14.1.js"></script> <!-- for input sharing --> <script src='dependencies/peerjs.min.js'></script> <!-- for content sharing, using NAF <script src='dependencies/socket.io.slim.js'></script> <script src="https://naf.benetou.fr/easyrtc/easyrtc.js"></script> <script src='dependencies/networked-aframe.min.js'></script> --> <script src="dependencies/aframe-physics-system.min.js"></script> <!-- still experimenting, see webdav.html --> <script src='dependencies/webdav.js'></script> <script src='jxr.js?12345'></script> <!-- replacing with local copies as CDNs are like unpkg tend to be slow <script type="module" src="https://unpkg.com/immers-client/dist/destination.bundle.js"></script> <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script> <script src="https://unpkg.com/aframe-troika-text/dist/aframe-troika-text.min.js"></script> <script src="aframe-html.js"></script> <script src="https://unpkg.com/peerjs@1.4.5/dist/peerjs.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.4.0/socket.io.slim.js"></script> <script src="https://naf.benetou.fr/easyrtc/easyrtc.js"></script> <script src="https://unpkg.com/networked-aframe@^0.10.0/dist/networked-aframe.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/aframe-mirror@latest/index.js"></script> --> <link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png"> <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png"> <link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png"> <link rel="manifest" href="site.webmanifest"> </head> <body> <div style='position:fixed;z-index:1; top: 0%; left: 0%; border-bottom: 70px solid transparent; border-left: 70px solid #eee; '> <a href="https://git.benetou.fr/utopiah/text-code-xr-engine/issues/"> <img style='position:fixed;left:10px;' title='code repository' src='gitea_logo.svg'> </a> </div> <div> <div id="observablehq-numberOfPages-835aa7e9"></div> <div id="observablehq-result_as_html-ab4c1560"></div> </div> <div id="observablehq-key"> <div id="observablehq-viewof-offsetExample-ab4c1560"></div> <div id="observablehq-result_as_html-ab4c1560"></div> </div> <button id=mainbutton style="display:none; z-index: 1; position: absolute; width:50%; margin: auto; text-align:center; top:45%; left:30%; height:30%;" onclick="startExperience()">Start the experience (hand tracking recommended)</button> <a-scene cursor="rayOrigin: mouse" raycaster="objects: [html]; interval:100;" adjust-height-in-vr startfunctions disable-components-via-url enable-components-via-url NOcommands-from-external-json> <!-- screenstack dynamic-view selectionboxonpinches glossary timeline issues fot toolbox physics="debug:true; friction: 0.01;" networked-scene="serverURL: https://naf.benetou.fr/; adapter: easyrtc; audio: true;" refresh-text-content-from-wiki-page="pagename:TestingPairCollaboration" --> <a-assets> <template id="avatar-template"></template> <template id="left-hand-default-template"> <a-entity networked-hand-controls="hand:left"></a-entity> </template> <template id="right-hand-default-template"> <a-entity networked-hand-controls="hand:right"></a-entity> </template> </a-assets> <a-entity id="rig"> <a-entity id="player" networked="template:#avatar-template;attachTemplateToLocal:false;" hud camera look-controls wasd-controls waistattach="target: .movebypinch" position="0 1.6 0"> <a-troika-text odometer value="odometer" position="0 -0.5 -0.9" rotation="-10 0 0"></a-troika-text> </a-entity> <a-entity id="rightHand" pinchprimary hand-tracking-controls="hand: right;"> </a-entity> <a-entity id="leftHand" pinchsecondary wristattachsecondary="target: #box" hand-tracking-controls="hand: left;"></a-entity> </a-entity> <script> let positions = [] AFRAME.registerComponent('odometer',{ init: function () { this.tick = AFRAME.utils.throttleTick(this.tick, 50, this); }, tick: function () { let el = this.el let pos = document.getElementById('player').getAttribute('position').clone() positions.push( pos ) if (positions.length > 20) { let dist = pos.distanceTo( positions[positions.length-20] ) //console.log(dist) // could be done via setFeedbackHUD() instead el.setAttribute('value', dist.toFixed(2)) } }}) AFRAME.registerComponent('wristright',{ init: function () { var el = this.el this.worldPosition=new THREE.Vector3(); }, tick: function () { var worldPosition=this.worldPosition; document.querySelector("#rightHand").object3D.traverse( e => { if (e.name == "wrist") { worldPosition.copy(e.position);e.parent.updateMatrixWorld();e.parent.localToWorld(worldPosition) rotation = e.rotation.x*180/3.14 + " " + e.rotation.y*180/3.14 + " " + e.rotation.z*180/3.14 this.el.setAttribute("rotation", rotation) this.el.setAttribute("position", AFRAME.utils.coordinates.stringify( worldPosition ) ) } }) }, }); </script> <a-box pressable start-on-press id="box" scale="0.05 0.05 0.05" color="pink"> <a-entity collider-check raycaster="objects: .collidable; showLine:true;" ></a-entity> </a-box> <!-- could attach functions here... BUT then they have to be activable with the other hand! --> <!-- visual reminders of shortcuts, a poster on the far left/right of keyboard shortcuts --> <a-entity light="type: ambient; color: #BBB; intensity: 0.6"></a-entity> <a-entity light="type: directional; color: #FFF; intensity: 1.4" position="-0.5 1 1"></a-entity> <a-troika-text value="SpaSca : Spatial Scaffolding" anchor="left" outline-width="5%" font="../content/ChakraPetch-Regular.ttf" position="-5.26197 6.54224 -1.81284" scale="4 4 5" rotation="90 0 0" troika-text="outlineWidth: 0.01; strokeColor: #ffffff" material="flatShading: true; blending: additive; emissive: #c061cb"></a-troika-text> <a-sky hide-on-enter-ar color="lightgray"></a-sky> <a-entity hide-on-enter-ar="" id="environment" class="hidableenvironment" ></a-entity> <a-entity hide-on-enter-ar="" id="environmentsky" class="hidableenvironment" ></a-entity> <a-troika-text anchor=left target value="instructions : \n--right pinch to move\n--left pinch to execute" position="0 0.65 -0.2" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target id="locationreload" value="jxr location.reload()" position="0 1.20 -0.1" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target id="makeAnchorsVisibleOnTargets" value="jxr makeAnchorsVisibleOnTargets()" position="0 1.05 -0.1" scale="0.1 0.1 0.1"></a-troika-text> <!-- <a-troika-text anchor=left target id="startdraw2d" annotation="content:dessiner en 2D" value="jxr startDraw2D()" position="0 1.45 -0.1" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target id="displaypred" value="jxr displayPred()" position="0 1.40 -0.1" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target value="jxr tiltUpId('codeditor')" position=" -0.3 1.65 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target value="jxr tiltDownId('codeditor')" position=" -0.3 1.60 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text> --> <a-troika-text anchor=left target value="jxr pushLeftClass('reader')" position=" -0.3 1.55 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target value="jxr pushRightClass('reader')" position=" -0.3 1.50 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target value="jxr pushUpClass('reader')" position=" -0.3 1.45 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target value="jxr pushDownClass('reader')" position=" -0.3 1.40 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target value="jxr pushBackClass('reader')" position=" -0.3 1.35 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text> <a-troika-text anchor=left target value="jxr pushFrontClass('reader')" position=" -0.3 1.30 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text> <!-- somehow disable hand interaction despite, according to the documentation, it should rely on world position <a-text target value="jxr qs #rig sa position 0 0 10" position="0 1.55 .5" rotation="0 180 0" scale="0.1 0.1 0.1"></a-text> --> <a-console position="2 2 0" rotation="0 -45 0" font-size="34" height=1 skip-intro=true></a-console> <!-- as with NAF can't attach if no pos to inherit from...--> <!-- <a-entity wristright> <a-box scale=".1 2 .01" static-body="mass:10" ></a-box> </a-entity> <a-entity visible="false" gltf-model="src: ../content/HockeyStickAlt.glb" NObody="type: dynamic; mass: 5; shape: hull;" position="0 2 -1"></a-entity> <a-gltf-model id="stick" NOwristright NOdynamic-body originsrc="https://poly.pizza/m/NQnXoyeezy" src="../content/HockeyStickAlt.glb" scale=".5 .5 .5" position="0 1 -1.2" rotation="0 0 0" ></a-gltf-model> <a-gltf-model hide-on-enter-ar="" visible=false src="../content/room.gltf" position="0 0 0" rotation="0 0 0" ></a-gltf-model> <a-gltf-model hide-on-enter-ar="" visible=false src="../content/kitchen.gltf" position=".5 0 0" rotation="0 110 0" ></a-gltf-model> <a-cylinder id="puck" dynamic-body="mass:.1" position="0 3 -.5" color="black" height=".02" radius="0.04"></a-cylinder> <a-plane rotation="-90 0 0" scale="5 5 5" position="0 0 0" opacity=.01 static-body></a-plane> --> <!-- map in HUD --> <!-- visual odometer as rotation changing arrow below arc in HUD --> <!-- now movable but should snap to floor, consider on-drop --> <a-cone changeover="color:red" target position="0 0.1 -1.0" color="blue" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> <a-cone changeover="color:red" target position="0 0.1 -1.0" color="blue" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> <a-cone changeover="color:red" target position="0 0.1 -1.4" color="blue" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> <a-cone changeover="color:red" target position="0 0.1 -1.8" color="blue" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> <a-cone changeover="color:red" target position="0 0.1 -2.2" color="blue" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> <a-cone changeover="color:red" target position="0 0.1 -2.6" color="blue" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> <a-cone changeover="color:red" target position="0 0.1 -3.0" color="blue" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> <a-torus position="0 0 -3" arc="180" color="#43A367" radius=".5" scale="1 4 1" height="10" radius-tubular="0.01"></a-torus> <a-torus position="0 1 -5" color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="0 2 -7" color="#43A367" radius=".5" radius-tubular="0.01"></a-torus> <a-torus position="0 1 -5" color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="0 1 -6" color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="0 1 -7" color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-1 1 -8" rotation="0 20 0" color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-2 1 -9" rotation="0 40 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-3 1 -10" rotation="0 60 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-4 1 -11" rotation="0 80 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-5 1 -12" rotation="0 90 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-6 1 -12" rotation="0 90 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-8 1 -12" rotation="0 90 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-10 1 -12" rotation="0 90 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-15 1 -12" rotation="0 90 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-torus position="-20 1 -12" rotation="0 90 0"color="#43A367" radius="1" radius-tubular="0.01"></a-torus> <a-entity class="workcone" scale=".2 .5 .2" position="0.5 0 -1"> <a-cone position="0 0.2 0" color="darkorange" height=".4" radius-bottom="0.2" radius-top="0.02"></a-cone> <a-cone position="0 0.2 0" color="white" height=".2" radius-bottom="0.15" radius-top="0.07"></a-cone> <a-cone position="0 0.1 0" color="white" height=".1" radius-bottom="0.18" radius-top="0.14"></a-cone> <a-box color="darkorange" scale=".5 .02 .5" position="0 0 0"></a-box> </a-entity> <a-entity class="workcone" scale=".5 1 .5" position="-.5 0 -1"> <a-cone position="0 0.2 0" color="darkorange" height=".4" radius-bottom="0.2" radius-top="0.02"></a-cone> <a-cone position="0 0.2 0" color="white" height=".2" radius-bottom="0.15" radius-top="0.07"></a-cone> <a-cone position="0 0.1 0" color="white" height=".1" radius-bottom="0.18" radius-top="0.14"></a-cone> <a-box color="darkorange" scale=".5 .02 .5" position="0 0 0"></a-box> </a-entity> <a-entity class="workcone" position="0 0 -3"> <a-cone position="0 0.2 0" color="darkorange" height=".4" radius-bottom="0.2" radius-top="0.02"></a-cone> <a-cone position="0 0.2 0" color="white" height=".2" radius-bottom="0.15" radius-top="0.07"></a-cone> <a-cone position="0 0.1 0" color="white" height=".1" radius-bottom="0.18" radius-top="0.14"></a-cone> <a-box color="darkorange" scale=".5 .02 .5" position="0 0 0"></a-box> </a-entity> <a-triangle color="red" position="0 .01 0" rotation="-90 0 0"></a-triangle> <a-entity target class="workcone" position="0 0 -.1"> <a-cone position="0 0.2 0" color="darkorange" height=".4" radius-bottom="0.2" radius-top="0.02"></a-cone> <a-cone position="0 0.2 0" color="blue" height=".2" radius-bottom="0.15" radius-top="0.07"></a-cone> <a-cone position="0 0.1 0" color="white" height=".1" radius-bottom="0.18" radius-top="0.14"></a-cone> <a-box color="darkorange" scale=".5 .02 .5" position="0 0 0"></a-box> </a-entity> <a-entity visible="false" class="widget" position="0 1 -1"> <a-entity target class="arrow" position="0 0 0" rotation="0 0 -90"> <a-cylinder color="red" height=".2" radius="0.01"></a-cylinder> <a-cone position="0 0.1 0" color="red" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> </a-entity> <a-entity target class="arrow" position="0 0 0" rotation="0 0 0"> <a-cylinder color="green" height=".2" radius="0.01"></a-cylinder> <a-cone position="0 0.1 0" color="green" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> </a-entity> <a-entity target class="arrow" position="0 0 0" rotation="90 0 0"> <a-cylinder color="blue" height=".2" radius="0.01"></a-cylinder> <a-cone position="0 0.1 0" color="blue" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> </a-entity> </a-entity> <a-entity target class="arrow" position="0 1 -5" rotation="-45 0 0"> <a-cylinder color="red" height=".2" radius="0.01"></a-cylinder> <a-cone position="0 0.1 0" color="red" height=".2" radius-bottom="0.02" radius-top="0"></a-cone> </a-entity> <!-- opacity can be changed based on time, e.g gradually do so after 1min, or distance, e.g .1 opacity if close to walls --> <a-entity visible="false" id="mrbottomlessskybox"> <a-box visible="false" scale="10 3 .1" src="../content/lcm-skyline.jpg" position="0 1.5 -3"></a-box> <a-box visible="false" scale="10 3 .1" src="../content/lcm-skyline.jpg" position="0 1.5 5"></a-box> <a-box visible="false" scale=".1 3 10" src="../content/lcm-skyline.jpg" position="-2 1.5 0"></a-box> <a-box visible="false" scale=".1 3 10" src="../content/lcm-skyline.jpg" position="2 1.5 0"></a-box> <a-box visible="false" scale="10 .1 10" src="../content/lcm-skycloudy.jpg" position="0 3 0"></a-box> </a-entity> <!-- bottomless skybox motivation https://twitter.com/utopiah/status/1719777887987937477 --> <a-entity visible="false" id="mrbottomless3Dmodels"> <a-gltf-model originsrc="https://poly.pizza/m/ecGdK1XryiQ" src="../content/WoodenFence.glb" position="-1 0 -1" rotation="0 0 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/ecGdK1XryiQ" src="../content/WoodenFence.glb" position="-1 0 1" rotation="0 0 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/ecGdK1XryiQ" src="../content/WoodenFence.glb" position="1 0 -1" rotation="0 0 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/ecGdK1XryiQ" src="../content/WoodenFence.glb" position="1 0 1" rotation="0 0 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/ecGdK1XryiQ" src="../content/WoodenFence.glb" position="0 0 -2" rotation="0 90 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/ecGdK1XryiQ" src="../content/WoodenFence.glb" position="0 0 2" rotation="0 90 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/38m6Q1H12DU" src="../content/WalkInTheWoods.glb" scale="5 5 5" position="0 1 -6" rotation="0 -12.1 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/38m6Q1H12DU" src="../content/WalkInTheWoods.glb" scale="5 5 5" position="0 1 5.3" rotation="0 -12.1 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/38m6Q1H12DU" src="../content/WalkInTheWoods.glb" scale="5 5 5" position="-4 1 -1.2" rotation="0 -12.1 0" ></a-gltf-model> <a-gltf-model originsrc="https://poly.pizza/m/38m6Q1H12DU" src="../content/WalkInTheWoods.glb" scale="5 5 5" position="4 1 -1.2" rotation="0 -12.1 0" ></a-gltf-model> <a-sphere color="lightblue" geometry="radius: 6; thetaLength: 90" material="side: back; shader: flat;"></a-sphere> </a-entity> <a-troika-text anchor=left pull="callback:forwardPullMultiplePages" target value=">>" position="0.2 1.2 -.8" rotation="0 0 0" scale="1 1 1"></a-troika-text> <a-box scale="0.1 0.01 30" position="-27 0.01 0" color="blue"></a-box> <a-box scale="0.1 0.01 30" position="27 0.01 0" color="blue"></a-box> <a-box scale="0.1 0.01 30" position="-9 0.01 0" color="blue"></a-box> <a-box scale="0.1 0.01 30" position="0 0.01 0" color="blue"></a-box> <a-box scale="0.1 0.01 30" position=" 9 0.01 0" color="blue"></a-box> <a-box hide-on-enter-ar="" scale="60 0.01 30" color="lightblue"></a-box> <a-box position="-1 1.6 -5" animation="property: position; to: 1 8 -10; dir: alternate; dur: 2000; easing: linear; loop: true" color="tomato"></a-box> <a-entity gltf-jxr gltf-model="url(../content/PopsicleChocolate-jxr.glb)" position="-.6 1.5 0"></a-entity> <a-tube control-points path="0 1 0,-5 1 -7,-20 1 -12,-25 1 0,-25 1 10,0 1 10,25 1 12,25 1 -12,-5 1 -12" radius="1" material="color: red;wireframe:true"></a-tube> <a-entity levels-to-load> <a-tube path="0 1 0,-5 1 -7,-20 1 -12,-25 1 0,-25 1 10,0 1 10,25 1 12,25 1 -12,-5 1 -12" radius="1" material="color: red;wireframe:true"></a-tube> <a-tube path="0 1 0,-5 1 -7,-20 1 -12,-25 1 0,-5 1 10,0 1 10,25 1 12,25 1 -12,-5 1 -12" radius="1" material="color: green;wireframe:true"></a-tube> <a-tube path="0 1 0,-5 1 -7,-20 1 -12,-25 1 0,-25 1 10,0 1 10,25 1 12,5 1 -2,-5 1 -12" radius="1" material="color: blue;wireframe:true"></a-tube> </a-entity> </a-scene> </body> </script> </html>