Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix look-at component for vec3 targets and cameras #261

Merged
merged 1 commit into from
May 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion components/look-at/examples/basic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,28 @@
<meta property="og:image" content="https://raw.githubusercontent.com/supermedium/superframe/master/components/look-at/examples/basic/preview.gif"></meta>
<script src="https://aframe.io/releases/0.9.0/aframe.min.js"></script>
<script src="../../dist/aframe-look-at-component.min.js"></script>
<script>
/**
* Use the spacebar to swap the camera to one that is looking at the target.
*
* Probably shouldn't do it in VR.
*/
AFRAME.registerComponent('toggleable-camera', {
init: function () {
document.addEventListener('keydown', AFRAME.utils.bind(this.toggleCamera, this));
},
toggleCamera: function (e) {
if (e.code === 'Space') {
if (this.el.hasAttribute('camera')) {
this.el.removeAttribute('camera');
this.el.sceneEl.querySelector('#look-cam').setAttribute('camera', 'active', true);
} else {
this.el.setAttribute('camera', { active: true });
}
}
}
})
</script>
</head>
<body>
<a-scene>
Expand All @@ -29,13 +51,18 @@
<a-cylinder radius="0.2" height="2" color="#7BC8A4" look-at="#target"
position="-4 0 1"></a-cylinder>
<a-box width="2" depth="1" height="0.25" color="#93648D" look-at="#target"
position="0 0 1"></a-box>
position="0 0 1" toggleable-camera></a-box>
<a-box width="1" depth="2" height="0.5" color="#999" look-at="#target"
position="4 0 1"></a-box>

<!-- This entity looks at the camera. Use WASD controls to test it -->
<a-box width="2" depth="2" height="2" color="#FFC65D" look-at="#look-cam"
position="-6 2.5 -2"></a-box>

<!-- This entity looks at the origin. Cone rotated to point in its lookAt direction. -->
<a-entity position="-4 4 -8" look-at="0 0 0">
<a-cone height="1" color="#C388A3" radius-bottom="0.5" radius-top="0" rotation="90 0 0"></a-cone>
</a-entity>
</a-entity>

<a-sky color="#ECECEC"></a-sky>
Expand Down
51 changes: 34 additions & 17 deletions components/look-at/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ delete AFRAME.components['look-at'];
*/
AFRAME.registerComponent('look-at', {
schema: {
default: '',
default: '0 0 0',

parse: function (value) {
// A static position to look at.
Expand All @@ -39,6 +39,9 @@ AFRAME.registerComponent('look-at', {
init: function () {
this.target3D = null;
this.vector = new THREE.Vector3();
this.cameraListener = AFRAME.utils.bind(this.cameraListener, this);
this.el.addEventListener('componentinitialized', this.cameraListener);
this.el.addEventListener('componentremoved', this.cameraListener);
},

/**
Expand All @@ -48,7 +51,6 @@ AFRAME.registerComponent('look-at', {
update: function () {
var self = this;
var target = self.data;
var object3D = self.el.object3D;
var targetEl;

// No longer looking at anything (i.e., look-at="").
Expand All @@ -58,7 +60,7 @@ AFRAME.registerComponent('look-at', {

// Look at a position.
if (typeof target === 'object') {
return object3D.lookAt(new THREE.Vector3(target.x, target.y, target.z));
return this.lookAt(new THREE.Vector3(target.x, target.y, target.z));
}

// Assume target is a string.
Expand All @@ -83,27 +85,42 @@ AFRAME.registerComponent('look-at', {
return function (t) {
// Track target object position. Depends on parent object keeping global transforms up
// to state with updateMatrixWorld(). In practice, this is handled by the renderer.
var target;
var target3D = this.target3D;
var object3D = this.el.object3D;
var vector = this.vector;

if (target3D) {
target3D.getWorldPosition(vec3);
if (this.el.getObject3D('camera')) {
// Flip the vector to -z, looking away from target for camera entities. When using
// lookat from THREE camera objects, this is applied for you, but since the camera is
// nested into a Object3D, we need to apply this manually.
// vector.subVectors(object3D.position, vec3).add(object3D.position);
} else {
vector = vec3;
}
object3D.lookAt(vector);
this.lookAt(vec3);
}
};
}
})(),

remove: function () {
this.el.removeEventListener('componentinitialized', this.cameraListener);
this.el.removeEventListener('componentremoved', this.cameraListener);
},

beginTracking: function (targetEl) {
this.target3D = targetEl.object3D;
},

cameraListener: function (e) {
if (e.detail && e.detail.name === 'camera') {
this.update();
}
},

lookAt: function (position) {
var vector = this.vector;
var object3D = this.el.object3D;

if (this.el.getObject3D('camera')) {
// Flip the vector to -z, looking away from target for camera entities. When using
// lookat from THREE camera objects, this is applied for you, but since the camera is
// nested into a Object3D, we need to apply this manually.
vector.subVectors(object3D.position, position).add(object3D.position);
} else {
vector.copy(position);
}

object3D.lookAt(vector);
}
});