• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Federico Barlotti

Bill-boarding oriented rectangle

18 posts in this topic

Ok, here's a more complicated question. tongue.png

 

I have two 3D points which I have to "connect" with a rectangle.. sort of what I'd do drawing a LPD3DXLINE between them, however it needs to be a 3D mesh (i.e. perspective and distance resize it). The thing is, it also needs to bill-board itself towards the camera, and here I really don't know how to do it..

I could build a sin/cosine function that rotates 4 points around 2 vectors given a width, that's easy.. but how do I take care of the bill-boarding too? 

 

I really don't have a clue about this one..

 

EDIT: here's an image as example...

 

g1WXL1s.png

Edited by Banderi
0

Share this post


Link to post
Share on other sites

The bilboard rotation is computed based on the direction of the object looking at the camera. If you have a look at function in your code, you can recompute the up,right and look vector based on the camera position and the object that is been bilboard position.

0

Share this post


Link to post
Share on other sites

I don't have any "look at function".. but even if I had, I fail at math at this point, I don't have a clue about how the matrices and the vector computing actually work for the transformations, the projections, etc.. I just know how to apply them with DirectX APIs, up to this limit.

So not be rude at all but.. could you be a bit more specific on how to do this? '^^

Edited by Banderi
0

Share this post


Link to post
Share on other sites

looked challenging at first, but its not that bad.

 

the midpoint between your 2 points is where to draw the billboard.

its coordinates are just the average of the coordinates of the two points p1 and p2:

 

mid.x=(p1.x+p2.x)/2;

mid.y=(p1.y+p2.y)/2;

mid.z=(p1.z+p2.z)/2;

 

then you need a billboard quad.

 

if is just something simple like a 10x10 quad, no problem.

 

if the distance from p1 to p2 defines the width of the billboard, its a bit more work.

 

so the next question is: what size quad do you want to draw?

 

once you have a quad mesh and a point to draw at, aiming it at the camera is trivial, billboard xr = cam xr + 180, billboard yr = - cam yr, as i recall.

 

so, what size quad do you need?

 

its not too hard to create / scale a quad based on the distance between p1 and p2 if that's what you need.

Edited by Norman Barrows
0

Share this post


Link to post
Share on other sites

If the quad is the rectangle, it needs to be the distance between the points by a fixed length ("thickness"), as if I was to draw a textured stripe between them.

So yeah, it basically would need to be scaled according to their distance while maintaining its other dimension.

Edited by Banderi
0

Share this post


Link to post
Share on other sites

Make a quad, position at midpoint of p1 and p2. (trivial)

 

Scale it on lets say X by distance between p1 and p2. So the position matrix looks like:

(p1-p2).magnitude(), 0              , 0              , 0

0                              , 1              , 0              , 0

0                              , 0              , 1              , 0

midpoint.x                , midpoint.y, midpoint.z, 1

(thats row major i think. bottom row is position)

 

Now you just need the matrix that looks from billboard to camera and use some math to combine them (multiply? in my own matrix code i need to do rotation and translation separately for it to work but it was written by me so... yeah.)

 

For the rotation matrix youll need:

-X axis direction (direction from midpoint/p1 to p2)

-Y axis direction (cross the above and the below vectors (X axis dir and Z axis dir))

-Z axis direction (direction from midpoint to camera)

 

So now we only need the direction from midpoint to camera, which is simply taking the unit vector from their difference.

 

What you need to know:

Matrices:

[local X axis direction] ,0

[local Y axis direction] ,0

[local Z axis direction] ,0

[position                   ] , 1 //1 means position 0 means vector/direction

 

Cross product:

Takes 2 vectors, gives a vector that is perpendicular to both (imagine the 2 vectors form a plane. The result is the normal of the plane. The 2 input vectors dont need to be perpendicular with each other!)

 

Magnitude/distance:

sqrt(xDifference^2 + yDifference^2 + zDifference^2)

 

Unit vector/direction:

Take the difference of 2 vectors (a-b), divide by the magnitude of the result. Gives direction vector with length 1.

 

That should be all that you need.

1

Share this post


Link to post
Share on other sites

