aframe glTF cube-env-map - aframe

I'm unable to see any reflexion on my gtLF model using "cube-env-map".
I'd like to get something like this :
helmet from threejs.org examples
I don't know if this is because of the .jpg files I use, or html or linked javascript scripts, or... anything else?
Here's my html :
<!DOCTYPE html>
<html>
<head>
<script src="https://aframe.io/releases/0.8.2/aframe.min.js"></script><!-- Master file for aframe (== a-scene) -->
<script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js"></script><!-- webcam/mobilecam -->
<script src="https://mkwy.fr/js/play-all-model-animations.js"></script><!-- animation -->
<script src="https://mkwy.fr/js/aframe-orbit-controls.min.js"></script><!-- orbit cam around target -->
<script src="https://mkwy.fr/js/aframe-extras.js"></script><!-- cub-env-map -->
</head>
<body>
<a-scene vr-mode-ui="enabled: false" embedded>
<a-assets>
<a-asset-item id="toy" src="https://mkwy.fr/assets/toyDrummerSolo.glb"></a-asset-item>
</a-assets>
<a-entity
gltf-model="#toy"
cube-env-map="path: https://mkwy.fr/assets/cube-env/; extension: jpg; reflectivity: 0.9;"
play-all-model-animations >
</a-entity>
<a-entity camera look-controls orbit-controls="target: 0 1 0; minDistance: 0.5; maxDistance: 60; initialPosition: 0 5 5"></a-entity>
</a-scene>
</body>
</html>
Many thanks in advance for your help,

(Assuming there are no console errors suggesting incorrect cubemap paths, or wrong extensions)
If your model looks like this:
And you want it to be more like this:
Then the answer lies in two factors - metalness, and roughness.
roughness determines whether the material is like a mirror (0), or completely diffuses the reflection (1).
metalness determines whether the material is metallic (1), or not (0).
You can deal with this in at least two ways:
Modify the materials in a modelling software like blender, or maya.
Modify the properties within an a-frame custom component.
A component would have to wait until the model is loaded, and change all (or some selected) model nodes. Like this:
AFRAME.registerComponent("foo", {
init: function() {
// wait until the model is loaded
this.el.addEventListener("model-loaded", e => {
// grab the mesh
let mesh = this.el.getObject3D("mesh");
mesh.traverse(node => {
// ignore nodes without materials
if (!node.material) return;
// assign the values.
node.material.metalness = 1;
node.material.roughness = 0;
})
})
}
})
You can check it out in this example.
The helmet is working with both jpg and png maps. As for arjs, if your model will be glitchy, and you'll experience z-fighting, just set the logarithmicDepthBuffer in the renderer:
<a-scene renderer="logarithmicDepthBuffer: true" embedded arjs>
Example here
.Seems to be working as expected:

Ok, I changed the settings in Blender, adding metalness, and now it works like a charm. It was confusing because in Blender you don't need to set metalness to get reflection (i.e. : a plastic bottle may have reflections). I have to play with these parameters. Many thanks!

Related

Why the ocean program in documentation is not working and showing error?

In Official documentation there's a program in which they mentioned reference of Don McCurdy’s aframe-extras to get for Aframe 1.2.0. But when I am running the program using CDN of production link. It never works. And I receive the following error as well.
My code is :
<!
DOCTYPE html>
<html lang="en">
<head>
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras#v6.1.1/dist/aframe-extras.min.js"></script>
<title>Proyectos</title>
</head>
<body>
<a-scene physics>
<script>
AFRAME.registerPrimitive('a-ocean', {
// Attaches the `ocean` component by default.
// Defaults the ocean to be parallel to the ground.
defaultComponents: {
ocean: {},
rotation: {x: -90, y: 0, z: 0}
},
// Maps HTML attributes to the `ocean` component's properties.
mappings: {
width: 'ocean.width',
depth: 'ocean.depth',
density: 'ocean.density',
color: 'ocean.color',
opacity: 'ocean.opacity'
}
});
</script>
<a-ocean color="aqua" depth="100" width="100"></a-ocean>
</a-scene>
</body>
</html>
a-ocean is defined in a-frame extras, so there is no need for you to define it again, you should be able to just use it. That explains the first error ("a-ocean is already registered").
Unfortunately is written using the THREE.js Geometry component, which was deprecated in THREE.js r125.
That corresponds to A-Frame 1.2.0.
This explains the second error ("mergeVertices is not a function").
So (until someone updates a-ocean) you have to use A-Frame 1.1.0 or earlier if you want to use a-ocean.
This code will give you a basic ocean
<html lang="en">
<head>
<script src="https://aframe.io/releases/1.1.0/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras#v6.1.1/dist/aframe-extras.min.js"></script>
<title>Proyectos</title>
</head>
<body>
<a-scene physics>
<a-ocean color="aqua" depth="100" width="100"></a-ocean>
</a-scene>
</body>
</html>
In terms of getting a-ocean fixed, it looks like there has been some work on this:
https://github.com/n5ro/aframe-extras/issues/362
That issue includes sample code for a fix, but nobody has made it into a PR yet...

