letter for future, misc

Coronavirus, or, a letter for the future

13 March 2020, Porto, Portugal

It’s roughly 3 am, I’ve had an idea to write a letter like this a few days ago, for posterity, so in the future people know what my thoughts about what was going on at the time were like, maybe it will be useful for some historians, but so far I have been putting it off but right now I feel this urge to write something.

In case anyone who is reading this and is not familiar with Coronavirus, or, the scientific name, COVID-19, I highly suggest a google search. The first thing I want to point out is that albeit it is called COVID-19 the brunt of the effects of the disease, so far have only been felt in early 2020, to be more specific, here in Portugal reports of confirmed sick people have only started about two weeks ago.

Reports of the virus share a scarily similar comparison to the World War Z book by Max Brooks, first only some small news about how there is a strange new disease in China, then the virus gets large enough that WHO has to finally do something, and now there are some news mentioning that a couple of medical experts in China tried to warn people about this while there was still time to contain it but the government silenced them. Anyway, back to my personal experiences, this is when I first noticed the virus, as large posts on Reddit started to grab people’s attention. Soon enough the virus was in Europe, with cases confirmed in France and Germany, but it was when the virus exploded in Italy that the paranoia really started to set in. Here in Portugal, as students were confirmed to be infected with the virus the whole university would close to prevent further spread of the disease.

A personal saying of mine that most people who I spoke with at the time agreed with was “For every confirmed case, there are 50 unconfirmed cases”, regardless, most engineering universities remained open. Meanwhile, around the globe, it seemed like the world had suddenly ran out of toilet paper, or at least Australia, Japan, and the UK did, and then later, easy to store consumables like pasta and lentils. Hand sanitizer dispensaries started to be installed everywhere, and of course, they all ran out as soon as they were installed or refilled. In the hospital next to my university, large medical tents were installed so they could help the overflowing problems in the hospitals. I feel like it’s important to point out this all happened in the week and a half the first case of the virus was confirmed in Portugal.
General safety guidelines were also distributed everywhere, most of them were to “wash my hands” for a long time(which I actually started doing as best as I could) and to “avoid touching your face” which was actually quite a tall task for me since when I program I very often grab my face either in frustration or purely out of instinct while thinking about more complex stuff.

Of course, that world leaders were, and currently are, going nuts. Right now Putin has just managed to pass a law to stay in power until 2036 and Trump who first started by saying the virus was “temporary” and “not a threat” has now ordered a complete shutdown of all flights from the European Union(the UK is not included due to the recent Brexit ordeal).

Speaking of complete shutdowns, the situation in Italy got pretty scary too, some of my friends in Italy have relayed their situation to me and it’s getting kinda extreme, hospitals are so full of people that they started to prioritize healing young people over the elderly, people can barely leave their houses let alone even think of going to the next town over. Sometimes I boot up live CCTV cameras of Rome and it’s downright scary to see places that I have been completely devoid of life.

Last Thursday(10 March 2020) when my classes started there was talk between the teachers with the students that a reunion between the DGS, an important health institution in Portugal would decide whether the university would close down. If that didn’t happen then the first confirmed case amongst one of the students in my university would inevitably force the university to close down. At that point, it was pretty clear to me that it was not a question of if but a question of when. As it happens, the following day was business as usual, but at the end of the day, we all received an e-mail from the administration that the university would close down until the 27th.

My personal thoughts about the shutdown of the university are rather bleak, I would prefer not to have classes going into the summer, and my self-discipline to watch video classes is not as good as actually being present and having to pay attention to what’s going on around me. Aside from that, the administration gave very little instructions on how to proceed: Should we hand in the current projects we have? What about future ones? They have since sent us a couple of emails with more clarifications but some questions are still up in the air.

It is important to mention that one of my biggest friends is currently out of Portugal, he got into an Erasmus-esque program, the European Project Semester and is now somewhere on the south of France, so far he hasn’t been concerned but, the disease has also spread to his town, and today Macron confirmed that all schools from Monday onwards will close. Right now his fate and what he will do is unknown, I have suggested returning back home, before a full lockdown like Italy happens, if it happens, either in Portugal or in France.

That is just what my life is right now, from my personal point of view, I don’t know what will happen to my academic studies, I don’t know what will happen to my friend, the world doesn’t know when this outbreak will end, and if current mathematical predictions aren’t wrong, we are barely starting on this logistical function, and I haven’t even discussed the economical recession that will succeed this entire endeavor, or how the fact that climate change is also a very real threat that gets almost no coverage compared to Coronavirus.

