private void ImportMap(string mapName)
{
Debug.Log ("Importing map from " + m_inputDir + "...");
bool success = true;
DirectoryInfo dirs = new DirectoryInfo(m_inputDir);
GameObject map = new GameObject();
map.name = mapName;
GameObject terrain = new GameObject();
terrain.name = "Ground";
terrain.transform.parent = map.transform;
terrain.layer = LayerMask.NameToLayer("Floor");
GameObject terrainObjects = new GameObject();
terrainObjects.name = "Objects";
terrainObjects.transform.parent = map.transform;
terrainObjects.layer = LayerMask.NameToLayer("MapObjects");
List<RosePatch> patches = new List<RosePatch>();
Dictionary<string, Rect> atlasRectHash = new Dictionary<string, Rect>();
Dictionary<string, Texture2D> atlasTexHash = new Dictionary< string, Texture2D >();
List<Texture2D> textures = new List<Texture2D>();
// Instantiate all patches
foreach(DirectoryInfo dir in dirs.GetDirectories())
{
if(!dir.Name.Contains("."))
{
RosePatch patch = new RosePatch( dir );
patch.Load();
patch.UpdateAtlas( ref atlasRectHash, ref atlasTexHash, ref textures );
patches.Add ( patch );
}
}
// Create a texture atlas from the textures of all patches and populate the rectangles in the hash
// Figure out the required size of the atlas from the number of textures in the atlas
int height, width; // these must be powers of 2 to be compatible with iPhone
if( atlasRectHash.Count <= 16 ) width = height = 4*256;
else if( atlasRectHash.Count <= 32 ) { width = 8*256; height = 4*256; }
else if( atlasRectHash.Count <= 64 ) { width = 8*256; height = 8*256; }
else if( atlasRectHash.Count <= 128 ) { width = 16*256; height = 8*256; }
else if( atlasRectHash.Count <= 256 ) { width = 16*256; height = 16*256; }
else throw new Exception("Number of tiles in terrain is larger than supported by terrain atlas");
Texture2D atlas = new Texture2D(width, height);
// Pack the textures into one texture atlas
Rect[] rects = atlas.PackTextures( textures.ToArray(), 0, Math.Max(width, height) );
atlas.anisoLevel = 11;
Texture2D myAtlas = new Texture2D(width, height);
myAtlas.SetPixels32( atlas.GetPixels32(0), 0);
string atlasPath = "Assets/Terrain/Textures/" + mapName + "_atlas.png";
if( !File.Exists( atlasPath ))
{
FileStream fs = new FileStream( atlasPath, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(myAtlas.EncodeToPNG());
bw.Close();
fs.Close();
AssetDatabase.Refresh();
}
myAtlas = Utils.loadTex(ref atlasPath);
// copy rects back to hash (should update rect refs in Tile objects
int rectID = 0;
foreach( string key in atlasTexHash.Keys)
atlasRectHash[key] = rects[rectID++];
// Generate the patches
foreach(RosePatch patch in patches)
patch.Import(terrain.transform, terrainObjects.transform, myAtlas, myAtlas, atlasRectHash);
//blend vertex normals at the seams between patches
Dictionary<string, List<PatchNormalIndex>> patchNormalLookup = new Dictionary<string, List<PatchNormalIndex>>();
int patchID = 0;
// combine all normal lookups into one big lookup containing patch ID and normal ID
foreach(RosePatch patch in patches)
{
// go through the lookup of this patch and append all normal id's to big lookup
foreach(string vertex in patch.edgeVertexLookup.Keys)
{
List<PatchNormalIndex> ids = new List<PatchNormalIndex>();
foreach(int id in patch.edgeVertexLookup[vertex])
ids.Add(new PatchNormalIndex(patchID, id));
if(!patchNormalLookup.ContainsKey(vertex))
patchNormalLookup.Add(vertex, ids);
else
patchNormalLookup[vertex].AddRange(ids);
}
patchID++;
}
// go through each enttry in the big lookup and calculate avg normal, then assign to corresponding patches
foreach(string vertex in patchNormalLookup.Keys)
{
Vector3 avg = Vector3.zero;
// First pass: calculate average normal
foreach(PatchNormalIndex entry in patchNormalLookup[vertex])
avg += patches[entry.patchID].m_mesh.normals[entry.normalID];
avg.Normalize();
// Second pass: assign new normal to corresponding patches
foreach(PatchNormalIndex entry in patchNormalLookup[vertex])
patches[entry.patchID].m_mesh.normals[entry.normalID] = avg;
}
terrainObjects.transform.localScale = new Vector3(1.0f, 1.0f, -1.0f);
terrainObjects.transform.Rotate (0.0f, -90.0f, 0.0f);
terrainObjects.transform.position = new Vector3(5200.0f, 0.0f, 5200.0f);
if(success)
Debug.Log ("Map Import Complete");
else
Debug.Log ("!Map Import Failed");
}