Game Development Community

Wrapped decals

by Ronald J Nelson · in Torque Game Engine Advanced · 04/09/2009 (8:05 am) · 6 replies

I released this code as an option in my Enhanced Projectiles resource which I am in the process of updating. The code itself is pretty much the blobShadow code modified for decals.

For some reason I am having an issue with getting this to work in TGEA 1.8.1 and I am having alot of instances of vertices shooting all over the place which would tell me that somewhere in the arrays there is garbage data being input, but I have no idea why. This code worked great in TGE and TGEA 1.03, but now it is just not something that is usable. SO I am putting it out here to see if someone else can point out my mistakes.

***THIS VERSION OF CODE REMOVED. LOOK BELOW FOR NEW CODE***

Thanks in advance for any assistance you can give me.

#1
04/12/2009 (7:51 pm)
@Ron, I don't know if it is caused by the line 15 code
DecalInstance* newDecal = allocateWrapDecalInstance();
allocateWrapDecalInstance() may allocate memory from a pool, if many projectiles shooting out, the pool might be used out?
Just a thought. Plus, I am expecting your enhanced projectile resource, and hope it could be planted to new Torque 3D. haha
#2
04/15/2009 (9:15 am)
Thanks Huan but it is supposed to do that. As for a T3D upgrade, probably not going to happen from me. If it does, it will be in the very far off future.
#3
07/27/2009 (5:01 pm)
Well after a ton of personal life crap I am finally coming back to this stuff. Since this code was originally based off of the blob shadow code I cannot see why I am getting problems. What I am seeing is a lot of artifacts that are obviously not getting proper coordinates set or the size is somehow being set incorrectly.

I know a lot of folks were waiting for an updated version of my projectile resource. Well honestly, I never got all of the updated stuff to work exactly the way I was striving towards. This is one of them.

This picture should give you a good idea of what is going on.

i72.photobucket.com/albums/i192/DTDA/wrappeddecalbug.jpg






#4
08/11/2009 (5:11 pm)
OK I managed to get the crazy vertexs to stop but now it only renders one decal at a time. Here is my new code:

void DecalManager::renderWrapDecal()
{
	for(S32 x=0; x<mWrapDecalQueue.size(); x++)
		mWrapDecalQueue[x]->buildWrapDecal();
	
	if (mDefaultSB.isNull())
	{
		GFXStateBlockDesc desc;
		desc.setCullMode(GFXCullNone);
		desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
		desc.setZEnable(true);
		desc.zFunc = GFXCmpLessEqual;
		desc.zWriteEnable = false;
		desc.setAlphaTest(true, GFXCmpGreater, 0);
		desc.samplersDefined = true;
		desc.samplers[0].textureColorOp = GFXTOPModulate;
		desc.samplers[1].textureColorOp = GFXTOPDisable;
		
		F32 depthbias = -0.00006f;
		F32 slopebias = -0.06f;
		
		desc.zBias = depthbias;
		desc.zSlopeBias = slopebias;
		
		mDefaultSB = GFX->createStateBlock(desc);
		
		desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendOne);
		
		mSelfIlluminatedSB = GFX->createStateBlock(desc);
	}
	
	sgThisIsSelfIlluminated = false;
	
	for(S32 x=0; x<mWrapDecalQueue.size(); x++)
	{
		sgThisIsSelfIlluminated = mWrapDecalQueue[x]->decalData->selfIlluminated;
		if(sgThisIsSelfIlluminated)
		{
			GFX->setStateBlock(mSelfIlluminatedSB);
		}
		else
		{
			GFX->setStateBlock(mDefaultSB);
		}

		GFX->setTexture(0, mWrapDecalQueue[x]->decalData->textureHandle);
		GFX->setVertexBuffer(mWrapDecalQueue[x]->exData->mWrapDecalBuffer);

		GFX->multWorld(mWrapDecalQueue[x]->exData->mTransform);
		
		for (U32 i = 0; i < mWrapDecalQueue[x]->exData->mPartition.size(); i++)
			GFX->drawPrimitive(GFXTriangleFan, mWrapDecalQueue[x]->exData->mPartition[i].vertexStart, (mWrapDecalQueue[x]->exData->mPartition[i].vertexCount - 2));
	}
}
#5
08/11/2009 (5:13 pm)
void DecalManager::addWrapDecal(const Point3F& pos,
                            Point3F normal,
                            Point3F impactNormal,
                            DecalData *decalData)
{
   if (smMaxNumDecals == 0)
      return;

   if(mWrapDecalQueue.size() >= smMaxNumDecals)
   {
      findWrapSpace();
   }
   DecalInstance* newDecal = allocateWrapDecalInstance();
   newDecal->decalData = decalData;
   newDecal->allocTime = Platform::getVirtualMilliseconds();
   newDecal->position = pos;
   newDecal->normal = normal;
   newDecal->impactNormal = impactNormal;
   mWrapDecalQueue.push_back(newDecal);
   mWrapQueueDirty = true;
}

