2017-11-24 4 views
0

Ich arbeite an einer Three.js-Szene, die 5 Meshes lädt, jedes mit einem einzelnen Material, das eine einzelne Bildtextur enthält. Sobald diese Bilder Last, ich versuche, die folgenden Aufgaben zu erfüllen:Three.js - uvsNeedUpdate = True löst kein Update aus

  1. Last 20 Bilder mit höherer Auflösung
  2. Aktualisierung der Materialeigenschaft jeder Masche ein Array von 5 Materialien zu laden (jeweils mit 1 Bildtextur) in jedes Netz
  3. Aktualisieren Sie die FaceVertexUvs der Geometrie jedes Netzes, um auf die entsprechenden Offsets innerhalb der neuen Texturen zu zeigen.

Die documentation on Geometry hat wenig über Geometry.faceVertexUvs zu sagen, aber this SO post schlägt man den folgenden Ansatz verwenden, kann mit mehreren Materialien in einer Geometrie zu arbeiten, wenn faceVertexUvs mit:

geometry.faceVertexUvs[ materialIndex ][ faceIndex ][ vertexIndex ] 

Das Problem ist, dass nach Wenn ich die obigen Schritte durchlaufe, rufe ich meshes[meshIdx].geometry.uvsNeedUpdate = true; an, aber meine neuen Materialien erscheinen nicht und meine Netze bleiben unverändert. Hat jemand eine Idee, warum das sein könnte?

Ich wäre unendlich dankbar für Hinweise oder Einblicke, die andere zu dieser Frage bieten können!

Hier ist mein vollständiges Codebeispiel:

/** 
 
* Globals 
 
**/ 
 

 
// Create a store for all images contained in the visualization 
 
var imageList = null; 
 

 
// Create a store for the image atlas files. Each key will represent 
 
// the index position of the atlas file, and the value will point 
 
// to the material at that index position 
 
var materials = {32: {}, 64: {}}; 
 

 
// Create global configs for image and atlas sizing 
 
var image, atlas; 
 

 
// Create a store of meshes 
 
var meshes = []; 
 

 
/** 
 
* Create Scene 
 
**/ 
 

 
// Create the scene and a camera to view it 
 
var scene = new THREE.Scene(); 
 

 
/** 
 
* Camera 
 
**/ 
 

 
// Specify the portion of the scene visiable at any time (in degrees) 
 
var fieldOfView = 75; 
 

 
// Specify the camera's aspect ratio 
 
var aspectRatio = window.innerWidth/window.innerHeight; 
 

 
/* 
 
Specify the near and far clipping planes. Only objects 
 
between those planes will be rendered in the scene 
 
(these values help control the number of items rendered 
 
at any given time) 
 
*/ 
 
var nearPlane = 100; 
 
var farPlane = 50000; 
 

 
// Use the values specified above to create a camera 
 
var camera = new THREE.PerspectiveCamera(
 
    fieldOfView, aspectRatio, nearPlane, farPlane 
 
); 
 

 
// Finally, set the camera's position 
 
camera.position.z = 12000; 
 
camera.position.y = -2000; 
 

 
/** 
 
* Renderer 
 
**/ 
 

 
// Create the canvas with a renderer 
 
var renderer = new THREE.WebGLRenderer({ antialias: true }); 
 

 
// Add support for retina displays 
 
renderer.setPixelRatio(window.devicePixelRatio); 
 

 
// Specify the size of the canvas 
 
renderer.setSize(window.innerWidth, window.innerHeight); 
 

 
// Add the canvas to the DOM 
 
document.body.appendChild(renderer.domElement); 
 

 
/** 
 
* Load External Data 
 
**/ 
 

 
// Identify data endpoint 
 
var dataUrl = 'https://s3.amazonaws.com/duhaime/blog/tsne-webgl/data/'; 
 

 
// Create a store for image position information 
 
var imagePositions = null; 
 

 
// Load the image position JSON file 
 
var fileLoader = new THREE.FileLoader(); 
 
fileLoader.load(dataUrl + 'image_tsne_projections.json', function(data) { 
 
    imagePositions = JSON.parse(data); 
 
    conditionallyBuildGeometries(32) 
 
}) 
 

 
/** 
 
* Load Atlas Textures 
 
**/ 
 

 
// List of all textures to be loaded, the size of subimages 
 
// in each, and the total number of atlas files for each size 
 
