/// <summary> /// /// </summary> /// <param name="texture"></param> /// <param name="channel"></param> private DensityMap(Texture texture, MapChannel channel) { Debug.Assert(texture != null); mFilter = MapFilter.Bilinear; //Add self to selfList mSelfKey = texture.Name + (int)channel; mSelfList.Add(mSelfKey, this); mRefCount = 0; //Get the texture buffer HardwarePixelBuffer buff = texture.GetBuffer(); //Prepare a PixelBox (8-bit greyscale) to receive the density values mPixels = new PixelBox(new BasicBox(0, 0, buff.Width, buff.Height), PixelFormat.BYTE_L); byte[] pixelData = new byte[mPixels.ConsecutiveSize]; mPixelPtr = Memory.PinObject(pixelData); mPixels.Data = mPixelPtr; if (channel == MapChannel.Color) { //Copy to the greyscale density map directly if no channel extraction is necessary buff.BlitToMemory(mPixels); } else { unsafe { //If channel extraction is necessary, first convert to a PF_R8G8B8A8 format PixelBox //This is necessary for the code below to properly extract the desired channel PixelBox tmpPixels = new PixelBox(new BasicBox(0, 0, buff.Width, buff.Height), PixelFormat.R8G8B8A8); byte[] tmpPix = new byte[tmpPixels.ConsecutiveSize]; byte * pixPtr = (byte *)Memory.PinObject(tmpPix); tmpPixels.Data = (IntPtr)pixPtr; buff.BlitToMemory(tmpPixels); //Pick out a channel from the pixel buffer int channelOffset = 0; switch (channel) { case MapChannel.Red: channelOffset = 3; break; case MapChannel.Green: channelOffset = 2; break; case MapChannel.Blue: channelOffset = 1; break; case MapChannel.Alpha: channelOffset = 0; break; default: //should never happen throw new Exception("Invalid channel"); } //And copy that channel into the density map byte *inputPtr = (byte *)pixPtr + channelOffset; byte *outputPtr = (byte *)pixPtr + channelOffset; byte *outputEndPtr = outputPtr + mPixels.ConsecutiveSize; while (outputPtr != outputEndPtr) { *outputPtr++ = *inputPtr++; inputPtr += 4; } //Finally, delete the temporary PF_R8G8B8A8 pixel buffer Memory.UnpinObject(tmpPix); tmpPixels = null; } } }
/// <summary> /// /// </summary> /// <param name="texture"></param> /// <param name="channel"></param> private ColorMap(Texture texture, MapChannel channel) { Debug.Assert(texture != null); mFilter = MapFilter.Bilinear; //Add self to selfList mSelfKey = texture.Name + (int)channel; mSelfList.Add(mSelfKey, this); mRefCount = 0; //Get the texture buffer HardwarePixelBuffer buff = texture.GetBuffer(); #warning Root::getSingleton().getRenderSystem()->getColourVertexElementType(); //Prepare a PixelBox (24-bit RGB) to receive the color values VertexElementType format = VertexElementType.Color_ARGB; switch (format) { case VertexElementType.Color_ARGB: //DirectX9 mPixels = new PixelBox(new BasicBox(0, 0, buff.Width, buff.Height), PixelFormat.A8B8G8R8); break; case VertexElementType.Color_ABGR: //OpenGL mPixels = new PixelBox(new BasicBox(0, 0, buff.Width, buff.Height), PixelFormat.A8B8G8R8); //Patch for Ogre's incorrect blitToMemory() when copying from PF_L8 in OpenGL if (buff.Format == PixelFormat.L8) { channel = MapChannel.Red; } break; default: throw new Exception("Unknown RenderSystem color format"); } byte[] pixelData = new byte[mPixels.ConsecutiveSize]; mPixelPtr = Memory.PinObject(pixelData); mPixels.Data = mPixelPtr; if (channel == MapChannel.Color) { //Copy to the color map directly if no channel extraction is necessary buff.BlitToMemory(mPixels); } else { unsafe { //If channel extraction is necessary, first convert to a PF_R8G8B8A8 format PixelBox //This is necessary for the code below to properly extract the desired channel PixelBox tmpPixels = new PixelBox(new BasicBox(0, 0, buff.Width, buff.Height), PixelFormat.R8G8B8A8); byte[] tmpPix = new byte[tmpPixels.ConsecutiveSize]; byte * pixPtr = (byte *)Memory.PinObject(tmpPix); tmpPixels.Data = (IntPtr)pixPtr; buff.BlitToMemory(tmpPixels); //Pick out a channel from the pixel buffer int channelOffset = 0; switch (channel) { case MapChannel.Red: channelOffset = 3; break; case MapChannel.Green: channelOffset = 2; break; case MapChannel.Blue: channelOffset = 1; break; case MapChannel.Alpha: channelOffset = 0; break; default: //should never happen throw new Exception("Invalid channel"); } //And copy that channel into the density map byte *inputPtr = (byte *)pixPtr + channelOffset; byte *outputPtr = (byte *)pixPtr + channelOffset; byte *outputEndPtr = outputPtr + mPixels.ConsecutiveSize; while (outputPtr != outputEndPtr) { *outputPtr++ = *inputPtr; *outputPtr++ = *inputPtr; *outputPtr++ = *inputPtr; *outputPtr++ = 0xFF; //Full alpha inputPtr += 4; } //Finally, delete the temporary PF_R8G8B8A8 pixel buffer Memory.UnpinObject(tmpPix); tmpPixels = null; tmpPix = null; } } }