void DecalInstance::buildWrapDecal()
{
   DecalExData *nData=new DecalExData;
   exData=nData;
   Point3F vecX, vecY;

   // construct matrix
   Point3F x,y,z;
   y = impactNormal;
   if (mFabs(y.z)>0.001f)
   {
      //mCross(y,Point3F(1,0,0),&z);
      z.set(0,y.z,-y.x);
      z.normalizeSafe();
      mCross(y,z,&x);
      x.normalizeSafe();
   }
   else
   {
      //mCross(y,Point3F(0,0,1),&x);
      x.set(y.y,-y.x,0);
      x.normalizeSafe();
      mCross(x,y,&z);
      z.normalizeSafe();
   }

   F32 ySkew = mFabs(mDot(impactNormal,normal));
   F32 xFactor, yFactor;
   if (ySkew>0)
   {
      xFactor=2*ySkew;
      yFactor=2/ySkew;
   }
   else
   {
      xFactor=2;
      yFactor=2;
   }

   // backup a bit (for the transforms) so that we can see the polys
   Point3F mPosition = Point3F(position.x + (-impactNormal.x * decalData->sizeX*2), 
                              position.y + (-impactNormal.y * decalData->sizeY*2), 
                              position.z + (-impactNormal.z * decalData->sizeX*2));

   MatrixF decalToWorld(true);
   decalToWorld.setColumn(0,x);
   decalToWorld.setColumn(1,y);
   decalToWorld.setColumn(2,z);
   decalToWorld.setColumn(3,mPosition);

   exData->mTransform = decalToWorld;

   MatrixF worldToDecal = decalToWorld;
   worldToDecal.inverse();

   // setup depth sort list
   // expanded allow the image to stretch
   Point3F extent(decalData->sizeX*5,decalData->sizeY*5,decalData->sizeX*5);
   smDepthSortList.clear();
   smDepthSortList.set(worldToDecal,extent);
   smDepthSortList.setInterestNormal(impactNormal);

   // build world space box and sphere around decal
   x *= decalData->sizeX*2;
   y *= decalData->sizeY*2;
   z *= decalData->sizeX*2;
   gDecalBox.maxExtents.set(mFabs(x.x)+mFabs(y.x)+mFabs(z.x),
                     mFabs(x.y)+mFabs(y.y)+mFabs(z.y),
                     mFabs(x.z)+mFabs(y.z)+mFabs(z.z));
   gDecalSphere.radius = gDecalBox.maxExtents.len();
   gDecalSphere.center = position;
   gDecalBox.minExtents  = position - gDecalBox.maxExtents;
   gDecalBox.maxExtents += position;

   // get polys
   gClientContainer.findObjects(smDecalMask,collisionCallback,this);

   // setup partition list
   gDecalPoly[0].set(-decalData->sizeX,0,-decalData->sizeY);
   gDecalPoly[1].set(-decalData->sizeX,0,decalData->sizeY);
   gDecalPoly[2].set(decalData->sizeX,0,decalData->sizeY);
   gDecalPoly[3].set(decalData->sizeX,0,-decalData->sizeY);

   exData->mPartition.clear();
   exData->mPartitionVerts.clear();
   smDepthSortList.depthPartition(gDecalPoly,4,exData->mPartition,exData->mPartitionVerts);

   if (exData->mPartitionVerts.size()>0)
   {
      exData->mWrapDecalBuffer.set(GFX, exData->mPartitionVerts.size(), GFXBufferTypeVolatile);
      exData->mWrapDecalBuffer.lock();
      // now set up tverts
      exData->mPartitionTVerts.setSize(exData->mPartitionVerts.size());
      F32 invSizeX = 1.0f / (decalData->sizeX);
	  F32 invSizeY = 1.0f / (decalData->sizeY);

      for (S32 i=0; i<exData->mPartitionVerts.size(); i++)
      {
         Point3F vert = exData->mPartitionVerts[i];
         exData->mWrapDecalBuffer[i].point.set(vert);
         exData->mWrapDecalBuffer[i].color.set(255, 255, 255, fade * 255.0f);
         exData->mWrapDecalBuffer[i].texCoord.set(0.5f + 0.5f * exData->mPartitionVerts[i].x * invSizeX, 0.5f + 0.5f * exData->mPartitionVerts[i].z * invSizeY);
      };

      exData->mWrapDecalBuffer.unlock();
   }
   smDepthSortList.clear();
}

Any help would be appreciated and will speed up my new release of the enhanced projectiles resource.
#6
08/12/2009 (3:03 pm)
OK I have tried just about everything I can think of on this. The only thing I might be missing is if there is some method to clear the buffer between GFX->drawPrimitive(s) so that the next decal can be rendered.