Picking example in x3dom - x3dom

Does anybody have simple sample regarding the picking x3dom objects. There are two samples given in the homepage of x3dom but they are complex for em to understand. I would be really thankful if someone could provide me with simpler example. Thanking you in advance.

not sure exactly what you mean by picking
here is a sample page which changes color based on mouseclick mouse over and mouse out
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" type="text/css" href="http://x3dom.org/x3dom/example/x3dom.css"> </link>
<script type="text/javascript" src = "http://x3dom.org/x3dom/example/x3dom.js"></script>
</head>
<body>
<X3D width="500px" height="400px" showLog='true' showStat="true">
<Scene DEF='scene' >
<Shape >
<Box onclick="toggleRendering();" onmouseover="toggleRendering2();" onmouseout="toggleRendering3();" />
<Appearance><Material diffuseColor='0 1 0' /></Appearance>
</Shape>
</Scene>
</X3D>
<script>
var flag = true;
function toggleRendering()
{
flag = !flag;
var mat = document.getElementsByTagName("Material");
var aMat = mat[0];
if (flag) aMat.diffuseColor = "1 0 0";
else aMat.diffuseColor = "0 0 1";
return false;
}
function toggleRendering2()
{
var mat = document.getElementsByTagName("Material");
var aMat = mat[0];
aMat.diffuseColor = "1 1 1";
return false;
}
function toggleRendering3()
{
var mat = document.getElementsByTagName("Material");
var aMat = mat[0];
aMat.diffuseColor = "0 0 0";
return false;
}
</script>
</body>
</html>

Related

Can´t reproduce bootstrap documentation using js example. Why?

I´m trying to reproduce bootstrap documentation example:
https://getbootstrap.com/docs/5.2/components/list-group/#javascript-behavior
With 2 diferences: using js to create the html tags and using a nested list instead of single list.
The 'activate' highlight doesn´t work and the right side content doesn´t change. Need help on why and how to make it work.
I´m also trying to create a collapse effect for the nested list when the parent item is clicked.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<!-- <link rel="stylesheet" href="style.css"> -->
</head>
<body>
<div id="tree"></div>
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<script>
function clearChildren(node){
while(node.children.length > 0)
node.removeChild(node.lastElementChild)
}
let idCounter = 0
function createNode(name,meta={}){
return {
name,
id: idCounter++,
children:new Array(),
meta
}
}
function makeTreeTable(parentElement, rootNode){
clearChildren(parentElement)
parentElement.setAttribute('class', 'row')
//Make Tree Div
const divTree = document.createElement('div')
divTree.setAttribute('class','col-8')
divTree.setAttribute('id', 'div-tree')
parentElement.appendChild(divTree)
//Make Meta Div
const divMeta = document.createElement('div')
divMeta.setAttribute('class','col-4')
divMeta.setAttribute('id', 'div-node')
parentElement.appendChild(divMeta)
const metaDisplay = document.createElement('div')
metaDisplay.setAttribute('class','tab-content')
metaDisplay.setAttribute('id','nav-tabContent')
divMeta.appendChild(metaDisplay)
maketree(divTree, rootNode, metaDisplay)
}
let activeMeta = 'tab-pane fade show active'
function createMetaList(treeNode){
const metaList = document.createElement('div')
console.log(treeNode.id)
metaList.setAttribute('id', `${treeNode.id}-meta`)
metaList.setAttribute('class',activeMeta)
activeMeta = 'tab-pane fade'
metaList.setAttribute('role','tabpanel')
metaList.setAttribute('aria-labelledby',treeNode.id)
for (const [key, value] of Object.entries(treeNode.meta)) {
const metaItem = document.createElement('div')
metaItem.innerHTML = `${key} : ${value}`
metaList.appendChild(metaItem)
}
return metaList
}
let activeNode = 'list-group-item list-group-item-action active'
function maketree(parentElement, nodeTgt, metaDisplay) {
//Make ul node
const ul = document.createElement("div");
ul.setAttribute('class', 'list-group')
ul.setAttribute('id','nodeTgt.name')
ul.setAttribute('role','tablist')
//Make all li´s nodes
for(const node of nodeTgt.children){
const li = document.createElement("a");
li.innerHTML = node.name;
li.setAttribute("id", node.id);
li.setAttribute("class", activeNode)
activeNode = 'list-group-item list-group-item-action'
li.setAttribute('data-bs-toogle','list')
li.setAttribute('role','tab')
li.setAttribute('href',`#${node.id}-meta`)
li.setAttribute('aria-controls',`${node.id}-meta`)
li.addEventListener('click',(e)=>{
e.stopPropagation()
console.log('clicked ', node.name)
})
ul.appendChild(li);
metaDisplay.appendChild(createMetaList(node))
//Make recursive items
if(nodeTgt.children.length > 0)
maketree(li,node, metaDisplay)
}
parentElement.appendChild(ul)
}
function makeMeta(i){
return{
meta1:`this is ${i}`,
meta2:`this is ${++i}`,
meta3:`this is ${++i}`,
}
}
const root = createNode('root', makeMeta(0))
root.children.push(createNode('node1', makeMeta(1)))
root.children.push(createNode('node2', makeMeta(2)))
root.children.push(createNode('node3', makeMeta(3)))
const node1 = root.children[0]
const node2 = root.children[1]
const node3 = root.children[2]
node1.children.push(createNode('node11', makeMeta(11)))
node1.children.push(createNode('node12', makeMeta(12)))
node2.children.push(createNode('node21', makeMeta(21)))
node2.children.push(createNode('node22', makeMeta(22)))
node3.children.push(createNode('node31', makeMeta(31)))
node3.children.push(createNode('node32', makeMeta(32)))
const node11 = node1.children[0]
const node12 = node1.children[1]
const node31 = node3.children[0]
const node32 = node3.children[1]
node11.children.push(createNode('node111', makeMeta(111)))
node11.children.push(createNode('node112', makeMeta(112)))
node12.children.push(createNode('node121', makeMeta(121)))
node12.children.push(createNode('node122', makeMeta(122)))
node31.children.push(createNode('node311', makeMeta(111)))
node31.children.push(createNode('node312', makeMeta(112)))
node32.children.push(createNode('node321', makeMeta(121)))
node32.children.push(createNode('node322', makeMeta(122)))
makeTreeTable(document.querySelector('#tree'), root)
</script>
</body>
</html>
Thanks
You need to initialize the created elements individually.
https://getbootstrap.com/docs/5.2/components/list-group/#via-javascript
Put the following at the end of your script:
const triggerTabList = document.querySelectorAll('#tree a')
triggerTabList.forEach(triggerEl => {
const tabTrigger = new bootstrap.Tab(triggerEl)
triggerEl.addEventListener('click', event => {
event.preventDefault()
tabTrigger.show()
})
})
Then you will see an error that says "#1-meta" is not a valid selector. I think you need to refactor your code to have all of the ids start with a letter [a-z]. So you want to use "meta-1" format instead.

