Issue "Wrapping" Decals
by DavidRM · in Torque Game Engine · 05/03/2006 (3:48 pm) · 7 replies
I'm trying to extend decals so that they will "wrap" around/across terrain and interiors, instead of just being a simple plane with a bitmap.
I pulled apart the shadow rendering to see how that was done, and lifted a chunk of the code. It almost works...
Sometimes, across simple ridges, it works perfectly. Around/across more complex angles, parts of the decal aren't visible. Sometimes only a portion of the decal (usually a vertical strip) is visible. (see images; I made the decal much bigger to better demonstrate the problem)



Here's the core of the code that calculates the decal "overlay":
I suspect the problem is in the transform matrix or in the box/sphere calculations. But my 3D math is rusty at best (this spring marks 16 years since Linear Algebra), so I'm not sure what to adjust.
Any assitance would be appreciated.
Thanks.
-David
I pulled apart the shadow rendering to see how that was done, and lifted a chunk of the code. It almost works...
Sometimes, across simple ridges, it works perfectly. Around/across more complex angles, parts of the decal aren't visible. Sometimes only a portion of the decal (usually a vertical strip) is visible. (see images; I made the decal much bigger to better demonstrate the problem)



Here's the core of the code that calculates the decal "overlay":
...updated code in next post
I suspect the problem is in the transform matrix or in the box/sphere calculations. But my 3D math is rusty at best (this spring marks 16 years since Linear Algebra), so I'm not sure what to adjust.
Any assitance would be appreciated.
Thanks.
-David
#2
I assume that the gClientContainer.findObjects() should return polys that are within an area defined by smDecalMask?
Maybe this function is not returning all the polys that it should.
05/04/2006 (6:47 pm)
Thanks for such a useful resource. I'll definitely be needing decal wrapping. I'm not familiar with how the decal manager works and am new to Torque engine so I'll take a stab in the dark.I assume that the gClientContainer.findObjects() should return polys that are within an area defined by smDecalMask?
Maybe this function is not returning all the polys that it should.
#3
I have it far enough now that I'm willing to move on. Several of the issues that remain can be resolved by a better "splat" image.
For the curious:


-David
05/04/2006 (9:49 pm)
I hadn't thought of it as a resource, really. More of a plea to "Please look at my code and tell me what I'm doing wrong." ;-) Also, I'm not sure how useful this would be for games that don't have a lot of paint flying around. Bullet holes, for example, don't usually need to "wrap" around a set of polys.I have it far enough now that I'm willing to move on. Several of the issues that remain can be resolved by a better "splat" image.
For the curious:
void DecalManager::addWrapDecal(const Point3F& pos,
Point3F normal,
Point3F impactNormal,
DecalData *decalData)
{
...
DecalExData *exData=new DecalExData;
newDecal->exData=exData;
// 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();
}
// backup a bit (for the transforms) so that we can "see" all the polys
Point3F position = Point3F(pos.x + (-impactNormal.x * decalData->sizeX*2), pos.y + (-impactNormal.y * decalData->sizeY*2), pos.z + (-impactNormal.z * decalData->sizeX*2));
MatrixF decalToWorld(true);
decalToWorld.setColumn(0,x);
decalToWorld.setColumn(1,y);
decalToWorld.setColumn(2,z);
decalToWorld.setColumn(3,position);
exData->mTransform=decalToWorld;
MatrixF worldToDecal=decalToWorld;
worldToDecal.inverse();
// setup depth sort list
// expanded to 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->sizeX*2;
z *= decalData->sizeY*2;
gDecalBox.max.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.max.len();
gDecalSphere.center = pos;
gDecalBox.min = pos - gDecalBox.max;
gDecalBox.max += pos;
// get polys
gClientContainer.findObjects(smDecalMask,DecalManager::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)
{
// 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++)
exData->mPartitionTVerts[i].set(0.5f + 0.5f * exData->mPartitionVerts[i].x * invSizeX,0.5f + 0.5f * exData->mPartitionVerts[i].z * invSizeY);
}
else
{
delete exData;
newDecal->exData=NULL;
// do it the old fashioned way
...
}
...
}

-David
#4
05/04/2006 (10:38 pm)
Is that a paintball chaingun? >.>
#5
-David
05/05/2006 (11:04 am)
@Paul: Yah. Though it's still waiting for animation and proper scripting. Right now it's just "the last gun model I loaded up for testing purposes". Plus, I just love seeing it's "cartoon chrome". :)-David
#6
-Eric
05/05/2006 (11:08 am)
Hehe. I'm glad to see you're working on the Paintball game again, David. :)-Eric
#7
05/05/2006 (10:42 pm)
That paint splat decal could easily be scorch mark from an explosion...
Torque Owner DavidRM
I'd love to find out what I'm doing wrong in the case of floors, ceilings, and why sometimes the decal is clipped oddly. Any suggestions?
-David