Skip to main content


Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Fat Cerberus

Sphere General / Future of Sphere: New map engine
The default Sphere map engine, even with the enhancements made to it in minisphere, is beginning to get a bit long in the tooth.  It's not object-oriented, and extending it often requires awkward hacks.

I would like to introduce a new map engine with minisphere 4.0, one coded in JavaScript from the ground up which is designed from the start to be extensible but nonetheless includes a great deal of functionality out of the box (in order not to sacrifice Sphere's biggest strength of being easy to pick up and start programming).  So I'm posting this thread to gather ideas and see what people would like to see in a map engine.
:pig_nose: *MUNCH*

This is a placeholder topic for the eventual Sphere 2.0.  I've decided to maintain minisphere for a while longer as a backward-compatible engine, and have forked the project for the purposes of the 2.0 overhaul.  The GitHub repository is here:

edit: Removed Sphere 2.0 repository for now (I still have the code saved locally), need to get minisphere 3.1 work out of the way first so that the new engine can be based on that instead of 3.0.8.  Too many merge conflicts to deal with trying to keep the two engines in sync right now.
Sphere General / Galileo improvements
So I took a second look at the Galileo API (I pretty much haven't touched it since implementing it in one of the 1.x versions), and noticed there were a lot of warts to it that made it awkward to use or too rigid.  I came up with what I think is a more robust and usable design which will debut in minisphere 3.1.

The new API supports a transformation matrix per-Group, coordinates in 3D space (XYZ) as well as the ability to set uniforms for a Group's shader.  Here's the API documentation for what's in the git repo now:

In theory it should also be possible to do basic 3D rendering by using a projection matrix, but I haven't tested that yet.  In any case it's not that far away from the original design as stolen from TurboSphere ;), but is much more flexible.
I started playing with shaders in earnest a few days ago, and I find that they're actually pretty nifty, so I'm working on improving the shader API in minisphere 3.1.  But I'm having issues understanding how OpenGL handles them, particularly this issue below:

It seems the GL API only allows you to set uniforms on the active shader program set by glUseProgram(), so could someone familiar with GL tell me (FJ maybe?), are the values you set for uniforms lost when you change programs, or are they in fact saved as part of the state of the shader program itself?  I can't find anything about this in the OpenGL docs.

The reason I ask is that I'm trying to figure out the best way to set up the shader API for minisphere 3.1, and whether it makes more sense to have the uniform setting methods on the Group object vs. the ShaderProgram itself.  I'm leaning towards the former but if OpenGL only tracks uniforms for the active shader, that requires me to cache the values.
Programming / I finally understand matrices
Matrices always confused me.  I knew they were used for transformations in 3D rendering, and Sphere has the color matrix which allows similar tricks with RGB colors... but I never understood more than that, it all just seemed like black magic.  Even the Wikipedia articles didn't help--all the algebraic equations just go right over my head.  It wasn't until I was working on improving minisphere's ColorMatrix object last night that it finally clicked: All the matrix is doing is setting each component of the output (color, point in space, etc.) proportionally to one or more components in the input.  This is why scaling factors are on the diagonal rather than filling the matrix--each component is set proportionally only to itself.

Basically it's a weighted average in N dimensions.  It's quite elegant.

I also now understand why 3D matrices are 4x4 as well: In order for translation to work, you need to have a known constant factor somewhere.  So you have the W coordinate, which is always 1 so that you can express translation as a product of it (W=1 * tx/ty/tz).

Why could I not find this layman's perspective on matrices anywhere else?  Everywhere I looked showed the mathematical theory behind them, but not much else.  If I had seen the description above, I would have understood immediately and then the math would have made more sense.
Site Comments / Forum text too small on mobile
Some of the text is fine, other text like the forum names are very tiny.  It's not bad on iOS but Android is practically unusable on any browser.  A screenshot from my Galaxy S5 is attached.

Compare the size of the forum names and descriptions to the text in the footer box.
So it finally struck me the other day, the beauty of the Pegasus design and its obsession with modules.  For a long time I thought it just added pointless complexity, but, well... I don't think that anymore.  It's now the direction I want to pursue for minisphere 4.0 and forwards. :)

The thing about CommonJS modules is, module import is language-agnostic: As long as the underlying platform (minisphere in this case) knows how to load a module given only its name and returns a set of bindings back to the JS environment, the JS code using those bindings doesn't care whether they came from JS code, loaded from a DLL, etc.  This is in stark contrast to, say, RequireScript which can only deal with JS scripts and expects a concrete SphereFS filename.  Module names by contrast are abstract.

What this means for us is that a plugin subsystem can easily be layered on top of the module system:

For instance a graphics plugin might register a module for itself, say "screen".  When a script says require("screen"), only then is the plugin loaded and a render window created.  And despite the lazy initialization, there's no risk of a race condition because the require() is also what gives you the bindings.

In this way plugin references are implicit, avoiding the need for a plugin manager GUI or anything of that sort; a game only loads plugins it uses, loads them on-demand (pre-loading, if needed, could be implemented via a Cell build step which scanned your scripts for require() calls), and any plugins which are never referenced never need to be included (in contrast to a plugin manager which can create unintended explicit references).
minisphere 3.0 includes basic, provisional support for TypeScript.  In order to maintain full compatibility with Sphere 1.x semantics, the ts.transpile() method is used to convert .ts scripts into JavaScript before evaluating them.  This allows all of TypeScript's syntax features to be used such as lambdas x => x * 812 and classes, however it loses features that require the full TypeScript program model such as compile-time type checking and module support.