It’s 4 AM now, I should probably wrap this up with a conclusion. This year has been insane from the very first day, USA and Iran are at each other’s throats, Trump has been impeached only for the senate to say “so what” and acquit him, Bernie Sanders hasn’t managed to secure a strong lead for the primaries and now COVID-19 has successfully disrupted my weekly routine completely and who knows what it will do next, I am honestly starting to get worried of the future, amongst the rising trends of nationalism and Euroscepticism, the looming threat of climate change always on the horizon, and now COVID-19 who is guaranteed to lead the world into an economic recession, we might be at a tipping point for humanity, and if we don’t stand up for the task, it will be too late.

I don’t want your hope. I don’t want you to be hopeful. I want you to panic, I want you to feel the fear I feel every day. And then I want you to act. I want you to act as if you would in a crisis. I want you to act as if the house was on fire, because it is.

Gretha Thunberg
Advertisement
misc, programming

Equirectangular Maps to Cube Maps

A solution to a mildly tough problem

On my last blog, I wrote about a way to generate worlds, and for that, I suggested using Cube Maps to store the data and then to convert to Equirectangular to display the map.
Converting to Equirectangular, thanks to Bartosz simple and beautiful to understand code, it is also easily convertible to other languages and can be modified to output either an entire set of coordinates or just a single coordinate.
However, reversing this algorithm is not so simple, since the maths aren’t reversible and thus we are forced to search for a different solution.

Salix alba’s solution to this problem is fantastical to convert an entire image, and the code can also be easily copy-pasted, however, the way the algorithm works doesn’t allow for what I truly needed: a way to convert single coordinates from one coordinate system to the other.

Understanding the various coordinate systems

When making the conversion from Equirectangular to Cube Map, we deal with multiple coordinate systems:

  • Equirectangular Coordinates – Also called Cylindrical Equidistant Projection, it’s aspect ratio is always 2:1, it uses the (x,y) coordinate system. It represents a projection of a planet.
  • Spherical Coordinates – Spherical coordinates imply two kinds of coordinates: latitude and longitude(or phi and theta). There is a third one, radius, but for our purposes, it doesn’t matter. They represent a spherical space or in our case, the globe.
  • Cartesian Coordinates – Cartesian coordinates make use of (x,y,z) coordinates. They represent a 3D space.
  • Cube Map Coordinates – Cube Maps go back to using only an (x,y), but to avoid confusion, let’s call it (u,v).

From Equirectangular to Spherical

When converting to spherical coordinates, we want to obtain the latitude and longitude of a determined pixel on the map. The calculations to achieve that is easy, the method is explained on Wikipedia and on Mathworld.
Which leaves us with this pseudo code whose output is in radians:

function calculatePhi(y, height) {
  return (1-2*y/height)/2.0 * Math.PI;
}
  
function calculateTheta(x, width) {
  return (2*x/width-1) * Math.PI;
}
The output, when converted to degrees follows this standard. (A latitude of 90 degrees will represent the north pole, etc)

From Spherical to Cartesian

Converting from spherical to cartesian is pretty simple, Wikipedia has a pretty good guide on it, as well as Paul Bourke in his blog post about this same theme.

function calculateX(theta, phi) {
  return Math.cos(phi) * Math.cos(theta);
}
  
function calculateY(phi) {
  return Math.sin(phi);
}
  
function calculateZ(theta, phi) {
  return Math.cos(phi) * Math.sin(theta);
}
All credits to SEOS for this image showcasing what’s happening during this conversion

Cartesian to Cube Map

This is the hardest conversion, thankfully, once again, Wikipedia has got our backs, however, this time the algorithm isn’t fully complete, instead, we need to add the last function to convert from local square coordinates to the “horizontal cross” shape we want.

This is due to the nature of the way the Cartesian to CubeMap is done by Wikipedia’s algorithm, which outputs a normalized result.

