示例#1
0
        public virtual void Copy(BufferBase src, int srcOffset, int destOffset, int length)
        {
            if (src == null || srcOffset < 0 || destOffset < 0 || length < 0)
            {
                throw new ArgumentException();
            }

            // Ensure we don't read past the end of either buffer.
            if ((src.Ptr + srcOffset) + length > src.Length || (this.Ptr + destOffset) + length > this.Length)
            {
                throw new ArgumentOutOfRangeException();
            }
        }
示例#2
0
        /// <summary>
        /// Sets buffers to a specified value
        /// </summary>
        /// <remarks>
        /// Sets the first length values of dest to the value "c".
        /// Make sure that the destination buffer has enough room for at least length characters.
        /// </remarks>
        /// <param name="dest">Destination pointer.</param>
        /// <param name="c">Value to set.</param>
        /// <param name="length">Number of bytes to set.</param>
        public static void Set(BufferBase dest, byte c, int length)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var ptr = dest.ToBytePointer();

                for (var i = 0; i < length; i++)
                {
                    ptr[i] = c;
                }
            }
        }
示例#3
0
文件: Buffer.cs 项目: bostich83/axiom
        public override void Copy(BufferBase src, int srcOffset, int destOffset, int length)
        {
            base.Copy(src, srcOffset, destOffset, length);

            if (src is ManagedBuffer)
            {
                Buffer.BlockCopy((src as ManagedBuffer).Buf, (src as ManagedBuffer).IdxPtr + srcOffset, this.Buf,
                                 this.IdxPtr + destOffset, length);
            }
#if !AXIOM_SAFE_ONLY
            else if (src is UnsafeBuffer)
            {
                Marshal.Copy((IntPtr)((int)src.Pin() + srcOffset), this.Buf, this.IdxPtr + destOffset, length);
                src.UnPin();
            }
#endif
        }
示例#4
0
            private void CopyIndexes(BufferBase src, BufferBase dst, int count, int indexOffset)
            {
                if (indexOffset == 0)
                {
                    Memory.Copy(src, dst, count);
                }
                else
                {
                    //FIXME

                    /*
                     * while( count-- != 0)
                     * {
                     * dst++ = static_cast<T>(*src++ + indexOffset);
                     * }*/
                }
            }
示例#5
0
文件: Buffer.cs 项目: bostich83/axiom
        public override void Copy(BufferBase src, int srcOffset, int destOffset, int length)
        {
            base.Copy(src, srcOffset, destOffset, length);

            unsafe
            {
                if (src is ManagedBuffer)
                {
                    Marshal.Copy((src as ManagedBuffer).Buf, (src as ManagedBuffer).IdxPtr + srcOffset,
                                 (IntPtr)(this.PtrBuf + destOffset), length);
                }
                else if (src is UnsafeBuffer)
                {
                    var pSrc  = src.ToBytePointer();
                    var pDest = this.ToBytePointer();

                    //Following code snippet was taken from http://msdn.microsoft.com/en-us/library/28k1s2k6(v=vs.80).aspx
                    var ps = pSrc + srcOffset;
                    var pd = pDest + destOffset;

                    // Loop over the count in blocks of 4 bytes, copying an integer (4 bytes) at a time:
                    for (var i = 0; i < length / 4; i++)
                    {
                        *((int *)pd) = *((int *)ps);
                        pd          += 4;
                        ps          += 4;
                    }

                    // Complete the copy by moving any bytes that weren't moved in blocks of 4:
                    for (var i = 0; i < length % 4; i++)
                    {
                        *pd = *ps;
                        pd++;
                        ps++;
                    }
                }
            }
        }
