Game Development Community

TSShapeInstance and Custom Material issue

by Adam Stewart · in Torque 3D Professional · 11/19/2012 (1:41 pm) · 1 replies

I'm having an issue when trying to apply a custom material to a TSShapeInstance I have in my level.

To give a background to what I'm doing, I've got a bunch of TSShapeInstances that I want to reference the same CustomMaterial but have different images/effects on them. For example I want to render a character with a T-Shirt and on the T-shirt I want to render the user's stored/saved username regardless to what character model they have.

To achieve this I have added a NamedTexTarget into my TSShapeInstance that points to different texture targets depending on what I want to render on the object. I have verified that my NamedTexTarget points to a valid TextureObject, I can render the TextureTarget to a gui and verify my render to texture works. In order to get different render targets I had to modify the TSShapeInstance connstructor to take in another parameter, in my case I decided to pass an object ID. The constructor then uses that object ID to find an object, we'll call it a SpecialRenderObject, I've made which performs a particular render to texture operation, such as render font text to a texture, My NamedTexTarget references the texture that SpecialRenderObject is storing.

I verified that this was working by explicitly declaring a SpecialRenderObject and creating a simple GUI render for that object and the object indeed renders my font text to a texture and I can then have my NamedTexTarget in my TSShapeInstance point to that texture and have that show up on a 3D model by declaring the NamedTexTarget as a sampler in my CustomMaterial declaration.

Now you may be saying, if this all worked then what's the issue. The issue is that I am now trying to remove my explicitly declared SpecialRenderObject and instead create unique SpecialRenderObject objects as I need them on a per object basis. Currently as is, all TShapeInstances store a NamedTexTarget that points to my global SpecialRenderObject and only the TSShapeInstances that have CustomMaterials associated with the SpecialRenderObject will show up with the render target texutre. I tried creating a new constructor for TSShapeInstance which takes in my additional parameter and left the existing constructors alone so as not to break existing functionality. My new constructor does exactly the same thing as TSShapeInstance( const Resource<TSShape> &shape, bool loadMaterials ) but with the additional parameter.

Some pseudo-code of my constructor:

TSShapeInstance::TSShapeInstance( const Resource<TSShape> & shape, const char * szObject, bool loadMaterials)
{
   VECTOR_SET_ASSOCIATION(mMeshObjects);
   VECTOR_SET_ASSOCIATION(mNodeTransforms);
   VECTOR_SET_ASSOCIATION(mNodeReferenceRotations);
   VECTOR_SET_ASSOCIATION(mNodeReferenceTranslations);
   VECTOR_SET_ASSOCIATION(mNodeReferenceUniformScales);
   VECTOR_SET_ASSOCIATION(mNodeReferenceScaleFactors);
   VECTOR_SET_ASSOCIATION(mNodeReferenceArbitraryScaleRots);
   VECTOR_SET_ASSOCIATION(mThreadList);
   VECTOR_SET_ASSOCIATION(mTransitionThreads);

   mShapeResource = shape;
   mShape = mShapeResource;

   mOverrideTarg.registerWithName("LabelTarget");

   attachTexture(szObject);

   buildInstanceData( mShape, loadMaterials );
}

mOverrideTarg is my NamedTexTarget, I modified TSShapeInstance so every instance has one.
"LabelTarget" is my sampler in my CustomMaterial so that the NamedTexTarget is associated with the CustomMaterial I want.
Also code for the attachTexture function:

void TSShapeInstance::attachTexture(const char * szSourceObject)
{
   if(strlen(szSourceObject))
   {
      SpecialRenderObject * pBitm = dynamic_cast<SpecialRenderObject*>(Sim::findObject(szSourceObject));
      mOverrideTarg.setTexture(pBitm ? pBitm->getShaderTextureObject() : NULL);
   }
}

SpecialRenderObject is my render to texture class, performs render operations then sticks it on a texture to give to somebody else, such as a NamedTexTarget.

The only differences between my new constructor and the existing constructor is the additional parameter and the fact that my constructor is only called where I explicitly create new TSShapeInstances. Within the existing constructor to get a prototype working I changed szObject in the attachTexture call from szObject to "RTT_TextObject", which is an explicitly defined SpecialRenderObject object. This works but every single object that uses the CustomMaterial associated with "LabelTarget" now displays the texture from "RTT_TextObject" whereas I would like to display different textures on each instance by declaring different SpecialRenderObjects and modifying their input parameters.
Oddly enough, as soon as I remove the attachTexture call from the original constructor I can no longer see my texture on TSShapeInstances created using my new constructor?!? I stepped through and verified that the original constructor is never getting called for instances I explicit create with the new constructor, anywhere within the lifetime of the application. I feel like I'm missing some link in the TSShapeInstance init process or there are two instances for each of my TSShapeIntances and I am modifying the wrong instance.. but all my debugging has led me to believe there is only one instance and it is holding the correct data in order to render what I expect.

I'm thinking this has something to do with the TSShape class underneath but I can't be certain. I was hoping to get some insight from someone with additional knowledge on the TSShape class/ Material loading process for TSShapeInstances. I notice some comments and functions relating to materialList cloning and I'm uncertain as to how the materialList in TSShape specifically relates to the materialList in TSShapeInstance.

Any assistance with this would be much appreciated as I have spent many hours digging through Engine code to no avail. If there is an easier way to achieve what I am trying to do then I am open to suggestion and I am not tied to my implementation. I basically need the ability to render to a texture a unique 2d/3d image/text and then apply that to a variety of TSShapeInstances while allowing all of them to use a single Material definition.

Thanks
Adam S.

About the author

Recent Threads


#1
11/20/2012 (1:47 pm)
So it seems my issue is two-fold and I will have to pursue an alternate course.

The first issue is that you cannot point multiple TextureHandles to a single NamedTexTarget. The second issue which was exposed in discovering the above and is what I am currently struggling with is mapping multiple/different textures to a single material on a per TSShapeInstance basis.

As far as I can tell it is not possible without heavy modifications to the Material system....

Anyone aware of a resource that overrides the built-in material system and allows material redefinition on a per instance basis?