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.
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?
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?
#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
or you could modify the getMaterialList method defined in tsShapeInstance.h to do the same thing.
Cheers
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
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 );
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
But thanks a ton Caylo you at least got me started.
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.
Torque 3D Owner Caylo Gypsyblood
And just last night i discovered all of the castray seem to return NULL, so by adding 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.