Loading multiple textures from different url's fails - three.js

I am trying to render textures on planes loaded from different URL's. For some reason after 2nd or 3rd image I can see in browser that loading image is stuck and it is not being rendered.
Adding the code used:
function init() {
loadPicturesFromDirectUrl();
}
function loadPicturesFromDirectUrl(currentPictureIndex) {
if (currentPictureIndex === undefined) {
currentPictureIndex = 0;
}
var picture = data.pictures[currentPictureIndex];
var loader = new THREE.TextureLoader();
loader.load(picture.url, function (texture) {
renderPicture(picture, texture);
currentPictureIndex++;
if (currentPictureIndex > data.pictures.length - 1) {
return;
}
loadPicturesFromDirectUrl(currentPictureIndex);
}, null, function (e) {
console.log(e);
});
}
function renderPicture(picture, texture) {
var planeGeometry = new THREE.PlaneGeometry(picture.size.width, picture.size.height);
var planeMaterial = new THREE.MeshBasicMaterial({ map: texture });
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.position.x = picture.location.x;
planeMesh.position.y = picture.location.y;
planeMesh.rotateY(myzeum.toRadians(180));
scene.add(planeMesh);
}

You may want to try to preload all the pictures in one function and store them in an array and render them only after all of them have been loaded. Like so:
var all_textures = [];
function init() {
loadPicturesFromDirectUrl();
for int (i = 0; i < all_picture.length; i++) {
renderPicture(data.pictures[i], all_textures[i])
}
}
function loadPicturesFromDirectUrl(currentPictureIndex) {
if (currentPictureIndex === undefined) {
currentPictureIndex = 0;
}
var picture = data.pictures[currentPictureIndex];
var loader = new THREE.TextureLoader();
loader.load(picture.url, function (texture) {
all_textures[currentPictureIndex] = texture
currentPictureIndex++;
if (currentPictureIndex > data.pictures.length - 1) {
return;
}
loadPicturesFromDirectUrl(currentPictureIndex);
}, null, function (e) {
console.log(e);
});
}
function renderPicture(picture, texture) {
var planeGeometry = new THREE.PlaneGeometry(picture.size.width, picture.size.height);
var planeMaterial = new THREE.MeshBasicMaterial({ map: texture });
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.position.x = picture.location.x;
planeMesh.position.y = picture.location.y;
planeMesh.rotateY(myzeum.toRadians(180));
scene.add(planeMesh);
}

Related

How do I render a svg as a mesh in three js

Im trying to render a SVG file as a mesh using SVGLoader in my three js application, but its not working
I followed the documentation to the SVGLoader step by step but still nothing
here is the documentation : https://threejs.org/docs/index.html?q=svg#examples/en/loaders/SVGLoader
and here is my code that i've tried :
const loader = new SVGLoader();
const group = new Group();
loader.load(
"../public/assets/svg/logo.svg",
function (data) {
const paths = data.paths;
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const material = new MeshBasicMaterial({
color: path.color,
side: DoubleSide,
depthWrite: false,
});
const shapes = SVGLoader.createShapes(path);
for (let j = 0; j < shapes.length; j++) {
const shape = shapes[j];
const geometry = new ShapeGeometry(shape);
const mesh = new Mesh(geometry, material);
group.add(mesh);
}
}
},
function (xhr) {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
function (error) {
console.log("An error happened", error);
}
);
scene.add(group);
Im not getting any error messages when I run my code.

require.js and three.js: Uncaught ReferenceError: THREE is not defined

