Game Development Community

Silhouette selection via postFx for Torque3D

by Konrad Kiss · 07/13/2009 (10:43 am) · 90 comments

This resource adds a new postFx to Torque3D that lets you have object selection with a line silhouette and an overlay. Here's an image to give you a better idea:

www.xenocell.com/dev/selection2.jpg


Before I go on with the resource, I'd like to express my thanks to those whom without I'd not been able to wrap this up now. They are:

Greg G for starting this thread.
Matt Jolly, who's made an awesome postFx, which started me on the road to figure out a lot more about shaders and postFx in T3D Beta3.
Tom Spilman for giving me glow code from Beta 3 before it was even out to be able to get started faster.
Huan Li for pointing out a change in code I couldn't find, which eventually led to this resource within a matter of hours. Also, for testing this resource!

Thanks again, guys.

One more thing, this resource does not include the method of selecting an object, only the way to render it as above. When you have your selection working, you can use this resource to make a ShapeBase to render as selected.

Alright, here we go:

0.) Don't forget to do a backup.

1.) Download the resource's files in this Torque3D only forum, and copy them into your game's source. The directory structure is the same in the zip as Torque3D's default dir structure, so you can just copy both the source and the game directory over your existing directories. No existing files should be overwritten. Don't recompile just yet.

2.) Engine source changes:

baseMatInstance.h

- Add the protected boolean mHasSelection to the BaseMatInstance class

- Also here, add the following as public methods:
// >>>
   bool hasSelection() { return mHasSelection; };
   void setSelection(bool sel) { mHasSelection = sel; };
   // <<<


matInstance.cpp

- in MatInstance::construct, set mHasSelection to false


renderPassManager.cpp

- include the new renderSelectionMgr.h

- in MeshRenderInst::clear, set mHasSelection to false


renderPassManager.h

- Add the boolean mHasSelection to the MeshRenderInst struct


sceneData.h

- Add the following to the SceneGraphData struct's BinType enum:
// >>>
      /// The selection render bin.
      /// @RenderSelectionMgr
      SelectionBin,
      // <<<


shapeBase.cpp

- Insert into ShapeBase.cpp and call this method when your object's (this) selection changes. Depending on your selection method, there are different ways to handle this, but at the end, you should call this to set the selection state of the mesh.
// >>>
void ShapeBase::setSelection( bool sel )
{
   if (!mShapeInstance || !isClientObject())
      return;

   if (!mShapeInstance->ownMaterialList())
      return;

   TSMaterialList* pMatList = mShapeInstance->getMaterialList();
   for (S32 j = 0; j < pMatList->getMaterialInstCount(); j++) 
   {
      BaseMatInstance * bmi = pMatList->getMaterialInst(j);
      bmi->setSelection(sel);
   }
}
// <<<


shapeBase.h

- Add the following as a public method to the ShapeBase class definition:
// >>>
   void setSelection( bool sel );
   // <<<


3.) Script changes:

core/scripts/client/renderManager.cs

- Add the following code to the end of the initRenderManager function:
// >>>
   DiffuseRenderPassManager.addManager( new RenderSelectionMgr() { renderOrder = 1.6; processAddOrder = 1.6; } );
   // <<<

Now it's time to recompile.

To turn this feature on, enter SelectionPostFx.enable() at the console, and make sure you use setSelection on a ShapeBase in view.

I still want to do dynamic coloring sometime. Right now, the shader's hardwired to do a shades-of-red silhouette and overlay. If you want to change the color, here's where you'll need to make modifications in selectionShaderP.hlsl:
float4 e = float4(vis, 0, 0, vis); // <-- silhouette color
   float4 ovr = float4(avgval, 0, 0, avgval); // <-- overlay color

   ovr *= 0.4; // <-- overlay "thickness" (0.4 = 40% transparency for the overlay)

That's all. Let me know if I forgot something! (It's possible, since I just extracted this from my game. I've tried to double-check all changes, but haven't yet had the time to test it in vanilla T3D Beta 3)

Thanks for following through.

--Konrad

About the author

Lead Developer at Bitgap Games (www.bitgap.com) currently working on Xenocell (www.xenocell.com) a massively multiplayer action strategy game based on Torque 3D technology.

#41
11/06/2009 (11:15 am)
Ah! That was it! It now works in both Basic and Advanced Lighting.


#42
11/06/2009 (12:48 pm)
Awesomeness! That's great to hear!
#43
12/25/2009 (8:09 am)
great, i've been looking for this.. but, i can't access the restricted forum.. (how do i get access?)

is there any other place you can upload the resource files in the meantime?
#44
12/25/2009 (5:00 pm)
This is available for Torque 3D licensees only. How would you be able to apply this resource anyway, if you don't have access to the source of the engine?

