Game Development Community

dev|Pro Game Development Curriculum

fxGuiSnooper

by Melv May · 03/04/2002 (10:03 am) · 39 comments

Download Code File

Ok, here it is.

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.cc" 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.


------------------------------------------
[EDIT] - MY POST FROM FORUM REGARDING GETTING ONLY THE SNOOPER OBJECT RENDERING IN ANOTHER GUI VIEW TO STOP FPS REDUCTION.
------------------------------------------

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. :)

------------------------------------------

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.
Page«First 1 2 Next»
#21
10/09/2006 (7:53 pm)
I won't be able to look at the code, but I believe there is a "sweep" or "sweep angle" variable, or perhaps one for each plane. Set those variables and the update code tilts the camera accordingly.
#22
11/17/2006 (11:28 am)
Does anyone know how I would make it so that the object it was set to was not rendered (only in the fxguisnooper view port).

I haven't a clue because the render functions for all game objects are done in that objects class and not in the cameras. So it is either rendered or not (in all viewports).
#23
01/01/2007 (4:03 am)
Is there someone who got this worked on Torque 1.5? Look down for news.
#24
01/03/2007 (2:10 am)
I updated this resource for Torque 1.5, if there is enough interest I would submit it as resource.
#25
01/03/2007 (8:17 pm)
I am definately interested : ). I was just about to do it so I would be eternally grateful for the time saving.
#26
01/03/2007 (8:18 pm)
Then wait a moment
#27
01/03/2007 (8:24 pm)
I don't know waht I changed, but it does work.
#include "sceneGraph/sceneGraph.h"
#include "game/gameConnection.h"
#include "console/consoleTypes.h"
#include "gui/core/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<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);

	// 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<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)
{
	// 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<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);
}
I would like to ask Melv if I should do it as own resource, but I cannot find his email or something to contact him.
#28
01/03/2007 (8:41 pm)
Wow. That was fast. Thanks heaps. I shall give it a go asap.
#29
01/03/2007 (8:43 pm)
Hopefully I can contact Melv soon.
#30
02/05/2007 (12:17 pm)
wow. i wasn't looking for this but this is great.
i will try this.

thanks
#31
08/24/2007 (11:58 am)
Hello, I know these are old posts, but I really would like to use this resource! I was able to get it to compile into torque without any errors but now I am unable to figure out how to use it for non-static object. I noticed others had posted this request but I do not see a definate answer. I basically want to attach the second veiwport to the player but have it shifted over a few units. (I am going for a stereo view) any help would be much appreciated!
#32
09/08/2007 (9:29 pm)
This great, i been looking for this for sometime now Yost can you post a picture of your split screen shot? I'm going to try to get more people in the forum to help us.

thanks
#33
10/18/2007 (8:41 am)
Thanks a lot Melv! I've ported it to TGEA but the new resource is still unapproved after 9 days...
#34
10/24/2007 (9:42 am)
Any chance you could post the code here, or a link to the new resource if its been approved?
#35
10/24/2007 (2:15 pm)
It shouldn't hurt anybody if I post the link to the unapproved resource here:

www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=13690
#36
02/15/2008 (2:34 pm)
Hello,
Just wondering if anyone out there has any ideas or suggestions as to achieve this effect. How would you be able to put that guiSnooper onto a world object. For instance, let's say I have a tv monitor in the game that is looking at a jail cell, a security camera. It would be cool to be able to look at a camera's viewpoint on some object in the game.
Any ideas or suggestions would be greatful.
Thx.
DALO
#37
02/16/2008 (12:44 am)
In TGEA you can do it with this resource. No idea if there's something similar for TGE.
#38
03/18/2008 (9:11 am)
hey, could this also be used for split screen? like halo style, where lets say up to 4 friends can be one one screen???
that would make great co-op play, and if u connect the computer to a plasma tv, via dvi, it would rule


but anyone have any idea how to add multiple player objects to the server from the same machine???


forget about controlls i have that covert and will post soon, ( after some more tests)
but the real problem is connecting multiople clients from the same machine

any ideas?

because once we have this, and with this resource, we would finally have split screen in tgea and tge sicne the beginning of torque ( to my knowledge no torque product has splitscreenexcept torque X, but thats not really tgea or tge lol)
#39
03/18/2008 (9:21 am)
Tom i'm looking for the same thing if someone can come up with the script code for split screen for the update to TGEA I'm welling to pay money.

thanks
Page«First 1 2 Next»