public static void generate(TriMesh mesh) {

    FloatBuffer tangents = BufferUtils.createFloatBuffer(mesh.getVertexCount() * 3);
    FloatBuffer binormals = BufferUtils.createFloatBuffer(mesh.getVertexCount() * 3);

    IntBuffer indexBuffer = mesh.getIndexBuffer();
    FloatBuffer vertexBuffer = mesh.getVertexBuffer();
    FloatBuffer textureBuffer = mesh.getTextureCoords(0).coords;
    indexBuffer.rewind();

    Vector3f tangent = new Vector3f();
    Vector3f binormal = new Vector3f();
    Vector3f normal = new Vector3f();
    Vector3f verts[] = new Vector3f[3];
    Vector2f texcoords[] = new Vector2f[3];

    for (int i = 0; i < 3; i++) {
      verts[i] = new Vector3f();
      texcoords[i] = new Vector2f();
    }

    for (int t = 0; t < indexBuffer.capacity() / 3; t++) {

      int index[] = new int[3];

      for (int v = 0; v < 3; v++) {
        index[v] = indexBuffer.get();
        verts[v].x = vertexBuffer.get(index[v] * 3);
        verts[v].y = vertexBuffer.get(index[v] * 3 + 1);
        verts[v].z = vertexBuffer.get(index[v] * 3 + 2);

        texcoords[v].x = textureBuffer.get(index[v] * 2);
        texcoords[v].y = textureBuffer.get(index[v] * 2 + 1);
      }

      computeTriangleTangentSpace(tangent, binormal, normal, verts, texcoords);

      for (int v = 0; v < 3; v++) {
        tangents.position(index[v] * 3);
        tangents.put(tangent.x);
        tangents.put(tangent.y);
        tangents.put(tangent.z);

        binormals.position(index[v] * 3);
        binormals.put(binormal.x);
        binormals.put(binormal.y);
        binormals.put(binormal.z);
      }
    }

    mesh.setTangentBuffer(tangents);
    mesh.setBinormalBuffer(binormals);
  }