void SpriteBatch::draw (const gdx_cpp::graphics::Texture& texture,float x,float y,float width,float height,int srcX,int srcY,int srcWidth,int srcHeight,bool flipX,bool flipY) {
    if (!drawing)
        throw std::runtime_error("SpriteBatch.begin must be called before draw.");

    if (&texture != lastTexture) {
        renderMesh();
        lastTexture = const_cast<Texture*>(&texture);
        invTexWidth = 1.0f / texture.getWidth();
        invTexHeight = 1.0f / texture.getHeight();
    } else if (idx == verticesSize) renderMesh();

    float u = srcX * invTexWidth;
    float v = (srcY + srcHeight) * invTexHeight;
    float u2 = (srcX + srcWidth) * invTexWidth;
    float v2 = srcY * invTexHeight;
    float fx2 = x + width;
    float fy2 = y + height;

    if (flipX) {
        float tmp = u;
        u = u2;
        u2 = tmp;
    }

    if (flipY) {
        float tmp = v;
        v = v2;
        v2 = tmp;
    }

    vertices[idx++] = x;
    vertices[idx++] = y;
    vertices[idx++] = color;
    vertices[idx++] = u;
    vertices[idx++] = v;

    vertices[idx++] = x;
    vertices[idx++] = fy2;
    vertices[idx++] = color;
    vertices[idx++] = u;
    vertices[idx++] = v2;

    vertices[idx++] = fx2;
    vertices[idx++] = fy2;
    vertices[idx++] = color;
    vertices[idx++] = u2;
    vertices[idx++] = v2;

    vertices[idx++] = fx2;
    vertices[idx++] = y;
    vertices[idx++] = color;
    vertices[idx++] = u2;
    vertices[idx++] = v;
}
void SpriteBatch::draw (const gdx_cpp::graphics::Texture& texture,float x,float y) {
    if (!drawing)
        throw std::runtime_error("SpriteBatch.begin must be called before draw.");

    if (&texture != lastTexture) {
        renderMesh();
        lastTexture = const_cast<Texture*>(&texture);
        invTexWidth = 1.0f / texture.getWidth();
        invTexHeight = 1.0f / texture.getHeight();
    } else if (idx == verticesSize) renderMesh();

    float fx2 = x + texture.getWidth();
    float fy2 = y + texture.getHeight();

    vertices[idx++] = x;
    vertices[idx++] = y;
    vertices[idx++] = color;
    vertices[idx++] = 0;
    vertices[idx++] = 1;

    vertices[idx++] = x;
    vertices[idx++] = fy2;
    vertices[idx++] = color;
    vertices[idx++] = 0;
    vertices[idx++] = 0;

    vertices[idx++] = fx2;
    vertices[idx++] = fy2;
    vertices[idx++] = color;
    vertices[idx++] = 1;
    vertices[idx++] = 0;

    vertices[idx++] = fx2;
    vertices[idx++] = y;
    vertices[idx++] = color;
    vertices[idx++] = 1;
    vertices[idx++] = 1;
}
void SpriteBatch::draw (const gdx_cpp::graphics::Texture& texture,const std::vector<float>& spriteVertices, int offset,int length) {
    if (!drawing)
        throw std::runtime_error("SpriteBatch.begin must be called before draw.");

    if (&texture != lastTexture) {
        renderMesh();
        lastTexture = const_cast<Texture*>(&texture);
        invTexWidth = 1.0f / texture.getWidth();
        invTexHeight = 1.0f / texture.getHeight();
    } else if (idx + length >= verticesSize) renderMesh();


    memcpy(&vertices[idx], &spriteVertices[offset], sizeof(float) * length);
    idx += length;
}
void SpriteBatch::draw (const gdx_cpp::graphics::Texture& texture,float x,float y,float originX,float originY,float width,float height,float scaleX,float scaleY,float rotation,int srcX,int srcY,int srcWidth,int srcHeight,bool flipX,bool flipY) {
    if (!drawing)
        throw new std::runtime_error("SpriteBatch.begin must be called before draw.");

    if (&texture != lastTexture) {
        renderMesh();
        lastTexture = const_cast<Texture*>(&texture);
        invTexWidth = 1.0f / texture.getWidth();
        invTexHeight = 1.0f / texture.getHeight();
    } else if (idx == 20000) {
        renderMesh();
    }

    // bottom left and top right corner points relative to origin
    float worldOriginX = x + originX;
    float worldOriginY = y + originY;
    float fx = -originX;
    float fy = -originY;
    float fx2 = width - originX;
    float fy2 = height - originY;

    // scale
    if (scaleX != 1 || scaleY != 1) {
        fx *= scaleX;
        fy *= scaleY;
        fx2 *= scaleX;
        fy2 *= scaleY;
    }

    // construct corner points, start from top left and go counter clockwise
    float p1x = fx;
    float p1y = fy;
    float p2x = fx;
    float p2y = fy2;
    float p3x = fx2;
    float p3y = fy2;
    float p4x = fx2;
    float p4y = fy;

    float x1;
    float y1;
    float x2;
    float y2;
    float x3;
    float y3;
    float x4;
    float y4;

    // rotate
    if (rotation != 0) {
        float cos = math::utils::cosDeg(rotation);
        float sin = math::utils::sinDeg(rotation);

        x1 = cos * p1x - sin * p1y;
        y1 = sin * p1x + cos * p1y;

        x2 = cos * p2x - sin * p2y;
        y2 = sin * p2x + cos * p2y;

        x3 = cos * p3x - sin * p3y;
        y3 = sin * p3x + cos * p3y;

        x4 = x1 + (x3 - x2);
        y4 = y3 - (y2 - y1);
    } else {
        x1 = p1x;
        y1 = p1y;

        x2 = p2x;
        y2 = p2y;

        x3 = p3x;
        y3 = p3y;

        x4 = p4x;
        y4 = p4y;
    }

    x1 += worldOriginX;
    y1 += worldOriginY;
    x2 += worldOriginX;
    y2 += worldOriginY;
    x3 += worldOriginX;
    y3 += worldOriginY;
    x4 += worldOriginX;
    y4 += worldOriginY;

    float u = srcX * invTexWidth;
    float v = (srcY + srcHeight) * invTexHeight;
    float u2 = (srcX + srcWidth) * invTexWidth;
    float v2 = srcY * invTexHeight;

    if (flipX) {
        float tmp = u;
        u = u2;
        u2 = tmp;
    }

    if (flipY) {
        float tmp = v;
        v = v2;
        v2 = tmp;
    }

    vertices[idx++] = x1;
    vertices[idx++] = y1;
    vertices[idx++] = color;
    vertices[idx++] = u;
    vertices[idx++] = v;

    vertices[idx++] = x2;
    vertices[idx++] = y2;
    vertices[idx++] = color;
    vertices[idx++] = u;
    vertices[idx++] = v2;

    vertices[idx++] = x3;
    vertices[idx++] = y3;
    vertices[idx++] = color;
    vertices[idx++] = u2;
    vertices[idx++] = v2;

    vertices[idx++] = x4;
    vertices[idx++] = y4;
    vertices[idx++] = color;
    vertices[idx++] = u2;
    vertices[idx++] = v;
}