does HTML5 Geolocation work?

I have the following script for HTML5 geolocation:
<!DOCTYPE html>
<html>
<head>
<title>Geolocation</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
body {
padding: 20px;
background-color:#ffffc9
}
p { margin : 0; }
</style>
<script>
function geoFindMe() {
var output = document.getElementById("out");
if (!navigator.geolocation){
output.innerHTML = "<p>Geolocation is not supported by your browser</p>";
return;
}
function success(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
output.innerHTML = '<p>Latitude is ' + latitude + '° <br>Longitude is ' + longitude + '°</p>';
var img = new Image();
img.src = "https://maps.googleapis.com/maps/api/staticmap?center=" + latitude + "," + longitude + "&zoom=13&size=300x300&sensor=false";
output.appendChild(img);
}
function error() {
output.innerHTML = "Unable to retrieve your location";
}
output.innerHTML = "<p>Locating…</p>";
navigator.geolocation.getCurrentPosition(success, error);
}
</script>
</head>
<body>
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/Using_geolocation -->
<p><button onclick="geoFindMe()">Show my location</button></p>
<div id="out"></div>
</body>
</html>
It always gives me the following result:
Your Latitude : 51.5412621
Your Longitude : -0.08813879999999999
Regardless of whether it is on a laptop or mobile and different browsers -- anyone any ideas? it seems unreliable to me!

How to get Pixijs with Cocoonjs to use a WebGLRenderer with canvas+ webview engine