示例#6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="lockedBuffer"></param>
        /// <param name="startIdx"></param>
        /// <param name="stepSize"></param>
        /// <param name="numSteps"></param>
        /// <param name="iterations"></param>
        protected void SubdivideCurve(BufferBase lockedBuffer, int startIdx, int stepSize, int numSteps, int iterations)
        {
            // Subdivides a curve within a sparsely populated buffer (gaps are already there to be interpolated into)
            int  leftIdx, rightIdx, destIdx, halfStep, maxIdx;
            bool firstSegment;

            maxIdx = startIdx + (numSteps * stepSize);
            var step = stepSize;

            while (iterations-- > 0)
            {
                halfStep     = step / 2;
                leftIdx      = startIdx;
                destIdx      = leftIdx + halfStep;
                rightIdx     = leftIdx + step;
                firstSegment = true;

                while (leftIdx < maxIdx)
                {
                    // Interpolate
                    InterpolateVertexData(lockedBuffer, leftIdx, rightIdx, destIdx);

                    // If 2nd or more segment, interpolate current left between current and last mid points
                    if (!firstSegment)
                    {
                        InterpolateVertexData(lockedBuffer, leftIdx - halfStep, leftIdx + halfStep, leftIdx);
                    }
                    // Next segment
                    leftIdx      = rightIdx;
                    destIdx      = leftIdx + halfStep;
                    rightIdx     = leftIdx + step;
                    firstSegment = false;
                }

                step = halfStep;
            }
        }
示例#7
0
        public virtual void LoadImages(Image[] images)
        {
            if (images.Length < 1)
            {
                throw new AxiomException("Cannot load empty vector of images");
            }

            // Set desired texture size and properties from images[0]
            this.srcWidth  = this.width = images[0].Width;
            this.srcHeight = this.height = images[0].Height;
            this.srcDepth  = this.depth = images[0].Depth;

            // Get source image format and adjust if required
            this.srcFormat = images[0].Format;
            if (this.treatLuminanceAsAlpha && this.srcFormat == PixelFormat.L8)
            {
                this.srcFormat = PixelFormat.A8;
            }

            if (this.desiredFormat != PixelFormat.Unknown)
            {
                // If have desired format, use it
                this.format = this.desiredFormat;
            }
            else
            {
                // Get the format according with desired bit depth
                this.format = PixelUtil.GetFormatForBitDepths(this.srcFormat, this.desiredIntegerBitDepth,
                                                              this.desiredFloatBitDepth);
            }

            // The custom mipmaps in the image have priority over everything
            var imageMips = images[0].NumMipMaps;

            if (imageMips > 0)
            {
                this.mipmapCount = this.requestedMipmapCount = imageMips;
                // Disable flag for auto mip generation
                this.usage &= ~TextureUsage.AutoMipMap;
            }

            // Create the texture
            CreateInternalResources();

            // Check if we're loading one image with multiple faces
            // or a vector of images representing the faces
            int  faces;
            bool multiImage;             // Load from multiple images?

            if (images.Length > 1)
            {
                faces      = images.Length;
                multiImage = true;
            }
            else
            {
                faces      = images[0].NumFaces;
                multiImage = false;
            }

            // Check wether number of faces in images exceeds number of faces
            // in this texture. If so, clamp it.
            if (faces > FaceCount)
            {
                faces = FaceCount;
            }

            // Say what we're doing
            if (TextureManager.Instance.Verbose)
            {
                var msg = new StringBuilder();
                msg.AppendFormat("Texture: {0}: Loading {1} faces( {2}, {3}x{4}x{5} ) with", _name, faces,
                                 PixelUtil.GetFormatName(images[0].Format), images[0].Width, images[0].Height,
                                 images[0].Depth);
                if (!(this.mipmapsHardwareGenerated && this.mipmapCount == 0))
                {
                    msg.AppendFormat(" {0}", this.mipmapCount);
                }

                if ((this.usage & TextureUsage.AutoMipMap) == TextureUsage.AutoMipMap)
                {
                    msg.AppendFormat("{0} generated mipmaps", this.mipmapsHardwareGenerated ? " hardware" : string.Empty);
                }
                else
                {
                    msg.Append(" custom mipmaps");
                }

                msg.AppendFormat(" from {0}.\n\t", multiImage ? "multiple Images" : "an Image");

                // Print data about first destination surface
                var buf = GetBuffer(0, 0);
                msg.AppendFormat(" Internal format is {0} , {1}x{2}x{3}.", PixelUtil.GetFormatName(buf.Format), buf.Width,
                                 buf.Height, buf.Depth);

                LogManager.Instance.Write(msg.ToString());
            }

            // Main loading loop
            // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips
            for (var mip = 0; mip <= imageMips; ++mip)
            {
                for (var i = 0; i < faces; ++i)
                {
                    PixelBox src;
                    if (multiImage)
                    {
                        // Load from multiple images
                        src = images[i].GetPixelBox(0, mip);
                    }
                    else
                    {
                        // Load from faces of images[0]
                        src = images[0].GetPixelBox(i, mip);
                    }

                    // Sets to treated format in case is difference
                    src.Format = this.srcFormat;

                    if (this.gamma != 1.0f)
                    {
                        // Apply gamma correction
                        // Do not overwrite original image but do gamma correction in temporary buffer
                        var bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, src.Format);
                        var buff    = new byte[bufSize];
                        var buffer  = BufferBase.Wrap(buff);

                        var corrected = new PixelBox(src.Width, src.Height, src.Depth, src.Format, buffer);
                        PixelConverter.BulkPixelConversion(src, corrected);

                        Image.ApplyGamma(corrected.Data, this.gamma, corrected.ConsecutiveSize, PixelUtil.GetNumElemBits(src.Format));

                        // Destination: entire texture. BlitFromMemory does
                        // the scaling to a power of two for us when needed
                        GetBuffer(i, mip).BlitFromMemory(corrected);
                    }
                    else
                    {
                        // Destination: entire texture. BlitFromMemory does
                        // the scaling to a power of two for us when needed
                        GetBuffer(i, mip).BlitFromMemory(src);
                    }
                }
            }

            // Update size (the final size, not including temp space)
            Size = FaceCount * PixelUtil.GetMemorySize(this.width, this.height, this.depth, this.format);
        }
