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 fullLayerAlpha(int layerIndex) { if (layerIndex < 0 || layerIndex >= mLayers.Count) { return; } for (int x = 0; x < (int)BTerrainTexturing.getAlphaTextureWidth(); x++) { for (int z = 0; z < (int)BTerrainTexturing.getAlphaTextureHeight(); z++) { mLayers[layerIndex].mAlphaLayer[x + BTerrainTexturing.getAlphaTextureWidth() * z] = Byte.MaxValue; } } }
public bool isLayerAllClear(int layerIndex) { if (layerIndex < 0 || layerIndex >= mLayers.Count) { return(false); } for (int x = 0; x < (int)BTerrainTexturing.getAlphaTextureWidth(); x++) { for (int z = 0; z < (int)BTerrainTexturing.getAlphaTextureHeight(); z++) { if (mLayers[layerIndex].mAlphaLayer[x + BTerrainTexturing.getAlphaTextureWidth() * z] != 0) { return(false); } } } return(true); }
public void removeHiddenLayers() { int sze = (int)(BTerrainTexturing.getAlphaTextureWidth() * BTerrainTexturing.getAlphaTextureHeight()); //remove layers below a fully opaque layer for (int i = 1; i < mLayers.Count; i++) { if (mLayers[i].mLayerType != BTerrainTexturingLayer.eLayerType.cLayer_Splat) { continue; } if (isLayerAllSolid(i)) { removeLayersBelow(i); i = 0; } } }
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); }
public void computeDecalLayerAlphaContrib(int layerIndex, int minXVertex, int minZVertex) { if (layerIndex < 0 || layerIndex >= mLayers.Count) { return; } //grab our decal instance if (mLayers[layerIndex].mLayerType != BTerrainTexturingLayer.eLayerType.cLayer_Decal) { return; } float vertsToHighResPixelSpaceRatio = BTerrainTexturing.getTextureWidth() / BTerrainQuadNode.cMaxWidth; BTerrainDecalInstance dcli = TerrainGlobals.getTexturing().getActiveDecalInstance(mLayers[layerIndex].mActiveTextureIndex); BTerrainActiveDecalContainer dcl = TerrainGlobals.getTexturing().getActiveDecal(dcli.mActiveDecalIndex); //scale, rotate, translate us int h = dcl.mHeight; int w = dcl.mWidth; int nW = (int)(w * ((1.0f / dcli.mUScale) / vertsToHighResPixelSpaceRatio)); int nH = (int)(h * ((1.0f / dcli.mVScale) / vertsToHighResPixelSpaceRatio)); int tW = 0; int tH = 0; byte[] tImgResized = null; byte[] tImgRotated = null; byte[] imgDat = new byte[h * w]; imgDat = ImageManipulation.valueGreyScaleImg(imgDat, w, h, ImageManipulation.eValueOperation.cValue_Set, 255); tImgResized = ImageManipulation.resizeGreyScaleImg(imgDat, w, h, nW, nH, ImageManipulation.eFilterType.cFilter_Linear); tImgRotated = ImageManipulation.rotateGreyScaleImg(tImgResized, nW, nH, (float)(-dcli.mRotation * (180.0f / Math.PI)), false, out nW, out nH, ImageManipulation.eFilterType.cFilter_Nearest); byte[] tImg = tImgRotated; int startX = (int)((dcli.mTileCenter.X / vertsToHighResPixelSpaceRatio) - (nW >> 1) - minXVertex); int startY = (int)((dcli.mTileCenter.Y / vertsToHighResPixelSpaceRatio) - (nH >> 1) - minZVertex); clearLayerAlpha(layerIndex); //copy back to masking for (int i = 0; i < nW; i++) { for (int j = 0; j < nH; j++) { int iS = startX + i; if (iS < 0 || iS >= BTerrainTexturing.getAlphaTextureWidth()) { continue; } int jS = startY + j; if (jS < 0 || jS >= BTerrainTexturing.getAlphaTextureHeight()) { continue; } int srcIndex = j + i * nW; int dstIndex = (int)(iS + BTerrainTexturing.getAlphaTextureHeight() * jS); byte val = tImg[srcIndex]; mLayers[layerIndex].mAlphaLayer[dstIndex] = val; } } //also, walk any layers that exist above us, and subtract out their values as well for (int k = layerIndex + 1; k < mLayers.Count; k++) { if (mLayers[k].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { for (int i = 0; i < BTerrainTexturing.getAlphaTextureWidth() * BTerrainTexturing.getAlphaTextureHeight(); i++) { mLayers[layerIndex].mAlphaLayer[i] = (byte)BMathLib.Clamp(mLayers[layerIndex].mAlphaLayer[i] - mLayers[k].mAlphaLayer[i], 0, 255); } } } imgDat = null; tImgResized = null; tImgRotated = null; tImg = null; }
//Functions will effect Decal Only public int newDecalLayer(int activeDecalInstanceIndex) { if (mLayers.Count > 0 && mLayers[mLayers.Count - 1].mActiveTextureIndex == activeDecalInstanceIndex && mLayers[mLayers.Count - 1].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Decal) { return(mLayers.Count - 1); } mLayers.Add(new BTerrainTexturingLayer()); mLayers[mLayers.Count - 1].mLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Decal; mLayers[mLayers.Count - 1].mActiveTextureIndex = activeDecalInstanceIndex; mLayers[mLayers.Count - 1].mAlphaLayer = new Byte[BTerrainTexturing.getAlphaTextureWidth() * BTerrainTexturing.getAlphaTextureHeight()]; fullLayerAlpha(mLayers.Count - 1); return(mLayers.Count - 1); }
public int newSplatLayer(int activeTextureIndex, bool insertKeepOrdering) { if (mLayers.Count > 0 && mLayers[mLayers.Count - 1].mActiveTextureIndex == activeTextureIndex && mLayers[mLayers.Count - 1].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { return(mLayers.Count - 1); } int addedIndex = -1; if (insertKeepOrdering) { for (int i = 0; i < mLayers.Count; i++) { if (mLayers[i].mActiveTextureIndex > activeTextureIndex) { addedIndex = i; break; } } } if (addedIndex == -1) { mLayers.Add(new BTerrainTexturingLayer()); addedIndex = mLayers.Count - 1; } else { mLayers.Insert(addedIndex, new BTerrainTexturingLayer()); } mLayers[addedIndex].mLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; mLayers[addedIndex].mActiveTextureIndex = activeTextureIndex; mLayers[addedIndex].mAlphaLayer = new Byte[BTerrainTexturing.getAlphaTextureWidth() * BTerrainTexturing.getAlphaTextureHeight()]; return(addedIndex); }
public void clearAllAlphasAtPixel(int x, int z) { if (x < 0 || z < 0 || x >= BTerrainTexturing.getAlphaTextureWidth() || z >= BTerrainTexturing.getAlphaTextureHeight()) { return; } for (int i = mLayers.Count - 1; i >= 0; i--) { mLayers[i].mAlphaLayer[x + BTerrainTexturing.getAlphaTextureWidth() * z] = 0; } }
//used for clipart public BTerrainTextureVector giveLayerChainAtPixel(int x, int z) { BTerrainTextureVector v = new BTerrainTextureVector(); if (x < 0 || z < 0 || x >= BTerrainTexturing.getAlphaTextureWidth() || z >= BTerrainTexturing.getAlphaTextureHeight()) { return(v); } for (int i = 0; i < mLayers.Count; i++) { BTerrainPerVertexLayerData layer = new BTerrainPerVertexLayerData(); layer.mActiveTextureIndex = mLayers[i].mActiveTextureIndex; layer.mLayerType = mLayers[i].mLayerType; layer.mAlphaContrib = mLayers[i].mAlphaLayer[x + BTerrainTexturing.getAlphaTextureWidth() * z]; v.mLayers.Add(layer); } return(v); }
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 ensureProperLayerOrdering() { ensureProperNumberLayers(); int numSplatLayers = TerrainGlobals.getTexturing().getActiveTextureCount(); int aWidth = (int)BTerrainTexturing.getAlphaTextureWidth(); int aHeight = (int)BTerrainTexturing.getAlphaTextureHeight(); for (int y = 0; y < aHeight; y++) { for (int x = 0; x < aWidth; x++) { int aIndex = x + aWidth * y; //create N floatN vectors floatN[] layerVecs = new floatN[numSplatLayers]; for (uint k = 0; k < numSplatLayers; k++) { layerVecs[k] = new floatN((uint)numSplatLayers); layerVecs[k][k] = 1; } //quick early out test to make sure we're not screwing up by re-normalizing.. floatN nVal = new floatN((uint)numSplatLayers); for (uint k = 0; k < numSplatLayers; k++) { byte b = mLayers[(int)k].mAlphaLayer[aIndex]; float alpha = ((float)b) / 255.0f; nVal[k] = alpha; } float len = nVal.Length(); if (len == 1.0f) { continue; } //now, calculate a VContrib vector for the current layering. floatN vContrib = layerVecs[0].Clone();//start with 100% base layer for (uint k = 1; k < numSplatLayers; k++) { byte b = mLayers[(int)k].mAlphaLayer[aIndex]; int lIdx = mLayers[(int)k].mActiveTextureIndex; float alpha = ((float)b) / 255.0f; vContrib = ( (layerVecs[lIdx] * alpha) + (vContrib * (1 - alpha)) ); } //vContrib now holds at each vector element, the amount the layer is visible to the final pixel //although it's not sorted in the current layer ordering //so, calculate the xF for the new layer ordering, and store it in a temp var floatN vContribSorted = new floatN((uint)numSplatLayers); floatN vContribSortedInv = new floatN((uint)numSplatLayers); //back solve to calculate new alpha value. vContribSorted[(uint)(numSplatLayers - 1)] = vContrib[(uint)(numSplatLayers - 1)]; vContribSortedInv[(uint)(numSplatLayers - 1)] = 1 - vContribSorted[(uint)(numSplatLayers - 1)]; for (int k = (numSplatLayers - 2); k >= 0; k--) { //multiply the inversions together that we have so far. float mulSoFar = 1; for (uint q = (uint)k + 1; q < numSplatLayers; q++) { mulSoFar *= vContribSortedInv[q]; } vContribSorted[(uint)k] = mulSoFar == 0 ? 0 : vContrib[(uint)(k)] / mulSoFar; vContribSortedInv[(uint)k] = 1 - vContribSorted[(uint)k]; //uint invK = (uint)((numSplatLayers - 2) - k); //float Vc = vContrib[(uint)(k + 1)]; //vContrib for upper layer //float invVc = 1.0f - Vc; ////current layer vContrib //float cVc = vContrib[(uint)(k)]; //float xF = invVc==0?0:(cVc / invVc); ////move back //vContribSorted[(uint)k] = xF; } //now copy back to the unsorted layer index for (int k = 0; k < numSplatLayers; k++) { mLayers[k].mAlphaLayer[aIndex] = (byte)(vContribSorted[(uint)mLayers[k].mActiveTextureIndex] * 255); } } } //ensure layers are sorted ensureProperSorting(); }
public void toTextureArray(ref List <Texture> mTempAlphaTextures, int minXVert, int minZVert) { bool doBlendedFill = true; //lock in our alpha texture int slicePitch = (int)(BTerrainTexturing.getAlphaTextureWidth() * BTerrainTexturing.getAlphaTextureHeight()); int count = Math.Min(mTempAlphaTextures.Count, mLayers.Count); int width = (int)BTerrainTexturing.getAlphaTextureWidth(); int height = (int)BTerrainTexturing.getAlphaTextureHeight(); byte[] tempLargerImg = new byte[(width + 2) * (height + 2)]; byte[] bordered = new byte[width * height]; int i = 0; for (i = 0; i < count; i++) { if (mTempAlphaTextures[i] != null) { GraphicsStream texstream = mTempAlphaTextures[i].LockRectangle(0, LockFlags.None); if (i == 0) { for (int k = 0; k < slicePitch; k++) { texstream.WriteByte(255); } } else { if (doBlendedFill) { fillCreateLayer(mLayers[i].mAlphaLayer, mLayers[i].mActiveTextureIndex, mLayers[i].mLayerType, minXVert, minZVert, tempLargerImg, bordered); texstream.Write(bordered, 0, slicePitch); } else { texstream.Write(mLayers[i].mAlphaLayer, 0, slicePitch); } } mTempAlphaTextures[i].UnlockRectangle(0); texstream.Close(); } else { } } //we've got more layers than we've preallocated if (mTempAlphaTextures.Count < mLayers.Count) { int diff = mLayers.Count - mTempAlphaTextures.Count; for (int k = 0; k < diff; k++) { mTempAlphaTextures.Add(new Texture(BRenderDevice.getDevice(), (int)BTerrainTexturing.getAlphaTextureWidth(), (int)BTerrainTexturing.getAlphaTextureHeight(), 1, 0, Format.L8, Pool.Managed)); GraphicsStream texstream = mTempAlphaTextures[mTempAlphaTextures.Count - 1].LockRectangle(0, LockFlags.None); if (doBlendedFill) { fillCreateLayer(mLayers[i + k].mAlphaLayer, mLayers[i + k].mActiveTextureIndex, mLayers[i + k].mLayerType, minXVert, minZVert, tempLargerImg, bordered); texstream.Write(bordered, 0, slicePitch); } else { texstream.Write(mLayers[i + k].mAlphaLayer, 0, slicePitch); } mTempAlphaTextures[mTempAlphaTextures.Count - 1].UnlockRectangle(0); texstream.Close(); } } tempLargerImg = null; }