I want to programmatically move the position of the view in a webvr scene. To do this I am using the position.add method.
Here is how I move the camera programmatically:
<a-entity position="33 0 -33" rotation="0 180 0" look-controls id="camera"
camera="userHeight: 1.6" listener></a-entity>
Camerage is moved here:
var obj3d = document.querySelector("#camera").object3D;
var angleobj = obj3d.getWorldDirection();
angleobj.y = 0;
obj3d.position.add(angleobj.multiplyScalar(0.004*3));
This works in normal mode, but in cardboard mode, the camera is not moving. How can I move the camera in cardboard view mode programmatically?
As far as i know, once you switch to the "VR mode", you get to use other camera than the one outside of "VR mode".
I think You should listen for the VR enter / exit events, and change the camera reference:
this.el.sceneEl.addEventListener('enter-vr',() => {
obj3d = document.querySelector("#camera").object3D;
}
this.el.sceneEl.addEventListener('exit-vr',() => {
obj3d = document.querySelector("#camera").object3D;
}
Please rethink, if this is necessary, when the user moves his head, and the camera goes wild, it can get really dizzy, really fast.
A-frame's Diego Marcos in his anwsers often recommends visual indications WHERE to look, instead of such options.
If the above does not work, try grabbing the camera entity, instead if its object3D:
var obj3d = document.querySelector("#camera");
and move it using the setAttribute() method
obj3d.setAttribute("position", {x: _x, y: _y, z: _z});
Related
I am trying to use the look-at feature of Ar.js dynamically through js. But for some reason, the 3d-object is not looking out of the screen.
Answering the topic
You can set the look-at component using javascript, by adding it to any a-frame entity:
// using an existing entity as a target
entity.setAttribute("look-at", "#selector");
// using a Vector3 position as target
entity.setAttribute("look-at", {x: 0, y: 0, z: 0})
Answering this specific case
The look-at component (and the used by it lookAt method) assume, that the model is orented towards the z-axis.
The duck model is oriented towards the x axis.
If it's possible, reorient the model in a 3D modelling software like blender.
If not, then you can use a parent node to reorient it:
<!-- Parent node will look at the user--/>
<a-entity look-at="[camera]">
<!-- Child node with the rotation offset--/>
<a-entity rotation="0 -90 0" gltf-model ....>
Check it out in this glitch
If there are more models, you can create a rotation offset array, and apply it to the [gltf-model] node each time you load a new model.
The <a-camera> already contains a camera. To change its properties just use the <a-camera> attributes:
<a-camera fov="60" ....></a-camera>
You have to call the lookAt method on the object3D of your entity. Something like this :
var camera = document.querySelector("[camera]");
var position = camera.object3D.position;
entityEl.object3D.lookAt(new THREE.Vector3(position.x, position.y, position.z));
I can create an entity as camera:
<a-entity id="camera" camera look-controls wasd-controls></a-entity>
and get the position and rotation information, but in VR mode the built-in, default camera automatically takes over.
How do I get the same kind of information about that default camera?
Or maybe I need a different KIND of information?
I tried this:
var scenic = document.querySelector('a-scene');
var cam = scenic.camera;
console.log("camera position x= " + cam.position.x);
But no matter when I trigger the cosole.log (ie; after moving about in the scene) it still signals:
camera position x= 0
For context: I want to make a projectile launcher that follows the camera around and allows users to launch from camera position in the direction and angle of the camera's FOV...
See example (triggered, at the moment, by pressing the P key in the registered component "launcher")
https://glitch.com/edit/#!/query-aframe-camera-position-rotation?path=index.html:27:0
var position = document.querySelector('a-scene').camera.el.object3D.position;
I have six planes set up as cube with textures to display a 360-degree jpg set. I positioned the planes 1000 away and made them 2000 (plus a little because the photos have a tiny bit of overlap) in height and width.
The a-camera is positioned at origin, within this cube, with wasd controls set to false, so the camera is limited to rotating in place. (I am coding on a laptop, using mouse drag to move the camera.)
I also have a sphere (invisible), placed in between the camera and the planes, and have added an event listener to it. This seemed simpler than putting event listeners on each of the six planes.
My current problem is wanting to enforce minimum and maximum tilt limits. Following is the function "handleTilt" for this purpose. The minimum tilt allowed depends on the size of the fov.
function handleTilt() {
console.log("handleTilt called");
var sceneEl = document.querySelector("a-scene");
var elCamera = sceneEl.querySelector("#rotationCam");
var camRotation = elCamera.getAttribute('rotation');
var xTilt = camRotation['x'];
var fov = elCamera.getAttribute('fov');
var minTilt = -65 + fov/2;
camRotation['x'] = xTilt > minTilt ? xTilt : minTilt;
// enforce maximum (straight up)
if (camRotation['x'] > 90) {
camRotation['x'] = 90;
}
console.log(camRotation);
}
The event handler is set up in this line:
<a-entity geometry="primitive:sphere" id="clickSphere"
radius="50" position="0 0 0" mousemove="handleTilt()">
When I do this, a console.log call on #clickSphere shows the event handler exists. But it is never invoked when I run the program and move the mouse to drag the camera to different angles.
As an alternative, I made the #clickSphere listen for onClick as follows:
<a-entity geometry="primitive:sphere" id="clickSphere"
radius="50" position="0 0 0" onclick="handleTilt()">
The only change is "mousemove" to "onclick". Now, the "handleClick()" function executes with each click, and if the camera was rotated to a value less than the minimum, it is put back to the minumum.
One bizarre thing, though, after clicking and adjusting the rotation a few times, the program goes into a state where I can't rotate the camera down below the minimum any more. It is as if the mousemove listener had become engaged, even though the only listener coded is the onclick. I can't for the life of me figure out why this kicks in.
Would it be possible to get some advice as to what I might be doing wrong, or a plan for troubleshooting? I'm new to aframe and JavaScript.
An alternative plan for enforcing the min and max camera tilts in real time would also be an acceptable solution.
I just pushed out this piece on the docs for ya: https://aframe.io/docs/0.6.0/components/look-controls.html#customizing-look-controls
While A-Frame’s look-controls component is primarily meant for VR with sensible defaults to work across platforms, many developers want to use A-Frame for non-VR use cases (e.g., desktop, touchscreen). We might want to modify the mouse and touch behaviors.
The best way to configure the behavior is to copy and customize the current look-controls component code. This allows us to configure the controls how we want (e.g., limit the pitch on touch, reverse one axis). If we were to include every possible configuration into the core component, we would be left maintaining a wide array of flags.
The component lives within a Browserify/Webpack context so you’ll need to replace the require statements with A-Frame globals (e.g., AFRAME.registerComponent, window.THREE, AFRAME.constants.DEFAULT_CAMERA_HEIGHT), and get rid of the module.exports.
Can modify https://github.com/aframevr/aframe/blob/master/src/components/look-controls.js to hack in your min/max just for mouse/touch.
I have an A-Frame multiplayer project, which relies on each user moving around the map, and it works well in desktop browsers. The stumbling block is the lack of motion controls in mobile, like the WASD-controls for the camera.
What workaround would you suggest? Perhaps, adding on-screen buttons and triggering keypress events with jQuery?
Or is there a more straightforward method of adding a function that would change the camera position for each on-screen button press? In this case, is there a way to find the exact functions attributed to the W, A, S, D keys?
Among several things I've tried was:
$(".up-button").click(function(){
window.dispatchEvent(new KeyboardEvent('keypress',{keyCode: 38}));
And another one:
var e = jQuery.Event("keydown");
e.which = 38;
$(window).trigger(e);
Neither is producing any change.
Have you tried something like:
window.dispatchEvent(new KeyboardEvent('keypress',{keyCode: 38} ) );
to simulate pressing the up arrow key?
You could simulate pressing wasd or up down left right.
The rotation might be a little more tricky though,
you would have to simulate the onMouseDown and onMouseMove events.
I see what you mean. Most people wouldn't even have a controller to properly move the character in your project/game. I've seen in a demo in A-Frame that is pretty clever in my opinion. Basically if the user is looking down on floor, then the camera moves forward. This is good as it requires no outside input whatsoever so it works on everything.
As how to implement it, this may be a solution:
//First calculate the verticle angle of the camera
var verticalAngle = getVerticalAngle(camera.getWorldDirection());
console.log('vertical angle:' + verticalAngle);
function getVerticalAngle(cameraVector) {
return vRadiansToDegrees(Math.atan(cameraVector.y));
}
function vRadiansToDegrees(radians) {
return radians * 180 / Math.PI;
}
And then move the camera forward if the user is looking down on the floor
if (verticalAngle < -43) {
//move camera
}
I have an interface I developed with three.js using the CSS3DObject rendering tool.
I have set the orbit to 0 to prevent rotating and limit my movement to panning and zooming.
Please note I'm also using Orbit Control.
I set the position of the camera to x=-2000 with the following code:
camera.position.x=-2000;
camera.position.z=4000;
When I do this, the camera moves positions but is still pointing to (0,0,0) resulting in a skewed look.
So I assume that I need to give it a vector
camera.up = new THREE.Vector3(0,1,0); //keeps the camera horizontal
camera.lookAt(new THREE.Vector3(2000,0,0)); //should point the camera straight forward
Please note that I'm still trying to find a good explanation of how setting up the lookAt works.
After a bit more research, it seems that the orbit control is overriding the camera.lookAt and as a result, doesn't do anything.
To achieve the panning I set the location of the camera x position equal to the value of the target.
I also removed the camera.up line.
var myCameraX = -2000;
var myCameraY = 500;
camera.position.x=myCameraX;
camera.position.y=myCamerYa;
control.target.set(myCameraX,myCameraY,0);
Hope that helps someone.