• 13
• 18
• 19
• 27
• 10

# Drawing billboard on mesh edges

This topic is 1774 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Okay, I'm able to draw billboards on mesh for bullet impact.

Sometimes, the player will shoot at the edges which will result in undesired results:

[attachment=15644:unreal.png]

How do I fix it?

Maybe I should bend the billboard to make it appear on 2 triangles?

##### Share on other sites

Why are you using billboards instead of decals ?

To fix this, you would need to compute the distance from the point of impact (that you already have) from the nearest edge. But not just any triangle edge (since the inner part of the mesh has plenty of those) - but you'd need to keep a separate outline edges.

For a full solution, you'd have to compute a silhouette mesh every frame and check against that - but that'd be an overkill.

It'd be easier if you just kept the hard edges in a separate array (you can compute them based on the angle between two neighbouring faces).

Then, during a check, just move the point of impact in the opposite direction of the vector connecting the point of impact with the edge.

BTW, plenty games just leave it as it is - since it's simply not so important to warrant the implementation of the above.

In the same time it will take you to implement the above, you can implement few more features that will make the game better (compared to a simple visual artifact that few people will notice in the heat of the game).

##### Share on other sites

1. What are decals? what is the difference between billboards and decals?

2. How do I detect if the billboard will reach the edge so I don't draw it?

##### Share on other sites

I was wandering when you gonna ask this question.

This is pretty hard-core to get right.

One of possible solutions is when you ray-cast/pick your mesh, you need to obtain list of triangles that are intersecting with decal aabb (or sphere), Bullet physics might have some functions to do that.

Then you need to clip those triangles against this aabb (if you mind fillrate problems).

I got this far:

Note, this is just to show how it looks like. Red outlined is a list of triangles that intersects aabb, the other thing in the middle are clipped triangles against aabb (blending disabled to show), additionally i skip triangles that are fabs(dot(hitnormal, trinorm)) < threshold so those texcoord stretching is not seen.

You might wanna look at Overgrowth article about projected decals.

Happy googling.

##### Share on other sites

@belfegor: Right now the easiest way to fix this problem is to not draw the billboard when it's too close to the edge, how do I detect if it's very close to the edges?

I'll take a look at decals, but I want to first fix the problem then I will see possible ways for improvement.

##### Share on other sites

I don't know easy/fast way to check when "billboard" is around edge.

I would go brute force:

1. Obtain raycast hit point and triangle normal that was hit

2. Make AABB from 4 points of your "billboard"

3. Make 6 planes from AABB

4. Go thru each triangle on mesh and test each of 3 points against planes to build list of triangles that "belong" to AABB

5. Test collected triangles normals against hit triangle normal

normalize( HitTriNrm );
for each tri
triNrm = getTriNormal( tri );
normalize( triNrm );
if( dot(triNrm, HitTriNrm) < 0.6f ) // there is a hard edge
break;

Edited by belfegor

##### Share on other sites
Although I got the idea, I don't understand how to do number 2 and 3 exactly, how do I create AABB from 4 points of my billboard? and how do I make 6 planes from AABB?

##### Share on other sites

2.

struct AABB
{
D3DXVECTOR3 minPt;
D3DXVECTOR3 maxPt;
};

D3DXVECTOR3 billPts[4];
...
AABB bb;
bb.minPt = D3DXVECTOR3(FLT_MAX, FLT_MAX, FLT_MAX);
bb.maxPt = D3DXVECTOR3(FLT_MIN, FLT_MIN, FLT_MIN);
for(int i = 0; i < 4; ++i)
{
// check min
if(bb.minPt.x > billPts.x) bb.minPt.x = billPts.x;
if(bb.minPt.y > billPts.y) bb.minPt.y = billPts.y;
if(bb.minPt.z > billPts.z) bb.minPt.z = billPts.z;

// check max
if(bb.maxPt.x < billPts.x) bb.maxPt.x = billPts.x;
if(bb.maxPt.y < billPts.y) bb.maxPt.y = billPts.y;
if(bb.maxPt.z < billPts.z) bb.maxPt.z = billPts.z;
}


3.

struct _Plane
{
float nx;
float ny;
float nz;
float d;
};

_Plane PlaneFromPointNormal(const D3DXVECTOR3 &Pt, const D3DXVECTOR3 &Normal)
{
_Plane Result;
D3DXVECTOR3 NormalizedNormal;
D3DXVec3Normalize(&NormalizedNormal, &Normal);
Result.nx = NormalizedNormal.x;
Result.ny = NormalizedNormal.y;
Result.nz = NormalizedNormal.z;
Result.d = -D3DXVec3Dot(&Pt, &NormalizedNormal);
return Result;
}

std::array<_Plane, 6> ExtractPlanesFromBBox(const AABB* bb)
{
std::array<_Plane, 6> out;
D3DXVECTOR3 center = (bb->maxPt + bb->minPt) * 0.5f;
D3DXVECTOR3 extent = (bb->maxPt - bb->minPt) * 0.5f;

// up
D3DXVECTOR3 ptUp  = center + D3DXVECTOR3(0.0f, extent.y, 0.0f);
D3DXVECTOR3 nrmUp = center - ptUp;
out[0] = PlaneFromPointNormal(ptUp, nrmUp);

// down
D3DXVECTOR3 ptDown  = center + D3DXVECTOR3(0.0f, -extent.y, 0.0f);
D3DXVECTOR3 nrmDown = center - ptDown;
out[1] = PlaneFromPointNormal(ptDown, nrmDown);

// left
D3DXVECTOR3 ptLeft  = center + D3DXVECTOR3(-extent.x, 0.0f, 0.0f);
D3DXVECTOR3 nrmLeft = center - ptLeft;
out[2] = PlaneFromPointNormal(ptLeft, nrmLeft);

// right
D3DXVECTOR3 ptRight  = center + D3DXVECTOR3(extent.x, 0.0f, 0.0f);
D3DXVECTOR3 nrmRight = center - ptRight;
out[3] = PlaneFromPointNormal(ptRight, nrmRight);

// back
D3DXVECTOR3 ptBack  = center + D3DXVECTOR3(0.0f, 0.0f, -extent.z);
D3DXVECTOR3 nrmBack = center - ptBack;
out[4] = PlaneFromPointNormal(ptBack, nrmBack);

// front
D3DXVECTOR3 ptFront  = center + D3DXVECTOR3(0.0f, 0.0f, extent.z);
D3DXVECTOR3 nrmFront = center - ptFront;
out[5] = PlaneFromPointNormal(ptFront, nrmFront);

return out;
}


You'll need this also:

// plane - point relationship
float PlaneDotCoord(const _Plane* p, const D3DXVECTOR3* c)
{
return ( (p->nx) * (c->x) + (p->ny) * (c->y) + (p->nz) * (c->z) + (p->d) );
}
result > 0 - in front of plane
result < 0 - back of plane
result == 0 - on plane


Happy copy/pasting.