how is it possible to switch between the camera on desktop and VR?
i wanna use the mouse-cursor on desktop and when i enter VR it should switch to another camera with cursor-fusing.
here is my code:
<a-entity id="cam-desktop" camera="userHeight: 1.6; zoom:1 " look-controls mouse-cursor>
</a-entity>
<a-entity id="cam-vr" camera="userHeight: 1.6; zoom:1 " look-controls>
<a-animation begin="cursor-fusing" delay=" 3000" attribute="camera.zoom" from="1" to="4" dur="1000"></a-animation>
<a-animation begin="click" delay="500" attribute="camera.zoom" from="4" to="1" dur="1000"></a-animation>
<a-entity cursor="fuse: true; fuseTimeout:4000" geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03; thetaLength: 360; thetaStart: 0" rotation="0 0 90" position="0 0 -1" material="color: black; side: double; shader: flat">
<a-animation begin="cursor-fusing" attribute="geometry.thetaLength" from="360" to="0" easing="linear" dur="3000"></a-animation>
<a-animation begin="mouseleave" attribute="geometry.thetaLength" from="360" to="360" dur="0"></a-animation>
</entity>
</a-entity>
thank you very much!
You can create a component, which listenes to the 'enter-vr' and 'exit-vr' events, and set the active camera accordingly:
AFRAME.registerComponent('scenelistener',{
init:function(){
let vrcam = document.querySelector("#cam-vr");
let dcam = document.querySelector("#cam-desktop");
let vrmode = false;
this.el.sceneEl.addEventListener('enter-vr',function(){
if(!vrmode){
dcam.setAttribute('active',false);
vrcam.setAttribute('active',true);
vrmode!=vrmode;
}
}
this.el.sceneEl.addEventListener('exit-vr',function(){
if(vrmode){
dcam.setAttribute('active',true);
vrcam.setAttribute('active',false);
vrmode!=vrmode;
}
}
}
});
Actually, You can just paste the listeners anywhere, moreover You could just listen to any event and do stuff accordingly to the received event, I just wanted to show You the concept.Im not sure what happens if 2+ camera's are active, so i made them false on change.
UPDATE
I did not see that the cameras are entities, not primitives, so You have to set the attribute like this: setAttribute('camera','active',true)
I have some issues with the cursor, so i make it visible and invisible, depending on the vr state.
Working fiddle ( at least the camera switch ) here.
Related
I am trying to achive a feature where the user will be able to drag a card component up or down for either extending the content and make the card cover the screen or close the card. The card is resting above a map.
I found this one svelte-gestures package with pan. It works like a sharm when the card sits on the top of the screen but when i put it at the bottom and try to get it to move up i run into all kind of diffcult models that doesnt work.
Here is the code that works with a card at the top extending its height downwards:
<script>
import { pan } from 'svelte-gestures';
let cardHeight = 100;
let initialY = 0;
let screenheight = window.innerHeight;
function handlePan(event) {
let delta = event.detail.y - initialY;
cardHeight += delta;
initialY = event.detail.y;
}
</script>
<div
use:pan="{{delay: 0}}"
on:pan="{handlePan}"
style="height: {cardHeight}px; background-color: lightblue; overflow: hidden; position: absolute; left: 0; right: 0;"
>
<!-- Card content here -->
<div style="height: {cardHeight}px;">
<h1>Card</h1>
<p>Extend and de-extend me!</p>
</div>
</div>
I tried using screenheight and inverting the logic but i just seem to run into very strange problems with the card lagging or flipping all over the place.
Any help would be appreciated!
Best Regards,
Rasmus
I've been trying to update properties of the camera on the fly to no avail - really don't want to setup multiple cameras and switch between them.
AFRAME.registerComponent("camera-controller", {
init: function() {
this.el.addEventListener('model-loaded', this.update.bind(this));
},
update: function() {
var data = this.data;
var el = this.el;
// el.fov = 75;
el.object3D.el.components.camera.data.fov = 20;
el.updateProjectionMatrix();
console.log(el.object3D.el.components.camera.data.fov);
}
});
camera.fov just returns undefined and updateProjectionMatrix() is not a function.
You can simply update the [camera]s FOV property via setAttribute("camera", "fov", newFOV). Something like this:
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
AFRAME.registerComponent("foo", {
init: function() {
// grab the camera
const cam = document.querySelector("[camera]")
// on click
document.body.addEventListener("click", e => {
// grab the current FOV
const fov = cam.getAttribute("camera").fov
// update the camera with the new FOV
cam.setAttribute("camera", "fov", fov == 80 ? 120 : 80)
})
}
})
</script>
<a-scene foo>
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
<a-sky color="#ECECEC"></a-sky>
</a-scene>
You can make the transition animated with the standard animation component (animating camera.fov) - here's an example with one animation (to utilize the above js logic, you could make two animations if you prefer a more 'declarative' style).
I am trying to add animation along y axis to an entity using the animation component and also trying to change it's position along z axis in a custom component. However, the animation component takes the precedence and the position change in z-axis in the custom component does not work.
I would like to change the position along y axis using the animation component and change the position along z-axis using my custom component.
Here is my code -
<a-entity id="orca" position="4 1 -18" gltf-model="#orca1" static-body animation="property: position.y; dir: alternate; dur: 1000; easing: easeInSine; loop: true; to: -1" move></a-entity>
AFRAME.registerComponent('move', {
schema: {
},
init: function() {
this.directionVec3 = new THREE.Vector3(0, 1, 1);
},
tick: function(t, dt) {
var directionVec3 = this.directionVec3;
var currentPosition = this.el.object3D.position;
directionVec3.z = dt/1000;
this.el.setAttribute('position', {
z: currentPosition.z + directionVec3.z
});
if (currentPosition.z > 10) {
this.el.setAttribute('position', {
z: -14
});
}
}
});
Could you please help? The only reason for me to choose the animation component for movement along y-axis is that I get the smooth sine curve movement using easeInSine.
As you’ve seen the animation component overrides your position. In this case you can apply your component to a parent entity to avoid the collision:
<a-entity move>
<a-entity id="orca" position="4 1 -18" gltf-model="#orca1" static-body animation="property: position.y; dir: alternate; dur: 1000; easing: easeInSine; loop: true; to: -1">
</a-entity>
</a-entity>
Using AFrame and three. Have made an AFrame simple scene, a camera, a renderer, a spotlight, a plane and a cube.
I want the cube to cast shadow into the plane.
I have set, using the reference cube.object3D and spotlight.object3D, the .castShadow in the spotlight, in the cube.
I have set, using the reference plane.object3D, the receiveShadow in the plane.
Have also set the renderer.shadowMapEnabled.
But can not see any shadow casted into the plane.
Any hint ?
Thanks a lot.
Shadows have since been added to A-Frame: https://github.com/aframevr/aframe/pull/2350
https://aframe.io/docs/master/components/light.html#configuring-shadows
<a-scene shadow>
<a-entity light="type: directional; castShadows: true"></a-entity>
<a-box shadow="cast: true; receive: true"></a-box>
</a-scene>
many thanks for your answers.
I am learning A-Frame, Three.js, Javascript, and html just by doing.
It is awesome what you are doing with A-Frame.
Done the following, it is not perfect, but for now it works:
In the registerComponent init:function()
In the meshes to cast shadows:
el.getObject3D('mesh').castShadow = data.shadow; //data.shadow = true
In the meshes to receive shadows:
el.getObject3D('mesh').receiveShadow = data.shadow; //data.shadow = true
In the spotlight:
this.spotlight = new THREE.SpotLight(data.colorm);
el.setObject3D('spotlight', this.spotlight);
el.getObject3D('spotlight').castShadow = data.shadow;
el.getObject3D('spotlight').shadow.camera.near = data.shadowcameranear;
el.getObject3D('spotlight').shadow.camera.far = data.shadowcamerafar;
el.sceneEl.systems.light.registerLight(el);
And then using the scene has loaded event:
function setShadows()
{
aframeRenderer.shadowMap.enabled = true;
aframeRenderer.shadowMap.type = THREE.PCFSoftShadowMap;
aframeRenderer.setClearColor(0x000000, 1.0);
aframeRenderer.setSize(window.innerWidth, window.innerHeight);
aframeRenderer.shadowMap.enabled = true;
threeSpotLight.shadowCameraNear = 0.01;
threeSpotLight.castShadow = true;
threeCube.castShadow = true;
threeCube.receiveShadow = false;
threePlane.castShadow = false;
threePlane.receiveShadow = true;
threeSpotLight.visible = true;
}
I am very new to html5.
infact this is my first work.
I am working on a small project. Part of the project is to read an xml file which has shapes in it
<Graphic>
<object_type>LINE</object_type>
<field_1>3.6082475185394287</field_1>
<field_2>541.23712158203125</field_2>
<field_3>28.86598014831543</field_3>
<field_4>474.48452758789062</field_4>
<field_6 />
<field_7 />
<field_8 />
<field_9 />
</Graphic>
<Graphic>
<object_type>LINE</object_type>
<field_1>10.824742317199707</field_1>
<field_2>562.8865966796875</field_2>
<field_3>3.6082475185394287</field_3>
<field_4>541.23712158203125</field_4>
<field_6 />
<field_7 />
<field_8 />
<field_9 />
</Graphic>
after reading the xml file i am iterating through the coordinates. and drawing the object on the html5 canvas.
I have two troubles....
1) the photo is being drawn upside down... so i need to rotate the canvas
Image can be viewed here
2) i need to scale the whole object within the canvas. for now i am dividing every coordinate with 8 to scale it down. how i can scale it according to screen resolution and canvas...
cannot get my head around this
If you are able to get the object width and height, you just need to calculate the scale factor related to the canvas:
var scaleFactorW = canvas.width/obj.width,
scaleFactorH = canvas.height/obj.height;
context.scale(scaleFactorW , scaleFactorH);
startDrawing(obj);
See this DEMO at jsfiddle.net
EDIT:
To maintain the object proportions for different canvas resolutions we need to calculate a scale factor that verifies the max scale based on canvas aspect ratio and the object proportions.
var canvasAspectRatio = canvas.width / canvas.height;
var objAspectRatio = obj.width / obj.height;
var scaleFactor = 1;
if (canvasAspectRatio > objAspectRatio) {
scaleFactor = canvas.height / obj.height;
} else {
scaleFactor = canvas.width / obj.width;
}
context.scale(scaleFactor, scaleFactor);
startDrawing(obj)
Found answer to the first question after doing bit of maths...
my canvas was
<canvas id="myCanvas" width="800" height="500" style="background: #FFFFFF; border: 5px solid black;" role="img">
Your browser does not support the canvas element.
</canvas>
and javascript became...
startDrawing(obj);
// rotate 180 degrees clockwise
context.rotate(180*(Math.PI/180));
// translate context to opposite of your actual canvas
context.translate(-800, -500);
still need the answer for the 2nd question.... the scaling