public GLDrawMap(battlecode.world.GameMap map) {
    mapWidth = map.getWidth() * DENSITY;
    mapHeight = map.getHeight() * DENSITY;

    this.map = map;
    // make map into point set
    points = prerenderMap(map.getTerrainMatrix());

    // compute normals
    norms = new Vector3f[mapHeight][mapWidth];
    Vector3f v1 = new Vector3f();
    Vector3f v2 = new Vector3f();
    Vector3f v3 = new Vector3f();
    Vector3f v4 = new Vector3f();

    Vector3f temp = new Vector3f();

    Vector3f total;
    for (int j = 0; j < mapHeight; j++) {
      for (int i = 0; i < mapWidth; i++) {
        int numNorms = 0;
        total = new Vector3f(0, 0, 0);
        norms[j][i] = new Vector3f();
        if (j > 0) {
          v3.sub(points[j - 1][i], points[j][i]);
          v3.normalize();

        } else if (j < mapHeight - 1) {
          v1.sub(points[j + 1][i], points[j][i]);
          v1.normalize();
        }
        if (i > 0) {
          v4.sub(points[j][i - 1], points[j][i]);
          v4.normalize();
        } else if (i < mapWidth - 1) {
          v2.sub(points[j][i + 1], points[j][i]);
          v2.normalize();
        }

        if (j > 0) {
          if (i < mapWidth - 1) {
            temp.cross(v2, v3);
            temp.normalize();
            total.add(temp);
            numNorms++;
          }
          if (i > 0) {
            temp.cross(v3, v4);
            temp.normalize();
            total.add(temp);
            numNorms++;
          }
        }
        if (j < mapHeight - 1) {
          if (i < mapWidth - 1) {
            temp.cross(v1, v2);
            temp.normalize();
            total.add(temp);
            numNorms++;
          }
          if (i > 0) {
            temp.cross(v4, v1);
            temp.normalize();
            total.add(temp);
            numNorms++;
          }
        }

        total.scale(1.0f / (float) numNorms);
        norms[j][i].set(total);
        norms[j][i].normalize();
      }
    }

    // compute colors
    // final Color3f groundColor = new Color3f(0.4f, 0.4f, 0.4f);
    // final Color3f obstacleColor = new Color3f(1.0f, 0.5f, 0.0f);
    final Color4f groundColor = new Color4f(243.0f / 255.0f, 221.0f / 255.0f, 92.0f / 255.0f, 1.0f);
    // final Color3f obstacleColor = new Color3f(47.0f / 255.0f, 23.0f / 255.0f, 0.0f);
    final Color4f obstacleColor = new Color4f(0.0f, 0.0f, 0.0f, 0.0f);

    cols = new Color4f[mapHeight][mapWidth];
    TerrainTile[][] tiles = map.getTerrainMatrix();
    for (int j = 0; j < mapHeight; j++) {
      for (int i = 0; i < mapWidth; i++) {
        cols[j][i] = groundColor;
      }
    }
    for (int j = 1; j < mapHeight; j++) {
      for (int i = 1; i < mapWidth; i++) {

        int numLand = 0;
        if (tiles[i / DENSITY][j / DENSITY] == TerrainTile.NORMAL) {
          numLand++;
        }
        if (tiles[i / DENSITY][j / DENSITY] == TerrainTile.NORMAL) {
          numLand++;
        }
        if (tiles[i / DENSITY][j / DENSITY] == TerrainTile.NORMAL) {
          numLand++;
        }
        if (tiles[i / DENSITY][j / DENSITY] == TerrainTile.NORMAL) {
          numLand++;
        }

        float landFrac = (float) numLand / 4.0f;
        Color4f color = new Color4f();
        color.interpolate(obstacleColor, groundColor, landFrac);

        cols[j][i] = color;

        // cols[j][i] = new Color3f(0.0f, 0.4f * landFrac, 0.4f * waterFrac);
      }
    }

    // make a list of all wall positions
    /*
    ArrayList<Vector3f> wallPositions = new ArrayList<Vector3f>();

    for(int j = 0; j < mapHeight; j++) {
    for(int i = 0; i < mapWidth; i++) {


    if(tiles[i/DENSITY][j/DENSITY] == TerrainType.VOID) {
    Vector3f wall = new Vector3f();
    wall.x = i + 0.5f;
    wall.z = j + 0.5f;
    //wall.y = getMapHeight(wall.x, wall.z, null);
    wall.y = getMapHeight(wall.x, wall.z);
    wallPositions.add(wall);
    }
    }
    }
     */
    /*

    // make walls
    walls = new Vector3f [wallPositions.size()];
    //wallPositions.toArray(walls);
     */
    // make vertex array
    vertices = new float[(mapWidth) * (mapHeight) * 3];
    int k = 0;
    for (int j = 0; j < mapHeight; j++) {
      for (int i = 0; i < mapWidth; i++) {

        vertices[k] = points[j][i].x;
        vertices[k + 1] = points[j][i].y;
        vertices[k + 2] = points[j][i].z;
        k += 3;
      }
    }

    // make normal array
    normals = new float[(mapWidth) * (mapHeight) * 3];
    k = 0;
    for (int j = 0; j < mapHeight; j++) {
      for (int i = 0; i < mapWidth; i++) {
        normals[k] = norms[j][i].x;
        normals[k + 1] = norms[j][i].y;
        normals[k + 2] = norms[j][i].z;
        k += 3;
      }
    }

    // make color array
    colors = new float[(mapWidth) * (mapHeight) * 4];
    colorNorm = new float[(mapWidth) * (mapHeight) * 4];
    k = 0;
    for (int j = 0; j < mapHeight; j++) {
      for (int i = 0; i < mapWidth; i++) {
        colors[k] = cols[j][i].x;
        colors[k + 1] = cols[j][i].y;
        colors[k + 2] = cols[j][i].z;
        colors[k + 3] = cols[j][i].w;

        float norm =
            (float)
                Math.sqrt(
                    cols[j][i].x * cols[j][i].x
                        + cols[j][i].y * cols[j][i].y
                        + cols[j][i].z * cols[j][i].z);
        float val = (norm < 0.3f) ? 0.0f : 0.9f;
        colorNorm[k] = val;
        colorNorm[k + 1] = val;
        colorNorm[k + 2] = val;
        colorNorm[k + 3] = 1.0f;
        k += 4;
      }
    }

    Vector2f[][] txc = new Vector2f[mapHeight][mapWidth];
    int maxWidth = Math.max(mapWidth, mapHeight);
    for (int j = 0; j < mapHeight; j++) {
      /*if(j % 2 == 1) {
      for(int i = 0; i < mapWidth + 1; i++) {
      l.add((j - 1) * (mapWidth + 1) + i);
      l.add(j * (mapWidth + 1) + i);
      }
      } else {
      for(int i = mapWidth; i >= 0; i--) {
      l.add(j * (mapWidth + 1) + i);
      l.add((j - 1) * (mapWidth + 1) + i);
      }
      }*/

      // if(j % 2 == 1) {
      for (int i = 0; i < mapWidth; i++) {
        txc[j][i] = new Vector2f((float) i / (float) maxWidth, (float) j / (float) maxWidth);
      }
      /*} else {
      for(int i = mapWidth; i >= 0; i--) {
      txc[j][i] = new Vector2f((float)i / (float)maxWidth, 1.0f - (float)j / (float)maxWidth);
      }
      }*/
    }

    // make texcoord array
    //		int rowWidth = mapWidth ;
    texCoords = new float[(mapWidth) * (mapHeight) * 2];
    k = 0;
    for (int j = 0; j < mapHeight; j++) {
      for (int i = 0; i < mapWidth; i++) {
        texCoords[k] = txc[j][i].x;
        texCoords[k + 1] = txc[j][i].y;
        k += 2;
      }
    } /*
      for(int j = 0; j < mapHeight + 1; j++) {
      for(int i = 0; i < mapWidth + 1; i++) {
      texCoords[2 * i + j * rowWidth * 2] = i / (float)(maxWidth);
      texCoords[2 * i + 1 + j * rowWidth * 2] = 1.0f - j / (float)(maxWidth);
      }
      }*/

    // compute triangle indices
    LinkedList<Integer> l = new LinkedList<Integer>();

    // generate triangle list indices
    /*for(int j = 0; j < mapHeight; j++) {
    for(int i = 0; i < mapWidth; i++) {
    int ul = j * (mapWidth + 1) + i;
    l.add(ul);
    l.add(ul + (mapWidth + 1));
    l.add(ul + 1);

    l.add(ul + 1);
    l.add(ul + (mapWidth + 1));
    l.add(ul + (mapWidth + 1) + 1);
    }
    }*/

    // generate triangle strip indices
    for (int j = 1; j < mapHeight; j++) {
      if (j % 2 == 1) {
        for (int i = 0; i < mapWidth; i++) {
          l.add((j - 1) * (mapWidth) + i);
          l.add(j * (mapWidth) + i);
        }
      } else {
        for (int i = mapWidth - 1; i >= 0; i--) {
          l.add(j * (mapWidth) + i);
          l.add((j - 1) * (mapWidth) + i);
        }
      }
    }

    // generate triangle list indices
    /*for(int j = 0; j < mapHeight; j++) {
    for(int i = 0; i < mapWidth; i++) {
    int index = i + j * (mapWidth + 1);
    l.add(index);
    l.add(index + mapWidth + 1 + 1);
    l.add(index + 1);

    l.add(index);
    l.add(index + mapWidth + 1);
    l.add(index + mapWidth + 1 + 1);

    }
    }*/
    indices = new int[l.size()];
    for (int i = 0; i < l.size(); i++) {
      indices[i] = l.get(i).intValue();
    }
  }
  public void draw(GL2 gl, GLU glu, GLDrawState ds) {
    final Color4f highColor = new Color4f(0.0f, 1.0f, 0.0f, 1.0f);
    final Color4f lowColor = new Color4f(1.0f, 1.0f, 1.0f, 1.0f);

    Color4f[][] trueCols = new Color4f[mapHeight][mapWidth];
    //		InternalTerrainTile tiles[][] = ds.getGameMap().getTerrainMatrix();
    // Update colors

    for (int j = 0; j < mapHeight; j++) {
      for (int i = 0; i < mapWidth; i++) {

        // float fluxAmount = getMapHeight(i, j)/64.f;
        //	System.out.println(flux[j/DENSITY][i/DENSITY] + " " + fluxAmount);

        // float fluxAmount = (float)tiles[i/DENSITY][j/DENSITY].getFlux();

        Color4f tintColor = new Color4f();
        Color4f trueColor = new Color4f();

        tintColor.interpolate(lowColor, highColor, 0);
        // System.out.println(actualHeight/maxHeight);

        trueColor.interpolate(cols[j][i], tintColor, 1.0f);
        trueColor.w = cols[j][i].w;
        trueCols[j][i] = trueColor;

        // If void, see through to the background.
        /*if(tiles[i/DENSITY][j/DENSITY] == TerrainType.VOID){
        trueCols[j][i].w = 0.0f;
        }*/

      }
    }
    // System.out.println(map.getTerrainMatrix()[0][0].getFlux() + " " + MAX_FLUX_PER_TILE + " " +
    // trueCols[0][0].x);

    int k = 0;
    for (int j = 0; j < mapHeight; j++) {
      for (int i = 0; i < mapWidth; i++) {
        colors[k] = trueCols[j][i].x;
        colors[k + 1] = trueCols[j][i].y;
        colors[k + 2] = trueCols[j][i].z;
        colors[k + 3] = trueCols[j][i].w;

        float norm =
            (float)
                Math.sqrt(
                    trueCols[j][i].x * trueCols[j][i].x
                        + trueCols[j][i].y * trueCols[j][i].y
                        + trueCols[j][i].z * trueCols[j][i].z);
        float val = (norm < 0.3f) ? 0.0f : 0.9f;
        colorNorm[k] = val;
        colorNorm[k + 1] = val;
        colorNorm[k + 2] = val;
        colorNorm[k + 3] = 1.0f;
        k += 4;
      }
    }

    if (tex == null && texturePath != null) {
      tex = GLGameRenderer.textureCache.getResource(texturePath, texturePath).tex;
      texturePath = null;
    }
    gl.glPushMatrix();
    //	gl.glTranslatef(1.5f, 0.0f, 1.5f);
    if (tex != null) {
      System.out.println("Using texture");
      gl.glEnable(GL2.GL_TEXTURE_2D);
      tex.bind(gl);
      gl.glBegin(GL2.GL_TRIANGLE_STRIP);
      for (int i = 0; i < indices.length; i++) {
        gl.glTexCoord2f(texCoords[indices[i] * 2], texCoords[indices[i] * 2 + 1]);
        gl.glColor4f(
            colorNorm[indices[i] * 4],
            colorNorm[indices[i] * 4 + 1],
            colorNorm[indices[i] * 4 + 2],
            colorNorm[indices[i] * 4 + 3]);
        gl.glNormal3f(
            normals[indices[i] * 3], normals[indices[i] * 3 + 1], normals[indices[i] * 3 + 2]);
        gl.glVertex3f(
            vertices[indices[i] * 3], vertices[indices[i] * 3 + 1], vertices[indices[i] * 3 + 2]);
      }
      gl.glEnd();
    } else {
      gl.glEnable(gl.GL_BLEND);
      gl.glBegin(GL2.GL_TRIANGLE_STRIP);
      for (int i = 0; i < indices.length; i++) {
        gl.glColor4f(
            colors[indices[i] * 4],
            colors[indices[i] * 4 + 1],
            colors[indices[i] * 4 + 2],
            colors[indices[i] * 4 + 3]);
        gl.glNormal3f(
            normals[indices[i] * 3], normals[indices[i] * 3 + 1], normals[indices[i] * 3 + 2]);
        gl.glVertex3f(
            vertices[indices[i] * 3], vertices[indices[i] * 3 + 1], vertices[indices[i] * 3 + 2]);
      }
      gl.glEnd();
      gl.glDisable(gl.GL_BLEND);
    }
    gl.glPopMatrix();

    boolean showGrid = RenderConfiguration.showGridlines();
    if (showGrid) {
      gl.glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
      gl.glNormal3f(0.0f, 1.0f, 0.0f);
      gl.glLineWidth(1.0f);

      // do the horizontal gridlines
      /*
      gl.glBegin(GL2.GL_LINES);
      for (int j = 1; j < map.getHeight(); ++j) {
      	gl.glVertex3f(0.0f, 0.0f, j);
      	gl.glVertex3f(map.getWidth(), 0.0f, j);
      }
      gl.glEnd();
      */
      gl.glBegin(GL2.GL_LINE_STRIP);
      for (int j = 0; j < mapHeight; j++) {
        if ((j + 1) % DENSITY != 0) {
          continue;
        }
        if ((j + 1) % (DENSITY * 2) == 0) {
          for (int i = 0; i < mapWidth; i++) {
            Vector3f p;
            Vector3f pOne;
            Vector3f pTwo;

            pOne = points[j][i];
            p = new Vector3f(0.0f, 0.0f, 0.0f);
            p.add(pOne);
            if (j < mapHeight - 1 && i > 0) {
              pTwo = points[j + 1][i - 1];
              p.add(pTwo);
              p.scale(.5f);
            }

            gl.glVertex3f(p.x, p.y + 0.01f, p.z);

            pOne = points[j][i];
            p = new Vector3f(0.0f, 0.0f, 0.0f);
            p.add(pOne);
            if (j < mapHeight - 1) {
              pTwo = points[j + 1][i];
              p.add(pTwo);
              p.scale(.5f);
            }

            gl.glVertex3f(p.x, p.y + 0.01f, p.z);
          }
        } else {
          for (int i = mapWidth - 1; i >= 0; i--) {
            Vector3f p;
            Vector3f pOne;
            Vector3f pTwo;

            pOne = points[j][i];
            p = new Vector3f(0.0f, 0.0f, 0.0f);
            p.add(pOne);
            if (j < mapHeight - 1) {
              pTwo = points[j + 1][i];
              p.add(pTwo);
              p.scale(.5f);
            }

            gl.glVertex3f(p.x, p.y + 0.01f, p.z);
            pOne = points[j][i];
            p = new Vector3f(0.0f, 0.0f, 0.0f);
            p.add(pOne);
            if (j < mapHeight - 1 && i > 0) {

              pTwo = points[j + 1][i - 1];
              p.add(pTwo);
              p.scale(.5f);
            }

            gl.glVertex3f(p.x, p.y + 0.01f, p.z);
          }
        }
      }
      gl.glEnd();

      // do the vertical gridlines
      /*
      gl.glBegin(GL2.GL_LINES);
      for (int j = 1; j < map.getWidth(); ++j) {
      	gl.glVertex3f(j, 0.0f, 0.0f);
      	gl.glVertex3f(j, 0.0f, map.getHeight());
      }
      gl.glEnd();
      */
      gl.glBegin(GL2.GL_LINE_STRIP);
      for (int i = 0; i < mapWidth; i++) {
        if ((i + 1) % DENSITY != 0) {
          continue;
        }
        if ((i + 1) % (DENSITY * 2) == 0) {
          for (int j = 0; j < mapHeight; j++) {
            Vector3f p;
            Vector3f pOne;
            Vector3f pTwo;

            pOne = points[j][i];
            p = new Vector3f(0.0f, 0.0f, 0.0f);
            p.add(pOne);
            if (j > 0 && i < mapWidth - 1) {
              pTwo = points[j - 1][i + 1];
              p.add(pTwo);
              p.scale(.5f);
            }

            gl.glVertex3f(p.x, p.y + 0.01f, p.z);

            pOne = points[j][i];
            p = new Vector3f(0.0f, 0.0f, 0.0f);
            p.add(pOne);
            if (i < mapWidth - 1) {
              pTwo = points[j][i + 1];
              p.add(pTwo);
              p.scale(.5f);
            }

            gl.glVertex3f(p.x, p.y + 0.01f, p.z);
          }
        } else {
          for (int j = mapHeight - 1; j >= 0; j--) {
            Vector3f p;
            Vector3f pOne;
            Vector3f pTwo;

            pOne = points[j][i];
            p = new Vector3f(0.0f, 0.0f, 0.0f);
            p.add(pOne);
            if (i < mapWidth - 1) {
              pTwo = points[j][i + 1];
              p.add(pTwo);
              p.scale(.5f);
            }

            gl.glVertex3f(p.x, p.y + 0.01f, p.z);

            pOne = points[j][i];
            p = new Vector3f(0.0f, 0.0f, 0.0f);
            p.add(pOne);
            if (j > 0 && i < mapWidth - 1) {
              pTwo = points[j - 1][i + 1];
              p.add(pTwo);
              p.scale(.5f);
            }

            gl.glVertex3f(p.x, p.y + 0.01f, p.z);
          }
        }
      }
      gl.glEnd();
    }
  }