You know the object position  and you know the camera position. So what you need to do is recompute the right up and look vector of the object based on the camera position relative to the object. That way the object will always look at the camera no matter what the camera position is. You do not need to mock around with the vertices position at all. I have attached a piece of code from my engine that will do just that. If you have any question, please feel free to ask. Another thing to know is that my matrix is row major. So your basic Axis's are row based not column based.

 

  //**************************************************
  //Build an billboard matrix.
  //Using your own up vector.
  //**************************************************
  Matrix4x4 Matrix4x4::BillboardLookAt(const Vector3& objectPosition,const Vector3& target,const Vector3& up)
  {
    Vector3 lForward = (target-objectPosition).normalized();
    Vector3 lRight = Vector3::Cross(up,lForward).normalized();
    Vector3 lUp = Vector3::Cross(lForward,lRight).normalized();
    return Matrix4x4::From(lRight,lUp,lForward,Vector3::one,objectPosition);
  }

 

  //**************************************************
  //Build an matrix from a given set of vectors.
  //**************************************************
  Matrix4x4 Matrix4x4::From(const Vector3& right,const Vector3& up,const Vector3& forward,const Vector3& scale,const Vector3& position)
  {
    Matrix4x4 m = Matrix4x4::identity;
    m.Array[0]=right.x*scale.x;
    m.Array[1]=right.y*scale.x;
    m.Array[2]=right.z*scale.x;
    m.Array[4]=up.x*scale.y;
    m.Array[5]=up.y*scale.y;
    m.Array[6]=up.z*scale.y;
    m.Array[8]=forward.x*scale.z;
    m.Array[9]=forward.y*scale.z;
    m.Array[10]=forward.z*scale.z;
    m.Array[12]=position.x;
    m.Array[13]=position.y;
    m.Array[14]=position.z;
    return m;
  }

Edited by BornToCode
0

Share this post


Link to post
Share on other sites

..sweet Jesus, my brain exploded. Hold on a sec *picks up brain*

 

@BornToCode

This kind of bill-boarding is not what I require, and I've also achieved it through a waaaay simpler way (same rotation matrix of the camera applied on the mesh).

In other words, if I apply the matrix to a rectangular mesh, it rotates it toward the camera with the original position fixedly projected on a plane. That's not supposed to happen in my case, as the rectangle has to be a connection between two 3D points ;)

 

@Waterlimon

Not to be rude.. but I just don't get a single word.. as I said, I HORRIBLY fail at math in this point..

Could you make it simpler? If possible, can you use DirectX APIs to do that?

Edited by Banderi
0

Share this post


Link to post
Share on other sites

I am trying to follow Waterlimon pseudo but can't get it to work right:

D3DXVECTOR3 start(0.0f, 0.0f, -5.0f);
    D3DXVECTOR3 end(0.0f, .0f, 5.0f);
    D3DXVECTOR3 mid = (end + start) * 0.5f;

    D3DXMATRIX lWorld, lRot, lTra, lWVP;
    D3DXMatrixTranslation(&lTra, mid.x, mid.y, mid.z);
    lTra.m[0][0] = D3DXVec3Length(&(end - start));
    D3DXMatrixIdentity(&lRot);
    D3DXVECTOR3 xDir = end - start;
    D3DXVec3Normalize(&xDir, &xDir);
    D3DXVECTOR3 zDir = cam->Position - mid;
    D3DXVec3Normalize(&zDir, &zDir);
    D3DXVECTOR3 yDir;
    D3DXVec3Cross(&yDir, &xDir, &zDir);
    D3DXVec3Normalize(&yDir, &yDir);
    lRot.m[0][0] = xDir.x; lRot.m[0][1] = xDir.y; lRot.m[0][2] = xDir.z;
    lRot.m[1][0] = yDir.x; lRot.m[1][1] = yDir.y; lRot.m[1][2] = yDir.z;
    lRot.m[2][0] = zDir.x; lRot.m[2][1] = zDir.y; lRot.m[2][2] = zDir.z;
    lWorld = lRot * lTra;
...

Quad doesn't scale along start-end point and orientation is wrong.

Edited by belfegor
0

Share this post


Link to post
Share on other sites
I might have a mistake there somewhere since matrices are kind of blurry to me too.
-Is the majorness correct? (rows being the vectors)
-Is the matrix multiplication order correct? (i usually have problems with the translation part so that might be wrong)
0

Share this post


Link to post
Share on other sites
Oh i assumed the points to be same depth. Might want to do this in screen space.

Screen space you would just transform the points to screen space, then make quad of correct size (distance between points) and rotate it in 2D.
0

Share this post


Link to post
Share on other sites

Creating the mesh quad should be more straightforward, like you said.

 

The following was taken from user Floyd of the BlitzBasic forums. Say that the vector from Point 1 to Point 2 describes the Z axis of the quad, and say that the Y axis of this quad is aligned to the mesh normal (so the Y axis is perpendicular to the quad). You can figure global Pitch (X) and Yaw (Y) rotation values from these axes.

