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(); } }
/// <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; } } }
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 }
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); * }*/ } }
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++; } } } }
/// <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; } }
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); }
/// <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); }
/// <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); }
/// <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; } } } }
/// <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 } }
/// <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); }
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); } }
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; } } } }