Drawing vibrating spheres

Hello,

The code below is just a sketch illustrating sound dispersion in the open air with attenuation per distance in a 2D space. I would, however, like to draw it in a 3D space. Regretfully, Canvas3D does not provide a sphere. Is there a way to do it in SuoerCollider? Using gradients is not easy for me to accomplish a layer of 3D-like spheres.

Best regards,

(
var numWaves = 26, window, view, run = true, vibration;
window = Window("sound dispersion in air", Rect(0, 0, 720, 720));
window.onClose = { run = false; };
window.front;

StaticText(window, Rect(520, 360, 256, 256))
.stringColor_(Color.grey(0.5))
.font_(Font("Arial", 128))
.string_("🧍");

view = UserView(window, window.bounds);

view.drawFunc = {
	Pen.use {
		//Pen.width = 0;
		numWaves.do { |n|
			var radius = 20 * (n + 1) + vibration;
			var inset = view.bounds.width / 2 - radius;
			var colour = Color.grey(0,(n / numWaves));
			var oval = view.bounds.insetBy(inset);
			//[radius, inset].postln;
			//Pen.color = colour;
			Pen.addOval(oval)
			.fillRadialGradient(
				oval.center,
				oval.center,
				oval.center, 
				oval.width,
				Color.grey(0, 0.06), Color.grey(0, 0))
			/*.fillRadialGradient(
				oval.center - (radius / 2),
				oval.center,
				oval.center- (radius / 2),
				oval.width,
				Color.grey(0, 0), Color.grey(0, 0.07))*/;
			//(numWaves-1 == n).if {Pen.fill} {Pen.stroke};
		};
};};
{ 
	while { run } {
		inf.do{ |i|
			vibration = sin(i) * 5;
			20.reciprocal.wait;
			window.refresh;}
	} 
}.fork(AppClock)
)

Depending on your needs, it may be easier to use e.g. a 3d game engine for doing advanced displaying. I myself have used the free and open source cross-platform godot game engine in the past to do so, which opened up a whole new universe of possibilities. See: https://godotengine.org/

For communication between supercollider and godot I used our beloved OSC protocol.

Unfortunately, godot does not support OSC out of the box, and godot devs have explicitly confirmed on multiple occasions they have no interest in implementing out of the box support for OSC (my impression at the time was that they didn’t realize that OSC is not only about “sound” control).
At some point someone started a godot C++ plugin to support OSC, but I really don’t like the idea of extending godot with c++ plugins since those are hard to maintain, especially as their plugin API at the time was not stable between versions, and hard to build by end users with no sw development experience.

The godot engine on the other hand does offer built-in support for working with the UDP protocol, and so I’ve been able to implement a parser for a (simple) subset of OSC in godot script itself, sophisticated enough for my needs at the time. The advantage of implementing it in godot script is that it works out of the box, requires no C++ compilation by the end user, and automatically is cross-platform (desktop/mobile/game consoles).

Obviously there’s some learning curve to using godot, but it’s a pretty well designed game engine with plenty of tutorials online, getting more popular all the time.

If this way of working sounds interesting to you, here’s a github repo containing a minimal sample (the repo is using only simple 2d graphics, but godot is fully 3d capable):

In the readme of the repo, 2 links are added to blog entries that give some explanation about how the OSC parsing works and how it is integrated in the sample project.

I once scripted the byte decryption of a Sonic Pi OSC message within Godot, this was painful.

Last time I had to make both SuperCollider and Godot communicate, I used this library, which I found quite easy to install and use : frankie / gdosc · GitLab .

1 Like

Thank you very much for letting me know godot! I will try it!

The easiest solution might be to use a browser-based 3d drawing engine. I can’t recommend a specific one, but I know there are many available. You can host this inside of a WebView in an sclang UI, and use runJavaScript and onJavaScriptMsg to communicate with whatever JavaScript API is doing the rendering.

2 Likes

Thank you! I will try it as well!

Try playing around with this some:

(
var win = Window.new("We have nothing to sphere but sphere itself.", Rect(300, 300, 500, 500)).front;

var sphere = UserView(win, win.view.bounds)
.background_(Color.black)
.drawFunc_{
	var radius = 100, center = 200@200, offset = radius/4, lightSize = radius/25;
	var rect = Rect.aboutPoint(center, radius, radius);
	var rect2 = Rect.aboutPoint(center-offset, radius, radius);
	Pen.addOval(rect)
	.clip
	.addOval(rect)
	.color_(Color.grey)
	.fill
	.addOval(rect2)
	.fillRadialGradient(rect2.center, rect2.center, lightSize, radius, Color.white, Color.grey(0.5, 0))
	};
)

Openframeworks might be a nice option If you know c++. Its kinda fun to use SuperCollider and OF together with OSC, which comes with both.