public HashMap<String, UpdatedTerrainPatch> call() throws Exception {
      // long start = System.currentTimeMillis();
      // if (isLodCalcRunning()) {
      //    return null;
      // }
      setLodCalcRunning(true);

      TerrainQuad terrainQuad = (TerrainQuad) getSpatial();

      // go through each patch and calculate its LOD based on camera distance
      HashMap<String, UpdatedTerrainPatch> updated = new HashMap<String, UpdatedTerrainPatch>();
      boolean lodChanged =
          terrainQuad.calculateLod(
              camLocations, updated, lodCalculator); // 'updated' gets populated here

      if (!lodChanged) {
        // not worth updating anything else since no one's LOD changed
        setLodCalcRunning(false);
        return null;
      }

      // then calculate its neighbour LOD values for seaming in the shader
      terrainQuad.findNeighboursLod(updated);

      terrainQuad.fixEdges(updated); // 'updated' can get added to here

      terrainQuad.reIndexPages(updated, lodCalculator.usesVariableLod());

      // setUpdateQuadLODs(updated); // set back to main ogl thread

      setLodCalcRunning(false);

      return updated;
    }
 protected void prepareTerrain() {
   TerrainQuad terrain = (TerrainQuad) getSpatial();
   terrain
       .cacheTerrainTransforms(); // cache the terrain's world transforms so they can be accessed
   // on the separate thread safely
 }