Beispiel #1
0
        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;
                    }
                }
            }
        }