glNormalPointer - problem with smoothing

I want to read PLY file. My problem is that when I apply normals to my object it looks not nice. I calculate normals for each triangle. Should I calculate normals for each vertex?

Rendered object has got bad looking shades.

each object it’s seperate file. It looks fine when I get calculated normals from cooked mesh in PhysX 3.2 and render it.

//--------------------------------------------------------------------
// CPLYReader class atributes
//--------------------------------------------------------------------
vector pxTriVertex; // vector of read vertexes from .ply file
vector normals; // vector of calculated normals
vector pxIndices; // vector of read vertexes from .ply file

//------------------------------------------------------

for(unsigned int i = 0; i < pxIndices.size(); i+=3)
{
vertex1 = pxTriVertex.at( pxIndices.at(i) );
vertex2 = pxTriVertex.at( pxIndices.at(i+1) );
vertex3 = pxTriVertex.at( pxIndices.at(i+2) );

	normal = calculateNormal(vertex1,vertex2,vertex3);
	normals.push_back(normal); // dodaj do wektora
}

//--------------------------------------------------------------
// calculate normal
//--------------------------------------------------------------
PxVec3 calculateNormal(PxVec3 vertex1, PxVec3 vertex2, PxVec3 vertex3)
{
// Licz wektory 1 i 2
PxVec3 v1, v2, vc, normal;
float value;

v1.x = vertex1.x - vertex2.x;
v1.y = vertex1.y - vertex2.y;
v1.z = vertex1.z - vertex2.z;

v2.x = vertex1.x - vertex3.x;
v2.y = vertex1.y - vertex3.y;
v2.z = vertex1.z - vertex3.z;

// iloczyn wektorowy (cross)

vc.x = (v1.y * v2.z) - (v2.y * v1.z);
vc.y = (v2.x * v1.z) - (v1.x * v2.z);
vc.z = (v1.x * v2.y) - (v2.x * v1.y);

// normalizacja

value = sqrt( (vc.x * vc.x) + (vc.y * vc.y) + (vc.z * vc.z) );

normal.x = vc.x / value;
normal.y = vc.y / value;
normal.z = vc.z / value;

return normal;

}
//------------------------------------------------------------
// OpenGL
//--------------------------------------------------------------
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//glEnable(GL_LIGHT1);

GLfloat ambient[4]={0.2f,0.2f,0.2f,1.0f};
GLfloat diffuse[4]={0.8,0.8,0.8,1.0f};
GLfloat specular[4]={0.0f, 0.0f, 0.0f, 1.0f};
GLfloat mat_diffuse[4]={0.85f,0.85f,0.85f,1.0f};

glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);

GLfloat LightPosition[] = {10, 45, 0.0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
//glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
glMaterialf(GL_FRONT, GL_SHININESS, 0.1 * 128.0);

/------------------------------------------------------
// render object
// vector ply;
// -----------------------------------------------------
glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glEnable ( GL_COLOR_MATERIAL );
glColor3b(63,63,63);
glMultMatrixf(mat);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, ply[number].pxTriVertex.data() );
glNormalPointer(GL_FLOAT, 0, ply[number].normals.data());
glDrawElements(GL_TRIANGLES, ply[number].pxIndices.size() , GL_UNSIGNED_INT , ply[number].pxIndices.data() );
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable( GL_COLOR_MATERIAL);
glPopMatrix();

Yes, the glDrawElements call requires the same amount of vertex and normal data.
Make sure pxTriVertex.size() == normals.size() in your code or you’ll crash.

I haven’t checked your cross() implementation, but make sure to generate the face normal on the front face.

Then to smooth out all edges the algorithm is to walk over the list of indices and generate one normal per index by averaging the face normals of all triangles which share this index and normalize the result.
That averaging can be weighted by triangle area or angle between the normals to improve the look.

If you want to preserve sharp edges it’s getting more complicated. Here’s a simple explanation of the necessary steps for that algorithm: https://user.xmission.com/~nate/smooth.html