Only if you give it the right information in the right order. If he's drawing that sphere as individual triangles but passing the same normal for every vertex in a triangle he won't see normal interpolation at all. For some reason I'm having a hard time reading his normal calculation code (what's the "norm" variable even for?) or else I'd try to point out a problem there.

Il add some comments.

I add a triangle to the polygon and compute the triangles normal.

void Drawable::addTriangle(const Triangle &tri)
{
int amount = vertex_data.size();
glm::vec3 const & a = tri.v1;
glm::vec3 const & b = tri.v2;
glm::vec3 const & c = tri.v3;
/*
Calculate the normal of the triangle using this formula:
triangle ( v1, v2, v3 )
edge1 = v2-v1
edge2 = v3-v1
triangle.normal = cross(edge1, edge2).normalize()
*/
const glm::vec3 n1 = glm::normalize(glm::cross(b - a, c - a));
vertex_data.push_back(tri.v1);
vertex_data.push_back(tri.v2);
vertex_data.push_back(tri.v3);
uv_data.push_back(tri.u1);
uv_data.push_back(tri.u2);
uv_data.push_back(tri.u3);
norm_data.push_back(n1);
norm_data.push_back(n1);
norm_data.push_back(n1);
index_data.push_back(amount);
index_data.push_back(amount + 1);
index_data.push_back(amount + 2);
}

Once all triangles have been added I call phongNormals()

void Drawable::phongNormals()
{
int amount = vertex_data.size();
//Get a list of all individual vertecies
std::vector<glm::vec3> vecsToCheck;
for(int i = 0; i < amount; i++)
{
bool foundIt = false;
for(int j = 0; j < vecsToCheck.size(); j++)
{
if(vecsToCheck[j] == vertex_data[i]) foundIt = true;
}
if(!foundIt) vecsToCheck.push_back(vertex_data[i]);
}
for(int i = 0; i < vecsToCheck.size(); i++)
{
const glm::vec3 ver = vecsToCheck[i];
std::vector<glm::vec3> norms;
std::vector<unsigned int> indexs;
///compare the current verticie to check with all verticies in the polygon
///if its equal I store that verticies normal(and thus the normal of the triangle it creates) as well as the position that the original normal is stored in.
for(int j = 0; j < amount; j++)
{
if(ver == vertex_data[j])
{
norms.push_back(norm_data[j]);
indexs.push_back(j);
}
}
///
///Using this formula:
///vertex v1, v2, v3, ....
///triangle tr1, tr2, tr3 // all share vertex v1
///v1.normal = normalize( tr1.normal + tr2.normal + tr3.normal )
///
glm::vec3 norm = glm::vec3(0.0f);
for (unsigned int j = 0; j < norms.size(); j++)
{
///add the normal of all the triangles that share the given verticie
norm += norms[j];
}
///normalize it
norm = glm::normalize(norm);
///and replace the old normal with the new one
for (unsigned int j = 0; j < indexs.size(); j++)
{
norm_data[indexs[j]] = norms[j];
}
}
}

In the vertex shader i multiply the normal by the model matrix to account for rotation or scaling(not translation)

#version 120
uniform mat4 MVP;
uniform mat4 Model;
attribute vec4 Position;
attribute vec2 UV;
attribute vec3 Normals;
varying vec2 uv;
varying vec3 normals;
void main(){
normals = normalize((Model * vec4(Normals.x, Normals.y, Normals.z, 0.0f)).xyz);
uv = UV;
gl_Position = MVP * Position;
}

and then apply it in the frag

#version 120
varying vec2 uv;
uniform sampler2D myTexture;
uniform bool DrawLines;
varying vec3 normals;
uniform vec4 AmbientLight;
uniform vec4 DiffuseLight;
void main(){
vec4 color;
if(DrawLines)
{
color = vec4(1,1,1,1);
}
else
{
color = texture2D( myTexture, uv ).rgba;
vec3 ambLight = AmbientLight.xyz * AmbientLight.w;
float DiffuseFactor = dot(normals, DiffuseLight.xyz);
vec3 diffLight = vec3(0, 0, 0);
if (DiffuseFactor > 0) {
diffLight = DiffuseLight.xyz * DiffuseLight.w * DiffuseFactor;
}
color.xyz = color.xyz * (ambLight + diffLight);
}
gl_FragColor = color;
}