public void ExportData() { Config config = this.GetConfig(); Export export = new Export(); export.width.Maximum = this.heightData.Width; export.width.Value = this.heightData.Width; export.height.Maximum = this.heightData.Height; export.height.Value = this.heightData.Height; if (config.exportRescaleMode) { export.subzeroMode2.Checked = true; } if (export.ShowDialog() == System.Windows.Forms.DialogResult.OK) { if (this.FileDialog(this.exportHeightmapDialog, ref config.lastExportedFile)) { string path = this.exportHeightmapDialog.FileName; string ext = path.Substring(path.LastIndexOf('.'), path.Length - path.LastIndexOf('.')).ToLower(); //config.lastExportedFile = path; config.exportRescaleMode = export.subzeroMode2.Checked; HeightData toExport = Main.GetResizedHeightData(this.heightData, (int)export.width.Value, (int)export.height.Value); // rescale the values if necessary if (ext != ".shd" && export.subzeroMode2.Checked) { Main.ScaleHeightValues(ref toExport, 0, short.MaxValue - 1); } if (ext == ".shd") { System.IO.BinaryWriter writer = new System.IO.BinaryWriter(System.IO.File.Open(path, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write)); writer.Write(toExport.Width); writer.Write(toExport.Height); for (int i = 0; i < toExport.Length; i++) { writer.Write(toExport[i]); } writer.Close(); } else { Main.HeightDataToBitmap(toExport).Save(path); } toExport.Dispose(); } } }
public void ReturnHandler(object sender, MapReturnedEventArgs e) { Config config = Main.Get().GetConfig(); HeightData data = Main.GetResizedHeightData(e.HeightMap, Math.Min(e.HeightMap.Width, (int)config.mapDetailLevel), Math.Min(e.HeightMap.Height, (int)config.mapDetailLevel)); e.HeightMap.Dispose(); Main.StretchHeightValues(ref data); if (this.maps.Contains(e.Label)) { this.WriteToConsole("Warning: Map with label \"" + e.Label + "\" was returned more than once!"); this.maps[e.Label] = data; } else { this.maps.Add(e.Label, data); } }
public void ExecuteScript(string script, bool syntaxCheckOnly, uint[] parameters) { // kill current syntax check in progress (if any is running) if (this.IsGGenRunning() && mode == Mode.SyntaxCheck && syntaxCheckOnly == false) { // wait for the syntax check to finish (it usually takes just milliseconds) this.GGenThread.Join(); // do the check one the requested script is finished this.ScheduleSyntaxCheck(); } // syntax checks are not allowed while a script is being executed else if (this.IsGGenRunning() && syntaxCheckOnly == true) { // do the check one the requested script is finished if (!this.isCheckScheduled) { this.ScheduleSyntaxCheck(); } return; } // having two generators running at once shouldn't happen else if (this.IsGGenRunning() && mode == Mode.Standard) { throw new Exception("Two GeoGens can't possibly be running at one time"); } if (!syntaxCheckOnly) { this.mode = Mode.Standard; this.ButtonsRunMode(); this.AddStatus("Executing"); this.ClearData(); this.WriteToConsole("Starting at " + DateTime.Now.ToString("HH:mm:ss") + "..."); } else { this.mode = Mode.SyntaxCheck; this.lastCheckContent = ""; this.AddStatus("Checking syntax"); } System.Threading.ThreadStart starter = new System.Threading.ThreadStart(delegate { try { try { ggen.SetScript(script); } catch (SyntaxErrorException) { this.MapGenerationFailed("Compilation failed!"); return; } try { ggen.LoadArgs(); } catch (ArgsUnreadableException) { this.MapGenerationFailed("Map header is unreadable!"); return; } // do not generate the map during syntax check runs if (!syntaxCheckOnly) { // no list of arguments was passed to the function -> use params from the param table if (parameters == null) { var zipped = this.parameters.Item.Cast <PropertyGridEx.CustomProperty>().Zip(ggen.Args, (Property, Arg) => new { Property, Arg }); foreach (var item in zipped) { // fill in only matching arguments if (item.Property.Type.Name == "Boolean" && item.Arg.Type == ScriptArgType.Bool) { item.Arg.Value = (uint)item.Property.Value; } else if (item.Property.Type.Name == "UInt32" && item.Arg.Type == ScriptArgType.Int) { item.Arg.Value = (uint)item.Property.Value; } else if (item.Property.Type.Name == "Int32" && item.Arg.Type == ScriptArgType.Int) { item.Arg.Value = (uint)((int)item.Property.Value); } else if (item.Property.Type.Name == "String" && item.Arg.Type == ScriptArgType.Enum) { item.Arg.Value = (uint)item.Property.Choices.IndexOf(item.Property.Value); } } /*int i = 0; * foreach (PropertyGridEx.CustomProperty property in this.parameters.Item) * { * * * Generator.ScriptArg arg = ggen.Args[i]; * * // we ran out of parameters... * if (i == ggen.Args.Count()) * { * break; * } * * // fill in only matching arguments * if (property.Type.Name == "Boolean" && arg.Type == ScriptArgType.Bool) * { * arg.Value = (uint)property.Value; * } * * else if (property.Type.Name == "UInt32" && arg.Type == ScriptArgType.Int) * { * arg.Value = (uint)property.Value; * } * else if (property.Type.Name == "Int32" && arg.Type == ScriptArgType.Int) * { * arg.Value = (uint)((int)property.Value); * } * else if (property.Type.Name == "String" && arg.Type == ScriptArgType.Enum) * { * arg.Value = (uint)property.Choices.IndexOf(property.Value); * } * * i++; * }*/ } // the argument list was passed to the function else { var zipped = parameters.Zip(ggen.Args, (Param, Arg) => new { Param, Arg }); foreach (var item in zipped) { item.Arg.Value = item.Param; } /*int i = 0; * foreach (uint currentParam in parameters) * { * Generator.ScriptArg arg = ggen.Args[i]; * * // we ran out of parameters... * if (i == ggen.Args.Length) * { * break; * } * * arg.Value = currentParam; * * i++; * }*/ } this.startTime = System.DateTime.Now.Ticks / 10000; HeightData result; try { if (this.config.seed == 0) { ggen.Seed = (uint)DateTime.Now.Ticks; } else { ggen.Seed = this.config.seed; } result = ggen.Generate(); } catch (GenerationFailedException) { this.MapGenerationFailed("Map generation failed!"); return; } catch (ExceptionInCallbackException e) { // the thread was aborted if (e.InnerException is ThreadAbortException) { this.ggen.Reset(); this.BeginInvoke(new MethodInvoker(delegate() { this.MapGenerationFailed("Aborted!"); })); return; } // else unknown exception, we want to debug this case throw; } // map was generated successfully HeightData result2 = Main.GetResizedHeightData(result, Math.Min(result.Width, (int)config.mapDetailLevel), Math.Min(result.Height, (int)config.mapDetailLevel)); result.Dispose(); Main.StretchHeightValues(ref result2); maps.Add("[Main]", result2); this.RemoveStatus("Executing"); this.Invoke(new MethodInvoker(delegate() { // was this part of a benchmark? if (benchmarkStatus != null) { this.Benchmark(); return; } this.ReloadMaps(null); this.WriteToConsole("Finished after " + Math.Round((System.DateTime.Now.Ticks / 10000 - this.startTime) / 1000d, 3) + " seconds!" + Environment.NewLine); this.ButtonsNoRunMode(); })); } else { this.Invoke(new MethodInvoker(delegate() { this.RebuildArgsTable(); this.SetErrorStatus(false); })); } } catch (InternalErrorException e) { this.WriteToConsole("Error: " + e.InnerException.Message); this.MapGenerationFailed("GeoGen has unexpectedly crashed!"); } finally { this.BeginInvoke(new MethodInvoker(delegate() { this.RemoveStatus("Executing"); this.RemoveStatus("Checking syntax"); this.ExecuteScheduledCheck(); })); } }); GGenThread = new System.Threading.Thread(starter); GGenThread.Start(); }
public static HeightData LoadHeightmapFromImageFile(string path) { Config config = Main.Get().GetConfig(); HeightData heights; string ext = path.Substring(path.LastIndexOf('.'), path.Length - path.LastIndexOf('.')).ToLower(); if (ext == ".shd") { // byte-by-byte binary reading System.IO.BinaryReader reader = new System.IO.BinaryReader(System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read)); // read first eight bytes with map dimensions int width = reader.ReadInt32(); int height = reader.ReadInt32(); heights = new HeightData((UInt16)width, (UInt16)height); // read the double bytes containing the height data for (int i = 0; i < width * height; i++) { heights[i] = reader.ReadInt16(); } reader.Close(); reader.Dispose(); } else { // read the bitmap file System.Drawing.Bitmap bitmap; try { bitmap = new System.Drawing.Bitmap(path); } catch (ArgumentException) { return(null); } System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height); System.Drawing.Imaging.BitmapData data = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat); heights = new HeightData((UInt16)bitmap.Width, (UInt16)bitmap.Height); // prepare memory space for the color data byte[] bytes = new byte[data.Stride * bitmap.Height]; int pixelSize = data.Stride / data.Width; // get a pointer to the to first line (=first pixel) IntPtr ptr = data.Scan0; // create a byte copy of the heightmap data System.Runtime.InteropServices.Marshal.Copy(ptr, bytes, 0, data.Stride * bitmap.Height); // create the color data for (int i = 0; i < bytes.Length; i += pixelSize) { heights[i / pixelSize] = (short)((short)bytes[i] * 128); } bitmap.UnlockBits(data); bitmap.Dispose(); } HeightData heights2 = Main.GetResizedHeightData(heights, Math.Min(heights.Width, (int)config.mapDetailLevel), Math.Min(heights.Height, (int)config.mapDetailLevel)); return(heights2); }
public void SetTerrain(HeightData original){ Config config = this.GetConfig(); try { // store original's size int originalHeight = original.Height; int originalWidth = original.Width; // load the overlay pattern //System.Drawing.Bitmap overlayBitmap = new System.Drawing.Bitmap("../overlays/Topographic.bmp"); // prepare memory space for the newly created color data this.heightData = Main.GetResizedHeightData(original, Math.Min(original.Width, (int)config.ModelDetailLevel), Math.Min(original.Height, (int)config.ModelDetailLevel)); this.textureBase = Main.GetResizedHeightData(original, Math.Min(original.Width, (int)config.TextureDetailLevel), Math.Min(original.Height, (int)config.TextureDetailLevel)); // release some memory (to prevent OutOfMemory exception) // original = null; // dimension multipliers float fWidth = 100f / (float)this.heightData.Width; float fHeight = 100f / (float)this.heightData.Height; float texFWidth = fWidth; float texFHeight = fHeight; float offsetX = 0; float offsetY = 0; // adjust the multipliers for non-square bitmaps if (originalHeight > originalWidth) { offsetY = (float)((float)(this.heightData.Height - this.heightData.Width) * 100f / (float)this.heightData.Height) / 2f; fWidth *= (float)originalWidth / (float)originalHeight; } else if (originalHeight < originalWidth) { offsetY = (float)((float)(this.heightData.Width - this.heightData.Height) * 100f / (float)this.heightData.Width) / 2f; fHeight *= (float)originalHeight / (float)originalWidth; } // the vertex array for the model Vertex[] vertices = new Vertex[this.heightData.Length ]; // fill in vertex data (only position and texcoords for now) for (int y = 0; y < this.heightData.Height; y++) { float fy = (float)y; // precalculate some stuff that stays constant for whole row float yPos = offsetY + (fy + 0.5f) * fHeight; float texYPos = (fy + 0.5f) * texFHeight; for (int x = 0; x < this.heightData.Width; x++) { float fx = (float)x; int vertexIndex = x + y * this.heightData.Width; vertices[vertexIndex].Position.X = offsetX + fx * fWidth; vertices[vertexIndex].Position.Y = yPos; vertices[vertexIndex].Position.Z = (float)((float)this.heightData[x, y] * 0.005f / 128f); if (!this.config.enableTerrainUnderZero && vertices[vertexIndex].Position.Z < 0) vertices[vertexIndex].Position.Z = 0; vertices[vertexIndex].TexCoord.X = (fx + 0.5f) * texFWidth / 100f; vertices[vertexIndex].TexCoord.Y = texYPos / 100f; } } uint[] indices = new uint[this.heightData.Length * 6]; // build index array for (int y = 0; y < this.heightData.Height - 1; y++) { for (int x = 0; x < this.heightData.Width - 1; x++) { float fx = (float)x; int vertexIndex = (x + y * this.heightData.Width) * 6; // first triangle indices[vertexIndex] = (uint)(x + y * this.heightData.Width); indices[vertexIndex + 1] = (uint)(x + 1 + y * this.heightData.Width); indices[vertexIndex + 2] = (uint)(x + (y + 1) * this.heightData.Width); // second triangle indices[vertexIndex + 3] = (uint)(x + 1 + (y + 1) * this.heightData.Width); indices[vertexIndex + 4] = (uint)(x + (y + 1) * this.heightData.Width); indices[vertexIndex + 5] = (uint)(x + 1 + y * this.heightData.Width); } } // build face normals Vector3[] faceNormals = new Vector3[(this.heightData.Width - 1) * (this.heightData.Height - 1) * 2]; for (int y = 0; y < this.heightData.Height - 1; y++) { for (int x = 0; x < this.heightData.Width - 1; x++) { faceNormals[(x + y * (this.heightData.Width - 1)) * 2] = this.CalculateNormal(vertices[x + (y + 1) * this.heightData.Width].Position, vertices[x + y * this.heightData.Width].Position, vertices[(x + 1) + y * this.heightData.Width].Position); faceNormals[(x + y * (this.heightData.Width - 1)) * 2 + 1] = this.CalculateNormal(vertices[x + (y + 1) * this.heightData.Width].Position, vertices[x + y * this.heightData.Width].Position, vertices[(x + 1) + (y + 1) * this.heightData.Width].Position); } } // build vertex normals for (int y = 0; y < this.heightData.Height; y++) { for (int x = 0; x < this.heightData.Width; x++) { int faceCount = 0; // upper left triangle if (x > 0 && y > 0) { vertices[x + y * this.heightData.Width].Normal = faceNormals[((x - 1) + (y - 1) * (this.heightData.Width - 1)) * 2 + 1] ; faceCount++; } // bottom left triangles if (x > 0 && y < this.heightData.Height - 1) { vertices[x + y * this.heightData.Width].Normal += faceNormals[((x - 1) + y * (this.heightData.Width - 1)) * 2]; vertices[x + y * this.heightData.Width].Normal += faceNormals[((x - 1) + y * (this.heightData.Width - 1)) * 2 + 1]; faceCount += 2; } // upper right triangles if (x < this.heightData.Width - 1 && y > 0) { vertices[x + y * this.heightData.Width].Normal += faceNormals[(x + (y - 1) * (this.heightData.Width - 1)) * 2]; vertices[x + y * this.heightData.Width].Normal += faceNormals[(x + (y - 1) * (this.heightData.Width - 1)) * 2 + 1]; faceCount += 2; } if (x < this.heightData.Width - 1 && y < this.heightData.Height - 1) { vertices[x + y * this.heightData.Width].Normal += faceNormals[(x + y * (this.heightData.Width - 1)) * 2]; faceCount++; } vertices[x + y * this.heightData.Width].Normal /= faceCount; } } // release the context from the GUI thread this.Invoke(new System.Windows.Forms.MethodInvoker(delegate() { viewport.Context.MakeCurrent(null); })); // grab the context for this thread viewport.MakeCurrent(); // delete the previous buffer content if (this.vertexBufferHandle != 0) { GL.DeleteBuffers(1, ref this.vertexBufferHandle); } // allocate the buffer GL.GenBuffers(1, out this.vertexBufferHandle); GL.GenBuffers(1, out this.indexBufferHandle); // tell that we are using that buffer GL.BindBuffer(BufferTarget.ArrayBuffer, this.vertexBufferHandle); GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * 8 * sizeof(float)), vertices, BufferUsageHint.StaticDraw); GL.BindBuffer(BufferTarget.ElementArrayBuffer, this.indexBufferHandle); // upload the data into the buffer into GPU GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(uint)), indices, BufferUsageHint.StaticDraw); // make sure the massive vertex array is gone from RAM vertices = null; indices = null; // release the context from current thread viewport.Context.MakeCurrent(null); try { this.Invoke(new System.Windows.Forms.MethodInvoker(delegate() { try { // regrab the context for the GUI thread viewport.MakeCurrent(); // rebuild the texture this.ApplyTexture(); // UI stuff this.Output3dButtonsOn(); this.viewport.Invalidate(); this.HideBuildingModel(); } catch (Exception e) { } })); } // this might throw exceptions in case the main thread was terminated while this thread is running catch (Exception e) { }; } catch (OutOfMemoryException) { try{ this.Invoke(new System.Windows.Forms.MethodInvoker(delegate() { this.HideBuildingModel(); this.OutOfMemory(); })); } catch{ return; }; } }