Get image rotation and rotate the resulting object accordingly.

This commit is contained in:
johnshaughnessy 2018-09-04 15:07:19 -07:00
Родитель 55c991ee40
Коммит 5006510a48
6 изменённых файлов: 96 добавлений и 6 удалений

Двоичные данные
doc/image_orientations.gif Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 19 KiB

Просмотреть файл

@ -13,6 +13,9 @@ AFRAME.registerComponent("offset-relative-to", {
on: {
type: "string"
},
orientation: {
default: 1 // see doc/image_orientations.gif
},
selfDestruct: {
default: false
}
@ -27,6 +30,9 @@ AFRAME.registerComponent("offset-relative-to", {
},
updateOffset: (function() {
const y = new THREE.Vector3(0, 1, 0);
const z = new THREE.Vector3(0, 0, -1);
const QUARTER_CIRCLE = Math.PI / 2;
const offsetVector = new THREE.Vector3();
return function() {
const obj = this.el.object3D;
@ -40,6 +46,38 @@ AFRAME.registerComponent("offset-relative-to", {
this.el.body && this.el.body.position.copy(obj.position);
target.getWorldQuaternion(obj.quaternion);
this.el.body && this.el.body.quaternion.copy(obj.quaternion);
// See doc/image_orientations.gif
switch (this.data.orientation) {
case 8:
obj.rotateOnAxis(z, 3 * QUARTER_CIRCLE);
break;
case 7:
obj.rotateOnAxis(z, 3 * QUARTER_CIRCLE);
obj.rotateOnAxis(y, 2 * QUARTER_CIRCLE);
break;
case 6:
obj.rotateOnAxis(z, QUARTER_CIRCLE);
break;
case 5:
obj.rotateOnAxis(z, QUARTER_CIRCLE);
obj.rotateOnAxis(y, 2 * QUARTER_CIRCLE);
break;
case 4:
obj.rotateOnAxis(z, 2 * QUARTER_CIRCLE);
obj.rotateOnAxis(y, 2 * QUARTER_CIRCLE);
break;
case 3:
obj.rotateOnAxis(z, 2 * QUARTER_CIRCLE);
break;
case 2:
obj.rotateOnAxis(y, 2 * QUARTER_CIRCLE);
break;
case 1:
default:
break;
}
if (this.data.selfDestruct) {
if (this.data.on) {
this.el.sceneEl.removeEventListener(this.data.on, this.updateOffset);

Просмотреть файл

@ -84,7 +84,7 @@ AFRAME.registerComponent("super-spawner", {
const thisGrabId = nextGrabId++;
this.heldEntities.set(hand, thisGrabId);
const entity = addMedia(this.data.src, ObjectContentOrigins.SPAWNER);
const entity = addMedia(this.data.src, ObjectContentOrigins.SPAWNER).entity;
entity.object3D.position.copy(
this.data.useCustomSpawnPosition ? this.data.spawnPosition : this.el.object3D.position
);

Просмотреть файл

@ -306,11 +306,14 @@ const onReady = async () => {
const offset = { x: 0, y: 0, z: -1.5 };
const spawnMediaInfrontOfPlayer = (src, contentOrigin) => {
const entity = addMedia(src, contentOrigin, true);
const { entity, orientation } = addMedia(src, contentOrigin, true);
entity.setAttribute("offset-relative-to", {
target: "#player-camera",
offset
orientation.then(or => {
entity.setAttribute("offset-relative-to", {
target: "#player-camera",
offset,
orientation: or
});
});
};

1
src/react-components/2d-hud.js поставляемый
Просмотреть файл

@ -75,6 +75,7 @@ const BottomHUD = ({ onCreateObject, showImageOnlyButton, onMediaPicked }) => (
BottomHUD.propTypes = {
onCreateObject: PropTypes.func,
showImageOnlyButton: PropTypes.bool,
onMediaPicked: PropTypes.func
};

Просмотреть файл

@ -51,6 +51,45 @@ export const upload = file => {
}).then(r => r.json());
};
// https://stackoverflow.com/questions/7584794/accessing-jpeg-exif-rotation-data-in-javascript-on-the-client-side/32490603#32490603
function getOrientation(file, callback) {
const reader = new FileReader();
reader.onload = function(e) {
const view = new DataView(e.target.result);
if (view.getUint16(0, false) != 0xffd8) {
return callback(-2);
}
const length = view.byteLength;
let offset = 2;
while (offset < length) {
if (view.getUint16(offset + 2, false) <= 8) return callback(-1);
const marker = view.getUint16(offset, false);
offset += 2;
if (marker == 0xffe1) {
if (view.getUint32((offset += 2), false) != 0x45786966) {
return callback(-1);
}
const little = view.getUint16((offset += 6), false) == 0x4949;
offset += view.getUint32(offset + 4, little);
const tags = view.getUint16(offset, little);
offset += 2;
for (let i = 0; i < tags; i++) {
if (view.getUint16(offset + i * 12, little) == 0x0112) {
return callback(view.getUint16(offset + i * 12 + 8, little));
}
}
} else if ((marker & 0xff00) != 0xff00) {
break;
} else {
offset += view.getUint16(offset, false);
}
}
return callback(-1);
};
reader.readAsArrayBuffer(file);
}
let interactableId = 0;
export const addMedia = (src, contentOrigin, resize = false) => {
const scene = AFRAME.scenes[0];
@ -61,6 +100,15 @@ export const addMedia = (src, contentOrigin, resize = false) => {
entity.setAttribute("media-loader", { resize, src: typeof src === "string" ? src : "" });
scene.appendChild(entity);
const orientation = new Promise(function(resolve) {
if (src instanceof File) {
getOrientation(src, x => {
resolve(x);
});
} else {
resolve(1);
}
});
if (src instanceof File) {
upload(src)
.then(response => {
@ -78,5 +126,5 @@ export const addMedia = (src, contentOrigin, resize = false) => {
scene.emit("object_spawned", { objectType });
});
return entity;
return { entity, orientation };
};