示例#8
0
 /// <summary>
 ///	Method for copying data from one IntPtr to another.
 /// </summary>
 /// <param name="src">Source pointer.</param>
 /// <param name="dest">Destination pointer.</param>
 /// <param name="srcOffset">Offset at which to copy from the source pointer.</param>
 /// <param name="destOffset">Offset at which to begin copying to the destination pointer.</param>
 /// <param name="length">Length of data (in bytes) to copy.</param>
 public static void Copy(BufferBase src, BufferBase dest, int srcOffset, int destOffset, int length)
 {
     Contract.RequiresNotNull(dest, "dest");
     dest.Copy(src, srcOffset, destOffset, length);
 }
示例#9
0
 /// <summary>
 ///	Method for copying data from one IntPtr to another.
 /// </summary>
 /// <param name="src">Source pointer.</param>
 /// <param name="dest">Destination pointer.</param>
 /// <param name="length">Length of data (in bytes) to copy.</param>
 public static void Copy(BufferBase src, BufferBase dest, int length)
 {
     Copy(src, dest, 0, 0, length);
 }
示例#10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="lockedBuffer"></param>
        /// <param name="leftIndex"></param>
        /// <param name="rightIndex"></param>
        /// <param name="destIndex"></param>
        protected void InterpolateVertexData(BufferBase lockedBuffer, int leftIndex, int rightIndex, int destIndex)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var vertexSize  = this.declaration.GetVertexSize(0);
                var elemPos     = this.declaration.FindElementBySemantic(VertexElementSemantic.Position);
                var elemNorm    = this.declaration.FindElementBySemantic(VertexElementSemantic.Normal);
                var elemDiffuse = this.declaration.FindElementBySemantic(VertexElementSemantic.Diffuse);
                var elemTex0    = this.declaration.FindElementBySemantic(VertexElementSemantic.TexCoords, 0);
                var elemTex1    = this.declaration.FindElementBySemantic(VertexElementSemantic.TexCoords, 1);

                //byte* pDestChar, pLeftChar, pRightChar;

                // Set up pointers & interpolate
                var pDest  = (lockedBuffer + (vertexSize * destIndex));
                var pLeft  = (lockedBuffer + (vertexSize * leftIndex));
                var pRight = (lockedBuffer + (vertexSize * rightIndex));

                // Position
                var pDestReal  = (pDest + elemPos.Offset).ToFloatPointer();
                var pLeftReal  = (pLeft + elemPos.Offset).ToFloatPointer();
                var pRightReal = (pRight + elemPos.Offset).ToFloatPointer();

                pDestReal[0] = (pLeftReal[0] + pRightReal[0]) * 0.5f;
                pDestReal[1] = (pLeftReal[1] + pRightReal[1]) * 0.5f;
                pDestReal[2] = (pLeftReal[2] + pRightReal[2]) * 0.5f;

                if (elemNorm != null)
                {
                    // Normals
                    pDestReal  = (pDest + elemNorm.Offset).ToFloatPointer();
                    pLeftReal  = (pLeft + elemNorm.Offset).ToFloatPointer();
                    pRightReal = (pRight + elemNorm.Offset).ToFloatPointer();

                    var norm = Vector3.Zero;
                    norm.x = (pLeftReal[0] + pRightReal[0]) * 0.5f;
                    norm.y = (pLeftReal[1] + pRightReal[1]) * 0.5f;
                    norm.z = (pLeftReal[2] + pRightReal[2]) * 0.5f;
                    norm.Normalize();

                    pDestReal[0] = norm.x;
                    pDestReal[1] = norm.y;
                    pDestReal[2] = norm.z;
                }
                if (elemDiffuse != null)
                {
                    // Blend each byte individually
                    var pDestChar  = (pDest + elemDiffuse.Offset).ToBytePointer();
                    var pLeftChar  = (pLeft + elemDiffuse.Offset).ToBytePointer();
                    var pRightChar = (pRight + elemDiffuse.Offset).ToBytePointer();

                    // 4 bytes to RGBA
                    pDestChar[0] = (byte)((pLeftChar[0] + pRightReal[0]) * 0.5f);
                    pDestChar[1] = (byte)((pLeftChar[1] + pRightChar[1]) * 0.5f);
                    pDestChar[2] = (byte)((pLeftChar[2] + pRightChar[2]) * 0.5f);
                    pDestChar[3] = (byte)((pLeftChar[3] + pRightChar[3]) * 0.5f);
                }
                if (elemTex0 != null)
                {
                    // Blend each byte individually
                    pDestReal  = (pDest + elemTex0.Offset).ToFloatPointer();
                    pLeftReal  = (pLeft + elemTex0.Offset).ToFloatPointer();
                    pRightReal = (pRight + elemTex0.Offset).ToFloatPointer();

                    for (var dim = 0; dim < VertexElement.GetTypeCount(elemTex0.Type); dim++)
                    {
                        pDestReal[dim] = (pLeftReal[dim] + pRightReal[dim]) * 0.5f;
                    }
                }
                if (elemTex1 != null)
                {
                    // Blend each byte individually
                    pDestReal  = (pDest + elemTex1.Offset).ToFloatPointer();
                    pLeftReal  = (pLeft + elemTex1.Offset).ToFloatPointer();
                    pRightReal = (pRight + elemTex1.Offset).ToFloatPointer();

                    for (var dim = 0; dim < VertexElement.GetTypeCount(elemTex1.Type); dim++)
                    {
                        pDestReal[dim] = (pLeftReal[dim] + pRightReal[dim]) * 0.5f;
                    }
                }
            }
        }
