void contractSetValue(ref DAGMask src, ref DAGMask dst) { Point[] neighOffset = new Point[] { new Point(-1, -1), new Point(-1, 0), new Point(-1, 1), new Point(1, -1), new Point(1, 0), new Point(1, 1), new Point(0, -1), new Point(0, 1) }; for (int x = 0; x < src.Width; x++) { for (int y = 0; y < src.Height; y++) { float min = float.MaxValue; for (int i = 0; i < neighOffset.Length; i++) { Point off = neighOffset[i]; if (x + off.X < 0 || x + off.X >= src.Width || y + off.Y < 0 || y + off.Y >= src.Height) { continue; } if (src[x + off.X, y + off.Y] < min) { min = src[x + off.X, y + off.Y]; } } dst[x, y] = min; } } }
public DAGMask execute(int width, int height) { List<int> outputNodes = findIndexesOfNodesOfType(typeof(Device_ToCurrentMask)); if(outputNodes.Count ==0) { MessageBox.Show("Error: Cannot compute graph:\n Missing ToCurrentMask output node", "Cannot execute graph", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } else if (outputNodes.Count > 1) { MessageBox.Show("Error: Cannot compute graph:\n Multiple ToCurrentMask output nodes found.", "Cannot execute graph", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } Device_ToCurrentMask dcm = mNodes[outputNodes[0]] as Device_ToCurrentMask; OutputGenerationParams ogp = new OutputGenerationParams(); ogp.Width = width; ogp.Height = height; if (!dcm.computeOutput(null, ogp)) return null; DAGMask dMask = dcm.ResultMask.Clone(); return dMask; }
public DAGMask Clone() { DAGMask m = new DAGMask(mWidth, mHeight); CopyTo(m); return(m); }
override public bool computeOutput(ConnectionPoint connPoint, OutputGenerationParams parms) { if (!verifyInputConnections()) { return(false); } if (!gatherInputAndParameters(parms)) { return(false); } MaskParam mp = ((MaskParam)(connPoint.ParamType)); mp.Value = InputMask.Clone(); mp.Value.mConstraintMask = ConstraintMask; int numTimesToRun = parms.Width >> 1; DAGMask outMask = InputMask.Clone();// DAGMask distMask = new DAGMask(parms.Width, parms.Height); int maxRange = 0; for (int i = 0; i < numTimesToRun; i++) { DAGMask smallerMask = new DAGMask(parms.Width, parms.Height); bool madeChange = contractSetValue(ref outMask, ref smallerMask, ref distMask, i); outMask = smallerMask.Clone(); if (madeChange) { maxRange = i; } else { break; } } //normalize our input now... for (int x = 0; x < parms.Width; x++) { for (int y = 0; y < parms.Height; y++) { mp.Value[x, y] = distMask[x, y] / (float)maxRange; } } outMask = null; return(true); }
void transferSoil(DAGMask inMask, List <Point> travelPath, int width, int height, ref DAGMask subMask, ref DAGMask addMask, float slopeBiasScalar) { float amtOfSoilInStream = 0; Point currPt = new Point(); Point nxtPt = new Point(); for (int i = 0; i < travelPath.Count - 1; i++) { currPt.X = travelPath[i].X; currPt.Y = travelPath[i].Y; nxtPt.X = travelPath[i + 1].X; nxtPt.Y = travelPath[i + 1].Y; //determine sediment saturation based upon slope^2 float Height = inMask[currPt.X, currPt.Y] - subMask[currPt.X, currPt.Y] + addMask[currPt.X, currPt.Y]; float nHeight = inMask[nxtPt.X, nxtPt.Y] - subMask[nxtPt.X, nxtPt.Y] + addMask[nxtPt.X, nxtPt.Y]; float slope = Height - nHeight; float cDepositThreshold = 0.00390625f;// 1/256 //CLM MAGIC NUMBER if (slope < cDepositThreshold || amtOfSoilInStream > SedimentCarryAmt) { //deposit soil //how much soil should we deposit? float soilAmt = (slope * (1.0f - SoilHardness)); if (amtOfSoilInStream > 0) { amtOfSoilInStream -= soilAmt; addSoil(soilAmt, currPt.X, currPt.Y, ref inMask, ref subMask, ref addMask); } } else { //pickup soil float soilAmt = (slope * (1.0f - SoilHardness)); // CLM MAGIC NUMBER amtOfSoilInStream += soilAmt; removeSoil(soilAmt, currPt.X, currPt.Y, ref inMask, ref subMask, ref addMask); } if (amtOfSoilInStream < 0) { break; } } //do we have soil suspended in the stream? // if (amtOfSoilInStream > 0) // addSoil(amtOfSoilInStream, currPt.X, currPt.Y, ref inMask, ref subMask, ref addMask); }
void calculateErosion(DAGMask inMask, int width, int height, ref DAGMask subMask, ref DAGMask addMask, int amtScalar) { Random rnd = new Random(); Point prevPt = new Point(rnd.Next(width), rnd.Next(width)); for (int passCount = 0; passCount < width * Amount; passCount++) { Point currPt = new Point(rnd.Next(width), rnd.Next(width)); List <Point> travelPath = calculatePath(inMask, width, height, ref subMask, ref addMask, currPt); transferSoil(inMask, travelPath, width, height, ref subMask, ref addMask, 1.0f); } }
public bool writeToFile(string filename, OutputGenerationParams parms) { if (!verifyInputConnections()) { return(false); } DAGMask m = mInputMask.Value; //temp haxor string ext = Path.GetExtension(filename); if (ext == ".r16") { FileStream s = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write); BinaryWriter f = new BinaryWriter(s); for (int x = 0; x < parms.Width; x++) { for (int y = 0; y < parms.Height; y++) { float k = m[x, y]; float scaledk = (k + 1) * 0.5f; ushort v = (ushort)(scaledk * ushort.MaxValue); f.Write(v); } } f.Close(); s.Close(); } else if (ext == ".raw") { FileStream s = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write); BinaryWriter f = new BinaryWriter(s); for (int x = 0; x < parms.Width; x++) { for (int y = 0; y < parms.Height; y++) { float k = m[x, y]; float scaledk = (k + 1) * 0.5f; byte v = (byte)(scaledk * byte.MaxValue); f.Write(v); } } f.Close(); s.Close(); } return(true); }
override public bool computeOutput(ConnectionPoint connPoint, OutputGenerationParams parms) { if (!verifyInputConnections()) { return(false); } gatherInputAndParameters(parms); MaskParam mp = ((MaskParam)(connPoint.ParamType)); // mp.Value = InputMask.Clone(); DAGMask baseMask = InputMask.Clone(); DAGMask addMask = new DAGMask(parms.Width, parms.Height); DAGMask subMask = new DAGMask(parms.Width, parms.Height); //if we're doing multiscale erosion if (MultiscaleEnable) { //subtract multiscale mask from our base mask before doing erosion multiscaleDisplace(ref baseMask, ref subMask, ref addMask); } //CLM it actually looks better (less noisy) w/o this high fidelity step! calculateErosion(baseMask, baseMask.Width, baseMask.Height, ref subMask, ref addMask, 0); //calculate our mask 'channels' for (int x = 0; x < parms.Width; x++) { for (int y = 0; y < parms.Height; y++) { baseMask[x, y] = baseMask[x, y] + addMask[x, y] - subMask[x, y]; } } //need to find which output this connection point is connected to... mp.Value = baseMask.Clone(); return(true); }
public void generatePreview(CanvasNode cn) { OutputGenerationParams ogp = new OutputGenerationParams(); ogp.Width = 128; ogp.Height = 128; MaskDAGGraphNode gn = (MaskDAGGraphNode)cn; MaskParam mp = new MaskParam(); InputConnectionPoint icp = new InputConnectionPoint(mp,true,"Preview",gn,this); gn.computeOutput(icp,ogp); if (onUpdateCallback != null) { DAGMask m = mp.Value; onUpdateCallback(ref m); } }
override public bool computeOutput(ConnectionPoint connPoint, OutputGenerationParams parms) { if (!verifyInputConnections()) { return(false); } if (!gatherInputAndParameters(parms)) { return(false); } MaskParam mp = ((MaskParam)(connPoint.ParamType)); mp.Value = InputMask.Clone(); mp.Value.mConstraintMask = ConstraintMask; DAGMask outMask = InputMask.Clone(); for (int i = 0; i < NumPixels; i++) { DAGMask smallerMask = new DAGMask(parms.Width, parms.Height); contractSetValue(ref outMask, ref smallerMask); outMask = smallerMask.Clone(); } //normalize our input now... for (int x = 0; x < parms.Width; x++) { for (int y = 0; y < parms.Height; y++) { mp.Value[x, y] = outMask[x, y]; } } outMask = null; return(true); }
bool contractSetValue(ref DAGMask src, ref DAGMask dst, ref DAGMask distMask, float valToSet) { Point[] neighOffset = new Point[] { new Point(-1, -1), new Point(-1, 0), new Point(-1, 1), new Point(1, -1), new Point(1, 0), new Point(1, 1), new Point(0, -1), new Point(0, 1) }; bool setVal = false; for (int x = 0; x < src.Width; x++) { for (int y = 0; y < src.Height; y++) { float min = float.MaxValue; for (int i = 0; i < neighOffset.Length; i++) { Point off = neighOffset[i]; if (x + off.X < 0 || x + off.X >= src.Width || y + off.Y < 0 || y + off.Y >= src.Height) { continue; } if (src[x + off.X, y + off.Y] < min) { min = src[x + off.X, y + off.Y]; } } if (min < src[x, y]) { distMask[x, y] = valToSet; setVal = true; } dst[x, y] = min; } } return(setVal); }
void multiscaleDisplace(ref DAGMask baseMask, ref DAGMask subMask, ref DAGMask addMask) { eFilterType type = eFilterType.cFilter_Linear;//eFilterType.cFilter_Nearest;// int level = 4; // int l = level; for (int l = level; l > 0; l--) { //resize to smaller texture DAGMask smallMask = new DAGMask(baseMask.Width >> l, baseMask.Height >> l); resizeF32Img(baseMask, smallMask, baseMask.Width, baseMask.Height, smallMask.Width, smallMask.Height, type); DAGMask addMaskSmall = new DAGMask(smallMask.Width, smallMask.Height); DAGMask subMaskSmall = new DAGMask(smallMask.Width, smallMask.Height); resizeF32Img(addMask, addMaskSmall, addMask.Width, addMask.Height, addMaskSmall.Width, addMaskSmall.Height, type); resizeF32Img(subMask, subMaskSmall, subMask.Width, subMask.Height, subMaskSmall.Width, subMaskSmall.Height, type); //calculate erosion calculateErosion(smallMask, smallMask.Width, smallMask.Height, ref subMaskSmall, ref addMaskSmall, l); //move back DAGMask addMaskBig = new DAGMask(baseMask.Width, baseMask.Height); DAGMask subMaskBig = new DAGMask(baseMask.Width, baseMask.Height); resizeF32Img(addMaskSmall, addMaskBig, addMaskSmall.Width, addMaskSmall.Height, addMask.Width, addMask.Height, type); resizeF32Img(subMaskSmall, subMaskBig, subMaskSmall.Width, subMaskSmall.Height, subMask.Width, subMask.Height, type); DAGMask smallMaskBig = new DAGMask(baseMask.Width, baseMask.Height); resizeF32Img(smallMask, smallMaskBig, smallMask.Width, smallMask.Height, smallMaskBig.Width, smallMaskBig.Height, type); for (int x = 0; x < baseMask.Width; x++) { for (int y = 0; y < baseMask.Height; y++) { // baseMask[x, y] = smallMaskBig[x, y]; addMask[x, y] = addMaskBig[x, y]; subMask[x, y] = subMaskBig[x, y]; } } } }
public bool loadAndExecute() { if (mGraphMemoryStream == null) { return(false); } mGraphMemoryStream.Seek(0, SeekOrigin.Begin); int tWidth = CoreGlobals.getEditorMain().mITerrainShared.getNumXVerts(); int tHeight = CoreGlobals.getEditorMain().mITerrainShared.getNumXVerts(); DAGCanvas dg = new DAGCanvas(512, 512); dg.loadCanvasFromMemoryStream(mGraphMemoryStream); DAGMask resMask = dg.execute(tWidth, tHeight); if (resMask == null) { MessageBox.Show("There was an error computing Mask"); return(false); } mOutputMask = new ArrayBasedMask(mCapacity); for (int x = 0; x < tWidth; x++) { for (int y = 0; y < tHeight; y++) { mOutputMask.SetMaskWeight(x * tWidth + y, resMask[x, y]); } } dg.newCanvas(); dg = null; mGraphMemoryStream.Seek(0, SeekOrigin.Begin); return(true); }
void removeSoil(float soilAmt, int x, int y, ref DAGMask inMask, ref DAGMask subMask, ref DAGMask addMask) { //for visual clairty, make this a 2x2 subMask[x, y] += soilAmt; float hlfSol = soilAmt * 0.5f; if (y - 1 > 0) { subMask[x, y - 1] += hlfSol; } if (x - 1 > 0) { subMask[x - 1, y] += hlfSol; } if (y + 1 < inMask.Height) { subMask[x, y + 1] += hlfSol; } if (x + 1 < inMask.Width) { subMask[x + 1, y] += hlfSol; } }
static public void resizeF32Img(DAGMask inputTexture, DAGMask outputTexture, int inputWidth, int inputHeight, int newWidth, int newHeight, eFilterType method) { if (outputTexture == null) { outputTexture = new DAGMask(newWidth, newHeight); } if (inputWidth == newWidth && inputHeight == newHeight) { outputTexture = inputTexture.Clone(); return; } float xFactor = (float)inputWidth / newWidth; float yFactor = (float)inputHeight / newHeight; int dstOffset = inputWidth - newWidth; //create a new texture of new size switch (method) { case eFilterType.cFilter_Nearest: { int ox, oy; // for each line for (int y = 0; y < newHeight; y++) { // Y coordinate of the nearest point oy = (int)(y * yFactor); // for each pixel for (int x = 0; x < newWidth; x++) { // X coordinate of the nearest point ox = (int)(x * xFactor); int srcIndex = oy * inputWidth + ox; outputTexture[x, y] = inputTexture[ox, oy]; } // dstIndex += dstOffset; } break; } case eFilterType.cFilter_Linear: { float ox, oy, dx1, dy1, dx2, dy2; int ox1, oy1, ox2, oy2; int ymax = inputHeight - 1; int xmax = inputWidth - 1; float v1, v2; // for each line for (int y = 0; y < newHeight; y++) { // Y coordinates oy = (float)y * yFactor; oy1 = (int)oy; oy2 = (oy1 == ymax) ? oy1 : oy1 + 1; dy1 = oy - (float)oy1; dy2 = 1.0f - dy1; // for each pixel for (int x = 0; x < newWidth; x++) { // X coordinates ox = (float)x * xFactor; ox1 = (int)ox; ox2 = (ox1 == xmax) ? ox1 : ox1 + 1; dx1 = ox - (float)ox1; dx2 = 1.0f - dx1; // interpolate using 4 points { v1 = (float)(dx2 * (inputTexture[ox1, oy1]) + dx1 * (inputTexture[ox2, oy1])); v2 = (float)(dx2 * (inputTexture[ox1, oy2]) + dx1 * (inputTexture[ox2, oy2])); outputTexture[x, y] = (float)(dy2 * v1 + dy1 * v2); } } // dstIndex += dstOffset; } break; } } ; }
override public bool computeOutput(ConnectionPoint connPoint, OutputGenerationParams parms) { if (!verifyInputConnections()) { return(false); } if (!gatherInputAndParameters(parms)) { return(false); } MaskParam mp = ((MaskParam)(connPoint.ParamType)); mp.Value = InputMask.Clone(); mp.Value.mConstraintMask = ConstraintMask; int r = Radius; int[] w = CreateGaussianBlurRow(r); int wlen = w.Length; DAGMask tmpMask = new DAGMask(parms.Width, parms.Height); { float[] waSums = new float[wlen]; float[] wcSums = new float[wlen]; float[] aSums = new float[wlen]; for (int y = 0; y < parms.Height; ++y) { float waSum = 0; float wcSum = 0; float aSum = 0; int dstx = 0; for (int wx = 0; wx < wlen; ++wx) { int srcX = wx - r; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; if (srcX >= 0 && srcX < parms.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < parms.Height) { float c = InputMask[srcX, srcY]; float wp = w[wy]; waSums[wx] += wp; wp *= c;// +(c >> 7); wcSums[wx] += wp; //wp >>= 8; aSums[wx] += wp * c; } } int wwx = w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; } } // wcSum >>= 8; if (waSum == 0 || wcSum == 0) { tmpMask[dstx, y] = 0; } else { tmpMask[dstx, y] = aSum / waSum; } ++dstx; for (int x = 1; x < parms.Width; ++x) { for (int i = 0; i < wlen - 1; ++i) { waSums[i] = waSums[i + 1]; wcSums[i] = wcSums[i + 1]; aSums[i] = aSums[i + 1]; } waSum = 0; wcSum = 0; aSum = 0; int wx; for (wx = 0; wx < wlen - 1; ++wx) { float wwx = w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; } wx = wlen - 1; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; int srcX = x + wx - r; if (srcX >= 0 && srcX < parms.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < parms.Height) { float c = InputMask[srcX, srcY]; float wp = w[wy]; waSums[wx] += wp; wp *= c;// +(c >> 7); wcSums[wx] += wp; //wp >>= 8; aSums[wx] += wp * c; } } int wr = w[wx]; waSum += wr * waSums[wx]; wcSum += wr * wcSums[wx]; aSum += wr * aSums[wx]; } // wcSum >>= 8; if (waSum == 0 || wcSum == 0) { tmpMask[x, y] = 0; } else { tmpMask[x, y] = (aSum / waSum); } ++dstx; } } } //copy back for (int x = 0; x < parms.Width; x++) { for (int y = 0; y < parms.Height; y++) { mp.Value[x, y] = tmpMask[x, y]; } } tmpMask = null; return(true); }
void addSoil(float soilAmt, int x, int y, ref DAGMask inMask, ref DAGMask subMask, ref DAGMask addMask) { addMask[x, y] += soilAmt; return; //if the addition of the soil makes me taller than any neighbor //then distribute soil between them and myself. //float currHeight = inMask[x, y] - subMask[x, y] + addMask[x, y] + soilAmt; //bool[] lowerPts = new bool[8]; //float[] diffPts = new float[8]; ////calculate neighbor info //float slope = 0; //float diffSum = 0; //int lowestDiffIdx = 0; //float lowestDiff = float.MaxValue; //bool foundLower = false; //for (int i = 0; i < neighOffset.Length; i++) //{ // Point off = neighOffset[i]; // if (x + off.X < 0 || x + off.X >= inMask.Width || // y + off.Y < 0 || y + off.Y >= inMask.Height ) // { // lowerPts[i] = false; // diffPts[i] = 0; // continue; // } // float nHeight = inMask[x + off.X, y + off.Y] - subMask[x + off.X, y + off.Y] + addMask[x + off.X, y + off.Y]; // if (currHeight > nHeight) // { // lowerPts[i] = true; // diffPts[i] = currHeight - nHeight; // diffSum += diffPts[i]; // foundLower = true; // if(lowestDiff > diffPts[i]) // { // lowestDiff = diffPts[i]; // lowestDiffIdx = i; // } // } // else // { // lowerPts[i] = false; // diffPts[i] = 0; // } //} //if(!foundLower) //{ // addMask[x, y] += soilAmt; // return; //} ////distribute soil //float amtToDistribute = lowestDiff; //addMask[x, y] += soilAmt - lowestDiff; //for (int i = 0; i < neighOffset.Length; i++) //{ // if (lowerPts[i]) // { // float weight = diffPts[i] / diffSum; // addMask[x, y] += amtToDistribute * weight; // } //} }
List <Point> calculatePath(DAGMask inMask, int width, int height, ref DAGMask subMask, ref DAGMask addMask, Point currPt) { List <Point> points = new List <Point>(); points.Add(currPt); Point prevPt = currPt; int distanceMax = inMask.Width; while (distanceMax > 0) { float currHeight = inMask[currPt.X, currPt.Y] - subMask[currPt.X, currPt.Y] + addMask[currPt.X, currPt.Y]; bool[] lowerPts = new bool[8]; float[] diffPts = new float[8]; //calculate neighbor info float diffSum = 0; bool foundLower = false; for (int i = 0; i < neighOffset.Length; i++) { Point off = neighOffset[i]; if (currPt.X + off.X < 0 || currPt.X + off.X >= width || currPt.Y + off.Y < 0 || currPt.Y + off.Y >= height || (currPt.X + off.X == prevPt.X && currPt.Y + off.Y == prevPt.Y)) { lowerPts[i] = false; diffPts[i] = 0; continue; } float nHeight = inMask[currPt.X + off.X, currPt.Y + off.Y] - subMask[currPt.X + off.X, currPt.Y + off.Y] + addMask[currPt.X + off.X, currPt.Y + off.Y]; if (currHeight > nHeight) { lowerPts[i] = true; diffPts[i] = (currHeight - nHeight) * neighWeight[i]; diffSum += diffPts[i]; foundLower = true; } else { lowerPts[i] = false; diffPts[i] = 0; } } //we fell in a local minima; if (!foundLower) { break; } //randomly pick one of our next stebs based upon propbability of weight int minIndex = 0; float randomNum = (float)mRand.NextDouble(); float runningTotal = 0; for (int i = 0; i < neighOffset.Length; i++) { if (lowerPts[i]) { float weight = diffPts[i] / diffSum; if (runningTotal + weight > randomNum) { minIndex = i; break; } runningTotal += weight; } } prevPt.X = currPt.X; prevPt.Y = currPt.Y; currPt.X += neighOffset[minIndex].X; currPt.Y += neighOffset[minIndex].Y; points.Add(currPt); distanceMax--; if (distanceMax < 0) { break; } } ; return(points); }
override public bool computeOutput(ConnectionPoint connPoint, OutputGenerationParams parms) { if (!verifyInputConnections()) { return(false); } if (!gatherInputAndParameters(parms)) { return(false); } MaskParam mp = ((MaskParam)(connPoint.ParamType)); mp.Value = InputMask.Clone(); mp.Value.mConstraintMask = ConstraintMask; ConvMatrix filter = new ConvMatrix(1, 2, 1, 2, 4, 2, 1, 2, 1); filter.mFactor = 16; filter.mOffset = 0; for (int i = 0; i < SmoothPower; i++) { int[] neightbors = new int[] { -1, 1, //top left 0, 1, //top center 1, 1, //top right -1, 0, //mid left 0, 0, //mid center 1, 0, //mid right -1, -1, //bot left 0, -1, //bot center 1, -1, //bot right }; DAGMask tempImgArray = new DAGMask(parms.Width, parms.Height); for (int x = 0; x < parms.Width; x++) { for (int y = 0; y < parms.Height; y++) { float total = 0; for (int k = 0; k < 9; k++) { int xIndex = x + neightbors[k * 2]; int zIndex = y + neightbors[k * 2 + 1]; if (xIndex < 0 || xIndex > parms.Width - 1 || zIndex < 0 || zIndex > parms.Height - 1) { continue; } total += filter.mFilterCoeffs[k] * mp.Value[xIndex, zIndex]; } total = total / filter.mFactor + filter.mOffset; if (total > 1.0f) { total = 1.0f; } if (total < 0) { total = 0; } tempImgArray[x, y] = total; } } //send our mask back for (int x = 0; x < parms.Width; x++) { for (int y = 0; y < parms.Height; y++) { mp.Value[x, y] = BMathLib.Clamp(tempImgArray[x, y], 0, 1); } } tempImgArray = null; } return(true); }