Jump to content
  • Advertisement
Sign in to follow this  
Medo Mex

Drawing billboard on mesh edges

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

If you intended to correct an error in the post then please contact us.

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:



How do I fix it?


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

Share this post

Link to post
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 this post

Link to post
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 this post

Link to post
Share on other sites

I was wandering when you gonna ask this question. biggrin.png

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 this post

Link to post
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 this post

Link to post
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
            do not add "billboard"
Edited by belfegor

Share this post

Link to post
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 this post

Link to post
Share on other sites


struct AABB
    D3DXVECTOR3 minPt;
    D3DXVECTOR3 maxPt;
D3DXVECTOR3 billPts[4];
AABB bb;
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;



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. biggrin.png

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!