Sharing Variables/Data between Program and Modules

One of the challenges of switching to modules was defining variables that both the main program and module could use. The solution that seemed to work was to have my program import a simple file with all the shared variables. This loaded before the module, making the variables available to both the module and the program.

However, I am now trying to change some of my variables to Vector2 and Vector3, The problem is that the simple file does not know about vectors.

So, I was looking at ways where the main program and the module could share a collection of variables. For example, I can define a list of variables in one program and pass the address of that list to the other program. But I somehow have to let that other program know the offsets for those variables.

Before I make a mess of this - is there a recommended method of sharing variables/data between the main program and modules? In assembly language, you can create a “structure” that provides common definitions and offsets for variables in a list. Is there something like that you can use with three.js?

The idea of JS modules is to have them and their data to be separate from each other, so if your main program is a module and you’re trying to pass data between modules that might not be a good idea.

On the other hand, if you import a module into the main program, it’s possible to have a two-way communication between them.

Yes, that’s what I am doing. Running a main program and importing a module.

Both programs are sharing a lot of the same variables. Rather than passing a long collection of variables to the mod function as part of the function and having the mod function return a long collection of results back to the main program, it would seem that there should be a way to simply pass the address of a collection of inputs to the mod function and then have the mod pass back the address of a collection of results.

I have seen some complicated solutions on the internet, but I am also interested in determining which method works best with three.js.

ADDITION
An example: I want the module to compute the new speed, rotation, and position of an object (all of which are expressed in vector3 form). To do so, the module needs to know the current speed, rotation and position of the object along with a lot of other information (mostly constants). When the module is done, I want it to send me the new speed, rotation and position of the object so I can use those values elsewhere in my program.

The simplest way is probably declare an object in the module and export it, then you can pass w/e you want or add properties to that object on both sides:

compute.js

const xchange = {};

...

export { ... , xchange }

main module

import { ..., xchange } from 'compute.js'

const read_data = xchange.somedata;

xchange.writedata = ...;

you can also import THREE in both modules, that shouldn’t create any overhead for as long as THREE import paths are the same.

1 Like

It looks like that works.

In compute.js, I imported Vector2 and Vector3 from three.module.js
I then created a few test variables for xchange:

let xchange = {
		test1: {value: 0},
		test2: {value: new Vector2 (0,0)},
		test3: {value: new Vector3 (0,0,0)},
	};

In the main program, I added the following instructions:

let dummy1 = xchange.test1;
let dummy2 = new Vector2 (0,0);
	dummy2 = xchange.test2;
let dummy3 = new Vector3 (0,0,0);
	dummy3 = xchange.test3;

So, as far as I can tell, the Main Program treats all those variables as it’s own.

I assume that when I call the routines compute.js and it updates those values, that the updated values will be automatically carried over to the Main Program?

I am getting an error message regarding loading three.js module twice. However, I now see that the module is not using an import map command. So I assume that once I use the same steps for importing the three.js module into my module, that this error will disappear. (I will check to see how the three.js modules are doing this.)

Yes, if you create an importmap and then use the importmap variables in both modules, you shouldn’t get any errors.

The object name here is a pointer, so you will read/write from/to the same memory location.

1 Like

Regarding importing three.js modules, I was wrong. Apparently, you don’t use import maps in modules.

To avoid unexpected problems, I create a directory on my server that includes the files and file structure, e.g.:

mod146 build, etc. examples, etc. js [this includes my custom modules]

It took a bit of trial and error, but this is what avoids the error notice:

In the main program:

<script type="importmap">
	{"imports": {
//		"three": "../build/three.module.js",
		"three": "./mod146/build/three.module.js",
		"three/addons/": "./jsm/"
		}
	}
</script>
<script type="module">

import {
	AmbientLight,
	AnimationClip,
	[etc]
//} from "./mod146/build/three.module.js"; [EDIT: not what I used]
} from 'three'; [EDIT: this is what I used, same as three.js modules]

In my custom module, I load the three.js library with the following:

import {
	Object3D,
	Quaternion
} from '.../build/three.module.js';

I don’t know if that is correct or the best way to do it, but it seems to work.

You define map in the same html file along with your main module, then you can use this map variables in import statements in your main module AND in the modules you import.

1 Like

Thanks. I was not sure that the three/addon was for (I think that is a new one). I think I see now and will give this a try.

EDIT:
I incorrectly listed the command that the module used to load three.js. I have fixed that.
So, once the map defines the three.js module as “three”, it looks like all the modules and the main program can use that shortcut.

1 Like

Just a final note.

I have now been able to share variables with all my custom modules by making all my shared variables part of larger variables, e.g.:

let var_ = {
   input1: 0;
   input2: 0,
   result1: 0,
   result2: 0
}

when I call my module (whether defined as a function or class), I simply include the reference to var_.

This is extremely helpful since I can define all my variables in the main program and don’t have to load a “global variables” file at the beginning of my main program - one less file to worry about.

I assume this won’t create problems for users of programs like node.js.

You can also define a function like setup or init and export it from the module. This way you can hide the innerworkings of the module and allow to initialize the module from outside in a simple call.

1 Like

Exactly!

Where a module task requires updates, I am splitting the task into separate initialite and update functions, e.g. initTask(var_) and updateTask(var_).

And, if done properly, you can use functions multiple times. For example, if I want to move several objects, you can create separate variables for each object (e.g. var0_, var1_, etc). Each variable will have the same elements, but different values. Then I can initialize and update each one separately with, e.g., initObj(var0_) and initObj(var1_), etc. and moveObj(var0_) and moveObj(var1_), etc.

Ideally, when I am done moving everything into modules, the role of the main program will be mostly limited to holding variables and calling module functions.

1 Like