diff --git a/index.html b/index.html
index 31831da..f67e3be 100644
--- a/index.html
+++ b/index.html
@@ -38,7 +38,7 @@
src="https://cdn.glitch.com/e8742440-f85d-495a-8f52-6f066f464880%2FAMB_Suburbs_Afternoon_Woods_Spring_Small_ST_MKH8050-30shortened_amplified.mp3?v=1599596031022"
crossorigin="anonymous">
+ set-model-from-state snap="offset: 0.125; snap: 0.25">
+
+
-
-
{
// don't spawn if class specified in objects property but it is not matched intersected element
@@ -22,8 +24,8 @@ AFRAME.registerComponent('intersection-spawn', {
// Create element.
const spawnEl = document.createElement('a-entity');
- // Snap intersection point to grid and offset from center.
- spawnEl.setAttribute('position', evt.detail.intersection.point);
+ // // Snap intersection point to grid and offset from center.
+ // spawnEl.setAttribute('position', evt.detail.intersection.point);
// Set components and properties.
Object.keys(data).forEach(name => {
@@ -31,8 +33,18 @@ AFRAME.registerComponent('intersection-spawn', {
AFRAME.utils.entity.setComponentProperty(spawnEl, name, data[name]); // is setAttribute a new version of "set component property"?
});
- // Append to scene.
- el.sceneEl.appendChild(spawnEl); // check for another entity in identical position before spawning; change its color instead
+ const _worldToLocal = (originalPosition, targetEl) => {
+ // snap the intersection location to the gridlines
+ const helperVector = this.helperVector;
+ helperVector.copy(originalPosition);
+ targetEl.object3D.worldToLocal(helperVector);
+ return helperVector;
+ };
+
+ const localPos = _worldToLocal(evt.detail.intersection.point, this.targetEl); // convert world intersection position to local position
+ spawnEl.setAttribute('position', localPos)
+ this.targetEl.appendChild(spawnEl);
+
});
}
});
\ No newline at end of file
diff --git a/src/app/snap.js b/src/app/snap.js
index 3650a8f..b9fa272 100644
--- a/src/app/snap.js
+++ b/src/app/snap.js
@@ -1,33 +1,84 @@
/**
* Snap entity to the closest interval specified by `snap`.
* Offset entity by `offset`.
+ * If localId provided, then use the entity returned as the local reference space
*/
AFRAME.registerComponent('snap', {
dependencies: ['position'],
schema: {
- offset: {type: 'vec3'},
- snap: {type: 'vec3'}
+ offset: {type: 'number'},
+ snap: {type: 'number'},
+ localId: {type: 'selector'}
},
init: function () {
var self = this;
+ this.helperVector = new THREE.Vector3();
this.originalPos = this.el.getAttribute('position');
this.el.addEventListener('componentchanged', function (evt) {
if (evt.detail.name === 'position') {
self.update()
};
});
+ this.localEl = null;
+ if (!!this.data.anchorId) {
+ this.localEl = document.querySelector(this.data.localId)
+ }
},
update: function () {
+ // this element should be a child of the parent anchor container
+ // then use snapper as usual
const data = this.data;
- const pos = AFRAME.utils.clone(this.originalPos);
- pos.x = Math.floor(pos.x / data.snap.x) * data.snap.x + data.offset.x;
- pos.y = Math.floor(pos.y / data.snap.y) * data.snap.y + data.offset.y;
- pos.z = Math.floor(pos.z / data.snap.z) * data.snap.z + data.offset.z;
+ // const pos = AFRAME.utils.clone(this.originalPos);
+ // pos.x = Math.floor(pos.x / data.snap) * data.snap + data.offset.x;
+ // pos.y = Math.floor(pos.y / data.snap) * data.snap + data.offset.y;
+ // pos.z = Math.floor(pos.z / data.snap) * data.snap + data.offset.z;
+
+ // this.el.setAttribute('position', pos);
+
+ const _snapper = (originalPosition, offset, snap) => {
+ // snap the intersection location to the gridlines
+ const helperVector = this.helperVector;
+ helperVector.copy(originalPosition);
+
+ helperVector.x = Math.floor(helperVector.x / snap) * snap + offset;
+ helperVector.y = Math.floor(helperVector.y / snap) * snap + offset;
+ helperVector.z = Math.floor(helperVector.z / snap) * snap + offset;
+ return helperVector;
+ };
+
+ const _worldToLocal = (originalPosition) => {
+ // snap the intersection location to the gridlines
+ const helperVector = this.helperVector;
+ helperVector.copy(originalPosition);
+ this.el.object3D.worldToLocal(helperVector);
+ return helperVector;
+ };
+
+ const _convertLocalToWorld = (localPosition) => {
+ // Use Three.js's localToWorld method to convert the position
+ const worldPosition = new THREE.Vector3();
+ worldPosition.copy(localPosition);
+ this.el.object3D.localToWorld(worldPosition);
+
+ return worldPosition;
+ }
+
+ let snapPos;
+ if (this.localEl && this.localEl.object3D) {
+ // this.el.object3D.quaternion.copy(this.anchorEl.object3D.quaternion); copy from
+ const localPos = _worldToLocal(this.localEl.object3D.position); // convert world object from which to localize (anchor) to local position of this object
+ const localSnapPos = _snapper(localPos, this.data.offset, this.data.snap); // use snapping logic which assumes local intersection
+ snapPos = _convertLocalToWorld(localSnapPos); // world snap position
+ } else {
+ snapPos = _snapper(this.el.object3D.position, this.data.offset, this.data.snap);
+ }
+
+ this.el.object3D.position.copy(snapPos);
+
- this.el.setAttribute('position', pos);
}
});
\ No newline at end of file