Game Development Community

Force Object\Scene Update?

by JPaxson · in Torque Game Engine · 05/17/2006 (1:55 pm) · 4 replies

Hello,

I have been playing with an extension of the very nice fxRenderObject resource (it was very helpful). I have extended it to my needs and added console method hooks to modify the objects properties on the fly via script calls, etc. My problem is this....

The console method i created to change the color of my object on the fly works great, but the color change doesnt take effect until i enter the editor and select the object then poof the color changes to the value i set in the console. Is there a "setDirtyBit" or something similar I am leaving out, or is there a way in general to force a scene update? I've tried reloadMaterials(), even a hacky %obj.settransform(%obj.getTransform());
and still no love. Anyone else run into the same problem? Any clues would be greatly appreciated.

#1
05/18/2006 (4:51 pm)
Quote:
Is there a "setDirtyBit" or something similar I am leaving out

In essence, yes. Even when you are in a standalone or singleplayer situation, Torque is still running as a client/server model. The oject that you are changing the colors for is most likely the server object while the actual object that is doing the rendering is the client object. You have a to add a little bit of networking code in so that the changes you make on the server object get propagated to the client object. Since it is already doing this when you are in the Mission Editor (which often forces a network update directly) then it is most likely that the color value is already getting sent by packUpdate and unpackUpdate. You probably just need to call setMaskBits() with the appropriate mask (check inspectorPostApply() where it sets a mask bit). This flags a piece of data as dirty and causes the engine to send the network update with the new data across to the client.

For a more in-depth explanantion of how all of this works check out Making a Ghostable Object.
#2
05/22/2006 (1:29 pm)
Thanks, Matt.

I figured that was the type of thing that was going on. I read the links provided, looked at other classes that inherit from SceneObject like fxRenderObject does (i.e. waterblock), and added the suggested setMaskBits(fxRenderObjectMask); to my function like the default fxRenderObject::inspectPostApply() does.

When I added a function to set the objects color, I added the appropriate variable declaration, addField(..), and added a console function to access the protected variable for color. As i said previously my function is called, and indeed sets the objects color via the console function i created, but the change never takes effect until i enter the editor and select the object. When I add the "setMaskBits(fxRenderObjectMask); " call to my setColor function I get a hard crash and the following error in the console.log...(about 53 MB worth of the following line before it crashes)

(0): Call to setColor in (null) uses result of void function call.

Everything works fine without adding this call (except having to select the object in editor to see change).

So then I created a custom bitmask per the Ghostable Object example you pointed me too, changed my packUpdate, unpackUpdate, inspectPostApply(), and my setcolor function to match the custom mask, and I get the same error and the same crash as above.

The only difference is is that if I create a custom mask and start with BIT(0), BIT(1), etc. My error is that i dont have the right version or resource for this version of TSE, and the app bails out in the disconnectedCleanup function (particularly ... clearTextureHolds();) in client\scripts\serverConnection.cs

From the examples you pointed me to, and what is working in engine I just dont see what I am doing wrong. Any other ideas?
#3
05/22/2006 (1:36 pm)
class fxRenderObject : public SceneObject
{
private:
	typedef SceneObject		Parent;
	void setShaderParams();

protected:

	// Create and use these to specify custom events.
	//
	// NOTE:-	Using these allows you to group the changes into related
	//			events.  No need to change everything if something minor
	//			changes.  Only really important if you have *lots* of these
	//			objects at start-up or you send alot of changes whilst the
	//			game is in progress.
	//
	//			Use "setMaskBits(fxRenderObjectMask)" to signal.

	enum {	
		fxRenderObjectMask		= (1 << 0),
		fxRenderObjectAnother	= (1 << 1) 
	};

	
	S32								mLastRenderTime;
	F32								mCurrentAngle;
    MatInstance*					mMaterial;
	//GFXTexHandle					mDetailTex;

	// Fields.
	F32								mQuadSize;
	F32								mQuadRotateSpeed;
    StringTableEntry				mMaterialName;
	//StringTableEntry				mDetailName;
    ColorI							mObjColor;
	
	
   // Helper functions
   void render(SceneGraphData& sgd, MatInstance* mat);

   // Initialize the vertex buffer.  Returns number of
   // primitives in the buffer and the vertext buffer.
   // Don't destroy this buffer when you're done with it.
   virtual GFXVertexBuffer* initVertexBuffer(U32& numPrims);

public:
	fxRenderObject();
	~fxRenderObject();

	// SceneObject
	void renderObject(SceneState*, SceneRenderImage*);
	virtual bool prepRenderImage(SceneState*, const U32 stateKey, const U32 startZone,
								const bool modifyBaseZoneState = false);

	void setColor(U32 r, U32 g, U32 b, U32 a);

	// SimObject      
	bool onAdd();
	void onRemove();
	void onEditorEnable();
	void onEditorDisable();
	void inspectPostApply();

	// NetObject
	U32 packUpdate(NetConnection *, U32, BitStream *);
	void unpackUpdate(NetConnection *, BitStream *);

