public void moveSelectdDecalsFromEditorInput() { if (mDecalInstances.Count == 0) { return; } int xCenterGlobal = 0; int zCenterGlobal = 0; //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!!!! float vertsToHighResPixelSpaceRatio = BTerrainTexturing.getTextureWidth() / BTerrainQuadNode.cMaxWidth; int mVisTileIntetersectionX = TerrainGlobals.getEditor().mVisTileIntetersectionX; int mVisTileIntetersectionZ = TerrainGlobals.getEditor().mVisTileIntetersectionZ; Vector3 intpt = TerrainGlobals.getEditor().mBrushIntersectionPoint; for (int i = 0; i < mDecalInstances.Count; i++) { if (mDecalInstances[i].mIsSelected) { int myTileX = mVisTileIntetersectionX; // (int)((mDecalInstances[i].mTileCenter.X / vertsToHighResPixelSpaceRatio) + (diffX)); int myTileZ = mVisTileIntetersectionZ; // (int)((mDecalInstances[i].mTileCenter.Y / vertsToHighResPixelSpaceRatio) + (diffZ)); BTerrainActiveDecalContainer dcl = mActiveDecals[mDecalInstances[i].mActiveDecalIndex]; Vector3 a = TerrainGlobals.getTerrain().getPostDeformPos(myTileX, myTileZ); Vector3 b = TerrainGlobals.getTerrain().getPostDeformPos(myTileX + 1, myTileZ); Vector3 c = TerrainGlobals.getTerrain().getPostDeformPos(myTileX, myTileZ + 1); Vector3 d = TerrainGlobals.getTerrain().getPostDeformPos(myTileX + 1, myTileZ + 1); //find the max def for this tile float x1 = (float)Math.Abs(a.X - b.X); float x2 = (float)Math.Abs(c.X - d.X); float xM = x1 > x2 ? x1 : x2; float xPT = xM > 0 ? (intpt.X - a.X) / xM : 0; //gives us percentage IN THE TILE float z1 = (float)Math.Abs(a.Z - c.Z); float z2 = (float)Math.Abs(b.Z - d.Z); float zM = z1 > z2 ? z1 : z2; float zPT = zM > 0 ? (intpt.Z - a.Z) / zM : 0; //gives us percentage IN THE TILE //scale that up to percentages in the space of our pixels mDecalInstances[i].mTileCenter.X = ((xPT * vertsToHighResPixelSpaceRatio) + (myTileX * vertsToHighResPixelSpaceRatio)); mDecalInstances[i].mTileCenter.Y = ((zPT * vertsToHighResPixelSpaceRatio) + (myTileZ * vertsToHighResPixelSpaceRatio)); recomputeDecalInstanceBounds(i, true); } } }
public bool mIsSelected; //editor can select a decal instance public void computeBounds() { float vertsToHighResPixelSpaceRatio = BTerrainTexturing.getTextureWidth() / BTerrainQuadNode.cMaxWidth; BTerrainActiveDecalContainer dcl = TerrainGlobals.getTexturing().getActiveDecal(mActiveDecalIndex); int h = (int)(dcl.mWidth * (1.0f / mUScale)); int w = (int)(dcl.mHeight * (1.0f / mVScale)); //rotate our bounds float angleRad = mRotation;// -rotAngle * Math.PI / 180; float angleCos = (float)Math.Cos(angleRad); float angleSin = (float)Math.Sin(angleRad); float halfWidth = w >> 1; float halfHeight = h >> 1; float halfNewWidth, halfNewHeight; int newWidth, newHeight; // rotate corners float cx1 = halfWidth * angleCos; float cy1 = halfWidth * angleSin; float cx2 = halfWidth * angleCos - halfHeight * angleSin; float cy2 = halfWidth * angleSin + halfHeight * angleCos; float cx3 = -halfHeight * angleSin; float cy3 = halfHeight * angleCos; float cx4 = 0; float cy4 = 0; halfNewWidth = Math.Max(Math.Max(cx1, cx2), Math.Max(cx3, cx4)) - Math.Min(Math.Min(cx1, cx2), Math.Min(cx3, cx4)); halfNewHeight = Math.Max(Math.Max(cy1, cy2), Math.Max(cy3, cy4)) - Math.Min(Math.Min(cy1, cy2), Math.Min(cy3, cy4)); newWidth = (int)(halfNewWidth * 2 + 0.5); newHeight = (int)(halfNewHeight * 2 + 0.5); w = newWidth >> 1; h = newHeight >> 1; mTileBoundsMin.X = (int)((mTileCenter.X - (w)) / vertsToHighResPixelSpaceRatio); mTileBoundsMax.X = (int)((mTileCenter.X + (w)) / vertsToHighResPixelSpaceRatio); mTileBoundsMin.Y = (int)((mTileCenter.Y - (h)) / vertsToHighResPixelSpaceRatio); mTileBoundsMax.Y = (int)((mTileCenter.Y + (h)) / vertsToHighResPixelSpaceRatio); }
public void resizeSelectedDecals(float xScaleAmt, float yScaleAmt) { float vertsToHighResPixelSpaceRatio = BTerrainTexturing.getTextureWidth() / BTerrainQuadNode.cMaxWidth; for (int i = 0; i < mDecalInstances.Count; i++) { if (mDecalInstances[i].mIsSelected) { BTerrainActiveDecalContainer dcl = mActiveDecals[mDecalInstances[i].mActiveDecalIndex]; mDecalInstances[i].mUScale += xScaleAmt; mDecalInstances[i].mVScale += yScaleAmt; recomputeDecalInstanceBounds(i, true); } } }
//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 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; }