How does the asset schema property work with img assets?

I am trying to pass an image as an asset property type to some other component (so that either a #selector or a url(url) can be passed) but it seems to take in the entire html component, instead of just the url.
<!DOCTYPE html>
<html>
<head>
<title>Hello, WebVR! - A-Frame</title>
<meta name='description' content='Hello, WebVR! - A-Frame'>
<script src='../../global/js/aframe-v0.8.0.min.js'></script>
<script>
AFRAME.registerComponent('some-component', {
schema: {
image: {type:'asset', default:''},
model: {type:'asset', default:''}
},
init: function() {
console.log(this.data.image); //prints out <img id="SomeImage" src="../../someDir/someFile.jpg">
console.log(this.data.model); //prints out '../../someDir/someModel.gltf'
}
});
</script>
</head>
<body>
<a-scene >
<a-assets timeout='3000'>
<!-- this works as an asset no problem -->
<a-asset-item id='SomeModel' src='../../global/assets/models/gltf/UserHead/UserHead.gltf'></a-asset-item>
<!-- this does not pass as an asset but rather an html element -->
<img id='SomeImage' src='../../global/assets/textures/equirectangular/CloudySky.jpg'>
</a-assets>
<a-entity some-component='image:#SomeImage; model:#SomeModel;'></a-entity>
</a-scene>
</body>
</html>
Thought I might look to see how A-Frame handles this in the material component can't see where does the 'src' property on material come from?
<a-entity id='skyBox'
geometry='primitive:sphere; radius:50; segments-height:6; segments-width:6;'
material='shader:flat; src:#skyMap; side:back; height:2048; width:2048'>
</a-entity>
Material component (can't see src): https://github.com/aframevr/aframe/blob/master/src/components/material.js
Thanks!
EDIT:
As per Piotr's discoveries below it looks like images are handed as a special case, as can be in the src code here with frame 0.8.0 where an image source is handed like this:
hash: function (data) {
if (data.src.tagName) {
// Since `data.src` can be an element, parse out the string if necessary for the hash.
data = utils.extendDeep({}, data);
data.src = data.src.src;
}
return JSON.stringify(data);
},
So basically if an image we the asset property will not handle image's properly and an additional step of grabbing the url from it via
data.src.src
OR
data.src.getAttribute('src');
Please correct me if i'm wrong, but i think it's not in the material schema.
I think the devil's in the component.js, which not only seems to allow you to assign a value to any given property, but also has the constructor for any component, and parses the schema.
That being said, the material does not need a src in the schema, as it seems to be a part of every component. Furthermore there are multiple parsers like the assetParse, or src-loader, checking whether an attribute is a html element, or even a video / image asset.
As for the material part, check out the dist source code, where
I think what you're looking for is:
module.exports.updateMapMaterialFromData
where you can see a-frame team uses the data.src for the material, and updates the texture with it. Just give it a ctrl+F (only 3 hits).
So when
module.exports.updateMapMaterialFromData('map', 'src', shader, data);
is called, with the given definition:
module.exports.updateMapMaterialFromData = function (materialName, dataName, shader, data) {
var el = shader.el;
var material = shader.material;
var src = data[dataName];
.......
makes src = data[src] => they make updates using a local variable src.
Also you can see the src-loader in action where the material system is registered, and when a src attribute is found out, the validateSrc function fires one of the two callbacks:
utils.srcLoader.validateSrc(src, loadImageCb, loadVideoCb);

scene api - getAframeElements

I have use floorplan conversion api to convert my 2d floorplan to 3d and get the sceneId back 71c8eef9-b44e-447f-a0d2-fd299318da56.
I want to convert it to afame component inside my aframe application.So I use getAframeElements and get two entity back and following your official sample:
const sceneEl = document.querySelector('a-scene')
io3d.scene.getAframeElements(sceneId)
.then(elements => {
// this will give us two elements
// The first is the actual scene according to the scene structure hierarchy
// The second is the camera with potential waypoints that where defined in the scene structure
// you can leverage the waypoints using our A-Frame tour component
elements.forEach((el) => {
// add elements to the scene
sceneEl.appendChild(el)
})
sceneEl.appendChild(element)
})
Then It added to aframe, but nothing happens! I got nothing.
Do I miss something?
Hard to tell what's going on there without the full HTML and JavaScript, but the full code to get that working is:
<!DOCTYPE html>
<html>
<head>
<script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script>
<script src="https://3d.io/releases/3dio-js/1.x.x/3dio.min.js"></script>
</head>
<body>
<a-scene></a-scene>
<script>
io3d.scene.getAframeElements('71c8eef9-b44e-447f-a0d2-fd299318da56').then(elems => {
document.querySelector('a-scene').appendChild(elems[0])
})
</script>
</body>
</html>
And you can see it working at https://aspiring-snowman.glitch.me/

Google Visualization and Plone - "e[0].K is undefined" error message

I just posted this in the Google Visualization group, but I thought I would reach out to the Plone community as well for help.
I am using Plone 4.2.4 and wanted to integrate Google Charts with an Oracle back end via cx_Oracle. There is already a very nice package called EEA.Daviz. However, it was way more than I needed and I thought I could do it on my own, so I created some page templates and Python code that wraps the Javascript. On my laptop (Mac OS X) it all worked fine.
However, once I pushed it to my server (SLES 10), BarCharts stopped working. I have only tested Bar, Line and Motion charts. All I get is a red error box that says "e[0].K is undefined". After googling around, I found a very similar description of my problem that suggests it is a Google Visualization error and the fix is to change the width and height properties. However, changing the height or width did not fix it. What is very strange is that, if I copy the example JS from the BarChart page and copy it into a vanilla Zope Page Template, it works just fine. However, once I wrap it in the master template, I get the red error message again.
So I am confused. I have the same theme installed on my laptop and it did not give me any problems. I know I can display BarCharts on the server without the theme in a vanilla Page Template.
Can anyone point me in the right direction?
ZPT that Works:
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['COUNTRY', ' COUNT'],
['Austria', 19],
['Belgium', 73],
['Bulgaria', 20]]
); var options = {
title: 'Test Bar Chart'}; var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
chart.draw(data, options);}
</script>
</head>
<body>
<div id="chart_div" style="width: 900px; height: 1000px;"></div>
</body>
</html>
ZPT that does NOT work:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="context/main_template/macros/master"
i18n:domain="plone">
<metal:main fill-slot="javascript_head_slot">
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['COUNTRY', ' COUNT'],
['Austria', 19],
['Belgium', 73],
['Bulgaria', 20]]
); var options = {
title: 'Test Bar Chart'}; var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
chart.draw(data, options);}
</script>
</metal:main>
<body>
<metal:main fill-slot="main">
<tal:main-macro metal:define-macro="main">
<div id="chart_div" style="width: 900px; height: 1000px;"></div>
</tal:main-macro>
</metal:main>
</body>
</html>
I've tested your second example and it seems to work as intended so maybe there is something wrong with your data coming from Oracle (format, missing values, etc). You'll have to do some JS debugging out there. Try adding a breakpoint to see what e[0] is and why it doesn't have the K attribute (or why e is an empty Array).
Also, EEA Daviz is a bundle that brings together multiple Visualization frameworks (Google Charts, Simile Exhibit and in the near future Highcharts) but you can always use one or more of its components without bringing in the entire plane Thus, you should also try EEA Google Charts. Don't forget that you'll need collective.js.jqueryui < 1.9 for Plone 4.2.x

