I want to make something similar to this and I have a problem in rotating the camera/scene(I tried both). The problem I am facing is since we cannot set camera rotation in aframe anymore I tried wrapping it into an a-entity tag which I will hereby call camera-rig and rotate that, however, if the user interacts with the camera and then clicks on the button the entity that should be in focus will not be in focus can anyone help me with it
what I want to make(click here)
what I have made(click here)
To rotate the world in glitch please click on introduce button in the scene
Animating the look at to move towards the target is a bit more involved.
I mostly got it to work, but there are some problems.
glitch here
Yes it is true that look-controls overrides the rotation component. But you can still set the rotation of the camera using THREEjs commands.
AFRAME.registerComponent('camcontrol',{
init: function(){
let self = this;
this.el.addEventListener('loaded', function(){
self.cam3d = self.el.object3D.children[0];
});
this.el.addEventListener('animationcomplete__look', function(){
self.data.animactive = false;
});
},
update: function(){
if (this.data.animactive){
let rot = this.data.rot;
// console.log('update: rot ', rot);
let euler = new THREE.Euler( rot.x, rot.y, rot.z, 'ZXY');
this.cam3d.setRotationFromEuler(euler);
}
},
lookAt: function(pos){
this.cam3d.lookAt(pos.x, pos.y, pos.z);
}
});
glitch here
Related
Does anyone have a code to force orbit controls in three.js to move the scene on mousemove instead of click + mousemove I've tried using the answer in this thread:
How to recreate the Three.js OrbitControl movement on mouse move?
but sadly it throws an error "Maximum call stack size exceeded error" and I just get a black canvas with nothing in it...
I also tried changing
scope.domElement.addEventListener( 'mousedown', onMouseDown, false );
to
scope.domElement.addEventListener( 'mousemove', onMouseDown, false );
In the OrbitControls.js file but that seems to freeze when moving and stops every now and again...
Has anyone managed to solve this?
Thanks in advance!
How about this; https://jsfiddle.net/EthanHermsey/e3b501cw/51/
document.addEventListener('mousemove', function(e){
let scale = -0.01;
orbit.rotateY( e.movementX * scale );
orbit.rotateX( e.movementY * scale );
orbit.rotation.z = 0; //this is important to keep the camera level..
})
//the camera rotation pivot
orbit = new THREE.Object3D();
orbit.rotation.order = "YXZ"; //this is important to keep level, so Z should be the last axis to rotate in order...
orbit.position.copy( mesh.position );
scene.add(orbit );
//offset the camera and add it to the pivot
//you could adapt the code so that you can 'zoom' by changing the z value in camera.position in a mousewheel event..
let cameraDistance = 1;
camera.position.z = cameraDistance;
orbit.add( camera );
Use an Object3D that acts as a pivot for the camera. It rotates on mouse movement.
EDIT: I found my own answer but found a way. You can enable auto rotate with the mouse position, but you have to make OrbitControl's handleMouseMoveRotate public, by copying the function and setting it as this.handleMouseMoveRotate.
Then in setup you add an event listener and send the event to the controls.
document.body.addEventListener( 'mousemove', ( e )=>{
controls.handleMouseMoveRotate( e )
});
And make sure to set controls.enableRotate = false;
I am trying to create a simple animation based on my mouse movement. An object that is placed in the center of the screen should pull away from the center based on my mouse movement. But when i try to do that the object jitters around a lot despite the mouse movement being smooth.
I have created a fiddle to show the problem: https://jsfiddle.net/ahof0gLc/
The object is moved as follows when the mouse moves:
animX += event.movementX||event.mozMovementX||event.webkitMovementX||0;
It is then pulled back toward the center like so:
if (animX) animX *= Math.pow(0.99, delta);
I have tried several methods. But because the mouse movement is counteracting the deceleration it jitters a lot. How can I fix this?
Updated with a really hacky spring model. Using mouse over and mouse leave to track mouse.
https://jsfiddle.net/eex3aphm/
You have a fight between your mousemove and your animation.
I changed your mouse movement handler to use a temporary variable to hold the movement:
var pullX = 0;
var onMouseMove = function(event) {
event.preventDefault();
pullX = event.movementX||event.mozMovementX||event.webkitMovementX||0;
};
Then moved the update to the deceleration equation:
animX = (animX + pullX) * Math.pow(0.99, delta);
pullX = 0;
This keeps you from messing with your deceleration on mouse move.
https://jsfiddle.net/r57t7v3o/
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 the following problem:
I create a Raphael canvas in a div. This happens as soon as the page is loaded and the initRadar() function is called:
var r;
var paper;
var c;
function initRadar(){
r = $( "#circ" );
paper = Raphael("circ", r.width(), r.height());
c = paper.circle(r.width()/2, r.height()/2, r.height()/2-2);
$(window).on("orientationchange",function(){
//redraw(); // <--- the way I wanted it
setTimeout(function(){ redraw(); }, 300); // <--- *yuck*
});
}
This functions perfectly so far. My problem starts when the orientation of the viewport changes. I thought I could add an event handle to the window, which fires, when the orientation changes and redraw the content. And it works... kind of. I wanted to call the second function:
function redraw(){
c.remove();
c = paper.circle(r.width()/2, r.height()/2, r.height()/2-2);
}
Whenever the orientation changes, this function redraws the content. And this also works... almost. The problem is, I have a race condition. Even though the orientation change event fired, the #circ div still has the old size and position. This leads to the strange effect, that when the viewport is in portrait mode, the landscape circle is drawn and vice versa.
My current solution is to use the timeout function (yuck), to wait a few ms so that the layout is done before I draw the circle. It works, but it is ugly and I don't want to have such a hack in my code.
Can someone point me in the direction how to solve this problem correctly?
I have a really simple scene which has one .dae mesh in it, and a 7000*7000 plane underneath the mesh. I'd like it to be lit by a high SpotLight, so the mesh throws a shadow on the ground. But, something seems to be broken! No matter how high I put the SpotLight, it never lights up the plane! Also, it lights the mesh up only a little, while it is in a small square (perimeter).
You can see the situation here:
As soon as I move the mesh (a monster) around, it wont be lit anymore.
This is how I instantiate the light:
// create a spotlight
self.spotLight = new THREE.SpotLight();
// set its position
self.spotLight.position.y = 1000; //I recon it needs to be relatively high so it lights up everything
self.spotLight.position.x = 0; //(0, 0) are the coordinates where the mesh is spawned, and are the center of the plane
self.spotLight.position.z = 0;
self.spotLight.castShadow = true;
This is how the plane is made:
//The plane.
self.plane = new THREE.Mesh(new THREE.PlaneGeometry(self.groundSize, self.groundSize), new THREE.MeshLambertMaterial({color: 0x5C8A00}));
self.plane.receiveShadow = true;
self.plane.position.x = 0;
self.plane.position.y = -26;
self.plane.position.z = 0;
Also, here's another picture, this time, I've added a lot of PointLights:
You can see how the shadow still disappears!
Now, what am I doing wrong here? AFAIK, light should disperse equally in all directions! And also, there is another problem, I seem to be unable to add multiple SpotLights on the scene! Everything slows down completely if I do so - is this intended? Maybe it's because I enabled shadows on all of them...
#Neil, the same thing happens in your code as well!
I have created a jsfiddle showing a plane with Lambert material and a rotating cube that is casting a shadow, maybe you can see what is different to yours.
edit
Try playing about with some of the params, I can stop the clipping on my demo with:
spotLight.shadowCameraFov = 70;
update demo and moving demo