function G = extractG(VList, FList)

nV = size(VList,1);
nF = size(FList,1);

%G = zeros(nF*4, nV*2);

nz = nF*12;
rowi = zeros(nz,1);
coli = zeros(nz,1);
vali = zeros(nz,1);

rowId = 1; idx=1;
for i=1:nF
    %       const Eigen::Vector3i& idx = mesh->Triangles->row(fi);
    % 		const Vector3& a = mesh->InitalVertices->row(idx[0]);
    % 		const Vector3& b = mesh->InitalVertices->row(idx[1]);
    % 		const Vector3& c = mesh->InitalVertices->row(idx[2]);
    %
    % 		restX<<b[0]-a[0], c[0]-a[0], b[1]-a[1], c[1]-a[1];
    % 		restX = restX.inverse().eval();
    %
    % 		for(int ci=0; ci<2; ++ci){
    % 			for(int cj=0; cj<2; ++cj){//dims
    % 				DefGradTriplets.push_back(Triplet<double>(rowId+2*ci+cj,2*idx[0]+ci,-restX(0,cj)-restX(1,cj)));
    % 				DefGradTriplets.push_back(Triplet<double>(rowId+2*ci+cj,2*idx[1]+ci,restX(0,cj)));
    % 				DefGradTriplets.push_back(Triplet<double>(rowId+2*ci+cj,2*idx[2]+ci,restX(1,cj)));
    % 			}
    % 		}
    
    fvids = FList(i,:);
    a = VList(fvids(1),1:2)';
    b = VList(fvids(2),1:2)';
    c = VList(fvids(3),1:2)';
    restX = [b-a c-a];
    invX = inv(restX);
    
    for cj=1:2
        for ci=1:2
           rowi(idx,1) = rowId+2*(cj-1)+ci-1; coli(idx,1) = 2*fvids(1)+ci-2; vali(idx,1) = -invX(1,cj)-invX(2,cj); idx = idx + 1;%G(rowId+2*(ci-1)+cj-1,2*fvids(1)+ci-2) = -invX(1,cj)-invX(2,cj);
           rowi(idx,1) = rowId+2*(cj-1)+ci-1; coli(idx,1) = 2*fvids(2)+ci-2; vali(idx,1) = invX(1,cj); idx = idx + 1;%G(rowId+2*(ci-1)+cj-1,2*fvids(2)+ci-2) = invX(1,cj);
           rowi(idx,1) = rowId+2*(cj-1)+ci-1; coli(idx,1) = 2*fvids(3)+ci-2; vali(idx,1) = invX(2,cj); idx = idx + 1;%G(rowId+2*(ci-1)+cj-1,2*fvids(3)+ci-2) = invX(2,cj);
        end
    end
    rowId = rowId + 4;
    
end

G = sparse(rowi, coli, vali, 4*nF, 2*nV);

% %test
% vecV = zeros(2*nV,1);
% for i=1:nV
%     vecV(2*i-1) = VList(i,1);
%     vecV(2*i)   = VList(i,2);
% end
% G*vecV

end

