/// <summary> /// Dispose the hardware index and vertex buffers /// </summary> public virtual void Dispose() { indexData.indexBuffer.Dispose(); VertexBufferBinding bindings = vertexData.vertexBufferBinding; for (ushort b = 0; b < bindings.BindingCount; ++b) { bindings.GetBuffer(b).Dispose(); } }
public unsafe void CalculateNormals() { Vector3 normal; HardwareVertexBuffer buffer = null; VertexBufferBinding binding = terrain.vertexBufferBinding; if (binding != null) { buffer = binding.GetBuffer(NORMAL); } else { // int i = 0; } IntPtr norm = buffer.Lock(BufferLocking.Discard); float *normPtr = (float *)norm.ToPointer(); int count = 0; for (int j = 0; j < size; j++) { for (int i = 0; i < size; i++) { GetNormalAt(GetVertex(i, j, 0), GetVertex(i, j, 2), out normal); normPtr[count++] = normal.x; normPtr[count++] = normal.y; normPtr[count++] = normal.z; } } buffer.Unlock(); }
public void Build(bool stencilShadows, bool logDetails) { // Ok, here's where we transfer the vertices and indexes to the shared buffers VertexDeclaration dcl = vertexData.vertexDeclaration; VertexBufferBinding binds = vertexData.vertexBufferBinding; // create index buffer, and lock if (logDetails) { log.InfoFormat("GeometryBucket.Build: Creating index buffer indexType {0} indexData.indexCount {1}", indexType, indexData.indexCount); } indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(indexType, indexData.indexCount, BufferUsage.StaticWriteOnly); IntPtr indexBufferIntPtr = indexData.indexBuffer.Lock(BufferLocking.Discard); // create all vertex buffers, and lock ushort b; ushort posBufferIdx = dcl.FindElementBySemantic(VertexElementSemantic.Position).Source; List <List <VertexElement> > bufferElements = new List <List <VertexElement> >(); unsafe { byte *[] destBufferPtrs = new byte *[binds.BindingCount]; for (b = 0; b < binds.BindingCount; ++b) { int vertexCount = vertexData.vertexCount; if (logDetails) { log.InfoFormat("GeometryBucket.Build b {0}, binds.BindingCount {1}, vertexCount {2}, dcl.GetVertexSize(b) {3}", b, binds.BindingCount, vertexCount, dcl.GetVertexSize(b)); } // Need to double the vertex count for the position buffer // if we're doing stencil shadows if (stencilShadows && b == posBufferIdx) { vertexCount = vertexCount * 2; if (vertexCount > maxVertexIndex) { throw new Exception("Index range exceeded when using stencil shadows, consider " + "reducing your region size or reducing poly count"); } } HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer(dcl.GetVertexSize(b), vertexCount, BufferUsage.StaticWriteOnly); binds.SetBinding(b, vbuf); IntPtr pLock = vbuf.Lock(BufferLocking.Discard); destBufferPtrs[b] = (byte *)pLock.ToPointer(); // Pre-cache vertex elements per buffer bufferElements.Add(dcl.FindElementBySource(b)); } // iterate over the geometry items int indexOffset = 0; IEnumerator iter = queuedGeometry.GetEnumerator(); Vector3 regionCenter = parent.Parent.Parent.Center; int * pDestInt = (int *)indexBufferIntPtr.ToPointer(); ushort * pDestUShort = (ushort *)indexBufferIntPtr.ToPointer(); foreach (QueuedGeometry geom in queuedGeometry) { // copy indexes across with offset IndexData srcIdxData = geom.geometry.indexData; IntPtr srcIntPtr = srcIdxData.indexBuffer.Lock(BufferLocking.ReadOnly); if (indexType == IndexType.Size32) { int *pSrcInt = (int *)srcIntPtr.ToPointer(); for (int i = 0; i < srcIdxData.indexCount; i++) { *pDestInt++ = (*pSrcInt++) + indexOffset; } } else { ushort *pSrcUShort = (ushort *)(srcIntPtr.ToPointer()); for (int i = 0; i < srcIdxData.indexCount; i++) { *pDestUShort++ = (ushort)((*pSrcUShort++) + indexOffset); } } srcIdxData.indexBuffer.Unlock(); // Now deal with vertex buffers // we can rely on buffer counts / formats being the same VertexData srcVData = geom.geometry.vertexData; VertexBufferBinding srcBinds = srcVData.vertexBufferBinding; for (b = 0; b < binds.BindingCount; ++b) { // Iterate over vertices destBufferPtrs[b] = CopyVertices(srcBinds.GetBuffer(b), destBufferPtrs[b], bufferElements[b], geom, regionCenter); } indexOffset += geom.geometry.vertexData.vertexCount; } } // unlock everything indexData.indexBuffer.Unlock(); for (b = 0; b < binds.BindingCount; ++b) { binds.GetBuffer(b).Unlock(); } // If we're dealing with stencil shadows, copy the position data from // the early half of the buffer to the latter part if (stencilShadows) { unsafe { HardwareVertexBuffer buf = binds.GetBuffer(posBufferIdx); IntPtr src = buf.Lock(BufferLocking.Normal); byte * pSrc = (byte *)src.ToPointer(); // Point dest at second half (remember vertexcount is original count) byte *pDst = pSrc + buf.VertexSize * vertexData.vertexCount; int count = buf.VertexSize * buf.VertexCount; while (count-- > 0) { *pDst++ = *pSrc++; } buf.Unlock(); // Also set up hardware W buffer if appropriate RenderSystem rend = Root.Instance.RenderSystem; if (null != rend && rend.Caps.CheckCap(Capabilities.VertexPrograms)) { buf = HardwareBufferManager.Instance.CreateVertexBuffer(sizeof(float), vertexData.vertexCount * 2, BufferUsage.StaticWriteOnly, false); // Fill the first half with 1.0, second half with 0.0 float *pW = (float *)buf.Lock(BufferLocking.Discard).ToPointer(); for (int v = 0; v < vertexData.vertexCount; ++v) { *pW++ = 1.0f; } for (int v = 0; v < vertexData.vertexCount; ++v) { *pW++ = 0.0f; } buf.Unlock(); vertexData.hardwareShadowVolWBuffer = buf; } } } }
public void Init(TerrainOptions options) { this.options = options; numMipMaps = options.maxMipmap; size = options.size; terrain = new VertexData(); terrain.vertexStart = 0; // Turbo: appended factor 3 // Not sure about that, but without that the terrain manager seems // to mess up memory because of buffer overruns //terrain.vertexCount = options.size * options.size; terrain.vertexCount = options.size * options.size * 3; VertexDeclaration decl = terrain.vertexDeclaration; VertexBufferBinding binding = terrain.vertexBufferBinding; int offset = 0; // Position/Normal decl.AddElement(POSITION, 0, VertexElementType.Float3, VertexElementSemantic.Position); decl.AddElement(NORMAL, 0, VertexElementType.Float3, VertexElementSemantic.Normal); // TexCoords decl.AddElement(TEXCOORD, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0); offset += VertexElement.GetTypeSize(VertexElementType.Float2); decl.AddElement(TEXCOORD, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 1); offset += VertexElement.GetTypeSize(VertexElementType.Float2); // TODO: Color HardwareVertexBuffer buffer = HardwareBufferManager.Instance.CreateVertexBuffer( decl.GetVertexSize(POSITION), terrain.vertexCount, BufferUsage.StaticWriteOnly, true); binding.SetBinding(POSITION, buffer); buffer = HardwareBufferManager.Instance.CreateVertexBuffer( decl.GetVertexSize(NORMAL), terrain.vertexCount, BufferUsage.StaticWriteOnly, true); binding.SetBinding(NORMAL, buffer); buffer = HardwareBufferManager.Instance.CreateVertexBuffer( offset, terrain.vertexCount, BufferUsage.StaticWriteOnly, true); binding.SetBinding(TEXCOORD, buffer); minLevelDistSqr = new float[numMipMaps]; int endx = options.startx + options.size; int endz = options.startz + options.size; // TODO: name buffers different so we can unlock HardwareVertexBuffer posBuffer = binding.GetBuffer(POSITION); IntPtr pos = posBuffer.Lock(BufferLocking.Discard); HardwareVertexBuffer texBuffer = binding.GetBuffer(TEXCOORD); IntPtr tex = texBuffer.Lock(BufferLocking.Discard); float min = 99999999, max = 0; unsafe { float *posPtr = (float *)pos.ToPointer(); float *texPtr = (float *)tex.ToPointer(); int posCount = 0; int texCount = 0; for (int j = options.startz; j < endz; j++) { for (int i = options.startx; i < endx; i++) { float height = options.GetWorldHeight(i, j) * options.scaley; posPtr[posCount++] = (float)i * options.scalex; posPtr[posCount++] = height; posPtr[posCount++] = (float)j * options.scalez; texPtr[texCount++] = (float)i / (float)options.worldSize; texPtr[texCount++] = (float)j / (float)options.worldSize; texPtr[texCount++] = ((float)i / (float)options.size) * (float)options.detailTile; texPtr[texCount++] = ((float)j / (float)options.size) * (float)options.detailTile; if (height < min) { min = height; } if (height > max) { max = height; } } // for i } // for j } // unsafe // unlock the buffers posBuffer.Unlock(); texBuffer.Unlock(); box.SetExtents( new Vector3((float)options.startx * options.scalex, min, (float)options.startz * options.scalez), new Vector3((float)(endx - 1) * options.scalex, max, (float)(endz - 1) * options.scalez)); center = new Vector3((options.startx * options.scalex + endx - 1) / 2, (min + max) / 2, (options.startz * options.scalez + endz - 1) / 2); float C = CalculateCFactor(); CalculateMinLevelDist2(C); }
public void Init(TerrainOptions options) { this.options = options; this.numMipMaps = options.maxMipmap; this.size = options.size; this.terrain = new VertexData(); this.terrain.vertexStart = 0; this.terrain.vertexCount = options.size * options.size; VertexDeclaration decl = this.terrain.vertexDeclaration; VertexBufferBinding binding = this.terrain.vertexBufferBinding; int offset = 0; // Position/Normal decl.AddElement(POSITION, 0, VertexElementType.Float3, VertexElementSemantic.Position); decl.AddElement(NORMAL, 0, VertexElementType.Float3, VertexElementSemantic.Normal); // TexCoords decl.AddElement(TEXCOORD, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0); offset += VertexElement.GetTypeSize(VertexElementType.Float2); decl.AddElement(TEXCOORD, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 1); offset += VertexElement.GetTypeSize(VertexElementType.Float2); // TODO: Color HardwareVertexBuffer buffer = HardwareBufferManager.Instance.CreateVertexBuffer(decl.Clone(POSITION), this.terrain.vertexCount, BufferUsage.StaticWriteOnly, true); binding.SetBinding(POSITION, buffer); buffer = HardwareBufferManager.Instance.CreateVertexBuffer(decl.Clone(NORMAL), this.terrain.vertexCount, BufferUsage.StaticWriteOnly, true); binding.SetBinding(NORMAL, buffer); buffer = HardwareBufferManager.Instance.CreateVertexBuffer(decl.Clone(TEXCOORD), this.terrain.vertexCount, BufferUsage.StaticWriteOnly, true); binding.SetBinding(TEXCOORD, buffer); this.minLevelDistSqr = new float[this.numMipMaps]; int endx = options.startx + options.size; int endz = options.startz + options.size; // TODO: name buffers different so we can unlock HardwareVertexBuffer posBuffer = binding.GetBuffer(POSITION); var pos = posBuffer.Lock(BufferLocking.Discard); HardwareVertexBuffer texBuffer = binding.GetBuffer(TEXCOORD); var tex = texBuffer.Lock(BufferLocking.Discard); float min = 99999999, max = 0; #if !AXIOM_SAFE_ONLY unsafe #endif { var posPtr = pos.ToFloatPointer(); var texPtr = tex.ToFloatPointer(); int posCount = 0; int texCount = 0; for (int j = options.startz; j < endz; j++) { for (int i = options.startx; i < endx; i++) { float height = options.GetWorldHeight(i, j) * options.scaley; posPtr[posCount++] = i * options.scalex; posPtr[posCount++] = height; posPtr[posCount++] = j * options.scalez; texPtr[texCount++] = (float)i / options.worldSize; texPtr[texCount++] = (float)j / options.worldSize; texPtr[texCount++] = ((float)i / options.size) * options.detailTile; texPtr[texCount++] = ((float)j / options.size) * options.detailTile; if (height < min) { min = height; } if (height > max) { max = height; } } // for i } // for j } // unsafe // unlock the buffers posBuffer.Unlock(); texBuffer.Unlock(); this.box.SetExtents(new Vector3(options.startx * options.scalex, min, options.startz * options.scalez), new Vector3((endx - 1) * options.scalex, max, (endz - 1) * options.scalez)); this.center = new Vector3((options.startx * options.scalex + endx - 1) / 2, (min + max) / 2, (options.startz * options.scalez + endz - 1) / 2); float C = CalculateCFactor(); CalculateMinLevelDist2(C); }
public void Load() { if (inUse == false) { return; } bool bLit = Options.Instance.Lit; bool bColored = Options.Instance.Colored; bool bCoverage = Options.Instance.Coverage_Vertex_Color; bool bBase = Options.Instance.Base_Vertex_Color; bool bShadowed = Options.Instance.Vertex_Shadowed; bool bInstant_colored = Options.Instance.Vertex_Instant_Colored; float scale_x = Options.Instance.Scale.x; float scale_z = Options.Instance.Scale.z; // VertexDeclaration decl = renderOp.vertexData.vertexDeclaration; VertexBufferBinding bind = renderOp.vertexData.vertexBufferBinding; // float[] matHeight = new float[2]; // matHeight[0] = Options.Instance.MatHeight[0]; // matHeight[1] = Options.Instance.MatHeight[1]; // float absmaxHeight = Data2DManager.Instance.GetMaxHeight(); // Calculate the offset in the data long tileSize = Options.Instance.TileSize; // long offSetX = info.TileX * tileSize; // long offSetZ = info.TileZ * tileSize; long offSetX = 0; long offSetZ = 0; long endx = offSetX + tileSize; long endz = offSetZ + tileSize; //calculate min and max heights; float min = 99999999.9f; float max = 0.0f; float Aux1 = ( float )1.0f / (Options.Instance.PageSize - 1); long pageSize = Options.Instance.PageSize; float[] HeightData = Data2DManager.Instance.GetData2D(info.PageX, info.PageZ).HeightData; // long HeightDataPos = offSetZ * pageSize; long HeightDataPos = (info.TileZ * tileSize * pageSize) + (info.TileX * tileSize); float Tex1DataPos = info.TileX * tileSize; float Tex2DataPos = info.TileZ * tileSize; HardwareVertexBuffer vVertices = bind.GetBuffer(POSITION); // HardwareVertexBuffer vNormals; // HardwareVertexBuffer vTextures = bind.GetBuffer(TEXCOORD); // HardwareVertexBuffer vColors; // if ( Options.Instance.Lit) vNormals = bind.GetBuffer(NORMAL);; // if (Options.Instance.Colored || // Options.Instance.Coverage_Vertex_Color || // Options.Instance.Base_Vertex_Color) // { // vColors = bind.GetBuffer(COLORS); // } // IntPtr ipPos = vVertices.Lock(BufferLocking.Discard); // IntPtr ipTex = vTextures.Lock(BufferLocking.Discard); // IntPtr ipNrm = vNormals.Lock(BufferLocking.Discard); // IntPtr ipClr = vColors.Lock(BufferLocking.Discard); int cntPos = 0; // int cntTex = 0; // int cntNrm = 0; // int cntClr = 0; unsafe { float *pPos = (float *)ipPos.ToPointer(); // float* pNrm = (float *)ipNrm.ToPointer(); // float* pTex = (float *)ipTex.ToPointer(); // float* pClr = (float *)ipClr.ToPointer(); for (long k = offSetZ; k <= endz; k++) { float posZ = ( float )(k - offSetZ) * scale_z; for (long i = offSetX; i <= endx; i++) { float height = HeightData[i + HeightDataPos]; // // min = Math.Min(height, min); // max = Math.Max(height, max); min = height < min ? height : min; max = height > max ? height : max; // // // Position pPos[cntPos++] = ( float )((i - offSetX) * scale_x); //X pPos[cntPos++] = height; //Y pPos[cntPos++] = posZ; //Z // // normals Vector3 norm; if (bLit == true) { norm = Data2DManager.Instance.GetNormalAt(info.PageX, info.PageZ, (info.TileX * tileSize) + i, (info.TileZ * tileSize) + k); pPos[cntPos++] = norm.x; pPos[cntPos++] = norm.y; pPos[cntPos++] = norm.z; #if _VisibilityCheck //TODO: This must be moved to Preprocessing phase mTmpAngle = mConeNormal.dotProduct(norm); if (mTmpAngle > mAngle) { mAngle = mTmpAngle; } mConeNormal += norm; mConeNormal.normalise(); #endif } // Texture pPos[cntPos++] = (Tex1DataPos + i) * Aux1; //Tex1DataPos; pPos[cntPos++] = (Tex2DataPos + k) * Aux1; //Tex2DataPos; // pTex[cntTex++] = (Tex1DataPos + k) * Aux1; //Tex2DataPos; // pTex[cntTex++] = (Tex2DataPos + i) * Aux1; //Tex1DataPos; // Colors //Tex2DataPos += Aux1; } //Tex2DataPos += Aux1; HeightDataPos += pageSize; } } vVertices.Unlock(); // vTextures.Unlock(); box.SetExtents(new Vector3(0.0F, min, 0.0F), new Vector3(((float)tileSize) * scale_x, max, ((float)tileSize) * scale_z)); worldBoundingSphere.Center = box.Center; worldBoundingSphere.Radius = box.Maximum.Length; isLoaded = true; needReload = false; }