fxGuiSnooper ...
by Melv May · in Torque Game Engine · 03/03/2002 (11:35 am) · 17 replies
Before you say anything, I have just submitted this to the resource section. I apologise for the long post.
This gui control allows you to show the scene from any named objects' viewpoint. You can setup automatic sweeping (like a security camera) in all axis as well as put a bitmap/colour overlay for the finishing effect.
Before I get started I would just like to point out that this control will seriously affect your framerate as you are effectively rendering another view, so you could see your framerate drop by half in some circumstances. Saying that, if you use it like a security camera / monitoring device then you can place it on a seperate GUI screen so that you maintain your FPS.
Create a file named "fxGuiSnooper.cc" and paste the code (at the bottom of the post) into it, compile and you should have a new control named "fxGuiSnooper" in the controls list within the GUI editor.
The properties explained are:-
(All angles are in degrees)
"ViewRotation" - Sets an initial rotation to the view.
"ViewOffset" - Sets an initial translation to the view.
"FOV" - Sets the Field-of-view. (Hmmm!)
"SweepAmplitude" - Sets the magnitude to which the view will automatically sweep. You can individually select each axis XYZ. The sweep will be centered around the initial rotation e.g 60 = (-30)->(+30).
"SweepTime" - Sets the time constants for the sweep to complete. Again, you can individually select the time for each axis. The time is in mS e.g. 1000mS = 1 Sec. Sweeping will continue for an infinite period.
"AttachedObject" - Sets the object to which the view will be attached. Essentially, the view will use the objects' position as a base for snooping. If you move the object, then the view should move with it. Try naming a tree or building as a test.
"OverlayBitmap" - Sets the bitmap which will be overlayed ontop of the view. This allows you to blend/obscure the view for screen effects such as interlacing/moire fringing etc.
"OverlayTile" - Sets the bitmap tile mode. When on, the bitmap will be tessellated over the view.
"OverlayColour" - Sets the overlay colour mode. When on, the overlay colour/mask settings are used to colourise the view so you can do green-screens etc. (See my fxGuiFilter control).
"BitmapOverlay" - Selects the bitmap filename to use for the overlay. Using "fps/client/ui/" is a good idea.
"ColourOverlay" - Selects the RGB colours used for the colourisation effect.
"Red/Green/BlueMask" - Selects the masking effect used for the colourisation effect. A tick indicates that that colour channel can be written to using the ColourOverlay.
----------------------------------------------------------------------------------
I hope you enjoy. If there is a better way of doing what I'm doing here then please let me know. I post this stuff in the hope that I might get helpful advice regarding the details of the engine.
Melv. 3/3/2002.
----------------------------------------------------------------------------------
#include "sceneGraph/sceneGraph.h"
#include "game/gameConnection.h"
#include "console/consoleTypes.h"
#include "gui/guiTSControl.h"
class fxGuiSnooper : public GuiTSCtrl
{
private:
typedef GuiTSCtrl Parent;
Point3F mRotateView; // View Rotation.
Point3F mOffsetView; // Offset Distance.
F32 mFov; // Field of View.
Point3F mSweepAmplitude; // Sweep Amplitude.
Point3F mSweepTime; // Sweep Time.
bool mUseOverlayBitmap; // Use Overlay Bitmap Flag.
bool mUseOverlayColour; // Use Overlay Colour Flag.
bool mOverlayTile; // Overlay Tile Flag.
ColorF mOverlayColor; // Filter Colour Vector.
bool mOverlayRedMask; // Overlay Red Mask Flag.
bool mOverlayGreenMask; // Overlay Green Mask Flag.
bool mOverlayBlueMask; // Overlay Blue Mask Flag.
StringTableEntry mObjectName; // Attached Object Name.
SceneObject* mAttachedObject; // Attached Object.
U32 mLastTimeStamp; // Last Time Stamp.
Point3F mCurrentSweepMagnitude; // Current Sweep Phase.
StringTableEntry mOverlayBitmapName; // Overlay Bitmap Name.
TextureHandle mOverlayTextureHandle; // Overlay Texture Handle.
void renderWorld(const RectI & updateRect);
void onRender(Point2I offset, const RectI &updateRect);
public:
fxGuiSnooper();
static void initPersistFields();
static void consoleInit();
bool processCameraQuery(CameraQuery * query);
void setViewObject(const char* ObjectName);
void setViewRotation(Point3F Rotation);
void setOverlayBitmap(const char *name);
void setOverlayColor(ColorF OverlayColor);
void setOverlayMask(bool RedMask, bool GreenMask, bool BlueMask);
bool onWake();
void onSleep();
DECLARE_CONOBJECT(fxGuiSnooper);
};
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(fxGuiSnooper);
//------------------------------------------------------------------------------
fxGuiSnooper::fxGuiSnooper() :
mRotateView(0,0,0),
mOffsetView(0,0,0),
mFov(60.0),
mSweepAmplitude(0,0,60),
mSweepTime(5000,5000,5000),
mCurrentSweepMagnitude(0,0,0),
mAttachedObject(NULL),
mOverlayRedMask(GL_TRUE),
mOverlayGreenMask(GL_TRUE),
mOverlayBlueMask(GL_TRUE),
mOverlayTile(false),
mUseOverlayBitmap(false),
mUseOverlayColour(false),
mLastTimeStamp(Platform::getRealMilliseconds())
{
// Create Empty Attached Object Name.
mObjectName = StringTable->insert("");
// Create Empty Overlay Bitmap Name.
mOverlayBitmapName = StringTable->insert("");
// Set Default Overlay Colour.
mOverlayColor.set(1, 1, 1, 0.5f);
};
//------------------------------------------------------------------------------
void fxGuiSnooper::initPersistFields()
{
// Initialise parents' persistent fields.
Parent::initPersistFields();
// Add out own persistent fields.
addField( "ViewRotation", TypePoint3F, Offset( mRotateView, fxGuiSnooper ) );
addField( "ViewOffset", TypePoint3F, Offset( mOffsetView, fxGuiSnooper ) );
addField( "FOV", TypeF32, Offset( mFov, fxGuiSnooper ) );
addField( "SweepAmplitude", TypePoint3F, Offset( mSweepAmplitude, fxGuiSnooper ) );
addField( "SweepTime", TypePoint3F, Offset( mSweepTime, fxGuiSnooper ) );
addField( "AttachedObject", TypeString, Offset( mObjectName, fxGuiSnooper ) );
addField( "OverlayBitmap", TypeBool, Offset( mUseOverlayBitmap, fxGuiSnooper ) );
addField( "OverlayTile", TypeBool, Offset( mOverlayTile, fxGuiSnooper ) );
addField( "OverlayColour", TypeBool, Offset( mUseOverlayColour, fxGuiSnooper ) );
addField( "BitmapOverlay", TypeFilename, Offset(mOverlayBitmapName, fxGuiSnooper));
addField( "ColorOverlay", TypeColorF, Offset( mOverlayColor, fxGuiSnooper ) );
addField( "RedMask", TypeBool, Offset( mOverlayRedMask, fxGuiSnooper ) );
addField( "GreenMask", TypeBool, Offset( mOverlayGreenMask, fxGuiSnooper ) );
addField( "BlueMask", TypeBool, Offset( mOverlayBlueMask, fxGuiSnooper ) );
}
//------------------------------------------------------------------------------
bool fxGuiSnooper::onWake()
{
// Wake-up Parent.
if (!Parent::onWake()) return false;
// Set Active.
setActive(true);
// Have we an Attached Object Name?
if (mObjectName)
{
// Yes, so attach to it.
setViewObject(mObjectName);
}
// Set Overlay Bitmap.
setOverlayBitmap(mOverlayBitmapName);
// Return OK.
return true;
}
//------------------------------------------------------------------------------
void fxGuiSnooper::onSleep()
{
// Reset Overlay Texture Handle.
mOverlayTextureHandle = NULL;
// Call Parent.
Parent::onSleep();
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setViewRotation(Point3F Rotation)
{
// Set the Rotation internally.
mRotateView = Rotation;
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setViewObject(const char* ObjectName)
{
// Get Root Group.
SimGroup* SG = Sim::getRootGroup();
// Interate Sim Group.
for (SimSetIterator itr(SG); *itr; ++itr)
{
// Is this our Type?
if ((*itr)->getType() & STATIC_COLLISION_MASK)
{
// Yes, so cast our Object.
SceneObject* SceneObj = static_cast(*itr);
// Check that it's a Server Object.
if (SceneObj->isServerObject())
{
const char* getName;
getName = SceneObj->getName();
// Yes, so is this our Object?
if (getName && dStrcmp(getName, ObjectName) == 0)
{
// Store Scene Object.
mAttachedObject = SceneObj;
// Return OK.
return;
}
}
}
}
// Reset Object.
mAttachedObject = NULL;
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setOverlayBitmap(const char *name)
{
// Set Overlay Bitmap Name.
mOverlayBitmapName = StringTable->insert(name);
// Have we got an Overlay Name?
if (*mOverlayBitmapName)
// Yes, so get Texture Handle.
mOverlayTextureHandle = TextureHandle(mOverlayBitmapName, BitmapTexture, true);
else
// No, so reset Texture Handle.
mOverlayTextureHandle = NULL;
// Update.
setUpdate();
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setOverlayColor(ColorF OverlayColor)
{
// Set the Overlay Colour internally.
mOverlayColor = OverlayColor;
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setOverlayMask(bool RedMask, bool GreenMask, bool BlueMask)
{
// Set the Overlay Masks internally.
mOverlayRedMask = RedMask;
mOverlayGreenMask = GreenMask;
mOverlayBlueMask = BlueMask;
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setViewRotation,void,5,5,"Sets View Rotation.")
{
Point3F Rotation;
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast(object);
// Fetch Rotation.
Rotation.set( mDegToRad(dAtof(argv[2])),
mDegToRad(dAtof(argv[3])),
mDegToRad(dAtof(argv[4])));
// Set Rotation.
Viewport->setViewRotation(Rotation);
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setViewObject,void,3,3,"Sets View to Object.")
{
F32 Rotation;
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast(object);
// Set the GuiFilter Filter Colour.
Viewport->setViewObject(argv[2]);
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setOverlayBitmap,void,3,3,"Sets Overlay Bitmap.")
{
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast(object);
// Set Overlay Bitmap.
Viewport->setOverlayBitmap(argv[2]);
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setOverlayColor,void,5,6,"Sets Overlay Color.")
{
F32 r,g,b,a;
ColorF TempColor;
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast(object);
// Convert RGB Ascii parms to float.
r = dAtof(argv[2]);
g = dAtof(argv[3]);
b = dAtof(argv[4]);
// Did we get an alpha param?
if (argc == 6)
// Yep, so convert it.
a = dAtof(argv[5]);
else
// Nope, so default to 1.
a = 1;
// Setup our temporary colour vector.
TempColor.set(r,g,b,a);
// Set the fxGuiSnooper Overlay Colour.
Viewport->setOverlayColor(TempColor);
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setOverlayMask,void,5,5,"Sets Overlay Masks.")
{
F32 r,g,b;
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast(object);
// Convert RGB Ascii parms to float.
r = dAtof(argv[2]);
g = dAtof(argv[3]);
b = dAtof(argv[4]);
// Set the fxGuiSnooper Masks.
Viewport->setOverlayMask(r,g,b);
}
//------------------------------------------------------------------------------
static void cfxGuiBitmapSetOverlayBitmap(SimObject *obj, S32, const char **argv)
{
// Fetch HUD Control.
fxGuiSnooper *ctrl = static_cast(obj);
// Set Overlay Bitmap.
ctrl->setOverlayBitmap(argv[2]);
}
//------------------------------------------------------------------------------
void fxGuiSnooper::consoleInit()
{
Con::addCommand("fxGuiSnooper", "setOverlayBitmap", cfxGuiBitmapSetOverlayBitmap, "fxGuiSnooper.setOverlayBitmap(Bitmap)", 3, 3);
}
//------------------------------------------------------------------------------
void fxGuiSnooper::renderWorld(const RectI & updateRect)
{
// Set-up OpenGL for a scene render.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClear(GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glMatrixMode(GL_MODELVIEW);
dglSetCanonicalState();
// Render Client Scene Graph.
gClientSceneGraph->renderScene();
// Disable Depth Test.
glDisable(GL_DEPTH_TEST);
}
//------------------------------------------------------------------------------
void fxGuiSnooper::onRender(Point2I offset, const RectI &updateRect)
{
// Call Parent Render.
Parent::onRender(offset, updateRect);
// Set Clipping Rectangle to GUI Bounds.
dglSetClipRect(mBounds);
// Do we have an attached Object?
if (!mAttachedObject)
{
// No, so signal to user this problem ...
ColorF ErrorColor(1,0,0);
dglDrawRectFill(updateRect, ErrorColor);
ErrorColor.set(1,1,1);
char buf[256];
dSprintf(buf, sizeof(buf), "*** Object not selected ***");
dglSetBitmapModulation(ErrorColor);
dglDrawText(mProfile->mFont, offset, buf);
dglClearBitmapModulation();
// Return Error.
return;
}
// Are we using the Overlay Bitmap?
if (mUseOverlayBitmap)
{
// Yes, so do we have a texture Handle?
if (mOverlayTextureHandle)
{
// Yes, so clear Bitmap Modulation.
dglClearBitmapModulation();
// Are we tiling the Overlay Bitmap?
if(mOverlayTile)
{
RectI SrcRegion;
RectI DstRegion;
// Yes, so fetch texture object.
TextureObject* TextureObj = (TextureObject *)mOverlayTextureHandle;
// Calculate Tesselation Count.
float XTess = ((float)mBounds.extent.x/(float)TextureObj->bitmapWidth)+1;
float YTess = ((float)mBounds.extent.y/(float)TextureObj->bitmapHeight)+1;
for(int y = 0; y < YTess; ++y)
{
for(int x = 0; x < XTess; ++x)
{
// Calculate Source Region.
SrcRegion.set(0,0,TextureObj->bitmapWidth, TextureObj->bitmapHeight);
// Calculate Destination Region.
DstRegion.set(((TextureObj->bitmapWidth*x)+offset.x),
((TextureObj->bitmapHeight*y)+offset.y),
TextureObj->bitmapWidth,
TextureObj->bitmapHeight);
// Draw Tiled Bitmap.
dglDrawBitmapStretchSR(TextureObj, DstRegion, SrcRegion, false);
}
}
}
else
{
// No, so draw stretched Bitmap.
dglDrawBitmapStretch(mOverlayTextureHandle, mBounds);
}
}
}
// Are we using the Overlay Colour?
if (mUseOverlayColour)
{
// Set Colour Mask.
glColorMask(mOverlayRedMask, mOverlayGreenMask, mOverlayBlueMask, GL_TRUE);
// Draw our filled rectangle with the Filter Colour.
dglDrawRectFill(updateRect, mOverlayColor);
// Reset the Colour Mask.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
}
//------------------------------------------------------------------------------
bool fxGuiSnooper::processCameraQuery(CameraQuery * query)
{
Point3F CameraRotation; // Rotated View.
float VisibleDistance = 1100.0f; // Visible Distance.
// Get Game Connection.
GameConnection* pConnection = dynamic_cast(NetConnection::getServerConnection());
// Did we get the connection?
if (pConnection)
{
// Have we got an Attached Object?
if (mAttachedObject)
{
// Current Sweep.
EulerF mCurrentSweep;
// Create Camera Matrix.
MatrixF Camera(true);
// Craete Rotation Quaternion.
QuatF QRotation;
// Get Time Elapsed.
U32 CurrentTime = Platform::getRealMilliseconds();
U32 TimeElapsed = CurrentTime - mLastTimeStamp;
mLastTimeStamp = CurrentTime;
// Calculate new Sweep.
Point3F NewSweep( (U32)(360.0f / mSweepTime[0] * TimeElapsed) % 360,
(U32)(360.0f / mSweepTime[1] * TimeElapsed) % 360,
(U32)(360.0f / mSweepTime[2] * TimeElapsed) % 360);
// Add to Current Sweep.
mCurrentSweepMagnitude += NewSweep;
// Calculate Current Sweep Angle.
mCurrentSweep.set( mDegToRad((mSweepAmplitude[0] * mCos(mDegToRad(mCurrentSweepMagnitude[0])))/2 + mRotateView[0]),
mDegToRad((mSweepAmplitude[1] * mCos(mDegToRad(mCurrentSweepMagnitude[1])))/2 + mRotateView[1]),
mDegToRad((mSweepAmplitude[2] * mCos(mDegToRad(mCurrentSweepMagnitude[2])))/2 + mRotateView[2]));
// Set-up Quaternion Rotation.
QRotation.set(mCurrentSweep);
// Set Camera Matrix to new Rotation.
QRotation.setMatrix(&Camera);
// Set Position @ Attached Object.
Camera.setColumn(3, mAttachedObject->getBoxCenter() + mOffsetView);
// Set Camera Matrix.
query->cameraMatrix = Camera;
// Set Near/Far Planes.
query->nearPlane = 0.1;
query->farPlane = getMax(VisibleDistance, 50.f);
// Set FOV.
query->fov = mDegToRad(mFov);
// Return OK.
return(true);
}
}
// Return Error.
return(false);
}
This gui control allows you to show the scene from any named objects' viewpoint. You can setup automatic sweeping (like a security camera) in all axis as well as put a bitmap/colour overlay for the finishing effect.
Before I get started I would just like to point out that this control will seriously affect your framerate as you are effectively rendering another view, so you could see your framerate drop by half in some circumstances. Saying that, if you use it like a security camera / monitoring device then you can place it on a seperate GUI screen so that you maintain your FPS.
Create a file named "fxGuiSnooper.cc" and paste the code (at the bottom of the post) into it, compile and you should have a new control named "fxGuiSnooper" in the controls list within the GUI editor.
The properties explained are:-
(All angles are in degrees)
"ViewRotation" - Sets an initial rotation to the view.
"ViewOffset" - Sets an initial translation to the view.
"FOV" - Sets the Field-of-view. (Hmmm!)
"SweepAmplitude" - Sets the magnitude to which the view will automatically sweep. You can individually select each axis XYZ. The sweep will be centered around the initial rotation e.g 60 = (-30)->(+30).
"SweepTime" - Sets the time constants for the sweep to complete. Again, you can individually select the time for each axis. The time is in mS e.g. 1000mS = 1 Sec. Sweeping will continue for an infinite period.
"AttachedObject" - Sets the object to which the view will be attached. Essentially, the view will use the objects' position as a base for snooping. If you move the object, then the view should move with it. Try naming a tree or building as a test.
"OverlayBitmap" - Sets the bitmap which will be overlayed ontop of the view. This allows you to blend/obscure the view for screen effects such as interlacing/moire fringing etc.
"OverlayTile" - Sets the bitmap tile mode. When on, the bitmap will be tessellated over the view.
"OverlayColour" - Sets the overlay colour mode. When on, the overlay colour/mask settings are used to colourise the view so you can do green-screens etc. (See my fxGuiFilter control).
"BitmapOverlay" - Selects the bitmap filename to use for the overlay. Using "fps/client/ui/
"ColourOverlay" - Selects the RGB colours used for the colourisation effect.
"Red/Green/BlueMask" - Selects the masking effect used for the colourisation effect. A tick indicates that that colour channel can be written to using the ColourOverlay.
----------------------------------------------------------------------------------
I hope you enjoy. If there is a better way of doing what I'm doing here then please let me know. I post this stuff in the hope that I might get helpful advice regarding the details of the engine.
Melv. 3/3/2002.
----------------------------------------------------------------------------------
#include "sceneGraph/sceneGraph.h"
#include "game/gameConnection.h"
#include "console/consoleTypes.h"
#include "gui/guiTSControl.h"
class fxGuiSnooper : public GuiTSCtrl
{
private:
typedef GuiTSCtrl Parent;
Point3F mRotateView; // View Rotation.
Point3F mOffsetView; // Offset Distance.
F32 mFov; // Field of View.
Point3F mSweepAmplitude; // Sweep Amplitude.
Point3F mSweepTime; // Sweep Time.
bool mUseOverlayBitmap; // Use Overlay Bitmap Flag.
bool mUseOverlayColour; // Use Overlay Colour Flag.
bool mOverlayTile; // Overlay Tile Flag.
ColorF mOverlayColor; // Filter Colour Vector.
bool mOverlayRedMask; // Overlay Red Mask Flag.
bool mOverlayGreenMask; // Overlay Green Mask Flag.
bool mOverlayBlueMask; // Overlay Blue Mask Flag.
StringTableEntry mObjectName; // Attached Object Name.
SceneObject* mAttachedObject; // Attached Object.
U32 mLastTimeStamp; // Last Time Stamp.
Point3F mCurrentSweepMagnitude; // Current Sweep Phase.
StringTableEntry mOverlayBitmapName; // Overlay Bitmap Name.
TextureHandle mOverlayTextureHandle; // Overlay Texture Handle.
void renderWorld(const RectI & updateRect);
void onRender(Point2I offset, const RectI &updateRect);
public:
fxGuiSnooper();
static void initPersistFields();
static void consoleInit();
bool processCameraQuery(CameraQuery * query);
void setViewObject(const char* ObjectName);
void setViewRotation(Point3F Rotation);
void setOverlayBitmap(const char *name);
void setOverlayColor(ColorF OverlayColor);
void setOverlayMask(bool RedMask, bool GreenMask, bool BlueMask);
bool onWake();
void onSleep();
DECLARE_CONOBJECT(fxGuiSnooper);
};
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(fxGuiSnooper);
//------------------------------------------------------------------------------
fxGuiSnooper::fxGuiSnooper() :
mRotateView(0,0,0),
mOffsetView(0,0,0),
mFov(60.0),
mSweepAmplitude(0,0,60),
mSweepTime(5000,5000,5000),
mCurrentSweepMagnitude(0,0,0),
mAttachedObject(NULL),
mOverlayRedMask(GL_TRUE),
mOverlayGreenMask(GL_TRUE),
mOverlayBlueMask(GL_TRUE),
mOverlayTile(false),
mUseOverlayBitmap(false),
mUseOverlayColour(false),
mLastTimeStamp(Platform::getRealMilliseconds())
{
// Create Empty Attached Object Name.
mObjectName = StringTable->insert("");
// Create Empty Overlay Bitmap Name.
mOverlayBitmapName = StringTable->insert("");
// Set Default Overlay Colour.
mOverlayColor.set(1, 1, 1, 0.5f);
};
//------------------------------------------------------------------------------
void fxGuiSnooper::initPersistFields()
{
// Initialise parents' persistent fields.
Parent::initPersistFields();
// Add out own persistent fields.
addField( "ViewRotation", TypePoint3F, Offset( mRotateView, fxGuiSnooper ) );
addField( "ViewOffset", TypePoint3F, Offset( mOffsetView, fxGuiSnooper ) );
addField( "FOV", TypeF32, Offset( mFov, fxGuiSnooper ) );
addField( "SweepAmplitude", TypePoint3F, Offset( mSweepAmplitude, fxGuiSnooper ) );
addField( "SweepTime", TypePoint3F, Offset( mSweepTime, fxGuiSnooper ) );
addField( "AttachedObject", TypeString, Offset( mObjectName, fxGuiSnooper ) );
addField( "OverlayBitmap", TypeBool, Offset( mUseOverlayBitmap, fxGuiSnooper ) );
addField( "OverlayTile", TypeBool, Offset( mOverlayTile, fxGuiSnooper ) );
addField( "OverlayColour", TypeBool, Offset( mUseOverlayColour, fxGuiSnooper ) );
addField( "BitmapOverlay", TypeFilename, Offset(mOverlayBitmapName, fxGuiSnooper));
addField( "ColorOverlay", TypeColorF, Offset( mOverlayColor, fxGuiSnooper ) );
addField( "RedMask", TypeBool, Offset( mOverlayRedMask, fxGuiSnooper ) );
addField( "GreenMask", TypeBool, Offset( mOverlayGreenMask, fxGuiSnooper ) );
addField( "BlueMask", TypeBool, Offset( mOverlayBlueMask, fxGuiSnooper ) );
}
//------------------------------------------------------------------------------
bool fxGuiSnooper::onWake()
{
// Wake-up Parent.
if (!Parent::onWake()) return false;
// Set Active.
setActive(true);
// Have we an Attached Object Name?
if (mObjectName)
{
// Yes, so attach to it.
setViewObject(mObjectName);
}
// Set Overlay Bitmap.
setOverlayBitmap(mOverlayBitmapName);
// Return OK.
return true;
}
//------------------------------------------------------------------------------
void fxGuiSnooper::onSleep()
{
// Reset Overlay Texture Handle.
mOverlayTextureHandle = NULL;
// Call Parent.
Parent::onSleep();
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setViewRotation(Point3F Rotation)
{
// Set the Rotation internally.
mRotateView = Rotation;
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setViewObject(const char* ObjectName)
{
// Get Root Group.
SimGroup* SG = Sim::getRootGroup();
// Interate Sim Group.
for (SimSetIterator itr(SG); *itr; ++itr)
{
// Is this our Type?
if ((*itr)->getType() & STATIC_COLLISION_MASK)
{
// Yes, so cast our Object.
SceneObject* SceneObj = static_cast
// Check that it's a Server Object.
if (SceneObj->isServerObject())
{
const char* getName;
getName = SceneObj->getName();
// Yes, so is this our Object?
if (getName && dStrcmp(getName, ObjectName) == 0)
{
// Store Scene Object.
mAttachedObject = SceneObj;
// Return OK.
return;
}
}
}
}
// Reset Object.
mAttachedObject = NULL;
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setOverlayBitmap(const char *name)
{
// Set Overlay Bitmap Name.
mOverlayBitmapName = StringTable->insert(name);
// Have we got an Overlay Name?
if (*mOverlayBitmapName)
// Yes, so get Texture Handle.
mOverlayTextureHandle = TextureHandle(mOverlayBitmapName, BitmapTexture, true);
else
// No, so reset Texture Handle.
mOverlayTextureHandle = NULL;
// Update.
setUpdate();
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setOverlayColor(ColorF OverlayColor)
{
// Set the Overlay Colour internally.
mOverlayColor = OverlayColor;
}
//------------------------------------------------------------------------------
void fxGuiSnooper::setOverlayMask(bool RedMask, bool GreenMask, bool BlueMask)
{
// Set the Overlay Masks internally.
mOverlayRedMask = RedMask;
mOverlayGreenMask = GreenMask;
mOverlayBlueMask = BlueMask;
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setViewRotation,void,5,5,"Sets View Rotation.")
{
Point3F Rotation;
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast
// Fetch Rotation.
Rotation.set( mDegToRad(dAtof(argv[2])),
mDegToRad(dAtof(argv[3])),
mDegToRad(dAtof(argv[4])));
// Set Rotation.
Viewport->setViewRotation(Rotation);
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setViewObject,void,3,3,"Sets View to Object.")
{
F32 Rotation;
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast
// Set the GuiFilter Filter Colour.
Viewport->setViewObject(argv[2]);
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setOverlayBitmap,void,3,3,"Sets Overlay Bitmap.")
{
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast
// Set Overlay Bitmap.
Viewport->setOverlayBitmap(argv[2]);
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setOverlayColor,void,5,6,"Sets Overlay Color.")
{
F32 r,g,b,a;
ColorF TempColor;
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast
// Convert RGB Ascii parms to float.
r = dAtof(argv[2]);
g = dAtof(argv[3]);
b = dAtof(argv[4]);
// Did we get an alpha param?
if (argc == 6)
// Yep, so convert it.
a = dAtof(argv[5]);
else
// Nope, so default to 1.
a = 1;
// Setup our temporary colour vector.
TempColor.set(r,g,b,a);
// Set the fxGuiSnooper Overlay Colour.
Viewport->setOverlayColor(TempColor);
}
//------------------------------------------------------------------------------
ConsoleMethod(fxGuiSnooper,setOverlayMask,void,5,5,"Sets Overlay Masks.")
{
F32 r,g,b;
// Fetch the fxGuiSnooper object.
fxGuiSnooper *Viewport = static_cast
// Convert RGB Ascii parms to float.
r = dAtof(argv[2]);
g = dAtof(argv[3]);
b = dAtof(argv[4]);
// Set the fxGuiSnooper Masks.
Viewport->setOverlayMask(r,g,b);
}
//------------------------------------------------------------------------------
static void cfxGuiBitmapSetOverlayBitmap(SimObject *obj, S32, const char **argv)
{
// Fetch HUD Control.
fxGuiSnooper *ctrl = static_cast
// Set Overlay Bitmap.
ctrl->setOverlayBitmap(argv[2]);
}
//------------------------------------------------------------------------------
void fxGuiSnooper::consoleInit()
{
Con::addCommand("fxGuiSnooper", "setOverlayBitmap", cfxGuiBitmapSetOverlayBitmap, "fxGuiSnooper.setOverlayBitmap(Bitmap)", 3, 3);
}
//------------------------------------------------------------------------------
void fxGuiSnooper::renderWorld(const RectI & updateRect)
{
// Set-up OpenGL for a scene render.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClear(GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glMatrixMode(GL_MODELVIEW);
dglSetCanonicalState();
// Render Client Scene Graph.
gClientSceneGraph->renderScene();
// Disable Depth Test.
glDisable(GL_DEPTH_TEST);
}
//------------------------------------------------------------------------------
void fxGuiSnooper::onRender(Point2I offset, const RectI &updateRect)
{
// Call Parent Render.
Parent::onRender(offset, updateRect);
// Set Clipping Rectangle to GUI Bounds.
dglSetClipRect(mBounds);
// Do we have an attached Object?
if (!mAttachedObject)
{
// No, so signal to user this problem ...
ColorF ErrorColor(1,0,0);
dglDrawRectFill(updateRect, ErrorColor);
ErrorColor.set(1,1,1);
char buf[256];
dSprintf(buf, sizeof(buf), "*** Object not selected ***");
dglSetBitmapModulation(ErrorColor);
dglDrawText(mProfile->mFont, offset, buf);
dglClearBitmapModulation();
// Return Error.
return;
}
// Are we using the Overlay Bitmap?
if (mUseOverlayBitmap)
{
// Yes, so do we have a texture Handle?
if (mOverlayTextureHandle)
{
// Yes, so clear Bitmap Modulation.
dglClearBitmapModulation();
// Are we tiling the Overlay Bitmap?
if(mOverlayTile)
{
RectI SrcRegion;
RectI DstRegion;
// Yes, so fetch texture object.
TextureObject* TextureObj = (TextureObject *)mOverlayTextureHandle;
// Calculate Tesselation Count.
float XTess = ((float)mBounds.extent.x/(float)TextureObj->bitmapWidth)+1;
float YTess = ((float)mBounds.extent.y/(float)TextureObj->bitmapHeight)+1;
for(int y = 0; y < YTess; ++y)
{
for(int x = 0; x < XTess; ++x)
{
// Calculate Source Region.
SrcRegion.set(0,0,TextureObj->bitmapWidth, TextureObj->bitmapHeight);
// Calculate Destination Region.
DstRegion.set(((TextureObj->bitmapWidth*x)+offset.x),
((TextureObj->bitmapHeight*y)+offset.y),
TextureObj->bitmapWidth,
TextureObj->bitmapHeight);
// Draw Tiled Bitmap.
dglDrawBitmapStretchSR(TextureObj, DstRegion, SrcRegion, false);
}
}
}
else
{
// No, so draw stretched Bitmap.
dglDrawBitmapStretch(mOverlayTextureHandle, mBounds);
}
}
}
// Are we using the Overlay Colour?
if (mUseOverlayColour)
{
// Set Colour Mask.
glColorMask(mOverlayRedMask, mOverlayGreenMask, mOverlayBlueMask, GL_TRUE);
// Draw our filled rectangle with the Filter Colour.
dglDrawRectFill(updateRect, mOverlayColor);
// Reset the Colour Mask.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
}
//------------------------------------------------------------------------------
bool fxGuiSnooper::processCameraQuery(CameraQuery * query)
{
Point3F CameraRotation; // Rotated View.
float VisibleDistance = 1100.0f; // Visible Distance.
// Get Game Connection.
GameConnection* pConnection = dynamic_cast
// Did we get the connection?
if (pConnection)
{
// Have we got an Attached Object?
if (mAttachedObject)
{
// Current Sweep.
EulerF mCurrentSweep;
// Create Camera Matrix.
MatrixF Camera(true);
// Craete Rotation Quaternion.
QuatF QRotation;
// Get Time Elapsed.
U32 CurrentTime = Platform::getRealMilliseconds();
U32 TimeElapsed = CurrentTime - mLastTimeStamp;
mLastTimeStamp = CurrentTime;
// Calculate new Sweep.
Point3F NewSweep( (U32)(360.0f / mSweepTime[0] * TimeElapsed) % 360,
(U32)(360.0f / mSweepTime[1] * TimeElapsed) % 360,
(U32)(360.0f / mSweepTime[2] * TimeElapsed) % 360);
// Add to Current Sweep.
mCurrentSweepMagnitude += NewSweep;
// Calculate Current Sweep Angle.
mCurrentSweep.set( mDegToRad((mSweepAmplitude[0] * mCos(mDegToRad(mCurrentSweepMagnitude[0])))/2 + mRotateView[0]),
mDegToRad((mSweepAmplitude[1] * mCos(mDegToRad(mCurrentSweepMagnitude[1])))/2 + mRotateView[1]),
mDegToRad((mSweepAmplitude[2] * mCos(mDegToRad(mCurrentSweepMagnitude[2])))/2 + mRotateView[2]));
// Set-up Quaternion Rotation.
QRotation.set(mCurrentSweep);
// Set Camera Matrix to new Rotation.
QRotation.setMatrix(&Camera);
// Set Position @ Attached Object.
Camera.setColumn(3, mAttachedObject->getBoxCenter() + mOffsetView);
// Set Camera Matrix.
query->cameraMatrix = Camera;
// Set Near/Far Planes.
query->nearPlane = 0.1;
query->farPlane = getMax(VisibleDistance, 50.f);
// Set FOV.
query->fov = mDegToRad(mFov);
// Return OK.
return(true);
}
}
// Return Error.
return(false);
}
About the author
#2
I'm sure there are many ways to approach this effect and this is just one of them.
I use a variant of this control for my project which attachs to custom camera-marker objects (which themselves store the view settings).
03/03/2002 (12:47 pm)
Yes, you are correct if that's all you wanted to do but I like the ability to encapsulate the rotation/zoom/overlay effects with the ability to place this in-window alongside the main-view without touching the players view.I'm sure there are many ways to approach this effect and this is just one of them.
I use a variant of this control for my project which attachs to custom camera-marker objects (which themselves store the view settings).
#3
I was thinking about the camera thing last night and that was one of the main problems I thought of. It may be necessary to completely change your control point or whatever the net scope is centered around... (though on the bright side, this would stop the frame rate from dropping heh)
just something to check out
-noh
Edit: by the way... i knew a guy on everquest/tallon zek named melvin mayhem.. coincidence? or no?
03/03/2002 (1:13 pm)
Do you know how playing over the net would affect what you see in the other view? For example, would just viewing the world through a 'security camera' show people running past if the server doesn't know to ghost those locations to you (assuming the camera is outside the net scope of your current control point)I was thinking about the camera thing last night and that was one of the main problems I thought of. It may be necessary to completely change your control point or whatever the net scope is centered around... (though on the bright side, this would stop the frame rate from dropping heh)
just something to check out
-noh
Edit: by the way... i knew a guy on everquest/tallon zek named melvin mayhem.. coincidence? or no?
#4
But thanks for the code, anyways!!
03/03/2002 (2:54 pm)
Cool effect, indeed! But adding one "security camera" into my testlevel decreases the framerate by approx. 20 fps... that's pretty heavy... Any chance to optimize performance?But thanks for the code, anyways!!
#5
You have to realise that the control renders another view completely so you will always get a big hit on framerate. Most of the time taken for your FPS figure is calculating/rendering the view so adding another will nearly always have this effect. Nothing is free in this game (sorry for the pun). :)
The call to render the client scene graph is atomic as far as I'm concerned so I'm not sure if there are any stages such as lighting that can be skipped. I will have to investigate that further.
There are a few things that you can do in terms of optimisation.
- You could show the camera in another HUD view e.g. select your new GUI which has the camera view in it. If you are not rendering the main view then your FPS should stay almost the same.
- It might be possible to reduce the frame-rate of the view by only rendering alternate views. This would mean rendering to a bitmap so that it could be blitted on alternate frames.
Games that use this effect normally switch to an alternate view though.
03/04/2002 (12:41 am)
Hmmm....You have to realise that the control renders another view completely so you will always get a big hit on framerate. Most of the time taken for your FPS figure is calculating/rendering the view so adding another will nearly always have this effect. Nothing is free in this game (sorry for the pun). :)
The call to render the client scene graph is atomic as far as I'm concerned so I'm not sure if there are any stages such as lighting that can be skipped. I will have to investigate that further.
There are a few things that you can do in terms of optimisation.
- You could show the camera in another HUD view e.g. select your new GUI which has the camera view in it. If you are not rendering the main view then your FPS should stay almost the same.
- It might be possible to reduce the frame-rate of the view by only rendering alternate views. This would mean rendering to a bitmap so that it could be blitted on alternate frames.
Games that use this effect normally switch to an alternate view though.
#6
03/04/2002 (9:52 am)
melv, isnt there anyway to stop rendering the original view while in the alternate one?
#7
You should be able to either call "Canvas.setContent(MyNewGui);" from script or "Canvas->setContentControl(MyNewGuiObject);" for within the engine.
"\engine\gui\guiCanvas.cc" (Line 88) shows how this in done within the engine. or the "Start Mission" buttons' 'command' field from the mainmenu GUI.
Just create a GUI with only the Snooper in it (and any extra stuff for eye-food). Whenever you want to use one, then simply tell the Snooper where to snoop and fire-up the GUI.
I'm just going to try this myself (in case I'm misleading anyone). :)
p.s. NohBdy: Certainly not Melvin Mayhem, but it sounds kinda cool. Well, about as good as the damn name "Melvyn" can get anyway. :)
03/04/2002 (12:15 pm)
You are quite correct.You should be able to either call "Canvas.setContent(MyNewGui);" from script or "Canvas->setContentControl(MyNewGuiObject);" for within the engine.
"\engine\gui\guiCanvas.cc" (Line 88) shows how this in done within the engine. or the "Start Mission" buttons' 'command' field from the mainmenu GUI.
Just create a GUI with only the Snooper in it (and any extra stuff for eye-food). Whenever you want to use one, then simply tell the Snooper where to snoop and fire-up the GUI.
I'm just going to try this myself (in case I'm misleading anyone). :)
p.s. NohBdy: Certainly not Melvin Mayhem, but it sounds kinda cool. Well, about as good as the damn name "Melvyn" can get anyway. :)
#8
(So as there is no confusion at all I will give you a step by step guide)
- Run up the Demo App and start-up good ol' "Scorched Planet".
- Goto the Gui editor (F10) and create a new GUI by selected "New" (above "Save"). In the dialog enter "SnooperCam" as the GUI name and select "fxGuiSnooper" from the class list. OK.
- Edit the fxGuiSnooper object e.g. select a named world object like a pyramid or something (you may have to edit these in the world editor if you haven't already done so). Set the Z sweep time to something like 2000mS, apply and save the gui to "fps/client/ui".
- Goto the SCRIPT file "fps/client/init.cs" and insert the line 'exec("./ui/SnooperCamGui.gui");' in the "Load up the Game GUIs" block @ line 48.
- Select the "PlayGui" gui screen. Quit and restart.
Go into "Scorched Planet" again, drop down the console and type 'Canvas.setContent("SnooperCam");' to bring up your SnooperCam and 'Canvas.setContent("PlayGui");' to restore the 'normal' game screen.
Dependent on how your gui works you may want to modify this example.
Hope this helps someone, somewhere. :)
03/04/2002 (1:08 pm)
Ok, here goes then ...(So as there is no confusion at all I will give you a step by step guide)
- Run up the Demo App and start-up good ol' "Scorched Planet".
- Goto the Gui editor (F10) and create a new GUI by selected "New" (above "Save"). In the dialog enter "SnooperCam" as the GUI name and select "fxGuiSnooper" from the class list. OK.
- Edit the fxGuiSnooper object e.g. select a named world object like a pyramid or something (you may have to edit these in the world editor if you haven't already done so). Set the Z sweep time to something like 2000mS, apply and save the gui to "fps/client/ui".
- Goto the SCRIPT file "fps/client/init.cs" and insert the line 'exec("./ui/SnooperCamGui.gui");' in the "Load up the Game GUIs" block @ line 48.
- Select the "PlayGui" gui screen. Quit and restart.
Go into "Scorched Planet" again, drop down the console and type 'Canvas.setContent("SnooperCam");' to bring up your SnooperCam and 'Canvas.setContent("PlayGui");' to restore the 'normal' game screen.
Dependent on how your gui works you may want to modify this example.
Hope this helps someone, somewhere. :)
#9
I hope that this thread is stil alive.
I have made a change in the c class code this is my fist in c++ so I hope that you can tell me if I did the correct thing.
I changed the setViewObject not to loop through the Sim set why does it need to do it when there is a method to find it directly
the findObject method.
The code seems to work fine.
Please test it. I have.
void fxGuiSnooper::setViewObject(const char* ObjectName)
{
SimObject* SimObject = Sim::findObject(ObjectName);
// Yes, so cast our Object.
if(SimObject)
{
SceneObject* SceneObj=static_castSimObject);
// Check that it's a Server Object.
if(SceneObj->isServerObject())
{
mAttachedObject = SceneObj;
return;
}
}
// Return OK.
return;
// Reset Object.
mAttachedObject = NULL;
}
The old Code is still in the class file.
Well I hope this one will improve performance.
As I sed I am new to C++ Programming.
And this is what I figure out that must happen in an hour or two
So do not expect miracles.
I am still trying to figure out how all fits together.
reading reading ....
I must say that this is far less code than the original.
12/08/2003 (4:21 am)
Hi all,I hope that this thread is stil alive.
I have made a change in the c class code this is my fist in c++ so I hope that you can tell me if I did the correct thing.
I changed the setViewObject not to loop through the Sim set why does it need to do it when there is a method to find it directly
the findObject method.
The code seems to work fine.
Please test it. I have.
void fxGuiSnooper::setViewObject(const char* ObjectName)
{
SimObject* SimObject = Sim::findObject(ObjectName);
// Yes, so cast our Object.
if(SimObject)
{
SceneObject* SceneObj=static_cast
// Check that it's a Server Object.
if(SceneObj->isServerObject())
{
mAttachedObject = SceneObj;
return;
}
}
// Return OK.
return;
// Reset Object.
mAttachedObject = NULL;
}
The old Code is still in the class file.
Well I hope this one will improve performance.
As I sed I am new to C++ Programming.
And this is what I figure out that must happen in an hour or two
So do not expect miracles.
I am still trying to figure out how all fits together.
reading reading ....
I must say that this is far less code than the original.
#10
This object was done when I'd been looking at the engine for about 5 minutes and the original post was done 21 months ago!
It looks like you're still learning here so I'll give you a hint at why this works on a local-client only. A local client can use Sim::findObject and it returns objects that are on the server perfectly but if you try running this on a client that is not running within the same process as the server and you'll get NULL from Sim::findObject. There are ways to bypass this limitation within the control but they nearly all involve potentially breaking 'security'.
Just try running this on a remote client to see what I mean. This was done "back in the day" when I was still learning about the inner workings of the TGE.
- Melv.
12/08/2003 (4:34 am)
Nick,This object was done when I'd been looking at the engine for about 5 minutes and the original post was done 21 months ago!
It looks like you're still learning here so I'll give you a hint at why this works on a local-client only. A local client can use Sim::findObject and it returns objects that are on the server perfectly but if you try running this on a client that is not running within the same process as the server and you'll get NULL from Sim::findObject. There are ways to bypass this limitation within the control but they nearly all involve potentially breaking 'security'.
Just try running this on a remote client to see what I mean. This was done "back in the day" when I was still learning about the inner workings of the TGE.
- Melv.
#11
But I will test the network and server process.
I will try it at home when I get a chance.
Is their a way I can get all the in's and outs of all the code
Like the SDK docs in a zip file to download someplace.
I do not have a line at home and the docs really helps me but I need to take it home and read through it without desterbanse from ppl at work - O yes I know this has nothing to do with my coding skills (or the thread).
12/08/2003 (5:11 am)
Thanks for the fast post I am not attaking the code it just looked simpler the way I did it.But I will test the network and server process.
I will try it at home when I get a chance.
Is their a way I can get all the in's and outs of all the code
Like the SDK docs in a zip file to download someplace.
I do not have a line at home and the docs really helps me but I need to take it home and read through it without desterbanse from ppl at work - O yes I know this has nothing to do with my coding skills (or the thread).
#12
You could try this...
Torque Docs
You can of course compile the engine documentation with DOxygen.
- Melv.
12/08/2003 (8:38 am)
Nick,You could try this...
Torque Docs
You can of course compile the engine documentation with DOxygen.
- Melv.
#13
Have you released any titles?
I would like to have a look at them.
12/08/2003 (9:42 pm)
Thanks for the link.Have you released any titles?
I would like to have a look at them.
#15
If you need ppl to help you with your site dev I am your man.
This will be for free becouse I may need your help in the future
coding help, advice not doing actual coding I can see that you a busy man.
Tell me where are your team working from.
What tools are you using for graphics?
I am in South africa.
12/09/2003 (2:02 am)
Hi,If you need ppl to help you with your site dev I am your man.
This will be for free becouse I may need your help in the future
coding help, advice not doing actual coding I can see that you a busy man.
Tell me where are your team working from.
What tools are you using for graphics?
I am in South africa.
#16
We've pretty much got everything covered but thanks for the offer. If you're refering to the models, they were done in MAX by our artist. Not sure about the other tools he uses, just that he does a great job. :)
- Melv.
12/09/2003 (8:31 am)
Nick,We've pretty much got everything covered but thanks for the offer. If you're refering to the models, they were done in MAX by our artist. Not sure about the other tools he uses, just that he does a great job. :)
- Melv.
Torque 3D Owner Xavier "eXoDuS" Amado
Default Studio Name