docs: public static void generateTangents(TFloatList positions, TFloatList normals, TFloatList textures, TIntList indices, TFloatList tangents) {
          // Adapted from: http://www.terathon.com/code/tangent.html
          // Size of the tangent list (without the handedness value)
          final int size = normals.size();
          // Initialize all tangents to (0, 0, 0, 0)
          tangents.fill(0, size / 3 * 4, 0);
          // Storage for the derivatives in respect to u and v
          final float[] du = new float[size];
          final float[] dv = new float[size];
          // Iterate over the entire mesh
          for (int i = 0; i < indices.size(); i += 3) {
              // Triangle position indices
              final int pos0 = indices.get(i) * 3;
              final int pos1 = indices.get(i + 1) * 3;
              final int pos2 = indices.get(i + 2) * 3;
              // First triangle vertex position
              final float x0 = positions.get(pos0);
              final float y0 = positions.get(pos0 + 1);
              final float z0 = positions.get(pos0 + 2);
              // Second triangle vertex position
              final float x1 = positions.get(pos1);
              final float y1 = positions.get(pos1 + 1);
              final float z1 = positions.get(pos1 + 2);
              // Third triangle vertex position
              final float x2 = positions.get(pos2);
              final float y2 = positions.get(pos2 + 1);
              final float z2 = positions.get(pos2 + 2);
              // Triangle texture coord indices
              final int tex0 = indices.get(i) * 2;
              final int tex1 = indices.get(i + 1) * 2;
              final int tex2 = indices.get(i + 2) * 2;
              // First triangle vertex texture coord
              final float u0 = textures.get(tex0);
              final float v0 = textures.get(tex0 + 1);
              // Second triangle vertex texture coord
              final float u1 = textures.get(tex1);
              final float v1 = textures.get(tex1 + 1);
              // Third triangle vertex texture coord
              final float u2 = textures.get(tex2);
              final float v2 = textures.get(tex2 + 1);
              // First edge position difference
              final float x10 = x1 - x0;
              final float y10 = y1 - y0;
              final float z10 = z1 - z0;
              // Second edge position difference
              final float x20 = x2 - x0;
              final float y20 = y2 - y0;
              final float z20 = z2 - z0;
              // First edge texture coord difference
              final float u10 = u1 - u0;
              final float v10 = v1 - v0;
              // Second edge texture coord difference
              final float u20 = u2 - u0;
              final float v20 = v2 - v0;
              //  Coefficient for derivative calculation
              float r = 1 / (u10 * v20 - u20 * v10);
              // Derivative in respect to U
              final float dux = (v20 * x10 - v10 * x20) * r;
              final float duy = (v20 * y10 - v10 * y20) * r;
              final float duz = (v20 * z10 - v10 * z20) * r;
              // Derivative in respect to V
              final float dvx = (u10 * x20 - u20 * x10) * r;
              final float dvy = (u10 * y20 - u20 * y10) * r;
              final float dvz = (u10 * z20 - u20 * z10) * r;
              // Add the derivative in respect to U to the first vertex
              du[pos0] += dux;
              du[pos0 + 1] += duy;
              du[pos0 + 2] += duz;
              // Add the derivative in respect to U to the second vertex
              du[pos1] += dux;
              du[pos1 + 1] += duy;
              du[pos1 + 2] += duz;
              // Add the derivative in respect to U to the third vertex
              du[pos2] += dux;
              du[pos2 + 1] += duy;
              du[pos2 + 2] += duz;
              // Add the derivative in respect to V to the first vertex
              dv[pos0] += dvx;
              dv[pos0 + 1] += dvy;
              dv[pos0 + 2] += dvz;
              // Add the derivative in respect to V to the second vertex
              dv[pos1] += dvx;
              dv[pos1 + 1] += dvy;
              dv[pos1 + 2] += dvz;
              // Add the derivative in respect to V to the first vertex
              dv[pos2] += dvx;
              dv[pos2 + 1] += dvy;
              dv[pos2 + 2] += dvz;
          }
          // Iterate over all the tangents
          for (int i = 0; i < indices.size(); i++) {
              // Index for the normal
              final int nor = indices.get(i) * 3;
              // Get the normal
              final float nx = normals.get(nor);
              final float ny = normals.get(nor + 1);
              final float nz = normals.get(nor + 2);
              // Get the derivative in respect to U
              final float dux = du[nor];
              final float duy = du[nor + 1];
              final float duz = du[nor + 2];
              // Get the derivative in respect to V
              final float dvx = dv[nor];
              final float dvy = dv[nor + 1];
              final float dvz = dv[nor + 2];
              // Dot the normal and derivative in respect to U
              final float d = nx * dux + ny * duy + nz * duz;
              // Calculate the tangent using Gram-Schmidt
              float tx = (dux - nx * d);
              float ty = (duy - ny * d);
              float tz = (duz - nz * d);
              // Length of the tangent
              final float l = (float) Math.sqrt(tx * tx + ty * ty + tz * tz);
              // Normalize the tangent
              tx /= l;
              ty /= l;
              tz /= l;
              // Index for the tangent
              final int tan = indices.get(i) * 4;
              // Set the tangent coordinates
              tangents.set(tan, tx);
              tangents.set(tan + 1, ty);
              tangents.set(tan + 2, tz);
              // Cross the normal and the derivative in respect to U
              final float cx = ny * duz - nz * duy;
              final float cy = nz * dux - nx * duz;
              final float cz = nx * duy - ny * dux;
              // Dot this cross product with the derivative in respect to V
              final float d2 = cx * dvx + cy * dvy + cz * dvz;
              // Determine the handedness
              final float h = d2 < 0 ? -1 : 1;
              // Set the handedness value
              tangents.set(tan + 3, h);
          }
      }