public int addActiveDecalInstance(int activeDecalIndex, int xPos, int zPos, float uScale, float vScale, float rotation, int minXTile, int maxXTile, int minYTile, int maxYTile) { BTerrainDecalInstance di = new BTerrainDecalInstance(); di.mActiveDecalIndex = activeDecalIndex; di.mRotation = rotation; di.mUScale = uScale; di.mVScale = vScale; di.mTileCenter = new Vector2(xPos, zPos); di.mTileBoundsMin.X = minXTile; di.mTileBoundsMin.Y = minYTile; di.mTileBoundsMax.X = maxXTile; di.mTileBoundsMax.Y = maxYTile; di.mIsSelected = false; mDecalInstances.Add(di); return(mDecalInstances.Count - 1); }
private int giveLayerIDAtPixelInternal(int x, int y, int startingLayer, ref BTerrainTexturingLayer.eLayerType selectedLayerType) { if (startingLayer > mLayers.Count - 1) { startingLayer = mLayers.Count - 1; } if (startingLayer < 0) { selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; return(0); } for (int i = startingLayer; i >= 0; i--) { if (mLayers[i].mAlphaLayer[x + BTerrainTexturing.getAlphaTextureWidth() * y] != 0) { if (mLayers[i].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; return(mLayers[i].mActiveTextureIndex); } else { BTerrainDecalInstance dcli = TerrainGlobals.getTexturing().getActiveDecalInstance(mLayers[i].mActiveTextureIndex); if (TerrainGlobals.getEditor().mVisTileIntetersectionX <= dcli.mTileBoundsMax.X && TerrainGlobals.getEditor().mVisTileIntetersectionX >= dcli.mTileBoundsMin.X && TerrainGlobals.getEditor().mVisTileIntetersectionZ <= dcli.mTileBoundsMax.Y && TerrainGlobals.getEditor().mVisTileIntetersectionZ >= dcli.mTileBoundsMin.Y) { selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Decal; return(i);// dcli.mActiveDecalIndex; } } } } selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; return(-1); }
//CLM USED FOR EXPORT public unsafe void convertLayersToTexturingDataHandle(BTerrainLayerContainer input, List <Texture> tempAlphaTextures, BTerrainCompositeTexture output, int minXVert, int minZVert, int lod, int channelCount) { // BTerrainLayerContainer input = node.mLayerContainer; // BTerrainCompositeTexture output = node.getTextureData(lod).mCompositeTexture; Viewport vp = new Viewport(); vp.X = output.mXPixelOffset; vp.Y = output.mYPixelOffset; vp.Width = output.mWidth; vp.Height = output.mWidth; vp.MinZ = 0; vp.MaxZ = 1; BRenderDevice.getDevice().Viewport = vp; Microsoft.DirectX.Direct3D.Effect shader = TerrainGlobals.getTexturing().mCompositeShader; shader.Begin(0); shader.BeginPass(0); for (int i = 0; i < channelCount; i++) { for (int k = 0; k < output.mNumMips; k++) { //actually render Surface compositeTarget = null; float scale = 1; try { if (output.UsingAtlas == false) { compositeTarget = output.mTextures[i].GetSurfaceLevel(k); BRenderDevice.getDevice().SetRenderTarget(0, compositeTarget); } else { BTerrainCompositeAtlasTexture atlas = output.mAtlas; if (atlas.mTextures[i].Disposed == true) { atlas.reCreate(); } scale = atlas.mAtlasScale; compositeTarget = atlas.mTextures[i].GetSurfaceLevel(k); BRenderDevice.getDevice().SetRenderTarget(0, compositeTarget); } { BTerrainTexturingLayer.eLayerType lastType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; float layerInc = 1.0f / (float)(cMaxNumBlends - 1);// (float)input.getNumLayers(); for (int j = 0; j < input.getNumLayers(); j++) { // BRenderDevice.getDevice().Clear(ClearFlags.ZBuffer | ClearFlags.Target, unchecked((int)0xFFFF0000), 1.0f, 0); //compose a splat shader.SetValue(mShaderContribOverride, 1); shader.SetValue(mShaderAlphaOverride, 1); if (input.giveLayer(j).mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { if (lastType != BTerrainTexturingLayer.eLayerType.cLayer_Splat) { shader.EndPass(); shader.BeginPass(0); lastType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; } if (TerrainGlobals.getEditor().getRenderMode() == BTerrainEditor.eEditorRenderMode.cRenderTextureSelectRender) { if (TerrainGlobals.getEditor().getMode() != BTerrainEditor.eEditorMode.cModeTexEdit) { if (j == 0) { shader.SetValue(mShaderContribOverride, 0); shader.SetValue(mShaderAlphaOverride, 0); } else { continue; } } else { if (input.giveLayer(j).mActiveTextureIndex != TerrainGlobals.getTerrainFrontEnd().SelectedTextureIndex) { shader.SetValue(mShaderContribOverride, 0); } else { shader.SetValue(mShaderContribOverride, 1); } shader.SetValue(mShaderAlphaOverride, 0); } } float targetLayer = (float)(j * layerInc); shader.SetValue(mShaderNumLayersHandle, targetLayer); shader.SetValue(mShaderAlphaTexArrayHandle, tempAlphaTextures[j]); //lock in our target texture BTerrainActiveTextureContainer active = TerrainGlobals.getTexturing().getActiveTexture(input.giveLayer(j).mActiveTextureIndex); if (active == null) { compositeTarget.Dispose(); continue; } shader.SetValue(mShaderTexArrayHandle, active.mTexChannels[i].mTexture); float[] uvs = new float[2]; uvs[0] = active.mUScale; uvs[1] = active.mVScale; shader.SetValue(mShaderLayerUV, uvs); } else //compose a decal { if (lastType != BTerrainTexturingLayer.eLayerType.cLayer_Decal) { shader.EndPass(); shader.BeginPass(1); lastType = BTerrainTexturingLayer.eLayerType.cLayer_Decal; } bool doWhite = false; if (TerrainGlobals.getEditor().getRenderMode() == BTerrainEditor.eEditorRenderMode.cRenderTextureSelectRender) { if (TerrainGlobals.getEditor().getMode() == BTerrainEditor.eEditorMode.cModeTexEdit) { shader.SetValue(mShaderContribOverride, 0); } else if (TerrainGlobals.getEditor().getMode() == BTerrainEditor.eEditorMode.cModeDecalEdit) { doWhite = true; if (TerrainGlobals.getTexturing().getActiveDecalInstance(input.giveLayer(j).mActiveTextureIndex).mActiveDecalIndex != TerrainGlobals.getTerrainFrontEnd().SelectedDecalIndex) { shader.SetValue(mShaderContribOverride, 0); } else { shader.SetValue(mShaderContribOverride, 1); shader.SetValue(mShaderAlphaOverride, 1); } } } //Grab our decal instance BTerrainDecalInstance decal = getActiveDecalInstance(input.giveLayer(j).mActiveTextureIndex); if (decal == null) { compositeTarget.Dispose(); continue; } Vector4 selColor = new Vector4(1, 1, 1, 1); if (decal.mIsSelected) { selColor.Y = 0.75f; selColor.Z = 0.75f; } shader.SetValue(mShaderColorOverload, selColor); //grab the decal we care about BTerrainActiveDecalContainer active = getActiveDecal(decal.mActiveDecalIndex); if (active == null) { compositeTarget.Dispose(); continue; } if (doWhite) { shader.SetValue(mShaderAlphaTexArrayHandle, tempAlphaTextures[0]); } else { shader.SetValue(mShaderAlphaTexArrayHandle, tempAlphaTextures[j]); } shader.SetValue(mShaderAlphaTexDecalHandle, active.mTexChannels[(int)BTerrainTexturing.eTextureChannels.cOpacity].mTexture); shader.SetValue(mShaderTexDecalHandle, active.mTexChannels[i].mTexture); float[] decalDat = new float[4]; decalDat[0] = decal.mRotation; //compute our U and V offset float vertsToHighResPixelSpaceRatio = BTerrainTexturing.getTextureWidth() / BTerrainQuadNode.cMaxWidth; decalDat[1] = (decal.mTileCenter.X - (minXVert * vertsToHighResPixelSpaceRatio)) / BTerrainTexturing.getTextureWidth(); decalDat[2] = (decal.mTileCenter.Y - (minZVert * vertsToHighResPixelSpaceRatio)) / BTerrainTexturing.getTextureHeight(); decalDat[3] = 0; shader.SetValue(mShaderLayerDecalData, decalDat); float[] uvs = new float[2]; uvs[0] = decal.mUScale; uvs[1] = decal.mVScale; shader.SetValue(mShaderLayerUV, uvs); } shader.CommitChanges(); BRenderDevice.getDevice().Viewport = vp; BRenderDevice.getDevice().DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 4, 0, 2); } shader.EndPass(); shader.BeginPass(0); } } catch (Direct3DXException e) { CoreGlobals.getErrorManager().SendToErrorWarningViewer("An error has occured during the compositing process"); } finally { if (compositeTarget != null) { compositeTarget.Dispose(); } } } } shader.EndPass(); shader.End(); }
public void recomputeDecalInstanceBounds(int activeDecalInstanceIndex, bool redistributeToQNs) { //CLM THIS MATH IS VERY TRICKY!! PLEASE TALK TO ME BEFORE SCREWING WITH IT!!!! //CLM THIS MATH IS VERY TRICKY!! PLEASE TALK TO ME BEFORE SCREWING WITH IT!!!! //grab a list of previous QNs that we affected List <BTerrainQuadNode> oldNodes = giveNodesIntersectingDecalInstance(activeDecalInstanceIndex); BTerrainDecalInstance dcli = mDecalInstances[activeDecalInstanceIndex]; BTerrainActiveDecalContainer dcl = mActiveDecals[dcli.mActiveDecalIndex]; dcli.computeBounds(); if (redistributeToQNs) { List <BTerrainQuadNode> newNodes = giveNodesIntersectingDecalInstance(activeDecalInstanceIndex); for (int i = 0; i < newNodes.Count; i++) { //does this container already contain this decal reference? if (!newNodes[i].mLayerContainer.containsID(activeDecalInstanceIndex, BTerrainTexturingLayer.eLayerType.cLayer_Decal)) { if (newNodes[i].mLayerContainer.getNumDecalLayers() + 1 >= BTerrainTexturing.cMaxDecalsPerChunk) { MessageBox.Show("Error: This decal operation exceeds the max number of decals for one or more chunks.\n Please remove decals to get below the " + BTerrainTexturing.cMaxDecalsPerChunk + " max value."); continue; } newNodes[i].mLayerContainer.newDecalLayer(activeDecalInstanceIndex); int index = newNodes[i].mLayerContainer.giveLayerIndex(activeDecalInstanceIndex, BTerrainTexturingLayer.eLayerType.cLayer_Decal); newNodes[i].mLayerContainer.computeDecalLayerAlphaContrib(index, newNodes[i].getDesc().mMinXVert, newNodes[i].getDesc().mMinZVert); } else { int index = newNodes[i].mLayerContainer.giveLayerIndex(activeDecalInstanceIndex, BTerrainTexturingLayer.eLayerType.cLayer_Decal); newNodes[i].mLayerContainer.computeDecalLayerAlphaContrib(index, newNodes[i].getDesc().mMinXVert, newNodes[i].getDesc().mMinZVert); } //newNodes[i].getTextureData().free(); for (int lod = 0; lod < Terrain.BTerrainTexturing.cMaxNumLevels; lod++) { newNodes[i].getTextureData(lod).free(); } } //remove references from any older nodes that don't use us. for (int i = 0; i < oldNodes.Count; i++) { if (!newNodes.Contains(oldNodes[i])) { int index = oldNodes[i].mLayerContainer.giveLayerIndex(activeDecalInstanceIndex, BTerrainTexturingLayer.eLayerType.cLayer_Decal); if (index != -1) { oldNodes[i].mLayerContainer.removeLayer(index); } //oldNodes[i].getTextureData().free(); for (int lod = 0; lod < Terrain.BTerrainTexturing.cMaxNumLevels; lod++) { oldNodes[i].getTextureData(lod).free(); } } } newNodes.Clear(); newNodes = null; } oldNodes.Clear(); oldNodes = null; }
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; }