var textureSets = { 
 
    32: { size: 32, count: 5 }, 
 
    64: { size: 64, count: 20 } 
 
} 
 

 
// Create a texture loader so we can load our image files 
 
var textureLoader = new THREE.TextureLoader(); 
 

 
function loadTextures(size) { 
 
    for (var i=0; i<textureSets[size].count; i++) { 
 
    var url = dataUrl + 'atlas_files/' + size + 'px/atlas-' + i + '.jpg'; 
 
    textureLoader.load(url, handleTexture.bind(null, size, i)); 
 
    } 
 
} 
 

 
// Callback function that adds the texture to the list of textures 
 
// and calls the geometry builder if all textures have loaded 
 
function handleTexture(size, idx, texture) { 
 
    var material = new THREE.MeshBasicMaterial({ map: texture }); 
 
    materials[size][idx] = material; 
 
    conditionallyBuildGeometries(size, idx) 
 
} 
 

 
// If the textures and the mapping from image idx to positional information 
 
// are all loaded, create the geometries 
 
function conditionallyBuildGeometries(size, idx) { 
 
    if (size === 32) { 
 
    var nLoaded = Object.keys(materials[size]).length; 
 
    var nRequired = textureSets[size].count; 
 
    if (nLoaded === nRequired && imagePositions) { 
 
     document.querySelector('#loading').style.display = 'none'; 
 
     buildGeometry(size); 
 
     loadTextures(64) 
 
    } 
 
    } else { 
 
    updateGeometry(size, idx) 
 
    } 
 
} 
 

 
loadTextures(32) 
 

 
/** 
 
* Build Image Geometry 
 
**/ 
 

 
// Iterate over the textures in the current texture set 
 
// and for each, add a new mesh to the scene 
 
function buildGeometry(size) { 
 
    setImageAndAtlasSize(size); 
 
    for (var i=0; i<textureSets[size].count; i++) { 
 
    // Create one new geometry per atlas 
 
    var geometry = new THREE.Geometry(); 
 
    for (var j=0; j<atlas.cols*atlas.rows; j++) { 
 
     geometry = updateVertices(geometry, i, j); 
 
     geometry = updateFaces(geometry); 
 
     geometry = updateFaceVertexUvs(geometry, j, 0); 
 
    } 
 
    buildMesh(geometry, materials[size][i]); 
 
    } 
 
} 
 

 
function setImageAndAtlasSize(size) { 
 
    // Identify the subimage size in px (width/height) and the 
 
    // size of the image as it will be displayed in the map 
 
    image = { width: size, height: size, shownWidth: 64, shownHeight: 64 }; 
 
    
 
    // Identify the total number of cols & rows in the image atlas 
 
    atlas = { width: 2048, height: 2048, cols: 2048/size, rows: 2048/size }; 
 
} 
 

 
// Get the x, y, z coords for the subimage at index position j 
 
// of atlas in index position i 
 
function getCoords(i, j) { 
 
    var idx = (i * atlas.rows * atlas.cols) + j; 
 
    var coords = imagePositions[idx]; 
 
    coords.x *= 2200; 
 
    coords.y *= 1200; 
 
    coords.z = (-200 + j/100); 
 
    return coords; 
 
} 
 

 
// Add one vertex for each corner of the image, using the 
 
// following order: lower left, lower right, upper right, upper left 
 
function updateVertices(geometry, i, j) { 
 
    // Retrieve the x, y, z coords for this subimage 
 
    var coords = getCoords(i, j); 
 
    geometry.vertices.push(
 
    new THREE.Vector3(
 
     coords.x, 
 
     coords.y, 
 
     coords.z 
 
    ), 
 
    new THREE.Vector3(
 
     coords.x + image.shownWidth, 
 
     coords.y, 
 
     coords.z 
 
    ), 
 
    new THREE.Vector3(
 
     coords.x + image.shownWidth, 
 
     coords.y + image.shownHeight, 
 
     coords.z 
 
    ), 
 
    new THREE.Vector3(
 
     coords.x, 
 
     coords.y + image.shownHeight, 
 
     coords.z 
 
    ) 
 
); 
 
    return geometry; 
 
} 
 

 
// Create two new faces for a given subimage, then add those 
 
// faces to the geometry 
 