I'm trying to include a threejs visual in a documentation page generated via Julia's Documenter.jl package. Unfortunately, the way Documenter currently handles javascript components is via require.js and it appears to break three.js (or its modules) with the error
Uncaught ReferenceError: THREE is not defined
My self-contained example is like this
var container = document.getElementById("three_container");
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xeeeeee );
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 200;
camera.lookAt(scene.position);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
const frontSpot = new THREE.SpotLight(0xeeeece);
frontSpot.position.set(1000, 1000, 1000);
scene.add(frontSpot);
const frontSpot2 = new THREE.SpotLight(0xddddce);
frontSpot2.position.set(-500, -500, -500);
scene.add(frontSpot2);
scene.add(new THREE.AmbientLight(0xffffff, 1));
function createSphere(radius, segments) {
const material = new THREE.MeshStandardMaterial({
color: 0xfcc742,
emissive: 0x111111,
specular: 0xffffff,
metalness: 0.8,
roughness: 0.6,
});
return new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, segments),
material
);
}
// sphere params
var radius = 1,
segments = 36,
rotation = 6;
// spheres
var sphere1 = createSphere(radius, segments);
sphere1.position.x = 35.35533905932738;
sphere1.position.y = 35.35533905932737;
sphere1.position.z = 99.99999999999999;
sphere1.scale.set(10,10,20);
sphere1.rotation.z = 3.9269908169872414;
sphere1.rotation.x = 2.137707831735906;
sphere1.rotation.y = 0.0;
sphere1.rotation.order = 'ZXY';
scene.add(sphere1);
var sphere2 = createSphere(radius, segments);
sphere2.position.x = 3.061616997868383e-15;
sphere2.position.y = 50.0;
sphere2.position.z = 74.99999999999999;
sphere2.scale.set(10,10,20);
sphere2.rotation.z = 4.71238898038469;
sphere2.rotation.x = 2.137707831735906;
sphere2.rotation.y = 0.0;
sphere2.rotation.order = 'ZXY';
scene.add(sphere2);
var sphere3 = createSphere(radius, segments);
sphere3.position.x = -35.35533905932737;
sphere3.position.y = 35.35533905932738;
sphere3.position.z = 49.999999999999986;
sphere3.scale.set(10,10,20);
sphere3.rotation.z = -0.7853981633974483;
sphere3.rotation.x = 2.137707831735906;
sphere3.rotation.y = 0.0;
sphere3.rotation.order = 'ZXY';
scene.add(sphere3);
var sphere4 = createSphere(radius, segments);
sphere4.position.x = -50.0;
sphere4.position.y = 6.123233995736766e-15;
sphere4.position.z = 24.999999999999986;
sphere4.scale.set(10,10,20);
sphere4.rotation.z = -2.220446049250313e-16;
sphere4.rotation.x = 2.137707831735906;
sphere4.rotation.y = 0.0;
sphere4.rotation.order = 'ZXY';
scene.add(sphere4);
var sphere5 = createSphere(radius, segments);
sphere5.position.x = -35.355339059327385;
sphere5.position.y = -35.35533905932737;
sphere5.position.z = 0.0;
sphere5.scale.set(10,10,20);
sphere5.rotation.z = 0.7853981633974481;
sphere5.rotation.x = 2.137707831735906;
sphere5.rotation.y = 0.0;
sphere5.rotation.order = 'ZXY';
scene.add(sphere5);
var sphere6 = createSphere(radius, segments);
sphere6.position.x = -9.184850993605149e-15;
sphere6.position.y = -50.0;
sphere6.position.z = -25.000000000000014;
sphere6.scale.set(10,10,20);
sphere6.rotation.z = 1.5707963267948963;
sphere6.rotation.x = 2.137707831735906;
sphere6.rotation.y = 0.0;
sphere6.rotation.order = 'ZXY';
scene.add(sphere6);
var sphere7 = createSphere(radius, segments);
sphere7.position.x = 35.35533905932737;
sphere7.position.y = -35.355339059327385;
sphere7.position.z = -49.999999999999986;
sphere7.scale.set(10,10,20);
sphere7.rotation.z = 2.356194490192345;
sphere7.rotation.x = 2.137707831735906;
sphere7.rotation.y = 0.0;
sphere7.rotation.order = 'ZXY';
scene.add(sphere7);
var sphere8 = createSphere(radius, segments);
sphere8.position.x = 50.0;
sphere8.position.y = -1.2246467991473532e-14;
sphere8.position.z = -75.00000000000001;
sphere8.scale.set(10,10,20);
sphere8.rotation.z = 3.141592653589793;
sphere8.rotation.x = 2.137707831735906;
sphere8.rotation.y = 0.0;
sphere8.rotation.order = 'ZXY';
scene.add(sphere8);
var sphere9 = createSphere(radius, segments);
sphere9.position.x = 35.355339059327385;
sphere9.position.y = 35.35533905932737;
sphere9.position.z = -100.00000000000001;
sphere9.scale.set(10,10,20);
sphere9.rotation.z = 3.9269908169872414;
sphere9.rotation.x = 2.137707831735906;
sphere9.rotation.y = 0.0;
sphere9.rotation.order = 'ZXY';
scene.add(sphere9);
var sphere10 = createSphere(radius, segments);
sphere10.position.x = 1.5308084989341916e-14;
sphere10.position.y = 50.0;
sphere10.position.z = -124.99999999999999;
sphere10.scale.set(10,10,20);
sphere10.rotation.z = 4.71238898038469;
sphere10.rotation.x = 2.137707831735906;
sphere10.rotation.y = 0.0;
sphere10.rotation.order = 'ZXY';
scene.add(sphere10);
// end spheres
document.body.appendChild(renderer.domElement);
//renderer.render(scene, camera);
var controls = new THREE.TrackballControls(camera);
function render() {
controls.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
I've read and tried various suggestions to make the THREE namespace available or something, but haven't had any luck. If I manually insert
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://unpkg.com/three#0.85.0/examples/js/controls/TrackballControls.js"></script>
<script src="https://unpkg.com/three#0.85.0/examples/js/Detector.js"></script>
at the top of the page <head>, everything works fine, but I cannot change the order when it's generated by Documenter. Any thoughts on how to work around this?
Edit: The requirejs configuration generated by Documenter looks like this:
// Generated by Documenter.jl
requirejs.config({
paths: {
'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/languages/julia.min',
'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.10.3/headroom.min',
'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min',
'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/contrib/auto-render.min',
'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min',
'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.10.3/jQuery.headroom.min',
'katex': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min',
'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min',
'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/languages/julia-repl.min',
},
shim: {
"highlight-julia": {
"deps": [
"highlight"
]
},
"katex-auto-render": {
"deps": [
"katex"
]
},
"headroom-jquery": {
"deps": [
"jquery",
"headroom"
]
},
"highlight-julia-repl": {
"deps": [
"highlight"
]
}
}
});
////////////////////////////////////////////////////////////////////////////////
require(['jquery', 'katex', 'katex-auto-render'], function($, katex, renderMathInElement) {
$(document).ready(function() {
renderMathInElement(
document.body,
{
"delimiters": [
{
"left": "$",
"right": "$",
"display": false
},
{
"left": "$$",
"right": "$$",
"display": true
},
{
"left": "\\[",
"right": "\\]",
"display": true
}
]
}
);
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($, hljs) {
$(document).ready(function() {
hljs.initHighlighting();
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) {
// Manages the top navigation bar (hides it when the user starts scrolling down on the
// mobile).
window.Headroom = Headroom; // work around buggy module loading?
$(document).ready(function() {
$('#documenter .docs-navbar').headroom({
"tolerance": {"up": 10, "down": 10},
});
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
// Modal settings dialog
$(document).ready(function() {
var settings = $('#documenter-settings');
$('#documenter-settings-button').click(function(){
settings.toggleClass('is-active');
});
// Close the dialog if X is clicked
$('#documenter-settings button.delete').click(function(){
settings.removeClass('is-active');
});
// Close dialog if ESC is pressed
$(document).keyup(function(e) {
if (e.keyCode == 27) settings.removeClass('is-active');
});
});
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
// Manages the showing and hiding of the sidebar.
$(document).ready(function() {
var sidebar = $("#documenter > .docs-sidebar");
var sidebar_button = $("#documenter-sidebar-button")
sidebar_button.click(function(ev) {
ev.preventDefault();
sidebar.toggleClass('visible');
if (sidebar.hasClass('visible')) {
// Makes sure that the current menu item is visible in the sidebar.
$("#documenter .docs-menu a.is-active").focus();
}
});
$("#documenter > .docs-main").bind('click', function(ev) {
if ($(ev.target).is(sidebar_button)) {
return;
}
if (sidebar.hasClass('visible')) {
sidebar.removeClass('visible');
}
});
})
// Resizes the package name / sitename in the sidebar if it is too wide.
// Inspired by: https://github.com/davatron5000/FitText.js
$(document).ready(function() {
e = $("#documenter .docs-autofit");
function resize() {
var L = parseInt(e.css('max-width'), 10);
var L0 = e.width();
if(L0 > L) {
var h0 = parseInt(e.css('font-size'), 10);
e.css('font-size', L * h0 / L0);
// TODO: make sure it survives resizes?
}
}
// call once and then register events
resize();
$(window).resize(resize);
$(window).on('orientationchange', resize);
});
// Scroll the navigation bar to the currently selected menu item
$(document).ready(function() {
var sidebar = $("#documenter .docs-menu").get(0);
var active = $("#documenter .docs-menu .is-active").get(0);
if(typeof active !== 'undefined') {
sidebar.scrollTop = active.offsetTop - sidebar.offsetTop - 15;
}
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
function set_theme(theme) {
var active = null;
var disabled = [];
for (var i = 0; i < document.styleSheets.length; i++) {
var ss = document.styleSheets[i];
var themename = ss.ownerNode.getAttribute("data-theme-name");
if(themename === null) continue; // ignore non-theme stylesheets
// Find the active theme
if(themename === theme) active = ss;
else disabled.push(ss);
}
if(active !== null) {
active.disabled = false;
if(active.ownerNode.getAttribute("data-theme-primary") === null) {
document.getElementsByTagName('html')[0].className = "theme--" + theme;
} else {
document.getElementsByTagName('html')[0].className = "";
}
disabled.forEach(function(ss){
ss.disabled = true;
});
}
// Store the theme in localStorage
if(typeof(window.localStorage) !== "undefined") {
window.localStorage.setItem("documenter-theme", theme);
} else {
console.error("Browser does not support window.localStorage");
}
}
// Theme picker setup
$(document).ready(function() {
// onchange callback
$('#documenter-themepicker').change(function themepick_callback(ev){
var themename = $('#documenter-themepicker option:selected').attr('value');
set_theme(themename);
});
// Make sure that the themepicker displays the correct theme when the theme is retrieved
// from localStorage
if(typeof(window.localStorage) !== "undefined") {
var theme = window.localStorage.getItem("documenter-theme");
if(theme !== null) {
$('#documenter-themepicker option').each(function(i,e) {
e.selected = (e.value === theme);
})
} else {
$('#documenter-themepicker option').each(function(i,e) {
e.selected = $("html").hasClass(`theme--${e.value}`);
})
}
}
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
// update the version selector with info from the siteinfo.js and ../versions.js files
$(document).ready(function() {
var version_selector = $("#documenter .docs-version-selector");
var version_selector_select = $("#documenter .docs-version-selector select");
version_selector_select.change(function(x) {
target_href = version_selector_select.children("option:selected").get(0).value;
window.location.href = target_href;
});
// add the current version to the selector based on siteinfo.js, but only if the selector is empty
if (typeof DOCUMENTER_CURRENT_VERSION !== 'undefined' && $('#version-selector > option').length == 0) {
var option = $("<option value='#' selected='selected'>" + DOCUMENTER_CURRENT_VERSION + "</option>");
version_selector_select.append(option);
}
if (typeof DOC_VERSIONS !== 'undefined') {
var existing_versions = version_selector_select.children("option");
var existing_versions_texts = existing_versions.map(function(i,x){return x.text});
DOC_VERSIONS.forEach(function(each) {
var version_url = documenterBaseURL + "/../" + each;
var existing_id = $.inArray(each, existing_versions_texts);
// if not already in the version selector, add it as a new option,
// otherwise update the old option with the URL and enable it
if (existing_id == -1) {
var option = $("<option value='" + version_url + "'>" + each + "</option>");
version_selector_select.append(option);
} else {
var option = existing_versions[existing_id];
option.value = version_url;
option.disabled = false;
}
});
}
// only show the version selector if the selector has been populated
if (version_selector_select.children("option").length > 0) {
version_selector.toggleClass("visible");
}
})
})

three.js order of loading resources

I have a obj model that I'm loading via THREE.LoadingManager and a few textures. When I'm opening the page with clear cache - I'm always getting model without textures. I can see them after pressing F5. My code looks like this:
var manager = new THREE.LoadingManager();
var loader = new THREE.TextureLoader(manager);
var textures_loaded = 0;
var id;
for (id in materials) {
loader.load('images/' + materials[id].unique_id + '.jpg', function(t) {
t.magFilter = THREE.NearestFilter;
t.minFilter = THREE.LinearMipMapLinearFilter;
var re = /images\/(\d+)\.jpg/g;
var result = re.exec(t.image.currentSrc);
material = materials.filter(function(obj) {
return obj.unique_id == result[1];
}).shift();
material.setTexture(t);
textures_loaded += 1;
if (textures_loaded == materials.length) {
mainLoop();
}
});
}
var loader = new THREE.OBJLoader(manager);
loader.load('obj/' + model.model_name, function (object) {
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
var mesh = model.meshes.filter(function(mesh) {
return mesh.name == child.name;
}).shift();
child.material.map = mesh.material.texture;
child.geometry.buffersNeedUpdate;
child.geometry.uvsNeedUpdate;
}
});
scene.add(object);
}
);
I'm running mainLoop only after all textures are loaded. But sometimes model loads faster. How can I control order of loading objects using THREE.LoadingManager ?. How can I show model only after everything is loaded ?
I would do something like this. Have two functions responsible for loading each set of content inline. In this case the meshes will not be loaded until the materials are done loading.
var manager = new THREE.LoadingManager();
var loader = new THREE.TextureLoader(manager);
function loadMaterials(materials, callback){
var textures_loaded = 0;
for (var id in materials) {
loader.load('images/' + materials[id].unique_id + '.jpg', function(t) {
t.magFilter = THREE.NearestFilter;
t.minFilter = THREE.LinearMipMapLinearFilter;
var re = /images\/(\d+)\.jpg/g;
var result = re.exec(t.image.currentSrc);
material = materials.filter(function(obj) {
return obj.unique_id == result[1];
}).shift();
material.setTexture(t);
textures_loaded += 1;
if (textures_loaded == materials.length) {
callback("materialsLoaded");
//mainLoop();
}
});
}
}
var loadedMeshes = [];
function loadMeshes(meshes, callback){
var meshes_loaded = 0;
for(var i in meshes){
var loader = new THREE.OBJLoader(manager);
loader.load('obj/' + model.model_name, function (object) {
loadedMeshes.push(object);
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
//you'll need to map to the right material.
child.material.map = mesh.material.texture;
child.geometry.buffersNeedUpdate;
child.geometry.uvsNeedUpdate;
}
});
if(loadedMeshes.length == meshes.length){
callback("meshesLoaded");
}
};
}
}
var materials = ["material1", "material2"];
var meshes = ["mesh1.obj", "mesh2.obj"];
function onLoad(){
for(var i in loadedMeshes){
scene.add(loadedMeshes[i]);
}
mainLoop();
}
function init(){
loadMaterials(materials, function(t){
console.log(t);
loadMeshes(meshes, function(t){
console.log(t);
onLoad(t);
})
})
}
Maybe you can try to execute your mainLoop only when the document is ready, using some jQuery:
$('document').ready(function mainLoop(){});
"this event does not get triggered until all assets such as images have been completely received"
from jQuery .ready event

Load multiple OBJ-files together with multple textures

Using the many examples on ThreeJS, I'm able to load multiple OBJ files into my scene. I'm also able to load multiple images as textures. However, the textures get assigned to the objects in 'order of appearance' and therefore, sometimes the wrong image gets assigned to the OBJ files.
I retrieve a list of OBJ files and textures from a JavaScript array, let's say:
…
"arr_threejs": [{
"geometry": "my_first_object.obj",
"material_uvmap": "my_first_texture.jpg",
}, {
"geometry": "my_second_object.obj",
"material_uvmap": "my_second_object.obj",
}],…
Then, I use this 'loader' class to load the textures:
for (var i = 0; i < arr_threejs.length; i++) {
var loader = new THREE.ImageLoader(manager);
str_material_uvmap_url = arr_threejs[i].material_uvmap;
loader.load(str_material_uvmap_url, function (image) {
console.log(image);
var index = textures.push(new THREE.Texture()) - 1;
textures[index].image = image;
textures[index].needsUpdate = true;
});
}
And, simillary, the geometry:
var loader = new THREE.OBJLoader(manager);
for (var i = 0; i < arr_threejs.length; i++) {
str_model_url = arr_threejs[i].geometry;
loader.load(str_model_url, function (object, i) {
var index = get_index_by_url(str_model_url); //doesn't work
objects[index] = object;
objects[index].traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.map = textures[index];
child.material.side = THREE.DoubleSide;
}
});
scene.add(objects[index]);
}, onProgress, onError);
}
It seems I have no way in the callback function to know what object or what texture I'm dealing with. var index = get_index_by_url(str_model_url); doesnt work, because str_model_url isn't passed as arguement.
So, my question is,
specifically:
Is there a way to know the index of the image or object that I'm trying to load?
or generally:
Is there a standard way to load multple OBJ-files with textures?
You can use anonymus functions. For example:
loader.load(str_model_url, (function (url,scale) { return function (object, i) {
console.log( url );
console.log( scale );
}}) (str_model_url, 0.5)
, onProgress
, onError
);
Here's #stdob answer implemented in my code:
// MODEL
// model - LOAD TEXTURE
for (var i = 0; i < arr_threejs.length; i++) {
var loader = new THREE.ImageLoader(manager);
str_material_uvmap_url = arr_threejs[i].material_uvmap;
loader.load(str_material_uvmap_url, (function (url, index) {
return function (image, i) {
textures[index] = new THREE.Texture();
textures[index].image = image;
textures[index].needsUpdate = true;
}
})(str_material_uvmap_url, i)
, onProgress
, onError
);
}
// model - LOAD OBJECT
var loader = new THREE.OBJLoader(manager);
for (var i = 0; i < arr_threejs.length; i++) {
str_model_url = arr_threejs[i].geometry;
loader.load(str_model_url, (function (url, index) {
return function (object, i) {
objects[index] = object;
objects[index].traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.map = textures[index];
child.material.side = THREE.DoubleSide;
}
});
scene.add(objects[index]);
}
})(str_model_url, i)
, onProgress
, onError
);
}

migrating from Three.JS 51 to 54 (texture problems)

i'm having some problems migrating my code to the newest release of Three.JS.
I've already tried alot, but my models keep looking black (the color function seems broken)) and as soon as I try loading a model with a texture, it crashes.
I know some things have changed regarding textures in the transition from r52 to r53 but I can't seem to implement it right. I use a dynamic loading system to cache JSON models.
Currently the code looks like this:
var MB = MB || {};
MB.Part = function () {
this.id = MB.ObjectCount++;
this.type = 'part';
this.name = '';
this.reference = undefined;
this.mesh = undefined;
this.colour = undefined;
this.texture = undefined;
this.Object3D = undefined;
this.parent = undefined;
this.visible = true;
this.position = new THREE.Vector3();
this.rotation = new THREE.Vector3();
MB.Objects[this.id] = this
};
MB.Part.prototype.load = function (reference, name, mesh, color, texture, position, rotation, visible, visible3D, callback) {
var context = this;
if (!position) position = new THREE.Vector3();
if (!rotation) rotation = new THREE.Vector3();
if (this.isGeometrySetup(mesh, texture)) {
this.insert(context, reference, name, mesh, color, texture, position, rotation, visible, visible3D);
if (callback) callback()
} else {
var loader = new THREE.JSONLoader(false);
loader.load(PATH + 'data/parts/json/' + mesh + '.js', function (geometry) {
context.setupGeometry(geometry, mesh, texture);
context.insert(context, reference, name, mesh, color, texture, position, rotation, visible, visible3D);
if (callback) callback()
})
}
};
MB.Part.prototype.insert = function (context, reference, name, mesh, color, texture, position, rotation, visible, visible3D) {
context.reference = reference;
context.mesh = mesh;
context.name = name;
if (color) context.colour = color;
if (texture) context.texture = texture;
context.visible = visible;
if (color) {
context.setupColour(color);
var Object3D = new THREE.Mesh(MB.Library.geometries[mesh], MB.Library.colours[color])
} else if (texture) {
var Object3D = new THREE.Mesh(MB.Library.geometries[texture], new THREE.MeshFaceMaterial())
}
context.Object3D = Object3D;
context.Object3D.doubleSided = true;
context.position.copy(position);
context.rotation.copy(rotation);
Object3D.Object = context;
Object3D.scale.set(SCALE, SCALE, SCALE);
Object3D.position.copy(context.position);
Object3D.rotation.copy(context.rotation);
Object3D.visible = visible3D;
MB.Object3Ds[Object3D.id] = Object3D
};
MB.Part.prototype.isGeometrySetup = function (mesh, texture) {
if (texture) {
if (!MB.Library.geometries[texture]) return false;
else return true
} else {
if (!MB.Library.geometries[mesh]) return false;
else return true
}
};
MB.Part.prototype.setupGeometry = function (geometry, mesh, texture) {
if (texture) {
if (!MB.Library.geometries[texture]) {
var file = this.loadTexture(PATH + 'data/parts/textures/' + texture + '.png');
MB.Library.geometries[texture] = geometry;
MB.Library.geometries[texture].materials[0].map = file;
MB.Library.geometries[texture].materials[0].wireframe = (RENDER === 'WIREFRAME') ? true : false
}
} else {
if (!MB.Library.geometries[mesh]) {
MB.Library.geometries[mesh] = geometry
}
}
};
MB.Part.prototype.loadTexture = function (url, mapping, callback) {
var image = new Image(),
texture = new THREE.Texture(image, mapping);
image.onload = function () {
texture.needsUpdate = true;
if (callback) callback(this)
};
image.crossOrigin = '';
image.src = url;
return texture
};
MB.Part.prototype.setupColour = function (colour) {
if (!MB.Library.colours[colour]) {
var materialColour = '0x' + COLOURS[colour].hex;
var materialOpacity = COLOURS[colour].opacity;
MB.Library.colours[colour] = new THREE.MeshPhongMaterial({
ambient: new THREE.Color(materialColour),
color: new THREE.Color(materialColour),
opacity: materialOpacity,
shininess: 100
});
MB.Library.colours[colour].wireframe = (RENDER === 'WIREFRAME') ? true : false;
MB.Library.colours[colour].transparent = (COLOURS[colour].opacity < 1) ? true : false
}
};
MB.Part.prototype.setColour = function (colour) {
if (this.colour) {
this.setupColour(colour);
this.colour = colour;
this.Object3D.material = MB.Library.colours[colour]
}
};
MB.ObjectCount = 0;
MB.Object3Ds = {};
MB.Objects = {};
MB.Library = {
'colours': {},
'geometries': {}
};
The problem seems to be situated here:
if (texture) {
if (!MB.Library.geometries[texture]) {
var file = this.loadTexture(PATH + 'data/parts/textures/' + texture + '.png');
MB.Library.geometries[texture] = geometry;
MB.Library.geometries[texture].materials[0].map = file;
MB.Library.geometries[texture].materials[0].wireframe = (RENDER === 'WIREFRAME') ? true : false
}
and in the overall way I still handle textures.
Any help would be greatly appreciated!
Thomas
Geometry doesn't have a materials array anymore. The array has been moved to MeshFaceMaterial.
new THREE.Mesh( geometry, new THREE.MeshFaceMaterials( materials ) );

Resources