protected void renderTriangles(int start, int stop) {
    for (int i = start; i < stop; i++) {
      float a[] = vertices[triangles[i][VERTEX1]];
      float b[] = vertices[triangles[i][VERTEX2]];
      float c[] = vertices[triangles[i][VERTEX3]];
      int tex = triangles[i][TEXTURE_INDEX];

      /*
      // removing for 0149 with the return of P2D
      // ewjordan: hack to 'fix' accuracy issues when drawing in 2d
      // see also render_lines() where similar hack is employed
      float shift = 0.15f;//was 0.49f
      boolean shifted = false;
      if (drawing2D() && (a[Z] == 0)) {
        shifted = true;
        a[TX] += shift;
        a[TY] += shift;
        a[VX] += shift*a[VW];
        a[VY] += shift*a[VW];
        b[TX] += shift;
        b[TY] += shift;
        b[VX] += shift*b[VW];
        b[VY] += shift*b[VW];
        c[TX] += shift;
        c[TY] += shift;
        c[VX] += shift*c[VW];
        c[VY] += shift*c[VW];
      }
      */

      triangle.reset();

      // This is only true when not textured.
      // We really should pass specular straight through to triangle rendering.
      float ar = clamp(triangleColors[i][0][TRI_DIFFUSE_R] + triangleColors[i][0][TRI_SPECULAR_R]);
      float ag = clamp(triangleColors[i][0][TRI_DIFFUSE_G] + triangleColors[i][0][TRI_SPECULAR_G]);
      float ab = clamp(triangleColors[i][0][TRI_DIFFUSE_B] + triangleColors[i][0][TRI_SPECULAR_B]);
      float br = clamp(triangleColors[i][1][TRI_DIFFUSE_R] + triangleColors[i][1][TRI_SPECULAR_R]);
      float bg = clamp(triangleColors[i][1][TRI_DIFFUSE_G] + triangleColors[i][1][TRI_SPECULAR_G]);
      float bb = clamp(triangleColors[i][1][TRI_DIFFUSE_B] + triangleColors[i][1][TRI_SPECULAR_B]);
      float cr = clamp(triangleColors[i][2][TRI_DIFFUSE_R] + triangleColors[i][2][TRI_SPECULAR_R]);
      float cg = clamp(triangleColors[i][2][TRI_DIFFUSE_G] + triangleColors[i][2][TRI_SPECULAR_G]);
      float cb = clamp(triangleColors[i][2][TRI_DIFFUSE_B] + triangleColors[i][2][TRI_SPECULAR_B]);

      // ACCURATE TEXTURE CODE
      boolean failedToPrecalc = false;
      if (s_enableAccurateTextures && frustumMode){
        boolean textured = true;
        smoothTriangle.reset(3);
        smoothTriangle.smooth = true;
        smoothTriangle.interpARGB = true;
        smoothTriangle.setIntensities(ar, ag, ab, a[A],
                                      br, bg, bb, b[A],
                                      cr, cg, cb, c[A]);
        if (tex > -1 && textures[tex] != null) {
          smoothTriangle.setCamVertices(a[VX], a[VY], a[VZ],
                                        b[VX], b[VY], b[VZ],
                                        c[VX], c[VY], c[VZ]);
          smoothTriangle.interpUV = true;
          smoothTriangle.texture(textures[tex]);
          float umult = textures[tex].width;  // apparently no check for textureMode is needed here
          float vmult = textures[tex].height;
          smoothTriangle.vertices[0][U] = a[U]*umult;
          smoothTriangle.vertices[0][V] = a[V]*vmult;
          smoothTriangle.vertices[1][U] = b[U]*umult;
          smoothTriangle.vertices[1][V] = b[V]*vmult;
          smoothTriangle.vertices[2][U] = c[U]*umult;
          smoothTriangle.vertices[2][V] = c[V]*vmult;
        } else {
          smoothTriangle.interpUV = false;
          textured = false;
        }

        smoothTriangle.setVertices(a[TX], a[TY], a[TZ],
                                   b[TX], b[TY], b[TZ],
                                   c[TX], c[TY], c[TZ]);


        if (!textured || smoothTriangle.precomputeAccurateTexturing()){
                smoothTriangle.render();
        } else {
                // Something went wrong with the precomputation,
                // so we need to fall back on normal PTriangle
                // rendering.
                failedToPrecalc = true;
        }
      }

      // Normal triangle rendering
      // Note: this is not an end-if from the smoothed texturing mode
      // because it's possible that the precalculation will fail and we
      // need to fall back on normal rendering.
      if (!s_enableAccurateTextures || failedToPrecalc || (frustumMode == false)){
      if (tex > -1 && textures[tex] != null) {
        triangle.setTexture(textures[tex]);
        triangle.setUV(a[U], a[V], b[U], b[V], c[U], c[V]);
      }

      triangle.setIntensities(ar, ag, ab, a[A],
                              br, bg, bb, b[A],
                              cr, cg, cb, c[A]);

      triangle.setVertices(a[TX], a[TY], a[TZ],
                           b[TX], b[TY], b[TZ],
                           c[TX], c[TY], c[TZ]);

          triangle.render();
      }

      /*
      // removing for 0149 with the return of P2D
      if (drawing2D() && shifted){
        a[TX] -= shift;
        a[TY] -= shift;
        a[VX] -= shift*a[VW];
        a[VY] -= shift*a[VW];
        b[TX] -= shift;
        b[TY] -= shift;
        b[VX] -= shift*b[VW];
        b[VY] -= shift*b[VW];
        c[TX] -= shift;
        c[TY] -= shift;
        c[VX] -= shift*c[VW];
        c[VY] -= shift*c[VW];
      }
      */
    }
  }