function updateFaces(geometry) { 
 
    // Add the first face (the lower-right triangle) 
 
    var faceOne = new THREE.Face3(
 
    geometry.vertices.length-4, 
 
    geometry.vertices.length-3, 
 
    geometry.vertices.length-2 
 
) 
 
    // Add the second face (the upper-left triangle) 
 
    var faceTwo = new THREE.Face3(
 
    geometry.vertices.length-4, 
 
    geometry.vertices.length-2, 
 
    geometry.vertices.length-1 
 
) 
 
    // Add those faces to the geometry 
 
    geometry.faces.push(faceOne, faceTwo); 
 
    return geometry; 
 
} 
 

 
function updateFaceVertexUvs(geometry, j, materialIdx) { 
 
    // Identify the relative width and height of the subimages 
 
    // within the image atlas 
 
    var relativeW = image.width/atlas.width; 
 
    var relativeH = image.height/atlas.height; 
 

 
    // Identify this subimage's offset in the x dimension 
 
    // An xOffset of 0 means the subimage starts flush with 
 
    // the left-hand edge of the atlas 
 
    var xOffset = (j % atlas.cols) * relativeW; 
 
    
 
    // Identify this subimage's offset in the y dimension 
 
    // A yOffset of 0 means the subimage starts flush with 
 
    // the bottom edge of the atlas 
 
    var yOffset = 1 - (Math.floor(j/atlas.cols) * relativeH) - relativeH; 
 
    
 
    // Create an empty list of faceVertexUvs for the given material Idx 
 
    // if it doesn't exist yet 
 
    if (!geometry.faceVertexUvs[materialIdx]) { 
 
    geometry.faceVertexUvs[materialIdx] = []; 
 
    } 
 

 
    // Use the xOffset and yOffset (and the knowledge that 
 
    // each row and column contains only 32 images) to specify 
 
    // the regions of the current image 
 
    geometry.faceVertexUvs[materialIdx][j*2] = [ 
 
    new THREE.Vector2(xOffset, yOffset), 
 
    new THREE.Vector2(xOffset + relativeW, yOffset), 
 
    new THREE.Vector2(xOffset + relativeW, yOffset + relativeH) 
 
    ]; 
 

 
    // Map the region of the image described by the lower-left, 
 
    // upper-right, and upper-left vertices to `faceTwo` 
 
    geometry.faceVertexUvs[materialIdx][(j*2) + 1] = [ 
 
    new THREE.Vector2(xOffset, yOffset), 
 
    new THREE.Vector2(xOffset + relativeW, yOffset + relativeH), 
 
    new THREE.Vector2(xOffset, yOffset + relativeH) 
 
    ]; 
 

 
    return geometry; 
 
} 
 

 
function buildMesh(geometry, material) { 
 
    // Convert the geometry to a BuferGeometry for additional performance 
 
    //var geometry = new THREE.BufferGeometry().fromGeometry(geometry); 
 
    // Combine the image geometry and material into a mesh 
 
    var mesh = new THREE.Mesh(geometry, [material]); 
 
    // Set the position of the image mesh in the x,y,z dimensions 
 
    mesh.position.set(0,0,0) 
 
    // Add the image to the scene 
 
    scene.add(mesh); 
 
    // Save this mesh 
 
    meshes.push(mesh); 
 
} 
 

 
/** 
 
* Update Geometries with new VertexUvs and materials 
 
**/ 
 

 
function updateGeometry(size, idx) { 
 

 
    // Update the image and atlas sizes 
 
    setImageAndAtlasSize(size) 
 

 
    // Determine how many of the higher resolution atlas files 
 
    // it takes to account for all subimages in a lower resolution 
 
    // atlas file 
 
    var lowResPerAtlas = (2048/32)**2; 
 
    var highResPerAtlas = (2048/64)**2; 
 
    var atlasRatio = lowResPerAtlas/highResPerAtlas; 
 

 
    // Determine which of the original meshes the newly-loaded high-res 
 
    // atlas corresponds to 
 
    var meshIdx = Math.floor(idx/atlasRatio); 
 
    
 
    // Determine the material index position to use in this mesh. 
 
    // The mesh's materials array will look like this: 
 
    // mesh.material = [32px, 64px_0, 64px_1, 64px_2, 64px_3, 64_px_4]; 
 
    var materialIdx = (idx % atlasRatio) + 1; 
 

 
    // Add the newly loaded material into the appropriate mesh 
 
    meshes[meshIdx].material[materialIdx] = materials[size][idx]; 
 

 
    //console.log(meshIdx, materialIdx, idx, meshes[materialIdx].material) 
 

 
    // Pluck out the geometry of this mesh update: 
 
    var geometry = meshes[meshIdx].geometry; 
 

 
    for (var j=0; j<highResPerAtlas; j++) { 
 
    geometry = updateFaceVertexUvs(geometry, j, materialIdx); 
 
    } 
 
    
 
    geometry.faceVertexUvs[0] = []; 
 

 
    meshes[meshIdx].geometry = geometry; 
 
    meshes[meshIdx].geometry.colorsNeedUpdate = true; 
 
    meshes[meshIdx].geometry.groupsNeedUpdate = true; 
 
    meshes[meshIdx].geometry.lineDistancesNeedUpdate = true; 
 
    meshes[meshIdx].geometry.normalsNeedUpdate = true; 
 
    meshes[meshIdx].geometry.uvsNeedUpdate = true; 
 
    meshes[meshIdx].geometry.verticesNeedUpdate = true; 
 

 
    // Indicate the material needs update 
 
    meshes[meshIdx].material.needsUpdate = true; 
 
} 
 

 
/** 
 
* Lights 
 
**/ 
 

 
// Add a point light with #fff color, .7 intensity, and 0 distance 
 