示例#11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="lockedBuffer"></param>
        protected void DistributeControlPoints(BufferBase lockedBuffer)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                // Insert original control points into expanded mesh
                var uStep = 1 << this.uLevel;
                var vStep = 1 << this.vLevel;


                var elemPos     = this.declaration.FindElementBySemantic(VertexElementSemantic.Position);
                var elemNorm    = this.declaration.FindElementBySemantic(VertexElementSemantic.Normal);
                var elemTex0    = this.declaration.FindElementBySemantic(VertexElementSemantic.TexCoords, 0);
                var elemTex1    = this.declaration.FindElementBySemantic(VertexElementSemantic.TexCoords, 1);
                var elemDiffuse = this.declaration.FindElementBySemantic(VertexElementSemantic.Diffuse);

                var pSrc       = this.controlPointBuffer;
                var vertexSize = this.declaration.GetVertexSize(0);

                for (var v = 0; v < this.meshHeight; v += vStep)
                {
                    // set dest by v from base
                    var pDest = lockedBuffer + (vertexSize * this.meshWidth * v);

                    for (var u = 0; u < this.meshWidth; u += uStep)
                    {
                        // Copy Position
                        var pSrcReal  = (pSrc + elemPos.Offset).ToFloatPointer();
                        var pDestReal = (pDest + elemPos.Offset).ToFloatPointer();
                        pDestReal[0] = pSrcReal[0];
                        pDestReal[1] = pSrcReal[1];
                        pDestReal[2] = pSrcReal[2];

                        // Copy Normals
                        if (elemNorm != null)
                        {
                            pSrcReal     = (pSrc + elemNorm.Offset).ToFloatPointer();
                            pDestReal    = (pDest + elemNorm.Offset).ToFloatPointer();
                            pDestReal[0] = pSrcReal[0];
                            pDestReal[1] = pSrcReal[1];
                            pDestReal[2] = pSrcReal[2];
                        }

                        // Copy Diffuse
                        if (elemDiffuse != null)
                        {
                            var pSrcRGBA  = (pSrc + elemDiffuse.Offset).ToIntPointer();
                            var pDestRGBA = (pDest + elemDiffuse.Offset).ToIntPointer();
                            pDestRGBA[0] = pSrcRGBA[0];
                        }

                        // Copy texture coords
                        if (elemTex0 != null)
                        {
                            pSrcReal  = (pSrc + elemTex0.Offset).ToFloatPointer();
                            pDestReal = (pDest + elemTex0.Offset).ToFloatPointer();
                            for (var dim = 0; dim < VertexElement.GetTypeCount(elemTex0.Type); dim++)
                            {
                                pDestReal[dim] = pSrcReal[dim];
                            }
                        }
                        if (elemTex1 != null)
                        {
                            pSrcReal  = (pSrc + elemTex1.Offset).ToFloatPointer();
                            pDestReal = (pDest + elemTex1.Offset).ToFloatPointer();
                            for (var dim = 0; dim < VertexElement.GetTypeCount(elemTex1.Type); dim++)
                            {
                                pDestReal[dim] = pSrcReal[dim];
                            }
                        }

                        // Increment source by one vertex
                        pSrc += vertexSize;
                        // Increment dest by 1 vertex * uStep
                        pDest += vertexSize * uStep;
                    }             // u
                }                 // v
            }
        }