	// ConObject.
	static void initPersistFields();

	// Declare Console Object.
	DECLARE_CONOBJECT(fxRenderObject);
};

#endif // _FXRENDEROBJECT_H_
#4
05/22/2006 (1:42 pm)
void fxRenderObject::initPersistFields()
{
	// Initialise parents' persistent fields.
	Parent::initPersistFields();

	// Add out own persistent fields.
   addGroup("Properties");
   addField( "QuadSize",		   TypeF32,		Offset( mQuadSize,			fxRenderObject ) );
   addField( "QuadRotateSpeed",	   TypeF32,		Offset( mQuadRotateSpeed,	fxRenderObject ) );
   addField( "Material",		   TypeString,	Offset( mMaterialName,		fxRenderObject ) );
   addField( "ObjColor",		   TypeColorI,  Offset( mObjColor,          fxRenderObject ) );
   //addField( "DetailTexture",   TypeString,	Offset( mDetailName,		   fxRenderObject ) );
   endGroup("Properties" );
}


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

void fxRenderObject::inspectPostApply()
{
	// Set Parent.
	Parent::inspectPostApply();

	// Set fxPortal Mask.
	setMaskBits(fxRenderObjectMask);
}

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


U32 fxRenderObject::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
{
	
	// Pack Parent.
	U32 retMask = Parent::packUpdate(con, mask, stream);

	// Write fxRenderObject Mask Flag.
	if (stream->writeFlag(mask & fxRenderObjectMask))
	{
		// Write Object Transform.
		stream->writeAffineTransform(mObjToWorld);
		// Write Material Name.
		stream->writeString(mMaterialName);
        // Write Detail Name
        //stream->writeString(mDetailName);
		// Write Quad Size.
		stream->write(mQuadSize);
		// Write Quad Rotate Speed.
		stream->write(mQuadRotateSpeed);
		// Write Object Color
		stream->write( mObjColor );
	}

	// Were done ...
	return(retMask);
	
}

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

void fxRenderObject::unpackUpdate(NetConnection * con, BitStream * stream)
{
	
	// Unpack Parent.
	Parent::unpackUpdate(con, stream);

	// Read fxRenderObject Mask Flag.
	if(stream->readFlag())
	{
      MatrixF		ObjectMatrix;

      // Read Object Transform.
      stream->readAffineTransform(&ObjectMatrix);

      // Read Texture Name.
      mMaterialName = StringTable->insert(stream->readSTString());
      // Read Detail Name
      //mDetailName = StringTable->insert(stream->readSTString());
      // Read Quad Size.
      stream->read(&mQuadSize);
      // Read Quad Rotate Speed.
      stream->read(&mQuadRotateSpeed);
	  // Read Object Color
	  stream->read( &mObjColor );

      // Set Transform.
      setTransform(ObjectMatrix);

      // Reset the previous material and detail texture
      SAFE_DELETE(mMaterial);
      mMaterial = new MatInstance(mMaterialName);
      if (!mMaterial || !mMaterial->getMaterial())
      {
         Con::errorf("fxRenderObject::unpackUpdate - failed to locate material '%s'!", mMaterialName);

         // TODO: Return here?  Assert?
      }

      // TODO: Need to reset the previous detail texture
      // free() isn't implemented?
      //mDetailTex.free();

      //mDetailTex.set(mDetailName, &GFXDefaultStaticDiffuseProfile);

      // Calculate Quad Radius.
      F32 QuadHalfSize = mQuadSize / 2.0f;

      // Set bounding box.
      //
      // NOTE:-	Set this box to completely encapsulate your object.
      //			You must reset the world box and set the render transform
      //			after changing this.
      mObjBox.min.set( -QuadHalfSize, -QuadHalfSize, -QuadHalfSize );
      mObjBox.max.set(  QuadHalfSize, +QuadHalfSize,  QuadHalfSize );

      // Reset the World Box.
      resetWorldBox();
      // Set the Render Transform.
      setRenderTransform(mObjToWorld);
	}
	
}

//-----------------------------------------------------------------------------
// set shader parameters for user defined color
//-----------------------------------------------------------------------------

// set the color of our object
void fxRenderObject::setColor(U32 r, U32 g, U32 b, U32 a)
{
	mObjColor.red = r;
	mObjColor.green = g;
	mObjColor.blue = b;
	mObjColor.alpha = a;

	//set mask bits so scene knows 
	//this object is dirty
	//setMaskBits(fxRenderObjectMask); <---causes the crash
		
}

// Console Functions for Runtime Access to variables
ConsoleMethod(fxRenderObject, setColor, void, 3, 3, "Set the color of the current fxRenderObject (r g b a 0-255)")
{  
	ColorI mObjColor;
	dSscanf(argv[2], "%d %d %d %d", &mObjColor.red, &mObjColor.green, &mObjColor.blue, &mObjColor.alpha);  
    object->setColor(mObjColor.red, mObjColor.green, mObjColor.blue,mObjColor.alpha);
	
}