I can't seem to get the canvas+ webview engine within Cocoon to use a PIXI.WebGLRenderer no matter what I try. Here is a simple example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<script type="text/javascript" src="http://pixijs.download/release/pixi.js"></script>
<title>Simple Test</title>
</head>
<body style="background-color: #99ff99; margin: 0; padding: 0;" onload="runTest()">
<script>
function runTest() {
var renderer = PIXI.autoDetectRenderer( 500, 200 );
document.body.appendChild( renderer.view );
var stageContainer = new PIXI.Container();
var text = new PIXI.Text( 'renderer.type='+renderer.type, { fontFamily: "Arial", fontSize: '12px', fill: "white" } );
text.x = text.y = 50;
stageContainer.addChild( text );
renderer.render( stageContainer );
}
</script>
</body>
</html>
With the Cocoon Launcher app I've tested this on:
iPhone5 (iOS 10.2)
iPad2 (iOS 9.3.5)
HP 10 Plus (android 4.4.2)
With webview+, all display "renderer=1" (which means PIXI.WebGLRenderer)
But with canvas+, all display "renderer=2" (which means PIXI.CanvasRenderer)
Is it possible to get canvas+ mode to work with WebGL in Pixi.js?
I have also tried forcing the renderer to be WebGL by replacing the autoDetectRenderer line with:
var renderer = new PIXI.WebGLRenderer( 500, 200 );
In this case my Cocoon Launcher on iphone and ipad crashes!
On the android, it just shows a black screen.
I have also tried with Pixi.js v3.0.1 with the same results.
So, is it possible to use WebGL with Cocoon's Canvas+ mode with Pixi.js?
Any help much appreciated, thanks
I managed to get it working, but not with the latest Pixi.js (v4.2.3), only with an old version - v3.0.10.
The key was to add cordova.js and use the document.addEventListener( "deviceready", runTest, false );
Here is some updated code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<script type="text/javascript" src="cordova.js"></script>
<script src="js/pixi-3.0.10.js"></script>
<title>Simple Test</title>
</head>
<body style="background-color: #99ff99; margin: 0; padding: 0;">
<script>
function runTest() {
var renderer = new PIXI.WebGLRenderer( 300, 100 );
document.body.appendChild( renderer.view );
var stageContainer = new PIXI.Container();
var text = new PIXI.Text( 'rrr.type='+renderer.type, { fontFamily: "Arial", fontSize: '12px', fill: "white" } );
text.x = text.y = 50;
stageContainer.addChild( text );
renderer.render( stageContainer );
}
document.addEventListener( "deviceready", runTest, false );
</script>
</body>
</html>
This is only a partial answer because it only works with an outdated version of Pixi.js
As for me, I'm abandoning canvas+ for now because what I got working showed poor and erratic results compared with the webview+ mode. Also, as an aside, according to various performance tests I've made, it seems that the old Pixi.js v3.0.10 is dramatically out performing v4.2.3 as well.. so looks like I'll be sticking with that also.

Create a simplified reflective custom shader in A-FRAME

