I have made a patch, for openGL and direct3d (no software yet), i will post the code/patches in irrEXT in the next day or so. For now, here is a demo.
Code: Select all
http://owned.co.za/rotatedemo.zip
Code: Select all
http://owned.co.za/rotatedemo.zip
Hmmm So have I. lol.I have made a patch, for openGL and direct3d (no software yet), i will post the code/patches in irrEXT in the next day or so. For now, here is a demo.
Code: Select all
//! Rotates and Draws a part of the texture into the rectangle.
void CSoftwareDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor * const colors, bool useAlphaChannelOfTexture,
f32 angleInDegree)
{
if (texture)
{
if (texture->getDriverType() != EDT_SOFTWARE)
{
os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR);
return;
}
bool isScaled = (destRect.getSize() != sourceRect.getSize());
if (isScaled)
{
//! make a copy that is scaled to fit the destRect.
core::dimension2di size = destRect.getSize();
video::IImage * scaledImage = createImage(texture->getColorFormat(), core::dimension2d<u32>((u32)size.Width, (u32)size.Height));
((CSoftwareTexture*)texture)->getImage()->copyToScalingBoxFilter(scaledImage);
if (!scaledImage)
return;
const core::rect<s32> scaledSourceRect(0, 0, destRect.getSize().Width, destRect.getSize().Height);
if (useAlphaChannelOfTexture)
scaledImage->copyToWithAlpha(
RenderTargetSurface, destRect.UpperLeftCorner, scaledSourceRect, colors->color, clipRect);
else
scaledImage->copyTo(
RenderTargetSurface, destRect.UpperLeftCorner, scaledSourceRect, clipRect);
scaledImage->drop();
return;
}
if (useAlphaChannelOfTexture)
((CSoftwareTexture*)texture)->getImage()->copyToWithAlpha(
RenderTargetSurface, destRect.UpperLeftCorner, sourceRect, colors->color, clipRect);
else
((CSoftwareTexture*)texture)->getImage()->copyTo(
RenderTargetSurface, destRect.UpperLeftCorner, sourceRect, clipRect);
}
}
Code: Select all
Add the following code the COpenGLDriver.h
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
const core::rect<s32>& sourceRect, const f32 rotation = 0, const bool filtering = false,
const core::vector2df scale = core::vector2df(1.0f, 1.0f),
SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false);
Add the following code the COpenGLDriver.cpp
void COpenGLDriver::draw2DImage(const video::ITexture* texture,
const core::position2d<s32>& pos,
const core::rect<s32>& sourceRect,
const f32 rotation,
const bool filtering,
const core::vector2df scale,
SColor color,
bool useAlphaChannelOfTexture)
{
if (!texture)
return;
if (!sourceRect.isValid())
return;
core::position2d<s32> targetPos(pos);
core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner);
// This needs to be signed as it may go negative.
core::dimension2d<s32> sourceSize(sourceRect.getSize());
//FuzzYspo0N :: Needed for scaling the image.
core::vector2df vSourceSize = core::vector2df(f32(sourceSize.Width), f32(sourceSize.Height));
//FuzzYspo0N :: Start at the origin (thanks Josie)
core::rectf imageRect = core::rectf(0, 0, vSourceSize.X, vSourceSize.Y);
core::rectf scaleRect = imageRect;
core::vector2df destCenter = imageRect.getCenter() + core::vector2df(f32(targetPos.X), f32(targetPos.Y));
//FuzzYspo0N :: Points for rendering
core::vector2df topLeft = core::vector2df();
core::vector2df topRight = core::vector2df();
core::vector2df bottomLeft = core::vector2df();
core::vector2df bottomRight = core::vector2df();
//FuzzYspo0N :: Handle scaling of the verts
if(!scale.equals(core::vector2df(1.0f, 1.0f)))
{
//FuzzYspo0N :: Resize the rectangle
imageRect.LowerRightCorner.X *= scale.X;
imageRect.LowerRightCorner.Y *= scale.Y;
//FuzzYspo0N :: Update the translation
imageRect += core::vector2df(f32(destCenter.X - (imageRect.getWidth() / 2.0f)), f32(destCenter.Y - (imageRect.getHeight() / 2.0f)));
scaleRect.UpperLeftCorner = imageRect.UpperLeftCorner;
scaleRect.LowerRightCorner = imageRect.LowerRightCorner;
//FuzzYspo0N :: Adjust rendering coords
topLeft = scaleRect.UpperLeftCorner;
bottomRight = scaleRect.LowerRightCorner;
topRight = core::vector2df(scaleRect.LowerRightCorner.X, scaleRect.UpperLeftCorner.Y);
bottomLeft = core::vector2df(scaleRect.UpperLeftCorner.X, scaleRect.LowerRightCorner.Y);
}
else
{
scaleRect += core::vector2df(f32(targetPos.X), f32(targetPos.Y));
//FuzzYspo0N :: Adjust rendering coords
topLeft = scaleRect.UpperLeftCorner;
bottomRight = scaleRect.LowerRightCorner;
topRight = core::vector2df(scaleRect.LowerRightCorner.X, scaleRect.UpperLeftCorner.Y);
bottomLeft = core::vector2df(scaleRect.UpperLeftCorner.X, scaleRect.LowerRightCorner.Y);
}
//FuzzYspo0N :: Simple rotation of the verts.
f32 lRotation = rotation; // Local rotation
if(lRotation > 0.0f)
{
if(lRotation > 360.0f)
{
//Just cap it for logical reasons.
lRotation = fmodf(lRotation, 360.0f);
}
//Rotate the points seperately
topLeft.rotateBy(rotation, destCenter);
topRight.rotateBy(rotation, destCenter);
bottomLeft.rotateBy(rotation, destCenter);
bottomRight.rotateBy(rotation, destCenter);
}
//FuzzYspo0N :: Some clarity on the clipping. Dont draw when its off screen, when it was offscreen it was "shifted".
const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
core::rectf renderSize = core::rectf(0.0f, 0.0f, f32(renderTargetSize.Width), f32(renderTargetSize.Height));
if(!renderSize.isPointInside(topLeft) && !renderSize.isPointInside(topRight) && !renderSize.isPointInside(bottomLeft) && !renderSize.isPointInside(bottomRight))
{
//FuzzYspo0N :: Offscreen , dont bother rendering
return;
}
// ok, we've clipped everything.
// now draw it.
// texcoords need to be flipped horizontally for RTTs
const bool isRTT = texture->isRenderTarget();
const core::dimension2d<u32>& ss = texture->getOriginalSize();
const f32 invW = 1.f / static_cast<f32>(ss.Width);
const f32 invH = 1.f / static_cast<f32>(ss.Height);
const core::rect<f32> tcoords(
sourcePos.X * invW,
(isRTT?(sourcePos.Y + sourceSize.Height):sourcePos.Y) * invH,
(sourcePos.X + sourceSize.Width) * invW,
(isRTT?sourcePos.Y:(sourcePos.Y + sourceSize.Height)) * invH);
const core::rect<s32> poss(targetPos, sourceSize);
disableTextures(1);
if (!setActiveTexture(0, texture))
return;
setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
//FuzzYspo0N :: Adding filtering option, default in irrlicht is DISABLED, so enabling it only causes a state change, and back (at the end)
if(filtering)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
glBegin(GL_QUADS);
//Upper left
glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
glVertex2f(GLfloat(topLeft.X), GLfloat(topLeft.Y));
//Top right
glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
glVertex2f(GLfloat(topRight.X), GLfloat(topRight.Y));
//Bottom right
glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
glVertex2f(GLfloat(bottomRight.X), GLfloat(bottomRight.Y));
//Bottom left
glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
glVertex2f(GLfloat(bottomLeft.X), GLfloat(bottomLeft.Y));
glEnd();
//FuzzYspo0N :: Reset the states
if(filtering)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
}
Woops, Tecan you are right. This is meant to be in include/IVideoDriver.h , and the empty declarations need to exist in every driver present in your irrlicht buildour patch is all screwy, the line numbers dont match the svn
Code: Select all
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
const core::rect<s32>& sourceRect, const f32 rotation = 0, const bool filtering = false,
const core::vector2df scale = core::vector2df(1.0f, 1.0f),
SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) =0;
Code: Select all
//Get mouse position
core::vector2di pos2 = device->getCursorControl()->getPosition();
//Get new sizes/rotations
f32 myRotation = (pos2.X / 800.0f) * 360.0f;
f32 myScale = (pos2.Y / 600.0f) * 2.0f;
//sprite is 200, 100 so centered is 300, 250. Draw it here, and apply new changes (rot, sca)
driver->draw2DImage(tex, core::vector2di(300, 250), core::recti(0,0, tex->getOriginalSize().Width, tex->getOriginalSize().Height), myRotation, true, myScale, video::SColor(255,255,255,255), true);
Don't be sorry.Also, Ulf. I don't agree with your implementation. Sorry!
Code: Select all
void CD3D9Driver::draw2DImage(const video::ITexture* texture,
const core::position2d<s32>& pos,
const core::rect<s32>& sourceRect,
const f32 rotation,
const bool filtering,
const core::vector2df scale,
SColor color,
bool useAlphaChannelOfTexture)
{
if (!texture)
return;
if (!sourceRect.isValid())
return;
if (!setActiveTexture(0, const_cast<video::ITexture*>(texture)))
return;
core::position2d<s32> targetPos = pos;
core::position2d<s32> sourcePos = sourceRect.UpperLeftCorner;
// This needs to be signed as it may go negative.
core::dimension2d<s32> sourceSize(sourceRect.getSize());
//FuzzYspo0N :: Needed for scaling the image.
core::vector2df vSourceSize = core::vector2df(f32(sourceSize.Width), f32(sourceSize.Height));
//FuzzYspo0N :: Start at the origin (thanks Josie)
core::rectf imageRect = core::rectf(0, 0, vSourceSize.X, vSourceSize.Y);
core::rectf scaleRect = imageRect;
core::vector2df destCenter = imageRect.getCenter() + core::vector2df(f32(targetPos.X), f32(targetPos.Y));
//FuzzYspo0N :: Points for rendering
core::vector2df topLeft = core::vector2df();
core::vector2df topRight = core::vector2df();
core::vector2df bottomLeft = core::vector2df();
core::vector2df bottomRight = core::vector2df();
//FuzzYspo0N :: Handle scaling of the verts
if(!scale.equals(core::vector2df(1.0f, 1.0f)))
{
//FuzzYspo0N :: Resize the rectangle
imageRect.LowerRightCorner.X *= scale.X;
imageRect.LowerRightCorner.Y *= scale.Y;
//FuzzYspo0N :: Update the translation
imageRect += core::vector2df(f32(destCenter.X - (imageRect.getWidth() / 2.0f)), f32(destCenter.Y - (imageRect.getHeight() / 2.0f)));
scaleRect.UpperLeftCorner = imageRect.UpperLeftCorner;
scaleRect.LowerRightCorner = imageRect.LowerRightCorner;
//FuzzYspo0N :: Adjust rendering coords
topLeft = scaleRect.UpperLeftCorner;
bottomRight = scaleRect.LowerRightCorner;
topRight = core::vector2df(scaleRect.LowerRightCorner.X, scaleRect.UpperLeftCorner.Y);
bottomLeft = core::vector2df(scaleRect.UpperLeftCorner.X, scaleRect.LowerRightCorner.Y);
}
else
{
scaleRect += core::vector2df(f32(targetPos.X), f32(targetPos.Y));
//FuzzYspo0N :: Adjust rendering coords
topLeft = scaleRect.UpperLeftCorner;
bottomRight = scaleRect.LowerRightCorner;
topRight = core::vector2df(scaleRect.LowerRightCorner.X, scaleRect.UpperLeftCorner.Y);
bottomLeft = core::vector2df(scaleRect.UpperLeftCorner.X, scaleRect.LowerRightCorner.Y);
}
//FuzzYspo0N :: Simple rotation of the verts.
f32 lRotation = rotation; // Local rotation
if(lRotation > 0.0f)
{
if(lRotation > 360.0f)
{
//Just cap it for logical reasons.
lRotation = fmodf(lRotation, 360.0f);
}
//Rotate the points seperately
topLeft.rotateBy(rotation, destCenter);
topRight.rotateBy(rotation, destCenter);
bottomLeft.rotateBy(rotation, destCenter);
bottomRight.rotateBy(rotation, destCenter);
}
//FuzzYspo0N :: Some clarity on the clipping. Dont draw when its off screen, when it was offscreen it was "shifted".
const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
core::rectf renderSize = core::rectf(0.0f, 0.0f, f32(renderTargetSize.Width), f32(renderTargetSize.Height));
// clip these coordinates
if(!renderSize.isPointInside(topLeft) && !renderSize.isPointInside(topRight) && !renderSize.isPointInside(bottomLeft) && !renderSize.isPointInside(bottomRight))
{
//FuzzYspo0N :: Offscreen , dont bother rendering
return;
}
// ok, we've clipped everything.
// now draw it.
core::rect<f32> tcoords;
tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;
tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;
tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);
tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);
const core::rect<s32> poss(targetPos, sourceSize);
setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
S3DVertex vtx[4];
vtx[0] = S3DVertex((f32)topLeft.X, (f32)topLeft.Y, 0.0f,
0.0f, 0.0f, 0.0f, color,
tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
vtx[1] = S3DVertex((f32)topRight.X, (f32)topRight.Y, 0.0f,
0.0f, 0.0f, 0.0f, color,
tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
vtx[2] = S3DVertex((f32)bottomRight.X, (f32)bottomRight.Y, 0.0f,
0.0f, 0.0f, 0.0f, color,
tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
vtx[3] = S3DVertex((f32)bottomLeft.X, (f32)bottomLeft.Y, 0.0f,
0.0f, 0.0f, 0.0f, color,
tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
s16 indices[6] = {0,1,2,0,2,3};
setVertexShader(EVT_STANDARD);
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex));
}