Click and Drag component of A-frame for parent entity - aframe

I have created a dice entity from six plane entities. However, when I click and drag the dice entity, instead of moving that dice, only one sided face gets dragged.
This can be tried hands on at link http://shrouded-chamber-73425.herokuapp.com/

Rather than creating a box from six planes, you should create one box and use a material that will render the dice faces for you. You can use three.js CubeTexture:
AFRAME.registerComponent('dice-texture', {
init: function () {
var box = this.el.getOrCreateObject3D('mesh');
var loader = new THREE.CubeTextureLoader();
loader.setPath('/images/diceTextures/');
var textureCube = loader.load([
'1.png', '2.png',
'3.png', '4.png',
'5.png', '6.png'
]);
box.material = new THREE.MeshStandardMaterial({envMap: textureCube);
}
});
<a-entity geometry="primitive: box" dice-texture></a-entity>
Then you can further optimize so that every box shares the same material so you aren't creating a new one each time.

Related

How can I learn pixels band values from image in screen of Earth Engine?

I want to learn pixels band values, for example when I clik on mNDWI image in screen of Earth Engine, I need learning values of red, green and blue
var geometry=ee.Geometry.Polygon([[38.877002459052335,40.75574968156597],
[41.206104021552335,41.17882292442983],
[40.645801287177335,41.59918091806734],
[40.052539568427335,41.84517989453356],
[39.569141130927335,41.886088143011904],
[38.800098162177335,41.48405920501165],
[38.877002459052335,40.75574968156597],
]);
var s2SR = ee.ImageCollection('COPERNICUS/S2_SR')
//filter start and end date
.filter(ee.Filter.calendarRange(2020,2020,'year'))
.filter(ee.Filter.calendarRange(8,8,'month'))
//filter according to drawn boundary
.filterBounds(geometry)
.filterMetadata('CLOUD_COVERAGE_ASSESSMENT', 'less_than',10);
//Map.addLayer(s2SR, {bands:['B4', 'B3', 'B2'], min:0, max:8000}, 's2SR');
// adding mNDWI function
var addMNDWI = function(image) {
var mndwi = ee.Image(image).normalizedDifference(['B3', 'B11']).rename('MNDWI');
return ee.Image(image).addBands(mndwi);
};
var mndwı=s2SR
.map(addMNDWI);
Map.addLayer(mndwı.first(), { min:245, max:5000}, 'mndwı');
It is simple to view the values for any displayed image. First, click on the “Inspector” tab in the top right pane of the Earth Engine Code Editor.
Then, click wherever you want on the map. The Inspector tab will display:
The coordinates of the location you clicked.
The values of every band of every image under that point. (When there are many, as a chart.)
The details of the image (or feature), including properties.

Aframe gltf-model demo with envmap

It's very convenient to load GLTF- model in aframe, but no case is found that contains envmap texture. I'd like to see that the official can provide the same case as three official. pmremGenerator.fromEquirectangular(texture) function is used to make gltf model produce real reflection effect
https://threejs.org/examples/#webgl_loader_gltf
https://threejs.org/examples/#webgl_materials_envmaps_hdr
One way would be creating a custom component, which will:
wait until the model is loaded
traverse through the object's children
if they have a material property - apply the envMap
The envmap needs to be a CubeTexture - which adds another level of complication, when you want to use a panorama. You can use a the WebGLRenderTargetCube - It's an object which provides a texture from a Cube Camera 'watching' the panorama.
Overall The component code could look like this:
// create the 'cubecamera' objct
var targetCube = new THREE.WebGLRenderTargetCube(512, 512);
var renderer = this.el.sceneEl.renderer;
// wait until the model is loaded
this.el.addEventListener("model-loaded", e => {
let mesh = this.el.getObject3D("mesh");
// load the texture
var texture = new THREE.TextureLoader().load( URL,
function() {
// create a cube texture from the panorama
var cubeTex = targetCube.fromEquirectangularTexture(renderer, texture);
mesh.traverse(function(node) {
// if a node has a material attribute - it can have a envMap
if (node.material) {
node.material.envMap = cubeTex.texture;
node.material.envMap.intensity = 3;
node.material.needsUpdate = true;
}
});
}
Check it out in this glitch.
I was having the same issue and i found that cube-env-map from a-frame-extras works like a charm.
View component on GitHub
Its docs describe it as:
Applies a CubeTexture as the envMap of an entity, without otherwise
modifying the preset materials
And the code is super simple:
yarn add aframe-extras
import 'aframe-extras'
<a-entity
gltf-model="src: url('/path/to/file.glb')"
cube-env-map="path: /cubeMapFolder/;
extension: jpg;
reflectivity: 0.9;">
</a-entity>
In THREE demo, I remember that WebGLRenderTargetCube was used to produce envmap, but recently it was found thatPMREMGenerator was basically used to generate envmap texture with mipmap. It also supports HDR image format, making gltf model better than JPG texture.
I don't know how these JS modules PMREMGenerator and RGBELoader are used together with the components of Aframe. Can someone provide such an example in Aframe ,Thanks
That's the same High dynamic range (RGBE) Image-based Lighting (IBL) using run-time generated pre-filtered roughness mipmaps (PMREM)

Aframe Image with Depth one side only

I want to show an image with a frame. Using <a-image> gives me a plane with the image.
<a-box src="path/to/img.jpg> however gives me the image but it's giving me the image 6 times. Is it possible to get the box with am image at the front and any color at all other sides?
I don't know if you can do this with Aframe (I don't think so), but you can do it with Threejs, by making an array of materials that contain a material for each box face, and applying that to the box mesh.
const loadManager = new THREE.LoadingManager();
const loader = new THREE.TextureLoader(loadManager);
const materials = [
new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-1.jpg')}),
new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-2.jpg')}),
new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-3.jpg')}),
new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-4.jpg')}),
new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-5.jpg')}),
new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-6.jpg')}),
];
loadManager.onLoad = () => {
const cube = new THREE.Mesh(geometry, materials);
scene.add(cube);
cubes.push(cube); // add to our list of cubes to rotate
};
you can place this code inside of a custom component that is attached the cube geometry.
Here is the tutorial that the above code was taken from, on threejsfundamentals.

On mesh click, ArcRotateCamera focus on

I'm using ArcRotateCamera, when I click on mesh, I have to focus camera on
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2, Math.PI / 2, 300, BABYLON.Vector3.Zero(), scene);
camera.setTarget(BABYLON.Vector3.Zero());
// on mesh click, focus in
var i = 2;
var pickInfo = scene.pick(scene.pointerX, scene.pointerY);
if (pickInfo.hit) {
pickInfo.pickedMesh.actionManager = new BABYLON.ActionManager(scene);
pickInfo.pickedMesh.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger,
function (event) {
camera.position = (new BABYLON.Vector3(pickInfo.pickedPoint.x, pickInfo.pickedPoint.y, camera.position.z + i));
i += 2;
})
);
}
this code changes mesh's z position but don't makes it in the center of screen
There are a few things that can be changed in your code.
1st - what you are doing is executing a code action after a click, instead of simply running the code in the callback after a pick has occurred. You are registering a pick action (technically user click) on right on the first frame, but only if the mouse was found in the right location at the right moment. My guess is that it didn't work every time (unless you scene is covered with meshes :-) )
2nd - you are changing the camera's position, instead of change the position to which it is looking. Changing the camera's position won't result in what you want (to see the selected mesh), it will move the camera to a new position while still focusing on the old position.
There are a few ways to solve this. The first is this:
scene.onPointerDown = function(evt, pickInfo) {
if(pickInfo.hit) {
camera.focusOn([pickInfo.pickedMesh], true);
}
}
The ArcRotate camera provides focusOn function that focuses on a group of meshes, while fixing the orientation of the camera. this is very helpful. You can see a demo here:
https://playground.babylonjs.com/#A1210C#51
Another solution would be to use the setTarget function:
https://playground.babylonjs.com/#A1210C#52
Which works a bit differently (notice the orientation change of the camera).
Another thing - use the pointer events integrated in Babylon, as they are saving you the extra call for a scene pick. pointer down is executed with the pickinfo integrated in the function, so you can get the picking info of the current pointer down / up / move each frame.
**** EDIT ****
After a new comment - since you want to animate the values, all you need to do is store the current values, calculate the new ones, and animate the values using the internal animation system (documentation here - https://doc.babylonjs.com/babylon101/animations#basic-animation) . There are many ways to achieve this, I took an old function and modernized it :-)
Here is the demo - https://playground.babylonjs.com/#A1210C#53

What's the easiest way to render a 2D shape in an A-Frame scene?

Say, a shape of a human outline.
Ideally it could be converted to 3d by extruding, but even if it has no depth, that's fine for my use case.
I think the easiest way would be taking a transparent png image (the human outline), and use it as a source for an a-plane
<a-plane material="src: img.png; transparent: true"></a-plane>
Glitch here.
....but if you want to create a geometry with a custom shape, which will be helpful for extrusion, then check this out:
Creating a simple shape with the underlying THREE.js
First you need an array of 2D points:
let points = [];
points.push(new THREE.Vector2(0, 0));
// and so on for as many as you want
Create a THREE.Shape object which vertices will be created from the array
var shape = new THREE.Shape(points);
Create a mesh with the shape geometry, and any material, and add it to the scene, or entity
var geometry = new THREE.ShapeGeometry(shape);
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
var mesh = new THREE.Mesh(geometry, material);
entity.object3D.add(mesh);
More on:
1) THREE.Shape
2) THREE.ShapeGeometry
3) THREE.Mesh
Extrusion
Instead of the ShapeGeometry you can use the ExtrudeGeometry object:
var extrudedGeometry = new THREE.ExtrudeGeometry(shape, {amount: 5, bevelEnabled: false});
Where the amount is basically the "thickness". More on Three.ExtrudeGeometry here.
Usage with AFRAME
I'd recommend creating an AFRAME custom component:
js
AFRAME.registerComponent('foo', {
init: function() {
// mesh creation
this.el.object3D.add(mesh);
}
})
HTML
<a-entity foo></a-entity>
2D shape here.
Extruded 2D shape here.
Three.js examples here. They are quite more complicated than my polygons :)
There are also a couple of pre-built A-Frame components you could use to help with extrusion.
https://github.com/JosePedroDias/aframe-extrude-and-lathe
https://github.com/luiguild/aframe-svg-extruder
You can find examples of usage in each of those repos.

Resources