示例#12
0
        /// <summary>
        ///     Sets up the surface by defining it's control points, type and initial subdivision level.
        /// </summary>
        /// <remarks>
        ///     This method initialises the surface by passing it a set of control points. The type of curves to be used
        ///     are also defined here, although the only supported option currently is a bezier patch. You can also
        ///     specify a global subdivision level here if you like, although it is recommended that the parameter
        ///     is left as AUTO_LEVEL, which means the system decides how much subdivision is required (based on the
        ///     curvature of the surface).
        /// </remarks>
        /// <param name="controlPointArray">
        ///     An array containing the vertex data which define control points of the curves
        ///     rather than actual vertices. Note that you are expected to provide not
        ///     just position information, but potentially normals and texture coordinates too.
        ///     The array is internally treated as a contiguous memory buffer without any gaps between the elements.
        ///     The format of the buffer is defined in the VertexDeclaration parameter.
        /// </param>
        /// <param name="declaration">
        ///     VertexDeclaration describing the contents of the buffer.
        ///     Note this declaration must _only_ draw on buffer source 0!
        /// </param>
        /// <param name="width">Specifies the width of the patch in control points.</param>
        /// <param name="height">Specifies the height of the patch in control points.</param>
        /// <param name="type">The type of surface.</param>
        /// <param name="uMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision,
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="vMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision,
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="visibleSide">Determines which side of the patch (or both) triangles are generated for.</param>
        public void DefineSurface(Array controlPointArray, VertexDeclaration declaration, int width, int height,
                                  PatchSurfaceType type, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel,
                                  VisibleSide visibleSide)
        {
            if (height == 0 || width == 0)
            {
                return;                 // Do nothing - garbage
            }

            //pin the input to have a pointer
            Memory.UnpinObject(controlPointArray);
            this.controlPointBuffer = Memory.PinObject(controlPointArray);

            this.type          = type;
            this.controlWidth  = width;
            this.controlHeight = height;
            this.controlCount  = width * height;
            this.declaration   = declaration;

            // Copy positions into Vector3 vector
            this.controlPoints.Clear();
            var elem     = declaration.FindElementBySemantic(VertexElementSemantic.Position);
            var vertSize = declaration.GetVertexSize(0);

#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var pVert = this.controlPointBuffer;
                for (var i = 0; i < this.controlCount; i++)
                {
                    var pReal = (pVert + ((i * vertSize) + elem.Offset)).ToFloatPointer();
                    this.controlPoints.Add(new Vector3(pReal[0], pReal[1], pReal[2]));
                }
            }
            this.side = visibleSide;

            // Determine max level
            // Initialize to 100% detail
            this.subdivisionFactor = 1.0f;

            if (uMaxSubdivisionLevel == AUTO_LEVEL)
            {
                this.uLevel = this.maxULevel = GetAutoULevel();
            }
            else
            {
                this.uLevel = this.maxULevel = uMaxSubdivisionLevel;
            }

            if (vMaxSubdivisionLevel == AUTO_LEVEL)
            {
                this.vLevel = this.maxVLevel = GetAutoVLevel();
            }
            else
            {
                this.vLevel = this.maxVLevel = vMaxSubdivisionLevel;
            }

            // Derive mesh width / height
            this.meshWidth  = (LevelWidth(this.maxULevel) - 1) * ((this.controlWidth - 1) / 2) + 1;
            this.meshHeight = (LevelWidth(this.maxVLevel) - 1) * ((this.controlHeight - 1) / 2) + 1;

            // Calculate number of required vertices / indexes at max resolution
            this.requiredVertexCount = this.meshWidth * this.meshHeight;
            var iterations = (this.side == VisibleSide.Both) ? 2 : 1;
            this.requiredIndexCount = (this.meshWidth - 1) * (this.meshHeight - 1) * 2 * iterations * 3;

            // Calculate bounds based on control points
            var min         = Vector3.Zero;
            var max         = Vector3.Zero;
            var maxSqRadius = 0.0f;
            var first       = true;

            for (var i = 0; i < this.controlPoints.Count; i++)
            {
                var vec = this.controlPoints[i];
                if (first)
                {
                    min         = max = vec;
                    maxSqRadius = vec.LengthSquared;
                    first       = false;
                }
                else
                {
                    min.Floor(vec);
                    max.Ceil(vec);
                    maxSqRadius = Utility.Max(vec.LengthSquared, maxSqRadius);
                }
            }

            // set the bounds of the patch
            this.aabb.SetExtents(min, max);
            this.boundingSphereRadius = Utility.Sqrt(maxSqRadius);
        }