It is no coincidence that I've put the resource in the private forums.
#45
12/25/2009 (5:34 pm)
@rorshach82 - If you are working with the demo, this is not available to you. If you are working with source code, then there is a bigger issue.
#46
01/03/2010 (7:55 am)
using the Beta 5 fix in the thread my compiler generates these errors :(

Error	10	error C2039: 'getMaterialInstCount' : is not a member of 'TSMaterialList'	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\T3D\shapeBase.cpp	4301
Error	2	error C2039: 'setEyePosition' : is not a member of 'BaseMatInstance'	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\renderInstance\renderSelectionMgr.cpp	100
Error	3	error C2039: 'setSelection' : is not a member of 'ShapeBase'	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\T3D\shapeBase.cpp	4292
Error	4	error C2065: 'mShapeInstance' : undeclared identifier	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\T3D\shapeBase.cpp	4294
Error	6	error C2065: 'mShapeInstance' : undeclared identifier	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\T3D\shapeBase.cpp	4297
Error	8	error C2065: 'mShapeInstance' : undeclared identifier	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\T3D\shapeBase.cpp	4300
Error	9	error C2227: left of '->getMaterialList' must point to class/struct/union/generic type	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\T3D\shapeBase.cpp	4300
Error	7	error C2227: left of '->ownMaterialList' must point to class/struct/union/generic type	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\T3D\shapeBase.cpp	4297
Error	1	error C2660: 'BaseMatInstance::setTransforms' : function does not take 3 arguments	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\renderInstance\renderSelectionMgr.cpp	99
Error	5	error C3861: 'isClientObject': identifier not found	c:\Torque\Torque 3D 2009 Pro 1.1 Alpha\Engine\source\T3D\shapeBase.cpp	4294
#47
01/03/2010 (8:07 am)
@Bryce: See Rex's post
#48
01/03/2010 (8:26 am)
Thanx Konrad, can't try now, but will give it a shot tomorrow.

Kudos 2 U for the speedy reply :D
#49
01/07/2010 (8:53 am)
ok i have it compiling no errors, and i added the console command that ted made. But the silhouette doesn't show up. I get no errors or warnings and I have followed the instructions to the letter, I promise. Version = 1.1a
#50
01/07/2010 (9:16 am)
You will need a method to select your objects - like the one in afx. You have to wire this with your object selection, and call setSelection(true) on any shapebase derivative object that you want displayed with the silhouette. To remove an object from the "silhouette bin" issue setSelection(false).
#51
01/07/2010 (7:15 pm)
I have a method, but it is all in script rather than c++. Is there a way to get a script side command, or should i just rework my selection to be in c++?
#52
01/07/2010 (7:31 pm)
Just expose ShapeBase::setSelection to script. Also, be sure to call it on the client.
#53
01/07/2010 (7:40 pm)
Ah call it on the client, that could be where i have gone wrong...

Thanks Konrad
#54
01/07/2010 (7:42 pm)
You're welcome. Let me know when it works for you.
#55
01/07/2010 (7:52 pm)
To be honest, I have a feeling I won't get it working :( I am too nub with client to server.

Could you please tell me what I would need to do exactly?

So far I have;

*Compiled the resource without error.
*Exposed the function to script (i think, i used the code Ted Southard made on page 2)
*I am just trying to call the selection from the console to make sure it works
#56
01/07/2010 (8:00 pm)
The console will run anything you type on the server side. You'll need to take the ghost id of a server object on your client (LocalClientConnection will store the client if you don't run dedicated). After resolving the ghost id, call setSelection(true) on the object (ie. the player).

Read posts #24 and #26 on the 2nd page. Btw, it's always useful to read all posts regardless, usually it saves you a lot of time. :)
#57
01/22/2010 (4:14 pm)
I have everything hooked in and updated for 1.0.1 Alpha. To test, I hardcoded mHasSelection to true. However, there is no outline showing up, and it is because the mElementlist is empty. This is empty because the Postfx.mEnabled is false, which is false because this effect never gets added.

How do Postfx get added? What am I missing?

--EDIT
Got it. Need to set IsEnabled to true in selection.cs

singleton PostEffect( SelectionPostFX )  
{  
   renderTime = "PFXAfterDiffuse";  

   shader = PFX_SelectionShader;  
   stateBlock = PFX_DefaultSelectionStateBlock;  
   texture[0] = "#selection";   
   texture[1] = "$backBuffer";  
   target = "$backBuffer";  
   
   isEnabled = true;
};
#58
01/22/2010 (4:47 pm)
Thanks for the info, Martin.
#59
01/22/2010 (5:47 pm)
@Konrad - No thank you....

When in doubt, read, then read AGAIN. I missed the part on PAGE 1, just before the explanation about the color change in the .hlsl file, where you are supposed to call SelectionPostFX.enable() from the console.

So, it was there all the time. Thanks Konrad.
#60
02/09/2010 (2:08 am)

omg sry i have change this

DiffuseRenderPassManager.addManager( new RenderSelectionMgr() { renderOrder = 1.55 ; processAddOrder = 1.55 ; } );