Google maps KML polygons

I have successfully imported a kml file to a Google map so that it displays real estate boundaries.
I have also used the tutorial at https://google-developers.appspot.com/maps/documentation/javascript/examples/polygon-arrays to draw simple polygons and have them click-able.
However, I don't know how to make the polygons created by the kml file click-able. The polygons on the kml are quite complex shapes and consist of many coordinates to form the polygons. The example below is just for 1 real estate boundary:
-83.6530304633209,34.8237504877659,0 -83.65536046332301,34.8248804877671,0 -83.65672046332431,34.8262904877683,0 -83.6567504633242,34.8271904877693,0 -83.655330463323,34.8308304877725,0 -83.6565104633242,34.8333304877749,0 -83.65765046332511,34.8349204877764,0 -83.6571104633247,34.8383604877794,0 -83.6591604633265,34.8443604877853,0 -83.6588104633263,34.8468904877875,0 -83.6591604633265,34.8507504877912,0 -83.6583904633258,34.8543804877945,0 -83.6569404633244,34.8566604877968,0 -83.65475046332242,34.8599504877998,0 -83.6545604633223,34.8610404878007,0 -83.6543204633219,34.8635704878032,0 -83.65568046332331,34.8684104878075,0 -83.6553904633231,34.8695004878086,0 -83.6546604633224,34.8706904878097,0 -83.654380463322,34.872050487811,0 -83.6552304633228,34.8745504878134,0 -83.65494046332262,34.8759104878145,0 -83.65377046332161,34.8768304878154,0 -83.6504704633185,34.8796104878179,0 -83.64877046331689,34.8814504878196,0 -83.6469204633151,34.8849204878229,0 -83.6450204633134,34.8870304878249,0 -83.64227046331081,34.8897904878275,0 -83.6389204633076,34.8911304878288,0 -83.6344604633034,34.8921304878297,0 -83.6330604633022,34.8926104878301,0 -83.6295204632988,34.8948504878322,0 -83.6278404632974,34.8969604878341,0 -83.6273304632969,34.89832048783551,0 -83.62726046329681,34.8994904878366,0 -83.6286904632982,34.9030704878399,0 -83.6287304632981,34.9045104878412,0 -83.62844046329791,34.9056004878421,0 -83.6268704632964,34.9077104878443,0 -83.6256904632953,34.9086304878451,0 -83.6240704632939,34.9091204878455,0 -83.6226304632926,34.9088804878452,0 -83.6204304632904,34.9083904878448,0 -83.6179704632882,34.9100604878463,0 -83.61680046328711,34.9109904878471,0 -83.6157204632862,34.9116404878477,0 -83.61126046328189,34.9123704878484,0 -83.610200463281,34.91347048784951,0
These coordinates do not work when i manually convert them into latlng pairs and insert them into the Google tutorial above like so:
new google.maps.LatLng(-83.6530304633209,34.8237504877659),
new google.maps.LatLng(83.65536046332301,34.8248804877671),
new google.maps.LatLng(-83.65672046332431,34.8262904877683),
new google.maps.LatLng(-83.6567504633242,34.8271904877693)
Anyone have any ideas on how I can either make the kml layer polygons click-able or use the kml data to redraw the polygons and make them click-able?
Thanks
edit: This is the code i'm using to load the kml:
<!-- Declare the application as HTML5 using the <!DOCTYPE html> declaration -->
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map_canvas { height: 100% }
</style>
<!-- include the Maps API JavaScript using a script tag -->
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=AIzaSyAaWOu7N4OX8BlYUwZhvWP2V0P6YQryN9Y&sensor=true"></script>
<script type="text/javascript">
function initialize()
{
<!-- create a JavaScript object literal to hold a number of map properties -->
var myOptions =
{
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP,
fillColor: '#0000ff'
};
<!-- a JavaScript function to create a "map" object -->
var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
var myLayer = new google.maps.KmlLayer('http://www.domain.com/gmaps/1.kml',{suppressInfoWindows: true,map: map});
google.maps.event.addListener
(
myLayer,"mouseover",function()
{
this.setOptions({fillColor: "#000000"});
}
);
google.maps.event.addListener
(
myLayer, 'click', function(kmlEvent)
{
var text = kmlEvent.featureData.description;
showInContentWindow(text);
}
);
google.maps.event.addListener
(
myLayer,"mouseover",function()
{
this.setOptions
(
{
fillColor: "#000000"
}
);
}
);
function showInContentWindow(text)
{
var sidediv = document.getElementById('content_window');
sidediv.innerHTML = text;
}
}
</script>
</head>
<!-- initialize the map object from the body tag's onload event -->
<body onLoad="initialize()">
<!-- create a div element named "map_canvas" to hold the Map -->
<div id="map_canvas" style="width:79%; height:100%; float:left"></div>
<div id="content_window" style="width:19%; height:100%; float:left"></div>
</body>
</html>
Unfortunately, you don't get a mouseover event with the KmlLayerapi-doc; check at the api-doc, scroll down a bit to see the Events, and all you get for events are: click, defaultviewport_changed, and status_changed. I have also explored the options that are available because the KmlLayer is an MVCObjectapi-doc, but that doesn't offer additional events. I don't think this is possible.
There may be another way to achieve what you want, but I haven't found it; let's see what others may be able to add.
Using KmlLayer, you can't change the properties of the Polygons. If you use a third party KML parser like geoxml3 or geoxml-v3 to render the polygons as native Google Maps API v3 objects you can change their properties (but whether the performance is acceptable will depend on how complex your KML is). You can also dynamically change Polygons in tiles rendered using FusionTablesLayer (import your KML into a Fusion Tabel).
Example changing the color of Polygons from KML rendered using geoxml3 on mouseover

Resources