   [C++/ DX9.0c] Rendering Sprites & Meshes Together [SOLVED - Solution provided]
  Problem:I can render meshes as I want and sprites (D3DXSPRITE) as I want, however when I attempt to render both meshes and sprites together I have problems. If I use the billboard option when batching sprites they appear at the right translations but if i dont they move about whenever i move the camera (viewpoint). I am setting the same view matrix for the device and the sprite interface. Actually it might be better if I just put the code below for drawing sprites.Firsely this is the method which is called to draw sprites, passing in a pointer to a sprite interface, a vector of "basesceneobjects" which have had sprites set as their 3D representation and a DWORD of options as to how they are rendered (used in the "Begin" method call).void SceneGraph::DrawSprites(ID3DXSprite *sprite, vector<BaseSceneObject*> *sceneObjects,DWORD options){//(1) Validateif(!sprite || !m_viewer || !sceneObjects || !sceneObjects->size())return;D3DXMATRIX scale;D3DXMATRIX world;//(2) Set the world view for the sprite interfacesprite->SetWorldViewLH(NULL,m_viewer->GetViewMatrix());//(3) Batch all the spritessprite->Begin(options);vector<BaseSceneObject*>::iterator it;for(it = sceneObjects->begin();it!= sceneObjects->end();it++){//(4) Create a scaling matrix for the sprite textureD3DXMatrixScaling(&scale,(*it)->GetSprite()->GetWidth()/(*it)->GetSprite()->GetMaterial()->GetTexture()->GetTextureWidth(),(*it)->GetSprite()->GetHeight()/(*it)->GetSprite()->GetMaterial()->GetTexture()->GetTextureHeight(),1.0f);//(5) Apply the scaling matrix to the sprites world matrixD3DXMatrixMultiply(&world, &scale, (*it)->GetWorldMatrix());//(6) Alter the sprites translation so that it is centred (within their bounding boxes)world._41 -= (((*it)->GetBoxMax().x - (*it)->GetBoxMin().x) / 2);world._42 -= (((*it)->GetBoxMax().y - (*it)->GetBoxMin().y) / 2);world._43 -= (((*it)->GetBoxMax().z - (*it)->GetBoxMin().z) / 2);//(7) Let the sprite interface know about the sprites world matrixsprite->SetTransform(&world);//(8) Draw the spritesprite->Draw((*it)->GetSprite()->GetMaterial()->GetTexture()->GetTexture(),NULL,NULL,NULL,0xFFFFFFFF);}//(9) Send the sprites to the device to be renderedsprite->End();}Next is how this method is called, once to render billboarded sprites (this works even with meshes present in the scene) and one without billboarded sprites (this does not work, as described the sprites move about the screen as if there is some relation to the camera/viewpoint).//(2) Render Spritesif(!sprite)return;//(a) Render billboarded spritesDrawSprites(sprite,m_billboardedSprites,D3DXSPRITE_BILLBOARD |D3DXSPRITE_OBJECTSPACE | D3DXSPRITE_SORT_TEXTURE | D3DXSPRITE_SORT_DEPTH_BACKTOFRONT);//(b) Render nonbillboard spritesDrawSprites(sprite,m_nonBillboardedSprites,D3DXSPRITE_OBJECTSPACE | D3DXSPRITE_SORT_TEXTURE | D3DXSPRITE_SORT_DEPTH_BACKTOFRONT);Any suggestions, or further questions required to help solve this problem are very much welcome.Thanks for your time,Alex.[Edited by - CHTHONIC on June 21, 2006 9:25:15 AM]
  After taking a bit of a break from it and coming back to look at this problem I noticed that the first sprite rendered is actually rendered relative to the last mesh rendered and not where it should be in object space. What could be causing this?Thanks for your time once again,Alex.   ;  This is possibly due to sprite world matrix is not set properly, and use some elements from meshes matrix.Anyway I suggest if sprites matrices are used like billboard, to include matrix in sprite class.Following example will rotate camera around 0,0,0 point with billboard always facing camera:D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );D3DXVECTOR3 vEyePt;D3DXVECTOR3 vLookatPt( 0.0f, 1.0f, 0.0f );static float f = 0.0f;f += g_fElpasedTime;if(f>0.0001f){f=0.0f;g_fViewAngle+=0.01f;if(g_fViewAngle >=D3DX_PI*2) g_fViewAngle = 0.0f;}vEyePt.x =3.0f*cosf( ( g_fViewAngle ) );vEyePt.z =3.0f*sinf( ( g_fViewAngle ) );vEyePt.y = 4;D3DXMATRIXA16 matView, matBillboardMatrix;D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );D3DXMatrixInverse( &m_matBillboardMatrix, NULL, &matView );m_matBillboardMatrix._41 = 0;// xm_matBillboardMatrix._42 = 0;// ym_matBillboardMatrix._43 = 0;// zg_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(SpriteVertex) );g_pd3dDevice->SetFVF( SpriteVertex::FVF );g_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matBillboardMatrix );// Render the billboardg_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );Something like this [smile]   ;  Sorry i did not make myself clear the view/world matrices of each object are stored in the BaseSceneObject class itself. The BaseSceneObject class (and it's subclasses) have a 3D representation set for them by an LOD system. If this 3D representation is a sprite (possibly a billboarded sprite) it is rendered via the sprite segment of the scenegraph as shown in my first post.Alex.   ;  Anyway you need separate matrix for billboarded sprites to calculate world matrix of a sprite.   ;  Again, like i said billboarded sprites work fine. It's sprites which are not rendered as billboards that are not working properly, also please notice i am using the D3DXSPRITE interface to render sprites, not my own textured quad batch rendering system.Alex.   ;  If you are using sprites for user interface (2D) you need to switch to orthogonal view. If you planing to use sprites in 3D view you need to use quads for rendering, as I know.;  This is not true steamer. There is a "D3DXSPRITE_OBJECTSPACE" flag which allows you to render your sprites in 3D space and works fine when i dont render any meshes for both billboarded and nonbillboarded sprites. However when i have meshes and sprites in my scene, nonbillboarded sprites (sprites rendered without the "D3DXSPRITE_BILLBOARD" flag) start rendering 3D space relative to the last mesh rendered, however if they are billboarded ("D3DXSPRITE_BILLBOARD" flag is used) they still render in their correct positions in 3D space. If printscreens will help explain you to see what i mean, i shall do a few.Thanks,Alex.   ;  Yes you are right./*D3DXSPRITE_OBJECTSPACEThe world, view, and projection transforms are not modified. The transforms currently set to the device are used to transform the sprites when the batched sprites are drawn (when ID3DXSprite::Flush or ID3DXSprite::End is called). If this flag is not specified, then world, view, and projection transforms are modified so that sprites are drawn in screen-space coordinates.*/ from MSDNInsted:world._41 -= (((*it)->GetBoxMax().x - (*it)->GetBoxMin().x) / 2);world._42 -= (((*it)->GetBoxMax().y - (*it)->GetBoxMin().y) / 2);world._43 -= (((*it)->GetBoxMax().z - (*it)->GetBoxMin().z) / 2);Try:D3DXVector3 vec;vec.x -= (((*it)->GetBoxMax().x - (*it)->GetBoxMin().x) / 2);vec.y -= (((*it)->GetBoxMax().y - (*it)->GetBoxMin().y) / 2);vec.z -= (((*it)->GetBoxMax().z - (*it)->GetBoxMin().z) / 2);sprite->Draw((*it)->GetSprite()->GetMaterial()->GetTexture()->GetTexture(),NULL,NULL,vec,0xFFFFFFFF);Maybe this will help you.   ;  Steamer,_41,_42,_43 is simple the translation vector of the object bunged into its world matrix form, if the scene object is represented by a sprite i need to shift it by its halfsize in each dimension so that it is rendered, centred within it's bounding box. Removing this/changing this has no effect. The first sprite is still rendered relative to the last mesh rendered when i dont use the billboarding flag on the D3DXSPRITE interface.Alex.   