inline fx32 gFxDiv(fx32 numer, fx32 denom)
{
if(denom==0)
{
OS_Printf("Error! Division by zero!!!/n");
return 0;
}
FX_DivAsync(numer, denom);
return FX_GetDivResult();
}
inline fx32 gFxMul(fx32 v1, fx32 v2)
{
s64 result = ((fx64)(v1) * (v2) + 0x800LL) >> FX32_SHIFT;
if(result<FX32_MIN||result>FX32_MAX)
{
WARNING((result > FX32_MIN && result < FX32_MAX), "gFxMul: Overflow/Underflow");
if (result < FX32_MIN) return FX32_MIN;
if (result > FX32_MAX) return FX32_MAX;
}
return FX32_CAST(result);
}
//
// Render tags
//
void CarTag::render()
{
if ( True == mTagInfo[QUICK_TIME_EVENT].state )
{
Vector3Fx offset;
Vector3Fx normal = mCar->getCarOnTrack().getNormal();
offset = normal * mTagInfo[QUICK_TIME_EVENT].height;
/*BillboardRenderer::setTexture(sQuickTimeEventTextures[mTagInfo[QUICK_TIME_EVENT].param]);
BillboardRenderer::setAlpha( (u8)mTagInfo[QUICK_TIME_EVENT].alpha );
BillboardRenderer::setColor(0x7fff);
BillboardRenderer::setCameraPos(CameraManager::getCurrentCamera()->getPosition());
BillboardRenderer::setCameraMatrix(CameraManager::getCurrentCamera()->mLookAt.matrix);
VecFx32 position;
position.x = offset.x + mCar->getPosition().x;
position.y = offset.y + mCar->getPosition().y;
position.z = offset.z + mCar->getPosition().z;
BillboardRenderer::render(mTagInfo[QUICK_TIME_EVENT].size, position); */
CarRenderer& carRenderer = mCar->getCarRenderer();
Vector3Fx position = carRenderer.getWorldPosition();
position += offset;
G3_MtxMode(GX_MTXMODE_POSITION_VECTOR);
G3_PushMtx();
G3_Translate(position.x, position.y, position.z);
G3_MultMtx33(&carRenderer.getRotation());
G3_PositionTest(0,0,0);
VecFx32 screenPos;
fx32 screenPosW;
while(G3X_GetPositionTestResult(&screenPos,&screenPosW)){};
screenPos.x= gFxDiv((screenPos.x+ screenPosW),
gFxMul(screenPosW, 2*FX32_ONE));
screenPos.y= gFxDiv((screenPos.y+ screenPosW),
gFxMul(screenPosW, 2*FX32_ONE));
screenPos.x= gFxMul(screenPos.x, 255 * FX32_ONE) >> FX32_SHIFT;
screenPos.y= 191-(gFxMul(screenPos.y, 191 * FX32_ONE) >> FX32_SHIFT);
fx16 vx[4];
fx16 vy[4];
NTTexture* ptexture = sQuickTimeEventTextures[mTagInfo[QUICK_TIME_EVENT].param];
G3_TexImageParam( ptexture->getTextureFormat(),
GX_TEXGEN_TEXCOORD, // use texcoord
ptexture->getTexSizeS(),
ptexture->getTexSizeT(),
ptexture->getRepeatMode(), // repeat S & T
ptexture->getFlipMode(), // no flip
ptexture->getColor0Mode(), // mColor 0 is transparent
(unsigned long)ptexture->getTextureAdress() // the offset of the mTexture image
);
G3_TexPlttBase((unsigned long)ptexture->getPaletteAdress(), ptexture->getTextureFormat() );
G3_PolygonAttr(
GX_LIGHTMASK_NONE, // disable lights
GX_POLYGONMODE_MODULATE, // modulation mode GX_POLYGONMODE_DECAL,//
GX_CULL_NONE, // cull back
RaceStateRenderer::getPolygonId(RaceStateRenderer::POLYGON_BILLBOARD), // polygon ID (0 - 63)
31, // alpha (0 - 31)
GX_POLYGON_ATTR_MISC_NONE // OR of GXPolygonAttrMisc's value
);
int height = ptexture->getHeight();
int width = ptexture->getWidth();
vx[0] = (fx16)((screenPos.x - width / 2));
vy[0] = (fx16)((screenPos.y + height / 2));
vx[1] = (fx16)((screenPos.x - width / 2));
vy[1] = (fx16)((screenPos.y - height / 2));
vx[2] = (fx16)((screenPos.x + width / 2));
vy[2] = (fx16)((screenPos.y - height / 2));
vx[3] = (fx16)((screenPos.x + width / 2));
vy[3] = (fx16)((screenPos.y + height / 2));
fx32 u[4];
fx32 v[4];
u[0] = 0;
v[0] = ptexture->getHeight() * FX32_ONE;
u[1] = 0;
v[1] = 0;
u[2] = ptexture->getWidth() * FX32_ONE;
v[2] = 0;
u[3] = ptexture->getWidth() * FX32_ONE;
v[3] = ptexture->getHeight() * FX32_ONE;
G3_MtxMode(GX_MTXMODE_PROJECTION);
G3_PushMtx();
G3_Identity();
G3_Ortho( 0, Renderer::SCREEN_HEIGHT,
0, Renderer::SCREEN_WIDTH,
0, 0xffff,
NULL);
G3_MtxMode(GX_MTXMODE_POSITION_VECTOR);
G3_PushMtx();
G3_Identity();
G3_Begin(GX_BEGIN_QUADS);
G3_Color(0x7fff);
for (int i = 0; i < 4; i++)
{
if(ptexture)
{
G3_TexCoord( u[i], v[i] );
G3_Vtx(vx[i], vy[i], (short)0x8000);
}
else
{
G3_Vtx(vx[i], vy[i], (short)0x8000);
}
}
G3_End();
G3_MtxMode(GX_MTXMODE_PROJECTION);
G3_PopMtx(1);
G3_MtxMode(GX_MTXMODE_POSITION_VECTOR);
G3_PopMtx(1);
G3_PopMtx(1);
}
}