We need to find the Roll (Z) value.

 

A way to find this Roll (Z) rotation value for the quad to face the camera is to imagine that this value will make the quad place the camera in this quad's ZY plane.

There may be some negations needed based on what you consider as positive or negative sides, angles etc., but the logic is here.

 

2ps3ymg.png

 

To do the above, you need to get the camera's position in the quad's local space. Store it in a vector like "cameraLocalPos".

Then you can find the global Roll (Z) value for the quad with this: roll = ATan2( cameraLocalPos.X, cameraLocalPos.Y )

Note the inversion of the ATan2 parameters since we want the angle relative to the Y axis rather than the usual X axis.

 

Then rotate the quad in global coordinates by the following: Quad.Rotate( GlobalPItch, GlobalYaw, roll ).

Edited by Kryzon
2

Share this post


Link to post
Share on other sites

@Kryzon

Sounds exactly what I need, although the rectangle should not be aligned with any standard axis;

So, one million dollar question: how do I get it to rotate around a particular non-aligned axis (which should correspond to the distance between the points) a certain angle, such that said angle returns a bill-boarded normal (which if I got it right, should be the same formula you showed)?

Edited by Banderi
0

Share this post


Link to post
Share on other sites

What you're asking depends on how you created the mesh, and how it's positioned relative to its "pivot point" (or transformation matrix, in other words).

 

Steps:

1) Create a blank mesh object with an identity pivot point. This pivot point being identity means it's located at the world's origin and has zero orientation.

 

2) Measure the distance between the two 3D points and consider this as the length of the quad. The height of the quad is some predefined value.

Build the quad with absolute world coordinates and centered on the world's origin (so this mesh is actually centered on its own pivot point, which is also at the worlds origin). 

Make sure the length of the quad goes along the world's Z axis.

Make sure the visible face of the quad points along the world's Y axis.

This mesh is aligned to the world, it's not facing the camera yet.

 

3) Build a rotation matrix from vectors A and B.

Vector A is the 'vector going from point 1 to point 2' (considered as Z).

Vector B is the resulting vector from 'crossProduct( A, World_Y_Axis )' (considered as X). 

With these two vectors A and B you can find an orientation matrix O.

 

4) Find the location at 'the middle point between point 1 and point 2' (it's just the average of their coordinates). This finds a location vector L.

 

5) Transform the quad's matrix by orientation O and location L. This positions and orients the quad just like you want it to be, except it's not facing the camera yet.

 

6) Transform the quad's matrix Roll (Z) value by the way previously described in post #12. This way the rectangle faces the camera.

Edited by Kryzon
1

Share this post


Link to post
Share on other sites

Building the objects transformation matrix yourself sounds like the easiest approach, except that the two vectors to build the rotation part from are p2-p1 and (to make it face the camera) camera.position - p1 (or any other point on the line).

 

From there you just get the third vector with a cross product and after that use another cross product between the first and third vector to "fix" the second one (to be orthogonal). Normalize all vectors and you should be done. In your matrix, the first vector is the x-axis, the third one is the y-axis and the second is z. That choice is arbitrary and only depends on how your rectangle is modeled (I assume x being along the length, y being the width and z being the normal vector facing the camera).

 

There is no manual scaling going on unless what you mean is that is has to scale itself to cancel out the scaling you get from perspective projection.

 

When you create the geometry, do _not_ center it around the origin or you're just making it pointlessly complicated to move it into position. Just use (0,width,0), (0,-width,0), (length,width,0) and ((length,-width,0).

 

That approach has worked perfectly fine to have a ton of laser beams flying around. At least it's how I remember it, since the whole project seems to have disappeared.

2

Share this post


Link to post
Share on other sites

camera.position - p1 (or any other point on the line).

 

[...]

 
From there you just get the third vector with a cross product and after that use another cross product between the first and third vector to "fix" the second one (to be orthogonal).

That's an interesting way to get the orientation, it should be much faster.

Thanks for sharing.

0

Share this post


Link to post
Share on other sites

As Trienco proposed i removed scaling and created geometry with predetermined width and length (height in my case) and now it seems to work correctly.

Thank you.

0

Share this post


Link to post
Share on other sites

There is one special case that needs to be considered. If the camera and both points are on the same line, the cross product will be all 0 (or very close to it). On the bright side, in this special case you would be looking at the front or rear edge of the rectangle and couldn't see it anyway.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0