static public void rasterLightsToNode(BTerrainQuadNode node) { worldChunk wc = null; for (int x = 0; x < mWorldChunks.GetLength(0); x++) { for (int y = 0; y < mWorldChunks.GetLength(1); y++) { if (mWorldChunks[x, y].mQNPointer == node) { wc = mWorldChunks[x, y]; break; } } if (wc != null) { break; } } if (wc == null) { return; } rasterLightsToNode(wc); }
//------------------------------------------ public override bool applyToDstImg(BTerrainQuadNode node, int terrainGridX, int terrainGridZ, bool selectionMode, bool alternate) { if (!selectionMode) { return(applyToDstLayer(node, terrainGridX, terrainGridZ, selectionMode, alternate)); } return(applyMask(node, terrainGridX, terrainGridZ, alternate)); }
void renderLeafNode(BTerrainQuadNode node) { int lod = (int)BTerrainVisual.eLODLevel.cLOD0; BTerrainQuadNodeDesc desc = node.getDesc(); float scale = TerrainGlobals.getTerrain().getTileScale() * ((int)Math.Pow(2, lod)); Vector4 DataVals = new Vector4(2 * (BTerrainQuadNode.getMaxNodeWidth() >> lod), scale, desc.mMinXVert, desc.mMinZVert); mTerrainGPUShader.mShader.SetValue(mShaderDataValsHandle, DataVals); mTerrainGPUShader.mShader.CommitChanges(); BRenderDevice.getDevice().DrawPrimitives(PrimitiveType.TriangleList, 0, (int)mNumPrims); }
public override bool applyToDstImg(BTerrainQuadNode node, int x, int z, bool selectionMode, bool alternate) { BTerrainLayerContainer layers = node.mLayerContainer; BTerrainActiveDecalContainer decal = TerrainGlobals.getTexturing().getActiveDecal(TerrainGlobals.getTerrainFrontEnd().SelectedDecalIndex); bool changed = false; return(changed); }
static public bool isChunkUsed(BTerrainQuadNode node) { for (int i = 0; i < mQNChunks.Count; i++) { if (mQNChunks[i].mOwnerNodeDesc.mMinXVert == node.getDesc().mMinXVert&& mQNChunks[i].mOwnerNodeDesc.mMinZVert == node.getDesc().mMinZVert) { return(true); } } return(false); }
//------------------------------------------ //called to create the mask form the texture public unsafe bool applyMask(BTerrainQuadNode node, int x, int z, bool alternate) { UInt32 *MskPtr = mStroke.getBits(); mMskImgWidth = (uint)mStroke.cBufferSize; mMskImgHeight = (uint)mStroke.cBufferSize; bool changed = Texturing_LayerEditor.setMaskAlphaToTextureBlending(node, BTerrainTexturing.getAlphaTextureWidth(), BTerrainTexturing.getAlphaTextureWidth(), MskPtr, mMskImgWidth, mMskImgHeight, mStroke.mAlphaValue, x, z, alternate); mStroke.unlockBits(); return(changed); }
//------------------------------------------ //called to apply a texutre directly to a masked area public unsafe bool applyToMask(BTerrainQuadNode node) { bool changed = false; BTerrainQuadNodeDesc desc = node.getDesc(); changed = Texturing_LayerEditor.setIndexToMaskedArea(node, desc.mMinXVert, desc.mMinZVert, desc.mMaxXVert, desc.mMaxZVert, (char)mTexArrayIndex); if (changed) { //node.getTextureData().free(); for (int i = 0; i < Terrain.BTerrainTexturing.cMaxNumLevels; i++) { node.getTextureData(i).free(); } } return(changed); }
//------------------------------------------ //called to apply the texture to the terrain public unsafe bool applyToDstLayer(BTerrainQuadNode node, int terrainGridX, int terrainGridZ, bool selectionMode, bool alternate) { UInt32 *MskPtr = mStroke.getBits(); mMskImgWidth = (uint)mStroke.cBufferSize; mMskImgHeight = (uint)mStroke.cBufferSize; bool changed = Texturing_LayerEditor.setMaskAlphaToLayer(node, MskPtr, mMskImgWidth, mMskImgHeight, mStroke.mAlphaValue, terrainGridX, terrainGridZ, (char)mTexArrayIndex); mStroke.unlockBits(); if (changed) { //node.getTextureData().free(); for (int i = 0; i < Terrain.BTerrainTexturing.cMaxNumLevels; i++) { node.getTextureData(i).free(); } } return(true); }
public bool render() { if (mSetVBs.Count == 0) { createRenderVBs(); if (mSetVBs.Count == 0) { return(false); } } BRenderDevice.getDevice().VertexDeclaration = VertexTypes.Pos.vertDecl; //my shader is started in the parent FoliageManager class.. BTerrainQuadNode qn = TerrainGlobals.getTerrain().getQuadNodeLeafArray()[mOwnerQNIndex]; //find our visual handle index //CLM the skirts f**k this up.. just find the highest LOD that's valid... BTerrainVisualDataHandle vdh = null; for (int i = 0; i < (int)Terrain.BTerrainVisual.eLODLevel.cLODCount; i++) { if (qn.mVisualDataIndxPerLOD[i] != -1) { vdh = TerrainGlobals.getVisual().getVisualHandle(qn.mVisualDataIndxPerLOD[i]); break; } } if (vdh == null) { return(false); } //bind my QN positions texture FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mTerrainQNPosTexture, vdh.mHandle.mPositionsTexture); Vector4 QnData = new Vector4((BTerrainQuadNode.getMaxNodeWidth() >> vdh.LOD), TerrainGlobals.getTerrain().getTileScale(), mOwnerNodeDesc.mMinXVert, mOwnerNodeDesc.mMinZVert); FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mTerrainQNData, QnData); for (int setI = 0; setI < mSetsUsed.Count; setI++) { FoliageSet set = FoliageManager.giveSet(mSetsUsed[setI]); float rcpBladeImgWidth = 1.0f / (float)set.mNumBlades; FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetRCPBladeTexWidth, rcpBladeImgWidth); FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetAlbedoTexture, set.mD3DAlbedoTexture == null? BRenderDevice.getTextureManager().getDefaultTexture(TextureManager.eDefaultTextures.cDefTex_Red): set.mD3DAlbedoTexture.mTexture); FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetOpacityTexture, set.mD3DOpacityTexture == null ? BRenderDevice.getTextureManager().getDefaultTexture(TextureManager.eDefaultTextures.cDefTex_White) : set.mD3DOpacityTexture.mTexture); FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetPositionsTexture, set.mD3DPositionsTexture); FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetUVsTexture, set.mD3DUVsTexture); //DRAW US FOOL! BRenderDevice.getDevice().SetStreamSource(0, mSetVBs[setI], 0); BRenderDevice.getDevice().Indices = mSetIBs[setI]; FoliageManager.mFoliageGPUShader.mShader.CommitChanges(); BRenderDevice.getDevice().DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, mSetVertCount[setI], 0, mSetPolyCount[setI]); } return(true); }
private void makeCursorLODVB(ref VertexBuffer vb, ref uint numVerts, BTerrainVisual.eLODLevel lod) { VertexTypes.Pos[] verts = null; uint width = BTerrainQuadNode.getMaxNodeWidth(); uint vd = width * 2; uint tw = width; uint td = width; int counter = 0; switch (lod) { case BTerrainVisual.eLODLevel.cLOD0: { numVerts = (width + 1) * (width + 1); verts = new VertexTypes.Pos[numVerts]; vd = width * 2; tw = width; td = width; for (int z = 0; z < td; z++) { for (int x = 0; x < tw; x++) { int k = z + (int)(x * vd); verts[counter++].x = (k); } } } break; case BTerrainVisual.eLODLevel.cLOD1: { numVerts = (1 + (width >> 1)) * (1 + (width >> 1)); verts = new VertexTypes.Pos[numVerts]; tw = width >> 1; td = width >> 1; vd = 2 * (width >> 1); for (int x = 0; x < tw; x++) { for (int z = 0; z < td; z++) { int k = z + (int)(x * vd); verts[counter++].x = (k); } } } break; case BTerrainVisual.eLODLevel.cLOD2: { numVerts = (1 + (width >> 2)) * (1 + (width >> 2)); verts = new VertexTypes.Pos[numVerts]; tw = width >> 2; td = width >> 2; vd = 2 * (width >> 2); for (int x = 0; x < tw; x++) { for (int z = 0; z < td; z++) { int k = z + (int)(x * vd); verts[counter++].x = (k); } } } break; case BTerrainVisual.eLODLevel.cLOD3: { numVerts = (1 + (width >> 3)) * (1 + (width >> 3)); verts = new VertexTypes.Pos[numVerts]; tw = width >> 3; td = width >> 3; vd = 2 * (width >> 3); for (int x = 0; x < tw; x++) { for (int z = 0; z < td; z++) { int k = z + (int)(x * vd); verts[counter++].x = (k); } } } break; default: return; } vb = new VertexBuffer(typeof(VertexTypes.Pos), (int)numVerts, BRenderDevice.getDevice(), Usage.None, VertexFormats.Position, Pool.Managed); GraphicsStream stream = vb.Lock(0, (int)numVerts * sizeof(float) * 3, LockFlags.None); stream.Write(verts); vb.Unlock(); verts = null; }
//---------------------------------------------- unsafe static public bool setMaskAlphaToTextureBlending(BTerrainQuadNode node, uint dstImgWidth, uint dstImgHeight, UInt32 *mskImg, uint mskImgWidth, uint mskImgHeight, float intensity, int xpos, int ypos, bool alternate) { BTerrainQuadNodeDesc desc = node.getDesc(); bool changed = false; //create our position in the dst img, adjust for boundries int mskMaxX = (int)mskImgWidth; if (mskImgWidth + xpos >= dstImgWidth) { mskMaxX -= ((int)mskImgWidth) + xpos - ((int)dstImgWidth); } int mskMaxY = (int)mskImgHeight; if (mskImgHeight + ypos >= dstImgHeight) { mskMaxY -= ((int)mskImgHeight) + ypos - ((int)dstImgHeight); } int mskMinX = 0; int mskMinY = 0; if (xpos < 0) { mskMinX = -xpos; } if (ypos < 0) { mskMinY = -ypos; } //validate extents... if (mskMinX > mskImgWidth || mskMinY > mskImgHeight) { return(false); } int minX = (int)(desc.m_min.X / TerrainGlobals.getTerrain().getTileScale()); int maxX = (int)(desc.m_max.X / TerrainGlobals.getTerrain().getTileScale()); int minZ = (int)(desc.m_min.Z / TerrainGlobals.getTerrain().getTileScale()); int maxZ = (int)(desc.m_max.Z / TerrainGlobals.getTerrain().getTileScale()); for (int x = minX; x <= maxX; x++) { for (int z = minZ; z <= maxZ; z++) { int maskX = x - minX + mskMinX; int maskY = z - minZ + mskMinY; int mIP = maskX * ((int)mskImgWidth) + maskY; char alpha = (char)(((mskImg[mIP] & 0xFF000000) >> 24)); float factor = alpha / 255.0f * intensity;; int vertIndex = (int)(x * TerrainGlobals.getTerrain().getNumZVerts() + z); float curWeight = Masking.getCurrSelectionMaskWeights().GetMaskWeight(vertIndex); float newWeight; if (!alternate) { newWeight = (curWeight > factor) ? curWeight : factor; } else//CLM Changes to erasing.. { newWeight = BMathLib.Clamp(curWeight - factor, 0, 1); } Masking.addSelectedVert(x, z, newWeight); changed = true; } } return(changed); }
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); }
private void generateGridChunks(ref XTDVisualHeader header) { //Create and write our flat terrain quadnode chunks BTerrainQuadNode[] mLeafNodes = TerrainGlobals.getTerrain().getQuadNodeLeafArray(); for (int i = 0; i < mLeafNodes.Length; i++) { int width = (int)BTerrainQuadNode.getMaxNodeWidth(); ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); XTDTerrainChunk gridNode = new XTDTerrainChunk(); int locX = mLeafNodes[i].getDesc().mMinXVert / width; int locZ = mLeafNodes[i].getDesc().mMinZVert / width; gridNode.gridLocX = locX; gridNode.gridLocZ = locZ; //calculate our chunk data gridNode.heightmapOnly = false; gridNode.maxVertStride = 64; //lets get our verts, normals, and ambOcclu int mnX = locX * width; int mnZ = locZ * width; BBoundingBox bb = new BBoundingBox(); bb.empty(); for (int z = 0; z < width + 1; z++) { for (int x = 0; x < width + 1; x++) { int xVal = (int)(mnX + x); int zVal = (int)(mnZ + z); Vector3 v = TerrainGlobals.getTerrain().getPos(xVal, zVal); bb.addPoint(v); } } gridNode.mMin = bb.min; gridNode.mMax = bb.max; //IF WE CONTAIN FOLIAGE! increase the size of our bounding boxes.. if (FoliageManager.isChunkUsed(mLeafNodes[i])) { BBoundingBox bbA = FoliageManager.giveMaxBBs(); gridNode.mMin += bbA.min; gridNode.mMax += bbA.max; } //expand our box a tad float scle = TerrainGlobals.getTerrain().getTileScale(); gridNode.mMin -= new Vector3(scle, scle, scle); gridNode.mMax += new Vector3(scle, scle, scle); //send the verts off to the compressor to be compressed properly into an image (using whatever technique) //be sure to assign a corolary ID so we can reference it later. writeChunk(gridNode, binWriter); //add this chunk to our main data stream ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_TerrainChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; } mLeafNodes = null; }
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 CameraMovement() { //camera controls float incAmt = 2 * SmartSpeedupCamera(); Dir = mEye - mLookAt; mRight = Vector3.Cross(Dir, mUp); mRight = BMathLib.Normalize(mRight); Vector3 ndir = -Dir; ndir.Y = 0; ndir = BMathLib.Normalize(ndir); Vector3 kDir = BMathLib.Normalize(Dir); Vector3 inc; Matrix matRotation; int mouseDeltaX = 0; int mouseDeltaY = 0; Point currPos = Point.Empty; UIManager.GetCursorPos(ref currPos); if (mbFirstMouseIntput) { mLastMousePosX = currPos.X; mLastMousePosY = currPos.Y; mbFirstMouseIntput = false; } else { mouseDeltaX = mLastMousePosX - currPos.X; mouseDeltaY = mLastMousePosY - currPos.Y; mLastMousePosX = currPos.X; mLastMousePosY = currPos.Y; } switch (mCamMode) { case eCamModes.cCamMode_Free: case eCamModes.cCamMode_RTS: if (mCamMode == eCamModes.cCamMode_RTS) //EDGE PUSH MODE { const int edgeAmt = 20; Point size = new Point(); BRenderDevice.getParentWindowSize(ref size); Point cursorPos = Point.Empty; UIManager.GetCursorPos(ref cursorPos); if (cursorPos.Y < edgeAmt) { CheckAssignMovement(out inc, mLookAt, ndir * incAmt); mEye += inc; mLookAt += inc; } else if (cursorPos.Y > size.Y - edgeAmt) { CheckAssignMovement(out inc, mLookAt, -ndir * incAmt); mEye += inc; mLookAt += inc; } else if (cursorPos.X < edgeAmt) { CheckAssignMovement(out inc, mLookAt, -mRight * incAmt); mEye += inc; mLookAt += inc; } else if (cursorPos.X > size.X - edgeAmt) { CheckAssignMovement(out inc, mLookAt, mRight * incAmt); mEye += inc; mLookAt += inc; } } if (SimGlobals.getSimMain().isUsingDesignerControls()) { if (UIManager.GetMouseButtonDown(UIManager.eMouseButton.cMiddle) && (UIManager.GetAsyncKeyStateB(Key.LeftAlt) || UIManager.GetAsyncKeyStateB(Key.RightAlt))) { //Rotation! if (mouseDeltaX != 0 || mouseDeltaY != 0) { matRotation = Matrix.RotationAxis(mRight, Geometry.DegreeToRadian((float)-mouseDeltaY / 5.0f)); Dir.TransformCoordinate(matRotation); Vector3 t = Vector3.Normalize(Dir); if (Vector3.Dot(t, mUp) < mCamDotLimit && Vector3.Dot(t, mUp) > -mCamDotLimit) { mEye = mLookAt + Dir; } matRotation = Matrix.RotationY(Geometry.DegreeToRadian((float)-mouseDeltaX / 5.0f)); Dir.TransformCoordinate(matRotation); t = Vector3.Normalize(Dir); if (Vector3.Dot(t, mUp) < mCamDotLimit && Vector3.Dot(t, mUp) > -mCamDotLimit) { mEye = mLookAt + Dir; } } mTranslationPressed = false; } else if (UIManager.GetMouseButtonDown(UIManager.eMouseButton.cMiddle)) { if (mTranslationPressed) { float yE = mEye.Y; float yL = mLookAt.Y; Vector3 r0 = TerrainGlobals.getEditor().getRayPosFromMouseCoords(false); Vector3 rD = TerrainGlobals.getEditor().getRayPosFromMouseCoords(true) - r0; rD.Normalize(); Vector3 iPt = new Vector3(); BTerrainQuadNode node = null; TerrainGlobals.getTerrain().rayIntersects(ref r0, ref rD, ref iPt, ref node, true); Vector3 diff = mTranlationInterception - iPt; Vector3 eyeDiff = mLookAt - mEye; mLookAt += diff; mEye += diff; mLookAt.Y = yL; mEye.Y = yE; } else { mTranslationPressed = true; Vector3 r0 = TerrainGlobals.getEditor().getRayPosFromMouseCoords(false); Vector3 rD = TerrainGlobals.getEditor().getRayPosFromMouseCoords(true) - r0; rD.Normalize(); BTerrainQuadNode node = null; TerrainGlobals.getTerrain().rayIntersects(ref r0, ref rD, ref mTranlationInterception, ref node, true); } /* * //TRANSLATION * float lSq = Eye.Y * 0.3f; * float forwardInc = (float)mouseDeltaY / -20.0f; * float rightInc = (float)mouseDeltaX / 20.0f; * * Vector3 k = ndir * forwardInc + Right * rightInc; * * CheckAssignMovement(out inc, LookAt, k); * Eye += inc; * LookAt += inc; * */ } else { mTranslationPressed = false; } if ((UIManager.WheelDelta != 0) && (UIManager.GetAsyncKeyStateB(Key.LeftAlt) || UIManager.GetAsyncKeyStateB(Key.RightAlt))) { //ZOOM int sign = UIManager.WheelDelta > 0 ? -1 : 1; float heightDiff = (float)Math.Log(mEye.Y); float lSq = mEye.Y * 0.3f; Zoom = Math.Abs(lSq * (float)(UIManager.WheelDelta / 120f)); kDir.Scale(Zoom * sign); mEye += kDir; } //allow WASD || Arrow keys to translate us... if (UIManager.GetAsyncKeyStateB(Key.W) || UIManager.GetAsyncKeyStateB(Key.UpArrow) || UIManager.GetAsyncKeyStateB(Key.NumPad8)) { if (UIManager.GetAsyncKeyStateB(Key.LeftAlt) || UIManager.GetAsyncKeyStateB(Key.RightAlt)) { //ZOOM int sign = UIManager.WheelDelta > 0 ? -1 : 1; Zoom = 2 * (float)(UIManager.WheelDelta / 120f); kDir.Scale(Zoom * sign); mEye -= kDir; } else { CheckAssignMovement(out inc, mLookAt, ndir * incAmt); mEye += inc; mLookAt += inc; } } if (UIManager.GetAsyncKeyStateB(Key.S) || UIManager.GetAsyncKeyStateB(Key.DownArrow) || UIManager.GetAsyncKeyStateB(Key.NumPad2)) { if (UIManager.GetAsyncKeyStateB(Key.LeftAlt) || UIManager.GetAsyncKeyStateB(Key.RightAlt)) { //ZOOM int sign = UIManager.WheelDelta > 0 ? -1 : 1; Zoom = 2 * (float)(UIManager.WheelDelta / 120f); kDir.Scale(Zoom * sign); mEye += kDir; } else { CheckAssignMovement(out inc, mLookAt, -ndir * incAmt); mEye += inc; mLookAt += inc; } } if (UIManager.GetAsyncKeyStateB(Key.A) || UIManager.GetAsyncKeyStateB(Key.LeftArrow) || UIManager.GetAsyncKeyStateB(Key.NumPad4)) { CheckAssignMovement(out inc, mLookAt, -mRight * incAmt); mEye += inc; mLookAt += inc; } if (UIManager.GetAsyncKeyStateB(Key.D) || UIManager.GetAsyncKeyStateB(Key.RightArrow) || UIManager.GetAsyncKeyStateB(Key.NumPad6)) { CheckAssignMovement(out inc, mLookAt, mRight * incAmt); mEye += inc; mLookAt += inc; } } else //artist camera controls { Dir.Scale(Zoom); Zoom = 1; if ((UIManager.GetAsyncKeyStateB(Key.LeftShift)) || (UIManager.GetAsyncKeyStateB(Key.RightShift)) || (CoreGlobals.getSettingsFile().ArtistModePan == false && UIManager.GetMouseButtonDown(UIManager.eMouseButton.cMiddle))) { if (UIManager.GetAsyncKeyStateB(Key.LeftControl) || UIManager.GetAsyncKeyStateB(Key.RightControl)) { if (mbInvertZoom == true) { mouseDeltaY = -1 * mouseDeltaY; } Zoom = 1 + mouseDeltaY / 100f; mEye = mLookAt + Dir; } else if (!UIManager.GetMouseButtonDown(UIManager.eMouseButton.cLeft)) { //Rotation! if (mouseDeltaX != 0 || mouseDeltaY != 0) { matRotation = Matrix.RotationAxis(mRight, Geometry.DegreeToRadian((float)-mouseDeltaY / 5.0f)); Dir.TransformCoordinate(matRotation); Vector3 t = Vector3.Normalize(Dir); if (Vector3.Dot(t, mUp) < mCamDotLimit && Vector3.Dot(t, mUp) > -mCamDotLimit) { mEye = mLookAt + Dir; } matRotation = Matrix.RotationY(Geometry.DegreeToRadian((float)-mouseDeltaX / 5.0f)); Dir.TransformCoordinate(matRotation); t = Vector3.Normalize(Dir); if (Vector3.Dot(t, mUp) < mCamDotLimit && Vector3.Dot(t, mUp) > -mCamDotLimit) { mEye = mLookAt + Dir; } } } // Do nothing if control key is pressed if (UIManager.GetAsyncKeyStateB(Key.LeftControl) || UIManager.GetAsyncKeyStateB(Key.RightControl)) { return; } } else if (UIManager.GetMouseButtonDown(UIManager.eMouseButton.cMiddle)) { if (mTranslationPressed) { float yE = mEye.Y; float yL = mLookAt.Y; Vector3 r0 = TerrainGlobals.getEditor().getRayPosFromMouseCoords(false); Vector3 rD = TerrainGlobals.getEditor().getRayPosFromMouseCoords(true) - r0; rD.Normalize(); Vector3 iPt = new Vector3(); BTerrainQuadNode node = null; TerrainGlobals.getTerrain().rayIntersects(ref r0, ref rD, ref iPt, ref node, true); Vector3 diff = mTranlationInterception - iPt; Vector3 eyeDiff = mLookAt - mEye; mLookAt += diff; mEye += diff; mLookAt.Y = yL; mEye.Y = yE; } else { mTranslationPressed = true; Vector3 r0 = TerrainGlobals.getEditor().getRayPosFromMouseCoords(false); Vector3 rD = TerrainGlobals.getEditor().getRayPosFromMouseCoords(true) - r0; rD.Normalize(); BTerrainQuadNode node = null; TerrainGlobals.getTerrain().rayIntersects(ref r0, ref rD, ref mTranlationInterception, ref node, true); } } else { mTranslationPressed = false; if (UIManager.GetAsyncKeyStateB(Key.W) || UIManager.GetAsyncKeyStateB(Key.UpArrow) || UIManager.GetAsyncKeyStateB(Key.NumPad8)) { CheckAssignMovement(out inc, mLookAt, ndir * incAmt); mEye += inc; mLookAt += inc; } if (UIManager.GetAsyncKeyStateB(Key.S) || UIManager.GetAsyncKeyStateB(Key.DownArrow) || UIManager.GetAsyncKeyStateB(Key.NumPad2)) { CheckAssignMovement(out inc, mLookAt, -ndir * incAmt); mEye += inc; mLookAt += inc; } if (UIManager.GetAsyncKeyStateB(Key.A) || UIManager.GetAsyncKeyStateB(Key.LeftArrow) || UIManager.GetAsyncKeyStateB(Key.NumPad4)) { CheckAssignMovement(out inc, mLookAt, -mRight * incAmt); mEye += inc; mLookAt += inc; } if (UIManager.GetAsyncKeyStateB(Key.D) || UIManager.GetAsyncKeyStateB(Key.RightArrow) || UIManager.GetAsyncKeyStateB(Key.NumPad6)) { CheckAssignMovement(out inc, mLookAt, mRight * incAmt); mEye += inc; mLookAt += inc; } } } if (UIManager.GetAsyncKeyStateB(Key.Space) && (UIManager.GetAsyncKeyStateB(Key.LeftShift) || UIManager.GetAsyncKeyStateB(Key.RightShift))) { SimGlobals.getSimMain().LookAtSelectedObject(); } else if (UIManager.GetAsyncKeyStateB(Key.Space)) { snapCamera(eCamSnaps.cCamSnap_RTS); } break; case eCamModes.cCamMode_ModelView: { if (UIManager.GetMouseButtonDown(UIManager.eMouseButton.cMiddle) && (UIManager.GetAsyncKeyStateB(Key.LeftAlt) || UIManager.GetAsyncKeyStateB(Key.RightAlt))) { // Orbit camera if (mouseDeltaX != 0 || mouseDeltaY != 0) { matRotation = Matrix.RotationAxis(mRight, Geometry.DegreeToRadian((float)-mouseDeltaY / 5.0f)); Dir.TransformCoordinate(matRotation); Vector3 t = Vector3.Normalize(Dir); if (Vector3.Dot(t, mUp) < mCamDotLimit && Vector3.Dot(t, mUp) > -mCamDotLimit) { mEye = mLookAt + Dir; } matRotation = Matrix.RotationY(Geometry.DegreeToRadian((float)-mouseDeltaX / 5.0f)); Dir.TransformCoordinate(matRotation); t = Vector3.Normalize(Dir); if (Vector3.Dot(t, mUp) < mCamDotLimit && Vector3.Dot(t, mUp) > -mCamDotLimit) { mEye = mLookAt + Dir; } } } else if (UIManager.GetMouseButtonDown(UIManager.eMouseButton.cMiddle)) { // Translate (pan) float distFromModel = Vector3.Length(mEye - mModelBoundingBox.getCenter()); float translationFactor = distFromModel / 1400.0f; float upInc = (float)mouseDeltaY * translationFactor; float rightInc = (float)mouseDeltaX * translationFactor; Vector3 up = Vector3.Cross(Dir, mRight); up = BMathLib.Normalize(up); Vector3 tranlation = up * upInc + mRight * rightInc; mEye += tranlation; mLookAt += tranlation; } if (UIManager.WheelDelta != 0) { // Zoom float distFromModel = Vector3.Length(mEye - mModelBoundingBox.getCenter()); float translationFactor = -distFromModel / 10.0f; mEye += kDir * (translationFactor * (UIManager.WheelDelta / 120f)); } if (UIManager.GetAsyncKeyStateB(Key.Space)) { snapCamera(eCamSnaps.cCamSnap_ModelView); } } break; } }
public abstract bool applyToDstImg(BTerrainQuadNode node, int terrainGridX, int terrainGridZ, bool selectionMode, bool alternate);
//CLM USED FOR GAME public unsafe void convertLayersToTexturingDataHandle(BTerrainLayerContainer input, BTerrainCompositeTexture output, BTerrainQuadNode node, int lod) { //lock in our alpha texture BTerrainQuadNodeDesc desc = node.getDesc(); int numlayers = input.getNumLayers(); BTerrainLayerContainer tContainer = TerrainGlobals.getEditor().generateContainerFromTexDeformations(desc.mMinXVert, desc.mMinZVert); if (tContainer == null) { tContainer = input; } tContainer.toTextureArray(ref mTempAlphaTextures, desc.mMinXVert, desc.mMinZVert); convertLayersToTexturingDataHandle(tContainer, mTempAlphaTextures, output, desc.mMinXVert, desc.mMinZVert, lod, (int)BTerrainTexturing.eTextureChannels.cSplatChannelCount); tContainer = null; }
public void calcHeightRaycastWorker(object workerObjectDat) { Random rnd = new Random(); heightGenWorkerData packet = workerObjectDat as heightGenWorkerData; bool doRacyast = true; for (int x = (int)packet.minXVert; x < (int)packet.maxXVert; x++) { for (int z = (int)packet.minZVert; z < (int)packet.maxZVert; z++) { if (!doRacyast) { float u = (float)(x / ((float)mWidth - 1)); float v = (float)(z / ((float)mHeight - 1)); float h = TerrainGlobals.getTerrain().getHeightParametric(u, v); if (h > mHeights[x * mWidth + z]) { mHeights[x * mWidth + z] = h; } } else if (doRacyast) { //only if we're used in a tile that is passable bool sharesPassable = false; if (!TerrainGlobals.getEditor().getSimRep().getDataTiles().isLandObstructedComposite(x, z)) { sharesPassable |= true; } if (!TerrainGlobals.getEditor().getSimRep().getDataTiles().isLandObstructedComposite(x - 1, z)) { sharesPassable |= true; } if (!TerrainGlobals.getEditor().getSimRep().getDataTiles().isLandObstructedComposite(x - 1, z - 1)) { sharesPassable |= true; } if (!TerrainGlobals.getEditor().getSimRep().getDataTiles().isLandObstructedComposite(x, z - 1)) { sharesPassable |= true; } if (sharesPassable) { float xzoff = 0.01f; Vector3 origin = new Vector3(x * mTileScale + xzoff, TerrainGlobals.getTerrain().getBBMax().Y, z * mTileScale + xzoff); Vector3 dir = -BMathLib.unitY; Vector3 intPt = new Vector3(); BTerrainQuadNode ownerNode = new BTerrainQuadNode(); if (TerrainGlobals.getTerrain().rayIntersects(ref origin, ref dir, ref intPt, ref ownerNode, false)) { if (intPt.Y > mHeights[x * mWidth + z]) { mHeights[x * mWidth + z] = intPt.Y + 0.001f; } } else { // mHeights[x * mWidth + z] = 200.0f; if (x != 0 && z != 0 && x < mWidth && z < mHeight) { break; } bool hit = false; for (int i = 0; i < 4; i++) { dir = -BMathLib.unitY; origin.X = (x * mTileScale + xzoff) + ((float)(rnd.NextDouble() * 0.2f) - 0.1f); origin.Z = (z * mTileScale + xzoff) + ((float)(rnd.NextDouble() * 0.2f) - 0.1f); //origin.Y = TerrainGlobals.getTerrain().getBBMax().Y; if (TerrainGlobals.getTerrain().rayIntersects(ref origin, ref dir, ref intPt, ref ownerNode, false)) { if (intPt.Y > mHeights[x * mWidth + z]) { mHeights[x * mWidth + z] = intPt.Y; hit = true; break; } } } } } } } } Interlocked.Decrement(ref mWorkInc); if (mWorkInc <= 0) { mWorkCompleted.Set(); } }
public void evaluateLOD(Vector3 pt, Vector3 eye, BTerrainLayerContainer layers, BTerrainQuadNode ownerQN)//CLM this is only called on visible nodes { mAgePrediction = mAgePrediction | 0x00000001; int lod = TerrainGlobals.getTexturing().getTextureLODLevel(pt, eye); if (lod != mTextureLODLevel)// || mCompositeTexture==null || mCompositeTexture.mState==eCompositeTextureState.cCS_Free) { mTextureLODLevel = lod; if (mCompositeTexture != null) { mCompositeTexture.free(); mCompositeTexture = null; } /* * mCompositeTexture = TerrainGlobals.getTexturing().getCompositeTexture((int)(BTerrainTexturing.getTextureWidth() >> mTextureLODLevel), (int)(BTerrainTexturing.getTextureHeight() >> mTextureLODLevel)); * if (mCompositeTexture != null) * { * mCompositeTexture.mOwnerNode = ownerQN; * layers.convertToTexturingDataHandle(ref mCompositeTexture); * }*/ } }
private void writeTessData(bool refineTerrain, float eLOD, float minorityBias, ref ExportResults results) { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); //write the 'header' int nodeWidth = 16; int numXPatches = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)nodeWidth); int numZPatches = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)nodeWidth); int numXChunks = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)BTerrainQuadNode.getMaxNodeDepth()); int numPatches = numXPatches * numZPatches; binWriter.Write(Xbox_EndianSwap.endSwapI32(numXPatches)); binWriter.Write(Xbox_EndianSwap.endSwapI32(numZPatches)); //do this for each patch byte[] tDat = new byte[numPatches]; Vector4[] bbDat = new Vector4[numPatches * 2]; //CLM - instead of writing floating point values (and taking up more memory) //write indexes into our discrete step array if (refineTerrain) { ErrorMetricRefine refiner = null; refiner = new ErrorMetricRefine(); refiner.init(TerrainGlobals.getTerrain().getNumXVerts(), TerrainGlobals.getTerrain().getNumZVerts()); refiner.refine(eLOD);//, nodeWidth + 1); markOverrideTessellations(refiner); for (int x = 0; x < numXPatches; x++) { for (int z = 0; z < numZPatches; z++) { int xMinVert = x * nodeWidth; int zMinVert = z * nodeWidth; tDat[x + z * numXPatches] = giveMaxTesselation(ref refiner, xMinVert, zMinVert, nodeWidth, minorityBias); } } refiner.destroy(); refiner = null; smoothTessNeighbors(tDat, numXPatches, numZPatches); } else { for (int i = 0; i < numPatches; i++) { tDat[i] = 0; } } //write to the disk for (int i = 0; i < tDat.Length; i++) { binWriter.Write(tDat[i]); } //generate and write our bounding boxes for (int x = 0; x < numXPatches; x++) { for (int z = 0; z < numZPatches; z++) { Vector4 min = new Vector4(9000, 9000, 9000, 0); Vector4 max = new Vector4(-9000, -9000, -9000, 0); for (int i = 0; i < nodeWidth + 1; i++) { for (int j = 0; j < nodeWidth + 1; j++) { int xVal = x * nodeWidth + i; int zVal = z * nodeWidth + j; if (xVal >= TerrainGlobals.getTerrain().getNumXVerts() || zVal >= TerrainGlobals.getTerrain().getNumXVerts()) { continue; } long kIndex = xVal + TerrainGlobals.getTerrain().getNumXVerts() * zVal; Vector3 v = TerrainGlobals.getTerrain().getPos(xVal, zVal); if (v.X < min.X) { min.X = v.X; } if (v.Y < min.Y) { min.Y = v.Y; } if (v.Z < min.Z) { min.Z = v.Z; } if (v.X > max.X) { max.X = v.X; } if (v.Y > max.Y) { max.Y = v.Y; } if (v.Z > max.Z) { max.Z = v.Z; } } } //NOTE: THE GAME EXPECTS THIS DATA IN NON-SWIZZLED FORM int q = x + z * numZPatches; q *= 2; bbDat[q] = min; bbDat[q + 1] = max; } } for (int i = 0; i < bbDat.Length; i++) { binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].X)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].Y)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].Z)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].W)); } ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_TessChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; results.terrainTessValuesMemorySize = tDat.Length + (bbDat.Length * sizeof(float) * 4); tDat = null; bbDat = null; }