public BitmapSource Shadow(GradientDef gradient) { if (gradient == null) return null; if (pixelData == null) return null; double cosAzimuth = Math.Cos(azimuth * 0.0174532925); double sinAzimuth = Math.Sin(azimuth * 0.0174532925); double cosElev = Math.Cos(elevation * 0.0174532925); double sinElev = Math.Sin(elevation * 0.0174532925); // draw the pixels scaled to color range - we need to know min max double xInc = (double)Boundary.Object.W / (double)width; double yInc = (double)Boundary.Object.H / (double)height; double x = Boundary.Object.X; double y = Boundary.Object.Y; System.Windows.Media.PixelFormat pf = System.Windows.Media.PixelFormats.Rgb24; int rawStride = width * 3; Color c = new Color(); // n is the index into noiseData // i,j are indexes into the bitmap data - range of the widow size // x,y are indexes into the noise module to get the value - range of teh bounds // int n = 0; for (int j = 0; j < height; ++j) { int yIndex = j * rawStride; int ii = 0; for (int i = 0; i < rawStride; i += 3) { // Calculate the positions of the current point's four-neighbors. int xLeftOffset, xRightOffset; int yUpOffset, yDownOffset; { if (ii == 0) { xLeftOffset = 0; xRightOffset = 1; } else if (ii == (int)width - 1) { xLeftOffset = -1; xRightOffset = 0; } else { xLeftOffset = -1; xRightOffset = 1; } if (j == 0) { yDownOffset = 0; yUpOffset = 1; } else if (j == (int)height - 1) { yDownOffset = -1; yUpOffset = 0; } else { yDownOffset = -1; yUpOffset = 1; } } yDownOffset *= width; yUpOffset *= width; // Get the noise value of the current point in the source noise map // and the noise values of its four-neighbors. double nc = noiseData[j * width + ii]; double nl = noiseData[j * width + ii + xLeftOffset]; double nr = noiseData[j * width + ii + xRightOffset]; double nd = noiseData[j * width + ii + yDownOffset]; double nu = noiseData[j * width + ii + yUpOffset]; if (mNormal) { nc = (nc - min) / (max - min); nl = (nl - min) / (max - min); nr = (nr - min) / (max - min); nd = (nd - min) / (max - min); nu = (nu - min) / (max - min); } // Now do the lighting calculations. double lightIntensity; { double io = 1.0 * 1.41421356 * sinElev / 2.0; double ix = (1.0 - io) * contrast * 1.41421356 * cosElev * cosAzimuth; double iy = (1.0 - io) * contrast * 1.41421356 * cosElev * sinAzimuth; lightIntensity = (ix * (nl - nr) + iy * (nd - nu) + io); if (lightIntensity < 0.0) { lightIntensity = 0.0; } lightIntensity *= intensity; } gradient.GetColor(nc, ref c); pixelData[i + yIndex] = (byte)NMath.ClampValue((int)(c.R * lightIntensity), 0, 255); pixelData[i + yIndex + 1] = (byte)NMath.ClampValue((int)(c.G * lightIntensity), 0, 255); pixelData[i + yIndex + 2] = (byte)NMath.ClampValue((int)(c.B * lightIntensity), 0, 255); x += xInc; ii += 1; } y += yInc; x = Boundary.Object.X; } BitmapSource bitmap = null; if (noDispatch) bitmap = BitmapSource.Create(width, height, 96, 96, pf, null, pixelData, rawStride); else Application.Current.Dispatcher.Invoke((Action)(() => { bitmap = BitmapSource.Create(width, height, 96, 96, pf, null, pixelData, rawStride); })); return bitmap; }
public BitmapSource Render(Adapter noise, GradientDef gradient, bool redraw = false) { if (noise == null) return null; if (gradient == null) return null; if (pixelData == null) return null; // draw the pixels scaled to color range - we need to know min max double xInc = (double)Boundary.Object.W / (double)width; double yInc = (double)Boundary.Object.H / (double)height; double x = Boundary.Object.X; double y = Boundary.Object.Y; BitmapSource bitmap = null; System.Windows.Media.PixelFormat pf = System.Windows.Media.PixelFormats.Rgb24; int rawStride; rawStride = width * 3; if (!mNormal) { min = 1000000; max = -1000000; } Color c = new Color(); // n is the index into noiseData // i,j are indexes into the bitmap data - range of the widow size // x,y are indexes into the noise module to get the value - range of the bounds int n = 0; for (int j = 0; j < height; ++j) { int yIndex = j * rawStride; for (int i = 0; i < rawStride; i += 3) { double val = 0; if (redraw) val = noiseData[n++]; else { if (mTile) { double swValue, seValue, neValue; swValue = noise.GetValue(x, y); seValue = noise.GetValue(Boundary.Object.W - x, y); neValue = noise.GetValue(x, Boundary.Object.H - y); double mirrorx = (swValue + seValue) / 2; double mirrory = (swValue + neValue) / 2; // lerp between mirror and real double xloc = (x - Boundary.Object.X) / Boundary.Object.W; double yloc = (y - Boundary.Object.Y) / Boundary.Object.H; double factorx = Math.Abs(0.5 - xloc) * 2; double factory = Math.Abs(0.5 - yloc) * 2; if (Math.Abs(factorx - factory) < 0.1) { // calculate how much towards x is it double factor = ((factorx - factory) / 0.1 + 1) / 2; double valx = (mirrorx * factorx + swValue * (1 - factorx)); double valy = (mirrory * factory + swValue * (1 - factory)); val = (valx * factor + valy * (1 - factor)); } else { if (factorx > factory) val = (mirrorx * factorx + swValue * (1 - factorx)); else val = (mirrory * factory + swValue * (1 - factory)); } } else val = noise.GetValue(x, y); noiseData[n++] = val; } if (!mNormal) { if (val < min) min = val; if (val > max) max = val; } if (!mShadow) { if (mNormal) val = (val - min) / (max - min); gradient.GetColor(val, ref c); pixelData[i + yIndex] = c.R; pixelData[i + yIndex + 1] = c.G; pixelData[i + yIndex + 2] = c.B; } x += xInc; } y += yInc; x = Boundary.Object.X; } if (!mShadow) { if (noDispatch) bitmap = BitmapSource.Create(width, height, 96, 96, pf, null, pixelData, rawStride); else Application.Current.Dispatcher.Invoke((Action)(() => { bitmap = BitmapSource.Create(width, height, 96, 96, pf, null, pixelData, rawStride); })); } else bitmap = Shadow(gradient); return bitmap; }