Game Development Community

getMaterialList not working?

by Ronald J Nelson · in Torque Game Engine Advanced · 03/23/2009 (4:35 am) · 7 replies

I was in the process of updating a couple of resources I have been using when I ran across this problem. It was not an issue in the previous version of TGEA so it might be a bug. Iam currently updating some work done by Tom Spilman and others that used the TriRay casts.

The first part of this is that I need to pass the materialList to the TSMesh code now since well MaterialInstances are now BaseMatInstances and they are not a number anymore but an actual BaseMatInstance. So in the TSStatice portion I was reading to send to the TSMesh portiong I did the following to update it.


bool TSStatic::castRay( const Point3F& start, const Point3F& end, TriRayInfo* rayInfo )
{
   TSShapeInstance* si = this->mShapeInstance;
   if ( !si || !si->getShape() || si->getShape()->details.empty() )
      return false;
   TSMaterialList * materials = si->getMaterialList();
   
   TSShape* tsShape = si->getShape();

   Point3F tstart, tend;

   MatrixF mat = this->getWorldTransform();
   mat.mulP(start,&tstart);
   mat.mulP(end,&tend);

   si->setStatics(0);

   rayInfo->distance = F32_MAX;
   
   const TSDetail& detail = tsShape->details[0];
   S32 ss = detail.subShapeNum;
   //S32 od = detail.objectDetailNum;

   S32 first = tsShape->subShapeFirstObject[ss];
   S32 last = tsShape->subShapeFirstObject[ss] + tsShape->subShapeNumObjects[ss];

   for ( S32 m=first; m < last; m++ )
   {
      TSMesh* mesh = tsShape->meshes[ m ];
      if ( !mesh || mesh->getMeshType() != TSMesh::StandardMeshType )
         continue;

      TriRayInfo info;
	  if ( mesh->castRayTri( 0, tstart, tend, &info, materials ) && info.distance < rayInfo->distance )
      {
         *rayInfo = info;

         // Ok... we got a hit... cast back into world 
         // space and return it.
         MatrixF invmat( mat );
         invmat.inverse();
         invmat.mulP(rayInfo->point);
      }
   }

   si->clearStatics();
   return rayInfo->distance < F32_MAX;
}

The problem is not in my changes I am sure but in the getMaterialList function. The materialList does not pass the if(materials) test. If you try to use it in anyway its crashes the engine so I can safely say it doesn't exist. However, it should exist and performing the same types of tests on the earlier versions of the engine, it did.

Any ideas?

#1
03/23/2009 (11:22 am)
I am having nearly the same problem, this is what i have found.
And just last night i discovered all of the castray seem to return NULL, so by adding
info->material = materials->getMaterialInst( TSShapeInstance::smRenderData.materialIndex );
into function TSMesh::castRayOpcode right after if(cfs.GetNbFaces()==0) return false;. We now have TSMaterialList* materials information, and not NULL.

This is from TGEA1.81 work, and material = materials->getMaterialInst( TSShapeInstance::smRenderData.materialIndex ); only return the first material from the list.
#2
03/23/2009 (11:51 am)
Thanks Caylo you just made my day.
#3
03/23/2009 (11:57 am)
Your welcome, i spent weeks playing with that solution. Probably simple to 'real' programmers. But finding it was truly convoluted.
#4
03/23/2009 (4:35 pm)
FYI, if you need the material list, you can check to see if si->getMaterialList() returns NULL, and if it does, then get the material list from the TSShape instead. i.e.

TSShape* tsShape = si->getShape();
TSMaterialList * materials = si->getMaterialList();
if (materials == NULL)
{
   materials = tsShape->materialList;
}

or you could modify the getMaterialList method defined in tsShapeInstance.h to do the same thing.

Cheers
#5
03/23/2009 (8:26 pm)
I believe the above proposals will return the material list for the entire mesh. It won't tell you what material is assigned to the face that the castray intersected.

I could be wrong but thats how I understand the process.

I was going to try the following at a later date.

Try to store the matindex's in a Vector (ie matIndexPerFace) during prepOpcode so that we can link matindex to faceid etc.

Then in TSMesh::castRayOpcode you could do the following.

S32 matIndex = matIndexPerFace[face.mFaceID];
info->material = materials->getMaterialInst( matIndex );
#6
03/23/2009 (8:39 pm)
Yes, it only return the first material from the list. But from what i needed that was just fine. I do think the prepOpcode method is similar to how terrain and interior work, but im not skilled enough to emulate it.
#7
03/24/2009 (1:19 am)
Oh I see what you are saying. I have only tested Caylo's code on simple objects with one material so I hadn't even considered the issue with tsStatics with several materials. I will have to look into this a bit further as well.

But thanks a ton Caylo you at least got me started.