I would use the canvas to plot the 3d positions of each photo.
I created a fiddle here with text:
https://jsfiddle.net/2qu6m4h3/
And one with random shapes:
https://jsfiddle.net/d2th9ekb/
It creates a canvas element to draw text to. It interrogates the canvas for pixel positions. Those positions are then sent to a function which places cubes in 3d. Rather than place cubes you could place sprite objects which display each one of your photos. Use the scale property to give yourself more room between positions.
Here's the code:
/*
Start Setup text canvas and tools
*/
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.canvas.width = 400;
ctx.canvas.height = 200;
function createTextSourceCanvas(text,src) {
src.font = '50pt Times';
src.fillStyle = '#00ff00';
src.fillRect(0, 0, canvas.width, canvas.height);
src.fillStyle = '#FFFFFF';
src.textAlign = "center";
src.textBaseline = "middle";
src.fillText(text, canvas.width /2, canvas.height /2);
}
function examineText(src, fi){
var positiveResults = [];
var width = src.canvas.width;
var height = src.canvas.height;
var imgData = src.getImageData(0, 0,width, height);
for(var x = 0; x < width; x+=fi){
for(var y = 0; y < height; y+=fi ){
var pixel = getPixelXY(imgData, x, y)
if(pixel[0] == 0 && pixel[1] == 255 && pixel[2] == 0){
continue;
}
positiveResults.push([x,y]);
}
}
return positiveResults;
}
function getPixel(imgData, index) {
var i = index*4, d = imgData.data;
return [d[i],d[i+1],d[i+2],d[i+3]]
}
function getPixelXY(imgData, x, y) {
return getPixel(imgData, y*imgData.width+x);
}
/*
End Setup text canvas and tools
*/
/*
Start Setup Threejs canvas and tools
*/
var scene;
var renderer;
var camera;
var cube;
var controls;
function init3d(){
renderer = new THREE.WebGLRenderer( {antialias:true} );
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize (width, height);
document.body.appendChild (renderer.domElement);
scene = new THREE.Scene()
camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
camera.position.y = 160;
camera.position.z = 400;
camera.lookAt (new THREE.Vector3(0,0,0));
controls = new THREE.OrbitControls (camera, renderer.domElement);
var gridXZ = new THREE.GridHelper(100, 10);
scene.add(gridXZ);
var pointLight = new THREE.PointLight (0xffffff);
pointLight.position.set (0,300,200);
scene.add (pointLight);
window.addEventListener ('resize', onWindowResize, false);
}
function onWindowResize (){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize (window.innerWidth, window.innerHeight);
}
function animate(){
controls.update();
requestAnimationFrame ( animate );
renderer.render (scene, camera);
}
/*
End Setup Threejs canvas and tools
*/
/*
Start create 3d from text examination
*/
function create3dProjectionText(scene, positions, wExtent, hExtent, scale){
if(scale == undefined){
scale = 1;
}
var group = new THREE.Object3D();
var cubeGeometry = new THREE.BoxGeometry (2,2,2);
var cubeMaterial = new THREE.MeshLambertMaterial ({color: 0xFFFFFF});
for(var i in positions){
cube = new THREE.Mesh (cubeGeometry, cubeMaterial);
cube.position.set (positions[i][0]*scale - (wExtent*scale/2), positions[i][1]*scale -(hExtent*scale/2), 0);
group.add (cube);
}
group.rotateX( -Math.PI );
scene.add(group);
}
/*
End create 3d from text examination
*/
//initialize the 3d space
init3d();
//initialize the text canvas
createTextSourceCanvas("Hello World", ctx);
//
create3dProjectionText(scene, examineText(ctx ,4), ctx.canvas.width, ctx.canvas.height, 1.5);
animate();