示例#13
0
            protected int CopyVertices(HardwareVertexBuffer srcBuf, BufferBase pDst, List <VertexElement> elems,
                                       QueuedGeometry geom, Vector3 regionCenter)
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    // lock source
                    var src    = srcBuf.Lock(BufferLocking.ReadOnly);
                    var bufInc = srcBuf.VertexSize;

                    var temp = Vector3.Zero;

                    // Calculate elem sizes outside the loop
                    var elemSizes = new int[elems.Count];
                    for (var i = 0; i < elems.Count; i++)
                    {
                        elemSizes[i] = VertexElement.GetTypeSize(elems[i].Type);
                    }

                    // Move the position offset calculation outside the loop
                    var positionDelta = geom.position - regionCenter;

                    for (var v = 0; v < geom.geometry.vertexData.vertexCount; ++v)
                    {
                        // iterate over vertex elements
                        for (var i = 0; i < elems.Count; i++)
                        {
                            var elem     = elems[i];
                            var pSrcReal = (src + elem.Offset).ToFloatPointer();
                            var pDstReal = (pDst + elem.Offset).ToFloatPointer();

                            switch (elem.Semantic)
                            {
                            case VertexElementSemantic.Position:
                                temp.x = pSrcReal[0];
                                temp.y = pSrcReal[1];
                                temp.z = pSrcReal[2];
                                // transform
                                temp        = (geom.orientation * (temp * geom.scale));
                                pDstReal[0] = temp.x + positionDelta.x;
                                pDstReal[1] = temp.y + positionDelta.y;
                                pDstReal[2] = temp.z + positionDelta.z;
                                break;

                            case VertexElementSemantic.Normal:
                            case VertexElementSemantic.Tangent:
                            case VertexElementSemantic.Binormal:
                                temp.x = pSrcReal[0];
                                temp.y = pSrcReal[1];
                                temp.z = pSrcReal[2];
                                // rotation only
                                temp        = geom.orientation * temp;
                                pDstReal[0] = temp.x;
                                pDstReal[1] = temp.y;
                                pDstReal[2] = temp.z;
                                break;

                            default:
                                // just raw copy
                                var size = elemSizes[i];
                                // Optimize the loop for the case that
                                // these things are in units of 4
                                if ((size & 0x3) == 0x3)
                                {
                                    var cnt = size / 4;
                                    while (cnt-- > 0)
                                    {
                                        pDstReal[cnt] = pSrcReal[cnt];
                                    }
                                }
                                else
                                {
                                    // Fall back to the byte-by-byte copy
                                    var pbSrc = (src + elem.Offset).ToBytePointer();
                                    var pbDst = (pDst + elem.Offset).ToBytePointer();
                                    while (size-- > 0)
                                    {
                                        pbDst[size] = pbSrc[size];
                                    }
                                }
                                break;
                            }
                        }

                        // Increment both pointers
                        pDst.Ptr += bufInc;
                        src.Ptr  += bufInc;
                    }

                    srcBuf.Unlock();
                    return(pDst.Ptr);
                }
            }
