static void avgSmNormals(MeshVertex v) {
    Vec3f normalSum = MeshTempState.getInstance().vec3f1;
    for (; v != null; v = v.next) {
      if (v.index == IDX_UNDEFINED) {
        normalSum.set(v.norm[0]);
        int sm = v.smGroup;

        for (MeshVertex i = v.next; i != null; i = i.next) {
          if (i.smGroup == sm) {
            assert (i.index == IDX_UNDEFINED);
            i.index = IDX_SET_SMOOTH;
            normalSum.add(i.norm[0]);
          }
        }

        if (MeshUtil.isNormalOkAfterWeld(normalSum)) {
          normalSum.normalize();
          for (MeshVertex i = v; i != null; i = i.next) {
            if (i.smGroup == sm) {
              i.norm[0].set(normalSum);
            }
          }
        }
      }
    }
  }
  static int processVertices(
      MeshVertex[] pVerts, int nVertex, boolean allHardEdges, boolean allSameSmoothing) {
    int nNewVerts = 0;
    Vec3f normalSum = MeshTempState.getInstance().vec3f1;
    for (int i = 0; i < nVertex; ++i) {
      if (pVerts[i] != null) {
        if (!allHardEdges) {
          if (allSameSmoothing) {
            // calculate average normal for one smoothing group
            normalSum.set(pVerts[i].norm[0]);
            for (MeshVertex v = pVerts[i].next; v != null; v = v.next) {
              normalSum.add(v.norm[0]);
            }

            if (MeshUtil.isNormalOkAfterWeld(normalSum)) {
              normalSum.normalize();
              for (MeshVertex v = pVerts[i]; v != null; v = v.next) {
                v.norm[0].set(normalSum);
              }
            }
          } else {
            // various Sm
            mergeSmIndexes(pVerts[i]);
            avgSmNormals(pVerts[i]);
          }
        }
        // weld points based on texture and assign new indexes
        nNewVerts = weldWithTB(pVerts[i], nNewVerts);
      }
    }
    return nNewVerts;
  }