Масштабирование и поворот текстуры на другую текстуру по необработанным буферным данным

Я представил это gamedev, но они кажутся довольно медленными, поэтому я надеюсь, что смогу найти ответ здесь.

Я возился с C ++ AMP и OGRE, пытаясь сделать запись / изменение текстур по своему вкусу легче от моего имени. В этом я пытался нарисовать текстуру на моей «динамической» текстуре со странными результатами. Похоже, что 3/4 моего изображения обрезается, и это сводит меня с ума, потому что я не могу найти решение.

Вот видео проблемы: http://www.youtube.com/watch?v=uFWxHtHtqAI

И вот весь необходимый код для понимания, хотя ядро ​​действительно находится там, где есть проблема:

#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;
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;
}

Как видите, динамическая текстура — это размер окна (в нашем случае это 800×600), а minotaur.jpg — 84×84. Я просто размещаю его на половине ширины и высоты (в центре), поворачивая его на угол (радианы) и масштабируя до 4х.

В самом ядре я просто следовал 2D матрице вращения (где x и y смещены параметрами ‘x’ и ‘y’):

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

Также обратите внимание, что idx [1] представляет значение x в массиве, а idx [0] представляет y, потому что оно организовано таким образом, что value = buffer[y + (x * height)] (или что-то в этом роде, но просто знайте, что это в правильном формате).

Спасибо за любую помощь!

С Уважением,
Tannz0rz

0

Решение

Я нашел решение благодаря этому парню: 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);
}
});
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]