示例#14
0
            public void Build(bool stencilShadows, int logLevel)
            {
                // Ok, here's where we transfer the vertices and indexes to the shared buffers
                var dcl   = this.vertexData.vertexDeclaration;
                var binds = this.vertexData.vertexBufferBinding;

                // create index buffer, and lock
                if (logLevel <= 1)
                {
                    LogManager.Instance.Write("GeometryBucket.Build: Creating index buffer indexType {0} indexData.indexCount {1}",
                                              this.indexType, this.indexData.indexCount);
                }
                this.indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(this.indexType,
                                                                                              this.indexData.indexCount,
                                                                                              BufferUsage.StaticWriteOnly);
                var indexBufferIntPtr = this.indexData.indexBuffer.Lock(BufferLocking.Discard);

                // create all vertex buffers, and lock
                short b;
                var   posBufferIdx = dcl.FindElementBySemantic(VertexElementSemantic.Position).Source;

                var bufferElements = new List <List <VertexElement> >();

#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    var destBufferPtrs = new BufferBase[binds.BindingCount];
                    for (b = 0; b < binds.BindingCount; ++b)
                    {
                        var vertexCount = this.vertexData.vertexCount;
                        if (logLevel <= 1)
                        {
                            LogManager.Instance.Write(
                                "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 > this.maxVertexIndex)
                            {
                                throw new Exception("Index range exceeded when using stencil shadows, consider " +
                                                    "reducing your region size or reducing poly count");
                            }
                        }
                        var vbuf = HardwareBufferManager.Instance.CreateVertexBuffer(dcl.Clone(b), vertexCount,
                                                                                     BufferUsage.StaticWriteOnly);
                        binds.SetBinding(b, vbuf);
                        var pLock = vbuf.Lock(BufferLocking.Discard);
                        destBufferPtrs[b] = pLock;
                        // Pre-cache vertex elements per buffer
                        bufferElements.Add(dcl.FindElementBySource(b));
                    }

                    // iterate over the geometry items
                    var         indexOffset  = 0;
                    IEnumerator iter         = this.queuedGeometry.GetEnumerator();
                    var         regionCenter = this.parent.Parent.Parent.Center;
                    var         pDestInt     = indexBufferIntPtr.ToIntPointer();
                    var         pDestUShort  = indexBufferIntPtr.ToUShortPointer();
                    foreach (var geom in this.queuedGeometry)
                    {
                        // copy indexes across with offset
                        var srcIdxData = geom.geometry.indexData;
                        var srcIntPtr  = srcIdxData.indexBuffer.Lock(BufferLocking.ReadOnly);
                        if (this.indexType == IndexType.Size32)
                        {
                            var pSrcInt = srcIntPtr.ToIntPointer();
                            for (var i = 0; i < srcIdxData.indexCount; i++)
                            {
                                pDestInt[i] = pSrcInt[i] + indexOffset;
                            }
                        }
                        else
                        {
                            var pSrcUShort = srcIntPtr.ToUShortPointer();
                            for (var i = 0; i < srcIdxData.indexCount; i++)
                            {
                                pDestUShort[i] = (ushort)(pSrcUShort[i] + indexOffset);
                            }
                        }

                        srcIdxData.indexBuffer.Unlock();

                        // Now deal with vertex buffers
                        // we can rely on buffer counts / formats being the same
                        var srcVData = geom.geometry.vertexData;
                        var srcBinds = srcVData.vertexBufferBinding;
                        for (b = 0; b < binds.BindingCount; ++b)
                        {
                            // Iterate over vertices
                            destBufferPtrs[b].Ptr = CopyVertices(srcBinds.GetBuffer(b), destBufferPtrs[b], bufferElements[b], geom,
                                                                 regionCenter);
                        }
                        indexOffset += geom.geometry.vertexData.vertexCount;
                    }
                }

                // unlock everything
                this.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)
                {
#if !AXIOM_SAFE_ONLY
                    unsafe
#endif
                    {
                        var buf  = binds.GetBuffer(posBufferIdx);
                        var src  = buf.Lock(BufferLocking.Normal);
                        var pSrc = src.ToBytePointer();
                        // Point dest at second half (remember vertexcount is original count)
                        var pDst = (src + (buf.VertexSize * this.vertexData.vertexCount)).ToBytePointer();

                        var count = buf.VertexSize * buf.VertexCount;
                        while (count-- > 0)
                        {
                            pDst[count] = pSrc[count];
                        }
                        buf.Unlock();

                        // Also set up hardware W buffer if appropriate
                        var rend = Root.Instance.RenderSystem;
                        if (null != rend && rend.Capabilities.HasCapability(Capabilities.VertexPrograms))
                        {
                            var decl = HardwareBufferManager.Instance.CreateVertexDeclaration();
                            decl.AddElement(0, 0, VertexElementType.Float1, VertexElementSemantic.Position);
                            buf = HardwareBufferManager.Instance.CreateVertexBuffer(decl, this.vertexData.vertexCount * 2,
                                                                                    BufferUsage.StaticWriteOnly, false);
                            // Fill the first half with 1.0, second half with 0.0
                            var pbuf = buf.Lock(BufferLocking.Discard).ToFloatPointer();
                            var pW   = 0;
                            for (var v = 0; v < this.vertexData.vertexCount; ++v)
                            {
                                pbuf[pW++] = 1.0f;
                            }
                            for (var v = 0; v < this.vertexData.vertexCount; ++v)
                            {
                                pbuf[pW++] = 0.0f;
                            }
                            buf.Unlock();
                            this.vertexData.hardwareShadowVolWBuffer = buf;
                        }
                    }
                }
            }