Since TypeScript is a proper superset of JavaScript, it strikes me that, for Sphere 2.0, we could standardize on TypeScript instead of plain JavaScript.  minisphere 4.0 would be a good place to start experimenting with this.

If this were implemented, legacy constructs such as RequireScript()--which for compatibility reasons can never be made SphereFS compliant--could be deprecated in favor of TS's much cleaner imports system.  This would bring us closer to the original vision of Pegasus without the hackiness of extensions like CommonJS.
Programming / I think I just found an optimizer bug
So I started getting weird segfaults in minisphere after a recent change, but they'd only show up in a release build and were 100% non-reproducible in an unoptimized build.  I figured I was invoking undefined behavior somewhere, but skimming my code everything looked fine.

I have the following declaration at the top of debugger.c:

Code: (c) [Select]
static vector_t* s_sources;

This vector maintains a list of sources without a backing script file, e.g. scripts embedded in a map file.  Keeping that code in memory enables SSJ to download it later for display.  The vector is properly initialized on startup:
Code: (c) [Select]
s_sources = vector_new(sizeof(struct source));

And if I print out its length right then, I get zero as expected.  However I was getting segfaults later on accessing that same vector, verified by adding debugging information to the release build, and examining its contents showed it had insane garbage values.  Very strange.  Now mind you, by specification in C static variables are always supposed to be initialized to zero on startup if they don't have an explicit initializer.  However, making the following change fixes the crash...

Code: (c) [Select]
static vector_t* s_sources = NULL;

...and introduces a new crash when accessing a completely unrelated static vector later on!  I'm pretty sure the optimizer is at fault here, because turning off optimization makes the segfaults stop, even still using the release CRT.  Are the uninitialized static variables being optimized away even though they are assigned to later on?  If so, why didn't this issue show up long before now since the minisphere codebase has always had a lot of static variables?  I'm completely baffled.  I mean, even if the pointer isn't actually initialized to zero, it still shouldn't be crashing since it's assigned a valid value before anything else is done with it.
Programming / strnewf(): malloc + sprintf in one
While working on SSJ, I wrote the following function:
Code: (c) [Select]
strnewf(const char* fmt, ...)
va_list ap, apc;
char* buffer;
int   buf_size;

va_start(ap, fmt);
va_copy(apc, ap);
buf_size = vsnprintf(NULL, 0, fmt, apc) + 1;
buffer = malloc(buf_size);
va_copy(apc, ap);
vsnprintf(buffer, buf_size, fmt, apc);
return buffer;

Code: (c) [Select]
char* string = strnewf("%s ate %d pigs", "maggie", 812);
/* do stuff with string... */

It's quite useful when you need a formatted string on-the-fly but don't want to have to guess at the correct buffer size and risk a buffer overflow.
I've noticed a lot of spambots seem to have found the forums recently.  I can check Who's Online now and it often shows about 8-10 users "Registering for an account".  Nothing ever comes of it so the spam filters are obviously doing what they're supposed to, but it's weird that the activity has picked up all of a sudden.
Programming / ArrayBuffer polyfill for ES3/5 engines
I just found this while aimlessly Googling around:

It's a complete implementation of the ArrayBuffer and DataView objects (but not typed arrays, apparently) for non-supporting JS engines, including ES3.  It might be interesting to see how this performs in Sphere 1.x; I'd expect it to be pretty slow compared to natively-implemented buffers, but who knows?
Sphere General / Future of Sphere: Physics engine?
I've been entertaining thoughts recently of integrating a physics engine with minisphere.  I initially looked at Box2D, but that's C++ and I'd prefer to keep the engine pure C if at all possible.  This led me to look into Chipmunk:

It's C and appears to be a primary competitor to Box2D--usually faster, but with fewer bells and whistles.  It also apparently has a JS port.

My question to you guys is: Would there be any interest in seeing this become a reality?
Off-Topic Discussions / 4K TVs make awesome displays
Largely as an experiment, I hooked up my basement computer to my 55-inch UHDTV and set Windows to its native resolution of 3840x2160.  My first impression was "this is way too large to be practical as a computer monitor".  But then a curious thing happened: I found I stopped maximizing windows--a habit not even 1080p displays could shake me of.  I always felt desktop systems with free-moving windows were pointless, as all the practical workflows I've ever seen involved either a single maximized window, or in a pinch, sometimes with two side-by-side (which Snap makes into child's play).

At 4K/2160p, my typical desktop instead tends to look something like this (external link because this is absolutely ginormous and will break the page otherwise):

The application I'm primarily working with at the time goes to the bottom center, right in line with my seat, while ancillary stuff goes off to the sides or top, where it's more difficult to reach--ergonomically speaking--but (and here's the important part!) still completely visible at all times.  Which alleviates a lot of the pain of having to Alt+Tab between maximized applications when, for example, transcribing data.
Off-Topic Discussions / Anyone here play Undertale?

I discovered it completely by accident, as YouTube started suggesting me random songs from the soundtrack.

I spoiled most of the story for myself before I even played it, and I still love it.  I've never seen a game play with the fourth wall quite the way this one does: It never technically breaks it, but merely shifts it.  It's hard to explain without spoiling anything, the best I can describe is similar to the way Homestuck treats the fourth wall, by moving the goalposts.  It also takes a lot of inspiration from Earthbound.

Depending on your playstyle--you can either go pacifist, genocide, or anywhere in-between and the story actually changes depending on which route you take.  Which is very refreshing, in most games with this kind of mechanic the difference between the "good" and "evil" paths is mostly superficial.  This actually makes you deal with the consequences of your actions, and it's awesome.