function localToGlobalCoords(coords, index, cubeFaceSize) {
    switch (index)
    {
        case 0:// POSITIVE X - FRONT
            coords[0] = cubeFaceSize*2 - coords[0]*cubeFaceSize;
            coords[1] = cubeFaceSize*2 - coords[1]*cubeFaceSize;
            break;	
        case 1:// NEGATIVE X - BACK
            coords[0] = cubeFaceSize*4 - coords[0]*cubeFaceSize;
            coords[1] = cubeFaceSize*2 - coords[1]*cubeFaceSize;
            break;	
        case 2:// POSITIVE Y - TOP
            temp = coords[0];
            coords[0] = cubeFaceSize*2 - cubeFaceSize*coords[1];
            coords[1] = cubeFaceSize*temp;
            break;	
        case 3:// NEGATIVE Y - BOTTOM
            temp = coords[0];
            coords[0] = cubeFaceSize - cubeFaceSize*(-coords[1]);
            coords[1] = cubeFaceSize*3 - cubeFaceSize*temp;
            break;	
        case 4:// POSITIVE Z - RIGHT
            coords[0] = cubeFaceSize*3 - coords[0]*cubeFaceSize;
            coords[1] = cubeFaceSize*2 - coords[1]*cubeFaceSize;
            break;	
        case 5:// NEGATIVE Z - LEFT
            coords[0] = cubeFaceSize - coords[0]*cubeFaceSize;
            coords[1] = cubeFaceSize*2 - coords[1]*cubeFaceSize;
            break;	
    }
    return coords;
}

Essentially, what is happening here is that we are projecting the points that are sitting in a sphere, and projecting them onto a square.

Huge thanks to proj4.org for this image

Closing thoughts

Converting between coordinate systems can be complicated, especially if we don’t know exactly what we are dealing with. My solution is by no means a perfect solution to this problem, if your main goal is to convert an entire image then I highly recommend you use Salix alba’s solution instead.

What I wanted was to convert a single point from Equirectangular to Cube Map, and although Salix Alba’s solution is quite amazing, it simply did not fit the bill for what I wanted, which forced me to look for other options.

programming, worldbuilding

Mapping Planets

Distortions, Seamless Noise, and how to handle it.

Generating the planet

One of the simplest ways to generate a planet, is to use noise, which gives you a couple of options on which noise to use, let’s inspect each one and determine the best option:

  • Perlin Noise – Perlin Noise is the most basic option, it was developed by Ken Perlin in 1983, however it has a couple shortcomings, there are a couple visual artifacts and it’s speed at generating large images can be quite slow when compared to the other alternatives.
  • Simplex Noise – Simplex Noise was designed by Ken Perlin in 2001 in an attempt to address Perlin Noise’s shortcomings, it’s a pretty decent and fast solution however it has a major drawback, the use of 3D Simplex Noise is protected under a patent, which makes using it a pretty expensive affair.
  • Open Simplex Noise – Open Simplex Noise was developed by KDotJPG with one simple goal in mind: make a modern alternative to Simplex Noise that is free to use, that has no distortions and is relatively fast.

Out of the three I personally prefer Open Simplex Noise and is what I use for my personal projects. Do take note, the current implementation of OpenSimplexNoise needs some extra work so you can get easy access to the scale, octaves, and seeds. There is a multitude of guides out there on the internet explaining what each of these does and I highly recommend a read, however, that is not what I want to talk about in this blog post.

This is what Open Simplex Noise with 16 octaves looks like.

Seamless noise

Noise is infinite, which means if we simply give it a canvas with a ratio of 2:1 to make an equirectangular map it will not loop when you eventually try to put the map on a sphere(shoutout to this amazing website), and you will get massive variations on the horizontal seam and on the poles.

There is a multitude of ways to fix this, on this amazing blog post Red Blob Games only needs to generate an island, using a function that takes distance from the center as a variable and setting it height 0 at the edges minimizing seams.

However, this is not what we want. We want to generate a planet, with the possibility for north and south poles and to do that we are gonna need some more complex math calculations.

Spherical Mapping

A method that can generate spherical planets would be to convert the cartesian coordinates of our canvas to spherical coordinates, generate noise based on those coordinates and finally convert that noise back to cartesian and map it to the canvas.

However this implementation has its limitations, and the why and how it happens is demonstrated by Ron Valstar in this brilliant blog post mainly the fact that the shapes of the continents look extremely weird and distorted and therefore is not what I want.

Cube Mapping

The second method I ended up using was motivated by both Ron Valstar’s post and acko’s Making Worlds series of blog posts, in them, they describe the generation of a globe through generating a cube and then inflating it as if it was a balloon until it’s shaped like a sphere.

