public static float[] calcSmoothNormals(float[] vertices, int[] indices) {
        int vc = vertices.length / CTM_POSITION_ELEMENT_COUNT;
        int tc = indices.length / 3;
        float[] smoothNormals = new float[vc * CTM_NORMAL_ELEMENT_COUNT];//no setting to 0 needed in Java compared to C

        // Calculate sums of all neighboring triangle normals for each vertex
        for (int i = 0; i < tc; ++i) {
            // Get triangle corner indices
            int[] tri = Arrays.copyOfRange(indices, i * 3, i * 3 + 3);

            // Calculate the normalized cross product of two triangle edges (i.e. the
            // flat triangle normal)
            float[] v1 = new float[3];
            float[] v2 = new float[3];
            for (int j = 0; j < 3; ++j) {
                v1[j] = vertices[tri[1] * 3 + j] - vertices[tri[0] * 3 + j];
                v2[j] = vertices[tri[2] * 3 + j] - vertices[tri[0] * 3 + j];
            }
            float[] n = new float[3];
            n[0] = v1[1] * v2[2] - v1[2] * v2[1];
            n[1] = v1[2] * v2[0] - v1[0] * v2[2];
            n[2] = v1[0] * v2[1] - v1[1] * v2[0];
            float len = (float) sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
            if (len > 1e-10f) {
                len = 1.0f / len;
            } else {
                len = 1.0f;
            }
            for (int j = 0; j < 3; ++j) {
                n[j] *= len;
            }

            // Add the flat normal to all three triangle vertices
            for (int k = 0; k < 3; ++k) {
                for (int j = 0; j < 3; ++j) {
                    smoothNormals[tri[k] * 3 + j] += n[j];
                }
            }
        }

        // Normalize the normal sums, which gives the unit length smooth normals
        for (int i = 0; i < vc; ++i) {
            float len = (float) sqrt(smoothNormals[i * 3] * smoothNormals[i * 3]
                    + smoothNormals[i * 3 + 1] * smoothNormals[i * 3 + 1]
                    + smoothNormals[i * 3 + 2] * smoothNormals[i * 3 + 2]);
            if (len > 1e-10f) {
                len = 1.0f / len;
            } else {
                len = 1.0f;
            }
            for (int j = 0; j < 3; ++j) {
                smoothNormals[i * 3 + j] *= len;
            }
        }

        return smoothNormals;
    }
public static float [ ] calcSmoothNormals ( float [ ] vertices , int [ ] indices ) { int vc = vertices . length / CTM_POSITION_ELEMENT_COUNT ; int tc = indices . length / 3 ; float [ ] smoothNormals = new float [ vc * CTM_NORMAL_ELEMENT_COUNT ] ; for ( int i = 0 ; i < tc ; ++ i ) { int [ ] tri = Arrays . copyOfRange ( indices , i * 3 , i * 3 + 3 ) ; float [ ] v1 = new float [ 3 ] ; float [ ] v2 = new float [ 3 ] ; for ( int j = 0 ; j < 3 ; ++ j ) { v1 [ j ] = vertices [ tri [ 1 ] * 3 + j ] - vertices [ tri [ 0 ] * 3 + j ] ; v2 [ j ] = vertices [ tri [ 2 ] * 3 + j ] - vertices [ tri [ 0 ] * 3 + j ] ; } float [ ] n = new float [ 3 ] ; n [ 0 ] = v1 [ 1 ] * v2 [ 2 ] - v1 [ 2 ] * v2 [ 1 ] ; n [ 1 ] = v1 [ 2 ] * v2 [ 0 ] - v1 [ 0 ] * v2 [ 2 ] ; n [ 2 ] = v1 [ 0 ] * v2 [ 1 ] - v1 [ 1 ] * v2 [ 0 ] ; float len = ( float ) sqrt ( n [ 0 ] * n [ 0 ] + n [ 1 ] * n [ 1 ] + n [ 2 ] * n [ 2 ] ) ; if ( len > 1e-10f ) { len = 1.0f / len ; } else { len = 1.0f ; } for ( int j = 0 ; j < 3 ; ++ j ) { n [ j ] *= len ; } for ( int k = 0 ; k < 3 ; ++ k ) { for ( int j = 0 ; j < 3 ; ++ j ) { smoothNormals [ tri [ k ] * 3 + j ] += n [ j ] ; } } } for ( int i = 0 ; i < vc ; ++ i ) { float len = ( float ) sqrt ( smoothNormals [ i * 3 ] * smoothNormals [ i * 3 ] + smoothNormals [ i * 3 + 1 ] * smoothNormals [ i * 3 + 1 ] + smoothNormals [ i * 3 + 2 ] * smoothNormals [ i * 3 + 2 ] ) ; if ( len > 1e-10f ) { len = 1.0f / len ; } else { len = 1.0f ; } for ( int j = 0 ; j < 3 ; ++ j ) { smoothNormals [ i * 3 + j ] *= len ; } } return smoothNormals ; }
Calculate the smooth normals for a given mesh. These are used as the
nominal normals for normal deltas and reconstruction.

@param vertices vertex coordinate values
@param indices  vertex indices
@return smoothed normals