|
|
|
@ -3,7 +3,9 @@ |
|
|
|
|
<title>SpaSca : Spatial Scaffolding</title> |
|
|
|
|
<head> |
|
|
|
|
<!-- Suggestions? https://git.benetou.fr/utopiah/text-code-xr-engine/issues/ --> |
|
|
|
|
<script src='dependencies/aframe.offline.min.js'></script> |
|
|
|
|
<!-- 1.6 needed for real-world-meshing <script src='dependencies/aframe.offline.min.js'></script>--> |
|
|
|
|
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script> |
|
|
|
|
|
|
|
|
|
<script src="dependencies/a-console.js"></script> |
|
|
|
|
<script src='dependencies/aframe-troika-text.min.js'></script> |
|
|
|
|
<script src='dependencies/webdav.js'></script> |
|
|
|
@ -13,121 +15,12 @@ |
|
|
|
|
<body> |
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
|
|
|
|
|
|
//________________________________________________________________ |
|
|
|
|
const endpointDomainOrIP = '192.168.0.129' // note that if the certificate is NOT proper, then consider opening it first to accept it on device |
|
|
|
|
// e.g https://hmd.link/?https://192.168.0.129:8443/ |
|
|
|
|
const endpoint = 'https://'+endpointDomainOrIP+':8443/' // unfortunately not public yet due to API usage on poly.pizza |
|
|
|
|
|
|
|
|
|
function getModelFromKeyword(keyword){ |
|
|
|
|
fetch(endpoint+"search?keyword="+keyword) |
|
|
|
|
.then(r=>r.json()) |
|
|
|
|
.then(r=>getPoly(r.results[0].Download.replace('.glb','').replace(/.*\//,''))) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getPoly(hashid){ |
|
|
|
|
fetch(endpoint+'getpoly?id='+hashid) |
|
|
|
|
// assumes it went well |
|
|
|
|
setTimeout( _ => { |
|
|
|
|
let el = document.createElement("a-entity") |
|
|
|
|
el.setAttribute('gltf-model', endpoint+'static/'+hashid+'.glb') |
|
|
|
|
el.setAttribute('position','0 1 -.5') |
|
|
|
|
el.setAttribute('scale','.001 .001 .001') |
|
|
|
|
el.setAttribute('target','true') |
|
|
|
|
AFRAME.scenes[0].appendChild(el) |
|
|
|
|
}, 1000) |
|
|
|
|
function getFurnitures(){ |
|
|
|
|
// from https://aframe.io/docs/1.6.0/components/real-world-meshing.html |
|
|
|
|
worldMeshes = Array.from(document.querySelectorAll("[data-world-mesh]") ) |
|
|
|
|
worldMeshes.map( el => console.log( el.getAttribute("data-world-mesh") ) ) |
|
|
|
|
// should be use in order to snap onreleased to a specific object, e.g |
|
|
|
|
} |
|
|
|
|
//________________________________________________________________ |
|
|
|
|
// used for keywords like LAST / PREVIOUS / ALL |
|
|
|
|
let addedContent = [] |
|
|
|
|
|
|
|
|
|
function getAllPrimitives(){ |
|
|
|
|
const other_primitives = ["camera", "cursor", "sky", "light", "sound", "videosphere"] |
|
|
|
|
const other_primitives_with_param_needed = ["text", "gltf-model", "obj-model", "troika-text"] |
|
|
|
|
return Object.getOwnPropertyNames(AFRAME.primitives.primitives) |
|
|
|
|
// thanks to https://github.com/Utopiah/aframe-inVR-blocks-based-editor/blob/master/aframe-invr-inspect.js |
|
|
|
|
.map( i => i.replace("a-","")) |
|
|
|
|
.filter( i => other_primitives.indexOf(i) < 0 ) |
|
|
|
|
.filter( i => other_primitives_with_param_needed.indexOf(i) < 0 ) // temporarilty disabled |
|
|
|
|
// .map( (i,j) => addPrimitive( i, ""+ j/7 + " 1.4 -0.5" ) ) |
|
|
|
|
.map( (i,j) => i ) |
|
|
|
|
} // adapted from https://git.benetou.fr/utopiah/text-code-xr-engine/src/commit/0e1f297ec0cd17b0356811dfa0ab55f1e2629e7c/index.html#L2101 |
|
|
|
|
|
|
|
|
|
const SpeechRecognition = window.webkitSpeechRecognition; |
|
|
|
|
recognizer = new SpeechRecognition(); |
|
|
|
|
recognizer.interimResults = true; |
|
|
|
|
recognizer.continuous = true; |
|
|
|
|
// does not work recognizer.lang = 'fr-FR'; |
|
|
|
|
recognizer.lang = 'en-US'; |
|
|
|
|
|
|
|
|
|
const aframeprimitives = getAllPrimitives() |
|
|
|
|
const speechactions = [ "add", "apply", "delete", "clone", "model", "undo" ] |
|
|
|
|
const speechcustomcomponents = [ "target", "teleporter" ] |
|
|
|
|
|
|
|
|
|
let speechCommands = [] |
|
|
|
|
|
|
|
|
|
recognizer.onresult = (event) => { |
|
|
|
|
let result = event.results[event.resultIndex] |
|
|
|
|
if (result.isFinal) { |
|
|
|
|
console.log('You said: ' + result[0].transcript ) |
|
|
|
|
|
|
|
|
|
let speechContent = result[0].transcript |
|
|
|
|
let latest = addedContent.at(-1) |
|
|
|
|
let cmd_words = speechContent.split(" ").map( i => i.toLowerCase() ) |
|
|
|
|
let el |
|
|
|
|
|
|
|
|
|
switch(cmd_words[0]) { |
|
|
|
|
case speechactions[0]: |
|
|
|
|
console.log("recognized proper command") |
|
|
|
|
let primitive = cmd_words[1] // assuming fixed order for now |
|
|
|
|
el = document.createElement("a-"+primitive) |
|
|
|
|
el.setAttribute("target", "") |
|
|
|
|
el.setAttribute("scale", ".1 .1 .1") |
|
|
|
|
el.setAttribute("position", "0 1.5 -0.4") |
|
|
|
|
addedContent.push(el) |
|
|
|
|
AFRAME.scenes[0].appendChild( el ) |
|
|
|
|
speechCommands.push( speechContent ) |
|
|
|
|
break; |
|
|
|
|
case speechactions[1] : |
|
|
|
|
console.log("recognized apply command") |
|
|
|
|
latest.setAttribute( cmd_words[1], cmd_words[2]) // assuming fixed order for now |
|
|
|
|
speechCommands.push( speechContent ) |
|
|
|
|
break; |
|
|
|
|
case speechactions[2] : |
|
|
|
|
deleteTarget( latest ) |
|
|
|
|
speechCommands.push( speechContent ) |
|
|
|
|
break; |
|
|
|
|
case speechactions[3] : |
|
|
|
|
el = latest.cloneNode(true) // does not work properly, losing some attributes, in particular scale can be problematic |
|
|
|
|
//["scale", "position", "rotation", "wireframe", "target", "material"].map( prop => el.setAttribute(prop, latest.getAttribute(prop) ) ) |
|
|
|
|
//["scale", "position", "rotation", "target" ].map( prop => el.setAttribute(prop, latest.getAttribute(prop) ) ) |
|
|
|
|
el.setAttribute("scale", latest.getAttribute("scale") ) |
|
|
|
|
el.setAttribute("position", latest.getAttribute("position") ) |
|
|
|
|
el.setAttribute("rotation", latest.getAttribute("rotation") ) |
|
|
|
|
el.setAttribute("target", latest.getAttribute("target") ) |
|
|
|
|
// untested |
|
|
|
|
if (cmd_words[1]) console.log('could clone',cmd_words[1],'n times instead') |
|
|
|
|
// could optionally add a number of times |
|
|
|
|
addedContent.push(el) |
|
|
|
|
AFRAME.scenes[0].appendChild( el ) |
|
|
|
|
el.object3D.translateX(10) // due to scaling |
|
|
|
|
speechCommands.push( speechContent ) |
|
|
|
|
break; |
|
|
|
|
case speechactions[4] : |
|
|
|
|
getModelFromKeyword( cmd_words[1] ) // requires the backend (proxy, LAN only for now, waiting for API clarification on 403) |
|
|
|
|
speechCommands.push( speechContent ) |
|
|
|
|
break; |
|
|
|
|
case speechactions[5] : |
|
|
|
|
console.log( "should undo", speechCommands.at(-1) ) |
|
|
|
|
// note that not all commands might be undo-able |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
addedContent.push( addNewNoteAsPostItNote(speechContent, "0 1.2 -.5") ) |
|
|
|
|
// could become jxr code proper later, also allowing to re-execute a command again |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
recognizer.start(); |
|
|
|
|
|
|
|
|
|
var forceXaxis |
|
|
|
|
// setInterval( _ => console.log(forceXaxis), 1000) |
|
|
|
@ -413,8 +306,12 @@ setTimeout( _ => { |
|
|
|
|
</a> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<a-scene startfunctions onemptypinch="onHoveredTeleport()"> |
|
|
|
|
<a-gltf-model hide-on-enter-ar="" id="environment" src="../content/CubeRoom.glb" rotation="0 -90 0" position="0 0 1" scale="" ></a-gltf-model> |
|
|
|
|
<a-scene |
|
|
|
|
real-world-meshing="meshesEnabled: false; planeMixin: xrplane" xr-mode-ui="XRMode: ar" |
|
|
|
|
startfunctions onemptypinch="onHoveredTeleport()"> |
|
|
|
|
<a-mixin id="xrplane" material="color: pink" visible="false"> </a-mixin> |
|
|
|
|
|
|
|
|
|
<a-gltf-model NOhide-on-enter-ar="" id="environment" src="../content/CubeRoom.glb" rotation="0 -90 0" position="0 0 1" scale="" ></a-gltf-model> |
|
|
|
|
<!-- Cube Room by Anonymous [CC-BY] via Poly Pizza --> |
|
|
|
|
|
|
|
|
|
<a-entity id="rig"> |
|
|
|
@ -498,97 +395,8 @@ setTimeout( _ => { |
|
|
|
|
<a-box id="namedteleporter" teleporter height=".1" class="teleportable" material="color: cyan" position="2 0 2" ></a-box> |
|
|
|
|
|
|
|
|
|
<a-box target teleporter height=".1" depth=".1" width=".1" class="teleportable" material="color: red" position="0 1 -.5" ></a-box> |
|
|
|
|
<a-troika-text anchor=left value="jxr getFurnitures()" target position=" 0.3 1.25 0" rotation="0 -40 0" scale="0.1 0.1 0.1"></a-troika-text> |
|
|
|
|
|
|
|
|
|
<a-entity position="-1 1 -3.5" scaffolding> |
|
|
|
|
<a-box teleporter height=".01" depth=".4" width="1" class="teleportable" material="color: white" position=".5 0 -.2" ></a-box> |
|
|
|
|
<a-entity position="0 0.5 0" class="scaffolding_front"> |
|
|
|
|
<a-cylinder radius=".05"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="0 -.5 -.2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="0 0.5 -.4" class="scaffolding_back"> |
|
|
|
|
<a-cylinder radius=".05" position="0 0 0"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 -45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="1 -.5 .2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="-1 2 -3.5" scaffolding> |
|
|
|
|
<a-box teleporter height=".01" depth=".4" width="1" class="teleportable" material="color: white" position=".5 0 -.2" ></a-box> |
|
|
|
|
<a-entity position="0 0.5 0" class="scaffolding_front"> |
|
|
|
|
<a-cylinder radius=".05"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="0 -.5 -.2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="0 0.5 -.4" class="scaffolding_back"> |
|
|
|
|
<a-cylinder radius=".05" position="0 0 0"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 -45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="1 -.5 .2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="0 0 -3.5" scaffolding> |
|
|
|
|
<a-box teleporter height=".01" depth=".4" width="1" class="teleportable" material="color: white" position=".5 0 -.2" ></a-box> |
|
|
|
|
<a-entity position="0 0.5 0" class="scaffolding_front"> |
|
|
|
|
<a-cylinder radius=".05"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="0 -.5 -.2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="0 0.5 -.4" class="scaffolding_back"> |
|
|
|
|
<a-cylinder radius=".05" position="0 0 0"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 -45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="1 -.5 .2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="0 1 -3.5" scaffolding> |
|
|
|
|
<a-box teleporter height=".01" depth=".4" width="1" class="teleportable" material="color: white" position=".5 0 -.2" ></a-box> |
|
|
|
|
<a-entity position="0 0.5 0" class="scaffolding_front"> |
|
|
|
|
<a-cylinder radius=".05"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="0 -.5 -.2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="0 0.5 -.4" class="scaffolding_back"> |
|
|
|
|
<a-cylinder radius=".05" position="0 0 0"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 -45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="1 -.5 .2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="1 0 -3.5" scaffolding> |
|
|
|
|
<a-box teleporter height=".01" depth=".4" width="1" class="teleportable" material="color: white" position=".5 0 -.2" ></a-box> |
|
|
|
|
<a-entity position="0 0.5 0" class="scaffolding_front"> |
|
|
|
|
<a-cylinder radius=".05"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="0 -.5 -.2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="0 0.5 -.4" class="scaffolding_back"> |
|
|
|
|
<a-cylinder radius=".05" position="0 0 0"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 -45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="1 -.5 .2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="-1 0 -3.5" scaffolding> |
|
|
|
|
<a-box teleporter height=".01" depth=".4" width="1" class="teleportable" material="color: white" position=".5 0 -.2" ></a-box> |
|
|
|
|
<a-entity position="0 0.5 0" class="scaffolding_front"> |
|
|
|
|
<a-cylinder radius=".05"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="0 -.5 -.2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
<a-entity position="0 0.5 -.4" class="scaffolding_back"> |
|
|
|
|
<a-cylinder radius=".05" position="0 0 0"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" position=".5 -.5 0" rotation="0 0 90"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=1.2 position=".5 0 0" rotation="0 0 -45"></a-cylinder> |
|
|
|
|
<a-cylinder radius=".05" height=".4" position="1 -.5 .2" rotation="90 0 0"></a-cylinder> |
|
|
|
|
</a-entity> |
|
|
|
|
</a-entity> |
|
|
|
|
</a-scene> |
|
|
|
|
</body> |
|
|
|
|
</script> |
|
|
|
|