Thread: Translating Transformed Vertices

  1. #1
    Registered User
    Join Date
    Jun 2003
    Posts
    361

    Translating Transformed Vertices

    Hullo hullo.

    I'm in a 2D jam. I've got a some Transformed vertices:
    Code:
    #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
    And I'm trying to use:
    Code:
    D3DXMATRIX matTrans;
    	
        Kinetics.Update();
    	
    	m_pD3DDevice->SetVertexShader(D3DFVF_CUSTOMVERTEX);
    	m_pD3DDevice->SetStreamSource(0, m_pVBuffer, sizeof(CUSTOMVERTEX));
    
    	D3DXMatrixTranslation(&matTrans, (float)Kinetics.pX, (float)Kinetics.pY, 0.0f);
    
    	m_pD3DDevice->SetTransform(D3DTS_WORLD, &matTrans);
    
        m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
    Kinetics.Update just assigns new values to pX and pY each time.

    However, my fancy little box is just sitting still. Is this not a valid method to move vertices in screen space? If not, are there any suggestions on how to do it?

    Thanks

  2. #2
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    The transformation is not being applied because when you specify RHW you are saying the vertices are already transformed and lit so don't let DirectX do it.

    That having been said, you can just make a dynamic vertex buffer and update the verts by locking , changing, unlocking whenever you need to. You may want to look at the ID3DXSprite interface for a very nice 2D interface.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  3. #3
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    I never really understood what RHW was. I've been using DirectX for a long time now, but never really looked in-depth into all of this FVF declaration stuff/picking what suits my needs.

    I'm hoping to stay away from the Locking/Unlocking method. Each scene will be updating about 8 Million vertices (perhaps a touch ambitious). And just that (without having to Lock/Unlock inbetween) is going to end up taking a lot of resources.

    Oh a whim, I removed the RHW property, made the necessary adjustments to classes/declaration of vertices, and disabled the D3DRS_LIGHTING property. Now my box has gone AWOL. I take it this wasn't a valid alternative?

  4. #4
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    So now that you have removed RHW DirectX will transform and light your vertices for you. Now you have disabled lighting so we are just transforming your vertices. Make sure you have your world matrix, camera matrix and projection matrix all set to appropriate values.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If you don't have a lot of vertices the added complexity and performance hit of locking/unlocking the buffer might be overkill. I would simply use an array of your own vertices and then use DrawPrimitiveUP to render them. Then to change the position you do not need to unlock or lock anything. Downside is that your vertices are going to be stored in system RAM which means they must be passed across the AGP bus as opposed to being stored in Video RAM and being passed directly to the GPU via the internal video card bus.

    But locking and unlocking is extremely costly and if you do that for every 2D object in every frame - it's going to be a mess.

    If you insist on unlocking/locking I might suggest you use a vector of vertex buffers that require unlocking and locking. At the start of the frame Lock all of them. At the end of the frame unlock them. This guarantees that you will only lock/unlock each vertex buffer only once. However I really don't recommend using IDirect3DVertexBuffer9's for this type of thing.

  6. #6
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Hmm, I was hoping to avoid having to set up the Camera and Projection Matrices, but I guess if I just stick to an Orthoganal Camera, it would be alright. Everything is strictly going to be 2D, and I was just looking for the quickest setup that would involve the least amount of per-frame calls.

    I'll look into the DrawPrimitiveUP function, I haven't seen the "UP" ending before. I'm also not very familiar with vectors in this sense, but I'll give it some thought too.

    The key thing right now is speed, and from what I'm thinking, perhaps setting up these matrices is the way to go. That way I have my 4 vertice box, and I'll just call D3DXMatrixTranslation, oh, only about 2 Million times.

    Thanks for the tips.

  7. #7
    Registered User
    Join Date
    Jun 2003
    Posts
    361

    Oh where oh where has my little box gone?

    I've been staring at this code for about three hours now. My little box just doesn't want to come back...
    Note: These are pieces of my files.

    Code:
    CAMERA AND PROJECTION INITIALIZATION
    D3DXMATRIX matOrtho;
    D3DXMATRIX matIdentity;
    
    D3DXMatrixOrthoLH(&matOrtho, (float)GetSystemMetrics(SM_CXSCREEN), (float)GetSystemMetrics(SM_CYSCREEN), 0.0f, 1.0f);
    D3DXMatrixIdentity(&matIdentity);
    
    m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matOrtho);
    m_pD3DDevice->SetTransform(D3DTS_WORLD, &matIdentity);
    m_pD3DDevice->SetTransform(D3DTS_VIEW, &matIdentity);
    
    m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
    m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, false);
    m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, false);
    
    VERTICE INITIALIZATION
    HRESULT Status;
    const int NUMVERTICES = 4;
    	
    m_pD3DDevice = pD3DDevice;
    if(m_pD3DDevice == NULL)
    	return E_FAIL;
    	
    CUSTOMVERTEX *pVertices = NULL;
    
    Status = m_pD3DDevice->CreateVertexBuffer(NUMVERTICES * sizeof(CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&m_pVBuffer);
    if(FAILED(Status))
    	return E_FAIL;
    
    Status = m_pVBuffer->Lock(0, NUMVERTICES * sizeof(CUSTOMVERTEX), (BYTE**)&pVertices, 0);
    if(FAILED(Status))
    	return E_FAIL;
    
    pVertices[0].Colour = pVertices[1].Colour = pVertices[2].Colour = pVertices[3].Colour = D3DCOLOR_XRGB(0, 200, 0);
    pVertices[0].Z = pVertices[1].Z = pVertices[2].Z = pVertices[3].Z = 0.0f;
    pVertices[0].X = pVertices[3].X = -(PIXELWIDTH / 2.0f) + 50.0f;
    pVertices[1].X = pVertices[2].X =  (PIXELWIDTH / 2.0f) + 50.0f;
    pVertices[0].Y = pVertices[1].Y = -(PIXELHEIGHT / 2.0f) + 50.0f;
    pVertices[2].Y = pVertices[3].Y =  (PIXELHEIGHT / 2.0f) + 50.0f;
    
    m_pVBuffer->Unlock();
    
    RENDERING
    m_pD3DDevice->SetVertexShader(D3DFVF_CUSTOMVERTEX);
    m_pD3DDevice->SetStreamSource(0, m_pVBuffer, sizeof(CUSTOMVERTEX));
    
    m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
    My understanding was that with an Orthogonal Camera Setup, the centre of the screen is the origin (0, 0), and goes from -1/2 of the value to +1/2 of the value passed into the D3DXMatrixOrthoLH() Initialisation.

    Note: I'm drawing a Triangle Fan (Hence the funky vertice declarations. Though I'm sure most of you would've picked up on that anyways).

    Any thoughts?
    Last edited by Epo; 12-02-2004 at 10:20 PM. Reason: Holy tab spacing batman! (Fixing it...)

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    That code looks pre-DirectX 9.0

  9. #9
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Right you are. That's my bad though, I should've mentioned I'm in DX8. (I still haven't made the switch over to 9 and I keep forgetting people are actually using it over 8.)

    I'm not in the wrong section of the forums am I?
    Last edited by Epo; 12-02-2004 at 11:51 PM. Reason: I am now downloading the DX9 SDK... :)

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    When you don't see your rendered objects it is usually because of one of these reasons.
    • Incorrect alpha state. Object is at 0 alpha.
    • Cull mode is incorrect or vertices are ordered in opposite direction of current cull. For all tests I set cull mode to D3DCULL_NONE. This ensures that your object, if translated correctly and setup correctly, will be shown. Then toggle between CCW and CW to see if your ordering is off.
    • Object has been translated off-screen. This can be due to many factors, some unforeseen or overlooked. It's all about coordinate spaces and often times not seeing an object is the direct result of the programmer using the wrong coordinate space at the wrong time or using the coordinate space incorrectly.
    • Colors of the vertexes are not being sent to Direct3D. Check the FVF declaration. Make sure the FVF matches not only what is in your vertex structure but that the FVF declaration matches the ORDER in which they appear in your structure.
      I.E.:

      struct Vertex
      {
      D3DXVECTOR3 x,y,z;
      D3DCOLOR Diffuse;
      D3DCOLOR Specular;
      float u,v;

      static const DWORD FVF;
      };

      The correct FVF for this is:

      const DWORD Vertex::FVF=D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1;

      Notice the declaration matches the contents of my structure as well as the order. This is extremely important and will help you later. Some tutorials overlook this and IMO miss a key issue in avoiding simple errors.
    • The primitive you are creating or sending to DirectX cannot be rendered correctly given your vertex information/ordering. This usually means your object is being created incorrectly or the vertices cannot be used by DirectX to create a triangle fan, triangle strip, line list, etc. Check the SDK. I will tell you that for clockwise ordered quads the correct triangulation for a triangle strip is:
      0................1
      ....................
      ....................
      ....................
      ....................
      2.................3

      Any other order will cause DirectX to FAIL TO RENDER the primitive because it cannot correctly process the vertexes.
    • Stream stride value is incorrect for your vertex format. For vertex buffers make sure the stream stride value is correct. It should be sizeof(vertex_struct). Any other value will cause incorrect intepretation of the data you are sending. Sometimes this produces weird results. For instance it may just so happen that your primitive is displayed, but something isn't right. So you look in the wrong place for the bug when all along it is because your data alignment is incorrect. This is a very annoying bug. Always make sure your vertex stride member is sizeof(vertex_struct). This will take care of any constructors or other data you are storing in the vertex buffer.
    • Incorrect FVF for the vertex. Sometimes the error is as simple as your FVF declaration being incorrect. For instance if you declare the vertex to have a diffuse and specular color, yet only specify D3DFVF_DIFFUSE - the color will not render correctly because the lighting engine will not use the specular color. So you could change the specular color all day long and it would NEVER affect the specular component of the primitive. The image will still render correctly if you are using sizeof(vertex_struct) which may lead you to the false assumption that your specular color is simply wrong. You change it and still no effect. Make sure the FVF has all the required members for your vertex. The same holds true for making sure your struct has all the components of the FVF declaration.
    • No light is reaching your object. Basically in 3D if there is no light....there is nothing there. So Direct3D is rendering a pure black primitive. One good way to test this is to clear the backbuffer in pure blue or pure red (0,0,255,255 or 255,0,0) and render the scene. If you see a bunch of pure black objects then your problem is lighting. There are two solutions to this. Either turn lighting off and specify to DirectX that the light value for the vertex comes from the vertex itself or you can put a D3DLIGHT9 in your world. Directional lights are the easiest and least costly. Check the SDK.
    • No material specified for your 3D object or primitive, If you are using Direct3D's default lighting engine it is very possible that your material properties are incorrect. Also if you use the lighting engine your object MUST have a material or you MUST specify the vertex colors in the vertex itself or Direct3D cannot light the vertexes. No material=no light. If it does not compute the light reaching the vertexes or the color at the vertexes correctly then it interpolates from 0.0f to 0.0f which is 0.0f - black. If you are clearing the screen to black then you wouldn't see anything rendered.
    Last edited by VirtualAce; 12-03-2004 at 09:32 AM.

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I've looked at your code and according to your setup your object should be at 0,0,0 in world space and camera space. Try setting the vertex z components to something a tad above 0.0f. It could be that they are being culled by the near clip plane. Try .1f or .2f. 0.0f should work, but its worth a shot.

    Incidentally quads are more suited to D3DPT_TRIANGLESTRIP than fans.

    Also for your update function when using a custom vertex buffer.

    Code:
    ...
    for (int i=0;i<num_vertexes;i++)
    {
      Vertexes[i].x+=increment_x;
      Vertexes[i].y+=increment_y;
    }
    But instead of incrementing you could also just directly assign the vertices a new absolute position.
    Last edited by VirtualAce; 12-03-2004 at 09:42 AM.

  12. #12
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Hey Bubba,

    Thanks for the in-depth reply. I went through each of those suggestions and still could not find the error.

    I noticed myself too that the Orthogonal View bounded Z between 0.0 and 1.0, but no matter the Z values for my vertices, I still can't see my box.

    This is becoming less of a concern for me, there're other aspects I can work on before really needing to render. I'm just curious though, what tipped you off that this code was pre DirectX9?

  13. #13
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    m_pD3DDevice->SetVertexShader(D3DFVF_CUSTOMVERTEX);

    That did.

  14. #14
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Ah, I see. As opposed to the SetFVF() method. I was hoping it was going to be the Orthogonal Camera setup.

    I've been messing around with DX9 since the beginning of this thread. And it's.....very similar. The only troubles I'm really having now are finding a way to actually set up an Orthogonal Projection matrix. Other than DrunkenHyena, I haven't been able to find many in-depth tutorials on DX9.

    So far my two options as I see it are:
    1) Figure out this Orthogonal Projection (which I'm hoping will be similar enough to DX8 that I can just code it in that way and fix any minor discrepancies as they show up.)

    2) Use DrawPrimitiveUP(). I have, let's call them "Floaties". One Floaty consists of 4 vertices. I will be drawing 2 Million Floaties on screen, each with their own position and speed. So each frame I must update each and every Floaty.
    To use DrawPrimitiveUP(), do I just adjust the vertice X, Y values, and call DrawPrimitiveUP (essentially the only thing I'm leaving out is locking/unlocking)?

    Speed/efficienty is taking precedence (spelling?) over simplicity.

  15. #15
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Quote Originally Posted by Epo
    Ah, I see. As opposed to the SetFVF() method. I was hoping it was going to be the Orthogonal Camera setup.

    I've been messing around with DX9 since the beginning of this thread. And it's.....very similar. The only troubles I'm really having now are finding a way to actually set up an Orthogonal Projection matrix. Other than DrunkenHyena, I haven't been able to find many in-depth tutorials on DX9.

    So far my two options as I see it are:
    1) Figure out this Orthogonal Projection (which I'm hoping will be similar enough to DX8 that I can just code it in that way and fix any minor discrepancies as they show up.)

    2) Use DrawPrimitiveUP(). I have, let's call them "Floaties". One Floaty consists of 4 vertices. I will be drawing 2 Million Floaties on screen, each with their own position and speed. So each frame I must update each and every Floaty.
    To use DrawPrimitiveUP(), do I just adjust the vertice X, Y values, and call DrawPrimitiveUP (essentially the only thing I'm leaving out is locking/unlocking)?

    Speed/efficienty is taking precedence (spelling?) over simplicity.
    Maybe if you posted the whole project we could help more? Just a thought.

    The ortho-projection matrix is described in the SDK Help file on the page for D3DXMatrixOrthoLH. There are also off-center matrices and their RH counter-parts.

    DrawPrimitive(U)ser(P)ointer. Yes, you will not be locking/unlocking this. You simply manipulate your own array or what not and then you send that directly to DrawPrimitiveUP. This is slower than using vertex buffers but maybe it won't be significant for you.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Vertices and Indices
    By beene in forum Game Programming
    Replies: 15
    Last Post: 05-07-2007, 03:08 AM
  2. Replies: 14
    Last Post: 06-28-2006, 01:58 AM
  3. Having trouble translating psudeo-code to real-code.
    By Lithorien in forum C++ Programming
    Replies: 13
    Last Post: 10-05-2004, 07:51 PM
  4. Translating Java to C. Mergesorting linked list.
    By Mikro in forum C Programming
    Replies: 10
    Last Post: 06-22-2004, 11:34 AM
  5. winding vertices
    By confuted in forum Game Programming
    Replies: 0
    Last Post: 07-21-2002, 09:54 PM