private void compactLayers(int bottomLayerIndex, int topLayerIndex) { int sze = (int)(BTerrainTexturing.getAlphaTextureWidth() * BTerrainTexturing.getAlphaTextureHeight()); //subtract from middle layers first BTerrainTexturingLayer topLayer = giveLayer(topLayerIndex); for (int i = bottomLayerIndex + 1; i < topLayerIndex; i++) { BTerrainTexturingLayer middleLayer = giveLayer(i); // if (middleLayer.mLayerType != BTerrainTexturingLayer.eLayerType.cLayer_Splat) // continue; for (int x = 0; x < sze; x++) { middleLayer.mAlphaLayer[x] = (byte)(BMathLib.Clamp(middleLayer.mAlphaLayer[x] - topLayer.mAlphaLayer[x], 0, 255)); } } //now add it to the bottom layer BTerrainTexturingLayer bottomLayer = giveLayer(bottomLayerIndex); for (int x = 0; x < sze; x++) { bottomLayer.mAlphaLayer[x] = (byte)(BMathLib.Clamp(bottomLayer.mAlphaLayer[x] + topLayer.mAlphaLayer[x], 0, 255)); } //remove top layer removeLayer(topLayerIndex); }
public void append(BTerrainLayerContainer target) { //let's just take the values here and add them to ourselves.. for (int i = 0; i < target.getNumLayers(); i++) { BTerrainTexturingLayer lyr = new BTerrainTexturingLayer(); target.mLayers[i].copyTo(lyr); mLayers.Add(lyr); } }
public void copyTo(BTerrainTexturingLayer target) { target.mLayerType = mLayerType; target.mActiveTextureIndex = mActiveTextureIndex; if (target.mAlphaLayer == null) { target.mAlphaLayer = new Byte[BTerrainTexturing.getAlphaTextureWidth() * BTerrainTexturing.getAlphaTextureHeight()]; } mAlphaLayer.CopyTo(target.mAlphaLayer, 0); }
public void removeRedundantLayers() { for (int i = 0; i < getNumLayers(); i++) { BTerrainTexturingLayer topLayer = giveLayer(i); if (topLayer.mLayerType != BTerrainTexturingLayer.eLayerType.cLayer_Splat) { continue; } //find another layer with my same ID; int idToFind = topLayer.mActiveTextureIndex; for (int q = i + 1; q < getNumLayers(); q++) { if (giveLayer(q).mActiveTextureIndex == idToFind && giveLayer(q).mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { compactLayers(i, q); } } } }
unsafe static void valToLayerColumn(BTerrainLayerContainer layers, BTerrainTexturingLayer tLayer, int dIP, byte val, int layerIndex) { if (val == 0) { return; } if (TerrainGlobals.getEditor().mEraseTextureInstead) { //if i'm erasing, ignore layers above me and just get rid of my values.. tLayer.mAlphaLayer[dIP] = (byte)(BMathLib.Clamp(tLayer.mAlphaLayer[dIP] - val, 0, 255)); } else { if (layerIndex + 1 >= layers.getNumLayers()) { //no layers above me tLayer.mAlphaLayer[dIP] = (byte)(BMathLib.Clamp(tLayer.mAlphaLayer[dIP] + val, 0, 255)); } else { float maxByte = 0; List <float> vList = new List <float>(); for (int k = layerIndex + 1; k < layers.getNumLayers(); k++) { if (layers.giveLayer(k).mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat && layers.giveLayer(k).mAlphaLayer[dIP] != byte.MinValue) { float v = layers.giveLayer(k).mAlphaLayer[dIP]; vList.Add(v); if (v > maxByte) { maxByte = v; } } } if (vList.Count == 0) { tLayer.mAlphaLayer[dIP] = (byte)(BMathLib.Clamp(tLayer.mAlphaLayer[dIP] + val, 0, 255)); return; } if (tLayer.mAlphaLayer[dIP] < maxByte) { tLayer.mAlphaLayer[dIP] = (byte)maxByte; } //normalize the contribs for everything above me floatN vec = new floatN((uint)(vList.Count)); vec.set(vList); vec = floatN.Normalize(vec); byte hVal = (byte)(val); uint T = 0; int remainder = 0; for (int k = layerIndex + 1; k < layers.getNumLayers(); k++) { if (layers.giveLayer(k).mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat && layers.giveLayer(k).mAlphaLayer[dIP] != byte.MinValue) { float amt = vec[T++]; int kQ = layers.giveLayer(k).mAlphaLayer[dIP]; int Del = (int)(((hVal * amt) + remainder)); int R = kQ - Del; if (R < 0) { remainder = Del - kQ; layers.giveLayer(k).mAlphaLayer[dIP] = 0; } else { layers.giveLayer(k).mAlphaLayer[dIP] = (byte)BMathLib.Clamp(R, 0, 255); remainder = 0; } } } tLayer.mAlphaLayer[dIP] = (byte)(BMathLib.Clamp(tLayer.mAlphaLayer[dIP] + remainder + val, 0, 255)); } } }
unsafe static public bool setMaskAlphaToLayer(BTerrainQuadNode node, UInt32 *mskImg, uint mskImgWidth, uint mskImgHeight, float alphaScalar, int terrainGridX, int terrainGridZ, char index) { bool changed = false; uint dstImgWidth = BTerrainTexturing.getAlphaTextureWidth(); uint dstImgHeight = BTerrainTexturing.getAlphaTextureWidth(); float vertsToPixelsRatio = BTerrainTexturing.getAlphaTextureWidth() / (float)BTerrainQuadNode.getMaxNodeWidth(); int minxvert = node.getDesc().mMinXVert; int minzvert = node.getDesc().mMinZVert; int maxxvert = node.getDesc().mMaxXVert; int maxzvert = node.getDesc().mMaxZVert; BTerrainLayerContainer layers = node.mLayerContainer; int layerIndex = layers.giveLayerIndex(index, BTerrainTexturingLayer.eLayerType.cLayer_Splat); if (TerrainGlobals.getEditor().mEraseTextureInstead&& layerIndex == 0) { return(false); } // layers.removeRedundantLayers();//CLM is this still needed?!??! if (layerIndex == -1) { if (TerrainGlobals.getEditor().mEraseTextureInstead) //we're erasing, and the texture doesn't exist.. { return(false); } //i don't exist yet. newSplatLayerEverywhere(index); layerIndex = layers.giveLayerIndex(index, BTerrainTexturingLayer.eLayerType.cLayer_Splat); BTerrainTexturingLayer tLayer = layers.giveLayer(layerIndex); for (int x = 0; x < BTerrainTexturing.getAlphaTextureWidth(); x++) { for (int z = 0; z < BTerrainTexturing.getAlphaTextureWidth(); z++) { float curWeight = TerrainGlobals.getTerrain().getSoftSelectionWeight(terrainGridX, terrainGridZ); if (!BMathLib.compare(curWeight, 0.0f)) { int cX = (int)((x * vertsToPixelsRatio) + minxvert); int cZ = (int)((z * vertsToPixelsRatio) + minzvert); curWeight = BMathLib.Clamp(curWeight, 0, 1); int dIP = x + ((int)BTerrainTexturing.getAlphaTextureHeight()) * z; byte alphaMapVal = giveBrushAlphaValue(mskImg, mskImgWidth, mskImgHeight, minxvert, minzvert, maxxvert, maxzvert, cX, cZ, terrainGridX, terrainGridZ); byte val = (byte)(alphaMapVal * alphaScalar * curWeight); tLayer.mAlphaLayer[dIP] = val; } } } changed = true; } else { BTerrainTexturingLayer tLayer = layers.giveLayer(layerIndex); //this layer already exists. //If a pixel exists above me, subtract me from it, rather than adding to me. for (int x = 0; x < BTerrainTexturing.getAlphaTextureWidth(); x++) { for (int z = 0; z < BTerrainTexturing.getAlphaTextureWidth(); z++) { //find the closest vert int cX = (int)((x * vertsToPixelsRatio) + minxvert); int cZ = (int)((z * vertsToPixelsRatio) + minzvert); int dIP = x + ((int)BTerrainTexturing.getAlphaTextureHeight()) * z; float curWeight = TerrainGlobals.getTerrain().getSoftSelectionWeight(terrainGridX, terrainGridZ); if (!BMathLib.compare(curWeight, 0.0f)) { changed = true; curWeight = BMathLib.Clamp(curWeight, 0, 1); byte alphaMapVal = giveBrushAlphaValue(mskImg, mskImgWidth, mskImgHeight, minxvert, minzvert, maxxvert, maxzvert, cX, cZ, terrainGridX, terrainGridZ); byte val = (byte)(alphaMapVal * alphaScalar * curWeight); valToLayerColumn(layers, tLayer, dIP, val, layerIndex); } } } } layers.removeBlankLayers(); return(changed); }
//---------------------------------------------- unsafe static public bool setIndexToMaskedArea(BTerrainQuadNode node, int minxvert, int minzvert, int maxxvert, int maxzvert, char index) { bool changed = false; uint dstImgWidth = BTerrainTexturing.getAlphaTextureWidth(); uint dstImgHeight = BTerrainTexturing.getAlphaTextureWidth(); float vertsToPixelsRatio = BTerrainTexturing.getAlphaTextureWidth() / (float)BTerrainQuadNode.getMaxNodeWidth(); BTerrainLayerContainer layers = node.mLayerContainer; int layerIndex = layers.giveLayerIndex(index, BTerrainTexturingLayer.eLayerType.cLayer_Splat); if (TerrainGlobals.getEditor().mEraseTextureInstead&& layerIndex == 0) { return(false); } //layers.removeRedundantLayers();//CLM is this still needed?!??! if (layerIndex == -1) { if (TerrainGlobals.getEditor().mEraseTextureInstead) //we're erasing, and the texture doesn't exist.. { return(false); } //i don't exist yet. newSplatLayerEverywhere(index); layerIndex = layers.giveLayerIndex(index, BTerrainTexturingLayer.eLayerType.cLayer_Splat); BTerrainTexturingLayer tLayer = layers.giveLayer(layerIndex); for (int x = 0; x < BTerrainTexturing.getAlphaTextureWidth(); x++) { for (int z = 0; z < BTerrainTexturing.getAlphaTextureWidth(); z++) { //find the closest vert int cX = (int)((x * vertsToPixelsRatio) + minxvert); int cZ = (int)((z * vertsToPixelsRatio) + minzvert); int vertIndex = (int)(cX * TerrainGlobals.getTerrain().getNumZVerts() + cZ); float curWeight = 1.0f; if (Masking.isPointSelected(vertIndex, ref curWeight)) { curWeight = BMathLib.Clamp(curWeight, 0, 1); int dIP = x + ((int)BTerrainTexturing.getAlphaTextureHeight()) * z; byte val = (byte)(curWeight * byte.MaxValue); tLayer.mAlphaLayer[dIP] = val; } } } changed = true; } else { BTerrainTexturingLayer tLayer = layers.giveLayer(layerIndex); //this layer already exists. //If a pixel exists above me, subtract me from it, rather than adding to me. for (int x = 0; x < BTerrainTexturing.getAlphaTextureWidth(); x++) { for (int z = 0; z < BTerrainTexturing.getAlphaTextureWidth(); z++) { //find the closest vert int cX = (int)((x * vertsToPixelsRatio) + minxvert); int cZ = (int)((z * vertsToPixelsRatio) + minzvert); int vertIndex = (int)(cX * TerrainGlobals.getTerrain().getNumZVerts() + cZ); float curWeight = 1.0f; if (Masking.isPointSelected(vertIndex, ref curWeight)) { changed = true; int dIP = x + ((int)BTerrainTexturing.getAlphaTextureHeight()) * z; curWeight = BMathLib.Clamp(curWeight, 0, 1); byte val = (byte)(curWeight * byte.MaxValue); valToLayerColumn(layers, tLayer, dIP, val, layerIndex); } } } } layers.removeBlankLayers(); return(changed); }
void fillCreateLayer(byte[] inputImg, int activeTexIndex, BTerrainTexturingLayer.eLayerType type, int minXTile, int minZTile, byte[] tempLargerImge, byte[] tempBorderedImg) { int width = (int)BTerrainTexturing.getAlphaTextureWidth(); int height = (int)BTerrainTexturing.getAlphaTextureHeight(); int lw = width + 2; int lh = height + 2; //Create our texture first, border it, then resize it. //fill the origional texture into the new texture for (int q = 0; q < (width); q++) { for (int j = 0; j < (height); j++) { tempLargerImge[(q + 1) + lw * (j + 1)] = inputImg[q + (width) * j]; } } int numXNodes = (int)(TerrainGlobals.getTerrain().getNumXVerts() / BTerrainQuadNode.cMaxWidth); int rootXNode = (int)(minXTile / BTerrainQuadNode.cMaxWidth); int rootZNode = (int)(minZTile / BTerrainQuadNode.cMaxHeight); BTerrainQuadNode rootNode = TerrainGlobals.getTerrain().getLeafNode(rootXNode, rootZNode);//TerrainGlobals.getTerrain().getQuadNodeRoot().getLeafNodeContainingTile(minXTile, minZTile); BTerrainQuadNode node = null; int layerIndex = 0; BTerrainTexturingLayer lyr = null; #region SIDES //grab neighbor alpha values, paste them into my edges. //LEFT SIDE FILL node = TerrainGlobals.getTerrain().getLeafNode(rootXNode - 1, rootZNode);// rootNode.getNeighborNode(-1, 0); if ((node != null) && ((layerIndex = node.mLayerContainer.giveLayerIndex(activeTexIndex, type)) != -1)) { { lyr = node.mLayerContainer.giveLayer(layerIndex); //grab the RIGHT pixels for (int i = 0; i < height; i++) { int srcIndex = (width - 1) + width * i; int destIndex = 0 + (lw * (i + 1)); tempLargerImge[destIndex] = lyr.mAlphaLayer[srcIndex]; } } } else { //extend the LEFT pixels for (int i = 0; i < height; i++) { int srcIndex = 0 + width * i; int destIndex = 0 + (lw * (i + 1)); tempLargerImge[destIndex] = inputImg[srcIndex]; } } //RIGHT SIDE FILL node = TerrainGlobals.getTerrain().getLeafNode(rootXNode + 1, rootZNode);// rootNode.getNeighborNode(1, 0); if ((node != null) && ((layerIndex = node.mLayerContainer.giveLayerIndex(activeTexIndex, type)) != -1)) { lyr = node.mLayerContainer.giveLayer(layerIndex); //grab the LEFT pixels for (int i = 0; i < height; i++) { int srcIndex = 0 + width * i; int destIndex = (lw - 1) + (lw * (i + 1)); tempLargerImge[destIndex] = lyr.mAlphaLayer[srcIndex]; } } else { //extend the RIGHT pixels for (int i = 0; i < height; i++) { int srcIndex = (width - 1) + width * i; int destIndex = (lw - 1) + (lw * (i + 1)); tempLargerImge[destIndex] = inputImg[srcIndex]; } } //TOP SIDE FILL node = TerrainGlobals.getTerrain().getLeafNode(rootXNode, rootZNode + 1);// rootNode.getNeighborNode(0, 1); if ((node != null) && ((layerIndex = node.mLayerContainer.giveLayerIndex(activeTexIndex, type)) != -1)) { { lyr = node.mLayerContainer.giveLayer(layerIndex); //grab the BOTTOM pixels for (int i = 0; i < width; i++) { int srcIndex = i + width * 0; int destIndex = (i + 1) + (lw * (lh - 1)); tempLargerImge[destIndex] = lyr.mAlphaLayer[srcIndex]; } } } else { //extend the TOP pixels for (int i = 0; i < width; i++) { int srcIndex = i + width * (height - 1); int destIndex = (i + 1) + (lw * (lh - 1)); tempLargerImge[destIndex] = inputImg[srcIndex]; } } //BOTTOM SIDE FILL node = TerrainGlobals.getTerrain().getLeafNode(rootXNode, rootZNode - 1);// rootNode.getNeighborNode(0, -1); if ((node != null) && ((layerIndex = node.mLayerContainer.giveLayerIndex(activeTexIndex, type)) != -1)) { { lyr = node.mLayerContainer.giveLayer(layerIndex); //grab the TOP pixels for (int i = 0; i < width; i++) { int srcIndex = i + width * (height - 1); int destIndex = (i + 1) + (lw * 0); tempLargerImge[destIndex] = lyr.mAlphaLayer[srcIndex]; } } } else { //extend the BOTTOM pixels for (int i = 0; i < width; i++) { int srcIndex = i + width * 0; int destIndex = (i + 1) + (0); tempLargerImge[destIndex] = inputImg[srcIndex]; } } #endregion #region CORNERS //TOP LEFT CORNER node = TerrainGlobals.getTerrain().getLeafNode(rootXNode - 1, rootZNode + 1);//rootNode.getNeighborNode(-1, 1); if ((node != null) && ((layerIndex = node.mLayerContainer.giveLayerIndex(activeTexIndex, type)) != -1)) { { lyr = node.mLayerContainer.giveLayer(layerIndex); //grab the BOTTOM RIGHT pixel //for (int i = 0; i < width; i++) { int srcIndex = (width - 1) + width * 0; int destIndex = 0 + (lw * (lh - 1)); tempLargerImge[destIndex] = lyr.mAlphaLayer[srcIndex]; } } } else { //grab the tpo+1, left+1 pixel //for (int i = 0; i < width; i++) { int srcIndex = 1 + width * (height - 2); int destIndex = 0 + (lw * (lh - 1)); tempLargerImge[destIndex] = inputImg[srcIndex]; } } //TOP RIGHT CORNER node = TerrainGlobals.getTerrain().getLeafNode(rootXNode + 1, rootZNode + 1);//rootNode.getNeighborNode(1, 1); if ((node != null) && ((layerIndex = node.mLayerContainer.giveLayerIndex(activeTexIndex, type)) != -1)) { { lyr = node.mLayerContainer.giveLayer(layerIndex); //grab the BOTTOM LEFT pixel //for (int i = 0; i < width; i++) { int srcIndex = 0;// +width * (height - 1); int destIndex = (lw - 1) + (lw * (lh - 1)); tempLargerImge[destIndex] = lyr.mAlphaLayer[srcIndex]; } } } else { //grab the TOP+1 RIGHT+1 pixel //for (int i = 0; i < width; i++) { int srcIndex = (width - 2) + width * (height - 2); int destIndex = (lw - 1) + (lw * (lh - 1)); tempLargerImge[destIndex] = inputImg[srcIndex]; } } //BOTTOM LEFT CORNER node = TerrainGlobals.getTerrain().getLeafNode(rootXNode - 1, rootZNode - 1);//rootNode.getNeighborNode(-1, -1); if ((node != null) && ((layerIndex = node.mLayerContainer.giveLayerIndex(activeTexIndex, type)) != -1)) { { lyr = node.mLayerContainer.giveLayer(layerIndex); //grab the TOP RIGHT pixel //for (int i = 0; i < width; i++) { int srcIndex = (width - 1) + width * (height - 1); int destIndex = 0 + (lw * 0); tempLargerImge[destIndex] = lyr.mAlphaLayer[srcIndex]; } } } else { //grab the BOTTOM+1 LEFT+1 pixel //for (int i = 0; i < width; i++) { int srcIndex = 1 + width * 1; int destIndex = 0 + (lw * 0); tempLargerImge[destIndex] = inputImg[srcIndex]; } } //BOTTOM RIGHT CORNER node = TerrainGlobals.getTerrain().getLeafNode(rootXNode + 1, rootZNode - 1);//rootNode.getNeighborNode(1, -1); if ((node != null) && ((layerIndex = node.mLayerContainer.giveLayerIndex(activeTexIndex, type)) != -1)) { { lyr = node.mLayerContainer.giveLayer(layerIndex); //grab the TOP LEFT pixel //for (int i = 0; i < width; i++) { int srcIndex = (0) + width * (height - 1); int destIndex = (lw - 1) + (lw * 0); tempLargerImge[destIndex] = lyr.mAlphaLayer[srcIndex]; } } } else { //grab the BOTTOM+1 RIGHT+1 pixel //for (int i = 0; i < width; i++) { int srcIndex = (width - 2) + width * 1; int destIndex = (lw - 1) + (lw * 0); tempLargerImge[destIndex] = inputImg[srcIndex]; } } #endregion ImageManipulation.resizeGreyScaleImg(tempLargerImge, tempBorderedImg, width + 2, height + 2, width, height, ImageManipulation.eFilterType.cFilter_Linear); }