Question

I submitted this to gamedev, but they seem rather slow so I hope I could find an answer here.

I've been messing with C++ AMP and OGRE in attempt to make writing to/altering textures to my liking easier on my behalf. In this I've been trying to draw a texture onto my "dynamic" texture with strange results. It appears that a solid 3/4 of my image is cropped off and it's driving me mad as I cannot seem to find the fix.

Here's a video of the problem: http://www.youtube.com/watch?v=uFWxHtHtqAI

And here's all of the necessary code for the sake of understanding even though the kernel is really where the issue at hand rests:

DynamicTexture.h

#define ValidTexCoord(x, y, width, height) ((x) >= 0 && (x) < (width) && (y) >= 0 && (y) < (height))

void TextureKernel(array<uint32, 2> &buffer, array_view<uint32, 2> texture, uint32 x, uint32 y, Real rot, Real scale, bool alpha)
{
    Real
        c = cos(-rot) / scale,
        s = sin(-rot) / scale;
    int32
        //e = int32(sqrt((texture.extent[1] * texture.extent[1]) + (texture.extent[0] * texture.extent[0])) * scale * 0.5F),
        dx = texture.extent[1] / 2,
        dy = texture.extent[0] / 2;

    parallel_for_each(buffer.extent, [=, &buffer](index<2> idx) restrict(amp)
    {
        int32
            tex_x = int32((Real(idx[1] - x) * c) - (Real(idx[0] - y) * s)) + dx,
            tex_y = int32((Real(idx[1] - x) * s) + (Real(idx[0] - y) * c)) + dy;

        if(ValidTexCoord(tex_x, tex_y, texture.extent[1], texture.extent[0]))
        {
            if(!alpha || (alpha && texture(tex_y, tex_x) != 0))
            {
                buffer(idx) = texture(tex_y, tex_x);
            }
        }
        else
        {
            buffer(idx) = 0x336699FF;
        }
    });
}

template<typename T, int32 Rank>
void SetKernel(array<T, Rank> &arr, T val)
{
    parallel_for_each(arr.extent, [&arr, val](index<Rank> idx) restrict(amp)
    {
        arr(idx) = val;
    }); 
}

class DynamicTexture
{
    static int32
        id;

    array<uint32, 2>
        buffer;

public:
    const int32
        width, 
        height;

    TexturePtr
        textureptr;

    DynamicTexture(const int32 width, const int32 height, uint32 color = 0) : 
        width(width),
        height(height),
        buffer(extent<2>(height, width))
    {
        SetKernel(buffer, color);

        textureptr = TextureManager::getSingleton().createManual("DynamicTexture" + StringConverter::toString(++id), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TextureType::TEX_TYPE_2D, width, height, 0, PixelFormat::PF_A8R8G8B8);
    }

    ~DynamicTexture()
    {
    }

    void Texture(TexturePtr texture, uint32 x, uint32 y, Real rot = 0.F, Real scale = 1.F, bool alpha = false)
    {
        HardwarePixelBufferSharedPtr 
            pixelbuffer = texture->getBuffer();

        TextureKernel(buffer, array_view<uint32, 2>(texture->getHeight(), texture->getWidth(), (uint32 *)pixelbuffer->lock(HardwareBuffer::HBL_READ_ONLY)), x, y, rot, scale, alpha);

        pixelbuffer->unlock();
    }

    void CopyToBuffer()
    {
        HardwarePixelBufferSharedPtr 
            pixelbuffer = textureptr->getBuffer();

        copy(buffer, stdext::make_checked_array_iterator<uint32 *>((uint32 *)pixelbuffer->lock(HardwareBuffer::HBL_DISCARD), width * height));

        pixelbuffer->unlock();
    }

    void Reset(uint32 color)
    {
        SetKernel(buffer, color);
    }
};

int32 
    DynamicTexture::id = 0;

main.cpp

void initScene()
{
    dynamictexture = new DynamicTexture(window->getWidth(), window->getHeight());

    TextureManager::getSingleton().load("minotaur.jpg", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TextureType::TEX_TYPE_2D, 0);
}

bool frameStarted(const FrameEvent &evt) 
{
    static Real
        ang = 0.F;

    ang += 0.05F;

    if(ang > Math::TWO_PI)
    {
        ang = 0.F;
    }

    dynamictexture->Reset(0);
    dynamictexture->Texture(TextureManager::getSingleton().getByName("minotaur.jpg"), dynamictexture->width / 2, dynamictexture->height / 2, ang, 4.F, true);
    dynamictexture->CopyToBuffer();

    return true; 
}

As you can see, the dynamic texture is the size of the window (which in this case is 800x600) and the minotaur.jpg is 84x84. I'm simply placing it at half the width and height (center), rotating it by ang (radians), and scaling it to 4x.

In the kernel itself, I simply followed a 2D rotation matrix (where x and y are offset by the parameters 'x' and 'y'):

x' = x cosθ - y sinθ
y' = x sinθ + y cosθ

Also note that idx[1] represents the x value in the array and idx[0] represents the y because it's arranged in the manner that value = buffer[y + (x * height)] (or something along those lines, but just know it's in the correct format).

Thanks for any and all help!

Regards, Tannz0rz

Était-ce utile?

La solution

I found the solution thanks to this guy: https://sites.google.com/site/ofauckland/examples/rotating-pixels

const Real
    HALF_PI = Math::HALF_PI;
const int32
    cx = texture.extent[1] / 2,
    cy = texture.extent[0] / 2;

parallel_for_each(buffer.extent, [=, &buffer](index<2> idx) restrict(amp)
{
    int32
        tex_x = idx[1] - x,
        tex_y = idx[0] - y;
    Real
        dist = sqrt(Real((tex_x * tex_x) + (tex_y * tex_y))) / scale,
        theta = atan2(Real(tex_y), Real(tex_x)) - angle - HALF_PI;

    tex_x = int32(dist * sin(theta)) + cx;
    tex_y = int32(dist * cos(theta)) + cy;

    if(ValidTexCoord(tex_x, tex_y, texture.extent[1], texture.extent[0]))
    {
        buffer(idx) = texture(tex_y, tex_x);
    }
});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top