So I have inevitably gone down the path of custom shaders in A-FRAME. When really researching this, and given I could be considered a newbie with this tech, I have bumped into all sorts of complicated and not-so clear solutions.
Examples like: https://rawgit.com/mrdoob/three.js/master/examples/webgl_materials_cubemap_balls_reflection.html , create even more questions than answers.
However, when I visited this example: https://stemkoski.github.io/Three.js/Reflection.html , I did notice a different approach which seemed a bit more simplified.
This lead me to research more about CubeCameras and how threejs can use it as a shader in order to simulate reflectivity.
//Create cube camera
var cubeCamera = new THREE.CubeCamera( 1, 100000, 128 );
scene.add( cubeCamera );
//Create car
var chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeCamera.renderTarget } );
var car = new Mesh( carGeometry, chromeMaterial );
scene.add( car );
//Update the render target cube
car.setVisible( false );
cubeCamera.position.copy( car.position );
cubeCamera.updateCubeMap( renderer, scene );
//Render the scene
car.setVisible( true );
renderer.render( scene, camera );
Now the question is, how can I translate that into A-FRAME? I tried the following:
AFRAME.registerComponent('chromeThing', {
schema: {
???
},
init: function () {
var el = this.el; // Entity.
var cubeCam = document.querySelector('#cubeCam'); //There is an <a-entity camera id="cubeCam">
var mirrorCubeMaterial = new THREE.MeshBasicMaterial( { envMap: cubeCam.renderTarget } );
mirrorCube = new THREE.Mesh( el, mirrorCubeMaterial );
el.setObject3D('mesh', mirrorCube);
}
});
As you might notice, I'm not sure what the scheme of this would be.
Also, should this be a shader or a component? (how could I use this best)
EDIT:
After #ngokevin reply, I've come up with this code which is still not giving me the desired results.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Chrome box</title>
<meta name="description" content="Physically-Based Materials - A-Frame">
<meta name="apple-mobile-web-app-capable" content="yes">
<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<script src="https://rawgit.com/ngokevin/kframe/master/dist/kframe.min.js"></script>
<script src="https://rawgit.com/ngokevin/kframe/master/components/reverse-look-controls/index.js"></script>
</head>
<body>
<a-scene>
<a-assets>
<img id="equi1" crossorigin src="https://rawgit.com/aframevr/aframe/master/examples/boilerplate/panorama/puydesancy.jpg" preload="auto">
</a-assets>
<!-- MAIN CAMERA -->
<a-entity id="mainCam" camera="userHeight: 1.6" reverse-look-controls wasd-controls></a-entity>
<!-- CMAERA FOR TEXTURE (?) -->
<a-entity id="cubecamera" camera near="0.1" far="5000" fov="512"></a-entity>
<!-- SKY DOME TO REFLECT ON BOX -->
<a-sky src="#equi1"></sky>
<!-- MAKE THIS BOX CHROME -->
<a-box id="theCube" camera-envmap-material="#cubecamera" color="tomato" depth="2" height="4" width="5" position="0 0 -3" materials=""></a-box>
<!-- THIS BOX IS MOVING AND SHOULD REFLECT ON THE CHROME BOX -->
<a-box id="reflector" color="red" position="0 0 20">
<a-animation attribute="rotation" dur="10000" fill="forwards" to="0 360 0" repeat="indefinite"></a-animation>
</a-box>
</a-scene>
</body>
<script>
AFRAME.registerComponent('camera-envmap-material', {
dependencies: ['material'],
// Selector type so we do `<a-entity camera-envmap-material="#cubecamera">`.
schema: {
type: 'selector'
},
init: function () {
var cameraEl = this.data;
var material = this.el.getObject3D('mesh').material;
// Set envmap on existing material.
// This assumes you have a CubeCamera component that does `setObject3D('cube-camera', new THREE.CubeCamera)`.
material.envMap = cameraEl.getObject3D('camera').renderTarget;
material.needsUpdate = true;
}
});
</script>
</html>
UPDATE #2
After recommendations from #ngokevin here is where I'm at, however, I can't get component to update. The problem seems to be the passing of variables to the tick:function(), I keep getting Uncaught TypeError: Cannot read property 'renderTarget' of undefined
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Chrome box</title>
<meta name="description" content="Physically-Based Materials - A-Frame">
<meta name="apple-mobile-web-app-capable" content="yes">
<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<script src="https://rawgit.com/ngokevin/kframe/master/dist/kframe.min.js"></script>
<script src="https://rawgit.com/ngokevin/kframe/master/components/reverse-look-controls/index.js"></script>
</head>
<body>
<a-scene>
<a-assets>
<img id="equi1" crossorigin src="https://rawgit.com/aframevr/aframe/master/examples/boilerplate/panorama/puydesancy.jpg" preload="auto">
</a-assets>
<!-- MAIN CAMERA -->
<a-entity id="mainCam" camera="userHeight: 1.6" reverse-look-controls wasd-controls></a-entity>
<!-- SKY DOME TO REFLECT ON BOX -->
<a-sky src="#equi1"></sky>
<!-- MAKE THIS BOX CHROME -->
<a-box id="theCube" camera-envmap-material depth="2" height="4" width="5" position="0 0 -3" metalness="1">
</a-box>
<!-- MAKE THIS ROTATE AND REFLECT ON CHROME -->
<a-box id="reflector" color="red" position="0 0 10">
<a-animation attribute="rotation" dur="10000" fill="forwards" to="0 360 0" repeat="indefinite"></a-animation>
</a-box>
</a-scene>
</body>
<script>
AFRAME.registerComponent('camera-envmap-material', {
dependencies: ['material'],
init: function(data) {
this.cameraEl = this.data;
this.material = this.el.getObject3D('mesh').material;
this.theElement = this.el;
this.theScene = this.theElement.sceneEl;
if (!this.theScene.renderStarted) {
this.theScene.addEventListener('renderstart', this.init.bind(this));
return;
}
this.cubeCamera = new THREE.CubeCamera( 0.1, 5000, 512);
this.cubeCamera.position.set(5, 2, 4);
this.cubeCamera.updateCubeMap( this.theScene.renderer, this.theScene.object3D );
this.theElement.setObject3D('cube-camera', this.cubeCamera);
this.material.envMap = this.cubeCamera.renderTarget;
this.material.needsUpdate = true;
},
tick:function(){
this.material.envMap = this.cubeCamera.renderTarget;
this.material.needsUpdate = true;
}
});
</script>
</html>
A component would be okay to set properties on an existing material. A shader is more for registering shaders/materials, but A-Frame already has basic/standard materials. And you want the selector property in the schema.:
AFRAME.registerComponent('camera-envmap-material', {
dependencies: ['material'],
// Selector type so we do `<a-entity camera-envmap-material="#cubecamera">`.
schema: {
type: 'selector'
},
init: function () {
var cameraEl = this.data;
var material = this.el.getObject3D('mesh').material;
// Set envmap on existing material.
// This assumes you have a CubeCamera component that does `setObject3D('cube-camera', new THREE.CubeCamera)`.
material.envMap = cameraEl.getObject3D('camera').renderTarget;
material.needsUpdate = true;
}
});
Update
AFRAME.registerComponent('camera-envmap-material', {
dependencies: ['material'],
init: function () {
var cameraEl = this.data;
var material = this.el.getObject3D('mesh').material;
if (!this.el.sceneEl.renderStarted) {
this.el.sceneEl.addEventListener('renderstart', this.init.bind(this));
return;
}
var cubeCamera = new THREE.CubeCamera( 1, 100000, 128 );
cubeCamera.position.set(5, 2, 4);
cubeCamera.updateCubeMap( this.el.sceneEl.renderer, this.el.sceneEl.object3D );
this.el.setObject3D('cube-camera', cubeCamera);
material.envMap = cubeCamera.renderTarget;
material.needsUpdate = true;
}
});

