handling multiple simulations

master
Fabien Benetou 2 years ago
parent b107f524ca
commit eeff456d80
  1. 201
      index.html
  2. 24
      portail.html

@ -4,84 +4,17 @@
</head>
<body>
<script>
/*
play sounds as described in email
Sounds/FX/CEREMA_BOUCLE_EAU.mp3
try rely on periodic bounding box height as volume
unfortunately document.querySelector("#watersim").object3D.children[0].geometry.boundingBox.max or min doesn't seem to change despite the displacement map working
*/
AFRAME.registerComponent('randomfx', {
init: function () {
var FXsounds = Array.from( document.querySelectorAll(".randomfx") )
setInterval( _ => { FXsounds[Math.floor(Math.random()*FXsounds.length)].components.sound.playSound() }, 9000 )
var simsrc = "simulations/initial_simulation_data/crop_outpy_"
var forceSimulationSource = AFRAME.utils.getUrlParameter('simsrc');
if ( forceSimulationSource ) {
simsrc = forceSimulationSource
console.log(simsrc,"switched from default simulation to this one")
// sould also update the src of id="debug_sim_cerema" with a specific step, e.g 50
}
})
// configurator.html e.g https://github.com/Utopiah/philosophy-vr-experimentation-lab/blob/master/public/configurator.html
/* TODO 11th
Repare
- Il faudrait peut être faire un léger shift vers le bas pour que l'on ne voit pas la texture de l'eau initialement. (le 0 de la simulation vaut 0.001 dans les données)
- Le cube reset est bas et petit en VR
- Avec le bug de reset sur l'eau, est ce qu'il serait possible d'associer un des boutons des manettes du Quest à l'action "Recharger la page" ? Comme la simulation est courte, cela permettrait de rafraîchir facilement.
Extra
- Couleurs batiments/toits plus neutres
Problematique
- Au niveau du sol, en début de simulation, on a un effet de scintillement entre le sol blanc et l'eau qui peut être désagréable.
- J'ai un utilisateur qui m'a demandé si c'était possible d'animer un peu la texture de l'eau
A discuter
- Il y a un bug avec la position du modèle 3D et des bâtiments procéduraux (au moins sur la Ruelle) cf capture
Etonnant car arbres OK?
A reparer
- faire le test in_situ quand la localisation sera gere
- Il faut un peu revoir les hot-spots dans le quartier des Baquets, certains sont dans des jardins et on peut se retrouver enferme
*/
// TODO after pres 26th :
/*
- fix reset button (water animation ignored)
- add lamp model (insure it doesn't load twice)
- add "dirty" water texture with animation (via e.g repeat/offset in material)
- define color scheme for specific objects, e.g house/roof
- fix teleports, should include parent offsets
- mapping type/tags/filters -> function + opt. colors scheme or 3D model
- geom
var houses = josm.elements.filter( e => (e.type == "way" && e.tags && e.tags["building"]) )
.filter( i => !loadedosmways.includes(i.id) )
.map( e => e.geometry)
houses.map( e => { makeBuilding( e, buildingHeight*(1+Math.random()), el ) })
highway
- points
var trees = josm.elements.filter( i => i.type == "node" && i.tags && i.tags.natural == "tree")
var lamp = josm.elements.filter( i => i.type == "node" && i.tags && i.tags.highway == "street_lamp")
trees.map( e => { makeTree( e, el ) } )
lamp.map( e => { makeLamp( e, el ) } )
*/
// TODO pres 19th :
// - showcase elevations unoptimized and possibly optimized with FPS, ideally on Quest2
// - showcase new assets from OSM (to check first, might look at recent add in that area)
// Done
// - add models of 2nd spot and easily switch from one to the other, e.g URL argument
// - add 1 audio track (might have to check on phones if fine or if need extra permission
// - transform function resetAnimations() to interactive action, possibly with seeking
const simsrc = "ruelle_sim_data/crop_outpy_"
const simext = ".jpg"
const simstart = 1
const simend = 95
const simend = 95 // mostly correct as new simulations got to 96 steps
const sim_filename_padding = true
const animationSpeedStep = 500
var animationCurrentStep = simstart
@ -94,6 +27,10 @@ function animationStep(){
displacementMap: simsrc+(animationCurrentStep++)+simext,
})
//wsim.setAttribute("material", "displacementMap", simsrc+(animationCurrentStep++)+simext)
//wsim.object3D.children[0].material.needsUpdate = true //no need to do this for every step...
//wsim.object3D.children[0].material.map.offset.setX(animationCurrentStep/1000) // same problem, that offset is not just for the texture but also for the displacement map
// should find a way to decouple
// otherwise could try a custom shader but might still encounter the same problem
if (animationCurrentStep >= simend) resetAnimations()
}
@ -147,6 +84,13 @@ AFRAME.registerComponent('texture-drift', {
}
})
AFRAME.registerComponent('randomfx', {
init: function () {
var FXsounds = Array.from( document.querySelectorAll(".randomfx") )
setInterval( _ => { FXsounds[Math.floor(Math.random()*FXsounds.length)].components.sound.playSound() }, 9000 )
}
})
AFRAME.registerComponent('set-initial-camera-from-data', {
init: function () {
this.el.setAttribute("position", positionsCurated[selection].worldposition[0] + " 1.6 " + positionsCurated[selection].worldposition[1] )
@ -276,13 +220,15 @@ function fromOSMTo3DElements( josm, el ){
var highways = josm.elements.filter( e => (e.type == "way" && e.tags && e.tags["highway"]) ).map( e => e.geometry)
// not so good, shows paths rather than a usable geometry
if (!disableWaysForGLTFExportInHubs)
highways.map( e => { makeWay( e, wayHeight, el ) })
highways.map( e => { makeWay( e, wayHeight, el, 0x120a06 ) })
}
function geolocalized( pos ){
console.log( pos.coords )
}
const loader = new THREE.TextureLoader();
function addWall(a, b, h, el, color=0x6d6a64){
var geometry = new THREE.BufferGeometry();
// create a simple rectangle shape. We duplicate the top left and bottom right
@ -299,7 +245,12 @@ function addWall(a, b, h, el, color=0x6d6a64){
// itemSize = 3 because there are 3 values (components) per vertex
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
var material = new THREE.MeshBasicMaterial( { color: color, side: THREE.DoubleSide } );
const material = new THREE.MeshBasicMaterial({
color : new THREE.Color( 0x6d6a64 ).offsetHSL(0,0,-Math.random()/10),
side: THREE.DoubleSide,
map: loader.load('Visuals/TEXTURE_BAT/TEXTURE_BAT_Base_Color.jpg'),
});
var mesh = new THREE.Mesh( geometry, material );
var entity = document.createElement("a-entity");
// not sure it's the best level of abstraction, maybe building instead
@ -318,7 +269,10 @@ function addFan(a, b, c, el, verticalOffset, color ){
// itemSize = 3 because there are 3 values (components) per vertex
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
var material = new THREE.MeshBasicMaterial( { color: color, side: THREE.DoubleSide } );
const material = new THREE.MeshBasicMaterial({
color : color,
side: THREE.DoubleSide,
});
var mesh = new THREE.Mesh( geometry, material );
var entity = document.createElement("a-entity");
entity.object3D.add( mesh );
@ -362,14 +316,14 @@ function getCentroid(points){
return centroid;
}
function makeWay( points, height, el ){
function makeWay( points, height, el, color=0xCCCCCC ){
var poly = points.map( p => pointFromCoordinates( p ) )
var way = document.createElement("a-entity")
//way.setAttribute("position", "0 1 0") // vertical offset to avoid z-fighting on large horizontal planes
way.className = "way"
way.setAttribute("shadow", "") // somehow doesn't seem to receive, only casts
el.appendChild( way )
make3DFloor( poly, way )
make3DFloor( poly, way, color, "Visuals/TEXTURE_BAT/TEXTURE_SOL_Base_Color.jpg")
}
function makeLamp( treedata, el){
@ -405,7 +359,7 @@ function makeBuilding( points, height, el ){
el.appendChild( building )
makeWalls( poly, height, building )
// make3DFloor( poly, building ) // not visibile so might be removed
var color = new THREE.Color( 0x8080FF ).offsetHSL(0,0,-Math.random());
var color = new THREE.Color( 0x8F8FFF ).offsetHSL(0,0,-Math.random());
make3DRoof( poly, building, height, color )
building.setAttribute("shadow", "")// somehow doesn't seem to receive it, only casts
@ -489,9 +443,13 @@ AFRAME.registerComponent('hotspots', {
init: function () {
var el = this.el
hotspots.map( h => {
var pointEl = document.createElement("a-sphere")
pointEl.setAttribute("opacity", .3)
pointEl.setAttribute("geometry", "segmentsHeight: 4; segmentsWidth: 8")
//var pointEl = document.createElement("a-sphere")
//pointEl.setAttribute("geometry", "segmentsHeight: 4; segmentsWidth: 8")
var pointEl = document.createElement("a-gltf-model")
pointEl.setAttribute("gltf-model", "Visuals/ASSETS_3D/AA_Hotspot.glb")
//pointEl.setAttribute("opacity", .3)
pointEl.setAttribute("model-opacity", .3)
pointEl.setAttribute("scale", "50 50 50")
pointEl.setAttribute("position", h[0] + " 3 " + h[1])
pointEl.setAttribute("teleport-via-cursor", true)
el.appendChild( pointEl )
@ -500,6 +458,26 @@ AFRAME.registerComponent('hotspots', {
}
})
// from https://stackoverflow.com/questions/43914818/alpha-animation-in-aframe-for-a-object-model
AFRAME.registerComponent('model-opacity', {
schema: {default: 1.0},
init: function () {
this.el.addEventListener('model-loaded', this.update.bind(this));
},
update: function () {
var mesh = this.el.getObject3D('mesh');
var data = this.data;
if (!mesh) { return; }
mesh.traverse(function (node) {
if (node.isMesh) {
node.material.opacity = data;
node.material.transparent = data < 1.0;
node.material.needsUpdate = true;
}
});
}
});
AFRAME.registerComponent('teleport-via-cursor', {
init: function () {
var el = this.el
@ -510,10 +488,12 @@ AFRAME.registerComponent('teleport-via-cursor', {
// might want to blink too, e.g black sphere around the camera for .5s
});
this.el.addEventListener('fusing', function (evt) {
el.setAttribute("opacity", 1)
//el.setAttribute("opacity", 1)
el.setAttribute("model-opacity", 1)
});
this.el.addEventListener('mouseleave', function (evt) {
el.setAttribute("opacity", 0.3)
//el.setAttribute("opacity", 0.3)
el.setAttribute("model-opacity", .3)
});
}
});
@ -583,14 +563,32 @@ AFRAME.registerComponent('displaymodels', {
})
}
})
AFRAME.registerComponent('forcestats', {
init: function () {
var forcestats = AFRAME.utils.getUrlParameter('forcestats');
console.log(forcestats)
if (forcestats == "true") this.el.setAttribute("stats", true)
}
})
AFRAME.registerComponent('customdebug', {
init: function () {
var el = this.el
var debugmode = AFRAME.utils.getUrlParameter('debugmode');
if (debugmode && debugmode == "true") {
Array.from( document.querySelectorAll(".debug") ).map( e => e.setAttribute("visible", true) )
document.querySelector("#mainbutton").style.display = "none";
el.addEventListener('loaded', function () {
el.components.inspector.openInspector()
setTimeout(function () { // setTimeout for good measure.
AFRAME.scenes[0].camera.position.set(400,600,-30)
AFRAME.scenes[0].camera.rotation.set(-1.6,0.65,1.6);
}, 1000)
});
}
}
})
function resetAnimations(){
Array.from( document.querySelectorAll("[animation]") )
.map( a => Object.keys( a.components )
@ -618,8 +616,8 @@ function playSound(param){
resetAnimations()
}
</script>
<button style="z-index: 1; position: absolute; width:50%; margin: auto; text-align:center; top:45%; left:30%; height:30%;" onclick="playSound(this)">Demarrer l'experience</button>
<a-scene displaymodels forcestats>
<button id=mainbutton style="z-index: 1; position: absolute; width:50%; margin: auto; text-align:center; top:45%; left:30%; height:30%;" onclick="playSound(this)">Demarrer l'experience</button>
<a-scene displaymodels forcestats customdebug>
<a-entity id="hotspots" hotspots ></a-entity>
<!-- Quest available only during event, otherwise cardboard -->
<a-entity id="leftHand" hand-tracking-controls="hand: left;"></a-entity>
@ -638,12 +636,13 @@ function playSound(param){
></a-entity>
<!-- consider time as HUD text display-->
<a-entity cursor="fuse: true; fuseTimeout: 500"
position="0 0 -1"
geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
material="color: black; shader: flat">
position="0 0 -3"
geometry="primitive: ring; radiusInner: 0.04; radiusOuter: 0.05"
material="color: orange; shader: flat">
</a-entity>
</a-entity>
<a-box resetanimations position="1 1.4 1" rotation="-180 0 -180" scale=".2 .2 .2"><a-text value="reset" color="black" position="-.2 0 .5"></a-text></a-box>
<a-gltf-model resetanimations="" position="6 6 9" scale="100 100 100" rotation="29 -160 -10" gltf-model="Visuals/ASSETS_3D/AA_Reset.glb" opacity="1"></a-gltf-model>
<a-gltf-model position="-2.2864 1.02726 -1.41235" scale="30 30 30" rotation="0 70 0" gltf-model="Visuals/ASSETS_3D/AA_Crue.glb" opacity="1"></a-gltf-model>
</a-entity>
<a-plane id="ground" position="0 -.2 0" rotation="-90 0 0" width="1000" height="1000" color="lightgrey"></a-plane>
@ -654,11 +653,6 @@ function playSound(param){
</a-entity>
<a-entity position="-70 0 -42" osm id="osm"></a-entity>
<!--
live layers (deactivated by default)
material="src: https://wxs.ign.fr/ortho/geoportail/r/wms?LAYERS=ORTHOIMAGERY.ORTHOPHOTOS.BDORTHO&EXCEPTIONS=text/xml&FORMAT=image/jpeg&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&STYLES=&CRS=CRS:84&BBOX=0.470286,49.338484,0.556117,49.381417&WIDTH=4096&HEIGHT=4096; displacementScale: 20; displacementMap: https://wxs.ign.fr/altimetrie/geoportail/r/wms?LAYERS=ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES&EXCEPTIONS=text/xml&FORMAT=image/jpeg&SERVICE=WMS&VERSION=1.3.0&REQUEST=GETMAP&STYLES=&CRS=CRS:84&BBOX=0.470286,49.338484,0.556117,49.381417&WIDTH=1024&HEIGHT=1024;" ></a-plane>
-->
<!-- offset on test data for easier vr testing -->
<a-gltf-model class="models_ruelle" visible="" position="-140.71021 0.73 -28.54369" scale="1.2 1.2 1.2" rotation="0 -111.8545396388247 0" gltf-model="Visuals/EXPORTS/EXPORTS_gltf/AA_Quaidelaruelle.glb" listosmways=""></a-gltf-model>
@ -666,14 +660,23 @@ material="src: https://wxs.ign.fr/ortho/geoportail/r/wms?LAYERS=ORTHOIMAGERY.ORT
<a-plane id="landscape" position="0 -20 0" scale="10 10 10" rotation="-90 0 -90" width="100" height="100" geometry="segmentsHeight: 128; segmentsWidth: 128"
material="src: ign_terrain_cached.jpg; displacementScale: 20; displacementMap: ign_elevation_cached.jpg;"></a-plane>
<a-plane id="watersim" cerema="" position="0 -50.25 0" rotation="-90 90 0" src="Visuals/TEXTURE_EAU/Texture_eau_Base_Color.png"
material="displacementScale: 0.01; wireframe: false; displacementMap: ruelle_sim_data/crop_outpy_1.jpg"
<a-plane id="watersim" cerema="" position="0 -50.25 0" rotation="-90 90 0" src="Visuals/EAU/Eau_01.jpg"
material="displacementScale: 0.02; wireframe: false; displacementMap: "
geometry="segmentsHeight: 128; segmentsWidth: 128" scale="1000 1000 100"></a-plane>
<!-- animation might fail due texture.neddUpdate unset -->
<a-image id="debug_baquet_osm" src="baquet_osm.png" visible=false position="-235 1.1 145" rotation="-90 90 0" scale="200 200 200" material="opacity: 0.5" class=debug></a-image>
<a-image id="debug_ruelle_osm" src="ruelle_osm.png" visible=false position="-40 1 -220" rotation="-90 90 0" material="opacity: 0.5" scale="200 200 200" class="debug"></a-image>
<a-image id="debug_sim_cerema" src="" visible=false position="0 1.2 0" rotation="-90 90 0" material="opacity: 0.5" scale="1000 1000 1000" class="debug"></a-image>
<a-sky src="cloudsky.jpg"
animation="from: #000; to: #aaf; loop: true; dur: 20000; dir: alternate; loop:true; property: components.material.material.color; type: color;"
animation_texture="property: material.offset; to: 1 1; dur: 200; easing: linear; loop: true; dir: alternate;"
></a-sky>
</a-scene>
<!--
live layers (deactivated by default)
material="src: https://wxs.ign.fr/ortho/geoportail/r/wms?LAYERS=ORTHOIMAGERY.ORTHOPHOTOS.BDORTHO&EXCEPTIONS=text/xml&FORMAT=image/jpeg&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&STYLES=&CRS=CRS:84&BBOX=0.470286,49.338484,0.556117,49.381417&WIDTH=4096&HEIGHT=4096; displacementScale: 20; displacementMap: https://wxs.ign.fr/altimetrie/geoportail/r/wms?LAYERS=ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES&EXCEPTIONS=text/xml&FORMAT=image/jpeg&SERVICE=WMS&VERSION=1.3.0&REQUEST=GETMAP&STYLES=&CRS=CRS:84&BBOX=0.470286,49.338484,0.556117,49.381417&WIDTH=1024&HEIGHT=1024;" ></a-plane>
-->
</body>
</html>

@ -4,10 +4,10 @@
<h2>Experience par lieu</h2>
<center>
<table><tr>
<td><a target="_blank" class="experiencetdnks" href="https://fabien.benetou.fr/pub/home/CEREMA/?">
<td><a target="_blank" class="experiencelinks" href="https://fabien.benetou.fr/pub/home/CEREMA/?">
<img src="ruelle_osm.png" width="300px"/><br><br>
<center>Quai de la Ruelle</center></a></td>
<td><a target="_blank" class="experiencetdnks" href="https://fabien.benetou.fr/pub/home/CEREMA/?position=1">
<td><a target="_blank" class="experiencelinks" href="https://fabien.benetou.fr/pub/home/CEREMA/?position=1">
<img src="baquet_osm.png" width="300px"/><br><br>
<center>Les Baquets</center></a></td>
</tr></table>
@ -15,6 +15,14 @@
<h2>Options</h2>
<ul>
<li>Choisir une simulation
<ul>
<li onclick="forceSimsrc(this)">1</li>
<li onclick="forceSimsrc(this)">2</li>
<li onclick="forceSimsrc(this)">3</li>
<li onclick="forceSimsrc(this)">4</li>
</ul>
</li>
<li>Forcer l'affichage des performances
<ul>
<li onclick="forceStats(this)">true</li>
@ -28,6 +36,12 @@
<li onclick="adjustHeight(this)">20</li>
</ul>
</li>
<li>Debug mode :
<ul>
<li onclick="debugMode(this)">true</li>
<li onclick="debugMode(this)">false</li>
</ul>
</li>
</ul>
<h2>Documentation</h2>
@ -43,5 +57,11 @@ function adjustHeight(param){
function forceStats(param){
links.map( e => e.href += "&forcestats="+param.textContent)
}
function debugMode(param){
links.map( e => e.href += "&debugmode="+param.textContent)
}
function forceSimsrc(param){
links.map( e => e.href += "&simsrc=simulations/scenario"+param.textContent+"_crops/heure_sim_")
}
</script>
<html>

Loading…
Cancel
Save