fxGuiSnooper TGEA
by Shaderman · 11/12/2007 (1:44 pm) · 14 comments
Download Code File
I've ported Melvyn's work to TGEA (1.0.3). Here are the setup instructions / properties (copied from his resource):
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.
Add the file "fxGuiSnooper.cpp" to your engine code, compile and you should have a new control named "fxGuiSnooper" in the controls list within the GUI editor.
The "camera.png" can be used as an example for the bitmap overlay (not a very good one I might add) but is not needed otherwise.
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 bsae 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.
Thanks for sharing Melvyn!
Stefan
I've ported Melvyn's work to TGEA (1.0.3). Here are the setup instructions / properties (copied from his resource):
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.
Add the file "fxGuiSnooper.cpp" to your engine code, compile and you should have a new control named "fxGuiSnooper" in the controls list within the GUI editor.
The "camera.png" can be used as an example for the bitmap overlay (not a very good one I might add) but is not needed otherwise.
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 bsae 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.
Thanks for sharing Melvyn!
Stefan
#2
http://www.garagegames.com/mg/forums/result.thread.php?qt=58720
12/01/2007 (4:40 am)
James, that is already working @ a decent extent.http://www.garagegames.com/mg/forums/result.thread.php?qt=58720
#3
12/01/2007 (5:08 am)
Yeh I found that after I ported it over myself :P
#4
When the gui renders it is producing an odd picture in picture effect.
07/15/2008 (8:46 pm)
I have been trying to update this to TGEA 1.7.1 and ran into a little problem.When the gui renders it is producing an odd picture in picture effect.
#5
fxGuiSnooper.cpp
07/16/2008 (11:24 am)
Just realized it doesn't help much without code.fxGuiSnooper.cpp
#include "sceneGraph/sceneGraph.h"
#include "T3D/gameConnection.h"
#include "console/consoleTypes.h"
#include "gui/3d/guiTSControl.h"
#include "gui/core/guiControl.h"
class GuiSnooper : 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.
GFXTexHandle mOverlayTextureHandle; // Overlay Texture Handle.
void renderWorld(const RectI & updateRect);
void onRender(Point2I offset, const RectI &updateRect);
public:
GuiSnooper();
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(GuiSnooper);
};
IMPLEMENT_CONOBJECT(GuiSnooper);
//------------------------------------------------------------------------------
GuiSnooper::GuiSnooper() :
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(true),
mOverlayGreenMask(true),
mOverlayBlueMask(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 GuiSnooper::initPersistFields()
{
// Initialise parents' persistent fields.
Parent::initPersistFields();
// Add out own persistent fields.
addField( "ViewRotation", TypePoint3F, Offset( mRotateView, GuiSnooper ) );
addField( "ViewOffset", TypePoint3F, Offset( mOffsetView, GuiSnooper ) );
addField( "FOV", TypeF32, Offset( mFov, GuiSnooper ) );
addField( "SweepAmplitude", TypePoint3F, Offset( mSweepAmplitude, GuiSnooper ) );
addField( "SweepTime", TypePoint3F, Offset( mSweepTime, GuiSnooper ) );
addField( "AttachedObject", TypeString, Offset( mObjectName, GuiSnooper ) );
addField( "OverlayBitmap", TypeBool, Offset( mUseOverlayBitmap, GuiSnooper ) );
addField( "OverlayTile", TypeBool, Offset( mOverlayTile, GuiSnooper ) );
addField( "OverlayColour", TypeBool, Offset( mUseOverlayColour, GuiSnooper ) );
addField( "BitmapOverlay", TypeFilename, Offset(mOverlayBitmapName, GuiSnooper));
addField( "ColorOverlay", TypeColorF, Offset( mOverlayColor, GuiSnooper ) );
addField( "RedMask", TypeBool, Offset( mOverlayRedMask, GuiSnooper ) );
addField( "GreenMask", TypeBool, Offset( mOverlayGreenMask, GuiSnooper ) );
addField( "BlueMask", TypeBool, Offset( mOverlayBlueMask, GuiSnooper ) );
}
//------------------------------------------------------------------------------
bool GuiSnooper::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 GuiSnooper::onSleep()
{
// Reset Overlay Texture Handle.
mOverlayTextureHandle = NULL;
// Call Parent.
Parent::onSleep();
}
//------------------------------------------------------------------------------
void GuiSnooper::setViewRotation(Point3F Rotation)
{
// Set the Rotation internally.
mRotateView = Rotation;
}
//------------------------------------------------------------------------------
void GuiSnooper::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<SceneObject*>(*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 GuiSnooper::setOverlayBitmap(const char *name)
{
// Set Overlay Bitmap Name.
mOverlayBitmapName = StringTable->insert(name);
if (*mOverlayBitmapName)
// Yes, so get Texture Handle.
mOverlayTextureHandle.set( mOverlayBitmapName, &GFXDefaultGUIProfile );
else
// No, so reset Texture Handle.
mOverlayTextureHandle = NULL;
// Update.
setUpdate();
}
//------------------------------------------------------------------------------
void GuiSnooper::setOverlayColor(ColorF OverlayColor)
{
// Set the Overlay Colour internally.
mOverlayColor = OverlayColor;
}
//------------------------------------------------------------------------------
void GuiSnooper::setOverlayMask(bool RedMask, bool GreenMask, bool BlueMask)
{
// Set the Overlay Masks internally.
mOverlayRedMask = RedMask;
mOverlayGreenMask = GreenMask;
mOverlayBlueMask = BlueMask;
}
//------------------------------------------------------------------------------
ConsoleMethod(GuiSnooper,setViewRotation,void,5,5,"Sets View Rotation.")
{
Point3F Rotation;
// Fetch the GuiSnooper object.
GuiSnooper *Viewport = static_cast<GuiSnooper*>(object);
// Fetch Rotation.
Rotation.set( mDegToRad(dAtof(argv[2])),
mDegToRad(dAtof(argv[3])),
mDegToRad(dAtof(argv[4])));
// Set Rotation.
Viewport->setViewRotation(Rotation);
}
//------------------------------------------------------------------------------
ConsoleMethod(GuiSnooper,setViewObject,void,3,3,"Sets View to Object.")
{
// F32 Rotation;
// Fetch the GuiSnooper object.
GuiSnooper *Viewport = static_cast<GuiSnooper*>(object);
// Set the GuiFilter Filter Colour.
Viewport->setViewObject(argv[2]);
}
//------------------------------------------------------------------------------
ConsoleMethod(GuiSnooper,setOverlayBitmap,void,3,3,"Sets Overlay Bitmap.")
{
// Fetch the GuiSnooper object.
GuiSnooper *Viewport = static_cast<GuiSnooper*>(object);
// Set Overlay Bitmap.
Viewport->setOverlayBitmap(argv[2]);
}
//------------------------------------------------------------------------------
ConsoleMethod(GuiSnooper,setOverlayColor,void,5,6,"Sets Overlay Color.")
{
F32 r,g,b,a;
ColorF TempColor;
// Fetch the GuiSnooper object.
GuiSnooper *Viewport = static_cast<GuiSnooper*>(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 GuiSnooper Overlay Colour.
Viewport->setOverlayColor(TempColor);
}
//------------------------------------------------------------------------------
ConsoleMethod(GuiSnooper,setOverlayMask,void,5,5,"Sets Overlay Masks.")
{
F32 r,g,b;
// Fetch the GuiSnooper object.
GuiSnooper *Viewport = static_cast<GuiSnooper*>(object);
// Convert RGB Ascii parms to float.
r = dAtof(argv[2]);
g = dAtof(argv[3]);
b = dAtof(argv[4]);
// Set the GuiSnooper Masks.
Viewport->setOverlayMask(r,g,b);
}
//------------------------------------------------------------------------------
static void cfxGuiBitmapSetOverlayBitmap(SimObject *obj, S32, const char **argv)
{
// Fetch HUD Control.
GuiSnooper *ctrl = static_cast<GuiSnooper*>(obj);
// Set Overlay Bitmap.
ctrl->setOverlayBitmap(argv[2]);
}
//------------------------------------------------------------------------------
void GuiSnooper::consoleInit()
{
Con::addCommand("GuiSnooper", "setOverlayBitmap", cfxGuiBitmapSetOverlayBitmap, "GuiSnooper.setOverlayBitmap(Bitmap)", 3, 3);
}
//------------------------------------------------------------------------------
void GuiSnooper::renderWorld(const RectI & updateRect)
{
GFX->clear(GFXClearZBuffer, ColorI(0,0,0), 1.0f, 0);
GFX->setZEnable(true);
GFX->setZWriteEnable(true);
GFX->setZFunc(GFXCmpLessEqual);
GFX->setCullMode(GFXCullNone);
// Render Client Scene Graph.
gClientSceneGraph->renderScene();
GFX->setZEnable(false);
}
//------------------------------------------------------------------------------
void GuiSnooper::onRender(Point2I offset, const RectI &updateRect)
{
// Call Parent Render.
Parent::onRender(offset, updateRect);
// Set Clipping Rectangle to GUI Bounds.
GFX->setClipRect(getBounds());
// Do we have an attached Object?
if (!mAttachedObject)
{
// No, so signal to user this problem ...
ColorF ErrorColor(1,0,0);
GFX->getDrawUtil()->drawRectFill(updateRect, ErrorColor);
ErrorColor.set(1,1,1);
char buf[256];
dSprintf(buf, sizeof(buf), "*** Object not selected ***");
GFX->getDrawUtil()->setBitmapModulation(ErrorColor);
GFX->getDrawUtil()->drawText(mProfile->mFont, offset, buf);
GFX->getDrawUtil()->clearBitmapModulation();
// 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.
GFX->getDrawUtil()->clearBitmapModulation();
// Are we tiling the Overlay Bitmap?
if(mOverlayTile)
{
RectI SrcRegion;
RectI DstRegion;
// Yes, so fetch texture object.
GFXTextureObject* TextureObj = mOverlayTextureHandle;
// Calculate Tesselation Count.
float XTess = ((float)mBounds.extent.x/(float)TextureObj->mBitmapSize.x)+1;
float YTess = ((float)mBounds.extent.y/(float)TextureObj->mBitmapSize.y)+1;
for(int y = 0; y < YTess; ++y)
{
for(int x = 0; x < XTess; ++x)
{
// Calculate Source Region.
SrcRegion.set(0,0,TextureObj->mBitmapSize.x, TextureObj->mBitmapSize.y);
// Calculate Destination Region.
DstRegion.set(((TextureObj->mBitmapSize.x*x)+offset.x),
((TextureObj->mBitmapSize.y*y)+offset.y),
TextureObj->mBitmapSize.x,
TextureObj->mBitmapSize.y);
// Draw Tiled Bitmap.
GFX->getDrawUtil()->drawBitmapStretchSR(TextureObj, DstRegion, SrcRegion);
}
}
}
else
{
// No, so draw stretched Bitmap.
GFX->getDrawUtil()->drawBitmapStretch(mOverlayTextureHandle, mBounds);
}
}
}
// Are we using the Overlay Colour?
if (mUseOverlayColour)
{
// Set Colour Mask.
GFX->enableColorWrites(mOverlayRedMask, mOverlayGreenMask, mOverlayBlueMask, true);
// Draw our filled rectangle with the Filter Colour.
GFX->getDrawUtil()->drawRectFill(updateRect, mOverlayColor);
// Reset the Colour Mask.
GFX->enableColorWrites(true, true, true, true);
}
}
//------------------------------------------------------------------------------
bool GuiSnooper::processCameraQuery(CameraQuery * query)
{
Point3F CameraRotation; // Rotated View.
float VisibleDistance = 1100.0f; // Visible Distance.
// Get Game Connection.
GameConnection* pConnection = dynamic_cast<GameConnection *>(NetConnection::getConnectionToServer());
// 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.1f;
query->farPlane = getMax(VisibleDistance, 50.f);
// Set FOV.
query->fov = mDegToRad(mFov);
// Return OK.
return(true);
}
}
// Return Error.
return(false);
}
#6
Also I needed to replace the three instances of "mBounds" with "getBounds()" before the code would even compile. Said mBounds is a private member.
07/23/2008 (10:12 am)
I'm getting the same thing, picture-in-picture. With two GuiSnooper windows, the first is PIP and the second is 2PIP. Also I needed to replace the three instances of "mBounds" with "getBounds()" before the code would even compile. Said mBounds is a private member.
#7
The problem as it turns out is a call in Parent::onRender .
So I duplicated it's code in GuiSnooper::onRender then commenting out the one line that was causing the error.
This is the line in Parent::render that is the problem.
//gClientSceneGraph->getLightManager()->hdrRender();
This is the code I used to fix it for the GuiSnooper.
07/23/2008 (10:44 am)
I actually found the problem the same day and tried to post it but GG website kept eating my post so I went on to other things and forgot to come back and post the fix.The problem as it turns out is a call in Parent::onRender .
So I duplicated it's code in GuiSnooper::onRender then commenting out the one line that was causing the error.
This is the line in Parent::render that is the problem.
//gClientSceneGraph->getLightManager()->hdrRender();
This is the code I used to fix it for the GuiSnooper.
void GuiSnooper::onRender(Point2I offset, const RectI &updateRect)
{
// Call Parent Render.
//Parent::onRender(offset, updateRect);
if(!processCameraQuery(&mLastCameraQuery))
return;
// Clear the zBuffer so GUI doesn't hose object rendering accidentally
GFX->clear( GFXClearZBuffer , ColorI(20,20,20), 1.0f, 0 );
// set up the camera and viewport stuff:
F32 wwidth;
F32 wheight;
if(!mLastCameraQuery.ortho)
{
wwidth = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2);
wheight = F32(getHeight()) / F32(getWidth()) * wwidth;
}
else
{
wwidth = mLastCameraQuery.fov;
wheight = F32(getHeight()) / F32(getWidth()) * wwidth;
}
F32 hscale = wwidth * 2 / F32(getWidth());
F32 vscale = wheight * 2 / F32(getHeight());
F32 left = (updateRect.point.x - offset.x) * hscale - wwidth;
F32 right = (updateRect.point.x + updateRect.extent.x - offset.x) * hscale - wwidth;
F32 top = wheight - vscale * (updateRect.point.y - offset.y);
F32 bottom = wheight - vscale * (updateRect.point.y + updateRect.extent.y - offset.y);
GFX->setViewport( updateRect );
if(!mLastCameraQuery.ortho)
{
GFX->setFrustum( left, right, bottom, top,
mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane );
}
else
{
GFX->setOrtho(left, right, bottom, top, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, true);
mOrthoWidth = right - left;
mOrthoHeight = top - bottom;
}
// We're going to be displaying this render at size of this control in
// pixels - let the scene know so that it can calculate e.g. reflections
// correctly for that final display result.
gClientSceneGraph->setDisplayTargetResolution(getExtent());
gClientSceneGraph->setVisibleDistance( mLastCameraQuery.farPlane );
gClientSceneGraph->getLightManager()->hdrPrepare(updateRect.point, updateRect.extent);
// save the world matrix before attempting to draw anything
//GFX->pushWorldMatrix();
// Set the GFX world matrix to the world-to-camera transform, but don't
// change the cameraMatrix in mLastCameraQuery. This is because
// mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world
// transform. In-place invert would save a copy but mess up any GUIs that
// depend on that value.
MatrixF worldToCamera = mLastCameraQuery.cameraMatrix;
worldToCamera.inverse();
GFX->setWorldMatrix( worldToCamera );
mSaveProjection = GFX->getProjectionMatrix();
mSaveModelview = GFX->getWorldMatrix();
mSaveViewport = updateRect;
renderWorld(updateRect);
// if(gDebugDraw) gDebugDraw->render();
// gClientSceneGraph->getLightManager()->hdrRender();//this is causing the picture in picture effect
// restore the world matrix so the GUI will render correctly
//GFX->popWorldMatrix();
// renderChildControls(offset, updateRect);
smFrameCount++;
// Set Clipping Rectangle to GUI Bounds.
GFX->setClipRect(getBounds());
// Do we have an attached Object?
if (!mAttachedObject)
{
// No, so signal to user this problem ...
ColorF ErrorColor(1,0,0);
GFX->getDrawUtil()->drawRectFill(updateRect, ErrorColor);
ErrorColor.set(1,1,1);
char buf[256];
dSprintf(buf, sizeof(buf), "*** Object not selected ***");
GFX->getDrawUtil()->setBitmapModulation(ErrorColor);
GFX->getDrawUtil()->drawText(mProfile->mFont, offset, buf);
GFX->getDrawUtil()->clearBitmapModulation();
// 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.
GFX->getDrawUtil()->clearBitmapModulation();
// Are we tiling the Overlay Bitmap?
if(mOverlayTile)
{
RectI SrcRegion;
RectI DstRegion;
// Yes, so fetch texture object.
GFXTextureObject* TextureObj = mOverlayTextureHandle;
// Calculate Tesselation Count.
float XTess = ((float)getBounds().extent.x/(float)TextureObj->mBitmapSize.x)+1;
float YTess = ((float)getBounds().extent.y/(float)TextureObj->mBitmapSize.y)+1;
for(int y = 0; y < YTess; ++y)
{
for(int x = 0; x < XTess; ++x)
{
// Calculate Source Region.
SrcRegion.set(0,0,TextureObj->mBitmapSize.x, TextureObj->mBitmapSize.y);
// Calculate Destination Region.
DstRegion.set(((TextureObj->mBitmapSize.x*x)+offset.x),
((TextureObj->mBitmapSize.y*y)+offset.y),
TextureObj->mBitmapSize.x,
TextureObj->mBitmapSize.y);
// Draw Tiled Bitmap.
GFX->getDrawUtil()->drawBitmapStretchSR(TextureObj, DstRegion, SrcRegion);
}
}
}
else
{
// No, so draw stretched Bitmap.
GFX->getDrawUtil()->drawBitmapStretch(mOverlayTextureHandle, getBounds());
}
}
}
// Are we using the Overlay Colour?
if (mUseOverlayColour)
{
// Set Colour Mask.
GFX->enableColorWrites(mOverlayRedMask, mOverlayGreenMask, mOverlayBlueMask, true);
// Draw our filled rectangle with the Filter Colour.
GFX->getDrawUtil()->drawRectFill(updateRect, mOverlayColor);
// Reset the Colour Mask.
GFX->enableColorWrites(true, true, true, true);
}
}
#8
I was just going to post that I found the same thing. GG should really look into this.
I like your solution, but I need to create some getters and setters for GuiTSCtrl.
07/23/2008 (12:30 pm)
Thanks Bill, I was just going to post that I found the same thing. GG should really look into this.
I like your solution, but I need to create some getters and setters for GuiTSCtrl.
#9
I think the problem is some GFX calls are not in the right order or I am not calling something correctly.
The code is the same as I posted above.
I am using the advanced camera resource but I don't think that is contributing to the error.
Here are some pics of the error.
In god mode with a godViewOffset of "-100 0 100".
The reflect for both the main playGui and the fxgui are messed up.


