public void ensureProperLayerOrdering() { ensureProperNumberLayers(); int numSplatLayers = TerrainGlobals.getTexturing().getActiveTextureCount(); //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; } //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].mAlphaContrib; 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); //back solve to calculate new alpha value. vContribSorted[(uint)(numSplatLayers - 1)] = vContrib[(uint)(numSplatLayers - 1)]; for (int k = (numSplatLayers - 2); k >= 0; 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].mAlphaContrib = (byte)(vContribSorted[(uint)mLayers[k].mActiveTextureIndex] * 255); } //ensure layers are sorted ensureProperSorting(); }
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)); } } }
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(); }