iOS Safari zooms into webpage from landscape to portrait

My problem is for my webpage designed for iOS. When testing on iPhone 5 (Safari) it loads fine in portrait mode then flips fine to landscape mode. But when going back to Portrait from Landscape it zooms in. I don't have this issue with iOS Chrome thought.
I've tried lots of different meta tags like :
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" >
But they seem to only cover the opposite issue of going from portrait to landscape zooming.
Some help would be greatly appreciated. I've spend many hours searching without success.
Here's a link if you wish to try it on a mobile device: http://www.blueberry-studio.co.uk/Robomoco_Websites/Device_iPhone_5/
and here's the code used:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1,IE=edge" />
<meta name="viewport" content="user-scalable=no, width=1280" />
<meta name="apple-mobile-web-app-capable" content="yes"/>
<style type="text/css">
#media screen and (orientation:portrait)
{
#robomocomobileportrait_hype_container {
display: block;
}
#robomocomobilelandscape_hype_container{
display: none;
}
}
#media screen and (orientation:landscape)
{
#robomocomobileportrait_hype_container {
display: none;
}
#robomocomobilelandscape_hype_container {
display: block;
}
}
</style>
<div id="robomocomobileportrait_hype_container" style="position:relative;overflow:hidden;width:1280px;height:2260px;">
<script type="text/javascript" charset="utf-8" src="Robomoco_mobile_portrait.hyperesources/robomocomobileportrait_hype_generated_script.js?71837"></script>
</div>
<div id="robomocomobilelandscape_hype_container" style="position:relative;overflow:hidden;width:1280px;height:720px;">
<script type="text/javascript" charset="utf-8" src="Robomoco_mobile_landscape.hyperesources/robomocomobilelandscape_hype_generated_script.js?17049"></script>
</div>
I've found a way that resolves my problem:
var alsoenlarge = true;
$(function(){
if(isScalePossible()){
$('body').css({overflow:'hidden'}); //geen scrollbars
$('#scalecontainer').css({position: 'absolute', margin: 0}); //centreren met de hand na resize
// Run scale function on start
scaleSite();
scaleSite();
// run scale function on browser resize
$(window).resize(scaleSite);
}
});
function scaleSite()
{
windoww = $(window).width();
sitew = $('#scalecontainer').width();
f = windoww/sitew;
if(!alsoenlarge && f>1) f = 1;
$('#scalecontainer').css({
"-moz-transform" : "scale("+f+")",
"-webkit-transform" : "scale("+f+")",
"-ms-transform" : "scale("+f+")",
"-o-transform" : "scale("+f+")",
"transform" : "scale("+f+")",
"left" : ((windoww-(sitew*f))/2)+"px"
});
}
function isScalePossible()
{
can = 'MozTransform' in document.body.style;
if(!can) can = 'webkitTransform' in document.body.style;
if(!can) can = 'msTransform' in document.body.style;
if(!can) can = 'OTransform' in document.body.style;
if(!can) can = 'transform' in document.body.style;
if(!can) can = 'Transform' in document.body.style;
return can;
}
And my content in this div:
<div id="scalecontainer"> </div>

Resources