20 September 2025

Python - List, set and dictionary

A list is an ordered collection of items. The items can be approached with their index.
a = [3, 0, 5]
a:list[int] = [3, 0, 5]
A set is an unordered collection of unique items. You can assign the same item as many times as you want without error. It will appear just once in the set.
a = {3, 0, 5}
a:set[int] = {3, 0, 5}
A dictionary is an unordered collection of key-value pairs.
a = {3: 'E'}
a:dict[int, str] = {3: 'E', 0: 'G', 5: 'S'}
The :list[] etc. are just datatype suggestions for the IDE. They don't mean anything to the actual program, and you can still assign whatever you want to the variable.

16 August 2025

Python - Execute a query with pyodbc

To work with a database via ODBC, first install the PyOdbc package and import it. The following simple query shows how to execute a select query and return data:
import pyodbc

def get_user(username) -> int:   
    with pyodbc.connect("Server=(LocalDB)\Test; Integrated Security=true; Driver={ODBC Driver 17 for SQL Server}") as conn:
        with conn.execute("SELECT id FROM Users WHERE username=?", username) as cursor:
            rows = cursor.fetchall()
    
    if len(rows) <= 0:
        return
    
    return rows[0].id

print(f"user ID: {get_user("EGS")}")

24 June 2025

.NET - Read/write a binary file line by line

To read a text file, you can use a StreamReader, but to read a binary file, you need a BinaryReader.This is how you use it:

if (File.Exists(FILENAME))
{
    using (var stream = new FileStream(FILENAME, FileMode.Open))
    using (var reader = new BinaryReader(stream))
    {
        if (stream.Length <= 0) return; //The file is empty.
        int i = reader.ReadInt32();
        string s = reader.ReadString();
    }
}

Writing is similar:

using (var stream = new FileStream(SaveFilePath, FileMode.Create))
using (var writer = new BinaryWriter(stream))
{
    writer.Write(305);
    writer.Write("EGS");
}

The file will be automatically created if it doesn't exist yet.

11 November 2024

Windows API - Set the icon of a window created with P/Invoke

This actually turned out to be very easy. Just load the icon as you would in .net.
var icon = new Icon(GetResourceStream("Cards.ico"));

GetResourceStream is a custom method of mine to load the icon file from the embedded resources.

To create the window, you already defined a window class struct somewhere.
var windowClass = new WindowClassEx();
All you have to do, is pass the icon's internal handle to this structure.
windowClass.Icon = icon.Handle;
And make sure the icon object is not destroyed while the window is open.

Windows will look for a small icon for the title bar in Icon when IconSmall is not set.

29 January 2024

GIT - avoid merge-commits

GIT inserts commits named merge branch '{name}' when there was a deviation from the branch. They can be reunited with a rebase command.
git pull --rebase

12 October 2023

GIT - rename a branch

Here's how to rename a GIT branch from Windows Explorer. This assumes GIT is installed on the computer.

  • Enter git branch -m "{new name}".
  • Enter git push origin :"{old name}" "{new name}".
  • Enter git push origin -u "{new name}".

22 September 2023

GIT - commit changes

Here's how to commit changes to GIT from Windows Explorer when the IDE doesn't have built-in support for GIT. This assumes GIT is installed on the computer.

  • In Explorer, navigate to the root folder of the project and choose File > Open command prompt.
  • Alternatively, run the command prompt; enter {drive letter}: unless the project is on the C drive; then enter cd "{full path to project root}".
  • Enter git add . to add new files.
  • Enter git commit -m "{description of the commit}".
  • Enter git push.

04 August 2023

MFA - Generate time-based one-time passwords (TOTP)

I had to implement MFA for a web application. I needed to generate a key the user could save in an authenticator app. My application had to use this key to generate a code to validate the authenticator codes the user would enter.

Generate the key

Generate a truly random sequence of bytes and convert them to base32. I'm using the default SHA1 algorithm to generate keys of twenty characters.

const string BASE32_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

using (var gen = new RNGCryptoServiceProvider()) //Use a cryptographically secure provider!
{
    byte[] bytes = new byte[HMACSHA1.Create().HashSize / 8];
    gen.GetBytes(bytes); //Fills the array with 20 bytes
    
    byte[] base32 = new byte[bytes.Length];
    double d = (double)byte.MaxValue / (double)BASE32_CHARS.Length;
    
    for (int i = 0; i < bytes.Length; i++)
    {
        double c = (double)bytes[i];
        int j = (int)Math.Floor(c / d); //If c is 255, j is 32, which is out of bounds!
        base32[i] = (byte)BASE32_CHARS[j < BASE32_CHARS.Length ? j : BASE32_CHARS.Length - 1]; //Scale from 255 to # of possible chars
    }
    
    return Encoding.ASCII.GetString(base32);
}