In first person the reflect appears ok for both.


These 2 pics show the same area without the fxguisnooper.
Refection is OK in god mode.

07/29/2008 (8:26 am)
I have been running into some water reflection problems.I think the problem is some GFX calls are not in the right order or I am not calling something correctly.
The code is the same as I posted above.
I am using the advanced camera resource but I don't think that is contributing to the error.
Here are some pics of the error.
In god mode with a godViewOffset of "-100 0 100".
The reflect for both the main playGui and the fxgui are messed up.


In first person the reflect appears ok for both.


These 2 pics show the same area without the fxguisnooper.
Refection is OK in god mode.

#10
01/07/2009 (1:18 pm)
Finished a port to 1.8 its a little buggy but its there.#include "sceneGraph/sceneGraph.h"
#include "T3D/gameConnection.h"
#include "console/consoleTypes.h"
#include "gui/3d/guiTSControl.h"
#include "gui/core/guiControl.h"
#include "renderInstance/renderPassManager.h"
#include "gfx/gfxDevice.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.
GFXTexHandle mOverlayTextureHandle; // Overlay Texture Handle.
GFXStateBlockRef mSnooperClearSB;
GFXStateBlockRef mDzEnableSB;
GFXStateBlockRef mEcwSB;
GFXStateBlockRef mEcwResetSB;
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(true),
mOverlayGreenMask(true),
mOverlayBlueMask(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<SceneObject*>(*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);
if (*mOverlayBitmapName)
// Yes, so get Texture Handle.
mOverlayTextureHandle.set( mOverlayBitmapName, &GFXDefaultGUIProfile, "" );
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<fxGuiSnooper*>(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<fxGuiSnooper*>(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<fxGuiSnooper*>(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<fxGuiSnooper*>(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<fxGuiSnooper*>(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<fxGuiSnooper*>(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)
{
/* proj = FGX->getProjectionMatrix();
myShaderConstBuffer->set(mModelViewProjSC, &proj);
myShaderConstBuffer->set(mOpacityMapSC, (S32) 0);
myShaderConstBuffer->set(mLightMapSC, (S32) 1);
GFX->setShaderConstBuffer(myShaderConstBuffer);
*/
GFX->clear(GFXClearZBuffer, ColorI(0,0,0), 1.0f, 0);
/*
GFX->setZEnable(true);
GFX->setZWriteEnable(true);
GFX->setZFunc(GFXCmpLessEqual);
GFX->setCullMode(GFXCullNone);
*/
GFXStateBlockDesc snooperClear;
snooperClear.zEnable = true;
snooperClear.zWriteEnable = true;
snooperClear.zFunc = GFXCmpLessEqual;
snooperClear.cullMode = GFXCullNone;
mSnooperClearSB = GFX->createStateBlock(snooperClear);
GFXStateBlockDesc dzEnable;
dzEnable.zEnable = false;
mDzEnableSB = GFX->createStateBlock(dzEnable);
GFX->setStateBlock(mSnooperClearSB);
// Render Client Scene Graph.
gClientSceneGraph->renderScene();
//GFX->setZEnable(false);
GFX->setStateBlock(mDzEnableSB);
}
//------------------------------------------------------------------------------
void fxGuiSnooper::onRender(Point2I offset, const RectI &updateRect)
{
// Declare StateBlocks
// Call Parent Render.
Parent::onRender(offset, updateRect);
// Set Clipping Rectangle to GUI Bounds.
GFX->setClipRect(getBounds());
// Do we have an attached Object?
if (!mAttachedObject)
{
// No, so signal to user this problem ...
ColorF ErrorColor(1,0,0);
GFX->getDrawUtil()->drawRectFill(updateRect, ErrorColor);
ErrorColor.set(1,1,1);
char buf[256];
dSprintf(buf, sizeof(buf), "*** Object not selected ***");
GFX->getDrawUtil()->setBitmapModulation(ErrorColor);
GFX->getDrawUtil()->drawText(mProfile->mFont, offset, buf);
GFX->getDrawUtil()->clearBitmapModulation();
// 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.
GFX->getDrawUtil()->clearBitmapModulation();
// Are we tiling the Overlay Bitmap?
if(mOverlayTile)
{
RectI SrcRegion;
RectI DstRegion;
// Yes, so fetch texture object.
GFXTextureObject* TextureObj = mOverlayTextureHandle;
// Calculate Tesselation Count.
float XTess = ((float)getWidth()/(float)TextureObj->mBitmapSize.x)+1;
float YTess = ((float)getHeight()/(float)TextureObj->mBitmapSize.y)+1;
for(int y = 0; y < YTess; ++y)
{
for(int x = 0; x < XTess; ++x)
{
// Calculate Source Region.
SrcRegion.set(0,0,TextureObj->mBitmapSize.x, TextureObj->mBitmapSize.y);
// Calculate Destination Region.
DstRegion.set(((TextureObj->mBitmapSize.x*x)+offset.x),
((TextureObj->mBitmapSize.y*y)+offset.y),
TextureObj->mBitmapSize.x,
TextureObj->mBitmapSize.y);
// Draw Tiled Bitmap.
GFX->getDrawUtil()->drawBitmapStretchSR(TextureObj, DstRegion, SrcRegion);
}
}
}
else
{
// No, so draw stretched Bitmap.
GFX->getDrawUtil()->drawBitmapStretch(mOverlayTextureHandle, getBounds());
}
}
}
// Are we using the Overlay Colour?
if (mUseOverlayColour)
{
// Set Colour Mask.
//GFX->enableColorWrites(mOverlayRedMask, mOverlayGreenMask, mOverlayBlueMask, true);
// Declare StateBlocks
GFXStateBlockDesc ecw;
ecw.colorWriteRed |= ( mOverlayRedMask ? GFXCOLORWRITEENABLE_RED : 0 );
ecw.colorWriteGreen |= ( mOverlayGreenMask ? GFXCOLORWRITEENABLE_GREEN : 0 );
ecw.colorWriteBlue |= ( mOverlayBlueMask ? GFXCOLORWRITEENABLE_BLUE : 0 );
ecw.colorWriteAlpha = GFXCOLORWRITEENABLE_ALPHA;
mEcwSB = GFX->createStateBlock(ecw);
GFXStateBlockDesc ecwReset;
ecwReset.colorWriteRed = GFXCOLORWRITEENABLE_RED;
ecwReset.colorWriteGreen = GFXCOLORWRITEENABLE_GREEN;
ecwReset.colorWriteBlue = GFXCOLORWRITEENABLE_BLUE;
ecwReset.colorWriteAlpha = GFXCOLORWRITEENABLE_ALPHA;
mEcwResetSB = GFX->createStateBlock(ecwReset);
GFX->setStateBlock(mEcwSB);
// Draw our filled rectangle with the Filter Colour.
GFX->getDrawUtil()->drawRectFill(updateRect, mOverlayColor);
// Reset the Colour Mask.
GFX->setStateBlock(mEcwResetSB);
//GFX->enableColorWrites(true, true, true, true);
}
}
//------------------------------------------------------------------------------
bool fxGuiSnooper::processCameraQuery(CameraQuery * query)
{
Point3F CameraRotation; // Rotated View.
float VisibleDistance = 1100.0f; // Visible Distance.
// Get Game Connection.
GameConnection* pConnection = dynamic_cast<GameConnection *>(NetConnection::getConnectionToServer());
// 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);
}
#11
01/05/2010 (6:31 pm)
Has anyone successfully implemented this resource in T3D?
#12
01/09/2010 (12:54 pm)
I implemented this resource to T3D and modify it so that it can be attached any kind of shape in the world editor, not only static shapes. I want to attach it to different players and use it as a split screen. But when I attach it to the player I start having a problem. The problem is that the animation for when the player walks or runs is not playing smoothly. It the image of the player starts to shake and it looks like one frame is ahead of the current frame. The strange part is that this only happens to the shape that has the camera attached to it. Any one has an idea why this is happening?
#13
any chance of you sharing yor T3D modifications. I just saw this and would like to persue a solution with this resource in T3D
01/14/2010 (11:30 pm)
jaunany chance of you sharing yor T3D modifications. I just saw this and would like to persue a solution with this resource in T3D
#14
09/02/2010 (3:58 pm)
To make this work with T3D 1.1 beta 2, just add this to the list of includes:#include "gfx/gfxDrawUtil.h"

Torque Owner Skylar Kelty
SkylarK
Perhaps you could port GuiObjectView as well? ;)