Trying to Implement drawBitmapRotated in TGEA
by Jorge Luis Gandulfo · in Torque Game Engine Advanced · 05/21/2008 (9:38 am) · 8 replies
Since the Speedometer GUI don't work by default, i was checking old resources, and still Speedometer in TGEA displays the needle as a drawed box.
So i was planning in resurrect and old resource i modified long ago to draw a bitmap spin.
My problem is the dlg.h don't exist anymore, and i used to put a function there to do the rotation trick.
Now i ported my old resource to TGEA, i just need this function to be working, i placed it on gfxDrawUtil.
If anybody can help me finish the rotation part of the function i will release an updated TGEA resource, sorry for asking this, but im pretty newbie in TGEA still, and my math skills seems to be affected by the vodka i been drinking all this years :).
Here is the function i added in gfxDrawUtil.ccp (copy paste from drawBitmapStretchSR)
I added the following in gfxDrawUtil.h
So i was planning in resurrect and old resource i modified long ago to draw a bitmap spin.
My problem is the dlg.h don't exist anymore, and i used to put a function there to do the rotation trick.
Now i ported my old resource to TGEA, i just need this function to be working, i placed it on gfxDrawUtil.
If anybody can help me finish the rotation part of the function i will release an updated TGEA resource, sorry for asking this, but im pretty newbie in TGEA still, and my math skills seems to be affected by the vodka i been drinking all this years :).
Here is the function i added in gfxDrawUtil.ccp (copy paste from drawBitmapStretchSR)
void GFXDrawUtil::drawBitmapRotated( GFXTextureObject *texture, const RectI &dstRect, const RectI &srcRect, const GFXBitmapFlip in_flip, F32 Angle, const Point2F Offset )
{
// Sanity if no texture is specified.
if(!texture)
return;
mDevice->setBaseRenderState();
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, 4, GFXBufferTypeVolatile );
verts.lock();
F32 texLeft = F32(srcRect.point.x) / F32(texture->mTextureSize.x);
F32 texRight = F32(srcRect.point.x + srcRect.extent.x) / F32(texture->mTextureSize.x);
F32 texTop = F32(srcRect.point.y) / F32(texture->mTextureSize.y);
F32 texBottom = F32(srcRect.point.y + srcRect.extent.y) / F32(texture->mTextureSize.y);
F32 screenLeft = (F32)dstRect.point.x;
F32 screenRight = (F32)(dstRect.point.x + dstRect.extent.x);
F32 screenTop = (F32)dstRect.point.y;
F32 screenBottom = (F32)(dstRect.point.y + dstRect.extent.y);
if( in_flip & GFXBitmapFlip_X )
{
F32 temp = texLeft;
texLeft = texRight;
texRight = temp;
}
if( in_flip & GFXBitmapFlip_Y )
{
F32 temp = texTop;
texTop = texBottom;
texBottom = temp;
}
const F32 fillConv = mDevice->getFillConventionOffset();
verts[0].point.set( screenLeft - fillConv, screenTop - fillConv, 0.f );
verts[1].point.set( screenRight - fillConv, screenTop - fillConv, 0.f );
verts[2].point.set( screenLeft - fillConv, screenBottom - fillConv, 0.f );
verts[3].point.set( screenRight - fillConv, screenBottom - fillConv, 0.f );
verts[0].color = verts[1].color = verts[2].color = verts[3].color = mBitmapModulation;
[b]
//Apply Offset
texLeft = texLeft + Offset.x;
texRight = texRight + Offset.x;
texTop = texTop + Offset.y;
texBottom = texBottom + Offset.y;
//Apply Offset
[/b]
verts[0].texCoord.set( texLeft, texTop );
verts[1].texCoord.set( texRight, texTop );
verts[2].texCoord.set( texLeft, texBottom );
verts[3].texCoord.set( texRight, texBottom );
[b]
//Apply Rotation
// angle is in degree's so convert to radians..radians = degrees * pi /180
Angle = Angle * 3.14 / 180.0f;
MatrixF rotMatrix( EulerF( 0.0, 0.0, Angle ) );
for( int i=0; i<4; i++ )
{
rotMatrix.mulP( verts[i].point );
}
[/b]
verts.unlock();
mDevice->setVertexBuffer( verts );
mDevice->setCullMode( GFXCullNone );
mDevice->setLightingEnable( false );
mDevice->setAlphaBlendEnable( true );
mDevice->setSrcBlend( GFXBlendSrcAlpha );
mDevice->setDestBlend( GFXBlendInvSrcAlpha );
mDevice->setTextureStageColorOp( 0, GFXTOPModulate );
mDevice->setTextureStageColorOp( 1, GFXTOPDisable );
mDevice->setTexture( 0, texture );
mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );
mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 );
mDevice->setAlphaBlendEnable( false );
}I added the following in gfxDrawUtil.h
void drawBitmapRotated( GFXTextureObject*texture, const RectI &dstRect, const RectI &srcRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None ,F32 Angle = 0, const Point2F Offset = Point2F(0,0) );
#2
The above is working for what I'm using it for...
05/21/2008 (6:32 pm)
Ok, here is my draw rotated:void GFXDrawUtil::drawBitmapRotated(GFXTextureObject *texture,const RectI& dstRect,const RectI& srcRect,const U32 in_flip,F32 spinAngle, const Point2F spinOffset)
{
if(!texture)
return;
mDevice->setBaseRenderState();
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, 4, GFXBufferTypeVolatile );
verts.lock();
F32 texLeft = F32(srcRect.point.x) / F32(texture->mTextureSize.x);
F32 texRight = F32(srcRect.point.x + srcRect.extent.x) / F32(texture->mTextureSize.x);
F32 texTop = F32(srcRect.point.y) / F32(texture->mTextureSize.y);
F32 texBottom = F32(srcRect.point.y + srcRect.extent.y) / F32(texture->mTextureSize.y);
F32 screenLeft = dstRect.point.x;
F32 screenRight = dstRect.point.x + dstRect.extent.x;
F32 screenTop = dstRect.point.y;
F32 screenBottom = dstRect.point.y + dstRect.extent.y;
if(in_flip & GFXBitmapFlip_X)
{
F32 temp = texLeft;
texLeft = texRight;
texRight = temp;
}
if(in_flip & GFXBitmapFlip_Y)
{
F32 temp = texTop;
texTop = texBottom;
texBottom = temp;
}
F32 X = 0;
// calculate the centroid of the rectangle (to use as rotation pivot)
if (screenLeft < screenRight)
{
X = screenLeft + ((screenRight - screenLeft)*0.5f);
}
else
{
X = screenRight + ((screenLeft - screenRight)*0.5f);
};
F32 Y = 0;
if (screenTop < screenBottom)
{
Y = screenTop + ((screenBottom - screenTop)*0.5f);
}
else
{
Y = screenBottom + ((screenTop - screenBottom)*0.5f);
};
// spin angle is in degree's so convert to radians..radians = degrees * pi /180
spinAngle = spinAngle * 3.14 / 180.0f;
Point2F screenPoint(X,Y);
F32 width = dstRect.extent.x;
width *= 0.5;
MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) );
Point3F offset( screenPoint.x, screenPoint.y, 0.0 );
//const F32 fillConv = mDevice->getFillConventionOffset();
verts[0].point.set( -width + spinOffset.x, -width + spinOffset.y, 0.0 );
verts[1].point.set( -width + spinOffset.x, width + spinOffset.y, 0.0 );
verts[2].point.set( width + spinOffset.x, width + spinOffset.y, 0.0 );
verts[3].point.set( width + spinOffset.x, -width + spinOffset.y, 0.0 );
verts[0].color = verts[1].color = verts[2].color = verts[3].color = mBitmapModulation;
verts[0].texCoord.set( texLeft, texTop );
verts[1].texCoord.set( texLeft, texBottom );
verts[2].texCoord.set( texRight, texBottom );
verts[3].texCoord.set( texRight, texTop );
for( int i=0; i<4; i++ )
{
rotMatrix.mulP( verts[i].point );
verts[i].point += offset;
}
verts.unlock();
mDevice->setVertexBuffer( verts );
mDevice->setCullMode( GFXCullNone );
mDevice->setLightingEnable( false );
mDevice->setAlphaBlendEnable( true );
mDevice->setSrcBlend( GFXBlendSrcAlpha );
mDevice->setDestBlend( GFXBlendInvSrcAlpha );
mDevice->setTextureStageColorOp( 0, GFXTOPModulate );
mDevice->setTextureStageColorOp( 1, GFXTOPDisable );
mDevice->setTexture( 0, texture );
mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );
mDevice->drawPrimitive(GFXTriangleFan, 0, 2 );
mDevice->setAlphaBlendEnable( false );
}The above is working for what I'm using it for...
#3
Thanks again
05/21/2008 (7:46 pm)
Thanks a lot for your help, i'm still having a problem, but at least i know this code wasn't it, seems both functions (the one i wrote and the one you did) are giving the same results, so i might be doing something wrong when i'm calling this function, so at least i won't waste my time anymore on this, anyway im adopting your function for now just in case :)Thanks again
#4
I have my image rotating 360 degrees, and the above code works with the function as it is above..
05/21/2008 (8:47 pm)
I had to mess around with how I was passing the angle values from script, it appears to reset itself at around 100 degrees, so I did the following:if($fovRotating > 0 && $fovRotating < 100 )
{
$fovRotating = ($fovRotating + 0.1);
}
else if ($fovRotating < 0 && $fovRotating > -100)
{
$fovRotating = ($fovRotating + 0.1);
}
else
{
if($fovRotating > 0)
$fovRotating = 0.01;
else
$fovRotating = -0.01;
}I have my image rotating 360 degrees, and the above code works with the function as it is above..
#5
The code im using to call this function is this:
code from ( GuiMeterCtrl::onRender(Point2I offset, const RectI &updateRect) )
In really Lost on what i could be doing wrong, since this is somehow a port of a code that WOrked on TGE.
THis is the resource im trying to port here
05/21/2008 (9:18 pm)
Im getting Weird results, after checking it better, i have 4 needles being diplaying instead of one if i use this Rotate Function, thats really weird to be honest (1 Needle is displayed in each corner of what appers to be an invisible BITMAP BOX, that rotates but with this error)The code im using to call this function is this:
code from ( GuiMeterCtrl::onRender(Point2I offset, const RectI &updateRect) )
...
RectI Bounds;
Bounds = getBounds();
// Center of widget
Point2F half(Bounds.extent.x / 2 - 1,Bounds.extent.y / 2 - 1);
// Make center the UI object's coordinate center
half.x += offset.x;
half.y += offset.y;
// Draw frame
if(mTextureObject) {
//dglSetBitmapModulation(mColor);
GFX->getDrawUtil()->setBitmapModulation(mColor);
Point2I texSize(mTextureObject->getWidth(), mTextureObject->getHeight() );
Point2I corner(half.x - mTextureObject->getWidth()/2, half.y - mTextureObject->getHeight()/2);
RectI srcRegion(0,0,mTextureObject->getWidth(),mTextureObject->getHeight());
RectI dstRect(corner, texSize);
//dglDrawBitmapStretchSR(mTextureObject, dstRect, srcRegion, false);
GFX->getDrawUtil()->drawBitmapStretchSR(mTextureObject, dstRect, srcRegion);
}
// Draw Spin
if(mMeterSpin) {
F32 ang = mAngle * (mSpinAng.y - mSpinAng.x) / 100.0 + mSpinAng.x;
Point2I texSize(mTextureObject->getWidth() , mTextureObject->getHeight() );
Point2I corner(half.x - mTextureObject->getWidth() /2 + mSpinOffset.x, half.y - mTextureObject->getHeight() /2 +mSpinOffset.y);
RectI srcRegion(0,0, mTextureObject->getWidth(), mTextureObject->getHeight() );
RectI dstRect(corner, texSize);
[B]
GFX->getDrawUtil()->drawBitmapRotated(mMeterSpin, dstRect, srcRegion, GFXBitmapFlip_None, ang, mSpinBitmapOffset);
[/B] }
..In really Lost on what i could be doing wrong, since this is somehow a port of a code that WOrked on TGE.
THis is the resource im trying to port here
#6
05/22/2008 (6:43 am)
I started from the same resource... Here is my onRender:if ( ( mValueType == GuiMeterValueTypeSpeed ) ^ ( mValueType == GuiMeterValueTypeEnergy ) )
{
// Must have a connection and player control object
GameConnection* conn = GameConnection::getConnectionToServer();
if (!conn)
return;
Vehicle* control = dynamic_cast<Vehicle*>(conn->getControlObject());
if (!control || !(control->getType() & VehicleObjectType))
return;
if ( mValueType == GuiMeterValueTypeEnergy )
{
mValue = control->getEnergyLevel();//getEnergyValue();
}
if ( mValueType == GuiMeterValueTypeSpeed )
{
mValue = control->getVelocity().len();
}
if (mValue > mMaxValue)
{
mValue = mMaxValue;
}
}
if ( !mInvert )
{
mAngle = mMinAngle + (mMaxAngle - mMinAngle) * (mValue / mMaxValue);
}
else
{
mAngle = mMaxAngle - (mMaxAngle - mMinAngle) * (mValue / mMaxValue);
}
// Center of widget
Point2F half(getBounds().extent.x / 2 - 1, getBounds().extent.y / 2 - 1);
// Make center the UI object's coordinate center
half.x += offset.x;
half.y += offset.y;
// Take back the tecture handle for spin and frame
GFXTextureObject* spin = (GFXTextureObject *) mMeterSpin;
GFXTextureObject* frame = (GFXTextureObject *) mTextureHandle;
// Draw frame
if(frame)
{
GFX->getDrawUtil()->setBitmapModulation(mColor);
Point2I texSize(frame->getBitmapWidth(), frame->getBitmapHeight() );
Point2I corner(half.x-frame->getBitmapWidth() / 2, half.y-frame->getBitmapHeight() / 2);
RectI srcRegion(0,0,frame->getBitmapWidth(), frame->getBitmapHeight());
RectI dstRect(corner, texSize);
GFX->getDrawUtil()->drawBitmapStretchSR(frame, dstRect, srcRegion);
}
// Draw Spin
if(spin)
{
GFX->getDrawUtil()->clearBitmapModulation();
F32 ang = mAngle * (mSpinAng.y - mSpinAng.x) / 100.0 + mSpinAng.x;
Point2I texSize(spin->getBitmapWidth(), spin->getBitmapHeight() );
Point2I corner(half.x-spin->getBitmapWidth() / 2 + mSpinOffset.x, half.y-spin->getBitmapHeight() / 2 + mSpinOffset.y);
RectI srcRegion(0, 0, spin->getBitmapWidth(), spin->getBitmapHeight());
RectI dstRect(corner, texSize);
if(mAdditive)
GFX->getDrawUtil()->drawBitmapRotatedAdd(spin, dstRect, srcRegion, false, ang, mSpinBitmapOffset);
else
GFX->getDrawUtil()->drawBitmapRotated(spin, dstRect, srcRegion, false, ang, mSpinBitmapOffset);
}
renderChildControls(offset, updateRect);
#7
05/22/2008 (10:15 am)
Thanks a lot Eric i'm testing it now and works great, i will upload it tonight as a resource, if you didn't already do that.
#8
05/22/2008 (10:51 am)
Glad it's working, no I haven't put it up as a resource, so feel free to...
Torque 3D Owner Eric Armstrong
Bloody Tongue Games