Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

D3D sprites

This topic is 5493 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

I''m trying to display sprites (the sdk calls them billboards) in my D3D application. In detail: I want to display objects that is located somewhere in my world and is always facing the viewer. I set up a rectangle (triangle-strip with 4 vertices) and when it should render I tried this (m_vecPos is the sprite position in world space): // Set up the world matrix, only containing the position D3DXMATRIX matWorld; D3DXMatrixIdentity(&matWorld); matWorld(3, 0) = m_vecPos.x; matWorld(3, 1) = m_vecPos.y; matWorld(3, 2) = m_vecPos.z; m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, matWorld); // Save the old view matrix D3DXMATRIX matViewOld; m_pD3DDevice->GetTransform(D3DTRANSFORMSTATE_VIEW, matViewOld); // Set up a new view matrix, stripping rotations D3DXMATRIX matView; D3DXMatrixIdentity(&matView); matView(3, 0) = matViewOld(3, 0); matView(3, 1) = matViewOld(3, 1); matView(3, 2) = matViewOld(3, 2); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, matView); // Render the rectangle if (FAILED(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, m_pvVertices, 4, NULL))) return hr; // Restore the old view matrix m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, matViewOld); It does work, the sprite is always facing the viewer, but now I want it to also roll (Z-rotation) when the viepoint rolls and I totally stuck up with that. Can anybody point me into the right direction? Or did I totally start wrong with my above solution? ArgoN

Share this post


Link to post
Share on other sites
Advertisement
I would do it like this:

1. Get the View matrix & strip away the translation part
2. Transpose the resulting rotation matrix to get the inverse
3. Concatenate this inverted rotation matrix with a rotateZ matrix to get the z roll
4. Concatenate the resulting matrix with the translation matrix for the sprite
5. Use this matrix as the world matrix when rendering the sprite

Don''t change the view matrix, it is better to multiply the world matrix with the inverse of the view matrix instead (as I do above)

- WitchLord

Share this post


Link to post
Share on other sites
My problem is that (due to my class structure) I don''t have access to the view roll angle when drawing a sprite. If there would be a way to strip the translation and the Z-rotation from the view matrix, everything would be fine...

ArgoN

Share this post


Link to post
Share on other sites
I''m not sure I understand what z rolling you want to do. Is it that you want the sprite edges to always be aligned with the screen edges? If you do like I wrote without adding the rotateZ matrix you get that behaviour.

1. Get the View matrix & strip away the translation part
2. Transpose the resulting rotation matrix to get the inverse
3. Concatenate the resulting matrix with the translation matrix for the sprite
4. Use this matrix as the world matrix when rendering the sprite





- WitchLord

Share this post


Link to post
Share on other sites
No, that''s what I don''t want. Like I did it above, the sprites edges are aligned to screen edges. Thats how it shouldn''t be.

Maybe my idea of what I try to do is nonsense. I''ll try to explain: I''m trying to create a little 3D space shooter to gain experiences in 3D programming. I need something that I can use for e.g. the engine''s thrust or a cloud trail. So I thought I can use sprites for it. The sprite should always face the viewer (which it does yet) so that it look like an object that is 3D but looks the same from all angles you''re looking on it. But if the viewer is rolling (rotating at his local Z axis), the sprite must also rotate the same so that it looks like it keeps it''s orientation in space. If the sprites edges are always aligned to screen edges, it looks like it would turn with the viewer when rolling.

Isn''t that the way sprites are supposed to behave?

ArgoN

Share this post


Link to post
Share on other sites
The simplest way would be to store the camera parameters so that they are globally available. But if you don''t, you can extract the camera roll angle by examining the camera up vector of the view matrix. The up vector can be retrieved from the the second column. (the structure of the viewmatrix)

To get the roll vector you examine the angle that would be need to roll the vector back to its position before the camera roll, which is on the yz-plane. Depending on the pitch of the camera the vector should either point upwards or downwards.

As you can imagine, it requires a lot of computations to extract the angles from the matrix. If you still want to know how it is done I can tell you how it''s done, but you have to ask nicely

- WitchLord

Share this post


Link to post
Share on other sites
Ok, lets see if I get it right


// 1) Get the current view matrix
D3DXMATRIX mat;
m_pD3DDevice->GetTransform(D3DTRANSFORMSTATE_VIEW, mat);

// 2) Strip translations
mat(3, 0) = 0;
mat(3, 1) = 0;
mat(3, 2) = 0;

// 3) Invert it to get a world matrix
D3DVALUE fDet;
D3DXMatrixInverse(&mat, &fDet, &mat);

// 4) Get the up vector from it and strip pitching (z-value)
D3DXVECTOR3 vecViewUp;
vecViewUp.x = mat(0, 1);
vecViewUp.y = mat(1, 1);
vecViewUp.z = 0;
D3DXVec3Normalize(&vecViewUp, &vecViewUp);

// 5) Calc angle to world y axis (viewers roll)
D3DXVECTOR3 vecWorldUp(0, 1, 0);
D3DVALUE fCosRollAngle = D3DXVec3Dot(&vecViewUp, &vecWorldUp);
D3DVALUE fRollAngle = acosf(fCosRollAngle);

// 6) Fix left/right rotation
if (vecViewUp.x > 0)
fRollAngle = -fRollAngle;

// 7) Apply Z rotation
D3DXMATRIX matRoll;
D3DXMatrixRotationZ(&matRoll, fRollAngle);
D3DXMatrixMultiply(&mat, &matRoll, &mat);

// 8) Apply sprite coordinates
D3DXMATRIX matPos;
D3DXMatrixIdentity(&matPos);
matPos(3, 0) = m_vecPos.x;
matPos(3, 1) = m_vecPos.y;
matPos(3, 2) = m_vecPos.z;
D3DXMatrixMultiply(&mat, &mat, &matPos);

// 9) Set world matrix
m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, mat);


Phew... that works, but isn't that a bit oversized for a simple sprite calculation? I thought sprites are supposed to be fast .

Hmmm, the code above could be optimized (e.g. the dot product of (x,y,z)*(0,1,0) can be simplified to y . And setting up the z-rotation matrix could also be faster because I already have the cosine of the angle).

But I still think it's oversized. Are sprites really that 'difficult' to calculate? Maybe I could get rid of the matrix inversion by modifying the view matrix instead.

Everything would be only little easier if I had the view roll angle: I could get rid of steps 4 to 6, but my class structure doesn't allow to easily retrieve the roll angle.

I thought about the above solution before, but I think it's pretty much for a simple sprite. If you know a better solution, I would love to ask you nicely


Edited by - ArgoN on June 22, 2000 7:04:50 PM

Share this post


Link to post
Share on other sites
You can get rid of the matrix inversion by using a transpose instead. Because the matrix only contains rotation information this will be the same as inversion.

I think you are also extracting the wrong vector from the matrix, because you have inverted the matrix the up vector will now be found on the second row instead.

You have to remember that much of this information can be shared among the sprite renderings, you''ll only have to compute their rotation matrices once for all of them.



- WitchLord

Share this post


Link to post
Share on other sites
Oops, you''re right with the wrong vector.

Ok, thats working for now. I''ll try to optimize it a bit more and it should be fast enough. Thanks for your help!

ArgoN

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

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

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!