var light = new THREE.PointLight(0xffffff, 1, 0); 
 

 
// Specify the light's position 
 
light.position.set(1, 1, 100); 
 

 
// Add the light to the scene 
 
scene.add(light) 
 

 
/** 
 
* Add Controls 
 
**/ 
 

 
var controls = new THREE.TrackballControls(camera, renderer.domElement); 
 

 
/** 
 
* Handle window resizes 
 
**/ 
 

 
window.addEventListener('resize', function() { 
 
    camera.aspect = window.innerWidth/window.innerHeight; 
 
    camera.updateProjectionMatrix(); 
 
    renderer.setSize(window.innerWidth, window.innerHeight); 
 
    controls.handleResize(); 
 
}); 
 

 
/** 
 
* Render! 
 
**/ 
 

 
// The main animation function that re-renders the scene each animation frame 
 
function animate() { 
 
requestAnimationFrame(animate); 
 
    renderer.render(scene, camera); 
 
    controls.update(); 
 
} 
 
animate();
* { 
 
    margin: 0; 
 
    padding: 0; 
 
    background: #000; 
 
    color: #fff; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.js"></script> 
 
<script src="https://s3-us-west-2.amazonaws.com/yale-dh-staging/tsne/assets/vendor/js/trackball-controls.js"></script> 
 
<div id='loading'>Loading</div>

+0

bezogen werden: https://stackoverflow.com/questions/45660848/using-multiple-textures-with-geometry-facevertexuvs – duhaime

Antwort

0

Dies ist ein bekannter Fehler: https://github.com/mrdoob/three.js/issues/7179

Statt einen faceVertexUv von Index Accessoren zu verändern, muss man eine .set() Methode verwenden auf dem entsprechenden Vektor innerhalb der FaceVertexUv, zB:

if (geometry.faceVertexUvs[0][faceIdx]) { 
    geometry.faceVertexUvs[0][faceIdx][0].set(xOffset, yOffset) 
    geometry.faceVertexUvs[0][faceIdx][1].set(xOffset + width, yOffset) 
    geometry.faceVertexUvs[0][faceIdx][2].set(xOffset + width, yOffset + height) 
    } else { 
    geometry.faceVertexUvs[0][faceIdx] = [ 
     new THREE.Vector2(xOffset, yOffset), 
     new THREE.Vector2(xOffset + width, yOffset), 
     new THREE.Vector2(xOffset + width, yOffset + height) 
    ] 
    } 

Voll Beispiel:

/** 
 
* Globals 
 
**/ 
 

 
// Create a store for all images contained in the visualization 
 
var imageList = null; 
 

 
// Create a store for the image atlas files. Each key will represent 
 
// the index position of the atlas file, and the value will point 
 
// to the material at that index position 
 
var materials = {32: {}, 64: {}}; 
 

 
// Create global configs for image and atlas sizing 
 
var image, atlas; 
 

 
// Create a store of meshes 
 
var meshes = []; 
 

 
/** 
 
* Create Scene 
 
**/ 
 

 
// Create the scene and a camera to view it 
 
var scene = new THREE.Scene(); 
 

 
/** 
 
* Camera 
 
**/ 
 

 
// Specify the portion of the scene visiable at any time (in degrees) 
 
var fieldOfView = 75; 
 

 
// Specify the camera's aspect ratio 
 
var aspectRatio = window.innerWidth/window.innerHeight; 
 

 
/* 
 
Specify the near and far clipping planes. Only objects 
 
between those planes will be rendered in the scene 
 
(these values help control the number of items rendered 
 
at any given time) 
 
*/ 
 
var nearPlane = 100; 
 
var farPlane = 50000; 
 

 
// Use the values specified above to create a camera 
 
var camera = new THREE.PerspectiveCamera(
 
    fieldOfView, aspectRatio, nearPlane, farPlane 
 
); 
 

 
// Finally, set the camera's position 
 
camera.position.z = 12000; 
 
camera.position.y = -2000; 
 

 
/** 
 
* Lights 
 
**/ 
 

 
// Add a point light with #fff color, .7 intensity, and 0 distance 
 
var light = new THREE.PointLight(0xffffff, 1, 0); 
 

 
// Specify the light's position 
 
light.position.set(1, 1, 100); 
 

 
// Add the light to the scene 
 
scene.add(light) 
 

 
/** 
 
* Renderer 
 
**/ 
 

 
// Create the canvas with a renderer 
 
var renderer = new THREE.WebGLRenderer({ antialias: true }); 
 

 
// Add support for retina displays 
 
renderer.setPixelRatio(window.devicePixelRatio); 
 

 
// Specify the size of the canvas 
 
renderer.setSize(window.innerWidth, window.innerHeight); 
 

 
// Add the canvas to the DOM 
 
document.body.appendChild(renderer.domElement); 
 

 
/** 
 
* Load External Data 
 
**/ 
 

 
// Identify data endpoint 
 
var dataUrl = 'https://s3.amazonaws.com/duhaime/blog/tsne-webgl/data/'; 
 

 
// Create a store for image position information 
 
var imagePositions = null; 
 

 
// Load the image position JSON file 
 
var fileLoader = new THREE.FileLoader(); 
 
fileLoader.load(dataUrl + 'image_tsne_projections.json', function(data) { 
 
    imagePositions = JSON.parse(data); 
 
    conditionallyBuildGeometries(32) 
 
}) 
 

 
/** 
 
* Load Atlas Textures 
 
**/ 
 

 
// List of all textures to be loaded, the size of subimages 
 
// in each, and the total count of atlas files for each size 
 
var textureSets = { 
 
    32: { size: 32, count: 5 }, 
 
    64: { size: 64, count: 20 } 
 
} 
 

 
// Create a texture loader so we can load our image files 
 
var textureLoader = new THREE.TextureLoader(); 
 

 
function loadTextures(size) { 
 
    for (var i=0; i<textureSets[size].count; i++) { 
 
    var url = dataUrl + 'atlas_files/' + size + 'px/atlas-' + i + '.jpg'; 
 
    textureLoader.load(url, handleTexture.bind(null, size, i)); 
 
    } 
 
} 
 

 
// Create a material from the new texture and call 
 
// the geometry builder if all textures have loaded 
 
function handleTexture(size, idx, texture) { 
 
    var material = new THREE.MeshBasicMaterial({ map: texture }); 
 
    materials[size][idx] = material; 
 
    conditionallyBuildGeometries(size, idx) 
 
} 
 

 
// If the textures and the mapping from image idx to positional information 
 
// are all loaded, create the geometries 
 
function conditionallyBuildGeometries(size, idx) { 
 
    if (size === 32) { 
 
    var nLoaded = Object.keys(materials[size]).length; 
 
    var nRequired = textureSets[size].count; 
 
    if (nLoaded === nRequired && imagePositions) { 
 
     document.querySelector('#loading').style.display = 'none'; 
 
     buildGeometry(size); 
 
     loadTextures(64) 
 
    } 
 
    } else { 
 
    updateGeometry(size, idx) 
 
    } 
 
} 
 

 
loadTextures(32) 
 

 
/** 
 
* Build Image Geometry 
 
**/ 
 

 
// Iterate over the textures in the current texture set 
 
// and for each, add a new mesh to the scene 
 
function buildGeometry(size) { 
 
    setImageAndAtlasSize(size); 
 
    for (var i=0; i<textureSets[size].count; i++) { 
 
    // Create one new geometry per set of 1024 images 
 
    var geometry = new THREE.Geometry(); 
 
    geometry.faceVertexUvs[0] = []; 
 
    for (var j=0; j<atlas.cols*atlas.rows; j++) { 
 
     geometry = updateVertices(geometry, i, j); 
 
     geometry = updateFaces(geometry); 
 
     geometry = updateFaceVertexUvs(geometry, j); 
 
     if ((j+1)%1024 === 0) { 
 
     buildMesh(geometry, materials[size][i]); 
 
     var geometry = new THREE.Geometry(); 
 
     } 
 
    } 
 
    } 
 
} 
 

 
function setImageAndAtlasSize(size) { 
 
    // Identify the subimage size in px (width/height) and the 
 
    // size of the image as it will be displayed in the map 
 
    image = { width: size, height: size, shownWidth: 64, shownHeight: 64 }; 
 
    
 
    // Identify the total number of cols & rows in the image atlas 
 
    atlas = { width: 2048, height: 2048, cols: 2048/size, rows: 2048/size }; 
 
} 
 

 
// Get the x, y, z coords for the subimage at index position j 
 
// of atlas in index position i 
 
function getCoords(i, j) { 
 
    var idx = (i * atlas.rows * atlas.cols) + j; 
 
    var coords = imagePositions[idx]; 
 
    coords.x *= 2200; 
 
    coords.y *= 1200; 
 
    coords.z = (-200 + j/100); 
 
    return coords; 
 
} 
 

 
// Add one vertex for each corner of the image, using the 
 
// following order: lower left, lower right, upper right, upper left 
 
function updateVertices(geometry, i, j) { 
 
    // Retrieve the x, y, z coords for this subimage 
 
    var coords = getCoords(i, j); 
 
    geometry.vertices.push(
 
    new THREE.Vector3(
 
     coords.x, 
 
     coords.y, 
 
     coords.z 
 
    ), 
 
    new THREE.Vector3(
 
     coords.x + image.shownWidth, 
 
     coords.y, 
 
     coords.z 
 
    ), 
 
    new THREE.Vector3(
 
     coords.x + image.shownWidth, 
 
     coords.y + image.shownHeight, 
 
     coords.z 
 
    ), 
 
    new THREE.Vector3(
 
     coords.x, 
 
     coords.y + image.shownHeight, 
 
     coords.z 
 
    ) 
 
); 
 
    return geometry; 
 
} 
 

 
// Create two new faces for a given subimage, then add those 
 
// faces to the geometry 
 
function updateFaces(geometry) { 
 
    // Add the first face (the lower-right triangle) 
 
    var faceOne = new THREE.Face3(
 
    geometry.vertices.length-4, 
 
    geometry.vertices.length-3, 
 
    geometry.vertices.length-2 
 
) 
 
    // Add the second face (the upper-left triangle) 
 
    var faceTwo = new THREE.Face3(
 
    geometry.vertices.length-4, 
 
    geometry.vertices.length-2, 
 
    geometry.vertices.length-1 
 
) 
 
    // Add those faces to the geometry 
 
    geometry.faces.push(faceOne, faceTwo); 
 
    return geometry; 
 
} 
 

 
function updateFaceVertexUvs(geometry, j) { 
 
    // Identify the relative width and height of the subimages 
 
    // within the image atlas 
 
    var relativeW = image.width/atlas.width; 
 
    var relativeH = image.height/atlas.height; 
 

 
    // Identify this subimage's offset in the x dimension 
 
    // An xOffset of 0 means the subimage starts flush with 
 
    // the left-hand edge of the atlas 
 
    var xOffset = (j % atlas.cols) * relativeW; 
 
    
 
    // Identify this subimage's offset in the y dimension 
 
    // A yOffset of 0 means the subimage starts flush with 
 
    // the bottom edge of the atlas 
 
    var yOffset = 1 - (Math.floor(j/atlas.cols) * relativeH) - relativeH; 
 

 
    // Determine the faceVertexUvs index position 
 
    var faceIdx = 2 * (j%1024); 
 

 
    // Use the xOffset and yOffset (and the knowledge that 
 
    // each row and column contains only 32 images) to specify 
 
    // the regions of the current image. Use .set() if the given 
 
    // faceVertex is already defined, due to a bug in updateVertexUvs: 
 
    // https://github.com/mrdoob/three.js/issues/7179 
 
    if (geometry.faceVertexUvs[0][faceIdx]) { 
 
    geometry.faceVertexUvs[0][faceIdx][0].set(xOffset, yOffset) 
 
    geometry.faceVertexUvs[0][faceIdx][1].set(xOffset + relativeW, yOffset) 
 
    geometry.faceVertexUvs[0][faceIdx][2].set(xOffset + relativeW, yOffset + relativeH) 
 
    } else { 
 
    geometry.faceVertexUvs[0][faceIdx] = [ 
 
     new THREE.Vector2(xOffset, yOffset), 
 
     new THREE.Vector2(xOffset + relativeW, yOffset), 
 
     new THREE.Vector2(xOffset + relativeW, yOffset + relativeH) 
 
    ] 
 
    } 
 
    // Map the region of the image described by the lower-left, 
 
    // upper-right, and upper-left vertices to `faceTwo` 
 
    if (geometry.faceVertexUvs[0][faceIdx+1]) { 
 
    geometry.faceVertexUvs[0][faceIdx+1][0].set(xOffset, yOffset) 
 
    geometry.faceVertexUvs[0][faceIdx+1][1].set(xOffset + relativeW, yOffset + relativeH) 
 
    geometry.faceVertexUvs[0][faceIdx+1][2].set(xOffset, yOffset + relativeH) 
 
    } else { 
 
    geometry.faceVertexUvs[0][faceIdx+1] = [ 
 
     new THREE.Vector2(xOffset, yOffset), 
 
     new THREE.Vector2(xOffset + relativeW, yOffset + relativeH), 
 
     new THREE.Vector2(xOffset, yOffset + relativeH) 
 
    ] 
 
    } 
 
    return geometry; 
 
} 
 

 
function buildMesh(geometry, material) { 
 
    // Convert the geometry to a BuferGeometry for additional performance 
 
    //var geometry = new THREE.BufferGeometry().fromGeometry(geometry); 
 
    // Combine the image geometry and material into a mesh 
 
    var mesh = new THREE.Mesh(geometry, material); 
 
    // Set the position of the image mesh in the x,y,z dimensions 
 
    mesh.position.set(0,0,0) 
 
    // Add the image to the scene 
 
    scene.add(mesh); 
 
    // Save this mesh 
 
    meshes.push(mesh); 
 
    return mesh; 
 
} 
 

 
/** 
 
* Update Geometries with new VertexUvs and materials 
 
**/ 
 

 
function updateGeometry(size, idx) { 
 
    // Update the image and atlas sizes 
 
    setImageAndAtlasSize(size) 
 
    // Update the appropriate material 
 
    meshes[idx].material = materials[size][idx]; 
 
    meshes[idx].material.needsUpdate = true; 
 
    // Update the facevertexuvs 
 
    for (var j=0; j<atlas.cols*atlas.rows; j++) { 
 
    meshes[idx].geometry = updateFaceVertexUvs(meshes[idx].geometry, j); 
 
    } 
 
    meshes[idx].geometry.uvsNeedUpdate = true; 
 
    meshes[idx].geometry.verticesNeedUpdate = true; 
 
} 
 

 
/** 
 
* Add Controls 
 
**/ 
 

 
var controls = new THREE.TrackballControls(camera, renderer.domElement); 
 

 
/** 
 
* Handle window resizes 
 
**/ 
 

 
window.addEventListener('resize', function() { 
 
    camera.aspect = window.innerWidth/window.innerHeight; 
 
    camera.updateProjectionMatrix(); 
 
    renderer.setSize(window.innerWidth, window.innerHeight); 
 
    controls.handleResize(); 
 
}); 
 

 
/** 
 
* Render! 
 
**/ 
 

 
// The main animation function that re-renders the scene each animation frame 
 
function animate() { 
 
requestAnimationFrame(animate); 
 
    renderer.render(scene, camera); 
 
    controls.update(); 
 
} 
 
animate();
* { 
 
    margin: 0; 
 
    padding: 0; 
 
    background: #000; 
 
    color: #fff; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.js"></script> 
 
<script src="https://s3-us-west-2.amazonaws.com/yale-dh-staging/tsne/assets/vendor/js/trackball-controls.js"></script> 
 
<div id='loading'>Loading</div>

Verwandte Themen