Easier way to print three.js objects to JavaScript console?

I frequently have a need to print three.js objects to the console during debugging sessions. Unfortunately, the current experience leaves much to be desired.

The simplest method is to simply print the object directly:

const box = new Box2();
console.log(box);

However, this has two problems: first, the console won’t display the actual coordinates, but instead will display an “Object” which you must manually expand by clicking. This is inconvenient if you have a large amount of debugging output and you are looking for anomalies.

The second problem is that when you print an object to the console, what the console displays is the value of the object right now - not what the value was at the time it was printed out. Recall that three.js recommended practices includes re-using vectors, boxes, planes and other objects rather than creating them new each time. This means that what is printed on the console may not be the value you were looking for.

A different approach is to manually destructure the object:

const box = new Box2();
console.log(box.min.x, box.min.y, box.max.x, box.min.y);

This has the advantage of providing the correct data, but it’s cumbersome to have to do this every time you want to log a three.js object.

What would be ideal is if all three.js objects had some kind of “toString()” method:

const box = new Box2();
console.log(box.toString());

Unfortunately, that does not exist. There are a couple of other things one could try:

const box = new Box2();
console.log(JSON.stringify(box));

The problem here is that (1) the extra quotes that JSON adds makes the output more cluttered, and (2) if the object contains any internal fields that are not part of its official API those will get included as well. As a general rule, I don’t like calling JSON.stringify() on class instances that are not vanilla objects.

You could also write a helper function for debugging:

const box = new Box2();
console.log(boxToString(box));

…however, you would eventually end up needing to write such a helper for every three.js type, or at least the most common ones. This seems like the kind of thing that individual three.js users should not have to reinvent themselves. And having to import the helper is not as convenient as having it be a method on the object, especially given that you’ll want to remove the import when you are done debugging.

The other approach, I suppose, is to make a swiss-army-knife stringifier that knows about many different kinds of three.js objects:

const box = new Box2();
console.log(formatThree(box)); // This will type-test that it's a box and format appropriately

This at least has the advantage that it’s only one import, but it still seems like the kind of thing that ought to be generally available rather than having each developer re-implement it.

Any other approaches I missed?

There is the Object3D.toJSON() method but that will be quite similar to what you’d get with JSON.stringify.
I would write a function that takes an Object3D and logs the relevant properties in a readable format.
Though if you have to look through long lists of objects to find discrepancies, you might want to consider not doing it by hand, and instead use a script to check if the state of your scene is how it should be.

Most often when I am debugging, it’s not the scene I am interested in, it’s the simulation. I tend to use a lot of the same basic three.js types in my simulation code - for example, my navigation mesh generator uses Vector2, Vector3, Box2, Plane and others; Similarly, my physics, terrain generation and interactive sculpting tools, particle system editor, foliage generator and so on use a lot of three.js types as well.

I already have a large number of debugging overlays / visualization layers (for example, the navigation mesh again has a translucent overlay that can be enabled). Those times when I actually need to go into the debugger and use console.log are typically one-off, ad-hoc checks, not worth writing a script for.

Yap, for in loop.
Combine that with most powerful function in Mocha, and some user defined factions in a bookmarklet, and you have the ultimate user debug tool.

1 Like

I subscribe to what @rrrr_rrrr said, I didn’t use for ... in for console printing much, but I used it to iterate all (meaningful) properties of objects with great success. It’s suited for lots of cases, especially considering that you can use the object[propertystring] alternative referencing of an object property, with all the benefits that come with it, like good for conditionals, .indexOf stuff and so on.