Loading objs with callbacks

Hi,
im trying to load multiple OBJs and Images with callbacks into my sketch. The loading works fine but the Problem is that the Images and OBJs order is diffrent evreytime i load the sketch. So the images i take for the texture dont fit with the OBJs.
Heres my code and thx 4 ur help:)
let x = 1;
var objects = [];
var images = [];
var totalObjects = 8;
var totalImages = 8;
var counterObject = 0;
var counterImage = 0;
var loadingObject = false;
var loadingImage = false;
var loading = true;

function loadObjectElement(filename) {
loadModel(filename, true, objectLoaded);

function objectLoaded(object) {
console.log(filename);
append(objects, object);
counterObject++;
if (counterObject == totalObjects) {
loadingObject = true;
}
}
}

function loadImageElement(filename) {
loadImage(filename, imageLoaded);

function imageLoaded(image) {
console.log(filename);
append(images, image);
counterImage++;
if (counterImage == totalImages) {
loadingImage = true;
}
}
}

function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);

for (let i = 1; i <= 8; i++) {
loadObjectElement(“assets/” + i + “.obj”);
}

for (let i = 1; i <= 8; i++) {
loadImageElement(“assets/” + i + “.png”);
}
}

function draw() {
if ((loadingImage) && (loadingObject)) {
loading = false;
}

if (!loading) {
texture(images[x])
scale(3);
model(objects[x]);
}
}

B/c file operations in JS are asynchronous we can’t control the order they’re finished loading.

Also we don’t control what arguments are passed to a callback b/c they’re pre-determined by the caller.

Otherwise you could easily pass the index to be used for each loaded file.

However JS had a hidden hack gem which can create a clone of a function w/ modified context this and/or pre-filled parameters in addition to regular passed arguments:

Let’s take for example your loadObjectElement() function which invokes p5js loadModel() passing objectLoaded() as its callback:

'use strict';

const
  ASSETS  = 8,
  TOTAL   = ASSETS << 1, // 16

  FOLDER  = 'assets/',
  OBJ_EXT = '.obj',
  IMG_EXT = '.png',

  objects = Array(ASSETS).fill(),
  images  = Array(ASSETS).fill();

var
  loading = true,
  objCounter = 0,
  imgCounter = 0;

function setup() {
  // blah, blah, blah...

  for (var i = 0; i++ < ASSETS; ) {
    loadObj(FOLDER + i + OBJ_EXT, i - 1);
    loadImg(FOLDER + i + IMG_EXT, i - 1);
  }
}

function draw() {
  if (loading)  return;

  // blah, blah, blah...
}

function loadObj(filename, index) {
  loadModel(filename, true, objectLoaded.bind(null, index));
}

function objectLoaded(idx, obj) {
  objects[idx] = obj;
  if (++objCounter + imgCounter == TOTAL)  loading = false;
}

function loadImg(filename, index) {
  loadImage(filename, imageLoaded.bind(null, index));
}

function imageLoaded(idx, img) {
  images[idx] = img;
  if (++imgCounter + objCounter == TOTAL)  loading = false;
}

By passing a bind() callback to a loading function, we can force any number of preceding parameters to be filled w/ pre-determined arguments in addition to the caller’s sent arguments.

We already know the loading caller sends 1 argument to its callback, which is the loaded asset itself.

That’s why your objectLoaded() callback has 1 parameter named object:

In my “hacked” version I’ve added 1 extra parameter which comes before the regular parameter:

function objectLoaded(idx, obj) {
  objects[idx] = obj;
  if (++objCounter + imgCounter == TOTAL)  loading = false;
}

That extra parameter is gonna be filled w/ the index value I’ve passed to bind():

function loadObj(filename, index) {
  loadModel(filename, true, objectLoaded.bind(null, index));
}

And that’s the hacked trick!

BtW, the code gets smaller & less complex if you instead just use preload() to load your assets:

'use strict';

const
  ASSETS  = 8,
  FOLDER  = 'assets/',
  OBJ_EXT = '.obj',
  IMG_EXT = '.png',

  objects = Array(ASSETS).fill(),
  images  = Array(ASSETS).fill();

function preload() {
  for (var i = 0; i++ < ASSETS; ) {
    loadObj(FOLDER + i + OBJ_EXT, i - 1);
    loadImg(FOLDER + i + IMG_EXT, i - 1);
  }
}

function loadObj(filename, index) {
  loadModel(filename, true, objectLoaded.bind(null, index));
}

function objectLoaded(idx, obj) {
  objects[idx] = obj;
}

function loadImg(filename, index) {
  loadImage(filename, imageLoaded.bind(null, index));
}

function imageLoaded(idx, img) {
  images[idx] = img;
}

Thanks a lot works perfect now!:slight_smile: