Game Development Community

3rd Person Super Crosshair

by Timothy Castagna · in Torque Game Engine Advanced · 08/15/2008 (6:24 am) · 16 replies

Hey All,
I'm currently in the middle of porting over the 3rd person super crosshair resource to tgea 1.7 and i need a little help. I got the code converted over and everything compiles fine but when i add the gui it crashes the game. i was wondering if anyone has any ideas whats wrong. Thanks.
#include "gfx/gfxDevice.h"
#include "gfx/primBuilder.h"
#include "gui/core/guiControl.h"
#include "gui/controls/guiBitmapCtrl.h"
#include "gui/3d/guiTSControl.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "T3D/gameConnection.h"
#include "T3D/shapeBase.h"
#include "terrain/terrData.h"
#include "interior/interior.h"

#define SMOOTH_FACTOR 10

class GuiCrossHairHud : public GuiBitmapCtrl
{
typedef GuiBitmapCtrl Parent;

ColorF mDamageFillColor;
ColorF mDamageFrameColor;
Point2I mDamageRectSize;
Point2I mDamageOffset;

Point2I mBitmapSize;
ColorF mFriendlyTargetColor;
ColorF mEnemyTargetColor;
ColorF mNeutralTargetColor;

ColorF mActiveColor;

Point2I mSmooth[SMOOTH_FACTOR];


// RectI origBounds;

protected:
void drawDamage(Point2I offset, F32 damage, F32 opacity);
void shuntSmoothArray();
Point2I avgSmoothArray();
void drawName( Point2I offset, const char *buf, F32 opacity);

public:
GuiCrossHairHud();

void onRender( Point2I, const RectI &);
static void initPersistFields();
DECLARE_CONOBJECT( GuiCrossHairHud );
};

/// Valid object types for which the cross hair will render, this
/// should really all be script controlled.
static const U32 ObjectMask = PlayerObjectType | VehicleObjectType;


//-----------------------------------------------------------------------------

IMPLEMENT_CONOBJECT( GuiCrossHairHud );

GuiCrossHairHud::GuiCrossHairHud()
{
U32 i;
mDamageFrameColor.set( 0.0f, 1.0f, 0.0f, 1.0f );
mDamageRectSize.set(50, 4);
mDamageOffset.set(0,32);

mBitmapSize.set(32,32);
mFriendlyTargetColor.set(0.0f,1.0f,0.0f,0.0f);
mEnemyTargetColor.set(1.0f,0.0f,0.0f,1.0f);
mNeutralTargetColor.set(1.0f,1.0f,1.0f,1.0f);

	for(i=0;i<SMOOTH_FACTOR;i++)
	{
		mSmooth[i] = Point2I(0,0);
	}
}

void GuiCrossHairHud::initPersistFields()
{
Parent::initPersistFields();
addField( "damageFillColor", TypeColorF, Offset( mDamageFillColor, GuiCrossHairHud ) );
addField( "damageFrameColor", TypeColorF, Offset( mDamageFrameColor, GuiCrossHairHud ) );
addField( "damageRect", TypePoint2I, Offset( mDamageRectSize, GuiCrossHairHud ) );
addField( "damageOffset", TypePoint2I, Offset( mDamageOffset, GuiCrossHairHud ) );

addField( "bitmapSize", TypePoint2I, Offset( mBitmapSize, GuiCrossHairHud ) );
addField( "friendlyTargetColor", TypeColorF, Offset( mFriendlyTargetColor, GuiCrossHairHud ) );
addField( "enemyTargetColor", TypeColorF, Offset( mEnemyTargetColor, GuiCrossHairHud ) );
addField( "neutralTargetColor", TypeColorF, Offset( mNeutralTargetColor, GuiCrossHairHud ) );
}

//-----------------------------------------------------------------------------

void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect)
{
// Must have a connection and player control object
GameConnection* conn = GameConnection::getConnectionToServer();
if (!conn)
return;
ShapeBase* control = (dynamic_cast<ShapeBase*>(conn->getControlObject()));
if (!control || !(control->getType() & ObjectMask))
	return;

// MUZZLE RAYCAST
MatrixF gun;
Point3F gunPos,gunVec;
//conn->getControlObject()->getMuzzleTransform(0,&gun);
control->getControlObject()->getMuzzleTransform(0,&gun);
gun.getColumn(3, &gunPos);

gun.getColumn(1, &gunVec);
Point3F gunEndPos = gunVec;
gunEndPos *= gClientSceneGraph->getVisibleDistance();
gunEndPos += gunPos;

static U32 losMask = TerrainObjectType | InteriorObjectType | ShapeBaseObjectType;
control->disableCollision(); // disable collisions with control object

RayInfo gunRay;
gunRay.object = 0;
gClientContainer.castRay(gunPos, gunEndPos, losMask, &gunRay);

control->enableCollision(); // we are done with the raycasting, so we can do this now

Point3F targetPoint = gunPos;
bool hasObject = false;
F32 dmgLevel = 1;
char* szShapeName = new char[24]; //StringTableEntry



if(gunRay.object == 0)
targetPoint = gunPos + (gunVec * (gClientSceneGraph->getVisibleDistance() / 2));
else
{
if (ShapeBase* obj = dynamic_cast<ShapeBase*>(gunRay.object))
{
if(obj->getShapeName())
{
hasObject = true;
dmgLevel = obj->getDamageValue();

dStrcpy(szShapeName, obj->getShapeName());

mActiveColor = mEnemyTargetColor;
}
}
targetPoint = gunRay.point;
}
Point3F projPnt(320.0f,320.0f,0.0f);

// setup TSCCtrl as parent, for doing the ->project
GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent());
if (!parent) return;

if (!parent->project(targetPoint, &projPnt))
{
return;
}

#1
08/15/2008 (6:26 am)
if(bool(mTextureObject))
{
//glDisable(GL_LIGHTING);
GFX->setBaseRenderState();
GFX->setLightingEnable(false);
GFX->setAlphaBlendEnable(true);

//glEnable(GL_TEXTURE_2D);

//glBindTexture(GL_TEXTURE_2D, mTextureHandle.getGLName() );
GFX->setTexture(0, mTextureObject );

//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GFX->setTextureStageColorOp(0, GFXTOPModulate);

//glEnable(GL_BLEND);
GFX->setSrcBlend(GFXBlendOne);
GFX->setDestBlend(GFXBlendZero);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GFX->setSrcBlend(GFXBlendSrcAlpha);
GFX->setDestBlend(GFXBlendInvSrcAlpha);

GFXVertexPCT *lVerts;
//GFX->mTextureManager *mTextureHandle;
if(hasObject)
{
	//glColor4fv(mActiveColor);
	lVerts->color = mActiveColor;
}
else
{
	//glColor4fv(mNeutralTargetColor);
	lVerts->color = mNeutralTargetColor;
}

//TextureObject* texture = (TextureObject*)mTextureHandle;
GFXTextureObject* texture = (GFXTextureObject*)mTextureObject;


shuntSmoothArray();
mSmooth[SMOOTH_FACTOR-1] = Point2I( projPnt.x - (mBitmapSize.x / 2) , projPnt.y - (mBitmapSize.y / 2));

//Point2I aimOffset = Point2I( projPnt.x - (mBitmapSize.x / 2) , projPnt.y - (mBitmapSize.y / 2) );

Point2I aimOffset = avgSmoothArray();

RectI rect(aimOffset,Point2I(mBitmapSize.x * 2,mBitmapSize.y * 2));

//glBegin(GL_TRIANGLE_FAN);
PrimBuild::begin(GFXTriangleFan,4);

//glTexCoord2f(0, 1);
PrimBuild::texCoord2f(0, 1);
//glVertex2f(rect.point.x, rect.point.y + rect.extent.y);
PrimBuild::vertex2f(rect.point.x, rect.point.y + rect.extent.y);


//glTexCoord2f(1, 1);
PrimBuild::texCoord2f(1, 1);
//glVertex2f(rect.point.x + rect.extent.x, rect.point.y + rect.extent.y);
PrimBuild::vertex2f(rect.point.x + rect.extent.x, rect.point.y + rect.extent.y);
//glTexCoord2f(1, 0);
PrimBuild::texCoord2f(1, 0);
//glVertex2f(rect.point.x + rect.extent.x, rect.point.y);
PrimBuild::vertex2f(rect.point.x + rect.extent.x, rect.point.y);
//glTexCoord2f(0, 0);
PrimBuild::texCoord2f(0, 0);
//glVertex2f(rect.point.x, rect.point.y);
PrimBuild::vertex2f(rect.point.x, rect.point.y);
//glEnd();
PrimBuild::end();
//glDisable(GL_BLEND);
//glDisable(GL_TEXTURE_2D);
}
else
{
Point2I aimOffset = Point2I( projPnt.x - 2,
projPnt.y - 2 );

RectI rect(aimOffset, Point2I(4,4));

//dglDrawRectFill(rect, ColorF(1.0f,1.0f,1.0f,1.0f));
 GFX->getDrawUtil()->drawRect(rect, ColorF(1.0f,1.0f,1.0f,1.0f));
}

//renderChildControls(offset, updateRect);

// if we have an object, render the hud part
if (hasObject)
{
drawDamage(Point2I(projPnt.x,projPnt.y + mBitmapSize.y) + mDamageOffset,dmgLevel , 1);
drawName(Point2I(projPnt.x,projPnt.y + mBitmapSize.y) + mDamageOffset,szShapeName,1);
}
}


//-----------------------------------------------------------------------------
/**
Display a damage bar ubove the shape.
This is a support funtion, called by onRender.
*/
void GuiCrossHairHud::drawDamage(Point2I offset, F32 damage, F32 opacity)
{
mActiveColor.alpha = mDamageFrameColor.alpha = opacity;

// Damage should be 0->1 (0 being no damage,or healthy), but
// we'll just make sure here as we flip it.
damage = mClampF(1 - damage, 0, 1);

// Center the bar
RectI rect(offset, mDamageRectSize);
rect.point.x -= mDamageRectSize.x / 2;

// Draw the border
//dglDrawRect(rect, mDamageFrameColor);
 GFX->getDrawUtil()->drawRect(rect, mDamageFrameColor);

// Draw the damage % fill
rect.point += Point2I(1, 1);
rect.extent -= Point2I(1, 1);
rect.extent.x = (S32)(rect.extent.x * damage);
if (rect.extent.x == 1)
rect.extent.x = 2;
if (rect.extent.x > 0)
//dglDrawRectFill(rect, mActiveColor);
GFX->getDrawUtil()->drawRectFill(rect, mActiveColor);
}

//------------------------------------------------------------------------------
void GuiCrossHairHud::shuntSmoothArray()
{
U8 i;

for (i=1;i<SMOOTH_FACTOR;i++)
{
mSmooth[i-1] = mSmooth[i];
}
}


//------------------------------------------------------------------------------
Point2I GuiCrossHairHud::avgSmoothArray()
{
U8 i;
Point2I average(0,0);

for (i=0;i<SMOOTH_FACTOR;i++)
{
average.x += mSmooth[i].x;
average.y += mSmooth[i].y;
}
average.x /= SMOOTH_FACTOR;
average.y /= SMOOTH_FACTOR;
return average;

}

//----------------------------------------------------------------------------
/// Render object names.
///
/// Helper function for GuiShapeNameHud::onRender
///
/// @param offset Screen coordinates to render name label. (Text is centered
/// horizontally about this location, with bottom of text at
/// specified y position.)
/// @param name String name to display.
/// @param opacity Opacity of name (a fraction).
void GuiCrossHairHud::drawName(Point2I offset, const char *name, F32 opacity)
{
// Center the name
offset.x -= mProfile->mFont->getStrWidth(name) / 2;
offset.y -= mProfile->mFont->getHeight();

// Deal with opacity and draw.
mActiveColor.alpha = opacity;
//dglSetBitmapModulation(mActiveColor);
GFX->getDrawUtil()->setBitmapModulation(mActiveColor);
//dglDrawText(mProfile->mFont, offset, name);
GFX->getDrawUtil()->drawText(mProfile->mFont, offset, name);
//dglClearBitmapModulation();
GFX->getDrawUtil()->clearBitmapModulation();
}
#2
08/15/2008 (12:21 pm)
Figured it out

control->getControlObject()->getMuzzleTransform(0,&gun);

needs to be

control->getMuzzleTransform(0,&gun);
#3
09/17/2008 (1:34 pm)
Nice.

Is this working fine now? Just curious before I try to implement this.
#4
10/22/2008 (1:30 am)
Are you really going to make me go figure out what file you're talking about?

i think i know which one, but i forget where =P



and what exactly does this do? if it is only a GUI edit, wouldn't that mean it just enables the crosshair when in third person?
#5
10/22/2008 (2:08 am)
And it does.



but just as a question, before i actually take a look at it, can you make the camera a few feet higher?
#6
10/22/2008 (3:01 am)
Couldn't get this working, had compile errors. I'll try again :)
#7
10/22/2008 (1:45 pm)
If it helps, this is for tgea 1.7
#8
03/12/2009 (1:58 am)
Any change someone can provide some insight as to how to get it to work with 1.8.1. The problems are just with these:

GFX->setBaseRenderState();
GFX->setLightingEnable(false);
GFX->setAlphaBlendEnable(true);
GFX->setTextureStageColorOp(0, GFXTOPModulate);
GFX->setSrcBlend(GFXBlendOne);
GFX->setDestBlend(GFXBlendZero);
GFX->setSrcBlend(GFXBlendSrcAlpha);
GFX->setDestBlend(GFXBlendInvSrcAlpha);
#9
04/14/2009 (8:22 pm)
Does this work in TGEA 1.8.1?
#10
04/27/2009 (4:39 am)
Can anyone please help?
#11
04/28/2009 (10:15 am)
So I commented out in guiCrossHairHud.cpp,

GFX->setBaseRenderState();
GFX->setLightingEnable(false);
GFX->setAlphaBlendEnable(true);
GFX->setTextureStageColorOp(0, GFXTOPModulate);
GFX->setSrcBlend(GFXBlendOne);
GFX->setDestBlend(GFXBlendZero);
GFX->setSrcBlend(GFXBlendSrcAlpha);
GFX->setDestBlend(GFXBlendInvSrcAlpha);

And the engine compiles with no errors but when I start the game the game crashes with no errors in the console.

But there are 2 warning that are showing up.

warning C4189: 'texture' : local variable is initialized but not referenced	d:..guiCrossHairHud.cpp	196

warning C4700: uninitialized local variable 'lVerts' used	d:..guicrosshairhud.cpp	187

Which points to this part of the code,

if(hasObject)
{
	//glColor4fv(mActiveColor);
[b]-->[/b]lVerts->color = mActiveColor;
}
else
{
	//glColor4fv(mNeutralTargetColor);
	lVerts->color = mNeutralTargetColor;
}

//TextureObject* texture = (TextureObject*)mTextureHandle;
[b]-->[/b] GFXTextureObject* texture = (GFXTextureObject*)mTextureObject;
#12
08/21/2009 (2:26 pm)
Did anyone ever get this working in TGEA 1.8.1? We (Archon Games) could REALLY use this code in our current project...
#13
10/11/2009 (11:26 pm)
maybe try changing the bitmap for the vector crosshair resource...
#14
03/22/2010 (9:06 am)
I found the issue with this code and why it is crashing the game engine. I have been able to successfully merge this into T3D without issue. drawName is the cuplrit behind the crash, get rid of it and it compiles. I will be posting an updated resource for this.
#15
03/22/2010 (10:42 am)
Pending my resource, you can fix this by...


Replace this code
//glDisable(GL_LIGHTING);  
GFX->setBaseRenderState();  
GFX->setLightingEnable(false);  
GFX->setAlphaBlendEnable(true);  
  
//glEnable(GL_TEXTURE_2D);  
  
//glBindTexture(GL_TEXTURE_2D, mTextureHandle.getGLName() );  
GFX->setTexture(0, mTextureObject );  
  
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);  
GFX->setTextureStageColorOp(0, GFXTOPModulate);  
  
//glEnable(GL_BLEND);  
GFX->setSrcBlend(GFXBlendOne);  
GFX->setDestBlend(GFXBlendZero);  
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  
GFX->setSrcBlend(GFXBlendSrcAlpha);  
GFX->setDestBlend(GFXBlendInvSrcAlpha);  
  
GFXVertexPCT *lVerts;  
//GFX->mTextureManager *mTextureHandle;  
if(hasObject)  
{  
    //glColor4fv(mActiveColor);  
    lVerts->color = mActiveColor;  
}  
else  
{  
    //glColor4fv(mNeutralTargetColor);  
    lVerts->color = mNeutralTargetColor;  
}

for this code

GFXStateBlockDesc desc;  
   desc.ffLighting = false;  
   desc.setCullMode( GFXCullNone );  
   desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);  
   desc.samplers[0].textureColorOp = GFXTOPModulate;  
   desc.samplers[1].textureColorOp = GFXTOPDisable;  
  
   GFXStateBlockRef myState = GFX->createStateBlock(desc);  
  
   // Render time code  
   GFX->setStateBlock(myState);  
  
   mDevice->setTexture( 0, texture );  
   mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );  
   mDevice->drawPrimitive(GFXTriangleFan, 0, 2 );