Generate a code

First calculate the number of intervals that passed since the reference time. This time is usually the unix epoch of 1 january 1970 0:00:00 UTC. Then decode the base32 key and use it to hash the interval counter. Finally use this hash to generate a code like an authenticator app would.

const uint INTERVAL = 30; //The default of 30 seconds
const uint CODE_LENGTH = 6; //The default of 6 digits

double seconds = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
ulong counter = (ulong)Math.Floor(seconds / INTERVAL);
byte[] counterBytes = BitConverter.GetBytes(counter);
Array.Reverse(counterBytes); //Must be big-endian while .net is little-endian

var hmac = HMACSHA1.Create();
hmac.Key = DecodeBase32(key);
hmac.ComputeHash(counterBytes);

int offset = hmac.Hash[hmac.Hash.Length - 1] & 0xf;
int bin = (hmac.Hash[offset + 0] & 0x7f) << 24 |
          (hmac.Hash[offset + 1] & 0xff) << 16 |
          (hmac.Hash[offset + 2] & 0xff) << 8 |
          (hmac.Hash[offset + 3] & 0xff);

return bin % (int)Math.Pow(10, CODE_LENGTH);

DecodeBase32(string value):

var base32 = BASE32_CHARS.Select((c, i) => new { c, i }).ToDictionary(ch => ch.c, ch => ch.i); //Each char and it's 0–31 index
string bits = string.Concat(value.Select(c => Convert.ToString(base32[c], 2).PadLeft(5, '0'))); //A string of 0's en 1's
return Enumerable.Range(0, bits.Length / 8).Select(i => Convert.ToByte(bits.Substring(i * 8, 8), 2)).ToArray();

02 August 2023

Visual Studio - flickering scroll bar when editing certain file types

I got a new laptop and installed Visual Studio 2022 on it. When editing sql and aspx files on the secondary monitor, I could not scroll down or right. The scrollbar just flickers when I hovered over it. With Visual Studio opened on the main monitor, scrolling works fine. It turns out this is an issue with Visual Studio rendering in combination with the main monitor scaled above 100 percent. There are two solutions for it.

Disable the Visual Studio option Environment > General > Optimize rendering for screens with different pixel densities and restart Visual Studio
This solves the scrolling issue, but causes text on all panels to appear a bit blurry.
Set Windows option System > Display > Scale to 100 percent.
This also solves the scrolling issue, but now your main monitor is not at the (for me at least) recommended 125 percent.

Windows 8-11 - start something automatically on start-up

For my work, I want a bat-file to run when Windows starts up. This starts up a local database server with my test database I use for all my development.

Startup folder

To do this, launch Explorer and go to %AppData%\Microsoft\Windows\Start Menu\Programs\Startup. Paste a shortcut to the file you want to run in this folder.

Run a command

Alternatively, you can run a command via Windows' Task Scheduler. Create a new task and set it for Windows 8 or 10. Add a trigger and set it to at log in. Add an action and enter the command including any arguments.

13 January 2022

SQL - check whether or not a column exists

This is a simple way for SQL Server and Sybase databases to check whether a column exists or not inside a query:

COL_LENGTH('Keywords', 'parent_id')

But you can't use that in a select clause. There is another trick though to select a column that may or may not exist:

SELECT (
  SELECT Keyw2.parent_id
  FROM (SELECT 0 AS parent_id) [Dummy]
  CROSS APPLY (SELECT FIRST parent_id FROM dba.Keywords WHERE keyword_id = Keyw.keyword_id) [Keyw2]
  ) [KeywordParent],
  ...
FROM dba.Keywords Keyw

The trick relies on not using a table alias in the subselect!

This can come in handy when columns may or may not exist depending on the application's database version.

07 January 2022

Visual Studio - High contrast syntax colors

When Windows is in a high contrast theme, Visual Studio displays all code in the same color. To change this, go to Tools > Options > Environment > Fonts and Colors and select Show settings for Text Editor. Now you can set the colors for identifiers (variable names), (user) type names, strings (text between quotes), literals, numbers, comments etc. This is my setup:

I've put this here so that next time I reinstall Visual Studio, I can refer to this screenshot to remember what colors I used.

Note that the Plain Text foreground is used for the caret's color.

02 March 2021

Math - Normalize a 3D vector

This method is part of the Vector3 class, and changes the vector into a unit vector.
void Normalize() {
  if (IsZero) return; //X, Y and Z are 0: it would set each component to NaN.
  float length = (float)Math.Sqrt(X * X + Y * Y + Z * Z);
  X /= length;
  Y /= length;
  Z /= length;
}

Math - Calculate a normal vector from three position vectors

This Vector3 constructor calculates a surface normal from three 3D vectors.
public Vector3(Vector3 a, Vector3 b, Vector3 c) {
  var u = b - a; //Requires an overloaded minus
  var v = c - a; //operator for two vector3's.
  X = (u.Y * v.Z) - (u.Z * v.Y);
  Y = (u.Z * v.X) - (u.X * v.Z);
  Z = (u.X * v.Y) - (u.Y * v.X);
  Normalize();
}

08 August 2020

Using Hiero Font Tool to create a distance field font to use with shaders

This article is about text rendering with a 3D graphics library, like OpenGL. A regular font atlas texture doesn't scale well. To render text that looks sharp at any size, you need a distance field texture atlas. Hiero is a tool that can create such a font. It requires Java.

  • Pick a font (system or file) and the characters you want (sample text).
  • Set Rendering to Java, so the effects are listed.
  • Remove the Color effect and add a Distance field effect.
  • Set it's Scale to 15 and Spread to 10. This high scale will make the sample slow to regenerate, so maybe do this last.
  • At the right-bottom, set X and Y to 0 and the four Padding values to 8.
  • Increase or decrease the Size of the glyphs, so they all fit on one page.

Now you can save the font. Hiero will create a png image of the glyphs and a fnt file describing their positions and sizes. With these, you can generate textured quads for your text. A specific fragment shader will use the distance fields in the texture to render sharp text.

21 July 2020

Math - Calculate a look-at matrix for OpenGL (II)

This is a simplification of the method to create a look-at or camera matrix from 2017. Based on DirectX documentation, it creates the matrix in one step, without multiplication. The matrix is created transposed for OpenGL. This method takes in a Vector3 Position and Direction.

This matrix doesn't work when looking straight up or down, because in that case the x-axis cross product fails. To solve this, manually set the x-axis in that case.

bool isVertical = direction.X == 0 && direction.Z == 0;
var up = new Vector3(0, 1, 0);
var zAxis = direction.Normalized();
var xAxis = isVertical ? new Vector3(1, 0, 0) : Vector3.CrossProduct(up, zAxis).Normalized();
var yAxis = Vector3.CrossProduct(zAxis, xAxis);

return new Matrix(
    xAxis.X, xAxis.Y, xAxis.Z, -Vector3.DotProduct(xAxis, position),
    yAxis.X, yAxis.Y, yAxis.Z, -Vector3.DotProduct(yAxis, position),
    zAxis.X, zAxis.Y, zAxis.Z, -Vector3.DotProduct(zAxis, position),
    0, 0, 0, 1
);

19 April 2020

OpenGL - Billboarding in the vertex shader

All of the particles of a particle system are typically billboarded to always face the camera. At first, you do this by calculating a model matrix for each particle and send it to the instance buffer. You could also just send the particle's position and calculate the model matrix in the vertex shader:

mat4 model = mat4(1); //Identity matrix
model = translate(model, position);

This requires a function to translate a matrix, which GLSL doesn't have, so you provide one.

mat4 translate(mat4 m, vec3 p)
{
    m[3][0] = m[0][0] * p.x + m[1][0] * p.y + m[2][0] * p.z + m[3][0];
    m[3][1] = m[0][1] * p.x + m[1][1] * p.y + m[2][1] * p.z + m[3][1];
    m[3][2] = m[0][2] * p.x + m[1][2] * p.y + m[2][2] * p.z + m[3][2];
    m[3][3] = m[0][3] * p.x + m[1][3] * p.y + m[2][3] * p.z + m[3][3];
    return m;
}

You then multiply this model matrix with the camera (view) matrix. It is the resulting modelView matrix that you want to billboard by removing the rotation from it:

mat4 billboard(mat4 m)
{
    m[0][0] = 1;
    m[0][1] = 0;
    m[0][2] = 0;

    m[1][0] = 0;
    m[1][1] = 1;
    m[1][2] = 0;

    m[2][0] = 0;
    m[2][1] = 0;
    m[2][2] = 1;

    return m;
}

31 December 2019

Math - Interpolating a value

Here's how to interpolate a value from one range to another:

Range 1: 100.....550.....1000
Range 2: 300..... x .....3000

This formula will do it:

public static float Interpolate(this float value, float minValue, float maxValue, float minScale, float maxScale) =>
  (((value - minValue) / (maxValue - minValue)) * (maxScale - minScale)) + minScale;

float x = 550.Interpolate(100, 1000, 300, 3000); //x = 1650

Try it

Range 1
Range 2 ...

See also

Scaling a value

16 July 2019

Math - Calculate the 3D world position of a 2D window vector

I render a 3D triangle. When I click on it, I want to know the point on the triangle that was clicked. To calculate this point, you need:
  • Point position: the window position of the mouse click. You get this point directly from the event raised by the operating system.
  • Matrix projection and camera (also called modelview): the matrices used to transform from object space to world space and then to 2D clip coordinates.
  • Rectangle viewport: the position and size of the viewport on which to project.
  • An InvertMatrix method. You can find an implementation here.
Then you calculate the line that contains all the points that project to the clicked position as follows:
public (Vector3 near, Vector3 far) GetWorldPosition(Point position)
{
    position.Y = viewport.Height - position.Y; //For OpenGL, the bottom is the origin.
    position -= viewport.Position; //Adjust to the viewport's position on the window.
    var p = position.Normalized(Size); //Normalize the point to the range [-1;1].
    var inv = (Projection * Camera).Invert(); //Calculate the inverse matrix.
    var near = new Vector4(p.X, p.Y, -1, 1) * inv;
    var far = new Vector4(p.X, p.Y, 1, 1) * inv;
    near.PerspectiveDivide(); //Divide X, Y and Z by the W component.
    far.PerspectiveDivide();
    return (near, far);
}
If you draw this line, it should appear as a dot until you move the camera, because every vector on this line projects on the same screen pixel.
Intersecting this line with the triangle then gives me the 3D point I'm looking for.

See also

Calculate the 2D window position of a 3D vector

10 April 2019

Math - Generate a UV sphere

The following code generates the vertices and faces of a UV sphere. It is based on this CodeProject article. The code is written in C#, but it's really about the math. It first generates the vertices in a two-dimensional array, and then the faces from that array. The top and bottom are treated separately, because they are only one single vertex. Because of this, the first and final parallel are finished with triangles instead of a quads.
public void GenerateUVSphere(float parallels, float meridians)
{
    ObjectVertex top = null, bottom = null;
    var vertices = new ObjectVertex[(int)Ceiling(parallels) - 1, (int)Ceiling(meridians)];

    for (int parallel = 0; parallel < parallels + 1; parallel++)
    {
        double p = parallel * (PI / parallels);

        for (int meridian = 0; meridian < meridians; meridian++)
        {
            double m = 2 * meridian * (PI / meridians);
            float x = (float)(Sin(p) * Cos(m));
            float y = (float)Cos(p);
            float z = (float)(Sin(p) * Sin(m));

            var vertex = new ObjectVertex(x, y, z);

            if (parallel <= 0)
                top = vertex;
            else if (parallel >= parallels)
                bottom = vertex;
            else
                vertices[parallel - 1, meridian] = vertex;
        }
    }

    for (int parallel = 0; parallel < parallels; parallel++)
    {
        for (int meridian = 0; meridian < meridians; meridian++)
        {
            bool last = meridian >= meridians - 1;

            if (parallel <= 0)
            {
                var a = vertices[parallel, meridian];
                var b = vertices[parallel, last ? 0 : meridian + 1];
                Faces.Add(new ObjectFace(this, top, b, a));
            }
            else if (parallel >= parallels - 1)
            {
                var a = vertices[parallel - 1, meridian];
                var b = vertices[parallel - 1, last ? 0 : meridian + 1];
                Faces.Add(new ObjectFace(this, bottom, a, b));
            }
            else
            {
                var a = vertices[parallel - 1, meridian];
                var b = vertices[parallel - 1, last ? 0 : meridian + 1];
                var c = vertices[parallel, meridian];
                var d = vertices[parallel, last ? 0 : meridian + 1];
                AddQuad(a, b, c, d, false);
            }
        }
    }
}