I'm playing with a very basic a-frame scene.
I'm looking for info to get camera position at runtime.
Should I use a Component and three.js code?
How could I do it?
First, grab the camera entity (https://aframe.io/docs/core/entity.html#Retrieving-an-Entity). The camera entity will have the camera component attached as an HTML attribute.
document.querySelector('[camera]') or document.querySelector('a-scene').camera.el
Then use getAttribute to grab the position. This will return an {X, Y, Z} object.
document.querySelector('[camera]').getAttribute('position')
To be notified of every time the camera updates its position, we can use the componentchanged event (https://aframe.io/docs/core/entity.html#Listening-for-Component-Changes):
document.querySelector('[camera]').addEventListener('componentchanged', function (evt) {
if (evt.detail.name === 'position') {
console.log('Camera position went from', evt.detail.oldData, 'to', evt.detail.newData);
}
});
I have finally adopted this solution:
<script>
AFRAME.registerComponent('acceleration', {
tick: function() {
var altitude = (this.el.getAttribute('position').z);
}
})
</script>
<a-scene>
<a-entity position="0 0 150">
<a-entity id="myCamera" camera acceleration look-controls keyboard-controls></a-entity>
</a-entity>
</a-scene>
My last problem is I don't get absolute coordinates of camera, but thoses relative to the initiale camera position.
Related
I have to rotate the camera during initial loading of object in three js.
So can anyone help me in which way i have to do that.Can i use Perspective Camera for this ?
for reference
https://theyearofgreta.com/
It is possible to tween the camera movement on the initial load of the object.
new TWEEN.Tween(currentPosition)
.to(targetPosition, 2000)
.onUpdate(function () {
camera.position.set(...currentPosition);
camera.lookAt(new THREE.Vector3(0, 0, 0));
});
I made a simple example to showcase the movement:
https://codepen.io/cdeep/pen/ZEygVNy
Basics of using tween for three.js animations:
http://learningthreejs.com/blog/2011/08/17/tweenjs-for-smooth-animation/
How do I turn off frustum culling on a gltf model in A-Frame? I know in Three.js you can just traverse the object and add node.frustumCulled = false. I've tried
AFRAME.registerComponent('disable-culling', {
init: function(){
var object3D = this.el.sceneEl.object3D;
object3D.traverse((node) => {
node.frustumCulled = false
})
}
})
but that doesn't work. Does anyone have any idea? The entity is
<a-entity
id="ball"
scale="0.3 0.3 0.3"
position="0 0 -7"
gltf-model="#ballModel"
disable-culling
animation-mixer="clip: *; loop: once; clampWhenFinished: true;"
shadow>
</a-entity>
I had a similar problem which was solved with frustum culling -
el.addEventListener('model-loaded', () => {
const model = el.getObject3D('mesh');
model.traverse((node) => {
if (node.isMesh) {
node.frustumCulled = false;
}
});
});
I wonder if your solution didn't work simply because the model hadn't finished loading.
Go back with your 3D model to Blender, select your model on object mode and then press "ctrl A" - apply all transformations.
I just had this problem where animated models were getting culled before fully exiting the scene. In my case, the cause seemed to be that the object scale was too small. Once I scaled up the object up in Blender and re-exported the gltf file, the models were culled correctly.
I've been trying to develop a VR experience using aframe on google cardboard. The player in this game will get point deduction and knock-back when collide with vehicle (car1). Initially I tried to apply static-body and dynamic-body and define the script when collide occurs. However, it's not working as intended.
I'm out of ideas and really don't understand why I cant get the knock-back.
Need some help from A-Frame experts and developers
Thanks in advance!
<a-scene stats physics="debug:true;
<a-entity id='player' camera="active: true" look-controls wasd-controls
data-aframe-default-camera static-body>
<a-text id="score" value="Score" position="-0.2 -0.5 -1" color="black" width="5" anchor="left"></a-text>
</a-entity>
<a-entity id='car1' obj-model="obj:#car_obj;mtl:#car_mtl" dynamic-body></a-entity>
</a-scene>
<script>
let score = 0;
let hit = false
const knockback= () => {
clearTimeout(resetId)
$("#player").body.position.set(0, 0.6,-4)
$("#player").body.velocity.set(0, 5,0)
$("#player").body.angularVelocity.set(0, 0,0)
hit = false
}
on($("#player"), 'collide', (e) => {
const car1 =$("#car1")
if (e.detail.body.id == car1.body.id){
hit = true
score = score + 1
$("#score").setAttribute('text','value','Score '+score)
}
})
</script>
following a partly sucessful answer to this question AFRAME position far away from camera
I'm trying to use a sphere around the camera to get a position around 100 from the camera.
I've added this sphere
<Entity
id='mouse-listener'
geometry='primitive: sphere;
radius: 100;
segmentsWidth: 64;
segmentsHeight: 64;'
position='0 0 0'
scale="-1 1 1"
material={{color: 'blue' }}
className='clickable'
events={{click: (e) => console.log(e)}}
/>
And my camera is as such
<Entity primitive='a-camera' id='camera' look-controls={`enabled:${isLookControlsEnabled}`} mouse-cursor mouse-zoom wasd-controls={wasdControls}>
I've tried adding the example listener component to the sphere entity
import AFRAME from 'aframe'
AFRAME.registerComponent('cursor-listener', {
init: function () {
this.el.addEventListener('click', function (evt) {
console.log('I was clicked at: ', evt.detail.intersection.point)
})
},
})
I just want to know the point on which it was clicked.
A-Frame comes with a mouse cursor. You add it as a separate entity:
<a-entity cursor="rayOrigin: mouse"></a-entity>
The events are mouseenter, mouseleave, click, mousedown, mouseup. Not onmouseup.
i've been tinkering around with three.js and i have a canvas i'd like to use as kind of a GUI. for that i have to check if an object is in the camera frustum.
my current code:
camera.updateMatrix();
camera.updateMatrixWorld();
var frustum = new THREE.Frustum();
var projScreenMatrix = new THREE.Matrix4();
projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
frustum.setFromProjectionMatrix( camera.projectionMatrix );
if(frustum.containsPoint( mesh.position )){
//stuff happens...
};
frustum.containsPoint()keeps returning false. what am i doing wrong here?
Your code is using
frustum.setFromMatrix( camera.projectionMatrix );
But that isn't the matrix you want. Instead use:
frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ) );
as answered in How to determine if plane is in Three.js camera Frustum
Three.js is doing view frustum Culling internally and only rendering when in camera frustum. Assuming that your Boundig Volumes are calculated correct, you can track weather a renderable Object3D is inside the camera view frustum when Object3D.onBeforeRender callback is called in your current frame