All credits to acko.net for this image, it explains the cube map concept in a easy way to visualize.

Now we simply have to generate six faces which is easy enough, there is a multitude of ways to do it.

The way I ended up doing it was by creating an array and then populating it with data. Converting the 2D coordinates of a canvas to the 3D coordinates of a cube and then generating noise for each of these 3D coordinates to then store them in the corresponding 2D coordinate value.

//Z STATIC
for(int y = 0; y < cubeFaceSize; y++) {
	for(int x = 0; x < cubeFaceSize * 2; x++) {
		//Generates FRONT
		if(x < cubeFaceSize) {
			cubeMap[cubeFaceSize+x][cubeFaceSize+y] = noise.noise3D(x, y, 0);                    
		}
		//Generates BACK
		else {
			cubeMap[cubeFaceSize*3+(x-cubeFaceSize)][cubeFaceSize+y] = noise.noise3D(cubeFaceSize-(x-cubeFaceSize), y, cubeFaceSize);
		}
	}
}
//X STATIC
for(int y = 0; y < cubeFaceSize; y++) {
	for(int x = 0; x < cubeFaceSize * 2; x++) {
		//Generates LEFT
		if(x < cubeFaceSize) {
			cubeMap[x][cubeFaceSize+y] = noise.noise3D(0, y, cubeFaceSize-x);                   
		}
		//Generates RIGHT
		else {
			cubeMap[cubeFaceSize*2+(x-cubeFaceSize)][cubeFaceSize+y] = noise.noise3D(cubeFaceSize, y, x-cubeFaceSize);
		}
	}
}
//Y STATIC
for(int y = 0; y < cubeFaceSize * 2; y++) {
	for(int x = 0; x < cubeFaceSize; x++) {
		//Generates TOP
		if(y < cubeFaceSize) {
			cubeMap[cubeFaceSize+x][y] = noise.noise3D(x, 0, cubeFaceSize-y);          
		}
		//Generates BOTTOM
		else {
			cubeMap[cubeFaceSize+x][cubeFaceSize*2+(y-cubeFaceSize)] = noise.noise3D(x, cubeFaceSize, y-cubeFaceSize);
		}                
	}
}

This way, we can generate a cube map, which is easily converted to an equirectangular map thanks to the amazing code snippet provided by Bartosz.

As you can see, the equirectangular map has much better-looking shapes, and when wrapped around a sphere it produces similar results to Spherical mapping without all its downsides, besides, an equirectangular projection can be easily converted by multiple programs, such as NASA’s G.Projector to basically any kind of map that has ever existed.

Closing Thoughts

Generating an entire planet can be a daunting task, and although noise can be quite a powerful tool if used properly it is still bound to problems that humans have had for centuries, such as how to map a globe to a 2D canvas with minimal distortion.

The solution I propose here only produces very roughly generated planets, with no regards whatsoever towards tectonic plates, rivers, proper island chains, or even mountain ranges and therefore is only really meant to be used as a demonstration or starting basis for more advanced simulations.

In fact, it only really produces a matrix of values within a certain specified range, for the greyscale images they are within 0 to 255 and are then converted to a pixel producing an image similar to the first greyscale image or on a range from -11000 to 8000 emulating real-world height differences and then painting the same color for height intervals.(eg: between 0 to 5 paint it in a sandy color to emulate beaches)

God used beautiful mathematics in creating the world.

Paul Dirac

misc

The Journey Begins

Thanks for joining me!

What is this blog gona be about?

Well, this blog is gona be catered towards my work, sort of a place where I can write down my notes and my methodologies for what I’m doing and why I’m doing them. Besides that, I’m also gona write what I thought about movies, books, games, etc that I watch/read/played. So stick around for the fun.

What are you working on right now?

The biggest project I have at the moment is a program to Worldbuild, a topic I’m fascinated with. My main focus right now is picking the language which I am gona work on (either Java or C#) and how to generate a basic outline of a planet.

Who are you?

I’m a programmer from Portugal, still in University.

What movies/books/games are you watching/reading/playing right now?

Right now I am playing a couple games: Stellaris, Monster Hunter World and Star Citizen mainly, haven’t been reading many books sadly, and neither have I been watching movies, I have however been watching a couple animes that I find are actually pretty good fun and a good distraction.

So yeah, that’s pretty much the biggest points I wanted to address. Thank you for taking your time to read this and stick around if you are curious!