public async void GenerateTexture(bool boundsChecker, int areaId = -1) //-1 dla wszystkich { if (this.loadingInProgress) { return; } this.loadingInProgress = true; editPanelMainSplitContainer.Panel2.Enabled = false; try { BitmapAreaProcessor bitmapProc = this.bitmapAreaInfo; if (bitmapProc == null) { throw new Exception($"Obiekt przetwarzania mapy bitowej jest NULL!"); } List <int> areaIdsList = (areaId == -1 ? bitmapProc.GetAllAreaIds() : new List <int>() { areaId }); int bmpWidth = this.sourceBitmap.Width; int bmpHeight = this.sourceBitmap.Height; if (bmpWidth < 1 || bmpHeight < 1) { throw new Exception($"odczytano błędne wymiary bitmapy źródłowej [{bmpWidth},{bmpHeight}]!"); } #region Wstępne wypełnianie bitmapy rezultatu - przezroczystość //WSTĘPNE WYPEŁNIANIE BITMAPY REZULTATU UpdateInfo($"Wstępne tworzenie bitmapy rezultatu"); PacketObjMsg transparentBmpPacket = await bitmapProc.GenerateTransparentBitmapTaskStart(bmpWidth, bmpHeight); this.resultBitmap = (Bitmap)transparentBmpPacket.Obj; if (!String.IsNullOrEmpty(transparentBmpPacket.Msg)) { MessageBox.Show(transparentBmpPacket.Msg); } #endregion foreach (int areaIdFromList in areaIdsList) { UpdateInfo($"Generowanie tekstury dla ID strefy [{areaIdFromList}]"); #region Ograniczenia strefy //POBIERANIE OGRANICZEŃ STREFY PacketObjMsg boundingsPacket = await bitmapProc.GetAreaBoundingsTaskStart(areaIdFromList); AreaBoundings areaBoundings = (AreaBoundings)boundingsPacket.Obj; if (!String.IsNullOrEmpty(boundingsPacket.Msg)) { MessageBox.Show(boundingsPacket.Msg); } int areaMinX = areaBoundings.BoundsX.X; int areaMaxX = areaBoundings.BoundsX.Y; int areaMinY = areaBoundings.BoundsY.X; int areaMaxY = areaBoundings.BoundsY.Y; //obiekt, który będzie przechowywał poszerzone ograniczenia strefy w przypadku, w którym rysowanie wyjdzie poza ograniczenia (np. losowe punkty krzywej) AreaBoundings processingAreaBoundings = areaBoundings.Copy(); #endregion #region Test ograniczeń stref //TEST //Brush brush = new SolidBrush(Color.FromArgb(255, 255, 0, 0)); //using (Graphics gr = Graphics.FromImage(this.resultBitmap)) //{ // gr.FillRectangle(brush, areaMinX, areaMinY, (areaMaxX - areaMinX), (areaMaxY - areaMinY)); //} #endregion #region Ustawienia użytkownika //USTAWIENIA UŻYTKOWNIKA DLA STREFY AreaSettings userAreaSettings = this.uiController.GetAreaSettings(areaIdFromList); AreaSettings.HairDrawingDirection hairDirection = userAreaSettings.Direction; AreaSettings.HairCuttingSide hairCuttingSide = userAreaSettings.CuttingSide; int drawingSteps = userAreaSettings.DrawingSteps; int drawingIterations = userAreaSettings.DrawingIterations; decimal iterationLossPercent = userAreaSettings.DrawingStepIterationLossPercent; decimal bezierRandomRangePercent = userAreaSettings.BezierRandomRangePercent; decimal bezierMarginPercent = userAreaSettings.BezierMarginPercent; double cuttingRangePercent = Convert.ToDouble(userAreaSettings.CuttingRangePercent); int bezierPointCount = userAreaSettings.MultiBezierPointCount; if (userAreaSettings.BezierLineType == AreaSettings.BezierType.Quadratic || userAreaSettings.BezierLineType == AreaSettings.BezierType.QuadraticCp) { bezierPointCount = 3; } else if (userAreaSettings.BezierLineType == AreaSettings.BezierType.Cubic) { bezierPointCount = 4; } Point3 backgroundRgbPalette = userAreaSettings.BackgroundRgbPalette; Point3 foregroundRgbPalette = userAreaSettings.ForegroundRgbPalette; bool hairMapDefinesOpacity = userAreaSettings.HairMapDefinesOpacity; bool hairMapDefinesBrightness = userAreaSettings.HairMapDefinesBrightness; #endregion #region Dane wynikowe //DANE WYNIKOWE int iterationLossCount = Convert.ToInt32(drawingIterations * (iterationLossPercent / 100)); int currentIterationCount = drawingIterations; int areaRangeX = areaMaxX - areaMinX; int areaRangeY = areaMaxY - areaMinY; #endregion #region Dane przetwarzane //DANE PRZETWARZANE W PĘTLACH int currentAxisPosition; double stepPercent; double positionPercent; double bezierPositionPercent; PacketObjMsg lineRangePacket; AreaLineRange lineRange; int rangePointFrom; int rangePointTo; int resultPoint; int boundRangeMin; int boundRangeMax; List <Point> hairBezierPoints = new List <Point>(); Point3 currentColorPalette = new Point3(0, 0, 0); int currentR = 0; int currentG = 0; int currentB = 0; bool cutOnStart = false; bool cutOnEnd = false; if (hairDirection == AreaSettings.HairDrawingDirection.TopToBottom || hairDirection == AreaSettings.HairDrawingDirection.LeftToRight) { cutOnStart = (hairCuttingSide == AreaSettings.HairCuttingSide.Beginning || hairCuttingSide == AreaSettings.HairCuttingSide.BothSides); cutOnEnd = (hairCuttingSide == AreaSettings.HairCuttingSide.End || hairCuttingSide == AreaSettings.HairCuttingSide.BothSides); } else if (hairDirection == AreaSettings.HairDrawingDirection.BottomToTop || hairDirection == AreaSettings.HairDrawingDirection.RightToLeft) { cutOnEnd = (hairCuttingSide == AreaSettings.HairCuttingSide.Beginning || hairCuttingSide == AreaSettings.HairCuttingSide.BothSides); cutOnStart = (hairCuttingSide == AreaSettings.HairCuttingSide.End || hairCuttingSide == AreaSettings.HairCuttingSide.BothSides); } #endregion for (int drawingStep = 0; drawingStep < drawingSteps; drawingStep++) //PĘTLA TONÓW - KROKI { if (currentIterationCount <= 0) { break; } stepPercent = DataProcessor.CalculatePercent(Convert.ToDouble(drawingSteps - 1), Convert.ToDouble(drawingStep)); #region Kolor podstawowy (ton) //WYODRĘBNIANIE PODSTAWOWEGO TONU KOLORU currentR = Convert.ToInt32(DataProcessor.Lerp(backgroundRgbPalette.X, foregroundRgbPalette.X, (stepPercent / 100))); currentG = Convert.ToInt32(DataProcessor.Lerp(backgroundRgbPalette.Y, foregroundRgbPalette.Y, (stepPercent / 100))); currentB = Convert.ToInt32(DataProcessor.Lerp(backgroundRgbPalette.Z, foregroundRgbPalette.Z, (stepPercent / 100))); currentR = DataProcessor.Clamp(0, 255, currentR); currentG = DataProcessor.Clamp(0, 255, currentG); currentB = DataProcessor.Clamp(0, 255, currentB); currentColorPalette = new Point3(currentR, currentG, currentB); #endregion for (int drawingIteration = 0; drawingIteration < currentIterationCount; drawingIteration++) //PĘTLA ITERACJI - SZTUK WŁOSA { hairBezierPoints.Clear(); positionPercent = DataProcessor.CalculatePercent(Convert.ToDouble(currentIterationCount - 1), Convert.ToDouble(drawingIteration)); for (int bezierPointIteration = 0; bezierPointIteration < bezierPointCount; bezierPointIteration++) { bezierPositionPercent = DataProcessor.CalculatePercent(Convert.ToDouble(bezierPointCount - 1), Convert.ToDouble(bezierPointIteration)); if (hairDirection == AreaSettings.HairDrawingDirection.TopToBottom || hairDirection == AreaSettings.HairDrawingDirection.BottomToTop) { #region Pionowo currentAxisPosition = Convert.ToInt32(DataProcessor.Lerp(areaMinY, areaMaxY, bezierPositionPercent / 100)); lineRangePacket = await this.bitmapAreaInfo.GetAreaLineRangeTaskStart ( BitmapAreaProcessor.AreaAxis.Y, currentAxisPosition, areaIdFromList ); lineRange = (AreaLineRange)lineRangePacket.Obj; //POBIERANIE PUNKTÓW GRANICZNYCH DLA STREFY rangePointFrom = lineRange.RangePointFrom; rangePointTo = lineRange.RangePointTo; //MODYFIKACJA O MARGINESY rangePointFrom = Convert.ToInt32(rangePointFrom - (rangePointTo - rangePointFrom) * (bezierMarginPercent / 100)); rangePointTo = Convert.ToInt32(rangePointTo + (rangePointTo - rangePointFrom) * (bezierMarginPercent / 100)); if (rangePointFrom < 0) { rangePointFrom = 0; } if (rangePointTo > this.resultBitmap.Width - 1) { rangePointTo = this.resultBitmap.Width - 1; } //WSTĘPNE TWORZENIE PUNKTU WYNIKOWEGO resultPoint = Convert.ToInt32(DataProcessor.Lerp(rangePointFrom, rangePointTo, positionPercent / 100)); //ZAKRES LOSOWANIA / LOSOWANIE PUNKTU boundRangeMin = Convert.ToInt32(resultPoint - ((rangePointTo - rangePointFrom) * (bezierRandomRangePercent / 100))); boundRangeMax = Convert.ToInt32(resultPoint + ((rangePointTo - rangePointFrom) * (bezierRandomRangePercent / 100))); resultPoint = this.random.Next(boundRangeMin, boundRangeMax + 1); resultPoint = DataProcessor.Clamp(0, this.resultBitmap.Width, resultPoint); //PRZYPISYWANIE PUNKTU WYNIKOWEGO hairBezierPoints.Add ( new Point ( resultPoint, currentAxisPosition ) ); #endregion } else if (hairDirection == AreaSettings.HairDrawingDirection.LeftToRight || hairDirection == AreaSettings.HairDrawingDirection.RightToLeft) { #region Poziomo currentAxisPosition = Convert.ToInt32(DataProcessor.Lerp(areaMinX, areaMaxX, bezierPositionPercent / 100)); lineRangePacket = await this.bitmapAreaInfo.GetAreaLineRangeTaskStart ( BitmapAreaProcessor.AreaAxis.X, currentAxisPosition, areaIdFromList ); lineRange = (AreaLineRange)lineRangePacket.Obj; //POBIERANIE PUNKTÓW GRANICZNYCH DLA STREFY rangePointFrom = lineRange.RangePointFrom; rangePointTo = lineRange.RangePointTo; //MODYFIKACJA O MARGINESY rangePointFrom = Convert.ToInt32(rangePointFrom - (rangePointTo - rangePointFrom) * (bezierMarginPercent / 100)); rangePointTo = Convert.ToInt32(rangePointTo + (rangePointTo - rangePointFrom) * (bezierMarginPercent / 100)); if (rangePointFrom < 0) { rangePointFrom = 0; } if (rangePointTo > this.resultBitmap.Height - 1) { rangePointTo = this.resultBitmap.Height - 1; } //WSTĘPNE TWORZENIE PUNKTU WYNIKOWEGO resultPoint = Convert.ToInt32(DataProcessor.Lerp(rangePointFrom, rangePointTo, positionPercent / 100)); //ZAKRES LOSOWANIA / LOSOWANIE PUNKTU boundRangeMin = Convert.ToInt32(resultPoint - ((rangePointTo - rangePointFrom) * (bezierRandomRangePercent / 100))); boundRangeMax = Convert.ToInt32(resultPoint + ((rangePointTo - rangePointFrom) * (bezierRandomRangePercent / 100))); resultPoint = this.random.Next(boundRangeMin, boundRangeMax + 1); resultPoint = DataProcessor.Clamp(0, this.resultBitmap.Height, resultPoint); //PRZYPISYWANIE PUNKTU WYNIKOWEGO hairBezierPoints.Add ( new Point ( currentAxisPosition, resultPoint ) ); #endregion } else if (hairDirection == AreaSettings.HairDrawingDirection.Radial) { } else if (hairDirection == AreaSettings.HairDrawingDirection.LinearX) { } else if (hairDirection == AreaSettings.HairDrawingDirection.LinearY) { } } //RYSOWANIE BitmapAreaProcessor.DrawBezierLineOnBitmap ( hairBezierPoints, this.resultBitmap, (userAreaSettings.BezierLineType == AreaSettings.BezierType.QuadraticCp), 0.02, currentColorPalette, cutOnStart, cutOnEnd, cuttingRangePercent, ref processingAreaBoundings ); //POSZERZANIE GRANIC STREFY - DLA PRZETWARZANIA PRZEZROCZYSTOŚCI / POŁYSKU //processingAreaBoundings.ExtendAreaBoundings(hairBezierPoints, this.resultBitmap.Width - 1, this.resultBitmap.Height - 1); } currentIterationCount -= iterationLossCount; } //PRZEZROCZYSTOŚĆ / POŁYSK BitmapAreaProcessor.AreaAxis glossOpacAxis = BitmapAreaProcessor.AreaAxis.None; if (hairDirection == AreaSettings.HairDrawingDirection.TopToBottom || hairDirection == AreaSettings.HairDrawingDirection.BottomToTop) { glossOpacAxis = BitmapAreaProcessor.AreaAxis.X; } else if (hairDirection == AreaSettings.HairDrawingDirection.LeftToRight || hairDirection == AreaSettings.HairDrawingDirection.RightToLeft) { glossOpacAxis = BitmapAreaProcessor.AreaAxis.Y; } PacketObjMsg glossOpacityPacket = await bitmapProc.GenerateHairTexGlossinessAndOpacityTaskStart ( processingAreaBoundings, //areaBoundings, this.resultBitmap, Color.FromArgb(255, backgroundRgbPalette.X, backgroundRgbPalette.Y, backgroundRgbPalette.Z), hairMapDefinesBrightness, hairMapDefinesOpacity, //new double[] { Convert.ToDouble(bezierMarginPercent / 100), Convert.ToDouble(bezierRandomRangePercent / 100) }, //glossOpacAxis boundsChecker ); this.resultBitmap = (Bitmap)glossOpacityPacket.Obj; if (!String.IsNullOrEmpty(glossOpacityPacket.Msg)) { MessageBox.Show(glossOpacityPacket.Msg); } } //WYŚWIETLANIE OBRAZU REZULTATU SetPreview(PreviewType.Result, this.resultBitmap); } catch (Exception exception) { MessageBox.Show($"Błąd generowania tekstury: {exception.Message}"); } UpdateInfo(""); editPanelMainSplitContainer.Panel2.Enabled = true; this.loadingInProgress = false; }